UNPKG

@ui18n/react

Version:

⚛️ Smart React internationalization with hooks, Server Components, and concurrent features - built for React 18+

772 lines (652 loc) 18.2 kB
# @ui18n/react 🌍 **React集成包** - 为React应用提供智能国际化支持 [![npm version](https://badge.fury.io/js/%40ui18n%2Freact.svg)](https://badge.fury.io/js/%40ui18n%2Freact) [![TypeScript](https://img.shields.io/badge/TypeScript-Ready-blue.svg)](https://www.typescriptlang.org/) [![React](https://img.shields.io/badge/React-18+-61dafb.svg)](https://reactjs.org/) ## 状态与范围 - 稳定内容(Stable):核心 UI 组件、上下文与常规 Hooks/插件。 - 实验接口(Incubating):Translator 依赖注入(ExperimentalTranslatorProvider、useTranslator)。用于“代码层切换后端适配器”,不提供界面化切换。接口可能演进,详见: - packages/react/docs/INCUBATING_TRANSLATOR.md - 选择与稳定性说明:docs/UI_PACKAGES_OVERVIEW.md - 若仅需“语言入口 UI”,推荐使用独立稳定包 @ui18n/selector-react(不绑定后端)。 ## ✨ 特性 - 🎯 **React专用设计** - 完美集成React生态系统 - 🪝 **强大的Hooks** - `useUI18n`, `useTranslation` 等 - 🧩 **智能UI组件** - 完全可定制的`<LanguageSelector>`组件 - 🔄 **Context支持** - 全局状态管理,避免prop drilling - ⚡ **性能优化** - 智能缓存,批量翻译,懒加载 - 🎨 **TypeScript完整支持** - 类型安全的翻译体验 - 🔌 **插件化架构** - 无障碍、移动端、主题等可选功能模块 - 🌍 **智能语言检测** - 自动识别用户系统语言并预填充 - 📱 **移动端优化** - 响应式设计,触摸手势,底部弹出选择器 ## 🚀 快速开始 ### 安装 ```bash npm install @ui18n/react @ui18n/core # 或 yarn add @ui18n/react @ui18n/core # 或 pnpm add @ui18n/react @ui18n/core ``` ### 基础使用 ```tsx import React from 'react'; import { UI18nProvider, useUI18n, LanguageSelector } from '@ui18n/react'; import { createUI18n } from '@ui18n/core'; // 1. 创建UI18n实例(自托管模式) const ui18n = createUI18n({ defaultLanguage: 'zh-CN', aiProvider: { type: 'openai', // 支持多种AI提供商 apiKey: 'your-openai-api-key' } }); // 2. 应用根组件 function App() { return ( <UI18nProvider ui18n={ui18n}> <HomePage /> </UI18nProvider> ); } // 3. 使用智能语言选择器 function HomePage() { const { t, currentLanguage } = useUI18n(); const [welcome, setWelcome] = React.useState(''); const [intro, setIntro] = React.useState(''); React.useEffect(() => { // t() 返回 Promise,需要异步处理 t('欢迎使用UI18n').then(setWelcome); t('这是一个智能国际化解决方案').then(setIntro); }, [currentLanguage]); return ( <div> {/* 智能语言选择器 - 支持中英文按钮 + 搜索框 */} <LanguageSelector defaultLanguages={['zh-CN', 'en']} showSearchBox={true} autoDetectSystemLanguage={true} /> <h1>{welcome}</h1> <p>{intro}</p> <p>当前语言: {currentLanguage}</p> </div> ); } export default App; ``` ## Incubating:Translator 依赖注入(代码层切换适配器) 仅用于通过“代码选择适配器 A/B”实现后端可插拔,不提供界面化切换。完整说明见 packages/react/docs/INCUBATING_TRANSLATOR.md。 最小用法示例(片段): ```tsx import { ExperimentalTranslatorProvider, useTranslator } from '@ui18n/react'; const adapterA = { translate: async ({ text, to }: any) => (to === 'zh-CN' ? '你好,世界' : `[A:${to}] ${text}`) }; const adapterB = { translate: async ({ text, to }: any) => (to === 'zh-CN' ? '世界你好' : `[B:${to}] ${text}`) }; // 代码层选择一个适配器(示例固定为 A) const translator = adapterA; function App() { return ( <ExperimentalTranslatorProvider translator={translator} initialLanguage="en"> <Inner /> </ExperimentalTranslatorProvider> ); } function Inner() { const { translate } = useTranslator(); // ... } ``` 提示:如果你只需要“语言入口 UI”,请优先选择稳定的 @ui18n/selector-react,详见 docs/UI_PACKAGES_OVERVIEW.md。 ## 完全自定义UI ```tsx import React from 'react'; import { LanguageSelector } from '@ui18n/react'; function CustomLanguageSelector() { return ( <LanguageSelector defaultLanguages={['zh-CN', 'en']} showSearchBox={true} className="my-custom-selector" // 自定义语言按钮渲染 renderLanguageButton={(lang, onClick) => ( <button className="my-custom-button" onClick={onClick} > {lang === 'zh-CN' ? '中文' : 'English'} </button> )} // 自定义搜索框渲染 renderSearchBox={(props) => ( <input {...props} className="my-custom-search" placeholder="搜索语言..." /> )} /> ); } ``` ## 🔌 插件架构 UI18n React包提供了强大的插件系统,让你可以按需加载功能模块: ### 无障碍插件 ```tsx import { useAccessibility } from '@ui18n/react'; function AccessibleLanguageSelector() { const { handleKeyDown, getAriaProps, getContrastClass } = useAccessibility({ enableKeyboardNavigation: true, enableScreenReader: true, enableHighContrast: true, ariaLabels: { languageSelector: '语言选择器', searchBox: '搜索语言', languageButton: (lang) => `选择${lang}语言` } }); return ( <div className={getContrastClass()} {...getAriaProps('selector')}> <LanguageSelector /> </div> ); } ``` ### 移动端插件 ```tsx import { useMobile } from '@ui18n/react'; function MobileLanguageSelector() { const { isMobile, getMobileClasses, BottomSheet, isBottomSheetOpen, setIsBottomSheetOpen } = useMobile({ enableMobileAdaptation: true, mobileBreakpoint: 768, enableTouchGestures: true, useBottomSheet: true }); return ( <div className={getMobileClasses()}> {isMobile ? ( <BottomSheet> <LanguageSelector /> </BottomSheet> ) : ( <LanguageSelector /> )} </div> ); } ``` ### 主题插件 ```tsx import { ThemeProvider, useTheme, getThemeStyles } from '@ui18n/react'; function ThemedApp() { return ( <ThemeProvider theme="auto" // 'light' | 'dark' | 'auto' colors={{ primary: '#3b82f6', secondary: '#6b7280', background: '#ffffff', text: '#1f2937', border: '#e5e7eb' }} fonts={{ family: 'system-ui, sans-serif', size: '14px' }} > <ThemedLanguageSelector /> </ThemeProvider> ); } function ThemedLanguageSelector() { const { currentTheme, colors, fonts } = useTheme(); return ( <div className={`ui18n-theme-${currentTheme}`} style={getThemeStyles(colors, fonts)} > <LanguageSelector /> </div> ); } ``` ## 📚 API文档 ### Hooks #### `useUI18n()` 主要的国际化Hook,提供完整的翻译功能。 ```tsx const { ui18n, // UI18n实例 t, // 翻译函数(简写) translate, // 翻译函数 currentLanguage, // 当前语言 switchLanguage, // 切换语言 isLoading // 加载状态 } = useUI18n(); ``` #### `useTranslation(text, options?)` 单个文本翻译Hook。 ```tsx const { translatedText, isLoading, error } = useTranslation('你好世界', { targetLanguage: 'en', enableCache: true }); ``` ### 组件 #### `<LanguageSelector>` - 智能语言选择器 完全可定制的语言选择组件,支持四大核心功能: **1. 中英文按钮 + 智能搜索框** ```tsx <LanguageSelector defaultLanguages={['zh-CN', 'en']} // 默认显示的语言按钮 showSearchBox={true} // 显示智能搜索框 autoDetectSystemLanguage={true} // 智能预填充系统语言 /> ``` **2. 完全自定义渲染** ```tsx <LanguageSelector defaultLanguages={['zh-CN', 'en', 'ja']} showSearchBox={true} className="my-selector" // 自定义语言按钮 renderLanguageButton={(lang, onClick) => ( <button className="custom-btn" onClick={onClick}> {lang === 'zh-CN' ? '中文' : lang === 'en' ? 'English' : '日本語'} </button> )} // 自定义搜索框 renderSearchBox={(props) => ( <input {...props} className="custom-search" placeholder="搜索语言..." /> )} /> ``` **3. 渐进式配置** ```tsx // 最简配置 <LanguageSelector /> // 中等配置 <LanguageSelector defaultLanguages={['zh-CN', 'en', 'ja', 'ko']} showSearchBox={true} /> // 完全自定义 <LanguageSelector defaultLanguages={['zh-CN', 'en']} showSearchBox={true} autoDetectSystemLanguage={true} className="my-custom-selector" renderLanguageButton={(lang, onClick) => ( <MyCustomButton language={lang} onClick={onClick} /> )} renderSearchBox={(props) => ( <MyCustomSearchBox {...props} /> )} /> ``` **4. 插件集成** ```tsx import { LanguageSelector } from '@ui18n/react'; import { useAccessibility, useMobile, ThemeProvider } from '@ui18n/react'; function EnhancedLanguageSelector() { const { getMobileClasses, BottomSheet } = useMobile({ enableMobileAdaptation: true, useBottomSheet: true }); const { getAriaProps, handleKeyDown } = useAccessibility({ enableKeyboardNavigation: true, enableScreenReader: true }); return ( <ThemeProvider theme="auto"> <div className={getMobileClasses()} {...getAriaProps('selector')}> <BottomSheet> <LanguageSelector defaultLanguages={['zh-CN', 'en']} showSearchBox={true} autoDetectSystemLanguage={true} /> </BottomSheet> </div> </ThemeProvider> ); } ``` #### Props接口 ```tsx interface LanguageSelectorProps { /** 默认显示的语言按钮 */ defaultLanguages?: SupportedLanguage[]; /** 是否显示搜索框 */ showSearchBox?: boolean; /** 是否自动检测系统语言 */ autoDetectSystemLanguage?: boolean; /** 自定义CSS类名 */ className?: string; /** 自定义语言按钮渲染 */ renderLanguageButton?: ( language: SupportedLanguage, onClick: () => void ) => React.ReactNode; /** 自定义搜索框渲染 */ renderSearchBox?: (props: { value: string; onChange: (e: React.ChangeEvent<HTMLInputElement>) => void; onFocus: () => void; onBlur: () => void; }) => React.ReactNode; } ``` ### Provider #### `<UI18nProvider>` 全局状态提供者,必须包裹在应用根部。 ```tsx <UI18nProvider ui18n={ui18nInstance} fallback={<div>初始化中...</div>} > <App /> </UI18nProvider> ``` ## 🎯 高级用法 ### 1. 智能语言检测与预填充 ```tsx import { LanguageSelector } from '@ui18n/react'; function SmartLanguageSelector() { return ( <LanguageSelector defaultLanguages={['zh-CN', 'en']} showSearchBox={true} autoDetectSystemLanguage={true} // 自动检测系统语言并预填充搜索框 /> ); } ``` ### 2. 企业级多功能集成 ```tsx import { LanguageSelector, ThemeProvider, useAccessibility, useMobile } from '@ui18n/react'; function EnterpriseLanguageSelector() { const { getMobileClasses, BottomSheet, isMobile } = useMobile({ enableMobileAdaptation: true, mobileBreakpoint: 768, useBottomSheet: true }); const { getAriaProps, handleKeyDown, getContrastClass } = useAccessibility({ enableKeyboardNavigation: true, enableScreenReader: true, enableHighContrast: true }); return ( <ThemeProvider theme="auto" colors={{ primary: '#007bff' }}> <div className={`${getMobileClasses()} ${getContrastClass()}`}> <BottomSheet> <LanguageSelector defaultLanguages={['zh-CN', 'en', 'ja', 'ko']} showSearchBox={true} autoDetectSystemLanguage={true} {...getAriaProps('selector')} renderLanguageButton={(lang, onClick) => ( <button className="enterprise-lang-btn" onClick={onClick} onKeyDown={(e) => handleKeyDown(e, onClick)} {...getAriaProps('button', lang)} > {lang === 'zh-CN' ? '中文' : lang === 'en' ? 'English' : lang === 'ja' ? '日本語' : '한국어'} </button> )} /> </BottomSheet> </div> </ThemeProvider> ); } ``` ### 3. 渐进式配置示例 ```tsx // 阶段1:最简配置(30秒上手) function BasicSetup() { return <LanguageSelector />; } // 阶段2:添加搜索功能 function WithSearch() { return ( <LanguageSelector defaultLanguages={['zh-CN', 'en']} showSearchBox={true} /> ); } // 阶段3:智能检测 function WithSmartDetection() { return ( <LanguageSelector defaultLanguages={['zh-CN', 'en']} showSearchBox={true} autoDetectSystemLanguage={true} /> ); } // 阶段4:完全自定义 function FullyCustomized() { return ( <LanguageSelector defaultLanguages={['zh-CN', 'en']} showSearchBox={true} autoDetectSystemLanguage={true} className="my-custom-selector" renderLanguageButton={(lang, onClick) => ( <MyCustomButton language={lang} onClick={onClick} /> )} renderSearchBox={(props) => ( <MyCustomSearchBox {...props} /> )} /> ); } ``` ### 4. 响应式移动端适配 ```tsx import { useMobile, LanguageSelector } from '@ui18n/react'; function ResponsiveLanguageSelector() { const { isMobile, getMobileClasses, BottomSheet, isBottomSheetOpen, setIsBottomSheetOpen } = useMobile({ enableMobileAdaptation: true, mobileBreakpoint: 768, useBottomSheet: true }); return ( <div className={getMobileClasses()}> {isMobile ? ( <> <button onClick={() => setIsBottomSheetOpen(true)}> 选择语言 </button> <BottomSheet> <LanguageSelector defaultLanguages={['zh-CN', 'en']} showSearchBox={true} /> </BottomSheet> </> ) : ( <LanguageSelector defaultLanguages={['zh-CN', 'en']} showSearchBox={true} /> )} </div> ); } ``` ### 5. 无障碍功能集成 ```tsx import { useAccessibility, LanguageSelector } from '@ui18n/react'; function AccessibleLanguageSelector() { const { handleKeyDown, getAriaProps, getContrastClass } = useAccessibility({ enableKeyboardNavigation: true, enableScreenReader: true, enableHighContrast: true, ariaLabels: { languageSelector: '语言选择器', searchBox: '搜索语言', languageButton: (lang) => `选择${lang}语言` } }); return ( <div className={getContrastClass()} {...getAriaProps('selector')}> <LanguageSelector defaultLanguages={['zh-CN', 'en']} showSearchBox={true} renderLanguageButton={(lang, onClick) => ( <button onClick={onClick} onKeyDown={(e) => handleKeyDown(e, onClick)} {...getAriaProps('button', lang)} > {lang === 'zh-CN' ? '中文' : 'English'} </button> )} renderSearchBox={(props) => ( <input {...props} {...getAriaProps('search')} /> )} /> </div> ); } ``` ## 🔧 配置选项 ```tsx import { createUI18n } from '@ui18n/core'; import { UI18nProvider } from '@ui18n/react'; // 自托管模式配置 const ui18n = createUI18n({ // 基础配置 defaultLanguage: 'zh-CN', fallbackLanguage: 'en', // AI提供商配置(自托管模式) aiProvider: { type: 'openai', // 支持 openai、claude、qwen 等 apiKey: process.env.REACT_APP_OPENAI_API_KEY, timeout: 10000, retries: 3 }, // 缓存配置 cache: { enabled: true, type: 'memory', maxSize: 1000, persistent: true // 使用localStorage持久化 } }); // 云端服务模式配置(可选) const cloudUI18n = createUI18n({ defaultLanguage: 'zh-CN', serviceMode: 'cloud', userKey: 'your-user-key', // 云端服务特定配置 cloudConfig: { endpoint: 'http://localhost:3000/api', timeout: 15000, retries: 2 } }); // React应用中使用 function App() { return ( <UI18nProvider ui18n={ui18n}> <YourApp /> </UI18nProvider> ); } ``` ### 插件配置 ```tsx import { LanguageSelector, ThemeProvider, useAccessibility, useMobile } from '@ui18n/react'; // 主题配置 function ThemedApp() { return ( <ThemeProvider theme="auto" // 'light' | 'dark' | 'auto' colors={{ primary: '#3b82f6', secondary: '#6b7280', background: '#ffffff', text: '#1f2937', border: '#e5e7eb' }} fonts={{ family: 'system-ui, sans-serif', size: '14px' }} > <App /> </ThemeProvider> ); } // 无障碍配置 const accessibilityConfig = { enableKeyboardNavigation: true, enableScreenReader: true, enableHighContrast: false, ariaLabels: { languageSelector: '语言选择器', searchBox: '搜索语言', languageButton: (lang) => `选择${lang}语言` } }; // 移动端配置 const mobileConfig = { enableMobileAdaptation: true, mobileBreakpoint: 768, enableTouchGestures: true, useBottomSheet: true }; ``` ## 🎨 样式定制 (略,保持原文档后续样式与性能章节内容) ## 🔗 相关链接 - Incubating 说明:packages/react/docs/INCUBATING_TRANSLATOR.md - UI 包选择与稳定性:docs/UI_PACKAGES_OVERVIEW.md - 核心包文档:../core/README.md - Vue集成包:../vue/README.md - CLI工具:../cli/README.md - GitHub仓库:https://github.com/iron-wayne/UI18N-OSS ## 📄 许可证 MIT License - 详见 [LICENSE](../../LICENSE) 文件。 ## 🤝 贡献 欢迎贡献代码!请查看 [贡献指南](../../CONTRIBUTING.md)。 ---