diff --git a/package-lock.json b/package-lock.json index def3d554565..f4ed2388a76 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4223,7 +4223,8 @@ "jsbn": { "version": "0.1.1", "bundled": true, - "dev": true + "dev": true, + "optional": true }, "json-schema": { "version": "0.2.3", diff --git a/src/app/accounts/settings.component.html b/src/app/accounts/settings.component.html index 3399272b19d..b8f20a4e967 100644 --- a/src/app/accounts/settings.component.html +++ b/src/app/accounts/settings.component.html @@ -42,6 +42,14 @@ {{'disableFaviconDesc' | i18n}} +
+ + + {{'languageDesc' | i18n}} +
diff --git a/src/app/accounts/settings.component.ts b/src/app/accounts/settings.component.ts index aaf2763582e..a694f9710ea 100644 --- a/src/app/accounts/settings.component.ts +++ b/src/app/accounts/settings.component.ts @@ -15,6 +15,8 @@ import { StorageService } from 'jslib/abstractions/storage.service'; import { ConstantsService } from 'jslib/services/constants.service'; +import { SupportedTranslationLocales } from '../../services/i18n.service'; + @Component({ selector: 'app-settings', templateUrl: 'settings.component.html', @@ -24,6 +26,8 @@ export class SettingsComponent implements OnInit { lockOption: number = null; disableGa: boolean = false; disableFavicons: boolean = false; + locales: any[]; + locale: string; constructor(private analytics: Angulartics2, private toasterService: ToasterService, private i18nService: I18nService, private platformUtilsService: PlatformUtilsService, @@ -43,11 +47,17 @@ export class SettingsComponent implements OnInit { { name: i18nService.t('onRestart'), value: -1 }, { name: i18nService.t('never'), value: null }, ]; + + this.locales = [ { locale: null, language: 'Default' } ]; + Object.keys(SupportedTranslationLocales).forEach((localId) => { + this.locales.push({locale: localId, language: i18nService.t(localId)}); + }); } async ngOnInit() { this.lockOption = await this.storageService.get(ConstantsService.lockOptionKey); this.disableFavicons = await this.storageService.get(ConstantsService.disableFaviconKey); + this.locale = await this.storageService.get('locale'); const disableGa = await this.storageService.get(ConstantsService.disableGaKey); const disableGaByDefault = this.platformUtilsService.isFirefox() || this.platformUtilsService.isMacAppStore(); @@ -79,4 +89,8 @@ export class SettingsComponent implements OnInit { const status = enabled ? 'Enabled' : 'Disabled'; this.analytics.eventTrack.next({ action: `${status} ${name}` }); } + + async saveLocale() { + await this.storageService.save('locale', this.locale); + } } diff --git a/src/app/services/services.module.ts b/src/app/services/services.module.ts index 1ac8d2052b4..dc0305b5fbb 100644 --- a/src/app/services/services.module.ts +++ b/src/app/services/services.module.ts @@ -110,7 +110,7 @@ environmentService.setUrlsFromStorage().then(() => { export function initFactory(): Function { return async () => { - await i18nService.init(); + await i18nService.init(await storageService.get('locale')); await authService.init(); const htmlEl = window.document.documentElement; htmlEl.classList.add('os_' + platformUtilsService.getDeviceString()); diff --git a/src/locales/en/messages.json b/src/locales/en/messages.json index 13c10312099..655d431af8e 100644 --- a/src/locales/en/messages.json +++ b/src/locales/en/messages.json @@ -770,6 +770,12 @@ "disableFaviconDesc": { "message": "Website Icons provide a recognizable image next to each login item in your vault." }, + "language": { + "message": "Language" + }, + "languageDesc": { + "message": "Change language. Require restart." + }, "copy": { "message": "Copy", "description": "Copy to clipboard" diff --git a/src/main.ts b/src/main.ts index 9da77e2bccf..229f2009730 100644 --- a/src/main.ts +++ b/src/main.ts @@ -62,15 +62,17 @@ export class Main { } bootstrap() { - this.windowMain.init().then(async () => { - await this.i18nService.init(app.getLocale()); - this.messagingMain.init(); - this.menuMain.init(); - this.powerMonitorMain.init(); - await this.updaterMain.init(); - }, (e: any) => { - // tslint:disable-next-line - console.error(e); + this.storageService.get('locale').then(async (locale) => { + this.windowMain.init().then(async () => { + await this.i18nService.init(locale !== null ? locale : app.getLocale()); + this.messagingMain.init(); + this.menuMain.init(); + this.powerMonitorMain.init(); + await this.updaterMain.init(); + }, (e: any) => { + // tslint:disable-next-line + console.error(e); + }); }); } } diff --git a/src/services/i18n.service.ts b/src/services/i18n.service.ts index 589e50979d6..690bba0c487 100644 --- a/src/services/i18n.service.ts +++ b/src/services/i18n.service.ts @@ -4,7 +4,7 @@ import * as path from 'path'; import { I18nService as I18nServiceAbstraction } from 'jslib/abstractions/i18n.service'; // First locale is the default (English) -const SupportedTranslationLocales = [ +export const SupportedTranslationLocales = [ 'en', 'cs', 'da', 'de', 'es', 'et', 'fi', 'fr', 'hr', 'hu', 'id', 'it', 'ja', 'nb', 'nl', 'pl', 'pt-BR', 'pt-PT', 'ro', 'ru', 'sk', 'sv', 'tr', 'uk', 'vi', 'zh-CN', 'zh-TW',