-
Notifications
You must be signed in to change notification settings - Fork 170
/
i18n.tsx
132 lines (123 loc) · 3.25 KB
/
i18n.tsx
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
import { i18n } from '@lingui/core'
import { I18nProvider } from '@lingui/react'
import { DEFAULT_LOCALE, SUPPORTED_LOCALES, SupportedLocale } from 'constants/locales'
import {
af,
ar,
ca,
cs,
da,
de,
el,
en,
es,
fi,
fr,
he,
hu,
id,
it,
ja,
ko,
nl,
no,
pl,
pt,
ro,
ru,
sr,
sv,
sw,
tr,
uk,
vi,
zh,
} from 'make-plural/plurals'
import { PluralCategory } from 'make-plural/plurals'
import { ReactNode, useEffect, useMemo } from 'react'
type LocalePlural = {
[key in SupportedLocale]: (n: number | string, ord?: boolean) => PluralCategory
}
const plurals: LocalePlural = {
'af-ZA': af,
'ar-SA': ar,
'ca-ES': ca,
'cs-CZ': cs,
'da-DK': da,
'de-DE': de,
'el-GR': el,
'en-US': en,
'es-ES': es,
'fi-FI': fi,
'fr-FR': fr,
'he-IL': he,
'hu-HU': hu,
'id-ID': id,
'it-IT': it,
'ja-JP': ja,
'ko-KR': ko,
'nl-NL': nl,
'no-NO': no,
'pl-PL': pl,
'pt-BR': pt,
'pt-PT': pt,
'ro-RO': ro,
'ru-RU': ru,
'sr-SP': sr,
'sv-SE': sv,
'sw-TZ': sw,
'tr-TR': tr,
'uk-UA': uk,
'vi-VN': vi,
'zh-CN': zh,
'zh-TW': zh,
pseudo: en,
}
export async function dynamicActivate(locale: SupportedLocale) {
i18n.loadLocaleData(locale, { plurals: () => plurals[locale] })
try {
const catalog = await import(`./locales/${locale}.js`)
// Bundlers will either export it as default or as a named export named default.
i18n.load(locale, catalog.messages || catalog.default.messages)
} catch {}
i18n.activate(locale)
}
interface ProviderProps {
locale?: SupportedLocale
forceRenderAfterLocaleChange?: boolean
onActivate?: (locale: SupportedLocale) => void
children: ReactNode
}
export function TestableProvider({ locale, forceRenderAfterLocaleChange, children }: ProviderProps) {
return <I18nProvider i18n={i18n}>{children}</I18nProvider>
}
export function Provider({ locale, forceRenderAfterLocaleChange = true, onActivate, children }: ProviderProps) {
const processedLocale = useMemo(() => {
if (locale && ![...SUPPORTED_LOCALES, 'pseudo'].includes(locale)) {
console.warn(`Unsupported locale: ${locale}. Falling back to ${DEFAULT_LOCALE}.`)
return DEFAULT_LOCALE
}
return locale ?? DEFAULT_LOCALE
}, [locale])
useEffect(() => {
dynamicActivate(processedLocale)
.then(() => onActivate?.(processedLocale))
.catch((error) => {
console.error('Failed to activate locale', processedLocale, error)
})
}, [processedLocale, onActivate])
// Initialize the locale immediately if it is DEFAULT_LOCALE, so that keys are shown while the translation messages load.
// This renders the translation _keys_, not the translation _messages_, which is only acceptable while loading the DEFAULT_LOCALE,
// as [there are no "default" messages](https://github.com/lingui/js-lingui/issues/388#issuecomment-497779030).
// See https://github.com/lingui/js-lingui/issues/1194#issuecomment-1068488619.
if (i18n.locale === undefined && locale === DEFAULT_LOCALE) {
i18n.loadLocaleData(DEFAULT_LOCALE, { plurals: () => plurals[DEFAULT_LOCALE] })
i18n.load(DEFAULT_LOCALE, {})
i18n.activate(DEFAULT_LOCALE)
}
return (
<I18nProvider forceRenderOnLocaleChange={forceRenderAfterLocaleChange} i18n={i18n}>
{children}
</I18nProvider>
)
}