[TOC]
## 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
```
其中多種語言之間用`,`隔開,而每種語言又可用`;`分隔,分隔的前面為該種語言的簡稱,后面為其權重(優先級)。

## langPackage/語言包
一般支持多語言的網站,其服務器都存儲了多種語言包。當客戶端向其請求時,服務器會查看請求頭看一看客戶端所愿意支持的語言,然后在自己的語言包中進行查找。客戶端給的接收清單中包含每一種語言的權重,服務器會返回客戶端它有的且客戶端相對更喜歡的那一種。如果服務器所存儲的語言包和客戶端給的清單匹配不上,那么一般來說會使用服務器所預置的默認語言包。
語言包示例
```
let langPack = {
"zh":{
title:'哈啰 世界!'
}
,"en":{
title:"hello world!"
}
}
```
## 封裝 getLang
該方法能自動識別客戶端愿意接收的語言類型,然后從服務器所儲存的多種語言包中選擇一種最合適的來返回數據。
最終使用效果像這樣
```
getLang(req,'title')
```
### 設計思路
#### 將accept-language解析成一個數組,并按照權重進行排序
首先需要對`accept-language`進行解析,將其解析成一個個對象。每個對象代表一種語言,它有兩個屬性:
- `langType`:語言的類型
- `q`:語言的權重
幫助我們篩選出客戶端相對較喜歡的那一種語言
接著將每個對象放在一個數組中,按照權重從大到小排列。
#### 選擇語言類型
然后依次將數組成員的`langType`和服務器中所儲存的語言包進行匹配,直到匹配成功或遍歷結束,如果遍歷結束時仍沒有匹配成功則按照服務器的默認的語言類型來返回數據。
#### 返回索要的數據
最后我們選擇了一種語言,我們可以通過`getLang`方法的第二個參數來決定從這個語言包中拿什么數據。
## 源碼
```
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解析成一個數組,并按照權重進行排序
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;
}
}
// 返回索要的數據
return langPack[langType][dataKey];
}
```