跳到主要内容 前端国际化最佳实践 | 极客日志
JavaScript 大前端
前端国际化最佳实践 介绍前端国际化最佳实践,对比硬编码字符串与使用专业库(如 i18next)的差异。方案涵盖翻译资源统一管理、参数化翻译、浏览器语言自动检测、日期时间数字货币本地化及 RTL 语言支持。通过规范化的 i18n 配置和组件封装,提升多语言用户体验,为业务全球化做准备。
DockerOne 发布于 2026/4/6 更新于 2026/4/13 1 浏览前端国际化最佳实践
毒舌时刻
前端国际化?这不是大公司才需要的吗?
"我的网站只面向国内用户,要什么国际化"——结果业务拓展到海外,临时抱佛脚,
"我直接用中文写死,多简单"——结果需要支持英文时,满世界找字符串,
"我用 Google 翻译,多快"——结果翻译质量差,用户体验差。
醒醒吧,国际化不是可选的,而是现代前端开发的标配!
为什么你需要这个?
全球用户覆盖 :吸引来自不同国家和地区的用户
业务拓展 :为未来的海外业务做准备
用户体验 :让用户使用自己熟悉的语言
品牌形象 :展现专业、全球化的品牌形象
合规要求 :满足某些国家的语言法规要求
反面教材
function Header ( ) {
return (
<div className ="header" >
<h1 > 欢迎来到我的网站</h1 >
<nav >
<a href ="/" > 首页</a >
<a href ="/about" > 关于我们</a >
<a href ="/contact" > 联系我们</a >
</nav >
</div >
);
}
function App ( ) {
const [language, setLanguage] = useState ( );
= ( ) => {
texts = {
: { : , : , : },
: { : , : , : }
};
texts[language][key];
};
(
);
}
微信扫一扫,关注极客日志 微信公众号「极客日志」,在微信中扫描左侧二维码关注。展示文案:极客日志 zeeklog
相关免费在线工具 Keycode 信息 查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online
Escape 与 Native 编解码 JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online
JavaScript / HTML 格式化 使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online
JavaScript 压缩与混淆 Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online
Base64 字符串编码/解码 将字符串编码和解码为其 Base64 格式表示形式即可。 在线工具,Base64 字符串编码/解码在线工具,online
Base64 文件转换器 将字符串、文件或图像转换为其 Base64 表示形式。 在线工具,Base64 文件转换器在线工具,online
'zh'
const
getText
key
const
zh
welcome
'欢迎'
about
'关于我们'
contact
'联系我们'
en
welcome
'Welcome'
about
'About Us'
contact
'Contact Us'
return
return
<div >
<button onClick ={() => setLanguage('zh')}>中文</button >
<button onClick ={() => setLanguage('en')}>English</button >
<h1 > {getText('welcome')}</h1 >
{/* 其他内容 */}
</div >
正确的做法
import i18n from 'i18next' ;
import { initReactI18next } from 'react-i18next' ;
import zh from './locales/zh.json' ;
import en from './locales/en.json' ;
import ja from './locales/ja.json' ;
i18n
.use (initReactI18next)
.init ({
resources : {
zh : { translation : zh },
en : { translation : en },
ja : { translation : ja }
},
lng : 'zh' ,
fallbackLng : 'en' ,
interpolation : {
escapeValue : false
},
detection : {
order : ['navigator' , 'localStorage' , 'cookie' ],
caches : ['localStorage' , 'cookie' ]
}
});
export default i18n;
{
"welcome" : "欢迎来到我的网站" ,
"nav" : {
"home" : "首页" ,
"about" : "关于我们" ,
"contact" : "联系我们"
} ,
"greeting" : "你好,{{name}}!" ,
"count" : "你有 {{count}} 条消息" ,
"date" : "今天是 {{date}}"
}
{
"welcome" : "Welcome to my website" ,
"nav" : {
"home" : "Home" ,
"about" : "About Us" ,
"contact" : "Contact Us"
} ,
"greeting" : "Hello, {{name}}!" ,
"count" : "You have {{count}} messages" ,
"date" : "Today is {{date}}"
}
import React from 'react' ;
import { useTranslation } from 'react-i18next' ;
function Header ( ) {
const { t } = useTranslation ();
return (
<div className ="header" >
<h1 > {t('welcome')}</h1 >
<nav >
<a href ="/" > {t('nav.home')}</a >
<a href ="/about" > {t('nav.about')}</a >
<a href ="/contact" > {t('nav.contact')}</a >
</nav >
</div >
);
}
function Greeting ({ name } ) {
const { t } = useTranslation ();
return (
<div >
{/* 带参数的翻译 */}
<p > {t('greeting', { name })}</p >
</div >
);
}
import React from 'react' ;
import { useTranslation } from 'react-i18next' ;
function LanguageSwitcher ( ) {
const { i18n } = useTranslation ();
const changeLanguage = (lng ) => {
i18n.changeLanguage (lng);
};
return (
<div className ="language-switcher" >
<button onClick ={() => changeLanguage('zh')}>中文</button >
<button onClick ={() => changeLanguage('en')}>English</button >
<button onClick ={() => changeLanguage('ja')}>日本語</button >
</div >
);
}
import React from 'react' ;
import { useTranslation } from 'react-i18next' ;
import { format } from 'date-fns' ;
import { zhCN, enUS, ja } from 'date-fns/locale' ;
function LocalizedDate ( ) {
const { i18n } = useTranslation ();
const currentDate = new Date ();
const getLocale = ( ) => {
switch (i18n.language ) {
case 'zh' : return zhCN;
case 'en' : return enUS;
case 'ja' : return ja;
default : return enUS;
}
};
const formattedDate = format (currentDate, 'yyyy 年 MM 月 dd 日 EEEE' , { locale : getLocale () });
return (
<div >
<p > {formattedDate}</p >
</div >
);
}
function LocalizedNumber ({ number } ) {
const { i18n } = useTranslation ();
const formattedNumber = new Intl .NumberFormat (i18n.language ).format (number);
return (
<div >
<p > {formattedNumber}</p >
</div >
);
}
function LocalizedCurrency ({ amount, currency } ) {
const { i18n } = useTranslation ();
const formattedCurrency = new Intl .NumberFormat (i18n.language , {
style : 'currency' ,
currency : currency
}).format (amount);
return (
<div >
<p > {formattedCurrency}</p >
</div >
);
}
// 正确的做法:RTL 语言支持
[dir="rtl" ] {
text-align : right;
}
[dir="rtl" ] .nav {
flex-direction : row-reverse;
}
function App ( ) {
const { i18n } = useTranslation ();
React .useEffect (() => {
const rtlLanguages = ['ar' , 'he' , 'fa' ];
document .documentElement .dir = rtlLanguages.includes (i18n.language ) ? 'rtl' : 'ltr' ;
}, [i18n.language ]);
return (
<div >
<LanguageSwitcher />
<Header />
<Greeting name ="张三" />
<LocalizedDate />
<LocalizedNumber number ={1234567.89} />
<LocalizedCurrency amount ={100} currency ="CNY" />
</div >
);
}
*.{js,jsx,ts,tsx}',
],
output: ' ./locales',
options: {
lngs: [' zh', ' en', ' ja'],
defaultLng: ' zh',
ns: [' translation'],
defaultValue: (lng, ns, key) => key,
resourceKeySeparator: ' .',
nsSeparator: ' :',
interpolation: {
prefix: ' {{',
suffix: ' }}'
}
}
};
*/
毒舌点评 看看,这才叫前端国际化最佳实践!不是简单地手动切换字符串,而是使用专业的国际化库,统一管理翻译资源,支持日期、时间、数字、货币的本地化,甚至支持 RTL 语言。
记住,国际化不仅仅是翻译文本,还包括日期、时间、数字、货币等格式的本地化,以及 RTL(从右到左)语言的支持。
所以,别再觉得国际化麻烦了,它是你网站走向世界的必备技能!
总结
使用专业库 :如 i18next、react-intl 等
统一管理翻译资源 :将翻译文本放在单独的 JSON 文件中
支持参数化翻译 :处理带变量的文本
自动检测语言 :根据用户浏览器设置自动切换语言
本地化格式 :处理日期、时间、数字、货币的本地化
RTL 支持 :支持从右到左的语言如阿拉伯语
懒加载翻译 :按需加载翻译资源,减少包大小
自动提取翻译 :使用工具自动提取需要翻译的字符串