@xndrjs/i18n 0.8.0 → 0.8.2-alpha.0

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.
Files changed (94) hide show
  1. package/README.md +1 -2
  2. package/dist/cli/audit.js +739 -0
  3. package/dist/cli/audit.js.map +1 -0
  4. package/dist/cli/codegen.js +1471 -0
  5. package/dist/cli/codegen.js.map +1 -0
  6. package/dist/cli/setup.js +148 -0
  7. package/dist/cli/setup.js.map +1 -0
  8. package/dist/codegen/index.js +43 -40
  9. package/dist/codegen/index.js.map +1 -1
  10. package/dist/index.d.ts +20 -1
  11. package/dist/index.js +56 -10
  12. package/dist/index.js.map +1 -1
  13. package/package.json +6 -9
  14. package/bin/audit.mjs +0 -14
  15. package/bin/codegen.mjs +0 -17
  16. package/bin/setup.mjs +0 -14
  17. package/src/IcuTranslationProviderMulti.test.ts +0 -215
  18. package/src/IcuTranslationProviderMulti.ts +0 -176
  19. package/src/audit/audit-dictionaries.test.ts +0 -134
  20. package/src/audit/audit-dictionaries.ts +0 -178
  21. package/src/audit/run-audit.test.ts +0 -169
  22. package/src/audit/run-audit.ts +0 -94
  23. package/src/builder-load-registry.ts +0 -39
  24. package/src/builder-loaders.ts +0 -15
  25. package/src/builder-types.test.ts +0 -49
  26. package/src/builder-types.ts +0 -24
  27. package/src/builder.test.ts +0 -260
  28. package/src/builder.ts +0 -10
  29. package/src/codegen/codegen-config-schema.ts +0 -156
  30. package/src/codegen/config.test.ts +0 -231
  31. package/src/codegen/config.ts +0 -42
  32. package/src/codegen/constants.ts +0 -9
  33. package/src/codegen/delivery-artifacts.test.ts +0 -167
  34. package/src/codegen/delivery-artifacts.ts +0 -154
  35. package/src/codegen/dictionary-spec-contract.test.ts +0 -28
  36. package/src/codegen/dictionary-spec-contract.ts +0 -138
  37. package/src/codegen/emit/dictionary-schema-file.ts +0 -113
  38. package/src/codegen/emit/instance-file.test.ts +0 -71
  39. package/src/codegen/emit/instance-file.ts +0 -257
  40. package/src/codegen/emit/namespace-loaders-file.test.ts +0 -251
  41. package/src/codegen/emit/namespace-loaders-file.ts +0 -229
  42. package/src/codegen/emit/types-file.test.ts +0 -96
  43. package/src/codegen/emit/types-file.ts +0 -142
  44. package/src/codegen/fixtures/billing-namespace.json +0 -6
  45. package/src/codegen/generate-i18n-types.test.ts +0 -1137
  46. package/src/codegen/generate-i18n-types.ts +0 -20
  47. package/src/codegen/icu-analysis.ts +0 -110
  48. package/src/codegen/locale-fallback.ts +0 -73
  49. package/src/codegen/locale-policy.test.ts +0 -35
  50. package/src/codegen/locale-policy.ts +0 -30
  51. package/src/codegen/paths.ts +0 -44
  52. package/src/codegen/project-locales-set-namespace.test.ts +0 -134
  53. package/src/codegen/read-dictionary.test.ts +0 -594
  54. package/src/codegen/read-dictionary.ts +0 -260
  55. package/src/codegen/regenerate-namespaces.ts +0 -180
  56. package/src/codegen/run-codegen.test.ts +0 -230
  57. package/src/codegen/run-codegen.ts +0 -252
  58. package/src/codegen/types.ts +0 -10
  59. package/src/codegen/write-file-if-changed.test.ts +0 -42
  60. package/src/codegen/write-file-if-changed.ts +0 -20
  61. package/src/codegen-config/build-config.ts +0 -15
  62. package/src/codegen-config/codegen-config.test.ts +0 -36
  63. package/src/codegen-config/index.ts +0 -37
  64. package/src/codegen-config/type-names.ts +0 -20
  65. package/src/codegen-config/write-config.ts +0 -8
  66. package/src/engine.ts +0 -47
  67. package/src/fetch-artifact.ts +0 -16
  68. package/src/format-core.ts +0 -91
  69. package/src/i18n-handle.ts +0 -202
  70. package/src/icu/extract-variables.test.ts +0 -199
  71. package/src/icu/extract-variables.ts +0 -227
  72. package/src/icu/parse-template.ts +0 -31
  73. package/src/index.ts +0 -58
  74. package/src/project-locales.test.ts +0 -280
  75. package/src/project-locales.ts +0 -211
  76. package/src/resolve-locale.test.ts +0 -91
  77. package/src/resolve-locale.ts +0 -88
  78. package/src/scope-multi.ts +0 -105
  79. package/src/scope-types.ts +0 -35
  80. package/src/scope.test.ts +0 -172
  81. package/src/serialized-state.test.ts +0 -114
  82. package/src/serialized-state.ts +0 -28
  83. package/src/setup/setup-i18n.test.ts +0 -85
  84. package/src/setup/setup-i18n.ts +0 -156
  85. package/src/types.ts +0 -65
  86. package/src/validation/create-args-schema.ts +0 -76
  87. package/src/validation/create-normalized-schema.ts +0 -52
  88. package/src/validation/errors.ts +0 -43
  89. package/src/validation/index.ts +0 -202
  90. package/src/validation/normalize.ts +0 -299
  91. package/src/validation/to-dictionary.ts +0 -67
  92. package/src/validation/types.ts +0 -82
  93. package/src/validation/validate-normalized.ts +0 -133
  94. package/src/validation/validation.test.ts +0 -562
