Vue3?接入?i18n?實現(xiàn)國際化多語言案例分析
1. 基本方法
在 Vue.js 3 中實現(xiàn)網(wǎng)頁的國際化多語言,最常用的包是 vue-i18n
,通常我們會與 vue-i18n-routing
一起使用。
vue-i18n
負(fù)責(zé)根據(jù)當(dāng)前頁面的語言渲染文本占位符,例如:
<span>{{ t('Login') }}</span>
當(dāng)語言設(shè)置為中文時,會將 Login
渲染為“登錄”。
vue-i18n-routing
負(fù)責(zé)將頁面語言與 URL 綁定,例如:
https://githubstar.pro/zh-CN/repo
表示訪問中文版的 /repo
路徑。
將不同語言的網(wǎng)頁放在不同的 URL 下有助于 SEO,因為可以在 <head>
部分添加語言信息,增加不同語言被搜索引擎索引的概率。
Google 對于多語言 Vue 站點的爬取機(jī)制如下:
- 類似 Vue 站點的 JS 動態(tài)頁面是可以被爬取的,不影響權(quán)重 (參見 Google SEO)。
- 與用戶首選語言匹配的頁面將優(yōu)先展示 (參見 Google SEO)。
2. 基礎(chǔ)實現(xiàn)
第一步,安裝一個 Vite 下使用 <i18n>
標(biāo)簽的插件:unplugin-vue-i18n
。
然后調(diào)整 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)), }, }, });
添加插件后,我們可以在組件內(nèi)使用 <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 作為當(dāng)前語言,編輯 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
= 英文
由于我們設(shè)置了 defaultLocale: 'zh-CN'
,默認(rèn)路徑為中文。
然后,我們需要將源代碼中涉及跳轉(zhuǎn)的部分,例如:
router.push({ name: 'home' });
全部加上 localePath
,表示是當(dāng)前語言的 URL 路徑下:
import { useLocalePath } from 'vue-i18n-routing'; const localePath = useLocalePath(); router.push(localePath({ name: 'home' }));
這樣就完成了路徑綁定。
4. 自動切換
有時,我們希望沒有默認(rèn)語言,而是根據(jù)用戶的瀏覽器語言自動選擇:
/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 中的存儲項。
邏輯是:如果用戶手動設(shè)定了語言(savedLang
),則使用之;如果沒有,則使用系統(tǒng)偏好的第一個語言。這樣,我們只要取 lang
的值就可以得到最終的偏好語言是中文還是英文。
然后,我們需要定義一個路徑守衛(wèi),以自動處理 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
,這樣請求才能到達(dá)router.beforeEach
。 - 我們?nèi)サ袅?nbsp;
defaultLocale
。 - 使用剛才定義的 store:
useLangStore()
這行代碼必須放在router.beforeEach
中,而不能放在模塊頂端,因為加載模塊時 Pinia 還沒有啟動。
這樣,就實現(xiàn)了無語言路徑自動跳轉(zhuǎn)到當(dāng)前偏好語言路徑。
5. 導(dǎo)航欄切換按鈕
然后,可以在導(dǎo)航欄增加一個按鈕,來手動切換語言,例如:
<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 中存儲當(dāng)前手動設(shè)定的語言,同時使用 switchLocalePath
來實現(xiàn)路徑和語言的切換。
6. SEO 和 Head Meta
同一內(nèi)容的不同語言版本應(yīng)該在 head
中進(jìn)行標(biāo)注,并指向所有其他替代頁面(參見 Google SEO)。這里我們可以在 App.vue
中用 useLocaleHead
和來自 @unhead/vue
包的 useHead
進(jìn)行設(shè)置:
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 || [])]), }); });
這樣就基本實現(xiàn)了一個多語言的國際化站點??赡茉谶M(jìn)行前端翻譯的同時,后端也需要進(jìn)行翻譯,請期待下一期:Python Flask 后端如何接入 i18n 實現(xiàn)國際化多語言!
7. 案例分析
案例:GithubStar.Pro 的前端界面國際化多語言,是使用本文所述的方法實現(xiàn)的,各位可以看看效果。
也歡迎各位使用 GithubStar.Pro 互贊平臺,提高您的開源項目知名度,收獲更多用戶。
到此這篇關(guān)于Vue3 如何接入 i18n 實現(xiàn)國際化多語言的文章就介紹到這了,更多相關(guān)Vue3 國際化多語言內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
vue結(jié)合Echarts實現(xiàn)點擊高亮效果的示例
下面小編就為大家分享一篇vue結(jié)合Echarts實現(xiàn)點擊高亮效果的示例,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧2018-03-03element-ui表單提交自動清空隱藏表單值實現(xiàn)
這篇文章主要為大家介紹了element-ui表單提交自動清空隱藏表單值實現(xiàn)示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-07-07Vue使用Echarts實現(xiàn)大屏可視化布局示例詳細(xì)講解
這篇文章主要介紹了Vue使用Echarts實現(xiàn)大屏可視化布局示例,本文通過實例代碼圖文相結(jié)合給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-01-01