[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
```
其中多种语言之间用`,`隔开,而每种语言又可用`;`分隔,分隔的前面为该种语言的简称,后面为其权重(优先级)。
![](https://box.kancloud.cn/41dfc9c9ce805f7c54c397c166dd2b28_351x74.png)
## 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];
}
```