@@ -1,257 +0,0 @@
1
- import { GENERATED_FILE_BANNER, toModuleBasename, toRelativeModuleImport } from "../paths.js";
2
- import type { DeliveryMode, LoaderStrategy } from "../codegen-config-schema.js";
3
- import type { ImportExtension } from "../types.js";
4
-
5
- /** Emits the generated instance module: `createI18n` factory wrapping the ICU provider. */
6
- export interface InstanceFileOptions {
7
- typesOutputPath: string;
8
- namespaceLoadersOutputPath: string;
9
- paramsTypeName: string;
10
- schemaTypeName: string;
11
- localeTypeName: string;
12
- localeFallbackConstName: string;
13
- factoryName: string;
14
- hasLocaleFallback: boolean;
15
- hasLocaleType: boolean;
16
- importExtension: ImportExtension;
17
- delivery: DeliveryMode;
18
- localeDeliveryAreaConstName?: string;
19
- loaderStrategy?: LoaderStrategy;
20
- }
21
-
22
- const STATE_TYPE = `{ dictionary: InitialSchema; resources?: readonly (readonly [string, string])[] }`;
23
-
24
- export function formatInstanceFile(options: InstanceFileOptions): string {
25
- const {
26
- typesOutputPath,
27
- namespaceLoadersOutputPath,
28
- paramsTypeName,
29
- schemaTypeName,
30
- localeTypeName,
31
- localeFallbackConstName,
32
- factoryName,
33
- hasLocaleFallback,
34
- hasLocaleType,
35
- importExtension,
36
- delivery,
37
- localeDeliveryAreaConstName = "LOCALE_DELIVERY_AREA",
38
- loaderStrategy = "import",
39
- } = options;
40
-
41
- const providerClass = "IcuTranslationProviderMulti";
42
- const typesModule = toModuleBasename(typesOutputPath);
43
- const typesImport = toRelativeModuleImport(typesModule, importExtension);
44
- const loadersModule = toModuleBasename(namespaceLoadersOutputPath);
45
- const loadersImport = toRelativeModuleImport(loadersModule, importExtension);
46
- const schemaTypesImport = `import type { ${paramsTypeName}, ${schemaTypeName}, InitialSchema } from '${typesImport}';\n`;
47
- const typesImportLine = formatTypesValueImport({
48
- hasLocaleType,
49
- hasLocaleFallback,
50
- localeTypeName,
51
- localeFallbackConstName,
52
- localeDeliveryAreaConstName,
53
- delivery,
54
- typesImport,
55
- });
56
- const packageImports = formatPackageImports(providerClass, loaderStrategy);
57
- const loadersImportLine =
58
- loaderStrategy === "fetch"
59
- ? `import { createNamespaceLoaders } from '${loadersImport}';\n`
60
- : `import { namespaceLoaders } from '${loadersImport}';\n`;
61
-
62
- const createFactoryBlock = formatCreateI18nFactory({
63
- providerClass,
64
- schemaTypeName,
65
- paramsTypeName,
66
- localeTypeName,
67
- localeFallbackConstName,
68
- factoryName,
69
- hasLocaleFallback,
70
- delivery,
71
- localeDeliveryAreaConstName,
72
- loaderStrategy,
73
- });
74
-
75
- return (
76
- `${GENERATED_FILE_BANNER}` +
77
- `import {\n` +
78
- ` ${packageImports},\n` +
79
- `} from '@xndrjs/i18n';\n` +
80
- schemaTypesImport +
81
- typesImportLine +
82
- loadersImportLine +
83
- `\n` +
84
- createFactoryBlock
85
- );
86
- }
87
-
88
- function formatTypesValueImport(options: {
89
- hasLocaleType: boolean;
90
- hasLocaleFallback: boolean;
91
- localeTypeName: string;
92
- localeFallbackConstName: string;
93
- localeDeliveryAreaConstName: string;
94
- delivery: DeliveryMode;
95
- typesImport: string;
96
- }): string {
97
- const {
98
- hasLocaleType,
99
- hasLocaleFallback,
100
- localeTypeName,
101
- localeFallbackConstName,
102
- localeDeliveryAreaConstName,
103
- delivery,
104
- typesImport,
105
- } = options;
106
-
107
- if (!hasLocaleType && delivery !== "custom") {
108
- return "";
109
- }
110
-
111
- const valueNames: string[] = [];
112
- if (hasLocaleFallback) {
113
- valueNames.push(localeFallbackConstName);
114
- }
115
- if (delivery === "custom") {
116
- valueNames.push(localeDeliveryAreaConstName);
117
- }
118
-
119
- if (valueNames.length > 0 && hasLocaleType) {
120
- return `import { ${valueNames.join(", ")}, type ${localeTypeName} } from '${typesImport}';\n`;
121
- }
122
- if (valueNames.length > 0) {
123
- return `import { ${valueNames.join(", ")} } from '${typesImport}';\n`;
124
- }
125
- if (hasLocaleType) {
126
- return `import type { ${localeTypeName} } from '${typesImport}';\n`;
127
- }
128
- return "";
129
- }
130
-
131
- function formatCreateI18nFactory(options: {
132
- providerClass: string;
133
- schemaTypeName: string;
134
- paramsTypeName: string;
135
- localeTypeName: string;
136
- localeFallbackConstName: string;
137
- factoryName: string;
138
- hasLocaleFallback: boolean;
139
- delivery: DeliveryMode;
140
- localeDeliveryAreaConstName: string;
141
- loaderStrategy: LoaderStrategy;
142
- }): string {
143
- const {
144
- providerClass,
145
- schemaTypeName,
146
- paramsTypeName,
147
- localeTypeName,
148
- localeFallbackConstName,
149
- factoryName,
150
- hasLocaleFallback,
151
- delivery,
152
- localeDeliveryAreaConstName,
153
- loaderStrategy,
154
- } = options;
155
-
156
- const providerTypeArgs = hasLocaleFallback
157
- ? `${schemaTypeName}, ${paramsTypeName}, ${localeTypeName}, typeof ${localeFallbackConstName}`
158
- : `${schemaTypeName}, ${paramsTypeName}`;
159
- const handleReturnType = `I18nHandle<${schemaTypeName}, ${paramsTypeName}, ${localeTypeName}>`;
160
- const handleTypeArgs = `<${schemaTypeName}, ${paramsTypeName}, ${localeTypeName}>`;
161
-
162
- const partitionForLocale =
163
- delivery === "custom"
164
- ? ` partitionForLocale: (locale) => ${localeDeliveryAreaConstName}[locale],\n`
165
- : ` partitionForLocale: (locale) => locale,\n`;
166
-
167
- const optionsType =
168
- loaderStrategy === "fetch"
169
- ? `{ fetchImpl: FetchArtifact; state?: ${STATE_TYPE}; onMissing?: OnMissingTranslation }`
170
- : `{ state?: ${STATE_TYPE}; onMissing?: OnMissingTranslation }`;
171
-
172
- const optionsParam =
173
- loaderStrategy === "fetch" ? ` options: ${optionsType},\n` : ` options?: ${optionsType},\n`;
174
-
175
- const namespaceLoadersLine =
176
- loaderStrategy === "fetch"
177
- ? ` namespaceLoaders: createNamespaceLoaders(fetchImpl),\n`
178
- : ` namespaceLoaders,\n`;
179
-
180
- return (
181
- `export function ${factoryName}(\n` +
182
- optionsParam +
183
- `): ${handleReturnType} {\n` +
184
- formatBody({
185
- providerClass,
186
- providerTypeArgs,
187
- hasLocaleFallback,
188
- localeFallbackConstName,
189
- loaderStrategy,
190
- }) +
191
- ` engine.seedBuilderResources(normalized.resources);\n` +
192
- ` return createI18nHandle${handleTypeArgs}(engine, {\n` +
193
- namespaceLoadersLine +
194
- partitionForLocale +
195
- ` } as I18nHandleOptions<${schemaTypeName}, ${localeTypeName}>);\n` +
196
- `}\n`
197
- );
198
- }
199
-
200
- function formatBody(options: {
201
- providerClass: string;
202
- providerTypeArgs: string;
203
- hasLocaleFallback: boolean;
204
- localeFallbackConstName: string;
205
- loaderStrategy: LoaderStrategy;
206
- }): string {
207
- const {
208
- providerClass,
209
- providerTypeArgs,
210
- hasLocaleFallback,
211
- localeFallbackConstName,
212
- loaderStrategy,
213
- } = options;
214
-
215
- if (loaderStrategy === "fetch") {
216
- const engineBlock = hasLocaleFallback
217
- ? ` const engine = new ${providerClass}<${providerTypeArgs}>(normalized.dictionary, {\n` +
218
- ` localeFallback: ${localeFallbackConstName},\n` +
219
- ` ...providerOptions,\n` +
220
- ` });\n`
221
- : ` const engine = new ${providerClass}<${providerTypeArgs}>(normalized.dictionary, providerOptions);\n`;
222
-
223
- return (
224
- ` const { fetchImpl, state, ...providerOptions } = options;\n` +
225
- ` const normalized = normalizeI18nCreateInput(state);\n` +
226
- engineBlock
227
- );
228
- }
229
-
230
- const engineBlock = hasLocaleFallback
231
- ? ` const engine = new ${providerClass}<${providerTypeArgs}>(normalized.dictionary, {\n` +
232
- ` localeFallback: ${localeFallbackConstName},\n` +
233
- ` ...providerOptions,\n` +
234
- ` });\n`
235
- : ` const engine = new ${providerClass}<${providerTypeArgs}>(normalized.dictionary, providerOptions);\n`;
236
-
237
- return (
238
- ` const { state, ...providerOptions } = options ?? {};\n` +
239
- ` const normalized = normalizeI18nCreateInput(state);\n` +
240
- engineBlock
241
- );
242
- }
243
-
244
- function formatPackageImports(providerClass: string, loaderStrategy: LoaderStrategy): string {
245
- const names = [
246
- providerClass,
247
- "createI18nHandle",
248
- "normalizeI18nCreateInput",
249
- "type I18nHandle",
250
- "type I18nHandleOptions",
251
- "type OnMissingTranslation",
252
- ];
253
- if (loaderStrategy === "fetch") {
254
- names.push("type FetchArtifact");
255
- }
256
- return names.join(",\n ");
257
- }
@@ -1,251 +0,0 @@
1
- import path from "node:path";
2
- import { describe, expect, it } from "vitest";
3
- import { formatNamespaceLoadersFile } from "./namespace-loaders-file.js";
4
-
5
- const projectRoot = "/project";
6
- const loadersOutputPath = path.join(projectRoot, "src/i18n/namespace-loaders.generated.ts");
7
-
8
- describe("formatNamespaceLoadersFile", () => {
9
- it("emits ns(locale) loaders in split mode", () => {
10
- const output = formatNamespaceLoadersFile({
11
- loadersOutputPath,
12
- lazyEntries: [
13
- {
14
- namespace: "billing",
15
- filePath: "src/i18n/translations/billing.json",
16
- absolutePath: path.join(projectRoot, "src/i18n/translations/billing.json"),
17
- },
18
- {
19
- namespace: "default",
20
- filePath: "src/i18n/translations/default.json",
21
- absolutePath: path.join(projectRoot, "src/i18n/translations/default.json"),
22
- },
23
- {
24
- namespace: "user",
25
- filePath: "src/i18n/translations/user.json",
26
- absolutePath: path.join(projectRoot, "src/i18n/translations/user.json"),
27
- },
28
- ],
29
- schemaTypeName: "AppSchema",
30
- localeTypeName: "AppLocale",
31
- typesModule: "i18n-types.generated",
32
- importExtension: "none",
33
- projectRoot,
34
- delivery: "split-by-locale",
35
- requestLocales: ["en", "it", "de-CH"],
36
- splitPathsByNamespace: {
37
- billing: {
38
- en: "src/i18n/generated/translations/billing.en.json",
39
- it: "src/i18n/generated/translations/billing.it.json",
40
- "de-CH": "src/i18n/generated/translations/billing.de-CH.json",
41
- },
42
- default: {
43
- en: "src/i18n/generated/translations/default.en.json",
44
- it: "src/i18n/generated/translations/default.it.json",
45
- "de-CH": "src/i18n/generated/translations/default.de-CH.json",
46
- },
47
- user: {
48
- en: "src/i18n/generated/translations/user.en.json",
49
- it: "src/i18n/generated/translations/user.it.json",
50
- "de-CH": "src/i18n/generated/translations/user.de-CH.json",
51
- },
52
- },
53
- });
54
-
55
- expect(output).toContain(
56
- "import type { AppSchema, LazyNamespace, AppLocale } from './i18n-types.generated';"
57
- );
58
- expect(output).toContain("[K in LazyNamespace]: (locale: AppLocale) => Promise<AppSchema[K]>;");
59
- expect(output).toContain("billing: (locale) => {");
60
- expect(output).toContain('case "en":');
61
- expect(output).toContain('case "it":');
62
- expect(output).toContain('case "de-CH":');
63
- expect(output).toContain(
64
- 'throw new Error(`[i18n] No translation artifact for namespace "billing" and locale "${String(locale)}".`);'
65
- );
66
- expect(output).toContain(
67
- "return import('./generated/translations/billing.en.json').then((m) => m.default);"
68
- );
69
- expect(output).toContain("user: (locale) => {");
70
- expect(output).toContain(
71
- 'export const defaultLazyNamespaces = ["billing", "default", "user"] as const;'
72
- );
73
- expect(output.match(/from '\.\/i18n-types\.generated'/g)?.length).toBe(1);
74
- });
75
-
76
- it("throws when a split path is missing", () => {
77
- expect(() =>
78
- formatNamespaceLoadersFile({
79
- loadersOutputPath,
80
- lazyEntries: [
81
- {
82
- namespace: "billing",
83
- filePath: "src/i18n/translations/billing.json",
84
- absolutePath: path.join(projectRoot, "src/i18n/translations/billing.json"),
85
- },
86
- ],
87
- schemaTypeName: "AppSchema",
88
- localeTypeName: "AppLocale",
89
- typesModule: "i18n-types.generated",
90
- importExtension: "none",
91
- projectRoot,
92
- delivery: "split-by-locale",
93
- requestLocales: ["en", "it"],
94
- splitPathsByNamespace: {
95
- billing: {
96
- en: "src/i18n/generated/translations/billing.en.json",
97
- },
98
- },
99
- })
100
- ).toThrow('[Codegen Error] Missing split path for namespace "billing", locale "it".');
101
- });
102
-
103
- it("emits ns(area) loaders in custom mode", () => {
104
- const output = formatNamespaceLoadersFile({
105
- loadersOutputPath,
106
- lazyEntries: [
107
- {
108
- namespace: "billing",
109
- filePath: "src/i18n/translations/billing.json",
110
- absolutePath: path.join(projectRoot, "src/i18n/translations/billing.json"),
111
- },
112
- {
113
- namespace: "default",
114
- filePath: "src/i18n/translations/default.json",
115
- absolutePath: path.join(projectRoot, "src/i18n/translations/default.json"),
116
- },
117
- ],
118
- schemaTypeName: "AppSchema",
119
- localeTypeName: "AppLocale",
120
- typesModule: "i18n-types.generated",
121
- importExtension: "none",
122
- projectRoot,
123
- delivery: "custom",
124
- deliveryAreaTypeName: "AppDeliveryArea",
125
- deliveryAreaNames: ["eu", "us"],
126
- splitPathsByNamespace: {
127
- billing: {
128
- eu: "src/i18n/generated/translations/billing.eu.json",
129
- us: "src/i18n/generated/translations/billing.us.json",
130
- },
131
- default: {
132
- eu: "src/i18n/generated/translations/default.eu.json",
133
- us: "src/i18n/generated/translations/default.us.json",
134
- },
135
- },
136
- });
137
-
138
- expect(output).toContain(
139
- "import type { AppSchema, LazyNamespace, AppDeliveryArea } from './i18n-types.generated';"
140
- );
141
- expect(output).toContain(
142
- "[K in LazyNamespace]: (area: AppDeliveryArea) => Promise<AppSchema[K]>;"
143
- );
144
- expect(output).toContain("billing: (area) => {");
145
- expect(output).toContain('case "eu":');
146
- expect(output).toContain('case "us":');
147
- expect(output).toContain(
148
- 'throw new Error(`[i18n] No translation artifact for namespace "billing" and area "${String(area)}".`);'
149
- );
150
- expect(output).toContain(
151
- "return import('./generated/translations/billing.eu.json').then((m) => m.default);"
152
- );
153
- expect(output).toContain(
154
- 'export const defaultLazyNamespaces = ["billing", "default"] as const;'
155
- );
156
- });
157
-
158
- it("throws when a custom delivery split path is missing", () => {
159
- expect(() =>
160
- formatNamespaceLoadersFile({
161
- loadersOutputPath,
162
- lazyEntries: [
163
- {
164
- namespace: "billing",
165
- filePath: "src/i18n/translations/billing.json",
166
- absolutePath: path.join(projectRoot, "src/i18n/translations/billing.json"),
167
- },
168
- ],
169
- schemaTypeName: "AppSchema",
170
- localeTypeName: "AppLocale",
171
- typesModule: "i18n-types.generated",
172
- importExtension: "none",
173
- projectRoot,
174
- delivery: "custom",
175
- deliveryAreaTypeName: "AppDeliveryArea",
176
- deliveryAreaNames: ["eu", "us"],
177
- splitPathsByNamespace: {
178
- billing: {
179
- eu: "src/i18n/generated/translations/billing.eu.json",
180
- },
181
- },
182
- })
183
- ).toThrow('[Codegen Error] Missing split path for namespace "billing", area "us".');
184
- });
185
-
186
- it("emits fetch loaders that pass a resource id to fetchImpl", () => {
187
- const output = formatNamespaceLoadersFile({
188
- loadersOutputPath,
189
- lazyEntries: [
190
- {
191
- namespace: "billing",
192
- filePath: "src/i18n/translations/billing.json",
193
- absolutePath: path.join(projectRoot, "src/i18n/translations/billing.json"),
194
- },
195
- ],
196
- schemaTypeName: "AppSchema",
197
- localeTypeName: "AppLocale",
198
- typesModule: "i18n-types.generated",
199
- importExtension: "none",
200
- projectRoot,
201
- delivery: "split-by-locale",
202
- requestLocales: ["en", "it"],
203
- loaderStrategy: "fetch",
204
- splitPathsByNamespace: {
205
- billing: {
206
- en: "src/i18n/generated/translations/billing.en.json",
207
- it: "src/i18n/generated/translations/billing.it.json",
208
- },
209
- },
210
- });
211
-
212
- expect(output).toContain("export function createNamespaceLoaders");
213
- expect(output).toContain("import type { FetchArtifact }");
214
- expect(output).toContain(
215
- 'fetchImpl({ locale, namespace: "billing" }) as Promise<AppSchema["billing"]>'
216
- );
217
- });
218
-
219
- it("emits custom-delivery fetch loaders with locale + area", () => {
220
- const output = formatNamespaceLoadersFile({
221
- loadersOutputPath,
222
- lazyEntries: [
223
- {
224
- namespace: "billing",
225
- filePath: "src/i18n/translations/billing.json",
226
- absolutePath: path.join(projectRoot, "src/i18n/translations/billing.json"),
227
- },
228
- ],
229
- schemaTypeName: "AppSchema",
230
- localeTypeName: "AppLocale",
231
- typesModule: "i18n-types.generated",
232
- importExtension: "none",
233
- projectRoot,
234
- delivery: "custom",
235
- deliveryAreaTypeName: "AppDeliveryArea",
236
- deliveryAreaNames: ["eu", "us"],
237
- loaderStrategy: "fetch",
238
- splitPathsByNamespace: {
239
- billing: {
240
- eu: "src/i18n/generated/translations/billing.eu.json",
241
- us: "src/i18n/generated/translations/billing.us.json",
242
- },
243
- },
244
- });
245
-
246
- expect(output).toContain("(area, { locale }) =>");
247
- expect(output).toContain(
248
- 'fetchImpl({ locale, namespace: "billing", area }) as Promise<AppSchema["billing"]>'
249
- );
250
- });
251
- });