國際化演示地址: H5-Dooring國際化
注: ⚠️本文爲掘金社區首發簽約文章,未獲受權禁止轉載javascript
多語言(i18n)支持 是企業項目走向國際化的必經之路,也是前端工程師最佳實踐的內容之一。不過,多語言框架衆多,會帶來一系列選型問題,相信你們在平時對項目進行多語言支持時,也每每會遇到以下幾個問題:css
其實,多語言框架雖多,可是從傳統的 jquery
時代到目前流行的 MVVM
框架,多語言方案一直在演進和優化,最終目的是將其普適化和最簡化。理解了這一點,學習多語言技術就容易多了。html
我在設計和實踐低代碼/零代碼搭建平臺 Dooring 的過程當中,也遇到了多語言方案的技術選型,目前方案基本完成,接下來我將帶你們一步步分析多語言在不一樣技術棧中的實現方案,並以實際的項目讓你們掌握多言語技術,在文章最後我也會提出對多語言將來演進的一些方向,供你們研究和探索。前端
按照我一貫的寫做風格,我會在下面列出文章的大綱,以便你們有選擇且高效率的閱讀和學習:vue
目前經常使用的多語言方案基本都是人工翻譯,而後經過動態替換來實現語言的切換,可是不一樣的技術框架模式稍有不一樣, 接下來咱們就逐個分析一下。java
在傳統方案中最容易想到的就是dom替換。咱們經過提早定義好多語言文件(或文案Map),並在html標籤中作語言映射,最後經過切換函數來動態的切換網站語言。其基本的模式以下:react
// 語言庫,咱們有兩種方式來定義
// 1. 單文件Map模式, lang.js
const lang = {
zh: {
'title': 'H5編輯器',
'userLogin': '用戶登陸',
'usernameError': '請輸入用戶名'
},
en: {
'title': 'H5 editor',
'userLogin': 'The user logs on',
'usernameError': 'Please enter your username'
},
}
// 2. 多語言包模式
lang/cn.json
lang/en.json
複製代碼
html標籤結構以下:jquery
<select id="langControl">
<option value="cn">中文</option>
<option value="en">English</option>
</select>
<div lang="title">H5編輯器</div>
<div lang="userLogin">用戶登陸</div>
複製代碼
最後咱們經過 javascript
遍歷 [lang]
屬性並經過映射關係來替換語言。固然咱們還能夠經過 template.js
這樣的模版引擎來優化咱們dom
的渲染替換方式,可是以上方案在落地過程當中仍然須要考慮不少問題。以下:webpack
在傳統方案中咱們爲了解決以上問題並支持更復雜系統,咱們不得不考慮插件化,固然 Jquery-I18n
就是一個很是不錯的解決方案。它能夠幫助咱們輕鬆地國際化 Web 應用程序,而且支持鏈式調用, 且能夠無刷新切換語言。接下來我就帶你們使用 Jquery-I18n
實現一個簡單的demo,讓你們更好的掌握該方案。git
<script src="https://cdn.bootcss.com/jquery/3.10.2/jquery.min.js"></script>
<script src="https://cdn.bootcss.com/js-cookie/latest/js.cookie.min.js"></script>
<script src="./js/jquery.i18n.js"></script>
複製代碼
<select id="langControl">
<option value="cn">中文</option>
<option value="en">English</option>
</select>
<div lang="title">H5編輯器</div>
<div lang="userLogin">用戶登陸</div>
複製代碼
function toggleLang(lang){
$("[lang]").i18n({
defaultLang: lang, // 默認語言
filePath: "/lang/", // 語言文件所在的目錄
filePrefix: "", // 語言文件前綴
fileSuffix: "", // 語言文件後綴
forever: true,
callback: function(res) {} // 初始化後的回調
});
}
// 語言切換
$('#langControl').change(val => {
toggleLang(val)
})
複製代碼
固然 Jquery-I18n
有更多強大的配置,你們能夠參考文檔進行配置,相關庫 github
地址以下:
固然以上方案還只是手動切換語言,更多的需求場景是要咱們基於用戶當前的瀏覽器環境或者網站連接地址的參數不一樣來自動切換對應的語言。對於經過連接參數來改變系統語言,這個咱們只須要經過解析參數並進行對應的處理便可,好比解析 http://xxx.xxx?lan=cn
或 http://xxx.xxx?lan=en
。固然瀏覽器也提供了對應的 api
能夠獲取當前用戶瀏覽的環境:navigator.language
,咱們在瀏覽器控制檯輸入該腳本的結果以下:
因此咱們能夠根據這個信息來自動匹配用戶當前的語言模式。
基於 Vue 的多語言方案網上也有不少,畢竟國內大部分企業都在使用 Vue 開發項目,因此我簡單列舉幾個成熟的方案給你們,並對其中一個方案給出具體的實踐:
固然你們若是作的不是很複雜的項目,也能夠直接採用 simplest-i18n,由於其更簡單輕量。
接下來我會以一個完整的例子來講明如何使用 vue-i18n 來作 Vue 項目的國際化。
import Vue from "vue";
import VueI18n from "vue-i18n";
Vue.use(VueI18n);
// 加載全部語言環境並記住上下文
function loadMessages() {
const context = require.context("./lang", true, /[a-z0-9-_]+.json$/i);
const messages = context
.keys()
.map((key) => ({ key, locale: key.match(/[a-z0-9-_]+/i)[0] }))
.reduce(
(messages, { key, locale }) => ({
...messages,
[locale]: context(key),
}),
{}
);
return { context, messages };
}
const { context, messages } = loadMessages();
// VueI18n 實例
const i18n = new VueI18n({
locale: navigator.language, // 根據瀏覽器環境設置網站語言
messages,
});
// 運行程序
const app = new Vue({
i18n,
// ...
}).$mount('#app');
// 切換語言(在組件內也可使用$i18n.locale來切換語言環境)
i18n.locale = 'en-US'
// 熱更新支持
if (module.hot) {
module.hot.accept(context.id, () => {
const { messages: newMessages } = loadMessages();
Object.keys(newMessages)
.filter((locale) => messages[locale] !== newMessages[locale])
.forEach((locale) => {
messages[locale] = newMessages[locale];
i18n.setLocaleMessage(locale, messages[locale]);
});
});
}
複製代碼
固然在項目中咱們還能夠延遲加載翻譯,原理相似 webpack 的異步加載文件,參考以下:
export function loadLangAsync(lang) {
// 若是語言相同
if (i18n.locale === lang) {
return Promise.resolve(...)
}
// 若是語言已經加載
if (loadedLanguages.includes(lang)) {
return Promise.resolve(...)
}
// 若是還沒有加載語言
return import(/* webpackChunkName: "lang-[request]" */ `@/lang/${lang}.json`).then(
messages => {
// ... 處理邏輯
}
)
}
複製代碼
同時 vue-cli
還提供了對應的插件 vue-cli-plugin-i18n 來支持經過配置化的方式開啓多語言。
首先其實多語言在 Vue 和 React 項目中都有一個很是簡單的方案,
其基本流程以下:
cookie
cookie
語言信息並刷新頁面固然市場上也有不少成熟的解決方案,以下:
接下來筆者將結合本身的案例,採用 react-i18next + i18next 方案來實現一個完整的 demo。
# npm
$ npm install react-i18next i18next --save
複製代碼
定義語言包(這裏和以前同樣,這裏不在重述)
代碼實現
3.1 全局配置i18n
// i18n.js
import i18n from "i18next";
import { initReactI18next } from "react-i18next";
import en from 'locales/en-US.js';
import cn from 'locales/zh-CN.js';
const resources = {
en: {
translation: en
},
cn: {
translation: cn
}
};
i18n
.use(initReactI18next) // 註冊
.init({
resources,
lng: "cn", // 默認語言
interpolation: {
escapeValue: false // xss安全開關
}
});
export default i18n;
複製代碼
3.2 配置入口文件
// index.js
import React, { Component } from "react";
import ReactDOM from "react-dom";
// ...其餘庫
import './i18n';
import App from './App';
ReactDOM.render(
<App />,
document.getElementById("root")
);
複製代碼
3.3 在react組件中使用:
import React from 'react';
import { useTranslation } from 'react-i18next';
function Home () {
const { t, i18n } = useTranslation();
return <h1>{t('title')}</h1>
}
複製代碼
以上就是一個完整的使用流程,固然你們也可使用該庫實現更多有意思的功能。
在介紹完不一樣技術棧實現的多語言方案以後,咱們以 H5-Dooring 爲實際案例,來將其國際化一下。由於 H5-Dooring 編輯器端主要採用 React 開發,並採用 umi 作工程化方案,因此我天然選擇 umi 對應的生態來實現,好在其提供了開箱即用的 @umijs/plugin-locale 插件,咱們能夠輕鬆的實現國際化,接下來我將採用該方案來帶你們實現國際化,若是你們也在使用 umi,能夠參考一下。
先上張效果圖:
首先咱們須要配置一下 umirc.ts
文件,添加以下配置:
locale: {
default: 'zh-CN', // 默認的語言
antd: true, // antd是否也支持國際化
title: true, // 頁面標題是否支持國際化
baseNavigator: true, // 開啓瀏覽器語言檢測
},
複製代碼
其次咱們須要定義多語言文件:
語言文件內容以下:
在作好基本準備工做以後,咱們看看如何在項目中使用多語言。咱們已入口頁面爲例來講明:
首先咱們須要引入對應的插件,以下:
import { useIntl, setLocale } from 'umi';
複製代碼
其次在 hooks
組件裏使用 hook
:
const Home = ({ location }) => {
// ... 其餘邏輯狀態
const [lang, setLang] = useState('En');
const intl = useIntl();
return <div> <span className={styles.btnControl} onClick={toggleLang}>{ lang } </span> <h3>{ intl.formatMessage({id: 'dr.friendHelp'}) }</h3> <h3>{ intl.formatMessage({id: 'dr.personHelp'}) }</h3> <Form.Item label={ intl.formatMessage({id: 'dr.cpEnName'}) } name="cpField" rules={[{ required: true, message: intl.formatMessage({id: 'dr.cpInfoError'}, { text: intl.formatMessage({id: 'dr.cpName'})}) }]}> <Input placeholder={ intl.formatMessage({id: 'dr.cpInfoError'}, { text: intl.formatMessage({id: 'dr.cpEnName'})}) } /> </Form.Item> </div>
}
複製代碼
以上就是基本的實現,咱們能夠在語言文件中使用變量,並在項目中動態指定變量的值,是否是很強大呢? 對於多語言切換,企業提供了對應的 API
,並支持無刷新切換和刷新切換兩種模式,使用方式以下:
const toggleLang = () => {
if(lang === 'En') {
setLocale('en-US', false);
setLang('中文')
return
}
setLocale('zh-CN', false);
setLang('En');
}
複製代碼
由上能夠看出咱們使用setLocale
這個api來切換語言,第一個參數爲語言文本,第二個參數表示切換語言時是否刷新頁面。
以上探索的方案都是人工來作翻譯,我在翻譯的過程當中耗費了大量的精力和時間,若是網站愈來愈複雜, 會投入更多的精力,因此說通用的智能化翻譯方案在將來將是迫切須要解決的問題,也是國際化 i18n 演進的必經之路,雖然國內已經有大公司內部在作對應的事情了,甚至已經有了必定的解決方案積累,在這裏我大體給出一個基本的思路設想:
這樣的話咱們只須要以一種語言爲基礎來進行正常開發,其餘語言會經過咱們的工具自動翻譯並轉化爲對應的語言文件。後續筆者會落實該方案,你們也能夠嘗試不一樣的智能化方案,一塊兒探索前端效能提高之路。