mirror of
https://github.com/bitwarden/browser.git
synced 2024-12-26 17:08:33 +01:00
converted i18nservice properly
This commit is contained in:
parent
222b58f440
commit
3ebb09fa8d
@ -60,8 +60,7 @@ import AutofillService from '../services/autofill.service';
|
||||
import BrowserMessagingService from '../services/browserMessaging.service';
|
||||
import BrowserPlatformUtilsService from '../services/browserPlatformUtils.service';
|
||||
import BrowserStorageService from '../services/browserStorage.service';
|
||||
import i18nService from '../services/i18n.service';
|
||||
import I18n2Service from '../services/i18n2.service';
|
||||
import I18nService from '../services/i18n.service';
|
||||
|
||||
import { AutofillService as AutofillServiceAbstraction } from '../services/abstractions/autofill.service';
|
||||
|
||||
@ -69,8 +68,7 @@ export default class MainBackground {
|
||||
messagingService: MessagingServiceAbstraction;
|
||||
storageService: StorageServiceAbstraction;
|
||||
secureStorageService: StorageServiceAbstraction;
|
||||
i18nService: any;
|
||||
i18n2Service: I18nServiceAbstraction;
|
||||
i18nService: I18nServiceAbstraction;
|
||||
platformUtilsService: PlatformUtilsServiceAbstraction;
|
||||
utilsService: UtilsServiceAbstraction;
|
||||
constantsService: ConstantsService;
|
||||
@ -117,12 +115,10 @@ export default class MainBackground {
|
||||
this.utilsService = new UtilsService();
|
||||
this.messagingService = new BrowserMessagingService();
|
||||
this.platformUtilsService = new BrowserPlatformUtilsService(this.messagingService);
|
||||
const delayi18nLoad = this.platformUtilsService.isEdge() || this.platformUtilsService.isSafari() ? 1000 : 0;
|
||||
this.storageService = new BrowserStorageService(this.platformUtilsService, false);
|
||||
this.secureStorageService = new BrowserStorageService(this.platformUtilsService, true);
|
||||
this.i18nService = i18nService(this.platformUtilsService);
|
||||
this.i18n2Service = new I18n2Service(window.navigator.language, this.i18nService);
|
||||
this.constantsService = new ConstantsService(this.i18nService, delayi18nLoad);
|
||||
this.i18nService = new I18nService(BrowserApi.getUILanguage(window),
|
||||
BrowserApi.isSafariApi ? './_locales/' : null);
|
||||
this.cryptoService = new CryptoService(this.storageService, this.secureStorageService);
|
||||
this.tokenService = new TokenService(this.storageService);
|
||||
this.appIdService = new AppIdService(this.storageService);
|
||||
@ -132,11 +128,11 @@ export default class MainBackground {
|
||||
this.userService = new UserService(this.tokenService, this.storageService);
|
||||
this.settingsService = new SettingsService(this.userService, this.storageService);
|
||||
this.cipherService = new CipherService(this.cryptoService, this.userService, this.settingsService,
|
||||
this.apiService, this.storageService, this.i18n2Service, this.platformUtilsService, this.utilsService);
|
||||
this.apiService, this.storageService, this.i18nService, this.platformUtilsService, this.utilsService);
|
||||
this.folderService = new FolderService(this.cryptoService, this.userService,
|
||||
() => this.i18nService.noneFolder, this.apiService, this.storageService, this.i18n2Service);
|
||||
() => this.i18nService.t('noneFolder'), this.apiService, this.storageService, this.i18nService);
|
||||
this.collectionService = new CollectionService(this.cryptoService, this.userService, this.storageService,
|
||||
this.i18n2Service);
|
||||
this.i18nService);
|
||||
this.lockService = new LockService(this.cipherService, this.folderService, this.collectionService,
|
||||
this.cryptoService, this.platformUtilsService, this.storageService, this.messagingService, async () => {
|
||||
await this.setIcon();
|
||||
@ -342,7 +338,7 @@ export default class MainBackground {
|
||||
id: 'autofill',
|
||||
parentId: 'root',
|
||||
contexts: ['all'],
|
||||
title: this.i18nService.autoFill,
|
||||
title: this.i18nService.t('autoFill'),
|
||||
});
|
||||
|
||||
// Firefox & Edge do not support writing to the clipboard from background
|
||||
@ -352,7 +348,7 @@ export default class MainBackground {
|
||||
id: 'copy-username',
|
||||
parentId: 'root',
|
||||
contexts: ['all'],
|
||||
title: this.i18nService.copyUsername,
|
||||
title: this.i18nService.t('copyUsername'),
|
||||
});
|
||||
|
||||
await this.contextMenusCreate({
|
||||
@ -360,7 +356,7 @@ export default class MainBackground {
|
||||
id: 'copy-password',
|
||||
parentId: 'root',
|
||||
contexts: ['all'],
|
||||
title: this.i18nService.copyPassword,
|
||||
title: this.i18nService.t('copyPassword'),
|
||||
});
|
||||
|
||||
await this.contextMenusCreate({
|
||||
@ -373,7 +369,7 @@ export default class MainBackground {
|
||||
id: 'generate-password',
|
||||
parentId: 'root',
|
||||
contexts: ['all'],
|
||||
title: this.i18nService.generatePasswordCopied,
|
||||
title: this.i18nService.t('generatePasswordCopied'),
|
||||
});
|
||||
}
|
||||
|
||||
@ -411,7 +407,7 @@ export default class MainBackground {
|
||||
theText = '9+';
|
||||
} else {
|
||||
if (contextMenuEnabled) {
|
||||
await this.loadNoLoginsContextMenuOptions(this.i18nService.noMatchingLogins);
|
||||
await this.loadNoLoginsContextMenuOptions(this.i18nService.t('noMatchingLogins'));
|
||||
}
|
||||
}
|
||||
|
||||
@ -424,7 +420,7 @@ export default class MainBackground {
|
||||
|
||||
private async loadMenuAndUpdateBadgeForLockedState(contextMenuEnabled: boolean) {
|
||||
if (contextMenuEnabled) {
|
||||
await this.loadNoLoginsContextMenuOptions(this.i18nService.vaultLocked);
|
||||
await this.loadNoLoginsContextMenuOptions(this.i18nService.t('vaultLocked'));
|
||||
}
|
||||
|
||||
const tabs = await BrowserApi.getActiveTabs();
|
||||
|
@ -7,6 +7,8 @@ import { LoginView } from 'jslib/models/view/loginView';
|
||||
import { ConstantsService } from 'jslib/services/constants.service';
|
||||
import { UtilsService } from 'jslib/services/utils.service';
|
||||
|
||||
import { I18nService } from 'jslib/abstractions/i18n.service';
|
||||
|
||||
import { Analytics } from 'jslib/misc';
|
||||
|
||||
import {
|
||||
@ -30,7 +32,7 @@ export default class RuntimeBackground {
|
||||
|
||||
constructor(private main: MainBackground, private autofillService: AutofillService,
|
||||
private cipherService: CipherService, private platformUtilsService: BrowserPlatformUtilsService,
|
||||
private storageService: StorageService, private i18nService: any, private analytics: Analytics) {
|
||||
private storageService: StorageService, private i18nService: I18nService, private analytics: Analytics) {
|
||||
this.isSafari = this.platformUtilsService.isSafari();
|
||||
this.runtime = this.isSafari ? safari.application : chrome.runtime;
|
||||
|
||||
@ -357,13 +359,13 @@ export default class RuntimeBackground {
|
||||
ConstantsService.enableAutoFillOnPageLoadKey);
|
||||
} else if (responseCommand === 'notificationBarFrameDataResponse') {
|
||||
responseData.i18n = {
|
||||
appName: this.i18nService.appName,
|
||||
close: this.i18nService.close,
|
||||
yes: this.i18nService.yes,
|
||||
never: this.i18nService.never,
|
||||
notificationAddSave: this.i18nService.notificationAddSave,
|
||||
notificationNeverSave: this.i18nService.notificationNeverSave,
|
||||
notificationAddDesc: this.i18nService.notificationAddDesc,
|
||||
appName: this.i18nService.t('appName'),
|
||||
close: this.i18nService.t('close'),
|
||||
yes: this.i18nService.t('yes'),
|
||||
never: this.i18nService.t('never'),
|
||||
notificationAddSave: this.i18nService.t('notificationAddSave'),
|
||||
notificationNeverSave: this.i18nService.t('notificationNeverSave'),
|
||||
notificationAddDesc: this.i18nService.t('notificationAddDesc'),
|
||||
};
|
||||
}
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
export class BrowserApi {
|
||||
static isSafariApi: boolean = (typeof safari !== 'undefined') &&
|
||||
navigator.userAgent.indexOf(' Safari/') !== -1 && navigator.userAgent.indexOf('Chrome') === -1;
|
||||
navigator.userAgent.indexOf(' Safari/') !== -1 && navigator.userAgent.indexOf('Chrome') === -1;
|
||||
static isChromeApi: boolean = !BrowserApi.isSafariApi && (typeof chrome !== 'undefined');
|
||||
|
||||
static async getTabFromCurrentWindowId(): Promise<any> {
|
||||
@ -264,4 +264,12 @@ export class BrowserApi {
|
||||
static gaFilter() {
|
||||
return BrowserApi.isSafariApi && safari.application.activeBrowserWindow.activeTab.private;
|
||||
}
|
||||
|
||||
static getUILanguage(win: Window) {
|
||||
if (BrowserApi.isSafariApi) {
|
||||
return win.navigator.language;
|
||||
} else {
|
||||
return chrome.i18n.getUILanguage();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -57,7 +57,7 @@ export const messagingService = new BrowserMessagingService();
|
||||
export const authService = new AuthService(getBgService<CryptoService>('cryptoService')(),
|
||||
getBgService<ApiService>('apiService')(), getBgService<UserService>('userService')(),
|
||||
getBgService<TokenService>('tokenService')(), getBgService<AppIdService>('appIdService')(),
|
||||
getBgService<I18nService>('i18n2Service')(), getBgService<PlatformUtilsService>('platformUtilsService')(),
|
||||
getBgService<I18nService>('i18nService')(), getBgService<PlatformUtilsService>('platformUtilsService')(),
|
||||
getBgService<ConstantsService>('constantsService')(), messagingService);
|
||||
|
||||
export function initFactory(i18nService: I18nService, storageService: StorageService,
|
||||
@ -102,7 +102,7 @@ export function initFactory(i18nService: I18nService, storageService: StorageSer
|
||||
{ provide: EnvironmentService, useFactory: getBgService<EnvironmentService>('environmentService'), deps: [] },
|
||||
{ provide: TotpService, useFactory: getBgService<TotpService>('totpService'), deps: [] },
|
||||
{ provide: TokenService, useFactory: getBgService<TokenService>('tokenService'), deps: [] },
|
||||
{ provide: I18nService, useFactory: getBgService<I18nService>('i18n2Service'), deps: [] },
|
||||
{ provide: I18nService, useFactory: getBgService<I18nService>('i18nService'), deps: [] },
|
||||
{ provide: UtilsService, useFactory: getBgService<UtilsService>('utilsService'), deps: [] },
|
||||
{ provide: CryptoService, useFactory: getBgService<CryptoService>('cryptoService'), deps: [] },
|
||||
{
|
||||
|
@ -1,69 +1,121 @@
|
||||
import { PlatformUtilsService } from 'jslib/abstractions';
|
||||
import { I18nService as I18nServiceAbstraction } from 'jslib/abstractions/i18n.service';
|
||||
|
||||
// First locale is the default (English)
|
||||
const SupportedLocales = [
|
||||
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',
|
||||
];
|
||||
|
||||
export default function i18nService(platformUtilsService: PlatformUtilsService) {
|
||||
const defaultMessages: any = {};
|
||||
const localeMessages: any = {};
|
||||
export default class I18nService implements I18nServiceAbstraction {
|
||||
defaultMessages: any = {};
|
||||
localeMessages: any = {};
|
||||
locale: string;
|
||||
translationLocale: string;
|
||||
collator: Intl.Collator;
|
||||
inited: boolean;
|
||||
|
||||
if (platformUtilsService.isEdge()) {
|
||||
loadMessages('../_locales/', 'en', localeMessages,
|
||||
(prop: string, message: string) => chrome.i18n.getMessage(prop));
|
||||
return localeMessages;
|
||||
}
|
||||
constructor(private systemLanguage: string, private localesDirectory: string) { }
|
||||
|
||||
if (platformUtilsService.isSafari()) {
|
||||
let lang = navigator.language;
|
||||
if (SupportedLocales.indexOf(lang) === -1) {
|
||||
lang = lang.slice(0, 2);
|
||||
async init(locale?: string) {
|
||||
if (this.inited) {
|
||||
throw new Error('i18n already initialized.');
|
||||
}
|
||||
|
||||
if (SupportedLocales.indexOf(lang) === -1) {
|
||||
lang = SupportedLocales[0];
|
||||
this.inited = true;
|
||||
this.locale = this.translationLocale = locale != null ? locale : this.systemLanguage;
|
||||
this.collator = new Intl.Collator(this.locale);
|
||||
|
||||
if (SupportedTranslationLocales.indexOf(this.translationLocale) === -1) {
|
||||
this.translationLocale = this.translationLocale.slice(0, 2);
|
||||
|
||||
if (SupportedTranslationLocales.indexOf(this.translationLocale) === -1) {
|
||||
this.translationLocale = SupportedTranslationLocales[0];
|
||||
}
|
||||
}
|
||||
|
||||
const dir = './_locales/';
|
||||
loadMessages(dir, lang, localeMessages, (prop: string, message: string) => message);
|
||||
if (lang !== SupportedLocales[0]) {
|
||||
loadMessages(dir, SupportedLocales[0], defaultMessages,
|
||||
(prop: string, message: string) => message);
|
||||
if (this.localesDirectory != null) {
|
||||
await this.loadMessages(this.localesDirectory, this.translationLocale, this.localeMessages);
|
||||
if (this.translationLocale !== SupportedTranslationLocales[0]) {
|
||||
await this.loadMessages(this.localesDirectory, SupportedTranslationLocales[0], this.defaultMessages);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return new Proxy({}, {
|
||||
get: (target, name) => {
|
||||
const id = name.toString();
|
||||
t(id: string, p1?: string, p2?: string, p3?: string): string {
|
||||
return this.translate(id, p1, p2, p3);
|
||||
}
|
||||
|
||||
if (platformUtilsService.isSafari()) {
|
||||
if (localeMessages.hasOwnProperty(id) && localeMessages[id]) {
|
||||
return localeMessages[id];
|
||||
} else if (defaultMessages.hasOwnProperty(id) && defaultMessages[id]) {
|
||||
return defaultMessages[id];
|
||||
translate(id: string, p1?: string, p2?: string, p3?: string): string {
|
||||
if (this.localesDirectory == null) {
|
||||
const placeholders: string[] = [];
|
||||
if (p1 != null) {
|
||||
placeholders.push(p1);
|
||||
}
|
||||
if (p2 != null) {
|
||||
placeholders.push(p2);
|
||||
}
|
||||
if (p3 != null) {
|
||||
placeholders.push(p3);
|
||||
}
|
||||
|
||||
if (placeholders.length) {
|
||||
return chrome.i18n.getMessage(id, placeholders);
|
||||
} else {
|
||||
return chrome.i18n.getMessage(id);
|
||||
}
|
||||
}
|
||||
|
||||
let result: string;
|
||||
if (this.localeMessages.hasOwnProperty(id) && this.localeMessages[id]) {
|
||||
result = this.localeMessages[id];
|
||||
} else if (this.defaultMessages.hasOwnProperty(id) && this.defaultMessages[id]) {
|
||||
result = this.defaultMessages[id];
|
||||
} else {
|
||||
result = '';
|
||||
}
|
||||
|
||||
if (result !== '') {
|
||||
if (p1 != null) {
|
||||
result = result.split('__$1__').join(p1);
|
||||
}
|
||||
if (p2 != null) {
|
||||
result = result.split('__$2__').join(p2);
|
||||
}
|
||||
if (p3 != null) {
|
||||
result = result.split('__$3__').join(p3);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private async loadMessages(localesDir: string, locale: string, messagesObj: any): Promise<any> {
|
||||
const formattedLocale = locale.replace('-', '_');
|
||||
const file = await fetch(localesDir + formattedLocale + '/messages.json');
|
||||
const locales = await file.json();
|
||||
for (const prop in locales) {
|
||||
if (!locales.hasOwnProperty(prop)) {
|
||||
continue;
|
||||
}
|
||||
messagesObj[prop] = locales[prop].message;
|
||||
|
||||
if (locales[prop].placeholders) {
|
||||
for (const placeProp in locales[prop].placeholders) {
|
||||
if (!locales[prop].placeholders.hasOwnProperty(placeProp) ||
|
||||
!locales[prop].placeholders[placeProp].content) {
|
||||
continue;
|
||||
}
|
||||
|
||||
const replaceToken = '\\$' + placeProp.toUpperCase() + '\\$';
|
||||
let replaceContent = locales[prop].placeholders[placeProp].content;
|
||||
if (replaceContent === '$1' || replaceContent === '$2' || replaceContent === '$3') {
|
||||
replaceContent = '__' + replaceContent + '__';
|
||||
}
|
||||
messagesObj[prop] = messagesObj[prop].replace(new RegExp(replaceToken, 'g'), replaceContent);
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
return chrome.i18n.getMessage(id);
|
||||
},
|
||||
set: (target, name, value) => {
|
||||
return false;
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
async function loadMessages(localesDir: string, locale: string, messagesObj: any,
|
||||
messageCallback: (prop: string, message: string) => string): Promise<any> {
|
||||
const formattedLocale = locale.replace('-', '_');
|
||||
const file = await fetch(localesDir + formattedLocale + '/messages.json');
|
||||
const locales = await file.json();
|
||||
for (const prop in locales) {
|
||||
if (locales.hasOwnProperty(prop)) {
|
||||
messagesObj[prop] = messageCallback(prop, locales[prop].message);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,29 +0,0 @@
|
||||
import { I18nService as I18nServiceAbstraction } from 'jslib/abstractions/i18n.service';
|
||||
|
||||
export default class I18n2Service implements I18nServiceAbstraction {
|
||||
locale: string;
|
||||
translationLocale: string;
|
||||
collator: Intl.Collator;
|
||||
inited: boolean;
|
||||
|
||||
constructor(private systemLanguage: string, private i18nService: any) {
|
||||
}
|
||||
|
||||
async init(locale?: string) {
|
||||
if (this.inited) {
|
||||
throw new Error('i18n already initialized.');
|
||||
}
|
||||
|
||||
this.inited = true;
|
||||
this.locale = this.translationLocale = locale != null ? locale : this.systemLanguage;
|
||||
this.collator = new Intl.Collator(this.locale);
|
||||
}
|
||||
|
||||
t(id: string, p1?: string, p2?: string, p3?: string): string {
|
||||
return this.translate(id);
|
||||
}
|
||||
|
||||
translate(id: string, p1?: string, p2?: string, p3?: string): string {
|
||||
return this.i18nService[id];
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user