|
|
import { MapOf, PromiseOrValue } from "@implab/core-amd/interfaces";
|
|
|
import { argumentNotEmptyString, isPromise, mixin } from "@implab/core-amd/safe";
|
|
|
|
|
|
export type LocaleProvider<T> = () => PromiseOrValue<T | {default: T}>;
|
|
|
|
|
|
function when<T, T2>(value: PromiseOrValue<T>, cb: (v: T) => PromiseOrValue<T2>): PromiseOrValue<T2> {
|
|
|
return isPromise(value) ?
|
|
|
value.then(cb) :
|
|
|
cb(value);
|
|
|
}
|
|
|
|
|
|
const loadPackage = <T extends object>(localeData: LocaleProvider<Partial<T>> | undefined) =>
|
|
|
localeData ?
|
|
|
when(localeData(), data => data && "default" in data ? data.default : data) :
|
|
|
undefined;
|
|
|
|
|
|
const chainObjects = <T extends object>(o1: T, o2: Partial<T> | undefined): T =>
|
|
|
o2 ? mixin(Object.create(o1) as T, o2) : o1;
|
|
|
|
|
|
export class NlsBundle<T extends object> {
|
|
|
private readonly _locales: MapOf<LocaleProvider<Partial<T>>>;
|
|
|
|
|
|
private readonly _default: T;
|
|
|
|
|
|
private _cache: MapOf<PromiseOrValue<T>>;
|
|
|
|
|
|
constructor(defNls: T, locales?: MapOf<LocaleProvider<Partial<T>>>) {
|
|
|
this._default = defNls;
|
|
|
this._locales = locales || {};
|
|
|
this._cache = {};
|
|
|
}
|
|
|
|
|
|
getLocale(locale: string) {
|
|
|
argumentNotEmptyString(locale, "locale");
|
|
|
const _loc = locale;
|
|
|
|
|
|
// en-US => ["en", "en-US"]
|
|
|
const locales = _loc.split(/-|_/).map((x, i, a) => a.slice(0, i + 1).join("-"));
|
|
|
return this._resolveLocale(locales);
|
|
|
}
|
|
|
|
|
|
_resolveLocale(locales: string[]): PromiseOrValue<T> {
|
|
|
if (!locales.length)
|
|
|
return this._default;
|
|
|
|
|
|
const locale = locales.pop();
|
|
|
if (!locale)
|
|
|
throw new Error("The locale can't be empty");
|
|
|
|
|
|
if (this._cache[locale])
|
|
|
return this._cache[locale];
|
|
|
|
|
|
const data = loadPackage(this._locales[locale]);
|
|
|
const parent = this._resolveLocale(locales);
|
|
|
|
|
|
return this._cache[locale] = when(data, x => {
|
|
|
return when(parent, y => this._cache[locale] = chainObjects(y, x));
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
|