Ruby on Rails 国际化支持
Ruby on Rails 国际化支持概述
在全球化的今天,开发的应用程序需要能够适应不同地区和语言的用户。Ruby on Rails 提供了强大的国际化(i18n)支持,使得开发者可以轻松地为应用添加多语言功能。国际化支持允许应用根据用户的语言偏好来显示不同语言的文本、日期、时间和数字格式等。
配置国际化
- 设置默认语言:在 Rails 应用的
config/application.rb
文件中,可以设置应用的默认语言。例如,如果希望默认语言为英语,可以添加以下代码:
module YourAppName
class Application < Rails::Application
config.i18n.default_locale = :en
end
end
- 添加支持的语言:在
config/application.rb
中,还可以指定应用支持的语言列表。例如,支持英语和中文:
module YourAppName
class Application < Rails::Application
config.i18n.available_locales = [:en, :zh]
end
end
配置语言文件
- 语言文件结构:Rails 使用 YAML 文件来存储不同语言的翻译。这些文件位于
config/locales
目录下。例如,英语的翻译文件为config/locales/en.yml
,中文的翻译文件为config/locales/zh.yml
。 - 示例翻译文件内容:
en.yml
:
en:
hello: "Hello"
welcome: "Welcome to our application"
- `zh.yml`:
zh:
hello: "你好"
welcome: "欢迎来到我们的应用程序"
在视图中使用国际化
- 简单文本翻译:在 Rails 视图文件(如 ERB 文件)中,可以使用
t
辅助方法来进行文本翻译。例如:
<%= t('hello') %>
如果当前语言设置为英语,将显示 “Hello”,如果设置为中文,将显示 “你好”。
2. 带参数的翻译:有时候翻译文本需要包含动态参数。例如,欢迎消息中包含用户名。首先,在语言文件中定义翻译:
- en.yml
:
en:
welcome_user: "Welcome, %{username}"
- `zh.yml`:
zh:
welcome_user: "欢迎,%{username}"
然后在视图中使用:
<%= t('welcome_user', username: @user.name) %>
在控制器中使用国际化
- 设置当前语言:在控制器中,可以根据用户的选择或其他条件设置当前语言。例如,假设用户选择的语言存储在会话(session)中:
class ApplicationController < ActionController::Base
before_action :set_locale
private
def set_locale
I18n.locale = session[:locale] || I18n.default_locale
end
end
- 获取翻译文本:在控制器中也可以使用
t
方法获取翻译后的文本。例如,在处理错误时返回国际化的错误消息:
class UsersController < ApplicationController
def create
@user = User.new(user_params)
if @user.save
redirect_to @user, notice: t('user_created_successfully')
else
render :new, alert: t('user_creation_failed')
end
end
end
日期和时间的国际化
- 日期格式:Rails 可以根据当前语言设置格式化日期。在语言文件中可以定义日期格式。例如,在
en.yml
中:
en:
date:
formats:
default: "%m/%d/%Y"
在 zh.yml
中:
zh:
date:
formats:
default: "%Y年%m月%d日"
在视图中格式化日期:
<%= l @user.created_at, format: :default %>
- 时间格式:类似地,可以定义时间格式。在语言文件中:
en.yml
:
en:
time:
formats:
default: "%I:%M %p"
- `zh.yml`:
zh:
time:
formats:
default: "%H时%M分"
在视图中格式化时间:
<%= l @user.last_login, format: :default %>
数字的国际化
- 数字格式:Rails 可以根据当前语言设置格式化数字。例如,英语中千位分隔符为逗号,中文中千位分隔符为空。在语言文件中:
en.yml
:
en:
number:
format:
delimiter: ","
separator: "."
- `zh.yml`:
zh:
number:
format:
delimiter: ""
separator: "."
在视图中格式化数字:
<%= number_with_delimiter @product.price %>
复杂翻译结构
- 命名空间:当应用规模较大时,为了更好地组织翻译,可以使用命名空间。例如,将用户相关的翻译放在
user
命名空间下:en.yml
:
en:
user:
login: "Login"
logout: "Logout"
profile: "Profile"
- `zh.yml`:
zh:
user:
login: "登录"
logout: "注销"
profile: "个人资料"
在视图中使用:
<%= t('user.login') %>
- 嵌套翻译:可以有多层嵌套的翻译结构。例如,在电商应用中,将产品相关的翻译进一步细分:
en.yml
:
en:
product:
details:
title: "Product Details"
description: "Description of the product"
reviews:
title: "Product Reviews"
count: "There are %{count} reviews"
- `zh.yml`:
zh:
product:
details:
title: "产品详情"
description: "产品的描述"
reviews:
title: "产品评论"
count: "有 %{count} 条评论"
在视图中使用:
<%= t('product.details.title') %>
<%= t('product.reviews.count', count: @product.reviews.count) %>
动态语言切换
- 用户界面提供语言切换功能:在应用的用户界面上,通常需要提供一个语言切换按钮或菜单。可以通过在视图中添加链接来实现。例如,在布局文件
app/views/layouts/application.html.erb
中添加语言切换链接:
<ul>
<li><%= link_to "English", set_locale_path(locale: :en) %></li>
<li><%= link_to "中文", set_locale_path(locale: :zh) %></li>
</ul>
- 控制器处理语言切换:在控制器中定义处理语言切换的方法。例如,在
ApplicationController
中:
class ApplicationController < ActionController::Base
def set_locale
session[:locale] = params[:locale]
redirect_back(fallback_location: root_path)
end
end
同时,需要在路由文件 config/routes.rb
中定义路由:
Rails.application.routes.draw do
get 'set_locale', to: 'application#set_locale', as: :set_locale
# 其他路由定义
end
国际化与表单
- 表单标签的国际化:在表单中,标签文本也需要国际化。例如,创建用户表单中用户名和密码的标签:
- 在语言文件中:
en.yml
:
- 在语言文件中:
en:
user:
form:
username: "Username"
password: "Password"
- `zh.yml`:
zh:
user:
form:
username: "用户名"
password: "密码"
- 在视图中:
<%= form_with(model: @user) do |form| %>
<%= form.label :username, t('user.form.username') %>
<%= form.text_field :username %>
<%= form.label :password, t('user.form.password') %>
<%= form.password_field :password %>
<%= form.submit %>
<% end %>
- 错误消息的国际化:当表单验证失败时,错误消息也应该是国际化的。Rails 会自动根据当前语言从语言文件中获取对应的错误消息。例如,在
en.yml
中:
en:
errors:
messages:
blank: "can't be blank"
在 zh.yml
中:
zh:
errors:
messages:
blank: "不能为空"
如果用户没有填写用户名,在英语环境下会显示 “Username can't be blank”,在中文环境下会显示 “用户名不能为空”。
国际化测试
- 单元测试:在测试中,可以使用
I18n.with_locale
方法来切换语言环境进行测试。例如,测试一个翻译文本:
require 'test_helper'
class TranslationTest < ActiveSupport::TestCase
test "hello translation in English" do
I18n.with_locale(:en) do
assert_equal "Hello", t('hello')
end
end
test "hello translation in Chinese" do
I18n.with_locale(:zh) do
assert_equal "你好", t('hello')
end
end
end
- 集成测试:在集成测试中,也可以模拟用户切换语言并验证界面上的文本是否正确翻译。例如,使用 Capybara 进行集成测试:
require 'test_helper'
require 'capybara/rails'
class InternationalizationIntegrationTest < ActionDispatch::IntegrationTest
include Capybara::DSL
test "language switch and translation on UI" do
visit root_path
click_link "中文"
assert page.has_text?("你好")
click_link "English"
assert page.has_text?("Hello")
end
end
国际化与 Rails 插件
- 一些插件对国际化的支持:许多 Rails 插件也支持国际化。例如,Devise 是一个常用的用户认证插件,它允许开发者覆盖其默认的翻译文本。可以在语言文件中添加 Devise 相关的翻译。例如,在
en.yml
中:
en:
devise:
sessions:
new:
title: "Log in"
在 zh.yml
中:
zh:
devise:
sessions:
new:
title: "登录"
- 自定义插件的国际化:如果开发自己的 Rails 插件,也应该考虑国际化支持。可以在插件的
config/locales
目录下添加语言文件,并在插件代码中使用t
方法进行翻译。例如,插件中有一个通知消息:
module MyPlugin
class Notifier
def notify_user
message = I18n.t('my_plugin.notification.message')
# 发送通知的逻辑
end
end
end
然后在 config/locales/my_plugin.en.yml
中:
en:
my_plugin:
notification:
message: "This is a notification from my plugin"
在 config/locales/my_plugin.zh.yml
中:
zh:
my_plugin:
notification:
message: "这是来自我的插件的通知"
部署与国际化
- 预编译语言文件:在部署 Rails 应用时,需要确保语言文件被正确预编译。在
config/environments/production.rb
中,可以设置:
config.i18n.preload_translations = true
这会在启动应用时预加载所有的翻译文件,提高性能。 2. 多语言内容存储:如果应用有大量的多语言内容,如文章、产品描述等,需要考虑如何存储这些内容。一种常见的方法是在数据库中为每种语言创建单独的字段。例如,对于产品表:
class CreateProducts < ActiveRecord::Migration[6.0]
def change
create_table :products do |t|
t.string :name_en
t.string :name_zh
t.text :description_en
t.text :description_zh
# 其他字段
t.timestamps
end
end
end
在控制器和视图中,根据当前语言选择相应的字段进行显示。
国际化的高级技巧
- 复数形式翻译:在不同语言中,名词的复数形式可能有不同的规则。Rails 提供了处理复数形式翻译的功能。例如,在英语中,数量为 1 时和大于 1 时的翻译不同。在语言文件中:
en.yml
:
en:
apple:
one: "1 apple"
other: "%{count} apples"
- `zh.yml`:
zh:
apple:
one: "1 个苹果"
other: "%{count} 个苹果"
在视图中使用:
<%= t('apple', count: @apples.count, scope: :apple) %>
- 根据地区进行翻译:有些语言在不同地区可能有一些差异。例如,英语在英国和美国可能有一些词汇的不同。可以通过在语言代码后添加地区代码来区分。例如,
en-GB
表示英式英语,en-US
表示美式英语。在语言文件中可以分别定义翻译:config/locales/en-GB.yml
:
en-GB:
elevator: "Lift"
- `config/locales/en-US.yml`:
en-US:
elevator: "Elevator"
在应用中,可以根据用户的地区设置来选择合适的翻译。这可能需要从用户的浏览器设置或其他来源获取地区信息。
通过以上全面的介绍,相信你已经对 Ruby on Rails 的国际化支持有了深入的理解,可以为你的应用添加强大的多语言功能,满足全球用户的需求。