@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
|
@@ -0,0 +1,129 @@
|
|
|
1
|
+
import { annotationVariableReferences, isRegistryFunction, } from "./compile-annotation.js";
|
|
2
|
+
/**
|
|
3
|
+
* Returns the names of the variables a compiled pattern reads.
|
|
4
|
+
*
|
|
5
|
+
* Mirrors what `compilePattern()` emits: expression arguments, the options of
|
|
6
|
+
* registry function annotations (unknown annotations are dropped from the
|
|
7
|
+
* output), and in `parts` mode the options of markup.
|
|
8
|
+
*/
|
|
9
|
+
export function patternVariableReferences(pattern, mode) {
|
|
10
|
+
const names = [];
|
|
11
|
+
for (const part of pattern) {
|
|
12
|
+
if (part.type === "expression") {
|
|
13
|
+
if (part.arg.type === "variable-reference") {
|
|
14
|
+
names.push(part.arg.name);
|
|
15
|
+
}
|
|
16
|
+
if (part.annotation && isRegistryFunction(part.annotation.name)) {
|
|
17
|
+
names.push(...annotationVariableReferences(part.annotation));
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
else if (part.type !== "text" && mode === "parts") {
|
|
21
|
+
for (const option of part.options ?? []) {
|
|
22
|
+
if (option.value.type === "variable-reference") {
|
|
23
|
+
names.push(option.value.name);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
return names;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Returns the names of the variables a compiled local variable reads.
|
|
32
|
+
*
|
|
33
|
+
* Mirrors what `compileLocalVariable()` emits: the argument and the options
|
|
34
|
+
* of a registry function annotation (unknown annotations are dropped).
|
|
35
|
+
*/
|
|
36
|
+
export function localVariableReferences(declaration) {
|
|
37
|
+
const names = [];
|
|
38
|
+
if (declaration.value.arg.type === "variable-reference") {
|
|
39
|
+
names.push(declaration.value.arg.name);
|
|
40
|
+
}
|
|
41
|
+
const annotation = declaration.value.annotation;
|
|
42
|
+
if (annotation && isRegistryFunction(annotation.name)) {
|
|
43
|
+
names.push(...annotationVariableReferences(annotation));
|
|
44
|
+
}
|
|
45
|
+
return names;
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Resolves the local variables a message function has to declare.
|
|
49
|
+
*
|
|
50
|
+
* Starting from the variables the function body reads (patterns, match
|
|
51
|
+
* conditions), it follows local variables to the variables they read in turn
|
|
52
|
+
* and returns only the locals that are read, ordered so that every local is
|
|
53
|
+
* declared after the locals it reads. Locals the message does not read are
|
|
54
|
+
* left out, so the output passes `noUnusedLocals`.
|
|
55
|
+
*
|
|
56
|
+
* Throws if a read variable is not declared, or if locals reference each
|
|
57
|
+
* other in a cycle, because the emitted code would throw a `ReferenceError`
|
|
58
|
+
* at runtime.
|
|
59
|
+
*
|
|
60
|
+
* @example
|
|
61
|
+
* // .input {$count}
|
|
62
|
+
* // .local countPlural = {$count :plural}
|
|
63
|
+
* // .local countPluralExact = {$count}
|
|
64
|
+
* resolveMessageLocals({ reads: ["countPlural"], ... })
|
|
65
|
+
* // { locals: [countPlural], readsInput: true }
|
|
66
|
+
*/
|
|
67
|
+
export function resolveMessageLocals(args) {
|
|
68
|
+
// first declaration wins, consistent with compileVariableAccess()
|
|
69
|
+
const declarationsByName = new Map();
|
|
70
|
+
for (const declaration of args.declarations) {
|
|
71
|
+
if (!declarationsByName.has(declaration.name)) {
|
|
72
|
+
declarationsByName.set(declaration.name, declaration);
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
const where = `message "${args.bundleId}" (locale "${args.locale}")`;
|
|
76
|
+
const used = new Set();
|
|
77
|
+
let readsInput = false;
|
|
78
|
+
const read = (name, readBy) => {
|
|
79
|
+
const declaration = declarationsByName.get(name);
|
|
80
|
+
if (!declaration) {
|
|
81
|
+
throw new Error(`The ${where} references the variable "${name}"${readBy ? ` in the local variable "${readBy}"` : ""}, but "${name}" is not declared. Declare it as an input variable or a local variable.`);
|
|
82
|
+
}
|
|
83
|
+
if (declaration.type === "input-variable") {
|
|
84
|
+
readsInput = true;
|
|
85
|
+
return;
|
|
86
|
+
}
|
|
87
|
+
if (used.has(name)) {
|
|
88
|
+
return;
|
|
89
|
+
}
|
|
90
|
+
used.add(name);
|
|
91
|
+
for (const dependency of localVariableReferences(declaration)) {
|
|
92
|
+
read(dependency, name);
|
|
93
|
+
}
|
|
94
|
+
};
|
|
95
|
+
for (const name of args.reads) {
|
|
96
|
+
read(name);
|
|
97
|
+
}
|
|
98
|
+
// Topological order. Locals keep their declaration order unless a local
|
|
99
|
+
// reads one that is declared after it.
|
|
100
|
+
const locals = [];
|
|
101
|
+
const state = new Map();
|
|
102
|
+
const visit = (name, path) => {
|
|
103
|
+
const declaration = declarationsByName.get(name);
|
|
104
|
+
if (declaration?.type !== "local-variable") {
|
|
105
|
+
return;
|
|
106
|
+
}
|
|
107
|
+
const current = state.get(name);
|
|
108
|
+
if (current === "done") {
|
|
109
|
+
return;
|
|
110
|
+
}
|
|
111
|
+
if (current === "visiting") {
|
|
112
|
+
const cycle = [...path.slice(path.indexOf(name)), name];
|
|
113
|
+
throw new Error(`The ${where} has local variables that reference each other in a cycle: ${cycle.join(" -> ")}.`);
|
|
114
|
+
}
|
|
115
|
+
state.set(name, "visiting");
|
|
116
|
+
for (const dependency of localVariableReferences(declaration)) {
|
|
117
|
+
visit(dependency, [...path, name]);
|
|
118
|
+
}
|
|
119
|
+
state.set(name, "done");
|
|
120
|
+
locals.push(declaration);
|
|
121
|
+
};
|
|
122
|
+
for (const declaration of declarationsByName.values()) {
|
|
123
|
+
if (declaration.type === "local-variable" && used.has(declaration.name)) {
|
|
124
|
+
visit(declaration.name, []);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
return { locals, readsInput };
|
|
128
|
+
}
|
|
129
|
+
//# sourceMappingURL=message-locals.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"message-locals.js","sourceRoot":"","sources":["../../src/compiler/message-locals.ts"],"names":[],"mappings":"AAMA,OAAO,EACN,4BAA4B,EAC5B,kBAAkB,GAClB,MAAM,yBAAyB,CAAC;AAGjC;;;;;;GAMG;AACH,MAAM,UAAU,yBAAyB,CACxC,OAAgB,EAChB,IAAwB;IAExB,MAAM,KAAK,GAAa,EAAE,CAAC;IAE3B,KAAK,MAAM,IAAI,IAAI,OAAO,EAAE,CAAC;QAC5B,IAAI,IAAI,CAAC,IAAI,KAAK,YAAY,EAAE,CAAC;YAChC,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,KAAK,oBAAoB,EAAE,CAAC;gBAC5C,KAAK,CAAC,IAAI,CAAC,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;YAC3B,CAAC;YACD,IAAI,IAAI,CAAC,UAAU,IAAI,kBAAkB,CAAC,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;gBACjE,KAAK,CAAC,IAAI,CAAC,GAAG,4BAA4B,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;YAC9D,CAAC;QACF,CAAC;aAAM,IAAI,IAAI,CAAC,IAAI,KAAK,MAAM,IAAI,IAAI,KAAK,OAAO,EAAE,CAAC;YACrD,KAAK,MAAM,MAAM,IAAI,IAAI,CAAC,OAAO,IAAI,EAAE,EAAE,CAAC;gBACzC,IAAI,MAAM,CAAC,KAAK,CAAC,IAAI,KAAK,oBAAoB,EAAE,CAAC;oBAChD,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,KAAK,CAAC,IAAI,CAAC,CAAC;gBAC/B,CAAC;YACF,CAAC;QACF,CAAC;IACF,CAAC;IAED,OAAO,KAAK,CAAC;AACd,CAAC;AAED;;;;;GAKG;AACH,MAAM,UAAU,uBAAuB,CAAC,WAA0B;IACjE,MAAM,KAAK,GAAa,EAAE,CAAC;IAC3B,IAAI,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,KAAK,oBAAoB,EAAE,CAAC;QACzD,KAAK,CAAC,IAAI,CAAC,WAAW,CAAC,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;IACxC,CAAC;IACD,MAAM,UAAU,GACf,WAAW,CAAC,KAAK,CAAC,UAAU,CAAC;IAC9B,IAAI,UAAU,IAAI,kBAAkB,CAAC,UAAU,CAAC,IAAI,CAAC,EAAE,CAAC;QACvD,KAAK,CAAC,IAAI,CAAC,GAAG,4BAA4B,CAAC,UAAU,CAAC,CAAC,CAAC;IACzD,CAAC;IACD,OAAO,KAAK,CAAC;AACd,CAAC;AAED;;;;;;;;;;;;;;;;;;;GAmBG;AACH,MAAM,UAAU,oBAAoB,CAAC,IAKpC;IACA,kEAAkE;IAClE,MAAM,kBAAkB,GAAG,IAAI,GAAG,EAAuB,CAAC;IAC1D,KAAK,MAAM,WAAW,IAAI,IAAI,CAAC,YAAY,EAAE,CAAC;QAC7C,IAAI,CAAC,kBAAkB,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;YAC/C,kBAAkB,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,EAAE,WAAW,CAAC,CAAC;QACvD,CAAC;IACF,CAAC;IAED,MAAM,KAAK,GAAG,YAAY,IAAI,CAAC,QAAQ,cAAc,IAAI,CAAC,MAAM,IAAI,CAAC;IACrE,MAAM,IAAI,GAAG,IAAI,GAAG,EAAU,CAAC;IAC/B,IAAI,UAAU,GAAG,KAAK,CAAC;IAEvB,MAAM,IAAI,GAAG,CAAC,IAAY,EAAE,MAAe,EAAE,EAAE;QAC9C,MAAM,WAAW,GAAG,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACjD,IAAI,CAAC,WAAW,EAAE,CAAC;YAClB,MAAM,IAAI,KAAK,CACd,OAAO,KAAK,6BAA6B,IAAI,IAC5C,MAAM,CAAC,CAAC,CAAC,2BAA2B,MAAM,GAAG,CAAC,CAAC,CAAC,EACjD,UAAU,IAAI,yEAAyE,CACvF,CAAC;QACH,CAAC;QACD,IAAI,WAAW,CAAC,IAAI,KAAK,gBAAgB,EAAE,CAAC;YAC3C,UAAU,GAAG,IAAI,CAAC;YAClB,OAAO;QACR,CAAC;QACD,IAAI,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,EAAE,CAAC;YACpB,OAAO;QACR,CAAC;QACD,IAAI,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACf,KAAK,MAAM,UAAU,IAAI,uBAAuB,CAAC,WAAW,CAAC,EAAE,CAAC;YAC/D,IAAI,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC;QACxB,CAAC;IACF,CAAC,CAAC;IAEF,KAAK,MAAM,IAAI,IAAI,IAAI,CAAC,KAAK,EAAE,CAAC;QAC/B,IAAI,CAAC,IAAI,CAAC,CAAC;IACZ,CAAC;IAED,wEAAwE;IACxE,uCAAuC;IACvC,MAAM,MAAM,GAAoB,EAAE,CAAC;IACnC,MAAM,KAAK,GAAG,IAAI,GAAG,EAA+B,CAAC;IACrD,MAAM,KAAK,GAAG,CAAC,IAAY,EAAE,IAAc,EAAE,EAAE;QAC9C,MAAM,WAAW,GAAG,kBAAkB,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QACjD,IAAI,WAAW,EAAE,IAAI,KAAK,gBAAgB,EAAE,CAAC;YAC5C,OAAO;QACR,CAAC;QACD,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,IAAI,CAAC,CAAC;QAChC,IAAI,OAAO,KAAK,MAAM,EAAE,CAAC;YACxB,OAAO;QACR,CAAC;QACD,IAAI,OAAO,KAAK,UAAU,EAAE,CAAC;YAC5B,MAAM,KAAK,GAAG,CAAC,GAAG,IAAI,CAAC,KAAK,CAAC,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,IAAI,CAAC,CAAC;YACxD,MAAM,IAAI,KAAK,CACd,OAAO,KAAK,8DAA8D,KAAK,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,CAC/F,CAAC;QACH,CAAC;QACD,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;QAC5B,KAAK,MAAM,UAAU,IAAI,uBAAuB,CAAC,WAAW,CAAC,EAAE,CAAC;YAC/D,KAAK,CAAC,UAAU,EAAE,CAAC,GAAG,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC;QACpC,CAAC;QACD,KAAK,CAAC,GAAG,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACxB,MAAM,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;IAC1B,CAAC,CAAC;IAEF,KAAK,MAAM,WAAW,IAAI,kBAAkB,CAAC,MAAM,EAAE,EAAE,CAAC;QACvD,IAAI,WAAW,CAAC,IAAI,KAAK,gBAAgB,IAAI,IAAI,CAAC,GAAG,CAAC,WAAW,CAAC,IAAI,CAAC,EAAE,CAAC;YACzE,KAAK,CAAC,WAAW,CAAC,IAAI,EAAE,EAAE,CAAC,CAAC;QAC7B,CAAC;IACF,CAAC;IAED,OAAO,EAAE,MAAM,EAAE,UAAU,EAAE,CAAC;AAC/B,CAAC","sourcesContent":["import type {\n\tDeclaration,\n\tFunctionReference,\n\tLocalVariable,\n\tPattern,\n} from \"@inlang/sdk\";\nimport {\n\tannotationVariableReferences,\n\tisRegistryFunction,\n} from \"./compile-annotation.js\";\nimport type { CompilePatternMode } from \"./compile-pattern.js\";\n\n/**\n * Returns the names of the variables a compiled pattern reads.\n *\n * Mirrors what `compilePattern()` emits: expression arguments, the options of\n * registry function annotations (unknown annotations are dropped from the\n * output), and in `parts` mode the options of markup.\n */\nexport function patternVariableReferences(\n\tpattern: Pattern,\n\tmode: CompilePatternMode\n): string[] {\n\tconst names: string[] = [];\n\n\tfor (const part of pattern) {\n\t\tif (part.type === \"expression\") {\n\t\t\tif (part.arg.type === \"variable-reference\") {\n\t\t\t\tnames.push(part.arg.name);\n\t\t\t}\n\t\t\tif (part.annotation && isRegistryFunction(part.annotation.name)) {\n\t\t\t\tnames.push(...annotationVariableReferences(part.annotation));\n\t\t\t}\n\t\t} else if (part.type !== \"text\" && mode === \"parts\") {\n\t\t\tfor (const option of part.options ?? []) {\n\t\t\t\tif (option.value.type === \"variable-reference\") {\n\t\t\t\t\tnames.push(option.value.name);\n\t\t\t\t}\n\t\t\t}\n\t\t}\n\t}\n\n\treturn names;\n}\n\n/**\n * Returns the names of the variables a compiled local variable reads.\n *\n * Mirrors what `compileLocalVariable()` emits: the argument and the options\n * of a registry function annotation (unknown annotations are dropped).\n */\nexport function localVariableReferences(declaration: LocalVariable): string[] {\n\tconst names: string[] = [];\n\tif (declaration.value.arg.type === \"variable-reference\") {\n\t\tnames.push(declaration.value.arg.name);\n\t}\n\tconst annotation: FunctionReference | undefined =\n\t\tdeclaration.value.annotation;\n\tif (annotation && isRegistryFunction(annotation.name)) {\n\t\tnames.push(...annotationVariableReferences(annotation));\n\t}\n\treturn names;\n}\n\n/**\n * Resolves the local variables a message function has to declare.\n *\n * Starting from the variables the function body reads (patterns, match\n * conditions), it follows local variables to the variables they read in turn\n * and returns only the locals that are read, ordered so that every local is\n * declared after the locals it reads. Locals the message does not read are\n * left out, so the output passes `noUnusedLocals`.\n *\n * Throws if a read variable is not declared, or if locals reference each\n * other in a cycle, because the emitted code would throw a `ReferenceError`\n * at runtime.\n *\n * @example\n * // .input {$count}\n * // .local countPlural = {$count :plural}\n * // .local countPluralExact = {$count}\n * resolveMessageLocals({ reads: [\"countPlural\"], ... })\n * // { locals: [countPlural], readsInput: true }\n */\nexport function resolveMessageLocals(args: {\n\treads: Iterable<string>;\n\tdeclarations: readonly Declaration[];\n\tbundleId: string;\n\tlocale: string;\n}): { locals: LocalVariable[]; readsInput: boolean } {\n\t// first declaration wins, consistent with compileVariableAccess()\n\tconst declarationsByName = new Map<string, Declaration>();\n\tfor (const declaration of args.declarations) {\n\t\tif (!declarationsByName.has(declaration.name)) {\n\t\t\tdeclarationsByName.set(declaration.name, declaration);\n\t\t}\n\t}\n\n\tconst where = `message \"${args.bundleId}\" (locale \"${args.locale}\")`;\n\tconst used = new Set<string>();\n\tlet readsInput = false;\n\n\tconst read = (name: string, readBy?: string) => {\n\t\tconst declaration = declarationsByName.get(name);\n\t\tif (!declaration) {\n\t\t\tthrow new Error(\n\t\t\t\t`The ${where} references the variable \"${name}\"${\n\t\t\t\t\treadBy ? ` in the local variable \"${readBy}\"` : \"\"\n\t\t\t\t}, but \"${name}\" is not declared. Declare it as an input variable or a local variable.`\n\t\t\t);\n\t\t}\n\t\tif (declaration.type === \"input-variable\") {\n\t\t\treadsInput = true;\n\t\t\treturn;\n\t\t}\n\t\tif (used.has(name)) {\n\t\t\treturn;\n\t\t}\n\t\tused.add(name);\n\t\tfor (const dependency of localVariableReferences(declaration)) {\n\t\t\tread(dependency, name);\n\t\t}\n\t};\n\n\tfor (const name of args.reads) {\n\t\tread(name);\n\t}\n\n\t// Topological order. Locals keep their declaration order unless a local\n\t// reads one that is declared after it.\n\tconst locals: LocalVariable[] = [];\n\tconst state = new Map<string, \"visiting\" | \"done\">();\n\tconst visit = (name: string, path: string[]) => {\n\t\tconst declaration = declarationsByName.get(name);\n\t\tif (declaration?.type !== \"local-variable\") {\n\t\t\treturn;\n\t\t}\n\t\tconst current = state.get(name);\n\t\tif (current === \"done\") {\n\t\t\treturn;\n\t\t}\n\t\tif (current === \"visiting\") {\n\t\t\tconst cycle = [...path.slice(path.indexOf(name)), name];\n\t\t\tthrow new Error(\n\t\t\t\t`The ${where} has local variables that reference each other in a cycle: ${cycle.join(\" -> \")}.`\n\t\t\t);\n\t\t}\n\t\tstate.set(name, \"visiting\");\n\t\tfor (const dependency of localVariableReferences(declaration)) {\n\t\t\tvisit(dependency, [...path, name]);\n\t\t}\n\t\tstate.set(name, \"done\");\n\t\tlocals.push(declaration);\n\t};\n\n\tfor (const declaration of declarationsByName.values()) {\n\t\tif (declaration.type === \"local-variable\" && used.has(declaration.name)) {\n\t\t\tvisit(declaration.name, []);\n\t\t}\n\t}\n\n\treturn { locals, readsInput };\n}\n"]}
|
|
@@ -34,6 +34,9 @@ export function generateOutput(compiledBundles, settings, fallbackMap, experimen
|
|
|
34
34
|
let file = "";
|
|
35
35
|
const inputTypeDefs = [];
|
|
36
36
|
const emittedInputTypeDefs = new Set();
|
|
37
|
+
// decided from compiler metadata, not from the file text, which also
|
|
38
|
+
// contains message text like "Open the registry. Now."
|
|
39
|
+
let usesRegistry = false;
|
|
37
40
|
for (const compiledBundle of compiledBundles) {
|
|
38
41
|
const compiledMessage = compiledBundle.messages[locale];
|
|
39
42
|
const bundleModuleId = toSafeModuleId(compiledBundle.bundle.node.id);
|
|
@@ -58,10 +61,13 @@ export function generateOutput(compiledBundles, settings, fallbackMap, experimen
|
|
|
58
61
|
}
|
|
59
62
|
continue;
|
|
60
63
|
}
|
|
64
|
+
if (compiledMessage.registryFunctions.length > 0) {
|
|
65
|
+
usesRegistry = true;
|
|
66
|
+
}
|
|
61
67
|
file += `\n\nexport const ${bundleModuleId} = ${compiledMessage.code}`;
|
|
62
68
|
}
|
|
63
69
|
// add import if used
|
|
64
|
-
if (
|
|
70
|
+
if (usesRegistry) {
|
|
65
71
|
file = `import * as registry from "../registry.js"\n` + file;
|
|
66
72
|
}
|
|
67
73
|
// add LocalizedString typedef reference if used
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"locale-modules.js","sourceRoot":"","sources":["../../../src/compiler/output-structure/locale-modules.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAElE,MAAM,kBAAkB,GAAG,IAAI,CAAC;AAEhC,MAAM,UAAU,0BAA0B,CAAC,MAAc,EAAE,QAAgB;IAC1E,OAAO,GAAG,kBAAkB,GAAG,cAAc,CAAC,MAAM,CAAC,IAAI,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAC;AACrF,CAAC;AAED,MAAM,UAAU,cAAc,CAC7B,eAA6C,EAC7C,QAAyD,EACzD,WAA+C,EAC/C,qCAAqC,GAAG,KAAK;IAE7C,MAAM,aAAa,GAAG,qCAAqC;QAC1D,CAAC,CAAC,wIAAwI;QAC1I,CAAC,CAAC,qEAAqE,CAAC;IAEzE,MAAM,SAAS,GAAG;QACjB,aAAa;QACb,EAAE;QACF,2EAA2E;QAC3E,GAAG,eAAe,CAAC,GAAG,CAAC,CAAC,cAAc,EAAE,EAAE;YACzC,MAAM,cAAc,GAAG,cAAc,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACrE,MAAM,kBAAkB,GACvB,cAAc,CAAC,kBAAkB;gBACjC,0BAA0B,CAAC,cAAc,CAAC,CAAC;YAC5C,MAAM,MAAM,GACX,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,CAC9C,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,gBAAgB,CACxC,IAAI,EAAE,CAAC;YACT,OAAO,iBAAiB,UAAU,CAAC,MAAM,EAAE,cAAc,CAAC,UAAU,CAAC,KAAK,kBAAkB,KAAK,CAAC;QACnG,CAAC,CAAC;QACF,QAAQ,CAAC,OAAO;aACd,GAAG,CACH,CAAC,MAAM,EAAE,EAAE,CACV,eAAe,kBAAkB,GAAG,cAAc,CAAC,MAAM,CAAC,YAAY,MAAM,MAAM,CACnF;aACA,IAAI,CAAC,IAAI,CAAC;QACZ,eAAe,CAAC,GAAG,CAAC,CAAC,EAAE,MAAM,EAAE,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,IAAI,CAAC,IAAI,CAAC;KAC3D,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAEb,MAAM,MAAM,GAA2B;QACtC,CAAC,oBAAoB,CAAC,EAAE,SAAS;KACjC,CAAC;IAEF,yBAAyB;IACzB,KAAK,MAAM,MAAM,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;QACvC,MAAM,QAAQ,GAAG,YAAY,MAAM,KAAK,CAAC;QACzC,IAAI,IAAI,GAAG,EAAE,CAAC;QACd,MAAM,aAAa,GAAa,EAAE,CAAC;QACnC,MAAM,oBAAoB,GAAG,IAAI,GAAG,EAAU,CAAC;
|
|
1
|
+
{"version":3,"file":"locale-modules.js","sourceRoot":"","sources":["../../../src/compiler/output-structure/locale-modules.ts"],"names":[],"mappings":"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","sourcesContent":["import type { ProjectSettings } from \"@inlang/sdk\";\nimport type { CompiledBundleWithMessages } from \"../compile-bundle.js\";\nimport { toSafeModuleId } from \"../safe-module-id.js\";\nimport { inputsType } from \"../jsdoc-types.js\";\nimport { toBundleInputTypeAliasName } from \"../compile-bundle.js\";\n\nconst localeImportPrefix = \"__\";\n\nexport function messageReferenceExpression(locale: string, bundleId: string) {\n\treturn `${localeImportPrefix}${toSafeModuleId(locale)}.${toSafeModuleId(bundleId)}`;\n}\n\nexport function generateOutput(\n\tcompiledBundles: CompiledBundleWithMessages[],\n\tsettings: Pick<ProjectSettings, \"locales\" | \"baseLocale\">,\n\tfallbackMap: Record<string, string | undefined>,\n\texperimentalMiddlewareLocaleSplitting = false\n): Record<string, string> {\n\tconst runtimeImport = experimentalMiddlewareLocaleSplitting\n\t\t? `import { getLocale, trackMessageCall, experimentalMiddlewareLocaleSplitting, isServer, experimentalStaticLocale } from \"../runtime.js\"`\n\t\t: `import { getLocale, experimentalStaticLocale } from \"../runtime.js\"`;\n\n\tconst indexFile = [\n\t\truntimeImport,\n\t\t\"\",\n\t\t`/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */`,\n\t\t...compiledBundles.map((compiledBundle) => {\n\t\t\tconst bundleModuleId = toSafeModuleId(compiledBundle.bundle.node.id);\n\t\t\tconst inputTypeAliasName =\n\t\t\t\tcompiledBundle.inputTypeAliasName ??\n\t\t\t\ttoBundleInputTypeAliasName(bundleModuleId);\n\t\t\tconst inputs =\n\t\t\t\tcompiledBundle.bundle.node.declarations?.filter(\n\t\t\t\t\t(decl) => decl.type === \"input-variable\"\n\t\t\t\t) ?? [];\n\t\t\treturn `/** @typedef {${inputsType(inputs, compiledBundle.matchTypes)}} ${inputTypeAliasName} */`;\n\t\t}),\n\t\tsettings.locales\n\t\t\t.map(\n\t\t\t\t(locale) =>\n\t\t\t\t\t`import * as ${localeImportPrefix}${toSafeModuleId(locale)} from \"./${locale}.js\"`\n\t\t\t)\n\t\t\t.join(\"\\n\"),\n\t\tcompiledBundles.map(({ bundle }) => bundle.code).join(\"\\n\"),\n\t].join(\"\\n\");\n\n\tconst output: Record<string, string> = {\n\t\t[\"messages/_index.js\"]: indexFile,\n\t};\n\n\t// generate message files\n\tfor (const locale of settings.locales) {\n\t\tconst filename = `messages/${locale}.js`;\n\t\tlet file = \"\";\n\t\tconst inputTypeDefs: string[] = [];\n\t\tconst emittedInputTypeDefs = new Set<string>();\n\t\t// decided from compiler metadata, not from the file text, which also\n\t\t// contains message text like \"Open the registry. Now.\"\n\t\tlet usesRegistry = false;\n\n\t\tfor (const compiledBundle of compiledBundles) {\n\t\t\tconst compiledMessage = compiledBundle.messages[locale];\n\t\t\tconst bundleModuleId = toSafeModuleId(compiledBundle.bundle.node.id);\n\t\t\tconst bundleId = compiledBundle.bundle.node.id;\n\t\t\tconst inputs =\n\t\t\t\tcompiledBundle.bundle.node.declarations?.filter(\n\t\t\t\t\t(decl) => decl.type === \"input-variable\"\n\t\t\t\t) ?? [];\n\t\t\tconst matchTypes = compiledBundle.matchTypes;\n\t\t\tconst inputTypeAliasName =\n\t\t\t\tcompiledBundle.inputTypeAliasName ??\n\t\t\t\ttoBundleInputTypeAliasName(bundleModuleId);\n\t\t\tif (!emittedInputTypeDefs.has(inputTypeAliasName)) {\n\t\t\t\tinputTypeDefs.push(\n\t\t\t\t\t`/** @typedef {${inputsType(inputs, matchTypes)}} ${inputTypeAliasName} */`\n\t\t\t\t);\n\t\t\t\temittedInputTypeDefs.add(inputTypeAliasName);\n\t\t\t}\n\t\t\tif (!compiledMessage) {\n\t\t\t\tconst fallbackLocale = fallbackMap[locale];\n\t\t\t\tif (fallbackLocale) {\n\t\t\t\t\t// use the fall back locale e.g. render the message in English if the German message is missing\n\t\t\t\t\tfile += `\\nexport { ${bundleModuleId} } from \"./${fallbackLocale}.js\"`;\n\t\t\t\t} else {\n\t\t\t\t\t// no fallback exists, render the bundleId\n\t\t\t\t\tfile += `\\n/** @type {(inputs: ${inputTypeAliasName}) => LocalizedString} */\\nexport const ${bundleModuleId} = () => /** @type {LocalizedString} */ ('${bundleId}')`;\n\t\t\t\t}\n\t\t\t\tcontinue;\n\t\t\t}\n\n\t\t\tif (compiledMessage.registryFunctions.length > 0) {\n\t\t\t\tusesRegistry = true;\n\t\t\t}\n\t\t\tfile += `\\n\\nexport const ${bundleModuleId} = ${compiledMessage.code}`;\n\t\t}\n\n\t\t// add import if used\n\t\tif (usesRegistry) {\n\t\t\tfile = `import * as registry from \"../registry.js\"\\n` + file;\n\t\t}\n\n\t\t// add LocalizedString typedef reference if used\n\t\tif (file.includes(\"LocalizedString\")) {\n\t\t\tconst inputTypeDefsBlock = inputTypeDefs.length\n\t\t\t\t? `${inputTypeDefs.join(\"\\n\")}\\n`\n\t\t\t\t: \"\";\n\t\t\tfile =\n\t\t\t\t`/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */\\n` +\n\t\t\t\tinputTypeDefsBlock +\n\t\t\t\tfile;\n\t\t}\n\n\t\toutput[filename] = file;\n\t}\n\treturn output;\n}\n"]}
|
|
@@ -13,10 +13,12 @@ test("should emit per locale message files", () => {
|
|
|
13
13
|
en: {
|
|
14
14
|
code: 'console.log("message in English");',
|
|
15
15
|
node: {},
|
|
16
|
+
registryFunctions: [],
|
|
16
17
|
},
|
|
17
18
|
de: {
|
|
18
19
|
code: 'console.log("message in German");',
|
|
19
20
|
node: {},
|
|
21
|
+
registryFunctions: [],
|
|
20
22
|
},
|
|
21
23
|
},
|
|
22
24
|
matchTypes: new Map(),
|
|
@@ -74,6 +76,7 @@ test("should handle case sensitivity in message IDs correctly", () => {
|
|
|
74
76
|
en: {
|
|
75
77
|
code: 'console.log("sad_penguin_bundle");',
|
|
76
78
|
node: {},
|
|
79
|
+
registryFunctions: [],
|
|
77
80
|
},
|
|
78
81
|
},
|
|
79
82
|
matchTypes: new Map(),
|
|
@@ -89,6 +92,7 @@ test("should handle case sensitivity in message IDs correctly", () => {
|
|
|
89
92
|
en: {
|
|
90
93
|
code: 'console.log("Sad_penguin_bundle");',
|
|
91
94
|
node: {},
|
|
95
|
+
registryFunctions: [],
|
|
92
96
|
},
|
|
93
97
|
},
|
|
94
98
|
matchTypes: new Map(),
|
|
@@ -122,6 +126,7 @@ test("prefixes locale imports to avoid message name collisions", () => {
|
|
|
122
126
|
no: {
|
|
123
127
|
code: "const no = () => 'Nei';",
|
|
124
128
|
node: {},
|
|
129
|
+
registryFunctions: [],
|
|
125
130
|
},
|
|
126
131
|
},
|
|
127
132
|
matchTypes: new Map(),
|
|
@@ -149,6 +154,7 @@ test("emits minimal runtime imports in index when middleware splitting is disabl
|
|
|
149
154
|
en: {
|
|
150
155
|
code: '() => "happy"',
|
|
151
156
|
node: {},
|
|
157
|
+
registryFunctions: [],
|
|
152
158
|
},
|
|
153
159
|
},
|
|
154
160
|
matchTypes: new Map(),
|
|
@@ -160,4 +166,33 @@ test("emits minimal runtime imports in index when middleware splitting is disabl
|
|
|
160
166
|
expect(output["messages/_index.js"]).not.toContain("experimentalMiddlewareLocaleSplitting");
|
|
161
167
|
expect(output["messages/_index.js"]).not.toContain("isServer");
|
|
162
168
|
});
|
|
169
|
+
test("imports the registry only when a message calls it, not when the text mentions it", () => {
|
|
170
|
+
const bundle = (id, code, registryFunctions) => ({
|
|
171
|
+
bundle: {
|
|
172
|
+
code: `export const ${id} = () => en_${id}()`,
|
|
173
|
+
node: { id },
|
|
174
|
+
},
|
|
175
|
+
messages: {
|
|
176
|
+
en: { code, node: {}, registryFunctions },
|
|
177
|
+
},
|
|
178
|
+
matchTypes: new Map(),
|
|
179
|
+
});
|
|
180
|
+
const settings = {
|
|
181
|
+
locales: ["en"],
|
|
182
|
+
baseLocale: "en",
|
|
183
|
+
};
|
|
184
|
+
const registryImport = /import \* as registry from ['"]\.\.\/registry\.js['"]/;
|
|
185
|
+
const textOnly = generateOutput([bundle("registry_text", "() => `Open the registry. Now.`", [])], settings, { en: undefined });
|
|
186
|
+
for (const [fileName, code] of Object.entries(textOnly)) {
|
|
187
|
+
if (fileName.startsWith("messages/")) {
|
|
188
|
+
expect(code).not.toMatch(registryImport);
|
|
189
|
+
}
|
|
190
|
+
}
|
|
191
|
+
const withNumber = generateOutput([
|
|
192
|
+
bundle("amount", '(i) => `${registry.number("en", i?.amount, {})}`', [
|
|
193
|
+
"number",
|
|
194
|
+
]),
|
|
195
|
+
], settings, { en: undefined });
|
|
196
|
+
expect(Object.values(withNumber).some((code) => registryImport.test(code))).toBe(true);
|
|
197
|
+
});
|
|
163
198
|
//# sourceMappingURL=locale-modules.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"locale-modules.test.js","sourceRoot":"","sources":["../../../src/compiler/output-structure/locale-modules.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EACN,cAAc,EACd,0BAA0B,GAC1B,MAAM,qBAAqB,CAAC;AAI7B,IAAI,CAAC,sCAAsC,EAAE,GAAG,EAAE;IACjD,MAAM,OAAO,GAAiC;QAC7C;YACC,MAAM,EAAE;gBACP,IAAI,EAAE,6BAA6B;gBACnC,IAAI,EAAE;oBACL,EAAE,EAAE,gBAAgB;iBACC;aACtB;YACD,QAAQ,EAAE;gBACT,EAAE,EAAE;oBACH,IAAI,EAAE,oCAAoC;oBAC1C,IAAI,EAAE,EAAwB;iBAC9B;gBACD,EAAE,EAAE;oBACH,IAAI,EAAE,mCAAmC;oBACzC,IAAI,EAAE,EAAwB;iBAC9B;aACD;YACD,UAAU,EAAE,IAAI,GAAG,EAAE;SACrB;KACD,CAAC;IAEF,MAAM,QAAQ,GAAoD;QACjE,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;QACrB,UAAU,EAAE,IAAI;KAChB,CAAC;IAEF,MAAM,WAAW,GAAuC;QACvD,EAAE,EAAE,IAAI;QACR,EAAE,EAAE,IAAI;KACR,CAAC;IAEF,MAAM,MAAM,GAAG,cAAc,CAAC,OAAO,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;IAE9D,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC;IAChD,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC;IAEhD,MAAM,CAAC,MAAM,CAAC,gBAAgB,CAAC,CAAC,CAAC,SAAS,CACzC,oCAAoC,CACpC,CAAC;AACH,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,+EAA+E,EAAE,GAAG,EAAE;IAC1F,MAAM,OAAO,GAAiC;QAC7C;YACC,MAAM,EAAE;gBACP,IAAI,EAAE,6BAA6B;gBACnC,IAAI,EAAE;oBACL,EAAE,EAAE,gBAAgB;iBACC;aACtB;YACD,QAAQ,EAAE,EAAE;YACZ,UAAU,EAAE,IAAI,GAAG,EAAE;SACrB;KACD,CAAC;IAEF,MAAM,QAAQ,GAAoD;QACjE,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,EAAE,IAAI,CAAC;QAC3B,UAAU,EAAE,IAAI;KAChB,CAAC;IAEF,MAAM,WAAW,GAAuC;QACvD,EAAE,EAAE,IAAI;QACR,EAAE,EAAE,IAAI;KACR,CAAC;IAEF,MAAM,MAAM,GAAG,cAAc,CAAC,OAAO,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;IAE9D,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC;IAChD,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC;IAChD,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC;AACjD,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,yDAAyD,EAAE,GAAG,EAAE;IACpE,MAAM,OAAO,GAAiC;QAC7C;YACC,MAAM,EAAE;gBACP,IAAI,EAAE,6BAA6B;gBACnC,IAAI,EAAE;oBACL,EAAE,EAAE,oBAAoB;iBACH;aACtB;YACD,QAAQ,EAAE;gBACT,EAAE,EAAE;oBACH,IAAI,EAAE,oCAAoC;oBAC1C,IAAI,EAAE,EAAwB;iBAC9B;aACD;YACD,UAAU,EAAE,IAAI,GAAG,EAAE;SACrB;QACD;YACC,MAAM,EAAE;gBACP,IAAI,EAAE,6BAA6B;gBACnC,IAAI,EAAE;oBACL,EAAE,EAAE,oBAAoB;iBACH;aACtB;YACD,QAAQ,EAAE;gBACT,EAAE,EAAE;oBACH,IAAI,EAAE,oCAAoC;oBAC1C,IAAI,EAAE,EAAwB;iBAC9B;aACD;YACD,UAAU,EAAE,IAAI,GAAG,EAAE;SACrB;KACD,CAAC;IAEF,MAAM,QAAQ,GAAoD;QACjE,OAAO,EAAE,CAAC,IAAI,CAAC;QACf,UAAU,EAAE,IAAI;KAChB,CAAC;IAEF,MAAM,WAAW,GAAuC,EAAE,CAAC;IAE3D,MAAM,MAAM,GAAG,cAAc,CAAC,OAAO,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;IAE9D,+BAA+B;IAC/B,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,oBAAoB,CAAC,CAAC;IACpD,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC;IAEhD,6CAA6C;IAC7C,MAAM,OAAO,GAAG,MAAM,CAAC,gBAAgB,CAAC,CAAC;IACzC,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,iCAAiC,CAAC,CAAC;IAC7D,MAAM,CAAC,OAAO,CAAC,CAAC,SAAS,CAAC,kCAAkC,CAAC,CAAC,CAAC,4BAA4B;AAC5F,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,0DAA0D,EAAE,GAAG,EAAE;IACrE,mDAAmD;IACnD,MAAM,OAAO,GAAiC;QAC7C;YACC,MAAM,EAAE;gBACP,IAAI,EAAE,wBAAwB;gBAC9B,IAAI,EAAE;oBACL,EAAE,EAAE,IAAI;iBACa;aACtB;YACD,QAAQ,EAAE;gBACT,EAAE,EAAE;oBACH,IAAI,EAAE,yBAAyB;oBAC/B,IAAI,EAAE,EAAwB;iBAC9B;aACD;YACD,UAAU,EAAE,IAAI,GAAG,EAAE;SACrB;KACD,CAAC;IAEF,MAAM,QAAQ,GAAoD;QACjE,OAAO,EAAE,CAAC,IAAI,CAAC;QACf,UAAU,EAAE,IAAI;KAChB,CAAC;IAEF,MAAM,MAAM,GAAG,cAAc,CAAC,OAAO,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;IAErD,MAAM,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,CAAC,SAAS,CAC7C,iCAAiC,CACjC,CAAC;IACF,MAAM,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CACjD,+BAA+B,CAC/B,CAAC;IACF,MAAM,CAAC,0BAA0B,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC,CAAC,IAAI,CAAC,SAAS,CAAC,CAAC;AAChE,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,8EAA8E,EAAE,GAAG,EAAE;IACzF,MAAM,OAAO,GAAiC;QAC7C;YACC,MAAM,EAAE;gBACP,IAAI,EAAE,2DAA2D;gBACjE,IAAI,EAAE;oBACL,EAAE,EAAE,gBAAgB;iBACC;aACtB;YACD,QAAQ,EAAE;gBACT,EAAE,EAAE;oBACH,IAAI,EAAE,eAAe;oBACrB,IAAI,EAAE,EAAwB;iBAC9B;aACD;YACD,UAAU,EAAE,IAAI,GAAG,EAAE;SACrB;KACD,CAAC;IAEF,MAAM,MAAM,GAAG,cAAc,CAC5B,OAAO,EACP,EAAE,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,EACrC,EAAE,EACF,KAAK,CACL,CAAC;IAEF,MAAM,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,CAAC,SAAS,CAC7C,qEAAqE,CACrE,CAAC;IACF,MAAM,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,kBAAkB,CAAC,CAAC;IACvE,MAAM,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,uCAAuC,CAAC,CAAC;IAC5F,MAAM,CAAC,MAAM,CAAC,oBAAoB,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;AAChE,CAAC,CAAC,CAAC","sourcesContent":["import { test, expect } from \"vitest\";\nimport {\n\tgenerateOutput,\n\tmessageReferenceExpression,\n} from \"./locale-modules.js\";\nimport type { Bundle, Message, ProjectSettings } from \"@inlang/sdk\";\nimport type { CompiledBundleWithMessages } from \"../compile-bundle.js\";\n\ntest(\"should emit per locale message files\", () => {\n\tconst bundles: CompiledBundleWithMessages[] = [\n\t\t{\n\t\t\tbundle: {\n\t\t\t\tcode: 'console.log(\"bundle code\");',\n\t\t\t\tnode: {\n\t\t\t\t\tid: \"happy_elephant\",\n\t\t\t\t} as unknown as Bundle,\n\t\t\t},\n\t\t\tmessages: {\n\t\t\t\ten: {\n\t\t\t\t\tcode: 'console.log(\"message in English\");',\n\t\t\t\t\tnode: {} as unknown as Message,\n\t\t\t\t},\n\t\t\t\tde: {\n\t\t\t\t\tcode: 'console.log(\"message in German\");',\n\t\t\t\t\tnode: {} as unknown as Message,\n\t\t\t\t},\n\t\t\t},\n\t\t\tmatchTypes: new Map(),\n\t\t},\n\t];\n\n\tconst settings: Pick<ProjectSettings, \"locales\" | \"baseLocale\"> = {\n\t\tlocales: [\"en\", \"de\"],\n\t\tbaseLocale: \"en\",\n\t};\n\n\tconst fallbackMap: Record<string, string | undefined> = {\n\t\ten: \"de\",\n\t\tde: \"en\",\n\t};\n\n\tconst output = generateOutput(bundles, settings, fallbackMap);\n\n\texpect(output).toHaveProperty(\"messages/en.js\");\n\texpect(output).toHaveProperty(\"messages/de.js\");\n\n\texpect(output[\"messages/en.js\"]).toContain(\n\t\t`console.log(\"message in English\");`\n\t);\n});\n\ntest(\"the files should include files for each locale, even if there are no messages\", () => {\n\tconst bundles: CompiledBundleWithMessages[] = [\n\t\t{\n\t\t\tbundle: {\n\t\t\t\tcode: 'console.log(\"bundle code\");',\n\t\t\t\tnode: {\n\t\t\t\t\tid: \"happy_elephant\",\n\t\t\t\t} as unknown as Bundle,\n\t\t\t},\n\t\t\tmessages: {},\n\t\t\tmatchTypes: new Map(),\n\t\t},\n\t];\n\n\tconst settings: Pick<ProjectSettings, \"locales\" | \"baseLocale\"> = {\n\t\tlocales: [\"en\", \"de\", \"fr\"],\n\t\tbaseLocale: \"en\",\n\t};\n\n\tconst fallbackMap: Record<string, string | undefined> = {\n\t\ten: \"de\",\n\t\tde: \"en\",\n\t};\n\n\tconst output = generateOutput(bundles, settings, fallbackMap);\n\n\texpect(output).toHaveProperty(\"messages/en.js\");\n\texpect(output).toHaveProperty(\"messages/de.js\");\n\texpect(output).toHaveProperty(\"messages/fr.js\");\n});\n\ntest(\"should handle case sensitivity in message IDs correctly\", () => {\n\tconst bundles: CompiledBundleWithMessages[] = [\n\t\t{\n\t\t\tbundle: {\n\t\t\t\tcode: 'console.log(\"bundle code\");',\n\t\t\t\tnode: {\n\t\t\t\t\tid: \"sad_penguin_bundle\",\n\t\t\t\t} as unknown as Bundle,\n\t\t\t},\n\t\t\tmessages: {\n\t\t\t\ten: {\n\t\t\t\t\tcode: 'console.log(\"sad_penguin_bundle\");',\n\t\t\t\t\tnode: {} as unknown as Message,\n\t\t\t\t},\n\t\t\t},\n\t\t\tmatchTypes: new Map(),\n\t\t},\n\t\t{\n\t\t\tbundle: {\n\t\t\t\tcode: 'console.log(\"bundle code\");',\n\t\t\t\tnode: {\n\t\t\t\t\tid: \"Sad_penguin_bundle\",\n\t\t\t\t} as unknown as Bundle,\n\t\t\t},\n\t\t\tmessages: {\n\t\t\t\ten: {\n\t\t\t\t\tcode: 'console.log(\"Sad_penguin_bundle\");',\n\t\t\t\t\tnode: {} as unknown as Message,\n\t\t\t\t},\n\t\t\t},\n\t\t\tmatchTypes: new Map(),\n\t\t},\n\t];\n\n\tconst settings: Pick<ProjectSettings, \"locales\" | \"baseLocale\"> = {\n\t\tlocales: [\"en\"],\n\t\tbaseLocale: \"en\",\n\t};\n\n\tconst fallbackMap: Record<string, string | undefined> = {};\n\n\tconst output = generateOutput(bundles, settings, fallbackMap);\n\n\t// Check that the output exists\n\texpect(output).toHaveProperty(\"messages/_index.js\");\n\texpect(output).toHaveProperty(\"messages/en.js\");\n\n\t// The exported constants should not conflict\n\tconst content = output[\"messages/en.js\"];\n\texpect(content).toContain(\"export const sad_penguin_bundle\");\n\texpect(content).toContain(\"export const sad_penguin_bundle1\"); // or some other unique name\n});\n\ntest(\"prefixes locale imports to avoid message name collisions\", () => {\n\t// https://github.com/opral/paraglide-js/issues/492\n\tconst bundles: CompiledBundleWithMessages[] = [\n\t\t{\n\t\t\tbundle: {\n\t\t\t\tcode: \"const no = () => 'No';\",\n\t\t\t\tnode: {\n\t\t\t\t\tid: \"no\",\n\t\t\t\t} as unknown as Bundle,\n\t\t\t},\n\t\t\tmessages: {\n\t\t\t\tno: {\n\t\t\t\t\tcode: \"const no = () => 'Nei';\",\n\t\t\t\t\tnode: {} as unknown as Message,\n\t\t\t\t},\n\t\t\t},\n\t\t\tmatchTypes: new Map(),\n\t\t},\n\t];\n\n\tconst settings: Pick<ProjectSettings, \"locales\" | \"baseLocale\"> = {\n\t\tlocales: [\"no\"],\n\t\tbaseLocale: \"no\",\n\t};\n\n\tconst output = generateOutput(bundles, settings, {});\n\n\texpect(output[\"messages/_index.js\"]).toContain(\n\t\t`import * as __no from \"./no.js\"`\n\t);\n\texpect(output[\"messages/_index.js\"]).not.toContain(\n\t\t`import * as no from \"./no.js\"`\n\t);\n\texpect(messageReferenceExpression(\"no\", \"no\")).toBe(\"__no.no\");\n});\n\ntest(\"emits minimal runtime imports in index when middleware splitting is disabled\", () => {\n\tconst bundles: CompiledBundleWithMessages[] = [\n\t\t{\n\t\t\tbundle: {\n\t\t\t\tcode: \"export const happy_elephant = () => __en.happy_elephant()\",\n\t\t\t\tnode: {\n\t\t\t\t\tid: \"happy_elephant\",\n\t\t\t\t} as unknown as Bundle,\n\t\t\t},\n\t\t\tmessages: {\n\t\t\t\ten: {\n\t\t\t\t\tcode: '() => \"happy\"',\n\t\t\t\t\tnode: {} as unknown as Message,\n\t\t\t\t},\n\t\t\t},\n\t\t\tmatchTypes: new Map(),\n\t\t},\n\t];\n\n\tconst output = generateOutput(\n\t\tbundles,\n\t\t{ locales: [\"en\"], baseLocale: \"en\" },\n\t\t{},\n\t\tfalse\n\t);\n\n\texpect(output[\"messages/_index.js\"]).toContain(\n\t\t'import { getLocale, experimentalStaticLocale } from \"../runtime.js\"'\n\t);\n\texpect(output[\"messages/_index.js\"]).not.toContain(\"trackMessageCall\");\n\texpect(output[\"messages/_index.js\"]).not.toContain(\"experimentalMiddlewareLocaleSplitting\");\n\texpect(output[\"messages/_index.js\"]).not.toContain(\"isServer\");\n});\n"]}
|
|
1
|
+
{"version":3,"file":"locale-modules.test.js","sourceRoot":"","sources":["../../../src/compiler/output-structure/locale-modules.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { test, expect } from \"vitest\";\nimport {\n\tgenerateOutput,\n\tmessageReferenceExpression,\n} from \"./locale-modules.js\";\nimport type { Bundle, Message, ProjectSettings } from \"@inlang/sdk\";\nimport type { CompiledBundleWithMessages } from \"../compile-bundle.js\";\n\ntest(\"should emit per locale message files\", () => {\n\tconst bundles: CompiledBundleWithMessages[] = [\n\t\t{\n\t\t\tbundle: {\n\t\t\t\tcode: 'console.log(\"bundle code\");',\n\t\t\t\tnode: {\n\t\t\t\t\tid: \"happy_elephant\",\n\t\t\t\t} as unknown as Bundle,\n\t\t\t},\n\t\t\tmessages: {\n\t\t\t\ten: {\n\t\t\t\t\tcode: 'console.log(\"message in English\");',\n\t\t\t\t\tnode: {} as unknown as Message,\n\t\t\t\t\tregistryFunctions: [],\n\t\t\t\t},\n\t\t\t\tde: {\n\t\t\t\t\tcode: 'console.log(\"message in German\");',\n\t\t\t\t\tnode: {} as unknown as Message,\n\t\t\t\t\tregistryFunctions: [],\n\t\t\t\t},\n\t\t\t},\n\t\t\tmatchTypes: new Map(),\n\t\t},\n\t];\n\n\tconst settings: Pick<ProjectSettings, \"locales\" | \"baseLocale\"> = {\n\t\tlocales: [\"en\", \"de\"],\n\t\tbaseLocale: \"en\",\n\t};\n\n\tconst fallbackMap: Record<string, string | undefined> = {\n\t\ten: \"de\",\n\t\tde: \"en\",\n\t};\n\n\tconst output = generateOutput(bundles, settings, fallbackMap);\n\n\texpect(output).toHaveProperty(\"messages/en.js\");\n\texpect(output).toHaveProperty(\"messages/de.js\");\n\n\texpect(output[\"messages/en.js\"]).toContain(\n\t\t`console.log(\"message in English\");`\n\t);\n});\n\ntest(\"the files should include files for each locale, even if there are no messages\", () => {\n\tconst bundles: CompiledBundleWithMessages[] = [\n\t\t{\n\t\t\tbundle: {\n\t\t\t\tcode: 'console.log(\"bundle code\");',\n\t\t\t\tnode: {\n\t\t\t\t\tid: \"happy_elephant\",\n\t\t\t\t} as unknown as Bundle,\n\t\t\t},\n\t\t\tmessages: {},\n\t\t\tmatchTypes: new Map(),\n\t\t},\n\t];\n\n\tconst settings: Pick<ProjectSettings, \"locales\" | \"baseLocale\"> = {\n\t\tlocales: [\"en\", \"de\", \"fr\"],\n\t\tbaseLocale: \"en\",\n\t};\n\n\tconst fallbackMap: Record<string, string | undefined> = {\n\t\ten: \"de\",\n\t\tde: \"en\",\n\t};\n\n\tconst output = generateOutput(bundles, settings, fallbackMap);\n\n\texpect(output).toHaveProperty(\"messages/en.js\");\n\texpect(output).toHaveProperty(\"messages/de.js\");\n\texpect(output).toHaveProperty(\"messages/fr.js\");\n});\n\ntest(\"should handle case sensitivity in message IDs correctly\", () => {\n\tconst bundles: CompiledBundleWithMessages[] = [\n\t\t{\n\t\t\tbundle: {\n\t\t\t\tcode: 'console.log(\"bundle code\");',\n\t\t\t\tnode: {\n\t\t\t\t\tid: \"sad_penguin_bundle\",\n\t\t\t\t} as unknown as Bundle,\n\t\t\t},\n\t\t\tmessages: {\n\t\t\t\ten: {\n\t\t\t\t\tcode: 'console.log(\"sad_penguin_bundle\");',\n\t\t\t\t\tnode: {} as unknown as Message,\n\t\t\t\t\tregistryFunctions: [],\n\t\t\t\t},\n\t\t\t},\n\t\t\tmatchTypes: new Map(),\n\t\t},\n\t\t{\n\t\t\tbundle: {\n\t\t\t\tcode: 'console.log(\"bundle code\");',\n\t\t\t\tnode: {\n\t\t\t\t\tid: \"Sad_penguin_bundle\",\n\t\t\t\t} as unknown as Bundle,\n\t\t\t},\n\t\t\tmessages: {\n\t\t\t\ten: {\n\t\t\t\t\tcode: 'console.log(\"Sad_penguin_bundle\");',\n\t\t\t\t\tnode: {} as unknown as Message,\n\t\t\t\t\tregistryFunctions: [],\n\t\t\t\t},\n\t\t\t},\n\t\t\tmatchTypes: new Map(),\n\t\t},\n\t];\n\n\tconst settings: Pick<ProjectSettings, \"locales\" | \"baseLocale\"> = {\n\t\tlocales: [\"en\"],\n\t\tbaseLocale: \"en\",\n\t};\n\n\tconst fallbackMap: Record<string, string | undefined> = {};\n\n\tconst output = generateOutput(bundles, settings, fallbackMap);\n\n\t// Check that the output exists\n\texpect(output).toHaveProperty(\"messages/_index.js\");\n\texpect(output).toHaveProperty(\"messages/en.js\");\n\n\t// The exported constants should not conflict\n\tconst content = output[\"messages/en.js\"];\n\texpect(content).toContain(\"export const sad_penguin_bundle\");\n\texpect(content).toContain(\"export const sad_penguin_bundle1\"); // or some other unique name\n});\n\ntest(\"prefixes locale imports to avoid message name collisions\", () => {\n\t// https://github.com/opral/paraglide-js/issues/492\n\tconst bundles: CompiledBundleWithMessages[] = [\n\t\t{\n\t\t\tbundle: {\n\t\t\t\tcode: \"const no = () => 'No';\",\n\t\t\t\tnode: {\n\t\t\t\t\tid: \"no\",\n\t\t\t\t} as unknown as Bundle,\n\t\t\t},\n\t\t\tmessages: {\n\t\t\t\tno: {\n\t\t\t\t\tcode: \"const no = () => 'Nei';\",\n\t\t\t\t\tnode: {} as unknown as Message,\n\t\t\t\t\tregistryFunctions: [],\n\t\t\t\t},\n\t\t\t},\n\t\t\tmatchTypes: new Map(),\n\t\t},\n\t];\n\n\tconst settings: Pick<ProjectSettings, \"locales\" | \"baseLocale\"> = {\n\t\tlocales: [\"no\"],\n\t\tbaseLocale: \"no\",\n\t};\n\n\tconst output = generateOutput(bundles, settings, {});\n\n\texpect(output[\"messages/_index.js\"]).toContain(\n\t\t`import * as __no from \"./no.js\"`\n\t);\n\texpect(output[\"messages/_index.js\"]).not.toContain(\n\t\t`import * as no from \"./no.js\"`\n\t);\n\texpect(messageReferenceExpression(\"no\", \"no\")).toBe(\"__no.no\");\n});\n\ntest(\"emits minimal runtime imports in index when middleware splitting is disabled\", () => {\n\tconst bundles: CompiledBundleWithMessages[] = [\n\t\t{\n\t\t\tbundle: {\n\t\t\t\tcode: \"export const happy_elephant = () => __en.happy_elephant()\",\n\t\t\t\tnode: {\n\t\t\t\t\tid: \"happy_elephant\",\n\t\t\t\t} as unknown as Bundle,\n\t\t\t},\n\t\t\tmessages: {\n\t\t\t\ten: {\n\t\t\t\t\tcode: '() => \"happy\"',\n\t\t\t\t\tnode: {} as unknown as Message,\n\t\t\t\t\tregistryFunctions: [],\n\t\t\t\t},\n\t\t\t},\n\t\t\tmatchTypes: new Map(),\n\t\t},\n\t];\n\n\tconst output = generateOutput(\n\t\tbundles,\n\t\t{ locales: [\"en\"], baseLocale: \"en\" },\n\t\t{},\n\t\tfalse\n\t);\n\n\texpect(output[\"messages/_index.js\"]).toContain(\n\t\t'import { getLocale, experimentalStaticLocale } from \"../runtime.js\"'\n\t);\n\texpect(output[\"messages/_index.js\"]).not.toContain(\"trackMessageCall\");\n\texpect(output[\"messages/_index.js\"]).not.toContain(\n\t\t\"experimentalMiddlewareLocaleSplitting\"\n\t);\n\texpect(output[\"messages/_index.js\"]).not.toContain(\"isServer\");\n});\n\ntest(\"imports the registry only when a message calls it, not when the text mentions it\", () => {\n\tconst bundle = (\n\t\tid: string,\n\t\tcode: string,\n\t\tregistryFunctions: string[]\n\t): CompiledBundleWithMessages => ({\n\t\tbundle: {\n\t\t\tcode: `export const ${id} = () => en_${id}()`,\n\t\t\tnode: { id } as unknown as Bundle,\n\t\t},\n\t\tmessages: {\n\t\t\ten: { code, node: {} as unknown as Message, registryFunctions },\n\t\t},\n\t\tmatchTypes: new Map(),\n\t});\n\tconst settings: Pick<ProjectSettings, \"locales\" | \"baseLocale\"> = {\n\t\tlocales: [\"en\"],\n\t\tbaseLocale: \"en\",\n\t};\n\tconst registryImport =\n\t\t/import \\* as registry from ['\"]\\.\\.\\/registry\\.js['\"]/;\n\n\tconst textOnly = generateOutput(\n\t\t[bundle(\"registry_text\", \"() => `Open the registry. Now.`\", [])],\n\t\tsettings,\n\t\t{ en: undefined }\n\t);\n\tfor (const [fileName, code] of Object.entries(textOnly)) {\n\t\tif (fileName.startsWith(\"messages/\")) {\n\t\t\texpect(code).not.toMatch(registryImport);\n\t\t}\n\t}\n\n\tconst withNumber = generateOutput(\n\t\t[\n\t\t\tbundle(\"amount\", '(i) => `${registry.number(\"en\", i?.amount, {})}`', [\n\t\t\t\t\"number\",\n\t\t\t]),\n\t\t],\n\t\tsettings,\n\t\t{ en: undefined }\n\t);\n\texpect(\n\t\tObject.values(withNumber).some((code) => registryImport.test(code))\n\t).toBe(true);\n});\n"]}
|
|
@@ -30,7 +30,7 @@ export function generateOutput(compiledBundles, settings, fallbackMap, experimen
|
|
|
30
30
|
if (!compiledMessage) {
|
|
31
31
|
needsFallback.push(locale);
|
|
32
32
|
}
|
|
33
|
-
else {
|
|
33
|
+
else if (!compiledBundle.unreferencedMessageLocales?.includes(locale)) {
|
|
34
34
|
messages.push(`const ${safeLocale}_${safeModuleId} = ${compiledMessage.code}`);
|
|
35
35
|
}
|
|
36
36
|
}
|
|
@@ -82,9 +82,11 @@ export function generateOutput(compiledBundles, settings, fallbackMap, experimen
|
|
|
82
82
|
`/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */\n\n` +
|
|
83
83
|
`/** @typedef {${inputTypeDefinition}} ${inputTypeAliasName} */\n\n` +
|
|
84
84
|
output[filename];
|
|
85
|
-
// Add the registry import to the message file
|
|
86
|
-
//
|
|
87
|
-
|
|
85
|
+
// Add the registry import to the message file if a message calls the
|
|
86
|
+
// registry. Decided from compiler metadata, not from the file text,
|
|
87
|
+
// which also contains message text like "Open the registry. Now."
|
|
88
|
+
const usesRegistry = settings.locales.some((locale) => (compiledBundle.messages[locale]?.registryFunctions.length ?? 0) > 0);
|
|
89
|
+
if (usesRegistry) {
|
|
88
90
|
output[filename] =
|
|
89
91
|
`import * as registry from '../registry.js'\n` + output[filename];
|
|
90
92
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message-modules.js","sourceRoot":"","sources":["../../../src/compiler/output-structure/message-modules.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,0BAA0B,EAAE,MAAM,kCAAkC,CAAC;AAC9E,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAElE,MAAM,UAAU,0BAA0B,CAAC,MAAc,EAAE,QAAgB;IAC1E,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,IAAI,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,cAAc,CAC7B,eAA6C,EAC7C,QAAyD,EACzD,WAA+C,EAC/C,qCAAqC,GAAG,KAAK;IAE7C,MAAM,MAAM,GAA2B,EAAE,CAAC;IAE1C,MAAM,eAAe,GAAG,IAAI,GAAG,EAAU,CAAC;IAE1C,KAAK,MAAM,cAAc,IAAI,eAAe,EAAE,CAAC;QAC9C,MAAM,QAAQ,GAAG,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/C,MAAM,YAAY,GAAG,cAAc,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACnE,MAAM,MAAM,GACX,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,CAC9C,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,gBAAgB,CACxC,IAAI,EAAE,CAAC;QACT,MAAM,UAAU,GAAG,cAAc,CAAC,UAAU,CAAC;QAC7C,MAAM,kBAAkB,GACvB,cAAc,CAAC,kBAAkB;YACjC,0BAA0B,CAAC,YAAY,CAAC,CAAC;QAC1C,MAAM,mBAAmB,GAAG,UAAU,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAE3D,cAAc;QACd,MAAM,QAAQ,GAAG,YAAY,YAAY,KAAK,CAAC;QAE/C,eAAe,CAAC,GAAG,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC;QAE1C,2BAA2B;QAC3B,MAAM,CAAC,QAAQ,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC;QAE9C,MAAM,aAAa,GAAa,EAAE,CAAC;QAEnC,MAAM,QAAQ,GAAa,EAAE,CAAC;QAE9B,WAAW;QACX,KAAK,MAAM,MAAM,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;YACvC,MAAM,UAAU,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;YAC1C,MAAM,eAAe,GAAG,cAAc,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAExD,IAAI,CAAC,eAAe,EAAE,CAAC;gBACtB,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC5B,CAAC;iBAAM,CAAC;
|
|
1
|
+
{"version":3,"file":"message-modules.js","sourceRoot":"","sources":["../../../src/compiler/output-structure/message-modules.ts"],"names":[],"mappings":"AAEA,OAAO,EAAE,0BAA0B,EAAE,MAAM,kCAAkC,CAAC;AAC9E,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AACtD,OAAO,EAAE,UAAU,EAAE,MAAM,mBAAmB,CAAC;AAC/C,OAAO,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAElE,MAAM,UAAU,0BAA0B,CAAC,MAAc,EAAE,QAAgB;IAC1E,OAAO,GAAG,cAAc,CAAC,MAAM,CAAC,IAAI,cAAc,CAAC,QAAQ,CAAC,EAAE,CAAC;AAChE,CAAC;AAED,MAAM,UAAU,cAAc,CAC7B,eAA6C,EAC7C,QAAyD,EACzD,WAA+C,EAC/C,qCAAqC,GAAG,KAAK;IAE7C,MAAM,MAAM,GAA2B,EAAE,CAAC;IAE1C,MAAM,eAAe,GAAG,IAAI,GAAG,EAAU,CAAC;IAE1C,KAAK,MAAM,cAAc,IAAI,eAAe,EAAE,CAAC;QAC9C,MAAM,QAAQ,GAAG,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC;QAC/C,MAAM,YAAY,GAAG,cAAc,CAAC,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;QACnE,MAAM,MAAM,GACX,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC,YAAY,EAAE,MAAM,CAC9C,CAAC,IAAI,EAAE,EAAE,CAAC,IAAI,CAAC,IAAI,KAAK,gBAAgB,CACxC,IAAI,EAAE,CAAC;QACT,MAAM,UAAU,GAAG,cAAc,CAAC,UAAU,CAAC;QAC7C,MAAM,kBAAkB,GACvB,cAAc,CAAC,kBAAkB;YACjC,0BAA0B,CAAC,YAAY,CAAC,CAAC;QAC1C,MAAM,mBAAmB,GAAG,UAAU,CAAC,MAAM,EAAE,UAAU,CAAC,CAAC;QAE3D,cAAc;QACd,MAAM,QAAQ,GAAG,YAAY,YAAY,KAAK,CAAC;QAE/C,eAAe,CAAC,GAAG,CAAC,GAAG,YAAY,KAAK,CAAC,CAAC;QAE1C,2BAA2B;QAC3B,MAAM,CAAC,QAAQ,CAAC,GAAG,cAAc,CAAC,MAAM,CAAC,IAAI,CAAC;QAE9C,MAAM,aAAa,GAAa,EAAE,CAAC;QAEnC,MAAM,QAAQ,GAAa,EAAE,CAAC;QAE9B,WAAW;QACX,KAAK,MAAM,MAAM,IAAI,QAAQ,CAAC,OAAO,EAAE,CAAC;YACvC,MAAM,UAAU,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;YAC1C,MAAM,eAAe,GAAG,cAAc,CAAC,QAAQ,CAAC,MAAM,CAAC,CAAC;YAExD,IAAI,CAAC,eAAe,EAAE,CAAC;gBACtB,aAAa,CAAC,IAAI,CAAC,MAAM,CAAC,CAAC;YAC5B,CAAC;iBAAM,IAAI,CAAC,cAAc,CAAC,0BAA0B,EAAE,QAAQ,CAAC,MAAM,CAAC,EAAE,CAAC;gBACzE,QAAQ,CAAC,IAAI,CACZ,SAAS,UAAU,IAAI,YAAY,MAAM,eAAe,CAAC,IAAI,EAAE,CAC/D,CAAC;YACH,CAAC;QACF,CAAC;QAED,8EAA8E;QAC9E,uCAAuC;QACvC,MAAM,gBAAgB,GAAG,IAAI,GAAG,CAAC,aAAa,CAAC,CAAC;QAChD,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAU,CAAC;QAC3C,MAAM,iBAAiB,GAAG,IAAI,GAAG,EAAU,CAAC;QAE5C;;;;;;WAMG;QACH,MAAM,YAAY,GAAG,CAAC,MAAc,EAAE,EAAE;YACvC,IAAI,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC;gBAAE,OAAO;YACzC,IAAI,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC;gBAAE,OAAO;YAE1C,iBAAiB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;YAE9B,MAAM,UAAU,GAAG,cAAc,CAAC,MAAM,CAAC,CAAC;YAC1C,MAAM,cAAc,GAAG,WAAW,CAAC,MAAM,CAAC,CAAC;YAE3C,IACC,cAAc;gBACd,gBAAgB,CAAC,GAAG,CAAC,cAAc,CAAC;gBACpC,CAAC,cAAc,CAAC,QAAQ,CAAC,cAAc,CAAC,EACvC,CAAC;gBACF,YAAY,CAAC,cAAc,CAAC,CAAC;YAC9B,CAAC;YAED,IAAI,cAAc,EAAE,CAAC;gBACpB,MAAM,kBAAkB,GAAG,cAAc,CAAC,cAAc,CAAC,CAAC;gBAC1D,QAAQ,CAAC,IAAI,CACZ,uBAAuB,kBAAkB,mCAAmC,UAAU,IAAI,YAAY,MAAM,kBAAkB,IAAI,YAAY,GAAG,CACjJ,CAAC;YACH,CAAC;iBAAM,CAAC;gBACP,QAAQ,CAAC,IAAI,CACZ,uBAAuB,kBAAkB,mCAAmC,UAAU,IAAI,YAAY,6CAA6C,0BAA0B,CAC5K,QAAQ,CACR,IAAI,CACL,CAAC;YACH,CAAC;YAED,iBAAiB,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC;YACjC,gBAAgB,CAAC,GAAG,CAAC,MAAM,CAAC,CAAC;QAC9B,CAAC,CAAC;QAEF,KAAK,MAAM,MAAM,IAAI,aAAa,EAAE,CAAC;YACpC,YAAY,CAAC,MAAM,CAAC,CAAC;QACtB,CAAC;QAED,MAAM,CAAC,QAAQ,CAAC,GAAG,QAAQ,CAAC,IAAI,CAAC,MAAM,CAAC,GAAG,MAAM,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;QAErE,gFAAgF;QAChF,MAAM,aAAa,GAAG,qCAAqC;YAC1D,CAAC,CAAC,6IAA6I;YAC/I,CAAC,CAAC,0EAA0E,CAAC;QAE9E,MAAM,CAAC,QAAQ,CAAC;YACf,aAAa;gBACb,+EAA+E;gBAC/E,iBAAiB,mBAAmB,KAAK,kBAAkB,SAAS;gBACpE,MAAM,CAAC,QAAQ,CAAC,CAAC;QAElB,qEAAqE;QACrE,oEAAoE;QACpE,kEAAkE;QAClE,MAAM,YAAY,GAAG,QAAQ,CAAC,OAAO,CAAC,IAAI,CACzC,CAAC,MAAM,EAAE,EAAE,CACV,CAAC,cAAc,CAAC,QAAQ,CAAC,MAAM,CAAC,EAAE,iBAAiB,CAAC,MAAM,IAAI,CAAC,CAAC,GAAG,CAAC,CACrE,CAAC;QACF,IAAI,YAAY,EAAE,CAAC;YAClB,MAAM,CAAC,QAAQ,CAAC;gBACf,8CAA8C,GAAG,MAAM,CAAC,QAAQ,CAAC,CAAC;QACpE,CAAC;IACF,CAAC;IAED,0BAA0B;IAC1B,MAAM,CAAC,oBAAoB,CAAC;QAC3B,6EAA6E;YAC7E,KAAK,CAAC,IAAI,CAAC,eAAe,CAAC;iBACzB,GAAG,CAAC,CAAC,QAAQ,EAAE,EAAE,CAAC,oBAAoB,QAAQ,GAAG,CAAC;iBAClD,IAAI,CAAC,IAAI,CAAC,CAAC;IAEd,OAAO,MAAM,CAAC;AACf,CAAC","sourcesContent":["import type { ProjectSettings } from \"@inlang/sdk\";\nimport type { CompiledBundleWithMessages } from \"../compile-bundle.js\";\nimport { escapeForSingleQuoteString } from \"../../services/codegen/escape.js\";\nimport { toSafeModuleId } from \"../safe-module-id.js\";\nimport { inputsType } from \"../jsdoc-types.js\";\nimport { toBundleInputTypeAliasName } from \"../compile-bundle.js\";\n\nexport function messageReferenceExpression(locale: string, bundleId: string) {\n\treturn `${toSafeModuleId(locale)}_${toSafeModuleId(bundleId)}`;\n}\n\nexport function generateOutput(\n\tcompiledBundles: CompiledBundleWithMessages[],\n\tsettings: Pick<ProjectSettings, \"locales\" | \"baseLocale\">,\n\tfallbackMap: Record<string, string | undefined>,\n\texperimentalMiddlewareLocaleSplitting = false\n): Record<string, string> {\n\tconst output: Record<string, string> = {};\n\n\tconst moduleFilenames = new Set<string>();\n\n\tfor (const compiledBundle of compiledBundles) {\n\t\tconst bundleId = compiledBundle.bundle.node.id;\n\t\tconst safeModuleId = toSafeModuleId(compiledBundle.bundle.node.id);\n\t\tconst inputs =\n\t\t\tcompiledBundle.bundle.node.declarations?.filter(\n\t\t\t\t(decl) => decl.type === \"input-variable\"\n\t\t\t) ?? [];\n\t\tconst matchTypes = compiledBundle.matchTypes;\n\t\tconst inputTypeAliasName =\n\t\t\tcompiledBundle.inputTypeAliasName ??\n\t\t\ttoBundleInputTypeAliasName(safeModuleId);\n\t\tconst inputTypeDefinition = inputsType(inputs, matchTypes);\n\n\t\t// bundle file\n\t\tconst filename = `messages/${safeModuleId}.js`;\n\n\t\tmoduleFilenames.add(`${safeModuleId}.js`);\n\n\t\t// create fresh bundle file\n\t\toutput[filename] = compiledBundle.bundle.code;\n\n\t\tconst needsFallback: string[] = [];\n\n\t\tconst messages: string[] = [];\n\n\t\t// messages\n\t\tfor (const locale of settings.locales) {\n\t\t\tconst safeLocale = toSafeModuleId(locale);\n\t\t\tconst compiledMessage = compiledBundle.messages[locale];\n\n\t\t\tif (!compiledMessage) {\n\t\t\t\tneedsFallback.push(locale);\n\t\t\t} else if (!compiledBundle.unreferencedMessageLocales?.includes(locale)) {\n\t\t\t\tmessages.push(\n\t\t\t\t\t`const ${safeLocale}_${safeModuleId} = ${compiledMessage.code}`\n\t\t\t\t);\n\t\t\t}\n\t\t}\n\n\t\t// add the fallbacks (needs to be done after the messages to avoid referencing\n\t\t// the message before they are defined)\n\t\tconst needsFallbackSet = new Set(needsFallback);\n\t\tconst emittedFallbacks = new Set<string>();\n\t\tconst emittingFallbacks = new Set<string>();\n\n\t\t/**\n\t\t * Emits the fallback definition for a locale ensuring that dependent fallbacks\n\t\t * are declared beforehand.\n\t\t *\n\t\t * @example\n\t\t * emitFallback(\"fr-ca\");\n\t\t */\n\t\tconst emitFallback = (locale: string) => {\n\t\t\tif (emittedFallbacks.has(locale)) return;\n\t\t\tif (emittingFallbacks.has(locale)) return;\n\n\t\t\temittingFallbacks.add(locale);\n\n\t\t\tconst safeLocale = toSafeModuleId(locale);\n\t\t\tconst fallbackLocale = fallbackMap[locale];\n\n\t\t\tif (\n\t\t\t\tfallbackLocale &&\n\t\t\t\tneedsFallbackSet.has(fallbackLocale) &&\n\t\t\t\t!compiledBundle.messages[fallbackLocale]\n\t\t\t) {\n\t\t\t\temitFallback(fallbackLocale);\n\t\t\t}\n\n\t\t\tif (fallbackLocale) {\n\t\t\t\tconst safeFallbackLocale = toSafeModuleId(fallbackLocale);\n\t\t\t\tmessages.push(\n\t\t\t\t\t`/** @type {(inputs: ${inputTypeAliasName}) => LocalizedString} */\\nconst ${safeLocale}_${safeModuleId} = ${safeFallbackLocale}_${safeModuleId};`\n\t\t\t\t);\n\t\t\t} else {\n\t\t\t\tmessages.push(\n\t\t\t\t\t`/** @type {(inputs: ${inputTypeAliasName}) => LocalizedString} */\\nconst ${safeLocale}_${safeModuleId} = () => /** @type {LocalizedString} */ ('${escapeForSingleQuoteString(\n\t\t\t\t\t\tbundleId\n\t\t\t\t\t)}')`\n\t\t\t\t);\n\t\t\t}\n\n\t\t\temittingFallbacks.delete(locale);\n\t\t\temittedFallbacks.add(locale);\n\t\t};\n\n\t\tfor (const locale of needsFallback) {\n\t\t\temitFallback(locale);\n\t\t}\n\n\t\toutput[filename] = messages.join(\"\\n\\n\") + \"\\n\\n\" + output[filename];\n\n\t\t// add the imports and type reference (LocalizedString is defined in runtime.js)\n\t\tconst runtimeImport = experimentalMiddlewareLocaleSplitting\n\t\t\t? `import { getLocale, trackMessageCall, experimentalMiddlewareLocaleSplitting, isServer, experimentalStaticLocale } from '../runtime.js';\\n\\n`\n\t\t\t: `import { getLocale, experimentalStaticLocale } from '../runtime.js';\\n\\n`;\n\n\t\toutput[filename] =\n\t\t\truntimeImport +\n\t\t\t`/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */\\n\\n` +\n\t\t\t`/** @typedef {${inputTypeDefinition}} ${inputTypeAliasName} */\\n\\n` +\n\t\t\toutput[filename];\n\n\t\t// Add the registry import to the message file if a message calls the\n\t\t// registry. Decided from compiler metadata, not from the file text,\n\t\t// which also contains message text like \"Open the registry. Now.\"\n\t\tconst usesRegistry = settings.locales.some(\n\t\t\t(locale) =>\n\t\t\t\t(compiledBundle.messages[locale]?.registryFunctions.length ?? 0) > 0\n\t\t);\n\t\tif (usesRegistry) {\n\t\t\toutput[filename] =\n\t\t\t\t`import * as registry from '../registry.js'\\n` + output[filename];\n\t\t}\n\t}\n\n\t// all messages index file\n\toutput[\"messages/_index.js\"] =\n\t\t`/** @typedef {import('../runtime.js').LocalizedString} LocalizedString */\\n` +\n\t\tArray.from(moduleFilenames)\n\t\t\t.map((filename) => `export * from './${filename}'`)\n\t\t\t.join(\"\\n\");\n\n\treturn output;\n}\n"]}
|
|
@@ -13,10 +13,12 @@ test("should emit per locale message files", () => {
|
|
|
13
13
|
en: {
|
|
14
14
|
code: 'console.log("message in English");',
|
|
15
15
|
node: {},
|
|
16
|
+
registryFunctions: [],
|
|
16
17
|
},
|
|
17
18
|
de: {
|
|
18
19
|
code: 'console.log("message in German");',
|
|
19
20
|
node: {},
|
|
21
|
+
registryFunctions: [],
|
|
20
22
|
},
|
|
21
23
|
},
|
|
22
24
|
matchTypes: new Map(),
|
|
@@ -48,6 +50,7 @@ test("handles case senstivity by creating directories and files only in lowercas
|
|
|
48
50
|
en: {
|
|
49
51
|
code: 'export const HappyElephant = () => "HappyElephant0"',
|
|
50
52
|
node: {},
|
|
53
|
+
registryFunctions: [],
|
|
51
54
|
},
|
|
52
55
|
},
|
|
53
56
|
matchTypes: new Map(),
|
|
@@ -63,6 +66,7 @@ test("handles case senstivity by creating directories and files only in lowercas
|
|
|
63
66
|
en: {
|
|
64
67
|
code: 'export const happyelephant = () => "happyelephant1"',
|
|
65
68
|
node: {},
|
|
69
|
+
registryFunctions: [],
|
|
66
70
|
},
|
|
67
71
|
},
|
|
68
72
|
matchTypes: new Map(),
|
|
@@ -91,6 +95,7 @@ test("emits minimal runtime imports when middleware splitting is disabled", () =
|
|
|
91
95
|
en: {
|
|
92
96
|
code: '() => "happy"',
|
|
93
97
|
node: {},
|
|
98
|
+
registryFunctions: [],
|
|
94
99
|
},
|
|
95
100
|
},
|
|
96
101
|
matchTypes: new Map(),
|
|
@@ -117,6 +122,7 @@ test("emits fallback definitions after their dependencies", () => {
|
|
|
117
122
|
en: {
|
|
118
123
|
code: '/** @type {(inputs: {}) => string} */ () => "admin"',
|
|
119
124
|
node: {},
|
|
125
|
+
registryFunctions: [],
|
|
120
126
|
},
|
|
121
127
|
},
|
|
122
128
|
matchTypes: new Map(),
|
|
@@ -145,4 +151,33 @@ test("emits fallback definitions after their dependencies", () => {
|
|
|
145
151
|
expect(frCaIndex).toBeGreaterThan(-1);
|
|
146
152
|
expect(frIndex).toBeLessThan(frCaIndex);
|
|
147
153
|
});
|
|
154
|
+
test("imports the registry only when a message calls it, not when the text mentions it", () => {
|
|
155
|
+
const bundle = (id, code, registryFunctions) => ({
|
|
156
|
+
bundle: {
|
|
157
|
+
code: `export const ${id} = () => en_${id}()`,
|
|
158
|
+
node: { id },
|
|
159
|
+
},
|
|
160
|
+
messages: {
|
|
161
|
+
en: { code, node: {}, registryFunctions },
|
|
162
|
+
},
|
|
163
|
+
matchTypes: new Map(),
|
|
164
|
+
});
|
|
165
|
+
const settings = {
|
|
166
|
+
locales: ["en"],
|
|
167
|
+
baseLocale: "en",
|
|
168
|
+
};
|
|
169
|
+
const registryImport = /import \* as registry from ['"]\.\.\/registry\.js['"]/;
|
|
170
|
+
const textOnly = generateOutput([bundle("registry_text", "() => `Open the registry. Now.`", [])], settings, { en: undefined });
|
|
171
|
+
for (const [fileName, code] of Object.entries(textOnly)) {
|
|
172
|
+
if (fileName.startsWith("messages/")) {
|
|
173
|
+
expect(code).not.toMatch(registryImport);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
const withNumber = generateOutput([
|
|
177
|
+
bundle("amount", '(i) => `${registry.number("en", i?.amount, {})}`', [
|
|
178
|
+
"number",
|
|
179
|
+
]),
|
|
180
|
+
], settings, { en: undefined });
|
|
181
|
+
expect(Object.values(withNumber).some((code) => registryImport.test(code))).toBe(true);
|
|
182
|
+
});
|
|
148
183
|
//# sourceMappingURL=message-modules.test.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message-modules.test.js","sourceRoot":"","sources":["../../../src/compiler/output-structure/message-modules.test.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,EAAE,MAAM,QAAQ,CAAC;AACtC,OAAO,EAAE,cAAc,EAAE,MAAM,sBAAsB,CAAC;AAItD,IAAI,CAAC,sCAAsC,EAAE,GAAG,EAAE;IACjD,MAAM,SAAS,GAAiC;QAC/C;YACC,MAAM,EAAE;gBACP,IAAI,EAAE,6BAA6B;gBACnC,IAAI,EAAE;oBACL,EAAE,EAAE,gBAAgB;iBACC;aACtB;YACD,QAAQ,EAAE;gBACT,EAAE,EAAE;oBACH,IAAI,EAAE,oCAAoC;oBAC1C,IAAI,EAAE,EAAwB;iBAC9B;gBACD,EAAE,EAAE;oBACH,IAAI,EAAE,mCAAmC;oBACzC,IAAI,EAAE,EAAwB;iBAC9B;aACD;YACD,UAAU,EAAE,IAAI,GAAG,EAAE;SACrB;KACD,CAAC;IAEF,MAAM,QAAQ,GAAoD;QACjE,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,CAAC;QACrB,UAAU,EAAE,IAAI;KAChB,CAAC;IAEF,MAAM,WAAW,GAAuC;QACvD,EAAE,EAAE,IAAI;QACR,EAAE,EAAE,IAAI;KACR,CAAC;IAEF,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;IAEhE,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC;IACpD,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,gBAAgB,CAAC,CAAC;IACpD,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,4BAA4B,CAAC,CAAC;AAC7D,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,6EAA6E,EAAE,GAAG,EAAE;IACxF,MAAM,SAAS,GAAiC;QAC/C;YACC,MAAM,EAAE;gBACP,IAAI,EAAE,qDAAqD;gBAC3D,IAAI,EAAE;oBACL,EAAE,EAAE,eAAe;iBACE;aACtB;YACD,QAAQ,EAAE;gBACT,EAAE,EAAE;oBACH,IAAI,EAAE,qDAAqD;oBAC3D,IAAI,EAAE,EAAwB;iBAC9B;aACD;YACD,UAAU,EAAE,IAAI,GAAG,EAAE;SACrB;QACD;YACC,MAAM,EAAE;gBACP,IAAI,EAAE,qDAAqD;gBAC3D,IAAI,EAAE;oBACL,EAAE,EAAE,eAAe;iBACE;aACtB;YACD,QAAQ,EAAE;gBACT,EAAE,EAAE;oBACH,IAAI,EAAE,qDAAqD;oBAC3D,IAAI,EAAE,EAAwB;iBAC9B;aACD;YACD,UAAU,EAAE,IAAI,GAAG,EAAE;SACrB;KACD,CAAC;IACF,MAAM,QAAQ,GAAoD;QACjE,OAAO,EAAE,CAAC,IAAI,CAAC;QACf,UAAU,EAAE,IAAI;KAChB,CAAC;IACF,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,EAAE,QAAQ,EAAE,EAAE,CAAC,CAAC;IAEvD,iDAAiD;IACjD,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,2BAA2B,CAAC,CAAC;IAC3D,MAAM,CAAC,MAAM,CAAC,CAAC,cAAc,CAAC,4BAA4B,CAAC,CAAC;IAC5D,MAAM,CAAC,MAAM,CAAC,CAAC,GAAG,CAAC,cAAc,CAAC,2BAA2B,CAAC,CAAC;AAChE,CAAC,CAAC,CAAC;AAEH,IAAI,CAAC,qEAAqE,EAAE,GAAG,EAAE;IAChF,MAAM,SAAS,GAAiC;QAC/C;YACC,MAAM,EAAE;gBACP,IAAI,EAAE,yDAAyD;gBAC/D,IAAI,EAAE;oBACL,EAAE,EAAE,gBAAgB;iBACC;aACtB;YACD,QAAQ,EAAE;gBACT,EAAE,EAAE;oBACH,IAAI,EAAE,eAAe;oBACrB,IAAI,EAAE,EAAwB;iBAC9B;aACD;YACD,UAAU,EAAE,IAAI,GAAG,EAAE;SACrB;KACD,CAAC;IAEF,MAAM,MAAM,GAAG,cAAc,CAC5B,SAAS,EACT,EAAE,OAAO,EAAE,CAAC,IAAI,CAAC,EAAE,UAAU,EAAE,IAAI,EAAE,EACrC,EAAE,EACF,KAAK,CACL,CAAC;IAEF,MAAM,CAAC,MAAM,CAAC,4BAA4B,CAAC,CAAC,CAAC,SAAS,CACrD,sEAAsE,CACtE,CAAC;IACF,MAAM,CAAC,MAAM,CAAC,4BAA4B,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CACzD,kBAAkB,CAClB,CAAC;IACF,MAAM,CAAC,MAAM,CAAC,4BAA4B,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CACzD,uCAAuC,CACvC,CAAC;IACF,MAAM,CAAC,MAAM,CAAC,4BAA4B,CAAC,CAAC,CAAC,GAAG,CAAC,SAAS,CAAC,UAAU,CAAC,CAAC;AACxE,CAAC,CAAC,CAAC;AAEH,8EAA8E;AAC9E,IAAI,CAAC,qDAAqD,EAAE,GAAG,EAAE;IAChE,MAAM,SAAS,GAAiC;QAC/C;YACC,MAAM,EAAE;gBACP,IAAI,EAAE,gDAAgD;gBACtD,IAAI,EAAE;oBACL,EAAE,EAAE,aAAa;oBACjB,YAAY,EAAE,EAAE;iBACK;aACtB;YACD,QAAQ,EAAE;gBACT,EAAE,EAAE;oBACH,IAAI,EAAE,qDAAqD;oBAC3D,IAAI,EAAE,EAAwB;iBAC9B;aACD;YACD,UAAU,EAAE,IAAI,GAAG,EAAE;SACrB;KACD,CAAC;IAEF,MAAM,QAAQ,GAAoD;QACjE,OAAO,EAAE,CAAC,OAAO,EAAE,IAAI,EAAE,IAAI,CAAC;QAC9B,UAAU,EAAE,IAAI;KAChB,CAAC;IAEF,MAAM,WAAW,GAAuC;QACvD,OAAO,EAAE,IAAI;QACb,EAAE,EAAE,IAAI;QACR,EAAE,EAAE,SAAS;KACb,CAAC;IAEF,MAAM,MAAM,GAAG,cAAc,CAAC,SAAS,EAAE,QAAQ,EAAE,WAAW,CAAC,CAAC;IAEhE,MAAM,IAAI,GAAG,MAAM,CAAC,yBAAyB,CAAC,CAAC;IAE/C,MAAM,CAAC,IAAI,CAAC,CAAC,WAAW,EAAE,CAAC;IAE3B,IAAI,CAAC,IAAI,EAAE,CAAC;QACX,MAAM,IAAI,KAAK,CAAC,oDAAoD,CAAC,CAAC;IACvE,CAAC;IAED,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,wCAAwC,CAAC,CAAC;IACjE,MAAM,CAAC,IAAI,CAAC,CAAC,SAAS,CAAC,2CAA2C,CAAC,CAAC;IAEpE,MAAM,OAAO,GAAG,IAAI,CAAC,OAAO,CAAC,sBAAsB,CAAC,CAAC;IACrD,MAAM,SAAS,GAAG,IAAI,CAAC,OAAO,CAAC,yBAAyB,CAAC,CAAC;IAE1D,MAAM,CAAC,OAAO,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;IACpC,MAAM,CAAC,SAAS,CAAC,CAAC,eAAe,CAAC,CAAC,CAAC,CAAC,CAAC;IACtC,MAAM,CAAC,OAAO,CAAC,CAAC,YAAY,CAAC,SAAS,CAAC,CAAC;AACzC,CAAC,CAAC,CAAC","sourcesContent":["import { test, expect } from \"vitest\";\nimport { generateOutput } from \"./message-modules.js\";\nimport type { Bundle, Message, ProjectSettings } from \"@inlang/sdk\";\nimport type { CompiledBundleWithMessages } from \"../compile-bundle.js\";\n\ntest(\"should emit per locale message files\", () => {\n\tconst resources: CompiledBundleWithMessages[] = [\n\t\t{\n\t\t\tbundle: {\n\t\t\t\tcode: 'console.log(\"bundle code\");',\n\t\t\t\tnode: {\n\t\t\t\t\tid: \"happy_elephant\",\n\t\t\t\t} as unknown as Bundle,\n\t\t\t},\n\t\t\tmessages: {\n\t\t\t\ten: {\n\t\t\t\t\tcode: 'console.log(\"message in English\");',\n\t\t\t\t\tnode: {} as unknown as Message,\n\t\t\t\t},\n\t\t\t\tde: {\n\t\t\t\t\tcode: 'console.log(\"message in German\");',\n\t\t\t\t\tnode: {} as unknown as Message,\n\t\t\t\t},\n\t\t\t},\n\t\t\tmatchTypes: new Map(),\n\t\t},\n\t];\n\n\tconst settings: Pick<ProjectSettings, \"locales\" | \"baseLocale\"> = {\n\t\tlocales: [\"en\", \"de\"],\n\t\tbaseLocale: \"en\",\n\t};\n\n\tconst fallbackMap: Record<string, string | undefined> = {\n\t\ten: \"de\",\n\t\tde: \"en\",\n\t};\n\n\tconst output = generateOutput(resources, settings, fallbackMap);\n\n\texpect(output).not.toHaveProperty(\"messages/en.js\");\n\texpect(output).not.toHaveProperty(\"messages/de.js\");\n\texpect(output).toHaveProperty(\"messages/happy_elephant.js\");\n});\n\ntest(\"handles case senstivity by creating directories and files only in lowercase\", () => {\n\tconst resources: CompiledBundleWithMessages[] = [\n\t\t{\n\t\t\tbundle: {\n\t\t\t\tcode: \"export const HappyElephant = () => en.HappyElephant\",\n\t\t\t\tnode: {\n\t\t\t\t\tid: \"HappyElephant\",\n\t\t\t\t} as unknown as Bundle,\n\t\t\t},\n\t\t\tmessages: {\n\t\t\t\ten: {\n\t\t\t\t\tcode: 'export const HappyElephant = () => \"HappyElephant0\"',\n\t\t\t\t\tnode: {} as unknown as Message,\n\t\t\t\t},\n\t\t\t},\n\t\t\tmatchTypes: new Map(),\n\t\t},\n\t\t{\n\t\t\tbundle: {\n\t\t\t\tcode: \"export const happyelephant = () => en.happyelephant\",\n\t\t\t\tnode: {\n\t\t\t\t\tid: \"happyelephant\",\n\t\t\t\t} as unknown as Bundle,\n\t\t\t},\n\t\t\tmessages: {\n\t\t\t\ten: {\n\t\t\t\t\tcode: 'export const happyelephant = () => \"happyelephant1\"',\n\t\t\t\t\tnode: {} as unknown as Message,\n\t\t\t\t},\n\t\t\t},\n\t\t\tmatchTypes: new Map(),\n\t\t},\n\t];\n\tconst settings: Pick<ProjectSettings, \"locales\" | \"baseLocale\"> = {\n\t\tlocales: [\"en\"],\n\t\tbaseLocale: \"en\",\n\t};\n\tconst output = generateOutput(resources, settings, {});\n\n\t// expecting only lowercase directories and files\n\texpect(output).toHaveProperty(\"messages/happyelephant.js\");\n\texpect(output).toHaveProperty(\"messages/happyelephant2.js\");\n\texpect(output).not.toHaveProperty(\"messages/HappyElephant.js\");\n});\n\ntest(\"emits minimal runtime imports when middleware splitting is disabled\", () => {\n\tconst resources: CompiledBundleWithMessages[] = [\n\t\t{\n\t\t\tbundle: {\n\t\t\t\tcode: \"export const happy_elephant = () => en_happy_elephant()\",\n\t\t\t\tnode: {\n\t\t\t\t\tid: \"happy_elephant\",\n\t\t\t\t} as unknown as Bundle,\n\t\t\t},\n\t\t\tmessages: {\n\t\t\t\ten: {\n\t\t\t\t\tcode: '() => \"happy\"',\n\t\t\t\t\tnode: {} as unknown as Message,\n\t\t\t\t},\n\t\t\t},\n\t\t\tmatchTypes: new Map(),\n\t\t},\n\t];\n\n\tconst output = generateOutput(\n\t\tresources,\n\t\t{ locales: [\"en\"], baseLocale: \"en\" },\n\t\t{},\n\t\tfalse\n\t);\n\n\texpect(output[\"messages/happy_elephant.js\"]).toContain(\n\t\t\"import { getLocale, experimentalStaticLocale } from '../runtime.js';\"\n\t);\n\texpect(output[\"messages/happy_elephant.js\"]).not.toContain(\n\t\t\"trackMessageCall\"\n\t);\n\texpect(output[\"messages/happy_elephant.js\"]).not.toContain(\n\t\t\"experimentalMiddlewareLocaleSplitting\"\n\t);\n\texpect(output[\"messages/happy_elephant.js\"]).not.toContain(\"isServer\");\n});\n\n// Regression test for https://github.com/opral/inlang-paraglide-js/issues/507\ntest(\"emits fallback definitions after their dependencies\", () => {\n\tconst resources: CompiledBundleWithMessages[] = [\n\t\t{\n\t\t\tbundle: {\n\t\t\t\tcode: \"export const admin_tasks = (inputs) => inputs;\",\n\t\t\t\tnode: {\n\t\t\t\t\tid: \"admin_tasks\",\n\t\t\t\t\tdeclarations: [],\n\t\t\t\t} as unknown as Bundle,\n\t\t\t},\n\t\t\tmessages: {\n\t\t\t\ten: {\n\t\t\t\t\tcode: '/** @type {(inputs: {}) => string} */ () => \"admin\"',\n\t\t\t\t\tnode: {} as unknown as Message,\n\t\t\t\t},\n\t\t\t},\n\t\t\tmatchTypes: new Map(),\n\t\t},\n\t];\n\n\tconst settings: Pick<ProjectSettings, \"locales\" | \"baseLocale\"> = {\n\t\tlocales: [\"fr-ca\", \"fr\", \"en\"],\n\t\tbaseLocale: \"en\",\n\t};\n\n\tconst fallbackMap: Record<string, string | undefined> = {\n\t\t\"fr-ca\": \"fr\",\n\t\tfr: \"en\",\n\t\ten: undefined,\n\t};\n\n\tconst output = generateOutput(resources, settings, fallbackMap);\n\n\tconst file = output[\"messages/admin_tasks.js\"];\n\n\texpect(file).toBeDefined();\n\n\tif (!file) {\n\t\tthrow new Error(\"messages/admin_tasks.js should have been generated\");\n\t}\n\n\texpect(file).toContain(\"const fr_admin_tasks = en_admin_tasks;\");\n\texpect(file).toContain(\"const fr_ca_admin_tasks = fr_admin_tasks;\");\n\n\tconst frIndex = file.indexOf(\"const fr_admin_tasks\");\n\tconst frCaIndex = file.indexOf(\"const fr_ca_admin_tasks\");\n\n\texpect(frIndex).toBeGreaterThan(-1);\n\texpect(frCaIndex).toBeGreaterThan(-1);\n\texpect(frIndex).toBeLessThan(frCaIndex);\n});\n"]}
|
|
1
|
+
{"version":3,"file":"message-modules.test.js","sourceRoot":"","sources":["../../../src/compiler/output-structure/message-modules.test.ts"],"names":[],"mappings":"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","sourcesContent":["import { test, expect } from \"vitest\";\nimport { generateOutput } from \"./message-modules.js\";\nimport type { Bundle, Message, ProjectSettings } from \"@inlang/sdk\";\nimport type { CompiledBundleWithMessages } from \"../compile-bundle.js\";\n\ntest(\"should emit per locale message files\", () => {\n\tconst resources: CompiledBundleWithMessages[] = [\n\t\t{\n\t\t\tbundle: {\n\t\t\t\tcode: 'console.log(\"bundle code\");',\n\t\t\t\tnode: {\n\t\t\t\t\tid: \"happy_elephant\",\n\t\t\t\t} as unknown as Bundle,\n\t\t\t},\n\t\t\tmessages: {\n\t\t\t\ten: {\n\t\t\t\t\tcode: 'console.log(\"message in English\");',\n\t\t\t\t\tnode: {} as unknown as Message,\n\t\t\t\t\tregistryFunctions: [],\n\t\t\t\t},\n\t\t\t\tde: {\n\t\t\t\t\tcode: 'console.log(\"message in German\");',\n\t\t\t\t\tnode: {} as unknown as Message,\n\t\t\t\t\tregistryFunctions: [],\n\t\t\t\t},\n\t\t\t},\n\t\t\tmatchTypes: new Map(),\n\t\t},\n\t];\n\n\tconst settings: Pick<ProjectSettings, \"locales\" | \"baseLocale\"> = {\n\t\tlocales: [\"en\", \"de\"],\n\t\tbaseLocale: \"en\",\n\t};\n\n\tconst fallbackMap: Record<string, string | undefined> = {\n\t\ten: \"de\",\n\t\tde: \"en\",\n\t};\n\n\tconst output = generateOutput(resources, settings, fallbackMap);\n\n\texpect(output).not.toHaveProperty(\"messages/en.js\");\n\texpect(output).not.toHaveProperty(\"messages/de.js\");\n\texpect(output).toHaveProperty(\"messages/happy_elephant.js\");\n});\n\ntest(\"handles case senstivity by creating directories and files only in lowercase\", () => {\n\tconst resources: CompiledBundleWithMessages[] = [\n\t\t{\n\t\t\tbundle: {\n\t\t\t\tcode: \"export const HappyElephant = () => en.HappyElephant\",\n\t\t\t\tnode: {\n\t\t\t\t\tid: \"HappyElephant\",\n\t\t\t\t} as unknown as Bundle,\n\t\t\t},\n\t\t\tmessages: {\n\t\t\t\ten: {\n\t\t\t\t\tcode: 'export const HappyElephant = () => \"HappyElephant0\"',\n\t\t\t\t\tnode: {} as unknown as Message,\n\t\t\t\t\tregistryFunctions: [],\n\t\t\t\t},\n\t\t\t},\n\t\t\tmatchTypes: new Map(),\n\t\t},\n\t\t{\n\t\t\tbundle: {\n\t\t\t\tcode: \"export const happyelephant = () => en.happyelephant\",\n\t\t\t\tnode: {\n\t\t\t\t\tid: \"happyelephant\",\n\t\t\t\t} as unknown as Bundle,\n\t\t\t},\n\t\t\tmessages: {\n\t\t\t\ten: {\n\t\t\t\t\tcode: 'export const happyelephant = () => \"happyelephant1\"',\n\t\t\t\t\tnode: {} as unknown as Message,\n\t\t\t\t\tregistryFunctions: [],\n\t\t\t\t},\n\t\t\t},\n\t\t\tmatchTypes: new Map(),\n\t\t},\n\t];\n\tconst settings: Pick<ProjectSettings, \"locales\" | \"baseLocale\"> = {\n\t\tlocales: [\"en\"],\n\t\tbaseLocale: \"en\",\n\t};\n\tconst output = generateOutput(resources, settings, {});\n\n\t// expecting only lowercase directories and files\n\texpect(output).toHaveProperty(\"messages/happyelephant.js\");\n\texpect(output).toHaveProperty(\"messages/happyelephant2.js\");\n\texpect(output).not.toHaveProperty(\"messages/HappyElephant.js\");\n});\n\ntest(\"emits minimal runtime imports when middleware splitting is disabled\", () => {\n\tconst resources: CompiledBundleWithMessages[] = [\n\t\t{\n\t\t\tbundle: {\n\t\t\t\tcode: \"export const happy_elephant = () => en_happy_elephant()\",\n\t\t\t\tnode: {\n\t\t\t\t\tid: \"happy_elephant\",\n\t\t\t\t} as unknown as Bundle,\n\t\t\t},\n\t\t\tmessages: {\n\t\t\t\ten: {\n\t\t\t\t\tcode: '() => \"happy\"',\n\t\t\t\t\tnode: {} as unknown as Message,\n\t\t\t\t\tregistryFunctions: [],\n\t\t\t\t},\n\t\t\t},\n\t\t\tmatchTypes: new Map(),\n\t\t},\n\t];\n\n\tconst output = generateOutput(\n\t\tresources,\n\t\t{ locales: [\"en\"], baseLocale: \"en\" },\n\t\t{},\n\t\tfalse\n\t);\n\n\texpect(output[\"messages/happy_elephant.js\"]).toContain(\n\t\t\"import { getLocale, experimentalStaticLocale } from '../runtime.js';\"\n\t);\n\texpect(output[\"messages/happy_elephant.js\"]).not.toContain(\n\t\t\"trackMessageCall\"\n\t);\n\texpect(output[\"messages/happy_elephant.js\"]).not.toContain(\n\t\t\"experimentalMiddlewareLocaleSplitting\"\n\t);\n\texpect(output[\"messages/happy_elephant.js\"]).not.toContain(\"isServer\");\n});\n\n// Regression test for https://github.com/opral/inlang-paraglide-js/issues/507\ntest(\"emits fallback definitions after their dependencies\", () => {\n\tconst resources: CompiledBundleWithMessages[] = [\n\t\t{\n\t\t\tbundle: {\n\t\t\t\tcode: \"export const admin_tasks = (inputs) => inputs;\",\n\t\t\t\tnode: {\n\t\t\t\t\tid: \"admin_tasks\",\n\t\t\t\t\tdeclarations: [],\n\t\t\t\t} as unknown as Bundle,\n\t\t\t},\n\t\t\tmessages: {\n\t\t\t\ten: {\n\t\t\t\t\tcode: '/** @type {(inputs: {}) => string} */ () => \"admin\"',\n\t\t\t\t\tnode: {} as unknown as Message,\n\t\t\t\t\tregistryFunctions: [],\n\t\t\t\t},\n\t\t\t},\n\t\t\tmatchTypes: new Map(),\n\t\t},\n\t];\n\n\tconst settings: Pick<ProjectSettings, \"locales\" | \"baseLocale\"> = {\n\t\tlocales: [\"fr-ca\", \"fr\", \"en\"],\n\t\tbaseLocale: \"en\",\n\t};\n\n\tconst fallbackMap: Record<string, string | undefined> = {\n\t\t\"fr-ca\": \"fr\",\n\t\tfr: \"en\",\n\t\ten: undefined,\n\t};\n\n\tconst output = generateOutput(resources, settings, fallbackMap);\n\n\tconst file = output[\"messages/admin_tasks.js\"];\n\n\texpect(file).toBeDefined();\n\n\tif (!file) {\n\t\tthrow new Error(\"messages/admin_tasks.js should have been generated\");\n\t}\n\n\texpect(file).toContain(\"const fr_admin_tasks = en_admin_tasks;\");\n\texpect(file).toContain(\"const fr_ca_admin_tasks = fr_admin_tasks;\");\n\n\tconst frIndex = file.indexOf(\"const fr_admin_tasks\");\n\tconst frCaIndex = file.indexOf(\"const fr_ca_admin_tasks\");\n\n\texpect(frIndex).toBeGreaterThan(-1);\n\texpect(frCaIndex).toBeGreaterThan(-1);\n\texpect(frIndex).toBeLessThan(frCaIndex);\n});\n\ntest(\"imports the registry only when a message calls it, not when the text mentions it\", () => {\n\tconst bundle = (\n\t\tid: string,\n\t\tcode: string,\n\t\tregistryFunctions: string[]\n\t): CompiledBundleWithMessages => ({\n\t\tbundle: {\n\t\t\tcode: `export const ${id} = () => en_${id}()`,\n\t\t\tnode: { id } as unknown as Bundle,\n\t\t},\n\t\tmessages: {\n\t\t\ten: { code, node: {} as unknown as Message, registryFunctions },\n\t\t},\n\t\tmatchTypes: new Map(),\n\t});\n\tconst settings: Pick<ProjectSettings, \"locales\" | \"baseLocale\"> = {\n\t\tlocales: [\"en\"],\n\t\tbaseLocale: \"en\",\n\t};\n\tconst registryImport =\n\t\t/import \\* as registry from ['\"]\\.\\.\\/registry\\.js['\"]/;\n\n\tconst textOnly = generateOutput(\n\t\t[bundle(\"registry_text\", \"() => `Open the registry. Now.`\", [])],\n\t\tsettings,\n\t\t{ en: undefined }\n\t);\n\tfor (const [fileName, code] of Object.entries(textOnly)) {\n\t\tif (fileName.startsWith(\"messages/\")) {\n\t\t\texpect(code).not.toMatch(registryImport);\n\t\t}\n\t}\n\n\tconst withNumber = generateOutput(\n\t\t[\n\t\t\tbundle(\"amount\", '(i) => `${registry.number(\"en\", i?.amount, {})}`', [\n\t\t\t\t\"number\",\n\t\t\t]),\n\t\t],\n\t\tsettings,\n\t\t{ en: undefined }\n\t);\n\texpect(\n\t\tObject.values(withNumber).some((code) => registryImport.test(code))\n\t).toBe(true);\n});\n"]}
|
|
@@ -11,3 +11,15 @@
|
|
|
11
11
|
* Creates the Registry file
|
|
12
12
|
*/
|
|
13
13
|
export declare function createRegistry(): string;
|
|
14
|
+
/**
|
|
15
|
+
* Returns the given registry functions and the registry functions they call,
|
|
16
|
+
* in registry order.
|
|
17
|
+
*
|
|
18
|
+
* @example
|
|
19
|
+
* withRegistryDependencies(["icuPound"]) // ["number", "icuPound"]
|
|
20
|
+
*/
|
|
21
|
+
export declare function withRegistryDependencies(names: Iterable<string>): string[];
|
|
22
|
+
/**
|
|
23
|
+
* Returns the code of the given registry functions without `export`, by name.
|
|
24
|
+
*/
|
|
25
|
+
export declare function registryFunctionCode(names: Iterable<string>): Record<string, string>;
|