@xndrjs/i18n 0.7.0 → 0.8.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.
- package/README.md +67 -872
- package/dist/codegen/index.d.ts +117 -51
- package/dist/codegen/index.js +1585 -93
- package/dist/codegen/index.js.map +1 -1
- package/dist/index.d.ts +100 -234
- package/dist/index.js +74 -638
- package/dist/index.js.map +1 -1
- package/dist/validation/index.d.ts +5 -0
- package/dist/validation/index.js.map +1 -1
- package/package.json +2 -2
- package/src/IcuTranslationProviderMulti.test.ts +18 -40
- package/src/IcuTranslationProviderMulti.ts +27 -37
- package/src/audit/audit-dictionaries.ts +1 -1
- package/src/audit/run-audit.test.ts +6 -7
- package/src/builder-load-registry.ts +26 -5
- package/src/builder-loaders.ts +8 -11
- package/src/builder-types.test.ts +11 -42
- package/src/builder.test.ts +82 -243
- package/src/builder.ts +8 -110
- package/src/codegen/codegen-config-schema.ts +82 -77
- package/src/codegen/config.test.ts +55 -143
- package/src/codegen/config.ts +10 -67
- package/src/codegen/dictionary-spec-contract.test.ts +28 -0
- package/src/codegen/dictionary-spec-contract.ts +138 -0
- package/src/codegen/emit/dictionary-schema-file.ts +7 -43
- package/src/codegen/emit/instance-file.test.ts +35 -52
- package/src/codegen/emit/instance-file.ts +170 -268
- package/src/codegen/emit/namespace-loaders-file.test.ts +72 -74
- package/src/codegen/emit/namespace-loaders-file.ts +147 -90
- package/src/codegen/emit/types-file.test.ts +20 -41
- package/src/codegen/emit/types-file.ts +48 -74
- package/src/codegen/generate-i18n-types.test.ts +163 -492
- package/src/codegen/generate-i18n-types.ts +7 -269
- package/src/codegen/paths.ts +0 -14
- package/src/codegen/project-locales-set-namespace.test.ts +44 -86
- package/src/codegen/read-dictionary.test.ts +27 -9
- package/src/codegen/read-dictionary.ts +18 -40
- package/src/codegen/regenerate-namespaces.ts +180 -0
- package/src/codegen/run-codegen.test.ts +230 -0
- package/src/codegen/run-codegen.ts +252 -0
- package/src/codegen/types.ts +0 -6
- package/src/codegen-config/build-config.ts +4 -23
- package/src/codegen-config/codegen-config.test.ts +10 -6
- package/src/codegen-config/index.ts +18 -3
- package/src/engine.ts +3 -27
- package/src/fetch-artifact.ts +16 -0
- package/src/i18n-handle.ts +202 -0
- package/src/index.ts +15 -34
- package/src/project-locales.ts +2 -2
- package/src/scope-multi.ts +1 -20
- package/src/scope-types.ts +14 -6
- package/src/scope.test.ts +3 -312
- package/src/serialized-state.test.ts +114 -0
- package/src/serialized-state.ts +28 -0
- package/src/setup/setup-i18n.test.ts +22 -33
- package/src/setup/setup-i18n.ts +22 -27
- package/src/types.ts +3 -3
- package/src/validation/index.ts +4 -0
- package/src/IcuTranslationProviderSingle.test.ts +0 -177
- package/src/IcuTranslationProviderSingle.ts +0 -114
- package/src/builder-multi.ts +0 -481
- package/src/codegen/emit/dictionary-file.test.ts +0 -215
- package/src/codegen/emit/dictionary-file.ts +0 -244
- package/src/deep-freeze.test.ts +0 -40
- package/src/deep-freeze.ts +0 -22
- package/src/patch-key.test.ts +0 -186
- package/src/patch-key.ts +0 -140
- package/src/scope-single.ts +0 -85
- package/src/single-builder.ts +0 -153
|
@@ -8,27 +8,19 @@ import { GENERATED_FILE_BANNER } from "../paths.js";
|
|
|
8
8
|
import type { NamespaceEntry } from "../types.js";
|
|
9
9
|
|
|
10
10
|
/**
|
|
11
|
-
* Emits
|
|
12
|
-
*
|
|
11
|
+
* Emits lazy-load type aliases. Every namespace is lazy; `InitialSchema` is empty
|
|
12
|
+
* (cold start / hydrate via `resources` only).
|
|
13
13
|
*/
|
|
14
|
-
export function formatLazyTypesBlock(
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
): string {
|
|
19
|
-
const loadOnInitUnion =
|
|
20
|
-
loadOnInitSet.size > 0
|
|
21
|
-
? [...loadOnInitSet]
|
|
22
|
-
.sort()
|
|
23
|
-
.map((namespace) => `'${namespace}'`)
|
|
24
|
-
.join(" | ")
|
|
14
|
+
export function formatLazyTypesBlock(lazyEntries: NamespaceEntry[]): string {
|
|
15
|
+
const lazyUnion =
|
|
16
|
+
lazyEntries.length > 0
|
|
17
|
+
? lazyEntries.map((entry) => `'${entry.namespace}'`).join(" | ")
|
|
25
18
|
: "never";
|
|
26
|
-
const lazyUnion = lazyEntries.map((entry) => `'${entry.namespace}'`).join(" | ");
|
|
27
19
|
|
|
28
20
|
return (
|
|
29
|
-
`export type LoadOnInitNamespace = ${loadOnInitUnion};\n` +
|
|
30
21
|
`export type LazyNamespace = ${lazyUnion};\n` +
|
|
31
|
-
|
|
22
|
+
`/** Empty cold-start schema — namespaces arrive via \`namespaceLoaders\`. */\n` +
|
|
23
|
+
`export type InitialSchema = Record<string, never>;\n\n`
|
|
32
24
|
);
|
|
33
25
|
}
|
|
34
26
|
|
|
@@ -40,7 +32,6 @@ export function formatLocaleTemplateType(localeTypeName: string, hasLocaleUnion:
|
|
|
40
32
|
}
|
|
41
33
|
|
|
42
34
|
export interface TypesFileOptions {
|
|
43
|
-
isSingle: boolean;
|
|
44
35
|
entries: NamespaceEntry[];
|
|
45
36
|
projectRoot: string;
|
|
46
37
|
typesOutputPath: string;
|
|
@@ -51,19 +42,18 @@ export interface TypesFileOptions {
|
|
|
51
42
|
localeFallbackTypeName: string;
|
|
52
43
|
localeFallback?: Record<string, string | null> | undefined;
|
|
53
44
|
paramsByNamespace: Record<string, Record<string, string>>;
|
|
54
|
-
|
|
45
|
+
/** Sorted request locales — emits `ProjectLocales` const + `ProjectLocale` type. */
|
|
46
|
+
requestLocales: readonly string[];
|
|
55
47
|
deliveryAreaTypeName?: string;
|
|
56
|
-
|
|
48
|
+
/** Sorted delivery area names — emits `ProjectDeliveryAreas` const + type. */
|
|
49
|
+
deliveryAreaNames?: readonly string[];
|
|
57
50
|
deliveryArtifacts?: DeliveryArtifactsMap;
|
|
58
51
|
localeDeliveryAreaConstName?: string;
|
|
59
|
-
hasLazy: boolean;
|
|
60
|
-
loadOnInitSet: Set<string>;
|
|
61
52
|
lazyEntries: NamespaceEntry[];
|
|
62
53
|
}
|
|
63
54
|
|
|
64
55
|
export function formatTypesFile(options: TypesFileOptions): string {
|
|
65
56
|
const {
|
|
66
|
-
isSingle,
|
|
67
57
|
entries,
|
|
68
58
|
paramsTypeName,
|
|
69
59
|
schemaTypeName,
|
|
@@ -72,27 +62,32 @@ export function formatTypesFile(options: TypesFileOptions): string {
|
|
|
72
62
|
localeFallbackTypeName,
|
|
73
63
|
localeFallback,
|
|
74
64
|
paramsByNamespace,
|
|
75
|
-
|
|
65
|
+
requestLocales,
|
|
76
66
|
deliveryAreaTypeName,
|
|
77
|
-
|
|
67
|
+
deliveryAreaNames,
|
|
78
68
|
deliveryArtifacts,
|
|
79
69
|
localeDeliveryAreaConstName = "LOCALE_DELIVERY_AREA",
|
|
80
|
-
hasLazy,
|
|
81
|
-
loadOnInitSet,
|
|
82
70
|
lazyEntries,
|
|
83
71
|
} = options;
|
|
84
72
|
|
|
85
|
-
const hasLocaleUnion =
|
|
73
|
+
const hasLocaleUnion = requestLocales.length > 0;
|
|
86
74
|
const localeTemplateType = formatLocaleTemplateType(localeTypeName, hasLocaleUnion);
|
|
75
|
+
const localesConstName = `${localeTypeName}s`;
|
|
87
76
|
|
|
88
|
-
const localeBlock =
|
|
77
|
+
const localeBlock = hasLocaleUnion
|
|
89
78
|
? `${localeFallback ? formatLocaleFallbackBlock(localeFallback, localeFallbackConstName, localeFallbackTypeName) : ""}` +
|
|
90
|
-
`export
|
|
79
|
+
`export const ${localesConstName} = [${requestLocales.map((locale) => JSON.stringify(locale)).join(", ")}] as const;\n` +
|
|
80
|
+
`export type ${localeTypeName} = (typeof ${localesConstName})[number];\n\n`
|
|
91
81
|
: "";
|
|
92
82
|
|
|
83
|
+
const deliveryAreasConstName = deliveryAreaTypeName ? `${deliveryAreaTypeName}s` : undefined;
|
|
93
84
|
const deliveryAreaBlock =
|
|
94
|
-
deliveryAreaTypeName &&
|
|
95
|
-
|
|
85
|
+
deliveryAreaTypeName &&
|
|
86
|
+
deliveryAreasConstName &&
|
|
87
|
+
deliveryAreaNames &&
|
|
88
|
+
deliveryAreaNames.length > 0
|
|
89
|
+
? `export const ${deliveryAreasConstName} = [${deliveryAreaNames.map((area) => JSON.stringify(area)).join(", ")}] as const;\n` +
|
|
90
|
+
`export type ${deliveryAreaTypeName} = (typeof ${deliveryAreasConstName})[number];\n\n` +
|
|
96
91
|
(deliveryArtifacts
|
|
97
92
|
? formatDeliveryArtifactsBlock(
|
|
98
93
|
deliveryArtifacts,
|
|
@@ -109,56 +104,35 @@ export function formatTypesFile(options: TypesFileOptions): string {
|
|
|
109
104
|
: "")
|
|
110
105
|
: "";
|
|
111
106
|
|
|
112
|
-
|
|
113
|
-
|
|
107
|
+
const namespaceBlocks = entries
|
|
108
|
+
.map((entry) => {
|
|
109
|
+
const keyTypes = paramsByNamespace[entry.namespace] ?? {};
|
|
110
|
+
const lines = Object.entries(keyTypes)
|
|
111
|
+
.map(([key, type]) => ` ${key}: ${type};`)
|
|
112
|
+
.join("\n");
|
|
113
|
+
return ` ${entry.namespace}: {\n${lines}\n };`;
|
|
114
|
+
})
|
|
115
|
+
.join("\n");
|
|
114
116
|
|
|
115
|
-
|
|
116
|
-
const onlyNamespace = entries[0]!.namespace;
|
|
117
|
-
const keyTypes = paramsByNamespace[onlyNamespace] ?? {};
|
|
118
|
-
const paramsLines = Object.entries(keyTypes)
|
|
119
|
-
.map(([key, type]) => ` ${key}: ${type};`)
|
|
120
|
-
.join("\n");
|
|
117
|
+
const paramsBlock = `export type ${paramsTypeName} = {\n${namespaceBlocks}\n};`;
|
|
121
118
|
|
|
122
|
-
|
|
119
|
+
const schemaLines = entries
|
|
120
|
+
.map((entry) => {
|
|
121
|
+
const keyTypes = paramsByNamespace[entry.namespace] ?? {};
|
|
122
|
+
const lines = Object.keys(keyTypes)
|
|
123
|
+
.map((key) => ` ${key}: ${localeTemplateType};`)
|
|
124
|
+
.join("\n");
|
|
125
|
+
return ` ${entry.namespace}: {\n${lines}\n };`;
|
|
126
|
+
})
|
|
127
|
+
.join("\n");
|
|
123
128
|
|
|
124
|
-
|
|
125
|
-
.map((key) => ` ${key}: ${localeTemplateType};`)
|
|
126
|
-
.join("\n");
|
|
129
|
+
const schemaBlock = `export type ${schemaTypeName} = {\n${schemaLines}\n};`;
|
|
127
130
|
|
|
128
|
-
|
|
129
|
-
} else {
|
|
130
|
-
const namespaceBlocks = entries
|
|
131
|
-
.map((entry) => {
|
|
132
|
-
const keyTypes = paramsByNamespace[entry.namespace] ?? {};
|
|
133
|
-
const lines = Object.entries(keyTypes)
|
|
134
|
-
.map(([key, type]) => ` ${key}: ${type};`)
|
|
135
|
-
.join("\n");
|
|
136
|
-
return ` ${entry.namespace}: {\n${lines}\n };`;
|
|
137
|
-
})
|
|
138
|
-
.join("\n");
|
|
139
|
-
|
|
140
|
-
paramsBlock = `export type ${paramsTypeName} = {\n${namespaceBlocks}\n};`;
|
|
141
|
-
|
|
142
|
-
const schemaLines = entries
|
|
143
|
-
.map((entry) => {
|
|
144
|
-
const keyTypes = paramsByNamespace[entry.namespace] ?? {};
|
|
145
|
-
const lines = Object.keys(keyTypes)
|
|
146
|
-
.map((key) => ` ${key}: ${localeTemplateType};`)
|
|
147
|
-
.join("\n");
|
|
148
|
-
return ` ${entry.namespace}: {\n${lines}\n };`;
|
|
149
|
-
})
|
|
150
|
-
.join("\n");
|
|
151
|
-
|
|
152
|
-
schemaBlock = `export type ${schemaTypeName} = {\n${schemaLines}\n};`;
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
const lazyTypesBlock = hasLazy
|
|
156
|
-
? formatLazyTypesBlock(loadOnInitSet, lazyEntries, schemaTypeName)
|
|
157
|
-
: "";
|
|
131
|
+
const lazyTypesBlock = formatLazyTypesBlock(lazyEntries);
|
|
158
132
|
|
|
159
133
|
return (
|
|
160
134
|
`${GENERATED_FILE_BANNER}` +
|
|
161
|
-
`export const I18N_MODE = '
|
|
135
|
+
`export const I18N_MODE = 'multi' as const;\n\n` +
|
|
162
136
|
`${localeBlock}` +
|
|
163
137
|
`${deliveryAreaBlock}` +
|
|
164
138
|
`${paramsBlock}\n\n` +
|