@better-translate/tanstack-router 1.0.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.
- package/LICENSE +21 -0
- package/README.md +5 -0
- package/dist/chunk-LRCKROLX.js +194 -0
- package/dist/index.cjs +206 -0
- package/dist/index.d.cts +22 -0
- package/dist/index.d.ts +22 -0
- package/dist/index.js +16 -0
- package/dist/navigation.cjs +400 -0
- package/dist/navigation.d.cts +46 -0
- package/dist/navigation.d.ts +46 -0
- package/dist/navigation.js +232 -0
- package/dist/server.cjs +121 -0
- package/dist/server.d.cts +30 -0
- package/dist/server.d.ts +30 -0
- package/dist/server.js +98 -0
- package/package.json +67 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Jorge Alvarenga
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
package/README.md
ADDED
|
@@ -0,0 +1,5 @@
|
|
|
1
|
+
# @better-translate/tanstack-router
|
|
2
|
+
|
|
3
|
+
`@better-translate/tanstack-router` adds locale-aware routing and navigation helpers for TanStack Router and TanStack Start. Use it with `@better-translate/core`, and pair it with `@better-translate/react` when your UI renders translations in React components.
|
|
4
|
+
|
|
5
|
+
Full docs: [better-translate-placeholder.com/en/docs/adapters/tanstack-router](https://better-translate-placeholder.com/en/docs/adapters/tanstack-router)
|
|
@@ -0,0 +1,194 @@
|
|
|
1
|
+
// src/shared.ts
|
|
2
|
+
var DEFAULT_ROUTE_TEMPLATE = "/{-$locale}";
|
|
3
|
+
function hasLocale(locales, value) {
|
|
4
|
+
return locales.includes(value);
|
|
5
|
+
}
|
|
6
|
+
function defineRouting(config) {
|
|
7
|
+
const routeTemplate = config.routeTemplate ?? DEFAULT_ROUTE_TEMPLATE;
|
|
8
|
+
validateRouting({
|
|
9
|
+
...config,
|
|
10
|
+
routeTemplate
|
|
11
|
+
});
|
|
12
|
+
return Object.freeze({
|
|
13
|
+
locales: [...config.locales],
|
|
14
|
+
defaultLocale: config.defaultLocale,
|
|
15
|
+
routeTemplate
|
|
16
|
+
});
|
|
17
|
+
}
|
|
18
|
+
function normalizePathname(pathname) {
|
|
19
|
+
if (!pathname) {
|
|
20
|
+
return "/";
|
|
21
|
+
}
|
|
22
|
+
return pathname.startsWith("/") ? pathname : `/${pathname}`;
|
|
23
|
+
}
|
|
24
|
+
function getPathnameLocale(pathname, routing) {
|
|
25
|
+
return analyzePathname(pathname, routing).explicitLocale;
|
|
26
|
+
}
|
|
27
|
+
function isPathnameInScope(pathname, routing) {
|
|
28
|
+
return analyzePathname(pathname, routing).inScope;
|
|
29
|
+
}
|
|
30
|
+
function stripLocaleFromPathname(pathname, routing) {
|
|
31
|
+
const analyzed = analyzePathname(pathname, routing);
|
|
32
|
+
return analyzed.inScope ? analyzed.deLocalizedPathname : normalizePathname(pathname);
|
|
33
|
+
}
|
|
34
|
+
function localizePathname(pathname, locale, routing) {
|
|
35
|
+
const normalizedPathname = normalizePathname(pathname);
|
|
36
|
+
const deLocalizedPathname = stripLocaleFromPathname(
|
|
37
|
+
normalizedPathname,
|
|
38
|
+
routing
|
|
39
|
+
);
|
|
40
|
+
if (!isPathnameInScope(deLocalizedPathname, routing)) {
|
|
41
|
+
return normalizedPathname;
|
|
42
|
+
}
|
|
43
|
+
const parsedTemplate = parseRouteTemplate(routing.routeTemplate);
|
|
44
|
+
if (!parsedTemplate.isRequired && locale === routing.defaultLocale) {
|
|
45
|
+
return deLocalizedPathname;
|
|
46
|
+
}
|
|
47
|
+
const pathnameSegments = splitPathname(deLocalizedPathname);
|
|
48
|
+
const localizedSegments = [...pathnameSegments];
|
|
49
|
+
localizedSegments.splice(parsedTemplate.localeSegmentIndex, 0, locale);
|
|
50
|
+
return joinPathname(localizedSegments);
|
|
51
|
+
}
|
|
52
|
+
function splitHrefString(href) {
|
|
53
|
+
const hashIndex = href.indexOf("#");
|
|
54
|
+
const searchIndex = href.indexOf("?");
|
|
55
|
+
const pathnameEnd = hashIndex === -1 ? searchIndex === -1 ? href.length : searchIndex : searchIndex === -1 ? hashIndex : Math.min(searchIndex, hashIndex);
|
|
56
|
+
const pathname = href.slice(0, pathnameEnd) || "/";
|
|
57
|
+
const search = searchIndex === -1 ? "" : href.slice(searchIndex, hashIndex === -1 ? href.length : hashIndex);
|
|
58
|
+
const hash = hashIndex === -1 ? "" : href.slice(hashIndex);
|
|
59
|
+
return {
|
|
60
|
+
hash,
|
|
61
|
+
pathname: normalizePathname(pathname),
|
|
62
|
+
search
|
|
63
|
+
};
|
|
64
|
+
}
|
|
65
|
+
function isAbsoluteHref(href) {
|
|
66
|
+
return /^[a-zA-Z][a-zA-Z\d+\-.]*:/.test(href) || href.startsWith("//");
|
|
67
|
+
}
|
|
68
|
+
function parseRouteTemplate(routeTemplate) {
|
|
69
|
+
const normalizedRouteTemplate = normalizePathname(
|
|
70
|
+
routeTemplate ?? DEFAULT_ROUTE_TEMPLATE
|
|
71
|
+
);
|
|
72
|
+
const localizedSegments = splitPathname(normalizedRouteTemplate);
|
|
73
|
+
let localeSegmentIndex = -1;
|
|
74
|
+
let localeParamName = "";
|
|
75
|
+
let isRequired = false;
|
|
76
|
+
for (let index = 0; index < localizedSegments.length; index += 1) {
|
|
77
|
+
const segment = localizedSegments[index];
|
|
78
|
+
const localeMatch = /^\{(-?)\$([a-zA-Z_$][a-zA-Z0-9_$]*)\}$/.exec(segment);
|
|
79
|
+
if (localeMatch) {
|
|
80
|
+
if (localeSegmentIndex !== -1) {
|
|
81
|
+
throw new Error(
|
|
82
|
+
`Route template "${normalizedRouteTemplate}" must contain exactly one locale segment.`
|
|
83
|
+
);
|
|
84
|
+
}
|
|
85
|
+
localeSegmentIndex = index;
|
|
86
|
+
localeParamName = localeMatch[2];
|
|
87
|
+
isRequired = localeMatch[1] !== "-";
|
|
88
|
+
continue;
|
|
89
|
+
}
|
|
90
|
+
if (looksDynamic(segment)) {
|
|
91
|
+
throw new Error(
|
|
92
|
+
`Route template "${normalizedRouteTemplate}" can only contain one locale segment like "{-$locale}" or "{$locale}" plus static path segments.`
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
if (localeSegmentIndex === -1) {
|
|
97
|
+
throw new Error(
|
|
98
|
+
`Route template "${normalizedRouteTemplate}" must contain one locale segment like "{-$locale}" or "{$locale}".`
|
|
99
|
+
);
|
|
100
|
+
}
|
|
101
|
+
const deLocalizedSegments = localizedSegments.filter(
|
|
102
|
+
(_, index) => index !== localeSegmentIndex
|
|
103
|
+
);
|
|
104
|
+
return {
|
|
105
|
+
deLocalizedSegments,
|
|
106
|
+
isRequired,
|
|
107
|
+
localeParamName,
|
|
108
|
+
localeSegment: localizedSegments[localeSegmentIndex],
|
|
109
|
+
localeSegmentIndex,
|
|
110
|
+
localizedSegments,
|
|
111
|
+
routeTemplate: normalizedRouteTemplate
|
|
112
|
+
};
|
|
113
|
+
}
|
|
114
|
+
function validateRouting(config) {
|
|
115
|
+
if (config.locales.length === 0) {
|
|
116
|
+
throw new Error("defineRouting(...) requires at least one locale.");
|
|
117
|
+
}
|
|
118
|
+
if (!config.locales.includes(config.defaultLocale)) {
|
|
119
|
+
throw new Error(
|
|
120
|
+
`Default locale "${config.defaultLocale}" must be included in locales.`
|
|
121
|
+
);
|
|
122
|
+
}
|
|
123
|
+
parseRouteTemplate(config.routeTemplate);
|
|
124
|
+
const localeSet = /* @__PURE__ */ new Set();
|
|
125
|
+
for (const locale of config.locales) {
|
|
126
|
+
if (localeSet.has(locale)) {
|
|
127
|
+
throw new Error(`Duplicate locale "${locale}" found in routing config.`);
|
|
128
|
+
}
|
|
129
|
+
localeSet.add(locale);
|
|
130
|
+
}
|
|
131
|
+
}
|
|
132
|
+
function analyzePathname(pathname, routing) {
|
|
133
|
+
const parsedTemplate = parseRouteTemplate(routing.routeTemplate);
|
|
134
|
+
const pathnameSegments = splitPathname(pathname);
|
|
135
|
+
let explicitLocale;
|
|
136
|
+
let localePathIndex = -1;
|
|
137
|
+
let pathnameIndex = 0;
|
|
138
|
+
for (let templateIndex = 0; templateIndex < parsedTemplate.localizedSegments.length; templateIndex += 1) {
|
|
139
|
+
if (templateIndex === parsedTemplate.localeSegmentIndex) {
|
|
140
|
+
const maybeLocale = pathnameSegments[pathnameIndex];
|
|
141
|
+
if (maybeLocale && hasLocale(routing.locales, maybeLocale)) {
|
|
142
|
+
explicitLocale = maybeLocale;
|
|
143
|
+
localePathIndex = pathnameIndex;
|
|
144
|
+
pathnameIndex += 1;
|
|
145
|
+
}
|
|
146
|
+
continue;
|
|
147
|
+
}
|
|
148
|
+
const templateSegment = parsedTemplate.localizedSegments[templateIndex];
|
|
149
|
+
const pathnameSegment = pathnameSegments[pathnameIndex];
|
|
150
|
+
if (pathnameSegment !== templateSegment) {
|
|
151
|
+
return {
|
|
152
|
+
deLocalizedPathname: normalizePathname(pathname),
|
|
153
|
+
explicitLocale: void 0,
|
|
154
|
+
inScope: false
|
|
155
|
+
};
|
|
156
|
+
}
|
|
157
|
+
pathnameIndex += 1;
|
|
158
|
+
}
|
|
159
|
+
if (localePathIndex === -1) {
|
|
160
|
+
return {
|
|
161
|
+
deLocalizedPathname: joinPathname(pathnameSegments),
|
|
162
|
+
explicitLocale: void 0,
|
|
163
|
+
inScope: true
|
|
164
|
+
};
|
|
165
|
+
}
|
|
166
|
+
const deLocalizedSegments = [...pathnameSegments];
|
|
167
|
+
deLocalizedSegments.splice(localePathIndex, 1);
|
|
168
|
+
return {
|
|
169
|
+
deLocalizedPathname: joinPathname(deLocalizedSegments),
|
|
170
|
+
explicitLocale,
|
|
171
|
+
inScope: true
|
|
172
|
+
};
|
|
173
|
+
}
|
|
174
|
+
function looksDynamic(segment) {
|
|
175
|
+
return segment.startsWith("[") || segment.startsWith("$") || segment.includes("{") || segment.includes("}");
|
|
176
|
+
}
|
|
177
|
+
function splitPathname(pathname) {
|
|
178
|
+
return normalizePathname(pathname).split("/").filter(Boolean);
|
|
179
|
+
}
|
|
180
|
+
function joinPathname(segments) {
|
|
181
|
+
return segments.length === 0 ? "/" : `/${segments.join("/")}`;
|
|
182
|
+
}
|
|
183
|
+
|
|
184
|
+
export {
|
|
185
|
+
hasLocale,
|
|
186
|
+
defineRouting,
|
|
187
|
+
getPathnameLocale,
|
|
188
|
+
isPathnameInScope,
|
|
189
|
+
stripLocaleFromPathname,
|
|
190
|
+
localizePathname,
|
|
191
|
+
splitHrefString,
|
|
192
|
+
isAbsoluteHref,
|
|
193
|
+
parseRouteTemplate
|
|
194
|
+
};
|
package/dist/index.cjs
ADDED
|
@@ -0,0 +1,206 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __defProp = Object.defineProperty;
|
|
3
|
+
var __getOwnPropDesc = Object.getOwnPropertyDescriptor;
|
|
4
|
+
var __getOwnPropNames = Object.getOwnPropertyNames;
|
|
5
|
+
var __hasOwnProp = Object.prototype.hasOwnProperty;
|
|
6
|
+
var __export = (target, all) => {
|
|
7
|
+
for (var name in all)
|
|
8
|
+
__defProp(target, name, { get: all[name], enumerable: true });
|
|
9
|
+
};
|
|
10
|
+
var __copyProps = (to, from, except, desc) => {
|
|
11
|
+
if (from && typeof from === "object" || typeof from === "function") {
|
|
12
|
+
for (let key of __getOwnPropNames(from))
|
|
13
|
+
if (!__hasOwnProp.call(to, key) && key !== except)
|
|
14
|
+
__defProp(to, key, { get: () => from[key], enumerable: !(desc = __getOwnPropDesc(from, key)) || desc.enumerable });
|
|
15
|
+
}
|
|
16
|
+
return to;
|
|
17
|
+
};
|
|
18
|
+
var __toCommonJS = (mod) => __copyProps(__defProp({}, "__esModule", { value: true }), mod);
|
|
19
|
+
|
|
20
|
+
// src/index.ts
|
|
21
|
+
var index_exports = {};
|
|
22
|
+
__export(index_exports, {
|
|
23
|
+
defineRouting: () => defineRouting,
|
|
24
|
+
getPathnameLocale: () => getPathnameLocale,
|
|
25
|
+
hasLocale: () => hasLocale,
|
|
26
|
+
isPathnameInScope: () => isPathnameInScope,
|
|
27
|
+
localizePathname: () => localizePathname,
|
|
28
|
+
stripLocaleFromPathname: () => stripLocaleFromPathname
|
|
29
|
+
});
|
|
30
|
+
module.exports = __toCommonJS(index_exports);
|
|
31
|
+
|
|
32
|
+
// src/shared.ts
|
|
33
|
+
var DEFAULT_ROUTE_TEMPLATE = "/{-$locale}";
|
|
34
|
+
function hasLocale(locales, value) {
|
|
35
|
+
return locales.includes(value);
|
|
36
|
+
}
|
|
37
|
+
function defineRouting(config) {
|
|
38
|
+
const routeTemplate = config.routeTemplate ?? DEFAULT_ROUTE_TEMPLATE;
|
|
39
|
+
validateRouting({
|
|
40
|
+
...config,
|
|
41
|
+
routeTemplate
|
|
42
|
+
});
|
|
43
|
+
return Object.freeze({
|
|
44
|
+
locales: [...config.locales],
|
|
45
|
+
defaultLocale: config.defaultLocale,
|
|
46
|
+
routeTemplate
|
|
47
|
+
});
|
|
48
|
+
}
|
|
49
|
+
function normalizePathname(pathname) {
|
|
50
|
+
if (!pathname) {
|
|
51
|
+
return "/";
|
|
52
|
+
}
|
|
53
|
+
return pathname.startsWith("/") ? pathname : `/${pathname}`;
|
|
54
|
+
}
|
|
55
|
+
function getPathnameLocale(pathname, routing) {
|
|
56
|
+
return analyzePathname(pathname, routing).explicitLocale;
|
|
57
|
+
}
|
|
58
|
+
function isPathnameInScope(pathname, routing) {
|
|
59
|
+
return analyzePathname(pathname, routing).inScope;
|
|
60
|
+
}
|
|
61
|
+
function stripLocaleFromPathname(pathname, routing) {
|
|
62
|
+
const analyzed = analyzePathname(pathname, routing);
|
|
63
|
+
return analyzed.inScope ? analyzed.deLocalizedPathname : normalizePathname(pathname);
|
|
64
|
+
}
|
|
65
|
+
function localizePathname(pathname, locale, routing) {
|
|
66
|
+
const normalizedPathname = normalizePathname(pathname);
|
|
67
|
+
const deLocalizedPathname = stripLocaleFromPathname(
|
|
68
|
+
normalizedPathname,
|
|
69
|
+
routing
|
|
70
|
+
);
|
|
71
|
+
if (!isPathnameInScope(deLocalizedPathname, routing)) {
|
|
72
|
+
return normalizedPathname;
|
|
73
|
+
}
|
|
74
|
+
const parsedTemplate = parseRouteTemplate(routing.routeTemplate);
|
|
75
|
+
if (!parsedTemplate.isRequired && locale === routing.defaultLocale) {
|
|
76
|
+
return deLocalizedPathname;
|
|
77
|
+
}
|
|
78
|
+
const pathnameSegments = splitPathname(deLocalizedPathname);
|
|
79
|
+
const localizedSegments = [...pathnameSegments];
|
|
80
|
+
localizedSegments.splice(parsedTemplate.localeSegmentIndex, 0, locale);
|
|
81
|
+
return joinPathname(localizedSegments);
|
|
82
|
+
}
|
|
83
|
+
function parseRouteTemplate(routeTemplate) {
|
|
84
|
+
const normalizedRouteTemplate = normalizePathname(
|
|
85
|
+
routeTemplate ?? DEFAULT_ROUTE_TEMPLATE
|
|
86
|
+
);
|
|
87
|
+
const localizedSegments = splitPathname(normalizedRouteTemplate);
|
|
88
|
+
let localeSegmentIndex = -1;
|
|
89
|
+
let localeParamName = "";
|
|
90
|
+
let isRequired = false;
|
|
91
|
+
for (let index = 0; index < localizedSegments.length; index += 1) {
|
|
92
|
+
const segment = localizedSegments[index];
|
|
93
|
+
const localeMatch = /^\{(-?)\$([a-zA-Z_$][a-zA-Z0-9_$]*)\}$/.exec(segment);
|
|
94
|
+
if (localeMatch) {
|
|
95
|
+
if (localeSegmentIndex !== -1) {
|
|
96
|
+
throw new Error(
|
|
97
|
+
`Route template "${normalizedRouteTemplate}" must contain exactly one locale segment.`
|
|
98
|
+
);
|
|
99
|
+
}
|
|
100
|
+
localeSegmentIndex = index;
|
|
101
|
+
localeParamName = localeMatch[2];
|
|
102
|
+
isRequired = localeMatch[1] !== "-";
|
|
103
|
+
continue;
|
|
104
|
+
}
|
|
105
|
+
if (looksDynamic(segment)) {
|
|
106
|
+
throw new Error(
|
|
107
|
+
`Route template "${normalizedRouteTemplate}" can only contain one locale segment like "{-$locale}" or "{$locale}" plus static path segments.`
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
if (localeSegmentIndex === -1) {
|
|
112
|
+
throw new Error(
|
|
113
|
+
`Route template "${normalizedRouteTemplate}" must contain one locale segment like "{-$locale}" or "{$locale}".`
|
|
114
|
+
);
|
|
115
|
+
}
|
|
116
|
+
const deLocalizedSegments = localizedSegments.filter(
|
|
117
|
+
(_, index) => index !== localeSegmentIndex
|
|
118
|
+
);
|
|
119
|
+
return {
|
|
120
|
+
deLocalizedSegments,
|
|
121
|
+
isRequired,
|
|
122
|
+
localeParamName,
|
|
123
|
+
localeSegment: localizedSegments[localeSegmentIndex],
|
|
124
|
+
localeSegmentIndex,
|
|
125
|
+
localizedSegments,
|
|
126
|
+
routeTemplate: normalizedRouteTemplate
|
|
127
|
+
};
|
|
128
|
+
}
|
|
129
|
+
function validateRouting(config) {
|
|
130
|
+
if (config.locales.length === 0) {
|
|
131
|
+
throw new Error("defineRouting(...) requires at least one locale.");
|
|
132
|
+
}
|
|
133
|
+
if (!config.locales.includes(config.defaultLocale)) {
|
|
134
|
+
throw new Error(
|
|
135
|
+
`Default locale "${config.defaultLocale}" must be included in locales.`
|
|
136
|
+
);
|
|
137
|
+
}
|
|
138
|
+
parseRouteTemplate(config.routeTemplate);
|
|
139
|
+
const localeSet = /* @__PURE__ */ new Set();
|
|
140
|
+
for (const locale of config.locales) {
|
|
141
|
+
if (localeSet.has(locale)) {
|
|
142
|
+
throw new Error(`Duplicate locale "${locale}" found in routing config.`);
|
|
143
|
+
}
|
|
144
|
+
localeSet.add(locale);
|
|
145
|
+
}
|
|
146
|
+
}
|
|
147
|
+
function analyzePathname(pathname, routing) {
|
|
148
|
+
const parsedTemplate = parseRouteTemplate(routing.routeTemplate);
|
|
149
|
+
const pathnameSegments = splitPathname(pathname);
|
|
150
|
+
let explicitLocale;
|
|
151
|
+
let localePathIndex = -1;
|
|
152
|
+
let pathnameIndex = 0;
|
|
153
|
+
for (let templateIndex = 0; templateIndex < parsedTemplate.localizedSegments.length; templateIndex += 1) {
|
|
154
|
+
if (templateIndex === parsedTemplate.localeSegmentIndex) {
|
|
155
|
+
const maybeLocale = pathnameSegments[pathnameIndex];
|
|
156
|
+
if (maybeLocale && hasLocale(routing.locales, maybeLocale)) {
|
|
157
|
+
explicitLocale = maybeLocale;
|
|
158
|
+
localePathIndex = pathnameIndex;
|
|
159
|
+
pathnameIndex += 1;
|
|
160
|
+
}
|
|
161
|
+
continue;
|
|
162
|
+
}
|
|
163
|
+
const templateSegment = parsedTemplate.localizedSegments[templateIndex];
|
|
164
|
+
const pathnameSegment = pathnameSegments[pathnameIndex];
|
|
165
|
+
if (pathnameSegment !== templateSegment) {
|
|
166
|
+
return {
|
|
167
|
+
deLocalizedPathname: normalizePathname(pathname),
|
|
168
|
+
explicitLocale: void 0,
|
|
169
|
+
inScope: false
|
|
170
|
+
};
|
|
171
|
+
}
|
|
172
|
+
pathnameIndex += 1;
|
|
173
|
+
}
|
|
174
|
+
if (localePathIndex === -1) {
|
|
175
|
+
return {
|
|
176
|
+
deLocalizedPathname: joinPathname(pathnameSegments),
|
|
177
|
+
explicitLocale: void 0,
|
|
178
|
+
inScope: true
|
|
179
|
+
};
|
|
180
|
+
}
|
|
181
|
+
const deLocalizedSegments = [...pathnameSegments];
|
|
182
|
+
deLocalizedSegments.splice(localePathIndex, 1);
|
|
183
|
+
return {
|
|
184
|
+
deLocalizedPathname: joinPathname(deLocalizedSegments),
|
|
185
|
+
explicitLocale,
|
|
186
|
+
inScope: true
|
|
187
|
+
};
|
|
188
|
+
}
|
|
189
|
+
function looksDynamic(segment) {
|
|
190
|
+
return segment.startsWith("[") || segment.startsWith("$") || segment.includes("{") || segment.includes("}");
|
|
191
|
+
}
|
|
192
|
+
function splitPathname(pathname) {
|
|
193
|
+
return normalizePathname(pathname).split("/").filter(Boolean);
|
|
194
|
+
}
|
|
195
|
+
function joinPathname(segments) {
|
|
196
|
+
return segments.length === 0 ? "/" : `/${segments.join("/")}`;
|
|
197
|
+
}
|
|
198
|
+
// Annotate the CommonJS export names for ESM import in node:
|
|
199
|
+
0 && (module.exports = {
|
|
200
|
+
defineRouting,
|
|
201
|
+
getPathnameLocale,
|
|
202
|
+
hasLocale,
|
|
203
|
+
isPathnameInScope,
|
|
204
|
+
localizePathname,
|
|
205
|
+
stripLocaleFromPathname
|
|
206
|
+
});
|
package/dist/index.d.cts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
interface RoutingConfig<TLocale extends string> {
|
|
2
|
+
locales: readonly TLocale[];
|
|
3
|
+
defaultLocale: TLocale;
|
|
4
|
+
routeTemplate?: string;
|
|
5
|
+
}
|
|
6
|
+
type DefinedRouting<TLocale extends string, TDefaultLocale extends TLocale = TLocale> = Readonly<{
|
|
7
|
+
locales: readonly TLocale[];
|
|
8
|
+
defaultLocale: TDefaultLocale;
|
|
9
|
+
routeTemplate: string;
|
|
10
|
+
}>;
|
|
11
|
+
declare function hasLocale<TLocale extends string>(locales: readonly TLocale[], value: string): value is TLocale;
|
|
12
|
+
declare function defineRouting<const TLocales extends readonly string[], const TDefaultLocale extends TLocales[number]>(config: {
|
|
13
|
+
locales: TLocales;
|
|
14
|
+
defaultLocale: TDefaultLocale;
|
|
15
|
+
routeTemplate?: string;
|
|
16
|
+
}): DefinedRouting<TLocales[number], TDefaultLocale>;
|
|
17
|
+
declare function getPathnameLocale<TLocale extends string>(pathname: string, routing: RoutingConfig<TLocale>): TLocale | undefined;
|
|
18
|
+
declare function isPathnameInScope<TLocale extends string>(pathname: string, routing: RoutingConfig<TLocale>): boolean;
|
|
19
|
+
declare function stripLocaleFromPathname<TLocale extends string>(pathname: string, routing: RoutingConfig<TLocale>): string;
|
|
20
|
+
declare function localizePathname<TLocale extends string>(pathname: string, locale: TLocale, routing: RoutingConfig<TLocale>): string;
|
|
21
|
+
|
|
22
|
+
export { type DefinedRouting, type RoutingConfig, defineRouting, getPathnameLocale, hasLocale, isPathnameInScope, localizePathname, stripLocaleFromPathname };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
interface RoutingConfig<TLocale extends string> {
|
|
2
|
+
locales: readonly TLocale[];
|
|
3
|
+
defaultLocale: TLocale;
|
|
4
|
+
routeTemplate?: string;
|
|
5
|
+
}
|
|
6
|
+
type DefinedRouting<TLocale extends string, TDefaultLocale extends TLocale = TLocale> = Readonly<{
|
|
7
|
+
locales: readonly TLocale[];
|
|
8
|
+
defaultLocale: TDefaultLocale;
|
|
9
|
+
routeTemplate: string;
|
|
10
|
+
}>;
|
|
11
|
+
declare function hasLocale<TLocale extends string>(locales: readonly TLocale[], value: string): value is TLocale;
|
|
12
|
+
declare function defineRouting<const TLocales extends readonly string[], const TDefaultLocale extends TLocales[number]>(config: {
|
|
13
|
+
locales: TLocales;
|
|
14
|
+
defaultLocale: TDefaultLocale;
|
|
15
|
+
routeTemplate?: string;
|
|
16
|
+
}): DefinedRouting<TLocales[number], TDefaultLocale>;
|
|
17
|
+
declare function getPathnameLocale<TLocale extends string>(pathname: string, routing: RoutingConfig<TLocale>): TLocale | undefined;
|
|
18
|
+
declare function isPathnameInScope<TLocale extends string>(pathname: string, routing: RoutingConfig<TLocale>): boolean;
|
|
19
|
+
declare function stripLocaleFromPathname<TLocale extends string>(pathname: string, routing: RoutingConfig<TLocale>): string;
|
|
20
|
+
declare function localizePathname<TLocale extends string>(pathname: string, locale: TLocale, routing: RoutingConfig<TLocale>): string;
|
|
21
|
+
|
|
22
|
+
export { type DefinedRouting, type RoutingConfig, defineRouting, getPathnameLocale, hasLocale, isPathnameInScope, localizePathname, stripLocaleFromPathname };
|
package/dist/index.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import {
|
|
2
|
+
defineRouting,
|
|
3
|
+
getPathnameLocale,
|
|
4
|
+
hasLocale,
|
|
5
|
+
isPathnameInScope,
|
|
6
|
+
localizePathname,
|
|
7
|
+
stripLocaleFromPathname
|
|
8
|
+
} from "./chunk-LRCKROLX.js";
|
|
9
|
+
export {
|
|
10
|
+
defineRouting,
|
|
11
|
+
getPathnameLocale,
|
|
12
|
+
hasLocale,
|
|
13
|
+
isPathnameInScope,
|
|
14
|
+
localizePathname,
|
|
15
|
+
stripLocaleFromPathname
|
|
16
|
+
};
|