前端国际化:别让你的应用只懂一种语言
前端国际化:别让你的应用只懂一种语言
毒舌时刻
这应用写得跟方言似的,出了本地就没人懂。
各位前端同行,咱们今天聊聊前端国际化。别告诉我你的应用还只有中文版本,那感觉就像在国际会议上只说方言——能说,但没人懂。
为什么你需要国际化
最近看到一个项目,想拓展海外市场,但所有文本都是硬编码在代码里的。我就想问:你是在做本地应用还是在做国际产品?
反面教材
// 反面教材:硬编码文本 function App() { return ( <div> <h1>欢迎来到我的网站</h1> <p>这是一个示例应用</p> <button>点击我</button> <div> <h2>产品列表</h2> <ul> <li>产品 1</li> <li>产品 2</li> <li>产品 3</li> </ul> </div> </div> ); } export default App; 毒舌点评:这代码,就像在写日记,只有自己能看懂。
正确姿势
1. i18next
// 正确姿势:i18next // 1. 配置 // i18n.js import i18n from 'i18next'; import { initReactI18next } from 'react-i18next'; const resources = { zh: { translation: { welcome: '欢迎来到我的网站', description: '这是一个示例应用', button: '点击我', products: '产品列表', product1: '产品 1', product2: '产品 2', product3: '产品 3' } }, en: { translation: { welcome: 'Welcome to my website', description: 'This is a sample application', button: 'Click me', products: 'Product List', product1: 'Product 1', product2: 'Product 2', product3: 'Product 3' } } }; i18n .use(initReactI18next) .init({ resources, lng: 'zh', fallbackLng: 'en', interpolation: { escapeValue: false } }); export default i18n; // 2. 使用 // App.jsx import React from 'react'; import { useTranslation } from 'react-i18next'; function App() { const { t, i18n } = useTranslation(); const changeLanguage = (lng) => { i18n.changeLanguage(lng); }; return ( <div> <div> <button onClick={() => changeLanguage('zh')}>中文</button> <button onClick={() => changeLanguage('en')}>English</button> </div> <h1>{t('welcome')}</h1> <p>{t('description')}</p> <button>{t('button')}</button> <div> <h2>{t('products')}</h2> <ul> <li>{t('product1')}</li> <li>{t('product2')}</li> <li>{t('product3')}</li> </ul> </div> </div> ); } export default App; // 3. 入口文件 // index.js import React from 'react'; import ReactDOM from 'react-dom'; import App from './App'; import './i18n'; ReactDOM.render( <React.StrictMode> <App /> </React.StrictMode>, document.getElementById('root') ); 2. react-intl
// 正确姿势:react-intl // 1. 配置 // App.jsx import React from 'react'; import { IntlProvider, FormattedMessage } from 'react-intl'; const zhMessages = { welcome: '欢迎来到我的网站', description: '这是一个示例应用', button: '点击我', products: '产品列表', product1: '产品 1', product2: '产品 2', product3: '产品 3' }; const enMessages = { welcome: 'Welcome to my website', description: 'This is a sample application', button: 'Click me', products: 'Product List', product1: 'Product 1', product2: 'Product 2', product3: 'Product 3' }; function App() { const [locale, setLocale] = React.useState('zh'); const messages = locale === 'zh' ? zhMessages : enMessages; return ( <IntlProvider locale={locale} messages={messages}> <div> <div> <button onClick={() => setLocale('zh')}>中文</button> <button onClick={() => setLocale('en')}>English</button> </div> <h1><FormattedMessage /></h1> <p><FormattedMessage /></p> <button><FormattedMessage /></button> <div> <h2><FormattedMessage /></h2> <ul> <li><FormattedMessage /></li> <li><FormattedMessage /></li> <li><FormattedMessage /></li> </ul> </div> </div> </IntlProvider> ); } export default App; 3. 日期和数字格式化
// 正确姿势:日期和数字格式化 import React from 'react'; import { useTranslation } from 'react-i18next'; function FormattingExample() { const { t, i18n } = useTranslation(); const formatDate = (date) => { return new Intl.DateTimeFormat(i18n.language).format(date); }; const formatNumber = (number) => { return new Intl.NumberFormat(i18n.language).format(number); }; return ( <div> <p>{t('currentDate')}: {formatDate(new Date())}</p> <p>{t('price')}: {formatNumber(12345.67)}</p> </div> ); } export default FormattingExample; 毒舌点评:这才叫国际化,让你的应用在全球范围内都能被理解。