From c8ba585854559566fee196f7a4082e3c3f43dec1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marcos=20G=C3=B3mez?= Date: Sun, 14 Jan 2018 19:37:02 +0100 Subject: [PATCH] langParser.js: Generate language list dynamically This adds ``langParser.js`` to generate the available language list automatically from available translation files. This also adds a npm script for generating before webpack bundles. Modifies .gitignore so that generated ``languages.js`` file is ignored. Adds tests. Renames ``nb_NO.json`` to ``nb-NO.json`` to comply with RFC standards. Closes: https://github.com/coala/gci-leaders/issues/125 --- lib/langParser.js | 15 +++++++ package-lock.json | 71 ++++++++++++-------------------- package.json | 5 ++- src/js/languages.json | 1 + src/js/locale.js | 8 +--- tests/__data__/test-languages.js | 1 + tests/lib/langParser.test.js | 22 ++++++++++ webpack.config.js | 3 ++ 8 files changed, 75 insertions(+), 51 deletions(-) create mode 100644 lib/langParser.js create mode 100644 src/js/languages.json create mode 100644 tests/__data__/test-languages.js create mode 100644 tests/lib/langParser.test.js diff --git a/lib/langParser.js b/lib/langParser.js new file mode 100644 index 0000000..948f777 --- /dev/null +++ b/lib/langParser.js @@ -0,0 +1,15 @@ +const fs = require('fs') +const iso639 = require('iso-639-1') + +const availableLanguages = {} + +fs.readdir(`${__dirname}/../static/i18n`, (err, items) => { + items.forEach(function(value) { + const langName = value.substring(0, value.indexOf('.')) + const normalizedName = langName.split('_')[0] + const nativeName = iso639.getNativeName(normalizedName) + availableLanguages[nativeName] = langName + }) +}) + +module.exports = availableLanguages diff --git a/package-lock.json b/package-lock.json index 15d3fe5..9c9a786 100644 --- a/package-lock.json +++ b/package-lock.json @@ -49,7 +49,7 @@ "acorn": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.2.1.tgz", - "integrity": "sha1-MXrHghgmwixwLWYYmrg1lnXxNdc=", + "integrity": "sha512-jG0u7c4Ly+3QkkW18V+NRDN+4bWHdln30NL1ZL2AvFZZmQe/BfopYCtghCKKVBUSetZ4QKcyA0pY6/4Gw8Pv8w==", "dev": true }, "acorn-dynamic-import": { @@ -143,7 +143,7 @@ "ansi-escapes": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.0.0.tgz", - "integrity": "sha1-7D6LTp+AZPwCw6ybZfHCdb2o75I=", + "integrity": "sha512-O/klc27mWNUigtv0F8NJWbLF00OcegQalkqKURWdosW08YZKi4m6CnSUSvIZG1otNJbTWhN01Hhz389DW7mvDQ==", "dev": true }, "ansi-html": { @@ -1187,13 +1187,6 @@ "integrity": "sha1-RqoXUftqL5PuXmibsQh9SxTGwgU=", "dev": true }, - "bindings": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.0.tgz", - "integrity": "sha512-DpLh5EzMR2kzvX1KIlVC0VkC3iZtHKTgdtZ0a3pglBZdaQFjt5S9g9xd1lE+YvXyfd6mtCeRnrUfOLYiTMlNSw==", - "dev": true, - "optional": true - }, "bluebird": { "version": "3.5.1", "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.1.tgz", @@ -2481,7 +2474,7 @@ "debug": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/debug/-/debug-3.1.0.tgz", - "integrity": "sha1-W7WgZyYotkFJVmuhaBnmFRjGcmE=", + "integrity": "sha512-OX8XqP7/1a9cqkxYw2yXss15f26NKWBpDXQd0/uK/KPqdQhxbPa994hnzjcE2VqQpDslf55723cKPUOGSmMY3g==", "dev": true, "requires": { "ms": "2.0.0" @@ -2670,7 +2663,7 @@ "doctrine": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.0.2.tgz", - "integrity": "sha1-aPls6O/FbMQmUfH6rbTxdSc7AHU=", + "integrity": "sha512-y0tm5Pq6ywp3qSTZ1vPgVdAnbDEoeoc5wlOHXoY1c4Wug/a7JvqHIl7BTvwodaHmejWkK/9dSb3sCYfyo/om8A==", "dev": true, "requires": { "esutils": "2.0.2" @@ -3170,7 +3163,7 @@ "espree": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/espree/-/espree-3.5.2.tgz", - "integrity": "sha1-dWrai5eenc/NswqtjRqTBKkF4co=", + "integrity": "sha512-sadKeYwaR/aJ3stC2CdvgXu1T16TdYN+qwCpcWbMnGJ8s0zNWemzrvb2GbD4OhmJ/fwpJjudThAlLobGbWZbCQ==", "dev": true, "requires": { "acorn": "5.2.1", @@ -3406,7 +3399,7 @@ "external-editor": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-2.1.0.tgz", - "integrity": "sha1-PQJqIbf5W1cmOH1CAKwWDTcsO0g=", + "integrity": "sha512-E44iT5QVOUJBKij4IIV3uvxuNlbKS38Tw1HiupxEIHPv9qtC2PrDYohbXV5U+1jnfIXttny8gUhj+oZvflFlzA==", "dev": true, "requires": { "chardet": "0.4.2", @@ -3742,8 +3735,7 @@ "fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=", - "dev": true + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" }, "function-bind": { "version": "1.1.1", @@ -3763,6 +3755,12 @@ "integrity": "sha1-szmUr0V6gRVwDUEPMXczy+egkEs=", "dev": true }, + "generate-json-webpack-plugin": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/generate-json-webpack-plugin/-/generate-json-webpack-plugin-0.2.2.tgz", + "integrity": "sha512-2TUQqI7I9kGXwZxnRqJczYvBuBPrHq+EQKP1b0m2vArPlzsi/cIaJGg5IQSS26HSqRiYCZJ+z7azPzUCTP3pyg==", + "dev": true + }, "get-caller-file": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", @@ -3792,7 +3790,7 @@ "glob": { "version": "7.1.2", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", - "integrity": "sha512-MJTUg1kjuLeQCJ+ccE4Vpa6kKVXkPYJ2mOCQyUuKLcLQsdrMCpBPUi8qVE6+YuaJkozeA9NusTAw3hLr8Xe5EQ==", + "integrity": "sha1-wZyd+aAocC1nhhI4SmVSQExjbRU=", "requires": { "fs.realpath": "1.0.0", "inflight": "1.0.6", @@ -4261,7 +4259,7 @@ "inquirer": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-3.3.0.tgz", - "integrity": "sha1-ndLyrXZdyrH/BEO0kUQqILoifck=", + "integrity": "sha512-h+xtnyk4EwKvFWHrUYsWErEVR+igKtLdchu+o0Z1RL7VU/jVMFbYir2bp6bAj8efFNxWqHX0dIss6fJQ+/+qeQ==", "dev": true, "requires": { "ansi-escapes": "3.0.0", @@ -4576,6 +4574,11 @@ "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=", "dev": true }, + "iso-639-1": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/iso-639-1/-/iso-639-1-2.0.3.tgz", + "integrity": "sha512-PZhOTDH05ZLJyCqxAH65EzGaLO801KCvoEahAFoiqlp2HmnGUm8sO19KwWPCiWd3odjmoYd9ytzk2WtVYgWyCg==" + }, "isobject": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz", @@ -4918,8 +4921,7 @@ "integrity": "sha512-xyVdAmcG8M3jWtVeadDUU6MAHLBrjkP4clz2UtTZ1gpe5bRLk27VjQOpzTwK20MkV/6iZQhSuRVuzHS5kD0HpA==", "dev": true, "requires": { - "pretty-format": "22.0.3", - "weak": "1.0.1" + "pretty-format": "22.0.3" } }, "jest-matcher-utils": { @@ -5565,7 +5567,7 @@ "lru-cache": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.1.tgz", - "integrity": "sha1-Yi4y6CSItJJ5EUpPns9F581rulU=", + "integrity": "sha512-q4spe4KTfsAS1SUHLO0wz8Qiyf1+vMIAgpRYioFYDMNqKfHQbg+AVDH3i4fvpl71/P1L0dBl+fQi+P37UYf0ew==", "dev": true, "requires": { "pseudomap": "1.0.2", @@ -5794,7 +5796,6 @@ "version": "3.0.4", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "integrity": "sha1-UWbihkV/AzBgZL5Ul+jbsMPTIIM=", - "dev": true, "requires": { "brace-expansion": "1.1.8" } @@ -5919,13 +5920,6 @@ "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", "dev": true }, - "nan": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/nan/-/nan-2.8.0.tgz", - "integrity": "sha1-7XFfP+neArV6XmJS2QqWZ14fCFo=", - "dev": true, - "optional": true - }, "natural-compare": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", @@ -6502,7 +6496,7 @@ "pluralize": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", - "integrity": "sha1-KYuJ34uTsCIdv0Ia0rGx6iP8Z3c=", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", "dev": true }, "pn": { @@ -7462,7 +7456,7 @@ "readable-stream": { "version": "2.3.3", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.3.tgz", - "integrity": "sha1-No8lEtefnUb9/HE0mueHi7weuVw=", + "integrity": "sha512-m+qzzcn7KUxEmd1gMbchF+Y2eIUbieUaxkWtptyHywrX0rE8QEYqPC07Vuy4Wm32/xE16NcdBctb8S0Xe/5IeQ==", "requires": { "core-util-is": "1.0.2", "inherits": "2.0.3", @@ -8379,7 +8373,7 @@ "string_decoder": { "version": "1.0.3", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz", - "integrity": "sha1-D8Z9fBQYJd6UKC3VNr7GubzoYKs=", + "integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==", "requires": { "safe-buffer": "5.1.1" } @@ -8798,7 +8792,7 @@ "tmp": { "version": "0.0.33", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", - "integrity": "sha1-bTQzWIl2jSGyvNoKonfO07G/rfk=", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", "dev": true, "requires": { "os-tmpdir": "1.0.2" @@ -9227,17 +9221,6 @@ "minimalistic-assert": "1.0.0" } }, - "weak": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/weak/-/weak-1.0.1.tgz", - "integrity": "sha1-q5mqswcGlZqgIAy4z1RbucszuZ4=", - "dev": true, - "optional": true, - "requires": { - "bindings": "1.3.0", - "nan": "2.8.0" - } - }, "webidl-conversions": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz", @@ -9657,7 +9640,7 @@ "which": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/which/-/which-1.3.0.tgz", - "integrity": "sha1-/wS9/AEO5UfXgL7DjhrBwnd9JTo=", + "integrity": "sha512-xcJpopdamTuY5duC/KnTTNBraPK54YwpenP4lzxU8H91GudWpFv38u0CKjclE1Wi2EH2EDz5LRcHcKbCIzqGyg==", "dev": true, "requires": { "isexe": "2.0.0" diff --git a/package.json b/package.json index 019c92d..a29c13d 100644 --- a/package.json +++ b/package.json @@ -9,9 +9,10 @@ "generate": "node ./lib/generate.js", "gather": "node ./lib/gather.js", "main": "node ./lib/main.js", + "languages": "node ./lib/langParser.js", "clean": "rm -rf out/*", "dev": "webpack-dev-server --progress", - "bundle": "NODE_ENV=production webpack --progress", + "bundle": "set NODE_ENV=production && webpack --progress", "build": "npm run bundle && npm run gather && npm run scrape && npm run planet && npm run main && npm run generate", "build:clean": "npm run clean && npm run build", "test": "jest" @@ -27,6 +28,7 @@ "find-rss": "^1.6.4", "glob": "^7.1.2", "graphql-client": "^2.0.0", + "iso-639-1": "^2.0.3", "jquery": "^3.2.1", "jquery.i18n": "git+https://github.com/wikimedia/jquery.i18n.git", "json2yaml": "^1.1.0", @@ -53,6 +55,7 @@ "eslint-plugin-prettier": "^2.3.1", "expose-loader": "^0.7.4", "extract-text-webpack-plugin": "^3.0.2", + "generate-json-webpack-plugin": "^0.2.2", "jest": "^22.0.3", "mockdate": "^2.0.2", "postcss-loader": "^2.0.9", diff --git a/src/js/languages.json b/src/js/languages.json new file mode 100644 index 0000000..690089f --- /dev/null +++ b/src/js/languages.json @@ -0,0 +1 @@ +{"English":"en","Español":"es","Norsk bokmål":"nb_NO","język polski":"pl"} \ No newline at end of file diff --git a/src/js/locale.js b/src/js/locale.js index 4d8edfd..3f1eace 100644 --- a/src/js/locale.js +++ b/src/js/locale.js @@ -1,4 +1,5 @@ import init from './app' +const langs = require('./languages.json') var browserLocale @@ -26,12 +27,7 @@ function updateTranslation(localex) { } $(window).on('load', function() { - var localeOptions = { - English: 'en', - Español: 'es', - Polski: 'pl', - 'Norwegian Bokmål': 'nb_NO', - } + var localeOptions = langs var locList = $('#lang-select') $.each(localeOptions, function(key, value) { diff --git a/tests/__data__/test-languages.js b/tests/__data__/test-languages.js new file mode 100644 index 0000000..5d8152b --- /dev/null +++ b/tests/__data__/test-languages.js @@ -0,0 +1 @@ +export default {"Languages":{"English":"en","Español":"es","日本語":"ja-AK","Français":"fr"}} // eslint-disable-line \ No newline at end of file diff --git a/tests/lib/langParser.test.js b/tests/lib/langParser.test.js new file mode 100644 index 0000000..a6a8e63 --- /dev/null +++ b/tests/lib/langParser.test.js @@ -0,0 +1,22 @@ +/** + * langParser Library Test + */ + +const fs = require('fs') +const iso639 = require('iso-639-1') + +const testLangs = ['en', 'es', 'ja_AK', 'fr'] +const expectedLangs = ['English', 'Español', '日本語', 'Français'] + +describe('lib.langParser', () => { + it('should get nativeName for each language', () => { + const resultLangs = [] + testLangs.forEach(function(value) { + const normalizedName = value.split('_')[0] + const nativeName = iso639.getNativeName(normalizedName) + resultLangs.push(nativeName) + }) + + expect(resultLangs).toEqual(expectedLangs) + }) +}) diff --git a/webpack.config.js b/webpack.config.js index 14a4df9..460d53e 100644 --- a/webpack.config.js +++ b/webpack.config.js @@ -4,7 +4,9 @@ const CleanWebpackPlugin = require('clean-webpack-plugin') const CopyWebpackPlugin = require('copy-webpack-plugin') const ManifestPlugin = require('webpack-manifest-plugin') const UglifyJSPlugin = require('uglifyjs-webpack-plugin') +const GenerateJsonPlugin = require('generate-json-webpack-plugin') const path = require('path') +const generatedLangList = require('./lib/langParser') const isProduction = process.env.NODE_ENV === 'production' const hash = isProduction ? '.[hash]' : '' @@ -104,6 +106,7 @@ module.exports = { ]), new ExtractTextPlugin(`[name]${hash}.css`), new ManifestPlugin(), + new GenerateJsonPlugin('../src/js/languages.json', generatedLangList), ].concat( isProduction ? [