@inlang/paraglide-js 2.0.0-beta.15 → 2.0.0-beta.17

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 (120) hide show
  1. package/dist/bundler-plugins/unplugin.d.ts.map +1 -1
  2. package/dist/bundler-plugins/unplugin.js +10 -3
  3. package/dist/cli/steps/run-compiler.js +1 -1
  4. package/dist/compiler/compile-bundle.d.ts.map +1 -1
  5. package/dist/compiler/compile-bundle.js +9 -4
  6. package/dist/compiler/compile-bundle.test.js +11 -0
  7. package/dist/compiler/compile-message.d.ts +0 -3
  8. package/dist/compiler/compile-message.d.ts.map +1 -1
  9. package/dist/compiler/compile-message.js +14 -9
  10. package/dist/compiler/compile-message.test.js +25 -3
  11. package/dist/compiler/compile-project.d.ts.map +1 -1
  12. package/dist/compiler/compile-project.js +0 -3
  13. package/dist/compiler/compile-project.test.js +59 -66
  14. package/dist/compiler/compile.d.ts +41 -2
  15. package/dist/compiler/compile.d.ts.map +1 -1
  16. package/dist/compiler/compile.js +12 -4
  17. package/dist/compiler/compile.test.js +29 -7
  18. package/dist/compiler/jsdoc-types.d.ts +9 -3
  19. package/dist/compiler/jsdoc-types.d.ts.map +1 -1
  20. package/dist/compiler/jsdoc-types.js +15 -11
  21. package/dist/compiler/output-structure/locale-modules.d.ts.map +1 -1
  22. package/dist/compiler/output-structure/locale-modules.js +5 -8
  23. package/dist/compiler/runtime/assert-is-locale.js +1 -1
  24. package/dist/compiler/runtime/create-runtime.d.ts +3 -4
  25. package/dist/compiler/runtime/create-runtime.d.ts.map +1 -1
  26. package/dist/compiler/runtime/create-runtime.js +28 -11
  27. package/dist/compiler/runtime/de-localize-path.d.ts +2 -2
  28. package/dist/compiler/runtime/de-localize-path.d.ts.map +1 -1
  29. package/dist/compiler/runtime/de-localize-path.js +25 -6
  30. package/dist/compiler/runtime/de-localize-path.test.js +83 -21
  31. package/dist/compiler/runtime/de-localized-path.d.ts +27 -0
  32. package/dist/compiler/runtime/de-localized-path.d.ts.map +1 -0
  33. package/dist/compiler/runtime/de-localized-path.js +32 -0
  34. package/dist/compiler/runtime/de-localized-path.test.d.ts +2 -0
  35. package/dist/compiler/runtime/de-localized-path.test.d.ts.map +1 -0
  36. package/dist/compiler/runtime/de-localized-path.test.js +48 -0
  37. package/dist/compiler/runtime/detect-locale-from-request.d.ts +22 -0
  38. package/dist/compiler/runtime/detect-locale-from-request.d.ts.map +1 -0
  39. package/dist/compiler/runtime/detect-locale-from-request.js +44 -0
  40. package/dist/compiler/runtime/e2e.test.d.ts +2 -0
  41. package/dist/compiler/runtime/e2e.test.d.ts.map +1 -0
  42. package/dist/compiler/runtime/e2e.test.js +33 -0
  43. package/dist/compiler/runtime/extract-locale-from-cookie.js +1 -1
  44. package/dist/compiler/runtime/extract-locale-from-pathname.d.ts.map +1 -1
  45. package/dist/compiler/runtime/extract-locale-from-pathname.js +19 -3
  46. package/dist/compiler/runtime/extract-locale-from-pathname.test.js +83 -0
  47. package/dist/compiler/runtime/extract-locale-from-request.d.ts.map +1 -1
  48. package/dist/compiler/runtime/extract-locale-from-request.js +2 -4
  49. package/dist/compiler/runtime/extract-locale-from-request.test.js +5 -0
  50. package/dist/compiler/runtime/get-locale-from-path.d.ts +13 -0
  51. package/dist/compiler/runtime/get-locale-from-path.d.ts.map +1 -0
  52. package/dist/compiler/runtime/get-locale-from-path.js +17 -0
  53. package/dist/compiler/runtime/get-locale-from-path.test.d.ts +2 -0
  54. package/dist/compiler/runtime/get-locale-from-path.test.d.ts.map +1 -0
  55. package/dist/compiler/runtime/get-locale-from-path.test.js +22 -0
  56. package/dist/compiler/runtime/get-locale.d.ts.map +1 -1
  57. package/dist/compiler/runtime/get-locale.js +7 -5
  58. package/dist/compiler/runtime/get-locale.test.js +2 -2
  59. package/dist/compiler/runtime/is-locale.js +1 -1
  60. package/dist/compiler/runtime/jsdoc-runtime.d.ts +2 -0
  61. package/dist/compiler/runtime/jsdoc-runtime.d.ts.map +1 -0
  62. package/dist/compiler/runtime/jsdoc-runtime.js +131 -0
  63. package/dist/compiler/runtime/locale-in-path.d.ts +13 -0
  64. package/dist/compiler/runtime/locale-in-path.d.ts.map +1 -0
  65. package/dist/compiler/runtime/locale-in-path.js +17 -0
  66. package/dist/compiler/runtime/locale-in-path.test.d.ts +2 -0
  67. package/dist/compiler/runtime/locale-in-path.test.d.ts.map +1 -0
  68. package/dist/compiler/runtime/locale-in-path.test.js +22 -0
  69. package/dist/compiler/runtime/localize-path.d.ts +2 -2
  70. package/dist/compiler/runtime/localize-path.d.ts.map +1 -1
  71. package/dist/compiler/runtime/localize-path.js +61 -13
  72. package/dist/compiler/runtime/localize-path.test.js +192 -20
  73. package/dist/compiler/runtime/localized-path.d.ts +32 -0
  74. package/dist/compiler/runtime/localized-path.d.ts.map +1 -0
  75. package/dist/compiler/runtime/localized-path.js +44 -0
  76. package/dist/compiler/runtime/localized-path.test.d.ts +2 -0
  77. package/dist/compiler/runtime/localized-path.test.d.ts.map +1 -0
  78. package/dist/compiler/runtime/localized-path.test.js +42 -0
  79. package/dist/compiler/runtime/mock-runtime.d.ts +6 -0
  80. package/dist/compiler/runtime/mock-runtime.d.ts.map +1 -0
  81. package/dist/compiler/runtime/mock-runtime.js +31 -0
  82. package/dist/compiler/runtime/path-to-regexp.d.ts +2 -0
  83. package/dist/compiler/runtime/path-to-regexp.d.ts.map +1 -0
  84. package/dist/compiler/runtime/path-to-regexp.js +1 -0
  85. package/dist/compiler/runtime/pathname-pattern.d.ts +30 -0
  86. package/dist/compiler/runtime/pathname-pattern.d.ts.map +1 -0
  87. package/dist/compiler/runtime/pathname-pattern.js +99 -0
  88. package/dist/compiler/runtime/pathname-pattern.test.d.ts +2 -0
  89. package/dist/compiler/runtime/pathname-pattern.test.d.ts.map +1 -0
  90. package/dist/compiler/runtime/pathname-pattern.test.js +103 -0
  91. package/dist/compiler/runtime/set-locale.d.ts.map +1 -1
  92. package/dist/compiler/runtime/set-locale.js +5 -5
  93. package/dist/compiler/runtime/set-locale.test.js +1 -1
  94. package/dist/compiler/runtime/ts-runtime.d.ts +2 -0
  95. package/dist/compiler/runtime/ts-runtime.d.ts.map +1 -0
  96. package/dist/compiler/runtime/ts-runtime.js +119 -0
  97. package/dist/compiler/runtime/type.d.ts +2 -2
  98. package/dist/compiler/runtime/type.d.ts.map +1 -1
  99. package/dist/compiler/runtime/type.test.js +48 -11
  100. package/dist/compiler/runtime/variables.d.ts +46 -0
  101. package/dist/compiler/runtime/variables.d.ts.map +1 -0
  102. package/dist/compiler/runtime/variables.js +45 -0
  103. package/dist/compiler/strategy.d.ts +13 -0
  104. package/dist/compiler/strategy.d.ts.map +1 -0
  105. package/dist/compiler/strategy.js +12 -0
  106. package/dist/compiler/strategy.test.d.ts +2 -0
  107. package/dist/compiler/strategy.test.d.ts.map +1 -0
  108. package/dist/compiler/strategy.test.js +9 -0
  109. package/dist/path-to-regexp/index.d.ts +12 -0
  110. package/dist/path-to-regexp/index.d.ts.map +1 -0
  111. package/dist/path-to-regexp/index.js +11 -0
  112. package/dist/services/env-variables/index.js +1 -1
  113. package/dist/services/file-handling/write-output.d.ts +6 -1
  114. package/dist/services/file-handling/write-output.d.ts.map +1 -1
  115. package/dist/services/file-handling/write-output.js +33 -19
  116. package/dist/services/file-handling/write-output.test.js +60 -11
  117. package/dist/urlpattern-polyfill/index.d.ts +2 -0
  118. package/dist/urlpattern-polyfill/index.d.ts.map +1 -0
  119. package/dist/urlpattern-polyfill/index.js +1 -0
  120. package/package.json +12 -8
