@inlang/paraglide-js 2.0.13 → 2.2.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.
Files changed (58) hide show
  1. package/dist/bundler-plugins/vite.d.ts +1 -1
  2. package/dist/bundler-plugins/vite.d.ts.map +1 -1
  3. package/dist/compiler/compile-bundle.d.ts +2 -1
  4. package/dist/compiler/compile-bundle.d.ts.map +1 -1
  5. package/dist/compiler/compile-bundle.js +4 -3
  6. package/dist/compiler/compile-bundle.test.js +64 -0
  7. package/dist/compiler/compile-project.d.ts.map +1 -1
  8. package/dist/compiler/compile-project.js +1 -0
  9. package/dist/compiler/compiler-options.d.ts +17 -3
  10. package/dist/compiler/compiler-options.d.ts.map +1 -1
  11. package/dist/compiler/runtime/create-runtime.d.ts.map +1 -1
  12. package/dist/compiler/runtime/create-runtime.js +8 -0
  13. package/dist/compiler/runtime/extract-locale-from-cookie.d.ts +1 -1
  14. package/dist/compiler/runtime/extract-locale-from-cookie.js +1 -1
  15. package/dist/compiler/runtime/extract-locale-from-header.d.ts +2 -0
  16. package/dist/compiler/runtime/extract-locale-from-header.d.ts.map +1 -0
  17. package/dist/compiler/runtime/extract-locale-from-header.js +43 -0
  18. package/dist/compiler/runtime/extract-locale-from-header.test.d.ts +2 -0
  19. package/dist/compiler/runtime/extract-locale-from-header.test.d.ts.map +1 -0
  20. package/dist/compiler/runtime/extract-locale-from-header.test.js +51 -0
  21. package/dist/compiler/runtime/extract-locale-from-navigator.d.ts +2 -0
  22. package/dist/compiler/runtime/extract-locale-from-navigator.d.ts.map +1 -0
  23. package/dist/compiler/runtime/extract-locale-from-navigator.js +31 -0
  24. package/dist/compiler/runtime/extract-locale-from-navigator.test.d.ts +2 -0
  25. package/dist/compiler/runtime/extract-locale-from-navigator.test.d.ts.map +1 -0
  26. package/dist/compiler/runtime/extract-locale-from-navigator.test.js +29 -0
  27. package/dist/compiler/runtime/extract-locale-from-request-async.d.ts +31 -0
  28. package/dist/compiler/runtime/extract-locale-from-request-async.d.ts.map +1 -0
  29. package/dist/compiler/runtime/extract-locale-from-request-async.js +55 -0
  30. package/dist/compiler/runtime/extract-locale-from-request-async.test.d.ts +2 -0
  31. package/dist/compiler/runtime/extract-locale-from-request-async.test.d.ts.map +1 -0
  32. package/dist/compiler/runtime/extract-locale-from-request-async.test.js +58 -0
  33. package/dist/compiler/runtime/extract-locale-from-request.d.ts +3 -0
  34. package/dist/compiler/runtime/extract-locale-from-request.d.ts.map +1 -1
  35. package/dist/compiler/runtime/extract-locale-from-request.js +12 -36
  36. package/dist/compiler/runtime/extract-locale-from-request.test.js +84 -2
  37. package/dist/compiler/runtime/get-locale.d.ts.map +1 -1
  38. package/dist/compiler/runtime/get-locale.js +16 -26
  39. package/dist/compiler/runtime/get-locale.test.js +154 -1
  40. package/dist/compiler/runtime/set-locale.d.ts.map +1 -1
  41. package/dist/compiler/runtime/set-locale.js +18 -3
  42. package/dist/compiler/runtime/set-locale.test.js +146 -6
  43. package/dist/compiler/runtime/strategy.d.ts +60 -0
  44. package/dist/compiler/runtime/strategy.d.ts.map +1 -0
  45. package/dist/compiler/runtime/strategy.js +60 -0
  46. package/dist/compiler/runtime/strategy.test.d.ts +2 -0
  47. package/dist/compiler/runtime/strategy.test.d.ts.map +1 -0
  48. package/dist/compiler/runtime/strategy.test.js +94 -0
  49. package/dist/compiler/runtime/type.d.ts +5 -0
  50. package/dist/compiler/runtime/type.d.ts.map +1 -1
  51. package/dist/compiler/runtime/variables.d.ts +2 -2
  52. package/dist/compiler/runtime/variables.d.ts.map +1 -1
  53. package/dist/compiler/runtime/variables.js +1 -1
  54. package/dist/compiler/server/middleware.d.ts.map +1 -1
  55. package/dist/compiler/server/middleware.js +14 -2
  56. package/dist/compiler/server/middleware.test.js +263 -0
  57. package/dist/services/env-variables/index.js +1 -1
  58. package/package.json +6 -6
