@intlayer/i18next 9.5.1 → 9.5.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -1
- package/dist/esm/createInstance.mjs +10 -18
- package/dist/esm/createInstance.mjs.map +1 -1
- package/dist/esm/index.mjs.map +1 -1
- package/dist/esm/resolveTranslation.mjs +2 -2
- package/dist/esm/resolveTranslation.mjs.map +1 -1
- package/dist/types/createInstance.d.ts +0 -2
- package/dist/types/createInstance.d.ts.map +1 -1
- package/dist/types/getDictionary.d.ts +1 -1
- package/dist/types/getDictionaryDynamic.d.ts +1 -1
- package/dist/types/index.d.ts +1 -1
- package/dist/types/index.d.ts.map +1 -1
- package/dist/types/typedTranslation.d.ts +1 -1
- package/package.json +9 -9
package/README.md
CHANGED
|
@@ -328,4 +328,4 @@ Contribute on [GitHub](https://github.com/aymericzip/intlayer), [GitLab](https:/
|
|
|
328
328
|
|
|
329
329
|
If you like Intlayer, give us a ⭐ on GitHub. It helps others discover the project! [See why GitHub Stars matter](https://github.com/aymericzip/intlayer/blob/main/CONTRIBUTING.md#why-github-stars-matter-).
|
|
330
330
|
|
|
331
|
-
[](https://
|
|
331
|
+
[](https://star-history.com/#aymericzip/intlayer&Date)
|
|
@@ -1,9 +1,10 @@
|
|
|
1
1
|
import { getInterpolationValues, resolveTranslation } from "./resolveTranslation.mjs";
|
|
2
2
|
import { internationalization, log } from "@intlayer/config/built";
|
|
3
3
|
import { getIntlayer } from "@intlayer/core/interpreter";
|
|
4
|
-
import { navigatePath,
|
|
4
|
+
import { navigatePath, resolveMessageNodeToString } from "@intlayer/core/messageFormat";
|
|
5
5
|
import * as ANSIColors from "@intlayer/config/colors";
|
|
6
6
|
import { colorize, getAppLogger } from "@intlayer/config/logger";
|
|
7
|
+
import { getHTMLTextDir } from "@intlayer/core/localization";
|
|
7
8
|
|
|
8
9
|
//#region src/createInstance.ts
|
|
9
10
|
const warnIgnoredResources = (location) => {
|
|
@@ -41,7 +42,7 @@ const createInstance = (instanceOptions = {}) => {
|
|
|
41
42
|
});
|
|
42
43
|
if (resolved !== void 0) return resolved;
|
|
43
44
|
const defaultValue = options?.defaultValue;
|
|
44
|
-
if (typeof defaultValue === "string") return
|
|
45
|
+
if (typeof defaultValue === "string") return resolveMessageNodeToString(defaultValue, getInterpolationValues(options), lang);
|
|
45
46
|
return key;
|
|
46
47
|
};
|
|
47
48
|
const instance = {
|
|
@@ -94,12 +95,12 @@ const createInstance = (instanceOptions = {}) => {
|
|
|
94
95
|
if (result !== void 0) return result;
|
|
95
96
|
}
|
|
96
97
|
const defaultValue = options?.defaultValue;
|
|
97
|
-
if (typeof defaultValue === "string") return
|
|
98
|
+
if (typeof defaultValue === "string") return resolveMessageNodeToString(defaultValue, getInterpolationValues(options), currentLanguage);
|
|
98
99
|
return defaultValue ?? (Array.isArray(key) ? key[key.length - 1] : key);
|
|
99
100
|
},
|
|
100
|
-
async changeLanguage(
|
|
101
|
+
async changeLanguage(language, cb) {
|
|
101
102
|
const prev = currentLanguage;
|
|
102
|
-
if (
|
|
103
|
+
if (language) currentLanguage = language;
|
|
103
104
|
emit("languageChanged", currentLanguage, prev);
|
|
104
105
|
const t = instance.t.bind(instance);
|
|
105
106
|
cb?.(null, t);
|
|
@@ -128,8 +129,8 @@ const createInstance = (instanceOptions = {}) => {
|
|
|
128
129
|
* tAbout('counter.label'); // ✓ typed key and return value
|
|
129
130
|
* ```
|
|
130
131
|
*/
|
|
131
|
-
getFixedT: ((
|
|
132
|
-
const fixedLng = Array.isArray(
|
|
132
|
+
getFixedT: ((language, ns, keyPrefix) => {
|
|
133
|
+
const fixedLng = Array.isArray(language) ? language[0] ?? currentLanguage : language ?? currentLanguage;
|
|
133
134
|
const fixedNS = ns ?? defaultNS;
|
|
134
135
|
return (key, opts) => {
|
|
135
136
|
const fullKey = keyPrefix ? `${keyPrefix}.${key}` : key;
|
|
@@ -172,17 +173,8 @@ const createInstance = (instanceOptions = {}) => {
|
|
|
172
173
|
...opts
|
|
173
174
|
});
|
|
174
175
|
},
|
|
175
|
-
dir(
|
|
176
|
-
return
|
|
177
|
-
"ar",
|
|
178
|
-
"he",
|
|
179
|
-
"fa",
|
|
180
|
-
"ur",
|
|
181
|
-
"ps",
|
|
182
|
-
"yi",
|
|
183
|
-
"dv",
|
|
184
|
-
"ug"
|
|
185
|
-
].some((l) => (lng ?? currentLanguage).startsWith(l)) ? "rtl" : "ltr";
|
|
176
|
+
dir(language) {
|
|
177
|
+
return getHTMLTextDir(language ?? currentLanguage) === "rtl" ? "rtl" : "ltr";
|
|
186
178
|
},
|
|
187
179
|
setDefaultNamespace(ns) {
|
|
188
180
|
defaultNS = ns;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createInstance.mjs","names":[],"sources":["../../src/createInstance.ts"],"sourcesContent":["import { internationalization, log } from '@intlayer/config/built';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, getAppLogger } from '@intlayer/config/logger';\nimport { getIntlayer } from '@intlayer/core/interpreter';\nimport { navigatePath, resolveMessage } from '@intlayer/core/messageFormat';\nimport type {\n DictionaryKeys,\n LocalesValues,\n} from '@intlayer/types/module_augmentation';\nimport type {\n createInstance as _createInstance,\n i18n as I18nInterface,\n InitOptions,\n TOptions,\n} from 'i18next';\nimport {\n getInterpolationValues,\n resolveTranslation,\n} from './resolveTranslation';\nimport type { TypedGetFixedT } from './typedTranslation';\n\nexport type { TypedGetFixedT } from './typedTranslation';\n\ntype EventHandler = (...args: unknown[]) => void;\n\nconst warnIgnoredResources = (location: string) => {\n const appLogger = getAppLogger({ log });\n appLogger(\n `${colorize(location, ANSIColors.CYAN)}: the ${colorize('`resources`', ANSIColors.CYAN)} option is ignored when using ${colorize('@intlayer/i18next', ANSIColors.MAGENTA)} — translations are served from the compiled intlayer dictionaries instead. Remove the resource imports and the ${colorize('`resources`', ANSIColors.CYAN)} option to reduce your bundle size.`\n );\n};\n\nexport const createInstance: typeof _createInstance = (\n instanceOptions: InitOptions = {}\n): I18nInterface => {\n if ((instanceOptions as Record<string, unknown>).resources !== undefined) {\n warnIgnoredResources('createInstance');\n }\n\n const config = internationalization;\n\n let currentLanguage: string =\n (instanceOptions.lng as string) ?? config?.defaultLocale ?? 'en';\n\n let defaultNS: string =\n (instanceOptions.defaultNS as string) ??\n (Array.isArray(instanceOptions.ns)\n ? (instanceOptions.ns[0] as string)\n : (instanceOptions.ns as string)) ??\n 'translation';\n\n const listeners = new Map<string, Set<EventHandler>>();\n let initialized = false;\n\n const emit = (event: string, ...args: unknown[]) => {\n listeners.get(event)?.forEach((h) => {\n h(...args);\n });\n };\n\n const getSeparators = () => ({\n keySeparator:\n (instanceOptions.keySeparator as string | false | undefined) ?? '.',\n nsSeparator:\n (instanceOptions.nsSeparator as string | false | undefined) ?? ':',\n });\n\n /**\n * Resolves a key through the full i18next pipeline (namespace prefix,\n * `ns` option, plural/context suffixes, `$t()` nesting, interpolation).\n * Falls back to the interpolated `defaultValue`, then to the key itself.\n */\n const resolveKey = (\n lang: string,\n ns: string,\n key: string,\n opts?: TOptions | string\n ): string => {\n const options =\n typeof opts === 'string' ? { defaultValue: opts } : (opts as TOptions);\n\n const resolved = resolveTranslation({\n locale: lang as LocalesValues,\n namespace: ns,\n key,\n options,\n ...getSeparators(),\n });\n\n if (resolved !== undefined) return resolved as string;\n\n const defaultValue = (options as Record<string, unknown> | undefined)\n ?.defaultValue;\n if (typeof defaultValue === 'string') {\n return resolveMessage(\n defaultValue,\n getInterpolationValues(options),\n lang as LocalesValues,\n 'i18next'\n );\n }\n\n return key;\n };\n\n const instance = {\n get language() {\n return currentLanguage;\n },\n get languages() {\n return (config?.locales?.map(String) ?? [\n currentLanguage,\n ]) as readonly string[];\n },\n get resolvedLanguage() {\n return currentLanguage;\n },\n get isInitialized() {\n return initialized;\n },\n isInitializing: false,\n initializedStoreOnce: false,\n initializedLanguageOnce: false,\n options: instanceOptions,\n modules: {} as I18nInterface['modules'],\n services: {} as I18nInterface['services'],\n store: {} as I18nInterface['store'],\n format: ((value: unknown) => String(value)) as I18nInterface['format'],\n\n async init(optionsOrCb?: unknown, cb?: unknown) {\n const opts =\n typeof optionsOrCb === 'function'\n ? {}\n : ((optionsOrCb ?? {}) as Record<string, unknown>);\n if (opts.resources !== undefined) {\n warnIgnoredResources('i18next.init');\n }\n if (opts.lng) currentLanguage = opts.lng as string;\n if (opts.defaultNS) defaultNS = opts.defaultNS as string;\n else if (opts.ns)\n defaultNS = Array.isArray(opts.ns)\n ? (opts.ns[0] as string)\n : (opts.ns as string);\n initialized = true;\n emit('initialized', opts);\n const t = instance.t.bind(instance);\n const callback = typeof optionsOrCb === 'function' ? optionsOrCb : cb;\n (callback as ((err: unknown, t: unknown) => void) | undefined)?.(null, t);\n return t as unknown as Promise<I18nInterface['t']>;\n },\n\n t(\n key: unknown,\n optionsOrDefaultValue?: unknown,\n extraOpts?: unknown\n ): unknown {\n const options =\n typeof optionsOrDefaultValue === 'string'\n ? {\n defaultValue: optionsOrDefaultValue,\n ...((extraOpts ?? {}) as Record<string, unknown>),\n }\n : (optionsOrDefaultValue as TOptions | undefined);\n const keys: string[] = Array.isArray(key)\n ? (key as string[])\n : [String(key)];\n for (const candidateKey of keys) {\n const result = resolveTranslation({\n locale: currentLanguage as LocalesValues,\n namespace: defaultNS,\n key: candidateKey,\n options,\n ...getSeparators(),\n });\n if (result !== undefined) return result;\n }\n\n const defaultValue = (options as Record<string, unknown> | undefined)\n ?.defaultValue;\n if (typeof defaultValue === 'string') {\n return resolveMessage(\n defaultValue,\n getInterpolationValues(options),\n currentLanguage as LocalesValues,\n 'i18next'\n );\n }\n\n return defaultValue ?? (Array.isArray(key) ? key[key.length - 1] : key);\n },\n\n async changeLanguage(lng?: string, cb?: unknown) {\n const prev = currentLanguage;\n if (lng) currentLanguage = lng;\n emit('languageChanged', currentLanguage, prev);\n const t = instance.t.bind(instance);\n (cb as ((err: unknown, t: unknown) => void) | undefined)?.(null, t);\n return t as unknown as Promise<I18nInterface['t']>;\n },\n\n exists(key: string, options?: unknown): boolean {\n return (\n resolveTranslation({\n locale: currentLanguage as LocalesValues,\n namespace: defaultNS,\n key,\n options: options as TOptions,\n ...getSeparators(),\n }) !== undefined\n );\n },\n\n /**\n * Returns a `t()` function bound to a fixed locale and namespace.\n * When `ns` matches a registered intlayer dictionary key, the returned\n * function's `key` parameter is typed to only accept valid dot-notation\n * paths for that dictionary, and its return type is resolved from the\n * content at that path. With a `keyPrefix`, keys are relative dot-paths\n * under the prefix.\n *\n * @example\n * ```ts\n * const tAbout = i18n.getFixedT(null, 'about');\n * tAbout('counter.label'); // ✓ typed key and return value\n * ```\n */\n getFixedT: ((\n lng: string | readonly string[] | null,\n ns?: string | null,\n keyPrefix?: string\n ) => {\n const fixedLng = Array.isArray(lng)\n ? ((lng[0] as string) ?? currentLanguage)\n : ((lng as string) ?? currentLanguage);\n const fixedNS = ns ?? defaultNS;\n return (key: string, opts?: TOptions): string => {\n const fullKey = keyPrefix ? `${keyPrefix}.${key}` : key;\n return resolveKey(fixedLng, fixedNS, fullKey, opts);\n };\n }) as TypedGetFixedT,\n\n use(module: unknown) {\n (module as { init?: (i18n: I18nInterface) => void })?.init?.(\n instance as unknown as I18nInterface\n );\n return instance as unknown as I18nInterface;\n },\n\n on(event: string, handler: EventHandler) {\n if (!listeners.has(event)) listeners.set(event, new Set());\n listeners.get(event)!.add(handler);\n return instance as unknown as I18nInterface;\n },\n\n once(event: string, handler: EventHandler) {\n const wrapper: EventHandler = (...args) => {\n handler(...args);\n instance.off(event, wrapper);\n };\n instance.on(event, wrapper);\n return instance as unknown as I18nInterface;\n },\n\n off(event: string, handler?: EventHandler) {\n if (!handler) listeners.delete(event);\n else listeners.get(event)?.delete(handler);\n },\n\n emit(eventName: string, ...args: unknown[]) {\n emit(eventName, ...args);\n },\n\n createInstance(opts?: InitOptions, _cb?: unknown) {\n return createInstance({ ...instanceOptions, ...opts });\n },\n\n cloneInstance(opts?: Record<string, unknown>, _cb?: unknown) {\n return createInstance({ ...instanceOptions, ...opts });\n },\n\n dir(lng?: string): 'ltr' | 'rtl' {\n const rtl = ['ar', 'he', 'fa', 'ur', 'ps', 'yi', 'dv', 'ug'];\n return rtl.some((l) => (lng ?? currentLanguage).startsWith(l))\n ? 'rtl'\n : 'ltr';\n },\n\n setDefaultNamespace(ns: string) {\n defaultNS = ns;\n },\n\n hasLoadedNamespace(ns: string | readonly string[]): boolean {\n try {\n getIntlayer(\n (Array.isArray(ns) ? ns[0] : ns) as DictionaryKeys,\n currentLanguage as LocalesValues\n );\n return true;\n } catch {\n return false;\n }\n },\n\n async loadNamespaces(_ns: unknown) {},\n async loadLanguages(_lngs: unknown) {},\n loadResources(_cb?: unknown) {},\n async reloadResources() {},\n\n getDataByLanguage(_lng: string) {\n return undefined;\n },\n\n getResource(lng: string, ns: string, key: string): unknown {\n try {\n return navigatePath(\n getIntlayer(ns as DictionaryKeys, lng as LocalesValues),\n key\n );\n } catch {\n return undefined;\n }\n },\n\n addResource: () => instance as unknown as I18nInterface,\n addResources: () => instance as unknown as I18nInterface,\n addResourceBundle: () => instance as unknown as I18nInterface,\n hasResourceBundle: () => false,\n getResourceBundle: () => undefined,\n removeResourceBundle: () => instance as unknown as I18nInterface,\n\n toJSON() {\n return {\n options: instanceOptions,\n store: {} as I18nInterface['store'],\n language: currentLanguage,\n languages: (config?.locales?.map(String) ?? [\n currentLanguage,\n ]) as readonly string[],\n resolvedLanguage: currentLanguage,\n };\n },\n };\n\n return instance as unknown as I18nInterface;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"createInstance.mjs","names":[],"sources":["../../src/createInstance.ts"],"sourcesContent":["import { internationalization, log } from '@intlayer/config/built';\nimport * as ANSIColors from '@intlayer/config/colors';\nimport { colorize, getAppLogger } from '@intlayer/config/logger';\nimport { getIntlayer } from '@intlayer/core/interpreter';\nimport { getHTMLTextDir } from '@intlayer/core/localization';\nimport {\n navigatePath,\n resolveMessageNodeToString,\n} from '@intlayer/core/messageFormat';\nimport type {\n DictionaryKeys,\n LocalesValues,\n} from '@intlayer/types/module_augmentation';\nimport type {\n createInstance as _createInstance,\n i18n as I18nInterface,\n InitOptions,\n TOptions,\n} from 'i18next';\nimport {\n getInterpolationValues,\n resolveTranslation,\n} from './resolveTranslation';\nimport type { TypedGetFixedT } from './typedTranslation';\n\ntype EventHandler = (...args: unknown[]) => void;\n\nconst warnIgnoredResources = (location: string) => {\n const appLogger = getAppLogger({ log });\n appLogger(\n `${colorize(location, ANSIColors.CYAN)}: the ${colorize('`resources`', ANSIColors.CYAN)} option is ignored when using ${colorize('@intlayer/i18next', ANSIColors.MAGENTA)} — translations are served from the compiled intlayer dictionaries instead. Remove the resource imports and the ${colorize('`resources`', ANSIColors.CYAN)} option to reduce your bundle size.`\n );\n};\n\nexport const createInstance: typeof _createInstance = (\n instanceOptions: InitOptions = {}\n): I18nInterface => {\n if ((instanceOptions as Record<string, unknown>).resources !== undefined) {\n warnIgnoredResources('createInstance');\n }\n\n const config = internationalization;\n\n let currentLanguage: string =\n (instanceOptions.lng as string) ?? config?.defaultLocale ?? 'en';\n\n let defaultNS: string =\n (instanceOptions.defaultNS as string) ??\n (Array.isArray(instanceOptions.ns)\n ? (instanceOptions.ns[0] as string)\n : (instanceOptions.ns as string)) ??\n 'translation';\n\n const listeners = new Map<string, Set<EventHandler>>();\n let initialized = false;\n\n const emit = (event: string, ...args: unknown[]) => {\n listeners.get(event)?.forEach((h) => {\n h(...args);\n });\n };\n\n const getSeparators = () => ({\n keySeparator:\n (instanceOptions.keySeparator as string | false | undefined) ?? '.',\n nsSeparator:\n (instanceOptions.nsSeparator as string | false | undefined) ?? ':',\n });\n\n /**\n * Resolves a key through the full i18next pipeline (namespace prefix,\n * `ns` option, plural/context suffixes, `$t()` nesting, interpolation).\n * Falls back to the interpolated `defaultValue`, then to the key itself.\n */\n const resolveKey = (\n lang: string,\n ns: string,\n key: string,\n opts?: TOptions | string\n ): string => {\n const options =\n typeof opts === 'string' ? { defaultValue: opts } : (opts as TOptions);\n\n const resolved = resolveTranslation({\n locale: lang as LocalesValues,\n namespace: ns,\n key,\n options,\n ...getSeparators(),\n });\n\n if (resolved !== undefined) return resolved as string;\n\n const defaultValue = (options as Record<string, unknown> | undefined)\n ?.defaultValue;\n if (typeof defaultValue === 'string') {\n // A runtime default gets `{{name}}` / `{{price, number}}` interpolation only;\n // dialect constructs (`$t()`, plural blocks) belong in dictionaries, where\n // the build converts them — parsing them here would ship the parser.\n return resolveMessageNodeToString(\n defaultValue,\n getInterpolationValues(options),\n lang as LocalesValues\n );\n }\n\n return key;\n };\n\n const instance = {\n get language() {\n return currentLanguage;\n },\n get languages() {\n return (config?.locales?.map(String) ?? [\n currentLanguage,\n ]) as readonly string[];\n },\n get resolvedLanguage() {\n return currentLanguage;\n },\n get isInitialized() {\n return initialized;\n },\n isInitializing: false,\n initializedStoreOnce: false,\n initializedLanguageOnce: false,\n options: instanceOptions,\n modules: {} as I18nInterface['modules'],\n services: {} as I18nInterface['services'],\n store: {} as I18nInterface['store'],\n format: ((value: unknown) => String(value)) as I18nInterface['format'],\n\n async init(optionsOrCb?: unknown, cb?: unknown) {\n const opts =\n typeof optionsOrCb === 'function'\n ? {}\n : ((optionsOrCb ?? {}) as Record<string, unknown>);\n if (opts.resources !== undefined) {\n warnIgnoredResources('i18next.init');\n }\n if (opts.lng) currentLanguage = opts.lng as string;\n if (opts.defaultNS) defaultNS = opts.defaultNS as string;\n else if (opts.ns)\n defaultNS = Array.isArray(opts.ns)\n ? (opts.ns[0] as string)\n : (opts.ns as string);\n initialized = true;\n emit('initialized', opts);\n const t = instance.t.bind(instance);\n const callback = typeof optionsOrCb === 'function' ? optionsOrCb : cb;\n (callback as ((err: unknown, t: unknown) => void) | undefined)?.(null, t);\n return t as unknown as Promise<I18nInterface['t']>;\n },\n\n t(\n key: unknown,\n optionsOrDefaultValue?: unknown,\n extraOpts?: unknown\n ): unknown {\n const options =\n typeof optionsOrDefaultValue === 'string'\n ? {\n defaultValue: optionsOrDefaultValue,\n ...((extraOpts ?? {}) as Record<string, unknown>),\n }\n : (optionsOrDefaultValue as TOptions | undefined);\n const keys: string[] = Array.isArray(key)\n ? (key as string[])\n : [String(key)];\n for (const candidateKey of keys) {\n const result = resolveTranslation({\n locale: currentLanguage as LocalesValues,\n namespace: defaultNS,\n key: candidateKey,\n options,\n ...getSeparators(),\n });\n if (result !== undefined) return result;\n }\n\n const defaultValue = (options as Record<string, unknown> | undefined)\n ?.defaultValue;\n if (typeof defaultValue === 'string') {\n // A runtime default gets `{{name}}` / `{{price, number}}` interpolation only;\n // dialect constructs (`$t()`, plural blocks) belong in dictionaries, where\n // the build converts them — parsing them here would ship the parser.\n return resolveMessageNodeToString(\n defaultValue,\n getInterpolationValues(options),\n currentLanguage as LocalesValues\n );\n }\n\n return defaultValue ?? (Array.isArray(key) ? key[key.length - 1] : key);\n },\n\n async changeLanguage(language?: string, cb?: unknown) {\n const prev = currentLanguage;\n\n if (language) currentLanguage = language;\n\n emit('languageChanged', currentLanguage, prev);\n const t = instance.t.bind(instance);\n\n (cb as ((err: unknown, t: unknown) => void) | undefined)?.(null, t);\n\n return t as unknown as Promise<I18nInterface['t']>;\n },\n\n exists(key: string, options?: unknown): boolean {\n return (\n resolveTranslation({\n locale: currentLanguage as LocalesValues,\n namespace: defaultNS,\n key,\n options: options as TOptions,\n ...getSeparators(),\n }) !== undefined\n );\n },\n\n /**\n * Returns a `t()` function bound to a fixed locale and namespace.\n * When `ns` matches a registered intlayer dictionary key, the returned\n * function's `key` parameter is typed to only accept valid dot-notation\n * paths for that dictionary, and its return type is resolved from the\n * content at that path. With a `keyPrefix`, keys are relative dot-paths\n * under the prefix.\n *\n * @example\n * ```ts\n * const tAbout = i18n.getFixedT(null, 'about');\n * tAbout('counter.label'); // ✓ typed key and return value\n * ```\n */\n getFixedT: ((\n language: string | readonly string[] | null,\n ns?: string | null,\n keyPrefix?: string\n ) => {\n const fixedLng = Array.isArray(language)\n ? ((language[0] as string) ?? currentLanguage)\n : ((language as string) ?? currentLanguage);\n\n const fixedNS = ns ?? defaultNS;\n\n return (key: string, opts?: TOptions): string => {\n const fullKey = keyPrefix ? `${keyPrefix}.${key}` : key;\n return resolveKey(fixedLng, fixedNS, fullKey, opts);\n };\n }) as TypedGetFixedT,\n\n use(module: unknown) {\n (module as { init?: (i18n: I18nInterface) => void })?.init?.(\n instance as unknown as I18nInterface\n );\n return instance as unknown as I18nInterface;\n },\n\n on(event: string, handler: EventHandler) {\n if (!listeners.has(event)) listeners.set(event, new Set());\n listeners.get(event)!.add(handler);\n return instance as unknown as I18nInterface;\n },\n\n once(event: string, handler: EventHandler) {\n const wrapper: EventHandler = (...args) => {\n handler(...args);\n instance.off(event, wrapper);\n };\n instance.on(event, wrapper);\n return instance as unknown as I18nInterface;\n },\n\n off(event: string, handler?: EventHandler) {\n if (!handler) listeners.delete(event);\n else listeners.get(event)?.delete(handler);\n },\n\n emit(eventName: string, ...args: unknown[]) {\n emit(eventName, ...args);\n },\n\n createInstance(opts?: InitOptions, _cb?: unknown) {\n return createInstance({ ...instanceOptions, ...opts });\n },\n\n cloneInstance(opts?: Record<string, unknown>, _cb?: unknown) {\n return createInstance({ ...instanceOptions, ...opts });\n },\n\n dir(language?: string): 'ltr' | 'rtl' {\n const direction = getHTMLTextDir(\n (language ?? currentLanguage) as LocalesValues\n );\n return direction === 'rtl' ? 'rtl' : 'ltr';\n },\n\n setDefaultNamespace(ns: string) {\n defaultNS = ns;\n },\n\n hasLoadedNamespace(ns: string | readonly string[]): boolean {\n try {\n getIntlayer(\n (Array.isArray(ns) ? ns[0] : ns) as DictionaryKeys,\n currentLanguage as LocalesValues\n );\n return true;\n } catch {\n return false;\n }\n },\n\n async loadNamespaces(_ns: unknown) {},\n async loadLanguages(_lngs: unknown) {},\n loadResources(_cb?: unknown) {},\n async reloadResources() {},\n\n getDataByLanguage(_lng: string) {\n return undefined;\n },\n\n getResource(lng: string, ns: string, key: string): unknown {\n try {\n return navigatePath(\n getIntlayer(ns as DictionaryKeys, lng as LocalesValues),\n key\n );\n } catch {\n return undefined;\n }\n },\n\n addResource: () => instance as unknown as I18nInterface,\n addResources: () => instance as unknown as I18nInterface,\n addResourceBundle: () => instance as unknown as I18nInterface,\n hasResourceBundle: () => false,\n getResourceBundle: () => undefined,\n removeResourceBundle: () => instance as unknown as I18nInterface,\n\n toJSON() {\n return {\n options: instanceOptions,\n store: {} as I18nInterface['store'],\n language: currentLanguage,\n languages: (config?.locales?.map(String) ?? [\n currentLanguage,\n ]) as readonly string[],\n resolvedLanguage: currentLanguage,\n };\n },\n };\n\n return instance as unknown as I18nInterface;\n};\n"],"mappings":"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"}
|
package/dist/esm/index.mjs.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/index.ts"],"sourcesContent":["import type {\n changeLanguage as _changeLanguage,\n dir as _dir,\n exists as _exists,\n hasLoadedNamespace as _hasLoadedNamespace,\n init as _init,\n loadLanguages as _loadLanguages,\n loadNamespaces as _loadNamespaces,\n loadResources as _loadResources,\n reloadResources as _reloadResources,\n setDefaultNamespace as _setDefaultNamespace,\n t as _t,\n use as _use,\n i18n,\n} from 'i18next';\nimport { createInstance
|
|
1
|
+
{"version":3,"file":"index.mjs","names":[],"sources":["../../src/index.ts"],"sourcesContent":["import type {\n changeLanguage as _changeLanguage,\n dir as _dir,\n exists as _exists,\n hasLoadedNamespace as _hasLoadedNamespace,\n init as _init,\n loadLanguages as _loadLanguages,\n loadNamespaces as _loadNamespaces,\n loadResources as _loadResources,\n reloadResources as _reloadResources,\n setDefaultNamespace as _setDefaultNamespace,\n t as _t,\n use as _use,\n i18n,\n} from 'i18next';\nimport { createInstance } from './createInstance';\nimport type { TypedGetFixedT } from './typedTranslation';\n\nexport { getDictionary } from './getDictionary';\nexport { getDictionaryDynamic } from './getDictionaryDynamic';\nexport {\n getInterpolationValues,\n type ResolveTranslationParams,\n resolveTranslation,\n} from './resolveTranslation';\nexport type {\n ContentAtPath,\n ScopedDotPaths,\n ScopedTFunction,\n TranslatedValue,\n TypedGetFixedT,\n TypedTFunction,\n} from './typedTranslation';\n\nconst i18next: i18n = createInstance();\n\nexport { createInstance };\nexport default i18next;\nexport { i18next };\n\nexport const dir: typeof _dir = i18next.dir.bind(i18next);\nexport const init: typeof _init = i18next.init.bind(i18next);\nexport const loadResources: typeof _loadResources =\n i18next.loadResources.bind(i18next);\nexport const reloadResources: typeof _reloadResources =\n i18next.reloadResources.bind(i18next);\nexport const use: typeof _use = i18next.use.bind(i18next);\nexport const changeLanguage: typeof _changeLanguage =\n i18next.changeLanguage.bind(i18next);\n\n/**\n * Returns a `t()` function bound to a fixed locale and namespace.\n * When `ns` matches a registered intlayer dictionary key, the returned\n * function's `key` parameter is typed to only accept valid dot-notation\n * paths for that dictionary.\n *\n * @example\n * ```ts\n * const tAbout = getFixedT(null, 'about');\n * tAbout('counter.label'); // ✓ typed\n * ```\n */\nexport const getFixedT: TypedGetFixedT = i18next.getFixedT.bind(\n i18next\n) as unknown as TypedGetFixedT;\n\nexport const t: typeof _t = i18next.t.bind(i18next);\nexport const exists: typeof _exists = i18next.exists.bind(i18next);\nexport const setDefaultNamespace: typeof _setDefaultNamespace =\n i18next.setDefaultNamespace.bind(i18next);\nexport const hasLoadedNamespace: typeof _hasLoadedNamespace =\n i18next.hasLoadedNamespace.bind(i18next);\nexport const loadNamespaces: typeof _loadNamespaces =\n i18next.loadNamespaces.bind(i18next);\nexport const loadLanguages: typeof _loadLanguages =\n i18next.loadLanguages.bind(i18next);\n\n/**\n * No-op shim for i18next's `keyFromSelector`. This helper is not exposed by\n * every supported i18next version, so a permissive identity function is\n * provided to keep `.keyFromSelector(...)` call-sites working.\n */\nexport const keyFromSelector = (selector: unknown): unknown => selector;\n\nexport type { InitOptions, i18n, TFunction, TOptions } from 'i18next';\n"],"mappings":";;;;;;AAkCA,MAAM,UAAgB,eAAe;AAMrC,MAAa,MAAmB,QAAQ,IAAI,KAAK,OAAO;AACxD,MAAa,OAAqB,QAAQ,KAAK,KAAK,OAAO;AAC3D,MAAa,gBACX,QAAQ,cAAc,KAAK,OAAO;AACpC,MAAa,kBACX,QAAQ,gBAAgB,KAAK,OAAO;AACtC,MAAa,MAAmB,QAAQ,IAAI,KAAK,OAAO;AACxD,MAAa,iBACX,QAAQ,eAAe,KAAK,OAAO;;;;;;;;;;;;;AAcrC,MAAa,YAA4B,QAAQ,UAAU,KACzD,OACF;AAEA,MAAa,IAAe,QAAQ,EAAE,KAAK,OAAO;AAClD,MAAa,SAAyB,QAAQ,OAAO,KAAK,OAAO;AACjE,MAAa,sBACX,QAAQ,oBAAoB,KAAK,OAAO;AAC1C,MAAa,qBACX,QAAQ,mBAAmB,KAAK,OAAO;AACzC,MAAa,iBACX,QAAQ,eAAe,KAAK,OAAO;AACrC,MAAa,gBACX,QAAQ,cAAc,KAAK,OAAO;;;;;;AAOpC,MAAa,mBAAmB,aAA+B"}
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { getIntlayer } from "@intlayer/core/interpreter";
|
|
2
|
-
import { navigatePath,
|
|
2
|
+
import { navigatePath, resolveMessageNodeToString } from "@intlayer/core/messageFormat";
|
|
3
3
|
import { getDictionaries } from "@intlayer/dictionaries-entry";
|
|
4
4
|
|
|
5
5
|
//#region src/resolveTranslation.ts
|
|
@@ -132,7 +132,7 @@ const resolveTranslation = ({ locale, namespace, key, options, keySeparator = ".
|
|
|
132
132
|
if (resolvedValue === null || resolvedValue === void 0) return void 0;
|
|
133
133
|
if (options?.returnObjects && typeof resolvedValue === "object" && resolvedValue !== null) return resolvedValue;
|
|
134
134
|
const values = getInterpolationValues(options);
|
|
135
|
-
let resolved =
|
|
135
|
+
let resolved = resolveMessageNodeToString(resolvedValue, values, options?.lng ?? locale);
|
|
136
136
|
if (depth < MAX_NESTING_DEPTH && resolved.includes("$t(")) resolved = resolved.replace(/\$t\(\s*([^),]+?)\s*(?:,[^)]*)?\)/g, (match, nestedKey) => {
|
|
137
137
|
const nestedValue = resolveTranslation({
|
|
138
138
|
locale,
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"resolveTranslation.mjs","names":[],"sources":["../../src/resolveTranslation.ts"],"sourcesContent":["import { getIntlayer } from '@intlayer/core/interpreter';\nimport {\n type MessageValues,\n navigatePath,\n resolveMessage,\n} from '@intlayer/core/messageFormat';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\nimport type {\n DictionaryKeys,\n LocalesValues,\n} from '@intlayer/types/module_augmentation';\nimport type { TOptions } from 'i18next';\n\n/**\n * Shared i18next-dialect translation resolution.\n *\n * Implements the i18next lookup pipeline on top of intlayer dictionaries:\n * namespace prefix (`ns:key`), `ns` option override, plural suffixes\n * (`key_one`, `key_other`, …) via `Intl.PluralRules`, context suffixes\n * (`key_male`), `$t()` nesting, `defaultValue` and `{{var}}` interpolation.\n *\n * Used by `@intlayer/i18next` (instance `t`) and `@intlayer/react-i18next`\n * (`useTranslation`, `<Trans>`).\n */\n\n/** Option keys that are control flags, never interpolation values. */\nconst CONTROL_OPTION_KEYS = new Set([\n 'defaultValue',\n 'ns',\n 'lng',\n 'lngs',\n 'fallbackLng',\n 'returnObjects',\n 'returnDetails',\n 'keySeparator',\n 'nsSeparator',\n 'ordinal',\n 'postProcess',\n 'postProcessPassResolved',\n 'interpolation',\n 'replace',\n 'joinArrays',\n 'nsMode',\n 'keyPrefix',\n]);\n\n/** Maximum `$t()` nesting recursion depth. */\nconst MAX_NESTING_DEPTH = 5;\n\n/**\n * Canonical key of the single dictionary produced when a JSON source pattern\n * has no `{{key}}` segment (one file holds the whole namespace, e.g.\n * `./src/i18n/{{locale}}.json`). Used as the fallback namespace so i18next's\n * default `translation` namespace resolves against the whole-file dictionary.\n */\nconst ROOT_DICTIONARY_KEY = 'index';\n\n/**\n * Reads a dictionary from the runtime registry, returning `undefined` when the\n * namespace is not a registered dictionary.\n *\n * `getIntlayer` never throws for a missing key — in development it returns a\n * path-stringifying fallback proxy — so a plain `getIntlayer` call cannot tell\n * \"missing namespace\" apart from \"resolved content\". The registry membership\n * check makes the distinction explicit before resolving.\n */\nconst getDictionaryOrUndefined = (\n namespace: DictionaryKeys,\n locale: LocalesValues\n): unknown => {\n if (!(namespace in getDictionaries())) return undefined;\n\n return getIntlayer(namespace, locale);\n};\n\n/**\n * Builds the ordered list of key candidates following i18next's resolution\n * order: context + plural → context → plural → exact key.\n */\nconst buildKeyCandidates = (\n path: string,\n locale: string,\n count: number | undefined,\n context: string | undefined,\n ordinal: boolean\n): string[] => {\n const candidates: string[] = [];\n\n const pluralCategory =\n count === undefined\n ? undefined\n : new Intl.PluralRules(locale, {\n type: ordinal ? 'ordinal' : 'cardinal',\n }).select(count);\n\n if (context) {\n if (pluralCategory) {\n if (ordinal) {\n candidates.push(`${path}_${context}_ordinal_${pluralCategory}`);\n }\n candidates.push(`${path}_${context}_${pluralCategory}`);\n if (count !== 1) candidates.push(`${path}_${context}_plural`);\n }\n candidates.push(`${path}_${context}`);\n }\n\n if (pluralCategory) {\n if (ordinal) candidates.push(`${path}_ordinal_${pluralCategory}`);\n candidates.push(`${path}_${pluralCategory}`);\n // Legacy i18next v3 JSON suffix\n if (count !== 1) candidates.push(`${path}_plural`);\n }\n\n candidates.push(path);\n\n return candidates;\n};\n\n/** Extracts interpolation values from i18next `t()` options. */\nexport const getInterpolationValues = (options?: TOptions): MessageValues => {\n if (!options || typeof options !== 'object') return {};\n\n const replace = (options as { replace?: MessageValues }).replace;\n if (replace) {\n // `count` and `context` are always interpolatable, even with `replace`\n const values: MessageValues = { ...replace };\n if (options.count !== undefined) values.count ??= options.count;\n if (options.context !== undefined) values.context ??= options.context;\n return values;\n }\n\n const values: MessageValues = {};\n for (const [optionKey, optionValue] of Object.entries(options)) {\n if (!CONTROL_OPTION_KEYS.has(optionKey)) values[optionKey] = optionValue;\n }\n return values;\n};\n\nexport type ResolveTranslationParams = {\n /** Locale to resolve against. */\n locale: LocalesValues;\n /** Default namespace (dictionary key) when the key has no `ns:` prefix. */\n namespace: string;\n /** The translation key, possibly `ns:path.to.key`. */\n key: string;\n /** i18next `t()` options (interpolation values, count, context, …). */\n options?: TOptions;\n /** Custom key separator (`init({ keySeparator })`). */\n keySeparator?: string | false;\n /** Custom namespace separator (`init({ nsSeparator })`). */\n nsSeparator?: string | false;\n /** Internal `$t()` nesting recursion depth. */\n depth?: number;\n /**\n * Pre-resolved content of the `namespace` dictionary for `locale`.\n *\n * Supplied by the build-optimized `useDictionary` / `getDictionary`\n * variants, where the dictionary is imported at build time instead of read\n * from the runtime registry. Only used when the call resolves to the\n * default `namespace` without a locale override — cross-namespace\n * (`other:key`, `{ ns }`) and `{ lng }` lookups still go through\n * `getIntlayer`.\n */\n dictionaryContent?: unknown;\n};\n\n/**\n * Resolves a single translation key the i18next way against intlayer\n * dictionaries.\n *\n * Returns the resolved value: a string in the common case, or an\n * object/array when `returnObjects: true`. Returns `undefined` when the key\n * cannot be resolved (caller decides between `defaultValue`, fallback keys\n * and key echo).\n */\nexport const resolveTranslation = ({\n locale,\n namespace,\n key,\n options,\n keySeparator = '.',\n nsSeparator = ':',\n depth = 0,\n dictionaryContent,\n}: ResolveTranslationParams): unknown => {\n // Namespace resolution: `ns:` prefix > `ns` option > default namespace\n let targetNamespace = namespace;\n let path = key;\n\n if (nsSeparator !== false && key.includes(nsSeparator)) {\n const separatorIndex = key.indexOf(nsSeparator);\n targetNamespace = key.slice(0, separatorIndex);\n path = key.slice(separatorIndex + nsSeparator.length);\n } else if (options?.ns) {\n targetNamespace = Array.isArray(options.ns)\n ? (options.ns[0] as string)\n : (options.ns as string);\n }\n\n const count = typeof options?.count === 'number' ? options.count : undefined;\n const context =\n options?.context !== undefined ? String(options.context) : undefined;\n const ordinal = options?.ordinal === true;\n\n const resolvedLocale = ((options?.lng as string) ?? locale) as LocalesValues;\n\n let dictionary: unknown;\n if (\n dictionaryContent !== undefined &&\n targetNamespace === namespace &&\n options?.lng === undefined\n ) {\n dictionary = dictionaryContent;\n } else {\n dictionary = getDictionaryOrUndefined(\n targetNamespace as DictionaryKeys,\n resolvedLocale\n );\n\n // i18next's default namespace is `translation`, but a single-file JSON\n // source (no `{{key}}` segment) is loaded as the root `index` dictionary.\n // When the *default* namespace is not itself a registered dictionary, fall\n // back to `index` so `t('login.heroSubtitle')` resolves against the\n // whole-file dictionary. Explicit `ns:` prefixes / `ns` options never fall\n // back, so a genuinely missing namespace still returns `undefined`.\n if (\n dictionary === undefined &&\n targetNamespace === namespace &&\n targetNamespace !== ROOT_DICTIONARY_KEY\n ) {\n dictionary = getDictionaryOrUndefined(\n ROOT_DICTIONARY_KEY as DictionaryKeys,\n resolvedLocale\n );\n }\n\n if (dictionary === undefined) return undefined;\n }\n\n let resolvedValue: unknown;\n for (const candidate of buildKeyCandidates(\n path,\n (options?.lng as string) ?? (locale as string),\n count,\n context,\n ordinal\n )) {\n const value = navigatePath(dictionary, candidate, keySeparator);\n if (value !== null && value !== undefined) {\n resolvedValue = value;\n break;\n }\n }\n\n if (resolvedValue === null || resolvedValue === undefined) return undefined;\n\n // `returnObjects: true` — return the raw subtree\n if (\n options?.returnObjects &&\n typeof resolvedValue === 'object' &&\n resolvedValue !== null\n ) {\n return resolvedValue;\n }\n\n const values = getInterpolationValues(options);\n\n let resolved = resolveMessage(\n resolvedValue,\n values,\n ((options?.lng as string) ?? locale) as LocalesValues,\n 'i18next'\n );\n\n // `$t(key)` nesting\n if (depth < MAX_NESTING_DEPTH && resolved.includes('$t(')) {\n resolved = resolved.replace(\n /\\$t\\(\\s*([^),]+?)\\s*(?:,[^)]*)?\\)/g,\n (match, nestedKey: string) => {\n const nestedValue = resolveTranslation({\n locale,\n namespace: targetNamespace,\n key: nestedKey.trim(),\n options,\n keySeparator,\n nsSeparator,\n depth: depth + 1,\n dictionaryContent:\n targetNamespace === namespace ? dictionaryContent : undefined,\n });\n return typeof nestedValue === 'string' ? nestedValue : match;\n }\n );\n }\n\n return resolved;\n};\n"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"resolveTranslation.mjs","names":[],"sources":["../../src/resolveTranslation.ts"],"sourcesContent":["import { getIntlayer } from '@intlayer/core/interpreter';\nimport {\n type MessageValues,\n navigatePath,\n resolveMessageNodeToString,\n} from '@intlayer/core/messageFormat';\nimport { getDictionaries } from '@intlayer/dictionaries-entry';\nimport type {\n DictionaryKeys,\n LocalesValues,\n} from '@intlayer/types/module_augmentation';\nimport type { TOptions } from 'i18next';\n\n/**\n * Shared i18next-dialect translation resolution.\n *\n * Implements the i18next lookup pipeline on top of intlayer dictionaries:\n * namespace prefix (`ns:key`), `ns` option override, plural suffixes\n * (`key_one`, `key_other`, …) via `Intl.PluralRules`, context suffixes\n * (`key_male`), `$t()` nesting, `defaultValue` and `{{var}}` interpolation.\n *\n * Used by `@intlayer/i18next` (instance `t`) and `@intlayer/react-i18next`\n * (`useTranslation`, `<Trans>`).\n */\n\n/** Option keys that are control flags, never interpolation values. */\nconst CONTROL_OPTION_KEYS = new Set([\n 'defaultValue',\n 'ns',\n 'lng',\n 'lngs',\n 'fallbackLng',\n 'returnObjects',\n 'returnDetails',\n 'keySeparator',\n 'nsSeparator',\n 'ordinal',\n 'postProcess',\n 'postProcessPassResolved',\n 'interpolation',\n 'replace',\n 'joinArrays',\n 'nsMode',\n 'keyPrefix',\n]);\n\n/** Maximum `$t()` nesting recursion depth. */\nconst MAX_NESTING_DEPTH = 5;\n\n/**\n * Canonical key of the single dictionary produced when a JSON source pattern\n * has no `{{key}}` segment (one file holds the whole namespace, e.g.\n * `./src/i18n/{{locale}}.json`). Used as the fallback namespace so i18next's\n * default `translation` namespace resolves against the whole-file dictionary.\n */\nconst ROOT_DICTIONARY_KEY = 'index';\n\n/**\n * Reads a dictionary from the runtime registry, returning `undefined` when the\n * namespace is not a registered dictionary.\n *\n * `getIntlayer` never throws for a missing key — in development it returns a\n * path-stringifying fallback proxy — so a plain `getIntlayer` call cannot tell\n * \"missing namespace\" apart from \"resolved content\". The registry membership\n * check makes the distinction explicit before resolving.\n */\nconst getDictionaryOrUndefined = (\n namespace: DictionaryKeys,\n locale: LocalesValues\n): unknown => {\n if (!(namespace in getDictionaries())) return undefined;\n\n return getIntlayer(namespace, locale);\n};\n\n/**\n * Builds the ordered list of key candidates following i18next's resolution\n * order: context + plural → context → plural → exact key.\n */\nconst buildKeyCandidates = (\n path: string,\n locale: string,\n count: number | undefined,\n context: string | undefined,\n ordinal: boolean\n): string[] => {\n const candidates: string[] = [];\n\n const pluralCategory =\n count === undefined\n ? undefined\n : new Intl.PluralRules(locale, {\n type: ordinal ? 'ordinal' : 'cardinal',\n }).select(count);\n\n if (context) {\n if (pluralCategory) {\n if (ordinal) {\n candidates.push(`${path}_${context}_ordinal_${pluralCategory}`);\n }\n candidates.push(`${path}_${context}_${pluralCategory}`);\n if (count !== 1) candidates.push(`${path}_${context}_plural`);\n }\n candidates.push(`${path}_${context}`);\n }\n\n if (pluralCategory) {\n if (ordinal) candidates.push(`${path}_ordinal_${pluralCategory}`);\n candidates.push(`${path}_${pluralCategory}`);\n // Legacy i18next v3 JSON suffix\n if (count !== 1) candidates.push(`${path}_plural`);\n }\n\n candidates.push(path);\n\n return candidates;\n};\n\n/** Extracts interpolation values from i18next `t()` options. */\nexport const getInterpolationValues = (options?: TOptions): MessageValues => {\n if (!options || typeof options !== 'object') return {};\n\n const replace = (options as { replace?: MessageValues }).replace;\n if (replace) {\n // `count` and `context` are always interpolatable, even with `replace`\n const values: MessageValues = { ...replace };\n if (options.count !== undefined) values.count ??= options.count;\n if (options.context !== undefined) values.context ??= options.context;\n return values;\n }\n\n const values: MessageValues = {};\n for (const [optionKey, optionValue] of Object.entries(options)) {\n if (!CONTROL_OPTION_KEYS.has(optionKey)) values[optionKey] = optionValue;\n }\n return values;\n};\n\nexport type ResolveTranslationParams = {\n /** Locale to resolve against. */\n locale: LocalesValues;\n /** Default namespace (dictionary key) when the key has no `ns:` prefix. */\n namespace: string;\n /** The translation key, possibly `ns:path.to.key`. */\n key: string;\n /** i18next `t()` options (interpolation values, count, context, …). */\n options?: TOptions;\n /** Custom key separator (`init({ keySeparator })`). */\n keySeparator?: string | false;\n /** Custom namespace separator (`init({ nsSeparator })`). */\n nsSeparator?: string | false;\n /** Internal `$t()` nesting recursion depth. */\n depth?: number;\n /**\n * Pre-resolved content of the `namespace` dictionary for `locale`.\n *\n * Supplied by the build-optimized `useDictionary` / `getDictionary`\n * variants, where the dictionary is imported at build time instead of read\n * from the runtime registry. Only used when the call resolves to the\n * default `namespace` without a locale override — cross-namespace\n * (`other:key`, `{ ns }`) and `{ lng }` lookups still go through\n * `getIntlayer`.\n */\n dictionaryContent?: unknown;\n};\n\n/**\n * Resolves a single translation key the i18next way against intlayer\n * dictionaries.\n *\n * Returns the resolved value: a string in the common case, or an\n * object/array when `returnObjects: true`. Returns `undefined` when the key\n * cannot be resolved (caller decides between `defaultValue`, fallback keys\n * and key echo).\n */\nexport const resolveTranslation = ({\n locale,\n namespace,\n key,\n options,\n keySeparator = '.',\n nsSeparator = ':',\n depth = 0,\n dictionaryContent,\n}: ResolveTranslationParams): unknown => {\n // Namespace resolution: `ns:` prefix > `ns` option > default namespace\n let targetNamespace = namespace;\n let path = key;\n\n if (nsSeparator !== false && key.includes(nsSeparator)) {\n const separatorIndex = key.indexOf(nsSeparator);\n targetNamespace = key.slice(0, separatorIndex);\n path = key.slice(separatorIndex + nsSeparator.length);\n } else if (options?.ns) {\n targetNamespace = Array.isArray(options.ns)\n ? (options.ns[0] as string)\n : (options.ns as string);\n }\n\n const count = typeof options?.count === 'number' ? options.count : undefined;\n const context =\n options?.context !== undefined ? String(options.context) : undefined;\n const ordinal = options?.ordinal === true;\n\n const resolvedLocale = ((options?.lng as string) ?? locale) as LocalesValues;\n\n let dictionary: unknown;\n if (\n dictionaryContent !== undefined &&\n targetNamespace === namespace &&\n options?.lng === undefined\n ) {\n dictionary = dictionaryContent;\n } else {\n dictionary = getDictionaryOrUndefined(\n targetNamespace as DictionaryKeys,\n resolvedLocale\n );\n\n // i18next's default namespace is `translation`, but a single-file JSON\n // source (no `{{key}}` segment) is loaded as the root `index` dictionary.\n // When the *default* namespace is not itself a registered dictionary, fall\n // back to `index` so `t('login.heroSubtitle')` resolves against the\n // whole-file dictionary. Explicit `ns:` prefixes / `ns` options never fall\n // back, so a genuinely missing namespace still returns `undefined`.\n if (\n dictionary === undefined &&\n targetNamespace === namespace &&\n targetNamespace !== ROOT_DICTIONARY_KEY\n ) {\n dictionary = getDictionaryOrUndefined(\n ROOT_DICTIONARY_KEY as DictionaryKeys,\n resolvedLocale\n );\n }\n\n if (dictionary === undefined) return undefined;\n }\n\n let resolvedValue: unknown;\n for (const candidate of buildKeyCandidates(\n path,\n (options?.lng as string) ?? (locale as string),\n count,\n context,\n ordinal\n )) {\n const value = navigatePath(dictionary, candidate, keySeparator);\n if (value !== null && value !== undefined) {\n resolvedValue = value;\n break;\n }\n }\n\n if (resolvedValue === null || resolvedValue === undefined) return undefined;\n\n // `returnObjects: true` — return the raw subtree\n if (\n options?.returnObjects &&\n typeof resolvedValue === 'object' &&\n resolvedValue !== null\n ) {\n return resolvedValue;\n }\n\n const values = getInterpolationValues(options);\n\n // Dictionary content was converted to intlayer nodes at build time, so no\n // i18next parser is needed here — which keeps it out of the app bundle.\n let resolved = resolveMessageNodeToString(\n resolvedValue,\n values,\n ((options?.lng as string) ?? locale) as LocalesValues\n );\n\n // `$t(key)` nesting\n if (depth < MAX_NESTING_DEPTH && resolved.includes('$t(')) {\n resolved = resolved.replace(\n /\\$t\\(\\s*([^),]+?)\\s*(?:,[^)]*)?\\)/g,\n (match, nestedKey: string) => {\n const nestedValue = resolveTranslation({\n locale,\n namespace: targetNamespace,\n key: nestedKey.trim(),\n options,\n keySeparator,\n nsSeparator,\n depth: depth + 1,\n dictionaryContent:\n targetNamespace === namespace ? dictionaryContent : undefined,\n });\n return typeof nestedValue === 'string' ? nestedValue : match;\n }\n );\n }\n\n return resolved;\n};\n"],"mappings":"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"}
|
|
@@ -1,7 +1,5 @@
|
|
|
1
|
-
import { TypedGetFixedT } from "./typedTranslation.js";
|
|
2
1
|
import { createInstance as createInstance$1 } from "i18next";
|
|
3
2
|
//#region src/createInstance.d.ts
|
|
4
3
|
export declare const createInstance: typeof createInstance$1;
|
|
5
4
|
//#endregion
|
|
6
|
-
export type { TypedGetFixedT };
|
|
7
5
|
//# sourceMappingURL=createInstance.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"createInstance.d.ts","names":[],"sources":["../../src/createInstance.ts"],"mappings":"
|
|
1
|
+
{"version":3,"file":"createInstance.d.ts","names":[],"sources":["../../src/createInstance.ts"],"mappings":";;qBAkCa,uBAAuB"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ScopedTFunction, TypedTFunction } from "./typedTranslation.js";
|
|
2
|
-
import { DictionaryKeys, LocalesValues } from "@intlayer/types/module_augmentation";
|
|
3
2
|
import { Dictionary } from "@intlayer/types/dictionary";
|
|
3
|
+
import { DictionaryKeys, LocalesValues } from "@intlayer/types/module_augmentation";
|
|
4
4
|
//#region src/getDictionary.d.ts
|
|
5
5
|
/**
|
|
6
6
|
* Overload set for {@link getDictionary}: without a key prefix the returned
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { ScopedTFunction, TypedTFunction } from "./typedTranslation.js";
|
|
2
|
-
import { DictionaryKeys, LocalesValues, StrictModeLocaleMap } from "@intlayer/types/module_augmentation";
|
|
3
2
|
import { Dictionary } from "@intlayer/types/dictionary";
|
|
3
|
+
import { DictionaryKeys, LocalesValues, StrictModeLocaleMap } from "@intlayer/types/module_augmentation";
|
|
4
4
|
//#region src/getDictionaryDynamic.d.ts
|
|
5
5
|
/**
|
|
6
6
|
* Overload set for {@link getDictionaryDynamic}: without a key prefix the
|
package/dist/types/index.d.ts
CHANGED
|
@@ -1,5 +1,5 @@
|
|
|
1
|
-
import { ContentAtPath, ScopedDotPaths, ScopedTFunction, TranslatedValue, TypedGetFixedT, TypedTFunction } from "./typedTranslation.js";
|
|
2
1
|
import { createInstance } from "./createInstance.js";
|
|
2
|
+
import { ContentAtPath, ScopedDotPaths, ScopedTFunction, TranslatedValue, TypedGetFixedT, TypedTFunction } from "./typedTranslation.js";
|
|
3
3
|
import { getDictionary } from "./getDictionary.js";
|
|
4
4
|
import { getDictionaryDynamic } from "./getDictionaryDynamic.js";
|
|
5
5
|
import { ResolveTranslationParams, getInterpolationValues, resolveTranslation } from "./resolveTranslation.js";
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/index.ts"],"mappings":";;;;;;;
|
|
1
|
+
{"version":3,"file":"index.d.ts","names":[],"sources":["../../src/index.ts"],"mappings":";;;;;;;cAkCM,SAAS;qBAMF,YAAY;qBACZ,aAAa;qBACb,sBAAsB;qBAEtB,wBAAwB;qBAExB,YAAY;qBACZ,uBAAuB;;;;;;;;;;;;;qBAevB,WAAW;qBAIX,UAAU;qBACV,eAAe;qBACf,4BAA4B;qBAE5B,2BAA2B;qBAE3B,uBAAuB;qBAEvB,sBAAsB;;;;;;qBAQtB,kBAAe"}
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { TOptions } from "i18next";
|
|
2
|
+
import { DictionaryKeys } from "@intlayer/types/module_augmentation";
|
|
2
3
|
import { GetNestingResult } from "@intlayer/core/interpreter";
|
|
3
4
|
import { ValidDotPathsFor } from "@intlayer/core/transpiler";
|
|
4
|
-
import { DictionaryKeys } from "@intlayer/types/module_augmentation";
|
|
5
5
|
//#region src/typedTranslation.d.ts
|
|
6
6
|
/**
|
|
7
7
|
* The interpreter-resolved content type at dot-path `P` of dictionary `N` —
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@intlayer/i18next",
|
|
3
|
-
"version": "9.5.
|
|
3
|
+
"version": "9.5.3",
|
|
4
4
|
"private": false,
|
|
5
5
|
"description": "i18next API adapter for intlayer — drop-in compatibility layer that exposes the i18next interface while using @intlayer/core under the hood",
|
|
6
6
|
"keywords": [
|
|
@@ -74,15 +74,15 @@
|
|
|
74
74
|
"typecheck": "tsc --noEmit --project tsconfig.types.json"
|
|
75
75
|
},
|
|
76
76
|
"dependencies": {
|
|
77
|
-
"@intlayer/config": "9.5.
|
|
78
|
-
"@intlayer/core": "9.5.
|
|
79
|
-
"@intlayer/dictionaries-entry": "9.5.
|
|
80
|
-
"@intlayer/engine": "9.5.
|
|
81
|
-
"@intlayer/types": "9.5.
|
|
82
|
-
"vite-intlayer": "9.5.
|
|
77
|
+
"@intlayer/config": "9.5.3",
|
|
78
|
+
"@intlayer/core": "9.5.3",
|
|
79
|
+
"@intlayer/dictionaries-entry": "9.5.3",
|
|
80
|
+
"@intlayer/engine": "9.5.3",
|
|
81
|
+
"@intlayer/types": "9.5.3",
|
|
82
|
+
"vite-intlayer": "9.5.3"
|
|
83
83
|
},
|
|
84
84
|
"devDependencies": {
|
|
85
|
-
"@types/node": "
|
|
85
|
+
"@types/node": "^22",
|
|
86
86
|
"@utils/ts-config": "1.0.4",
|
|
87
87
|
"@utils/ts-config-types": "1.0.4",
|
|
88
88
|
"@utils/tsdown-config": "1.0.4",
|
|
@@ -90,7 +90,7 @@
|
|
|
90
90
|
"rimraf": "6.1.3",
|
|
91
91
|
"tsdown": "0.23.0",
|
|
92
92
|
"typescript": "7.0.2",
|
|
93
|
-
"vite": "8.
|
|
93
|
+
"vite": "8.3.0",
|
|
94
94
|
"vitest": "5.0.0"
|
|
95
95
|
},
|
|
96
96
|
"peerDependencies": {
|