thingsboard-aplcache
Merge pull request #941 from dyosick/simplify-localizations-management Simplify …
Changes
ui/package.json 16(+9 -7)
ui/src/app/app.config.js 72(+33 -39)
ui/src/app/app.js 4(+2 -2)
ui/src/app/locale/locale.constant-en_US.json 2929(+1454 -1475)
ui/src/app/locale/locale.constant-es_ES.json 2624(+1304 -1320)
ui/src/app/locale/locale.constant-it_IT.json 2900(+1441 -1459)
ui/src/app/locale/locale.constant-ko_KR.json 2665(+1325 -1340)
ui/src/app/locale/locale.constant-ru_RU.json 2724(+1354 -1370)
ui/src/app/locale/locale.constant-zh_CN.json 2907(+1445 -1462)
ui/src/app/profile/profile.tpl.html 4(+2 -2)
ui/webpack.config.dev.js 30(+27 -3)
ui/webpack.config.prod.js 32(+28 -4)
Details
ui/package.json 16(+9 -7)
diff --git a/ui/package.json b/ui/package.json
index a4b0e4d..4959237 100644
--- a/ui/package.json
+++ b/ui/package.json
@@ -36,12 +36,12 @@
"angular-socialshare": "^2.3.8",
"angular-storage": "0.0.15",
"angular-touch": "1.5.8",
- "angular-translate": "2.13.1",
- "angular-translate-handler-log": "2.13.1",
- "angular-translate-interpolation-messageformat": "2.13.1",
- "angular-translate-loader-static-files": "2.13.1",
- "angular-translate-storage-cookie": "2.13.1",
- "angular-translate-storage-local": "2.13.1",
+ "angular-translate": "2.18.1",
+ "angular-translate-handler-log": "2.18.1",
+ "angular-translate-interpolation-messageformat": "2.18.1",
+ "angular-translate-loader-static-files": "2.18.1",
+ "angular-translate-storage-cookie": "2.18.1",
+ "angular-translate-storage-local": "2.18.1",
"angular-ui-ace": "^0.2.3",
"angular-ui-router": "^0.3.1",
"angular-websocket": "^2.0.1",
@@ -127,7 +127,9 @@
"webpack-dev-middleware": "^1.6.1",
"webpack-dev-server": "^1.15.1",
"webpack-hot-middleware": "^2.12.2",
- "webpack-material-design-icons": "^0.1.0"
+ "webpack-material-design-icons": "^0.1.0",
+ "directory-tree": "^2.1.0",
+ "jsonminify": "^0.4.1"
},
"engine": "node >= 5.9.0",
"nyc": {
ui/src/app/app.config.js 72(+33 -39)
diff --git a/ui/src/app/app.config.js b/ui/src/app/app.config.js
index a84bdde..3ae2122 100644
--- a/ui/src/app/app.config.js
+++ b/ui/src/app/app.config.js
@@ -15,10 +15,6 @@
*/
import injectTapEventPlugin from 'react-tap-event-plugin';
import UrlHandler from './url.handler';
-import addLocaleKorean from './locale/locale.constant-ko';
-import addLocaleChinese from './locale/locale.constant-zh';
-import addLocaleRussian from './locale/locale.constant-ru';
-import addLocaleSpanish from './locale/locale.constant-es';
/* eslint-disable import/no-unresolved, import/default */
@@ -38,46 +34,24 @@ export default function AppConfig($provide,
$mdThemingProvider,
$httpProvider,
$translateProvider,
- storeProvider,
- locales) {
+ storeProvider) {
injectTapEventPlugin();
$locationProvider.html5Mode(true);
$urlRouterProvider.otherwise(UrlHandler);
storeProvider.setCaching(false);
-
- $translateProvider.useSanitizeValueStrategy(null);
- $translateProvider.useMissingTranslationHandler('tbMissingTranslationHandler');
- $translateProvider.addInterpolation('$translateMessageFormatInterpolation');
- $translateProvider.fallbackLanguage('en_US');
-
- addLocaleKorean(locales);
- addLocaleChinese(locales);
- addLocaleRussian(locales);
- addLocaleSpanish(locales);
-
- for (var langKey in locales) {
- var translationTable = locales[langKey];
- $translateProvider.translations(langKey, translationTable);
- }
-
- var lang = $translateProvider.resolveClientLocale();
- if (lang) {
- lang = lang.toLowerCase();
- if (lang.startsWith('ko')) {
- $translateProvider.preferredLanguage('ko_KR');
- } else if (lang.startsWith('zh')) {
- $translateProvider.preferredLanguage('zh_CN');
- } else if (lang.startsWith('es')) {
- $translateProvider.preferredLanguage('es_ES');
- } else if (lang.startsWith('ru')) {
- $translateProvider.preferredLanguage('ru_RU');
- } else {
- $translateProvider.preferredLanguage('en_US');
- }
- } else {
- $translateProvider.preferredLanguage('en_US');
- }
+
+ $translateProvider.useSanitizeValueStrategy(null)
+ .useMissingTranslationHandler('tbMissingTranslationHandler')
+ .addInterpolation('$translateMessageFormatInterpolation')
+ .useStaticFilesLoader({
+ prefix: PUBLIC_PATH + 'locale/locale.constant-', //eslint-disable-line
+ suffix: '.json'
+ })
+ .registerAvailableLanguageKeys(SUPPORTED_LANGS, getLanguageAliases(SUPPORTED_LANGS)) //eslint-disable-line
+ .fallbackLanguage('en_US') // must be before determinePreferredLanguage
+ .uniformLanguageTag('java') // must be before determinePreferredLanguage
+ .determinePreferredLanguage();
$httpProvider.interceptors.push('globalInterceptor');
@@ -168,4 +142,24 @@ export default function AppConfig($provide,
//$mdThemingProvider.alwaysWatchTheme(true);
}
+ function getLanguageAliases(supportedLangs) {
+ var aliases = {};
+
+ supportedLangs.sort().forEach(function(item, index, array) {
+ if (item.length === 2) {
+ aliases[item] = item;
+ aliases[item + '_*'] = item;
+ } else {
+ var key = item.slice(0, 2);
+ if (index === 0 || key !== array[index - 1].slice(0, 2)) {
+ aliases[key] = item;
+ aliases[key + '_*'] = item;
+ } else {
+ aliases[item] = item;
+ }
+ }
+ });
+
+ return aliases;
+ }
}
\ No newline at end of file
ui/src/app/app.js 4(+2 -2)
diff --git a/ui/src/app/app.js b/ui/src/app/app.js
index f021efb..c8cdeb0 100644
--- a/ui/src/app/app.js
+++ b/ui/src/app/app.js
@@ -51,7 +51,7 @@ import react from 'ngreact';
import '@flowjs/ng-flow/dist/ng-flow-standalone.min';
import 'ngFlowchart/dist/ngFlowchart';
-import thingsboardLocales from './locale/locale.constant';
+import thingsboardTranslateHandler from './locale/translate-handler';
import thingsboardLogin from './login';
import thingsboardDialogs from './components/datakey-config-dialog.controller';
import thingsboardMenu from './services/menu.service';
@@ -117,7 +117,7 @@ angular.module('thingsboard', [
react.name,
'flow',
'flowchart',
- thingsboardLocales,
+ thingsboardTranslateHandler,
thingsboardLogin,
thingsboardDialogs,
thingsboardMenu,
diff --git a/ui/src/app/locale/translate-handler.js b/ui/src/app/locale/translate-handler.js
index 11feb00..9fb28f5 100644
--- a/ui/src/app/locale/translate-handler.js
+++ b/ui/src/app/locale/translate-handler.js
@@ -13,8 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+ export default angular.module('thingsboard.locale', [])
+ .factory('tbMissingTranslationHandler', ThingsboardMissingTranslateHandler)
+ .name;
+
/*@ngInject*/
-export default function ThingsboardMissingTranslateHandler($log, types) {
+function ThingsboardMissingTranslateHandler($log, types) {
return function (translationId) {
if (translationId && !translationId.startsWith(types.translate.customTranslationsPrefix)) {
diff --git a/ui/src/app/profile/profile.controller.js b/ui/src/app/profile/profile.controller.js
index d17a65a..b947bde 100644
--- a/ui/src/app/profile/profile.controller.js
+++ b/ui/src/app/profile/profile.controller.js
@@ -24,16 +24,9 @@ export default function ProfileController(userService, $scope, $document, $mdDia
var vm = this;
vm.profileUser = {};
-
vm.save = save;
vm.changePassword = changePassword;
- vm.languageList = {
- en_US: {value : "en_US", name: "language.en_US"},
- ko_KR: {value : "ko_KR", name: "language.ko_KR"},
- zh_CN: {value : "zh_CN", name: "language.zh_CN"},
- ru_RU: {value : "ru_RU", name: "language.ru_RU"},
- es_ES: {value : "es_ES", name: "language.es_ES"},
- };
+ vm.languageList = SUPPORTED_LANGS; //eslint-disable-line
loadProfile();
ui/src/app/profile/profile.tpl.html 4(+2 -2)
diff --git a/ui/src/app/profile/profile.tpl.html b/ui/src/app/profile/profile.tpl.html
index a0358c1..58e4aac 100644
--- a/ui/src/app/profile/profile.tpl.html
+++ b/ui/src/app/profile/profile.tpl.html
@@ -43,8 +43,8 @@
<md-input-container class="md-block">
<label translate>language.language</label>
<md-select name="language" ng-model="vm.profileUser.additionalInfo.lang">
- <md-option ng-repeat="lang in vm.languageList" ng-value="lang.value">
- {{lang.name | translate}}
+ <md-option ng-repeat="lang in vm.languageList" ng-value="lang">
+ {{ 'language.locales.' + lang | translate}}
</md-option>
</md-select>
</md-input-container>
ui/webpack.config.dev.js 30(+27 -3)
diff --git a/ui/webpack.config.dev.js b/ui/webpack.config.dev.js
index b1a1911..7d2b0d3 100644
--- a/ui/webpack.config.dev.js
+++ b/ui/webpack.config.dev.js
@@ -20,6 +20,17 @@ const ExtractTextPlugin = require('extract-text-webpack-plugin');
const CopyWebpackPlugin = require('copy-webpack-plugin');
const webpack = require('webpack');
const path = require('path');
+const dirTree = require('directory-tree');
+const jsonminify = require("jsonminify");
+
+const PUBLIC_RESOURCE_PATH = '/';
+
+var langs = [];
+dirTree('./src/app/locale/', {extensions:/\.json$/}, (item) => {
+ /* It is expected what the name of a locale file has the following format: */
+ /* 'locale.constant-LANG_CODE[_REGION_CODE].json', e.g. locale.constant-es.json or locale.constant-zh_CN.json*/
+ langs.push(item.name.slice(item.name.lastIndexOf('-') + 1, -5));
+});
/* devtool: 'cheap-module-eval-source-map', */
@@ -32,7 +43,7 @@ module.exports = {
],
output: {
path: path.resolve(__dirname, 'target/generated-resources/public/static'),
- publicPath: '/',
+ publicPath: PUBLIC_RESOURCE_PATH,
filename: 'bundle.js',
},
plugins: [
@@ -45,7 +56,18 @@ module.exports = {
moment: "moment"
}),
new CopyWebpackPlugin([
- { from: './src/thingsboard.ico', to: 'thingsboard.ico' }
+ {
+ from: './src/thingsboard.ico',
+ to: 'thingsboard.ico'
+ },
+ {
+ from: './src/app/locale',
+ to: 'locale',
+ ignore: [ '*.js' ],
+ transform: function(content, path) {
+ return Buffer.from(jsonminify(content.toString()));
+ }
+ }
]),
new webpack.HotModuleReplacementPlugin(),
new HtmlWebpackPlugin({
@@ -65,6 +87,8 @@ module.exports = {
'process.env': {
NODE_ENV: JSON.stringify('development'),
},
+ PUBLIC_PATH: PUBLIC_RESOURCE_PATH,
+ SUPPORTED_LANGS: JSON.stringify(langs)
}),
],
node: {
@@ -117,7 +141,7 @@ module.exports = {
'url?limit=8192',
'img?minimize'
]
- },
+ }
],
},
'html-minifier-loader': {
ui/webpack.config.prod.js 32(+28 -4)
diff --git a/ui/webpack.config.prod.js b/ui/webpack.config.prod.js
index f02b880..a442590 100644
--- a/ui/webpack.config.prod.js
+++ b/ui/webpack.config.prod.js
@@ -21,6 +21,17 @@ const CopyWebpackPlugin = require('copy-webpack-plugin');
const CompressionPlugin = require('compression-webpack-plugin');
const webpack = require('webpack');
const path = require('path');
+const dirTree = require('directory-tree');
+const jsonminify = require("jsonminify");
+
+const PUBLIC_RESOURCE_PATH = '/static/';
+
+var langs = [];
+dirTree('./src/app/locale/', {extensions:/\.json$/}, (item) => {
+ /* It is expected what the name of a locale file has the following format: */
+ /* 'locale.constant-LANG_CODE[_REGION_CODE].json', e.g. locale.constant-es.json or locale.constant-zh_CN.json*/
+ langs.push(item.name.slice(item.name.lastIndexOf('-') + 1, -5));
+});
module.exports = {
devtool: 'source-map',
@@ -30,7 +41,7 @@ module.exports = {
],
output: {
path: path.resolve(__dirname, 'target/generated-resources/public/static'),
- publicPath: '/static/',
+ publicPath: PUBLIC_RESOURCE_PATH,
filename: 'bundle.[hash].js',
},
plugins: [
@@ -43,7 +54,18 @@ module.exports = {
moment: "moment"
}),
new CopyWebpackPlugin([
- {from: './src/thingsboard.ico', to: 'thingsboard.ico'}
+ {
+ from: './src/thingsboard.ico',
+ to: 'thingsboard.ico'
+ },
+ {
+ from: './src/app/locale',
+ to: 'locale',
+ ignore: [ '*.js' ],
+ transform: function(content, path) {
+ return Buffer.from(jsonminify(content.toString()));
+ }
+ }
]),
new HtmlWebpackPlugin({
template: './src/index.html',
@@ -64,11 +86,13 @@ module.exports = {
'process.env': {
NODE_ENV: JSON.stringify('production'),
},
+ PUBLIC_PATH: PUBLIC_RESOURCE_PATH,
+ SUPPORTED_LANGS: JSON.stringify(langs)
}),
new CompressionPlugin({
asset: "[path].gz[query]",
algorithm: "gzip",
- test: /\.js$|\.css$|\.svg$|\.ttf$|\.woff$|\.woff2|\.eot$/,
+ test: /\.js$|\.css$|\.svg$|\.ttf$|\.woff$|\.woff2|\.eot$\.json$/,
threshold: 10240,
minRatio: 0.8
})
@@ -123,7 +147,7 @@ module.exports = {
'url?limit=8192',
'img?minimize'
]
- },
+ }
],
},
'html-minifier-loader': {