Skip to content

Commit 484a888

Browse files
authored
feat: move i18n configuration (#263)
1 parent acfa145 commit 484a888

22 files changed

Lines changed: 4967 additions & 30 deletions

config/i18n.ts

Lines changed: 361 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,361 @@
1+
import type {
2+
DateTimeFormats,
3+
NumberFormats,
4+
PluralizationRule,
5+
PluralizationRules,
6+
} from '@intlify/core-base'
7+
import type { LocaleObject } from '@nuxtjs/i18n'
8+
9+
interface LocaleObjectData extends LocaleObject {
10+
numberFormats?: NumberFormats
11+
dateTimeFormats?: DateTimeFormats
12+
pluralRule?: PluralizationRule
13+
}
14+
15+
export const countryLocaleVariants: Record<string, (LocaleObjectData & { country?: boolean })[]> = {
16+
/*ar: [
17+
// ar.json contains ar-EG translations
18+
// { code: 'ar-DZ', name: 'Arabic (Algeria)' },
19+
// { code: 'ar-BH', name: 'Arabic (Bahrain)' },
20+
{ country: true, code: 'ar-EG', name: 'العربية' },
21+
// { code: 'ar-EG', name: 'Arabic (Egypt)' },
22+
// { code: 'ar-IQ', name: 'Arabic (Iraq)' },
23+
// { code: 'ar-JO', name: 'Arabic (Jordan)' },
24+
// { code: 'ar-KW', name: 'Arabic (Kuwait)' },
25+
// { code: 'ar-LB', name: 'Arabic (Lebanon)' },
26+
// { code: 'ar-LY', name: 'Arabic (Libya)' },
27+
// { code: 'ar-MA', name: 'Arabic (Morocco)' },
28+
// { code: 'ar-OM', name: 'Arabic (Oman)' },
29+
// { code: 'ar-QA', name: 'Arabic (Qatar)' },
30+
// { code: 'ar-SA', name: 'Arabic (Saudi Arabia)' },
31+
// { code: 'ar-SY', name: 'Arabic (Syria)' },
32+
// { code: 'ar-TN', name: 'Arabic (Tunisia)' },
33+
// { code: 'ar-AE', name: 'Arabic (U.A.E.)' },
34+
// { code: 'ar-YE', name: 'Arabic (Yemen)' },
35+
],*/
36+
en: [
37+
// en.json contains en-US translations
38+
{ country: true, code: 'en-US', name: 'English (US)' },
39+
// { code: 'en-CA', name: 'English (Canada)' },
40+
// { code: 'en-GB', name: 'English (UK)' },
41+
],
42+
/*ca: [
43+
// ca.json contains ca-ES translations
44+
// { code: 'ca-AD', name: 'Català (Andorra)' },
45+
{ country: true, code: 'ca-ES', name: 'Català (Espanya)' },
46+
{ code: 'ca-valencia', name: 'Català (valencià)' },
47+
// { code: 'ca-FR', name: 'Català (França)' },
48+
// { code: 'ca-IT', name: 'Català (Itàlia)' },
49+
],*/
50+
es: [
51+
// es.json contains es-ES translations
52+
// { code: 'es-AR', name: 'Español (Argentina)' },
53+
// { code: 'es-BO', name: 'Español (Bolivia)' },
54+
// { code: 'es-CL', name: 'Español (Chile)' },
55+
// { code: 'es-CO', name: 'Español (Colombia)' },
56+
// { code: 'es-CR', name: 'Español (Costa Rica)' },
57+
// { code: 'es-DO', name: 'Español (República Dominicana)' },
58+
// { code: 'es-EC', name: 'Español (Ecuador)' },
59+
{ country: true, code: 'es-ES', name: 'Español (España)' },
60+
// TODO: Support es-419, if we include spanish country variants remove also fix on utils/language.ts module
61+
{ code: 'es-419', name: 'Español (Latinoamérica)' },
62+
// { code: 'es-GT', name: 'Español (Guatemala)' },
63+
// { code: 'es-HN', name: 'Español (Honduras)' },
64+
// { code: 'es-MX', name: 'Español (México)' },
65+
// { code: 'es-NI', name: 'Español (Nicaragua)' },
66+
// { code: 'es-PA', name: 'Español (Panamá)' },
67+
// { code: 'es-PE', name: 'Español (Perú)' },
68+
// { code: 'es-PR', name: 'Español (Puerto Rico)' },
69+
// { code: 'es-SV', name: 'Español (El Salvador)' },
70+
// { code: 'es-US', name: 'Español (Estados Unidos)' },
71+
// { code: 'es-UY', name: 'Español (Uruguay)' },
72+
// { code: 'es-VE', name: 'Español (Venezuela)' },
73+
],
74+
/*pt: [
75+
// pt.json contains pt-PT translations
76+
{ country: true, code: 'pt-PT', name: 'Português (Portugal)' },
77+
{ code: 'pt-BR', name: 'Português (Brasil)' },
78+
],*/
79+
}
80+
81+
const locales: (Omit<LocaleObjectData, 'code'> & { code: string })[] = [
82+
{
83+
code: 'en',
84+
file: 'en.json',
85+
name: 'English',
86+
},
87+
/*{
88+
code: 'ar',
89+
file: 'ar.json',
90+
name: 'العربية',
91+
dir: 'rtl',
92+
pluralRule: (choice: number) => {
93+
const name = new Intl.PluralRules('ar-EG').select(choice)
94+
return { zero: 0, one: 1, two: 2, few: 3, many: 4, other: 5 }[name]
95+
},
96+
} satisfies LocaleObjectData,
97+
{
98+
code: 'ckb',
99+
file: 'ckb.json',
100+
name: 'کوردیی ناوەندی',
101+
dir: 'rtl',
102+
pluralRule: (choice: number) => {
103+
const name = new Intl.PluralRules('ckb').select(choice)
104+
return { zero: 0, one: 1, two: 2, few: 3, many: 4, other: 5 }[name]
105+
},
106+
} satisfies LocaleObjectData,
107+
{
108+
code: 'fa-IR',
109+
file: 'fa-IR.json',
110+
name: 'فارسی',
111+
dir: 'rtl',
112+
pluralRule: (choice: number) => {
113+
const name = new Intl.PluralRules('fa-IR').select(choice)
114+
return { zero: 0, one: 1, two: 2, few: 3, many: 4, other: 5 }[name]
115+
},
116+
} satisfies LocaleObjectData,
117+
{
118+
code: 'ca',
119+
file: 'ca.json',
120+
name: 'Català',
121+
},
122+
{
123+
code: 'el-GR',
124+
file: 'el-GR.json',
125+
name: 'Ελληνικά',
126+
},
127+
*/
128+
{
129+
code: 'de-DE',
130+
file: 'de-DE.json',
131+
name: 'Deutsch',
132+
},
133+
/*{
134+
code: 'hu-HU',
135+
file: 'hu-HU.json',
136+
name: 'Magyar',
137+
},*/
138+
{
139+
code: 'zh-CN',
140+
file: 'zh-CN.json',
141+
name: '简体中文',
142+
},
143+
/*{
144+
code: 'zh-TW',
145+
file: 'zh-TW.json',
146+
name: '繁體中文',
147+
},
148+
{
149+
code: 'ja-JP',
150+
file: 'ja-JP.json',
151+
name: '日本語',
152+
},
153+
{
154+
code: 'nl-NL',
155+
file: 'nl-NL.json',
156+
name: 'Nederlands',
157+
},*/
158+
{
159+
code: 'es',
160+
file: 'es.json',
161+
name: 'Español',
162+
},
163+
/*{
164+
code: 'eu-ES',
165+
file: 'eu-ES.json',
166+
name: 'Euskara',
167+
},*/
168+
{
169+
code: 'fr-FR',
170+
file: 'fr-FR.json',
171+
name: 'Français',
172+
},
173+
/*{
174+
code: 'ru-RU',
175+
file: 'ru-RU.json',
176+
name: 'Русский',
177+
pluralRule: (choice: number) => {
178+
const name = new Intl.PluralRules('ru-RU').select(choice)
179+
return { zero: 2 /!* not used *!/, one: 0, two: 1 /!* not used *!/, few: 1, many: 2, other: 3 }[name]
180+
},
181+
},
182+
{
183+
code: 'uk-UA',
184+
file: 'uk-UA.json',
185+
name: 'Українська',
186+
pluralRule: (choice: number) => {
187+
if (choice === 0)
188+
return 0
189+
190+
const name = new Intl.PluralRules('uk-UA').select(choice)
191+
return { zero: 0, one: 1, two: 0 /!* not used *!/, few: 2, many: 3, other: 4 }[name]
192+
},
193+
},
194+
{
195+
code: 'cs-CZ',
196+
file: 'cs-CZ.json',
197+
name: 'Česky',
198+
},
199+
{
200+
code: 'pl-PL',
201+
file: 'pl-PL.json',
202+
name: 'Polski',
203+
pluralRule: (choice: number) => {
204+
if (choice === 0)
205+
return 0
206+
207+
const name = new Intl.PluralRules('pl-PL').select(choice)
208+
return { zero: 0, one: 1, two: 0 /!* not used *!/, few: 2, many: 3, other: 4 }[name]
209+
},
210+
},
211+
{
212+
code: 'pt',
213+
file: 'pt.json',
214+
name: 'Português',
215+
},
216+
{
217+
code: 'tr-TR',
218+
file: 'tr-TR.json',
219+
name: 'Türkçe',
220+
},
221+
{
222+
code: 'id-ID',
223+
file: 'id-ID.json',
224+
name: 'Indonesia',
225+
},
226+
{
227+
code: 'fi',
228+
file: 'fi.json',
229+
name: 'Suomi',
230+
},
231+
{
232+
code: 'gl-ES',
233+
file: 'gl-ES.json',
234+
name: 'Galego',
235+
},
236+
{
237+
code: 'ko-KR',
238+
file: 'ko-KR.json',
239+
name: '한국어',
240+
},*/
241+
{
242+
code: 'it-IT',
243+
file: 'it-IT.json',
244+
name: 'Italiano',
245+
},
246+
/*{
247+
code: 'sv',
248+
file: 'sv.json',
249+
name: 'Svenska',
250+
},
251+
{
252+
code: 'th-TH',
253+
file: 'th-TH.json',
254+
name: 'ไทย',
255+
},
256+
{
257+
code: 'tl-PH',
258+
file: 'tl-PH.json',
259+
name: 'Tagalog',
260+
},
261+
{
262+
code: 'vi-VN',
263+
file: 'vi-VN.json',
264+
name: 'Tiếng Việt',
265+
},
266+
{
267+
code: 'cy',
268+
file: 'cy.json',
269+
name: 'Cymraeg',
270+
},*/
271+
]
272+
273+
function buildLocales() {
274+
const useLocales = Object.values(locales).reduce((acc, data) => {
275+
const locales = countryLocaleVariants[data.code]
276+
if (locales) {
277+
locales.forEach(l => {
278+
const entry: LocaleObjectData = {
279+
...data,
280+
code: l.code,
281+
name: l.name,
282+
files: [data.file as string, `${l.code}.json`],
283+
}
284+
delete entry.file
285+
acc.push(entry)
286+
})
287+
} else {
288+
acc.push(data as LocaleObjectData)
289+
}
290+
return acc
291+
}, [] as LocaleObjectData[])
292+
293+
return useLocales.sort((a, b) => a.code.localeCompare(b.code))
294+
}
295+
296+
export const currentLocales = buildLocales()
297+
298+
export const datetimeFormats = Object.values(currentLocales).reduce((acc, data) => {
299+
const dateTimeFormats = data.dateTimeFormats
300+
if (dateTimeFormats) {
301+
acc[data.code] = { ...dateTimeFormats }
302+
delete data.dateTimeFormats
303+
} else {
304+
acc[data.code] = {
305+
shortDate: {
306+
dateStyle: 'short',
307+
},
308+
short: {
309+
dateStyle: 'short',
310+
timeStyle: 'short',
311+
},
312+
long: {
313+
dateStyle: 'long',
314+
timeStyle: 'medium',
315+
},
316+
}
317+
}
318+
319+
return acc
320+
}, {} as DateTimeFormats)
321+
322+
export const numberFormats = Object.values(currentLocales).reduce((acc, data) => {
323+
const numberFormats = data.numberFormats
324+
if (numberFormats) {
325+
acc[data.code] = { ...numberFormats }
326+
delete data.numberFormats
327+
} else {
328+
acc[data.code] = {
329+
percentage: {
330+
style: 'percent',
331+
maximumFractionDigits: 1,
332+
},
333+
smallCounting: {
334+
style: 'decimal',
335+
maximumFractionDigits: 0,
336+
},
337+
kiloCounting: {
338+
notation: 'compact',
339+
compactDisplay: 'short',
340+
maximumFractionDigits: 1,
341+
},
342+
millionCounting: {
343+
notation: 'compact',
344+
compactDisplay: 'short',
345+
maximumFractionDigits: 2,
346+
},
347+
}
348+
}
349+
350+
return acc
351+
}, {} as NumberFormats)
352+
353+
export const pluralRules = Object.values(currentLocales).reduce((acc, data) => {
354+
const pluralRule = data.pluralRule
355+
if (pluralRule) {
356+
acc[data.code] = pluralRule
357+
delete data.pluralRule
358+
}
359+
360+
return acc
361+
}, {} as PluralizationRules)

i18n/i18n.config.ts

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
1+
import { currentLocales, datetimeFormats, numberFormats, pluralRules } from '../config/i18n'
2+
13
export default defineI18nConfig(() => {
24
return {
3-
fallbackLocale: 'en',
5+
availableLocales: currentLocales.map(l => l.code),
6+
fallbackLocale: 'en-US',
7+
fallbackWarn: true,
8+
missingWarn: true,
9+
datetimeFormats,
10+
numberFormats,
11+
pluralRules,
412
}
513
})

i18n/locales/en-US.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}

i18n/locales/es-419.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}

i18n/locales/es-ES.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
{}

0 commit comments

Comments
 (0)