@@ -0,0 +1,60 @@
1
+ /**
2
+ * Checks if the given strategy is a custom strategy.
3
+ *
4
+ * @param {any} strategy The name of the custom strategy to validate.
5
+ * Must be a string that starts with "custom-" followed by alphanumeric characters, hyphens, or underscores.
6
+ * @returns {boolean} Returns true if it is a custom strategy, false otherwise.
7
+ */
8
+ export function isCustomStrategy(strategy: any): boolean;
9
+ /**
10
+ * Defines a custom strategy that is executed on the server.
11
+ *
12
+ * @param {any} strategy The name of the custom strategy to define. Must follow the pattern custom-name with alphanumeric characters, hyphens, or underscores.
13
+ * @param {CustomServerStrategyHandler} handler The handler for the custom strategy, which should implement
14
+ * the method getLocale.
15
+ * @returns {void}
16
+ */
17
+ export function defineCustomServerStrategy(strategy: any, handler: CustomServerStrategyHandler): void;
18
+ /**
19
+ * Defines a custom strategy that is executed on the client.
20
+ *
21
+ * @param {any} strategy The name of the custom strategy to define. Must follow the pattern custom-name with alphanumeric characters, hyphens, or underscores.
22
+ * @param {CustomClientStrategyHandler} handler The handler for the custom strategy, which should implement the
23
+ * methods getLocale and setLocale.
24
+ * @returns {void}
25
+ */
26
+ export function defineCustomClientStrategy(strategy: any, handler: CustomClientStrategyHandler): void;
27
+ /**
28
+ * @typedef {"cookie" | "baseLocale" | "globalVariable" | "url" | "preferredLanguage" | "localStorage"} BuiltInStrategy
29
+ */
30
+ /**
31
+ * @typedef {`custom_${string}`} CustomStrategy
32
+ */
33
+ /**
34
+ * @typedef {BuiltInStrategy | CustomStrategy} Strategy
35
+ */
36
+ /**
37
+ * @typedef {Array<Strategy>} Strategies
38
+ */
39
+ /**
40
+ * @typedef {{ getLocale: (request?: Request) => Promise<string | undefined> | (string | undefined) }} CustomServerStrategyHandler
41
+ */
42
+ /**
43
+ * @typedef {{ getLocale: () => Promise<string|undefined> | (string | undefined), setLocale: (locale: string) => Promise<void> | void }} CustomClientStrategyHandler
44
+ */
45
+ /** @type {Map<string, CustomServerStrategyHandler>} */
46
+ export const customServerStrategies: Map<string, CustomServerStrategyHandler>;
47
+ /** @type {Map<string, CustomClientStrategyHandler>} */
48
+ export const customClientStrategies: Map<string, CustomClientStrategyHandler>;
49
+ export type BuiltInStrategy = "cookie" | "baseLocale" | "globalVariable" | "url" | "preferredLanguage" | "localStorage";
50
+ export type CustomStrategy = `custom_${string}`;
51
+ export type Strategy = BuiltInStrategy | CustomStrategy;
52
+ export type Strategies = Array<Strategy>;
53
+ export type CustomServerStrategyHandler = {
54
+ getLocale: (request?: Request) => Promise<string | undefined> | (string | undefined);
55
+ };
56
+ export type CustomClientStrategyHandler = {
57
+ getLocale: () => Promise<string | undefined> | (string | undefined);
58
+ setLocale: (locale: string) => Promise<void> | void;
59
+ };
60
+ //# sourceMappingURL=strategy.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strategy.d.ts","sourceRoot":"","sources":["../../../src/compiler/runtime/strategy.js"],"names":[],"mappings":"AA6BA;;;;;;GAMG;AACH,2CAJW,GAAG,GAED,OAAO,CAMnB;AAED;;;;;;;GAOG;AACH,qDALW,GAAG,WACH,2BAA2B,GAEzB,IAAI,CAUhB;AAED;;;;;;;GAOG;AACH,qDALW,GAAG,WACH,2BAA2B,GAEzB,IAAI,CAUhB;AA5ED;;GAEG;AAEH;;GAEG;AAEH;;GAEG;AAEH;;GAEG;AAEH;;GAEG;AAEH;;GAEG;AAEH,uDAAuD;AACvD,qCADW,GAAG,CAAC,MAAM,EAAE,2BAA2B,CAAC,CACH;AAChD,uDAAuD;AACvD,qCADW,GAAG,CAAC,MAAM,EAAE,2BAA2B,CAAC,CACH;8BA1BnC,QAAQ,GAAG,YAAY,GAAG,gBAAgB,GAAG,KAAK,GAAG,mBAAmB,GAAG,cAAc;6BAIzF,UAAU,MAAM,EAAE;uBAIlB,eAAe,GAAG,cAAc;yBAIhC,KAAK,CAAC,QAAQ,CAAC;0CAIf;IAAE,SAAS,EAAE,CAAC,OAAO,CAAC,EAAE,OAAO,KAAK,OAAO,CAAC,MAAM,GAAG,SAAS,CAAC,GAAG,CAAC,MAAM,GAAG,SAAS,CAAC,CAAA;CAAE;0CAIxF;IAAE,SAAS,EAAE,MAAM,OAAO,CAAC,MAAM,GAAC,SAAS,CAAC,GAAG,CAAC,MAAM,GAAG,SAAS,CAAC,CAAC;IAAC,SAAS,EAAE,CAAC,MAAM,EAAE,MAAM,KAAK,OAAO,CAAC,IAAI,CAAC,GAAG,IAAI,CAAA;CAAE"}
@@ -0,0 +1,60 @@
1
+ /**
2
+ * @typedef {"cookie" | "baseLocale" | "globalVariable" | "url" | "preferredLanguage" | "localStorage"} BuiltInStrategy
3
+ */
4
+ /**
5
+ * @typedef {`custom_${string}`} CustomStrategy
6
+ */
7
+ /**
8
+ * @typedef {BuiltInStrategy | CustomStrategy} Strategy
9
+ */
10
+ /**
11
+ * @typedef {Array<Strategy>} Strategies
12
+ */
13
+ /**
14
+ * @typedef {{ getLocale: (request?: Request) => Promise<string | undefined> | (string | undefined) }} CustomServerStrategyHandler
15
+ */
16
+ /**
17
+ * @typedef {{ getLocale: () => Promise<string|undefined> | (string | undefined), setLocale: (locale: string) => Promise<void> | void }} CustomClientStrategyHandler
18
+ */
19
+ /** @type {Map<string, CustomServerStrategyHandler>} */
20
+ export const customServerStrategies = new Map();
21
+ /** @type {Map<string, CustomClientStrategyHandler>} */
22
+ export const customClientStrategies = new Map();
23
+ /**
24
+ * Checks if the given strategy is a custom strategy.
25
+ *
26
+ * @param {any} strategy The name of the custom strategy to validate.
27
+ * Must be a string that starts with "custom-" followed by alphanumeric characters, hyphens, or underscores.
28
+ * @returns {boolean} Returns true if it is a custom strategy, false otherwise.
29
+ */
30
+ export function isCustomStrategy(strategy) {
31
+ return (typeof strategy === "string" && /^custom-[A-Za-z0-9_-]+$/.test(strategy));
32
+ }
33
+ /**
34
+ * Defines a custom strategy that is executed on the server.
35
+ *
36
+ * @param {any} strategy The name of the custom strategy to define. Must follow the pattern custom-name with alphanumeric characters, hyphens, or underscores.
37
+ * @param {CustomServerStrategyHandler} handler The handler for the custom strategy, which should implement
38
+ * the method getLocale.
39
+ * @returns {void}
40
+ */
41
+ export function defineCustomServerStrategy(strategy, handler) {
42
+ if (!isCustomStrategy(strategy)) {
43
+ throw new Error(`Invalid custom strategy: "${strategy}". Must be a custom strategy following the pattern custom-name.`);
44
+ }
45
+ customServerStrategies.set(strategy, handler);
46
+ }
47
+ /**
48
+ * Defines a custom strategy that is executed on the client.
49
+ *
50
+ * @param {any} strategy The name of the custom strategy to define. Must follow the pattern custom-name with alphanumeric characters, hyphens, or underscores.
51
+ * @param {CustomClientStrategyHandler} handler The handler for the custom strategy, which should implement the
52
+ * methods getLocale and setLocale.
53
+ * @returns {void}
54
+ */
55
+ export function defineCustomClientStrategy(strategy, handler) {
56
+ if (!isCustomStrategy(strategy)) {
57
+ throw new Error(`Invalid custom strategy: "${strategy}". Must be a custom strategy following the pattern custom-name.`);
58
+ }
59
+ customClientStrategies.set(strategy, handler);
60
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=strategy.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"strategy.test.d.ts","sourceRoot":"","sources":["../../../src/compiler/runtime/strategy.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,94 @@
1
+ import { test, expect, describe, beforeEach } from "vitest";
2
+ import { newProject } from "@inlang/sdk";
3
+ import { defineCustomServerStrategy, defineCustomClientStrategy, isCustomStrategy, } from "./strategy.js";
4
+ import { createParaglide } from "../create-paraglide.js";
5
+ describe("isCustomStrategy", () => {
6
+ test("returns true for valid custom strategy patterns", () => {
7
+ expect(isCustomStrategy("custom-header")).toBe(true);
8
+ expect(isCustomStrategy("custom-auth123")).toBe(true);
9
+ expect(isCustomStrategy("custom-API")).toBe(true);
10
+ expect(isCustomStrategy("custom-sessionStorage")).toBe(true);
11
+ expect(isCustomStrategy("custom-oAuth2")).toBe(true);
12
+ expect(isCustomStrategy("custom-a")).toBe(true);
13
+ expect(isCustomStrategy("custom-1")).toBe(true);
14
+ expect(isCustomStrategy("custom-Z")).toBe(true);
15
+ expect(isCustomStrategy("custom-9")).toBe(true);
16
+ expect(isCustomStrategy("custom-aZ19")).toBe(true);
17
+ });
18
+ test("returns false for invalid custom strategy patterns", () => {
19
+ expect(isCustomStrategy("")).toBe(false);
20
+ expect(isCustomStrategy("custom_")).toBe(false);
21
+ expect(isCustomStrategy("custom-")).toBe(false);
22
+ expect(isCustomStrategy("header")).toBe(false);
23
+ expect(isCustomStrategy("custom")).toBe(false);
24
+ // These are now valid with our relaxed pattern:
25
+ expect(isCustomStrategy("custom-invalid-name")).toBe(true);
26
+ expect(isCustomStrategy("custom-invalid_name")).toBe(true);
27
+ // But spaces and special chars are still invalid:
28
+ expect(isCustomStrategy("custom-invalid name")).toBe(false);
29
+ expect(isCustomStrategy("custom-invalid@")).toBe(false);
30
+ expect(isCustomStrategy("Custom-header")).toBe(false);
31
+ expect(isCustomStrategy("CUSTOM-header")).toBe(false);
32
+ expect(isCustomStrategy(null)).toBe(false);
33
+ expect(isCustomStrategy(undefined)).toBe(false);
34
+ expect(isCustomStrategy(123)).toBe(false);
35
+ expect(isCustomStrategy({})).toBe(false);
36
+ expect(isCustomStrategy([])).toBe(false);
37
+ });
38
+ test("returns false for built-in strategy names", () => {
39
+ expect(isCustomStrategy("cookie")).toBe(false);
40
+ expect(isCustomStrategy("baseLocale")).toBe(false);
41
+ expect(isCustomStrategy("globalVariable")).toBe(false);
42
+ expect(isCustomStrategy("url")).toBe(false);
43
+ expect(isCustomStrategy("preferredLanguage")).toBe(false);
44
+ expect(isCustomStrategy("localStorage")).toBe(false);
45
+ });
46
+ });
47
+ describe.each([
48
+ ["defineCustomServerStrategy", defineCustomServerStrategy],
49
+ ["defineCustomClientStrategy", defineCustomClientStrategy],
50
+ ])("%s", (strategyName, defineStrategy) => {
51
+ beforeEach(() => {
52
+ // Reset global variables before each test
53
+ if (typeof globalThis !== "undefined") {
54
+ // @ts-expect-error - Testing environment cleanup
55
+ delete globalThis.document;
56
+ // @ts-expect-error - Testing environment cleanup
57
+ delete globalThis.window;
58
+ // @ts-expect-error - Testing environment cleanup
59
+ delete globalThis.localStorage;
60
+ // @ts-expect-error - Testing environment cleanup
61
+ delete globalThis.navigator;
62
+ }
63
+ });
64
+ const defaultHandler = { getLocale: () => "en", setLocale: () => { } };
65
+ const invalidInputs = [
66
+ ["", "empty name"],
67
+ ["@invalid", "names with special characters (@)"],
68
+ ["invalid!", "names with special characters (!)"],
69
+ ["inva lid", "names with spaces"],
70
+ ];
71
+ test.each(invalidInputs)(`${strategyName} throws error for %s (%s)`, (input) => {
72
+ expect(() => defineStrategy(input, defaultHandler)).toThrow(`Invalid custom strategy: "${input}". Must be a custom strategy following the pattern custom-name.`);
73
+ });
74
+ test(`${strategyName} should compile with custom strategies in strategy array`, async () => {
75
+ // Test that compile accepts custom strategies
76
+ const runtime = await createParaglide({
77
+ blob: await newProject({
78
+ settings: {
79
+ baseLocale: "en",
80
+ locales: ["en", "de", "fr"],
81
+ },
82
+ }),
83
+ strategy: ["custom-auth", "custom-header", "cookie", "baseLocale"],
84
+ cookieName: "PARAGLIDE_LOCALE",
85
+ });
86
+ // Verify the runtime contains the strategy array
87
+ expect(runtime.strategy).toEqual([
88
+ "custom-auth",
89
+ "custom-header",
90
+ "cookie",
91
+ "baseLocale",
92
+ ]);
93
+ });
94
+ });
@@ -27,8 +27,13 @@ export type Runtime = {
27
27
  deLocalizeUrl: typeof import("./localize-url.js").deLocalizeUrl;
28
28
  extractLocaleFromUrl: typeof import("./extract-locale-from-url.js").extractLocaleFromUrl;
29
29
  extractLocaleFromRequest: typeof import("./extract-locale-from-request.js").extractLocaleFromRequest;
30
+ extractLocaleFromRequestAsync: typeof import("./extract-locale-from-request-async.js").extractLocaleFromRequestAsync;
30
31
  extractLocaleFromCookie: typeof import("./extract-locale-from-cookie.js").extractLocaleFromCookie;
32
+ extractLocaleFromHeader: typeof import("./extract-locale-from-header.js").extractLocaleFromHeader;
33
+ extractLocaleFromNavigator: typeof import("./extract-locale-from-navigator.js").extractLocaleFromNavigator;
31
34
  generateStaticLocalizedUrls: typeof import("./generate-static-localized-urls.js").generateStaticLocalizedUrls;
32
35
  trackMessageCall: typeof import("./track-message-call.js").trackMessageCall;
36
+ defineCustomServerStrategy: typeof import("./strategy.js").defineCustomServerStrategy;
37
+ defineCustomClientStrategy: typeof import("./strategy.js").defineCustomClientStrategy;
33
38
  };
34
39
  //# sourceMappingURL=type.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"type.d.ts","sourceRoot":"","sources":["../../../src/compiler/runtime/type.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,OAAO,GAAG;IACrB,UAAU,EAAE,cAAc,gBAAgB,EAAE,UAAU,CAAC;IACvD,OAAO,EAAE,cAAc,gBAAgB,EAAE,OAAO,CAAC;IACjD,QAAQ,EAAE,cAAc,gBAAgB,EAAE,QAAQ,CAAC;IACnD,UAAU,EAAE,cAAc,gBAAgB,EAAE,UAAU,CAAC;IACvD,YAAY,EAAE,cAAc,gBAAgB,EAAE,YAAY,CAAC;IAC3D,WAAW,EAAE,cAAc,gBAAgB,EAAE,WAAW,CAAC;IACzD,wBAAwB,EAAE,cAAc,gBAAgB,EAAE,wBAAwB,CAAC;IACnF,uBAAuB,EAAE,cAAc,gBAAgB,EAAE,uBAAuB,CAAC;IACjF,qCAAqC,EAAE,cAAc,gBAAgB,EAAE,qCAAqC,CAAC;IAC7G,QAAQ,EAAE,cAAc,gBAAgB,EAAE,QAAQ,CAAC;IACnD,SAAS,EAAE,cAAc,iBAAiB,EAAE,SAAS,CAAC;IACtD,SAAS,EAAE,cAAc,iBAAiB,EAAE,SAAS,CAAC;IACtD,YAAY,EAAE,cAAc,qBAAqB,EAAE,YAAY,CAAC;IAChE,kBAAkB,EAAE,cAAc,iBAAiB,EAAE,kBAAkB,CAAC;IACxE,kBAAkB,EAAE,cAAc,iBAAiB,EAAE,kBAAkB,CAAC;IACxE,qBAAqB,EAAE,cAAc,qBAAqB,EAAE,qBAAqB,CAAC;IAClF,gCAAgC,EAAE,cAAc,gBAAgB,EAAE,gCAAgC,CAAC;IACnG,cAAc,EAAE,cAAc,uBAAuB,EAAE,cAAc,CAAC;IACtE,QAAQ,EAAE,cAAc,gBAAgB,EAAE,QAAQ,CAAC;IACnD,YAAY,EAAE,cAAc,oBAAoB,EAAE,YAAY,CAAC;IAC/D,cAAc,EAAE,cAAc,oBAAoB,EAAE,cAAc,CAAC;IACnE,WAAW,EAAE,cAAc,mBAAmB,EAAE,WAAW,CAAC;IAC5D,aAAa,EAAE,cAAc,mBAAmB,EAAE,aAAa,CAAC;IAChE,oBAAoB,EAAE,cAAc,8BAA8B,EAAE,oBAAoB,CAAC;IACzF,wBAAwB,EAAE,cAAc,kCAAkC,EAAE,wBAAwB,CAAC;IACrG,uBAAuB,EAAE,cAAc,iCAAiC,EAAE,uBAAuB,CAAC;IAClG,2BAA2B,EAAE,cAAc,qCAAqC,EAAE,2BAA2B,CAAC;IAC9G,gBAAgB,EAAE,cAAc,yBAAyB,EAAE,gBAAgB,CAAC;CAC5E,CAAC"}
1
+ {"version":3,"file":"type.d.ts","sourceRoot":"","sources":["../../../src/compiler/runtime/type.ts"],"names":[],"mappings":"AAAA;;GAEG;AACH,MAAM,MAAM,OAAO,GAAG;IACrB,UAAU,EAAE,cAAc,gBAAgB,EAAE,UAAU,CAAC;IACvD,OAAO,EAAE,cAAc,gBAAgB,EAAE,OAAO,CAAC;IACjD,QAAQ,EAAE,cAAc,gBAAgB,EAAE,QAAQ,CAAC;IACnD,UAAU,EAAE,cAAc,gBAAgB,EAAE,UAAU,CAAC;IACvD,YAAY,EAAE,cAAc,gBAAgB,EAAE,YAAY,CAAC;IAC3D,WAAW,EAAE,cAAc,gBAAgB,EAAE,WAAW,CAAC;IACzD,wBAAwB,EAAE,cAAc,gBAAgB,EAAE,wBAAwB,CAAC;IACnF,uBAAuB,EAAE,cAAc,gBAAgB,EAAE,uBAAuB,CAAC;IACjF,qCAAqC,EAAE,cAAc,gBAAgB,EAAE,qCAAqC,CAAC;IAC7G,QAAQ,EAAE,cAAc,gBAAgB,EAAE,QAAQ,CAAC;IACnD,SAAS,EAAE,cAAc,iBAAiB,EAAE,SAAS,CAAC;IACtD,SAAS,EAAE,cAAc,iBAAiB,EAAE,SAAS,CAAC;IACtD,YAAY,EAAE,cAAc,qBAAqB,EAAE,YAAY,CAAC;IAChE,kBAAkB,EAAE,cAAc,iBAAiB,EAAE,kBAAkB,CAAC;IACxE,kBAAkB,EAAE,cAAc,iBAAiB,EAAE,kBAAkB,CAAC;IACxE,qBAAqB,EAAE,cAAc,qBAAqB,EAAE,qBAAqB,CAAC;IAClF,gCAAgC,EAAE,cAAc,gBAAgB,EAAE,gCAAgC,CAAC;IACnG,cAAc,EAAE,cAAc,uBAAuB,EAAE,cAAc,CAAC;IACtE,QAAQ,EAAE,cAAc,gBAAgB,EAAE,QAAQ,CAAC;IACnD,YAAY,EAAE,cAAc,oBAAoB,EAAE,YAAY,CAAC;IAC/D,cAAc,EAAE,cAAc,oBAAoB,EAAE,cAAc,CAAC;IACnE,WAAW,EAAE,cAAc,mBAAmB,EAAE,WAAW,CAAC;IAC5D,aAAa,EAAE,cAAc,mBAAmB,EAAE,aAAa,CAAC;IAChE,oBAAoB,EAAE,cAAc,8BAA8B,EAAE,oBAAoB,CAAC;IACzF,wBAAwB,EAAE,cAAc,kCAAkC,EAAE,wBAAwB,CAAC;IACrG,6BAA6B,EAAE,cAAc,wCAAwC,EAAE,6BAA6B,CAAC;IACrH,uBAAuB,EAAE,cAAc,iCAAiC,EAAE,uBAAuB,CAAC;IAClG,uBAAuB,EAAE,cAAc,iCAAiC,EAAE,uBAAuB,CAAC;IAClG,0BAA0B,EAAE,cAAc,oCAAoC,EAAE,0BAA0B,CAAC;IAC3G,2BAA2B,EAAE,cAAc,qCAAqC,EAAE,2BAA2B,CAAC;IAC9G,gBAAgB,EAAE,cAAc,yBAAyB,EAAE,gBAAgB,CAAC;IAC5E,0BAA0B,EAAE,cAAc,eAAe,EAAE,0BAA0B,CAAC;IACtF,0BAA0B,EAAE,cAAc,eAAe,EAAE,0BAA0B,CAAC;CACtF,CAAC"}
@@ -36,9 +36,9 @@ export const cookieDomain: string;
36
36
  /** @type {string} */
37
37
  export const localStorageKey: string;
38
38
  /**
39
- * @type {Array<"cookie" | "baseLocale" | "globalVariable" | "url" | "preferredLanguage" | "localStorage">}
39
+ * @type {Array<"cookie" | "baseLocale" | "globalVariable" | "url" | "preferredLanguage" | "localStorage" | `custom-${string}`>}
40
40
  */
41
- export const strategy: Array<"cookie" | "baseLocale" | "globalVariable" | "url" | "preferredLanguage" | "localStorage">;
41
+ export const strategy: Array<"cookie" | "baseLocale" | "globalVariable" | "url" | "preferredLanguage" | "localStorage" | `custom-${string}`>;
42
42
  /**
43
43
  * The used URL patterns.
44
44
  *
@@ -1 +1 @@
1
- {"version":3,"file":"variables.d.ts","sourceRoot":"","sources":["../../../src/compiler/runtime/variables.js"],"names":[],"mappings":"AAwEA;;;;;;;;;GASG;AACH,wDAFW,0BAA0B,GAAG,SAAS,QAIhD;AApFD;;;;;;;GAOG;AACH,yBAA0B,IAAI,CAAC;AAE/B;;;;;;;GAOG;AACH,4CAA2D;AAE3D,qBAAqB;AACrB,yBADW,MAAM,CACyB;AAE1C,qBAAqB;AACrB,2BADW,MAAM,CAC8B;AAE/C,qBAAqB;AACrB,2BADW,MAAM,CAC6B;AAE9C,qBAAqB;AACrB,8BADW,MAAM,CACiC;AAElD;;GAEG;AACH,uBAFU,KAAK,CAAC,QAAQ,GAAG,YAAY,GAAG,gBAAgB,GAAG,KAAK,GAAG,mBAAmB,GAAG,cAAc,CAAC,CAE/D;AAE3C;;;;GAIG;AACH,0BAFU,KAAK,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CAAE,CAAC,CAE1C;AAE9B;;;;;;;;;;GAUG;AAEH;;;;;;;GAOG;AACH,oCAFU,0BAA0B,GAAG,SAAS,CAED;AAE/C,uCAAwC,KAAK,CAAC;AAE9C,oDAAqD,KAAK,CAAC;AAE3D,+BAAsD;AAgBtD,8CAA+C,KAAK,CAAC;AAErD,2CAA4C,KAAK,CAAC;AAElD,uDAAwD,KAAK,CAAC;AAE9D,0DAA2D,KAAK,CAAC;AAEjE,kDAAmD,KAAK,CAAC;AAEzD,qDAAsD,KAAK,CAAC;yCAnD/C;IACR,QAAQ,IAAI;QACV,MAAM,CAAC,EAAE,MAAM,CAAC;QACjB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;KACzB,GAAG,SAAS,CAAC;IACf,GAAG,EAAE,CAAC,KAAK,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;KAAC,EAC3E,EAAE,EAAE,GAAG,KAAK,GAAG,CAAA;CACjB"}
1
+ {"version":3,"file":"variables.d.ts","sourceRoot":"","sources":["../../../src/compiler/runtime/variables.js"],"names":[],"mappings":"AAwEA;;;;;;;;;GASG;AACH,wDAFW,0BAA0B,GAAG,SAAS,QAIhD;AApFD;;;;;;;GAOG;AACH,yBAA0B,IAAI,CAAC;AAE/B;;;;;;;GAOG;AACH,4CAA2D;AAE3D,qBAAqB;AACrB,yBADW,MAAM,CACyB;AAE1C,qBAAqB;AACrB,2BADW,MAAM,CAC8B;AAE/C,qBAAqB;AACrB,2BADW,MAAM,CAC6B;AAE9C,qBAAqB;AACrB,8BADW,MAAM,CACiC;AAElD;;GAEG;AACH,uBAFU,KAAK,CAAC,QAAQ,GAAG,YAAY,GAAG,gBAAgB,GAAG,KAAK,GAAG,mBAAmB,GAAG,cAAc,GAAG,UAAU,MAAM,EAAE,CAAC,CAEpF;AAE3C;;;;GAIG;AACH,0BAFU,KAAK,CAAC;IAAE,OAAO,EAAE,MAAM,CAAC;IAAC,SAAS,EAAE,KAAK,CAAC,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC,CAAA;CAAE,CAAC,CAE1C;AAE9B;;;;;;;;;;GAUG;AAEH;;;;;;;GAOG;AACH,oCAFU,0BAA0B,GAAG,SAAS,CAED;AAE/C,uCAAwC,KAAK,CAAC;AAE9C,oDAAqD,KAAK,CAAC;AAE3D,+BAAsD;AAgBtD,8CAA+C,KAAK,CAAC;AAErD,2CAA4C,KAAK,CAAC;AAElD,uDAAwD,KAAK,CAAC;AAE9D,0DAA2D,KAAK,CAAC;AAEjE,kDAAmD,KAAK,CAAC;AAEzD,qDAAsD,KAAK,CAAC;yCAnD/C;IACR,QAAQ,IAAI;QACV,MAAM,CAAC,EAAE,MAAM,CAAC;QACjB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;KACzB,GAAG,SAAS,CAAC;IACf,GAAG,EAAE,CAAC,KAAK,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAC;QAAC,YAAY,CAAC,EAAE,GAAG,CAAC,MAAM,CAAC,CAAA;KAAC,EAC3E,EAAE,EAAE,GAAG,KAAK,GAAG,CAAA;CACjB"}
@@ -25,7 +25,7 @@ export const cookieDomain = "<cookie-domain>";
25
25
  /** @type {string} */
26
26
  export const localStorageKey = "PARAGLIDE_LOCALE";
27
27
  /**
28
- * @type {Array<"cookie" | "baseLocale" | "globalVariable" | "url" | "preferredLanguage" | "localStorage">}
28
+ * @type {Array<"cookie" | "baseLocale" | "globalVariable" | "url" | "preferredLanguage" | "localStorage" | `custom-${string}`>}
29
29
  */
30
30
  export const strategy = ["globalVariable"];
31
31
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../../src/compiler/server/middleware.js"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AACH,oCA9Ca,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,cACrF;IAAE,UAAU,EAAC,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAA;CAAE,GACzC,OAAO,CAAC,QAAQ,CAAC,CA4H7B"}
1
+ {"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../../src/compiler/server/middleware.js"],"names":[],"mappings":"AAEA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA4DG;AACH,oCA9Ca,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,cACrF;IAAE,UAAU,EAAC,CAAC,QAAQ,EAAE,QAAQ,KAAK,IAAI,CAAA;CAAE,GACzC,OAAO,CAAC,QAAQ,CAAC,CA0I7B"}
@@ -68,7 +68,7 @@ export async function paraglideMiddleware(request, resolve, callbacks) {
68
68
  else if (!runtime.serverAsyncLocalStorage) {
69
69
  runtime.overwriteServerAsyncLocalStorage(createMockAsyncLocalStorage());
70
70
  }
71
- const locale = runtime.extractLocaleFromRequest(request);
71
+ const locale = await runtime.extractLocaleFromRequestAsync(request);
72
72
  const origin = new URL(request.url).origin;
73
73
  // if the client makes a request to a URL that doesn't match
74
74
  // the localizedUrl, redirect the client to the localized URL
@@ -76,7 +76,19 @@ export async function paraglideMiddleware(request, resolve, callbacks) {
76
76
  runtime.strategy.includes("url")) {
77
77
  const localizedUrl = runtime.localizeUrl(request.url, { locale });
78
78
  if (normalizeURL(localizedUrl.href) !== normalizeURL(request.url)) {
79
- const response = Response.redirect(localizedUrl, 307);
79
+ // Create headers object with Vary header if preferredLanguage strategy is used
80
+ /** @type {Record<string, string>} */
81
+ const headers = {};
82
+ if (runtime.strategy.includes("preferredLanguage")) {
83
+ headers["Vary"] = "Accept-Language";
84
+ }
85
+ const response = new Response(null, {
86
+ status: 307,
87
+ headers: {
88
+ Location: localizedUrl.href,
89
+ ...headers,
90
+ },
91
+ });
80
92
  callbacks?.onRedirect(response);
81
93
  return response;
82
94
  }
@@ -150,6 +150,79 @@ test("call onRedirect callback when redirecting to new url", async () => {
150
150
  expect(response.status).toBe(307); // Redirect status code
151
151
  expect(response.headers.get("Location")).toBe("https://example.com/fr/some-path");
152
152
  });
153
+ test("sets Vary: Accept-Language header when preferredLanguage strategy is used and redirect occurs", async () => {
154
+ const runtime = await createParaglide({
155
+ blob: await newProject({
156
+ settings: {
157
+ baseLocale: "en",
158
+ locales: ["en", "fr"],
159
+ },
160
+ }),
161
+ strategy: ["preferredLanguage", "url"],
162
+ urlPatterns: [
163
+ {
164
+ pattern: "https://example.com/:path(.*)?",
165
+ localized: [
166
+ ["en", "https://example.com/en/:path(.*)?"],
167
+ ["fr", "https://example.com/fr/:path(.*)?"],
168
+ ],
169
+ },
170
+ ],
171
+ });
172
+ // Request with Accept-Language header preferring French
173
+ const request = new Request("https://example.com/en/some-path", {
174
+ headers: {
175
+ "Accept-Language": "fr,en;q=0.8",
176
+ "Sec-Fetch-Dest": "document",
177
+ },
178
+ });
179
+ const response = await runtime.paraglideMiddleware(request, () => {
180
+ // This shouldn't be called since we should redirect
181
+ throw new Error("Should not reach here");
182
+ });
183
+ expect(response instanceof Response).toBe(true);
184
+ expect(response.status).toBe(307); // Redirect status code
185
+ expect(response.headers.get("Location")).toBe("https://example.com/fr/some-path");
186
+ // Should have Vary header when preferredLanguage strategy is used
187
+ expect(response.headers.get("Vary")).toBe("Accept-Language");
188
+ });
189
+ test("does not set Vary header when preferredLanguage strategy is not used", async () => {
190
+ const runtime = await createParaglide({
191
+ blob: await newProject({
192
+ settings: {
193
+ baseLocale: "en",
194
+ locales: ["en", "fr"],
195
+ },
196
+ }),
197
+ strategy: ["cookie", "url"],
198
+ cookieName: "PARAGLIDE_LOCALE",
199
+ urlPatterns: [
200
+ {
201
+ pattern: "https://example.com/:path(.*)?",
202
+ localized: [
203
+ ["en", "https://example.com/en/:path(.*)?"],
204
+ ["fr", "https://example.com/fr/:path(.*)?"],
205
+ ],
206
+ },
207
+ ],
208
+ });
209
+ // Request with cookie specifying French
210
+ const request = new Request("https://example.com/en/some-path", {
211
+ headers: {
212
+ cookie: `PARAGLIDE_LOCALE=fr`,
213
+ "Sec-Fetch-Dest": "document",
214
+ },
215
+ });
216
+ const response = await runtime.paraglideMiddleware(request, () => {
217
+ // This shouldn't be called since we should redirect
218
+ throw new Error("Should not reach here");
219
+ });
220
+ expect(response instanceof Response).toBe(true);
221
+ expect(response.status).toBe(307); // Redirect status code
222
+ expect(response.headers.get("Location")).toBe("https://example.com/fr/some-path");
223
+ // Should NOT have Vary header when preferredLanguage strategy is not used
224
+ expect(response.headers.get("Vary")).toBe(null);
225
+ });
153
226
  test("does not call onRedirect callback when there is no redirecting", async () => {
154
227
  const runtime = await createParaglide({
155
228
  blob: await newProject({
@@ -506,3 +579,193 @@ test("does not catch errors thrown by downstream resolve call", async () => {
506
579
  throw new Error("Downstream error");
507
580
  })).rejects.toThrow();
508
581
  });
582
+ test("middleware supports async custom server strategies", async () => {
583
+ const runtime = await createParaglide({
584
+ blob: await newProject({
585
+ settings: {
586
+ baseLocale: "en",
587
+ locales: ["en", "fr", "de"],
588
+ },
589
+ }),
590
+ strategy: ["custom-database", "baseLocale"],
591
+ });
592
+ // Mock an async custom strategy that simulates a database call
593
+ let databaseCallCount = 0;
594
+ runtime.defineCustomServerStrategy("custom-database", {
595
+ getLocale: async (request) => {
596
+ databaseCallCount++;
597
+ // Simulate async database call delay
598
+ await new Promise((resolve) => setTimeout(resolve, 10));
599
+ // Extract user ID from a custom header (simulating authentication)
600
+ if (!request)
601
+ return undefined;
602
+ const userId = request.headers.get("X-User-ID");
603
+ if (userId === "user123") {
604
+ return "fr";
605
+ }
606
+ if (userId === "user456") {
607
+ return "de";
608
+ }
609
+ return undefined; // No user preference found
610
+ },
611
+ });
612
+ // Test 1: Request with user preference
613
+ const requestWithUserPref = new Request("https://example.com/page", {
614
+ headers: {
615
+ "X-User-ID": "user123",
616
+ "Sec-Fetch-Dest": "document",
617
+ },
618
+ });
619
+ let middlewareResolveWasCalled = false;
620
+ await runtime.paraglideMiddleware(requestWithUserPref, (args) => {
621
+ middlewareResolveWasCalled = true;
622
+ expect(args.locale).toBe("fr"); // Should get locale from async custom strategy
623
+ return new Response("User preference locale");
624
+ });
625
+ expect(middlewareResolveWasCalled).toBe(true);
626
+ expect(databaseCallCount).toBe(1);
627
+ // Test 2: Request with different user preference
628
+ const requestWithOtherUser = new Request("https://example.com/page", {
629
+ headers: {
630
+ "X-User-ID": "user456",
631
+ "Sec-Fetch-Dest": "document",
632
+ },
633
+ });
634
+ await runtime.paraglideMiddleware(requestWithOtherUser, (args) => {
635
+ expect(args.locale).toBe("de"); // Should get different locale
636
+ return new Response("Other user preference");
637
+ });
638
+ expect(databaseCallCount).toBe(2);
639
+ });
640
+ test("middleware falls back to other strategies when async custom strategy returns undefined", async () => {
641
+ const runtime = await createParaglide({
642
+ blob: await newProject({
643
+ settings: {
644
+ baseLocale: "en",
645
+ locales: ["en", "fr", "de"],
646
+ },
647
+ }),
648
+ strategy: ["custom-database", "cookie", "baseLocale"],
649
+ cookieName: "PARAGLIDE_LOCALE",
650
+ });
651
+ // Mock async custom strategy that returns undefined for unknown users
652
+ runtime.defineCustomServerStrategy("custom-database", {
653
+ getLocale: async (request) => {
654
+ await new Promise((resolve) => setTimeout(resolve, 5));
655
+ if (!request)
656
+ return undefined;
657
+ const userId = request.headers.get("X-User-ID");
658
+ // Only return locale for known users
659
+ if (userId === "known-user") {
660
+ return "fr";
661
+ }
662
+ return undefined; // Unknown user, fallback to other strategies
663
+ },
664
+ });
665
+ // Request from unknown user with cookie fallback
666
+ const request = new Request("https://example.com/page", {
667
+ headers: {
668
+ "X-User-ID": "unknown-user",
669
+ cookie: "PARAGLIDE_LOCALE=de",
670
+ "Sec-Fetch-Dest": "document",
671
+ },
672
+ });
673
+ let middlewareResolveWasCalled = false;
674
+ await runtime.paraglideMiddleware(request, (args) => {
675
+ middlewareResolveWasCalled = true;
676
+ expect(args.locale).toBe("de"); // Should fallback to cookie strategy
677
+ return new Response("Fallback locale");
678
+ });
679
+ expect(middlewareResolveWasCalled).toBe(true);
680
+ });
681
+ test("middleware handles async custom strategy errors gracefully", async () => {
682
+ const runtime = await createParaglide({
683
+ blob: await newProject({
684
+ settings: {
685
+ baseLocale: "en",
686
+ locales: ["en", "fr"],
687
+ },
688
+ }),
689
+ strategy: ["custom-database", "baseLocale"],
690
+ });
691
+ // Mock async custom strategy that throws an error
692
+ runtime.defineCustomServerStrategy("custom-database", {
693
+ getLocale: async () => {
694
+ await new Promise((resolve) => setTimeout(resolve, 5));
695
+ throw new Error("Database connection failed");
696
+ },
697
+ });
698
+ const request = new Request("https://example.com/page", {
699
+ headers: { "Sec-Fetch-Dest": "document" },
700
+ });
701
+ // The middleware should handle the error and not crash
702
+ await expect(runtime.paraglideMiddleware(request, (args) => {
703
+ // If we reach here, the error was handled and fallback worked
704
+ expect(args.locale).toBe("en"); // Should fallback to baseLocale
705
+ return new Response("Error handled");
706
+ })).rejects.toThrow("Database connection failed");
707
+ });
708
+ test("middleware works with multiple async custom strategies", async () => {
709
+ const runtime = await createParaglide({
710
+ blob: await newProject({
711
+ settings: {
712
+ baseLocale: "en",
713
+ locales: ["en", "fr", "de", "es"],
714
+ },
715
+ }),
716
+ strategy: ["custom-userPref", "custom-region", "baseLocale"],
717
+ });
718
+ let userPrefCallCount = 0;
719
+ let regionCallCount = 0;
720
+ // First strategy: user preference
721
+ runtime.defineCustomServerStrategy("custom-userPref", {
722
+ getLocale: async (request) => {
723
+ userPrefCallCount++;
724
+ await new Promise((resolve) => setTimeout(resolve, 5));
725
+ if (!request)
726
+ return undefined;
727
+ const userId = request.headers.get("X-User-ID");
728
+ return userId === "premium-user" ? "fr" : undefined;
729
+ },
730
+ });
731
+ // Second strategy: region detection
732
+ runtime.defineCustomServerStrategy("custom-region", {
733
+ getLocale: async (request) => {
734
+ regionCallCount++;
735
+ await new Promise((resolve) => setTimeout(resolve, 5));
736
+ if (!request)
737
+ return undefined;
738
+ const region = request.headers.get("X-Region");
739
+ return region === "europe" ? "de" : undefined;
740
+ },
741
+ });
742
+ // Test 1: First strategy succeeds
743
+ const premiumUserRequest = new Request("https://example.com/page", {
744
+ headers: {
745
+ "X-User-ID": "premium-user",
746
+ "X-Region": "europe",
747
+ "Sec-Fetch-Dest": "document",
748
+ },
749
+ });
750
+ await runtime.paraglideMiddleware(premiumUserRequest, (args) => {
751
+ expect(args.locale).toBe("fr"); // Should use first strategy result
752
+ return new Response("Premium user");
753
+ });
754
+ expect(userPrefCallCount).toBe(1);
755
+ // Second strategy should not be called since first one succeeded
756
+ expect(regionCallCount).toBe(0);
757
+ // Test 2: First strategy fails, second succeeds
758
+ const regionalUserRequest = new Request("https://example.com/page", {
759
+ headers: {
760
+ "X-User-ID": "regular-user",
761
+ "X-Region": "europe",
762
+ "Sec-Fetch-Dest": "document",
763
+ },
764
+ });
765
+ await runtime.paraglideMiddleware(regionalUserRequest, (args) => {
766
+ expect(args.locale).toBe("de"); // Should use second strategy result
767
+ return new Response("Regional user");
768
+ });
769
+ expect(userPrefCallCount).toBe(2);
770
+ expect(regionCallCount).toBe(1);
771
+ });
@@ -1,5 +1,5 @@
1
1
  export const ENV_VARIABLES = {
2
2
  PARJS_APP_ID: "library.inlang.paraglideJs",
3
3
  PARJS_POSTHOG_TOKEN: "phc_m5yJZCxjOGxF8CJvP5sQ3H0d76xpnLrsmiZHduT4jDz",
4
- PARJS_PACKAGE_VERSION: "2.0.13",
4
+ PARJS_PACKAGE_VERSION: "2.2.0",
5
5
  };
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@inlang/paraglide-js",
3
3
  "type": "module",
4
- "version": "2.0.13",
4
+ "version": "2.2.0",
5
5
  "license": "MIT",
6
6
  "publishConfig": {
7
7
  "access": "public",
@@ -31,8 +31,8 @@
31
31
  "json5": "2.2.3",
32
32
  "unplugin": "^2.1.2",
33
33
  "urlpattern-polyfill": "^10.0.0",
34
- "@inlang/sdk": "2.4.8",
35
- "@inlang/recommend-sherlock": "0.2.1"
34
+ "@inlang/recommend-sherlock": "0.2.1",
35
+ "@inlang/sdk": "2.4.9"
36
36
  },
37
37
  "devDependencies": {
38
38
  "@eslint/js": "^9.18.0",
@@ -44,14 +44,14 @@
44
44
  "memfs": "4.17.0",
45
45
  "prettier": "^3.4.2",
46
46
  "rolldown": "1.0.0-beta.1",
47
- "typedoc": "0.28.3",
48
- "typedoc-plugin-markdown": "^4.6.0",
47
+ "typedoc": "^0.28.5",
48
+ "typedoc-plugin-markdown": "^4.7.0",
49
49
  "typedoc-plugin-missing-exports": "4.0.0",
50
50
  "typescript": "^5.7.3",
51
51
  "typescript-eslint": "^8.20.0",
52
52
  "vitest": "2.1.8",
53
53
  "@inlang/plugin-message-format": "4.0.0",
54
- "@inlang/paraglide-js": "2.0.13",
54
+ "@inlang/paraglide-js": "2.2.0",
55
55
  "@opral/tsconfig": "1.1.0"
56
56
  },
57
57
  "keywords": [