diff --git a/README.md b/README.md index 24da5e3..10611fa 100644 --- a/README.md +++ b/README.md @@ -16,17 +16,16 @@ npm i --save @kne/react-intl ### 概述 -### 项目概述 - -react-intl是一个基于[react-intl](https://formatjs.io/docs/react-intl/)的React国际化封装组件库,提供了更简便的API和更灵活的使用方式,帮助开发者快速实现React应用的国际化功能。 +@kne/react-intl是一个基于[react-intl](https://formatjs.io/docs/react-intl/)的React国际化封装组件库,提供了更简便的API和更灵活的使用方式。它与@kne/global-context深度集成,支持从上下文获取语言设置,并提供了命名空间支持,使得国际化资源的管理更加方便。 ### 主要特性 -- **简化的API**:对react-intl进行封装,提供更简洁的API -- **命名空间支持**:支持通过命名空间组织和管理国际化消息 -- **上下文集成**:与@kne/global-context集成,支持通过上下文获取locale信息 -- **灵活的Provider创建**:提供createIntlProvider和createWithIntlProvider方法创建定制化的国际化Provider -- **消息加载器**:提供localeLoader用于加载和管理国际化消息 +- **简化的API**:封装react-intl,提供更简洁直观的API +- **命名空间支持**:支持通过命名空间隔离和组织国际化消息 +- **上下文集成**:与@kne/global-context无缝集成,支持从上下文获取locale +- **灵活的Provider**:支持多种方式创建和使用国际化Provider +- **动态消息加载**:支持运行时动态加载和更新国际化消息 +- **函数式组件支持**:支持将intl实例作为render props传递 ### 安装 @@ -36,13 +35,13 @@ npm install @kne/react-intl ### 基本使用 -#### 创建国际化Provider +#### 1. 使用createIntlProvider创建Provider ```jsx import {createIntlProvider} from '@kne/react-intl'; +// 方式1:使用对象配置 const IntlProvider = createIntlProvider({ - locale: 'zh-CN', defaultLocale: 'zh-CN', messages: { 'zh-CN': { @@ -51,79 +50,116 @@ const IntlProvider = createIntlProvider({ 'en-US': { hello: 'Hello, world!' } - } + }, + namespace: 'app' }); -// 在应用根组件中使用 -const App = () => { - return ( - - - - ); -}; +// 方式2:使用参数配置 +const IntlProvider = createIntlProvider('zh-CN', { + hello: '你好,世界!' +}, 'app'); + +// 在应用中使用 +const App = () => ( + + + +); + +// 使用render props获取intl实例 +const App = () => ( + + {(intl) => ( +
{intl.formatMessage({id: 'hello'})}
+ )} +
+); ``` -#### 使用国际化消息 +#### 2. 使用createWithIntlProvider创建高阶组件 ```jsx -import {FormattedMessage, useIntl} from '@kne/react-intl'; +import {createWithIntlProvider} from '@kne/react-intl'; -// 使用FormattedMessage组件 -const HelloComponent = () => { - return ; -}; +const withIntl = createWithIntlProvider({ + defaultLocale: 'zh-CN', + defaultMessage: { + hello: '你好,世界!' + }, + namespace: 'app' +}); -// 使用useIntl hook -const HelloFunctionComponent = () => { - const intl = useIntl(); - return
{intl.formatMessage({id: 'hello'})}
; -}; +// 包装组件 +const WrappedComponent = withIntl(YourComponent); ``` -#### 加载国际化消息 +#### 3. 动态加载国际化消息 ```jsx -import {localeLoader} from '@kne/react-intl'; +import {localeLoader, messagesLoader} from '@kne/react-intl'; -// 加载中文消息 +// 加载单个语言的消息 localeLoader('zh-CN', { - welcome: '欢迎使用我们的应用' + welcome: '欢迎使用' }, 'app'); -// 加载英文消息 -localeLoader('en-US', { - welcome: 'Welcome to our application' +// 批量加载多个语言的消息 +messagesLoader({ + 'zh-CN': { + welcome: '欢迎使用' + }, + 'en-US': { + welcome: 'Welcome' + } }, 'app'); ``` -### 与@kne/global-context集成 +#### 4. 与@kne/global-context集成 ```jsx -import {createIntl} from '@kne/react-intl'; -import {createGlobalContext} from '@kne/global-context'; +import {createIntlProvider} from '@kne/react-intl'; +import {createContext} from '@kne/global-context'; -const {useGlobalContext, GlobalContextProvider} = createGlobalContext(); +const {useContext, ContextProvider} = createContext(); -const {IntlProvider, useIntl, FormattedMessage} = createIntl({ - getLocale: () => { - const [globalContext] = useGlobalContext(); - return globalContext.locale; +const IntlProvider = createIntlProvider({ + defaultLocale: 'zh-CN', + messages: { + 'zh-CN': { + hello: '你好' + } } }); -// 在应用中使用 -const App = () => { - return ( - - - - - - ); -}; +// locale将从context中获取 +const App = () => ( + + + + + +); ``` +### 最佳实践 + +1. **使用命名空间**: + - 为不同模块使用不同的命名空间,避免消息键冲突 + - 保持命名空间结构清晰,便于管理 + +2. **动态加载**: + - 按需加载国际化消息,减少初始加载大小 + - 使用messagesLoader批量加载相关消息 + +3. **上下文集成**: + - 优先使用上下文管理locale + - 在需要时才通过props覆盖locale + +4. **消息组织**: + - 使用有意义的消息键 + - 保持消息结构扁平化 + - 适当使用消息格式化功能 + ### 示例 @@ -142,15 +178,43 @@ const App = () => { - 这里填写示例标题 - 这里填写示例说明 -- _CreateIntl(@kne/current-lib_create-intl)[import * as _CreateIntl from "@kne/create-intl"] +- _ReactIntl(@kne/current-lib_react-intl)[import * as _ReactIntl from "@kne/react-intl"],antd(antd) ```jsx -const {default:CreateIntl} = _CreateIntl; +const { createIntlProvider, FormattedMessage } = _ReactIntl; +const { Select, Flex } = antd; +const { useState } = React; + +const IntlProvider = createIntlProvider({ + defaultLocale: 'zh-CN', + messages: { + 'zh-CN': { + hello: '你好,世界!' + }, + 'en-US': { + hello: 'Hello, world!' + } + } +}); -const BaseExample = ()=>{ - return
- -
; +const BaseExample = () => { + const [locale, setLocale] = useState('zh-CN'); + return ( + + + + + + + ); }; render(); diff --git a/doc/example.json b/doc/example.json index 7948df5..09c534e 100644 --- a/doc/example.json +++ b/doc/example.json @@ -7,9 +7,13 @@ "code": "./base.js", "scope": [ { - "name": "_CreateIntl", - "packageName": "@kne/current-lib_create-intl", - "importStatement": "import * as _CreateIntl from \"@kne/create-intl\"" + "name": "_ReactIntl", + "packageName": "@kne/current-lib_react-intl", + "importStatement": "import * as _ReactIntl from \"@kne/react-intl\"" + }, + { + "name": "antd", + "packageName": "antd" } ] } diff --git a/doc/summary.md b/doc/summary.md index 93d80cd..820e908 100644 --- a/doc/summary.md +++ b/doc/summary.md @@ -1,14 +1,13 @@ -### 项目概述 - -react-intl是一个基于[react-intl](https://formatjs.io/docs/react-intl/)的React国际化封装组件库,提供了更简便的API和更灵活的使用方式,帮助开发者快速实现React应用的国际化功能。 +@kne/react-intl是一个基于[react-intl](https://formatjs.io/docs/react-intl/)的React国际化封装组件库,提供了更简便的API和更灵活的使用方式。它与@kne/global-context深度集成,支持从上下文获取语言设置,并提供了命名空间支持,使得国际化资源的管理更加方便。 ### 主要特性 -- **简化的API**:对react-intl进行封装,提供更简洁的API -- **命名空间支持**:支持通过命名空间组织和管理国际化消息 -- **上下文集成**:与@kne/global-context集成,支持通过上下文获取locale信息 -- **灵活的Provider创建**:提供createIntlProvider和createWithIntlProvider方法创建定制化的国际化Provider -- **消息加载器**:提供localeLoader用于加载和管理国际化消息 +- **简化的API**:封装react-intl,提供更简洁直观的API +- **命名空间支持**:支持通过命名空间隔离和组织国际化消息 +- **上下文集成**:与@kne/global-context无缝集成,支持从上下文获取locale +- **灵活的Provider**:支持多种方式创建和使用国际化Provider +- **动态消息加载**:支持运行时动态加载和更新国际化消息 +- **函数式组件支持**:支持将intl实例作为render props传递 ### 安装 @@ -18,13 +17,13 @@ npm install @kne/react-intl ### 基本使用 -#### 创建国际化Provider +#### 1. 使用createIntlProvider创建Provider ```jsx import {createIntlProvider} from '@kne/react-intl'; +// 方式1:使用对象配置 const IntlProvider = createIntlProvider({ - locale: 'zh-CN', defaultLocale: 'zh-CN', messages: { 'zh-CN': { @@ -33,75 +32,112 @@ const IntlProvider = createIntlProvider({ 'en-US': { hello: 'Hello, world!' } - } + }, + namespace: 'app' }); -// 在应用根组件中使用 -const App = () => { - return ( - - - - ); -}; +// 方式2:使用参数配置 +const IntlProvider = createIntlProvider('zh-CN', { + hello: '你好,世界!' +}, 'app'); + +// 在应用中使用 +const App = () => ( + + + +); + +// 使用render props获取intl实例 +const App = () => ( + + {(intl) => ( +
{intl.formatMessage({id: 'hello'})}
+ )} +
+); ``` -#### 使用国际化消息 +#### 2. 使用createWithIntlProvider创建高阶组件 ```jsx -import {FormattedMessage, useIntl} from '@kne/react-intl'; - -// 使用FormattedMessage组件 -const HelloComponent = () => { - return ; -}; - -// 使用useIntl hook -const HelloFunctionComponent = () => { - const intl = useIntl(); - return
{intl.formatMessage({id: 'hello'})}
; -}; +import {createWithIntlProvider} from '@kne/react-intl'; + +const withIntl = createWithIntlProvider({ + defaultLocale: 'zh-CN', + defaultMessage: { + hello: '你好,世界!' + }, + namespace: 'app' +}); + +// 包装组件 +const WrappedComponent = withIntl(YourComponent); ``` -#### 加载国际化消息 +#### 3. 动态加载国际化消息 ```jsx -import {localeLoader} from '@kne/react-intl'; +import {localeLoader, messagesLoader} from '@kne/react-intl'; -// 加载中文消息 +// 加载单个语言的消息 localeLoader('zh-CN', { - welcome: '欢迎使用我们的应用' + welcome: '欢迎使用' }, 'app'); -// 加载英文消息 -localeLoader('en-US', { - welcome: 'Welcome to our application' +// 批量加载多个语言的消息 +messagesLoader({ + 'zh-CN': { + welcome: '欢迎使用' + }, + 'en-US': { + welcome: 'Welcome' + } }, 'app'); ``` -### 与@kne/global-context集成 +#### 4. 与@kne/global-context集成 ```jsx -import {createIntl} from '@kne/react-intl'; -import {createGlobalContext} from '@kne/global-context'; +import {createIntlProvider} from '@kne/react-intl'; +import {createContext} from '@kne/global-context'; -const {useGlobalContext, GlobalContextProvider} = createGlobalContext(); +const {useContext, ContextProvider} = createContext(); -const {IntlProvider, useIntl, FormattedMessage} = createIntl({ - getLocale: () => { - const [globalContext] = useGlobalContext(); - return globalContext.locale; +const IntlProvider = createIntlProvider({ + defaultLocale: 'zh-CN', + messages: { + 'zh-CN': { + hello: '你好' + } } }); -// 在应用中使用 -const App = () => { - return ( - - - - - - ); -}; +// locale将从context中获取 +const App = () => ( + + + + + +); ``` + +### 最佳实践 + +1. **使用命名空间**: + - 为不同模块使用不同的命名空间,避免消息键冲突 + - 保持命名空间结构清晰,便于管理 + +2. **动态加载**: + - 按需加载国际化消息,减少初始加载大小 + - 使用messagesLoader批量加载相关消息 + +3. **上下文集成**: + - 优先使用上下文管理locale + - 在需要时才通过props覆盖locale + +4. **消息组织**: + - 使用有意义的消息键 + - 保持消息结构扁平化 + - 适当使用消息格式化功能 diff --git a/package.json b/package.json index 05ee869..5b678e7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@kne/react-intl", - "version": "0.1.8", + "version": "0.1.9", "description": "快捷地创建国际化中需要使用到的组件", "syntax": { "esmodules": true diff --git a/src/index.js b/src/index.js index 596dbb3..b316b09 100644 --- a/src/index.js +++ b/src/index.js @@ -1,5 +1,5 @@ import React, { forwardRef } from 'react'; -import localeLoader, { message } from './loader'; +import localeLoader, { message, messagesLoader } from './loader'; import { IntlProvider, createIntl as createIntlBase, useIntl } from 'react-intl'; import { useContext } from '@kne/global-context'; @@ -14,8 +14,18 @@ const withIntlProvider = WrappedComponents => ); }); -export const createIntlProvider = (defaultLocale, defaultMessage, namespace) => { +const argsParse = (...args) => { + if (typeof args[0] === 'object' && typeof args[0].defaultLocale === 'string') { + return Object.assign({}, args[0]); + } + + return { defaultLocale: args[0], defaultMessage: args[1], namespace: args[2] }; +}; + +export const createIntlProvider = (...args) => { + const { defaultLocale, defaultMessage, namespace, messages } = argsParse(...args); defaultMessage && localeLoader(defaultLocale, defaultMessage, namespace); + messages && messagesLoader(messages, namespace); const InnerComponent = ({ children }) => { const intl = useIntl(); return children(intl); @@ -31,8 +41,10 @@ export const createIntlProvider = (defaultLocale, defaultMessage, namespace) => }; }; -export const createWithIntlProvider = (defaultLocale, defaultMessage, namespace) => { +export const createWithIntlProvider = (...args) => { + const { defaultLocale, defaultMessage, namespace, messages } = argsParse(...args); defaultMessage && localeLoader(defaultLocale, defaultMessage, namespace); + messages && messagesLoader(messages, namespace); return WrappedComponents => forwardRef(({ locale: propsLocale, ...props }, ref) => { const context = useContext(); diff --git a/src/loader.js b/src/loader.js index ecf9895..584cb51 100644 --- a/src/loader.js +++ b/src/loader.js @@ -8,4 +8,13 @@ const loader = (locale, localeMessage, namespace) => { return message; }; +export const messagesLoader = (messages, namespace) => { + Object.keys(messages).forEach(locale => { + if (!message[locale]) { + message[locale] = {}; + } + message[locale][namespace || 'global'] = Object.assign({}, message[locale][namespace || 'global'], messages[locale]); + }); +}; + export default loader;