|
|
import { MapOf } from "@implab/core-amd/interfaces";
|
|
|
import { isPromise, mixin } from "@implab/core-amd/safe";
|
|
|
import { locale as sysLocale } from "dojo/_base/kernel";
|
|
|
import { id as mid } from "module";
|
|
|
import { TraceSource } from "@implab/core-amd/log/TraceSource";
|
|
|
|
|
|
const trace = TraceSource.get(mid);
|
|
|
|
|
|
type PromiseOrValue<T> = PromiseLike<T> | T;
|
|
|
type ResolveCallback<T> = () => PromiseOrValue<T>;
|
|
|
|
|
|
trace.debug("Current sysLocale: {0}", sysLocale);
|
|
|
|
|
|
function when<T, T2>(value: PromiseOrValue<T>, cb: (v: T) => PromiseOrValue<T2>): PromiseOrValue<T2> {
|
|
|
return isPromise(value) ?
|
|
|
value.then(cb) :
|
|
|
cb(value);
|
|
|
}
|
|
|
|
|
|
function isCallback<T>(v: ResolveCallback<T> | PromiseOrValue<T>): v is ResolveCallback<T> {
|
|
|
return typeof v === "function";
|
|
|
}
|
|
|
|
|
|
function chainObjects<T extends object>(o1: T, o2: T) {
|
|
|
if (!o1)
|
|
|
return o2;
|
|
|
if (!o2)
|
|
|
return o1;
|
|
|
|
|
|
return mixin(Object.create(o1) as T, o2);
|
|
|
}
|
|
|
|
|
|
export class NlsBundle<T extends object> {
|
|
|
_locales: MapOf<ResolveCallback<T> | PromiseOrValue<T>>;
|
|
|
default: T;
|
|
|
|
|
|
_cache: MapOf<PromiseOrValue<T>>;
|
|
|
|
|
|
constructor(defNls: T, locales?: MapOf<any>) {
|
|
|
this.default = defNls;
|
|
|
this._locales = locales || {};
|
|
|
this._cache = {};
|
|
|
}
|
|
|
|
|
|
getLocale(locale: string) {
|
|
|
const _loc = locale || sysLocale;
|
|
|
|
|
|
const locales = new Array<string>();
|
|
|
|
|
|
_loc.split("-").reduce((a, x) => {
|
|
|
a.push(x);
|
|
|
locales.unshift(a.join("-"));
|
|
|
return a;
|
|
|
}, new Array<string>());
|
|
|
|
|
|
return this._resolveLocale(locales);
|
|
|
}
|
|
|
|
|
|
_resolveLocale(locales: string[]): PromiseOrValue<T> {
|
|
|
if (!locales.length)
|
|
|
return this.default;
|
|
|
|
|
|
const locale = locales.shift();
|
|
|
|
|
|
if (!locale)
|
|
|
return this._resolveLocale(locales);
|
|
|
|
|
|
if (this._cache[locale])
|
|
|
return this._cache[locale];
|
|
|
|
|
|
let data = this._locales[locale];
|
|
|
if (isCallback(data))
|
|
|
data = data();
|
|
|
|
|
|
const parent = this._resolveLocale(locales);
|
|
|
|
|
|
return this._cache[locale] = when(data, x => {
|
|
|
return when(parent, y => this._cache[locale] = chainObjects(y, x));
|
|
|
});
|
|
|
}
|
|
|
}
|
|
|
|