@intlayer/config 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 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
- [![Star History Chart](https://api.star-history.com/svg?repos=aymericzip/intlayer&type=Date)](https://api.star-history.com/#aymericzip/intlayer&Date)
331
+ [![Star History Chart](https://api.star-history.com/svg?repos=aymericzip/intlayer&type=Date)](https://star-history.com/#aymericzip/intlayer&Date)
@@ -2,8 +2,8 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
2
2
  const require_runtime = require('../_virtual/_rolldown/runtime.cjs');
3
3
  const require_utils_alias = require('../utils/alias.cjs');
4
4
  const require_configFile_getConfiguration = require('../configFile/getConfiguration.cjs');
5
- const require_bundle_logBundle = require('./logBundle.cjs');
6
5
  const require_envVars_envVars = require('../envVars/envVars.cjs');
6
+ const require_bundle_logBundle = require('./logBundle.cjs');
7
7
  let node_path = require("node:path");
8
8
  let node_fs_promises = require("node:fs/promises");
9
9
  let _intlayer_types_package_json = require("@intlayer/types/package.json");
@@ -9,9 +9,16 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
9
9
  *
10
10
  * The adapter therefore addresses lingui catalogs by the id's first dot-segment,
11
11
  * which lets a catalog split with `syncJSON({ splitKeys: 'key-prefix' })` resolve
12
- * one small dictionary per call site instead of the whole catalog. None of these
13
- * callers carries a namespace argument, so the optimize passes leave them to the
14
- * runtime resolver and only the usage analysis reads the ids.
12
+ * one small dictionary per call site instead of the whole catalog.
13
+ *
14
+ * None of these callers carries a namespace argument. `useLingui()` is bound
15
+ * through the root-scope path instead: the babel optimize pass collects the
16
+ * first segment of every static id passed to `_` / `t` / `<Trans>` in the
17
+ * file and hands the matching dictionaries to `useDictionary(...)`. `<Trans>`
18
+ * carries its own id, so each element is bound on its own with a `dictionary`
19
+ * prop. A catalog that has *not* been split still resolves —
20
+ * `rootDictionaryKey` points the fallback at lingui's single `messages`
21
+ * dictionary with the id kept intact.
15
22
  *
16
23
  * `t` and `_` are generic names, so all lingui callers require an import from
17
24
  * a lingui module to participate in matching — this avoids false positives on
@@ -27,6 +34,8 @@ const LINGUI_IMPORT_SOURCES = [
27
34
  "@lingui/react/macro",
28
35
  "@intlayer/lingui"
29
36
  ];
37
+ /** Key of lingui's single catalog, used when the id segment names no dictionary. */
38
+ const LINGUI_ROOT_DICTIONARY_KEY = "messages";
30
39
  const LINGUI_CALLERS = [
31
40
  {
32
41
  callerName: "useLingui",
@@ -34,7 +43,10 @@ const LINGUI_CALLERS = [
34
43
  importSources: LINGUI_IMPORT_SOURCES,
35
44
  namespaceSources: [],
36
45
  allowRootScope: true,
37
- translationFunction: "destructured-t"
46
+ rootDictionaryKey: LINGUI_ROOT_DICTIONARY_KEY,
47
+ translationFunction: "destructured-t",
48
+ staticReplacement: "useDictionary",
49
+ dynamicReplacement: "useDictionaryDynamic"
38
50
  },
39
51
  {
40
52
  callerName: "_",
@@ -62,7 +74,10 @@ const LINGUI_CALLERS = [
62
74
  requiresImport: true,
63
75
  jsxIdAttribute: "id",
64
76
  namespaceSources: [{ from: "path-first-segment" }],
65
- translationFunction: "self"
77
+ rootDictionaryKey: LINGUI_ROOT_DICTIONARY_KEY,
78
+ translationFunction: "self",
79
+ staticReplacement: "TransDictionary",
80
+ dynamicReplacement: "TransDictionaryDynamic"
66
81
  }
67
82
  ];
68
83
 
@@ -1 +1 @@
1
- {"version":3,"file":"lingui.cjs","names":[],"sources":["../../../../src/callers/compat/lingui.ts"],"sourcesContent":["import type { CallerDescriptor } from '../types';\n\n/**\n * Lingui — `@intlayer/lingui` compat adapter.\n *\n * Lingui is a single-catalog library: the namespace lives *inside* the message\n * id rather than in the file layout, so `i18n._('footer.github')` names both\n * the group (`footer`) and the field (`github`).\n *\n * The adapter therefore addresses lingui catalogs by the id's first dot-segment,\n * which lets a catalog split with `syncJSON({ splitKeys: 'key-prefix' })` resolve\n * one small dictionary per call site instead of the whole catalog. None of these\n * callers carries a namespace argument, so the optimize passes leave them to the\n * runtime resolver and only the usage analysis reads the ids.\n *\n * `t` and `_` are generic names, so all lingui callers require an import from\n * a lingui module to participate in matching — this avoids false positives on\n * unrelated `t()` helpers.\n *\n * Mirrors `compat/lingui/src/plugin/index.ts`.\n */\nconst LINGUI_IMPORT_SOURCES = [\n '@lingui/core',\n '@lingui/react',\n '@lingui/macro',\n '@lingui/core/macro',\n '@lingui/react/macro',\n '@intlayer/lingui',\n];\n\nexport const LINGUI_CALLERS: CallerDescriptor[] = [\n {\n callerName: 'useLingui',\n library: 'lingui',\n importSources: LINGUI_IMPORT_SOURCES,\n // `const { i18n, t, _ } = useLingui()` takes no namespace argument, so the\n // dictionary is only knowable from the ids passed to the returned\n // functions which the usage analysis reads and the optimize passes do not.\n namespaceSources: [],\n allowRootScope: true,\n translationFunction: 'destructured-t',\n },\n {\n callerName: '_',\n library: 'lingui',\n importSources: LINGUI_IMPORT_SOURCES,\n requiresImport: true,\n // `i18n._('id')` and the destructured `const { _ } = useLingui()` form.\n matchAsMethod: true,\n namespaceSources: [{ from: 'path-first-segment' }],\n translationFunction: 'self',\n },\n {\n callerName: 't',\n library: 'lingui',\n importSources: LINGUI_IMPORT_SOURCES,\n requiresImport: true,\n // `i18n.t('id')`, `t({ id: 'id' })` and the macro tagged template ``t`…` ``.\n matchAsMethod: true,\n matchAsTaggedTemplate: true,\n namespaceSources: [{ from: 'path-first-segment' }],\n translationFunction: 'self',\n },\n {\n callerName: 'Trans',\n library: 'lingui',\n importSources: LINGUI_IMPORT_SOURCES,\n requiresImport: true,\n // <Trans id=\"home.title\" message=\"Welcome\" />\n jsxIdAttribute: 'id',\n namespaceSources: [{ from: 'path-first-segment' }],\n translationFunction: 'self',\n },\n];\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;AAqBA,MAAM,wBAAwB;CAC5B;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,MAAa,iBAAqC;CAChD;EACE,YAAY;EACZ,SAAS;EACT,eAAe;EAIf,kBAAkB,CAAC;EACnB,gBAAgB;EAChB,qBAAqB;CACvB;CACA;EACE,YAAY;EACZ,SAAS;EACT,eAAe;EACf,gBAAgB;EAEhB,eAAe;EACf,kBAAkB,CAAC,EAAE,MAAM,qBAAqB,CAAC;EACjD,qBAAqB;CACvB;CACA;EACE,YAAY;EACZ,SAAS;EACT,eAAe;EACf,gBAAgB;EAEhB,eAAe;EACf,uBAAuB;EACvB,kBAAkB,CAAC,EAAE,MAAM,qBAAqB,CAAC;EACjD,qBAAqB;CACvB;CACA;EACE,YAAY;EACZ,SAAS;EACT,eAAe;EACf,gBAAgB;EAEhB,gBAAgB;EAChB,kBAAkB,CAAC,EAAE,MAAM,qBAAqB,CAAC;EACjD,qBAAqB;CACvB;AACF"}
1
+ {"version":3,"file":"lingui.cjs","names":[],"sources":["../../../../src/callers/compat/lingui.ts"],"sourcesContent":["import type { CallerDescriptor } from '../types';\n\n/**\n * Lingui — `@intlayer/lingui` compat adapter.\n *\n * Lingui is a single-catalog library: the namespace lives *inside* the message\n * id rather than in the file layout, so `i18n._('footer.github')` names both\n * the group (`footer`) and the field (`github`).\n *\n * The adapter therefore addresses lingui catalogs by the id's first dot-segment,\n * which lets a catalog split with `syncJSON({ splitKeys: 'key-prefix' })` resolve\n * one small dictionary per call site instead of the whole catalog.\n *\n * None of these callers carries a namespace argument. `useLingui()` is bound\n * through the root-scope path instead: the babel optimize pass collects the\n * first segment of every static id passed to `_` / `t` / `<Trans>` in the\n * file and hands the matching dictionaries to `useDictionary(...)`. `<Trans>`\n * carries its own id, so each element is bound on its own with a `dictionary`\n * prop. A catalog that has *not* been split still resolves —\n * `rootDictionaryKey` points the fallback at lingui's single `messages`\n * dictionary with the id kept intact.\n *\n * `t` and `_` are generic names, so all lingui callers require an import from\n * a lingui module to participate in matching — this avoids false positives on\n * unrelated `t()` helpers.\n *\n * Mirrors `compat/lingui/src/plugin/index.ts`.\n */\nconst LINGUI_IMPORT_SOURCES = [\n '@lingui/core',\n '@lingui/react',\n '@lingui/macro',\n '@lingui/core/macro',\n '@lingui/react/macro',\n '@intlayer/lingui',\n];\n\n/** Key of lingui's single catalog, used when the id segment names no dictionary. */\nconst LINGUI_ROOT_DICTIONARY_KEY = 'messages';\n\nexport const LINGUI_CALLERS: CallerDescriptor[] = [\n {\n callerName: 'useLingui',\n library: 'lingui',\n importSources: LINGUI_IMPORT_SOURCES,\n // `const { i18n, t, _ } = useLingui()` takes no namespace argument: the\n // dictionaries are named by the message ids passed to the returned\n // functions, so the call site binds through the root-scope path.\n namespaceSources: [],\n allowRootScope: true,\n rootDictionaryKey: LINGUI_ROOT_DICTIONARY_KEY,\n translationFunction: 'destructured-t',\n staticReplacement: 'useDictionary',\n dynamicReplacement: 'useDictionaryDynamic',\n },\n {\n callerName: '_',\n library: 'lingui',\n importSources: LINGUI_IMPORT_SOURCES,\n requiresImport: true,\n // `i18n._('id')` and the destructured `const { _ } = useLingui()` form.\n matchAsMethod: true,\n namespaceSources: [{ from: 'path-first-segment' }],\n translationFunction: 'self',\n },\n {\n callerName: 't',\n library: 'lingui',\n importSources: LINGUI_IMPORT_SOURCES,\n requiresImport: true,\n // `i18n.t('id')`, `t({ id: 'id' })` and the macro tagged template ``t`…` ``.\n matchAsMethod: true,\n matchAsTaggedTemplate: true,\n namespaceSources: [{ from: 'path-first-segment' }],\n translationFunction: 'self',\n },\n {\n callerName: 'Trans',\n library: 'lingui',\n importSources: LINGUI_IMPORT_SOURCES,\n requiresImport: true,\n // <Trans id=\"home.title\" message=\"Welcome\" />\n jsxIdAttribute: 'id',\n namespaceSources: [{ from: 'path-first-segment' }],\n rootDictionaryKey: LINGUI_ROOT_DICTIONARY_KEY,\n translationFunction: 'self',\n // The element names its own dictionary through `id`, so it is bound on\n // its own: the pass adds a `dictionary` prop and re-points the import.\n staticReplacement: 'TransDictionary',\n dynamicReplacement: 'TransDictionaryDynamic',\n },\n];\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,MAAM,wBAAwB;CAC5B;CACA;CACA;CACA;CACA;CACA;AACF;;AAGA,MAAM,6BAA6B;AAEnC,MAAa,iBAAqC;CAChD;EACE,YAAY;EACZ,SAAS;EACT,eAAe;EAIf,kBAAkB,CAAC;EACnB,gBAAgB;EAChB,mBAAmB;EACnB,qBAAqB;EACrB,mBAAmB;EACnB,oBAAoB;CACtB;CACA;EACE,YAAY;EACZ,SAAS;EACT,eAAe;EACf,gBAAgB;EAEhB,eAAe;EACf,kBAAkB,CAAC,EAAE,MAAM,qBAAqB,CAAC;EACjD,qBAAqB;CACvB;CACA;EACE,YAAY;EACZ,SAAS;EACT,eAAe;EACf,gBAAgB;EAEhB,eAAe;EACf,uBAAuB;EACvB,kBAAkB,CAAC,EAAE,MAAM,qBAAqB,CAAC;EACjD,qBAAqB;CACvB;CACA;EACE,YAAY;EACZ,SAAS;EACT,eAAe;EACf,gBAAgB;EAEhB,gBAAgB;EAChB,kBAAkB,CAAC,EAAE,MAAM,qBAAqB,CAAC;EACjD,mBAAmB;EACnB,qBAAqB;EAGrB,mBAAmB;EACnB,oBAAoB;CACtB;AACF"}
@@ -4,11 +4,13 @@ Object.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });
4
4
  * Whether the optimize pass can rewrite this caller's call sites at build time.
5
5
  *
6
6
  * Requires both replacement names and a call shape reachable through an import
7
- * specifier rename. Method-matched callers (`i18n.getFixedT`, `intl.formatMessage`)
8
- * and JSX components (`<Trans>`, `<FormattedMessage>`) are excluded — their call
9
- * sites keep resolving through the runtime dictionary registry.
7
+ * specifier rename: a plain imported function, or a JSX component whose
8
+ * element receives the dictionary as a prop (lingui's `<Trans>`).
9
+ * Method-matched callers (`i18n.getFixedT`, `intl.formatMessage`) are
10
+ * excluded — their call sites keep resolving through the runtime dictionary
11
+ * registry.
10
12
  */
11
- const isRewritableCaller = (descriptor) => descriptor.staticReplacement !== void 0 && descriptor.dynamicReplacement !== void 0 && descriptor.matchAsMethod !== true && descriptor.jsxIdAttribute === void 0;
13
+ const isRewritableCaller = (descriptor) => descriptor.staticReplacement !== void 0 && descriptor.dynamicReplacement !== void 0 && descriptor.matchAsMethod !== true;
12
14
  /**
13
15
  * Returns the callers of a registry slice that the optimize pass can rewrite
14
16
  * at build time. See {@link isRewritableCaller}.
@@ -1 +1 @@
1
- {"version":3,"file":"transform.cjs","names":[],"sources":["../../../src/callers/transform.ts"],"sourcesContent":["import type { CallerDescriptor, CallerValueSource } from './types';\n\n/**\n * Wire format of an extra caller forwarded to the `@intlayer/swc` plugin.\n *\n * Field names mirror the serde attributes of `ExtraCallerConfig` in\n * `packages/@intlayer/swc/src/lib.rs` — both sides must stay in sync.\n */\nexport type SwcExtraCallerConfig = {\n /** The function name the user calls, e.g. `\"useTranslation\"`. */\n callerName: string;\n /** Module specifiers exporting the function (original + `@intlayer/*`). */\n importSources: string[];\n /**\n * Zero-based index of the positional argument holding the namespace string.\n * Omitted for fixed/option namespace callers.\n */\n namespaceArgIndex?: number;\n /**\n * Compile-time constant namespace — the dictionary ident is inserted as a\n * new first argument (lingui's `useLingui()`).\n */\n fixedNamespace?: string;\n /**\n * Namespace read from a property of an options-object argument — the\n * dictionary ident is inserted as a new first argument and the property is\n * rewritten to the key-prefix remainder (vue-i18n's `useI18n({ namespace })`).\n */\n namespaceOption?: { argumentIndex: number; property: string };\n /** Replacement function name for static import mode, e.g. `\"useDictionary\"`. */\n staticReplacement: string;\n /** Replacement function name for dynamic/fetch mode, e.g. `\"useDictionaryDynamic\"`. */\n dynamicReplacement: string;\n};\n\n/**\n * Whether the optimize pass can rewrite this caller's call sites at build time.\n *\n * Requires both replacement names and a call shape reachable through an import\n * specifier rename. Method-matched callers (`i18n.getFixedT`, `intl.formatMessage`)\n * and JSX components (`<Trans>`, `<FormattedMessage>`) are excluded — their call\n * sites keep resolving through the runtime dictionary registry.\n */\nexport const isRewritableCaller = (descriptor: CallerDescriptor): boolean =>\n descriptor.staticReplacement !== undefined &&\n descriptor.dynamicReplacement !== undefined &&\n descriptor.matchAsMethod !== true &&\n descriptor.jsxIdAttribute === undefined;\n\n/**\n * Returns the callers of a registry slice that the optimize pass can rewrite\n * at build time. See {@link isRewritableCaller}.\n */\nexport const getRewritableCallers = (\n descriptors: CallerDescriptor[]\n): CallerDescriptor[] => descriptors.filter(isRewritableCaller);\n\nconst findSource = <F extends CallerValueSource['from']>(\n sources: CallerValueSource[],\n from: F\n): Extract<CallerValueSource, { from: F }> | undefined =>\n sources.find(\n (source): source is Extract<CallerValueSource, { from: F }> =>\n source.from === from\n );\n\n/**\n * Serialises the rewritable callers of a registry slice into the\n * `@intlayer/swc` plugin wire format (`extraCallers` option).\n *\n * A caller with no statically readable namespace source is dropped: the plugin\n * binds a dictionary from an argument, an option property or a fixed value\n * only, so forwarding it would emit a descriptor no call site can match.\n *\n * @param descriptors - Registry slice, e.g. `REACT_I18NEXT_CALLERS`.\n * @returns Configs ready to pass as the plugin's `extraCallers` option.\n */\nexport const toSwcExtraCallers = (\n descriptors: CallerDescriptor[]\n): SwcExtraCallerConfig[] =>\n getRewritableCallers(descriptors).flatMap((descriptor) => {\n const argumentSource = findSource(descriptor.namespaceSources, 'argument');\n const optionSource = findSource(descriptor.namespaceSources, 'option');\n const fixedSource = findSource(descriptor.namespaceSources, 'fixed');\n\n if (!argumentSource && !optionSource && !fixedSource) return [];\n\n return [\n {\n callerName: descriptor.callerName,\n importSources: descriptor.importSources,\n ...(argumentSource ? { namespaceArgIndex: argumentSource.index } : {}),\n ...(fixedSource ? { fixedNamespace: fixedSource.value } : {}),\n ...(optionSource\n ? {\n namespaceOption: {\n argumentIndex: optionSource.argumentIndex,\n property: optionSource.property,\n },\n }\n : {}),\n staticReplacement: descriptor.staticReplacement!,\n dynamicReplacement: descriptor.dynamicReplacement!,\n },\n ];\n });\n"],"mappings":";;;;;;;;;;AA2CA,MAAa,sBAAsB,eACjC,WAAW,sBAAsB,UACjC,WAAW,uBAAuB,UAClC,WAAW,kBAAkB,QAC7B,WAAW,mBAAmB;;;;;AAMhC,MAAa,wBACX,gBACuB,YAAY,OAAO,kBAAkB;AAE9D,MAAM,cACJ,SACA,SAEA,QAAQ,MACL,WACC,OAAO,SAAS,IACpB;;;;;;;;;;;;AAaF,MAAa,qBACX,gBAEA,qBAAqB,WAAW,CAAC,CAAC,SAAS,eAAe;CACxD,MAAM,iBAAiB,WAAW,WAAW,kBAAkB,UAAU;CACzE,MAAM,eAAe,WAAW,WAAW,kBAAkB,QAAQ;CACrE,MAAM,cAAc,WAAW,WAAW,kBAAkB,OAAO;CAEnE,IAAI,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,aAAa,OAAO,CAAC;CAE9D,OAAO,CACL;EACE,YAAY,WAAW;EACvB,eAAe,WAAW;EAC1B,GAAI,iBAAiB,EAAE,mBAAmB,eAAe,MAAM,IAAI,CAAC;EACpE,GAAI,cAAc,EAAE,gBAAgB,YAAY,MAAM,IAAI,CAAC;EAC3D,GAAI,eACA,EACE,iBAAiB;GACf,eAAe,aAAa;GAC5B,UAAU,aAAa;EACzB,EACF,IACA,CAAC;EACL,mBAAmB,WAAW;EAC9B,oBAAoB,WAAW;CACjC,CACF;AACF,CAAC"}
1
+ {"version":3,"file":"transform.cjs","names":[],"sources":["../../../src/callers/transform.ts"],"sourcesContent":["import type { CallerDescriptor, CallerValueSource } from './types';\n\n/**\n * Wire format of an extra caller forwarded to the `@intlayer/swc` plugin.\n *\n * Field names mirror the serde attributes of `ExtraCallerConfig` in\n * `packages/@intlayer/swc/src/lib.rs` — both sides must stay in sync.\n */\nexport type SwcExtraCallerConfig = {\n /** The function name the user calls, e.g. `\"useTranslation\"`. */\n callerName: string;\n /** Module specifiers exporting the function (original + `@intlayer/*`). */\n importSources: string[];\n /**\n * Zero-based index of the positional argument holding the namespace string.\n * Omitted for fixed/option namespace callers.\n */\n namespaceArgIndex?: number;\n /**\n * Compile-time constant namespace — the dictionary ident is inserted as a\n * new first argument (lingui's `useLingui()`).\n */\n fixedNamespace?: string;\n /**\n * Namespace read from a property of an options-object argument — the\n * dictionary ident is inserted as a new first argument and the property is\n * rewritten to the key-prefix remainder (vue-i18n's `useI18n({ namespace })`).\n */\n namespaceOption?: { argumentIndex: number; property: string };\n /** Replacement function name for static import mode, e.g. `\"useDictionary\"`. */\n staticReplacement: string;\n /** Replacement function name for dynamic/fetch mode, e.g. `\"useDictionaryDynamic\"`. */\n dynamicReplacement: string;\n};\n\n/**\n * Whether the optimize pass can rewrite this caller's call sites at build time.\n *\n * Requires both replacement names and a call shape reachable through an import\n * specifier rename: a plain imported function, or a JSX component whose\n * element receives the dictionary as a prop (lingui's `<Trans>`).\n * Method-matched callers (`i18n.getFixedT`, `intl.formatMessage`) are\n * excluded — their call sites keep resolving through the runtime dictionary\n * registry.\n */\nexport const isRewritableCaller = (descriptor: CallerDescriptor): boolean =>\n descriptor.staticReplacement !== undefined &&\n descriptor.dynamicReplacement !== undefined &&\n descriptor.matchAsMethod !== true;\n\n/**\n * Returns the callers of a registry slice that the optimize pass can rewrite\n * at build time. See {@link isRewritableCaller}.\n */\nexport const getRewritableCallers = (\n descriptors: CallerDescriptor[]\n): CallerDescriptor[] => descriptors.filter(isRewritableCaller);\n\nconst findSource = <F extends CallerValueSource['from']>(\n sources: CallerValueSource[],\n from: F\n): Extract<CallerValueSource, { from: F }> | undefined =>\n sources.find(\n (source): source is Extract<CallerValueSource, { from: F }> =>\n source.from === from\n );\n\n/**\n * Serialises the rewritable callers of a registry slice into the\n * `@intlayer/swc` plugin wire format (`extraCallers` option).\n *\n * A caller with no statically readable namespace source is dropped: the plugin\n * binds a dictionary from an argument, an option property or a fixed value\n * only, so forwarding it would emit a descriptor no call site can match.\n *\n * @param descriptors - Registry slice, e.g. `REACT_I18NEXT_CALLERS`.\n * @returns Configs ready to pass as the plugin's `extraCallers` option.\n */\nexport const toSwcExtraCallers = (\n descriptors: CallerDescriptor[]\n): SwcExtraCallerConfig[] =>\n getRewritableCallers(descriptors).flatMap((descriptor) => {\n const argumentSource = findSource(descriptor.namespaceSources, 'argument');\n const optionSource = findSource(descriptor.namespaceSources, 'option');\n const fixedSource = findSource(descriptor.namespaceSources, 'fixed');\n\n if (!argumentSource && !optionSource && !fixedSource) return [];\n\n return [\n {\n callerName: descriptor.callerName,\n importSources: descriptor.importSources,\n ...(argumentSource ? { namespaceArgIndex: argumentSource.index } : {}),\n ...(fixedSource ? { fixedNamespace: fixedSource.value } : {}),\n ...(optionSource\n ? {\n namespaceOption: {\n argumentIndex: optionSource.argumentIndex,\n property: optionSource.property,\n },\n }\n : {}),\n staticReplacement: descriptor.staticReplacement!,\n dynamicReplacement: descriptor.dynamicReplacement!,\n },\n ];\n });\n"],"mappings":";;;;;;;;;;;;AA6CA,MAAa,sBAAsB,eACjC,WAAW,sBAAsB,UACjC,WAAW,uBAAuB,UAClC,WAAW,kBAAkB;;;;;AAM/B,MAAa,wBACX,gBACuB,YAAY,OAAO,kBAAkB;AAE9D,MAAM,cACJ,SACA,SAEA,QAAQ,MACL,WACC,OAAO,SAAS,IACpB;;;;;;;;;;;;AAaF,MAAa,qBACX,gBAEA,qBAAqB,WAAW,CAAC,CAAC,SAAS,eAAe;CACxD,MAAM,iBAAiB,WAAW,WAAW,kBAAkB,UAAU;CACzE,MAAM,eAAe,WAAW,WAAW,kBAAkB,QAAQ;CACrE,MAAM,cAAc,WAAW,WAAW,kBAAkB,OAAO;CAEnE,IAAI,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,aAAa,OAAO,CAAC;CAE9D,OAAO,CACL;EACE,YAAY,WAAW;EACvB,eAAe,WAAW;EAC1B,GAAI,iBAAiB,EAAE,mBAAmB,eAAe,MAAM,IAAI,CAAC;EACpE,GAAI,cAAc,EAAE,gBAAgB,YAAY,MAAM,IAAI,CAAC;EAC3D,GAAI,eACA,EACE,iBAAiB;GACf,eAAe,aAAa;GAC5B,UAAU,aAAa;EACzB,EACF,IACA,CAAC;EACL,mBAAmB,WAAW;EAC9B,oBAAoB,WAAW;CACjC,CACF;AACF,CAAC"}
@@ -1,7 +1,7 @@
1
1
  import { getAlias } from "../utils/alias.mjs";
2
2
  import { getConfiguration } from "../configFile/getConfiguration.mjs";
3
- import { BundleLogger } from "./logBundle.mjs";
4
3
  import { getConfigEnvVars } from "../envVars/envVars.mjs";
4
+ import { BundleLogger } from "./logBundle.mjs";
5
5
  import { isAbsolute, join, resolve } from "node:path";
6
6
  import { mkdir, rm, writeFile } from "node:fs/promises";
7
7
  import configPackageJson from "@intlayer/types/package.json" with { type: "json" };
@@ -8,9 +8,16 @@
8
8
  *
9
9
  * The adapter therefore addresses lingui catalogs by the id's first dot-segment,
10
10
  * which lets a catalog split with `syncJSON({ splitKeys: 'key-prefix' })` resolve
11
- * one small dictionary per call site instead of the whole catalog. None of these
12
- * callers carries a namespace argument, so the optimize passes leave them to the
13
- * runtime resolver and only the usage analysis reads the ids.
11
+ * one small dictionary per call site instead of the whole catalog.
12
+ *
13
+ * None of these callers carries a namespace argument. `useLingui()` is bound
14
+ * through the root-scope path instead: the babel optimize pass collects the
15
+ * first segment of every static id passed to `_` / `t` / `<Trans>` in the
16
+ * file and hands the matching dictionaries to `useDictionary(...)`. `<Trans>`
17
+ * carries its own id, so each element is bound on its own with a `dictionary`
18
+ * prop. A catalog that has *not* been split still resolves —
19
+ * `rootDictionaryKey` points the fallback at lingui's single `messages`
20
+ * dictionary with the id kept intact.
14
21
  *
15
22
  * `t` and `_` are generic names, so all lingui callers require an import from
16
23
  * a lingui module to participate in matching — this avoids false positives on
@@ -26,6 +33,8 @@ const LINGUI_IMPORT_SOURCES = [
26
33
  "@lingui/react/macro",
27
34
  "@intlayer/lingui"
28
35
  ];
36
+ /** Key of lingui's single catalog, used when the id segment names no dictionary. */
37
+ const LINGUI_ROOT_DICTIONARY_KEY = "messages";
29
38
  const LINGUI_CALLERS = [
30
39
  {
31
40
  callerName: "useLingui",
@@ -33,7 +42,10 @@ const LINGUI_CALLERS = [
33
42
  importSources: LINGUI_IMPORT_SOURCES,
34
43
  namespaceSources: [],
35
44
  allowRootScope: true,
36
- translationFunction: "destructured-t"
45
+ rootDictionaryKey: LINGUI_ROOT_DICTIONARY_KEY,
46
+ translationFunction: "destructured-t",
47
+ staticReplacement: "useDictionary",
48
+ dynamicReplacement: "useDictionaryDynamic"
37
49
  },
38
50
  {
39
51
  callerName: "_",
@@ -61,7 +73,10 @@ const LINGUI_CALLERS = [
61
73
  requiresImport: true,
62
74
  jsxIdAttribute: "id",
63
75
  namespaceSources: [{ from: "path-first-segment" }],
64
- translationFunction: "self"
76
+ rootDictionaryKey: LINGUI_ROOT_DICTIONARY_KEY,
77
+ translationFunction: "self",
78
+ staticReplacement: "TransDictionary",
79
+ dynamicReplacement: "TransDictionaryDynamic"
65
80
  }
66
81
  ];
67
82
 
@@ -1 +1 @@
1
- {"version":3,"file":"lingui.mjs","names":[],"sources":["../../../../src/callers/compat/lingui.ts"],"sourcesContent":["import type { CallerDescriptor } from '../types';\n\n/**\n * Lingui — `@intlayer/lingui` compat adapter.\n *\n * Lingui is a single-catalog library: the namespace lives *inside* the message\n * id rather than in the file layout, so `i18n._('footer.github')` names both\n * the group (`footer`) and the field (`github`).\n *\n * The adapter therefore addresses lingui catalogs by the id's first dot-segment,\n * which lets a catalog split with `syncJSON({ splitKeys: 'key-prefix' })` resolve\n * one small dictionary per call site instead of the whole catalog. None of these\n * callers carries a namespace argument, so the optimize passes leave them to the\n * runtime resolver and only the usage analysis reads the ids.\n *\n * `t` and `_` are generic names, so all lingui callers require an import from\n * a lingui module to participate in matching — this avoids false positives on\n * unrelated `t()` helpers.\n *\n * Mirrors `compat/lingui/src/plugin/index.ts`.\n */\nconst LINGUI_IMPORT_SOURCES = [\n '@lingui/core',\n '@lingui/react',\n '@lingui/macro',\n '@lingui/core/macro',\n '@lingui/react/macro',\n '@intlayer/lingui',\n];\n\nexport const LINGUI_CALLERS: CallerDescriptor[] = [\n {\n callerName: 'useLingui',\n library: 'lingui',\n importSources: LINGUI_IMPORT_SOURCES,\n // `const { i18n, t, _ } = useLingui()` takes no namespace argument, so the\n // dictionary is only knowable from the ids passed to the returned\n // functions which the usage analysis reads and the optimize passes do not.\n namespaceSources: [],\n allowRootScope: true,\n translationFunction: 'destructured-t',\n },\n {\n callerName: '_',\n library: 'lingui',\n importSources: LINGUI_IMPORT_SOURCES,\n requiresImport: true,\n // `i18n._('id')` and the destructured `const { _ } = useLingui()` form.\n matchAsMethod: true,\n namespaceSources: [{ from: 'path-first-segment' }],\n translationFunction: 'self',\n },\n {\n callerName: 't',\n library: 'lingui',\n importSources: LINGUI_IMPORT_SOURCES,\n requiresImport: true,\n // `i18n.t('id')`, `t({ id: 'id' })` and the macro tagged template ``t`…` ``.\n matchAsMethod: true,\n matchAsTaggedTemplate: true,\n namespaceSources: [{ from: 'path-first-segment' }],\n translationFunction: 'self',\n },\n {\n callerName: 'Trans',\n library: 'lingui',\n importSources: LINGUI_IMPORT_SOURCES,\n requiresImport: true,\n // <Trans id=\"home.title\" message=\"Welcome\" />\n jsxIdAttribute: 'id',\n namespaceSources: [{ from: 'path-first-segment' }],\n translationFunction: 'self',\n },\n];\n"],"mappings":";;;;;;;;;;;;;;;;;;;;AAqBA,MAAM,wBAAwB;CAC5B;CACA;CACA;CACA;CACA;CACA;AACF;AAEA,MAAa,iBAAqC;CAChD;EACE,YAAY;EACZ,SAAS;EACT,eAAe;EAIf,kBAAkB,CAAC;EACnB,gBAAgB;EAChB,qBAAqB;CACvB;CACA;EACE,YAAY;EACZ,SAAS;EACT,eAAe;EACf,gBAAgB;EAEhB,eAAe;EACf,kBAAkB,CAAC,EAAE,MAAM,qBAAqB,CAAC;EACjD,qBAAqB;CACvB;CACA;EACE,YAAY;EACZ,SAAS;EACT,eAAe;EACf,gBAAgB;EAEhB,eAAe;EACf,uBAAuB;EACvB,kBAAkB,CAAC,EAAE,MAAM,qBAAqB,CAAC;EACjD,qBAAqB;CACvB;CACA;EACE,YAAY;EACZ,SAAS;EACT,eAAe;EACf,gBAAgB;EAEhB,gBAAgB;EAChB,kBAAkB,CAAC,EAAE,MAAM,qBAAqB,CAAC;EACjD,qBAAqB;CACvB;AACF"}
1
+ {"version":3,"file":"lingui.mjs","names":[],"sources":["../../../../src/callers/compat/lingui.ts"],"sourcesContent":["import type { CallerDescriptor } from '../types';\n\n/**\n * Lingui — `@intlayer/lingui` compat adapter.\n *\n * Lingui is a single-catalog library: the namespace lives *inside* the message\n * id rather than in the file layout, so `i18n._('footer.github')` names both\n * the group (`footer`) and the field (`github`).\n *\n * The adapter therefore addresses lingui catalogs by the id's first dot-segment,\n * which lets a catalog split with `syncJSON({ splitKeys: 'key-prefix' })` resolve\n * one small dictionary per call site instead of the whole catalog.\n *\n * None of these callers carries a namespace argument. `useLingui()` is bound\n * through the root-scope path instead: the babel optimize pass collects the\n * first segment of every static id passed to `_` / `t` / `<Trans>` in the\n * file and hands the matching dictionaries to `useDictionary(...)`. `<Trans>`\n * carries its own id, so each element is bound on its own with a `dictionary`\n * prop. A catalog that has *not* been split still resolves —\n * `rootDictionaryKey` points the fallback at lingui's single `messages`\n * dictionary with the id kept intact.\n *\n * `t` and `_` are generic names, so all lingui callers require an import from\n * a lingui module to participate in matching — this avoids false positives on\n * unrelated `t()` helpers.\n *\n * Mirrors `compat/lingui/src/plugin/index.ts`.\n */\nconst LINGUI_IMPORT_SOURCES = [\n '@lingui/core',\n '@lingui/react',\n '@lingui/macro',\n '@lingui/core/macro',\n '@lingui/react/macro',\n '@intlayer/lingui',\n];\n\n/** Key of lingui's single catalog, used when the id segment names no dictionary. */\nconst LINGUI_ROOT_DICTIONARY_KEY = 'messages';\n\nexport const LINGUI_CALLERS: CallerDescriptor[] = [\n {\n callerName: 'useLingui',\n library: 'lingui',\n importSources: LINGUI_IMPORT_SOURCES,\n // `const { i18n, t, _ } = useLingui()` takes no namespace argument: the\n // dictionaries are named by the message ids passed to the returned\n // functions, so the call site binds through the root-scope path.\n namespaceSources: [],\n allowRootScope: true,\n rootDictionaryKey: LINGUI_ROOT_DICTIONARY_KEY,\n translationFunction: 'destructured-t',\n staticReplacement: 'useDictionary',\n dynamicReplacement: 'useDictionaryDynamic',\n },\n {\n callerName: '_',\n library: 'lingui',\n importSources: LINGUI_IMPORT_SOURCES,\n requiresImport: true,\n // `i18n._('id')` and the destructured `const { _ } = useLingui()` form.\n matchAsMethod: true,\n namespaceSources: [{ from: 'path-first-segment' }],\n translationFunction: 'self',\n },\n {\n callerName: 't',\n library: 'lingui',\n importSources: LINGUI_IMPORT_SOURCES,\n requiresImport: true,\n // `i18n.t('id')`, `t({ id: 'id' })` and the macro tagged template ``t`…` ``.\n matchAsMethod: true,\n matchAsTaggedTemplate: true,\n namespaceSources: [{ from: 'path-first-segment' }],\n translationFunction: 'self',\n },\n {\n callerName: 'Trans',\n library: 'lingui',\n importSources: LINGUI_IMPORT_SOURCES,\n requiresImport: true,\n // <Trans id=\"home.title\" message=\"Welcome\" />\n jsxIdAttribute: 'id',\n namespaceSources: [{ from: 'path-first-segment' }],\n rootDictionaryKey: LINGUI_ROOT_DICTIONARY_KEY,\n translationFunction: 'self',\n // The element names its own dictionary through `id`, so it is bound on\n // its own: the pass adds a `dictionary` prop and re-points the import.\n staticReplacement: 'TransDictionary',\n dynamicReplacement: 'TransDictionaryDynamic',\n },\n];\n"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;AA4BA,MAAM,wBAAwB;CAC5B;CACA;CACA;CACA;CACA;CACA;AACF;;AAGA,MAAM,6BAA6B;AAEnC,MAAa,iBAAqC;CAChD;EACE,YAAY;EACZ,SAAS;EACT,eAAe;EAIf,kBAAkB,CAAC;EACnB,gBAAgB;EAChB,mBAAmB;EACnB,qBAAqB;EACrB,mBAAmB;EACnB,oBAAoB;CACtB;CACA;EACE,YAAY;EACZ,SAAS;EACT,eAAe;EACf,gBAAgB;EAEhB,eAAe;EACf,kBAAkB,CAAC,EAAE,MAAM,qBAAqB,CAAC;EACjD,qBAAqB;CACvB;CACA;EACE,YAAY;EACZ,SAAS;EACT,eAAe;EACf,gBAAgB;EAEhB,eAAe;EACf,uBAAuB;EACvB,kBAAkB,CAAC,EAAE,MAAM,qBAAqB,CAAC;EACjD,qBAAqB;CACvB;CACA;EACE,YAAY;EACZ,SAAS;EACT,eAAe;EACf,gBAAgB;EAEhB,gBAAgB;EAChB,kBAAkB,CAAC,EAAE,MAAM,qBAAqB,CAAC;EACjD,mBAAmB;EACnB,qBAAqB;EAGrB,mBAAmB;EACnB,oBAAoB;CACtB;AACF"}
@@ -3,11 +3,13 @@
3
3
  * Whether the optimize pass can rewrite this caller's call sites at build time.
4
4
  *
5
5
  * Requires both replacement names and a call shape reachable through an import
6
- * specifier rename. Method-matched callers (`i18n.getFixedT`, `intl.formatMessage`)
7
- * and JSX components (`<Trans>`, `<FormattedMessage>`) are excluded — their call
8
- * sites keep resolving through the runtime dictionary registry.
6
+ * specifier rename: a plain imported function, or a JSX component whose
7
+ * element receives the dictionary as a prop (lingui's `<Trans>`).
8
+ * Method-matched callers (`i18n.getFixedT`, `intl.formatMessage`) are
9
+ * excluded — their call sites keep resolving through the runtime dictionary
10
+ * registry.
9
11
  */
10
- const isRewritableCaller = (descriptor) => descriptor.staticReplacement !== void 0 && descriptor.dynamicReplacement !== void 0 && descriptor.matchAsMethod !== true && descriptor.jsxIdAttribute === void 0;
12
+ const isRewritableCaller = (descriptor) => descriptor.staticReplacement !== void 0 && descriptor.dynamicReplacement !== void 0 && descriptor.matchAsMethod !== true;
11
13
  /**
12
14
  * Returns the callers of a registry slice that the optimize pass can rewrite
13
15
  * at build time. See {@link isRewritableCaller}.
@@ -1 +1 @@
1
- {"version":3,"file":"transform.mjs","names":[],"sources":["../../../src/callers/transform.ts"],"sourcesContent":["import type { CallerDescriptor, CallerValueSource } from './types';\n\n/**\n * Wire format of an extra caller forwarded to the `@intlayer/swc` plugin.\n *\n * Field names mirror the serde attributes of `ExtraCallerConfig` in\n * `packages/@intlayer/swc/src/lib.rs` — both sides must stay in sync.\n */\nexport type SwcExtraCallerConfig = {\n /** The function name the user calls, e.g. `\"useTranslation\"`. */\n callerName: string;\n /** Module specifiers exporting the function (original + `@intlayer/*`). */\n importSources: string[];\n /**\n * Zero-based index of the positional argument holding the namespace string.\n * Omitted for fixed/option namespace callers.\n */\n namespaceArgIndex?: number;\n /**\n * Compile-time constant namespace — the dictionary ident is inserted as a\n * new first argument (lingui's `useLingui()`).\n */\n fixedNamespace?: string;\n /**\n * Namespace read from a property of an options-object argument — the\n * dictionary ident is inserted as a new first argument and the property is\n * rewritten to the key-prefix remainder (vue-i18n's `useI18n({ namespace })`).\n */\n namespaceOption?: { argumentIndex: number; property: string };\n /** Replacement function name for static import mode, e.g. `\"useDictionary\"`. */\n staticReplacement: string;\n /** Replacement function name for dynamic/fetch mode, e.g. `\"useDictionaryDynamic\"`. */\n dynamicReplacement: string;\n};\n\n/**\n * Whether the optimize pass can rewrite this caller's call sites at build time.\n *\n * Requires both replacement names and a call shape reachable through an import\n * specifier rename. Method-matched callers (`i18n.getFixedT`, `intl.formatMessage`)\n * and JSX components (`<Trans>`, `<FormattedMessage>`) are excluded — their call\n * sites keep resolving through the runtime dictionary registry.\n */\nexport const isRewritableCaller = (descriptor: CallerDescriptor): boolean =>\n descriptor.staticReplacement !== undefined &&\n descriptor.dynamicReplacement !== undefined &&\n descriptor.matchAsMethod !== true &&\n descriptor.jsxIdAttribute === undefined;\n\n/**\n * Returns the callers of a registry slice that the optimize pass can rewrite\n * at build time. See {@link isRewritableCaller}.\n */\nexport const getRewritableCallers = (\n descriptors: CallerDescriptor[]\n): CallerDescriptor[] => descriptors.filter(isRewritableCaller);\n\nconst findSource = <F extends CallerValueSource['from']>(\n sources: CallerValueSource[],\n from: F\n): Extract<CallerValueSource, { from: F }> | undefined =>\n sources.find(\n (source): source is Extract<CallerValueSource, { from: F }> =>\n source.from === from\n );\n\n/**\n * Serialises the rewritable callers of a registry slice into the\n * `@intlayer/swc` plugin wire format (`extraCallers` option).\n *\n * A caller with no statically readable namespace source is dropped: the plugin\n * binds a dictionary from an argument, an option property or a fixed value\n * only, so forwarding it would emit a descriptor no call site can match.\n *\n * @param descriptors - Registry slice, e.g. `REACT_I18NEXT_CALLERS`.\n * @returns Configs ready to pass as the plugin's `extraCallers` option.\n */\nexport const toSwcExtraCallers = (\n descriptors: CallerDescriptor[]\n): SwcExtraCallerConfig[] =>\n getRewritableCallers(descriptors).flatMap((descriptor) => {\n const argumentSource = findSource(descriptor.namespaceSources, 'argument');\n const optionSource = findSource(descriptor.namespaceSources, 'option');\n const fixedSource = findSource(descriptor.namespaceSources, 'fixed');\n\n if (!argumentSource && !optionSource && !fixedSource) return [];\n\n return [\n {\n callerName: descriptor.callerName,\n importSources: descriptor.importSources,\n ...(argumentSource ? { namespaceArgIndex: argumentSource.index } : {}),\n ...(fixedSource ? { fixedNamespace: fixedSource.value } : {}),\n ...(optionSource\n ? {\n namespaceOption: {\n argumentIndex: optionSource.argumentIndex,\n property: optionSource.property,\n },\n }\n : {}),\n staticReplacement: descriptor.staticReplacement!,\n dynamicReplacement: descriptor.dynamicReplacement!,\n },\n ];\n });\n"],"mappings":";;;;;;;;;AA2CA,MAAa,sBAAsB,eACjC,WAAW,sBAAsB,UACjC,WAAW,uBAAuB,UAClC,WAAW,kBAAkB,QAC7B,WAAW,mBAAmB;;;;;AAMhC,MAAa,wBACX,gBACuB,YAAY,OAAO,kBAAkB;AAE9D,MAAM,cACJ,SACA,SAEA,QAAQ,MACL,WACC,OAAO,SAAS,IACpB;;;;;;;;;;;;AAaF,MAAa,qBACX,gBAEA,qBAAqB,WAAW,CAAC,CAAC,SAAS,eAAe;CACxD,MAAM,iBAAiB,WAAW,WAAW,kBAAkB,UAAU;CACzE,MAAM,eAAe,WAAW,WAAW,kBAAkB,QAAQ;CACrE,MAAM,cAAc,WAAW,WAAW,kBAAkB,OAAO;CAEnE,IAAI,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,aAAa,OAAO,CAAC;CAE9D,OAAO,CACL;EACE,YAAY,WAAW;EACvB,eAAe,WAAW;EAC1B,GAAI,iBAAiB,EAAE,mBAAmB,eAAe,MAAM,IAAI,CAAC;EACpE,GAAI,cAAc,EAAE,gBAAgB,YAAY,MAAM,IAAI,CAAC;EAC3D,GAAI,eACA,EACE,iBAAiB;GACf,eAAe,aAAa;GAC5B,UAAU,aAAa;EACzB,EACF,IACA,CAAC;EACL,mBAAmB,WAAW;EAC9B,oBAAoB,WAAW;CACjC,CACF;AACF,CAAC"}
1
+ {"version":3,"file":"transform.mjs","names":[],"sources":["../../../src/callers/transform.ts"],"sourcesContent":["import type { CallerDescriptor, CallerValueSource } from './types';\n\n/**\n * Wire format of an extra caller forwarded to the `@intlayer/swc` plugin.\n *\n * Field names mirror the serde attributes of `ExtraCallerConfig` in\n * `packages/@intlayer/swc/src/lib.rs` — both sides must stay in sync.\n */\nexport type SwcExtraCallerConfig = {\n /** The function name the user calls, e.g. `\"useTranslation\"`. */\n callerName: string;\n /** Module specifiers exporting the function (original + `@intlayer/*`). */\n importSources: string[];\n /**\n * Zero-based index of the positional argument holding the namespace string.\n * Omitted for fixed/option namespace callers.\n */\n namespaceArgIndex?: number;\n /**\n * Compile-time constant namespace — the dictionary ident is inserted as a\n * new first argument (lingui's `useLingui()`).\n */\n fixedNamespace?: string;\n /**\n * Namespace read from a property of an options-object argument — the\n * dictionary ident is inserted as a new first argument and the property is\n * rewritten to the key-prefix remainder (vue-i18n's `useI18n({ namespace })`).\n */\n namespaceOption?: { argumentIndex: number; property: string };\n /** Replacement function name for static import mode, e.g. `\"useDictionary\"`. */\n staticReplacement: string;\n /** Replacement function name for dynamic/fetch mode, e.g. `\"useDictionaryDynamic\"`. */\n dynamicReplacement: string;\n};\n\n/**\n * Whether the optimize pass can rewrite this caller's call sites at build time.\n *\n * Requires both replacement names and a call shape reachable through an import\n * specifier rename: a plain imported function, or a JSX component whose\n * element receives the dictionary as a prop (lingui's `<Trans>`).\n * Method-matched callers (`i18n.getFixedT`, `intl.formatMessage`) are\n * excluded — their call sites keep resolving through the runtime dictionary\n * registry.\n */\nexport const isRewritableCaller = (descriptor: CallerDescriptor): boolean =>\n descriptor.staticReplacement !== undefined &&\n descriptor.dynamicReplacement !== undefined &&\n descriptor.matchAsMethod !== true;\n\n/**\n * Returns the callers of a registry slice that the optimize pass can rewrite\n * at build time. See {@link isRewritableCaller}.\n */\nexport const getRewritableCallers = (\n descriptors: CallerDescriptor[]\n): CallerDescriptor[] => descriptors.filter(isRewritableCaller);\n\nconst findSource = <F extends CallerValueSource['from']>(\n sources: CallerValueSource[],\n from: F\n): Extract<CallerValueSource, { from: F }> | undefined =>\n sources.find(\n (source): source is Extract<CallerValueSource, { from: F }> =>\n source.from === from\n );\n\n/**\n * Serialises the rewritable callers of a registry slice into the\n * `@intlayer/swc` plugin wire format (`extraCallers` option).\n *\n * A caller with no statically readable namespace source is dropped: the plugin\n * binds a dictionary from an argument, an option property or a fixed value\n * only, so forwarding it would emit a descriptor no call site can match.\n *\n * @param descriptors - Registry slice, e.g. `REACT_I18NEXT_CALLERS`.\n * @returns Configs ready to pass as the plugin's `extraCallers` option.\n */\nexport const toSwcExtraCallers = (\n descriptors: CallerDescriptor[]\n): SwcExtraCallerConfig[] =>\n getRewritableCallers(descriptors).flatMap((descriptor) => {\n const argumentSource = findSource(descriptor.namespaceSources, 'argument');\n const optionSource = findSource(descriptor.namespaceSources, 'option');\n const fixedSource = findSource(descriptor.namespaceSources, 'fixed');\n\n if (!argumentSource && !optionSource && !fixedSource) return [];\n\n return [\n {\n callerName: descriptor.callerName,\n importSources: descriptor.importSources,\n ...(argumentSource ? { namespaceArgIndex: argumentSource.index } : {}),\n ...(fixedSource ? { fixedNamespace: fixedSource.value } : {}),\n ...(optionSource\n ? {\n namespaceOption: {\n argumentIndex: optionSource.argumentIndex,\n property: optionSource.property,\n },\n }\n : {}),\n staticReplacement: descriptor.staticReplacement!,\n dynamicReplacement: descriptor.dynamicReplacement!,\n },\n ];\n });\n"],"mappings":";;;;;;;;;;;AA6CA,MAAa,sBAAsB,eACjC,WAAW,sBAAsB,UACjC,WAAW,uBAAuB,UAClC,WAAW,kBAAkB;;;;;AAM/B,MAAa,wBACX,gBACuB,YAAY,OAAO,kBAAkB;AAE9D,MAAM,cACJ,SACA,SAEA,QAAQ,MACL,WACC,OAAO,SAAS,IACpB;;;;;;;;;;;;AAaF,MAAa,qBACX,gBAEA,qBAAqB,WAAW,CAAC,CAAC,SAAS,eAAe;CACxD,MAAM,iBAAiB,WAAW,WAAW,kBAAkB,UAAU;CACzE,MAAM,eAAe,WAAW,WAAW,kBAAkB,QAAQ;CACrE,MAAM,cAAc,WAAW,WAAW,kBAAkB,OAAO;CAEnE,IAAI,CAAC,kBAAkB,CAAC,gBAAgB,CAAC,aAAa,OAAO,CAAC;CAE9D,OAAO,CACL;EACE,YAAY,WAAW;EACvB,eAAe,WAAW;EAC1B,GAAI,iBAAiB,EAAE,mBAAmB,eAAe,MAAM,IAAI,CAAC;EACpE,GAAI,cAAc,EAAE,gBAAgB,YAAY,MAAM,IAAI,CAAC;EAC3D,GAAI,eACA,EACE,iBAAiB;GACf,eAAe,aAAa;GAC5B,UAAU,aAAa;EACzB,EACF,IACA,CAAC;EACL,mBAAmB,WAAW;EAC9B,oBAAoB,WAAW;CACjC,CACF;AACF,CAAC"}
@@ -1 +1 @@
1
- {"version":3,"file":"lingui.d.ts","names":[],"sources":["../../../../src/callers/compat/lingui.ts"],"mappings":";;qBA8Ba,gBAAgB"}
1
+ {"version":3,"file":"lingui.d.ts","names":[],"sources":["../../../../src/callers/compat/lingui.ts"],"mappings":";;qBAwCa,gBAAgB"}
@@ -39,9 +39,11 @@ export type SwcExtraCallerConfig = {
39
39
  * Whether the optimize pass can rewrite this caller's call sites at build time.
40
40
  *
41
41
  * Requires both replacement names and a call shape reachable through an import
42
- * specifier rename. Method-matched callers (`i18n.getFixedT`, `intl.formatMessage`)
43
- * and JSX components (`<Trans>`, `<FormattedMessage>`) are excluded — their call
44
- * sites keep resolving through the runtime dictionary registry.
42
+ * specifier rename: a plain imported function, or a JSX component whose
43
+ * element receives the dictionary as a prop (lingui's `<Trans>`).
44
+ * Method-matched callers (`i18n.getFixedT`, `intl.formatMessage`) are
45
+ * excluded — their call sites keep resolving through the runtime dictionary
46
+ * registry.
45
47
  */
46
48
  export declare const isRewritableCaller: (descriptor: CallerDescriptor) => boolean;
47
49
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"transform.d.ts","names":[],"sources":["../../../src/callers/transform.ts"],"mappings":";;;;;;;;YAQY;;EAEV;;EAEA;;;;;EAKA;;;;;EAKA;;;;;;EAMA;IAAoB;IAAuB;;;EAE3C;;EAEA;;;;;;;;;;qBAWW,qBAAkB,YAAgB;;;;;qBAUlC,uBAAoB,aAClB,uBACZ;;;;;;;;;;;;qBAsBU,oBAAiB,aACf,uBACZ"}
1
+ {"version":3,"file":"transform.d.ts","names":[],"sources":["../../../src/callers/transform.ts"],"mappings":";;;;;;;;YAQY;;EAEV;;EAEA;;;;;EAKA;;;;;EAKA;;;;;;EAMA;IAAoB;IAAuB;;;EAE3C;;EAEA;;;;;;;;;;;;qBAaW,qBAAkB,YAAgB;;;;;qBASlC,uBAAoB,aAClB,uBACZ;;;;;;;;;;;;qBAsBU,oBAAiB,aACf,uBACZ"}
@@ -130,13 +130,29 @@ export type CallerDescriptor = {
130
130
  * (`useTranslations()` root scope) — the dictionary key is then the first
131
131
  * dot-segment of each message id passed to the returned `t()`.
132
132
  *
133
- * Analysis-only: the LSP resolves such bindings for go-to-definition, and
134
- * the ESLint rule stops reporting the missing argument as a dynamic key.
135
- * The optimize passes do **not** honour it — a call with no readable
136
- * namespace is left to the runtime registry, so declaring it never changes
137
- * the emitted bundle.
133
+ * The LSP resolves such bindings for go-to-definition, and the ESLint rule
134
+ * stops reporting the missing argument as a dynamic key.
135
+ *
136
+ * The babel optimize pass binds a root-scope call only when the library
137
+ * also declares `'self'` callers reading a `path-first-segment` namespace
138
+ * (lingui's `_` / `t` / `<Trans>`): the dictionaries are then the first
139
+ * segments of every static message id found in the same file, and the call
140
+ * receives them all. Any dynamic id in the file leaves the call to the
141
+ * runtime registry. Libraries whose ids only reach a *returned* function
142
+ * (`const t = useTranslations(); t('a.b')`) are never bound this way.
138
143
  */
139
144
  allowRootScope?: boolean;
145
+ /**
146
+ * Dictionary bound by a root-scope call whose first id segment is not itself
147
+ * a dictionary — the project keeps one whole-file catalog instead of one
148
+ * dictionary per prefix. The full id is then left intact, mirroring the
149
+ * runtime resolver's own fallback.
150
+ *
151
+ * lingui's single catalog is named `messages`; without this a lingui app
152
+ * that has *not* split its catalog would see every root-scope binding
153
+ * declined.
154
+ */
155
+ rootDictionaryKey?: string;
140
156
  /** How translated content is obtained from the caller's result. */
141
157
  translationFunction: CallerResultShape;
142
158
  /**
@@ -152,7 +168,10 @@ export type CallerDescriptor = {
152
168
  * it; original-library specifiers are bundler-aliased to the compat package).
153
169
  *
154
170
  * Only callers with both replacements set — and matched as plain imported
155
- * functions (not `matchAsMethod` / JSX) are rewritten at build time.
171
+ * functions or as JSX elements (`jsxIdAttribute`), not `matchAsMethod` —
172
+ * are rewritten at build time. A JSX element is bound by the first segment
173
+ * of its id attribute and receives the dictionary through a `dictionary`
174
+ * prop.
156
175
  */
157
176
  staticReplacement?: string;
158
177
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"types.d.ts","names":[],"sources":["../../../src/callers/types.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;YAyBY;;;EAEN;EAAkB;;;;EAElB;EAAgB;EAAuB;;;;;;;EAKvC;EAAe;;;;;;;;EAMf;;;;;;;;;;;;;;;;;;YAkBM;;;;YAUA;;EAEV;;EAEA;;;;;;EAMA;;;;;;EAMA;;;;;;EAMA;;EAEA;;;;;;EAMA;;;;;EAKA;;;;;EAKA,kBAAkB;;;;;;EAMlB,mBAAmB;;;;;;;EAOnB;;;;;;;;;;;;EAYA;;EAEA,qBAAqB;;;;;;EAMrB;;;;;;;;;;EAUA;;;;;EAKA"}
1
+ {"version":3,"file":"types.d.ts","names":[],"sources":["../../../src/callers/types.ts"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;YAyBY;;;EAEN;EAAkB;;;;EAElB;EAAgB;EAAuB;;;;;;;EAKvC;EAAe;;;;;;;;EAMf;;;;;;;;;;;;;;;;;;YAkBM;;;;YAUA;;EAEV;;EAEA;;;;;;EAMA;;;;;;EAMA;;;;;;EAMA;;EAEA;;;;;;EAMA;;;;;EAKA;;;;;EAKA,kBAAkB;;;;;;EAMlB,mBAAmB;;;;;;;EAOnB;;;;;;;;;;;;;;;;;EAiBA;;;;;;;;;;;EAWA;;EAEA,qBAAqB;;;;;;EAMrB;;;;;;;;;;;;;EAaA;;;;;EAKA"}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@intlayer/config",
3
- "version": "9.5.1",
3
+ "version": "9.5.3",
4
4
  "private": false,
5
5
  "description": "Retrieve Intlayer configurations and manage environment variables for both server-side and client-side environments.",
6
6
  "keywords": [
@@ -189,15 +189,15 @@
189
189
  "typecheck": "tsc --noEmit --project tsconfig.types.json"
190
190
  },
191
191
  "dependencies": {
192
- "@intlayer/types": "9.5.1",
192
+ "@intlayer/types": "9.5.3",
193
193
  "defu": "6.1.7",
194
194
  "dotenv": "17.4.2",
195
195
  "esbuild": "0.28.2",
196
196
  "json5": "2.2.3",
197
- "zod": "4.5.4"
197
+ "zod": "4.6.5"
198
198
  },
199
199
  "devDependencies": {
200
- "@types/node": "26.5.0",
200
+ "@types/node": "^22",
201
201
  "@utils/ts-config": "1.0.4",
202
202
  "@utils/ts-config-types": "1.0.4",
203
203
  "@utils/tsdown-config": "1.0.4",