app/src/main/assets/reader/i18n.js
raw · 1871 bytes
/* Language packs are bundled extension assets; no remote translation requests. */
globalThis.NarouI18n = {
async create() {
const read = async file => {
const response = await fetch(browser.runtime.getURL(`langpacks/${file}.json`));
if (!response.ok) throw new Error(`Language pack ${file}: ${response.status}`);
const value = await response.json();
if (!value || typeof value !== 'object' || Array.isArray(value)) throw new Error(`Invalid language pack: ${file}`);
return value;
};
const config = await read('config');
const supported = config.supportedLanguages;
if (!supported || !Object.hasOwn(supported, config.defaultLanguage) ||
!Object.keys(supported).every(code => /^[a-z]{2,3}(?:-[A-Za-z0-9]+)*$/.test(code))) throw new Error('Invalid language configuration');
const fallback = await read(config.defaultLanguage);
let pack = fallback;
const api = {
config, language: config.defaultLanguage,
text(key, values = {}) {
const value = typeof pack[key] === 'string' ? pack[key] : fallback[key];
return (typeof value === 'string' ? value : key).replace(/\{(\w+)\}/g, (match, name) => String(values[name] ?? match));
},
async setLanguage(code) {
if (!Object.hasOwn(supported, code)) code = config.defaultLanguage;
try {
const next = code === config.defaultLanguage ? fallback : await read(code);
pack = next; api.language = code;
} catch (error) {
console.warn('Could not load language pack', error);
pack = fallback; api.language = config.defaultLanguage;
}
}
};
let stored;
try { stored = (await browser.storage.local.get('narouTategaki')).narouTategaki?.language; } catch (_) {}
await api.setLanguage(stored || config.defaultLanguage);
return api;
}
};