@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.
- package/dist/bundler-plugins/unplugin.d.ts.map +1 -1
- package/dist/bundler-plugins/unplugin.js +10 -3
- package/dist/cli/steps/run-compiler.js +1 -1
- package/dist/compiler/compile-bundle.d.ts.map +1 -1
- package/dist/compiler/compile-bundle.js +9 -4
- package/dist/compiler/compile-bundle.test.js +11 -0
- package/dist/compiler/compile-message.d.ts +0 -3
- package/dist/compiler/compile-message.d.ts.map +1 -1
- package/dist/compiler/compile-message.js +14 -9
- package/dist/compiler/compile-message.test.js +25 -3
- package/dist/compiler/compile-project.d.ts.map +1 -1
- package/dist/compiler/compile-project.js +0 -3
- package/dist/compiler/compile-project.test.js +59 -66
- package/dist/compiler/compile.d.ts +41 -2
- package/dist/compiler/compile.d.ts.map +1 -1
- package/dist/compiler/compile.js +12 -4
- package/dist/compiler/compile.test.js +29 -7
- package/dist/compiler/jsdoc-types.d.ts +9 -3
- package/dist/compiler/jsdoc-types.d.ts.map +1 -1
- package/dist/compiler/jsdoc-types.js +15 -11
- package/dist/compiler/output-structure/locale-modules.d.ts.map +1 -1
- package/dist/compiler/output-structure/locale-modules.js +5 -8
- package/dist/compiler/runtime/assert-is-locale.js +1 -1
- package/dist/compiler/runtime/create-runtime.d.ts +3 -4
- package/dist/compiler/runtime/create-runtime.d.ts.map +1 -1
- package/dist/compiler/runtime/create-runtime.js +28 -11
- package/dist/compiler/runtime/de-localize-path.d.ts +2 -2
- package/dist/compiler/runtime/de-localize-path.d.ts.map +1 -1
- package/dist/compiler/runtime/de-localize-path.js +25 -6
- package/dist/compiler/runtime/de-localize-path.test.js +83 -21
- package/dist/compiler/runtime/de-localized-path.d.ts +27 -0
- package/dist/compiler/runtime/de-localized-path.d.ts.map +1 -0
- package/dist/compiler/runtime/de-localized-path.js +32 -0
- package/dist/compiler/runtime/de-localized-path.test.d.ts +2 -0
- package/dist/compiler/runtime/de-localized-path.test.d.ts.map +1 -0
- package/dist/compiler/runtime/de-localized-path.test.js +48 -0
- package/dist/compiler/runtime/detect-locale-from-request.d.ts +22 -0
- package/dist/compiler/runtime/detect-locale-from-request.d.ts.map +1 -0
- package/dist/compiler/runtime/detect-locale-from-request.js +44 -0
- package/dist/compiler/runtime/e2e.test.d.ts +2 -0
- package/dist/compiler/runtime/e2e.test.d.ts.map +1 -0
- package/dist/compiler/runtime/e2e.test.js +33 -0
- package/dist/compiler/runtime/extract-locale-from-cookie.js +1 -1
- package/dist/compiler/runtime/extract-locale-from-pathname.d.ts.map +1 -1
- package/dist/compiler/runtime/extract-locale-from-pathname.js +19 -3
- package/dist/compiler/runtime/extract-locale-from-pathname.test.js +83 -0
- package/dist/compiler/runtime/extract-locale-from-request.d.ts.map +1 -1
- package/dist/compiler/runtime/extract-locale-from-request.js +2 -4
- package/dist/compiler/runtime/extract-locale-from-request.test.js +5 -0
- package/dist/compiler/runtime/get-locale-from-path.d.ts +13 -0
- package/dist/compiler/runtime/get-locale-from-path.d.ts.map +1 -0
- package/dist/compiler/runtime/get-locale-from-path.js +17 -0
- package/dist/compiler/runtime/get-locale-from-path.test.d.ts +2 -0
- package/dist/compiler/runtime/get-locale-from-path.test.d.ts.map +1 -0
- package/dist/compiler/runtime/get-locale-from-path.test.js +22 -0
- package/dist/compiler/runtime/get-locale.d.ts.map +1 -1
- package/dist/compiler/runtime/get-locale.js +7 -5
- package/dist/compiler/runtime/get-locale.test.js +2 -2
- package/dist/compiler/runtime/is-locale.js +1 -1
- package/dist/compiler/runtime/jsdoc-runtime.d.ts +2 -0
- package/dist/compiler/runtime/jsdoc-runtime.d.ts.map +1 -0
- package/dist/compiler/runtime/jsdoc-runtime.js +131 -0
- package/dist/compiler/runtime/locale-in-path.d.ts +13 -0
- package/dist/compiler/runtime/locale-in-path.d.ts.map +1 -0
- package/dist/compiler/runtime/locale-in-path.js +17 -0
- package/dist/compiler/runtime/locale-in-path.test.d.ts +2 -0
- package/dist/compiler/runtime/locale-in-path.test.d.ts.map +1 -0
- package/dist/compiler/runtime/locale-in-path.test.js +22 -0
- package/dist/compiler/runtime/localize-path.d.ts +2 -2
- package/dist/compiler/runtime/localize-path.d.ts.map +1 -1
- package/dist/compiler/runtime/localize-path.js +61 -13
- package/dist/compiler/runtime/localize-path.test.js +192 -20
- package/dist/compiler/runtime/localized-path.d.ts +32 -0
- package/dist/compiler/runtime/localized-path.d.ts.map +1 -0
- package/dist/compiler/runtime/localized-path.js +44 -0
- package/dist/compiler/runtime/localized-path.test.d.ts +2 -0
- package/dist/compiler/runtime/localized-path.test.d.ts.map +1 -0
- package/dist/compiler/runtime/localized-path.test.js +42 -0
- package/dist/compiler/runtime/mock-runtime.d.ts +6 -0
- package/dist/compiler/runtime/mock-runtime.d.ts.map +1 -0
- package/dist/compiler/runtime/mock-runtime.js +31 -0
- package/dist/compiler/runtime/path-to-regexp.d.ts +2 -0
- package/dist/compiler/runtime/path-to-regexp.d.ts.map +1 -0
- package/dist/compiler/runtime/path-to-regexp.js +1 -0
- package/dist/compiler/runtime/pathname-pattern.d.ts +30 -0
- package/dist/compiler/runtime/pathname-pattern.d.ts.map +1 -0
- package/dist/compiler/runtime/pathname-pattern.js +99 -0
- package/dist/compiler/runtime/pathname-pattern.test.d.ts +2 -0
- package/dist/compiler/runtime/pathname-pattern.test.d.ts.map +1 -0
- package/dist/compiler/runtime/pathname-pattern.test.js +103 -0
- package/dist/compiler/runtime/set-locale.d.ts.map +1 -1
- package/dist/compiler/runtime/set-locale.js +5 -5
- package/dist/compiler/runtime/set-locale.test.js +1 -1
- package/dist/compiler/runtime/ts-runtime.d.ts +2 -0
- package/dist/compiler/runtime/ts-runtime.d.ts.map +1 -0
- package/dist/compiler/runtime/ts-runtime.js +119 -0
- package/dist/compiler/runtime/type.d.ts +2 -2
- package/dist/compiler/runtime/type.d.ts.map +1 -1
- package/dist/compiler/runtime/type.test.js +48 -11
- package/dist/compiler/runtime/variables.d.ts +46 -0
- package/dist/compiler/runtime/variables.d.ts.map +1 -0
- package/dist/compiler/runtime/variables.js +45 -0
- package/dist/compiler/strategy.d.ts +13 -0
- package/dist/compiler/strategy.d.ts.map +1 -0
- package/dist/compiler/strategy.js +12 -0
- package/dist/compiler/strategy.test.d.ts +2 -0
- package/dist/compiler/strategy.test.d.ts.map +1 -0
- package/dist/compiler/strategy.test.js +9 -0
- package/dist/path-to-regexp/index.d.ts +12 -0
- package/dist/path-to-regexp/index.d.ts.map +1 -0
- package/dist/path-to-regexp/index.js +11 -0
- package/dist/services/env-variables/index.js +1 -1
- package/dist/services/file-handling/write-output.d.ts +6 -1
- package/dist/services/file-handling/write-output.d.ts.map +1 -1
- package/dist/services/file-handling/write-output.js +33 -19
- package/dist/services/file-handling/write-output.test.js +60 -11
- package/dist/urlpattern-polyfill/index.d.ts +2 -0
- package/dist/urlpattern-polyfill/index.d.ts.map +1 -0
- package/dist/urlpattern-polyfill/index.js +1 -0
- 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
|
-
|
|
15
|
-
|
|
16
|
-
|
|
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":"
|
|
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 "./
|
|
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 === "
|
|
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 @@
|
|
|
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":"
|
|
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 "./
|
|
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 (
|
|
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 (
|
|
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", "
|
|
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: ["
|
|
36
|
+
strategy: ["globalVariable"],
|
|
37
37
|
},
|
|
38
38
|
});
|
|
39
39
|
expect(() => runtime.getLocale()).toThrow();
|
|
@@ -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 @@
|
|
|
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}
|
|
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(
|
|
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":"
|
|
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 "./
|
|
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}
|
|
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(
|
|
32
|
+
export function localizePath(pathname, options) {
|
|
33
|
+
const url = new URL(pathname, "http://y.com");
|
|
33
34
|
const locale = options?.locale ?? getLocale();
|
|
34
|
-
const
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
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
|
-
|
|
42
|
-
|
|
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
|
-
|
|
45
|
-
|
|
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
|
}
|