diff --git a/client/pages/config/index.vue b/client/pages/config/index.vue index 881f77b6..526edaa0 100644 --- a/client/pages/config/index.vue +++ b/client/pages/config/index.vue @@ -72,9 +72,14 @@ -
-

{{ $strings.LabelSettingsDateFormat }}

- +
+

{{ $strings.LabelSettingsDateFormat }}

+ +
+ +
+

{{ $strings.LabelLanguageDefaultServer }}

+
@@ -321,6 +326,10 @@ export default { bookshelfView: !val ? this.$constants.BookshelfView.DETAIL : this.$constants.BookshelfView.STANDARD }) }, + updateServerLanguage(val) { + this.$setLanguageCode(val) + this.updateSettingsKey('language', val) + }, updateSettingsKey(key, val) { this.updateServerSettings({ [key]: val diff --git a/client/pages/login.vue b/client/pages/login.vue index 94e9f38b..2f5c4e75 100644 --- a/client/pages/login.vue +++ b/client/pages/login.vue @@ -128,6 +128,7 @@ export default { this.$store.commit('setServerSettings', serverSettings) this.$store.commit('setSource', Source) this.$store.commit('feeds/setFeeds', feeds) + this.$setServerLanguageCode(serverSettings.language) if (serverSettings.chromecastEnabled) { console.log('Chromecast enabled import script') @@ -189,6 +190,7 @@ export default { this.processing = false this.isInit = res.isInit this.showInitScreen = !res.isInit + this.$setServerLanguageCode(res.language) if (this.showInitScreen) { this.ConfigPath = res.ConfigPath || '' this.MetadataPath = res.MetadataPath || '' diff --git a/client/plugins/i18n.js b/client/plugins/i18n.js index 7e105225..123b216f 100644 --- a/client/plugins/i18n.js +++ b/client/plugins/i18n.js @@ -1,20 +1,31 @@ import Vue from "vue" import enUsStrings from '../strings/en-us.json' +import { supplant } from './utils' const defaultCode = 'en-us' -function supplant(str, subs) { - // source: http://crockford.com/javascript/remedial.html - return str.replace(/{([^{}]*)}/g, - function (a, b) { - var r = subs[b] - return typeof r === 'string' || typeof r === 'number' ? r : a - } - ) +const languageCodeMap = { + 'en-us': 'English', + 'es': 'Español', + 'it': 'Italiano', + 'pl': 'Polski', + 'zh-cn': '汉语 (简化字)' +} +Vue.prototype.$languageCodeOptions = Object.keys(languageCodeMap).map(code => { + return { + text: languageCodeMap[code], + value: code + } +}) + +Vue.prototype.$languageCodes = { + default: defaultCode, + current: defaultCode, + local: null, + server: null } -Vue.prototype.$i18nCode = '' -Vue.prototype.$strings = enUsStrings +Vue.prototype.$strings = { ...enUsStrings } Vue.prototype.$getString = (key, subs) => { if (!Vue.prototype.$strings[key]) return '' if (subs && Array.isArray(subs) && subs.length) { @@ -39,28 +50,58 @@ function loadTranslationStrings(code) { } async function loadi18n(code) { - if (Vue.prototype.$i18nCode == code) { + if (!code) return false + if (Vue.prototype.$languageCodes.current == code) { // already set - return + return false } + const strings = translations[code] || await loadTranslationStrings(code) if (!strings) { console.warn(`Invalid lang code ${code}`) - return + return false } translations[code] = strings - Vue.prototype.$i18nCode = code + Vue.prototype.$languageCodes.current = code + localStorage.setItem('lang', code) for (const key in Vue.prototype.$strings) { Vue.prototype.$strings[key] = strings[key] || translations[defaultCode][key] } + console.log('i18n strings=', Vue.prototype.$strings) + return true } -Vue.prototype.$i18nUpdate = loadi18n +Vue.prototype.$setLanguageCode = loadi18n + +// Set the servers default language code, does not override users local language code +Vue.prototype.$setServerLanguageCode = (code) => { + if (!code) return + + if (!languageCodeMap[code]) { + console.warn('invalid server language in', code) + } else { + Vue.prototype.$languageCodes.server = code + if (!Vue.prototype.$languageCodes.local && code !== defaultCode) { + loadi18n(code) + } + } +} + +// Initialize with language code in localStorage if valid +async function initialize() { + const localLanguage = localStorage.getItem('lang') + if (!localLanguage) return + + if (!languageCodeMap[localLanguage]) { + console.warn('Invalid local language code', localLanguage) + localStorage.setItem('lang', defaultCode) + } else if (localLanguage !== defaultCode) { + Vue.prototype.$languageCodes.local = localLanguage + loadi18n(localLanguage) + } +} +initialize() -const localLanguage = localStorage.getItem('lang') -if (localLanguage !== defaultCode) { - loadi18n(localLanguage) -} \ No newline at end of file diff --git a/client/plugins/utils.js b/client/plugins/utils.js index 6c29682b..7c7d196b 100644 --- a/client/plugins/utils.js +++ b/client/plugins/utils.js @@ -134,4 +134,14 @@ Vue.prototype.$parseCronExpression = (expression) => { return { description: `Run every ${weekdayText} at ${pieces[1]}:${pieces[0].padStart(2, '0')}` } +} + +export function supplant(str, subs) { + // source: http://crockford.com/javascript/remedial.html + return str.replace(/{([^{}]*)}/g, + function (a, b) { + var r = subs[b] + return typeof r === 'string' || typeof r === 'number' ? r : a + } + ) } \ No newline at end of file diff --git a/client/strings/en-us.json b/client/strings/en-us.json index a78e32c6..5c4083d7 100644 --- a/client/strings/en-us.json +++ b/client/strings/en-us.json @@ -204,6 +204,7 @@ "LabelInvalidParts": "Invalid Parts", "LabelItem": "Item", "LabelLanguage": "Language", + "LabelLanguageDefaultServer": "Default Server Language", "LabelLastSeen": "Last Seen", "LabelLastTime": "Last Time", "LabelLastUpdate": "Last Update", diff --git a/client/strings/zh-ch.json b/client/strings/zh-cn.json similarity index 99% rename from client/strings/zh-ch.json rename to client/strings/zh-cn.json index 3311a57e..9000d267 100644 --- a/client/strings/zh-ch.json +++ b/client/strings/zh-cn.json @@ -1,5 +1,5 @@ { - "ButtonHome": "Home", + "ButtonHome": "主页", "ButtonLatest": "Latest", "ButtonLibrary": "Library", "ButtonSeries": "Series", diff --git a/server/Server.js b/server/Server.js index b03feb6d..b51e0cd8 100644 --- a/server/Server.js +++ b/server/Server.js @@ -254,7 +254,8 @@ class Server { // status check for client to see if server has been initialized // server has been initialized if a root user exists const payload = { - isInit: this.db.hasRootUser + isInit: this.db.hasRootUser, + language: this.db.serverSettings.language } if (!payload.isInit) { payload.ConfigPath = global.ConfigPath diff --git a/server/objects/settings/ServerSettings.js b/server/objects/settings/ServerSettings.js index 8407e907..cb4b0fae 100644 --- a/server/objects/settings/ServerSettings.js +++ b/server/objects/settings/ServerSettings.js @@ -53,6 +53,7 @@ class ServerSettings { this.chromecastEnabled = false this.enableEReader = false this.dateFormat = 'MM/dd/yyyy' + this.language = 'en-us' this.logLevel = Logger.logLevel @@ -102,6 +103,7 @@ class ServerSettings { this.chromecastEnabled = !!settings.chromecastEnabled this.enableEReader = !!settings.enableEReader this.dateFormat = settings.dateFormat || 'MM/dd/yyyy' + this.language = settings.language || 'en-us' this.logLevel = settings.logLevel || Logger.logLevel this.version = settings.version || null @@ -153,6 +155,7 @@ class ServerSettings { chromecastEnabled: this.chromecastEnabled, enableEReader: this.enableEReader, dateFormat: this.dateFormat, + language: this.language, logLevel: this.logLevel, version: this.version }