penguin/narou-android

Simple 縦書き reader for narou

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;
  }
};