Accept-Language
我們能從請求頭中獲取到瀏覽器愿意接收的語言類型
let http = require('http');
http.createServer(function(req,res){
res.end(req.headers['accept-language']);
}).listen(8080);
<<< 輸出
zh-CN,zh;q=0.9
其中多種語言之間用,隔開,而每種語言又可用;分隔,分隔的前面為該種語言的簡稱,后面為其權(quán)重(優(yōu)先級)。
langPackage/語言包
一般支持多語言的網(wǎng)站,其服務(wù)器都存儲了多種語言包。當(dāng)客戶端向其請求時(shí),服務(wù)器會查看請求頭看一看客戶端所愿意支持的語言,然后在自己的語言包中進(jìn)行查找??蛻舳私o的接收清單中包含每一種語言的權(quán)重,服務(wù)器會返回客戶端它有的且客戶端相對更喜歡的那一種。如果服務(wù)器所存儲的語言包和客戶端給的清單匹配不上,那么一般來說會使用服務(wù)器所預(yù)置的默認(rèn)語言包。
語言包示例
let langPack = {
"zh":{
title:'哈啰 世界!'
}
,"en":{
title:"hello world!"
}
}
封裝 getLang
該方法能自動識別客戶端愿意接收的語言類型,然后從服務(wù)器所儲存的多種語言包中選擇一種最合適的來返回?cái)?shù)據(jù)。
最終使用效果像這樣
getLang(req,'title')
設(shè)計(jì)思路
將accept-language解析成一個(gè)數(shù)組,并按照權(quán)重進(jìn)行排序
首先需要對accept-language進(jìn)行解析,將其解析成一個(gè)個(gè)對象。每個(gè)對象代表一種語言,它有兩個(gè)屬性:
langType:語言的類型q:語言的權(quán)重
幫助我們篩選出客戶端相對較喜歡的那一種語言
接著將每個(gè)對象放在一個(gè)數(shù)組中,按照權(quán)重從大到小排列。
選擇語言類型
然后依次將數(shù)組成員的langType和服務(wù)器中所儲存的語言包進(jìn)行匹配,直到匹配成功或遍歷結(jié)束,如果遍歷結(jié)束時(shí)仍沒有匹配成功則按照服務(wù)器的默認(rèn)的語言類型來返回?cái)?shù)據(jù)。
返回索要的數(shù)據(jù)
最后我們選擇了一種語言,我們可以通過getLang方法的第二個(gè)參數(shù)來決定從這個(gè)語言包中拿什么數(shù)據(jù)。
源碼
function getLang(req,dataKey){
let langPack = {
'zh':{
data:'哈啰 世界!'
}
,'en':{
data:'hello world!'
}
};
//-------------------------------------------------
let acceptLanguage = req.headers['accept-language']
,langs = acceptLanguage.split(',')
,langType = 'en';
// 將accept-language解析成一個(gè)數(shù)組,并按照權(quán)重進(jìn)行排序
langs = langs.map(function(lang){
let [langType,langQ] = lang.split(';');
let q = langQ?parseFloat(langQ.split('=')[1]):1;
lang = {
langType
,q
};
return lang;
}).sort((a,b)=>b.q-a.q);
// 選擇語言類型
for(let i=0;i<langs.length;++i){
let curType = langs[i].langType;
if(langPack[curType]){
langType = curType;
break;
}
}
// 返回索要的數(shù)據(jù)
return langPack[langType][dataKey];
}