folder structure
- component.tsx
- lang/
---- index.ts
---- cn.ts
---- en.ts
// lang/index.ts
import { i18n } from 'store/i18n';
import * as cn from './cn';
import * as en from './en';
// cn en is a { Content:T } type
export const lang = i18n.createLangLoader({
cn,
en,
});
// lang/cn.ts
export const content = {
helloWorld: '你好世界!',
value: 1,
paragraphs: ['一', '二', '三'],
}
// export type content for `en.ts`
export type Content = typeof content;
// lang/en.ts
import type { Content } from './cn'
// use type Content for type checking
export const content: Content = {
helloWorld: 'Hello, World!',
value: 2,
paragraphs: ['one', 'two', 'three'],
}
// component.tsx
import { lang } from './lang'
const component = observer(() => (
<div>
{lang.helloText}
{lang.value}
{lang.paragraphs.join(' ')}
</div>
))
see also src\layouts\TitleBar\index.tsx
import { i18n } from 'store/i18n';
i18n.switchLang('en');
console.log(i18n.state.lang)
i18n.createLangLoader
accept a Record<string, { Content: T }>
as agrument。keys are language names, like cn
en
, values are language resource objects. The languages resource object has to be a object, but any key value are allowed. Type T
is the type Content
in import { Content } from './cn.ts'
. While there are more than one languages,, the language resource object in cn.ts
en.ts
has to be the same type (to prevent runtime error).
i18n.createLangLoader
returns a Proxy
, when access key on this proxy, it would proxy property access to corresponding languges. Such as lang.hello
would be cn.Content.hello
or en.Content.hello
.
To change language, change i18n.state.lang
. As it's observable
, whenever using something like lang.abc
in a component, it would access i18n.state.lang
in it's proxy logic, any component that are observer
would re-render automatically.
Usually, place language resources for a component (or a group of common used component) in a single i18n.createLangLoader
for better maintainability.