-
Notifications
You must be signed in to change notification settings - Fork 2
/
index.tsx
153 lines (140 loc) · 3.36 KB
/
index.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
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
import * as React from 'react'
import tinyI18n, { TinyI18n } from 'tiny-i18n'
import useI18nCore, { Dictionary, UseI18nOptions } from '@rcp/use.i18n'
export * from '@rcp/use.i18n'
import toCompClass from '@rcp/util.tocompclass'
export const I18nContext = React.createContext<TinyI18n>(tinyI18n)
function useForceUpdate(): [any, () => void] {
const [v, set] = React.useState(1)
const update = React.useCallback(() => {
set(v => v + 1)
}, [])
return [v, update]
}
const wrapFn = (fn, forceUpdate) => {
if (!fn) {
return fn
}
return (...argv) => {
const result = fn(...argv)
forceUpdate()
return result
}
}
/**
* @public
* @param opts {{}}
* @param [opts.tinyI18n] {TinyI18n}
* @param [opts.onUpdate] {() => void}
* @param [opts.language] {string}
* @param [opts.locale] {{}}
* @example
* <I18nProvider tinyI18n={tinyI18n} language="zh-cn">
* {children}
* </I18nProvider>
*/
export function I18nProvider({
onUpdate,
tinyI18n,
children,
...props
}: UseI18nOptions & { children?: any; onUpdate?: () => void }) {
const i18n = useI18nCore(
{},
{
tinyI18n,
...props
}
)
const [v, _forceUpdate] = useForceUpdate()
const forceUpdate = React.useCallback(
() => {
_forceUpdate()
onUpdate && onUpdate()
},
[_forceUpdate]
)
const value = React.useMemo(
() => {
return {
...i18n,
origin: i18n,
setLanguage: wrapFn(i18n.setLanguage, forceUpdate),
extendDictionary: wrapFn(i18n.extendDictionary, forceUpdate),
setDictionary: wrapFn(i18n.setDictionary, forceUpdate)
}
},
[v, forceUpdate, i18n]
)
return <I18nContext.Provider value={value}>{children}</I18nContext.Provider>
}
/**
* @public
* @example
* <I18nConsumer>
* {tinyI18n => <h1>{tinyI18n.i18n('title')}</h1>}
* </I18nConsumer>
*/
export const I18nConsumer = I18nContext.Consumer
/**
* @public
* @example
* class AppView extends React.Component {
* render() {
* const tinyI18n = this.props.tinyI18n;
* return <h1>{tinyI18n.i18n('title')}</h1>
* }
* }
* const App = withTinyI18n(AppView)
*/
export const withTinyI18n = function<PropsType = any, RefType = any>(
Component
): React.ComponentClass<PropsType & { tinyI18n: TinyI18n }, RefType> {
Component = toCompClass(Component)
return class WithTinyI18n extends React.Component<PropsType & { tinyI18n: TinyI18n }, RefType> {
originRef = React.createRef<RefType>()
render() {
return (
<I18nConsumer>
{tinyI18n => <Component ref={this.originRef} tinyI18n={tinyI18n} {...this.props} />}
</I18nConsumer>
)
}
}
}
/**
* @public
* @example
* function App() {
* const tinyI18n = useI18nContext()
* }
*/
export function useI18nContext() {
return React.useContext(I18nContext)
}
/**
* @public
* @example
* function App() {
* const tinyI18n = useI18n({
* 'zh-cn': {
* hi: '你好'
* }
* })
*
* return <h1>{tinyI18n.i18n('title')}</h1>
* }
*/
export default function useI18n(presetDict: Dictionary, opts: UseI18nOptions = {}) {
const tinyI18n = useI18nContext()
const currentLocale = tinyI18n.getDictionary(opts.language == null ? void 0 : opts.language)
return useI18nCore(presetDict, {
// @ts-ignore
tinyI18n: tinyI18n.origin || tinyI18n,
...opts,
locale: {
...currentLocale,
...opts.locale
}
})
}