From 8a2cd2ca9ae721f0458b86b7c99c6ec30c473277 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 --- .gitignore | 1 + lib/langParser.js | 20 ++++++++ package-lock.json | 65 +++++++++----------------- package.json | 4 +- src/js/locale.js | 8 +--- static/i18n/{nb_NO.json => nb-NO.json} | 0 tests/__data__/test-languages.js | 1 + tests/lib/langParser.test.js | 42 +++++++++++++++++ 8 files changed, 90 insertions(+), 51 deletions(-) create mode 100644 lib/langParser.js rename static/i18n/{nb_NO.json => nb-NO.json} (100%) create mode 100644 tests/__data__/test-languages.js create mode 100644 tests/lib/langParser.test.js diff --git a/.gitignore b/.gitignore index ecc771a..3240af4 100644 --- a/.gitignore +++ b/.gitignore @@ -3,3 +3,4 @@ out yarn.lock .DS_Store **.orig +src/js/languages.js diff --git a/lib/langParser.js b/lib/langParser.js new file mode 100644 index 0000000..6ef22f5 --- /dev/null +++ b/lib/langParser.js @@ -0,0 +1,20 @@ +const fs = require('fs') +const iso639 = require('iso-639-1') + +fs.readdir(`${__dirname}/../static/i18n`, (err, items) => { + const availableLanguages = { + Languages: {}, + } + items.forEach(function(value) { + const langName = value.substring(0, value.indexOf('.')) + const normalizedName = langName.split('-')[0] + const nativeName = iso639.getNativeName(normalizedName) + availableLanguages['Languages'][nativeName] = langName + }) + fs.writeFileSync( + `${__dirname}/../src/js/languages.js`, + 'export default ' + + JSON.stringify(availableLanguages) + + ' // eslint-disable-line' + ) +}) diff --git a/package-lock.json b/package-lock.json index 15d3fe5..c286332 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", @@ -3792,7 +3784,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 +4253,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 +4568,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 +4915,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 +5561,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 +5790,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 +5914,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 +6490,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 +7450,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 +8367,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 +8786,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 +9215,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 +9634,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..274e0d1 100644 --- a/package.json +++ b/package.json @@ -9,10 +9,11 @@ "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", - "build": "npm run bundle && npm run gather && npm run scrape && npm run planet && npm run main && npm run generate", + "build": "npm run languages && 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", diff --git a/src/js/locale.js b/src/js/locale.js index 4d8edfd..7037b6d 100644 --- a/src/js/locale.js +++ b/src/js/locale.js @@ -1,4 +1,5 @@ import init from './app' +import Languages from './languages' 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 = Languages['Languages'] var locList = $('#lang-select') $.each(localeOptions, function(key, value) { diff --git a/static/i18n/nb_NO.json b/static/i18n/nb-NO.json similarity index 100% rename from static/i18n/nb_NO.json rename to static/i18n/nb-NO.json 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..4c59bf8 --- /dev/null +++ b/tests/lib/langParser.test.js @@ -0,0 +1,42 @@ +/** + * 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) + }) + + it('should create a file given language codes', () => { + const langDict = { + Languages: {}, + } + testLangs.forEach(function(value) { + const normalizedName = value.split('-')[0] + const nativeName = iso639.getNativeName(normalizedName) + langDict['Languages'][nativeName] = value + }) + + const expectedData = fs + .readFileSync(`${__dirname}/../__data__/test-languages.js`) + .toString() + + const output = + 'export default ' + JSON.stringify(langDict) + ' // eslint-disable-line' + + expect(output).toEqual(expectedData) + }) +})