@woosh/meep-engine
Version:
Pure JavaScript game engine. Fully featured and production ready.
99 lines (71 loc) • 2.61 kB
JavaScript
import { array_get_index_in_range } from "../collection/array/array_get_index_in_range.js";
import { assert } from "../assert.js";
const resolve_chain = [];
export class LocalizationEngine {
/**
*
* @type {Object<LocaleDataset>}
*/
#locales = {};
/**
*
* @type {Object<LanguageMetadata>}
*/
#languages = {};
/**
*
* @param {string} key
* @param {LocaleDataset} dataset
*/
setLocaleDataset(key, dataset) {
assert.isString(key, 'key');
assert.defined(dataset, 'dataset');
this.#locales[key] = dataset;
}
/**
*
* @param {LanguageMetadata} metadata
*/
addLanguageMetadata(metadata) {
assert.defined(metadata, 'metadata');
this.#languages[metadata.locale] = metadata;
}
/**
*
* Resolves language and fragment key to a localized value, follows fallback links of known languages when no value found in requested language
*
* @param {string} language_key Locale key
* @param {string} fragment_key Object key
* @returns {Object|string|undefined}
*/
resolve(language_key, fragment_key) {
resolve_chain[0] = language_key;
let resolve_cursor = 0;
let resolve_chain_end = 1;
while (resolve_cursor < resolve_chain_end) {
const lang = resolve_chain[resolve_cursor++];
const locale = this.#locales[lang];
if (locale !== undefined && locale[fragment_key] !== undefined) {
// found a hit
return locale[fragment_key];
} else {
// see if there's a fallback locale
const metadata = this.#languages[lang];
if (metadata !== undefined) {
const fallbacks = metadata.fallback_languages;
const fallback_count = fallbacks.length;
for (let i = 0; i < fallback_count; i++) {
const fallback = fallbacks[i];
if (array_get_index_in_range(resolve_chain, fallback, 0, resolve_chain_end) !== -1) {
// circular dependency, that language was already attempted
continue;
}
resolve_chain[resolve_chain_end++] = fallback;
}
}
}
}
// chain exhausted, no result found
return undefined;
}
}