@uploadcare/file-uploader
Version:
Building blocks for Uploadcare products integration
131 lines (112 loc) • 3.55 kB
JavaScript
// @ts-check
import { debounce } from '../../blocks/utils/debounce.js';
import { resolveLocaleDefinition } from '../localeRegistry.js';
import { default as en } from '../../locales/file-uploader/en.js';
/** @param {string} key */
export const localeStateKey = (key) => `*l10n/${key}`;
export const DEFAULT_LOCALE = 'en';
export class LocaleManager {
/**
* @private
* @type {import('../Block.js').Block | null}
*/
_blockInstance = null;
/** @private */
_localeName = '';
/**
* @private
* @type {Set<() => void>}
*/
_callbacks = new Set();
/**
* @private
* @type {Map<import('../Block.js').Block, Map<string, () => void>>}
*/
_boundBlocks = new Map();
/** @param {import('../Block.js').Block} blockInstance */
constructor(blockInstance) {
this._blockInstance = blockInstance;
for (let [key, value] of Object.entries(en)) {
const noTranslation = this._blockInstance.has(localeStateKey(key))
? !this._blockInstance.$[localeStateKey(key)]
: true;
this._blockInstance.add(localeStateKey(key), value, noTranslation);
}
setTimeout(() => {
blockInstance.subConfigValue('localeName', async (localeName) => {
if (!this._blockInstance || !localeName) {
return;
}
this._localeName = localeName;
const definition = await resolveLocaleDefinition(localeName);
if (localeName !== DEFAULT_LOCALE && this._localeName !== localeName) {
return;
}
const overrides = this._blockInstance.cfg.localeDefinitionOverride?.[localeName];
for (const [key, value] of Object.entries(definition)) {
const overriddenValue = overrides?.[key];
this._blockInstance.add(localeStateKey(key), overriddenValue ?? value, true);
for (const callback of this._callbacks) {
callback();
}
}
});
blockInstance.subConfigValue('localeDefinitionOverride', (localeDefinitionOverride) => {
if (!localeDefinitionOverride) {
return;
}
const definition = localeDefinitionOverride[this._localeName];
if (!definition) {
return;
}
for (const [key, value] of Object.entries(definition)) {
this._blockInstance?.add(localeStateKey(key), value, true);
for (const callback of this._callbacks) {
callback();
}
}
});
});
}
/**
* @param {() => void} callback
* @returns {() => void}
*/
onLocaleChange(callback) {
const debouncedCb = debounce(callback, 0);
this._callbacks.add(debouncedCb);
return () => {
this._callbacks.delete(debouncedCb);
};
}
/**
* @param {import('../Block.js').Block} block
* @param {string} key
* @param {() => void} resolver
*/
bindL10n(block, key, resolver) {
block.$[key] = resolver();
if (!this._boundBlocks.has(block)) {
this._boundBlocks.set(block, new Map());
}
this._boundBlocks.get(block)?.get(key)?.();
const destroyCallback = this.onLocaleChange(() => {
block.$[key] = resolver();
});
this._boundBlocks.get(block)?.set(key, destroyCallback);
}
/** @param {import('../Block.js').Block} block */
destroyL10nBindings(block) {
const callbacks = this._boundBlocks.get(block);
if (!callbacks) {
return;
}
for (const callback of callbacks.values()) {
callback();
}
this._boundBlocks.delete(block);
}
destroy() {
this._callbacks.clear();
}
}