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 = PromiseLike | T; type ResolveCallback = () => PromiseOrValue; trace.debug("Current sysLocale: {0}", sysLocale); function when(value: PromiseOrValue, cb: (v: T) => PromiseOrValue): PromiseOrValue { return isPromise(value) ? value.then(cb) : cb(value); } function isCallback(v: ResolveCallback | PromiseOrValue): v is ResolveCallback { return typeof v === "function"; } function chainObjects(o1: T, o2: T) { if (!o1) return o2; if (!o2) return o1; return mixin(Object.create(o1) as T, o2); } export class NlsBundle { _locales: MapOf | PromiseOrValue>; default: T; _cache: MapOf>; constructor(defNls: T, locales?: MapOf) { this.default = defNls; this._locales = locales || {}; this._cache = {}; } getLocale(locale: string) { const _loc = locale || sysLocale; const locales = new Array(); _loc.split("-").reduce((a, x) => { a.push(x); locales.unshift(a.join("-")); return a; }, new Array()); return this._resolveLocale(locales); } _resolveLocale(locales: string[]): PromiseOrValue { 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)); }); } }