赞
踩
抛开Next.js
框架不谈,想必其他项目也经常会遇到国际化方案,大概逻辑都是差不多的,只是说这次本人碰巧在Next
上的项目有这样的需求,并记录下来。
其实不从代码角度上讲的话,无非是引入一个“变量”
,并且所有文本都依赖于这个“变量”
,然后再提前配置好一系列的语言文件,只要这个“变量”
变了,那我就利用这个变量做出映射
,从而达到切换语言的效果,只是说不同方案,对这个“变量”
呈现的方式不一样而已。对于变量的呈现方式如下:
方案一:
按域名来控制
,就像react官网一样,比如说你要看英文的,那你就访问reactjs.org
,如果你要看中文的,那你就访问zh-hans.reactjs.org
,如果你要看韩文的,那你就访问ko.reactjs.org
,如果你要看…
发现没有,其实就是不同语言,就访问不同的域名
方案二:
按路由来控制
,比如你要看英文的,那你就访问http://localhost:8080/en/admin/user
,如果你要看中文的,那你就访问http://localhost:8080/zh/admin/user
,如果你要看韩文的,那你访问http://localhost:8080/ko/admin/user
,如果你要看…
这种其实就是把语言变量放在了路由上
说了上面那么多,总算可以正文了~~
首先Next
在版本大于等于v10.0.0
后本身就支持国际化,并不需要特意引入网上那些杂七杂八的插件,什么react-intl
啊、react-i18next
啊、react-i18n-auto
啊等等,不是说他们不好,而是我感觉没必要,所以就自己写一个简单的hook
demo就好了。大家也可以直接自己看官网,下面的也是按照官网的快速上手来的
修改next项目中的next.config.js配置文件:
// next.config.js
module.exports = {
i18n: {
defaultLocale: 'zh', // 默认语言
locales: ['en', 'zh'], // 语言变量
},
...others
}
当然我这里采用的是上诉的方案二,按路由来控制,官网中有写到配置域名,也就是按域名来控制语言
然后新增语言文件
// en.jsx
const EN_JSON = {
"app.title":"international language"
}
// zh.jsx
const ZH_JSON = {
"app.title":"国际化语言"
}
可能细心的同学会发现,我这里新建的是两个.jsx
文件,而不是json,或者js文件,这也就意味着,我们自己的写的这个可以支持ReactNode
,并不完全局限于普通文本
了!
接着再写一个hook
// useTranslation.js import { useRouter } from 'next/router'; import En from '@/locales/en'; // 英文语言包,也就是上面的en.jsx import Zh from '@/locales/zh'; // 中文语言包,也就是上面的zh.jsx import { useCallback } from 'react'; const LanguageMap = { en: En, zh: Zh, }; const useTranslation = () => { const router = useRouter(); const jsonFun = useCallback( (key, params = {}) => { // 获取当前的语言包里面key所对应的value值 let value = LanguageMap[router.locale][key]; /* 如果传key进来,或者没有找到value,就直接返回key就好了, 页面上就显示key,方便找到漏翻译的字段 */ if (!key || !value) return key; /* 这里是为了能够让我们写的hook能支持传参,比如找到的value为'{name} 今年{age}岁啦~',这里的nameg和age都是为参数,也就是后面可以这种 形式传进来: const { t } = useTranslation() <div>{ t('app.message',{name:"张三", age:18}) }</div> // 翻译后的结果就是 <div>张三今年18岁啦~</div> */ Object.keys(params).forEach(item => { value = value.replace(new RegExp(`{${item}}`, 'g'), params[item]); }); return value; }, [router.locale] ); return { t: jsonFun, }; }; export default useTranslation;
然后利用next
内置的Link
组建进行切换:
import { useRouter } from 'next/router'; import Link from 'next/link'; import { useTranslation } from '@/utils/hooks'; const APP = () => { const { t } = useTranslation(); const { locale, asPath } = useRouter(); const LanguagesMenu = useMemo(() => { return ( <Menu items={[ { key: 'en', label: ( <Link href={`/en${asPath}`} locale="en"> Engilsh </Link> ), disabled: locale === 'en', }, { key: 'zh', label: ( <Link href={asPath} locale="zh"> 中文 </Link> ), disabled: locale === 'zh', }, ]} /> ); }, [asPath, locale]); // ReactNode return (<Dropdown overlay={LanguagesMenu} placement="bottom" trigger={['hover']} > <div className={styles.name} onClick={e => e.preventDefault()}> {locale === 'en' ? 'English' : '中文'} </div> </Dropdown>) }
最后再看下效果吧:
当然我这里是将 /
作为zh的路径
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。