@juit/vue-i18n 0.1.2 → 0.2.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 +125 -29
- package/dist/index.d.ts +280 -56
- package/dist/index.js +109 -84
- package/dist/index.js.map +1 -1
- package/package.json +3 -3
package/README.md
CHANGED
|
@@ -61,16 +61,87 @@ described below, or some options:
|
|
|
61
61
|
available in this language.
|
|
62
62
|
* `translations`: an object containing the translations for the messages to
|
|
63
63
|
translate, keyed by its identifier.
|
|
64
|
-
* `
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
64
|
+
* `dateTimeFormats`: date and time format aliases used formatting dates.
|
|
65
|
+
* `numberFormats`: number format aliases used formatting numbers.
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
### Date Time Format Aliases
|
|
69
|
+
|
|
70
|
+
Date time formatting aliases can be configured keyed by a simple string and
|
|
71
|
+
values as [`Intl.DateTimeFormatOptions`][5]
|
|
72
|
+
|
|
73
|
+
```typescript
|
|
74
|
+
import { createApp } from 'vue'
|
|
75
|
+
import { i18n } from '@juit/vue-i18n'
|
|
76
|
+
import MyApp from './app.vue'
|
|
77
|
+
|
|
78
|
+
const app = createApp(MyApp).use(i18n, {
|
|
79
|
+
defaultLanguage: 'en',
|
|
80
|
+
dateTimeFormats: {
|
|
81
|
+
custom: {
|
|
82
|
+
year: 'numeric',
|
|
83
|
+
month: '2-digit',
|
|
84
|
+
day: '2-digit',
|
|
85
|
+
},
|
|
86
|
+
}
|
|
87
|
+
})
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
The default (overridable) formats are as follows:
|
|
91
|
+
|
|
92
|
+
```typescript
|
|
93
|
+
{
|
|
94
|
+
// used when no alias or date time format is specified
|
|
95
|
+
default: { dateStyle: 'medium', timeStyle: 'medium' },
|
|
96
|
+
|
|
97
|
+
// generic formats
|
|
98
|
+
short: { dateStyle: 'short', timeStyle: 'short' },
|
|
99
|
+
medium: { dateStyle: 'medium', timeStyle: 'medium' },
|
|
100
|
+
long: { dateStyle: 'long', timeStyle: 'long' },
|
|
101
|
+
full: { dateStyle: 'full', timeStyle: 'full' },
|
|
102
|
+
|
|
103
|
+
// date only formats
|
|
104
|
+
date: { dateStyle: 'medium' },
|
|
105
|
+
shortDate: { dateStyle: 'short' },
|
|
106
|
+
mediumDate: { dateStyle: 'medium' },
|
|
107
|
+
longDate: { dateStyle: 'long' },
|
|
108
|
+
fullDate: { dateStyle: 'full' },
|
|
109
|
+
|
|
110
|
+
// time only formats
|
|
111
|
+
time: { timeStyle: 'medium' },
|
|
112
|
+
shortTime: { timeStyle: 'short' },
|
|
113
|
+
mediumTime: { timeStyle: 'medium' },
|
|
114
|
+
longTime: { timeStyle: 'long' },
|
|
115
|
+
fullTime: { timeStyle: 'full' },
|
|
116
|
+
}
|
|
117
|
+
```
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
### Number Format Aliases
|
|
121
|
+
|
|
122
|
+
Similarly to date time, also number formatting aliases can be configured keyed
|
|
123
|
+
by a simple string and values as [`Intl.NumberFormatOptions`][4]
|
|
124
|
+
|
|
125
|
+
```typescript
|
|
126
|
+
import { createApp } from 'vue'
|
|
127
|
+
import { i18n } from '@juit/vue-i18n'
|
|
128
|
+
import MyApp from './app.vue'
|
|
129
|
+
|
|
130
|
+
const app = createApp(MyApp).use(i18n, {
|
|
131
|
+
defaultLanguage: 'en',
|
|
132
|
+
numberFormats: {
|
|
133
|
+
speed: {
|
|
134
|
+
style: 'unit',
|
|
135
|
+
unit: 'kilometer-per-hour',
|
|
136
|
+
}
|
|
137
|
+
}
|
|
138
|
+
})
|
|
139
|
+
```
|
|
140
|
+
|
|
141
|
+
While there is no intrinsic default, each valid ISO-4217 currency code
|
|
142
|
+
(e.g. `EUR`, `USD`, ...) can be used as an alias.
|
|
143
|
+
|
|
144
|
+
To configure the default number format use the `default` key.
|
|
74
145
|
|
|
75
146
|
|
|
76
147
|
## Usage
|
|
@@ -211,8 +282,10 @@ The default format can be specified when configuring the plugin as the
|
|
|
211
282
|
## Formatting dates
|
|
212
283
|
|
|
213
284
|
The `d(...)` function can be used to format date-and-time values in the current
|
|
214
|
-
locale
|
|
215
|
-
|
|
285
|
+
locale.
|
|
286
|
+
|
|
287
|
+
When the second parameter is a string, it is considered to be one of the
|
|
288
|
+
_aliases_ configured when the plugin is setup.
|
|
216
289
|
|
|
217
290
|
```typescript
|
|
218
291
|
import { useTranslator } from '@juit/vue-i18n'
|
|
@@ -220,22 +293,13 @@ import { useTranslator } from '@juit/vue-i18n'
|
|
|
220
293
|
const translator = useTranslator()
|
|
221
294
|
|
|
222
295
|
const dateTime = translator.d(new Date()) // e.g. '03.02.2025, 18:08:05' in de-DE
|
|
223
|
-
const dateOnly = translator.d
|
|
224
|
-
const dateTime = translator.d
|
|
296
|
+
const dateOnly = translator.d(new Date(), 'date') // e.g. '03.02.2025' in de-DE
|
|
297
|
+
const dateTime = translator.d(new Date(), 'time') // e.g. '18:08:05' in de-DE
|
|
225
298
|
```
|
|
226
299
|
|
|
227
300
|
A full [`Intl.DateTimeFormatOptions`][5] set of options can also be specified
|
|
228
301
|
as a second parameter to fine-tune the formatting.
|
|
229
302
|
|
|
230
|
-
The second parameter can also be a simple string `full`, `long`, `medium`, or
|
|
231
|
-
`short`, as a shortcut to `options.dateStyle` or `options.timeStyle`.
|
|
232
|
-
|
|
233
|
-
The default formatting options for each method can be specified at configuration
|
|
234
|
-
time, using the `formats.dateTimeFormat`, `formats.dateOnlyFormat`, or
|
|
235
|
-
`formats.timeOnlyFormat` parameters.
|
|
236
|
-
|
|
237
|
-
By default, they are all set to `medium`.
|
|
238
|
-
|
|
239
303
|
|
|
240
304
|
## Configuring Types
|
|
241
305
|
|
|
@@ -255,27 +319,59 @@ in the configuration:
|
|
|
255
319
|
These are the arbitrary keys used to identify the
|
|
256
320
|
messages to be translated with the `t` and `tc`
|
|
257
321
|
methods of `Translator`.
|
|
322
|
+
* `dateTimeFormats`: the date and time formats _aliases_ used by the
|
|
323
|
+
application.
|
|
324
|
+
* `numberFormats`: the number formats _aliases_ used by the application.
|
|
258
325
|
|
|
259
326
|
To configure the types, follow the example below:
|
|
260
327
|
|
|
261
328
|
```typescript
|
|
262
329
|
const translations = {
|
|
263
|
-
|
|
264
|
-
} as const satisfies
|
|
330
|
+
hello: { en: 'Hello, world!', de: 'Hallo, Welt!' }
|
|
331
|
+
} as const satisfies Translations
|
|
332
|
+
|
|
333
|
+
const dateTimeFormats = {
|
|
334
|
+
// override the default format
|
|
335
|
+
default: { dateStyle: 'short', timeStyle: 'short' },
|
|
336
|
+
// add a new custom format
|
|
337
|
+
custom: {
|
|
338
|
+
day: '2-digit',
|
|
339
|
+
month: '2-digit',
|
|
340
|
+
year: 'numeric',
|
|
341
|
+
weekday: 'short',
|
|
342
|
+
timeZone: 'UTC',
|
|
343
|
+
},
|
|
344
|
+
} as const satisfies DateTimeFormats
|
|
345
|
+
|
|
346
|
+
const numberFormats = {
|
|
347
|
+
speed: { style: 'unit', unit: 'kilometer-per-hour' },
|
|
348
|
+
} as const satisfies NumberFormats
|
|
265
349
|
|
|
266
350
|
declare module '@juit/vue-i18n' {
|
|
267
351
|
export interface I18nConfiguration {
|
|
268
|
-
|
|
269
|
-
|
|
352
|
+
languages: 'de' | 'en',
|
|
353
|
+
translationKeys: keyof typeof translations,
|
|
354
|
+
dateTimeFormats: keyof typeof dateTimeFormats,
|
|
355
|
+
numberFormats: keyof typeof numberFormats,
|
|
270
356
|
}
|
|
271
357
|
}
|
|
358
|
+
|
|
359
|
+
const app = createApp(MyApp).use(i18n, {
|
|
360
|
+
defaultLanguage: 'en',
|
|
361
|
+
translations,
|
|
362
|
+
dateTimeFormats,
|
|
363
|
+
numberFormats,
|
|
364
|
+
})
|
|
272
365
|
```
|
|
273
366
|
|
|
274
367
|
In the example above, if any of the translation objects in our app is missing
|
|
275
368
|
a language (either `en` or `de`), TypeScript will complain.
|
|
276
369
|
|
|
277
|
-
In the same way, if we pass any other string but `hello` to `t(...)` or
|
|
278
|
-
TypeScript will report the wrong key.
|
|
370
|
+
In the same way, if we pass any other string but `hello` to `t(...)` or
|
|
371
|
+
`tc(...)`, TypeScript will report the wrong key.
|
|
372
|
+
|
|
373
|
+
Also, date time format aliases will be augumented using the customizations
|
|
374
|
+
specified in `dateTimeFormats` and `numberFormats`.
|
|
279
375
|
|
|
280
376
|
|
|
281
377
|
## Legal Stuff
|
package/dist/index.d.ts
CHANGED
|
@@ -19,19 +19,48 @@ declare type BaseTranslation = ISOLanguage extends Language ? {
|
|
|
19
19
|
export declare type DateInput = Date | string | number | null | undefined;
|
|
20
20
|
|
|
21
21
|
/**
|
|
22
|
-
*
|
|
23
|
-
*
|
|
22
|
+
* All known date and time formats aliases.
|
|
23
|
+
*
|
|
24
|
+
* When the `I18nConfig` interface is properly merged with and its contains
|
|
25
|
+
* the `dateTimeFormats` property, this type will represent the list of
|
|
26
|
+
* date and time formats available to the `d(...)` method.
|
|
27
|
+
*
|
|
28
|
+
* When left unconfigured, this type will be `string`.
|
|
29
|
+
*/
|
|
30
|
+
export declare type DateTimeFormatAlias = ExtractConfig<I18nConfiguration, string, 'dateTimeFormats'> | 'default' | 'short' | 'medium' | 'long' | 'full' | 'date' | 'shortDate' | 'mediumDate' | 'longDate' | 'fullDate' | 'time' | 'shortTime' | 'mediumTime' | 'longTime' | 'fullTime';
|
|
31
|
+
|
|
32
|
+
/**
|
|
33
|
+
* Options to initialize the date and time format _aliases_ used by the
|
|
34
|
+
* translation system.
|
|
35
|
+
*
|
|
36
|
+
* The default aliases (each can be overridden) are:
|
|
24
37
|
*
|
|
25
|
-
*
|
|
26
|
-
*
|
|
27
|
-
*
|
|
28
|
-
*
|
|
38
|
+
* ```ts
|
|
39
|
+
* {
|
|
40
|
+
* default: { dateStyle: 'medium', timeStyle: 'medium' },
|
|
41
|
+
* short: { dateStyle: 'short', timeStyle: 'short' },
|
|
42
|
+
* medium: { dateStyle: 'medium', timeStyle: 'medium' },
|
|
43
|
+
* long: { dateStyle: 'long', timeStyle: 'long' },
|
|
44
|
+
* full: { dateStyle: 'full', timeStyle: 'full' },
|
|
45
|
+
*
|
|
46
|
+
* // date only formats
|
|
47
|
+
* date: { dateStyle: 'medium' },
|
|
48
|
+
* shortDate: { dateStyle: 'short' },
|
|
49
|
+
* mediumDate: { dateStyle: 'medium' },
|
|
50
|
+
* longDate: { dateStyle: 'long' },
|
|
51
|
+
* fullDate: { dateStyle: 'full' },
|
|
52
|
+
*
|
|
53
|
+
* // time only formats
|
|
54
|
+
* time: { timeStyle: 'medium' },
|
|
55
|
+
* shortTime: { timeStyle: 'short' },
|
|
56
|
+
* mediumTime: { timeStyle: 'medium' },
|
|
57
|
+
* longTime: { timeStyle: 'long' },
|
|
58
|
+
* fullTime: { timeStyle: 'full' },
|
|
59
|
+
* }
|
|
60
|
+
* ```
|
|
29
61
|
*/
|
|
30
62
|
export declare interface DateTimeFormats {
|
|
31
|
-
|
|
32
|
-
timeOnlyFormat?: Intl.DateTimeFormatOptions | Intl.DateTimeFormatOptions['timeStyle'];
|
|
33
|
-
dateTimeFormat?: Intl.DateTimeFormatOptions | (Intl.DateTimeFormatOptions['dateStyle'] & Intl.DateTimeFormatOptions['timeStyle']);
|
|
34
|
-
numberFormat?: Intl.NumberFormatOptions;
|
|
63
|
+
readonly [key: string]: Intl.DateTimeFormatOptions;
|
|
35
64
|
}
|
|
36
65
|
|
|
37
66
|
/** The language or locale to use at construction */
|
|
@@ -66,18 +95,40 @@ export declare function i18n(app: App, optionsOrLanguage: Language | I18nOptions
|
|
|
66
95
|
* Those are the arbitrary keys used to identify the
|
|
67
96
|
* messages to be translated with the `t` and `tc`
|
|
68
97
|
* methods of `Translator`.
|
|
98
|
+
* * `dateTimeFormats`: the date and time formats _aliases_ used by the
|
|
99
|
+
* application.
|
|
100
|
+
* * `numberFormats`: the number formats _aliases_ used by the application.
|
|
69
101
|
*
|
|
70
102
|
* To configure the types, follow the example below:
|
|
71
103
|
*
|
|
72
104
|
* ```ts
|
|
73
105
|
* const translations = {
|
|
74
106
|
* 'hello': { en: 'Hello, world!', de: 'Hallo, Welt!' }
|
|
75
|
-
* } as const satisfies
|
|
107
|
+
* } as const satisfies Translations
|
|
108
|
+
*
|
|
109
|
+
* const dateTimeFormats = {
|
|
110
|
+
* // override the default format
|
|
111
|
+
* default: { dateStyle: 'short', timeStyle: 'short' },
|
|
112
|
+
* // add a new custom format
|
|
113
|
+
* custom: {
|
|
114
|
+
* day: '2-digit',
|
|
115
|
+
* month: '2-digit',
|
|
116
|
+
* year: 'numeric',
|
|
117
|
+
* weekday: 'short',
|
|
118
|
+
* timeZone: 'UTC',
|
|
119
|
+
* },
|
|
120
|
+
* } as const satisfies DateTimeFormats
|
|
121
|
+
*
|
|
122
|
+
* const numberFormats = {
|
|
123
|
+
* speed: { style: 'unit', unit: 'kilometer-per-hour' },
|
|
124
|
+
* } as const satisfies NumberFormats
|
|
76
125
|
*
|
|
77
126
|
* declare module '@juit/vue-i18n' {
|
|
78
127
|
* export interface I18nConfiguration {
|
|
79
|
-
*
|
|
80
|
-
*
|
|
128
|
+
* languages: 'de' | 'en',
|
|
129
|
+
* translationKeys: keyof typeof translations,
|
|
130
|
+
* dateTimeFormats: keyof typeof dateTimeFormats,
|
|
131
|
+
* numberFormats: keyof typeof numberFormats,
|
|
81
132
|
* }
|
|
82
133
|
* }
|
|
83
134
|
* ```
|
|
@@ -89,11 +140,12 @@ export declare interface I18nConfiguration {
|
|
|
89
140
|
export declare interface I18nOptions {
|
|
90
141
|
defaultLanguage: DefaultLanguage;
|
|
91
142
|
translations?: Translations;
|
|
92
|
-
|
|
143
|
+
dateTimeFormats?: DateTimeFormats;
|
|
144
|
+
numberFormats?: NumberFormats;
|
|
93
145
|
}
|
|
94
146
|
|
|
95
|
-
/**
|
|
96
|
-
export declare type
|
|
147
|
+
/** All known ISO-3166-1 countries and their names */
|
|
148
|
+
export declare type ISOCountries = {
|
|
97
149
|
AD: 'Andorra';
|
|
98
150
|
AE: 'United Arab Emirates';
|
|
99
151
|
AF: 'Afghanistan';
|
|
@@ -344,14 +396,180 @@ export declare type IsoCountries = {
|
|
|
344
396
|
ZW: 'Zimbabwe';
|
|
345
397
|
};
|
|
346
398
|
|
|
347
|
-
/** Array of all known ISO-3166-1
|
|
348
|
-
export declare type ISOCountry = keyof
|
|
399
|
+
/** Array of all known ISO-3166-1 country names */
|
|
400
|
+
export declare type ISOCountry = keyof ISOCountries;
|
|
401
|
+
|
|
402
|
+
/** All known ISO-4217 currencies and their name */
|
|
403
|
+
declare type ISOCurrencies = {
|
|
404
|
+
AED: 'United Arab Emirates Dirham';
|
|
405
|
+
AFN: 'Afghan Afghani';
|
|
406
|
+
ALL: 'Albanian Lek';
|
|
407
|
+
AMD: 'Armenian Dram';
|
|
408
|
+
ANG: 'Netherlands Antillean Guilder';
|
|
409
|
+
AOA: 'Angolan Kwanza';
|
|
410
|
+
ARS: 'Argentine Peso';
|
|
411
|
+
AUD: 'Australian Dollar';
|
|
412
|
+
AWG: 'Aruban Florin';
|
|
413
|
+
AZN: 'Azerbaijani Manat';
|
|
414
|
+
BAM: 'Bosnia-Herzegovina Convertible Mark';
|
|
415
|
+
BBD: 'Barbadian Dollar';
|
|
416
|
+
BDT: 'Bangladeshi Taka';
|
|
417
|
+
BGN: 'Bulgarian Lev';
|
|
418
|
+
BHD: 'Bahraini Dinar';
|
|
419
|
+
BIF: 'Burundian Franc';
|
|
420
|
+
BMD: 'Bermudan Dollar';
|
|
421
|
+
BND: 'Brunei Dollar';
|
|
422
|
+
BOB: 'Bolivian Boliviano';
|
|
423
|
+
BRL: 'Brazilian Real';
|
|
424
|
+
BSD: 'Bahamian Dollar';
|
|
425
|
+
BTN: 'Bhutanese Ngultrum';
|
|
426
|
+
BWP: 'Botswanan Pula';
|
|
427
|
+
BYN: 'Belarusian Ruble';
|
|
428
|
+
BZD: 'Belize Dollar';
|
|
429
|
+
CAD: 'Canadian Dollar';
|
|
430
|
+
CDF: 'Congolese Franc';
|
|
431
|
+
CHF: 'Swiss Franc';
|
|
432
|
+
CLP: 'Chilean Peso';
|
|
433
|
+
CNY: 'Chinese Yuan';
|
|
434
|
+
COP: 'Colombian Peso';
|
|
435
|
+
CRC: 'Costa Rican Colón';
|
|
436
|
+
CUC: 'Cuban Convertible Peso';
|
|
437
|
+
CUP: 'Cuban Peso';
|
|
438
|
+
CVE: 'Cape Verdean Escudo';
|
|
439
|
+
CZK: 'Czech Koruna';
|
|
440
|
+
DJF: 'Djiboutian Franc';
|
|
441
|
+
DKK: 'Danish Krone';
|
|
442
|
+
DOP: 'Dominican Peso';
|
|
443
|
+
DZD: 'Algerian Dinar';
|
|
444
|
+
EGP: 'Egyptian Pound';
|
|
445
|
+
ERN: 'Eritrean Nakfa';
|
|
446
|
+
ETB: 'Ethiopian Birr';
|
|
447
|
+
EUR: 'Euro';
|
|
448
|
+
FJD: 'Fijian Dollar';
|
|
449
|
+
FKP: 'Falkland Islands Pound';
|
|
450
|
+
GBP: 'British Pound';
|
|
451
|
+
GEL: 'Georgian Lari';
|
|
452
|
+
GHS: 'Ghanaian Cedi';
|
|
453
|
+
GIP: 'Gibraltar Pound';
|
|
454
|
+
GMD: 'Gambian Dalasi';
|
|
455
|
+
GNF: 'Guinean Franc';
|
|
456
|
+
GTQ: 'Guatemalan Quetzal';
|
|
457
|
+
GYD: 'Guyanaese Dollar';
|
|
458
|
+
HKD: 'Hong Kong Dollar';
|
|
459
|
+
HNL: 'Honduran Lempira';
|
|
460
|
+
HRK: 'Croatian Kuna';
|
|
461
|
+
HTG: 'Haitian Gourde';
|
|
462
|
+
HUF: 'Hungarian Forint';
|
|
463
|
+
IDR: 'Indonesian Rupiah';
|
|
464
|
+
ILS: 'Israeli New Shekel';
|
|
465
|
+
INR: 'Indian Rupee';
|
|
466
|
+
IQD: 'Iraqi Dinar';
|
|
467
|
+
IRR: 'Iranian Rial';
|
|
468
|
+
ISK: 'Icelandic Króna';
|
|
469
|
+
JMD: 'Jamaican Dollar';
|
|
470
|
+
JOD: 'Jordanian Dinar';
|
|
471
|
+
JPY: 'Japanese Yen';
|
|
472
|
+
KES: 'Kenyan Shilling';
|
|
473
|
+
KGS: 'Kyrgystani Som';
|
|
474
|
+
KHR: 'Cambodian Riel';
|
|
475
|
+
KMF: 'Comorian Franc';
|
|
476
|
+
KPW: 'North Korean Won';
|
|
477
|
+
KRW: 'South Korean Won';
|
|
478
|
+
KWD: 'Kuwaiti Dinar';
|
|
479
|
+
KYD: 'Cayman Islands Dollar';
|
|
480
|
+
KZT: 'Kazakhstani Tenge';
|
|
481
|
+
LAK: 'Laotian Kip';
|
|
482
|
+
LBP: 'Lebanese Pound';
|
|
483
|
+
LKR: 'Sri Lankan Rupee';
|
|
484
|
+
LRD: 'Liberian Dollar';
|
|
485
|
+
LSL: 'Lesotho Loti';
|
|
486
|
+
LYD: 'Libyan Dinar';
|
|
487
|
+
MAD: 'Moroccan Dirham';
|
|
488
|
+
MDL: 'Moldovan Leu';
|
|
489
|
+
MGA: 'Malagasy Ariary';
|
|
490
|
+
MKD: 'Macedonian Denar';
|
|
491
|
+
MMK: 'Myanmar Kyat';
|
|
492
|
+
MNT: 'Mongolian Tugrik';
|
|
493
|
+
MOP: 'Macanese Pataca';
|
|
494
|
+
MRU: 'Mauritanian Ouguiya';
|
|
495
|
+
MUR: 'Mauritian Rupee';
|
|
496
|
+
MVR: 'Maldivian Rufiyaa';
|
|
497
|
+
MWK: 'Malawian Kwacha';
|
|
498
|
+
MXN: 'Mexican Peso';
|
|
499
|
+
MYR: 'Malaysian Ringgit';
|
|
500
|
+
MZN: 'Mozambican Metical';
|
|
501
|
+
NAD: 'Namibian Dollar';
|
|
502
|
+
NGN: 'Nigerian Naira';
|
|
503
|
+
NIO: 'Nicaraguan Córdoba';
|
|
504
|
+
NOK: 'Norwegian Krone';
|
|
505
|
+
NPR: 'Nepalese Rupee';
|
|
506
|
+
NZD: 'New Zealand Dollar';
|
|
507
|
+
OMR: 'Omani Rial';
|
|
508
|
+
PAB: 'Panamanian Balboa';
|
|
509
|
+
PEN: 'Peruvian Sol';
|
|
510
|
+
PGK: 'Papua New Guinean Kina';
|
|
511
|
+
PHP: 'Philippine Peso';
|
|
512
|
+
PKR: 'Pakistani Rupee';
|
|
513
|
+
PLN: 'Polish Zloty';
|
|
514
|
+
PYG: 'Paraguayan Guarani';
|
|
515
|
+
QAR: 'Qatari Riyal';
|
|
516
|
+
RON: 'Romanian Leu';
|
|
517
|
+
RSD: 'Serbian Dinar';
|
|
518
|
+
RUB: 'Russian Ruble';
|
|
519
|
+
RWF: 'Rwandan Franc';
|
|
520
|
+
SAR: 'Saudi Riyal';
|
|
521
|
+
SBD: 'Solomon Islands Dollar';
|
|
522
|
+
SCR: 'Seychellois Rupee';
|
|
523
|
+
SDG: 'Sudanese Pound';
|
|
524
|
+
SEK: 'Swedish Krona';
|
|
525
|
+
SGD: 'Singapore Dollar';
|
|
526
|
+
SHP: 'St. Helena Pound';
|
|
527
|
+
SLL: 'Sierra Leonean Leone (1964—2022)';
|
|
528
|
+
SOS: 'Somali Shilling';
|
|
529
|
+
SRD: 'Surinamese Dollar';
|
|
530
|
+
SSP: 'South Sudanese Pound';
|
|
531
|
+
STN: 'São Tomé & Príncipe Dobra';
|
|
532
|
+
SVC: 'Salvadoran Colón';
|
|
533
|
+
SYP: 'Syrian Pound';
|
|
534
|
+
SZL: 'Swazi Lilangeni';
|
|
535
|
+
THB: 'Thai Baht';
|
|
536
|
+
TJS: 'Tajikistani Somoni';
|
|
537
|
+
TMT: 'Turkmenistani Manat';
|
|
538
|
+
TND: 'Tunisian Dinar';
|
|
539
|
+
TOP: 'Tongan Paʻanga';
|
|
540
|
+
TRY: 'Turkish Lira';
|
|
541
|
+
TTD: 'Trinidad & Tobago Dollar';
|
|
542
|
+
TWD: 'New Taiwan Dollar';
|
|
543
|
+
TZS: 'Tanzanian Shilling';
|
|
544
|
+
UAH: 'Ukrainian Hryvnia';
|
|
545
|
+
UGX: 'Ugandan Shilling';
|
|
546
|
+
USD: 'US Dollar';
|
|
547
|
+
UYU: 'Uruguayan Peso';
|
|
548
|
+
UZS: 'Uzbekistani Som';
|
|
549
|
+
VES: 'Venezuelan Bolívar';
|
|
550
|
+
VND: 'Vietnamese Dong';
|
|
551
|
+
VUV: 'Vanuatu Vatu';
|
|
552
|
+
WST: 'Samoan Tala';
|
|
553
|
+
XAF: 'Central African CFA Franc';
|
|
554
|
+
XCD: 'East Caribbean Dollar';
|
|
555
|
+
XDR: 'Special Drawing Rights';
|
|
556
|
+
XOF: 'West African CFA Franc';
|
|
557
|
+
XPF: 'CFP Franc';
|
|
558
|
+
XSU: 'Sucre';
|
|
559
|
+
YER: 'Yemeni Rial';
|
|
560
|
+
ZAR: 'South African Rand';
|
|
561
|
+
ZMW: 'Zambian Kwacha';
|
|
562
|
+
ZWL: 'Zimbabwean Dollar (2009)';
|
|
563
|
+
};
|
|
564
|
+
|
|
565
|
+
/** All known ISO-4217 currency codes */
|
|
566
|
+
declare type ISOCurrency = keyof ISOCurrencies;
|
|
349
567
|
|
|
350
|
-
/** All known ISO-639-1
|
|
351
|
-
export declare type ISOLanguage = keyof
|
|
568
|
+
/** All known ISO-639-1 language codes */
|
|
569
|
+
export declare type ISOLanguage = keyof ISOLanguages;
|
|
352
570
|
|
|
353
|
-
/**
|
|
354
|
-
export declare type
|
|
571
|
+
/** All known ISO-639-1 languages and their name */
|
|
572
|
+
export declare type ISOLanguages = {
|
|
355
573
|
aa: 'Afar';
|
|
356
574
|
ab: 'Abkhazian';
|
|
357
575
|
ae: 'Avestan';
|
|
@@ -544,6 +762,36 @@ export declare type Language = ExtractConfig<I18nConfiguration, ISOLanguage, 'la
|
|
|
544
762
|
/** Create a _reactive_ translator object from the given options */
|
|
545
763
|
export declare function makeTranslator(options: I18nOptions): Translator;
|
|
546
764
|
|
|
765
|
+
/**
|
|
766
|
+
* All known number formats aliases.
|
|
767
|
+
*
|
|
768
|
+
* When the `I18nConfig` interface is properly merged with and its contains
|
|
769
|
+
* the `numberFormats` property, this type will represent the list of
|
|
770
|
+
* date and time formats available to the `n(...)` method.
|
|
771
|
+
*
|
|
772
|
+
* When left unconfigured, this type will be `string`.
|
|
773
|
+
*/
|
|
774
|
+
export declare type NumberFormatAlias = ExtractConfig<I18nConfiguration, string, 'numberFormats'> | 'default' | ISOCurrency;
|
|
775
|
+
|
|
776
|
+
/**
|
|
777
|
+
* Options to initialize the number format _aliases_ used by the translation
|
|
778
|
+
* system.
|
|
779
|
+
*
|
|
780
|
+
* The default aliases (each can be overridden) are:
|
|
781
|
+
*
|
|
782
|
+
* ```ts
|
|
783
|
+
* {
|
|
784
|
+
* default: { }, // use the default number format
|
|
785
|
+
* EUR: { style: 'currency', currency: 'EUR' },
|
|
786
|
+
* USD: { style: 'currency', currency: 'USD' },
|
|
787
|
+
* // ... all currency codes can be used as aliases
|
|
788
|
+
* }
|
|
789
|
+
* ```
|
|
790
|
+
*/
|
|
791
|
+
export declare interface NumberFormats {
|
|
792
|
+
readonly [key: string]: Intl.NumberFormatOptions;
|
|
793
|
+
}
|
|
794
|
+
|
|
547
795
|
/** Prettify our `Translations` exported type */
|
|
548
796
|
declare type PrettifyTranslation<T> = {
|
|
549
797
|
[l in keyof T]: T[l];
|
|
@@ -638,45 +886,21 @@ export declare interface Translator {
|
|
|
638
886
|
*/
|
|
639
887
|
tc(key: TranslationKey | Translation, n: number, params?: TranslationParams): string;
|
|
640
888
|
/**
|
|
641
|
-
* Format a number
|
|
889
|
+
* Format a number according to the current language.
|
|
642
890
|
*
|
|
643
|
-
*
|
|
644
|
-
*
|
|
891
|
+
* When `format` is provided, it will be used to configure the number format.
|
|
892
|
+
* This can be one of the aliases specified at initialization, or a
|
|
893
|
+
* fully-fledged `Intl.NumberFormatOptions` object.
|
|
645
894
|
*/
|
|
646
|
-
n(value?: number | bigint | null | undefined,
|
|
895
|
+
n(value?: number | bigint | null | undefined, format?: NumberFormatAlias | Intl.NumberFormatOptions): string;
|
|
647
896
|
/**
|
|
648
|
-
* Format
|
|
897
|
+
* Format date and time according to the current language.
|
|
649
898
|
*
|
|
650
|
-
* When `format` is provided, it will be used to configure the
|
|
651
|
-
*
|
|
899
|
+
* When `format` is provided, it will be used to configure the date and time
|
|
900
|
+
* format. This can be one of the aliases specified at initialization, or a
|
|
901
|
+
* fully-fledged `Intl.DateTimeFormatOptions` object.
|
|
652
902
|
*/
|
|
653
|
-
|
|
654
|
-
d: {
|
|
655
|
-
/**
|
|
656
|
-
* Format date and time according to the current language.
|
|
657
|
-
*
|
|
658
|
-
* When `style` is provided, it will be used to configure the date and time
|
|
659
|
-
* format, otherwise the default `format.dateTimeFormat` plugin option will
|
|
660
|
-
* be used.
|
|
661
|
-
*/
|
|
662
|
-
(date?: DateInput, style?: DateTimeFormats['dateTimeFormat']): string;
|
|
663
|
-
/**
|
|
664
|
-
* Format the date part (without time) according to the current language.
|
|
665
|
-
*
|
|
666
|
-
* When `style` is provided, it will be used to configure the date and time
|
|
667
|
-
* format, otherwise the default `format.dateOnlyFormat` plugin option will
|
|
668
|
-
* be used.
|
|
669
|
-
*/
|
|
670
|
-
date(date?: DateInput, style?: DateTimeFormats['dateOnlyFormat']): string;
|
|
671
|
-
/**
|
|
672
|
-
* Format the time part (without date) according to the current language.
|
|
673
|
-
*
|
|
674
|
-
* When `style` is provided, it will be used to configure the date and time
|
|
675
|
-
* format, otherwise the default `format.timeOnlyFormat` plugin option will
|
|
676
|
-
* be used.
|
|
677
|
-
*/
|
|
678
|
-
time(date?: DateInput, style?: DateTimeFormats['timeOnlyFormat']): string;
|
|
679
|
-
};
|
|
903
|
+
d(date?: DateInput, format?: DateTimeFormatAlias | Intl.DateTimeFormatOptions): string;
|
|
680
904
|
}
|
|
681
905
|
|
|
682
906
|
/** Retrieve the translator instance from the Vue app */
|
package/dist/index.js
CHANGED
|
@@ -1,126 +1,151 @@
|
|
|
1
|
-
import { shallowRef as
|
|
2
|
-
function
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
6
|
-
|
|
7
|
-
numberFormat: d = {}
|
|
8
|
-
} = e.formats || {}, l = T(new Intl.Locale(a)), m = z(() => {
|
|
9
|
-
const { language: t, region: r } = l.value, c = [t];
|
|
10
|
-
return r && c.unshift(`${t}-${r}`), t !== a && c.push(a), c;
|
|
11
|
-
});
|
|
12
|
-
function f(t, r = u) {
|
|
13
|
-
if (t == null || t === "") return "";
|
|
14
|
-
const c = t instanceof Date ? t : new Date(t), y = typeof r == "string" ? { dateStyle: r, timeStyle: r } : r;
|
|
15
|
-
return new Intl.DateTimeFormat(l.value, y).format(c);
|
|
1
|
+
import { shallowRef as h, watch as w, computed as b, reactive as $, warn as c, inject as T } from "vue";
|
|
2
|
+
function v(e) {
|
|
3
|
+
let n;
|
|
4
|
+
try {
|
|
5
|
+
n = new Intl.DisplayNames("en-US", { type: "language" }).of(e.language);
|
|
6
|
+
} catch {
|
|
16
7
|
}
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
8
|
+
if ((!n || n === e.language) && c(`Unknown language code "${e.language}"`), !e.region) return;
|
|
9
|
+
let o;
|
|
10
|
+
try {
|
|
11
|
+
o = new Intl.DisplayNames("en-US", { type: "region" }).of(e.region);
|
|
12
|
+
} catch {
|
|
22
13
|
}
|
|
23
|
-
|
|
14
|
+
(!o || o === "Unknown Region" || o === e.region) && c(`Unknown region code "${e.region}"`);
|
|
15
|
+
}
|
|
16
|
+
function D(e) {
|
|
17
|
+
const n = typeof e.defaultLanguage == "string" ? new Intl.Locale(e.defaultLanguage) : e.defaultLanguage, o = n.region ? `${n.language}-${n.region}` : n.language, a = e.translations ? structuredClone(e.translations) : {}, u = {
|
|
18
|
+
default: { dateStyle: "medium", timeStyle: "medium" },
|
|
19
|
+
short: { dateStyle: "short", timeStyle: "short" },
|
|
20
|
+
medium: { dateStyle: "medium", timeStyle: "medium" },
|
|
21
|
+
long: { dateStyle: "long", timeStyle: "long" },
|
|
22
|
+
full: { dateStyle: "full", timeStyle: "full" },
|
|
23
|
+
// date only formats
|
|
24
|
+
date: { dateStyle: "medium" },
|
|
25
|
+
shortDate: { dateStyle: "short" },
|
|
26
|
+
mediumDate: { dateStyle: "medium" },
|
|
27
|
+
longDate: { dateStyle: "long" },
|
|
28
|
+
fullDate: { dateStyle: "full" },
|
|
29
|
+
// time only formats
|
|
30
|
+
time: { timeStyle: "medium" },
|
|
31
|
+
shortTime: { timeStyle: "short" },
|
|
32
|
+
mediumTime: { timeStyle: "medium" },
|
|
33
|
+
longTime: { timeStyle: "long" },
|
|
34
|
+
fullTime: { timeStyle: "full" },
|
|
35
|
+
// overrides and custom formats
|
|
36
|
+
...e.dateTimeFormats
|
|
37
|
+
}, s = {
|
|
38
|
+
// Expand all currency codes into number formats for currencies
|
|
39
|
+
...Intl.supportedValuesOf("currency").reduce((t, r) => (t[r] = { style: "currency", currency: r }, t), {}),
|
|
40
|
+
// Add the default number format
|
|
41
|
+
default: {},
|
|
42
|
+
// Overrides and custom formats
|
|
43
|
+
...e.numberFormats
|
|
44
|
+
}, i = h(new Intl.Locale(o));
|
|
45
|
+
w(i, v, { immediate: !0 });
|
|
46
|
+
const f = b(() => {
|
|
47
|
+
const { language: t, region: r } = i.value, g = [t];
|
|
48
|
+
return r && g.unshift(`${t}-${r}`), t !== o && g.push(o), g;
|
|
49
|
+
}), l = {
|
|
24
50
|
get locale() {
|
|
25
|
-
return
|
|
51
|
+
return i.value;
|
|
26
52
|
},
|
|
27
53
|
set locale(t) {
|
|
28
|
-
|
|
54
|
+
i.value = t;
|
|
29
55
|
},
|
|
30
56
|
get language() {
|
|
31
|
-
return
|
|
57
|
+
return l.locale.language;
|
|
32
58
|
},
|
|
33
59
|
set language(t) {
|
|
34
|
-
|
|
60
|
+
l.locale = new Intl.Locale(t, { ...i.value });
|
|
35
61
|
},
|
|
36
62
|
get region() {
|
|
37
|
-
return
|
|
63
|
+
return l.locale.region;
|
|
38
64
|
},
|
|
39
65
|
set region(t) {
|
|
40
|
-
|
|
66
|
+
l.locale = new Intl.Locale(l.language, { ...l.locale, region: t || void 0 });
|
|
41
67
|
},
|
|
42
|
-
n(t, r) {
|
|
68
|
+
n(t, r = "default") {
|
|
43
69
|
if (t == null) return "";
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
return new Intl.NumberFormat(s.locale, { style: "currency", currency: c }).format(t);
|
|
47
|
-
} else {
|
|
48
|
-
const c = r || d;
|
|
49
|
-
return new Intl.NumberFormat(s.locale, c).format(t);
|
|
50
|
-
}
|
|
70
|
+
const g = typeof r == "string" ? s[r] : r;
|
|
71
|
+
return g || c(`NumberFormat alias "${r}" not found`), new Intl.NumberFormat(l.locale, g).format(t);
|
|
51
72
|
},
|
|
52
73
|
t(t, r) {
|
|
53
|
-
return
|
|
74
|
+
return l.tc(t, 1, r);
|
|
54
75
|
},
|
|
55
|
-
tc(t, r,
|
|
56
|
-
const
|
|
57
|
-
return
|
|
76
|
+
tc(t, r, g) {
|
|
77
|
+
const m = I(a, t, f.value), p = new Intl.NumberFormat(l.locale, s.default);
|
|
78
|
+
return k(m, Object.assign({ n: r }, g), p);
|
|
58
79
|
},
|
|
59
|
-
d
|
|
80
|
+
d(t, r = "default") {
|
|
81
|
+
if (t == null || t === "") return "";
|
|
82
|
+
const g = t instanceof Date ? t : new Date(t), m = typeof r == "string" ? u[r] : r;
|
|
83
|
+
return m || c(`DateTimeFormat alias "${r}" not found`), new Intl.DateTimeFormat(i.value, m).format(g);
|
|
84
|
+
}
|
|
60
85
|
};
|
|
61
|
-
return
|
|
86
|
+
return $(l);
|
|
62
87
|
}
|
|
63
|
-
const
|
|
64
|
-
function
|
|
88
|
+
const d = /* @__PURE__ */ new WeakMap();
|
|
89
|
+
function I(e, n, o) {
|
|
65
90
|
if (!n) throw new Error("No translation key specified");
|
|
66
91
|
if (typeof n == "string") {
|
|
67
|
-
let
|
|
68
|
-
|
|
69
|
-
let
|
|
70
|
-
|
|
71
|
-
let
|
|
72
|
-
if (!
|
|
73
|
-
let
|
|
74
|
-
|
|
92
|
+
let a = d.get(e);
|
|
93
|
+
a || d.set(e, a = {});
|
|
94
|
+
let u = a[o[0]];
|
|
95
|
+
u || (a[o[0]] = u = {});
|
|
96
|
+
let s = u[n];
|
|
97
|
+
if (!s) {
|
|
98
|
+
let i = e[n];
|
|
99
|
+
i || (c(`Translation key "${n}" not found`), i = { [o[o.length - 1]]: n }), s = y(i, o), u[n] = s;
|
|
75
100
|
}
|
|
76
|
-
return
|
|
101
|
+
return s;
|
|
77
102
|
} else
|
|
78
|
-
return
|
|
103
|
+
return y(n, o);
|
|
79
104
|
}
|
|
80
|
-
function
|
|
81
|
-
let
|
|
105
|
+
function y(e, n) {
|
|
106
|
+
let o;
|
|
82
107
|
for (const l of n)
|
|
83
|
-
if (
|
|
84
|
-
if (!
|
|
108
|
+
if (o = e[l], o) break;
|
|
109
|
+
if (!o) {
|
|
85
110
|
const l = n[n.length - 1];
|
|
86
|
-
return
|
|
111
|
+
return c(`Translation missing default language "${l}" in`, e), { zero: "", singular: "", plural: "" };
|
|
87
112
|
}
|
|
88
|
-
let
|
|
89
|
-
const
|
|
90
|
-
if (
|
|
91
|
-
const [l] =
|
|
92
|
-
|
|
93
|
-
} else if (
|
|
94
|
-
const [l,
|
|
95
|
-
|
|
113
|
+
let a;
|
|
114
|
+
const u = o.split(new RegExp("(?<!\\\\)(?:\\\\\\\\)*\\|"));
|
|
115
|
+
if (u.length === 1) {
|
|
116
|
+
const [l] = u;
|
|
117
|
+
a = { zero: l, singular: l, plural: l };
|
|
118
|
+
} else if (u.length === 2) {
|
|
119
|
+
const [l, t] = u;
|
|
120
|
+
a = { zero: t, singular: l, plural: t };
|
|
96
121
|
} else {
|
|
97
|
-
const [l,
|
|
98
|
-
|
|
122
|
+
const [l, t, r] = u;
|
|
123
|
+
a = { zero: l, singular: t, plural: r };
|
|
99
124
|
}
|
|
100
|
-
const { zero:
|
|
101
|
-
return { zero:
|
|
125
|
+
const { zero: s, singular: i, plural: f } = a;
|
|
126
|
+
return { zero: s.trim(), singular: i.trim(), plural: f.trim() };
|
|
102
127
|
}
|
|
103
|
-
function
|
|
104
|
-
const
|
|
105
|
-
let
|
|
106
|
-
for (const [
|
|
107
|
-
const
|
|
108
|
-
|
|
128
|
+
function k(e, n, o) {
|
|
129
|
+
const a = typeof n.n == "string" ? Number(n.n) : n.n;
|
|
130
|
+
let u = a === 0 ? e.zero : a === 1 ? e.singular : e.plural;
|
|
131
|
+
for (const [s, i] of Object.entries(n)) {
|
|
132
|
+
const f = typeof i == "number" ? o.format(i) : typeof i == "string" ? i : i ? String(i) : "", l = new RegExp(`(.|^)({\\s*${s}\\s*})`, "gi");
|
|
133
|
+
u = u.replaceAll(l, (t, r, g) => r === "\\" ? g : r + f);
|
|
109
134
|
}
|
|
110
|
-
return
|
|
135
|
+
return u.trim();
|
|
111
136
|
}
|
|
112
137
|
const S = Symbol.for("@juit/vue-i18n/translator");
|
|
113
|
-
function
|
|
114
|
-
const
|
|
115
|
-
return e.config.globalProperties.$t =
|
|
138
|
+
function L(e, n) {
|
|
139
|
+
const a = D(typeof n == "string" ? { defaultLanguage: n } : n);
|
|
140
|
+
return e.config.globalProperties.$t = a.t, e.config.globalProperties.$tc = a.tc, e.config.globalProperties.$n = a.n, e.config.globalProperties.$d = a.d, e.provide(S, a), e;
|
|
116
141
|
}
|
|
117
|
-
function
|
|
118
|
-
const e =
|
|
142
|
+
function z() {
|
|
143
|
+
const e = T(S);
|
|
119
144
|
if (!e) throw new Error("No translator found in the Vue app");
|
|
120
145
|
return e;
|
|
121
146
|
}
|
|
122
147
|
export {
|
|
123
|
-
|
|
124
|
-
|
|
148
|
+
L as i18n,
|
|
149
|
+
z as useTranslator
|
|
125
150
|
};
|
|
126
151
|
//# sourceMappingURL=index.js.map
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sources":["../lib/translator.ts","../lib/index.ts"],"sourcesContent":["import { computed, reactive, shallowRef, warn } from 'vue'\n\nimport type { DateTimeFormats, I18nOptions, ISOCountry, Translation, TranslationKey } from './index'\nimport type { ISOLanguage } from './iso-639'\n\n/* ===== TRANSLATOR INTERFACE =============================================== */\n\n/**\n * Parameters for the formatting of a translation.\n *\n * This type is used to pass parameters to the `t` and `tc` methods of the\n * translator, allowing for the interpolation of values into the translated\n * message.\n *\n * When the parameter value is a number, it will be formatted using the `n`\n * formatter before being interpolated into the message.\n */\nexport interface TranslationParams {\n [ key: string ]: string | number\n}\n\n/**\n * The date input type for date and time translation\n *\n * When the input is a non-empty `string`, or a `number`, it will be constructed\n * into a `Date` object before being formatted.\n *\n * When the input is `null`, `undefined`, or an empty string, formatted result\n * will be a simple empty string.\n */\nexport type DateInput = Date | string | number | null | undefined\n\n/**\n * The translator interface for the application.\n *\n * This interface provides methods to translate messages, format numbers, and\n * format dates and times.\n *\n * Configured instances can be accessed using the `useI18n()` composition\n * function, which will provide an instance of the translator.\n */\nexport interface Translator {\n /** The current ISO-639-1 language code used by this translator. */\n language: ISOLanguage\n /** The region (if any) used by thus translator to localize translations. */\n region: ISOCountry | undefined\n /** The `Locale` used by this translator (merges `language` and `region`) */\n locale: Intl.Locale\n\n /**\n * Return the (possibly parameterized) translation for the specified message\n * in the current language.\n *\n * Internally, this method uses the `tc(...)` function with `n=1`, in order to\n * avoid duplication of message keys\n */\n t(key: TranslationKey | Translation, params?: TranslationParams): string\n\n /**\n * Return the (possibly parameterized) translation for the specified message\n * in the current language, with pluralization.\n *\n * For pluralization, translation messages should be separated by the pipe\n * character, like in Vue I18N. Example:\n *\n * * `\" one apple | {n} apples \"` when _two_ translations are separated by a\n * pipe, the first will be used for singular, the second for zero or plural\n * * `\" no apples | one apple | {n} apples \"` when _three_ translations are\n * separated by a pipe, the first will be used for zero, the second for\n * singular, the second for zero or plural\n *\n * For convenience, the `{n}` message parameter will always be contextualized\n * with the number, unless overridden in the `params` themselves.\n */\n tc(key: TranslationKey | Translation, n: number, params?: TranslationParams): string\n\n /**\n * Format a number into a string according to the current language.\n *\n * If the `currency` parameter is set, the number will be formatted as a\n * currency value, using the specified currency symbol.\n */\n n(value?: number | bigint | null | undefined, currency?: string): string\n\n /**\n * Format a number into a string according to the current language.\n *\n * When `format` is provided, it will be used to configure the number format,\n * otherwise the default `format.numberFormat` plugin option will be used.\n */\n n(value?: number | bigint | null | undefined, format?: Intl.NumberFormatOptions): string\n\n d: {\n /**\n * Format date and time according to the current language.\n *\n * When `style` is provided, it will be used to configure the date and time\n * format, otherwise the default `format.dateTimeFormat` plugin option will\n * be used.\n */\n (date?: DateInput, style?: DateTimeFormats['dateTimeFormat']): string\n /**\n * Format the date part (without time) according to the current language.\n *\n * When `style` is provided, it will be used to configure the date and time\n * format, otherwise the default `format.dateOnlyFormat` plugin option will\n * be used.\n */\n date(date?: DateInput, style?: DateTimeFormats['dateOnlyFormat']): string\n /**\n * Format the time part (without date) according to the current language.\n *\n * When `style` is provided, it will be used to configure the date and time\n * format, otherwise the default `format.timeOnlyFormat` plugin option will\n * be used.\n */\n time(date?: DateInput, style?: DateTimeFormats['timeOnlyFormat']): string\n }\n}\n\n/* ===== TRANSLATOR IMPLEMENTATION ========================================== */\n\n/** Create a _reactive_ translator object from the given options */\nexport function makeTranslator(options: I18nOptions): Translator {\n // Default locale, parsing the default language\n const defaultLocale: Intl.Locale = typeof options.defaultLanguage === 'string' ?\n new Intl.Locale(options.defaultLanguage) :\n options.defaultLanguage\n\n // Normalized default language (language-REGION)\n const defaultLanguage = defaultLocale.region ?\n `${defaultLocale.language}-${defaultLocale.region}` :\n defaultLocale.language\n\n const translations: InternalTranslations = options.translations ? structuredClone(options.translations) : {}\n const {\n dateOnlyFormat = { dateStyle: 'medium' },\n timeOnlyFormat = { timeStyle: 'medium' },\n dateTimeFormat = { dateStyle: 'medium', timeStyle: 'medium' },\n numberFormat = {},\n } = options.formats || {}\n\n // Current locale, from the browser's language settings\n const locale = shallowRef(new Intl.Locale(defaultLanguage))\n\n // Language order, from the current locale\n const languages = computed(() => {\n const { language, region } = locale.value\n const order: string[] = [ language ]\n if (region) order.unshift(`${language}-${region}`)\n if (language !== defaultLanguage) order.push(defaultLanguage)\n return order as any as LanguageKeys\n })\n\n // Date-time translator, from the current locale\n function dateTime(input?: DateInput, style = dateTimeFormat): string {\n if ((input == null) || (input === '')) return ''\n\n const date = input instanceof Date ? input : new Date(input)\n const options = typeof style === 'string' ? { dateStyle: style, timeStyle: style } : style\n return new Intl.DateTimeFormat(locale.value, options).format(date)\n }\n\n // Date-only translator, from the current locale\n function dateOnly(input?: DateInput, style = dateOnlyFormat): string {\n const options = typeof style === 'string' ? { dateStyle: style } : style\n return dateTime(input, options)\n }\n\n // Time-only translator, from the current locale\n function timeOnly(input?: DateInput, style = timeOnlyFormat): string {\n const options = typeof style === 'string' ? { timeStyle: style } : style\n return dateTime(input, options)\n }\n\n // The translator object (non-reactive)\n const translator = {\n get locale() {\n return locale.value\n },\n\n set locale(value: Intl.Locale) {\n locale.value = value\n },\n\n get language(): ISOLanguage {\n return translator.locale.language as ISOLanguage\n },\n\n set language(value: ISOLanguage) {\n translator.locale = new Intl.Locale(value, { ...locale.value })\n },\n\n get region(): ISOCountry | undefined {\n return translator.locale.region as ISOCountry\n },\n\n set region(value: ISOCountry | undefined) {\n translator.locale = new Intl.Locale(translator.language, { ...translator.locale, region: value || undefined })\n },\n\n n(value?: number | bigint | null | undefined, currencyOrOptions?: string | Intl.NumberFormatOptions): string {\n if (value == null) return '' // null or undefined produces an empty string\n if (typeof currencyOrOptions === 'string') {\n const currency = currencyOrOptions\n return new Intl.NumberFormat(translator.locale, { style: 'currency', currency }).format(value)\n } else {\n const options = currencyOrOptions || numberFormat\n return new Intl.NumberFormat(translator.locale, options).format(value)\n }\n },\n\n t(translation: TranslationKey | Translation, params?: TranslationParams): string {\n return translator.tc(translation, 1, params)\n },\n\n tc(translation: TranslationKey | Translation, n: number, params?: TranslationParams): string {\n const template = getTemplate(translations, translation, languages.value)\n const format = new Intl.NumberFormat(translator.locale, numberFormat)\n return replaceParams(template, Object.assign({ n }, params), format)\n },\n\n d: Object.assign(dateTime, { date: dateOnly, time: timeOnly }),\n } as const satisfies Translator\n\n // Return a reactive version of the translator\n return reactive(translator)\n}\n\n/* ===== TRANSLATION UTILITIES ============================================== */\n\ntype LanguageKeys = readonly [ string, ...string[] ]\ntype InternalTranslation = Record<string, string | undefined>\ntype InternalTranslations = Record<string, InternalTranslation>\ntype TranslationTemplate = { zero: string, singular: string, plural: string }\n\n/**\n * Cached parsed translation templates.\n *\n * The keys are:\n * 1) the translations instance (WeakMap key)\n * 2) the current language (first entry in the order)\n * 3) the translation key\n */\nconst caches = new WeakMap<InternalTranslations, Record<string, Record<string, TranslationTemplate>>>()\n\n/** Get the `TranslationTemplate` for the translation or translation key. */\nfunction getTemplate(\n translations: InternalTranslations,\n translation: TranslationKey | Translation,\n languages: LanguageKeys,\n): TranslationTemplate {\n if (! translation) throw new Error('No translation key specified')\n\n if (typeof translation === 'string') {\n // Get the cache for the messages instance\n let cache = caches.get(translations)\n if (! cache) caches.set(translations, cache = {})\n\n // Get the cache for the current language\n let languageCache = cache[languages[0]]\n if (! languageCache) cache[languages[0]] = languageCache = {}\n\n // Get the translation from the cache or parse it\n let template = languageCache[translation]\n if (! template) {\n let object = translations[translation]\n if (! object) {\n warn(`Translation key \"${translation}\" not found`)\n object = { [languages[languages.length - 1]!]: translation }\n }\n template = extractTemplate(object, languages)\n languageCache[translation] = template\n }\n\n return template\n } else {\n return extractTemplate(translation, languages)\n }\n}\n\n/**\n * Extract a message from a translation, according to its locale, and split\n * it into its parsed components: zero, singular, and plural.\n */\nfunction extractTemplate(\n translation: InternalTranslation,\n languages: LanguageKeys,\n): TranslationTemplate {\n let string: string | undefined = undefined\n\n for (const language of languages) {\n string = translation[language as any]\n if (string) break\n }\n\n if (! string) {\n const language = languages[languages.length - 1]\n warn(`Translation missing default language \"${language}\" in`, translation)\n return { zero: '', singular: '', plural: '' }\n }\n\n let parsed: TranslationTemplate\n\n const translations = string.split(/(?<!\\\\)(?:\\\\\\\\)*\\|/)\n if (translations.length === 1) {\n const [ singular ] = translations\n parsed = { zero: singular!, singular: singular!, plural: singular! }\n } else if (translations.length === 2) {\n const [ singular, plural ] = translations\n parsed ={ zero: plural!, singular: singular!, plural: plural! }\n } else {\n const [ zero, singular, plural ] = translations\n parsed ={ zero: zero!, singular: singular!, plural: plural! }\n }\n\n const { zero, singular, plural } = parsed\n return { zero: zero.trim(), singular: singular.trim(), plural: plural.trim() }\n}\n\n/** Replace the parameters in a translation template, returning a string */\nfunction replaceParams(\n template: TranslationTemplate,\n params: TranslationParams,\n format: Intl.NumberFormat,\n): string {\n // Select the template to use based on the \"n\" (number) parameter\n const n = typeof params.n === 'string' ? Number(params.n) : params.n\n let formatted = n === 0 ? template.zero :\n n === 1 ? template.singular :\n template.plural\n\n // Replace any property `{ prop }` with the associated value\n for (const [ prop, value ] of Object.entries(params)) {\n const string =\n typeof value === 'number' ? format.format(value) :\n typeof value === 'string' ? value :\n value ? String(value) : ''\n\n // Expression matches `{ xxx }` where `{` is _not_ preceded by a '\\'\n const expr = new RegExp(`(.|^)({\\\\s*${prop}\\\\s*})`, 'gi')\n formatted = formatted.replaceAll(expr, (_, before, token) => {\n return before === '\\\\' ? token : before + string\n })\n }\n\n // All done!\n return formatted.trim()\n}\n","import { inject } from 'vue'\n\nimport { makeTranslator } from './translator'\n\nimport type { App } from 'vue'\nimport type { ISOLanguage } from './iso-639'\nimport type { Translator } from './translator'\n\n/* ===== REFERENCE LANGUAGES AND COUNTRIES ================================== */\n\nexport type * from './iso-3166'\nexport type * from './iso-639'\n\n/* ===== TYPES FOR DECLARATION MERGING ====================================== */\n\n/**\n * I18n Configuration interface (to be merged with the actual configuration).\n *\n * This interface (intentionally empty) is used to merge the actual per-app\n * configuration of the translation system, in order to provide the correct\n * types to the rest of the system.\n *\n * Two properties are expected to be defined in the configuration:\n *\n * * `languages`: the list of supported languages for the application. Those\n * are ISO 639-1 language codes, and when specified, _every_\n * translation _must_ include a translation for each.\n * * `translationKeys`: the list of translation keys known by the application.\n * Those are the arbitrary keys used to identify the\n * messages to be translated with the `t` and `tc`\n * methods of `Translator`.\n *\n * To configure the types, follow the example below:\n *\n * ```ts\n * const translations = {\n * 'hello': { en: 'Hello, world!', de: 'Hallo, Welt!' }\n * } as const satisfies TranslationsOptions\n *\n * declare module '@juit/vue-i18n' {\n * export interface I18nConfiguration {\n * translationKeys: keyof typeof translations\n * languages: 'de' | 'en'\n * }\n * }\n * ```\n */\nexport interface I18nConfiguration {\n // languages: 'de' | 'en'\n // translationKeys: 'hello'\n}\n\n/* ===== FROM CONFIG TO TRANSLATIONS ======================================== */\n\n/** Extract the value associated with key `K` from type `T` if it extends `R`, otherwise return `R` */\ntype ExtractConfig<T, R, K extends string> = T extends { [ X in K ]: infer V } ? V extends R ? V : R : R\n\n/** The languages configured in `I18nConfiguration` or all ISO languages */\nexport type Language = ExtractConfig<I18nConfiguration, ISOLanguage, 'languages'>\n\n/** Base translations, either required when languages are set or all optional */\ntype BaseTranslation = ISOLanguage extends Language ? {\n readonly [ key in ISOLanguage ]?: string\n} : {\n readonly [ key in Language ]: string\n}\n\n/** Extended translations, supporting multiple region of each language */\ntype ExtendedTranslation = {\n readonly [ key in `${Language}-${string}` ]?: string\n}\n\n/** Prettify our `Translations` exported type */\ntype PrettifyTranslation<T> = { [ l in keyof T ]: T[l] }\n\n/**\n * A type describing the translations for a given translation key.\n *\n * When the `I18nConfig` interface is properly merged with and its contains\n * the `languages` property, this type will represent the list of required\n * translation keys (languages) required for each translation.\n *\n * When left unconfigured, all ISO languages will be considered as optional.\n */\nexport type Translation = PrettifyTranslation<BaseTranslation & ExtendedTranslation>\n\n/**\n * All known translation keys.\n *\n * When the `I18nConfig` interface is properly merged with and its contains\n * the `translationKeys` property, this type will represent the list of\n * translations keys available to the `t(...)` and `tc(...)` methods.\n *\n * When left unconfigured, this type will be `string`.\n */\nexport type TranslationKey = ExtractConfig<I18nConfiguration, string, 'translationKeys'>\n\n/* ===== MODULE INITIALIZATION ============================================== */\n\n/* Export the translator types */\nexport type * from './translator'\n\n/**\n * Options to initialize the translations handled by the translation system.\n *\n * Shared translations are defined as a key-value pair, where the key is the\n * identifier of the translation, and the value is an object containing the\n * translations for each language.\n */\nexport interface Translations {\n readonly [ key: string ]: Translation\n}\n\n/**\n * Options to initialize the date and time formats used by the translation\n * system.\n *\n * * `dateTimeFormat`: the default format for times and dates used by `$d(...)`.\n * * `dateOnlyFormat`: the default format for dates used by `$d.date(...)`.\n * * `timeOnlyFormat`: the default format for times used by `$d.time(...)`.\n * * `numberFormat`: the default format for numbers used by `$n(...)`.\n */\nexport interface DateTimeFormats {\n dateOnlyFormat?: Intl.DateTimeFormatOptions | Intl.DateTimeFormatOptions['dateStyle']\n timeOnlyFormat?: Intl.DateTimeFormatOptions | Intl.DateTimeFormatOptions['timeStyle']\n dateTimeFormat?: Intl.DateTimeFormatOptions | (Intl.DateTimeFormatOptions['dateStyle'] & Intl.DateTimeFormatOptions['timeStyle'])\n numberFormat?: Intl.NumberFormatOptions\n}\n\n/** The language or locale to use at construction */\nexport type DefaultLanguage = ISOLanguage | `${ISOLanguage}-${string}` | Intl.Locale\n\n/** Options to initialize the I18n plugin */\nexport interface I18nOptions {\n defaultLanguage: DefaultLanguage,\n translations?: Translations,\n formats?: DateTimeFormats,\n}\n\n/* ===== PUBLIC METHODS ===================================================== */\n\n/** Symbol for Vue injections */\nconst injectionSymbol = Symbol.for('@juit/vue-i18n/translator')\n\n/** Initialize the translation system plugin */\nexport function i18n(app: App, optionsOrLanguage: Language | I18nOptions): App {\n const options = typeof optionsOrLanguage === 'string' ?\n { defaultLanguage: optionsOrLanguage } : optionsOrLanguage\n\n const translator = makeTranslator(options)\n\n app.config.globalProperties.$t = translator.t\n app.config.globalProperties.$tc = translator.tc\n app.config.globalProperties.$n = translator.n\n app.config.globalProperties.$d = translator.d\n\n app.provide(injectionSymbol, translator)\n return app\n}\n\n/** Retrieve the translator instance from the Vue app */\nexport function useTranslator(): Translator {\n const translator = inject(injectionSymbol)\n if (! translator) throw new Error('No translator found in the Vue app')\n return translator as Translator\n}\n\n/* ===== VUE EXTENSIONS ===================================================== */\n\n// Extension to the Vue component interface\ndeclare module 'vue' {\n interface ComponentCustomProperties {\n /** Translate a message according to the current language */\n $t: Translator['t']\n /**\n * Return the (possibly parameterized) translation for the specified message\n * in the current language, with pluralization.\n */\n $tc: Translator['tc']\n /** Format a number into a string according to the current language */\n $n: Translator['n']\n /**\n * Format date and time using the specified style (defaults to `medium`)\n * according to the current language\n */\n $d: Translator['d']\n }\n}\n"],"names":["makeTranslator","options","defaultLocale","defaultLanguage","translations","dateOnlyFormat","timeOnlyFormat","dateTimeFormat","numberFormat","locale","shallowRef","languages","computed","language","region","order","dateTime","input","style","date","dateOnly","timeOnly","translator","value","currencyOrOptions","currency","translation","params","n","template","getTemplate","format","replaceParams","reactive","caches","cache","languageCache","object","warn","extractTemplate","string","parsed","singular","plural","zero","formatted","prop","expr","_","before","token","injectionSymbol","i18n","app","optionsOrLanguage","useTranslator","inject"],"mappings":"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"}
|
|
1
|
+
{"version":3,"file":"index.js","sources":["../lib/translator.ts","../lib/index.ts"],"sourcesContent":["import { computed, reactive, shallowRef, warn, watch } from 'vue'\n\nimport type {\n DateTimeFormatAlias,\n DateTimeFormats,\n I18nOptions,\n ISOCountry,\n NumberFormatAlias,\n NumberFormats,\n Translation,\n TranslationKey,\n} from './index'\nimport type { ISOLanguage } from './iso-639'\n\n/* ===== TRANSLATOR INTERFACE =============================================== */\n\n/**\n * Parameters for the formatting of a translation.\n *\n * This type is used to pass parameters to the `t` and `tc` methods of the\n * translator, allowing for the interpolation of values into the translated\n * message.\n *\n * When the parameter value is a number, it will be formatted using the `n`\n * formatter before being interpolated into the message.\n */\nexport interface TranslationParams {\n [ key: string ]: string | number\n}\n\n/**\n * The date input type for date and time translation\n *\n * When the input is a non-empty `string`, or a `number`, it will be constructed\n * into a `Date` object before being formatted.\n *\n * When the input is `null`, `undefined`, or an empty string, formatted result\n * will be a simple empty string.\n */\nexport type DateInput = Date | string | number | null | undefined\n\n/**\n * The translator interface for the application.\n *\n * This interface provides methods to translate messages, format numbers, and\n * format dates and times.\n *\n * Configured instances can be accessed using the `useI18n()` composition\n * function, which will provide an instance of the translator.\n */\nexport interface Translator {\n /** The current ISO-639-1 language code used by this translator. */\n language: ISOLanguage\n /** The region (if any) used by thus translator to localize translations. */\n region: ISOCountry | undefined\n /** The `Locale` used by this translator (merges `language` and `region`) */\n locale: Intl.Locale\n\n /**\n * Return the (possibly parameterized) translation for the specified message\n * in the current language.\n *\n * Internally, this method uses the `tc(...)` function with `n=1`, in order to\n * avoid duplication of message keys\n */\n t(key: TranslationKey | Translation, params?: TranslationParams): string\n\n /**\n * Return the (possibly parameterized) translation for the specified message\n * in the current language, with pluralization.\n *\n * For pluralization, translation messages should be separated by the pipe\n * character, like in Vue I18N. Example:\n *\n * * `\" one apple | {n} apples \"` when _two_ translations are separated by a\n * pipe, the first will be used for singular, the second for zero or plural\n * * `\" no apples | one apple | {n} apples \"` when _three_ translations are\n * separated by a pipe, the first will be used for zero, the second for\n * singular, the second for zero or plural\n *\n * For convenience, the `{n}` message parameter will always be contextualized\n * with the number, unless overridden in the `params` themselves.\n */\n tc(key: TranslationKey | Translation, n: number, params?: TranslationParams): string\n\n /**\n * Format a number according to the current language.\n *\n * When `format` is provided, it will be used to configure the number format.\n * This can be one of the aliases specified at initialization, or a\n * fully-fledged `Intl.NumberFormatOptions` object.\n */\n n(value?: number | bigint | null | undefined, format?: NumberFormatAlias | Intl.NumberFormatOptions): string\n\n /**\n * Format date and time according to the current language.\n *\n * When `format` is provided, it will be used to configure the date and time\n * format. This can be one of the aliases specified at initialization, or a\n * fully-fledged `Intl.DateTimeFormatOptions` object.\n */\n d(date?: DateInput, format?: DateTimeFormatAlias | Intl.DateTimeFormatOptions): string\n}\n\n/* ===== TRANSLATOR IMPLEMENTATION ========================================== */\n\nfunction checkLocale(locale: Intl.Locale): void {\n let languageString: string | undefined\n try {\n languageString = new Intl.DisplayNames('en-US', { type: 'language' }).of(locale.language)\n /* v8 ignore next */\n } catch { /* */ }\n\n if ((! languageString) || (languageString === locale.language)) {\n warn(`Unknown language code \"${locale.language}\"`)\n }\n\n if (! locale.region) return\n\n let regionString: string | undefined\n try {\n regionString = new Intl.DisplayNames('en-US', { type: 'region' }).of(locale.region)\n /* v8 ignore next */\n } catch { /* */ }\n\n if ((! regionString) || (regionString === 'Unknown Region') || (regionString === locale.region)) {\n warn(`Unknown region code \"${locale.region}\"`)\n }\n}\n\n/** Create a _reactive_ translator object from the given options */\nexport function makeTranslator(options: I18nOptions): Translator {\n // Default locale, parsing the default language\n const defaultLocale: Intl.Locale = typeof options.defaultLanguage === 'string' ?\n new Intl.Locale(options.defaultLanguage) :\n options.defaultLanguage\n\n // Normalized default language (language-REGION)\n const defaultLanguage = defaultLocale.region ?\n `${defaultLocale.language}-${defaultLocale.region}` :\n defaultLocale.language\n\n const translations: InternalTranslations = options.translations ? structuredClone(options.translations) : {}\n const dateTimeFormats: DateTimeFormats = {\n default: { dateStyle: 'medium', timeStyle: 'medium' },\n short: { dateStyle: 'short', timeStyle: 'short' },\n medium: { dateStyle: 'medium', timeStyle: 'medium' },\n long: { dateStyle: 'long', timeStyle: 'long' },\n full: { dateStyle: 'full', timeStyle: 'full' },\n\n // date only formats\n date: { dateStyle: 'medium' },\n shortDate: { dateStyle: 'short' },\n mediumDate: { dateStyle: 'medium' },\n longDate: { dateStyle: 'long' },\n fullDate: { dateStyle: 'full' },\n\n // time only formats\n time: { timeStyle: 'medium' },\n shortTime: { timeStyle: 'short' },\n mediumTime: { timeStyle: 'medium' },\n longTime: { timeStyle: 'long' },\n fullTime: { timeStyle: 'full' },\n\n // overrides and custom formats\n ...options.dateTimeFormats,\n }\n\n const numberFormats: NumberFormats = {\n // Expand all currency codes into number formats for currencies\n ...Intl.supportedValuesOf('currency').reduce((formats, currency) => {\n formats[currency] = { style: 'currency', currency }\n return formats\n }, {} as Record<string, Intl.NumberFormatOptions>),\n // Add the default number format\n default: {},\n // Overrides and custom formats\n ...options.numberFormats,\n }\n\n // Current locale, from the browser's language settings\n const locale = shallowRef(new Intl.Locale(defaultLanguage))\n watch(locale, checkLocale, { immediate: true })\n // checkLocale(locale.value)\n\n // Language order, from the current locale\n const languages = computed(() => {\n const { language, region } = locale.value\n const order: string[] = [ language ]\n if (region) order.unshift(`${language}-${region}`)\n if (language !== defaultLanguage) order.push(defaultLanguage)\n return order as any as LanguageKeys\n })\n\n // The translator object (non-reactive)\n const translator = {\n get locale() {\n return locale.value\n },\n\n set locale(value: Intl.Locale) {\n locale.value = value\n },\n\n get language(): ISOLanguage {\n return translator.locale.language as ISOLanguage\n },\n\n set language(value: ISOLanguage) {\n translator.locale = new Intl.Locale(value, { ...locale.value })\n },\n\n get region(): ISOCountry | undefined {\n return translator.locale.region as ISOCountry\n },\n\n set region(value: ISOCountry | undefined) {\n translator.locale = new Intl.Locale(translator.language, { ...translator.locale, region: value || undefined })\n },\n\n n(value?: number | bigint | null | undefined, format: string | Intl.NumberFormatOptions = 'default'): string {\n if (value == null) return '' // null or undefined produces an empty string\n\n const options = typeof format === 'string' ? numberFormats[format] : format\n if (! options) warn(`NumberFormat alias \"${format}\" not found`)\n\n return new Intl.NumberFormat(translator.locale, options).format(value)\n },\n\n t(translation: TranslationKey | Translation, params?: TranslationParams): string {\n return translator.tc(translation, 1, params)\n },\n\n tc(translation: TranslationKey | Translation, n: number, params?: TranslationParams): string {\n const template = getTemplate(translations, translation, languages.value)\n const format = new Intl.NumberFormat(translator.locale, numberFormats['default'])\n return replaceParams(template, Object.assign({ n }, params), format)\n },\n\n d(input?: DateInput, format: DateTimeFormatAlias | Intl.DateTimeFormatOptions = 'default'): string {\n if ((input == null) || (input === '')) return ''\n\n const date = input instanceof Date ? input : new Date(input)\n const options = typeof format === 'string' ? dateTimeFormats[format] : format\n if (! options) warn(`DateTimeFormat alias \"${format}\" not found`)\n\n return new Intl.DateTimeFormat(locale.value, options).format(date)\n },\n } as const satisfies Translator\n\n // Return a reactive version of the translator\n return reactive(translator)\n}\n\n/* ===== TRANSLATION UTILITIES ============================================== */\n\ntype LanguageKeys = readonly [ string, ...string[] ]\ntype InternalTranslation = Record<string, string | undefined>\ntype InternalTranslations = Record<string, InternalTranslation>\ntype TranslationTemplate = { zero: string, singular: string, plural: string }\n\n/**\n * Cached parsed translation templates.\n *\n * The keys are:\n * 1) the translations instance (WeakMap key)\n * 2) the current language (first entry in the order)\n * 3) the translation key\n */\nconst caches = new WeakMap<InternalTranslations, Record<string, Record<string, TranslationTemplate>>>()\n\n/** Get the `TranslationTemplate` for the translation or translation key. */\nfunction getTemplate(\n translations: InternalTranslations,\n translation: TranslationKey | Translation,\n languages: LanguageKeys,\n): TranslationTemplate {\n if (! translation) throw new Error('No translation key specified')\n\n if (typeof translation === 'string') {\n // Get the cache for the messages instance\n let cache = caches.get(translations)\n if (! cache) caches.set(translations, cache = {})\n\n // Get the cache for the current language\n let languageCache = cache[languages[0]]\n if (! languageCache) cache[languages[0]] = languageCache = {}\n\n // Get the translation from the cache or parse it\n let template = languageCache[translation]\n if (! template) {\n let object = translations[translation]\n if (! object) {\n warn(`Translation key \"${translation}\" not found`)\n object = { [languages[languages.length - 1]!]: translation }\n }\n template = extractTemplate(object, languages)\n languageCache[translation] = template\n }\n\n return template\n } else {\n return extractTemplate(translation, languages)\n }\n}\n\n/**\n * Extract a message from a translation, according to its locale, and split\n * it into its parsed components: zero, singular, and plural.\n */\nfunction extractTemplate(\n translation: InternalTranslation,\n languages: LanguageKeys,\n): TranslationTemplate {\n let string: string | undefined = undefined\n\n for (const language of languages) {\n string = translation[language as any]\n if (string) break\n }\n\n if (! string) {\n const language = languages[languages.length - 1]\n warn(`Translation missing default language \"${language}\" in`, translation)\n return { zero: '', singular: '', plural: '' }\n }\n\n let parsed: TranslationTemplate\n\n const translations = string.split(/(?<!\\\\)(?:\\\\\\\\)*\\|/)\n if (translations.length === 1) {\n const [ singular ] = translations\n parsed = { zero: singular!, singular: singular!, plural: singular! }\n } else if (translations.length === 2) {\n const [ singular, plural ] = translations\n parsed ={ zero: plural!, singular: singular!, plural: plural! }\n } else {\n const [ zero, singular, plural ] = translations\n parsed ={ zero: zero!, singular: singular!, plural: plural! }\n }\n\n const { zero, singular, plural } = parsed\n return { zero: zero.trim(), singular: singular.trim(), plural: plural.trim() }\n}\n\n/** Replace the parameters in a translation template, returning a string */\nfunction replaceParams(\n template: TranslationTemplate,\n params: TranslationParams,\n format: Intl.NumberFormat,\n): string {\n // Select the template to use based on the \"n\" (number) parameter\n const n = typeof params.n === 'string' ? Number(params.n) : params.n\n let formatted = n === 0 ? template.zero :\n n === 1 ? template.singular :\n template.plural\n\n // Replace any property `{ prop }` with the associated value\n for (const [ prop, value ] of Object.entries(params)) {\n const string =\n typeof value === 'number' ? format.format(value) :\n typeof value === 'string' ? value :\n value ? String(value) : ''\n\n // Expression matches `{ xxx }` where `{` is _not_ preceded by a '\\'\n const expr = new RegExp(`(.|^)({\\\\s*${prop}\\\\s*})`, 'gi')\n formatted = formatted.replaceAll(expr, (_, before, token) => {\n return before === '\\\\' ? token : before + string\n })\n }\n\n // All done!\n return formatted.trim()\n}\n","import { inject } from 'vue'\n\nimport { makeTranslator } from './translator'\n\nimport type { App } from 'vue'\nimport type { ISOCurrency } from './iso-4217'\nimport type { ISOLanguage } from './iso-639'\nimport type { Translator } from './translator'\n\n/* ===== REFERENCE LANGUAGES AND COUNTRIES ================================== */\n\nexport type * from './iso-3166'\nexport type * from './iso-639'\n\n/* ===== TYPES FOR DECLARATION MERGING ====================================== */\n\n/**\n * I18n Configuration interface (to be merged with the actual configuration).\n *\n * This interface (intentionally empty) is used to merge the actual per-app\n * configuration of the translation system, in order to provide the correct\n * types to the rest of the system.\n *\n * Two properties are expected to be defined in the configuration:\n *\n * * `languages`: the list of supported languages for the application. Those\n * are ISO 639-1 language codes, and when specified, _every_\n * translation _must_ include a translation for each.\n * * `translationKeys`: the list of translation keys known by the application.\n * Those are the arbitrary keys used to identify the\n * messages to be translated with the `t` and `tc`\n * methods of `Translator`.\n * * `dateTimeFormats`: the date and time formats _aliases_ used by the\n * application.\n * * `numberFormats`: the number formats _aliases_ used by the application.\n *\n * To configure the types, follow the example below:\n *\n * ```ts\n * const translations = {\n * 'hello': { en: 'Hello, world!', de: 'Hallo, Welt!' }\n * } as const satisfies Translations\n *\n * const dateTimeFormats = {\n * // override the default format\n * default: { dateStyle: 'short', timeStyle: 'short' },\n * // add a new custom format\n * custom: {\n * day: '2-digit',\n * month: '2-digit',\n * year: 'numeric',\n * weekday: 'short',\n * timeZone: 'UTC',\n * },\n * } as const satisfies DateTimeFormats\n *\n * const numberFormats = {\n * speed: { style: 'unit', unit: 'kilometer-per-hour' },\n * } as const satisfies NumberFormats\n *\n * declare module '@juit/vue-i18n' {\n * export interface I18nConfiguration {\n * languages: 'de' | 'en',\n * translationKeys: keyof typeof translations,\n * dateTimeFormats: keyof typeof dateTimeFormats,\n * numberFormats: keyof typeof numberFormats,\n * }\n * }\n * ```\n */\nexport interface I18nConfiguration {\n // intentionally empty\n}\n\n/* ===== FROM CONFIG TO TRANSLATIONS ======================================== */\n\n/** Extract the value associated with key `K` from type `T` if it extends `R`, otherwise return `R` */\ntype ExtractConfig<T, R, K extends string> = T extends { [ X in K ]: infer V } ? V extends R ? V : R : R\n\n/** The languages configured in `I18nConfiguration` or all ISO languages */\nexport type Language = ExtractConfig<I18nConfiguration, ISOLanguage, 'languages'>\n\n/** Base translations, either required when languages are set or all optional */\ntype BaseTranslation = ISOLanguage extends Language ? {\n readonly [ key in ISOLanguage ]?: string\n} : {\n readonly [ key in Language ]: string\n}\n\n/** Extended translations, supporting multiple region of each language */\ntype ExtendedTranslation = {\n readonly [ key in `${Language}-${string}` ]?: string\n}\n\n/** Prettify our `Translations` exported type */\ntype PrettifyTranslation<T> = { [ l in keyof T ]: T[l] }\n\n/**\n * A type describing the translations for a given translation key.\n *\n * When the `I18nConfig` interface is properly merged with and its contains\n * the `languages` property, this type will represent the list of required\n * translation keys (languages) required for each translation.\n *\n * When left unconfigured, all ISO languages will be considered as optional.\n */\nexport type Translation = PrettifyTranslation<BaseTranslation & ExtendedTranslation>\n\n/**\n * All known translation keys.\n *\n * When the `I18nConfig` interface is properly merged with and its contains\n * the `translationKeys` property, this type will represent the list of\n * translations keys available to the `t(...)` and `tc(...)` methods.\n *\n * When left unconfigured, this type will be `string`.\n */\nexport type TranslationKey = ExtractConfig<I18nConfiguration, string, 'translationKeys'>\n\n/**\n * All known date and time formats aliases.\n *\n * When the `I18nConfig` interface is properly merged with and its contains\n * the `dateTimeFormats` property, this type will represent the list of\n * date and time formats available to the `d(...)` method.\n *\n * When left unconfigured, this type will be `string`.\n */\nexport type DateTimeFormatAlias = ExtractConfig<I18nConfiguration, string, 'dateTimeFormats'>\n | 'default' | 'short' | 'medium' | 'long' | 'full'\n | 'date' | 'shortDate' | 'mediumDate' | 'longDate' | 'fullDate'\n | 'time' | 'shortTime' | 'mediumTime' | 'longTime' | 'fullTime'\n\n/**\n * All known number formats aliases.\n *\n * When the `I18nConfig` interface is properly merged with and its contains\n * the `numberFormats` property, this type will represent the list of\n * date and time formats available to the `n(...)` method.\n *\n * When left unconfigured, this type will be `string`.\n */\nexport type NumberFormatAlias = ExtractConfig<I18nConfiguration, string, 'numberFormats'>\n | 'default' | ISOCurrency\n\n/* ===== MODULE INITIALIZATION ============================================== */\n\n/* Export the translator types */\nexport type * from './translator'\n\n/**\n * Options to initialize the translations handled by the translation system.\n *\n * Shared translations are defined as a key-value pair, where the key is the\n * identifier of the translation, and the value is an object containing the\n * translations for each language.\n */\nexport interface Translations {\n readonly [ key: string ]: Translation\n}\n\n/**\n * Options to initialize the date and time format _aliases_ used by the\n * translation system.\n *\n * The default aliases (each can be overridden) are:\n *\n * ```ts\n * {\n * default: { dateStyle: 'medium', timeStyle: 'medium' },\n * short: { dateStyle: 'short', timeStyle: 'short' },\n * medium: { dateStyle: 'medium', timeStyle: 'medium' },\n * long: { dateStyle: 'long', timeStyle: 'long' },\n * full: { dateStyle: 'full', timeStyle: 'full' },\n *\n * // date only formats\n * date: { dateStyle: 'medium' },\n * shortDate: { dateStyle: 'short' },\n * mediumDate: { dateStyle: 'medium' },\n * longDate: { dateStyle: 'long' },\n * fullDate: { dateStyle: 'full' },\n *\n * // time only formats\n * time: { timeStyle: 'medium' },\n * shortTime: { timeStyle: 'short' },\n * mediumTime: { timeStyle: 'medium' },\n * longTime: { timeStyle: 'long' },\n * fullTime: { timeStyle: 'full' },\n * }\n * ```\n */\nexport interface DateTimeFormats {\n readonly [ key: string ]: Intl.DateTimeFormatOptions\n}\n\n/**\n * Options to initialize the number format _aliases_ used by the translation\n * system.\n *\n * The default aliases (each can be overridden) are:\n *\n * ```ts\n * {\n * default: { }, // use the default number format\n * EUR: { style: 'currency', currency: 'EUR' },\n * USD: { style: 'currency', currency: 'USD' },\n * // ... all currency codes can be used as aliases\n * }\n * ```\n */\nexport interface NumberFormats {\n readonly [ key: string ]: Intl.NumberFormatOptions\n}\n\n/** The language or locale to use at construction */\nexport type DefaultLanguage = ISOLanguage | `${ISOLanguage}-${string}` | Intl.Locale\n\n/** Options to initialize the I18n plugin */\nexport interface I18nOptions {\n defaultLanguage: DefaultLanguage,\n translations?: Translations,\n dateTimeFormats?: DateTimeFormats,\n numberFormats?: NumberFormats,\n}\n\n/* ===== PUBLIC METHODS ===================================================== */\n\n/** Symbol for Vue injections */\nconst injectionSymbol = Symbol.for('@juit/vue-i18n/translator')\n\n/** Initialize the translation system plugin */\nexport function i18n(app: App, optionsOrLanguage: Language | I18nOptions): App {\n const options = typeof optionsOrLanguage === 'string' ?\n { defaultLanguage: optionsOrLanguage } : optionsOrLanguage\n\n const translator = makeTranslator(options)\n\n app.config.globalProperties.$t = translator.t\n app.config.globalProperties.$tc = translator.tc\n app.config.globalProperties.$n = translator.n\n app.config.globalProperties.$d = translator.d\n\n app.provide(injectionSymbol, translator)\n return app\n}\n\n/** Retrieve the translator instance from the Vue app */\nexport function useTranslator(): Translator {\n const translator = inject(injectionSymbol)\n if (! translator) throw new Error('No translator found in the Vue app')\n return translator as Translator\n}\n\n/* ===== VUE EXTENSIONS ===================================================== */\n\n// Extension to the Vue component interface\ndeclare module 'vue' {\n interface ComponentCustomProperties {\n /** Translate a message according to the current language */\n $t: Translator['t']\n /**\n * Return the (possibly parameterized) translation for the specified message\n * in the current language, with pluralization.\n */\n $tc: Translator['tc']\n /** Format a number into a string according to the current language */\n $n: Translator['n']\n /**\n * Format date and time using the specified style (defaults to `medium`)\n * according to the current language\n */\n $d: Translator['d']\n }\n}\n"],"names":["checkLocale","locale","languageString","warn","regionString","makeTranslator","options","defaultLocale","defaultLanguage","translations","dateTimeFormats","numberFormats","formats","currency","shallowRef","watch","languages","computed","language","region","order","translator","value","format","translation","params","n","template","getTemplate","replaceParams","input","date","reactive","caches","cache","languageCache","object","extractTemplate","string","parsed","singular","plural","zero","formatted","prop","expr","_","before","token","injectionSymbol","i18n","app","optionsOrLanguage","useTranslator","inject"],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@juit/vue-i18n",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.2.0",
|
|
4
4
|
"type": "module",
|
|
5
5
|
"exports": {
|
|
6
6
|
".": {
|
|
@@ -18,12 +18,12 @@
|
|
|
18
18
|
"vue": "^3.5.13"
|
|
19
19
|
},
|
|
20
20
|
"devDependencies": {
|
|
21
|
-
"@plugjs/eslint-plugin": "^0.3.
|
|
21
|
+
"@plugjs/eslint-plugin": "^0.3.12",
|
|
22
22
|
"@types/node": "<21",
|
|
23
23
|
"@vitejs/plugin-vue": "^5.2.1",
|
|
24
24
|
"@vitest/coverage-v8": "^3.0.5",
|
|
25
25
|
"@vue/test-utils": "^2.4.6",
|
|
26
|
-
"eslint": "^9.20.
|
|
26
|
+
"eslint": "^9.20.1",
|
|
27
27
|
"eslint-plugin-vue": "^9.32.0",
|
|
28
28
|
"jsdom": "^26.0.0",
|
|
29
29
|
"typescript": "<5.7",
|