-
Notifications
You must be signed in to change notification settings - Fork 13
Expand file tree
/
Copy pathcontext.tsx
More file actions
101 lines (85 loc) · 3.66 KB
/
Copy pathcontext.tsx
File metadata and controls
101 lines (85 loc) · 3.66 KB
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
import { createContext, useContext, useLayoutEffect, useState, type ReactElement, type ReactNode } from "react";
import { type TranslationKey, type TranslationMessages, translationCatalogs } from "./catalog";
import {
formatCount,
formatDate,
formatDateTime,
formatNumber,
formatTime,
persistLocalePreference,
readStoredLocalePreference,
resolveLocaleState,
type ResolvedLocaleState,
translateMessage,
} from "./runtime";
import type { DateTimeValue, LocalePreference, PluralCountLabels, TranslationValues } from "./types";
type I18nContextValue = Readonly<ResolvedLocaleState & {
messages: TranslationMessages;
setLocalePreference: (localePreference: LocalePreference) => void;
t: (key: TranslationKey, values?: TranslationValues) => string;
formatDate: (value: DateTimeValue, options?: Readonly<Intl.DateTimeFormatOptions>) => string;
formatTime: (value: DateTimeValue, options?: Readonly<Intl.DateTimeFormatOptions>) => string;
formatDateTime: (value: DateTimeValue, options?: Readonly<Intl.DateTimeFormatOptions>) => string;
formatNumber: (value: number, options?: Readonly<Intl.NumberFormatOptions>) => string;
formatCount: (value: number, labels: PluralCountLabels) => string;
}>;
const I18nContext = createContext<I18nContextValue | null>(null);
type Props = Readonly<{
children: ReactNode;
}>;
export function I18nProvider(props: Props): ReactElement {
const { children } = props;
const [localePreference, setLocalePreferenceState] = useState<LocalePreference>(() => readStoredLocalePreference());
const resolvedLocaleState = resolveLocaleState(localePreference);
const messages = translationCatalogs[resolvedLocaleState.locale];
useLayoutEffect(() => {
document.documentElement.lang = resolvedLocaleState.locale;
document.documentElement.dir = resolvedLocaleState.direction;
}, [resolvedLocaleState.direction, resolvedLocaleState.locale]);
function setLocalePreference(nextLocalePreference: LocalePreference): void {
setLocalePreferenceState(nextLocalePreference);
persistLocalePreference(nextLocalePreference);
}
function t(key: TranslationKey, values?: TranslationValues): string {
return translateMessage(resolvedLocaleState.locale, key, values);
}
function formatDateValue(value: DateTimeValue, options?: Readonly<Intl.DateTimeFormatOptions>): string {
return formatDate(resolvedLocaleState.locale, value, options);
}
function formatTimeValue(value: DateTimeValue, options?: Readonly<Intl.DateTimeFormatOptions>): string {
return formatTime(resolvedLocaleState.locale, value, options);
}
function formatDateTimeValue(value: DateTimeValue, options?: Readonly<Intl.DateTimeFormatOptions>): string {
return formatDateTime(resolvedLocaleState.locale, value, options);
}
function formatNumberValue(value: number, options?: Readonly<Intl.NumberFormatOptions>): string {
return formatNumber(resolvedLocaleState.locale, value, options);
}
function formatCountValue(value: number, labels: PluralCountLabels): string {
return formatCount(resolvedLocaleState.locale, value, labels);
}
return (
<I18nContext.Provider
value={{
...resolvedLocaleState,
messages,
setLocalePreference,
t,
formatDate: formatDateValue,
formatTime: formatTimeValue,
formatDateTime: formatDateTimeValue,
formatNumber: formatNumberValue,
formatCount: formatCountValue,
}}
>
{children}
</I18nContext.Provider>
);
}
export function useI18n(): I18nContextValue {
const contextValue = useContext(I18nContext);
if (contextValue === null) {
throw new Error("useI18n must be used within I18nProvider");
}
return contextValue;
}