@inlang/paraglide-js 2.26.0 → 2.28.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 +11 -1
- package/dist/bundler-plugins/per-locale-build/index.js +14 -7
- package/dist/bundler-plugins/per-locale-build/index.js.map +1 -1
- package/dist/bundler-plugins/per-locale-build/vite-environments.test.js +237 -4
- package/dist/bundler-plugins/per-locale-build/vite-environments.test.js.map +1 -1
- package/dist/bundler-plugins/unplugin.d.ts +1 -1
- package/dist/bundler-plugins/unplugin.js +79 -10
- package/dist/bundler-plugins/unplugin.js.map +1 -1
- package/dist/bundler-plugins/unplugin.test.js +334 -1
- package/dist/bundler-plugins/unplugin.test.js.map +1 -1
- package/dist/bundler-plugins/vite.js +2 -1
- package/dist/bundler-plugins/vite.js.map +1 -1
- package/dist/bundler-plugins/vite.test.js +1 -1
- package/dist/bundler-plugins/vite.test.js.map +1 -1
- package/dist/cli/commands/compile/command.js +13 -0
- package/dist/cli/commands/compile/command.js.map +1 -1
- package/dist/cli/commands/compile/command.test.js +87 -3
- package/dist/cli/commands/compile/command.test.js.map +1 -1
- package/dist/cli/commands/init/command.d.ts +5 -0
- package/dist/cli/commands/init/command.js +216 -44
- package/dist/cli/commands/init/command.js.map +1 -1
- package/dist/cli/commands/init/command.test.d.ts +1 -0
- package/dist/cli/commands/init/command.test.js +123 -0
- package/dist/cli/commands/init/command.test.js.map +1 -0
- package/dist/cli/defaults.js +2 -2
- package/dist/cli/defaults.js.map +1 -1
- package/dist/cli/init-options.d.ts +11 -0
- package/dist/cli/init-options.js +2 -0
- package/dist/cli/init-options.js.map +1 -0
- package/dist/cli/steps/add-inlang-check.d.ts +19 -0
- package/dist/cli/steps/add-inlang-check.js +60 -0
- package/dist/cli/steps/add-inlang-check.js.map +1 -0
- package/dist/cli/steps/add-inlang-check.test.d.ts +1 -0
- package/dist/cli/steps/add-inlang-check.test.js +88 -0
- package/dist/cli/steps/add-inlang-check.test.js.map +1 -0
- package/dist/cli/steps/add-message-lint.d.ts +34 -0
- package/dist/cli/steps/add-message-lint.js +105 -0
- package/dist/cli/steps/add-message-lint.js.map +1 -0
- package/dist/cli/steps/add-message-lint.test.d.ts +1 -0
- package/dist/cli/steps/add-message-lint.test.js +74 -0
- package/dist/cli/steps/add-message-lint.test.js.map +1 -0
- package/dist/cli/steps/add-vite-plugin.d.ts +18 -0
- package/dist/cli/steps/add-vite-plugin.js +34 -6
- package/dist/cli/steps/add-vite-plugin.js.map +1 -1
- package/dist/cli/steps/add-vite-plugin.test.js +25 -9
- package/dist/cli/steps/add-vite-plugin.test.js.map +1 -1
- package/dist/cli/steps/agents-md-suggestion.d.ts +11 -0
- package/dist/cli/steps/agents-md-suggestion.js +19 -0
- package/dist/cli/steps/agents-md-suggestion.js.map +1 -0
- package/dist/cli/steps/agents-md-suggestion.test.d.ts +1 -0
- package/dist/cli/steps/agents-md-suggestion.test.js +36 -0
- package/dist/cli/steps/agents-md-suggestion.test.js.map +1 -0
- package/dist/cli/steps/check-for-uncomitted-changes.d.ts +3 -0
- package/dist/cli/steps/check-for-uncomitted-changes.js +15 -3
- package/dist/cli/steps/check-for-uncomitted-changes.js.map +1 -1
- package/dist/cli/steps/detect-bundler.d.ts +1 -0
- package/dist/cli/steps/detect-bundler.js +7 -1
- package/dist/cli/steps/detect-bundler.js.map +1 -1
- package/dist/cli/steps/initialize-inlang-project.d.ts +4 -3
- package/dist/cli/steps/initialize-inlang-project.js +60 -157
- package/dist/cli/steps/initialize-inlang-project.js.map +1 -1
- package/dist/cli/steps/maybe-add-machine-translation.d.ts +4 -0
- package/dist/cli/steps/maybe-add-machine-translation.js +14 -8
- package/dist/cli/steps/maybe-add-machine-translation.js.map +1 -1
- package/dist/cli/steps/maybe-add-sherlock.d.ts +2 -0
- package/dist/cli/steps/maybe-add-sherlock.js +13 -7
- package/dist/cli/steps/maybe-add-sherlock.js.map +1 -1
- package/dist/cli/steps/maybe-add-sherlock.test.d.ts +1 -0
- package/dist/cli/steps/maybe-add-sherlock.test.js +44 -0
- package/dist/cli/steps/maybe-add-sherlock.test.js.map +1 -0
- package/dist/cli/steps/prompt-for-outdir.d.ts +2 -0
- package/dist/cli/steps/prompt-for-outdir.js +4 -0
- package/dist/cli/steps/prompt-for-outdir.js.map +1 -1
- package/dist/cli/steps/update-package-json.js +8 -13
- package/dist/cli/steps/update-package-json.js.map +1 -1
- package/dist/cli/steps/update-ts-config.d.ts +6 -0
- package/dist/cli/steps/update-ts-config.js +27 -4
- package/dist/cli/steps/update-ts-config.js.map +1 -1
- package/dist/cli/utils.d.ts +11 -0
- package/dist/cli/utils.js +21 -0
- package/dist/cli/utils.js.map +1 -1
- package/dist/cli/utils.test.d.ts +1 -0
- package/dist/cli/utils.test.js +16 -0
- package/dist/cli/utils.test.js.map +1 -0
- package/dist/compiler/compile-annotation.d.ts +48 -1
- package/dist/compiler/compile-annotation.js +243 -10
- package/dist/compiler/compile-annotation.js.map +1 -1
- package/dist/compiler/compile-bundle.d.ts +7 -2
- package/dist/compiler/compile-bundle.js +97 -3
- package/dist/compiler/compile-bundle.js.map +1 -1
- package/dist/compiler/compile-bundle.test.js +232 -19
- package/dist/compiler/compile-bundle.test.js.map +1 -1
- package/dist/compiler/compile-lifecycle.test.d.ts +1 -0
- package/dist/compiler/compile-lifecycle.test.js +69 -0
- package/dist/compiler/compile-lifecycle.test.js.map +1 -0
- package/dist/compiler/compile-local-variable.d.ts +3 -0
- package/dist/compiler/compile-local-variable.js +5 -2
- package/dist/compiler/compile-local-variable.js.map +1 -1
- package/dist/compiler/compile-local-variable.test.js +55 -15
- package/dist/compiler/compile-local-variable.test.js.map +1 -1
- package/dist/compiler/compile-message.d.ts +29 -1
- package/dist/compiler/compile-message.exact-number.test.d.ts +1 -0
- package/dist/compiler/compile-message.exact-number.test.js +786 -0
- package/dist/compiler/compile-message.exact-number.test.js.map +1 -0
- package/dist/compiler/compile-message.js +162 -66
- package/dist/compiler/compile-message.js.map +1 -1
- package/dist/compiler/compile-message.locals.test.d.ts +1 -0
- package/dist/compiler/compile-message.locals.test.js +498 -0
- package/dist/compiler/compile-message.locals.test.js.map +1 -0
- package/dist/compiler/compile-message.test.js +113 -22
- package/dist/compiler/compile-message.test.js.map +1 -1
- package/dist/compiler/compile-pattern.d.ts +5 -0
- package/dist/compiler/compile-pattern.js +6 -18
- package/dist/compiler/compile-pattern.js.map +1 -1
- package/dist/compiler/compile-pattern.test.js +169 -5
- package/dist/compiler/compile-pattern.test.js.map +1 -1
- package/dist/compiler/compile-project.js +5 -1
- package/dist/compiler/compile-project.js.map +1 -1
- package/dist/compiler/compile-project.test.js +1260 -185
- package/dist/compiler/compile-project.test.js.map +1 -1
- package/dist/compiler/compile.js +36 -17
- package/dist/compiler/compile.js.map +1 -1
- package/dist/compiler/compile.test.js +71 -1
- package/dist/compiler/compile.test.js.map +1 -1
- package/dist/compiler/compiler-options.d.ts +41 -0
- package/dist/compiler/compiler-options.js.map +1 -1
- package/dist/compiler/create-readme.d.ts +4 -1
- package/dist/compiler/create-readme.js +33 -125
- package/dist/compiler/create-readme.js.map +1 -1
- package/dist/compiler/emit-ts-declarations.interop.test.js +2 -2
- package/dist/compiler/emit-ts-declarations.interop.test.js.map +1 -1
- package/dist/compiler/emit-ts-declarations.test.js +4 -4
- package/dist/compiler/emit-ts-declarations.test.js.map +1 -1
- package/dist/compiler/index.d.ts +1 -1
- package/dist/compiler/index.js +1 -1
- package/dist/compiler/index.js.map +1 -1
- package/dist/compiler/input-alias.d.ts +21 -0
- package/dist/compiler/input-alias.js +42 -0
- package/dist/compiler/input-alias.js.map +1 -0
- package/dist/compiler/input-alias.test.d.ts +1 -0
- package/dist/compiler/input-alias.test.js +58 -0
- package/dist/compiler/input-alias.test.js.map +1 -0
- package/dist/compiler/message-locals.d.ts +46 -0
- package/dist/compiler/message-locals.js +129 -0
- package/dist/compiler/message-locals.js.map +1 -0
- package/dist/compiler/output-structure/locale-modules.js +7 -1
- package/dist/compiler/output-structure/locale-modules.js.map +1 -1
- package/dist/compiler/output-structure/locale-modules.test.js +35 -0
- package/dist/compiler/output-structure/locale-modules.test.js.map +1 -1
- package/dist/compiler/output-structure/message-modules.js +6 -4
- package/dist/compiler/output-structure/message-modules.js.map +1 -1
- package/dist/compiler/output-structure/message-modules.test.js +35 -0
- package/dist/compiler/output-structure/message-modules.test.js.map +1 -1
- package/dist/compiler/registry.d.ts +12 -0
- package/dist/compiler/registry.js +158 -31
- package/dist/compiler/registry.js.map +1 -1
- package/dist/compiler/registry.test.d.ts +1 -0
- package/dist/compiler/registry.test.js +291 -0
- package/dist/compiler/registry.test.js.map +1 -0
- package/dist/compiler/runtime/create-runtime.d.ts +2 -0
- package/dist/compiler/runtime/create-runtime.js +9 -0
- package/dist/compiler/runtime/create-runtime.js.map +1 -1
- package/dist/compiler/runtime/extract-locale-from-cookie.js +8 -1
- package/dist/compiler/runtime/extract-locale-from-cookie.js.map +1 -1
- package/dist/compiler/runtime/extract-locale-from-cookie.test.js +26 -0
- package/dist/compiler/runtime/extract-locale-from-cookie.test.js.map +1 -1
- package/dist/compiler/runtime/extract-locale-from-header.js +47 -5
- package/dist/compiler/runtime/extract-locale-from-header.js.map +1 -1
- package/dist/compiler/runtime/extract-locale-from-header.test.js +58 -0
- package/dist/compiler/runtime/extract-locale-from-header.test.js.map +1 -1
- package/dist/compiler/runtime/get-locale.js +7 -1
- package/dist/compiler/runtime/get-locale.js.map +1 -1
- package/dist/compiler/runtime/get-locale.test.js +95 -0
- package/dist/compiler/runtime/get-locale.test.js.map +1 -1
- package/dist/compiler/runtime/localize-href.d.ts +8 -0
- package/dist/compiler/runtime/localize-href.js +60 -0
- package/dist/compiler/runtime/localize-href.js.map +1 -1
- package/dist/compiler/runtime/localize-href.test.js +227 -1
- package/dist/compiler/runtime/localize-href.test.js.map +1 -1
- package/dist/compiler/runtime/set-locale.js +24 -6
- package/dist/compiler/runtime/set-locale.js.map +1 -1
- package/dist/compiler/runtime/set-locale.test.js +182 -0
- package/dist/compiler/runtime/set-locale.test.js.map +1 -1
- package/dist/compiler/runtime/type.d.ts +2 -0
- package/dist/compiler/runtime/type.js.map +1 -1
- package/dist/compiler/runtime/type.test.js +34 -0
- package/dist/compiler/runtime/type.test.js.map +1 -1
- package/dist/compiler/runtime/variables.d.ts +2 -0
- package/dist/compiler/runtime/variables.js +7 -0
- package/dist/compiler/runtime/variables.js.map +1 -1
- package/dist/compiler/server/create-server-file.js +24 -0
- package/dist/compiler/server/create-server-file.js.map +1 -1
- package/dist/compiler/server/create-server-file.test.js +8 -2
- package/dist/compiler/server/create-server-file.test.js.map +1 -1
- package/dist/compiler/server/middleware.d.ts +8 -2
- package/dist/compiler/server/middleware.js +204 -11
- package/dist/compiler/server/middleware.js.map +1 -1
- package/dist/compiler/server/middleware.test.js +750 -3
- package/dist/compiler/server/middleware.test.js.map +1 -1
- package/dist/eslint/index.d.ts +4 -0
- package/dist/eslint/index.js +8 -0
- package/dist/eslint/index.js.map +1 -0
- package/dist/eslint/no-dynamic-message-access.d.ts +3 -0
- package/dist/eslint/no-dynamic-message-access.js +150 -0
- package/dist/eslint/no-dynamic-message-access.js.map +1 -0
- package/dist/eslint/no-dynamic-message-access.test.d.ts +1 -0
- package/dist/eslint/no-dynamic-message-access.test.js +126 -0
- package/dist/eslint/no-dynamic-message-access.test.js.map +1 -0
- package/dist/eslint/oxlint.test.d.ts +1 -0
- package/dist/eslint/oxlint.test.js +64 -0
- package/dist/eslint/oxlint.test.js.map +1 -0
- package/dist/services/config/config-schema.d.ts +2 -0
- package/dist/services/config/config-schema.js +2 -0
- package/dist/services/config/config-schema.js.map +1 -1
- package/dist/services/config/load-paraglide-config.test.js +12 -0
- package/dist/services/config/load-paraglide-config.test.js.map +1 -1
- package/dist/services/env-variables/index.js +1 -1
- package/dist/services/env-variables/index.js.map +1 -1
- package/dist/services/file-handling/write-output.bench.js +51 -11
- package/dist/services/file-handling/write-output.bench.js.map +1 -1
- package/dist/services/file-handling/write-output.js +60 -20
- package/dist/services/file-handling/write-output.js.map +1 -1
- package/dist/services/file-handling/write-output.test.js +175 -0
- package/dist/services/file-handling/write-output.test.js.map +1 -1
- package/package.json +15 -5
|
@@ -1,21 +1,55 @@
|
|
|
1
1
|
import { compileVariableAccess } from "./variable-access.js";
|
|
2
2
|
import { escapeForDoubleQuoteString } from "../services/codegen/escape.js";
|
|
3
|
+
import { Logger } from "../services/logger/index.js";
|
|
3
4
|
/**
|
|
4
|
-
* The functions shipped in the generated registry.js file
|
|
5
|
+
* The functions shipped in the generated registry.js file, by the annotation
|
|
6
|
+
* name that calls them.
|
|
5
7
|
*
|
|
6
8
|
* @see createRegistry()
|
|
7
9
|
*/
|
|
8
|
-
const
|
|
9
|
-
"plural",
|
|
10
|
-
"number",
|
|
11
|
-
"datetime",
|
|
12
|
-
"relativetime",
|
|
10
|
+
const registryFunctionByAnnotation = new Map([
|
|
11
|
+
["plural", "plural"],
|
|
12
|
+
["number", "number"],
|
|
13
|
+
["datetime", "datetime"],
|
|
14
|
+
["relativetime", "relativetime"],
|
|
15
|
+
// `#` in ICU MessageFormat 1 plurals, as imported by the ICU1 plugin
|
|
16
|
+
["icu:pound", "icuPound"],
|
|
17
|
+
// `{d, date, short}` and `{d, time, short}` in ICU MessageFormat 1, as
|
|
18
|
+
// imported by the ICU1 plugin, see icuStyleAnnotation()
|
|
19
|
+
["date", "datetime"],
|
|
20
|
+
["time", "datetime"],
|
|
13
21
|
]);
|
|
22
|
+
/**
|
|
23
|
+
* The formatter names listed in warnings: the annotation names that call a
|
|
24
|
+
* registry function.
|
|
25
|
+
*/
|
|
26
|
+
const displayedRegistryFunctions = Array.from(registryFunctionByAnnotation.keys());
|
|
14
27
|
export function isRegistryFunction(name) {
|
|
15
|
-
return
|
|
28
|
+
return registryFunctionByAnnotation.has(name);
|
|
16
29
|
}
|
|
17
30
|
export function registryFunctionNamesForDisplay() {
|
|
18
|
-
return
|
|
31
|
+
return displayedRegistryFunctions.join(", ");
|
|
32
|
+
}
|
|
33
|
+
const logger = new Logger();
|
|
34
|
+
/**
|
|
35
|
+
* Tracks annotation names that have already been warned about to avoid
|
|
36
|
+
* spamming the console when the same unsupported formatter is used in
|
|
37
|
+
* many messages (or across watch-mode recompiles).
|
|
38
|
+
*/
|
|
39
|
+
const warnedUnsupportedAnnotations = new Set();
|
|
40
|
+
/**
|
|
41
|
+
* Returns the value unformatted, and warns once per formatter name.
|
|
42
|
+
*
|
|
43
|
+
* Unknown annotations, on pattern expressions and on local variables, fall
|
|
44
|
+
* back to plain interpolation to avoid breaking compilation of messages
|
|
45
|
+
* imported from other i18n libraries (e.g. i18next's `{{value, customFormat}}`).
|
|
46
|
+
*/
|
|
47
|
+
export function ignoreUnknownFormatter(name, value) {
|
|
48
|
+
if (!warnedUnsupportedAnnotations.has(name)) {
|
|
49
|
+
warnedUnsupportedAnnotations.add(name);
|
|
50
|
+
logger.warn(`The formatter "${name}" is unknown and will be ignored. The value is interpolated without formatting. Supported formatters: ${registryFunctionNamesForDisplay()}.`);
|
|
51
|
+
}
|
|
52
|
+
return value;
|
|
19
53
|
}
|
|
20
54
|
/**
|
|
21
55
|
* Wraps a compiled expression value in a `registry.*` call if an
|
|
@@ -25,14 +59,191 @@ export function registryFunctionNamesForDisplay() {
|
|
|
25
59
|
* compileAnnotation("i?.count", "en", { type: "function-reference", name: "number", options: [] })
|
|
26
60
|
* >> 'registry.number("en", i?.count, {})'
|
|
27
61
|
*/
|
|
28
|
-
export function compileAnnotation(str, locale, annotation, declarations) {
|
|
62
|
+
export function compileAnnotation(str, locale, annotation, declarations, registryUsage) {
|
|
29
63
|
if (!annotation) {
|
|
30
64
|
return str;
|
|
31
65
|
}
|
|
32
66
|
if (annotation.name === "relativetime") {
|
|
33
67
|
validateRelativeTimeOptions(annotation);
|
|
34
68
|
}
|
|
35
|
-
|
|
69
|
+
if (offsetAnnotations.has(annotation.name)) {
|
|
70
|
+
validateOffsetOptions(annotation);
|
|
71
|
+
}
|
|
72
|
+
const functionName = registryFunctionByAnnotation.get(annotation.name) ?? annotation.name;
|
|
73
|
+
registryUsage?.add(functionName);
|
|
74
|
+
const options = withDefaultDateTimeStyles(icuStyleAnnotation(annotation)).options;
|
|
75
|
+
// the options of `date` and `time` are those of `datetime`
|
|
76
|
+
const optionsOf = functionName === "datetime" ? "datetime" : annotation.name;
|
|
77
|
+
// compileOptions emits a plain data object, so the registry can safely cache it.
|
|
78
|
+
const cacheable = ["plural", "number", "datetime", "relativetime"].includes(functionName) &&
|
|
79
|
+
!options.some((option) => option.name === "__proto__")
|
|
80
|
+
? ", true"
|
|
81
|
+
: "";
|
|
82
|
+
return `registry.${functionName}("${locale}", ${str}, ${compileOptions(optionsOf, options, declarations)}${cacheable})`;
|
|
83
|
+
}
|
|
84
|
+
const icuDateTimeStyles = new Set(["short", "medium", "long", "full"]);
|
|
85
|
+
const intlNumberStyles = new Set(["decimal", "percent", "currency", "unit"]);
|
|
86
|
+
/**
|
|
87
|
+
* Translates the ICU MessageFormat 1 `style` of an annotation to the options
|
|
88
|
+
* of the registry function.
|
|
89
|
+
*
|
|
90
|
+
* The ICU1 plugin imports `{n, number, integer}` as `{$n :number style=integer}`
|
|
91
|
+
* and `{d, date, short}` as `{$d :date style=short}`. Intl knows the number
|
|
92
|
+
* styles "decimal", "percent", "currency" (with a `currency`) and "unit", and
|
|
93
|
+
* throws for others. The date and time styles are Intl's `dateStyle` and
|
|
94
|
+
* `timeStyle`. A style without an Intl equivalent, like an ICU skeleton
|
|
95
|
+
* (`::currency/EUR`), is left out with a warning.
|
|
96
|
+
*
|
|
97
|
+
* @example
|
|
98
|
+
* icuStyleAnnotation({ name: "date", options: [{ name: "style", value: "short" }] })
|
|
99
|
+
* >> { name: "date", options: [{ name: "dateStyle", value: "short" }] }
|
|
100
|
+
*/
|
|
101
|
+
export function icuStyleAnnotation(annotation) {
|
|
102
|
+
const style = annotation.options.find((option) => option.name === "style");
|
|
103
|
+
const others = annotation.options.filter((option) => option !== style);
|
|
104
|
+
const literal = (name, value) => ({
|
|
105
|
+
name,
|
|
106
|
+
value: { type: "literal", value },
|
|
107
|
+
});
|
|
108
|
+
if (annotation.name === "date" || annotation.name === "time") {
|
|
109
|
+
const optionName = annotation.name === "date" ? "dateStyle" : "timeStyle";
|
|
110
|
+
if (style?.value.type === "literal") {
|
|
111
|
+
if (icuDateTimeStyles.has(style.value.value)) {
|
|
112
|
+
return {
|
|
113
|
+
...annotation,
|
|
114
|
+
options: [literal(optionName, style.value.value), ...others],
|
|
115
|
+
};
|
|
116
|
+
}
|
|
117
|
+
ignoreUnknownStyle(annotation.name, style.value.value);
|
|
118
|
+
}
|
|
119
|
+
else if (style) {
|
|
120
|
+
return {
|
|
121
|
+
...annotation,
|
|
122
|
+
options: [{ name: optionName, value: style.value }, ...others],
|
|
123
|
+
};
|
|
124
|
+
}
|
|
125
|
+
// without a style, withDefaultDateTimeStyles() applies the default
|
|
126
|
+
return { ...annotation, options: others };
|
|
127
|
+
}
|
|
128
|
+
if (annotation.name === "number" && style?.value.type === "literal") {
|
|
129
|
+
const value = style.value.value;
|
|
130
|
+
if (value === "integer") {
|
|
131
|
+
const hasFractionDigits = others.some((option) => option.name === "maximumFractionDigits");
|
|
132
|
+
return {
|
|
133
|
+
...annotation,
|
|
134
|
+
options: hasFractionDigits
|
|
135
|
+
? others
|
|
136
|
+
: [literal("maximumFractionDigits", "0"), ...others],
|
|
137
|
+
};
|
|
138
|
+
}
|
|
139
|
+
const hasCurrency = others.some((option) => option.name === "currency");
|
|
140
|
+
if (!intlNumberStyles.has(value) ||
|
|
141
|
+
(value === "currency" && !hasCurrency)) {
|
|
142
|
+
ignoreUnknownStyle(annotation.name, value);
|
|
143
|
+
return { ...annotation, options: others };
|
|
144
|
+
}
|
|
145
|
+
}
|
|
146
|
+
return annotation;
|
|
147
|
+
}
|
|
148
|
+
/**
|
|
149
|
+
* The `Intl.DateTimeFormat` options that pick which parts of a date are shown.
|
|
150
|
+
* Without any of them, Intl shows only the numeric date, e.g. "10/9/2026".
|
|
151
|
+
* `dateStyle` and `timeStyle` cannot be combined with the others: Intl throws.
|
|
152
|
+
*/
|
|
153
|
+
const dateTimeFieldOptions = new Set([
|
|
154
|
+
"dateStyle",
|
|
155
|
+
"timeStyle",
|
|
156
|
+
"weekday",
|
|
157
|
+
"era",
|
|
158
|
+
"year",
|
|
159
|
+
"month",
|
|
160
|
+
"day",
|
|
161
|
+
"dayPeriod",
|
|
162
|
+
"hour",
|
|
163
|
+
"minute",
|
|
164
|
+
"second",
|
|
165
|
+
"fractionalSecondDigits",
|
|
166
|
+
"timeZoneName",
|
|
167
|
+
]);
|
|
168
|
+
/**
|
|
169
|
+
* The styles a date formatter uses when its options pick no fields.
|
|
170
|
+
*
|
|
171
|
+
* - `date`: MessageFormat 2 (LDML 47 `:date` `style=medium`) and ICU
|
|
172
|
+
* MessageFormat 1 (`{d, date}`) both default to "medium", e.g. "Oct 9, 2026".
|
|
173
|
+
* - `time`: ICU MessageFormat 1 `{d, time}` defaults to "medium", e.g.
|
|
174
|
+
* "4:30:00 PM", while MessageFormat 2 (LDML 47 `:time`) defaults to "short".
|
|
175
|
+
* `{$d :time}` is what the ICU1 plugin imports `{d, time}` as, so it keeps
|
|
176
|
+
* ICU's default. Write `{$d :time style=short}` for MessageFormat 2's.
|
|
177
|
+
* - `datetime`: MessageFormat 2 (LDML 47 `:datetime`) defaults to
|
|
178
|
+
* `dateStyle=medium timeStyle=short`, e.g. "Oct 9, 2026, 4:30 PM".
|
|
179
|
+
*/
|
|
180
|
+
const defaultDateTimeStyles = new Map([
|
|
181
|
+
["date", [["dateStyle", "medium"]]],
|
|
182
|
+
["time", [["timeStyle", "medium"]]],
|
|
183
|
+
[
|
|
184
|
+
"datetime",
|
|
185
|
+
[
|
|
186
|
+
["dateStyle", "medium"],
|
|
187
|
+
["timeStyle", "short"],
|
|
188
|
+
],
|
|
189
|
+
],
|
|
190
|
+
]);
|
|
191
|
+
/**
|
|
192
|
+
* Adds the default styles of `date`, `time` and `datetime` when the options
|
|
193
|
+
* pick no fields. Options like `timeZone` or `hour12` are kept.
|
|
194
|
+
*
|
|
195
|
+
* @example
|
|
196
|
+
* withDefaultDateTimeStyles({ name: "datetime", options: [] })
|
|
197
|
+
* >> { name: "datetime", options: [{ name: "dateStyle", value: "medium" }, { name: "timeStyle", value: "short" }] }
|
|
198
|
+
*/
|
|
199
|
+
export function withDefaultDateTimeStyles(annotation) {
|
|
200
|
+
const defaults = defaultDateTimeStyles.get(annotation.name);
|
|
201
|
+
if (!defaults ||
|
|
202
|
+
annotation.options.some((option) => dateTimeFieldOptions.has(option.name))) {
|
|
203
|
+
return annotation;
|
|
204
|
+
}
|
|
205
|
+
return {
|
|
206
|
+
...annotation,
|
|
207
|
+
options: [
|
|
208
|
+
...defaults.map(([name, value]) => ({
|
|
209
|
+
name,
|
|
210
|
+
value: { type: "literal", value },
|
|
211
|
+
})),
|
|
212
|
+
...annotation.options,
|
|
213
|
+
],
|
|
214
|
+
};
|
|
215
|
+
}
|
|
216
|
+
const warnedUnknownStyles = new Set();
|
|
217
|
+
function ignoreUnknownStyle(name, style) {
|
|
218
|
+
const key = `${name} ${style}`;
|
|
219
|
+
if (warnedUnknownStyles.has(key))
|
|
220
|
+
return;
|
|
221
|
+
warnedUnknownStyles.add(key);
|
|
222
|
+
logger.warn(`The style "${style}" of the formatter "${name}" is not supported and will be ignored.${name === "number" && style === "currency"
|
|
223
|
+
? ' The "currency" style needs a "currency" option.'
|
|
224
|
+
: ""}`);
|
|
225
|
+
}
|
|
226
|
+
/**
|
|
227
|
+
* Returns the names of the variables the compiled options of an annotation
|
|
228
|
+
* read.
|
|
229
|
+
*
|
|
230
|
+
* @example
|
|
231
|
+
* // {$date :relativetime unit=$unit}
|
|
232
|
+
* annotationVariableReferences(annotation) // ["unit"]
|
|
233
|
+
*/
|
|
234
|
+
export function annotationVariableReferences(annotation) {
|
|
235
|
+
const names = [];
|
|
236
|
+
for (const option of annotation.options) {
|
|
237
|
+
if (option.value.type === "variable-reference") {
|
|
238
|
+
names.push(option.value.name);
|
|
239
|
+
}
|
|
240
|
+
else if (annotation.name === "relativetime" &&
|
|
241
|
+
option.name === "unit" &&
|
|
242
|
+
isDollarVariableReference(option.value.value)) {
|
|
243
|
+
names.push(option.value.value.slice(1));
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
return names;
|
|
36
247
|
}
|
|
37
248
|
function compileOptions(annotationName, options, declarations) {
|
|
38
249
|
if (options.length === 0) {
|
|
@@ -83,6 +294,10 @@ function compileOptionLiteralOrVarRef(annotationName, optionName, value, declara
|
|
|
83
294
|
if (shouldEmitBooleanLiteral(annotationName, optionName, value.value)) {
|
|
84
295
|
return value.value;
|
|
85
296
|
}
|
|
297
|
+
if (offsetAnnotations.has(annotationName) && optionName === "offset") {
|
|
298
|
+
// validated by validateOffsetOptions()
|
|
299
|
+
return String(Number(value.value));
|
|
300
|
+
}
|
|
86
301
|
return `"${escapeForDoubleQuoteString(value.value)}"`;
|
|
87
302
|
}
|
|
88
303
|
function shouldEmitNumberLiteral(annotationName, optionName, literal) {
|
|
@@ -130,6 +345,24 @@ function validateRelativeTimeOptions(annotation) {
|
|
|
130
345
|
throw new Error(`Invalid "relativetime" unit "${unitOption.value.value}". Expected one of: ${Array.from(relativeTimeUnits).join(", ")}.`);
|
|
131
346
|
}
|
|
132
347
|
}
|
|
348
|
+
/**
|
|
349
|
+
* Annotations with an ICU MessageFormat 1 plural `offset` option.
|
|
350
|
+
*
|
|
351
|
+
* `{count, plural, offset:1 …}` imports as `{$count :plural offset=1}`, and
|
|
352
|
+
* `#` inside it as `{$count :icu:pound offset=1}`. The registry subtracts the
|
|
353
|
+
* offset from the input, so it has to be a number.
|
|
354
|
+
*/
|
|
355
|
+
const offsetAnnotations = new Set(["plural", "icu:pound"]);
|
|
356
|
+
const offsetPattern = /^-?(?:0|[1-9]\d*)(?:\.\d+)?$/;
|
|
357
|
+
function validateOffsetOptions(annotation) {
|
|
358
|
+
for (const option of annotation.options) {
|
|
359
|
+
if (option.name === "offset" &&
|
|
360
|
+
option.value.type === "literal" &&
|
|
361
|
+
!offsetPattern.test(option.value.value)) {
|
|
362
|
+
throw new Error(`Invalid "${annotation.name}" offset "${option.value.value}". Expected a number.`);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
}
|
|
133
366
|
function isDollarVariableReference(value) {
|
|
134
367
|
return value.startsWith("$") && value.length > 1;
|
|
135
368
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compile-annotation.js","sourceRoot":"","sources":["../../src/compiler/compile-annotation.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n\tDeclaration,\n\tFunctionReference,\n\tLiteral,\n\tVariableReference,\n} from \"@inlang/sdk\";\nimport { compileVariableAccess } from \"./variable-access.js\";\nimport { escapeForDoubleQuoteString } from \"../services/codegen/escape.js\";\n\n/**\n * The functions shipped in the generated registry.js file.\n *\n * @see createRegistry()\n */\nconst registryFunctionNames = new Set([\n\t\"plural\",\n\t\"number\",\n\t\"datetime\",\n\t\"relativetime\",\n]);\n\nexport function isRegistryFunction(name: string): boolean {\n\treturn registryFunctionNames.has(name);\n}\n\nexport function registryFunctionNamesForDisplay(): string {\n\treturn Array.from(registryFunctionNames).join(\", \");\n}\n\n/**\n * Wraps a compiled expression value in a `registry.*` call if an\n * annotation is present.\n *\n * @example\n * compileAnnotation(\"i?.count\", \"en\", { type: \"function-reference\", name: \"number\", options: [] })\n * >> 'registry.number(\"en\", i?.count, {})'\n */\nexport function compileAnnotation(\n\tstr: string,\n\tlocale: string,\n\tannotation?: FunctionReference,\n\tdeclarations?: Declaration[]\n): string {\n\tif (!annotation) {\n\t\treturn str;\n\t}\n\tif (annotation.name === \"relativetime\") {\n\t\tvalidateRelativeTimeOptions(annotation);\n\t}\n\treturn `registry.${annotation.name}(\"${locale}\", ${str}, ${compileOptions(annotation.name, annotation.options, declarations)})`;\n}\n\nfunction compileOptions(\n\tannotationName: string,\n\toptions: FunctionReference[\"options\"],\n\tdeclarations?: Declaration[]\n): string {\n\tif (options.length === 0) {\n\t\treturn \"{}\";\n\t}\n\tconst entries: string[] = options.map(\n\t\t(option) =>\n\t\t\t`${option.name}: ${compileOptionLiteralOrVarRef(\n\t\t\t\tannotationName,\n\t\t\t\toption.name,\n\t\t\t\toption.value,\n\t\t\t\tdeclarations\n\t\t\t)}`\n\t);\n\tconst code = \"{ \" + entries.join(\", \") + \" }\";\n\n\treturn code;\n}\n\nconst numericOptionNamesByAnnotation: Record<string, ReadonlySet<string>> = {\n\tnumber: new Set([\n\t\t\"minimumIntegerDigits\",\n\t\t\"minimumFractionDigits\",\n\t\t\"maximumFractionDigits\",\n\t\t\"minimumSignificantDigits\",\n\t\t\"maximumSignificantDigits\",\n\t\t\"roundingIncrement\",\n\t]),\n\tplural: new Set([\n\t\t\"minimumIntegerDigits\",\n\t\t\"minimumFractionDigits\",\n\t\t\"maximumFractionDigits\",\n\t\t\"minimumSignificantDigits\",\n\t\t\"maximumSignificantDigits\",\n\t]),\n\tdatetime: new Set([\"fractionalSecondDigits\"]),\n};\n\nconst booleanOptionNamesByAnnotation: Record<string, ReadonlySet<string>> = {\n\tnumber: new Set([\"useGrouping\"]),\n\tdatetime: new Set([\"hour12\"]),\n};\n\nconst jsNonNegativeIntegerPattern = /^(?:0|[1-9]\\d*)$/;\n\nfunction compileOptionLiteralOrVarRef(\n\tannotationName: string,\n\toptionName: string,\n\tvalue: Literal | VariableReference,\n\tdeclarations?: Declaration[]\n): string {\n\tif (value.type === \"variable-reference\") {\n\t\tif (annotationName === \"relativetime\" && optionName === \"unit\") {\n\t\t\treturn `/** @type {import(\"../registry.js\").RelativeTimeFormatUnit} */ (${compileVariableAccess(value.name, declarations)})`;\n\t\t}\n\t\treturn compileVariableAccess(value.name, declarations);\n\t}\n\n\tif (\n\t\tannotationName === \"relativetime\" &&\n\t\toptionName === \"unit\" &&\n\t\tisDollarVariableReference(value.value)\n\t) {\n\t\treturn `/** @type {import(\"../registry.js\").RelativeTimeFormatUnit} */ (${compileVariableAccess(value.value.slice(1), declarations)})`;\n\t}\n\n\tif (shouldEmitNumberLiteral(annotationName, optionName, value.value)) {\n\t\treturn value.value;\n\t}\n\n\tif (shouldEmitBooleanLiteral(annotationName, optionName, value.value)) {\n\t\treturn value.value;\n\t}\n\n\treturn `\"${escapeForDoubleQuoteString(value.value)}\"`;\n}\n\nfunction shouldEmitNumberLiteral(\n\tannotationName: string,\n\toptionName: string,\n\tliteral: string\n): boolean {\n\treturn (\n\t\tnumericOptionNamesByAnnotation[annotationName]?.has(optionName) === true &&\n\t\tjsNonNegativeIntegerPattern.test(literal)\n\t);\n}\n\nfunction shouldEmitBooleanLiteral(\n\tannotationName: string,\n\toptionName: string,\n\tliteral: string\n): boolean {\n\treturn (\n\t\tbooleanOptionNamesByAnnotation[annotationName]?.has(optionName) === true &&\n\t\t(literal === \"true\" || literal === \"false\")\n\t);\n}\n\nconst relativeTimeUnits = new Set([\n\t\"year\",\n\t\"years\",\n\t\"quarter\",\n\t\"quarters\",\n\t\"month\",\n\t\"months\",\n\t\"week\",\n\t\"weeks\",\n\t\"day\",\n\t\"days\",\n\t\"hour\",\n\t\"hours\",\n\t\"minute\",\n\t\"minutes\",\n\t\"second\",\n\t\"seconds\",\n]);\n\nfunction validateRelativeTimeOptions(annotation: FunctionReference): void {\n\tconst unitOptions = annotation.options.filter(\n\t\t(option) => option.name === \"unit\"\n\t);\n\n\tif (unitOptions.length === 0) {\n\t\tthrow new Error('The \"relativetime\" formatter requires a \"unit\" option.');\n\t}\n\n\tif (unitOptions.length > 1) {\n\t\tthrow new Error(\n\t\t\t'The \"relativetime\" formatter requires exactly one \"unit\" option.'\n\t\t);\n\t}\n\n\tconst [unitOption] = unitOptions;\n\tif (!unitOption || unitOption.value.type === \"variable-reference\") {\n\t\treturn;\n\t}\n\n\tif (isDollarVariableReference(unitOption.value.value)) {\n\t\treturn;\n\t}\n\n\tif (!relativeTimeUnits.has(unitOption.value.value)) {\n\t\tthrow new Error(\n\t\t\t`Invalid \"relativetime\" unit \"${unitOption.value.value}\". Expected one of: ${Array.from(\n\t\t\t\trelativeTimeUnits\n\t\t\t).join(\", \")}.`\n\t\t);\n\t}\n}\n\nfunction isDollarVariableReference(value: string): boolean {\n\treturn value.startsWith(\"$\") && value.length > 1;\n}\n"]}
|
|
1
|
+
{"version":3,"file":"compile-annotation.js","sourceRoot":"","sources":["../../src/compiler/compile-annotation.ts"],"names":[],"mappings":"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","sourcesContent":["import type {\n\tDeclaration,\n\tFunctionReference,\n\tLiteral,\n\tVariableReference,\n} from \"@inlang/sdk\";\nimport { compileVariableAccess } from \"./variable-access.js\";\nimport { escapeForDoubleQuoteString } from \"../services/codegen/escape.js\";\nimport { Logger } from \"../services/logger/index.js\";\n\n/**\n * The functions shipped in the generated registry.js file, by the annotation\n * name that calls them.\n *\n * @see createRegistry()\n */\nconst registryFunctionByAnnotation = new Map([\n\t[\"plural\", \"plural\"],\n\t[\"number\", \"number\"],\n\t[\"datetime\", \"datetime\"],\n\t[\"relativetime\", \"relativetime\"],\n\t// `#` in ICU MessageFormat 1 plurals, as imported by the ICU1 plugin\n\t[\"icu:pound\", \"icuPound\"],\n\t// `{d, date, short}` and `{d, time, short}` in ICU MessageFormat 1, as\n\t// imported by the ICU1 plugin, see icuStyleAnnotation()\n\t[\"date\", \"datetime\"],\n\t[\"time\", \"datetime\"],\n]);\n\n/**\n * The formatter names listed in warnings: the annotation names that call a\n * registry function.\n */\nconst displayedRegistryFunctions = Array.from(\n\tregistryFunctionByAnnotation.keys()\n);\n\nexport function isRegistryFunction(name: string): boolean {\n\treturn registryFunctionByAnnotation.has(name);\n}\n\nexport function registryFunctionNamesForDisplay(): string {\n\treturn displayedRegistryFunctions.join(\", \");\n}\n\nconst logger = new Logger();\n\n/**\n * Tracks annotation names that have already been warned about to avoid\n * spamming the console when the same unsupported formatter is used in\n * many messages (or across watch-mode recompiles).\n */\nconst warnedUnsupportedAnnotations = new Set<string>();\n\n/**\n * Returns the value unformatted, and warns once per formatter name.\n *\n * Unknown annotations, on pattern expressions and on local variables, fall\n * back to plain interpolation to avoid breaking compilation of messages\n * imported from other i18n libraries (e.g. i18next's `{{value, customFormat}}`).\n */\nexport function ignoreUnknownFormatter(name: string, value: string): string {\n\tif (!warnedUnsupportedAnnotations.has(name)) {\n\t\twarnedUnsupportedAnnotations.add(name);\n\t\tlogger.warn(\n\t\t\t`The formatter \"${name}\" is unknown and will be ignored. The value is interpolated without formatting. Supported formatters: ${registryFunctionNamesForDisplay()}.`\n\t\t);\n\t}\n\treturn value;\n}\n\n/**\n * The names of the registry functions a message calls, collected while it is\n * compiled. The output decides from it whether to import the registry.\n */\nexport type RegistryUsage = Set<string>;\n\n/**\n * Wraps a compiled expression value in a `registry.*` call if an\n * annotation is present.\n *\n * @example\n * compileAnnotation(\"i?.count\", \"en\", { type: \"function-reference\", name: \"number\", options: [] })\n * >> 'registry.number(\"en\", i?.count, {})'\n */\nexport function compileAnnotation(\n\tstr: string,\n\tlocale: string,\n\tannotation?: FunctionReference,\n\tdeclarations?: Declaration[],\n\tregistryUsage?: RegistryUsage\n): string {\n\tif (!annotation) {\n\t\treturn str;\n\t}\n\tif (annotation.name === \"relativetime\") {\n\t\tvalidateRelativeTimeOptions(annotation);\n\t}\n\tif (offsetAnnotations.has(annotation.name)) {\n\t\tvalidateOffsetOptions(annotation);\n\t}\n\tconst functionName =\n\t\tregistryFunctionByAnnotation.get(annotation.name) ?? annotation.name;\n\tregistryUsage?.add(functionName);\n\tconst options = withDefaultDateTimeStyles(\n\t\ticuStyleAnnotation(annotation)\n\t).options;\n\t// the options of `date` and `time` are those of `datetime`\n\tconst optionsOf = functionName === \"datetime\" ? \"datetime\" : annotation.name;\n\t// compileOptions emits a plain data object, so the registry can safely cache it.\n\tconst cacheable =\n\t\t[\"plural\", \"number\", \"datetime\", \"relativetime\"].includes(functionName) &&\n\t\t!options.some((option) => option.name === \"__proto__\")\n\t\t\t? \", true\"\n\t\t\t: \"\";\n\treturn `registry.${functionName}(\"${locale}\", ${str}, ${compileOptions(optionsOf, options, declarations)}${cacheable})`;\n}\n\nconst icuDateTimeStyles = new Set([\"short\", \"medium\", \"long\", \"full\"]);\n\nconst intlNumberStyles = new Set([\"decimal\", \"percent\", \"currency\", \"unit\"]);\n\n/**\n * Translates the ICU MessageFormat 1 `style` of an annotation to the options\n * of the registry function.\n *\n * The ICU1 plugin imports `{n, number, integer}` as `{$n :number style=integer}`\n * and `{d, date, short}` as `{$d :date style=short}`. Intl knows the number\n * styles \"decimal\", \"percent\", \"currency\" (with a `currency`) and \"unit\", and\n * throws for others. The date and time styles are Intl's `dateStyle` and\n * `timeStyle`. A style without an Intl equivalent, like an ICU skeleton\n * (`::currency/EUR`), is left out with a warning.\n *\n * @example\n * icuStyleAnnotation({ name: \"date\", options: [{ name: \"style\", value: \"short\" }] })\n * >> { name: \"date\", options: [{ name: \"dateStyle\", value: \"short\" }] }\n */\nexport function icuStyleAnnotation(\n\tannotation: FunctionReference\n): FunctionReference {\n\tconst style = annotation.options.find((option) => option.name === \"style\");\n\tconst others = annotation.options.filter((option) => option !== style);\n\tconst literal = (name: string, value: string) => ({\n\t\tname,\n\t\tvalue: { type: \"literal\" as const, value },\n\t});\n\n\tif (annotation.name === \"date\" || annotation.name === \"time\") {\n\t\tconst optionName = annotation.name === \"date\" ? \"dateStyle\" : \"timeStyle\";\n\t\tif (style?.value.type === \"literal\") {\n\t\t\tif (icuDateTimeStyles.has(style.value.value)) {\n\t\t\t\treturn {\n\t\t\t\t\t...annotation,\n\t\t\t\t\toptions: [literal(optionName, style.value.value), ...others],\n\t\t\t\t};\n\t\t\t}\n\t\t\tignoreUnknownStyle(annotation.name, style.value.value);\n\t\t} else if (style) {\n\t\t\treturn {\n\t\t\t\t...annotation,\n\t\t\t\toptions: [{ name: optionName, value: style.value }, ...others],\n\t\t\t};\n\t\t}\n\t\t// without a style, withDefaultDateTimeStyles() applies the default\n\t\treturn { ...annotation, options: others };\n\t}\n\n\tif (annotation.name === \"number\" && style?.value.type === \"literal\") {\n\t\tconst value = style.value.value;\n\t\tif (value === \"integer\") {\n\t\t\tconst hasFractionDigits = others.some(\n\t\t\t\t(option) => option.name === \"maximumFractionDigits\"\n\t\t\t);\n\t\t\treturn {\n\t\t\t\t...annotation,\n\t\t\t\toptions: hasFractionDigits\n\t\t\t\t\t? others\n\t\t\t\t\t: [literal(\"maximumFractionDigits\", \"0\"), ...others],\n\t\t\t};\n\t\t}\n\t\tconst hasCurrency = others.some((option) => option.name === \"currency\");\n\t\tif (\n\t\t\t!intlNumberStyles.has(value) ||\n\t\t\t(value === \"currency\" && !hasCurrency)\n\t\t) {\n\t\t\tignoreUnknownStyle(annotation.name, value);\n\t\t\treturn { ...annotation, options: others };\n\t\t}\n\t}\n\n\treturn annotation;\n}\n\n/**\n * The `Intl.DateTimeFormat` options that pick which parts of a date are shown.\n * Without any of them, Intl shows only the numeric date, e.g. \"10/9/2026\".\n * `dateStyle` and `timeStyle` cannot be combined with the others: Intl throws.\n */\nconst dateTimeFieldOptions = new Set([\n\t\"dateStyle\",\n\t\"timeStyle\",\n\t\"weekday\",\n\t\"era\",\n\t\"year\",\n\t\"month\",\n\t\"day\",\n\t\"dayPeriod\",\n\t\"hour\",\n\t\"minute\",\n\t\"second\",\n\t\"fractionalSecondDigits\",\n\t\"timeZoneName\",\n]);\n\n/**\n * The styles a date formatter uses when its options pick no fields.\n *\n * - `date`: MessageFormat 2 (LDML 47 `:date` `style=medium`) and ICU\n * MessageFormat 1 (`{d, date}`) both default to \"medium\", e.g. \"Oct 9, 2026\".\n * - `time`: ICU MessageFormat 1 `{d, time}` defaults to \"medium\", e.g.\n * \"4:30:00 PM\", while MessageFormat 2 (LDML 47 `:time`) defaults to \"short\".\n * `{$d :time}` is what the ICU1 plugin imports `{d, time}` as, so it keeps\n * ICU's default. Write `{$d :time style=short}` for MessageFormat 2's.\n * - `datetime`: MessageFormat 2 (LDML 47 `:datetime`) defaults to\n * `dateStyle=medium timeStyle=short`, e.g. \"Oct 9, 2026, 4:30 PM\".\n */\nconst defaultDateTimeStyles = new Map<string, Array<[string, string]>>([\n\t[\"date\", [[\"dateStyle\", \"medium\"]]],\n\t[\"time\", [[\"timeStyle\", \"medium\"]]],\n\t[\n\t\t\"datetime\",\n\t\t[\n\t\t\t[\"dateStyle\", \"medium\"],\n\t\t\t[\"timeStyle\", \"short\"],\n\t\t],\n\t],\n]);\n\n/**\n * Adds the default styles of `date`, `time` and `datetime` when the options\n * pick no fields. Options like `timeZone` or `hour12` are kept.\n *\n * @example\n * withDefaultDateTimeStyles({ name: \"datetime\", options: [] })\n * >> { name: \"datetime\", options: [{ name: \"dateStyle\", value: \"medium\" }, { name: \"timeStyle\", value: \"short\" }] }\n */\nexport function withDefaultDateTimeStyles(\n\tannotation: FunctionReference\n): FunctionReference {\n\tconst defaults = defaultDateTimeStyles.get(annotation.name);\n\tif (\n\t\t!defaults ||\n\t\tannotation.options.some((option) => dateTimeFieldOptions.has(option.name))\n\t) {\n\t\treturn annotation;\n\t}\n\treturn {\n\t\t...annotation,\n\t\toptions: [\n\t\t\t...defaults.map(([name, value]) => ({\n\t\t\t\tname,\n\t\t\t\tvalue: { type: \"literal\" as const, value },\n\t\t\t})),\n\t\t\t...annotation.options,\n\t\t],\n\t};\n}\n\nconst warnedUnknownStyles = new Set<string>();\n\nfunction ignoreUnknownStyle(name: string, style: string): void {\n\tconst key = `${name} ${style}`;\n\tif (warnedUnknownStyles.has(key)) return;\n\twarnedUnknownStyles.add(key);\n\tlogger.warn(\n\t\t`The style \"${style}\" of the formatter \"${name}\" is not supported and will be ignored.${\n\t\t\tname === \"number\" && style === \"currency\"\n\t\t\t\t? ' The \"currency\" style needs a \"currency\" option.'\n\t\t\t\t: \"\"\n\t\t}`\n\t);\n}\n\n/**\n * Returns the names of the variables the compiled options of an annotation\n * read.\n *\n * @example\n * // {$date :relativetime unit=$unit}\n * annotationVariableReferences(annotation) // [\"unit\"]\n */\nexport function annotationVariableReferences(\n\tannotation: FunctionReference\n): string[] {\n\tconst names: string[] = [];\n\tfor (const option of annotation.options) {\n\t\tif (option.value.type === \"variable-reference\") {\n\t\t\tnames.push(option.value.name);\n\t\t} else if (\n\t\t\tannotation.name === \"relativetime\" &&\n\t\t\toption.name === \"unit\" &&\n\t\t\tisDollarVariableReference(option.value.value)\n\t\t) {\n\t\t\tnames.push(option.value.value.slice(1));\n\t\t}\n\t}\n\treturn names;\n}\n\nfunction compileOptions(\n\tannotationName: string,\n\toptions: FunctionReference[\"options\"],\n\tdeclarations?: Declaration[]\n): string {\n\tif (options.length === 0) {\n\t\treturn \"{}\";\n\t}\n\tconst entries: string[] = options.map(\n\t\t(option) =>\n\t\t\t`${option.name}: ${compileOptionLiteralOrVarRef(\n\t\t\t\tannotationName,\n\t\t\t\toption.name,\n\t\t\t\toption.value,\n\t\t\t\tdeclarations\n\t\t\t)}`\n\t);\n\tconst code = \"{ \" + entries.join(\", \") + \" }\";\n\n\treturn code;\n}\n\nconst numericOptionNamesByAnnotation: Record<string, ReadonlySet<string>> = {\n\tnumber: new Set([\n\t\t\"minimumIntegerDigits\",\n\t\t\"minimumFractionDigits\",\n\t\t\"maximumFractionDigits\",\n\t\t\"minimumSignificantDigits\",\n\t\t\"maximumSignificantDigits\",\n\t\t\"roundingIncrement\",\n\t]),\n\tplural: new Set([\n\t\t\"minimumIntegerDigits\",\n\t\t\"minimumFractionDigits\",\n\t\t\"maximumFractionDigits\",\n\t\t\"minimumSignificantDigits\",\n\t\t\"maximumSignificantDigits\",\n\t]),\n\tdatetime: new Set([\"fractionalSecondDigits\"]),\n};\n\nconst booleanOptionNamesByAnnotation: Record<string, ReadonlySet<string>> = {\n\tnumber: new Set([\"useGrouping\"]),\n\tdatetime: new Set([\"hour12\"]),\n};\n\nconst jsNonNegativeIntegerPattern = /^(?:0|[1-9]\\d*)$/;\n\nfunction compileOptionLiteralOrVarRef(\n\tannotationName: string,\n\toptionName: string,\n\tvalue: Literal | VariableReference,\n\tdeclarations?: Declaration[]\n): string {\n\tif (value.type === \"variable-reference\") {\n\t\tif (annotationName === \"relativetime\" && optionName === \"unit\") {\n\t\t\treturn `/** @type {import(\"../registry.js\").RelativeTimeFormatUnit} */ (${compileVariableAccess(value.name, declarations)})`;\n\t\t}\n\t\treturn compileVariableAccess(value.name, declarations);\n\t}\n\n\tif (\n\t\tannotationName === \"relativetime\" &&\n\t\toptionName === \"unit\" &&\n\t\tisDollarVariableReference(value.value)\n\t) {\n\t\treturn `/** @type {import(\"../registry.js\").RelativeTimeFormatUnit} */ (${compileVariableAccess(value.value.slice(1), declarations)})`;\n\t}\n\n\tif (shouldEmitNumberLiteral(annotationName, optionName, value.value)) {\n\t\treturn value.value;\n\t}\n\n\tif (shouldEmitBooleanLiteral(annotationName, optionName, value.value)) {\n\t\treturn value.value;\n\t}\n\n\tif (offsetAnnotations.has(annotationName) && optionName === \"offset\") {\n\t\t// validated by validateOffsetOptions()\n\t\treturn String(Number(value.value));\n\t}\n\n\treturn `\"${escapeForDoubleQuoteString(value.value)}\"`;\n}\n\nfunction shouldEmitNumberLiteral(\n\tannotationName: string,\n\toptionName: string,\n\tliteral: string\n): boolean {\n\treturn (\n\t\tnumericOptionNamesByAnnotation[annotationName]?.has(optionName) === true &&\n\t\tjsNonNegativeIntegerPattern.test(literal)\n\t);\n}\n\nfunction shouldEmitBooleanLiteral(\n\tannotationName: string,\n\toptionName: string,\n\tliteral: string\n): boolean {\n\treturn (\n\t\tbooleanOptionNamesByAnnotation[annotationName]?.has(optionName) === true &&\n\t\t(literal === \"true\" || literal === \"false\")\n\t);\n}\n\nconst relativeTimeUnits = new Set([\n\t\"year\",\n\t\"years\",\n\t\"quarter\",\n\t\"quarters\",\n\t\"month\",\n\t\"months\",\n\t\"week\",\n\t\"weeks\",\n\t\"day\",\n\t\"days\",\n\t\"hour\",\n\t\"hours\",\n\t\"minute\",\n\t\"minutes\",\n\t\"second\",\n\t\"seconds\",\n]);\n\nfunction validateRelativeTimeOptions(annotation: FunctionReference): void {\n\tconst unitOptions = annotation.options.filter(\n\t\t(option) => option.name === \"unit\"\n\t);\n\n\tif (unitOptions.length === 0) {\n\t\tthrow new Error('The \"relativetime\" formatter requires a \"unit\" option.');\n\t}\n\n\tif (unitOptions.length > 1) {\n\t\tthrow new Error(\n\t\t\t'The \"relativetime\" formatter requires exactly one \"unit\" option.'\n\t\t);\n\t}\n\n\tconst [unitOption] = unitOptions;\n\tif (!unitOption || unitOption.value.type === \"variable-reference\") {\n\t\treturn;\n\t}\n\n\tif (isDollarVariableReference(unitOption.value.value)) {\n\t\treturn;\n\t}\n\n\tif (!relativeTimeUnits.has(unitOption.value.value)) {\n\t\tthrow new Error(\n\t\t\t`Invalid \"relativetime\" unit \"${unitOption.value.value}\". Expected one of: ${Array.from(\n\t\t\t\trelativeTimeUnits\n\t\t\t).join(\", \")}.`\n\t\t);\n\t}\n}\n\n/**\n * Annotations with an ICU MessageFormat 1 plural `offset` option.\n *\n * `{count, plural, offset:1 …}` imports as `{$count :plural offset=1}`, and\n * `#` inside it as `{$count :icu:pound offset=1}`. The registry subtracts the\n * offset from the input, so it has to be a number.\n */\nconst offsetAnnotations = new Set([\"plural\", \"icu:pound\"]);\n\nconst offsetPattern = /^-?(?:0|[1-9]\\d*)(?:\\.\\d+)?$/;\n\nfunction validateOffsetOptions(annotation: FunctionReference): void {\n\tfor (const option of annotation.options) {\n\t\tif (\n\t\t\toption.name === \"offset\" &&\n\t\t\toption.value.type === \"literal\" &&\n\t\t\t!offsetPattern.test(option.value.value)\n\t\t) {\n\t\t\tthrow new Error(\n\t\t\t\t`Invalid \"${annotation.name}\" offset \"${option.value.value}\". Expected a number.`\n\t\t\t);\n\t\t}\n\t}\n}\n\nfunction isDollarVariableReference(value: string): boolean {\n\treturn value.startsWith(\"$\") && value.length > 1;\n}\n"]}
|
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import type { Bundle, BundleNested,
|
|
1
|
+
import type { Bundle, BundleNested, ProjectSettings } from "@inlang/sdk";
|
|
2
|
+
import { type CompiledMessage } from "./compile-message.js";
|
|
2
3
|
import type { Compiled } from "./types.js";
|
|
3
4
|
import { type InputMatchTypes } from "./jsdoc-types.js";
|
|
4
5
|
import type { CompilerOptions } from "./compiler-options.js";
|
|
@@ -7,12 +8,14 @@ export type CompiledBundleWithMessages = {
|
|
|
7
8
|
bundle: Compiled<Bundle>;
|
|
8
9
|
/** The compilation results for the languages */
|
|
9
10
|
messages: {
|
|
10
|
-
[locale: string]:
|
|
11
|
+
[locale: string]: CompiledMessage;
|
|
11
12
|
};
|
|
12
13
|
/** Match literal types inferred from bundle variants */
|
|
13
14
|
matchTypes: InputMatchTypes;
|
|
14
15
|
/** Shared typedef name for bundle input types used across emitted JSDoc */
|
|
15
16
|
inputTypeAliasName?: string;
|
|
17
|
+
/** Compiled message helpers with no emitted reference in message-modules. */
|
|
18
|
+
unreferencedMessageLocales?: string[];
|
|
16
19
|
};
|
|
17
20
|
/**
|
|
18
21
|
* Compiles all the messages in the bundle and returns an index-function + each compiled message
|
|
@@ -22,6 +25,8 @@ export declare const compileBundle: (args: {
|
|
|
22
25
|
fallbackMap: Record<string, string | undefined>;
|
|
23
26
|
messageReferenceExpression: (locale: string, bundleId: string) => string;
|
|
24
27
|
settings?: ProjectSettings;
|
|
28
|
+
/** Internal layout control; locale modules keep text grouped by language. */
|
|
29
|
+
inlineMessages?: boolean;
|
|
25
30
|
experimentalMiddlewareLocaleSplitting?: boolean;
|
|
26
31
|
experimentalStaticLocale?: CompilerOptions["experimentalStaticLocale"];
|
|
27
32
|
}) => CompiledBundleWithMessages;
|
|
@@ -4,6 +4,7 @@ import { isValidIdentifier, quotePropertyKey } from "./variable-access.js";
|
|
|
4
4
|
import { toSafeModuleId } from "./safe-module-id.js";
|
|
5
5
|
import { escapeForDoubleQuoteString } from "../services/codegen/escape.js";
|
|
6
6
|
import { perLocaleBuildStaticLocaleExpression } from "./per-locale-build.js";
|
|
7
|
+
import { resolveInputAlias } from "./input-alias.js";
|
|
7
8
|
/**
|
|
8
9
|
* Compiles all the messages in the bundle and returns an index-function + each compiled message
|
|
9
10
|
*/
|
|
@@ -21,11 +22,22 @@ export const compileBundle = (args) => {
|
|
|
21
22
|
// set the pattern for the language tag
|
|
22
23
|
compiledMessages[message.locale] = compiledMessage;
|
|
23
24
|
}
|
|
25
|
+
const inlinePlainTextByLocale = args.inlineMessages !== true ||
|
|
26
|
+
args.experimentalStaticLocale === perLocaleBuildStaticLocaleExpression
|
|
27
|
+
? undefined
|
|
28
|
+
: findPlainTextMessages(args.bundle);
|
|
29
|
+
const unreferencedMessageLocales = findUnreferencedMessageLocales({
|
|
30
|
+
inlinePlainTextByLocale: inlinePlainTextByLocale ?? Object.create(null),
|
|
31
|
+
compiledMessages,
|
|
32
|
+
fallbackMap: args.fallbackMap,
|
|
33
|
+
hasMarkup,
|
|
34
|
+
});
|
|
24
35
|
return {
|
|
25
36
|
bundle: compileBundleFunction({
|
|
26
37
|
bundle: args.bundle,
|
|
27
38
|
availableLocales: Object.keys(args.fallbackMap),
|
|
28
39
|
messageReferenceExpression: args.messageReferenceExpression,
|
|
40
|
+
inlinePlainTextByLocale,
|
|
29
41
|
settings: args.settings,
|
|
30
42
|
matchTypes,
|
|
31
43
|
hasMarkup,
|
|
@@ -36,8 +48,54 @@ export const compileBundle = (args) => {
|
|
|
36
48
|
messages: compiledMessages,
|
|
37
49
|
matchTypes,
|
|
38
50
|
inputTypeAliasName,
|
|
51
|
+
unreferencedMessageLocales,
|
|
39
52
|
};
|
|
40
53
|
};
|
|
54
|
+
/**
|
|
55
|
+
* Finds one-variant messages whose pattern is entirely static text. Their
|
|
56
|
+
* dispatcher branch can return the string directly without retaining a
|
|
57
|
+
* locale message function in the client bundle.
|
|
58
|
+
*/
|
|
59
|
+
function findPlainTextMessages(bundle) {
|
|
60
|
+
const result = Object.create(null);
|
|
61
|
+
for (const message of bundle.messages) {
|
|
62
|
+
if (message.variants.length !== 1)
|
|
63
|
+
continue;
|
|
64
|
+
const variant = message.variants[0];
|
|
65
|
+
if (!variant || !variant.pattern.every((part) => part.type === "text")) {
|
|
66
|
+
continue;
|
|
67
|
+
}
|
|
68
|
+
// compilePattern emits static text inside a template literal, whose
|
|
69
|
+
// cooked value normalizes CR and CRLF line endings to LF.
|
|
70
|
+
result[message.locale] = variant.pattern
|
|
71
|
+
.map((part) => (part.type === "text" ? part.value : ""))
|
|
72
|
+
.join("")
|
|
73
|
+
.replace(/\r\n?/g, "\n");
|
|
74
|
+
}
|
|
75
|
+
return result;
|
|
76
|
+
}
|
|
77
|
+
function findUnreferencedMessageLocales(args) {
|
|
78
|
+
if (args.hasMarkup)
|
|
79
|
+
return [];
|
|
80
|
+
// Missing-locale aliases still call the first available compiled fallback
|
|
81
|
+
// function, even when the dispatcher's own branch uses an inline string.
|
|
82
|
+
const fallbackTargets = new Set();
|
|
83
|
+
for (const locale of Object.keys(args.fallbackMap)) {
|
|
84
|
+
if (Object.hasOwn(args.compiledMessages, locale))
|
|
85
|
+
continue;
|
|
86
|
+
let fallbackLocale = args.fallbackMap[locale];
|
|
87
|
+
const visited = new Set([locale]);
|
|
88
|
+
while (fallbackLocale && !visited.has(fallbackLocale)) {
|
|
89
|
+
visited.add(fallbackLocale);
|
|
90
|
+
if (Object.hasOwn(args.compiledMessages, fallbackLocale)) {
|
|
91
|
+
fallbackTargets.add(fallbackLocale);
|
|
92
|
+
break;
|
|
93
|
+
}
|
|
94
|
+
fallbackLocale = args.fallbackMap[fallbackLocale];
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
return Object.keys(args.inlinePlainTextByLocale).filter((locale) => !fallbackTargets.has(locale));
|
|
98
|
+
}
|
|
41
99
|
const compileBundleFunction = (args) => {
|
|
42
100
|
const inputs = args.bundle.declarations.filter((decl) => decl.type === "input-variable");
|
|
43
101
|
const hasInputs = inputs.length > 0;
|
|
@@ -51,6 +109,7 @@ const compileBundleFunction = (args) => {
|
|
|
51
109
|
baseLocale,
|
|
52
110
|
]
|
|
53
111
|
: args.availableLocales;
|
|
112
|
+
const allStringBranchesInline = dispatchLocales.every((locale) => args.inlinePlainTextByLocale?.[locale] !== undefined);
|
|
54
113
|
const inputType = args.inputTypeAliasName;
|
|
55
114
|
const localesUnion = args.availableLocales.length === 0
|
|
56
115
|
? "never"
|
|
@@ -69,9 +128,16 @@ const compileBundleFunction = (args) => {
|
|
|
69
128
|
const prefix = index > 0 ? continuationIndent : "";
|
|
70
129
|
const messageRef = args.messageReferenceExpression(locale, args.bundle.id);
|
|
71
130
|
if (mode === "string") {
|
|
131
|
+
const inlineText = args.inlinePlainTextByLocale?.[locale];
|
|
132
|
+
if (inlineText !== undefined) {
|
|
133
|
+
return `${prefix}${condition}return /** @type {LocalizedString} */ (${JSON.stringify(inlineText)})`;
|
|
134
|
+
}
|
|
72
135
|
return `${prefix}${condition}return ${messageRef}(inputs)`;
|
|
73
136
|
}
|
|
74
|
-
|
|
137
|
+
// A locale's message has .parts() only if its own variants have
|
|
138
|
+
// markup. Fallbacks and messages without markup are typed without
|
|
139
|
+
// it, so read it through a type that declares it optional.
|
|
140
|
+
return `${prefix}${condition}return /** @type {{ parts?: (inputs: ${inputType}) => import('../runtime.js').MessagePart[] }} */ (${messageRef}).parts?.(inputs) ?? [{ type: "text", value: ${messageRef}(inputs) }]`;
|
|
75
141
|
})
|
|
76
142
|
.join("\n");
|
|
77
143
|
const perLocaleBuild = args.experimentalStaticLocale === perLocaleBuildStaticLocaleExpression;
|
|
@@ -121,10 +187,13 @@ ${englishMatchTableDoc}${jsDocBundleFunctionTypes({
|
|
|
121
187
|
}
|
|
122
188
|
return `${indent}const locale = ${localeExpression}${overrideWarning}${maybeTrackMessageCall(indent)}`;
|
|
123
189
|
};
|
|
190
|
+
const keepUnusedInputsParameter = (indent) => allStringBranchesInline && !args.experimentalMiddlewareLocaleSplitting
|
|
191
|
+
? `\n${indent}void inputs;`
|
|
192
|
+
: "";
|
|
124
193
|
let code = "";
|
|
125
194
|
if (!args.hasMarkup) {
|
|
126
195
|
code = `${commonJsDoc}
|
|
127
|
-
${isSafeBundleId ? "export " : ""}const ${safeBundleId} = /** @type {(${bundleFunctionType}) & ${messageMetadataType}} */ ((inputs${hasInputs ? "" : " = {}"}, options = {}) => {${clientMiddlewareGuard("\t")}
|
|
196
|
+
${isSafeBundleId ? "export " : ""}const ${safeBundleId} = /** @type {(${bundleFunctionType}) & ${messageMetadataType}} */ ((inputs${hasInputs ? "" : " = {}"}, options = {}) => {${clientMiddlewareGuard("\t")}${keepUnusedInputsParameter("\t")}
|
|
128
197
|
${localeResolutionStatement("\t")}
|
|
129
198
|
${compileLocaleReturnStatements("string", "\t")}${!isFullyTranslated
|
|
130
199
|
? `\n return /** @type {LocalizedString} */ ("${args.bundle.id}")`
|
|
@@ -135,7 +204,7 @@ ${localeResolutionStatement("\t")}
|
|
|
135
204
|
code = `${commonJsDoc}
|
|
136
205
|
${isSafeBundleId ? "export " : ""}const ${safeBundleId} = /** @type {(${bundleFunctionType}) & { parts: ${partsFunctionType} } & ${messageMetadataType}} */ (
|
|
137
206
|
/* @__PURE__ */ Object.assign(
|
|
138
|
-
/** @type {${bundleFunctionType}} */ ((inputs${hasInputs ? "" : " = {}"}, options = {}) => {${clientMiddlewareGuard("\t\t\t")}
|
|
207
|
+
/** @type {${bundleFunctionType}} */ ((inputs${hasInputs ? "" : " = {}"}, options = {}) => {${clientMiddlewareGuard("\t\t\t")}${keepUnusedInputsParameter("\t\t\t")}
|
|
139
208
|
${localeResolutionStatement("\t\t\t")}
|
|
140
209
|
${compileLocaleReturnStatements("string", "\t\t\t")}${!isFullyTranslated
|
|
141
210
|
? `\n return /** @type {LocalizedString} */ (${JSON.stringify(args.bundle.id)})`
|
|
@@ -421,6 +490,31 @@ function collectInputMatchTypes(bundle) {
|
|
|
421
490
|
}
|
|
422
491
|
}
|
|
423
492
|
}
|
|
493
|
+
// Matches on un-annotated aliases of an input match the input value too.
|
|
494
|
+
// Widen an input type that was narrowed by direct matches: alias literals
|
|
495
|
+
// join the union and an alias catchall accepts any value. Inputs that are
|
|
496
|
+
// only matched through aliases keep their unnarrowed type.
|
|
497
|
+
const declarations = bundle.declarations ?? [];
|
|
498
|
+
for (const message of bundle.messages) {
|
|
499
|
+
for (const variant of message.variants) {
|
|
500
|
+
for (const match of variant.matches ?? []) {
|
|
501
|
+
if (inputNames.has(match.key))
|
|
502
|
+
continue;
|
|
503
|
+
const inputName = resolveInputAlias(match.key, declarations);
|
|
504
|
+
if (inputName === undefined)
|
|
505
|
+
continue;
|
|
506
|
+
const info = matchTypes.get(inputName);
|
|
507
|
+
if (!info)
|
|
508
|
+
continue;
|
|
509
|
+
if (match.type === "catchall-match") {
|
|
510
|
+
info.hasCatchAll = true;
|
|
511
|
+
}
|
|
512
|
+
else if (match.type === "literal-match") {
|
|
513
|
+
info.literals.add(match.value);
|
|
514
|
+
}
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
}
|
|
424
518
|
return matchTypes;
|
|
425
519
|
}
|
|
426
520
|
function bundleHasMarkup(bundle) {
|