《Ant Design Pro v5 获取动态菜单与基于角色权限管理视频教程》 和 《零基础学习 Vue3 教程 2021 年最新教程 免费视频教程》 正在更新
世界上最伟大的投资就是投资自己的教育

gem 介绍及源码分析之 http_accept_language (四)
1.介绍
之所以要介绍这个http_accept_language,是我在翻看ruby-china源码中无意中看到的,它可以让页面根据浏览器所使用的语言来自动调整网站的语言,比如你的浏览器的语言是en,网站就会自动用en这个locale。把它拿来介绍,也是因为它简单,并且里面涉及到一些有意义的知识,比如中间件(middleware)、HTTP协议等。
2. 安装及使用
添加下面这行到Gemfile文件中:
gem 'http_accept_language'
在使用之前,来看看我的应用的一些关于locale的配置。
# config/application.rb
config.i18n.default_locale = :'zh-CN'
我们试着先在浏览器发送一个请求,然后用pry来调试。
我的浏览器所使用的语言是en。
这是HTTP请求的头部信息,显示的正是en语言。然后用pry来得到这个HTTP的请求头部,一共有两种方法:
[1] pry(#<HomeController>)> request.headers["HTTP_ACCEPT_LANGUAGE"]
"en-US,en;q=0.8,zh-CN;q=0.6,zh;q=0.4"
[2] pry(#<HomeController>)> env["HTTP_ACCEPT_LANGUAGE"]
"en-US,en;q=0.8,zh-CN;q=0.6,zh;q=0.4"
http_accept_language
正是利用这个en-US,en;q=0.8,zh-CN;q=0.6,zh;q=0.4
信息来处理的,它就是解析这个字符串来得到真正的locale,再去rails中找到所有可用的locale进行匹配,并加载最终的locale。
[3] pry(#<HomeController>)> http_accept_language.compatible_language_from(I18n.available_locales)
:en
果然,输出的就是正确的en
。
关于具体的使用方法,就得查看官方的readme文档了。
3. 源码解析
在看源码之前,先来看rake middleware
指令的输出:
➜ rails365 git:(master) ✗ rake middleware
...
use HttpAcceptLanguage::Middleware
use ExceptionNotification::Rack
run Rails365::Application.routes
可以发现多了一个middleware。
来看下源码:
# https://github.com/iain/http_accept_language/blob/master/lib/http_accept_language/railtie.rb
module HttpAcceptLanguage
class Railtie < ::Rails::Railtie
initializer "http_accept_language.add_middleware" do |app|
app.middleware.use Middleware
ActiveSupport.on_load :action_controller do
include EasyAccess
end
end
end
module EasyAccess
def http_accept_language
@http_accept_language ||= request.env["http_accept_language.parser"] || Parser.new(request.env["HTTP_ACCEPT_LANGUAGE"])
end
end
end
Railtie是rails的一个组件,是在启动的时候加载和扩展各种组件,比如active_record, active_view等,rails的源码到处都有它的身影,在这里理解为启动的时候,就能加载组件就可以了。app.middleware.use Middleware
表示的是使用了这个Middleware
的rack中间件。
先来看下这个Middleware
中间件的源码:
# https://github.com/iain/http_accept_language/blob/master/lib/http_accept_language/middleware.rb
module HttpAcceptLanguage
class Middleware
def initialize(app)
@app = app
end
def call(env)
env["http_accept_language.parser"] = Parser.new(env["HTTP_ACCEPT_LANGUAGE"])
def env.http_accept_language
self["http_accept_language.parser"]
end
@app.call(env)
end
end
end
其实整个rails应用就是实现的rack中间件,默认情况下就自动加载了各种中间件的,在这里只不过插件多了一个,中间件就是得到HTTP请求,再把请求的数据,得到再处理,再按照规定的格式响应,比如rack规定了,响应必须包含状态码,头部信息,和响应的内容。
具体的关于rack中间件的内容可以参考下面两个链接:
上面中间件的内容就是把env["http_accept_language.parser"]
的信息读取了,之后进行解析,我们来看下是如何解析的。
def compatible_language_from(available_languages)
user_preferred_languages.map do |preferred| #en-US
preferred = preferred.downcase
preferred_language = preferred.split('-', 2).first
available_languages.find do |available| # en
available = available.to_s.downcase
preferred == available || preferred_language == available.split('-', 2).first
end
end.compact.first
end
def user_preferred_languages
@user_preferred_languages ||= begin
header.to_s.gsub(/\s+/, '').split(',').map do |language|
locale, quality = language.split(';q=')
raise ArgumentError, 'Not correctly formatted' unless locale =~ /^[a-z\-0-9]+|\*$/i
locale = locale.downcase.gsub(/-[a-z0-9]+$/i, &:upcase) # Uppercase territory
locale = nil if locale == '*' # Ignore wildcards
quality = quality ? quality.to_f : 1.0
[locale, quality]
end.sort do |(_, left), (_, right)|
right <=> left
end.map(&:first).compact
rescue ArgumentError # Just rescue anything if the browser messed up badly.
[]
end
end
所有相关的代码都在https://github.com/iain/http_accept_language/blob/master/lib/http_accept_language/parser.rb
这个文件里。
具体的代码就不分析了,只要原理懂了,代码层次的东西也是比较简单的。
完结。
本站帖子均为原创内容,如需转载请注明出处,谢谢。
© 汕尾市求知科技有限公司 | 关注我们 | 专业版网站 | 在线学员:1122
粤公网安备 44152102000088号 | 粤ICP备19038915号