@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.
Files changed (75) hide show
  1. package/README.md +2 -60
  2. package/dist/bundler-plugins/esbuild.d.ts +2 -0
  3. package/dist/bundler-plugins/esbuild.d.ts.map +1 -0
  4. package/dist/bundler-plugins/esbuild.js +3 -0
  5. package/dist/bundler-plugins/index.d.ts +4 -1
  6. package/dist/bundler-plugins/index.d.ts.map +1 -1
  7. package/dist/bundler-plugins/index.js +4 -1
  8. package/dist/bundler-plugins/rolldown.d.ts +2 -0
  9. package/dist/bundler-plugins/rolldown.d.ts.map +1 -0
  10. package/dist/bundler-plugins/rolldown.js +3 -0
  11. package/dist/bundler-plugins/rollup.d.ts +1 -1
  12. package/dist/bundler-plugins/rollup.d.ts.map +1 -1
  13. package/dist/bundler-plugins/rspack.d.ts +2 -0
  14. package/dist/bundler-plugins/rspack.d.ts.map +1 -0
  15. package/dist/bundler-plugins/rspack.js +3 -0
  16. package/dist/bundler-plugins/webpack.d.ts +1 -1
  17. package/dist/bundler-plugins/webpack.d.ts.map +1 -1
  18. package/dist/compiler/compile-bundle.js +1 -1
  19. package/dist/compiler/compile-project.test.js +32 -4
  20. package/dist/compiler/compile.test.js +7 -2
  21. package/dist/compiler/compiler-options.d.ts +4 -1
  22. package/dist/compiler/compiler-options.d.ts.map +1 -1
  23. package/dist/compiler/output-structure/locale-modules.d.ts.map +1 -1
  24. package/dist/compiler/output-structure/locale-modules.js +2 -0
  25. package/dist/compiler/output-structure/message-modules.d.ts.map +1 -1
  26. package/dist/compiler/output-structure/message-modules.js +2 -0
  27. package/dist/compiler/runtime/create-runtime.d.ts +2 -1
  28. package/dist/compiler/runtime/create-runtime.d.ts.map +1 -1
  29. package/dist/compiler/runtime/create-runtime.js +8 -4
  30. package/dist/compiler/runtime/get-locale.d.ts.map +1 -1
  31. package/dist/compiler/runtime/get-locale.js +3 -3
  32. package/dist/compiler/runtime/get-url-origin.d.ts.map +1 -1
  33. package/dist/compiler/runtime/get-url-origin.js +3 -2
  34. package/dist/compiler/runtime/server/create-server-runtime.d.ts +5 -0
  35. package/dist/compiler/runtime/server/create-server-runtime.d.ts.map +1 -0
  36. package/dist/compiler/runtime/server/create-server-runtime.js +27 -0
  37. package/dist/compiler/runtime/server/server-middleware.d.ts +75 -0
  38. package/dist/compiler/runtime/server/server-middleware.d.ts.map +1 -0
  39. package/dist/compiler/runtime/server/server-middleware.js +116 -0
  40. package/dist/compiler/runtime/server/server-middleware.test.d.ts +2 -0
  41. package/dist/compiler/runtime/server/server-middleware.test.d.ts.map +1 -0
  42. package/dist/compiler/runtime/server/server-middleware.test.js +169 -0
  43. package/dist/compiler/runtime/server/type.d.ts +7 -0
  44. package/dist/compiler/runtime/server/type.d.ts.map +1 -0
  45. package/dist/compiler/runtime/server/type.js +1 -0
  46. package/dist/compiler/runtime/server-middleware.d.ts +26 -1
  47. package/dist/compiler/runtime/server-middleware.d.ts.map +1 -1
  48. package/dist/compiler/runtime/server-middleware.js +54 -5
  49. package/dist/compiler/runtime/server-middleware.test.js +52 -0
  50. package/dist/compiler/runtime/type.d.ts +2 -1
  51. package/dist/compiler/runtime/type.d.ts.map +1 -1
  52. package/dist/compiler/runtime/variables.d.ts +30 -0
  53. package/dist/compiler/runtime/variables.d.ts.map +1 -1
  54. package/dist/compiler/runtime/variables.js +25 -0
  55. package/dist/compiler/safe-module-id.test.js +3 -0
  56. package/dist/compiler/server/create-server-file.d.ts +5 -0
  57. package/dist/compiler/server/create-server-file.d.ts.map +1 -0
  58. package/dist/compiler/server/create-server-file.js +27 -0
  59. package/dist/compiler/server/middleware.d.ts +75 -0
  60. package/dist/compiler/server/middleware.d.ts.map +1 -0
  61. package/dist/compiler/server/middleware.js +116 -0
  62. package/dist/compiler/server/middleware.test.d.ts +2 -0
  63. package/dist/compiler/server/middleware.test.d.ts.map +1 -0
  64. package/dist/compiler/server/middleware.test.js +169 -0
  65. package/dist/compiler/server/server-middleware.d.ts +75 -0
  66. package/dist/compiler/server/server-middleware.d.ts.map +1 -0
  67. package/dist/compiler/server/server-middleware.js +116 -0
  68. package/dist/compiler/server/server-middleware.test.d.ts +2 -0
  69. package/dist/compiler/server/server-middleware.test.d.ts.map +1 -0
  70. package/dist/compiler/server/server-middleware.test.js +169 -0
  71. package/dist/compiler/server/type.d.ts +7 -0
  72. package/dist/compiler/server/type.d.ts.map +1 -0
  73. package/dist/compiler/server/type.js +1 -0
  74. package/dist/services/env-variables/index.js +1 -1
  75. package/package.json +5 -5