@@ -1,4 +1,6 @@
1
+ import { assertIsLocale } from "./assert-is-locale.js";
1
2
  import { isLocale } from "./is-locale.js";
3
+ import { baseLocale, pathnameBase, pathnames, TREE_SHAKE_IS_DEFAULT_PATHNAMES, } from "./variables.js";
2
4
  /**
3
5
  * Extracts the locale from a given pathname.
4
6
  *
@@ -11,9 +13,23 @@ import { isLocale } from "./is-locale.js";
11
13
  * @returns {Locale|undefined} The extracted locale, or undefined if no locale is found.
12
14
  */
13
15
  export function extractLocaleFromPathname(pathname) {
14
- const [, maybeLocale] = pathname.split("/");
15
- if (isLocale(maybeLocale)) {
16
- return maybeLocale;
16
+ let path = pathnameBase
17
+ ? pathname.replace(pathnameBase, "") || "/"
18
+ : pathname;
19
+ // optimization to avoid loading the path-to-regexp library
20
+ // which saves around 2kb gzipped
21
+ if (TREE_SHAKE_IS_DEFAULT_PATHNAMES) {
22
+ const [, maybeLocale] = path.split("/");
23
+ return isLocale(maybeLocale) && maybeLocale !== baseLocale
24
+ ? maybeLocale
25
+ : baseLocale;
26
+ }
27
+ for (const patterns of Object.values(pathnames)) {
28
+ for (const [locale, localizedPattern] of Object.entries(patterns)) {
29
+ if (pathToRegexp.match(localizedPattern)(path)) {
30
+ return assertIsLocale(locale);
31
+ }
32
+ }
17
33
  }
18
34
  return undefined;
19
35
  }
@@ -4,6 +4,14 @@ test("returns the locale from the path", async () => {
4
4
  const runtime = await createRuntimeForTesting({
5
5
  baseLocale: "en",
6
6
  locales: ["en", "en-US"],
7
+ compilerOptions: {
8
+ pathnames: {
9
+ "/{*path}": {
10
+ en: "/en{/*path}",
11
+ "en-US": "/en-US{/*path}",
12
+ },
13
+ },
14
+ },
7
15
  });
8
16
  const path = "/en-US/about";
9
17
  const locale = runtime.extractLocaleFromPathname(path);
@@ -13,8 +21,83 @@ test("returns undefined if isLocale is false", async () => {
13
21
  const runtime = await createRuntimeForTesting({
14
22
  baseLocale: "en",
15
23
  locales: ["en"],
24
+ compilerOptions: {
25
+ pathnames: {
26
+ "/{*path}": {
27
+ en: "/en{/*path}",
28
+ },
29
+ },
30
+ },
16
31
  });
17
32
  const path = "/en-US/about";
18
33
  const locale = runtime.extractLocaleFromPathname(path);
19
34
  expect(locale).toBe(undefined);
20
35
  });
36
+ test("works for static paths", async () => {
37
+ const runtime = await createRuntimeForTesting({
38
+ baseLocale: "en",
39
+ locales: ["en", "de"],
40
+ compilerOptions: {
41
+ pathnames: {
42
+ "/about": {
43
+ en: "/about",
44
+ de: "/ueber-uns",
45
+ },
46
+ },
47
+ },
48
+ });
49
+ expect(runtime.extractLocaleFromPathname("/about")).toBe("en");
50
+ expect(runtime.extractLocaleFromPathname("/ueber-uns")).toBe("de");
51
+ });
52
+ test("works for default pathnames", async () => {
53
+ const runtime = await createRuntimeForTesting({
54
+ baseLocale: "en",
55
+ locales: ["en", "de"],
56
+ compilerOptions: {
57
+ // undefined auto creates default pathnames
58
+ pathnames: undefined,
59
+ },
60
+ });
61
+ expect(runtime.extractLocaleFromPathname("/")).toBe("en");
62
+ expect(runtime.extractLocaleFromPathname("/de/")).toBe("de");
63
+ // the base path is not prefixed
64
+ expect(runtime.extractLocaleFromPathname("/en")).toBe("en");
65
+ expect(runtime.extractLocaleFromPathname("/about")).toBe("en");
66
+ expect(runtime.extractLocaleFromPathname("/de/about")).toBe("de");
67
+ expect(runtime.extractLocaleFromPathname("/de/about/")).toBe("de");
68
+ expect(runtime.extractLocaleFromPathname("/fr/ueber-uns")).toBe("en");
69
+ });
70
+ test("works with pathnameBase for default pathnames option", async () => {
71
+ const runtime = await createRuntimeForTesting({
72
+ baseLocale: "en",
73
+ locales: ["en", "de"],
74
+ compilerOptions: {
75
+ pathnameBase: "/base",
76
+ },
77
+ });
78
+ expect(runtime.extractLocaleFromPathname("/base")).toBe("en");
79
+ expect(runtime.extractLocaleFromPathname("/base/de/")).toBe("de");
80
+ expect(runtime.extractLocaleFromPathname("/base/de/about")).toBe("de");
81
+ expect(runtime.extractLocaleFromPathname("/base/de/about/")).toBe("de");
82
+ expect(runtime.extractLocaleFromPathname("/base/fr/ueber-uns")).toBe("en");
83
+ });
84
+ test("works with pathnameBase for matching pathnames option", async () => {
85
+ const runtime = await createRuntimeForTesting({
86
+ baseLocale: "en",
87
+ locales: ["en", "de"],
88
+ compilerOptions: {
89
+ pathnameBase: "/base",
90
+ pathnames: {
91
+ "/{*path}": {
92
+ de: "/de{/*path}",
93
+ en: "/{*path}",
94
+ },
95
+ },
96
+ },
97
+ });
98
+ expect(runtime.extractLocaleFromPathname("/base")).toBe("en");
99
+ expect(runtime.extractLocaleFromPathname("/base/de/")).toBe("de");
100
+ expect(runtime.extractLocaleFromPathname("/base/de/about")).toBe("de");
101
+ expect(runtime.extractLocaleFromPathname("/base/de/about/")).toBe("de");
102
+ expect(runtime.extractLocaleFromPathname("/base/fr/ueber-uns")).toBe("en");
103
+ });
@@ -1 +1 @@
1
- {"version":3,"file":"extract-locale-from-request.d.ts","sourceRoot":"","sources":["../../../src/compiler/runtime/extract-locale-from-request.js"],"names":[],"mappings":"AAMA;;;;;;;GAOG;AACH,uCAFU,CAAC,OAAO,EAAE,OAAO,KAAK,MAAM,CA6BpC"}
1
+ {"version":3,"file":"extract-locale-from-request.d.ts","sourceRoot":"","sources":["../../../src/compiler/runtime/extract-locale-from-request.js"],"names":[],"mappings":"AAIA;;;;;;;GAOG;AACH,uCAFU,CAAC,OAAO,EAAE,OAAO,KAAK,MAAM,CA6BpC"}
@@ -1,8 +1,6 @@
1
1
  import { assertIsLocale } from "./assert-is-locale.js";
2
- import { baseLocale } from "./base-locale.js";
3
- import { cookieName } from "./cookie-name.js";
2
+ import { baseLocale, cookieName, strategy } from "./variables.js";
4
3
  import { extractLocaleFromPathname } from "./extract-locale-from-pathname.js";
5
- import { strategy } from "./strategy.js";
6
4
  /**
7
5
  * Detect a locale from a request.
8
6
  *
@@ -25,7 +23,7 @@ export const extractLocaleFromRequest = (request) => {
25
23
  else if (strat === "pathname") {
26
24
  locale = extractLocaleFromPathname(new URL(request.url).pathname);
27
25
  }
28
- else if (strat === "variable") {
26
+ else if (strat === "globalVariable") {
29
27
  locale = _locale;
30
28
  }
31
29
  else if (strat === "baseLocale") {
@@ -23,6 +23,11 @@ test("returns the locale from the pathname", async () => {
23
23
  locales: ["en"],
24
24
  compilerOptions: {
25
25
  strategy: ["pathname"],
26
+ pathnames: {
27
+ "/{*path}": {
28
+ en: "/en{/*path}",
29
+ },
30
+ },
26
31
  },
27
32
  });
28
33
  const request = new Request("http://example.com/en/home");
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Extracts the locale from a given path.
3
+ *
4
+ * @example
5
+ * const path = '/en/home';
6
+ * const locale = getLocaleFromPath(path);
7
+ * console.log(locale); // 'en'
8
+ *
9
+ * @param {string} path - The path from which to extract the locale.
10
+ * @returns {Locale|undefined} The extracted locale, or undefined if no locale is found.
11
+ */
12
+ export function getLocaleFromPath(path: string): Locale | undefined;
13
+ //# sourceMappingURL=get-locale-from-path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-locale-from-path.d.ts","sourceRoot":"","sources":["../../../src/compiler/runtime/get-locale-from-path.js"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,wCAHW,MAAM,GACJ,MAAM,GAAC,SAAS,CAO5B"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Extracts the locale from a given path.
3
+ *
4
+ * @example
5
+ * const path = '/en/home';
6
+ * const locale = getLocaleFromPath(path);
7
+ * console.log(locale); // 'en'
8
+ *
9
+ * @param {string} path - The path from which to extract the locale.
10
+ * @returns {Locale|undefined} The extracted locale, or undefined if no locale is found.
11
+ */
12
+ export function getLocaleFromPath(path) {
13
+ const [, maybeLocale] = path.split("/");
14
+ if (isLocale(maybeLocale)) {
15
+ return maybeLocale;
16
+ }
17
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=get-locale-from-path.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"get-locale-from-path.test.d.ts","sourceRoot":"","sources":["../../../src/compiler/runtime/get-locale-from-path.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,22 @@
1
+ import { test, expect, vi, describe, afterEach } from "vitest";
2
+ import { getLocaleFromPath } from "./get-locale-from-path.js";
3
+ // sequential to avoid global variable conflicts
4
+ describe.sequential("", () => {
5
+ afterEach(() => {
6
+ vi.resetAllMocks();
7
+ });
8
+ test("returns the locale from the path", () => {
9
+ // @ts-expect-error - global variable definition
10
+ globalThis.isLocale = vi.fn().mockReturnValue(true);
11
+ const path = "/en-US/about";
12
+ const locale = getLocaleFromPath(path);
13
+ expect(locale).toBe("en-US");
14
+ });
15
+ test("returns undefined if isLocale is false", () => {
16
+ // @ts-expect-error - global variable definition
17
+ globalThis.isLocale = vi.fn().mockReturnValue(false);
18
+ const path = "/en-US/about";
19
+ const locale = getLocaleFromPath(path);
20
+ expect(locale).toBe(undefined);
21
+ });
22
+ });
@@ -1 +1 @@
1
- {"version":3,"file":"get-locale.d.ts","sourceRoot":"","sources":["../../../src/compiler/runtime/get-locale.js"],"names":[],"mappings":"AAiBA;;;;;;;;;;;GAWG;AACH,sBAFU,MAAM,MAAM,CA8BpB"}
1
+ {"version":3,"file":"get-locale.d.ts","sourceRoot":"","sources":["../../../src/compiler/runtime/get-locale.js"],"names":[],"mappings":"AAsBA;;;;;;;;;;;GAWG;AACH,sBAFU,MAAM,MAAM,CAmCpB"}
@@ -1,8 +1,7 @@
1
1
  import { assertIsLocale } from "./assert-is-locale.js";
2
- import { baseLocale } from "./base-locale.js";
2
+ import { baseLocale, strategy, TREE_SHAKE_COOKIE_STRATEGY_USED, TREE_SHAKE_PATHNAME_STRATEGY_USED, TREE_SHAKE_GLOBAL_VARIABLE_STRATEGY_USED, } from "./variables.js";
3
3
  import { extractLocaleFromCookie } from "./extract-locale-from-cookie.js";
4
4
  import { extractLocaleFromPathname } from "./extract-locale-from-pathname.js";
5
- import { strategy } from "./strategy.js";
6
5
  /**
7
6
  * This is a fallback to get started with a custom
8
7
  * strategy and avoid type errors.
@@ -29,18 +28,21 @@ export let getLocale = () => {
29
28
  /** @type {string | undefined} */
30
29
  let locale;
31
30
  for (const strat of strategy) {
32
- if (strat === "cookie") {
31
+ if (TREE_SHAKE_COOKIE_STRATEGY_USED && strat === "cookie") {
33
32
  locale = extractLocaleFromCookie();
34
33
  }
35
34
  if (strat === "baseLocale") {
36
35
  locale = baseLocale;
37
36
  }
38
- if (strat === "pathname" &&
37
+ if (TREE_SHAKE_PATHNAME_STRATEGY_USED &&
38
+ strat === "pathname" &&
39
39
  typeof window !== "undefined" &&
40
40
  window.location?.pathname) {
41
41
  locale = extractLocaleFromPathname(window.location.pathname);
42
42
  }
43
- if (strat === "variable" && _locale !== undefined) {
43
+ if (TREE_SHAKE_GLOBAL_VARIABLE_STRATEGY_USED &&
44
+ strat === "globalVariable" &&
45
+ _locale !== undefined) {
44
46
  locale = _locale;
45
47
  }
46
48
  // check if match, else continue loop
@@ -22,7 +22,7 @@ test("doesn't throw when using pathname strategy on the server", async () => {
22
22
  baseLocale,
23
23
  locales: ["en", "de"],
24
24
  compilerOptions: {
25
- strategy: ["pathname", "variable", "baseLocale"],
25
+ strategy: ["pathname", "globalVariable", "baseLocale"],
26
26
  },
27
27
  });
28
28
  expect(() => runtime.getLocale()).not.toThrow();
@@ -33,7 +33,7 @@ test("throws if variable is used without baseLocale as fallback strategy", async
33
33
  baseLocale: "en",
34
34
  locales: ["en", "de"],
35
35
  compilerOptions: {
36
- strategy: ["variable"],
36
+ strategy: ["globalVariable"],
37
37
  },
38
38
  });
39
39
  expect(() => runtime.getLocale()).toThrow();
@@ -1,4 +1,4 @@
1
- import { locales } from "./locales.js";
1
+ import { locales } from "./variables.js";
2
2
  /**
3
3
  * Check if something is an available locale.
4
4
  *
@@ -0,0 +1,2 @@
1
+ export const jsdocRuntime: string;
2
+ //# sourceMappingURL=jsdoc-runtime.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"jsdoc-runtime.d.ts","sourceRoot":"","sources":["../../../src/compiler/runtime/jsdoc-runtime.js"],"names":[],"mappings":"AAaA,kCAyHE"}
@@ -0,0 +1,131 @@
1
+ import fs from "node:fs";
2
+ /**
3
+ * Load a file from the current directory.
4
+ *
5
+ * @param {string} path
6
+ * @returns {string}
7
+ */
8
+ const injectCode = (path) => fs.readFileSync(new URL(path, import.meta.url), "utf-8");
9
+ // to modify the runtime, outcomment the export const jsdocRuntime line
10
+ export const jsdocRuntime = `
11
+
12
+ /**
13
+ * The project's base locale.
14
+ *
15
+ * @example
16
+ * if (locale === baseLocale) {
17
+ * // do something
18
+ * }
19
+ */
20
+ export const baseLocale = "<replace>";
21
+
22
+ /**
23
+ * The project's locales that have been specified in the settings.
24
+ *
25
+ * @example
26
+ * if (locales.includes(userSelectedLocale) === false) {
27
+ * throw new Error('Locale is not available');
28
+ * }
29
+ */
30
+ export const locales = /** @type {const} */ (["<replace>"]);
31
+
32
+ /**
33
+ * This is a default implementation that is almost always
34
+ * overwritten by \`defineGetLocale()\` and \`defineSetLocale()\`.
35
+ *
36
+ * @type {Locale}
37
+ */
38
+ let _locale = baseLocale;
39
+
40
+ /**
41
+ * Define the \`getLocale()\` function.
42
+ *
43
+ * Use this function to define how the locale is resolved. For example,
44
+ * you can resolve the locale from the browser's preferred language,
45
+ * a cookie, env variable, or a user's preference.
46
+ *
47
+ * @example
48
+ * defineGetLocale(() => {
49
+ * // resolve the locale from a cookie. fallback to the base locale.
50
+ * return Cookies.get('locale') ?? baseLocale
51
+ * }
52
+ *
53
+ * @param {() => Locale} fn
54
+ * @type {(fn: () => Locale) => void}
55
+ */
56
+ export const defineGetLocale = (fn) => {
57
+ getLocale = fn;
58
+ };
59
+
60
+ /**
61
+ * Define the \`setLocale()\` function.
62
+ *
63
+ * Use this function to define how the locale is set. For example,
64
+ * modify a cookie, env variable, or a user's preference.
65
+ *
66
+ * @example
67
+ * defineSetLocale((newLocale) => {
68
+ * // set the locale in a cookie
69
+ * return Cookies.set('locale', newLocale)
70
+ * });
71
+ *
72
+ * @param {(newLocale: Locale) => void} fn
73
+ */
74
+ export const defineSetLocale = (fn) => {
75
+ setLocale = fn;
76
+ };
77
+
78
+ /**
79
+ * Get the current locale.
80
+ *
81
+ * @example
82
+ * if (getLocale() === 'de') {
83
+ * console.log('Germany 🇩🇪');
84
+ * } else if (getLocale() === 'nl') {
85
+ * console.log('Netherlands 🇳🇱');
86
+ * }
87
+ *
88
+ * @type {() => Locale}
89
+ */
90
+ export let getLocale =
91
+ /** default implementation likely overwritten by \`defineGetLocale()\` */ () =>
92
+ _locale;
93
+
94
+ /**
95
+ * Set the locale.
96
+ *
97
+ * @example
98
+ * setLocale('en');
99
+ *
100
+ * @param {Locale} newLocale
101
+ * @type {(newLocale: Locale) => void}
102
+ */
103
+ export let setLocale =
104
+ /** default implementation likely overwritten by \`defineSetLocale()\` */ (
105
+ newLocale
106
+ ) => {
107
+ _locale = newLocale;
108
+ };
109
+
110
+ ${injectCode("./is-locale.js")}
111
+
112
+ ${injectCode("./assert-is-locale.js")}
113
+
114
+ ${injectCode("./locale-in-path.js")}
115
+
116
+ ${injectCode("./localize-path.js")}
117
+
118
+ ${injectCode("./de-localize-path.js")}
119
+
120
+ // ------ TYPES ------
121
+
122
+ /**
123
+ * A locale that is available in the project.
124
+ *
125
+ * @example
126
+ * setLocale(request.locale as Locale)
127
+ *
128
+ * @typedef {(typeof locales)[number]} Locale
129
+ */
130
+
131
+ `;
@@ -0,0 +1,13 @@
1
+ /**
2
+ * Extracts the locale from a given path.
3
+ *
4
+ * @example
5
+ * const path = '/en/home';
6
+ * const locale = localeInPath(path);
7
+ * console.log(locale); // 'en'
8
+ *
9
+ * @param {string} path - The path from which to extract the locale.
10
+ * @returns {Locale|undefined} The extracted locale, or undefined if no locale is found.
11
+ */
12
+ export function localeInPath(path: string): Locale | undefined;
13
+ //# sourceMappingURL=locale-in-path.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locale-in-path.d.ts","sourceRoot":"","sources":["../../../src/compiler/runtime/locale-in-path.js"],"names":[],"mappings":"AAAA;;;;;;;;;;GAUG;AACH,mCAHW,MAAM,GACJ,MAAM,GAAC,SAAS,CAO5B"}
@@ -0,0 +1,17 @@
1
+ /**
2
+ * Extracts the locale from a given path.
3
+ *
4
+ * @example
5
+ * const path = '/en/home';
6
+ * const locale = localeInPath(path);
7
+ * console.log(locale); // 'en'
8
+ *
9
+ * @param {string} path - The path from which to extract the locale.
10
+ * @returns {Locale|undefined} The extracted locale, or undefined if no locale is found.
11
+ */
12
+ export function localeInPath(path) {
13
+ const [, maybeLocale] = path.split("/");
14
+ if (isLocale(maybeLocale)) {
15
+ return maybeLocale;
16
+ }
17
+ }
@@ -0,0 +1,2 @@
1
+ export {};
2
+ //# sourceMappingURL=locale-in-path.test.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"locale-in-path.test.d.ts","sourceRoot":"","sources":["../../../src/compiler/runtime/locale-in-path.test.ts"],"names":[],"mappings":""}
@@ -0,0 +1,22 @@
1
+ import { test, expect, vi, describe, afterEach } from "vitest";
2
+ import { localeInPath } from "./locale-in-path.js";
3
+ // sequential to avoid global variable conflicts
4
+ describe.sequential("", () => {
5
+ afterEach(() => {
6
+ vi.resetAllMocks();
7
+ });
8
+ test("returns the locale from the path", () => {
9
+ // @ts-expect-error - global variable definition
10
+ globalThis.isLocale = vi.fn().mockReturnValue(true);
11
+ const path = "/en-US/about";
12
+ const locale = localeInPath(path);
13
+ expect(locale).toBe("en-US");
14
+ });
15
+ test("returns undefined if isLocale is false", () => {
16
+ // @ts-expect-error - global variable definition
17
+ globalThis.isLocale = vi.fn().mockReturnValue(false);
18
+ const path = "/en-US/about";
19
+ const locale = localeInPath(path);
20
+ expect(locale).toBe(undefined);
21
+ });
22
+ });
@@ -21,12 +21,12 @@
21
21
  * @example
22
22
  * <a href={localizePath('/home')}>Home</a>
23
23
  *
24
- * @param {string} path
24
+ * @param {string} pathname
25
25
  * @param {Object} [options] - Optional parameters.
26
26
  * @param {Locale} [options.locale] - The locale to use for the path.
27
27
  * @returns {string}
28
28
  */
29
- export function localizePath(path: string, options?: {
29
+ export function localizePath(pathname: string, options?: {
30
30
  locale?: Locale;
31
31
  }): string;
32
32
  //# sourceMappingURL=localize-path.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"localize-path.d.ts","sourceRoot":"","sources":["../../../src/compiler/runtime/localize-path.js"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,mCALW,MAAM,YAEd;IAAyB,MAAM,GAAvB,MAAM;CACd,GAAU,MAAM,CAgBlB"}
1
+ {"version":3,"file":"localize-path.d.ts","sourceRoot":"","sources":["../../../src/compiler/runtime/localize-path.js"],"names":[],"mappings":"AASA;;;;;;;;;;;;;;;;;;;;;;;;;;;GA2BG;AACH,uCALW,MAAM,YAEd;IAAyB,MAAM,GAAvB,MAAM;CACd,GAAU,MAAM,CAqElB"}
@@ -1,4 +1,4 @@
1
- import { baseLocale } from "./base-locale.js";
1
+ import { baseLocale, pathnameBase, pathnames, TREE_SHAKE_IS_DEFAULT_PATHNAMES, } from "./variables.js";
2
2
  import { getLocale } from "./get-locale.js";
3
3
  import { extractLocaleFromPathname } from "./extract-locale-from-pathname.js";
4
4
  /**
@@ -24,24 +24,72 @@ import { extractLocaleFromPathname } from "./extract-locale-from-pathname.js";
24
24
  * @example
25
25
  * <a href={localizePath('/home')}>Home</a>
26
26
  *
27
- * @param {string} path
27
+ * @param {string} pathname
28
28
  * @param {Object} [options] - Optional parameters.
29
29
  * @param {Locale} [options.locale] - The locale to use for the path.
30
30
  * @returns {string}
31
31
  */
32
- export function localizePath(path, options) {
32
+ export function localizePath(pathname, options) {
33
+ const url = new URL(pathname, "http://y.com");
33
34
  const locale = options?.locale ?? getLocale();
34
- const hasLocale = extractLocaleFromPathname(path);
35
- const pathWithoutLocale = hasLocale
36
- ? "/" + path.split("/").slice(2).join("/")
37
- : path;
38
- if (locale === baseLocale) {
39
- return pathWithoutLocale;
35
+ const pathnameLocale = extractLocaleFromPathname(url.pathname);
36
+ // If the path is already localized, return it as is
37
+ if (pathnameLocale === locale) {
38
+ if (pathnameBase && !url.pathname.startsWith(pathnameBase)) {
39
+ return pathnameBase + pathname + url.search;
40
+ }
41
+ else {
42
+ return pathname + url.search;
43
+ }
40
44
  }
41
- else if (path === "/" || pathWithoutLocale === "/") {
42
- return `/${locale}`;
45
+ // no dynamic matching is needed if the default pathnames are used
46
+ // this is a tree-shaking optimization to avoid loading the path-to-regexp library
47
+ if (TREE_SHAKE_IS_DEFAULT_PATHNAMES) {
48
+ if (locale === baseLocale) {
49
+ let path = url.pathname;
50
+ if (pathnameBase && !path.startsWith(pathnameBase)) {
51
+ path = pathnameBase + path;
52
+ }
53
+ // remove the locale from the path
54
+ if (pathnameLocale) {
55
+ path = path.replace(`/${pathnameLocale}`, "");
56
+ }
57
+ return path + url.search;
58
+ }
59
+ else {
60
+ if (pathnameBase) {
61
+ return (`${pathnameBase}/${locale}${url.pathname.replace(pathnameBase, "")}` +
62
+ url.search);
63
+ }
64
+ return `/${locale}${url.pathname}` + url.search;
65
+ }
43
66
  }
44
- else {
45
- return `/${locale}${pathWithoutLocale}`;
67
+ // dynamic matching is needed
68
+ for (const [pattern, locales] of Object.entries(pathnames)) {
69
+ let path = url.pathname;
70
+ if (pathnameBase && path.startsWith(pathnameBase)) {
71
+ path = path.replace(pathnameBase, "");
72
+ }
73
+ if (pathnameLocale) {
74
+ path = path.replace(`/${pathnameLocale}`, "");
75
+ }
76
+ if (path === "") {
77
+ path = "/";
78
+ }
79
+ const hasMatch = pathToRegexp.match(pattern)(path);
80
+ if (hasMatch) {
81
+ const localizedPattern = /** @type {string} */ (locales[locale]);
82
+ const localizedPath = pathToRegexp.compile(localizedPattern)(hasMatch.params) + url.search;
83
+ if (pathnameBase && localizedPath !== "/") {
84
+ return pathnameBase + localizedPath;
85
+ }
86
+ else if (pathnameBase) {
87
+ return pathnameBase;
88
+ }
89
+ else {
90
+ return localizedPath;
91
+ }
92
+ }
46
93
  }
94
+ throw new Error("No match found for localized path. Refer to the documentation on how to define pathnames.");
47
95
  }