@xndrjs/i18n 0.3.3 → 0.5.0-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.
- package/README.md +193 -44
- package/dist/codegen/index.d.ts +85 -0
- package/dist/codegen/index.js +181 -0
- package/dist/codegen/index.js.map +1 -0
- package/dist/index.d.ts +34 -18
- package/dist/index.js +174 -145
- package/dist/index.js.map +1 -1
- package/dist/validation/index.d.ts +86 -4
- package/dist/validation/index.js.map +1 -1
- package/package.json +6 -1
- package/src/IcuTranslationProviderMulti.test.ts +48 -1
- package/src/IcuTranslationProviderMulti.ts +41 -61
- package/src/IcuTranslationProviderSingle.test.ts +67 -0
- package/src/IcuTranslationProviderSingle.ts +27 -51
- package/src/audit/audit-dictionaries.ts +4 -1
- package/src/audit/run-audit.test.ts +35 -1
- package/src/audit/run-audit.ts +15 -7
- package/src/codegen/codegen-config-schema.ts +68 -1
- package/src/codegen/config.test.ts +174 -39
- package/src/codegen/config.ts +14 -5
- package/src/codegen/constants.ts +8 -0
- package/src/codegen/delivery-artifacts.test.ts +142 -0
- package/src/codegen/delivery-artifacts.ts +124 -0
- package/src/codegen/emit/dictionary-file.test.ts +190 -0
- package/src/codegen/emit/dictionary-file.ts +165 -2
- package/src/codegen/emit/dictionary-schema-file.ts +5 -0
- package/src/codegen/emit/instance-file.ts +119 -38
- package/src/codegen/emit/namespace-loaders-file.test.ts +176 -0
- package/src/codegen/emit/namespace-loaders-file.ts +118 -32
- package/src/codegen/emit/types-file.test.ts +114 -0
- package/src/codegen/emit/types-file.ts +48 -11
- package/src/codegen/generate-i18n-types.test.ts +765 -22
- package/src/codegen/generate-i18n-types.ts +111 -58
- package/src/codegen/icu-analysis.ts +9 -2
- package/src/codegen/locale-fallback.ts +19 -10
- package/src/codegen/locale-policy.ts +4 -0
- package/src/codegen/paths.ts +9 -5
- package/src/codegen/project-locales-set-namespace.test.ts +11 -9
- package/src/codegen/read-dictionary.test.ts +474 -2
- package/src/codegen/read-dictionary.ts +164 -15
- package/src/codegen/write-file-if-changed.test.ts +42 -0
- package/src/codegen/write-file-if-changed.ts +20 -0
- package/src/codegen-config/build-config.ts +34 -0
- package/src/codegen-config/codegen-config.test.ts +32 -0
- package/src/codegen-config/index.ts +21 -0
- package/src/codegen-config/write-config.ts +8 -0
- package/src/deep-freeze.test.ts +13 -0
- package/src/deep-freeze.ts +5 -0
- package/src/format-core.ts +91 -0
- package/src/index.ts +8 -5
- package/src/project-locales.test.ts +129 -10
- package/src/project-locales.ts +90 -3
- package/src/setup/setup-i18n.test.ts +1 -1
- package/src/setup/setup-i18n.ts +9 -32
- package/src/types.ts +19 -4
- package/src/validation/normalize.ts +4 -0
- package/dist/types-C1CpXVOJ.d.ts +0 -83
- package/src/ensure-namespace.integration.test.ts +0 -66
- package/src/ensure-namespace.test.ts +0 -125
- package/src/ensure-namespace.ts +0 -70
- /package/src/{setup → codegen-config}/type-names.ts +0 -0
|
@@ -1,8 +1,90 @@
|
|
|
1
|
-
import {
|
|
2
|
-
export { d as NormalizedKeyDictionary, e as NormalizedMultiDictionary, P as ParsedKeyEntry, f as ParsedLocaleEntry, g as VariableType, h as extractVariables, m as mergeVariableSpecs, v as variableSpecsEqual } from '../types-C1CpXVOJ.js';
|
|
1
|
+
import { parse } from '@formatjs/icu-messageformat-parser';
|
|
3
2
|
import { z } from 'zod';
|
|
4
|
-
import '@formatjs/icu-messageformat-parser';
|
|
5
3
|
|
|
4
|
+
type VariableType = "string" | "number" | "date";
|
|
5
|
+
type VariableSpec = Record<string, VariableType>;
|
|
6
|
+
type VariableRole = "simple" | "plural" | "selectordinal" | "select" | "number" | "date" | "time";
|
|
7
|
+
type VariableMeta = {
|
|
8
|
+
type: VariableType;
|
|
9
|
+
roles: Set<VariableRole>;
|
|
10
|
+
};
|
|
11
|
+
type VariableMetaSpec = Record<string, VariableMeta>;
|
|
12
|
+
type IcuAst = ReturnType<typeof parse>;
|
|
13
|
+
declare function extractVariables(nodes: IcuAst): VariableSpec;
|
|
14
|
+
declare function mergeVariableSpecs(target: VariableSpec, source: VariableSpec): VariableSpec;
|
|
15
|
+
declare function variableSpecsEqual(a: VariableSpec, b: VariableSpec): boolean;
|
|
16
|
+
|
|
17
|
+
type ParsedLocaleEntry = {
|
|
18
|
+
readonly template: string;
|
|
19
|
+
readonly args: VariableSpec;
|
|
20
|
+
};
|
|
21
|
+
type ParsedKeyEntry = {
|
|
22
|
+
readonly locales: Readonly<Record<string, ParsedLocaleEntry>>;
|
|
23
|
+
readonly mergedArgs: VariableSpec;
|
|
24
|
+
};
|
|
25
|
+
type NormalizedKeyDictionary = Readonly<Record<string, ParsedKeyEntry>>;
|
|
26
|
+
type NormalizedMultiDictionary = Readonly<Record<string, NormalizedKeyDictionary>>;
|
|
27
|
+
type NormalizedDictionary = {
|
|
28
|
+
readonly mode: "single";
|
|
29
|
+
readonly keys: NormalizedKeyDictionary;
|
|
30
|
+
} | {
|
|
31
|
+
readonly mode: "multi";
|
|
32
|
+
readonly namespaces: NormalizedMultiDictionary;
|
|
33
|
+
};
|
|
34
|
+
type DictionarySpec = {
|
|
35
|
+
readonly mode: "single";
|
|
36
|
+
readonly requiredKeys: readonly string[];
|
|
37
|
+
readonly argsByKey: Readonly<Record<string, VariableSpec>>;
|
|
38
|
+
} | {
|
|
39
|
+
readonly mode: "multi";
|
|
40
|
+
readonly requiredKeys: Readonly<Record<string, readonly string[]>>;
|
|
41
|
+
readonly argsByKey: Readonly<Record<string, Readonly<Record<string, VariableSpec>>>>;
|
|
42
|
+
};
|
|
43
|
+
type ValidationIssue = {
|
|
44
|
+
readonly kind: "invalid_input";
|
|
45
|
+
readonly message: string;
|
|
46
|
+
} | {
|
|
47
|
+
readonly kind: "missing_key";
|
|
48
|
+
readonly path: readonly string[];
|
|
49
|
+
} | {
|
|
50
|
+
readonly kind: "invalid_locale_value";
|
|
51
|
+
readonly path: readonly string[];
|
|
52
|
+
readonly message: string;
|
|
53
|
+
} | {
|
|
54
|
+
readonly kind: "icu_syntax_error";
|
|
55
|
+
readonly path: readonly string[];
|
|
56
|
+
readonly message: string;
|
|
57
|
+
} | {
|
|
58
|
+
readonly kind: "locale_args_mismatch";
|
|
59
|
+
readonly path: readonly string[];
|
|
60
|
+
readonly locales: Readonly<Record<string, VariableSpec>>;
|
|
61
|
+
readonly message: string;
|
|
62
|
+
} | {
|
|
63
|
+
readonly kind: "variable_mismatch";
|
|
64
|
+
readonly path: readonly string[];
|
|
65
|
+
readonly expected: VariableSpec;
|
|
66
|
+
readonly found: VariableSpec;
|
|
67
|
+
readonly message: string;
|
|
68
|
+
} | {
|
|
69
|
+
readonly kind: "variable_type_mismatch";
|
|
70
|
+
readonly path: readonly string[];
|
|
71
|
+
readonly variable: string;
|
|
72
|
+
readonly expected: VariableType;
|
|
73
|
+
readonly found: VariableType;
|
|
74
|
+
readonly message: string;
|
|
75
|
+
};
|
|
76
|
+
type ValidationResult<T> = {
|
|
77
|
+
readonly ok: true;
|
|
78
|
+
readonly data: T;
|
|
79
|
+
} | {
|
|
80
|
+
readonly ok: false;
|
|
81
|
+
readonly issues: readonly ValidationIssue[];
|
|
82
|
+
};
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Validation step 1: coerce external input into a normalized dictionary shape
|
|
86
|
+
* (keys, locales, ICU args) against a `DictionarySpec`.
|
|
87
|
+
*/
|
|
6
88
|
declare function normalizeDictionary(input: unknown, spec: DictionarySpec): ValidationResult<NormalizedDictionary>;
|
|
7
89
|
|
|
8
90
|
type LocaleDictionary = Record<string, string>;
|
|
@@ -42,4 +124,4 @@ declare function parseTemplate(template: string): ParseTemplateResult;
|
|
|
42
124
|
declare function validateExternalDictionary<TSchema>(input: unknown, spec: DictionarySpec): ValidationResult<TSchema>;
|
|
43
125
|
declare function validateExternalNamespace<TNamespaceSchema>(namespace: string, input: unknown, spec: DictionarySpec): ValidationResult<TNamespaceSchema>;
|
|
44
126
|
|
|
45
|
-
export { DictionarySpec, DictionaryValidationError, NormalizedDictionary, type ParseTemplateResult, ValidationIssue, ValidationResult, VariableSpec, assertValidDictionary, createArgsSchema, createNormalizedDictionarySchema, formatIssues, normalizeDictionary, parseTemplate, toDictionary, toNamespaceDictionary, validateExternalDictionary, validateExternalNamespace, validateNormalizedDictionary };
|
|
127
|
+
export { type DictionarySpec, DictionaryValidationError, type NormalizedDictionary, type NormalizedKeyDictionary, type NormalizedMultiDictionary, type ParseTemplateResult, type ParsedKeyEntry, type ParsedLocaleEntry, type ValidationIssue, type ValidationResult, type VariableSpec, type VariableType, assertValidDictionary, createArgsSchema, createNormalizedDictionarySchema, extractVariables, formatIssues, mergeVariableSpecs, normalizeDictionary, parseTemplate, toDictionary, toNamespaceDictionary, validateExternalDictionary, validateExternalNamespace, validateNormalizedDictionary, variableSpecsEqual };
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../../src/icu/extract-variables.ts","../../src/icu/parse-template.ts","../../src/validation/normalize.ts","../../src/validation/to-dictionary.ts","../../src/validation/create-args-schema.ts","../../src/validation/create-normalized-schema.ts","../../src/validation/validate-normalized.ts","../../src/validation/errors.ts","../../src/validation/index.ts"],"names":["dictionary","z","key"],"mappings":"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","file":"index.js","sourcesContent":["import type { parse } from \"@formatjs/icu-messageformat-parser\";\n\nexport type VariableType = \"string\" | \"number\" | \"date\";\nexport type VariableSpec = Record<string, VariableType>;\n\nexport type VariableRole =\n | \"simple\"\n | \"plural\"\n | \"selectordinal\"\n | \"select\"\n | \"number\"\n | \"date\"\n | \"time\";\n\nexport type VariableMeta = {\n type: VariableType;\n roles: Set<VariableRole>;\n};\n\nexport type VariableMetaSpec = Record<string, VariableMeta>;\n\ntype IcuAst = ReturnType<typeof parse>;\ntype IcuNode = IcuAst[number];\n\nfunction isPluralOrOrdinalNode(node: IcuNode): node is Extract<IcuNode, { type: 6 }> {\n return node.type === 6 && \"pluralType\" in node && Boolean(node.pluralType);\n}\n\nfunction hasVariableName(node: IcuNode): node is Extract<IcuNode, { value: string }> {\n return \"value\" in node && typeof node.value === \"string\";\n}\n\nfunction addVariableMeta(\n variables: VariableMetaSpec,\n name: string,\n type: VariableType,\n role: VariableRole\n): void {\n const existing = variables[name];\n if (!existing) {\n variables[name] = { type, roles: new Set([role]) };\n return;\n }\n\n existing.roles.add(role);\n existing.type = mergeVariableTypes(existing.type, type);\n}\n\nfunction mergeVariableTypes(left: VariableType, right: VariableType): VariableType {\n if (left === right) {\n return left;\n }\n\n if ((left === \"string\" && right === \"number\") || (left === \"number\" && right === \"string\")) {\n return \"number\";\n }\n\n return right;\n}\n\nexport function extractVariableMeta(nodes: IcuAst): VariableMetaSpec {\n const variables: VariableMetaSpec = {};\n\n const walk = (walkNodes: IcuAst) => {\n for (const node of walkNodes) {\n if (node.type === 1 && hasVariableName(node)) {\n addVariableMeta(variables, node.value, \"string\", \"simple\");\n } else if (node.type === 2 && hasVariableName(node)) {\n addVariableMeta(variables, node.value, \"number\", \"number\");\n } else if (isPluralOrOrdinalNode(node) && hasVariableName(node)) {\n const role = node.pluralType === \"ordinal\" ? \"selectordinal\" : \"plural\";\n addVariableMeta(variables, node.value, \"number\", role);\n } else if (node.type === 3 && hasVariableName(node)) {\n addVariableMeta(variables, node.value, \"date\", \"date\");\n } else if (node.type === 4 && hasVariableName(node)) {\n addVariableMeta(variables, node.value, \"date\", \"time\");\n } else if (node.type === 5 && hasVariableName(node)) {\n addVariableMeta(variables, node.value, \"string\", \"select\");\n }\n\n if (\"options\" in node && node.options) {\n for (const option of Object.values(node.options)) {\n walk(option.value);\n }\n }\n\n if (\"children\" in node && Array.isArray(node.children)) {\n walk(node.children);\n }\n }\n };\n\n walk(nodes);\n return variables;\n}\n\nexport function variableMetaToSpec(meta: VariableMetaSpec): VariableSpec {\n return Object.fromEntries(Object.entries(meta).map(([name, entry]) => [name, entry.type]));\n}\n\nexport function extractVariables(nodes: IcuAst): VariableSpec {\n return variableMetaToSpec(extractVariableMeta(nodes));\n}\n\nexport function inferMergedVariableType(roles: Set<VariableRole>): VariableType | \"CONFLICT\" {\n const hasPlural = roles.has(\"plural\");\n const hasSelectordinal = roles.has(\"selectordinal\");\n const hasSelect = roles.has(\"select\");\n const hasSimple = roles.has(\"simple\");\n const hasNumber = roles.has(\"number\");\n const hasDate = roles.has(\"date\");\n const hasTime = roles.has(\"time\");\n\n // Incompatible numeric ICU constructs on the same variable.\n if (hasPlural && hasSelectordinal) {\n return \"CONFLICT\";\n }\n\n // Select (string-family) vs plural / ordinal / number-format (number-family).\n if (hasSelect && (hasPlural || hasSelectordinal || hasNumber)) {\n return \"CONFLICT\";\n }\n\n // Legacy explicit pairs — covered by the rule above, kept for clarity.\n if (hasPlural && hasSelect) {\n return \"CONFLICT\";\n }\n\n if (hasSelectordinal && hasSelect) {\n return \"CONFLICT\";\n }\n\n if (hasDate || hasTime) {\n if (hasPlural || hasSelect || hasSelectordinal || hasSimple || hasNumber) {\n return \"CONFLICT\";\n }\n return \"date\";\n }\n\n if (hasPlural || hasSelectordinal || hasNumber) {\n return \"number\";\n }\n\n if (hasSelect || hasSimple) {\n return \"string\";\n }\n\n return \"string\";\n}\n\nexport function mergeVariableMetaAcrossLocales(\n localeMetas: readonly VariableMetaSpec[]\n): { ok: true; merged: VariableSpec } | { ok: false; message: string } {\n const keySignatures = localeMetas.map((meta) => Object.keys(meta).sort().join(\",\"));\n if (new Set(keySignatures).size > 1) {\n return {\n ok: false,\n message: `Inconsistent ICU variable names across locales (keys: ${keySignatures.join(\" vs \")})`,\n };\n }\n\n const merged: VariableSpec = {};\n const variableNames = new Set(localeMetas.flatMap((meta) => Object.keys(meta)));\n\n for (const variableName of variableNames) {\n const combinedRoles = new Set<VariableRole>();\n\n for (const meta of localeMetas) {\n for (const role of meta[variableName]?.roles ?? []) {\n combinedRoles.add(role);\n }\n }\n\n const mergedType = inferMergedVariableType(combinedRoles);\n if (mergedType === \"CONFLICT\") {\n const rolesByLocale = localeMetas\n .map((meta) => {\n const entry = meta[variableName];\n if (!entry) {\n return null;\n }\n return [...entry.roles].sort().join(\"|\");\n })\n .filter((value): value is string => value !== null);\n\n return {\n ok: false,\n message: `Incompatible ICU variable \"${variableName}\" across locales (roles: ${rolesByLocale.join(\" vs \")})`,\n };\n }\n\n merged[variableName] = mergedType;\n }\n\n return { ok: true, merged };\n}\n\nexport function mergeVariableSpecs(target: VariableSpec, source: VariableSpec): VariableSpec {\n const merged = { ...target };\n\n for (const [varName, varType] of Object.entries(source)) {\n const existing = merged[varName];\n if (existing && existing !== varType) {\n merged[varName] = \"number\";\n } else {\n merged[varName] = varType;\n }\n }\n\n return merged;\n}\n\nexport function variableSpecsEqual(a: VariableSpec, b: VariableSpec): boolean {\n const aKeys = Object.keys(a).sort();\n const bKeys = Object.keys(b).sort();\n\n if (aKeys.length !== bKeys.length) {\n return false;\n }\n\n return aKeys.every((key, index) => {\n if (key !== bKeys[index]) {\n return false;\n }\n return a[key] === b[key];\n });\n}\n","import { parse } from \"@formatjs/icu-messageformat-parser\";\nimport {\n extractVariableMeta,\n variableMetaToSpec,\n type VariableMetaSpec,\n type VariableSpec,\n} from \"./extract-variables.js\";\n\nexport type ParseTemplateSuccess = {\n readonly ok: true;\n readonly args: VariableSpec;\n readonly meta: VariableMetaSpec;\n};\n\nexport type ParseTemplateFailure = {\n readonly ok: false;\n readonly message: string;\n};\n\nexport type ParseTemplateResult = ParseTemplateSuccess | ParseTemplateFailure;\n\nexport function parseTemplate(template: string): ParseTemplateResult {\n try {\n const ast = parse(template);\n const meta = extractVariableMeta(ast);\n return { ok: true, args: variableMetaToSpec(meta), meta };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return { ok: false, message };\n }\n}\n","import { mergeVariableMetaAcrossLocales, type VariableMetaSpec } from \"../icu/extract-variables.js\";\nimport { parseTemplate } from \"../icu/parse-template.js\";\nimport type {\n DictionarySpec,\n NormalizedDictionary,\n NormalizedKeyDictionary,\n ParsedKeyEntry,\n ValidationIssue,\n ValidationResult,\n} from \"./types.js\";\n\nfunction failure(issues: ValidationIssue[]): ValidationResult<NormalizedDictionary> {\n return { ok: false, issues };\n}\n\nfunction success(data: NormalizedDictionary): ValidationResult<NormalizedDictionary> {\n return { ok: true, data };\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction normalizeKeyDictionary(\n input: Record<string, unknown>,\n requiredKeys: readonly string[],\n keyPathPrefix: readonly string[]\n): ValidationResult<NormalizedKeyDictionary> {\n const issues: ValidationIssue[] = [];\n const keys: Record<string, ParsedKeyEntry> = {};\n\n for (const key of requiredKeys) {\n if (!(key in input)) {\n issues.push({ kind: \"missing_key\", path: [...keyPathPrefix, key] });\n continue;\n }\n\n const keyValue = input[key];\n if (!isPlainObject(keyValue)) {\n issues.push({\n kind: \"invalid_input\",\n message: `Expected object for key \"${key}\", got ${typeof keyValue}`,\n });\n continue;\n }\n\n const locales: Record<string, ParsedKeyEntry[\"locales\"][string]> = {};\n const localeMetas: VariableMetaSpec[] = [];\n let mergedArgs: ParsedKeyEntry[\"mergedArgs\"] = {};\n let localeArgsMismatch: ValidationIssue | undefined;\n\n for (const [locale, template] of Object.entries(keyValue)) {\n const localePath = [...keyPathPrefix, key, locale];\n\n if (typeof template !== \"string\") {\n issues.push({\n kind: \"invalid_locale_value\",\n path: localePath,\n message: `expected string, got ${typeof template}`,\n });\n continue;\n }\n\n const parsed = parseTemplate(template);\n if (!parsed.ok) {\n issues.push({\n kind: \"icu_syntax_error\",\n path: localePath,\n message: parsed.message,\n });\n continue;\n }\n\n locales[locale] = { template, args: parsed.args };\n localeMetas.push(parsed.meta);\n }\n\n if (localeMetas.length > 0) {\n const merged = mergeVariableMetaAcrossLocales(localeMetas);\n if (!merged.ok) {\n const localeArgs: Record<string, ParsedKeyEntry[\"mergedArgs\"]> = {};\n for (const [loc, entry] of Object.entries(locales)) {\n localeArgs[loc] = entry.args;\n }\n localeArgsMismatch = {\n kind: \"locale_args_mismatch\",\n path: [...keyPathPrefix, key],\n locales: localeArgs,\n message: merged.message,\n };\n } else {\n mergedArgs = merged.merged;\n }\n }\n\n if (localeArgsMismatch) {\n issues.push(localeArgsMismatch);\n }\n\n keys[key] = { locales, mergedArgs };\n }\n\n if (issues.length > 0) {\n return { ok: false, issues };\n }\n\n return { ok: true, data: keys };\n}\n\nexport function normalizeDictionary(\n input: unknown,\n spec: DictionarySpec\n): ValidationResult<NormalizedDictionary> {\n if (!isPlainObject(input)) {\n return failure([\n {\n kind: \"invalid_input\",\n message: `Expected object, got ${input === null ? \"null\" : typeof input}`,\n },\n ]);\n }\n\n if (spec.mode === \"single\") {\n const result = normalizeKeyDictionary(input, spec.requiredKeys, []);\n if (!result.ok) {\n return result;\n }\n\n return success({ mode: \"single\", keys: result.data });\n }\n\n const issues: ValidationIssue[] = [];\n const namespaces: Record<string, NormalizedKeyDictionary> = {};\n\n for (const [namespace, requiredKeys] of Object.entries(spec.requiredKeys)) {\n if (!(namespace in input)) {\n for (const key of requiredKeys) {\n issues.push({ kind: \"missing_key\", path: [namespace, key] });\n }\n continue;\n }\n\n const namespaceValue = input[namespace];\n if (!isPlainObject(namespaceValue)) {\n issues.push({\n kind: \"invalid_input\",\n message: `Expected object for namespace \"${namespace}\", got ${typeof namespaceValue}`,\n });\n continue;\n }\n\n const result = normalizeKeyDictionary(namespaceValue, requiredKeys, [namespace]);\n if (!result.ok) {\n issues.push(...result.issues);\n } else {\n namespaces[namespace] = result.data;\n }\n }\n\n if (issues.length > 0) {\n return failure(issues);\n }\n\n return success({ mode: \"multi\", namespaces });\n}\n","import type { NormalizedDictionary } from \"./types.js\";\n\ntype LocaleDictionary = Record<string, string>;\ntype KeyDictionary = Record<string, LocaleDictionary>;\ntype MultiDictionary = Record<string, KeyDictionary>;\n\nexport function toDictionary(normalized: NormalizedDictionary): KeyDictionary | MultiDictionary {\n if (normalized.mode === \"single\") {\n const dictionary: KeyDictionary = {};\n\n for (const [key, entry] of Object.entries(normalized.keys)) {\n const locales: LocaleDictionary = {};\n for (const [locale, localeEntry] of Object.entries(entry.locales)) {\n locales[locale] = localeEntry.template;\n }\n dictionary[key] = locales;\n }\n\n return dictionary;\n }\n\n const dictionary: MultiDictionary = {};\n\n for (const [namespace, keys] of Object.entries(normalized.namespaces)) {\n const namespaceDictionary: KeyDictionary = {};\n\n for (const [key, entry] of Object.entries(keys)) {\n const locales: LocaleDictionary = {};\n for (const [locale, localeEntry] of Object.entries(entry.locales)) {\n locales[locale] = localeEntry.template;\n }\n namespaceDictionary[key] = locales;\n }\n\n dictionary[namespace] = namespaceDictionary;\n }\n\n return dictionary;\n}\n\nexport function toNamespaceDictionary(\n normalized: NormalizedDictionary,\n namespace: string\n): KeyDictionary {\n if (normalized.mode !== \"multi\") {\n throw new Error(\n `[i18n] toNamespaceDictionary requires multi-mode normalized dictionary, got \"${normalized.mode}\"`\n );\n }\n\n const keys = normalized.namespaces[namespace];\n if (!keys) {\n return {};\n }\n\n const dictionary: KeyDictionary = {};\n\n for (const [key, entry] of Object.entries(keys)) {\n const locales: LocaleDictionary = {};\n for (const [locale, localeEntry] of Object.entries(entry.locales)) {\n locales[locale] = localeEntry.template;\n }\n dictionary[key] = locales;\n }\n\n return dictionary;\n}\n","import { z } from \"zod\";\nimport type { VariableSpec, VariableType } from \"../icu/extract-variables.js\";\n\nexport const variableTypeSchema = z.enum([\"string\", \"number\", \"date\"]);\n\nfunction formatVariableMismatch(expected: VariableSpec, found: VariableSpec): string {\n const expectedKeys = Object.keys(expected).sort();\n const foundKeys = Object.keys(found).sort();\n return `Expected variables [${expectedKeys.join(\", \")}], found [${foundKeys.join(\", \")}]`;\n}\n\nexport function createArgsSchema(expected: VariableSpec): z.ZodType<VariableSpec> {\n return z.record(z.string(), variableTypeSchema).superRefine((found, ctx) => {\n const expectedKeys = Object.keys(expected).sort();\n const foundKeys = Object.keys(found).sort();\n\n if (expectedKeys.join() !== foundKeys.join()) {\n ctx.addIssue({\n code: \"custom\",\n message: formatVariableMismatch(expected, found),\n });\n return;\n }\n\n for (const [name, type] of Object.entries(expected)) {\n if (found[name] !== type) {\n ctx.addIssue({\n code: \"custom\",\n message: `Variable \"${name}\": expected ${type}, found ${found[name]}`,\n });\n }\n }\n });\n}\n\nexport function mapArgsSchemaError(\n expected: VariableSpec,\n found: VariableSpec,\n message: string,\n path: readonly string[]\n) {\n const expectedKeys = Object.keys(expected).sort();\n const foundKeys = Object.keys(found).sort();\n\n if (expectedKeys.join() !== foundKeys.join()) {\n return {\n kind: \"variable_mismatch\" as const,\n path,\n expected,\n found,\n message,\n };\n }\n\n for (const [name, type] of Object.entries(expected)) {\n const foundType = found[name];\n if (foundType !== undefined && foundType !== type) {\n return {\n kind: \"variable_type_mismatch\" as const,\n path,\n variable: name,\n expected: type,\n found: foundType as VariableType,\n message,\n };\n }\n }\n\n return {\n kind: \"variable_mismatch\" as const,\n path,\n expected,\n found,\n message,\n };\n}\n","import { z } from \"zod\";\nimport type { VariableSpec } from \"../icu/extract-variables.js\";\nimport { createArgsSchema, variableTypeSchema } from \"./create-args-schema.js\";\nimport type { DictionarySpec, NormalizedDictionary, ParsedKeyEntry } from \"./types.js\";\n\nconst parsedLocaleEntrySchema = z.object({\n template: z.string(),\n args: z.record(z.string(), variableTypeSchema),\n});\n\nconst parsedKeyEntrySchema = z.object({\n locales: z.record(z.string(), parsedLocaleEntrySchema),\n mergedArgs: z.record(z.string(), variableTypeSchema),\n});\n\nfunction createKeyDictionarySchema(\n argsByKey: Readonly<Record<string, VariableSpec>>\n): z.ZodType<Record<string, ParsedKeyEntry>> {\n const keySchemas = Object.fromEntries(\n Object.entries(argsByKey).map(([key, expectedArgs]) => [\n key,\n parsedKeyEntrySchema.extend({\n mergedArgs: createArgsSchema(expectedArgs),\n }),\n ])\n );\n\n return z.object(keySchemas);\n}\n\nexport function createNormalizedDictionarySchema(\n spec: DictionarySpec\n): z.ZodType<NormalizedDictionary> {\n if (spec.mode === \"single\") {\n return z.object({\n mode: z.literal(\"single\"),\n keys: createKeyDictionarySchema(spec.argsByKey),\n }) as z.ZodType<NormalizedDictionary>;\n }\n\n const namespaceSchemas = Object.fromEntries(\n Object.entries(spec.argsByKey).map(([namespace, argsByKey]) => [\n namespace,\n createKeyDictionarySchema(argsByKey),\n ])\n );\n\n return z.object({\n mode: z.literal(\"multi\"),\n namespaces: z.object(namespaceSchemas),\n }) as z.ZodType<NormalizedDictionary>;\n}\n","import type { ZodError } from \"zod\";\nimport { mapArgsSchemaError } from \"./create-args-schema.js\";\nimport { createNormalizedDictionarySchema } from \"./create-normalized-schema.js\";\nimport type {\n DictionarySpec,\n NormalizedDictionary,\n ValidationIssue,\n ValidationResult,\n VariableSpec,\n} from \"./types.js\";\n\nfunction getExpectedArgs(spec: DictionarySpec, path: readonly string[]): VariableSpec | undefined {\n if (spec.mode === \"single\") {\n const key = path[path.length - 1];\n if (typeof key !== \"string\") {\n return undefined;\n }\n return spec.argsByKey[key];\n }\n\n const namespace = path[0];\n const key = path[path.length - 1];\n if (typeof namespace !== \"string\" || typeof key !== \"string\") {\n return undefined;\n }\n\n return spec.argsByKey[namespace]?.[key];\n}\n\nfunction getFoundArgs(\n normalized: NormalizedDictionary,\n path: readonly string[]\n): VariableSpec | undefined {\n if (normalized.mode === \"single\") {\n const key = path[path.length - 1];\n if (typeof key !== \"string\") {\n return undefined;\n }\n return normalized.keys[key]?.mergedArgs;\n }\n\n const namespace = path[0];\n const key = path[path.length - 1];\n if (typeof namespace !== \"string\" || typeof key !== \"string\") {\n return undefined;\n }\n\n return normalized.namespaces[namespace]?.[key]?.mergedArgs;\n}\n\nfunction mapZodError(\n error: ZodError,\n spec: DictionarySpec,\n normalized: NormalizedDictionary\n): ValidationIssue[] {\n return error.issues.map((issue) => {\n const path = issue.path.map(String);\n\n if (path.includes(\"mergedArgs\")) {\n const keyPath = path.slice(0, path.indexOf(\"mergedArgs\"));\n const expected = getExpectedArgs(spec, keyPath);\n const found = getFoundArgs(normalized, keyPath);\n\n if (expected && found) {\n return mapArgsSchemaError(expected, found, issue.message, keyPath);\n }\n }\n\n return {\n kind: \"invalid_input\" as const,\n message: path.length > 0 ? `${path.join(\".\")}: ${issue.message}` : issue.message,\n };\n });\n}\n\nexport function validateNormalizedDictionary(\n normalized: NormalizedDictionary,\n spec: DictionarySpec\n): ValidationResult<NormalizedDictionary> {\n const schema = createNormalizedDictionarySchema(spec);\n const result = schema.safeParse(normalized);\n\n if (result.success) {\n return { ok: true, data: result.data };\n }\n\n return {\n ok: false,\n issues: mapZodError(result.error, spec, normalized),\n };\n}\n","import type { ValidationIssue, ValidationResult } from \"./types.js\";\n\nfunction issueMessage(issue: ValidationIssue): string {\n switch (issue.kind) {\n case \"missing_key\":\n return `Missing required key at ${issue.path.join(\".\")}`;\n case \"invalid_input\":\n case \"invalid_locale_value\":\n case \"icu_syntax_error\":\n case \"locale_args_mismatch\":\n case \"variable_mismatch\":\n case \"variable_type_mismatch\":\n return issue.message;\n }\n}\n\nexport function formatIssues(issues: readonly ValidationIssue[]): string {\n return issues\n .map((issue) => {\n if (\"path\" in issue && issue.path.length > 0) {\n return `[${issue.path.join(\".\")}] ${issue.kind}: ${issueMessage(issue)}`;\n }\n return `${issue.kind}: ${issueMessage(issue)}`;\n })\n .join(\"\\n\");\n}\n\nexport class DictionaryValidationError extends Error {\n constructor(public readonly issues: readonly ValidationIssue[]) {\n super(formatIssues(issues));\n this.name = \"DictionaryValidationError\";\n }\n}\n\nexport function assertValidDictionary<T>(\n result: ValidationResult<T>\n): asserts result is { ok: true; data: T } {\n if (!result.ok) {\n throw new DictionaryValidationError(result.issues);\n }\n}\n","import { normalizeDictionary } from \"./normalize.js\";\nimport { toDictionary, toNamespaceDictionary } from \"./to-dictionary.js\";\nimport type { DictionarySpec, ValidationResult } from \"./types.js\";\nimport { validateNormalizedDictionary } from \"./validate-normalized.js\";\n\nexport function validateExternalDictionary<TSchema>(\n input: unknown,\n spec: DictionarySpec\n): ValidationResult<TSchema> {\n const step1 = normalizeDictionary(input, spec);\n if (!step1.ok) {\n return step1;\n }\n\n const step2 = validateNormalizedDictionary(step1.data, spec);\n if (!step2.ok) {\n return step2;\n }\n\n return { ok: true, data: toDictionary(step2.data) as TSchema };\n}\n\nexport function validateExternalNamespace<TNamespaceSchema>(\n namespace: string,\n input: unknown,\n spec: DictionarySpec\n): ValidationResult<TNamespaceSchema> {\n if (spec.mode !== \"multi\") {\n return {\n ok: false,\n issues: [\n {\n kind: \"invalid_input\",\n message: \"validateExternalNamespace requires multi-mode dictionary spec\",\n },\n ],\n };\n }\n\n const wrapped = { [namespace]: input };\n const namespaceSpec: DictionarySpec = {\n mode: \"multi\",\n requiredKeys: {\n [namespace]: spec.requiredKeys[namespace] ?? [],\n },\n argsByKey: {\n [namespace]: spec.argsByKey[namespace] ?? {},\n },\n };\n\n const step1 = normalizeDictionary(wrapped, namespaceSpec);\n if (!step1.ok) {\n return step1;\n }\n\n const step2 = validateNormalizedDictionary(step1.data, namespaceSpec);\n if (!step2.ok) {\n return step2;\n }\n\n return {\n ok: true,\n data: toNamespaceDictionary(step2.data, namespace) as TNamespaceSchema,\n };\n}\n\nexport { normalizeDictionary, validateNormalizedDictionary, toDictionary, toNamespaceDictionary };\nexport { createArgsSchema } from \"./create-args-schema.js\";\nexport { createNormalizedDictionarySchema } from \"./create-normalized-schema.js\";\nexport { DictionaryValidationError, assertValidDictionary, formatIssues } from \"./errors.js\";\nexport type {\n DictionarySpec,\n NormalizedDictionary,\n NormalizedKeyDictionary,\n NormalizedMultiDictionary,\n ParsedKeyEntry,\n ParsedLocaleEntry,\n ValidationIssue,\n ValidationResult,\n VariableSpec,\n VariableType,\n} from \"./types.js\";\n\nexport type { ParseTemplateResult } from \"../icu/parse-template.js\";\nexport { parseTemplate } from \"../icu/parse-template.js\";\nexport {\n extractVariables,\n mergeVariableSpecs,\n variableSpecsEqual,\n} from \"../icu/extract-variables.js\";\n"]}
|
|
1
|
+
{"version":3,"sources":["../../src/icu/extract-variables.ts","../../src/icu/parse-template.ts","../../src/validation/normalize.ts","../../src/validation/to-dictionary.ts","../../src/validation/create-args-schema.ts","../../src/validation/create-normalized-schema.ts","../../src/validation/validate-normalized.ts","../../src/validation/errors.ts","../../src/validation/index.ts"],"names":["dictionary","z","key"],"mappings":"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","file":"index.js","sourcesContent":["import type { parse } from \"@formatjs/icu-messageformat-parser\";\n\nexport type VariableType = \"string\" | \"number\" | \"date\";\nexport type VariableSpec = Record<string, VariableType>;\n\nexport type VariableRole =\n | \"simple\"\n | \"plural\"\n | \"selectordinal\"\n | \"select\"\n | \"number\"\n | \"date\"\n | \"time\";\n\nexport type VariableMeta = {\n type: VariableType;\n roles: Set<VariableRole>;\n};\n\nexport type VariableMetaSpec = Record<string, VariableMeta>;\n\ntype IcuAst = ReturnType<typeof parse>;\ntype IcuNode = IcuAst[number];\n\nfunction isPluralOrOrdinalNode(node: IcuNode): node is Extract<IcuNode, { type: 6 }> {\n return node.type === 6 && \"pluralType\" in node && Boolean(node.pluralType);\n}\n\nfunction hasVariableName(node: IcuNode): node is Extract<IcuNode, { value: string }> {\n return \"value\" in node && typeof node.value === \"string\";\n}\n\nfunction addVariableMeta(\n variables: VariableMetaSpec,\n name: string,\n type: VariableType,\n role: VariableRole\n): void {\n const existing = variables[name];\n if (!existing) {\n variables[name] = { type, roles: new Set([role]) };\n return;\n }\n\n existing.roles.add(role);\n existing.type = mergeVariableTypes(existing.type, type);\n}\n\nfunction mergeVariableTypes(left: VariableType, right: VariableType): VariableType {\n if (left === right) {\n return left;\n }\n\n if ((left === \"string\" && right === \"number\") || (left === \"number\" && right === \"string\")) {\n return \"number\";\n }\n\n return right;\n}\n\nexport function extractVariableMeta(nodes: IcuAst): VariableMetaSpec {\n const variables: VariableMetaSpec = {};\n\n const walk = (walkNodes: IcuAst) => {\n for (const node of walkNodes) {\n if (node.type === 1 && hasVariableName(node)) {\n addVariableMeta(variables, node.value, \"string\", \"simple\");\n } else if (node.type === 2 && hasVariableName(node)) {\n addVariableMeta(variables, node.value, \"number\", \"number\");\n } else if (isPluralOrOrdinalNode(node) && hasVariableName(node)) {\n const role = node.pluralType === \"ordinal\" ? \"selectordinal\" : \"plural\";\n addVariableMeta(variables, node.value, \"number\", role);\n } else if (node.type === 3 && hasVariableName(node)) {\n addVariableMeta(variables, node.value, \"date\", \"date\");\n } else if (node.type === 4 && hasVariableName(node)) {\n addVariableMeta(variables, node.value, \"date\", \"time\");\n } else if (node.type === 5 && hasVariableName(node)) {\n addVariableMeta(variables, node.value, \"string\", \"select\");\n }\n\n if (\"options\" in node && node.options) {\n for (const option of Object.values(node.options)) {\n walk(option.value);\n }\n }\n\n if (\"children\" in node && Array.isArray(node.children)) {\n walk(node.children);\n }\n }\n };\n\n walk(nodes);\n return variables;\n}\n\nexport function variableMetaToSpec(meta: VariableMetaSpec): VariableSpec {\n return Object.fromEntries(Object.entries(meta).map(([name, entry]) => [name, entry.type]));\n}\n\nexport function extractVariables(nodes: IcuAst): VariableSpec {\n return variableMetaToSpec(extractVariableMeta(nodes));\n}\n\nexport function inferMergedVariableType(roles: Set<VariableRole>): VariableType | \"CONFLICT\" {\n const hasPlural = roles.has(\"plural\");\n const hasSelectordinal = roles.has(\"selectordinal\");\n const hasSelect = roles.has(\"select\");\n const hasSimple = roles.has(\"simple\");\n const hasNumber = roles.has(\"number\");\n const hasDate = roles.has(\"date\");\n const hasTime = roles.has(\"time\");\n\n // Incompatible numeric ICU constructs on the same variable.\n if (hasPlural && hasSelectordinal) {\n return \"CONFLICT\";\n }\n\n // Select (string-family) vs plural / ordinal / number-format (number-family).\n if (hasSelect && (hasPlural || hasSelectordinal || hasNumber)) {\n return \"CONFLICT\";\n }\n\n // Legacy explicit pairs — covered by the rule above, kept for clarity.\n if (hasPlural && hasSelect) {\n return \"CONFLICT\";\n }\n\n if (hasSelectordinal && hasSelect) {\n return \"CONFLICT\";\n }\n\n if (hasDate || hasTime) {\n if (hasPlural || hasSelect || hasSelectordinal || hasSimple || hasNumber) {\n return \"CONFLICT\";\n }\n return \"date\";\n }\n\n if (hasPlural || hasSelectordinal || hasNumber) {\n return \"number\";\n }\n\n if (hasSelect || hasSimple) {\n return \"string\";\n }\n\n return \"string\";\n}\n\nexport function mergeVariableMetaAcrossLocales(\n localeMetas: readonly VariableMetaSpec[]\n): { ok: true; merged: VariableSpec } | { ok: false; message: string } {\n const keySignatures = localeMetas.map((meta) => Object.keys(meta).sort().join(\",\"));\n if (new Set(keySignatures).size > 1) {\n return {\n ok: false,\n message: `Inconsistent ICU variable names across locales (keys: ${keySignatures.join(\" vs \")})`,\n };\n }\n\n const merged: VariableSpec = {};\n const variableNames = new Set(localeMetas.flatMap((meta) => Object.keys(meta)));\n\n for (const variableName of variableNames) {\n const combinedRoles = new Set<VariableRole>();\n\n for (const meta of localeMetas) {\n for (const role of meta[variableName]?.roles ?? []) {\n combinedRoles.add(role);\n }\n }\n\n const mergedType = inferMergedVariableType(combinedRoles);\n if (mergedType === \"CONFLICT\") {\n const rolesByLocale = localeMetas\n .map((meta) => {\n const entry = meta[variableName];\n if (!entry) {\n return null;\n }\n return [...entry.roles].sort().join(\"|\");\n })\n .filter((value): value is string => value !== null);\n\n return {\n ok: false,\n message: `Incompatible ICU variable \"${variableName}\" across locales (roles: ${rolesByLocale.join(\" vs \")})`,\n };\n }\n\n merged[variableName] = mergedType;\n }\n\n return { ok: true, merged };\n}\n\nexport function mergeVariableSpecs(target: VariableSpec, source: VariableSpec): VariableSpec {\n const merged = { ...target };\n\n for (const [varName, varType] of Object.entries(source)) {\n const existing = merged[varName];\n if (existing && existing !== varType) {\n merged[varName] = \"number\";\n } else {\n merged[varName] = varType;\n }\n }\n\n return merged;\n}\n\nexport function variableSpecsEqual(a: VariableSpec, b: VariableSpec): boolean {\n const aKeys = Object.keys(a).sort();\n const bKeys = Object.keys(b).sort();\n\n if (aKeys.length !== bKeys.length) {\n return false;\n }\n\n return aKeys.every((key, index) => {\n if (key !== bKeys[index]) {\n return false;\n }\n return a[key] === b[key];\n });\n}\n","import { parse } from \"@formatjs/icu-messageformat-parser\";\nimport {\n extractVariableMeta,\n variableMetaToSpec,\n type VariableMetaSpec,\n type VariableSpec,\n} from \"./extract-variables.js\";\n\nexport type ParseTemplateSuccess = {\n readonly ok: true;\n readonly args: VariableSpec;\n readonly meta: VariableMetaSpec;\n};\n\nexport type ParseTemplateFailure = {\n readonly ok: false;\n readonly message: string;\n};\n\nexport type ParseTemplateResult = ParseTemplateSuccess | ParseTemplateFailure;\n\nexport function parseTemplate(template: string): ParseTemplateResult {\n try {\n const ast = parse(template);\n const meta = extractVariableMeta(ast);\n return { ok: true, args: variableMetaToSpec(meta), meta };\n } catch (error) {\n const message = error instanceof Error ? error.message : String(error);\n return { ok: false, message };\n }\n}\n","import { mergeVariableMetaAcrossLocales, type VariableMetaSpec } from \"../icu/extract-variables.js\";\nimport { parseTemplate } from \"../icu/parse-template.js\";\nimport type {\n DictionarySpec,\n NormalizedDictionary,\n NormalizedKeyDictionary,\n ParsedKeyEntry,\n ValidationIssue,\n ValidationResult,\n} from \"./types.js\";\n\nfunction failure(issues: ValidationIssue[]): ValidationResult<NormalizedDictionary> {\n return { ok: false, issues };\n}\n\nfunction success(data: NormalizedDictionary): ValidationResult<NormalizedDictionary> {\n return { ok: true, data };\n}\n\nfunction isPlainObject(value: unknown): value is Record<string, unknown> {\n return typeof value === \"object\" && value !== null && !Array.isArray(value);\n}\n\nfunction normalizeKeyDictionary(\n input: Record<string, unknown>,\n requiredKeys: readonly string[],\n keyPathPrefix: readonly string[]\n): ValidationResult<NormalizedKeyDictionary> {\n const issues: ValidationIssue[] = [];\n const keys: Record<string, ParsedKeyEntry> = {};\n\n for (const key of requiredKeys) {\n if (!(key in input)) {\n issues.push({ kind: \"missing_key\", path: [...keyPathPrefix, key] });\n continue;\n }\n\n const keyValue = input[key];\n if (!isPlainObject(keyValue)) {\n issues.push({\n kind: \"invalid_input\",\n message: `Expected object for key \"${key}\", got ${typeof keyValue}`,\n });\n continue;\n }\n\n const locales: Record<string, ParsedKeyEntry[\"locales\"][string]> = {};\n const localeMetas: VariableMetaSpec[] = [];\n let mergedArgs: ParsedKeyEntry[\"mergedArgs\"] = {};\n let localeArgsMismatch: ValidationIssue | undefined;\n\n for (const [locale, template] of Object.entries(keyValue)) {\n const localePath = [...keyPathPrefix, key, locale];\n\n if (typeof template !== \"string\") {\n issues.push({\n kind: \"invalid_locale_value\",\n path: localePath,\n message: `expected string, got ${typeof template}`,\n });\n continue;\n }\n\n const parsed = parseTemplate(template);\n if (!parsed.ok) {\n issues.push({\n kind: \"icu_syntax_error\",\n path: localePath,\n message: parsed.message,\n });\n continue;\n }\n\n locales[locale] = { template, args: parsed.args };\n localeMetas.push(parsed.meta);\n }\n\n if (localeMetas.length > 0) {\n const merged = mergeVariableMetaAcrossLocales(localeMetas);\n if (!merged.ok) {\n const localeArgs: Record<string, ParsedKeyEntry[\"mergedArgs\"]> = {};\n for (const [loc, entry] of Object.entries(locales)) {\n localeArgs[loc] = entry.args;\n }\n localeArgsMismatch = {\n kind: \"locale_args_mismatch\",\n path: [...keyPathPrefix, key],\n locales: localeArgs,\n message: merged.message,\n };\n } else {\n mergedArgs = merged.merged;\n }\n }\n\n if (localeArgsMismatch) {\n issues.push(localeArgsMismatch);\n }\n\n keys[key] = { locales, mergedArgs };\n }\n\n if (issues.length > 0) {\n return { ok: false, issues };\n }\n\n return { ok: true, data: keys };\n}\n\n/**\n * Validation step 1: coerce external input into a normalized dictionary shape\n * (keys, locales, ICU args) against a `DictionarySpec`.\n */\nexport function normalizeDictionary(\n input: unknown,\n spec: DictionarySpec\n): ValidationResult<NormalizedDictionary> {\n if (!isPlainObject(input)) {\n return failure([\n {\n kind: \"invalid_input\",\n message: `Expected object, got ${input === null ? \"null\" : typeof input}`,\n },\n ]);\n }\n\n if (spec.mode === \"single\") {\n const result = normalizeKeyDictionary(input, spec.requiredKeys, []);\n if (!result.ok) {\n return result;\n }\n\n return success({ mode: \"single\", keys: result.data });\n }\n\n const issues: ValidationIssue[] = [];\n const namespaces: Record<string, NormalizedKeyDictionary> = {};\n\n for (const [namespace, requiredKeys] of Object.entries(spec.requiredKeys)) {\n if (!(namespace in input)) {\n for (const key of requiredKeys) {\n issues.push({ kind: \"missing_key\", path: [namespace, key] });\n }\n continue;\n }\n\n const namespaceValue = input[namespace];\n if (!isPlainObject(namespaceValue)) {\n issues.push({\n kind: \"invalid_input\",\n message: `Expected object for namespace \"${namespace}\", got ${typeof namespaceValue}`,\n });\n continue;\n }\n\n const result = normalizeKeyDictionary(namespaceValue, requiredKeys, [namespace]);\n if (!result.ok) {\n issues.push(...result.issues);\n } else {\n namespaces[namespace] = result.data;\n }\n }\n\n if (issues.length > 0) {\n return failure(issues);\n }\n\n return success({ mode: \"multi\", namespaces });\n}\n","import type { NormalizedDictionary } from \"./types.js\";\n\ntype LocaleDictionary = Record<string, string>;\ntype KeyDictionary = Record<string, LocaleDictionary>;\ntype MultiDictionary = Record<string, KeyDictionary>;\n\nexport function toDictionary(normalized: NormalizedDictionary): KeyDictionary | MultiDictionary {\n if (normalized.mode === \"single\") {\n const dictionary: KeyDictionary = {};\n\n for (const [key, entry] of Object.entries(normalized.keys)) {\n const locales: LocaleDictionary = {};\n for (const [locale, localeEntry] of Object.entries(entry.locales)) {\n locales[locale] = localeEntry.template;\n }\n dictionary[key] = locales;\n }\n\n return dictionary;\n }\n\n const dictionary: MultiDictionary = {};\n\n for (const [namespace, keys] of Object.entries(normalized.namespaces)) {\n const namespaceDictionary: KeyDictionary = {};\n\n for (const [key, entry] of Object.entries(keys)) {\n const locales: LocaleDictionary = {};\n for (const [locale, localeEntry] of Object.entries(entry.locales)) {\n locales[locale] = localeEntry.template;\n }\n namespaceDictionary[key] = locales;\n }\n\n dictionary[namespace] = namespaceDictionary;\n }\n\n return dictionary;\n}\n\nexport function toNamespaceDictionary(\n normalized: NormalizedDictionary,\n namespace: string\n): KeyDictionary {\n if (normalized.mode !== \"multi\") {\n throw new Error(\n `[i18n] toNamespaceDictionary requires multi-mode normalized dictionary, got \"${normalized.mode}\"`\n );\n }\n\n const keys = normalized.namespaces[namespace];\n if (!keys) {\n return {};\n }\n\n const dictionary: KeyDictionary = {};\n\n for (const [key, entry] of Object.entries(keys)) {\n const locales: LocaleDictionary = {};\n for (const [locale, localeEntry] of Object.entries(entry.locales)) {\n locales[locale] = localeEntry.template;\n }\n dictionary[key] = locales;\n }\n\n return dictionary;\n}\n","import { z } from \"zod\";\nimport type { VariableSpec, VariableType } from \"../icu/extract-variables.js\";\n\nexport const variableTypeSchema = z.enum([\"string\", \"number\", \"date\"]);\n\nfunction formatVariableMismatch(expected: VariableSpec, found: VariableSpec): string {\n const expectedKeys = Object.keys(expected).sort();\n const foundKeys = Object.keys(found).sort();\n return `Expected variables [${expectedKeys.join(\", \")}], found [${foundKeys.join(\", \")}]`;\n}\n\nexport function createArgsSchema(expected: VariableSpec): z.ZodType<VariableSpec> {\n return z.record(z.string(), variableTypeSchema).superRefine((found, ctx) => {\n const expectedKeys = Object.keys(expected).sort();\n const foundKeys = Object.keys(found).sort();\n\n if (expectedKeys.join() !== foundKeys.join()) {\n ctx.addIssue({\n code: \"custom\",\n message: formatVariableMismatch(expected, found),\n });\n return;\n }\n\n for (const [name, type] of Object.entries(expected)) {\n if (found[name] !== type) {\n ctx.addIssue({\n code: \"custom\",\n message: `Variable \"${name}\": expected ${type}, found ${found[name]}`,\n });\n }\n }\n });\n}\n\nexport function mapArgsSchemaError(\n expected: VariableSpec,\n found: VariableSpec,\n message: string,\n path: readonly string[]\n) {\n const expectedKeys = Object.keys(expected).sort();\n const foundKeys = Object.keys(found).sort();\n\n if (expectedKeys.join() !== foundKeys.join()) {\n return {\n kind: \"variable_mismatch\" as const,\n path,\n expected,\n found,\n message,\n };\n }\n\n for (const [name, type] of Object.entries(expected)) {\n const foundType = found[name];\n if (foundType !== undefined && foundType !== type) {\n return {\n kind: \"variable_type_mismatch\" as const,\n path,\n variable: name,\n expected: type,\n found: foundType as VariableType,\n message,\n };\n }\n }\n\n return {\n kind: \"variable_mismatch\" as const,\n path,\n expected,\n found,\n message,\n };\n}\n","import { z } from \"zod\";\nimport type { VariableSpec } from \"../icu/extract-variables.js\";\nimport { createArgsSchema, variableTypeSchema } from \"./create-args-schema.js\";\nimport type { DictionarySpec, NormalizedDictionary, ParsedKeyEntry } from \"./types.js\";\n\nconst parsedLocaleEntrySchema = z.object({\n template: z.string(),\n args: z.record(z.string(), variableTypeSchema),\n});\n\nconst parsedKeyEntrySchema = z.object({\n locales: z.record(z.string(), parsedLocaleEntrySchema),\n mergedArgs: z.record(z.string(), variableTypeSchema),\n});\n\nfunction createKeyDictionarySchema(\n argsByKey: Readonly<Record<string, VariableSpec>>\n): z.ZodType<Record<string, ParsedKeyEntry>> {\n const keySchemas = Object.fromEntries(\n Object.entries(argsByKey).map(([key, expectedArgs]) => [\n key,\n parsedKeyEntrySchema.extend({\n mergedArgs: createArgsSchema(expectedArgs),\n }),\n ])\n );\n\n return z.object(keySchemas);\n}\n\nexport function createNormalizedDictionarySchema(\n spec: DictionarySpec\n): z.ZodType<NormalizedDictionary> {\n if (spec.mode === \"single\") {\n return z.object({\n mode: z.literal(\"single\"),\n keys: createKeyDictionarySchema(spec.argsByKey),\n }) as z.ZodType<NormalizedDictionary>;\n }\n\n const namespaceSchemas = Object.fromEntries(\n Object.entries(spec.argsByKey).map(([namespace, argsByKey]) => [\n namespace,\n createKeyDictionarySchema(argsByKey),\n ])\n );\n\n return z.object({\n mode: z.literal(\"multi\"),\n namespaces: z.object(namespaceSchemas),\n }) as z.ZodType<NormalizedDictionary>;\n}\n","import type { ZodError } from \"zod\";\nimport { mapArgsSchemaError } from \"./create-args-schema.js\";\nimport { createNormalizedDictionarySchema } from \"./create-normalized-schema.js\";\nimport type {\n DictionarySpec,\n NormalizedDictionary,\n ValidationIssue,\n ValidationResult,\n VariableSpec,\n} from \"./types.js\";\n\nfunction getExpectedArgs(spec: DictionarySpec, path: readonly string[]): VariableSpec | undefined {\n if (spec.mode === \"single\") {\n const key = path[path.length - 1];\n if (typeof key !== \"string\") {\n return undefined;\n }\n return spec.argsByKey[key];\n }\n\n const namespace = path[0];\n const key = path[path.length - 1];\n if (typeof namespace !== \"string\" || typeof key !== \"string\") {\n return undefined;\n }\n\n return spec.argsByKey[namespace]?.[key];\n}\n\nfunction getFoundArgs(\n normalized: NormalizedDictionary,\n path: readonly string[]\n): VariableSpec | undefined {\n if (normalized.mode === \"single\") {\n const key = path[path.length - 1];\n if (typeof key !== \"string\") {\n return undefined;\n }\n return normalized.keys[key]?.mergedArgs;\n }\n\n const namespace = path[0];\n const key = path[path.length - 1];\n if (typeof namespace !== \"string\" || typeof key !== \"string\") {\n return undefined;\n }\n\n return normalized.namespaces[namespace]?.[key]?.mergedArgs;\n}\n\nfunction mapZodError(\n error: ZodError,\n spec: DictionarySpec,\n normalized: NormalizedDictionary\n): ValidationIssue[] {\n return error.issues.map((issue) => {\n const path = issue.path.map(String);\n\n if (path.includes(\"mergedArgs\")) {\n const keyPath = path.slice(0, path.indexOf(\"mergedArgs\"));\n const expected = getExpectedArgs(spec, keyPath);\n const found = getFoundArgs(normalized, keyPath);\n\n if (expected && found) {\n return mapArgsSchemaError(expected, found, issue.message, keyPath);\n }\n }\n\n return {\n kind: \"invalid_input\" as const,\n message: path.length > 0 ? `${path.join(\".\")}: ${issue.message}` : issue.message,\n };\n });\n}\n\nexport function validateNormalizedDictionary(\n normalized: NormalizedDictionary,\n spec: DictionarySpec\n): ValidationResult<NormalizedDictionary> {\n const schema = createNormalizedDictionarySchema(spec);\n const result = schema.safeParse(normalized);\n\n if (result.success) {\n return { ok: true, data: result.data };\n }\n\n return {\n ok: false,\n issues: mapZodError(result.error, spec, normalized),\n };\n}\n","import type { ValidationIssue, ValidationResult } from \"./types.js\";\n\nfunction issueMessage(issue: ValidationIssue): string {\n switch (issue.kind) {\n case \"missing_key\":\n return `Missing required key at ${issue.path.join(\".\")}`;\n case \"invalid_input\":\n case \"invalid_locale_value\":\n case \"icu_syntax_error\":\n case \"locale_args_mismatch\":\n case \"variable_mismatch\":\n case \"variable_type_mismatch\":\n return issue.message;\n }\n}\n\nexport function formatIssues(issues: readonly ValidationIssue[]): string {\n return issues\n .map((issue) => {\n if (\"path\" in issue && issue.path.length > 0) {\n return `[${issue.path.join(\".\")}] ${issue.kind}: ${issueMessage(issue)}`;\n }\n return `${issue.kind}: ${issueMessage(issue)}`;\n })\n .join(\"\\n\");\n}\n\nexport class DictionaryValidationError extends Error {\n constructor(public readonly issues: readonly ValidationIssue[]) {\n super(formatIssues(issues));\n this.name = \"DictionaryValidationError\";\n }\n}\n\nexport function assertValidDictionary<T>(\n result: ValidationResult<T>\n): asserts result is { ok: true; data: T } {\n if (!result.ok) {\n throw new DictionaryValidationError(result.issues);\n }\n}\n","import { normalizeDictionary } from \"./normalize.js\";\nimport { toDictionary, toNamespaceDictionary } from \"./to-dictionary.js\";\nimport type { DictionarySpec, ValidationResult } from \"./types.js\";\nimport { validateNormalizedDictionary } from \"./validate-normalized.js\";\n\nexport function validateExternalDictionary<TSchema>(\n input: unknown,\n spec: DictionarySpec\n): ValidationResult<TSchema> {\n const step1 = normalizeDictionary(input, spec);\n if (!step1.ok) {\n return step1;\n }\n\n const step2 = validateNormalizedDictionary(step1.data, spec);\n if (!step2.ok) {\n return step2;\n }\n\n return { ok: true, data: toDictionary(step2.data) as TSchema };\n}\n\nexport function validateExternalNamespace<TNamespaceSchema>(\n namespace: string,\n input: unknown,\n spec: DictionarySpec\n): ValidationResult<TNamespaceSchema> {\n if (spec.mode !== \"multi\") {\n return {\n ok: false,\n issues: [\n {\n kind: \"invalid_input\",\n message: \"validateExternalNamespace requires multi-mode dictionary spec\",\n },\n ],\n };\n }\n\n const wrapped = { [namespace]: input };\n const namespaceSpec: DictionarySpec = {\n mode: \"multi\",\n requiredKeys: {\n [namespace]: spec.requiredKeys[namespace] ?? [],\n },\n argsByKey: {\n [namespace]: spec.argsByKey[namespace] ?? {},\n },\n };\n\n const step1 = normalizeDictionary(wrapped, namespaceSpec);\n if (!step1.ok) {\n return step1;\n }\n\n const step2 = validateNormalizedDictionary(step1.data, namespaceSpec);\n if (!step2.ok) {\n return step2;\n }\n\n return {\n ok: true,\n data: toNamespaceDictionary(step2.data, namespace) as TNamespaceSchema,\n };\n}\n\nexport { normalizeDictionary, validateNormalizedDictionary, toDictionary, toNamespaceDictionary };\nexport { createArgsSchema } from \"./create-args-schema.js\";\nexport { createNormalizedDictionarySchema } from \"./create-normalized-schema.js\";\nexport { DictionaryValidationError, assertValidDictionary, formatIssues } from \"./errors.js\";\nexport type {\n DictionarySpec,\n NormalizedDictionary,\n NormalizedKeyDictionary,\n NormalizedMultiDictionary,\n ParsedKeyEntry,\n ParsedLocaleEntry,\n ValidationIssue,\n ValidationResult,\n VariableSpec,\n VariableType,\n} from \"./types.js\";\n\nexport type { ParseTemplateResult } from \"../icu/parse-template.js\";\nexport { parseTemplate } from \"../icu/parse-template.js\";\nexport {\n extractVariables,\n mergeVariableSpecs,\n variableSpecsEqual,\n} from \"../icu/extract-variables.js\";\n"]}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@xndrjs/i18n",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.5.0-alpha.0",
|
|
4
4
|
"description": "Compiler-first, type-safe ICU MessageFormat i18n with runtime dictionary override from external sources.",
|
|
5
5
|
"private": false,
|
|
6
6
|
"license": "MIT",
|
|
@@ -26,6 +26,11 @@
|
|
|
26
26
|
"types": "./dist/validation/index.d.ts",
|
|
27
27
|
"import": "./dist/validation/index.js",
|
|
28
28
|
"default": "./dist/validation/index.js"
|
|
29
|
+
},
|
|
30
|
+
"./codegen": {
|
|
31
|
+
"types": "./dist/codegen/index.d.ts",
|
|
32
|
+
"import": "./dist/codegen/index.js",
|
|
33
|
+
"default": "./dist/codegen/index.js"
|
|
29
34
|
}
|
|
30
35
|
},
|
|
31
36
|
"files": [
|
|
@@ -161,7 +161,7 @@ describe("IcuTranslationProviderMulti", () => {
|
|
|
161
161
|
expect(() =>
|
|
162
162
|
partial.get("billing", "invoice_summary", "en", { count: 1, name: "Ada" })
|
|
163
163
|
).toThrow(
|
|
164
|
-
'[i18n] Namespace not loaded: "billing".
|
|
164
|
+
'[i18n] Namespace not loaded: "billing". Register it with setNamespace() before calling .get().'
|
|
165
165
|
);
|
|
166
166
|
});
|
|
167
167
|
|
|
@@ -287,4 +287,51 @@ describe("IcuTranslationProviderMulti", () => {
|
|
|
287
287
|
);
|
|
288
288
|
});
|
|
289
289
|
});
|
|
290
|
+
|
|
291
|
+
describe("onMissing", () => {
|
|
292
|
+
it('returns "namespace.key" with onMissing: "key"', () => {
|
|
293
|
+
const local = new IcuTranslationProviderMulti<TestSchema, TestParams>(dictionary, {
|
|
294
|
+
onMissing: "key",
|
|
295
|
+
});
|
|
296
|
+
expect(local.get("default", "missing_key" as "login_button", "en")).toBe(
|
|
297
|
+
"default.missing_key"
|
|
298
|
+
);
|
|
299
|
+
});
|
|
300
|
+
|
|
301
|
+
it("calls a custom handler with namespace, key, locale, and fallback chain", () => {
|
|
302
|
+
const contexts: unknown[] = [];
|
|
303
|
+
const local = new IcuTranslationProviderMulti<TestSchema, TestParams>(dictionary, {
|
|
304
|
+
onMissing: (context) => {
|
|
305
|
+
contexts.push(context);
|
|
306
|
+
return `<missing:${context.namespace}/${context.key}>`;
|
|
307
|
+
},
|
|
308
|
+
});
|
|
309
|
+
|
|
310
|
+
expect(local.get("default", "missing_key" as "login_button", "en")).toBe(
|
|
311
|
+
"<missing:default/missing_key>"
|
|
312
|
+
);
|
|
313
|
+
expect(contexts).toEqual([
|
|
314
|
+
{ namespace: "default", key: "missing_key", locale: "en", fallbackChain: "en" },
|
|
315
|
+
]);
|
|
316
|
+
});
|
|
317
|
+
|
|
318
|
+
it("still throws for unloaded namespaces with a lenient onMissing", () => {
|
|
319
|
+
const local = new IcuTranslationProviderMulti<TestSchema, TestParams>(
|
|
320
|
+
{ default: dictionary.default },
|
|
321
|
+
{ onMissing: "key" }
|
|
322
|
+
);
|
|
323
|
+
expect(() => local.get("billing", "account_balance", "en", { amount: 1 })).toThrow(
|
|
324
|
+
'[i18n] Namespace not loaded: "billing"'
|
|
325
|
+
);
|
|
326
|
+
});
|
|
327
|
+
|
|
328
|
+
it("applies onMissing through forLocale wrappers", () => {
|
|
329
|
+
const local = new IcuTranslationProviderMulti<TestSchema, TestParams>(dictionary, {
|
|
330
|
+
onMissing: "key",
|
|
331
|
+
});
|
|
332
|
+
expect(local.forLocale("en").get("default", "missing_key" as "login_button")).toBe(
|
|
333
|
+
"default.missing_key"
|
|
334
|
+
);
|
|
335
|
+
});
|
|
336
|
+
});
|
|
290
337
|
});
|
|
@@ -1,16 +1,13 @@
|
|
|
1
|
-
import { IntlMessageFormat } from "intl-messageformat";
|
|
2
1
|
import { cloneAndFreeze } from "./deep-freeze.js";
|
|
3
|
-
import {
|
|
4
|
-
|
|
5
|
-
resolveLocaleTemplate,
|
|
6
|
-
validateLocaleFallback,
|
|
7
|
-
} from "./resolve-locale.js";
|
|
2
|
+
import { resolveAndFormat } from "./format-core.js";
|
|
3
|
+
import { validateLocaleFallback } from "./resolve-locale.js";
|
|
8
4
|
import type {
|
|
9
5
|
IcuTranslationProviderOptions,
|
|
10
6
|
LocaleFallbackMap,
|
|
11
7
|
LocaleOfMulti,
|
|
12
8
|
MultiCompiledCache,
|
|
13
9
|
MultiDictionary,
|
|
10
|
+
OnMissingTranslation,
|
|
14
11
|
} from "./types.js";
|
|
15
12
|
|
|
16
13
|
export interface TranslationProviderMultiForLocale<
|
|
@@ -68,17 +65,8 @@ export class IcuTranslationProviderMultiForLocale<
|
|
|
68
65
|
key: K,
|
|
69
66
|
...args: Params[NS][K] extends never ? [] : [params: Params[NS][K]]
|
|
70
67
|
): string {
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
NS extends keyof Schema,
|
|
74
|
-
K extends keyof Schema[NS] & keyof Params[NS] & string,
|
|
75
|
-
>(
|
|
76
|
-
namespace: NS,
|
|
77
|
-
key: K,
|
|
78
|
-
locale: Locale,
|
|
79
|
-
...params: Params[NS][K] extends never ? [] : [params: Params[NS][K]]
|
|
80
|
-
) => string
|
|
81
|
-
)(namespace, key, this.locale, ...args);
|
|
68
|
+
const params = args[0] as Record<string, unknown> | undefined;
|
|
69
|
+
return this.provider.getWithLocale(String(namespace), String(key), this.locale, params);
|
|
82
70
|
}
|
|
83
71
|
}
|
|
84
72
|
|
|
@@ -91,6 +79,7 @@ export class IcuTranslationProviderMulti<
|
|
|
91
79
|
private dictionary: Schema;
|
|
92
80
|
private compiledCache: MultiCompiledCache = {};
|
|
93
81
|
private readonly localeFallback?: Fallback;
|
|
82
|
+
private readonly onMissing: OnMissingTranslation;
|
|
94
83
|
private loadedNamespaces: Set<string>;
|
|
95
84
|
|
|
96
85
|
constructor(dictionary: Partial<Schema>, options?: IcuTranslationProviderOptions<Fallback>) {
|
|
@@ -100,6 +89,7 @@ export class IcuTranslationProviderMulti<
|
|
|
100
89
|
validateLocaleFallback(options.localeFallback);
|
|
101
90
|
this.localeFallback = options.localeFallback;
|
|
102
91
|
}
|
|
92
|
+
this.onMissing = options?.onMissing ?? "throw";
|
|
103
93
|
}
|
|
104
94
|
|
|
105
95
|
get<NS extends keyof Schema, K extends keyof Schema[NS] & keyof Params[NS] & string>(
|
|
@@ -108,57 +98,47 @@ export class IcuTranslationProviderMulti<
|
|
|
108
98
|
locale: RequestLocales,
|
|
109
99
|
...args: Params[NS][K] extends never ? [] : [params: Params[NS][K]]
|
|
110
100
|
): string {
|
|
111
|
-
if (!this.loadedNamespaces.has(namespace as string)) {
|
|
112
|
-
throw new Error(
|
|
113
|
-
`[i18n] Namespace not loaded: "${String(namespace)}". Call ensureNamespacesLoaded(i18n, ["${String(namespace)}"]) first.`
|
|
114
|
-
);
|
|
115
|
-
}
|
|
116
|
-
|
|
117
101
|
const params = args[0] as Record<string, unknown> | undefined;
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
)?.[key];
|
|
121
|
-
const resolved = resolveLocaleTemplate(localeByKey, locale, this.localeFallback);
|
|
102
|
+
return this.getWithLocale(String(namespace), String(key), locale, params);
|
|
103
|
+
}
|
|
122
104
|
|
|
123
|
-
|
|
124
|
-
|
|
105
|
+
getWithLocale(
|
|
106
|
+
namespace: string,
|
|
107
|
+
key: string,
|
|
108
|
+
locale: string,
|
|
109
|
+
params?: Record<string, unknown>
|
|
110
|
+
): string {
|
|
111
|
+
if (!this.loadedNamespaces.has(namespace)) {
|
|
125
112
|
throw new Error(
|
|
126
|
-
`[i18n]
|
|
113
|
+
`[i18n] Namespace not loaded: "${namespace}". Register it with setNamespace() before calling .get().`
|
|
127
114
|
);
|
|
128
115
|
}
|
|
129
116
|
|
|
130
|
-
const
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
this.compiledCache[resolvedLocale] = {};
|
|
134
|
-
}
|
|
135
|
-
|
|
136
|
-
if (!this.compiledCache[resolvedLocale][namespace as string]) {
|
|
137
|
-
this.compiledCache[resolvedLocale][namespace as string] = {};
|
|
138
|
-
}
|
|
139
|
-
|
|
140
|
-
const namespaceCache = this.compiledCache[resolvedLocale][namespace as string]!;
|
|
141
|
-
const cacheKey = String(key);
|
|
142
|
-
|
|
143
|
-
if (!namespaceCache[cacheKey]) {
|
|
144
|
-
try {
|
|
145
|
-
namespaceCache[cacheKey] = new IntlMessageFormat(template, resolvedLocale);
|
|
146
|
-
} catch (err) {
|
|
147
|
-
const message = err instanceof Error ? err.message : String(err);
|
|
148
|
-
throw new Error(
|
|
149
|
-
`[i18n ICU Syntax Error] namespace "${String(namespace)}", key "${String(key)}" [${resolvedLocale}]: ${message}`
|
|
150
|
-
);
|
|
151
|
-
}
|
|
152
|
-
}
|
|
117
|
+
const localeByKey = (
|
|
118
|
+
this.dictionary[namespace] as Record<string, Record<string, string>> | undefined
|
|
119
|
+
)?.[key];
|
|
153
120
|
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
121
|
+
return resolveAndFormat({
|
|
122
|
+
localeByKey,
|
|
123
|
+
locale,
|
|
124
|
+
params,
|
|
125
|
+
getCache: (resolvedLocale) => {
|
|
126
|
+
if (!this.compiledCache[resolvedLocale]) {
|
|
127
|
+
this.compiledCache[resolvedLocale] = {};
|
|
128
|
+
}
|
|
129
|
+
if (!this.compiledCache[resolvedLocale]![namespace]) {
|
|
130
|
+
this.compiledCache[resolvedLocale]![namespace] = {};
|
|
131
|
+
}
|
|
132
|
+
return this.compiledCache[resolvedLocale]![namespace]!;
|
|
133
|
+
},
|
|
134
|
+
context: {
|
|
135
|
+
namespace,
|
|
136
|
+
key,
|
|
137
|
+
locale,
|
|
138
|
+
localeFallback: this.localeFallback,
|
|
139
|
+
onMissing: this.onMissing,
|
|
140
|
+
},
|
|
141
|
+
});
|
|
162
142
|
}
|
|
163
143
|
|
|
164
144
|
forLocale<Locale extends RequestLocales>(
|
|
@@ -365,4 +365,71 @@ describe("IcuTranslationProviderSingle", () => {
|
|
|
365
365
|
).toThrow("[i18n] Circular locale fallback detected");
|
|
366
366
|
});
|
|
367
367
|
});
|
|
368
|
+
|
|
369
|
+
describe("onMissing", () => {
|
|
370
|
+
it('throws on missing translations with onMissing: "throw" (explicit default)', () => {
|
|
371
|
+
const local = new IcuTranslationProviderSingle<TestSchema, TestParams>(dictionary, {
|
|
372
|
+
onMissing: "throw",
|
|
373
|
+
});
|
|
374
|
+
expect(() => local.get("missing_key" as "login_button", "en")).toThrow(
|
|
375
|
+
'[i18n] Missing key or locale: "missing_key" [en] (fallback chain: en)'
|
|
376
|
+
);
|
|
377
|
+
});
|
|
378
|
+
|
|
379
|
+
it('returns the key itself with onMissing: "key"', () => {
|
|
380
|
+
const local = new IcuTranslationProviderSingle<TestSchema, TestParams>(dictionary, {
|
|
381
|
+
onMissing: "key",
|
|
382
|
+
});
|
|
383
|
+
expect(local.get("missing_key" as "login_button", "en")).toBe("missing_key");
|
|
384
|
+
});
|
|
385
|
+
|
|
386
|
+
it("calls a custom handler with the missing-translation context", () => {
|
|
387
|
+
const contexts: unknown[] = [];
|
|
388
|
+
const local = new IcuTranslationProviderSingle<TestSchema, TestParams>(dictionary, {
|
|
389
|
+
onMissing: (context) => {
|
|
390
|
+
contexts.push(context);
|
|
391
|
+
return `<missing:${context.key}>`;
|
|
392
|
+
},
|
|
393
|
+
});
|
|
394
|
+
|
|
395
|
+
expect(local.get("missing_key" as "login_button", "en")).toBe("<missing:missing_key>");
|
|
396
|
+
expect(contexts).toEqual([{ key: "missing_key", locale: "en", fallbackChain: "en" }]);
|
|
397
|
+
});
|
|
398
|
+
|
|
399
|
+
it("includes the walked fallback chain in the handler context", () => {
|
|
400
|
+
const fallbackMap = { en: null, "de-CH": "fr", fr: null } as const;
|
|
401
|
+
const contexts: { fallbackChain: string }[] = [];
|
|
402
|
+
const local = new IcuTranslationProviderSingle<
|
|
403
|
+
TestSchema,
|
|
404
|
+
TestParams,
|
|
405
|
+
keyof typeof fallbackMap | LocaleOfSingle<TestSchema>,
|
|
406
|
+
typeof fallbackMap
|
|
407
|
+
>(dictionary, {
|
|
408
|
+
localeFallback: fallbackMap,
|
|
409
|
+
onMissing: (context) => {
|
|
410
|
+
contexts.push(context);
|
|
411
|
+
return context.key;
|
|
412
|
+
},
|
|
413
|
+
});
|
|
414
|
+
|
|
415
|
+
expect(local.get("login_button", "de-CH")).toBe("login_button");
|
|
416
|
+
expect(contexts[0]?.fallbackChain).toBe("de-CH → fr");
|
|
417
|
+
});
|
|
418
|
+
|
|
419
|
+
it("still throws ICU syntax and formatting errors with a lenient onMissing", () => {
|
|
420
|
+
const local = new IcuTranslationProviderSingle<TestSchema, TestParams>(dictionary, {
|
|
421
|
+
onMissing: "key",
|
|
422
|
+
});
|
|
423
|
+
expect(() => local.get("broken", "en", { name: "Ada" })).toThrow("[i18n ICU Syntax Error]");
|
|
424
|
+
// @ts-expect-error
|
|
425
|
+
expect(() => local.get("welcome", "en")).toThrow("[i18n Formatting Error]");
|
|
426
|
+
});
|
|
427
|
+
|
|
428
|
+
it("applies onMissing through forLocale wrappers", () => {
|
|
429
|
+
const local = new IcuTranslationProviderSingle<TestSchema, TestParams>(dictionary, {
|
|
430
|
+
onMissing: "key",
|
|
431
|
+
});
|
|
432
|
+
expect(local.forLocale("en").get("missing_key" as "login_button")).toBe("missing_key");
|
|
433
|
+
});
|
|
434
|
+
});
|
|
368
435
|
});
|