UNPKG

wuchale

Version:

Protobuf-like i18n from plain code

74 lines (73 loc) 2.17 kB
import { resolve } from "node:path"; import {} from "./adapters.js"; import { defaultGemini } from "./ai/gemini.js"; export const defaultConfig = { sourceLocale: 'en', otherLocales: [], adapters: {}, hmr: true, ai: defaultGemini, logLevel: 'info', }; function deepAssign(fromObj, toObj) { for (const [key, value] of Object.entries(fromObj)) { if (value === undefined) { delete toObj[key]; } if (!value || Array.isArray(value) || typeof value !== 'object') { toObj[key] = value; continue; } // objects if (!toObj[key] || Array.isArray(toObj[key]) || typeof toObj[key] !== 'object') { toObj[key] = {}; } deepAssign(fromObj[key], toObj[key]); } } export function defineConfig(config) { return config; } export function deepMergeObjects(source, target) { const full = { ...target }; deepAssign(source, full); return full; } export const defaultConfigNames = ['js', 'mjs'].map(ext => `wuchale.config.${ext}`); const displayName = new Intl.DisplayNames(['en'], { type: 'language' }); export const getLanguageName = (code) => displayName.of(code) ?? code; function checkValidLocale(locale) { try { getLanguageName(locale); } catch { throw new Error(`Invalid locale identifier: ${locale}`); } } export async function getConfig(configPath) { let module = null; for (const confName of [configPath, ...defaultConfigNames]) { if (!confName) { continue; } const fileUrl = `file://${resolve(confName)}`; try { module = await import(fileUrl); break; } catch (err) { if (err.code !== 'ERR_MODULE_NOT_FOUND' || err.url != fileUrl) { throw err; } } } if (module == null) { throw new Error('Config file not found'); } const config = deepMergeObjects(module.default, defaultConfig); checkValidLocale(config.sourceLocale); for (const loc of config.otherLocales) { checkValidLocale(loc); } return config; }