i18n draft
This commit is contained in:
parent
0d95ee7757
commit
af3f40021f
|
@ -0,0 +1,108 @@
|
||||||
|
// 主题管理
|
||||||
|
import cx from 'classnames';
|
||||||
|
import React from 'react';
|
||||||
|
import hoistNonReactStatic from 'hoist-non-react-statics';
|
||||||
|
import {ExtractProps, Omit} from './types';
|
||||||
|
|
||||||
|
type translateFn = (str: string, ...args: any[]) => string;
|
||||||
|
|
||||||
|
interface LocaleConfig {
|
||||||
|
[propsName: string]: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
let defaultLocale: string = '';
|
||||||
|
|
||||||
|
const locales: {
|
||||||
|
[propName: string]: LocaleConfig;
|
||||||
|
} = {};
|
||||||
|
|
||||||
|
export function register(name: string, config: LocaleConfig) {
|
||||||
|
locales[name] = config;
|
||||||
|
}
|
||||||
|
|
||||||
|
const fns: {
|
||||||
|
[propName: string]: translateFn;
|
||||||
|
} = {};
|
||||||
|
|
||||||
|
// todo 支持参数
|
||||||
|
function format(str: string, ...args: any[]) {
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function makeTranslator(locale?: string): translateFn {
|
||||||
|
if (locale && fns[locale]) {
|
||||||
|
return fns[locale];
|
||||||
|
}
|
||||||
|
|
||||||
|
const fn = (str: string, ...args: any[]) => {
|
||||||
|
if (!str || typeof str !== 'string') {
|
||||||
|
return str;
|
||||||
|
}
|
||||||
|
|
||||||
|
const dict = locales[locale!] || locales[defaultLocale];
|
||||||
|
return format(dict[str] || str, ...args);
|
||||||
|
};
|
||||||
|
|
||||||
|
locale && (fns[locale] = fn);
|
||||||
|
return fn;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function setDefaultLocale(loacle: string) {
|
||||||
|
defaultLocale = loacle;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface LocaleProps {
|
||||||
|
locale: string;
|
||||||
|
translate: translateFn;
|
||||||
|
}
|
||||||
|
|
||||||
|
export const LocaleContext = React.createContext('locale');
|
||||||
|
|
||||||
|
export function localeable<
|
||||||
|
T extends React.ComponentType<LocaleProps & ExtractProps<T>>
|
||||||
|
>(ComposedComponent: T) {
|
||||||
|
type ComposedProps = JSX.LibraryManagedAttributes<T, ExtractProps<T>>;
|
||||||
|
type Props = Omit<ComposedProps, keyof LocaleProps> & {
|
||||||
|
locale?: string;
|
||||||
|
translate: (str: string, ...args: any[]) => string;
|
||||||
|
};
|
||||||
|
|
||||||
|
const result = hoistNonReactStatic(
|
||||||
|
class extends React.Component<Props> {
|
||||||
|
static displayName = `I18N(${
|
||||||
|
ComposedComponent.displayName || ComposedComponent.name
|
||||||
|
})`;
|
||||||
|
static contextType = LocaleContext;
|
||||||
|
static ComposedComponent = ComposedComponent;
|
||||||
|
|
||||||
|
render() {
|
||||||
|
const locale: string =
|
||||||
|
this.props.locale || this.context || defaultLocale;
|
||||||
|
const translate = makeTranslator(locale);
|
||||||
|
const injectedProps: {
|
||||||
|
locale: string;
|
||||||
|
translate: translateFn;
|
||||||
|
} = {
|
||||||
|
locale,
|
||||||
|
translate
|
||||||
|
};
|
||||||
|
|
||||||
|
return (
|
||||||
|
<LocaleContext.Provider value={locale}>
|
||||||
|
<ComposedComponent
|
||||||
|
{
|
||||||
|
...(this.props as any) /* todo, 解决这个类型问题 */
|
||||||
|
}
|
||||||
|
{...injectedProps}
|
||||||
|
/>
|
||||||
|
</LocaleContext.Provider>
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ComposedComponent
|
||||||
|
);
|
||||||
|
|
||||||
|
return result as typeof result & {
|
||||||
|
ComposedComponent: T;
|
||||||
|
};
|
||||||
|
}
|
Loading…
Reference in New Issue