UNPKG

@sentzunhat/zacatl

Version:

A modular, high-performance TypeScript microservice framework for Node.js, featuring layered architecture, dependency injection, and robust validation for building scalable APIs and distributed systems.

156 lines 5.77 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.configureI18nNode = exports.mergeCatalogs = exports.resolveBuiltInLocalesDir = exports.loadCatalog = void 0; const fs_1 = __importDefault(require("fs")); const path_1 = __importDefault(require("path")); const error_1 = require("../error/index.js"); const i18n_1 = __importDefault(require("../third-party/i18n.js")); const isPlainObject = (value) => { return (typeof value === 'object' && value !== null && !Array.isArray(value) && Object.prototype.toString.call(value) === '[object Object]'); }; const deepMerge = (base, override) => { const out = { ...base }; for (const [key, overrideValue] of Object.entries(override)) { const baseValue = out[key]; if (isPlainObject(baseValue) && isPlainObject(overrideValue)) { out[key] = deepMerge(baseValue, overrideValue); continue; } out[key] = overrideValue; } return out; }; const readJsonFile = (filePath) => { const content = fs_1.default.readFileSync(filePath, 'utf-8'); const parsed = JSON.parse(content); if (!isPlainObject(parsed)) { throw new error_1.BadRequestError({ message: `Invalid locale JSON shape in ${filePath}`, reason: 'Locale file must contain a plain JSON object', component: 'I18nNode', operation: 'readJsonFile', metadata: { filePath }, }); } return parsed; }; const findExistingDir = (candidates) => { for (const candidate of candidates) { try { if (fs_1.default.existsSync(candidate) && fs_1.default.statSync(candidate).isDirectory()) { return candidate; } } catch { continue; } } return null; }; const loadCatalog = (input) => { const { localesDir, supportedLocales } = input; const catalog = {}; for (const locale of supportedLocales) { const filePath = path_1.default.join(localesDir, `${locale}.json`); if (!fs_1.default.existsSync(filePath)) { continue; } catalog[locale] = readJsonFile(filePath); } return catalog; }; exports.loadCatalog = loadCatalog; const getHere = () => { if (typeof __dirname !== 'undefined') return __dirname; if (typeof process !== 'undefined' && Array.isArray(process.argv) && typeof process.argv[1] === 'string' && process.argv[1].length > 0) { return path_1.default.dirname(process.argv[1]); } return process.cwd(); }; const resolveBuiltInLocalesDir = () => { const here = getHere(); const candidates = [ path_1.default.resolve(here, 'locales'), path_1.default.resolve(here, '../../build/localization/locales'), path_1.default.resolve(here, '../../src/localization/locales'), path_1.default.resolve(process.cwd(), 'src/localization/locales'), path_1.default.resolve(process.cwd(), 'localization/locales'), path_1.default.resolve(process.cwd(), 'locales'), ]; const found = findExistingDir(candidates); if (found == null) { throw new error_1.NotFoundError({ message: `Unable to locate built-in locales directory. Tried: ${candidates.join(', ')}`, reason: 'Built-in locales directory not found in expected paths', component: 'I18nNode', operation: 'resolveBuiltInLocalesDir', metadata: { candidates }, }); } return found; }; exports.resolveBuiltInLocalesDir = resolveBuiltInLocalesDir; const mergeCatalogs = (input) => { const { base, additions, overrideBuiltIn } = input; const out = {}; const locales = new Set([ ...Object.keys(base), ...additions.flatMap((a) => Object.keys(a)), ]); for (const locale of locales) { const baseLocale = base[locale] ?? {}; const additionsLocale = additions.reduce((acc, addition) => { const addLocale = addition[locale]; if (addLocale == null) { return acc; } return deepMerge(acc, addLocale); }, {}); out[locale] = overrideBuiltIn ? deepMerge(baseLocale, additionsLocale) : deepMerge(additionsLocale, baseLocale); } return out; }; exports.mergeCatalogs = mergeCatalogs; const configureI18nNode = (input = {}) => { const defaultLocale = input.locales?.default ?? 'en'; const supportedLocales = input.locales?.supported ?? ['en', 'es']; const objectNotation = input.objectNotation ?? true; const overrideBuiltIn = input.overrideBuiltIn ?? true; const builtInLocalesDir = (0, exports.resolveBuiltInLocalesDir)(); const builtInCatalog = (0, exports.loadCatalog)({ localesDir: builtInLocalesDir, supportedLocales, }); const additionalCatalogs = (input.locales?.directories ?? []) .filter((dir) => dir != null && dir.length > 0) .map((localesDir) => (0, exports.loadCatalog)({ localesDir, supportedLocales })); const staticCatalog = (0, exports.mergeCatalogs)({ base: builtInCatalog, additions: additionalCatalogs, overrideBuiltIn, }); i18n_1.default.configure({ locales: supportedLocales, defaultLocale, objectNotation, staticCatalog: staticCatalog, updateFiles: false, syncFiles: false, autoReload: false, }); return i18n_1.default; }; exports.configureI18nNode = configureI18nNode; //# sourceMappingURL=i18n-node.js.map