From 0c8cd3fbe952cb73875ae44a4ef0a6269079066b Mon Sep 17 00:00:00 2001 From: romulo bordezani Date: Tue, 11 Jun 2019 20:05:14 -0300 Subject: [PATCH] Language Detection implementation, bug fixes related to i18n and debugger helper added. --- extensions/ohif-i18n/package.json | 11 +-- extensions/ohif-i18n/rollup.config.js | 9 +++ extensions/ohif-i18n/src/config.js | 24 +++++++ extensions/ohif-i18n/src/debugger.js | 8 +++ extensions/ohif-i18n/src/index.js | 78 +++++++++++----------- extensions/ohif-i18n/yarn.lock | 14 ++++ extensions/ohif-vtk-extension/package.json | 1 + extensions/ohif-vtk-extension/yarn.lock | 6 ++ package.json | 3 +- src/App.js | 2 +- yarn.lock | 26 +++++--- 11 files changed, 125 insertions(+), 57 deletions(-) create mode 100644 extensions/ohif-i18n/src/config.js create mode 100644 extensions/ohif-i18n/src/debugger.js diff --git a/extensions/ohif-i18n/package.json b/extensions/ohif-i18n/package.json index 26ca6ae98..605094a2a 100644 --- a/extensions/ohif-i18n/package.json +++ b/extensions/ohif-i18n/package.json @@ -18,10 +18,10 @@ }, "peerDependencies": { "i18next": "^17.0.3", + "i18next-browser-languagedetector": "^3.0.1", "react": "^16.0.0", "react-dom": "^16.0.0", - "react-i18next": "^10.11.0", - "i18next-browser-languagedetector": "^3.0.1" + "react-i18next": "^10.11.0" }, "devDependencies": { "@babel/core": "^7.2.2", @@ -39,6 +39,7 @@ "eslint-plugin-react": "^7.11.1", "husky": "^1.3.1", "i18next": "^15.1.3", + "i18next-browser-languagedetector": "^3.0.1", "lint-staged": "^8.1.0", "prettier": "^1.15.3", "react": "^16.0.0", @@ -52,8 +53,7 @@ "rollup-plugin-node-resolve": "^4.0.0", "rollup-plugin-peer-deps-external": "^2.2.0", "rollup-plugin-postcss": "^2.0.3", - "rollup-plugin-url": "^2.1.0", - "i18next-browser-languagedetector": "^3.0.1" + "rollup-plugin-url": "^2.1.0" }, "husky": { "hooks": { @@ -80,6 +80,7 @@ }, "dependencies": { "@babel/runtime": "^7.2.0", - "classnames": "^2.2.6" + "classnames": "^2.2.6", + "rollup-plugin-json": "^4.0.0" } } diff --git a/extensions/ohif-i18n/rollup.config.js b/extensions/ohif-i18n/rollup.config.js index 10231e4ba..ef2ba0713 100644 --- a/extensions/ohif-i18n/rollup.config.js +++ b/extensions/ohif-i18n/rollup.config.js @@ -8,6 +8,7 @@ import pkg from './package.json'; // Deal with https://github.com/rollup/rollup-plugin-commonjs/issues/297 import builtins from 'rollup-plugin-node-builtins'; import copy from 'rollup-plugin-copy'; +import json from 'rollup-plugin-json'; const globals = { react: 'React', @@ -17,6 +18,7 @@ const globals = { 'prop-types': 'PropTypes', 'i18next': 'i18next', 'react-i18next': 'react-i18next', + 'i18next-browser-languagedetector': 'LngDetector' }; export default { @@ -48,6 +50,13 @@ export default { targets: ['src/locales'], outputFolder: 'dist', }), + json({ + // ignores indent and generates the smallest code + compact: true, // Default: false + + // generate a named export for every property of the JSON object + namedExports: true // Default: true + }), url(), babel({ exclude: 'node_modules/**', diff --git a/extensions/ohif-i18n/src/config.js b/extensions/ohif-i18n/src/config.js new file mode 100644 index 000000000..e9e1c1685 --- /dev/null +++ b/extensions/ohif-i18n/src/config.js @@ -0,0 +1,24 @@ +const debugMode = !!( + process.env.NODE_ENV !== 'production' && process.env.REACT_APP_I18N_DEBUG +); + +const detectionOptions = { + // order and from where user language should be detected + order: ['querystring', 'cookie', 'localStorage', 'navigator', 'htmlTag', 'path', 'subdomain'], + + // keys or params to lookup language from + lookupQuerystring: 'lng', + lookupCookie: 'i18next', + lookupLocalStorage: 'i18nextLng', + lookupFromPathIndex: 0, + lookupFromSubdomainIndex: 0, + + // cache user language on + caches: ['localStorage', 'cookie'], + excludeCacheFor: ['cimode'], // languages to not persist (cookie, localStorage) + + // optional htmlTag with lang attribute, the default is: + htmlTag: document.documentElement +}; + +export { debugMode, detectionOptions }; diff --git a/extensions/ohif-i18n/src/debugger.js b/extensions/ohif-i18n/src/debugger.js new file mode 100644 index 000000000..8fd2f6ef6 --- /dev/null +++ b/extensions/ohif-i18n/src/debugger.js @@ -0,0 +1,8 @@ +import { debugMode } from './config'; + +export default (message, level = 'log') => { + if (debugMode) { + // eslint-disable-next-line + console[level](message); + } +}; diff --git a/extensions/ohif-i18n/src/index.js b/extensions/ohif-i18n/src/index.js index 69b2b9f9d..f244d5be1 100755 --- a/extensions/ohif-i18n/src/index.js +++ b/extensions/ohif-i18n/src/index.js @@ -1,16 +1,11 @@ import i18n from 'i18next'; import { initReactI18next } from 'react-i18next'; import LngDetector from 'i18next-browser-languagedetector'; +import customDebug from './debugger'; +import pkg from '../package.json'; +import { debugMode, detectionOptions } from './config'; -const currentLanguage = process.env.REACT_APP_LANG || 'en-US'; -const debugMode = !!( - process.env.NODE_ENV !== 'production' && process.env.REACT_APP_I18N_DEBUG -); - -function getDefaultLanguage() { - const mainLanguage = currentLanguage.match(/(.*.)(-)/); - return mainLanguage !== null ? mainLanguage[1] : null; -} +let translate; function getNameSpaceString(key) { const nameSpaceMatcher = key.match(/[^/]+$/g); @@ -23,7 +18,7 @@ function getNameSpaceString(key) { return finalNameSpace; } -function getCleanKeyForNameSpaces(key) { +function getKeyForNameSpaces(key) { const cleanedKey = key.match(/[/\\].+(?=[/\\])/); let finalKey; @@ -40,8 +35,8 @@ function getLocales() { const locales = {}; context.keys().forEach(key => { - locales[getCleanKeyForNameSpaces(key)] = { - ...locales[getCleanKeyForNameSpaces(key)], + locales[getKeyForNameSpaces(key)] = { + ...locales[getKeyForNameSpaces(key)], [getNameSpaceString(key)]: context(key), }; }); @@ -52,43 +47,48 @@ function getLocales() { function addLocales(context) { context.keys().forEach(key => { i18n.addResourceBundle( - getCleanKeyForNameSpaces(key), + getKeyForNameSpaces(key), getNameSpaceString(key), context(key), true, true ); }); + customDebug(`Locales added successfully`, 'info'); } -let translate; +function initI18n(detection = detectionOptions) { + i18n + .use(LngDetector) + .use(initReactI18next) + .init({ + resources: getLocales(), + debug: debugMode, + keySeparator: false, + interpolation: { + escapeValue: false, + }, + detection, + fallbackNS: ['common'], + defaultNS: 'common', + react: { + wait: true, + }, + }) + .then(function(t) { + translate = t; + customDebug(`t function available.`, 'info'); + }); +} -i18n - .use(LngDetector) - .use(initReactI18next) - .init({ - resources: getLocales(), - fallbackLng: getDefaultLanguage(), +customDebug(`@ohif/i18n version ${pkg.version} loaded.`, 'info'); - lng: currentLanguage, - debug: debugMode, +initI18n(); - // have a common namespace used around the full app - keySeparator: false, // uses content as keys - interpolation: { - escapeValue: false, - }, +export { + translate as t, + addLocales, + initI18n +}; - fallbackNS: ['common'], - defaultNS: 'common', - - react: { - wait: true, - }, - }) - .then(function(t) { - translate = t; - }); - -export { translate as t, addLocales }; export default i18n; diff --git a/extensions/ohif-i18n/yarn.lock b/extensions/ohif-i18n/yarn.lock index 91116e353..89c09ec6d 100644 --- a/extensions/ohif-i18n/yarn.lock +++ b/extensions/ohif-i18n/yarn.lock @@ -4430,6 +4430,13 @@ rollup-plugin-copy@^2.0.1: fs-extra "^7.0.1" is-plain-object "^3.0.0" +rollup-plugin-json@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/rollup-plugin-json/-/rollup-plugin-json-4.0.0.tgz#a18da0a4b30bf5ca1ee76ddb1422afbb84ae2b9e" + integrity sha512-hgb8N7Cgfw5SZAkb3jf0QXii6QX/FOkiIq2M7BAQIEydjHvTyxXHQiIzZaTFgx1GK0cRCHOCBHIyEkkLdWKxow== + dependencies: + rollup-pluginutils "^2.5.0" + rollup-plugin-node-builtins@^2.1.2: version "2.1.2" resolved "https://registry.yarnpkg.com/rollup-plugin-node-builtins/-/rollup-plugin-node-builtins-2.1.2.tgz#24a1fed4a43257b6b64371d8abc6ce1ab14597e9" @@ -4491,6 +4498,13 @@ rollup-pluginutils@^2.0.1, rollup-pluginutils@^2.3.0, rollup-pluginutils@^2.3.3, dependencies: estree-walker "^0.6.1" +rollup-pluginutils@^2.5.0: + version "2.8.1" + resolved "https://registry.yarnpkg.com/rollup-pluginutils/-/rollup-pluginutils-2.8.1.tgz#8fa6dd0697344938ef26c2c09d2488ce9e33ce97" + integrity sha512-J5oAoysWar6GuZo0s+3bZ6sVZAC0pfqKz68De7ZgDi5z63jOVZn1uJL/+z1jeKHNbGII8kAyHF5q8LnxSX5lQg== + dependencies: + estree-walker "^0.6.1" + rollup@^1.1.2: version "1.13.1" resolved "https://registry.yarnpkg.com/rollup/-/rollup-1.13.1.tgz#86a474c29df0f303ed31e4c8be5d81c1038beae8" diff --git a/extensions/ohif-vtk-extension/package.json b/extensions/ohif-vtk-extension/package.json index 492862ec7..c307490e2 100644 --- a/extensions/ohif-vtk-extension/package.json +++ b/extensions/ohif-vtk-extension/package.json @@ -93,6 +93,7 @@ }, "dependencies": { "@babel/runtime": "^7.2.0", + "@ohif/i18n": "file:.yalc/@ohif/i18n", "classnames": "^2.2.6", "react-vtkjs-viewport": "^0.0.7" } diff --git a/extensions/ohif-vtk-extension/yarn.lock b/extensions/ohif-vtk-extension/yarn.lock index a109a0e37..aafd7402a 100644 --- a/extensions/ohif-vtk-extension/yarn.lock +++ b/extensions/ohif-vtk-extension/yarn.lock @@ -727,6 +727,12 @@ resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz#2b5a3ab3f918cca48a8c754c08168e3f03eba61b" integrity sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw== +"@ohif/i18n@file:.yalc/@ohif/i18n": + version "0.0.1-rc-003-62f0a044" + dependencies: + "@babel/runtime" "^7.2.0" + classnames "^2.2.6" + "@samverschueren/stream-to-observable@^0.3.0": version "0.3.0" resolved "https://registry.yarnpkg.com/@samverschueren/stream-to-observable/-/stream-to-observable-0.3.0.tgz#ecdf48d532c58ea477acfcab80348424f8d0662f" diff --git a/package.json b/package.json index 5eb2012f2..e44837be7 100644 --- a/package.json +++ b/package.json @@ -70,7 +70,7 @@ "@ohif/extension-cornerstone": "0.0.34", "@ohif/extension-dicom-microscopy": "0.0.6", "@ohif/extension-vtk": "file:.yalc/@ohif/extension-vtk", - "@ohif/i18n": "0.0.1-rc-001", + "@ohif/i18n": "file:.yalc/@ohif/i18n", "classnames": "^2.2.6", "cornerstone-core": "^2.2.8", "cornerstone-math": "^0.1.8", @@ -81,6 +81,7 @@ "dicomweb-client": "^0.4.2", "hammerjs": "^2.0.8", "i18next": "^17.0.3", + "i18next-browser-languagedetector": "^3.0.1", "lodash.isequal": "4.5.0", "moment": "^2.24.0", "ohif-core": "0.5.6", diff --git a/src/App.js b/src/App.js index 5c870d93b..3946c00d2 100644 --- a/src/App.js +++ b/src/App.js @@ -24,7 +24,7 @@ import WhiteLabellingContext from './WhiteLabellingContext'; import setupTools from './setupTools'; import ui from './redux/ui.js'; import i18n from '@ohif/i18n'; -import { I18nextProvider } from 'react-i18next'; +import { I18nextProvider } from 'react-i18next'; const { ExtensionManager } = OHIF.extensions; const { reducers, localStorage } = OHIF.redux; diff --git a/yarn.lock b/yarn.lock index b78114a5e..428ee2a02 100644 --- a/yarn.lock +++ b/yarn.lock @@ -1033,17 +1033,17 @@ classnames "^2.2.6" dicom-microscopy-viewer "^0.4.3" -"@ohif/extension-vtk@file:.yalc/@ohif/extension-vtk": - version "0.0.3-3bee9176" +"@ohif/extension-vtk@0.0.2": + version "0.0.2" + resolved "https://registry.yarnpkg.com/@ohif/extension-vtk/-/extension-vtk-0.0.2.tgz#99f0ea796ddae14d7e64cff958c0656b5d964f4e" + integrity sha512-WDuQVwK4RlHgXwbmKIECZrP90x8cVOwESQz8bJOeNG2eVPDBVlNWx/zOXShAhn6J62QG6Sn1RnHQWLedgGnhyA== dependencies: "@babel/runtime" "^7.2.0" classnames "^2.2.6" react-vtkjs-viewport "^0.0.7" -"@ohif/i18n@0.0.1-rc-001": - version "0.0.1-rc-001" - resolved "https://registry.yarnpkg.com/@ohif/i18n/-/i18n-0.0.1-rc-001.tgz#47286daa1411efb5f0219f0310484c8919bfe607" - integrity sha512-CJ9wqd15DpJ6adVMyXkyqQqcRZgSnMWJ7L3WyUpMqf66CvAFKzCUuckyiFeCupIq8ZGv7w4jaADSYKrLcpviUw== +"@ohif/i18n@file:.yalc/@ohif/i18n": + version "0.0.1-rc-003-18e6caf4" dependencies: "@babel/runtime" "^7.2.0" classnames "^2.2.6" @@ -6335,6 +6335,11 @@ husky@1.3.x: run-node "^1.0.0" slash "^2.0.0" +i18next-browser-languagedetector@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/i18next-browser-languagedetector/-/i18next-browser-languagedetector-3.0.1.tgz#a47c43176e8412c91e808afb7c6eb5367649aa8e" + integrity sha512-WFjPLNPWl62uu07AHY2g+KsC9qz0tyMq+OZEB/H7N58YKL/JLiCz9U709gaR20Mule/Ppn+uyfVx5REJJjn1HA== + i18next@^17.0.3: version "17.0.3" resolved "https://registry.yarnpkg.com/i18next/-/i18next-17.0.3.tgz#82d67826d13e8ca2cd2a3c87871533414e952d03" @@ -11788,13 +11793,13 @@ react-transition-group@^2.0.0, react-transition-group@^2.2.0: prop-types "^15.6.2" react-lifecycles-compat "^3.0.4" -"react-viewerbase@file:.yalc/react-viewerbase": - version "0.2.17-a5956254" +react-viewerbase@^0.7.0: + version "0.7.0" + resolved "https://registry.yarnpkg.com/react-viewerbase/-/react-viewerbase-0.7.0.tgz#b0f48a0f003b849c280b8ca67927d4780c68b0dc" + integrity sha512-1VQXREKSsqxtOSSHRou0gjBODrSOjE8SBJ6/dHG0gPgdmeotOg68xPMKYf9K7fYyGZ6CDA7oVCAmdTE4SVYP5Q== dependencies: "@babel/runtime" "7.2.0" - "@ohif/i18n" "0.0.1-rc-001" classnames "2.2.6" - i18next "^17.0.3" lodash.isequal "4.5.0" moment "2.24.0" prop-types "15.6.2" @@ -11802,7 +11807,6 @@ react-transition-group@^2.0.0, react-transition-group@^2.2.0: react-dates "18.4.1" react-dnd "7.0.2" react-dnd-html5-backend "7.0.2" - react-i18next "^10.11.0" react-with-direction "1.3.0" react-vtkjs-viewport@^0.0.7: