@inlang/paraglide-js 2.0.0-beta.20 → 2.0.0-beta.21

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 (53) hide show
  1. package/dist/bundler-plugins/rollup.d.ts +1 -1
  2. package/dist/bundler-plugins/rollup.d.ts.map +1 -1
  3. package/dist/bundler-plugins/unplugin.d.ts.map +1 -1
  4. package/dist/bundler-plugins/unplugin.js +10 -17
  5. package/dist/compiler/compile-bundle.d.ts.map +1 -1
  6. package/dist/compiler/compile-bundle.js +9 -21
  7. package/dist/compiler/compile-bundle.test.js +62 -39
  8. package/dist/compiler/compile-message.d.ts.map +1 -1
  9. package/dist/compiler/compile-message.js +5 -2
  10. package/dist/compiler/compile-message.test.js +23 -0
  11. package/dist/compiler/compile-project.test.js +26 -0
  12. package/dist/compiler/compile.d.ts +6 -3
  13. package/dist/compiler/compile.d.ts.map +1 -1
  14. package/dist/compiler/compile.js +6 -2
  15. package/dist/compiler/compile.test.js +6 -2
  16. package/dist/compiler/compiler-options.d.ts +1 -1
  17. package/dist/compiler/compiler-options.js +1 -1
  18. package/dist/compiler/output-structure/locale-modules.d.ts.map +1 -1
  19. package/dist/compiler/output-structure/locale-modules.js +6 -5
  20. package/dist/compiler/output-structure/message-modules.d.ts.map +1 -1
  21. package/dist/compiler/output-structure/message-modules.js +37 -24
  22. package/dist/compiler/output-structure/message-modules.test.js +48 -0
  23. package/dist/compiler/runtime/create-runtime.d.ts.map +1 -1
  24. package/dist/compiler/runtime/create-runtime.js +6 -3
  25. package/dist/compiler/runtime/extract-locale-from-url.d.ts +2 -2
  26. package/dist/compiler/runtime/extract-locale-from-url.d.ts.map +1 -1
  27. package/dist/compiler/runtime/extract-locale-from-url.js +24 -2
  28. package/dist/compiler/runtime/extract-locale-from-url.test.js +12 -0
  29. package/dist/compiler/runtime/localize-href.d.ts +63 -27
  30. package/dist/compiler/runtime/localize-href.d.ts.map +1 -1
  31. package/dist/compiler/runtime/localize-href.js +64 -38
  32. package/dist/compiler/runtime/localize-url.d.ts +80 -8
  33. package/dist/compiler/runtime/localize-url.d.ts.map +1 -1
  34. package/dist/compiler/runtime/localize-url.js +146 -16
  35. package/dist/compiler/runtime/localize-url.test.js +84 -0
  36. package/dist/compiler/runtime/server-middleware.d.ts +1 -3
  37. package/dist/compiler/runtime/server-middleware.d.ts.map +1 -1
  38. package/dist/compiler/runtime/server-middleware.js +1 -3
  39. package/dist/compiler/runtime/variables.d.ts +1 -0
  40. package/dist/compiler/runtime/variables.d.ts.map +1 -1
  41. package/dist/compiler/runtime/variables.js +1 -0
  42. package/dist/compiler/safe-module-id.d.ts +8 -0
  43. package/dist/compiler/safe-module-id.d.ts.map +1 -0
  44. package/dist/compiler/safe-module-id.js +71 -0
  45. package/dist/compiler/safe-module-id.test.d.ts +2 -0
  46. package/dist/compiler/safe-module-id.test.d.ts.map +1 -0
  47. package/dist/compiler/safe-module-id.test.js +27 -0
  48. package/dist/services/env-variables/index.js +1 -1
  49. package/dist/services/file-handling/write-output.d.ts +1 -1
  50. package/dist/services/file-handling/write-output.d.ts.map +1 -1
  51. package/dist/services/file-handling/write-output.js +1 -1
  52. package/dist/services/file-handling/write-output.test.js +2 -1
  53. package/package.json +3 -3
@@ -37,3 +37,51 @@ test("should emit per locale message files", () => {
37
37
  expect(output).toHaveProperty("messages/happy_elephant/de.js");
38
38
  expect(output).toHaveProperty("messages/happy_elephant/index.js");
39
39
  });
40
+ test("handles case senstivity by creating directories and files only in lowercase", () => {
41
+ const resources = [
42
+ {
43
+ bundle: {
44
+ code: "export const HappyElephant = () => en.HappyElephant",
45
+ node: {
46
+ id: "HappyElephant",
47
+ },
48
+ },
49
+ messages: {
50
+ en: {
51
+ code: 'export const HappyElephant = () => "HappyElephant0"',
52
+ node: {},
53
+ },
54
+ },
55
+ },
56
+ {
57
+ bundle: {
58
+ code: "export const happyelephant = () => en.happyelephant",
59
+ node: {
60
+ id: "happyelephant",
61
+ },
62
+ },
63
+ messages: {
64
+ en: {
65
+ code: 'export const happyelephant = () => "happyelephant1"',
66
+ node: {},
67
+ },
68
+ },
69
+ },
70
+ ];
71
+ const settings = {
72
+ locales: ["en"],
73
+ baseLocale: "en",
74
+ };
75
+ const output = generateMessageModules(resources, settings, {}, defaultCompilerOptions);
76
+ // expecting only lowercase directories and files
77
+ expect(output).toHaveProperty("messages/happyelephant/en.js");
78
+ expect(output).toHaveProperty("messages/happyelephant/index.js");
79
+ expect(output).not.toHaveProperty("messages/HappyElephant/en.js");
80
+ expect(output).not.toHaveProperty("messages/HappyElephant/index.js");
81
+ // expecting both bundles to be merged into the "happyelephant" module
82
+ expect(output["messages/happyelephant/index.js"]).includes(`export const happyelephant = () => en.happyelephant`);
83
+ expect(output["messages/happyelephant/index.js"]).includes(`export const HappyElephant = () => en.HappyElephant`);
84
+ // expecting both messages to be in their respective files
85
+ expect(output["messages/happyelephant/en.js"]).includes(`export const HappyElephant = () => "HappyElephant0"`);
86
+ expect(output["messages/happyelephant/en.js"]).includes(`export const HappyElephant = () => "HappyElephant0"`);
87
+ });
@@ -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,CA0FT;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;;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"}
@@ -5,8 +5,10 @@ import { defaultCompilerOptions, } from "../compiler-options.js";
5
5
  */
6
6
  export function createRuntimeFile(args) {
7
7
  const urlPatterns = args.compilerOptions.urlPatterns ?? [];
8
+ let defaultUrlPatternUsed = false;
8
9
  // add default urlPatterns for a good out of the box experience
9
10
  if (args.compilerOptions.urlPatterns === undefined) {
11
+ defaultUrlPatternUsed = true;
10
12
  urlPatterns.push({
11
13
  pattern: `:protocol://:domain(.*)::port?/:locale(${args.locales.filter((l) => l !== args.baseLocale).join("|")})?/:path(.*)?`,
12
14
  deLocalizedNamedGroups: { locale: null },
@@ -17,18 +19,19 @@ export function createRuntimeFile(args) {
17
19
  });
18
20
  }
19
21
  const code = `
20
- import "@inlang/paraglide-js/urlpattern-polyfill";
22
+ ${defaultUrlPatternUsed ? "/** @type {any} */\nconst URLPattern = {}" : `import "@inlang/paraglide-js/urlpattern-polyfill";`}
21
23
 
22
24
  ${injectCode("./variables.js")
23
25
  .replace(`export const baseLocale = "en";`, `export const baseLocale = "${args.baseLocale}";`)
24
26
  .replace(`export const locales = /** @type {const} */ (["en", "de"]);`, `export const locales = /** @type {const} */ (["${args.locales.join('", "')}"]);`)
25
- .replace(`export const strategy = ["globalVariable"];`, `export const strategy = ["${args.compilerOptions.strategy.join('", "')}"]`)
27
+ .replace(`export const strategy = ["globalVariable"];`, `export const strategy = ${JSON.stringify(args.compilerOptions.strategy, null, 2)};`)
26
28
  .replace(`<cookie-name>`, `${args.compilerOptions.cookieName}`)
27
29
  .replace(`export const TREE_SHAKE_COOKIE_STRATEGY_USED = false;`, `const TREE_SHAKE_COOKIE_STRATEGY_USED = ${args.compilerOptions.strategy.includes("cookie")};`)
28
30
  .replace(`export const TREE_SHAKE_URL_STRATEGY_USED = false;`, `const TREE_SHAKE_URL_STRATEGY_USED = ${args.compilerOptions.strategy.includes("url")};`)
29
31
  .replace(`export const TREE_SHAKE_GLOBAL_VARIABLE_STRATEGY_USED = false;`, `const TREE_SHAKE_GLOBAL_VARIABLE_STRATEGY_USED = ${args.compilerOptions.strategy.includes("globalVariable")};`)
30
32
  .replace(`export const TREE_SHAKE_PREFERRED_LANGUAGE_STRATEGY_USED = false;`, `const TREE_SHAKE_PREFERRED_LANGUAGE_STRATEGY_USED = ${args.compilerOptions.strategy.includes("preferredLanguage")};`)
31
- .replace(`export const urlPatterns = [];`, `export const urlPatterns = ${JSON.stringify(urlPatterns, null, 2)};`)}
33
+ .replace(`export const urlPatterns = [];`, `export const urlPatterns = ${JSON.stringify(urlPatterns, null, 2)};`)
34
+ .replace(`export const TREE_SHAKE_DEFAULT_URL_PATTERN_USED = false;`, `const TREE_SHAKE_DEFAULT_URL_PATTERN_USED = ${defaultUrlPatternUsed};`)}
32
35
 
33
36
  ${injectCode("./get-locale.js")}
34
37
 
@@ -1,8 +1,8 @@
1
1
  /**
2
2
  * Extracts the locale from a given URL using native URLPattern.
3
3
  *
4
- * @param {string} url - The full URL from which to extract the locale.
4
+ * @param {URL|string} url - The full URL from which to extract the locale.
5
5
  * @returns {Locale|undefined} The extracted locale, or undefined if no locale is found.
6
6
  */
7
- export function extractLocaleFromUrl(url: string): Locale | undefined;
7
+ export function extractLocaleFromUrl(url: URL | string): Locale | undefined;
8
8
  //# sourceMappingURL=extract-locale-from-url.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"extract-locale-from-url.d.ts","sourceRoot":"","sources":["../../../src/compiler/runtime/extract-locale-from-url.js"],"names":[],"mappings":"AAIA;;;;;GAKG;AACH,0CAHW,MAAM,GACJ,MAAM,GAAC,SAAS,CA+C5B"}
1
+ {"version":3,"file":"extract-locale-from-url.d.ts","sourceRoot":"","sources":["../../../src/compiler/runtime/extract-locale-from-url.js"],"names":[],"mappings":"AASA;;;;;GAKG;AACH,0CAHW,GAAG,GAAC,MAAM,GACR,MAAM,GAAC,SAAS,CAkD5B"}
@@ -1,13 +1,17 @@
1
1
  import { assertIsLocale } from "./assert-is-locale.js";
2
+ import { isLocale } from "./is-locale.js";
2
3
  import { aggregateGroups } from "./localize-url.js";
3
- import { urlPatterns } from "./variables.js";
4
+ import { baseLocale, TREE_SHAKE_DEFAULT_URL_PATTERN_USED, urlPatterns, } from "./variables.js";
4
5
  /**
5
6
  * Extracts the locale from a given URL using native URLPattern.
6
7
  *
7
- * @param {string} url - The full URL from which to extract the locale.
8
+ * @param {URL|string} url - The full URL from which to extract the locale.
8
9
  * @returns {Locale|undefined} The extracted locale, or undefined if no locale is found.
9
10
  */
10
11
  export function extractLocaleFromUrl(url) {
12
+ if (TREE_SHAKE_DEFAULT_URL_PATTERN_USED) {
13
+ return defaultUrlPatternExtractLocale(url);
14
+ }
11
15
  for (const element of urlPatterns) {
12
16
  const pattern = new URLPattern(element.pattern);
13
17
  const match = pattern.exec(url);
@@ -46,3 +50,21 @@ export function extractLocaleFromUrl(url) {
46
50
  }
47
51
  return undefined;
48
52
  }
53
+ /**
54
+ * https://github.com/opral/inlang-paraglide-js/issues/381
55
+ *
56
+ * @param {URL|string} url - The full URL from which to extract the locale.
57
+ * @returns {Locale|undefined} The extracted locale, or undefined if no locale is found.
58
+ */
59
+ function defaultUrlPatternExtractLocale(url) {
60
+ const urlObj = new URL(url, "http://dummy.com");
61
+ const pathSegments = urlObj.pathname.split("/").filter(Boolean);
62
+ if (pathSegments.length > 0) {
63
+ const potentialLocale = pathSegments[0];
64
+ if (isLocale(potentialLocale)) {
65
+ return potentialLocale;
66
+ }
67
+ }
68
+ // everything else has to be the base locale
69
+ return baseLocale;
70
+ }
@@ -87,3 +87,15 @@ test("regex works", async () => {
87
87
  expect(extractLocaleFromUrl(`https://example.com/de/subpage`)).toBe("de");
88
88
  expect(extractLocaleFromUrl(`https://example.com/subpage`)).toBe("en");
89
89
  });
90
+ test("default url pattern", async () => {
91
+ const r = await createRuntimeForTesting({
92
+ baseLocale: "en",
93
+ locales: ["en", "de"],
94
+ });
95
+ expect(r.extractLocaleFromUrl("https://example.com/")).toBe("en");
96
+ expect(r.extractLocaleFromUrl("https://example.com/de")).toBe("de");
97
+ // anyhing other than a valid locale must be the base locale
98
+ expect(r.extractLocaleFromUrl("https://example.com/fr")).toBe("en");
99
+ expect(r.extractLocaleFromUrl("https://example.com/optional-subpage")).toBe("en");
100
+ expect(r.extractLocaleFromUrl("https://example.com/de/optional-subpage")).toBe("de");
101
+ });
@@ -1,46 +1,82 @@
1
1
  /**
2
- * Localizes an href.
2
+ * High-level URL localization function optimized for client-side UI usage.
3
3
  *
4
- * In contrast to `localizeUrl()`, this function automatically
5
- * calls `getLocale()` to determine the target locale and
6
- * returns a relative path if appropriate.
4
+ * This is a convenience wrapper around `localizeUrl()` that provides features
5
+ * needed in UI:
6
+ *
7
+ * - Accepts relative paths (e.g., "/about")
8
+ * - Returns relative paths when possible
9
+ * - Automatically detects current locale if not specified
10
+ * - Handles string input/output instead of URL objects
7
11
  *
8
12
  * @example
9
- * localizeHref("/about")
10
- * // => "/de/about"
13
+ * ```typescript
14
+ * // In a React/Vue/Svelte component
15
+ * const NavLink = ({ href }) => {
16
+ * // Automatically uses current locale, keeps path relative
17
+ * return <a href={localizeHref(href)}>...</a>;
18
+ * };
19
+ *
20
+ * // Examples:
21
+ * localizeHref("/about")
22
+ * // => "/de/about" (if current locale is "de")
23
+ * localizeHref("/store", { locale: "fr" })
24
+ * // => "/fr/store" (explicit locale)
11
25
  *
12
- * // requires full URL and locale
13
- * localizeUrl("http://example.com/about", { locale: "de" })
14
- * // => "http://example.com/de/about"
26
+ * // Cross-origin links remain absolute
27
+ * localizeHref("https://other-site.com/about")
28
+ * // => "https://other-site.com/de/about"
29
+ * ```
15
30
  *
16
- * @param {string} href
17
- * @param {Object} [options] - Options
18
- * @param {string} [options.locale] - The target locale.
31
+ * For server-side URL localization (e.g., in middleware), use `localizeUrl()`
32
+ * which provides more precise control over URL handling.
33
+ *
34
+ * @param {string} href - The href to localize (can be relative or absolute)
35
+ * @param {Object} [options] - Options for localization
36
+ * @param {string} [options.locale] - Target locale. If not provided, uses `getLocale()`
37
+ * @returns {string} The localized href, relative if input was relative
19
38
  */
20
39
  export function localizeHref(href: string, options?: {
21
40
  locale?: string | undefined;
22
41
  }): string;
23
42
  /**
24
- * De-localizes an href.
43
+ * High-level URL de-localization function optimized for client-side UI usage.
44
+ *
45
+ * This is a convenience wrapper around `deLocalizeUrl()` that provides features
46
+ * needed in the UI:
25
47
  *
26
- * In contrast to `deLocalizeUrl()`, this function automatically
27
- * calls `getLocale()` to determine the base locale and
28
- * returns a relative path if appropriate.
48
+ * - Accepts relative paths (e.g., "/de/about")
49
+ * - Returns relative paths when possible
50
+ * - Handles string input/output instead of URL objects
29
51
  *
30
52
  * @example
31
- * deLocalizeHref("/de/about")
32
- * // => "/about"
53
+ * ```typescript
54
+ * // In a React/Vue/Svelte component
55
+ * const LocaleSwitcher = ({ href }) => {
56
+ * // Remove locale prefix before switching
57
+ * const baseHref = deLocalizeHref(href);
58
+ * return locales.map(locale =>
59
+ * <a href={localizeHref(baseHref, { locale })}>
60
+ * Switch to {locale}
61
+ * </a>
62
+ * );
63
+ * };
33
64
  *
34
- * // requires full URL and locale
35
- * deLocalizeUrl("http://example.com/de/about")
36
- * // => "http://example.com/about"
65
+ * // Examples:
66
+ * deLocalizeHref("/de/about") // => "/about"
67
+ * deLocalizeHref("/fr/store") // => "/store"
37
68
  *
38
- * @param {string} href
39
- * @returns {string} - The de-localized href.
69
+ * // Cross-origin links remain absolute
70
+ * deLocalizeHref("https://example.com/de/about")
71
+ * // => "https://example.com/about"
72
+ * ```
73
+ *
74
+ * For server-side URL de-localization (e.g., in middleware), use `deLocalizeUrl()`
75
+ * which provides more precise control over URL handling.
76
+ *
77
+ * @param {string} href - The href to de-localize (can be relative or absolute)
78
+ * @returns {string} The de-localized href, relative if input was relative
79
+ * @see deLocalizeUrl - For low-level URL de-localization in server contexts
40
80
  */
41
81
  export function deLocalizeHref(href: string): string;
42
- export function localizePath(href: string, options?: {
43
- locale?: string;
44
- }): string;
45
- export function deLocalizePath(href: string): string;
46
82
  //# sourceMappingURL=localize-href.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"localize-href.d.ts","sourceRoot":"","sources":["../../../src/compiler/runtime/localize-href.js"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;GAkBG;AACH,mCAJW,MAAM,YAEd;IAAyB,MAAM;CACjC,UAqBA;AAED;;;;;;;;;;;;;;;;;GAiBG;AACH,qCAHW,MAAM,GACJ,MAAM,CAclB;AAIS,mCAAO,MAAM,YAAY;IAAE,MAAM,CAAC,EAAE,MAAM,CAAA;CAAE,GAAK,MAAM,CAAA;AAQvD,qCAAO,MAAM,GAAK,MAAM,CAAA"}
1
+ {"version":3,"file":"localize-href.d.ts","sourceRoot":"","sources":["../../../src/compiler/runtime/localize-href.js"],"names":[],"mappings":"AAIA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAqCG;AACH,mCALW,MAAM,YAEd;IAAyB,MAAM;CAC/B,GAAU,MAAM,CAsBlB;AAED;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAsCG;AACH,qCAJW,MAAM,GACJ,MAAM,CAelB"}
@@ -2,28 +2,47 @@ import { getLocale } from "./get-locale.js";
2
2
  import { getUrlOrigin } from "./get-url-origin.js";
3
3
  import { deLocalizeUrl, localizeUrl } from "./localize-url.js";
4
4
  /**
5
- * Localizes an href.
5
+ * High-level URL localization function optimized for client-side UI usage.
6
6
  *
7
- * In contrast to `localizeUrl()`, this function automatically
8
- * calls `getLocale()` to determine the target locale and
9
- * returns a relative path if appropriate.
7
+ * This is a convenience wrapper around `localizeUrl()` that provides features
8
+ * needed in UI:
9
+ *
10
+ * - Accepts relative paths (e.g., "/about")
11
+ * - Returns relative paths when possible
12
+ * - Automatically detects current locale if not specified
13
+ * - Handles string input/output instead of URL objects
10
14
  *
11
15
  * @example
12
- * localizeHref("/about")
13
- * // => "/de/about"
16
+ * ```typescript
17
+ * // In a React/Vue/Svelte component
18
+ * const NavLink = ({ href }) => {
19
+ * // Automatically uses current locale, keeps path relative
20
+ * return <a href={localizeHref(href)}>...</a>;
21
+ * };
22
+ *
23
+ * // Examples:
24
+ * localizeHref("/about")
25
+ * // => "/de/about" (if current locale is "de")
26
+ * localizeHref("/store", { locale: "fr" })
27
+ * // => "/fr/store" (explicit locale)
28
+ *
29
+ * // Cross-origin links remain absolute
30
+ * localizeHref("https://other-site.com/about")
31
+ * // => "https://other-site.com/de/about"
32
+ * ```
14
33
  *
15
- * // requires full URL and locale
16
- * localizeUrl("http://example.com/about", { locale: "de" })
17
- * // => "http://example.com/de/about"
34
+ * For server-side URL localization (e.g., in middleware), use `localizeUrl()`
35
+ * which provides more precise control over URL handling.
18
36
  *
19
- * @param {string} href
20
- * @param {Object} [options] - Options
21
- * @param {string} [options.locale] - The target locale.
37
+ * @param {string} href - The href to localize (can be relative or absolute)
38
+ * @param {Object} [options] - Options for localization
39
+ * @param {string} [options.locale] - Target locale. If not provided, uses `getLocale()`
40
+ * @returns {string} The localized href, relative if input was relative
22
41
  */
