选择区域设置
学习添加对多种语言的支持。
本地化配置
创建一个新的配置文件,用于封装我们对可用本地化语言的了解以及默认使用的本地化语言:
1#--- 2# 摘自《使用 Rails 6 进行敏捷 Web 开发》, 3# 由 The Pragmatic Bookshelf 出版。 4# 版权适用于此代码。不得用于创建培训材料、课程、书籍、文章等。 5# 如有疑问,请联系我们。 6# 我们不保证此代码适用于任何用途。 7# 了解更多书籍信息,请访问 http://www.pragmaticprogrammer.com/titles/rails6。 8#--- 9#encoding: utf-8 10I18n.default_locale = :en 11 12LANGUAGES = [ 13 ['English', 'en'], 14 ["Español".html_safe, 'es'] 15]
这段代码完成了两件事。
第一件事是使用 I18n 模块设置默认本地化语言。虽然 I18n 这个名字听起来有点奇怪,但总比每次都输入“internationalization”要方便得多。毕竟,“internationalization”以字母 i 开头,以字母 n 结尾,中间有十八个字母。
接下来,代码定义了一个显示名称与本地化语言名称之间的关联列表。目前我们只有美式键盘可用,而像西班牙语这样的语言包含一些无法直接通过键盘输入的字符。不同操作系统处理方式不同,通常最简单的方法是从网页上复制粘贴正确的文本。如果这样做,请确保编辑器已配置为 UTF-8 编码。在此,我们选择使用西班牙语中带波浪号的 n 字符(ñ)的 HTML 等价形式。如果不做任何处理,标记本身会被显示出来。但通过调用 html_safe,我们告知 Rails 该字符串是安全的,可以被解释为包含 HTML 内容。
为了让 Rails 识别这一配置更改,需要重启服务器。
由于每页翻译内容现在都有 en 和 es 两个版本(后续还会增加更多),因此将本地化语言包含在 URL 中是合理的。我们计划将本地化语言放在路径开头,使其成为可选部分,并默认使用当前本地化语言,而当前本地化语言又默认为英语。为了实现这一点,我们首先修改 config/routes.rb:
1Rails.application.routes.draw do 2 get 'admin' => 'admin#index' 3 controller :sessions do 4 get 'login' => :new 5 post 'login' => :create 6 delete 'logout' => :destroy 7 end 8 get 'sessions/create' 9 get 'sessions/destroy' 10 11 resources :users 12 resources :products do 13 get :who_bought, on: :member 14 end 15 16 scope '(:locale)' do 17 resources :orders 18 resources :line_items 19 resources :carts 20 root 'store#index', as: 'store_index', via: :all 21 end 22end
我们将资源和根路由声明嵌套在 :locale 的 scope 声明中。此外,:locale 被括号包围,表示它是可选的。我们没有将管理功能和会话相关操作放入这个作用域,因为目前并不打算对它们进行本地化。
这意味着,默认的应用链接将使用默认的本地化语言——即英语。如果我们嵌入 es,它仍会路由到相同的控制器和动作,但我们希望这能导致本地化语言被设置为不同的值。
此时,我们已经对 config/routes 做了很多修改。由于路径中的嵌套和可选部分,整体结构可能难以直观理解。别担心!在开发模式下运行服务器时,Rails 提供了可视化辅助工具。只需运行本课末尾提供的应用程序,将 URL 添加到应用链接后 /rails/info/routes,即可查看所有路由列表。我们甚至可以像下面的应用程序所示进行筛选,快速找到感兴趣的路由。
No configuration found for ID: 666d138c6d6147b73a9db56b435bdb70888884b3bcd53a407832cbd3898fb880
在路由设置完成后,我们就可以从参数中提取本地化语言并将其提供给应用程序使用。为此,我们需要创建一个 before_action 回调。最合适的位置是在所有控制器的公共基类 ApplicationController 中:
1class ApplicationController < ActionController::Base 2 before_action :set_i18n_locale_from_params 3 # ... 4 before_action :authorize 5 6 # ... 7 8 protected 9 10 def set_i18n_locale_from_params 11 if params[:locale] 12 if I18n.available_locales.map(&:to_s).include?(params[:locale]) 13 I18n.locale = params[:locale] 14 else 15 flash.now[:notice] = 16 "#{params[:locale]} 翻译不可用" 17 logger.error flash.now[:notice] 18 end 19 end 20 end 21end
这个 set_i18n_locale_from_params 方法的作用正如其名:从参数中设置本地化语言,但仅当参数中存在本地化语言时才执行。否则,保持当前本地化语言不变。同时,当发生错误时,会向用户和管理员提供相应的提示信息。
此时,英文页面既可以在网站根路径访问,也可以通过以 /en 开头的页面访问。如果我们尝试使用其他语言代码,例如 es(西班牙语),就会看到一条提示信息,说明该语言的翻译不可用。
可运行的应用程序
尝试在应用程序链接末尾添加 /es 和 /en。
No configuration found for ID: 754a511ef6d606e657287da0105503792e55c4316ec2237c31290342af7d6b9e