@inlang/paraglide-js 2.0.0-beta.21 → 2.0.0-beta.23
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 +2 -60
- package/dist/bundler-plugins/esbuild.d.ts +2 -0
- package/dist/bundler-plugins/esbuild.d.ts.map +1 -0
- package/dist/bundler-plugins/esbuild.js +3 -0
- package/dist/bundler-plugins/index.d.ts +4 -1
- package/dist/bundler-plugins/index.d.ts.map +1 -1
- package/dist/bundler-plugins/index.js +4 -1
- package/dist/bundler-plugins/rolldown.d.ts +2 -0
- package/dist/bundler-plugins/rolldown.d.ts.map +1 -0
- package/dist/bundler-plugins/rolldown.js +3 -0
- package/dist/bundler-plugins/rollup.d.ts +1 -1
- package/dist/bundler-plugins/rollup.d.ts.map +1 -1
- package/dist/bundler-plugins/rspack.d.ts +2 -0
- package/dist/bundler-plugins/rspack.d.ts.map +1 -0
- package/dist/bundler-plugins/rspack.js +3 -0
- package/dist/bundler-plugins/webpack.d.ts +1 -1
- package/dist/bundler-plugins/webpack.d.ts.map +1 -1
- package/dist/compiler/compile-bundle.js +1 -1
- package/dist/compiler/compile-project.test.js +32 -4
- package/dist/compiler/compile.test.js +7 -2
- package/dist/compiler/compiler-options.d.ts +4 -1
- package/dist/compiler/compiler-options.d.ts.map +1 -1
- package/dist/compiler/output-structure/locale-modules.d.ts.map +1 -1
- package/dist/compiler/output-structure/locale-modules.js +2 -0
- package/dist/compiler/output-structure/message-modules.d.ts.map +1 -1
- package/dist/compiler/output-structure/message-modules.js +2 -0
- package/dist/compiler/runtime/create-runtime.d.ts +2 -1
- package/dist/compiler/runtime/create-runtime.d.ts.map +1 -1
- package/dist/compiler/runtime/create-runtime.js +8 -4
- package/dist/compiler/runtime/get-locale.d.ts.map +1 -1
- package/dist/compiler/runtime/get-locale.js +3 -3
- package/dist/compiler/runtime/get-url-origin.d.ts.map +1 -1
- package/dist/compiler/runtime/get-url-origin.js +3 -2
- package/dist/compiler/runtime/server/create-server-runtime.d.ts +5 -0
- package/dist/compiler/runtime/server/create-server-runtime.d.ts.map +1 -0
- package/dist/compiler/runtime/server/create-server-runtime.js +27 -0
- package/dist/compiler/runtime/server/server-middleware.d.ts +75 -0
- package/dist/compiler/runtime/server/server-middleware.d.ts.map +1 -0
- package/dist/compiler/runtime/server/server-middleware.js +116 -0
- package/dist/compiler/runtime/server/server-middleware.test.d.ts +2 -0
- package/dist/compiler/runtime/server/server-middleware.test.d.ts.map +1 -0
- package/dist/compiler/runtime/server/server-middleware.test.js +169 -0
- package/dist/compiler/runtime/server/type.d.ts +7 -0
- package/dist/compiler/runtime/server/type.d.ts.map +1 -0
- package/dist/compiler/runtime/server/type.js +1 -0
- package/dist/compiler/runtime/server-middleware.d.ts +26 -1
- package/dist/compiler/runtime/server-middleware.d.ts.map +1 -1
- package/dist/compiler/runtime/server-middleware.js +54 -5
- package/dist/compiler/runtime/server-middleware.test.js +52 -0
- package/dist/compiler/runtime/type.d.ts +2 -1
- package/dist/compiler/runtime/type.d.ts.map +1 -1
- package/dist/compiler/runtime/variables.d.ts +30 -0
- package/dist/compiler/runtime/variables.d.ts.map +1 -1
- package/dist/compiler/runtime/variables.js +25 -0
- package/dist/compiler/safe-module-id.test.js +3 -0
- package/dist/compiler/server/create-server-file.d.ts +5 -0
- package/dist/compiler/server/create-server-file.d.ts.map +1 -0
- package/dist/compiler/server/create-server-file.js +27 -0
- package/dist/compiler/server/middleware.d.ts +75 -0
- package/dist/compiler/server/middleware.d.ts.map +1 -0
- package/dist/compiler/server/middleware.js +116 -0
- package/dist/compiler/server/middleware.test.d.ts +2 -0
- package/dist/compiler/server/middleware.test.d.ts.map +1 -0
- package/dist/compiler/server/middleware.test.js +169 -0
- package/dist/compiler/server/server-middleware.d.ts +75 -0
- package/dist/compiler/server/server-middleware.d.ts.map +1 -0
- package/dist/compiler/server/server-middleware.js +116 -0
- package/dist/compiler/server/server-middleware.test.d.ts +2 -0
- package/dist/compiler/server/server-middleware.test.d.ts.map +1 -0
- package/dist/compiler/server/server-middleware.test.js +169 -0
- package/dist/compiler/server/type.d.ts +7 -0
- package/dist/compiler/server/type.d.ts.map +1 -0
- package/dist/compiler/server/type.js +1 -0
- package/dist/services/env-variables/index.js +1 -1
- package/package.json +5 -5
package/README.md
CHANGED
|
@@ -1,63 +1,5 @@
|
|
|
1
1
|
[](https://inlang.com)
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
A compiler-based i18n library that emits tree-shakable message functions. This means that only the messages you actually use are loaded without asynchronous waterfalls.
|
|
4
4
|
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
```bash
|
|
8
|
-
npx @inlang/paraglide-js@latest init
|
|
9
|
-
```
|
|
10
|
-
|
|
11
|
-
This will:
|
|
12
|
-
|
|
13
|
-
- Create an [inlang project](https://inlang.com/documentation/concept/project)
|
|
14
|
-
- Install necessary dependencies
|
|
15
|
-
- Generate a `messages/` folder where your translation files live
|
|
16
|
-
|
|
17
|
-
## Adding and editing Messages
|
|
18
|
-
|
|
19
|
-
Messages are stored in `messages/{locale}.json` as key-value pairs. You can add parameters with curly braces.
|
|
20
|
-
|
|
21
|
-
```diff
|
|
22
|
-
// messages/en.json
|
|
23
|
-
{
|
|
24
|
-
+ "greeting": "Hello {name}!"
|
|
25
|
-
}
|
|
26
|
-
```
|
|
27
|
-
|
|
28
|
-
Run the compiler via the CLI to generate the message functions.
|
|
29
|
-
|
|
30
|
-
```bash
|
|
31
|
-
npx @inlang/paraglide-js compile --project ./project.inlang --outdir ./src/paraglide
|
|
32
|
-
```
|
|
33
|
-
|
|
34
|
-
_If you are using a Bundler use one of the [Bundler Plugins](usage#usage-with-a-bundler) to recompile automatically._
|
|
35
|
-
|
|
36
|
-
## Using messages in code
|
|
37
|
-
|
|
38
|
-
After running the compiler import the messages with `import { m } from "./paraglide/messages"`. By convention, a wildcard import is used.
|
|
39
|
-
|
|
40
|
-
```js
|
|
41
|
-
import { m } from "./paraglide/messages.js";
|
|
42
|
-
|
|
43
|
-
m.greeting({ name: "Samuel" }); // Hello Samuel!
|
|
44
|
-
```
|
|
45
|
-
|
|
46
|
-
## Changing the locale
|
|
47
|
-
|
|
48
|
-
To change the locale, use the `setLocale` function.
|
|
49
|
-
|
|
50
|
-
```js
|
|
51
|
-
import { setLocale } from "./paraglide/runtime.js";
|
|
52
|
-
import { m } from "./paraglide/messages.js";
|
|
53
|
-
|
|
54
|
-
m.greeting({ name: "Samuel" }); // Hello Samuel!
|
|
55
|
-
|
|
56
|
-
setLocale("de");
|
|
57
|
-
|
|
58
|
-
m.greeting({ name: "Samuel" }); // Guten Tag Samuel!
|
|
59
|
-
```
|
|
60
|
-
|
|
61
|
-
## Define your strategy
|
|
62
|
-
|
|
63
|
-
In the last step, you need to define what strategy you want to use to resolve the locale. Visit the [strategy documentation](https://inlang.com/m/gerre34r/library-inlang-paraglideJs/strategy) to learn more.
|
|
5
|
+
Visit https://inlang.com/m/gerre34r/library-inlang-paraglideJs to learn more.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"esbuild.d.ts","sourceRoot":"","sources":["../../src/bundler-plugins/esbuild.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,sBAAsB,sFAAuC,CAAC"}
|
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { paraglideEsbuildPlugin } from "./esbuild.js";
|
|
2
|
+
export { paraglideRolldownPlugin } from "./rolldown.js";
|
|
2
3
|
export { paraglideRollupPlugin } from "./rollup.js";
|
|
4
|
+
export { paraglideRspackPlugin } from "./rspack.js";
|
|
5
|
+
export { paraglideVitePlugin } from "./vite.js";
|
|
3
6
|
export { paraglideWebpackPlugin } from "./webpack.js";
|
|
4
7
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/bundler-plugins/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../src/bundler-plugins/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC;AACtD,OAAO,EAAE,uBAAuB,EAAE,MAAM,eAAe,CAAC;AACxD,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC"}
|
|
@@ -1,3 +1,6 @@
|
|
|
1
|
-
export {
|
|
1
|
+
export { paraglideEsbuildPlugin } from "./esbuild.js";
|
|
2
|
+
export { paraglideRolldownPlugin } from "./rolldown.js";
|
|
2
3
|
export { paraglideRollupPlugin } from "./rollup.js";
|
|
4
|
+
export { paraglideRspackPlugin } from "./rspack.js";
|
|
5
|
+
export { paraglideVitePlugin } from "./vite.js";
|
|
3
6
|
export { paraglideWebpackPlugin } from "./webpack.js";
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rolldown.d.ts","sourceRoot":"","sources":["../../src/bundler-plugins/rolldown.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,uBAAuB,uIAAwC,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const paraglideRollupPlugin: (options: import("../index.js").CompilerOptions) => import("
|
|
1
|
+
export declare const paraglideRollupPlugin: (options: import("../index.js").CompilerOptions) => import("unplugin").RollupPlugin<any> | import("unplugin").RollupPlugin<any>[];
|
|
2
2
|
//# sourceMappingURL=rollup.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"rollup.d.ts","sourceRoot":"","sources":["../../src/bundler-plugins/rollup.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,qBAAqB,
|
|
1
|
+
{"version":3,"file":"rollup.d.ts","sourceRoot":"","sources":["../../src/bundler-plugins/rollup.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,qBAAqB,mIAAsC,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"rspack.d.ts","sourceRoot":"","sources":["../../src/bundler-plugins/rspack.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,qBAAqB,0EAAsC,CAAC"}
|
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
export declare const paraglideWebpackPlugin: (options: import("../index.js").CompilerOptions) => WebpackPluginInstance;
|
|
1
|
+
export declare const paraglideWebpackPlugin: (options: import("../index.js").CompilerOptions) => import("unplugin").WebpackPluginInstance;
|
|
2
2
|
//# sourceMappingURL=webpack.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"webpack.d.ts","sourceRoot":"","sources":["../../src/bundler-plugins/webpack.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,sBAAsB,
|
|
1
|
+
{"version":3,"file":"webpack.d.ts","sourceRoot":"","sources":["../../src/bundler-plugins/webpack.ts"],"names":[],"mappings":"AAGA,eAAO,MAAM,sBAAsB,8FAAuC,CAAC"}
|
|
@@ -38,7 +38,7 @@ const compileBundleFunction = (args) => {
|
|
|
38
38
|
* ${jsDocBundleFunctionTypes({ inputs, locales: args.availableLocales })}
|
|
39
39
|
*/
|
|
40
40
|
/* @__NO_SIDE_EFFECTS__ */
|
|
41
|
-
${isSafeBundleId ? "export" : ""}
|
|
41
|
+
${isSafeBundleId ? "export " : ""}const ${safeBundleId} = (inputs${hasInputs ? "" : " = {}"}, options = {}) => {
|
|
42
42
|
const locale = options.locale ?? getLocale()
|
|
43
43
|
${args.availableLocales
|
|
44
44
|
.map((locale, index) => `${index > 0 ? " " : ""}if (locale === "${locale}") return ${toSafeModuleId(locale)}.${safeBundleId}(inputs)`)
|
|
@@ -60,6 +60,32 @@ test("emitPrettierIgnore", async () => {
|
|
|
60
60
|
expect(_true).toHaveProperty(".prettierignore");
|
|
61
61
|
expect(_false).not.toHaveProperty(".prettierignore");
|
|
62
62
|
});
|
|
63
|
+
test("handles message bundles with a : in the id", async () => {
|
|
64
|
+
const project = await loadProjectInMemory({
|
|
65
|
+
blob: await newProject({
|
|
66
|
+
settings: {
|
|
67
|
+
locales: ["en", "de"],
|
|
68
|
+
baseLocale: "en",
|
|
69
|
+
},
|
|
70
|
+
}),
|
|
71
|
+
});
|
|
72
|
+
await insertBundleNested(project.db, createBundleNested({
|
|
73
|
+
id: "hello:world",
|
|
74
|
+
messages: [
|
|
75
|
+
{
|
|
76
|
+
locale: "en",
|
|
77
|
+
variants: [{ pattern: [{ type: "text", value: "Hello world!" }] }],
|
|
78
|
+
},
|
|
79
|
+
],
|
|
80
|
+
}));
|
|
81
|
+
const output = await compileProject({
|
|
82
|
+
project,
|
|
83
|
+
});
|
|
84
|
+
const code = await bundleCode(output, `export * as m from "./paraglide/messages.js"
|
|
85
|
+
export * as runtime from "./paraglide/runtime.js"`);
|
|
86
|
+
const { m } = await importCode(code);
|
|
87
|
+
expect(m["hello:world"]()).toBe("Hello world!");
|
|
88
|
+
});
|
|
63
89
|
// https://github.com/opral/inlang-paraglide-js/issues/347
|
|
64
90
|
test("can emit message bundles with more than 255 characters", async () => {
|
|
65
91
|
const project = await loadProjectInMemory({
|
|
@@ -464,10 +490,12 @@ describe.each([
|
|
|
464
490
|
m.sad_penguin_bundle({}, { locale: "---" })
|
|
465
491
|
`);
|
|
466
492
|
const program = project.createProgram();
|
|
467
|
-
const diagnostics = ts
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
493
|
+
const diagnostics = ts.getPreEmitDiagnostics(program).filter((d) => {
|
|
494
|
+
// async_hooks is a node module that is not available in the browser
|
|
495
|
+
return !d.messageText
|
|
496
|
+
.toString()
|
|
497
|
+
.includes("Cannot find module 'async_hooks'");
|
|
498
|
+
});
|
|
471
499
|
for (const diagnostic of diagnostics) {
|
|
472
500
|
console.error(diagnostic.messageText, diagnostic.file?.fileName);
|
|
473
501
|
}
|
|
@@ -27,7 +27,7 @@ test("loads a project and compiles it", async () => {
|
|
|
27
27
|
});
|
|
28
28
|
const files = await fs.promises.readdir("/output");
|
|
29
29
|
//runtime.js and messages.js are always compiled with the default options
|
|
30
|
-
expect(files).toEqual(expect.arrayContaining(["runtime.js", "messages.js"]));
|
|
30
|
+
expect(files).toEqual(expect.arrayContaining(["runtime.js", "server.js", "messages.js"]));
|
|
31
31
|
});
|
|
32
32
|
test("loads a local account from app data if exists", async () => {
|
|
33
33
|
const accountPath = getAccountFilePath();
|
|
@@ -180,7 +180,12 @@ test("emits additional files", async () => {
|
|
|
180
180
|
});
|
|
181
181
|
const outputDir = await fs.promises.readdir("/output");
|
|
182
182
|
const adapterDir = await fs.promises.readdir("/output/adapter");
|
|
183
|
-
expect(outputDir).toEqual(expect.arrayContaining([
|
|
183
|
+
expect(outputDir).toEqual(expect.arrayContaining([
|
|
184
|
+
"runtime.js",
|
|
185
|
+
"server.js",
|
|
186
|
+
"messages.js",
|
|
187
|
+
"adapter.js",
|
|
188
|
+
]));
|
|
184
189
|
expect(adapterDir).toEqual(["component.svelte"]);
|
|
185
190
|
});
|
|
186
191
|
test("includes eslint-disable comment", async () => {
|
|
@@ -146,7 +146,10 @@ export type CompilerOptions = {
|
|
|
146
146
|
*
|
|
147
147
|
* **`locale-modules`**
|
|
148
148
|
*
|
|
149
|
-
* Messages are bundled in a per locale module. Bundlers
|
|
149
|
+
* Messages are bundled in a per locale module. Bundlers often struggle with tree-shaking this structure,
|
|
150
|
+
* which can lead to more inefficient tree-shaking and larger bundle sizes compared to `message-modules`.
|
|
151
|
+
*
|
|
152
|
+
* The benefit are substantially fewer files which is needed in large projects.
|
|
150
153
|
*
|
|
151
154
|
* ```diff
|
|
152
155
|
* - outdir/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"compiler-options.d.ts","sourceRoot":"","sources":["../../src/compiler/compiler-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEjD,eAAO,MAAM,sBAAsB;;;;;;;CAOU,CAAC;AAE9C,MAAM,MAAM,eAAe,GAAG;IAC7B;;;;;;;;;;OAUG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;;;;;;OAUG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/B;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC;;;;;;;;;;;;OAYG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;IACrC;;;;OAIG;IACH,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC;;;;;;;;;;;;OAYG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB
|
|
1
|
+
{"version":3,"file":"compiler-options.d.ts","sourceRoot":"","sources":["../../src/compiler/compiler-options.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,mBAAmB,CAAC;AAEjD,eAAO,MAAM,sBAAsB;;;;;;;CAOU,CAAC;AAE9C,MAAM,MAAM,eAAe,GAAG;IAC7B;;;;;;;;;;OAUG;IACH,OAAO,EAAE,MAAM,CAAC;IAChB;;;;;;;;;;OAUG;IACH,MAAM,EAAE,MAAM,CAAC;IACf;;;;;;;;;;;;;;OAcG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC,UAAU,CAAC,CAAC;IAC/B;;;;OAIG;IACH,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB;;;;;;;;;;;;;;;;;;;;;;;;OAwBG;IACH,eAAe,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;IACzC;;;;;;;;;;;;OAYG;IACH,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B;;OAEG;IACH,WAAW,CAAC,EAAE,OAAO,CAAC,aAAa,CAAC,CAAC;IACrC;;;;OAIG;IACH,2BAA2B,CAAC,EAAE,OAAO,CAAC;IACtC;;;;;;;;;;;;OAYG;IACH,aAAa,CAAC,EAAE,OAAO,CAAC;IACxB;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA6CG;IACH,eAAe,CAAC,EAAE,gBAAgB,GAAG,iBAAiB,CAAC;IACvD;;;;OAIG;IACH,EAAE,CAAC,EAAE,GAAG,CAAC;CACT,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"locale-modules.d.ts","sourceRoot":"","sources":["../../../src/compiler/output-structure/locale-modules.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAGvE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"locale-modules.d.ts","sourceRoot":"","sources":["../../../src/compiler/output-structure/locale-modules.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAGvE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAI9D,wBAAgB,qBAAqB,CACpC,eAAe,EAAE,0BAA0B,EAAE,EAC7C,QAAQ,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,GAAG,YAAY,CAAC,EACzD,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EAC/C,eAAe,EAAE;IAChB,QAAQ,EAAE,WAAW,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAC;IACnD,UAAU,EAAE,WAAW,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC;CACvD,GACC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CA4DxB"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
import { createRuntimeFile } from "../runtime/create-runtime.js";
|
|
2
2
|
import { createRegistry } from "../registry.js";
|
|
3
3
|
import { toSafeModuleId } from "../safe-module-id.js";
|
|
4
|
+
import { createServerFile } from "../server/create-server-file.js";
|
|
4
5
|
export function generateLocaleModules(compiledBundles, settings, fallbackMap, compilerOptions) {
|
|
5
6
|
const indexFile = [
|
|
6
7
|
`import { getLocale } from "../runtime.js"`,
|
|
@@ -15,6 +16,7 @@ export function generateLocaleModules(compiledBundles, settings, fallbackMap, co
|
|
|
15
16
|
locales: settings.locales,
|
|
16
17
|
compilerOptions,
|
|
17
18
|
}),
|
|
19
|
+
["server.js"]: createServerFile(),
|
|
18
20
|
["registry.js"]: createRegistry(),
|
|
19
21
|
["messages/_index.js"]: indexFile,
|
|
20
22
|
["messages.js"]: [
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"message-modules.d.ts","sourceRoot":"","sources":["../../../src/compiler/output-structure/message-modules.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAIvE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;
|
|
1
|
+
{"version":3,"file":"message-modules.d.ts","sourceRoot":"","sources":["../../../src/compiler/output-structure/message-modules.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,aAAa,CAAC;AACnD,OAAO,KAAK,EAAE,0BAA0B,EAAE,MAAM,sBAAsB,CAAC;AAIvE,OAAO,KAAK,EAAE,eAAe,EAAE,MAAM,wBAAwB,CAAC;AAI9D,wBAAgB,sBAAsB,CACrC,eAAe,EAAE,0BAA0B,EAAE,EAC7C,QAAQ,EAAE,IAAI,CAAC,eAAe,EAAE,SAAS,GAAG,YAAY,CAAC,EACzD,WAAW,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,SAAS,CAAC,EAC/C,eAAe,EAAE;IAChB,QAAQ,EAAE,WAAW,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAC;IACnD,UAAU,EAAE,WAAW,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC;CACvD,GACC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAqFxB"}
|
|
@@ -2,6 +2,7 @@ import { createRuntimeFile } from "../runtime/create-runtime.js";
|
|
|
2
2
|
import { createRegistry } from "../registry.js";
|
|
3
3
|
import { escapeForSingleQuoteString } from "../../services/codegen/escape.js";
|
|
4
4
|
import { toSafeModuleId } from "../safe-module-id.js";
|
|
5
|
+
import { createServerFile } from "../server/create-server-file.js";
|
|
5
6
|
export function generateMessageModules(compiledBundles, settings, fallbackMap, compilerOptions) {
|
|
6
7
|
const output = {
|
|
7
8
|
["runtime.js"]: createRuntimeFile({
|
|
@@ -9,6 +10,7 @@ export function generateMessageModules(compiledBundles, settings, fallbackMap, c
|
|
|
9
10
|
locales: settings.locales,
|
|
10
11
|
compilerOptions,
|
|
11
12
|
}),
|
|
13
|
+
["server.js"]: createServerFile(),
|
|
12
14
|
["registry.js"]: createRegistry(),
|
|
13
15
|
};
|
|
14
16
|
// all messages index file
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import type { Runtime } from "./type.js";
|
|
2
2
|
import { type CompilerOptions } from "../compiler-options.js";
|
|
3
|
+
import type { ServerRuntime } from "../server/type.js";
|
|
3
4
|
/**
|
|
4
5
|
* Returns the code for the `runtime.js` module
|
|
5
6
|
*/
|
|
@@ -25,5 +26,5 @@ export declare function createRuntimeForTesting(args: {
|
|
|
25
26
|
baseLocale: string;
|
|
26
27
|
locales: string[];
|
|
27
28
|
compilerOptions?: Omit<CompilerOptions, "outdir" | "project" | "fs">;
|
|
28
|
-
}): Promise<Runtime>;
|
|
29
|
+
}): Promise<Runtime & ServerRuntime>;
|
|
29
30
|
//# sourceMappingURL=create-runtime.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"create-runtime.d.ts","sourceRoot":"","sources":["../../../src/compiler/runtime/create-runtime.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAEN,KAAK,eAAe,EACpB,MAAM,wBAAwB,CAAC;AAEhC;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,eAAe,EAAE;QAChB,QAAQ,EAAE,WAAW,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAC;QACnD,UAAU,EAAE,WAAW,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC;QACvD,WAAW,CAAC,EAAE,eAAe,CAAC,aAAa,CAAC,CAAC;KAC7C,CAAC;CACF,GAAG,MAAM,
|
|
1
|
+
{"version":3,"file":"create-runtime.d.ts","sourceRoot":"","sources":["../../../src/compiler/runtime/create-runtime.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,WAAW,CAAC;AACzC,OAAO,EAEN,KAAK,eAAe,EACpB,MAAM,wBAAwB,CAAC;AAEhC,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mBAAmB,CAAC;AAEvD;;GAEG;AACH,wBAAgB,iBAAiB,CAAC,IAAI,EAAE;IACvC,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,eAAe,EAAE;QAChB,QAAQ,EAAE,WAAW,CAAC,eAAe,CAAC,UAAU,CAAC,CAAC,CAAC;QACnD,UAAU,EAAE,WAAW,CAAC,eAAe,CAAC,YAAY,CAAC,CAAC,CAAC;QACvD,WAAW,CAAC,EAAE,eAAe,CAAC,aAAa,CAAC,CAAC;KAC7C,CAAC;CACF,GAAG,MAAM,CA+FT;AAkBD;;;;;;;;GAQG;AACH,wBAAsB,uBAAuB,CAAC,IAAI,EAAE;IACnD,UAAU,EAAE,MAAM,CAAC;IACnB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,eAAe,CAAC,EAAE,IAAI,CAAC,eAAe,EAAE,QAAQ,GAAG,SAAS,GAAG,IAAI,CAAC,CAAC;CACrE,GAAG,OAAO,CAAC,OAAO,GAAG,aAAa,CAAC,CA0BnC"}
|
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import fs from "node:fs";
|
|
2
2
|
import { defaultCompilerOptions, } from "../compiler-options.js";
|
|
3
|
+
import { createServerFile } from "../server/create-server-file.js";
|
|
3
4
|
/**
|
|
4
5
|
* Returns the code for the `runtime.js` module
|
|
5
6
|
*/
|
|
@@ -53,8 +54,6 @@ ${injectCode("./localize-url.js")}
|
|
|
53
54
|
|
|
54
55
|
${injectCode("./localize-href.js")}
|
|
55
56
|
|
|
56
|
-
${injectCode("./server-middleware.js")}
|
|
57
|
-
|
|
58
57
|
// ------ TYPES ------
|
|
59
58
|
|
|
60
59
|
/**
|
|
@@ -94,7 +93,7 @@ function injectCode(path) {
|
|
|
94
93
|
* })
|
|
95
94
|
*/
|
|
96
95
|
export async function createRuntimeForTesting(args) {
|
|
97
|
-
const
|
|
96
|
+
const clientSideRuntime = createRuntimeFile({
|
|
98
97
|
baseLocale: args.baseLocale,
|
|
99
98
|
locales: args.locales,
|
|
100
99
|
compilerOptions: {
|
|
@@ -104,7 +103,12 @@ export async function createRuntimeForTesting(args) {
|
|
|
104
103
|
})
|
|
105
104
|
// remove the polyfill import statement to avoid module resolution logic in testing
|
|
106
105
|
.replace(`import "@inlang/paraglide-js/urlpattern-polyfill";`, "");
|
|
106
|
+
// remove the server-side runtime import statement to avoid module resolution logic in testing
|
|
107
|
+
const serverSideRuntime = createServerFile()
|
|
108
|
+
.replace(`import * as runtime from "./runtime.js";`, "")
|
|
109
|
+
// the runtime functions are bundles, hence remove the runtime namespace
|
|
110
|
+
.replaceAll("runtime.", "");
|
|
107
111
|
await import("urlpattern-polyfill");
|
|
108
112
|
return await import("data:text/javascript;base64," +
|
|
109
|
-
Buffer.from(
|
|
113
|
+
Buffer.from(clientSideRuntime + serverSideRuntime, "utf-8").toString("base64"));
|
|
110
114
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-locale.d.ts","sourceRoot":"","sources":["../../../src/compiler/runtime/get-locale.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"get-locale.d.ts","sourceRoot":"","sources":["../../../src/compiler/runtime/get-locale.js"],"names":[],"mappings":"AAyBA;;;;;;;;;;;GAWG;AACH,sBAFU,MAAM,MAAM,CAgDpB;AA4BF;;;;;;;;;;;;;;GAcG;AACH,iCAFU,CAAC,EAAE,EAAE,MAAM,MAAM,KAAK,IAAI,CAIlC"}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { assertIsLocale } from "./assert-is-locale.js";
|
|
2
2
|
import { isLocale } from "./is-locale.js";
|
|
3
|
-
import { baseLocale, strategy, TREE_SHAKE_COOKIE_STRATEGY_USED, TREE_SHAKE_GLOBAL_VARIABLE_STRATEGY_USED, TREE_SHAKE_PREFERRED_LANGUAGE_STRATEGY_USED, TREE_SHAKE_URL_STRATEGY_USED, } from "./variables.js";
|
|
3
|
+
import { baseLocale, strategy, serverAsyncLocalStorage, TREE_SHAKE_COOKIE_STRATEGY_USED, TREE_SHAKE_GLOBAL_VARIABLE_STRATEGY_USED, TREE_SHAKE_PREFERRED_LANGUAGE_STRATEGY_USED, TREE_SHAKE_URL_STRATEGY_USED, } from "./variables.js";
|
|
4
4
|
import { extractLocaleFromCookie } from "./extract-locale-from-cookie.js";
|
|
5
5
|
import { extractLocaleFromUrl } from "./extract-locale-from-url.js";
|
|
6
6
|
/**
|
|
@@ -30,8 +30,8 @@ export let getLocale = () => {
|
|
|
30
30
|
let locale;
|
|
31
31
|
// if running in a server-side rendering context
|
|
32
32
|
// retrieve the locale from the async local storage
|
|
33
|
-
if (
|
|
34
|
-
const locale =
|
|
33
|
+
if (serverAsyncLocalStorage) {
|
|
34
|
+
const locale = serverAsyncLocalStorage?.getStore()?.locale;
|
|
35
35
|
if (locale) {
|
|
36
36
|
return locale;
|
|
37
37
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"get-url-origin.d.ts","sourceRoot":"","sources":["../../../src/compiler/runtime/get-url-origin.js"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"get-url-origin.d.ts","sourceRoot":"","sources":["../../../src/compiler/runtime/get-url-origin.js"],"names":[],"mappings":"AAEA;;;;;;;;GAQG;AACH,yBAFU,MAAM,MAAM,CASpB;AAEF;;;;;;;GAOG;AACH,kCAFU,CAAC,EAAE,EAAE,MAAM,MAAM,KAAK,IAAI,CAIlC"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { serverAsyncLocalStorage } from "./variables.js";
|
|
1
2
|
/**
|
|
2
3
|
* The origin of the current URL.
|
|
3
4
|
*
|
|
@@ -8,8 +9,8 @@
|
|
|
8
9
|
* @type {() => string}
|
|
9
10
|
*/
|
|
10
11
|
export let getUrlOrigin = () => {
|
|
11
|
-
if (
|
|
12
|
-
return
|
|
12
|
+
if (serverAsyncLocalStorage) {
|
|
13
|
+
return serverAsyncLocalStorage.getStore()?.origin ?? "http://fallback.com";
|
|
13
14
|
}
|
|
14
15
|
else if (typeof window !== "undefined") {
|
|
15
16
|
return window.location.origin;
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"create-server-runtime.d.ts","sourceRoot":"","sources":["../../../../src/compiler/runtime/server/create-server-runtime.ts"],"names":[],"mappings":"AAEA;;GAEG;AACH,wBAAgB,uBAAuB,IAAI,MAAM,CAQhD"}
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
import fs from "node:fs";
|
|
2
|
+
/**
|
|
3
|
+
* Returns the code for the `runtime.js` module
|
|
4
|
+
*/
|
|
5
|
+
export function createServerRuntimeFile() {
|
|
6
|
+
const code = `
|
|
7
|
+
import * as runtime from "./runtime.js";
|
|
8
|
+
|
|
9
|
+
${injectCode("./server-middleware.js")}
|
|
10
|
+
`;
|
|
11
|
+
return code;
|
|
12
|
+
}
|
|
13
|
+
/**
|
|
14
|
+
* Load a file from the current directory.
|
|
15
|
+
*
|
|
16
|
+
* Prunes the imports on top of the file as the runtime is
|
|
17
|
+
* self-contained.
|
|
18
|
+
*
|
|
19
|
+
* @param {string} path
|
|
20
|
+
* @returns {string}
|
|
21
|
+
*/
|
|
22
|
+
function injectCode(path) {
|
|
23
|
+
const code = fs.readFileSync(new URL(path, import.meta.url), "utf-8");
|
|
24
|
+
// Regex to match single-line and multi-line imports
|
|
25
|
+
const importRegex = /import\s+[\s\S]*?from\s+['"][^'"]+['"]\s*;?/g;
|
|
26
|
+
return code.replace(importRegex, "").trim();
|
|
27
|
+
}
|
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Server middleware that handles locale-based routing and request processing.
|
|
3
|
+
*
|
|
4
|
+
* This middleware performs several key functions:
|
|
5
|
+
*
|
|
6
|
+
* 1. Determines the locale for the incoming request using configured strategies
|
|
7
|
+
* 2. Handles URL localization and redirects
|
|
8
|
+
* 3. Maintains locale state using AsyncLocalStorage to prevent request interference
|
|
9
|
+
*
|
|
10
|
+
* When URL strategy is used:
|
|
11
|
+
*
|
|
12
|
+
* - If URL doesn't match the determined locale, redirects to localized URL
|
|
13
|
+
* - De-localizes URLs before passing to server (e.g., `/fr/about` → `/about`)
|
|
14
|
+
*
|
|
15
|
+
* @template T - The return type of the resolve function
|
|
16
|
+
*
|
|
17
|
+
* @param {Request} request - The incoming request object
|
|
18
|
+
* @param {(args: { request: Request, locale: import("./runtime.js").Locale }) => T | Promise<T>} resolve - Function to handle the request
|
|
19
|
+
* @param {Object} [options] - Optional configuration for the middleware
|
|
20
|
+
* @param {boolean} [options.disableAsyncLocalStorage=false] - If true, disables AsyncLocalStorage usage.
|
|
21
|
+
* ⚠️ WARNING: This should ONLY be used in serverless environments
|
|
22
|
+
* like Cloudflare Workers. Disabling AsyncLocalStorage in traditional
|
|
23
|
+
* server environments risks cross-request pollution where state from
|
|
24
|
+
* one request could leak into another concurrent request.
|
|
25
|
+
*
|
|
26
|
+
* @returns {Promise<Response | any>} Returns either:
|
|
27
|
+
* - A `Response` object (302 redirect) if URL localization is needed
|
|
28
|
+
* - The result of the resolve function if no redirect is required
|
|
29
|
+
*
|
|
30
|
+
* @example
|
|
31
|
+
* ```typescript
|
|
32
|
+
* // Basic usage in metaframeworks like NextJS, SvelteKit, Astro, Nuxt, etc.
|
|
33
|
+
* export const handle = async ({ event, resolve }) => {
|
|
34
|
+
* return serverMiddleware(event.request, ({ request, locale }) => {
|
|
35
|
+
* // let the framework further resolve the request
|
|
36
|
+
* return resolve(request);
|
|
37
|
+
* });
|
|
38
|
+
* };
|
|
39
|
+
* ```
|
|
40
|
+
*
|
|
41
|
+
* @example
|
|
42
|
+
* ```typescript
|
|
43
|
+
* // Usage in a framework like Express JS or Hono
|
|
44
|
+
* app.use(async (req, res, next) => {
|
|
45
|
+
* const result = await serverMiddleware(req, ({ request, locale }) => {
|
|
46
|
+
* // If a redirect happens this won't be called
|
|
47
|
+
* return next(request);
|
|
48
|
+
* });
|
|
49
|
+
* });
|
|
50
|
+
* ```
|
|
51
|
+
*
|
|
52
|
+
* @example
|
|
53
|
+
* ```typescript
|
|
54
|
+
* // Usage in serverless environments like Cloudflare Workers
|
|
55
|
+
* // ⚠️ WARNING: This should ONLY be used in serverless environments like Cloudflare Workers.
|
|
56
|
+
* // Disabling AsyncLocalStorage in traditional server environments risks cross-request pollution where state from
|
|
57
|
+
* // one request could leak into another concurrent request.
|
|
58
|
+
* export default {
|
|
59
|
+
* fetch: async (request) => {
|
|
60
|
+
* return serverMiddleware(
|
|
61
|
+
* request,
|
|
62
|
+
* ({ request, locale }) => handleRequest(request, locale),
|
|
63
|
+
* { disableAsyncLocalStorage: true }
|
|
64
|
+
* );
|
|
65
|
+
* }
|
|
66
|
+
* };
|
|
67
|
+
* ```
|
|
68
|
+
*/
|
|
69
|
+
export function serverMiddleware<T>(request: Request, resolve: (args: {
|
|
70
|
+
request: Request;
|
|
71
|
+
locale: import("./runtime.js").Locale;
|
|
72
|
+
}) => T | Promise<T>, options?: {
|
|
73
|
+
disableAsyncLocalStorage?: boolean | undefined;
|
|
74
|
+
}): Promise<Response | any>;
|
|
75
|
+
//# sourceMappingURL=server-middleware.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"server-middleware.d.ts","sourceRoot":"","sources":["../../../../src/compiler/runtime/server/server-middleware.js"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmEG;AACH,iCAtDa,CAAC,WAEH,OAAO,WACP,CAAC,IAAI,EAAE;IAAE,OAAO,EAAE,OAAO,CAAC;IAAC,MAAM,EAAE,OAAO,cAAc,EAAE,MAAM,CAAA;CAAE,KAAK,CAAC,GAAG,OAAO,CAAC,CAAC,CAAC,YAE7F;IAA0B,wBAAwB;CAMlD,GAAU,OAAO,CAAC,QAAQ,GAAG,GAAG,CAAC,CAgGnC"}
|