23
42
  export function localizeHref(href, options) {
24
43
  const locale = options?.locale ?? getLocale();
25
44
  const url = new URL(href, getUrlOrigin());
26
- const localized = localizeUrl(url, { locale });
45
+ const localized = localizeUrl(url, options);
27
46
  // if the origin is identical and the href is relative,
28
47
  // return the relative path
29
48
  if (href.startsWith("/") && url.origin === localized.origin) {
@@ -39,22 +58,43 @@ export function localizeHref(href, options) {
39
58
  return localized.href;
40
59
  }
41
60
  /**
42
- * De-localizes an href.
61
+ * High-level URL de-localization function optimized for client-side UI usage.
43
62
  *
44
- * In contrast to `deLocalizeUrl()`, this function automatically
45
- * calls `getLocale()` to determine the base locale and
46
- * returns a relative path if appropriate.
63
+ * This is a convenience wrapper around `deLocalizeUrl()` that provides features
64
+ * needed in the UI:
65
+ *
66
+ * - Accepts relative paths (e.g., "/de/about")
67
+ * - Returns relative paths when possible
68
+ * - Handles string input/output instead of URL objects
47
69
  *
48
70
  * @example
49
- * deLocalizeHref("/de/about")
50
- * // => "/about"
71
+ * ```typescript
72
+ * // In a React/Vue/Svelte component
73
+ * const LocaleSwitcher = ({ href }) => {
74
+ * // Remove locale prefix before switching
75
+ * const baseHref = deLocalizeHref(href);
76
+ * return locales.map(locale =>
77
+ * <a href={localizeHref(baseHref, { locale })}>
78
+ * Switch to {locale}
79
+ * </a>
80
+ * );
81
+ * };
82
+ *
83
+ * // Examples:
84
+ * deLocalizeHref("/de/about") // => "/about"
85
+ * deLocalizeHref("/fr/store") // => "/store"
86
+ *
87
+ * // Cross-origin links remain absolute
88
+ * deLocalizeHref("https://example.com/de/about")
89
+ * // => "https://example.com/about"
90
+ * ```
51
91
  *
52
- * // requires full URL and locale
53
- * deLocalizeUrl("http://example.com/de/about")
54
- * // => "http://example.com/about"
92
+ * For server-side URL de-localization (e.g., in middleware), use `deLocalizeUrl()`
93
+ * which provides more precise control over URL handling.
55
94
  *
56
- * @param {string} href
57
- * @returns {string} - The de-localized href.
95
+ * @param {string} href - The href to de-localize (can be relative or absolute)
96
+ * @returns {string} The de-localized href, relative if input was relative
97
+ * @see deLocalizeUrl - For low-level URL de-localization in server contexts
58
98
  */
59
99
  export function deLocalizeHref(href) {
60
100
  const url = new URL(href, getUrlOrigin());
@@ -66,17 +106,3 @@ export function deLocalizeHref(href) {
66
106
  }
67
107
  return deLocalized.href;
68
108
  }
69
- /**
70
- * @deprecated use `localizeHref` instead and give feedback on here https://github.com/opral/inlang-paraglide-js/issues/380
71
- * @type {(href: string, options?: { locale?: string }) => string}
72
- */
73
- export function localizePath(href, options) {
74
- return localizeHref(href, options);
75
- }
76
- /**
77
- * @deprecated use `deLocalizeHref` instead and give feedback on here https://github.com/opral/inlang-paraglide-js/issues/380
78
- * @type {(href: string) => string}
79
- */
80
- export function deLocalizePath(href) {
81
- return deLocalizeHref(href);
82
- }
@@ -1,13 +1,85 @@
1
1
  /**
2
- * Localizes a URL to a specific locale using the new namedGroups API.
3
- * @param {string | URL} url - The URL to localize.
4
- * @param {Object} options - Options containing the target locale.
5
- * @param {string} options.locale - The target locale.
6
- * @returns {URL} - The localized URL.
2
+ * Lower-level URL localization function, primarily used in server contexts.
3
+ *
4
+ * This function is designed for server-side usage where you need precise control
5
+ * over URL localization, such as in middleware or request handlers. It works with
6
+ * URL objects and always returns absolute URLs.
7
+ *
8
+ * For client-side UI components, use `localizeHref()` instead, which provides
9
+ * a more convenient API with relative paths and automatic locale detection.
10
+ *
11
+ * @example
12
+ * ```typescript
13
+ * // Server middleware example
14
+ * app.use((req, res, next) => {
15
+ * const url = new URL(req.url, `${req.protocol}://${req.headers.host}`);
16
+ * const localized = localizeUrl(url, { locale: "de" });
17
+ *
18
+ * if (localized.href !== url.href) {
19
+ * return res.redirect(localized.href);
20
+ * }
21
+ * next();
22
+ * });
23
+ * ```
24
+ *
25
+ * @example
26
+ * ```typescript
27
+ * // Using with URL patterns
28
+ * const url = new URL("https://example.com/about");
29
+ * localizeUrl(url, { locale: "de" });
30
+ * // => URL("https://example.com/de/about")
31
+ *
32
+ * // Using with domain-based localization
33
+ * const url = new URL("https://example.com/store");
34
+ * localizeUrl(url, { locale: "de" });
35
+ * // => URL("https://de.example.com/store")
36
+ * ```
37
+ *
38
+ * @param {string | URL} url - The URL to localize. If string, must be absolute.
39
+ * @param {Object} [options] - Options for localization
40
+ * @param {string} [options.locale] - Target locale. If not provided, uses getLocale()
41
+ * @returns {URL} The localized URL, always absolute
7
42
  */
8
- export function localizeUrl(url: string | URL, options: {
9
- locale: string;
43
+ export function localizeUrl(url: string | URL, options?: {
44
+ locale?: string | undefined;
10
45
  }): URL;
46
+ /**
47
+ * Low-level URL de-localization function, primarily used in server contexts.
48
+ *
49
+ * This function is designed for server-side usage where you need precise control
50
+ * over URL de-localization, such as in middleware or request handlers. It works with
51
+ * URL objects and always returns absolute URLs.
52
+ *
53
+ * For client-side UI components, use `deLocalizeHref()` instead, which provides
54
+ * a more convenient API with relative paths.
55
+ *
56
+ * @example
57
+ * ```typescript
58
+ * // Server middleware example
59
+ * app.use((req, res, next) => {
60
+ * const url = new URL(req.url, `${req.protocol}://${req.headers.host}`);
61
+ * const baseUrl = deLocalizeUrl(url);
62
+ *
63
+ * // Store the base URL for later use
64
+ * req.baseUrl = baseUrl;
65
+ * next();
66
+ * });
67
+ * ```
68
+ *
69
+ * @example
70
+ * ```typescript
71
+ * // Using with URL patterns
72
+ * const url = new URL("https://example.com/de/about");
73
+ * deLocalizeUrl(url); // => URL("https://example.com/about")
74
+ *
75
+ * // Using with domain-based localization
76
+ * const url = new URL("https://de.example.com/store");
77
+ * deLocalizeUrl(url); // => URL("https://example.com/store")
78
+ * ```
79
+ *
80
+ * @param {string | URL} url - The URL to de-localize. If string, must be absolute.
81
+ * @returns {URL} The de-localized URL, always absolute
82
+ */
11
83
  export function deLocalizeUrl(url: string | URL): URL;
12
- export function aggregateGroups(match: URLPatternResult): Record<string, string | null | undefined>;
84
+ export function aggregateGroups(match: any): Record<string, string | null | undefined>;
13
85
  //# sourceMappingURL=localize-url.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"localize-url.d.ts","sourceRoot":"","sources":["../../../src/compiler/runtime/localize-url.js"],"names":[],"mappings":"AAEA;;;;;;GAMG;AACH,iCALW,MAAM,GAAG,GAAG,WAEpB;IAAwB,MAAM,EAAtB,MAAM;CACd,GAAU,GAAG,CA6Bf;AAKS,mCAAM,MAAM,GAAG,GAAG,GAAK,GAAG,CAAA;AAyF1B,uCAAQ,gBAAgB,GAAK,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAA"}
1
+ {"version":3,"file":"localize-url.d.ts","sourceRoot":"","sources":["../../../src/compiler/runtime/localize-url.js"],"names":[],"mappings":"AAUA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAyCG;AACH,iCALW,MAAM,GAAG,GAAG,YAEpB;IAAyB,MAAM;CAC/B,GAAU,GAAG,CAoCf;AAuCD;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAoCG;AACH,mCAHW,MAAM,GAAG,GAAG,GACV,GAAG,CAkCf;AAmFS,uCAAQ,GAAG,GAAK,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,GAAG,SAAS,CAAC,CAAA"}