UNPKG

@intlayer/core

Version:

Includes core Intlayer functions like translation, dictionary, and utility functions shared across multiple packages.

86 lines (85 loc) 2.88 kB
//#region src/interpreter/getTranslation.ts /** * Check if a value is a plain object that can be safely merged. * Returns false for Promises, React elements, class instances, etc. */ const isPlainObject = (value) => { if (value === null || typeof value !== "object") return false; if (typeof value.then === "function") return false; if (value.$$typeof !== void 0 || value.__v_isVNode !== void 0 || value._isVNode !== void 0 || value.isJSX !== void 0) return false; const proto = Object.getPrototypeOf(value); return proto === Object.prototype || proto === null || Array.isArray(value); }; /** * Recursively merges two objects, skipping undefined source values. * First argument takes precedence. Arrays replace rather than merge. */ const deepMerge = (target, source) => { if (target === void 0) return source; if (source === void 0) return target; if (Array.isArray(target)) return target; if (isPlainObject(target) && isPlainObject(source)) { const result = { ...target }; for (const key of Object.keys(source)) { if (key === "__proto__" || key === "constructor" || source[key] === void 0) continue; result[key] = target[key] !== void 0 ? deepMerge(target[key], source[key]) : source[key]; } return result; } return target; }; /** * Picks the appropriate content from a locale map based on the provided locale. * * It handles: * 1. Exact locale match (e.g., 'en-US'). * 2. Generic locale fallback (e.g., 'en' if 'en-US' is not found). * 3. Explicit fallback locale. * 4. Deep merging of objects to ensure partial translations are complemented by fallbacks. * * @param languageContent - A map of locales to content. * @param locale - The target locale to retrieve. * @param fallback - Optional fallback locale if the target is not found. * @returns The translated content. * * @example * ```ts * const content = getTranslation({ * en: 'Hello', * fr: 'Bonjour', * }, 'fr'); * // 'Bonjour' * ``` */ const getTranslation = (languageContent, locale, fallback) => { const get = (loc) => languageContent[loc]; const seen = /* @__PURE__ */ new Set(); const locales = []; const addLocale = (loc) => { if (loc && !seen.has(loc)) { seen.add(loc); locales.push(loc); } }; addLocale(locale); if (locale.includes("-")) addLocale(locale.split("-")[0]); addLocale(fallback); if (fallback?.includes("-")) addLocale(fallback.split("-")[0]); const results = []; for (const loc of locales) { const val = get(loc); if (val === void 0) continue; if (typeof val === "string") { if (results.length === 0) return val; continue; } results.push(val); } if (results.length === 0) return void 0; if (results.length === 1) return results[0]; if (Array.isArray(results[0])) return results[0]; return results.reduce((acc, curr) => deepMerge(acc, curr)); }; //#endregion export { getTranslation }; //# sourceMappingURL=getTranslation.mjs.map