@sveltebase/i18n 0.2.3 → 0.3.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 +334 -0
- package/package.json +2 -2
package/README.md
ADDED
|
@@ -0,0 +1,334 @@
|
|
|
1
|
+
# `@sveltebase/i18n`
|
|
2
|
+
|
|
3
|
+
Simple i18n utilities for Svelte 5 apps.
|
|
4
|
+
|
|
5
|
+
`@sveltebase/i18n` gives you a small API for:
|
|
6
|
+
|
|
7
|
+
- defining your supported languages
|
|
8
|
+
- storing the active locale
|
|
9
|
+
- reading translations in components
|
|
10
|
+
- formatting dates and times for the current locale
|
|
11
|
+
|
|
12
|
+
It is designed to stay lightweight and work nicely with Svelte 5 runes.
|
|
13
|
+
|
|
14
|
+
## Install
|
|
15
|
+
|
|
16
|
+
Install the package with Bun:
|
|
17
|
+
|
|
18
|
+
```bash
|
|
19
|
+
bun add @sveltebase/i18n
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
## What it exports
|
|
23
|
+
|
|
24
|
+
- `createI18n`
|
|
25
|
+
- `getTranslations`
|
|
26
|
+
- `getFormat`
|
|
27
|
+
|
|
28
|
+
## Quick start
|
|
29
|
+
|
|
30
|
+
Create a shared i18n module:
|
|
31
|
+
|
|
32
|
+
```ts
|
|
33
|
+
import { createI18n } from "@sveltebase/i18n";
|
|
34
|
+
|
|
35
|
+
export const languages = [
|
|
36
|
+
{
|
|
37
|
+
code: "en",
|
|
38
|
+
label: "English",
|
|
39
|
+
messages: {
|
|
40
|
+
"app-title": "My app",
|
|
41
|
+
"welcome": "Welcome, {name}",
|
|
42
|
+
"just-now": "Just now",
|
|
43
|
+
"minutes-ago": "{minutes} minutes ago",
|
|
44
|
+
"today-at": "Today at {time}",
|
|
45
|
+
"yesterday-at": "Yesterday at {time}"
|
|
46
|
+
}
|
|
47
|
+
},
|
|
48
|
+
{
|
|
49
|
+
code: "uz",
|
|
50
|
+
label: "O‘zbekcha",
|
|
51
|
+
messages: {
|
|
52
|
+
"app-title": "Mening ilovam",
|
|
53
|
+
"welcome": "Xush kelibsiz, {name}",
|
|
54
|
+
"just-now": "Hozirgina",
|
|
55
|
+
"minutes-ago": "{minutes} daqiqa oldin",
|
|
56
|
+
"today-at": "Bugun {time} da",
|
|
57
|
+
"yesterday-at": "Kecha {time} da"
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
] as const;
|
|
61
|
+
|
|
62
|
+
export const i18n = createI18n(languages, "locale");
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
Then initialize it before using translations or formatters.
|
|
66
|
+
|
|
67
|
+
If you already have the request cookies available during the initial render, pass them to `init(cookies)` immediately. That lets the package restore the saved locale before your UI reads translations, so the correct language loads right away instead of first rendering with the fallback locale and switching later.
|
|
68
|
+
|
|
69
|
+
```ts
|
|
70
|
+
import { i18n } from "./i18n";
|
|
71
|
+
|
|
72
|
+
i18n.init(cookies);
|
|
73
|
+
```
|
|
74
|
+
|
|
75
|
+
## Basic usage in a Svelte component
|
|
76
|
+
|
|
77
|
+
```svelte
|
|
78
|
+
<script lang="ts">
|
|
79
|
+
import { getTranslations, getFormat } from "@sveltebase/i18n";
|
|
80
|
+
import { i18n } from "$lib/i18n";
|
|
81
|
+
|
|
82
|
+
const t = getTranslations();
|
|
83
|
+
const format = getFormat();
|
|
84
|
+
|
|
85
|
+
function switchLocale(locale: string) {
|
|
86
|
+
i18n.locale = locale;
|
|
87
|
+
}
|
|
88
|
+
</script>
|
|
89
|
+
|
|
90
|
+
<h1>{t("app-title")}</h1>
|
|
91
|
+
<p>{t("welcome", { name: "Jane" })}</p>
|
|
92
|
+
<p>{format(new Date(), { preset: "full", withTime: true })}</p>
|
|
93
|
+
|
|
94
|
+
<button onclick={() => switchLocale("en")}>English</button>
|
|
95
|
+
<button onclick={() => switchLocale("uz")}>O‘zbekcha</button>
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
## Creating your language list
|
|
99
|
+
|
|
100
|
+
Each language should have:
|
|
101
|
+
|
|
102
|
+
- `code`: locale code
|
|
103
|
+
- `label`: readable language name
|
|
104
|
+
- `messages`: translation dictionary
|
|
105
|
+
|
|
106
|
+
Example:
|
|
107
|
+
|
|
108
|
+
```ts
|
|
109
|
+
const languages = [
|
|
110
|
+
{
|
|
111
|
+
code: "en",
|
|
112
|
+
label: "English",
|
|
113
|
+
messages: {
|
|
114
|
+
"app-title": "My app",
|
|
115
|
+
"nav.home": "Home",
|
|
116
|
+
"nav.settings": "Settings"
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
{
|
|
120
|
+
code: "uz",
|
|
121
|
+
label: "O‘zbekcha",
|
|
122
|
+
messages: {
|
|
123
|
+
"app-title": "Mening ilovam",
|
|
124
|
+
"nav.home": "Bosh sahifa",
|
|
125
|
+
"nav.settings": "Sozlamalar"
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
] as const;
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
You can also import messages from JSON or split them across files if that fits your app better.
|
|
132
|
+
|
|
133
|
+
## Initialization
|
|
134
|
+
|
|
135
|
+
Call `init()` before using `getTranslations()` or `getFormat()`.
|
|
136
|
+
|
|
137
|
+
### Without cookies
|
|
138
|
+
|
|
139
|
+
If you do not have cookies available yet, you can initialize normally:
|
|
140
|
+
|
|
141
|
+
```ts
|
|
142
|
+
import { i18n } from "$lib/i18n";
|
|
143
|
+
|
|
144
|
+
i18n.init();
|
|
145
|
+
```
|
|
146
|
+
|
|
147
|
+
### With cookies in SvelteKit for faster first render
|
|
148
|
+
|
|
149
|
+
In SvelteKit, the recommended approach is to load all cookies in `+layout.server.ts`, return them from `load`, and then pass that data to `i18n.init(...)` in `+layout.svelte`.
|
|
150
|
+
|
|
151
|
+
This lets `@sveltebase/i18n` restore the saved locale before your UI reads translations, so the correct language is available immediately and you avoid rendering the fallback language first.
|
|
152
|
+
|
|
153
|
+
In `+layout.server.ts`:
|
|
154
|
+
|
|
155
|
+
```ts
|
|
156
|
+
export function load({ cookies }) {
|
|
157
|
+
return {
|
|
158
|
+
cookies: cookies.getAll()
|
|
159
|
+
};
|
|
160
|
+
}
|
|
161
|
+
```
|
|
162
|
+
|
|
163
|
+
Then in `+layout.svelte`:
|
|
164
|
+
|
|
165
|
+
```svelte
|
|
166
|
+
<script lang="ts">
|
|
167
|
+
import { i18n } from "$lib/i18n";
|
|
168
|
+
|
|
169
|
+
let { data } = $props();
|
|
170
|
+
|
|
171
|
+
i18n.init(data.cookies);
|
|
172
|
+
</script>
|
|
173
|
+
|
|
174
|
+
<slot />
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
The value passed to `i18n.init(...)` should be an array of cookie objects in this shape:
|
|
178
|
+
|
|
179
|
+
```ts
|
|
180
|
+
type Cookie = {
|
|
181
|
+
name: string;
|
|
182
|
+
value: string;
|
|
183
|
+
};
|
|
184
|
+
```
|
|
185
|
+
|
|
186
|
+
## API
|
|
187
|
+
|
|
188
|
+
## `createI18n(languages, localeStorageKey?)`
|
|
189
|
+
|
|
190
|
+
Creates an i18n instance.
|
|
191
|
+
|
|
192
|
+
### Parameters
|
|
193
|
+
|
|
194
|
+
- `languages`: an array of language definitions
|
|
195
|
+
- `localeStorageKey?`: the key used to persist the locale, defaults to `"locale"`
|
|
196
|
+
|
|
197
|
+
### Returns
|
|
198
|
+
|
|
199
|
+
An object with:
|
|
200
|
+
|
|
201
|
+
- `languages`
|
|
202
|
+
- `locale`
|
|
203
|
+
- `currentLanguage`
|
|
204
|
+
- `init(cookies?)`
|
|
205
|
+
|
|
206
|
+
### Example
|
|
207
|
+
|
|
208
|
+
```ts
|
|
209
|
+
import { createI18n } from "@sveltebase/i18n";
|
|
210
|
+
|
|
211
|
+
const languages = [
|
|
212
|
+
{
|
|
213
|
+
code: "en",
|
|
214
|
+
label: "English",
|
|
215
|
+
messages: {
|
|
216
|
+
hello: "Hello"
|
|
217
|
+
}
|
|
218
|
+
},
|
|
219
|
+
{
|
|
220
|
+
code: "uz",
|
|
221
|
+
label: "O‘zbekcha",
|
|
222
|
+
messages: {
|
|
223
|
+
hello: "Salom"
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
] as const;
|
|
227
|
+
|
|
228
|
+
const i18n = createI18n(languages, "locale");
|
|
229
|
+
```
|
|
230
|
+
|
|
231
|
+
## `getTranslations()`
|
|
232
|
+
|
|
233
|
+
Returns a translation function for the current locale.
|
|
234
|
+
|
|
235
|
+
### Example
|
|
236
|
+
|
|
237
|
+
```ts
|
|
238
|
+
import { getTranslations } from "@sveltebase/i18n";
|
|
239
|
+
|
|
240
|
+
const t = getTranslations();
|
|
241
|
+
|
|
242
|
+
t("hello");
|
|
243
|
+
t("welcome", { name: "Jane" });
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
## `getFormat()`
|
|
247
|
+
|
|
248
|
+
Returns a formatter function for locale-aware display.
|
|
249
|
+
|
|
250
|
+
### Example
|
|
251
|
+
|
|
252
|
+
```ts
|
|
253
|
+
import { getFormat } from "@sveltebase/i18n";
|
|
254
|
+
|
|
255
|
+
const format = getFormat();
|
|
256
|
+
|
|
257
|
+
format(new Date(), { preset: "full" });
|
|
258
|
+
format(new Date(), { preset: "custom", withTime: true });
|
|
259
|
+
format("13:45:00", { preset: "timestring" });
|
|
260
|
+
```
|
|
261
|
+
|
|
262
|
+
## Locale switching
|
|
263
|
+
|
|
264
|
+
You can switch the active locale by assigning to `i18n.locale`:
|
|
265
|
+
|
|
266
|
+
```ts
|
|
267
|
+
i18n.locale = "en";
|
|
268
|
+
```
|
|
269
|
+
|
|
270
|
+
You can also read the current language object:
|
|
271
|
+
|
|
272
|
+
```ts
|
|
273
|
+
console.log(i18n.currentLanguage.label);
|
|
274
|
+
```
|
|
275
|
+
|
|
276
|
+
## Formatting presets
|
|
277
|
+
|
|
278
|
+
`getFormat()` supports these presets:
|
|
279
|
+
|
|
280
|
+
- `default`
|
|
281
|
+
- `custom`
|
|
282
|
+
- `birthday`
|
|
283
|
+
- `month`
|
|
284
|
+
- `timestring`
|
|
285
|
+
- `full`
|
|
286
|
+
|
|
287
|
+
### Example
|
|
288
|
+
|
|
289
|
+
```ts
|
|
290
|
+
const format = getFormat();
|
|
291
|
+
|
|
292
|
+
format(new Date(), { preset: "month" });
|
|
293
|
+
format(new Date(), { preset: "birthday" });
|
|
294
|
+
format(new Date(), { preset: "full", withTime: true });
|
|
295
|
+
format("08:30:00", { preset: "timestring" });
|
|
296
|
+
```
|
|
297
|
+
|
|
298
|
+
## Type safety
|
|
299
|
+
|
|
300
|
+
When your language array is declared with `as const`, locale codes are inferred automatically.
|
|
301
|
+
|
|
302
|
+
```ts
|
|
303
|
+
const languages = [
|
|
304
|
+
{
|
|
305
|
+
code: "en",
|
|
306
|
+
label: "English",
|
|
307
|
+
messages: { hello: "Hello" }
|
|
308
|
+
},
|
|
309
|
+
{
|
|
310
|
+
code: "uz",
|
|
311
|
+
label: "O‘zbekcha",
|
|
312
|
+
messages: { hello: "Salom" }
|
|
313
|
+
}
|
|
314
|
+
] as const;
|
|
315
|
+
```
|
|
316
|
+
|
|
317
|
+
That improves typing for values like:
|
|
318
|
+
|
|
319
|
+
- `i18n.locale`
|
|
320
|
+
- `i18n.currentLanguage`
|
|
321
|
+
- language code parameters in your own functions
|
|
322
|
+
|
|
323
|
+
## Notes
|
|
324
|
+
|
|
325
|
+
- Call `init()` before using `getTranslations()` or `getFormat()`.
|
|
326
|
+
- Passing cookies into `init(cookies)` during the initial render helps the correct locale load faster and avoids rendering the fallback language first.
|
|
327
|
+
- The first language in the array is used as the fallback locale.
|
|
328
|
+
- Locale state is persisted using `@sveltebase/state`.
|
|
329
|
+
- Date formatting includes locale-specific behavior for Uzbek.
|
|
330
|
+
- This package is intended for Svelte 5 apps.
|
|
331
|
+
|
|
332
|
+
## License
|
|
333
|
+
|
|
334
|
+
ISC
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sveltebase/i18n",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.3.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"publishConfig": {
|
|
6
6
|
"access": "public"
|
|
@@ -18,7 +18,7 @@
|
|
|
18
18
|
}
|
|
19
19
|
},
|
|
20
20
|
"dependencies": {
|
|
21
|
-
"@sveltebase/state": "0.
|
|
21
|
+
"@sveltebase/state": "0.3.0",
|
|
22
22
|
"date-fns": "^4.1.0",
|
|
23
23
|
"use-intl": "^4.4.0",
|
|
24
24
|
"zod": "^4.1.11"
|