mirror of
https://github.com/bitwarden/browser.git
synced 2025-02-01 23:01:28 +01:00
[CSA-27] Use new dependency-free locale service for WebAuthN translations (#4557)
This commit is contained in:
parent
dc3a0b25cb
commit
dcc7846138
@ -1,5 +1,7 @@
|
||||
import { I18nService as BaseI18nService } from "@bitwarden/common/services/i18n.service";
|
||||
|
||||
import { SupportedTranslationLocales } from "../../translation-constants";
|
||||
|
||||
export class I18nService extends BaseI18nService {
|
||||
constructor(systemLanguage: string, localesDirectory: string) {
|
||||
super(systemLanguage || "en-US", localesDirectory, async (formattedLocale: string) => {
|
||||
@ -14,61 +16,6 @@ export class I18nService extends BaseI18nService {
|
||||
return locales;
|
||||
});
|
||||
|
||||
// Please leave 'en' where it is, as it's our fallback language in case no translation can be found
|
||||
this.supportedTranslationLocales = [
|
||||
"en",
|
||||
"af",
|
||||
"ar",
|
||||
"az",
|
||||
"be",
|
||||
"bg",
|
||||
"bn",
|
||||
"bs",
|
||||
"ca",
|
||||
"cs",
|
||||
"da",
|
||||
"de",
|
||||
"el",
|
||||
"en-GB",
|
||||
"en-IN",
|
||||
"eo",
|
||||
"es",
|
||||
"et",
|
||||
"eu",
|
||||
"fi",
|
||||
"fil",
|
||||
"fr",
|
||||
"he",
|
||||
"hi",
|
||||
"hr",
|
||||
"hu",
|
||||
"id",
|
||||
"it",
|
||||
"ja",
|
||||
"ka",
|
||||
"km",
|
||||
"kn",
|
||||
"ko",
|
||||
"lv",
|
||||
"ml",
|
||||
"nb",
|
||||
"nl",
|
||||
"nn",
|
||||
"pl",
|
||||
"pt-PT",
|
||||
"pt-BR",
|
||||
"ro",
|
||||
"ru",
|
||||
"si",
|
||||
"sk",
|
||||
"sl",
|
||||
"sr",
|
||||
"sv",
|
||||
"tr",
|
||||
"uk",
|
||||
"vi",
|
||||
"zh-CN",
|
||||
"zh-TW",
|
||||
];
|
||||
this.supportedTranslationLocales = SupportedTranslationLocales;
|
||||
}
|
||||
}
|
||||
|
31
apps/web/src/connectors/translation.service.ts
Normal file
31
apps/web/src/connectors/translation.service.ts
Normal file
@ -0,0 +1,31 @@
|
||||
import { TranslationService as BaseTranslationService } from "@bitwarden/common/services/translation.service";
|
||||
|
||||
import { SupportedTranslationLocales } from "../translation-constants";
|
||||
|
||||
export class TranslationService extends BaseTranslationService {
|
||||
private _translationLocale: string;
|
||||
|
||||
constructor(systemLanguage: string, localesDirectory: string) {
|
||||
super(systemLanguage || "en-US", localesDirectory, async (formattedLocale: string) => {
|
||||
const filePath =
|
||||
this.localesDirectory +
|
||||
"/" +
|
||||
formattedLocale +
|
||||
"/messages.json?cache=" +
|
||||
process.env.CACHE_TAG;
|
||||
const localesResult = await fetch(filePath);
|
||||
const locales = await localesResult.json();
|
||||
return locales;
|
||||
});
|
||||
|
||||
this.supportedTranslationLocales = SupportedTranslationLocales;
|
||||
}
|
||||
|
||||
get translationLocale(): string {
|
||||
return this._translationLocale;
|
||||
}
|
||||
|
||||
set translationLocale(locale: string) {
|
||||
this._translationLocale = locale;
|
||||
}
|
||||
}
|
@ -1,5 +1,6 @@
|
||||
import { b64Decode, getQsParam } from "./common";
|
||||
import { buildDataString, parseWebauthnJson } from "./common-webauthn";
|
||||
import { TranslationService } from "./translation.service";
|
||||
|
||||
require("./webauthn.scss");
|
||||
|
||||
@ -7,9 +8,8 @@ let parsed = false;
|
||||
let webauthnJson: any;
|
||||
let parentUrl: string = null;
|
||||
let sentSuccess = false;
|
||||
let locale = "en";
|
||||
|
||||
let locales: any = {};
|
||||
let locale: string = null;
|
||||
let localeService: TranslationService = null;
|
||||
|
||||
function parseParameters() {
|
||||
if (parsed) {
|
||||
@ -24,7 +24,7 @@ function parseParameters() {
|
||||
parentUrl = decodeURIComponent(parentUrl);
|
||||
}
|
||||
|
||||
locale = getQsParam("locale").replace("-", "_");
|
||||
locale = getQsParam("locale") ?? "en";
|
||||
|
||||
const version = getQsParam("v");
|
||||
|
||||
@ -61,18 +61,19 @@ function parseParametersV2() {
|
||||
document.addEventListener("DOMContentLoaded", async () => {
|
||||
parseParameters();
|
||||
try {
|
||||
locales = await loadLocales(locale);
|
||||
localeService = new TranslationService(locale, "locales");
|
||||
} catch {
|
||||
// eslint-disable-next-line
|
||||
console.error("Failed to load the locale", locale);
|
||||
locales = await loadLocales("en");
|
||||
error("Failed to load the provided locale " + locale);
|
||||
localeService = new TranslationService("en", "locales");
|
||||
}
|
||||
|
||||
document.getElementById("msg").innerText = translate("webAuthnFallbackMsg");
|
||||
document.getElementById("remember-label").innerText = translate("rememberMe");
|
||||
await localeService.init();
|
||||
|
||||
document.getElementById("msg").innerText = localeService.t("webAuthnFallbackMsg");
|
||||
document.getElementById("remember-label").innerText = localeService.t("rememberMe");
|
||||
|
||||
const button = document.getElementById("webauthn-button");
|
||||
button.innerText = translate("webAuthnAuthenticate");
|
||||
button.innerText = localeService.t("webAuthnAuthenticate");
|
||||
button.onclick = start;
|
||||
|
||||
document.getElementById("spinner").classList.add("d-none");
|
||||
@ -81,23 +82,13 @@ document.addEventListener("DOMContentLoaded", async () => {
|
||||
content.classList.remove("d-none");
|
||||
});
|
||||
|
||||
async function loadLocales(newLocale: string) {
|
||||
const filePath = `locales/${newLocale}/messages.json?cache=${process.env.CACHE_TAG}`;
|
||||
const localesResult = await fetch(filePath);
|
||||
return await localesResult.json();
|
||||
}
|
||||
|
||||
function translate(id: string) {
|
||||
return locales[id]?.message || "";
|
||||
}
|
||||
|
||||
function start() {
|
||||
if (sentSuccess) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!("credentials" in navigator)) {
|
||||
error(translate("webAuthnNotSupported"));
|
||||
error(localeService.t("webAuthnNotSupported"));
|
||||
return;
|
||||
}
|
||||
|
||||
@ -133,7 +124,7 @@ async function initWebAuthn(obj: any) {
|
||||
window.postMessage({ command: "webAuthnResult", data: dataString, remember: remember }, "*");
|
||||
|
||||
sentSuccess = true;
|
||||
success(translate("webAuthnSuccess"));
|
||||
success(localeService.t("webAuthnSuccess"));
|
||||
} catch (err) {
|
||||
error(err);
|
||||
}
|
||||
|
56
apps/web/src/translation-constants.ts
Normal file
56
apps/web/src/translation-constants.ts
Normal file
@ -0,0 +1,56 @@
|
||||
// Please leave 'en' where it is, as it's our fallback language in case no translation can be found
|
||||
export const SupportedTranslationLocales: string[] = [
|
||||
"en",
|
||||
"af",
|
||||
"ar",
|
||||
"az",
|
||||
"be",
|
||||
"bg",
|
||||
"bn",
|
||||
"bs",
|
||||
"ca",
|
||||
"cs",
|
||||
"da",
|
||||
"de",
|
||||
"el",
|
||||
"en-GB",
|
||||
"en-IN",
|
||||
"eo",
|
||||
"es",
|
||||
"et",
|
||||
"eu",
|
||||
"fi",
|
||||
"fil",
|
||||
"fr",
|
||||
"he",
|
||||
"hi",
|
||||
"hr",
|
||||
"hu",
|
||||
"id",
|
||||
"it",
|
||||
"ja",
|
||||
"ka",
|
||||
"km",
|
||||
"kn",
|
||||
"ko",
|
||||
"lv",
|
||||
"ml",
|
||||
"nb",
|
||||
"nl",
|
||||
"nn",
|
||||
"pl",
|
||||
"pt-PT",
|
||||
"pt-BR",
|
||||
"ro",
|
||||
"ru",
|
||||
"si",
|
||||
"sk",
|
||||
"sl",
|
||||
"sr",
|
||||
"sv",
|
||||
"tr",
|
||||
"uk",
|
||||
"vi",
|
||||
"zh-CN",
|
||||
"zh-TW",
|
||||
];
|
@ -1,11 +1,7 @@
|
||||
import { Observable } from "rxjs";
|
||||
|
||||
export abstract class I18nService {
|
||||
import { TranslationService } from "./translation.service";
|
||||
|
||||
export abstract class I18nService extends TranslationService {
|
||||
locale$: Observable<string>;
|
||||
supportedTranslationLocales: string[];
|
||||
translationLocale: string;
|
||||
collator: Intl.Collator;
|
||||
localeNames: Map<string, string>;
|
||||
t: (id: string, p1?: string | number, p2?: string | number, p3?: string | number) => string;
|
||||
translate: (id: string, p1?: string, p2?: string, p3?: string) => string;
|
||||
}
|
||||
|
8
libs/common/src/abstractions/translation.service.ts
Normal file
8
libs/common/src/abstractions/translation.service.ts
Normal file
@ -0,0 +1,8 @@
|
||||
export abstract class TranslationService {
|
||||
supportedTranslationLocales: string[];
|
||||
translationLocale: string;
|
||||
collator: Intl.Collator;
|
||||
localeNames: Map<string, string>;
|
||||
t: (id: string, p1?: string | number, p2?: string | number, p3?: string | number) => string;
|
||||
translate: (id: string, p1?: string, p2?: string, p3?: string) => string;
|
||||
}
|
@ -2,184 +2,27 @@ import { Observable, ReplaySubject } from "rxjs";
|
||||
|
||||
import { I18nService as I18nServiceAbstraction } from "../abstractions/i18n.service";
|
||||
|
||||
export class I18nService implements I18nServiceAbstraction {
|
||||
protected _locale = new ReplaySubject<string>(1);
|
||||
locale$: Observable<string> = this._locale.asObservable();
|
||||
// First locale is the default (English)
|
||||
supportedTranslationLocales: string[] = ["en"];
|
||||
defaultLocale = "en";
|
||||
translationLocale: string;
|
||||
collator: Intl.Collator;
|
||||
localeNames = new Map<string, string>([
|
||||
["af", "Afrikaans"],
|
||||
["ar", "العربية الفصحى"],
|
||||
["az", "Azərbaycanca"],
|
||||
["be", "Беларуская"],
|
||||
["bg", "български"],
|
||||
["bn", "বাংলা"],
|
||||
["bs", "bosanski jezik"],
|
||||
["ca", "català"],
|
||||
["cs", "čeština"],
|
||||
["da", "dansk"],
|
||||
["de", "Deutsch"],
|
||||
["el", "Ελληνικά"],
|
||||
["en", "English"],
|
||||
["en-GB", "English (British)"],
|
||||
["en-IN", "English (India)"],
|
||||
["eo", "Esperanto"],
|
||||
["es", "español"],
|
||||
["et", "eesti"],
|
||||
["eu", "euskara"],
|
||||
["fa", "فارسی"],
|
||||
["fi", "suomi"],
|
||||
["fil", "Wikang Filipino"],
|
||||
["fr", "français"],
|
||||
["he", "עברית"],
|
||||
["hi", "हिन्दी"],
|
||||
["hr", "hrvatski"],
|
||||
["hu", "magyar"],
|
||||
["id", "Bahasa Indonesia"],
|
||||
["it", "italiano"],
|
||||
["ja", "日本語"],
|
||||
["ka", "ქართული"],
|
||||
["km", "ខ្មែរ, ខេមរភាសា, ភាសាខ្មែរ"],
|
||||
["kn", "ಕನ್ನಡ"],
|
||||
["ko", "한국어"],
|
||||
["lt", "lietuvių kalba"],
|
||||
["lv", "Latvietis"],
|
||||
["me", "црногорски"],
|
||||
["ml", "മലയാളം"],
|
||||
["nb", "norsk (bokmål)"],
|
||||
["nl", "Nederlands"],
|
||||
["nn", "Norsk Nynorsk"],
|
||||
["pl", "polski"],
|
||||
["pt-BR", "português do Brasil"],
|
||||
["pt-PT", "português"],
|
||||
["ro", "română"],
|
||||
["ru", "русский"],
|
||||
["si", "සිංහල"],
|
||||
["sk", "slovenčina"],
|
||||
["sl", "Slovenski jezik, Slovenščina"],
|
||||
["sr", "Српски"],
|
||||
["sv", "svenska"],
|
||||
["th", "ไทย"],
|
||||
["tr", "Türkçe"],
|
||||
["uk", "українська"],
|
||||
["vi", "Tiếng Việt"],
|
||||
["zh-CN", "中文(中国大陆)"],
|
||||
["zh-TW", "中文(台灣)"],
|
||||
]);
|
||||
import { TranslationService } from "./translation.service";
|
||||
|
||||
protected inited: boolean;
|
||||
protected defaultMessages: any = {};
|
||||
protected localeMessages: any = {};
|
||||
export class I18nService extends TranslationService implements I18nServiceAbstraction {
|
||||
protected _locale = new ReplaySubject<string>(1);
|
||||
private _translationLocale: string;
|
||||
locale$: Observable<string> = this._locale.asObservable();
|
||||
|
||||
constructor(
|
||||
protected systemLanguage: string,
|
||||
protected localesDirectory: string,
|
||||
protected getLocalesJson: (formattedLocale: string) => Promise<any>
|
||||
) {
|
||||
this.systemLanguage = systemLanguage.replace("_", "-");
|
||||
super(systemLanguage, localesDirectory, getLocalesJson);
|
||||
}
|
||||
|
||||
async init(locale?: string) {
|
||||
if (this.inited) {
|
||||
throw new Error("i18n already initialized.");
|
||||
}
|
||||
if (this.supportedTranslationLocales == null || this.supportedTranslationLocales.length === 0) {
|
||||
throw new Error("supportedTranslationLocales not set.");
|
||||
}
|
||||
|
||||
this.inited = true;
|
||||
this.translationLocale = locale != null ? locale : this.systemLanguage;
|
||||
this._locale.next(this.translationLocale);
|
||||
|
||||
try {
|
||||
this.collator = new Intl.Collator(this.translationLocale, {
|
||||
numeric: true,
|
||||
sensitivity: "base",
|
||||
});
|
||||
} catch {
|
||||
this.collator = null;
|
||||
}
|
||||
|
||||
if (this.supportedTranslationLocales.indexOf(this.translationLocale) === -1) {
|
||||
this.translationLocale = this.translationLocale.slice(0, 2);
|
||||
|
||||
if (this.supportedTranslationLocales.indexOf(this.translationLocale) === -1) {
|
||||
this.translationLocale = this.defaultLocale;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.localesDirectory != null) {
|
||||
await this.loadMessages(this.translationLocale, this.localeMessages);
|
||||
if (this.translationLocale !== this.defaultLocale) {
|
||||
await this.loadMessages(this.defaultLocale, this.defaultMessages);
|
||||
}
|
||||
}
|
||||
get translationLocale(): string {
|
||||
return this._translationLocale;
|
||||
}
|
||||
|
||||
t(id: string, p1?: string, p2?: string, p3?: string): string {
|
||||
return this.translate(id, p1, p2, p3);
|
||||
}
|
||||
|
||||
translate(id: string, p1?: string | number, p2?: string | number, p3?: string | number): string {
|
||||
let result: string;
|
||||
// eslint-disable-next-line
|
||||
if (this.localeMessages.hasOwnProperty(id) && this.localeMessages[id]) {
|
||||
result = this.localeMessages[id];
|
||||
// eslint-disable-next-line
|
||||
} 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.toString());
|
||||
}
|
||||
if (p2 != null) {
|
||||
result = result.split("__$2__").join(p2.toString());
|
||||
}
|
||||
if (p3 != null) {
|
||||
result = result.split("__$3__").join(p3.toString());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private async loadMessages(locale: string, messagesObj: any): Promise<any> {
|
||||
const formattedLocale = locale.replace("-", "_");
|
||||
const locales = await this.getLocalesJson(formattedLocale);
|
||||
for (const prop in locales) {
|
||||
// eslint-disable-next-line
|
||||
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) || // eslint-disable-line
|
||||
!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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
set translationLocale(locale: string) {
|
||||
this._translationLocale = locale;
|
||||
this._locale.next(locale);
|
||||
}
|
||||
}
|
||||
|
180
libs/common/src/services/translation.service.ts
Normal file
180
libs/common/src/services/translation.service.ts
Normal file
@ -0,0 +1,180 @@
|
||||
import { TranslationService as TranslationServiceAbstraction } from "../abstractions/translation.service";
|
||||
|
||||
export abstract class TranslationService implements TranslationServiceAbstraction {
|
||||
// First locale is the default (English)
|
||||
supportedTranslationLocales: string[] = ["en"];
|
||||
defaultLocale = "en";
|
||||
abstract translationLocale: string;
|
||||
collator: Intl.Collator;
|
||||
localeNames = new Map<string, string>([
|
||||
["af", "Afrikaans"],
|
||||
["ar", "العربية الفصحى"],
|
||||
["az", "Azərbaycanca"],
|
||||
["be", "Беларуская"],
|
||||
["bg", "български"],
|
||||
["bn", "বাংলা"],
|
||||
["bs", "bosanski jezik"],
|
||||
["ca", "català"],
|
||||
["cs", "čeština"],
|
||||
["da", "dansk"],
|
||||
["de", "Deutsch"],
|
||||
["el", "Ελληνικά"],
|
||||
["en", "English"],
|
||||
["en-GB", "English (British)"],
|
||||
["en-IN", "English (India)"],
|
||||
["eo", "Esperanto"],
|
||||
["es", "español"],
|
||||
["et", "eesti"],
|
||||
["eu", "euskara"],
|
||||
["fa", "فارسی"],
|
||||
["fi", "suomi"],
|
||||
["fil", "Wikang Filipino"],
|
||||
["fr", "français"],
|
||||
["he", "עברית"],
|
||||
["hi", "हिन्दी"],
|
||||
["hr", "hrvatski"],
|
||||
["hu", "magyar"],
|
||||
["id", "Bahasa Indonesia"],
|
||||
["it", "italiano"],
|
||||
["ja", "日本語"],
|
||||
["ka", "ქართული"],
|
||||
["km", "ខ្មែរ, ខេមរភាសា, ភាសាខ្មែរ"],
|
||||
["kn", "ಕನ್ನಡ"],
|
||||
["ko", "한국어"],
|
||||
["lt", "lietuvių kalba"],
|
||||
["lv", "Latvietis"],
|
||||
["me", "црногорски"],
|
||||
["ml", "മലയാളം"],
|
||||
["nb", "norsk (bokmål)"],
|
||||
["nl", "Nederlands"],
|
||||
["nn", "Norsk Nynorsk"],
|
||||
["pl", "polski"],
|
||||
["pt-BR", "português do Brasil"],
|
||||
["pt-PT", "português"],
|
||||
["ro", "română"],
|
||||
["ru", "русский"],
|
||||
["si", "සිංහල"],
|
||||
["sk", "slovenčina"],
|
||||
["sl", "Slovenski jezik, Slovenščina"],
|
||||
["sr", "Српски"],
|
||||
["sv", "svenska"],
|
||||
["th", "ไทย"],
|
||||
["tr", "Türkçe"],
|
||||
["uk", "українська"],
|
||||
["vi", "Tiếng Việt"],
|
||||
["zh-CN", "中文(中国大陆)"],
|
||||
["zh-TW", "中文(台灣)"],
|
||||
]);
|
||||
|
||||
protected inited: boolean;
|
||||
protected defaultMessages: any = {};
|
||||
protected localeMessages: any = {};
|
||||
|
||||
constructor(
|
||||
protected systemLanguage: string,
|
||||
protected localesDirectory: string,
|
||||
protected getLocalesJson: (formattedLocale: string) => Promise<any>
|
||||
) {
|
||||
this.systemLanguage = systemLanguage.replace("_", "-");
|
||||
}
|
||||
|
||||
async init(locale?: string) {
|
||||
if (this.inited) {
|
||||
throw new Error("i18n already initialized.");
|
||||
}
|
||||
if (this.supportedTranslationLocales == null || this.supportedTranslationLocales.length === 0) {
|
||||
throw new Error("supportedTranslationLocales not set.");
|
||||
}
|
||||
|
||||
this.inited = true;
|
||||
this.translationLocale = locale != null ? locale : this.systemLanguage;
|
||||
|
||||
try {
|
||||
this.collator = new Intl.Collator(this.translationLocale, {
|
||||
numeric: true,
|
||||
sensitivity: "base",
|
||||
});
|
||||
} catch {
|
||||
this.collator = null;
|
||||
}
|
||||
|
||||
if (this.supportedTranslationLocales.indexOf(this.translationLocale) === -1) {
|
||||
this.translationLocale = this.translationLocale.slice(0, 2);
|
||||
|
||||
if (this.supportedTranslationLocales.indexOf(this.translationLocale) === -1) {
|
||||
this.translationLocale = this.defaultLocale;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.localesDirectory != null) {
|
||||
await this.loadMessages(this.translationLocale, this.localeMessages);
|
||||
if (this.translationLocale !== this.defaultLocale) {
|
||||
await this.loadMessages(this.defaultLocale, this.defaultMessages);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
t(id: string, p1?: string, p2?: string, p3?: string): string {
|
||||
return this.translate(id, p1, p2, p3);
|
||||
}
|
||||
|
||||
translate(id: string, p1?: string | number, p2?: string | number, p3?: string | number): string {
|
||||
let result: string;
|
||||
// eslint-disable-next-line
|
||||
if (this.localeMessages.hasOwnProperty(id) && this.localeMessages[id]) {
|
||||
result = this.localeMessages[id];
|
||||
// eslint-disable-next-line
|
||||
} 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.toString());
|
||||
}
|
||||
if (p2 != null) {
|
||||
result = result.split("__$2__").join(p2.toString());
|
||||
}
|
||||
if (p3 != null) {
|
||||
result = result.split("__$3__").join(p3.toString());
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected async loadMessages(locale: string, messagesObj: any): Promise<any> {
|
||||
const formattedLocale = locale.replace("-", "_");
|
||||
const locales = await this.getLocalesJson(formattedLocale);
|
||||
for (const prop in locales) {
|
||||
// eslint-disable-next-line
|
||||
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) || // eslint-disable-line
|
||||
!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
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user