@verbaly/sveltekit 0.47.0 → 0.49.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/README.md +30 -11
- package/dist/index.d.ts +12 -2
- package/dist/index.js +14 -2
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -37,14 +37,14 @@ export default { plugins: [verbaly(), sveltekit()] };
|
|
|
37
37
|
<html lang="%verbaly.lang%" dir="%verbaly.dir%"></html>
|
|
38
38
|
```
|
|
39
39
|
|
|
40
|
-
**3. Server hook**:
|
|
40
|
+
**3. Server hook**: resolves the locale per request:
|
|
41
41
|
|
|
42
42
|
```ts
|
|
43
43
|
// src/hooks.server.ts
|
|
44
44
|
import { verbalyHandle } from '@verbaly/sveltekit';
|
|
45
|
-
import { locales } from 'virtual:verbaly';
|
|
45
|
+
import { locales, routing } from 'virtual:verbaly';
|
|
46
46
|
|
|
47
|
-
export const handle = verbalyHandle({ locales });
|
|
47
|
+
export const handle = verbalyHandle({ locales, routing });
|
|
48
48
|
```
|
|
49
49
|
|
|
50
50
|
```ts
|
|
@@ -56,6 +56,23 @@ declare namespace App {
|
|
|
56
56
|
}
|
|
57
57
|
```
|
|
58
58
|
|
|
59
|
+
Passing `routing` is what makes the address decide the language: on `/es/docs` the answer is Spanish
|
|
60
|
+
whatever the visitor's cookie says. Leave it out and the cookie and browser decide, which is the
|
|
61
|
+
right answer only when your URLs carry no language.
|
|
62
|
+
|
|
63
|
+
**3b. If your URLs carry the language**, add the universal hook so one route tree serves them all:
|
|
64
|
+
|
|
65
|
+
```ts
|
|
66
|
+
// src/hooks.ts
|
|
67
|
+
import { verbalyReroute } from '@verbaly/sveltekit';
|
|
68
|
+
import { locales } from 'virtual:verbaly';
|
|
69
|
+
|
|
70
|
+
export const reroute = verbalyReroute({ locales });
|
|
71
|
+
```
|
|
72
|
+
|
|
73
|
+
`/es/docs` is then served by your `/docs` route, so you never duplicate route folders per language.
|
|
74
|
+
It goes in `hooks.ts`, not `hooks.server.ts`: client-side navigation needs it too.
|
|
75
|
+
|
|
59
76
|
**4. Hand the locale to the client**:
|
|
60
77
|
|
|
61
78
|
```ts
|
|
@@ -77,7 +94,7 @@ export const load = async ({ data }) => ({
|
|
|
77
94
|
|
|
78
95
|
(`createInstance(options)` remains available when you need custom options.)
|
|
79
96
|
|
|
80
|
-
```
|
|
97
|
+
```svelte
|
|
81
98
|
<!-- src/routes/+layout.svelte -->
|
|
82
99
|
<script>
|
|
83
100
|
import { provideVerbaly } from '@verbaly/svelte';
|
|
@@ -91,7 +108,7 @@ export const load = async ({ data }) => ({
|
|
|
91
108
|
|
|
92
109
|
**6. Switching languages** (client): persists the cookie the server hook reads:
|
|
93
110
|
|
|
94
|
-
```
|
|
111
|
+
```svelte
|
|
95
112
|
<script>
|
|
96
113
|
import { switchLocale } from '@verbaly/sveltekit';
|
|
97
114
|
import { useVerbaly } from '@verbaly/svelte';
|
|
@@ -99,17 +116,19 @@ export const load = async ({ data }) => ({
|
|
|
99
116
|
const verbaly = useVerbaly();
|
|
100
117
|
</script>
|
|
101
118
|
|
|
102
|
-
<button
|
|
119
|
+
<button onclick={() => switchLocale(verbaly, 'es')}>Español</button>
|
|
103
120
|
```
|
|
104
121
|
|
|
105
122
|
## 📖 API
|
|
106
123
|
|
|
107
|
-
| Export
|
|
108
|
-
|
|
|
109
|
-
| `verbalyHandle({ locales, fallback?, cookie? })`
|
|
110
|
-
| `
|
|
111
|
-
| `
|
|
124
|
+
| Export | What it does |
|
|
125
|
+
| ----------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
|
|
126
|
+
| `verbalyHandle({ locales, routing?, base?, fallback?, cookie? })` | SvelteKit `handle` hook: resolves the request locale (URL → cookie → `Accept-Language` → fallback), sets `event.locals.verbalyLocale`, fills `%verbaly.lang%` and `%verbaly.dir%` in `app.html`. |
|
|
127
|
+
| `verbalyReroute({ locales, base? })` | Universal `reroute` hook for `hooks.ts`: `/es/docs` routes as `/docs`, so one route tree serves every language. |
|
|
128
|
+
| `switchLocale(instance, locale, { cookie?, maxAge? })` | Awaits the catalog, switches the locale, writes the cookie and syncs `<html lang>`. SSR-safe. |
|
|
129
|
+
| `LOCALE_COOKIE` | Default cookie name (`verbaly-locale`), shared with core's `localStorage` key. |
|
|
112
130
|
|
|
131
|
+
- **`routing` decides whether the URL is consulted.** With `prefix-except-source`, a prefixed URL is the answer and an unprefixed one means your source language, so a saved choice can never translate your source tree. Without `routing`, only the cookie and the header are read.
|
|
113
132
|
- `cookie: false` disables cookie reading/writing (pure `Accept-Language`).
|
|
114
133
|
- No dependency on `@sveltejs/kit`: the hook is typed structurally and stays compatible across Kit 2.x.
|
|
115
134
|
|
package/dist/index.d.ts
CHANGED
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
import { SwitchLocaleOptions, switchLocale } from "verbaly";
|
|
1
|
+
import { Routing, SwitchLocaleOptions, switchLocale } from "verbaly";
|
|
2
2
|
//#region src/index.d.ts
|
|
3
3
|
declare const LOCALE_COOKIE: string;
|
|
4
4
|
interface HandleEvent {
|
|
5
5
|
request: Request;
|
|
6
|
+
url: URL;
|
|
6
7
|
cookies: {
|
|
7
8
|
get(name: string): string | undefined;
|
|
8
9
|
};
|
|
@@ -24,8 +25,17 @@ interface VerbalyHandleOptions {
|
|
|
24
25
|
locales: string[];
|
|
25
26
|
fallback?: string;
|
|
26
27
|
cookie?: string | false;
|
|
28
|
+
routing?: Routing;
|
|
29
|
+
base?: string;
|
|
27
30
|
}
|
|
28
31
|
declare function verbalyHandle(options: VerbalyHandleOptions): ({ event, resolve }: HandleInput) => Response | Promise<Response>;
|
|
32
|
+
interface VerbalyRerouteOptions {
|
|
33
|
+
locales: string[];
|
|
34
|
+
base?: string;
|
|
35
|
+
}
|
|
36
|
+
declare function verbalyReroute(options: VerbalyRerouteOptions): ({ url }: {
|
|
37
|
+
url: URL;
|
|
38
|
+
}) => string;
|
|
29
39
|
//#endregion
|
|
30
|
-
export { LOCALE_COOKIE, type SwitchLocaleOptions, VerbalyHandleOptions, switchLocale, verbalyHandle };
|
|
40
|
+
export { LOCALE_COOKIE, type SwitchLocaleOptions, VerbalyHandleOptions, VerbalyRerouteOptions, switchLocale, verbalyHandle, verbalyReroute };
|
|
31
41
|
//# sourceMappingURL=index.d.ts.map
|
package/dist/index.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { LOCALE_STORAGE_KEY, localeDirection, resolveRequestLocale, switchLocale } from "verbaly";
|
|
1
|
+
import { LOCALE_STORAGE_KEY, localeDirection, resolveRequestLocale, stripLocalePath, switchLocale } from "verbaly";
|
|
2
2
|
//#region src/index.ts
|
|
3
3
|
const LOCALE_COOKIE = LOCALE_STORAGE_KEY;
|
|
4
4
|
const LANG_PLACEHOLDER = "%verbaly.lang%";
|
|
@@ -10,6 +10,9 @@ function verbalyHandle(options) {
|
|
|
10
10
|
return ({ event, resolve }) => {
|
|
11
11
|
const resolved = resolveRequestLocale({
|
|
12
12
|
supported: locales,
|
|
13
|
+
path: event.url.pathname,
|
|
14
|
+
routing: options.routing,
|
|
15
|
+
base: options.base,
|
|
13
16
|
cookie: cookie ? event.cookies.get(cookie) : void 0,
|
|
14
17
|
header: event.request.headers.get("accept-language"),
|
|
15
18
|
fallback
|
|
@@ -18,7 +21,16 @@ function verbalyHandle(options) {
|
|
|
18
21
|
return resolve(event, { transformPageChunk: ({ html }) => html.replaceAll(LANG_PLACEHOLDER, resolved).replaceAll(DIR_PLACEHOLDER, localeDirection(resolved)) });
|
|
19
22
|
};
|
|
20
23
|
}
|
|
24
|
+
function verbalyReroute(options) {
|
|
25
|
+
const { locales } = options;
|
|
26
|
+
if (!Array.isArray(locales) || locales.length === 0) throw new Error("[verbaly] verbalyReroute needs `locales`: pass the `locales` export from 'virtual:verbaly'");
|
|
27
|
+
return ({ url }) => stripLocalePath({
|
|
28
|
+
supported: locales,
|
|
29
|
+
path: url.pathname,
|
|
30
|
+
base: options.base
|
|
31
|
+
});
|
|
32
|
+
}
|
|
21
33
|
//#endregion
|
|
22
|
-
export { LOCALE_COOKIE, switchLocale, verbalyHandle };
|
|
34
|
+
export { LOCALE_COOKIE, switchLocale, verbalyHandle, verbalyReroute };
|
|
23
35
|
|
|
24
36
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import {
|
|
1
|
+
{"version":3,"file":"index.js","names":[],"sources":["../src/index.ts"],"sourcesContent":["import {\n LOCALE_STORAGE_KEY,\n localeDirection,\n resolveRequestLocale,\n stripLocalePath,\n type Routing,\n} from 'verbaly';\n\n// derived from core's localStorage key: one identity per user across channels\nexport const LOCALE_COOKIE: string = LOCALE_STORAGE_KEY;\nconst LANG_PLACEHOLDER = '%verbaly.lang%';\nconst DIR_PLACEHOLDER = '%verbaly.dir%';\n\n// structural subset of @sveltejs/kit: no runtime or type dependency on kit\ninterface HandleEvent {\n request: Request;\n url: URL;\n cookies: { get(name: string): string | undefined };\n locals: { verbalyLocale?: string };\n}\ninterface ResolveOptions {\n transformPageChunk?(input: { html: string; done: boolean }): string | undefined;\n}\ninterface HandleInput {\n event: HandleEvent;\n resolve(event: HandleEvent, opts?: ResolveOptions): Response | Promise<Response>;\n}\n\nexport interface VerbalyHandleOptions {\n locales: string[];\n fallback?: string;\n cookie?: string | false;\n routing?: Routing;\n base?: string;\n}\n\n// server hook: sets event.locals.verbalyLocale and fills %verbaly.lang% / %verbaly.dir%\nexport function verbalyHandle(options: VerbalyHandleOptions) {\n const { locales, cookie = LOCALE_COOKIE } = options;\n if (!Array.isArray(locales) || locales.length === 0) {\n throw new Error(\n \"[verbaly] verbalyHandle needs `locales`: pass the `locales` export from 'virtual:verbaly' \" +\n '(requires @verbaly/vite ≥0.16) or list them yourself: verbalyHandle({ locales: [...] })',\n );\n }\n const fallback = options.fallback ?? locales[0]!;\n\n return ({ event, resolve }: HandleInput): Response | Promise<Response> => {\n const resolved = resolveRequestLocale({\n supported: locales,\n path: event.url.pathname,\n routing: options.routing,\n base: options.base,\n cookie: cookie ? event.cookies.get(cookie) : undefined,\n header: event.request.headers.get('accept-language'),\n fallback,\n });\n\n event.locals.verbalyLocale = resolved;\n return resolve(event, {\n transformPageChunk: ({ html }) =>\n html\n .replaceAll(LANG_PLACEHOLDER, resolved)\n .replaceAll(DIR_PLACEHOLDER, localeDirection(resolved)),\n });\n };\n}\n\nexport interface VerbalyRerouteOptions {\n locales: string[];\n base?: string;\n}\n\n// universal hook (hooks.ts, never hooks.server.ts): /es/docs routes as /docs, one route tree\nexport function verbalyReroute(options: VerbalyRerouteOptions) {\n const { locales } = options;\n if (!Array.isArray(locales) || locales.length === 0) {\n throw new Error(\n \"[verbaly] verbalyReroute needs `locales`: pass the `locales` export from 'virtual:verbaly'\",\n );\n }\n return ({ url }: { url: URL }): string =>\n stripLocalePath({ supported: locales, path: url.pathname, base: options.base });\n}\n\n// switchLocale moved to core in 0.18.0 (shared with @verbaly/nuxt): same API, re-exported\nexport { switchLocale } from 'verbaly';\nexport type { SwitchLocaleOptions } from 'verbaly';\n"],"mappings":";;AASA,MAAa,gBAAwB;AACrC,MAAM,mBAAmB;AACzB,MAAM,kBAAkB;AA0BxB,SAAgB,cAAc,SAA+B;CAC3D,MAAM,EAAE,SAAS,SAAS,kBAAkB;CAC5C,IAAI,CAAC,MAAM,QAAQ,OAAO,KAAK,QAAQ,WAAW,GAChD,MAAM,IAAI,MACR,mLAEF;CAEF,MAAM,WAAW,QAAQ,YAAY,QAAQ;CAE7C,QAAQ,EAAE,OAAO,cAAyD;EACxE,MAAM,WAAW,qBAAqB;GACpC,WAAW;GACX,MAAM,MAAM,IAAI;GAChB,SAAS,QAAQ;GACjB,MAAM,QAAQ;GACd,QAAQ,SAAS,MAAM,QAAQ,IAAI,MAAM,IAAI,KAAA;GAC7C,QAAQ,MAAM,QAAQ,QAAQ,IAAI,iBAAiB;GACnD;EACF,CAAC;EAED,MAAM,OAAO,gBAAgB;EAC7B,OAAO,QAAQ,OAAO,EACpB,qBAAqB,EAAE,WACrB,KACG,WAAW,kBAAkB,QAAQ,CAAC,CACtC,WAAW,iBAAiB,gBAAgB,QAAQ,CAAC,EAC5D,CAAC;CACH;AACF;AAQA,SAAgB,eAAe,SAAgC;CAC7D,MAAM,EAAE,YAAY;CACpB,IAAI,CAAC,MAAM,QAAQ,OAAO,KAAK,QAAQ,WAAW,GAChD,MAAM,IAAI,MACR,4FACF;CAEF,QAAQ,EAAE,UACR,gBAAgB;EAAE,WAAW;EAAS,MAAM,IAAI;EAAU,MAAM,QAAQ;CAAK,CAAC;AAClF"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@verbaly/sveltekit",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.49.0",
|
|
4
4
|
"description": "SvelteKit SSR integration for Verbaly: per-request locale negotiation and flash-free hydration.",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"i18n",
|
|
@@ -40,12 +40,12 @@
|
|
|
40
40
|
"access": "public"
|
|
41
41
|
},
|
|
42
42
|
"peerDependencies": {
|
|
43
|
-
"verbaly": "^0.
|
|
43
|
+
"verbaly": "^0.49.0"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
46
|
"@sveltejs/kit": "^2.70.3",
|
|
47
47
|
"svelte": "^5.57.0",
|
|
48
|
-
"verbaly": "^0.
|
|
48
|
+
"verbaly": "^0.49.0"
|
|
49
49
|
},
|
|
50
50
|
"scripts": {
|
|
51
51
|
"build": "tsdown",
|