andrei-bread-i18n
Version:
Small and type-safe package to create multi-language interfaces.
69 lines (68 loc) • 2.28 kB
JavaScript
export class I18N {
lang;
subscribers = new Set();
keysets;
constructor(options) {
this.keysets = options.languages;
this.setLang(options.defaultLang);
// call it just for the TS to not complain
this.lang = options.defaultLang;
}
getLang() {
return this.lang;
}
get(key, ...rest) {
const { keyset, pluralize } = this.keysets[this.lang];
if (typeof keyset === "function") {
return String(key);
}
const translation = keyset[key];
if (typeof translation === "undefined") {
return String(key);
}
const params = rest[0] || {};
if (typeof translation === "string") {
return interpolateTranslation(translation, params);
}
const pluralKey = pluralize(params.count);
const pluralizedTranslation = translation[pluralKey];
return interpolateTranslation(pluralizedTranslation, params);
}
async setLang(newLang) {
try {
if (newLang === this.lang) {
return;
}
const { keyset } = this.keysets[newLang];
if (typeof keyset === "function") {
const resolvedKeyset = await keyset();
this.keysets[newLang].keyset = resolvedKeyset;
}
this.lang = newLang;
this.subscribers.forEach((cb) => cb(newLang));
}
catch (error) {
console.error(`Error happened trying to update language. Can not resolve lazy loaded keyset for "${String(newLang)}" language. See the error below to get more details`);
throw error;
}
}
subscribe(cb, options) {
this.subscribers.add(cb);
if (options?.immediate) {
cb(this.lang);
}
return () => {
this.subscribers.delete(cb);
};
}
}
const mustacheParamRegex = /\{\{\s*([a-zA-Z10-9]+)\s*\}\}/g;
// not the most performant way, but it should be okay
function interpolateTranslation(translation, params) {
return translation.replace(mustacheParamRegex, (original, paramKey) => {
if (paramKey in params) {
return String(params[paramKey]);
}
return original;
});
}