使用vue-i18n实现语言切换
本文介绍了在Vue项目中实现国际化的方法。文章详细展示了如何在main.js中配置i18n,包括创建语言文件夹结构、定义支持的语言类型、自动检测语言偏好等核心功能。同时提供了页面中使用$t方法进行多语言切换的示例代码,以及一个可复用的语言切换组件,支持文本和下拉框两种切换方式。组件会保存用户选择的语言到localStorage,确保下次访问保持相同语言设置。
·
如果是 Vue 3,确保 vue-i18n 的版本是 9.x 以上 npm install vue-i18n@9。
如果是 Vue 2,确保 vue-i18n 的版本是 8.x 以下 npm install vue-i18n@8。
1.vue2写法
main.js配置
import Vue from 'vue'
import App from './App'
import store from './store' // store
import plugins from './plugins' // plugins
import './permission' // permission
import {
getDicts
} from "@/api/system/dict/data"
import uView from "uview-ui";
import i18n from "@/language/index.js"; // 引入 i18n
Vue.use(uView);
Vue.use(plugins)
Vue.config.productionTip = false
Vue.prototype.$store = store
Vue.prototype.getDicts = getDicts
App.mpType = 'app'
const app = new Vue({
...App,i18n
})
app.$mount()
新建一个文件夹存放各版本语言 index.js
import Vue from 'vue';
import VueI18n from 'vue-i18n';
import enUS from "./locales/en_US";
import kmKH from "./locales/km_KH";
import zhCN from "./locales/zh_CN";
// 支持的语言
const SUPPORTED_LANGS = ["zh-CN", "en-US", "km-KH"];
// 获取并规范化语言
const getLanguage = () => {
// 1. 优先使用 localStorage
let lang = localStorage.getItem("language");
// 2. 其次根据浏览器语言自动判断
if (!lang) {
const nav = navigator.language.toLowerCase();
if (nav.startsWith("zh")) {
lang = "zh-CN";
} else if (nav.startsWith("en")) {
lang = "en-US";
} else if (nav.startsWith("km")) {
lang = "km-KH";
} else {
lang = "zh-CN";
}
}
// 3. 确保语言被支持
if (!SUPPORTED_LANGS.includes(lang)) {
lang = "zh-CN";
}
// 4. 确保 localStorage 是标准格式
localStorage.setItem("language", lang);
return lang;
};
const language = getLanguage();
Vue.use(VueI18n);
const i18n = new VueI18n({
legacy: false, // 使用Composition API,这里必须设置为false
locale: language, // 默认显示语言
fallbackLocale: "zh-US", // 当语言找不到时,用中文兜底
globalInjection: true, // 全局注册$t方法
messages: {
// 配置语言对应的文件
"zh-CN": zhCN,
"en-US": enUS,
"km-KH": kmKH,
},
});
export default i18n;
层级如下
页面中使用
<template>
<view class="content">
<view class="title">
<p class="header">{{ $t("menu.title") }}</p>
<view class="home">
<div class="homeimg">
<p>{{ $t("login.title") }}</p>
</div>
</view>
</view>
<view class="container">
<view v-for="item in data" :key="item.name">
<uni-section :title="$t(menuTitle[item.name])" type="line"></uni-section>
<view class="grid-body">
<uni-grid :column="4" :showBorder="false" @change="changeGrid">
<uni-grid-item v-for="i in item.children" :key="i.name">
<view class="grid-item-box">
<u-icon :name="i.img" :size="80"></u-icon>
<text class="text">{{ $t(menuTitle[i.name]) }}</text>
</view>
</uni-grid-item>
</uni-grid>
</view>
</view>
</view>
</view>
</template>
<script>
export default {
data() {
return {
data: [
{
name: 'scgl',
children: [
{
name: 'scll',
url: '',
img: require('../static/icon/name.png')
},
]
},
]
};
},
computed: {
menuTitle() {
return this.$t('menuTitle');
}
},
methods: {
changeGrid(e) {
this.$modal.showToast('模块建设中~');
}
}
};
</script>
封装一个组件用于切换语言
<template>
<div class="language-switch-box">
<div class="change-box">
<template v-if="optionType === 'text'">
<span
@click="changeLanguage('zh-CN')"
:class="{ active: locale === 'zh-CN' }"
>中文</span
>
|
<span
@click="changeLanguage('en-US')"
:class="{ active: locale === 'en-US' }"
>English</span
>
|
<span
@click="changeLanguage('km-KH')"
:class="{ active: locale === 'km-KH' }"
>ខ្មែរ</span
>
</template>
<template v-else>
<el-select
v-model="locale"
@change="changeLanguage"
style="width: 140px"
>
<el-option
v-for="(value, key) in languageDict"
:key="key"
:label="value"
:value="key"
/>
</el-select>
</template>
</div>
</div>
</template>
<script>
import { useI18n } from "vue-i18n";
export default {
props: {
optionType: {
type: String,
default: "text",
},
},
data() {
return {
locale: localStorage.getItem("language") || "zh-CN",
languageDict: {
"zh-CN": "中文",
"en-US": "English",
"km-KH": "ខ្មែរ",
},
};
},
methods: {
changeLanguage(language) {
this.locale = language;
localStorage.setItem("language", language);
console.log("切换语言:", language);
console.log("当前 locale:", this.locale);
},
},
watch: {
locale(newLocale) {
this.$i18n.locale = newLocale;
},
},
};
</script>
2.vue3写法
main.js配置
import i18n from "@/language"; // 引入 i18n
app.use(i18n);
新建一个文件夹存放各版本语言 index.js
import { createI18n } from "vue-i18n";
import enUS from "./locales/en_US";
import kmKH from "./locales/km_KH";
import zhCN from "./locales/zh_CN";
// 支持的语言
const SUPPORTED_LANGS = ["zh-CN", "en-US", "km-KH"];
// 获取并规范化语言
const getLanguage = () => {
// 1. 优先使用 localStorage
let lang = localStorage.getItem("language");
// 2. 其次根据浏览器语言自动判断
if (!lang) {
const nav = navigator.language.toLowerCase();
if (nav.startsWith("zh")) {
lang = "zh-CN";
} else if (nav.startsWith("en")) {
lang = "en-US";
} else if (nav.startsWith("km")) {
lang = "km-KH";
} else {
lang = "zh-CN";
}
}
// 3. 确保语言被支持
if (!SUPPORTED_LANGS.includes(lang)) {
lang = "zh-CN";
}
// 4. 确保 localStorage 是标准格式
localStorage.setItem("language", lang);
return lang;
};
const language = getLanguage();
const i18n = createI18n({
legacy: false, // 使用Composition API,这里必须设置为false
locale: language, // 默认显示语言
fallbackLocale: "zh-CN", // 当语言找不到时,用中文兜底
globalInjection: true, // 全局注册$t方法
messages: {
// 配置语言对应的文件
"zh-CN": zhCN,
"en-US": enUS,
"km-KH": kmKH,
},
});
export default i18n;
语言包层级同上、用法同上、只是导入方法不同
问题记录
当需要动态使用语言包中的键
可以使用以下两种写法
<uni-section :title="$t(`menuTitle.${item.name}`)" type="line"></uni-section>
<text class="text">{{ $t(`menuTitle.${i.name}`) }}</text>
computed: {
menuTitle() {
return (key) => this.$t(`menuTitle.${key}`);
}
},
<uni-section :title="menuTitle(item.name)" type="line"></uni-section>
<text class="text">{{ menuTitle(i.name) }}</text>
在uniapp中需要把底部导航的展示内容也根据语言包配置切换
//在每个语言配置的文件中先将键名和键值配置好
//如
export default{
tabBar:{
mine:'我的',
home:'首页'
},
title:{
ceshi:'测试'
}
}
//先将text的值替换为对应的键名
"tabBar": {
"color": "#000000",
"selectedColor": "#000000",
"borderStyle": "white",
"backgroundColor": "#ffffff",
"list": [{
"pagePath": "pages/index",
"iconPath": "static/images/tabbar/home.png",
"selectedIconPath": "static/images/tabbar/home_.png",
"text": "home"
},
// {
// "pagePath": "pages/work/index",
// "iconPath": "static/images/tabbar/work.png",
// "selectedIconPath": "static/images/tabbar/work_.png",
// "text": "工作台"
// },
{
"pagePath": "pages/my/index",
"iconPath": "static/images/tabbar/mine.png",
"selectedIconPath": "static/images/tabbar/mine_.png",
"text": "mine"
}
]
},
//然后再App.vue文件中配置默认展示的语言包
onLaunch: function() {
this.setTabBarText();
},
methods:{
setTabBarText() {
const tabBarList = [{
index: 0,
text: this.$t('tabBar.home')
},
{
index: 1,
text: this.$t('tabBar.mine')
}
];
tabBarList.forEach(item => {
wx.setTabBarItem({
index: item.index,
text: item.text
});
});
},
}
//最后在切换语言包的组件里面添加事件 switch.vue
//如点击事件
changeLanguage(language) {
this.locale = language;
localStorage.setItem("language", language);
this.$i18n.locale = language; // 确保 Vue-i18n 的语言切换
this.$nextTick(() => {
this.setTabBarText();
});
},
//这样在切换语言的时候底部导航也会一起改变
更多推荐
所有评论(0)