2018-02-09 06:21:00 +01:00
|
|
|
import * as fs from 'fs';
|
2018-01-24 21:22:13 +01:00
|
|
|
import * as path from 'path';
|
|
|
|
|
2018-01-25 20:25:44 +01:00
|
|
|
import { I18nService as I18nServiceAbstraction } from 'jslib/abstractions/i18n.service';
|
|
|
|
|
2018-01-24 20:59:03 +01:00
|
|
|
// First locale is the default (English)
|
2018-01-27 04:39:45 +01:00
|
|
|
const SupportedTranslationLocales = [
|
2018-02-20 22:27:54 +01:00
|
|
|
'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',
|
2018-01-24 20:59:03 +01:00
|
|
|
];
|
|
|
|
|
2018-01-25 20:25:44 +01:00
|
|
|
export class I18nService implements I18nServiceAbstraction {
|
2018-01-24 20:59:03 +01:00
|
|
|
defaultMessages: any = {};
|
|
|
|
localeMessages: any = {};
|
2018-01-27 04:39:45 +01:00
|
|
|
locale: string;
|
|
|
|
translationLocale: string;
|
|
|
|
collator: Intl.Collator;
|
2018-01-24 20:59:03 +01:00
|
|
|
inited: boolean;
|
|
|
|
|
2018-01-24 22:02:18 +01:00
|
|
|
constructor(private systemLanguage: string, private localesDirectory: string) {
|
2018-01-24 20:59:03 +01:00
|
|
|
}
|
|
|
|
|
2018-01-27 04:39:45 +01:00
|
|
|
async init(locale?: string) {
|
2018-01-24 20:59:03 +01:00
|
|
|
if (this.inited) {
|
|
|
|
throw new Error('i18n already initialized.');
|
|
|
|
}
|
|
|
|
|
|
|
|
this.inited = true;
|
2018-01-27 04:39:45 +01:00
|
|
|
this.locale = this.translationLocale = locale != null ? locale : this.systemLanguage;
|
|
|
|
this.collator = new Intl.Collator(this.locale);
|
2018-01-24 20:59:03 +01:00
|
|
|
|
2018-01-27 04:39:45 +01:00
|
|
|
if (SupportedTranslationLocales.indexOf(this.translationLocale) === -1) {
|
|
|
|
this.translationLocale = this.translationLocale.slice(0, 2);
|
2018-01-24 20:59:03 +01:00
|
|
|
|
2018-01-27 04:39:45 +01:00
|
|
|
if (SupportedTranslationLocales.indexOf(this.translationLocale) === -1) {
|
|
|
|
this.translationLocale = SupportedTranslationLocales[0];
|
2018-01-24 20:59:03 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-01-27 04:39:45 +01:00
|
|
|
await this.loadMessages(this.translationLocale, this.localeMessages);
|
|
|
|
if (this.translationLocale !== SupportedTranslationLocales[0]) {
|
|
|
|
await this.loadMessages(SupportedTranslationLocales[0], this.defaultMessages);
|
2018-01-24 20:59:03 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-02-02 18:01:55 +01:00
|
|
|
t(id: string, p1?: string, p2?: string, p3?: string): string {
|
|
|
|
return this.translate(id, p1, p2, p3);
|
2018-01-24 20:59:03 +01:00
|
|
|
}
|
|
|
|
|
2018-02-02 18:01:55 +01:00
|
|
|
translate(id: string, p1?: string, p2?: string, p3?: string): string {
|
|
|
|
let result: string;
|
2018-01-24 20:59:03 +01:00
|
|
|
if (this.localeMessages.hasOwnProperty(id) && this.localeMessages[id]) {
|
2018-02-02 18:01:55 +01:00
|
|
|
result = this.localeMessages[id];
|
2018-01-24 20:59:03 +01:00
|
|
|
} else if (this.defaultMessages.hasOwnProperty(id) && this.defaultMessages[id]) {
|
2018-02-02 18:01:55 +01:00
|
|
|
result = this.defaultMessages[id];
|
|
|
|
} else {
|
|
|
|
result = '';
|
2018-01-24 20:59:03 +01:00
|
|
|
}
|
2018-02-02 18:01:55 +01:00
|
|
|
|
|
|
|
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;
|
2018-01-24 20:59:03 +01:00
|
|
|
}
|
|
|
|
|
2018-01-24 21:22:13 +01:00
|
|
|
private loadMessages(locale: string, messagesObj: any): Promise<any> {
|
2018-01-24 20:59:03 +01:00
|
|
|
const formattedLocale = locale.replace('-', '_');
|
2018-01-24 21:22:13 +01:00
|
|
|
const filePath = path.join(__dirname, this.localesDirectory + '/' + formattedLocale + '/messages.json');
|
2018-02-09 06:21:00 +01:00
|
|
|
const localesJson = fs.readFileSync(filePath, 'utf8');
|
|
|
|
const locales = JSON.parse(localesJson.replace(/^\uFEFF/, '')); // strip the BOM
|
2018-01-24 20:59:03 +01:00
|
|
|
for (const prop in locales) {
|
2018-02-02 18:01:55 +01:00
|
|
|
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);
|
|
|
|
}
|
2018-01-24 20:59:03 +01:00
|
|
|
}
|
|
|
|
}
|
2018-01-24 21:22:13 +01:00
|
|
|
|
|
|
|
return Promise.resolve();
|
2018-01-24 20:59:03 +01:00
|
|
|
}
|
|
|
|
}
|