Vue3 如何接入 i18n 实现国际化多语言
1. 基本方法
在 Vue.js 3 中实现网页的国际化多语言,最常用的包是 vue-i18n
,通常我们会与 vue-i18n-routing
一起使用。
vue-i18n
负责根据当前页面的语言渲染文本占位符,例如:
<span>{{ t('Login') }}</span>
当语言设置为中文时,会将 Login
渲染为“登录”。
vue-i18n-routing
负责将页面语言与 URL 绑定,例如:
https://githubstar.pro/zh-CN/repo
表示访问中文版的 /repo
路径。
将不同语言的网页放在不同的 URL 下有助于 SEO,因为可以在 <head>
部分添加语言信息,增加不同语言被搜索引擎索引的概率。
Google 对于多语言 Vue 站点的爬取机制如下:
- 类似 Vue 站点的 JS 动态页面是可以被爬取的,不影响权重 (参见 Google SEO)。
- 与用户首选语言匹配的页面将优先展示 (参见 Google SEO)。
2. 基础实现
第一步,安装一个 Vite 下使用 <i18n>
标签的插件:unplugin-vue-i18n
。
然后调整 vite.config.js
:
import { fileURLToPath, URL } from 'node:url';
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import VueDevTools from 'vite-plugin-vue-devtools';
import VueI18nPlugin from '@intlify/unplugin-vue-i18n/vite';
export default defineConfig({
plugins: [
vue(),
VueDevTools(),
VueI18nPlugin({}),
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url)),
},
},
});
添加插件后,我们可以在组件内使用 <i18n>
块:
<script setup lang="ts">
import { useI18n } from 'vue-i18n';
const { t, locale } = useI18n({ inheritLocale: true, useScope: 'local' });
</script>
<template>
<span>{{ t('Login') }}</span>
</template>
<i18n lang="yaml">
en:
Login: 'Login to web'
zh-CN:
Login: '登录'
</i18n>
这里我们定义了两种不同的语言。
3. 路径绑定
接下来,我们需要定义使用 URL 作为当前语言,编辑 router/index.ts
:
import { createRouter as _createRouter, type RouteLocationNormalized } from 'vue-i18n-routing';
import { createWebHistory } from 'vue-router';
import HomeView from '@/views/HomeView.vue';
const locales = [
{
code: 'en',
iso: 'en-US',
name: 'English',
},
{
code: 'zh-CN',
iso: 'zh-CN',
name: '中文',
},
];
export function createRouter(i18n: any) {
const router = _createRouter(i18n, {
version: 4,
locales: locales,
defaultLocale: 'zh-CN',
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/home',
name: 'home',
component: HomeView,
},
],
});
return router;
}
我们定义了支持的语言种类,并将原来的 routes
包装起来,vue-i18n-routing
会自动生成所有支持语言的 routes
:
/home
= 中文/en/home
= 英文
由于我们设置了 defaultLocale: 'zh-CN'
,默认路径为中文。
然后,我们需要将源代码中涉及跳转的部分,例如:
router.push({ name: 'home' });
全部加上 localePath
,表示是当前语言的 URL 路径下:
import { useLocalePath } from 'vue-i18n-routing';
const localePath = useLocalePath();
router.push(localePath({ name: 'home' }));
这样就完成了路径绑定。
4. 自动切换
有时,我们希望没有默认语言,而是根据用户的浏览器语言自动选择:
/zh-CN/home
= 中文/en/home
= 英文/home
-> 重定向 (浏览器偏好中文) ->/zh-CN/home
= 中文/home
-> 重定向 (浏览器偏好英文) ->/en/home
= 英文
这时我们需要定义一个 store,这里使用 Pinia store,Vuex 同理。
import { usePreferredLanguages, useStorage } from '@vueuse/core';
import { defineStore } from 'pinia';
export const useLangStore = defineStore('lang', {
state: () => {
const savedLang = useStorage<string | null>('lang', null, undefined);
const systemLang = usePreferredLanguages();
return { savedLang, systemLang };
},
getters: {
lang: (state) => {
const lang = state.savedLang || state.systemLang[0];
if (lang.startsWith('zh')) {
return 'zh-CN';
} else {
return 'en';
}
},
},
actions: {
setLang(l?: string) {
if (!l) {
this.savedLang = null;
} else {
this.savedLang = l;
}
},
}
});
这段代码使用了 VueUse 中的 usePreferredLanguages
来获得用户偏好的浏览器语言,并用 useStorage
添加了一个 LocalStorage 中的存储项。
逻辑是:如果用户手动设定了语言(savedLang
),则使用之;如果没有,则使用系统偏好的第一个语言。这样,我们只要取 lang
的值就可以得到最终的偏好语言是中文还是英文。
然后,我们需要定义一个路径守卫,以自动处理 URL 中没有语言的情况。
import { createRouter as _createRouter, type RouteLocationNormalized } from 'vue-i18n-routing';
import { createWebHistory } from 'vue-router';
import HomeView from '@/views/HomeView.vue';
const locales = [
{
code: 'en',
iso: 'en-US',
name: 'English',
},
{
code: 'zh-CN',
iso: 'zh-CN',
name: '中文',
},
{
code: '',
iso: '',
name: '',
}
];
export function createRouter(i18n: any) {
const router = _createRouter(i18n, {
version: 4,
locales: locales,
history: createWebHistory(import.meta.env.BASE_URL),
routes: [
{
path: '/home',
name: 'home',
component: HomeView,
},
],
});
router.beforeEach((to: RouteLocationNormalized, from: RouteLocationNormalized) => {
const lang = useLangStore();
const pathLocale = to.path.split('/')[1];
if ((!pathLocale) || (!locales.some(locale => locale.code === pathLocale))) {
return `/${lang.lang}${to.path}`;
}
});
return router;
}
这里需要注意三点:
- 我们增加了一个新的空
locales
,这样请求才能到达router.beforeEach
。 - 我们去掉了
defaultLocale
。 - 使用刚才定义的 store:
useLangStore()
这行代码必须放在router.beforeEach
中,而不能放在模块顶端,因为加载模块时 Pinia 还没有启动。
这样,就实现了无语言路径自动跳转到当前偏好语言路径。
5. 导航栏切换按钮
然后,可以在导航栏增加一个按钮,来手动切换语言,例如:
<script setup lang="ts">
import { useLocalePath, useSwitchLocalePath } from 'vue-i18n-routing';
import { useLangStore } from '@/stores/lang';
const lang = useLangStore();
const { t, locale } = useI18n({ inheritLocale: true, useScope: 'local' });
</script>
<template>
<div
@click="
lang.setLang('en');
router.push(switchLocalePath('en'));
menuShown = '';
"
class="py-2 px-2 gap-2 flex items-center cursor-pointer hover:bg-slate-400/10"
:class="{ 'text-sky-300': locale == 'en' }"
role="option"
tabindex="-1"
:aria-selected="locale == 'en'"
>
<IconEnglish class="w-5 h-5 text-slate-400 dark:text-slate-200" />
English
</div>
<div
@click="
lang.setLang('zh-CN');
router.push(switchLocalePath('zh-CN'));
menuShown = '';
"
class="py-2 px-2 gap-2 flex items-center cursor-pointer hover:bg-slate-400/10"
:class="{ 'text-sky-300': locale == 'zh-CN' }"
role="option"
tabindex="-1"
:aria-selected="locale == 'zh-CN'"
>
<IconChinese class="w-5 h-5 text-slate-400 dark:text-slate-200" />
中文
</div>
</template>
这里,我们在刚才定义的 store 中存储当前手动设定的语言,同时使用 switchLocalePath
来实现路径和语言的切换。
6. SEO 和 Head Meta
同一内容的不同语言版本应该在 head
中进行标注,并指向所有其他替代页面(参见 Google SEO)。这里我们可以在 App.vue
中用 useLocaleHead
和来自 @unhead/vue
包的 useHead
进行设置:
import { useLocaleHead } from 'vue-i18n-routing';
import { useHead } from '@unhead/vue';
const i18nHead = useLocaleHead({ addSeoAttributes: true, defaultLocale: null, strategy: null });
onMounted(() => {
useHead({
htmlAttrs: computed(() => ({
lang: i18nHead.value.htmlAttrs!.lang,
})),
link: computed(() => [...(i18nHead.value.link || [])]),
meta: computed(() => [...(i18nHead.value.meta || [])]),
});
});
这样就基本实现了一个多语言的国际化站点。可能在进行前端翻译的同时,后端也需要进行翻译,请期待下一期:Python Flask 后端如何接入 i18n 实现国际化多语言!
6. 案例分析
案例:GithubStar.Pro 的前端界面国际化多语言,是使用本文所述的方法实现的,各位可以看看效果。
也欢迎各位使用 GithubStar.Pro 互赞平台,提高您的开源项目知名度,收获更多用户。
Vue3 如何接入 i18n 实现国际化多语言的更多相关文章
- php gettext方式实现UTF-8国际化多语言(i18n)
php gettext方式实现UTF-8国际化多语言(i18n) 一.总结 一句话总结: 二.php gettext方式实现UTF-8国际化多语言(i18n) 近 来随着i18n(国际化)的逐渐标准化 ...
- WPF 实际国际化多语言界面
前段时候写了一个WPF多语言界面处理,个人感觉还行,分享给大家.使用合并字典,静态绑定,动态绑定.样式等东西 效果图 定义一个实体类LanguageModel,实际INotifyPropertyCha ...
- Go Revel - i18n(国际化)
##Messages `Messages`信息是对内容提供翻译的外部文本片段.revel提供了组织每一种语言文本片段的message文件.自动区域查找.基于cookie覆盖的消息嵌套和参数. 术语表: ...
- [Spring]Spring Mvc实现国际化/多语言
1.添加多语言文件*.properties F64_en_EN.properties详情如下: F60_G00_M100=Please select data. F60_G00_M101=Are yo ...
- yii2 api接口 实现国际化多语言设置
1) 在 /config/main.php 下添加如下代码: 'components' => [ 'language' => 'zh-CN', 'i18n' => [ 'transl ...
- iOS 国际化多语言设置 xcode7
iOS 国际化多语言设置 方式一: 1. 在storyboard中创建好UI,然后在 project 里面 Localizables 栏目里面,添加你需要的语言:默认是Englist; 比如这里我添 ...
- 更好用的excel国际化多语言导出
不知道大家在开发中有没有遇到过『excel导出』的需求,反正我最近写了不少这种功能,刚开始利用poi,一行行的手动塞数据,生成excel,而且还有国际化需求,比如:标题栏有一列,用户切换成" ...
- iOS 学习笔记六 【APP中的文字和APP名字的国际化多语言处理】
今天为新手解决下APP中的文字和APP名字的国际化多语言处理, 不多说了,直接上步骤: 1.打开你的项目,单机project名字,选中project,直接看图吧: 2.创建Localizable.st ...
- Blazor 国际化多语言界面 (I18nText )
在实际使用中,我们经常会遇到需要把程序界面多种语言切换,适应不同地区使用者的需求,本文介绍一个我初学Blazor接触到的库,边撸边讲解. 包名: Toolbelt.Blazor.I18nText ht ...
- vue-cli之路由独立成JS文件之后,如何在路由中获取vuex属性或者设置国际化i18n的当前使用语言
国际化vue-i18n的使用: import Vue from 'vue'; import VueI18n from 'vue-i18n'; // 引入语言包 import zh from '@/co ...
随机推荐
- .NET周刊【5月第1期 2024-05-05】
国内文章 一个开源轻量级的C#代码格式化工具(支持VS和VS Code) https://www.cnblogs.com/Can-daydayup/p/18164905 CSharpier是一个开源. ...
- linux 下对zip,rar,tar,tar.gz,tar.bz2,tar.xz,gzip,bzip2,xz文件的归档,压缩和解压缩
目录 一.关于打包和压缩 二.linux对rar文件的压缩和解压缩 三.使用tar对文件进行归档,压缩,解压缩 3.1 tar对文件进行归档和解压 3.2 归档的添加和删除 3.3 tar对文件进行归 ...
- Vue cli之组件的嵌套
前面显示Home.vue页面组件的内容时,我们是在App.vue通过import导入使用的.这个过程就是组件的嵌套使用.那么我们除了App.vue可以导入其他页面以外,也可以通过在Home.vue中导 ...
- HTML——input之单选按钮
在 HTML 中,把 <input> 标签的 type 属性设置为 radio 可以表示单选按钮.具体语法格式如下: <input type="radio" /& ...
- H.264码流解析
这一篇内容旨在对H.264码流中的一些概念做简单了解. 1.概念了解 VCL:Video Coding Layer视频编码层,它是H.264(AVC)编码中的核心,负责视频数据的编码工作.VCL层会应 ...
- WPF实现轮播图
1.效果图 2.前端代码 <Window x:Class="LiveChartDemo.View.CarouselView" xmlns="http://schem ...
- C# wpf 实现Converter定义与使用
1. 本身的值0, 如何转换为"男" 或"女"呢,可以定义sexConverter继承自IValueConverter即可,代码如下: [ValueConve ...
- 利用cycript动态调试app
一.准备 ios系统越狱环境 安装ssh 安装cycript 二.执行命令 找到进程注入: 6187 ?? 0:00.70 /var/containers/Bundle/Application/ 61 ...
- 【Effective C++】设计与声明——考虑写出一个不抛异常的swap函数
wap是个有趣的函数.原本它只是STL的一部分,而后成为异常安全性编程的脊柱,以及用来实现自我赋值可能性的一个常见机制.所谓swap两对象值,就是将两对象的值交换. 典型实现 缺省情况下的swap动作 ...
- Linux扩展篇-shell编程(九)-shell 异常处理
1.异常退出 ${0}:获取当前脚本的名称 $?:获取函数返回值或者上一个命令的退出状态 set -x:开启debug调试功能 按照目前个人理解,异常分为以下几种情况: 程序处理的异常退出 程序员判断 ...