JS魔法堂:不完全国际化&本地化手册 之 拓展篇
前言
最近加入到新项目组负责前端技术预研和选型,其中涉及到一个熟悉又陌生的需求——国际化&本地化。熟悉的是之前的项目也玩过,陌生的是之前的实现仅仅停留在"有"的阶段而已。趁着这个机会好好学习整理一下,为后面的技术选型做准备。 本篇作为系列的最后一篇,打算和大家一起看看HTTP的Content Negotiation机制和更多关于本地化的应用方向。
Content Negotiation(内容协同)
记得第一次接触国际化和本地化时是指服务端根据请求头字段Accept-Language
获取language-tag然后向用户返回相应的内容,这其实是利用HTTP提供的Content Negotiation机制。
所谓Content Negotiation机制其实就是通过Accept
,Accept-Language
和Accept-Encoding
等请求头字段作为依据对存在多个可用展现方式的某一资源选择最优的展现方式返回给用户,如语言文化、适合在屏幕上浏览还是用于打印等。
这里又分为服务端协商(Server-driven Negotiation)和代理端协商(Agent-driven Negotiation)
- Server-driven Negotiation
就是择优返回展现方式的算法由服务端提供的Content Negotiation就是Server-driven Negotiation了。
一般通过
Accept
,Accept-Language
,Accept-Encoding
和User-Agent
等请求头字段作为依据去选择最优解。 缺点:
a. 服务端永远无法精准地计算出最优解,部分原因是因为内容如何展现是由代理端决定,而请求中无法获取代理端的所有信息,若允许获取代理端的所有信息,那么网络传送的数据量将变大而且会涉及隐私安全的问题;
b. 服务端实现复杂度提高;
c. 由于对于同一个url可能会返回不同的响应报文,因此不能利用公用的缓存去暂存响应报文,从而丧失进一步的优化空间。
- Agent-driven Negotiation
就是代理端从服务端接收到一个基本的响应后,然后择优展现方式的算法由代理端(实际上就是让用户自行选择最优展现方式)提供的Content Negotiation就是Agent-driven Negotiation了。
注意这里是先从服务端接收一个基本的响应,然后代理根据这个响应再计算最优的展现方式。那么这个基本的响应是什么呢?HTTP/1.1定义300(Multiple Choices)和406(Not Acceptable)两个HTTP status code来通知代理端这个请求是的采用Agent-driven Negotiation.
300 Multiple Choices
当请求的资源在多个位置找到时,这些位置将以列表的形式作为响应报文返回给用户,由用户自行选择具体要访问哪个位置。若服务端打算推荐某个位置作为优先选择时,可将该位置作为响应头字段Location
的值返回.
406 Not Acceptable
当服务端发现无法满足请求头的Accept
,Accept-Charset
,Accept-Encoding
或Accept-Language
时,则会返回406状态编码。因此406不是表示存在多个选择而是表示没有适合的选项。
缺点:
a. 经过代理端计算后,需要发起第二个请求来获取最优展现形式的具体内容,响应延迟提高。 综合上述两种方式得到一种称为透明协商(Transparent Negotiation)的方式,其实就是对缓存系统作修改,让其除URL外还可以识别其他请求头字段等信息,来映射特定展现方式的响应报文。也就是说择优算法部分还是由服务端提供。
这里看来国际化/本地化是Content Negotiation的子集哦!
样式因文化而不同 by :lang
Selectors Level 4已经加入对BCP 47高级匹配算法的支持,即有以下玩法
<style>
:lang(en){ color: red; }
div:lang(en-GB){ color: red; }
</style>
<p>En janvier, toutes les boutiques de Londres affichent des panneaux
<span lang="en-GB">SALE</span>, mais en fait ces magasins sont bien propres!</p>
<div lang="en-GB">BIG SALE</div>
甚至还有支持通配符*
(虽然现在未被浏览器支持)
<style>
:lang(*-CH){color: red}
</style>
<p lang="de-CH">Hi guy!</p>
<p lang="it-CH">Hi man!</p>
总结
本系列粗略归纳了国际化&本地化相关内容,若有纰漏请各位指正,谢谢!
感谢
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- phpMyAdmin通过密码漏洞留后门文件
- php 调用百度sms来发送短信的实现示例
- MySQL 8.0 新特性:快速加列
- php判断电子邮件是否正确办法
- 用Laravel Sms实现laravel短信验证码的发送的实现
- kubernetes 近期进展 - 1.14-1.19
- Kubernetes 1.19.0——cronjob
- php获取微信openid方法总结
- Laravel 关联模型-关联新增和关联更新的方法
- 如何解决PHP获取不到SESSION信息之一般情况
- PHP实现通过二维数组键值获取一维键名操作示例
- laravel 判断查询数据库返回值的例子
- laravel框架数据库配置及操作数据库示例
- laravel 输出最后执行sql 附:whereIn的使用方法
- laravel框架模型、视图与控制器简单操作示例