package/README.md CHANGED
@@ -1,63 +1,5 @@
1
1
  [![Inlang-ecosystem compatibility badge](https://cdn.jsdelivr.net/gh/opral/monorepo@main/inlang/assets/md-badges/inlang.svg)](https://inlang.com)
2
2
 
3
- # Getting started
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
- To auto setup Paraglide JS, run the following command:
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,2 @@
1
+ export declare const paraglideEsbuildPlugin: (options: import("../index.js").CompilerOptions) => import("unplugin").EsbuildPlugin;
2
+ //# sourceMappingURL=esbuild.d.ts.map
@@ -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"}
@@ -0,0 +1,3 @@
1
+ import { createEsbuildPlugin } from "unplugin";
2
+ import { unpluginFactory } from "./unplugin.js";
3
+ export const paraglideEsbuildPlugin = createEsbuildPlugin(unpluginFactory);
@@ -1,4 +1,7 @@
1
- export { paraglideVitePlugin } from "./vite.js";
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,mBAAmB,EAAE,MAAM,WAAW,CAAC;AAChD,OAAO,EAAE,qBAAqB,EAAE,MAAM,aAAa,CAAC;AACpD,OAAO,EAAE,sBAAsB,EAAE,MAAM,cAAc,CAAC"}
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 { paraglideVitePlugin } from "./vite.js";
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,2 @@
1
+ export declare const paraglideRolldownPlugin: (options: import("../index.js").CompilerOptions) => import("unplugin").RolldownPlugin<any> | import("unplugin").RolldownPlugin<any>[];
2
+ //# sourceMappingURL=rolldown.d.ts.map
@@ -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"}
@@ -0,0 +1,3 @@
1
+ import { createRolldownPlugin } from "unplugin";
2
+ import { unpluginFactory } from "./unplugin.js";
3
+ export const paraglideRolldownPlugin = createRolldownPlugin(unpluginFactory);
@@ -1,2 +1,2 @@
1
- export declare const paraglideRollupPlugin: (options: import("../index.js").CompilerOptions) => import("rollup").Plugin<any> | import("rollup").Plugin<any>[];
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,mHAAsC,CAAC"}
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,2 @@
1
+ export declare const paraglideRspackPlugin: (options: import("../index.js").CompilerOptions) => RspackPluginInstance;
2
+ //# sourceMappingURL=rspack.d.ts.map
@@ -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"}
@@ -0,0 +1,3 @@
1
+ import { createRspackPlugin } from "unplugin";
2
+ import { unpluginFactory } from "./unplugin.js";
3
+ export const paraglideRspackPlugin = createRspackPlugin(unpluginFactory);
@@ -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,2EAAuC,CAAC"}
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" : ""} const ${safeBundleId} = (inputs${hasInputs ? "" : "= {}"}, options = {}) => {
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
- .getPreEmitDiagnostics(program)
469
- // runtime type here makes issues because of the path-to-regexp import
470
- .filter((d) => !d.file?.fileName.includes("runtime.js"));
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(["runtime.js", "messages.js", "adapter.js"]));
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 sometimes struggle tree-shaking this structure.
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;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;OA0CG;IACH,eAAe,CAAC,EAAE,gBAAgB,GAAG,iBAAiB,CAAC;IACvD;;;;OAIG;IACH,EAAE,CAAC,EAAE,GAAG,CAAC;CACT,CAAC"}
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;AAG9D,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,CA2DxB"}
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;AAG9D,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,CAoFxB"}
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,CAiGT;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,CAAC,CAkBnB"}
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 file = createRuntimeFile({
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(file, "utf-8").toString("base64"));
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":"AAwBA;;;;;;;;;;;GAWG;AACH,sBAFU,MAAM,MAAM,CAgDpB;AA4BF;;;;;;;;;;;;;;GAcG;AACH,iCAFU,CAAC,EAAE,EAAE,MAAM,MAAM,KAAK,IAAI,CAIlC"}
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 (serverMiddlewareAsyncStorage) {
34
- const locale = serverMiddlewareAsyncStorage?.getStore()?.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":"AAAA;;;;;;;;GAQG;AACH,yBAFU,MAAM,MAAM,CAWpB;AAEF;;;;;;;GAOG;AACH,kCAFU,CAAC,EAAE,EAAE,MAAM,MAAM,KAAK,IAAI,CAIlC"}
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 (serverMiddlewareAsyncStorage) {
12
- return (serverMiddlewareAsyncStorage.getStore()?.origin ?? "http://fallback.com");
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,5 @@
1
+ /**
2
+ * Returns the code for the `runtime.js` module
3
+ */
4
+ export declare function createServerRuntimeFile(): string;
5
+ //# sourceMappingURL=create-server-runtime.d.ts.map
@@ -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"}