什麼是多語言?
原文出自:https://www.pandashen.com
我們平時訪問一些文檔類型的網站時,經常可以看到頁面右上角有一個下拉框用來選擇當前頁面支持的語言,並在選中後將整個網頁的內容切換爲選中的語言,這就是項目中的多語言,多語言可以根據瀏覽器請求發送的語言類型在服務器進行設置,也可以在請求服務器時返回多種語言,並根據權重和瀏覽器的支持情況進行選擇和渲染。
功能描述
在本文中我們通過客戶端向服務器發送請求告訴服務器客戶端所支持的語言及權重,服務器檢索語言包並根據客戶端發送的語言類型和權重返回對應語言的內容。
在這個過程中客戶端向服務器發送請求需要使用請求頭 Accept-Language
,值中設置語言類型和權重,語言與語言之間使用 ,
隔開,語言與權重之間使用 ;
隔開,權重用 q
表示,與值用 =
隔開,如果權重值爲 1
則可省略(最大值),值的格式爲 zh-CN, zh;q=0.7, en;q=0.8, fr;q=0.1
。
服務器響應時,應通過響應頭告訴瀏覽器返回的內容爲何種語言,響應頭爲 Content-Language
, 值的格式爲 zh-CN, en
,多個語言之間使用 ,
隔開。
服務器的實現
// 文件:server.js
const http = require("http");
const querystring = require("querystring");
// 語言包
let languagesPackage = {
"zh-CN": "你好",
en: "Hello",
fr: "Bonjour"
};
// 默認語言爲英語
languagesPackage.defaultLanguage = "en";
// 創建服務器
const server = http.createServer((req, res) => {
// 獲取請求頭中的語言和權重
let languages = req.headers["accept-language"];
// 如果客戶端設置了語言
if (languages) {
// 解析語言爲 [{ name: 'zh-CN', q: 1 }, { name: 'en', q: '0.8' }] 格式
let lans = languages
.split(",")
.map(lang => {
let [name, q = 1] = Object.keys(
querystring.parse(lang.tirm(), ";q=")
);
return { name, q };
})
.sort((a, b) => b.q - a.q); // 並按照權重逆序排序
// 循環檢測 languagesPackage 是否存在客戶端的語言
for (let i = 0; i < lans.length; i++) {
let { name } = lans[i];
let content = languagesPackage[name];
// 如果存在直接設置響應頭並返回內容
if (content) {
res.setHeader("Content-Type", name);
return res.end(content);
}
}
}
// 如果客戶端沒設置語言活語言找不到時返回服務器設置的默認語言
res.setHeader("Content-Type", languagesPackage.defaultLanguage);
res.end(languagesPackage[languagesPackage.defaultLanguage]);
});
server.listen(3000, () => {
console.log("server start 3000");
});
其實上面服務器和客戶端配合實現多語言的思路就是客戶端向服務器發送 Accept-Language
告訴服務器需要的語言和權重,服務器解析後根據權重從大到小排序,然後循環判斷語言包中是否含有客戶端需要的語言,如果有,則中斷循環直接設置響應頭和返回對應內容,如果不存在客戶端的需要的語言或者客戶端沒有向後臺發送 Accept-Language
則返回服務器默認設置的語言類型和內容。
驗證多語言
爲了方便我們使用 curl
模擬客戶端向服務器發送請求查看返回內容是否正確,之所以使用 curl
是因爲只發送驗證的請求,方便設置 Accept-Language
請求頭,更靈活的控制多語言的類型和權重。
啓動服務器 server.js
,打開命令行窗口,輸入下面的命令執行,查看返回命令行響應體中的內容和設置的語言是否對應。
curl -v --header "Accept-Language: zh-CN, zh;q=0.7, en;q=0.8, fr;q=0.1" http://localhost:3000
總結
這樣我們就實現了一個簡單的多語言,其實真正的多語言在服務器是需要做繁瑣的解析和性能優化的(只解析界面有的單詞返回,保證響應體中的內容最小),在前端可以通過 JavaScript 的庫 il8n
(國際化語言包)來實現。