[vue]国际化功能的实现
[vue]国际化功能的实现通过语言的选择,使得网页展示内容为对应的语言UI组件使用的是ant-design-vue,直接使用它的国际化组件,用于实现ant-design-vue各组件的国际化;第一次实现国际化的功能时直接使用了 ant-design-vue的国际化组件,标签没有起作用在真正的使用过程中绕了很多弯路,这里记录一下,方便以后查找环境:"vue": "^3.0.0""ant-design
[vue]国际化功能的实现
通过语言的选择,使得网页展示内容为对应的语言
UI组件使用的是ant-design-vue,直接使用它的国际化组件,用于实现ant-design-vue各组件的国际化;
第一次实现国际化的功能时直接使用了 ant-design-vue的国际化组件,标签没有起作用
在真正的使用过程中绕了很多弯路,这里记录一下,方便以后查找
环境:
"vue": "^3.0.0"
"ant-design-vue": "^3.1.0-rc.5"
ant-design-vue的国际化
这个主要是引入的UI框架(ant-design-vue)自己的组件,例如时间选择组件,输入框等的默认提示信息的国际化变更
引入国际化组件 :ConfigProvider
const app = createApp(App);
import { ConfigProvider} from "ant-design-vue";
app.use(ConfigProvider);
修改antd的语言类型
<a-config-provider :locale="antdLocale">
该标签一般放在最外层的.vue文件中 一般是App.vue ,也可以是你自定义的其它可以包含其它所有路由的外层vue文件,这样修改语言的时候,内部的所有组件都可以被国际化组件重新渲染
引入ant-design-vue 的你涉及到的国际化文件类型
import zhCN from "ant-design-vue/es/locale/zh_CN";
import zhTW from "ant-design-vue/es/locale/zh_TW";
import enUS from "ant-design-vue/es/locale/en_US";
export const antdLang: { [key: string]: any } = {
zh_CN: zhCN,
zh_TW: zhTW,
en_US: enUS
};
设置antdLocale的定义与变更,param.key是点击要变成的语言的值,可以是 zh_CN/zh_TW/en_US
setup(){
const antdLocale=ref<string>(antdLang[" zh_CN"]);
const changLang=(param)=>{
//转化为antd对应的语言,
antdLocale.value=antdLang[param.key];//作用于所有的 ant-design-vue 的所有组件
}
}
配置自定义文件的国际化
像是菜单等这种目录内容,也希望根据选择的语言,实现不同的语言展示,这个的展示内容需要自已定义各种语言的展示内容
这个要如何实现?
基本设置
此时需要引入
npm install vue-i18n
配置文件i18n.ts
import { createI18n, VueMessageType } from "vue-i18n";
import { LocaleMessages } from "@intlify/core-base";
import zhCN from "ant-design-vue/es/locale/zh_CN";
import zhTW from "ant-design-vue/es/locale/zh_TW";
import enUS from "ant-design-vue/es/locale/en_US";
export const antdLang: { [key: string]: any } = {
zh_CN: zhCN,
zh_TW: zhTW,
en_US: enUS
};
//语言存储标志
export const langKey = "lang";
// 默认语言
export const defaultLang = "zh_CN";
/**
* 验证语言命名规则 zh_CN
* @returns boolen
*/
export const localeNameExp = (lang: string): boolean => {
const localeExp = new RegExp(`^([a-z]{2})_?([A-Z]{2})?$`);
return localeExp.test(lang);
};
/**
* 获取当前语言
* @returns string
*/
export const getLocale = (): string => {
const lang =typeof localStorage !== "undefined" ? localStorage.getItem(langKey) : "";
const isNavigatorLang =typeof navigator !== "undefined" && typeof navigator.language === "string";
const browserLang = isNavigatorLang ? navigator.language.split("-").join("_") :"";
return lang || browserLang || defaultLang;
};
/**
* 设置 html 页面 lang 属性值
* @param lang 语言的 key
*/
export const setPageLang = (lang: string) => {
//axios.defaults.headers.common['Accept-Language'] = locale
document.querySelector("html")?.setAttribute("lang", lang);
};
/**
* 切换语言
* @param lang 语言的 key
* @param reload 是否刷新页面(一般不应该整个页面刷新)
*/
export const setLocale = (lang: string, reload: boolean, callback: Function) => {
if (lang !== undefined && !localeNameExp(lang)) {
// for reset when lang === undefined
throw new Error("setLocale lang format error");
}
if (getLocale() !== lang) {
if (typeof localStorage !== "undefined") {
localStorage.setItem(langKey, lang || "");
}
if (reload) {
window.location.reload();
} else {
setPageLang(lang);
if (typeof callback === "function") {
callback();
}
}
}
};
/**
* 设置语言
* @param locale
*/
export function setI18nLang(locale: string, reload = true) {
setLocale(locale, reload, function() {
i18n.global.locale = locale; // legacy: true
// i18n.global.locale.value = locale;
});
}
/**
* 自动导入 所有自定义的语言--获取所有自定义的国际化文件,并返回
*/
export function importAllLocales(): LocaleMessages<VueMessageType> {
const modules: LocaleMessages<VueMessageType> = {};
const contextList=[];
try {
// 导入 @/views 下文件,包含子目录,文件名为:[/\\]locales[/\\]([a-z]{2})-?([A-Z]{2})?\.ts
const localesFolderReg: RegExp = new RegExp(
/[/\\]locales[/\\]([a-z]{2})_?([A-Z]{2})?\.ts$/,
"g"
);
// const folders = ["../router"];//"../views", "../components", "../"
// folders.forEach(item => {
//require.context("查找目录",是否查找子文件夹,符合规则的正则表达式) :
// require.context不能使用表达式的变量作为参数,只能直接使用
// require.context尝试变量替换后报错 require.context不是方法
//路径也不能使用变量代替
//require.context不能在循环中使用,因为require.context的参数只能使用字面值,不能使用变量代替
const folderRequireContext: __WebpackModuleApi.RequireContext = require.context("../router",true,/[/\\]locales[/\\]([a-z]{2})_?([A-Z]{2})?\.ts$/);
contextList.push(folderRequireContext);
//可以继续添加其它路径的folderRequireContext
contextList.forEach(requireCtx=>{
requireCtx.keys().forEach(fileName => {
// 获取内容
const modulesConent =requireCtx(fileName);
if (modulesConent.default) {
// 获取 PascalCase 命名
const modulesName = fileName.replace(/(.*\/)*([^.]+).*/gi, "$2");
if (modules[modulesName]) {
modules[modulesName] = {
...modules[modulesName],
...modulesConent.default
};
} else {
modules[modulesName] = modulesConent.default;
}
}
});
});
} catch (error) {
console.log(error);
}
console.log(modules);
return modules;
}
const messages = importAllLocales();
const i18n = createI18n({
// legacy: false,
locale: getLocale(),
messages: messages,
silentFallbackWarn:true,
silentTranslationWarn: true //去除警告信息
});
export default i18n;
在该配置文件中 importAllLocales 非常重要,将所有的自定义的国际化文件引入 i18n的范围内,使得 i18n.global.locale 值发生变化的时候 所有通过t()解析时去获取对应文件的值
报错 TypeError: __webpack_require__(...).context is not a function
TypeError: webpack_require(…).context is not a function
at importAllLocales (i18n.ts?b778:129)
at eval (i18n.ts?b778:166)
at Module…/src/config/i18n.ts (app.js:162)
at webpack_require (app.js:1473)
at fn (app.js:1755)
at eval (main.ts:6)
at Module…/src/main.ts (app.js:195)
at webpack_require (app.js:1473)
at app.js:2664
at Function.webpack_require.O (app.js:1522)
主要使用require.context(path,true,folderRule)使用变量了,若是直接使用值就没有问题
folderRule是个表达式,主要是用来表示文件名称的命名规则
全局使用国际化的配置,在main.ts文件中:
app.use( i18n);
在具体的vue文件中设置国际化的配置
template
<a-config-provider :locale="antdLocale">
script:
import { useI18n } from "vue-i18n";
import {antdLang,setI18nLang} from "@/config/i18n";
const { locale } = useI18n();//获取国际化配置文件中设置的语言默认值
const antdLocale=ref<string>(antdLang[locale.value]);
const changLang=(param)=>{
//转化为对应的语言,
antdLocale.value=antdLang[param.key];
//修改全局的国际化配置中当前语言的值
setI18nLang(param.key,false);
}
国际化展示自定义内容
在具体的国际化展示自定义内容中,类似于自定义的路由名称的国际化展示作为例子
我们在路由文件中定义路由时,可以设置路由的名称为一个键值"sider.index"
{
path: "/index",
name:"sider.index",
component: Index
},
然后在对应的locales文件夹的不同语言文件中分别设置该值应该展示的内容
en_US
export default {
'sider.index': 'index',
};
zh_CN
export default {
'sider.index': '首页',
};
在使用该值的过程中
需要使用方法t
这里的menu就是路由的一个项
{
path: "/index",
name:"sider.index",
component: Index
}
menu.name即指向了sider.index
然后通过t()解析该键值
相关代码
template:
<span>{{t(menu.name)}}</span>
引入t
import { useI18n } from "vue-i18n";
setup() {
const { t } = useI18n();
return {
t
}
}
importAllLocales() 引入的配置文件 对403/404这两个目录没有对应的中英问解析,所以报错.其它正常
silentFallbackWarn:true,
silentTranslationWarn: true //去除警告信息
同时设置上述值去除所有警告
然后可以看到正常的语言切换
更多推荐
所有评论(0)