From af3f40021f7ce285843ec5b3a7a499512ee1ac59 Mon Sep 17 00:00:00 2001 From: 2betop <2betop.cn@gmail.com> Date: Mon, 1 Jun 2020 20:54:41 +0800 Subject: [PATCH] i18n draft --- src/locale.tsx | 108 ++++++++++++++++++++++++++++++++++++++++++++ src/locale/en_UK.ts | 0 2 files changed, 108 insertions(+) create mode 100644 src/locale.tsx create mode 100644 src/locale/en_UK.ts diff --git a/src/locale.tsx b/src/locale.tsx new file mode 100644 index 00000000..f6a3aa75 --- /dev/null +++ b/src/locale.tsx @@ -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> +>(ComposedComponent: T) { + type ComposedProps = JSX.LibraryManagedAttributes>; + type Props = Omit & { + locale?: string; + translate: (str: string, ...args: any[]) => string; + }; + + const result = hoistNonReactStatic( + class extends React.Component { + 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 ( + + + + ); + } + }, + ComposedComponent + ); + + return result as typeof result & { + ComposedComponent: T; + }; +} diff --git a/src/locale/en_UK.ts b/src/locale/en_UK.ts new file mode 100644 index 00000000..e69de29b