@sveltebase/i18n 0.4.1 → 0.4.3
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 +103 -0
- package/dist/index.d.ts +1 -1
- package/dist/index.js +39 -7
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -39,8 +39,23 @@ export const languages = [
|
|
|
39
39
|
messages: {
|
|
40
40
|
"app-title": "My app",
|
|
41
41
|
"welcome": "Welcome, {name}",
|
|
42
|
+
|
|
42
43
|
"just-now": "Just now",
|
|
44
|
+
|
|
43
45
|
"minutes-ago": "{minutes} minutes ago",
|
|
46
|
+
"hours-ago": "{hours} hours ago",
|
|
47
|
+
"days-ago": "{days} days ago",
|
|
48
|
+
"weeks-ago": "{weeks} weeks ago",
|
|
49
|
+
"months-ago": "{months} months ago",
|
|
50
|
+
"years-ago": "{years} years ago",
|
|
51
|
+
|
|
52
|
+
"in-minutes": "in {minutes} minutes",
|
|
53
|
+
"in-hours": "in {hours} hours",
|
|
54
|
+
"in-days": "in {days} days",
|
|
55
|
+
"in-weeks": "in {weeks} weeks",
|
|
56
|
+
"in-months": "in {months} months",
|
|
57
|
+
"in-years": "in {years} years",
|
|
58
|
+
|
|
44
59
|
"today-at": "Today at {time}",
|
|
45
60
|
"yesterday-at": "Yesterday at {time}"
|
|
46
61
|
}
|
|
@@ -51,8 +66,23 @@ export const languages = [
|
|
|
51
66
|
messages: {
|
|
52
67
|
"app-title": "Mening ilovam",
|
|
53
68
|
"welcome": "Xush kelibsiz, {name}",
|
|
69
|
+
|
|
54
70
|
"just-now": "Hozirgina",
|
|
71
|
+
|
|
55
72
|
"minutes-ago": "{minutes} daqiqa oldin",
|
|
73
|
+
"hours-ago": "{hours} soat oldin",
|
|
74
|
+
"days-ago": "{days} kun oldin",
|
|
75
|
+
"weeks-ago": "{weeks} hafta oldin",
|
|
76
|
+
"months-ago": "{months} oy oldin",
|
|
77
|
+
"years-ago": "{years} yil oldin",
|
|
78
|
+
|
|
79
|
+
"in-minutes": "{minutes} daqiqadan keyin",
|
|
80
|
+
"in-hours": "{hours} soatdan keyin",
|
|
81
|
+
"in-days": "{days} kundan keyin",
|
|
82
|
+
"in-weeks": "{weeks} haftadan keyin",
|
|
83
|
+
"in-months": "{months} oydan keyin",
|
|
84
|
+
"in-years": "{years} yildan keyin",
|
|
85
|
+
|
|
56
86
|
"today-at": "Bugun {time} da",
|
|
57
87
|
"yesterday-at": "Kecha {time} da"
|
|
58
88
|
}
|
|
@@ -272,6 +302,7 @@ const format = getFormat();
|
|
|
272
302
|
|
|
273
303
|
format(new Date(), { preset: "full" });
|
|
274
304
|
format(new Date(), { preset: "custom", withTime: true });
|
|
305
|
+
format(Date.now() - 1000 * 60 * 5, { preset: "relative" });
|
|
275
306
|
format("13:45:00", { preset: "timestring" });
|
|
276
307
|
```
|
|
277
308
|
|
|
@@ -295,11 +326,19 @@ console.log(i18n.currentLanguage.label);
|
|
|
295
326
|
|
|
296
327
|
- `default`
|
|
297
328
|
- `custom`
|
|
329
|
+
- `relative`
|
|
298
330
|
- `birthday`
|
|
299
331
|
- `month`
|
|
300
332
|
- `timestring`
|
|
301
333
|
- `full`
|
|
302
334
|
|
|
335
|
+
### Preset notes
|
|
336
|
+
|
|
337
|
+
- `relative` always returns relative text for both past and future values. It does not fall back to an absolute date.
|
|
338
|
+
- `custom` can still mix relative labels such as `just-now` or `today-at` with locale-aware absolute dates for older values.
|
|
339
|
+
- `full` returns a full locale-aware date and optionally time.
|
|
340
|
+
- `timestring` is for time-only string values such as `"08:30:00"`.
|
|
341
|
+
|
|
303
342
|
### Example
|
|
304
343
|
|
|
305
344
|
```ts
|
|
@@ -308,9 +347,73 @@ const format = getFormat();
|
|
|
308
347
|
format(new Date(), { preset: "month" });
|
|
309
348
|
format(new Date(), { preset: "birthday" });
|
|
310
349
|
format(new Date(), { preset: "full", withTime: true });
|
|
350
|
+
format(Date.now() - 1000 * 60 * 5, { preset: "relative" });
|
|
311
351
|
format("08:30:00", { preset: "timestring" });
|
|
312
352
|
```
|
|
313
353
|
|
|
354
|
+
## Required locale strings for relative formatting
|
|
355
|
+
|
|
356
|
+
If you use `preset: "relative"`, make sure every locale provides these message keys:
|
|
357
|
+
|
|
358
|
+
- `just-now`
|
|
359
|
+
- `minutes-ago`
|
|
360
|
+
- `hours-ago`
|
|
361
|
+
- `days-ago`
|
|
362
|
+
- `weeks-ago`
|
|
363
|
+
- `months-ago`
|
|
364
|
+
- `years-ago`
|
|
365
|
+
- `in-minutes`
|
|
366
|
+
- `in-hours`
|
|
367
|
+
- `in-days`
|
|
368
|
+
- `in-weeks`
|
|
369
|
+
- `in-months`
|
|
370
|
+
- `in-years`
|
|
371
|
+
|
|
372
|
+
Example:
|
|
373
|
+
|
|
374
|
+
```ts
|
|
375
|
+
const languages = [
|
|
376
|
+
{
|
|
377
|
+
code: "en",
|
|
378
|
+
label: "English",
|
|
379
|
+
messages: {
|
|
380
|
+
"just-now": "Just now",
|
|
381
|
+
"minutes-ago": "{minutes} minutes ago",
|
|
382
|
+
"hours-ago": "{hours} hours ago",
|
|
383
|
+
"days-ago": "{days} days ago",
|
|
384
|
+
"weeks-ago": "{weeks} weeks ago",
|
|
385
|
+
"months-ago": "{months} months ago",
|
|
386
|
+
"years-ago": "{years} years ago",
|
|
387
|
+
"in-minutes": "in {minutes} minutes",
|
|
388
|
+
"in-hours": "in {hours} hours",
|
|
389
|
+
"in-days": "in {days} days",
|
|
390
|
+
"in-weeks": "in {weeks} weeks",
|
|
391
|
+
"in-months": "in {months} months",
|
|
392
|
+
"in-years": "in {years} years"
|
|
393
|
+
}
|
|
394
|
+
},
|
|
395
|
+
{
|
|
396
|
+
code: "uz",
|
|
397
|
+
label: "O‘zbekcha",
|
|
398
|
+
messages: {
|
|
399
|
+
"just-now": "Hozirgina",
|
|
400
|
+
"minutes-ago": "{minutes} daqiqa oldin",
|
|
401
|
+
"hours-ago": "{hours} soat oldin",
|
|
402
|
+
"days-ago": "{days} kun oldin",
|
|
403
|
+
"weeks-ago": "{weeks} hafta oldin",
|
|
404
|
+
"months-ago": "{months} oy oldin",
|
|
405
|
+
"years-ago": "{years} yil oldin",
|
|
406
|
+
"in-minutes": "{minutes} daqiqadan keyin",
|
|
407
|
+
"in-hours": "{hours} soatdan keyin",
|
|
408
|
+
"in-days": "{days} kundan keyin",
|
|
409
|
+
"in-weeks": "{weeks} haftadan keyin",
|
|
410
|
+
"in-months": "{months} oydan keyin",
|
|
411
|
+
"in-years": "{years} yildan keyin"
|
|
412
|
+
}
|
|
413
|
+
}
|
|
414
|
+
] as const;
|
|
415
|
+
```
|
|
416
|
+
|
|
314
417
|
## Type safety
|
|
315
418
|
|
|
316
419
|
When your language array is declared with `as const`, locale codes are inferred automatically.
|
package/dist/index.d.ts
CHANGED
|
@@ -13,7 +13,7 @@ type LanguageDefinition<TLocale extends string = string, TMessages extends Messa
|
|
|
13
13
|
messages: TMessages;
|
|
14
14
|
};
|
|
15
15
|
type FormatOptions = {
|
|
16
|
-
preset?: "default" | "custom" | "birthday" | "month" | "timestring" | "full";
|
|
16
|
+
preset?: "default" | "custom" | "birthday" | "month" | "timestring" | "full" | "relative";
|
|
17
17
|
withTime?: boolean;
|
|
18
18
|
};
|
|
19
19
|
|
package/dist/index.js
CHANGED
|
@@ -44,6 +44,36 @@ function formatTimeWithDateFns(value, format) {
|
|
|
44
44
|
const minutes = String(value.getMinutes()).padStart(2, "0");
|
|
45
45
|
return `${hours}:${minutes}`;
|
|
46
46
|
}
|
|
47
|
+
function formatRelativeDate(value, t) {
|
|
48
|
+
const now = new SvelteDate();
|
|
49
|
+
const diffMinutes = Math.floor((value.getTime() - now.getTime()) / 6e4);
|
|
50
|
+
const absMinutes = Math.abs(diffMinutes);
|
|
51
|
+
if (absMinutes < 1) {
|
|
52
|
+
return t("just-now");
|
|
53
|
+
}
|
|
54
|
+
const isFuture = diffMinutes > 0;
|
|
55
|
+
if (absMinutes < 60) {
|
|
56
|
+
return isFuture ? t("in-minutes", { minutes: absMinutes }) : t("minutes-ago", { minutes: absMinutes });
|
|
57
|
+
}
|
|
58
|
+
const absHours = Math.floor(absMinutes / 60);
|
|
59
|
+
if (absHours < 24) {
|
|
60
|
+
return isFuture ? t("in-hours", { hours: absHours }) : t("hours-ago", { hours: absHours });
|
|
61
|
+
}
|
|
62
|
+
const absDays = Math.floor(absHours / 24);
|
|
63
|
+
if (absDays < 7) {
|
|
64
|
+
return isFuture ? t("in-days", { days: absDays }) : t("days-ago", { days: absDays });
|
|
65
|
+
}
|
|
66
|
+
const absWeeks = Math.floor(absDays / 7);
|
|
67
|
+
if (absDays < 30) {
|
|
68
|
+
return isFuture ? t("in-weeks", { weeks: absWeeks }) : t("weeks-ago", { weeks: absWeeks });
|
|
69
|
+
}
|
|
70
|
+
const absMonths = Math.floor(absDays / 30);
|
|
71
|
+
if (absDays < 365) {
|
|
72
|
+
return isFuture ? t("in-months", { months: absMonths }) : t("months-ago", { months: absMonths });
|
|
73
|
+
}
|
|
74
|
+
const absYears = Math.floor(absDays / 365);
|
|
75
|
+
return isFuture ? t("in-years", { years: absYears }) : t("years-ago", { years: absYears });
|
|
76
|
+
}
|
|
47
77
|
var UZ_WEEKDAYS = [
|
|
48
78
|
"Yakshanba",
|
|
49
79
|
"Dushanba",
|
|
@@ -119,6 +149,9 @@ function createFormatForLocale(languages, locale, fallbackLocale, timeZone = "As
|
|
|
119
149
|
});
|
|
120
150
|
}
|
|
121
151
|
const date = toDate(value);
|
|
152
|
+
if (preset === "relative") {
|
|
153
|
+
return formatRelativeDate(date, t);
|
|
154
|
+
}
|
|
122
155
|
if (preset === "full") {
|
|
123
156
|
return locale === "uz" ? formatUzDate(date, true, withTime) : formatter.dateTime(date, {
|
|
124
157
|
year: "numeric",
|
|
@@ -289,16 +322,15 @@ function createI18n(languages, localeStorageKey = DEFAULT_LOCALE_STORAGE_KEY) {
|
|
|
289
322
|
);
|
|
290
323
|
},
|
|
291
324
|
init(cookies) {
|
|
292
|
-
if (initialized) {
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
325
|
+
if (!initialized) {
|
|
326
|
+
const resolvedCookies = typeof cookies === "function" ? cookies() : cookies;
|
|
327
|
+
if (resolvedCookies) {
|
|
328
|
+
localeState.init(resolvedCookies);
|
|
329
|
+
}
|
|
330
|
+
initialized = true;
|
|
298
331
|
}
|
|
299
332
|
const { set } = ensureContext();
|
|
300
333
|
set(i18n);
|
|
301
|
-
initialized = true;
|
|
302
334
|
}
|
|
303
335
|
};
|
|
304
336
|
i18nInternals.set(i18n, {
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@sveltebase/i18n",
|
|
3
|
-
"version": "0.4.
|
|
3
|
+
"version": "0.4.3",
|
|
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.4.
|
|
21
|
+
"@sveltebase/state": "0.4.3",
|
|
22
22
|
"use-intl": "^4.4.0"
|
|
23
23
|
},
|
|
24
24
|
"peerDependencies": {
|