NlsBundle.ts
60 lines
| 1.9 KiB
| video/mp2t
|
TypeScriptLexer
|
|
r65 | 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); | ||||
| } | ||||
|
|
r112 | 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; | ||||
|
|
r109 | export class NlsBundle<T extends object> { | ||
| private readonly _locales: MapOf<LocaleProvider<Partial<T>>>; | ||||
|
|
r65 | |||
|
|
r109 | private readonly _default: T; | ||
|
|
r65 | |||
| 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]; | ||||
|
|
r112 | const data = loadPackage(this._locales[locale]); | ||
|
|
r65 | const parent = this._resolveLocale(locales); | ||
| return this._cache[locale] = when(data, x => { | ||||
| return when(parent, y => this._cache[locale] = chainObjects(y, x)); | ||||
| }); | ||||
| } | ||||
| } | ||||
