ngx-translate-messageformat-compiler
Version:
> Compiler for ngx-translate that uses messageformat.js to compile translations using ICU syntax for handling pluralization and gender
159 lines (152 loc) • 6.32 kB
JavaScript
import * as i0 from '@angular/core';
import { InjectionToken, Optional, Inject, Injectable } from '@angular/core';
import { TranslateCompiler } from '@ngx-translate/core';
import MessageFormat from '@messageformat/core';
const MESSAGE_FORMAT_CONFIG = new InjectionToken("MESSAGE_FORMAT_CONFIG");
const defaultConfig = {
biDiSupport: false,
formatters: {},
strictNumberSign: false,
currency: "USD",
strictPluralKeys: true,
throwOnError: false,
fallbackPrefix: undefined,
};
/**
* This compiler expects ICU syntax and compiles the expressions with messageformat.js
*/
class TranslateMessageFormatCompiler extends TranslateCompiler {
constructor(config) {
super();
this.mfCache = new Map();
const { formatters: customFormatters, biDiSupport, strictNumberSign: strict, currency, strictPluralKeys, throwOnError, fallbackPrefix, } = {
...defaultConfig,
...config,
};
this.messageFormatOptions = {
customFormatters,
biDiSupport,
strict,
currency,
strictPluralKeys,
};
this.throwOnError = !!throwOnError;
this.fallbackPrefix = fallbackPrefix;
}
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
compile(value, lang) {
if (this.fallbackPrefix && value.startsWith(this.fallbackPrefix)) {
return value.slice(this.fallbackPrefix.length);
}
let result;
try {
result = this.getMessageFormatInstance(lang).compile(value);
}
catch (err) {
if (this.throwOnError) {
throw err;
}
// eslint-disable-next-line no-console
console.error(err);
// eslint-disable-next-line no-console
console.error(`[ngx-translate-messageformat-compiler] Could not compile message for lang '${lang}': '${value}'`);
result = compileFallback(value, lang);
}
if (!this.throwOnError) {
result = wrapInterpolationFunction(result, value);
}
return result;
}
compileTranslations(translations, lang) {
if (typeof translations === "string") {
return this.compile(translations, lang);
}
return Object.keys(translations).reduce((acc, key) => {
const value = translations[key];
acc[key] = this.compileTranslations(value, lang);
return acc;
}, {});
}
getMessageFormatInstance(locale) {
if (!this.mfCache.has(locale)) {
this.mfCache.set(locale, new MessageFormat(locale, this.messageFormatOptions));
}
// eslint-disable-next-line @typescript-eslint/no-non-null-assertion
return this.mfCache.get(locale);
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: TranslateMessageFormatCompiler, deps: [{ token: MESSAGE_FORMAT_CONFIG, optional: true }], target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: TranslateMessageFormatCompiler }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: TranslateMessageFormatCompiler, decorators: [{
type: Injectable
}], ctorParameters: () => [{ type: undefined, decorators: [{
type: Optional
}, {
type: Inject,
args: [MESSAGE_FORMAT_CONFIG]
}] }] });
function wrapInterpolationFunction(fn, message) {
return (params) => {
let result = message;
try {
result = fn(params);
}
catch (err) {
// eslint-disable-next-line no-console
console.error(err);
// eslint-disable-next-line no-console
console.error(
// eslint-disable-next-line @typescript-eslint/restrict-template-expressions
`[ngx-translate-messageformat-compiler] Could not interpolate '${message}' with params '${params}'`);
}
return result;
};
}
function compileFallback(message, lang) {
return () => {
// eslint-disable-next-line no-console
console.warn(`[ngx-translate-messageformat-compiler] Falling back to original invalid message: '${message}' ('${lang}')`);
return String(message);
};
}
const log = (...message) => {
/* eslint-disable-next-line no-console */
console.log(tag, ...message);
};
const tag = "[TranslateMessageFormatCompiler]";
class TranslateMessageFormatDebugCompiler extends TranslateMessageFormatCompiler {
// eslint-disable-next-line @typescript-eslint/no-unnecessary-type-parameters
compile(value, lang) {
log(`COMPILE (${lang})`, value);
const interpolationFn = super.compile(value, lang);
return isFunction(interpolationFn)
? this.wrap(interpolationFn, value)
: value;
}
compileTranslations(value, lang) {
log(`COMPILE (${lang})`, value);
return super.compileTranslations(value, lang);
}
wrap(fn, reference) {
return (params) => {
log("INTERPOLATE", reference, params);
return fn(params);
};
}
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: TranslateMessageFormatDebugCompiler, deps: null, target: i0.ɵɵFactoryTarget.Injectable }); }
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: TranslateMessageFormatDebugCompiler }); }
}
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "20.1.4", ngImport: i0, type: TranslateMessageFormatDebugCompiler, decorators: [{
type: Injectable
}] });
function isFunction(value) {
return typeof value === "function";
}
/*
* Public API Surface of ngx-translate-messageformat-compiler
*/
/**
* Generated bundle index. Do not edit.
*/
export { MESSAGE_FORMAT_CONFIG, TranslateMessageFormatCompiler, TranslateMessageFormatDebugCompiler, defaultConfig };
//# sourceMappingURL=ngx-translate-messageformat-compiler.mjs.map