MK
摩柯社区 - 一个极简的技术知识社区
AI 面试

Ruby on Rails 国际化支持

2024-06-054.6k 阅读

Ruby on Rails 国际化支持概述

在全球化的今天,开发的应用程序需要能够适应不同地区和语言的用户。Ruby on Rails 提供了强大的国际化(i18n)支持,使得开发者可以轻松地为应用添加多语言功能。国际化支持允许应用根据用户的语言偏好来显示不同语言的文本、日期、时间和数字格式等。

配置国际化

  1. 设置默认语言:在 Rails 应用的 config/application.rb 文件中,可以设置应用的默认语言。例如,如果希望默认语言为英语,可以添加以下代码:
module YourAppName
  class Application < Rails::Application
    config.i18n.default_locale = :en
  end
end
  1. 添加支持的语言:在 config/application.rb 中,还可以指定应用支持的语言列表。例如,支持英语和中文:
module YourAppName
  class Application < Rails::Application
    config.i18n.available_locales = [:en, :zh]
  end
end

配置语言文件

  1. 语言文件结构:Rails 使用 YAML 文件来存储不同语言的翻译。这些文件位于 config/locales 目录下。例如,英语的翻译文件为 config/locales/en.yml,中文的翻译文件为 config/locales/zh.yml
  2. 示例翻译文件内容
    • en.yml
en:
  hello: "Hello"
  welcome: "Welcome to our application"
- `zh.yml`:
zh:
  hello: "你好"
  welcome: "欢迎来到我们的应用程序"

在视图中使用国际化

  1. 简单文本翻译:在 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) %>

在控制器中使用国际化

  1. 设置当前语言:在控制器中,可以根据用户的选择或其他条件设置当前语言。例如,假设用户选择的语言存储在会话(session)中:
class ApplicationController < ActionController::Base
  before_action :set_locale

  private
  def set_locale
    I18n.locale = session[:locale] || I18n.default_locale
  end
end
  1. 获取翻译文本:在控制器中也可以使用 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

日期和时间的国际化

  1. 日期格式: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 %>
  1. 时间格式:类似地,可以定义时间格式。在语言文件中:
    • en.yml
en:
  time:
    formats:
      default: "%I:%M %p"
- `zh.yml`:
zh:
  time:
    formats:
      default: "%H时%M分"

在视图中格式化时间:

<%= l @user.last_login, format: :default %>

数字的国际化

  1. 数字格式:Rails 可以根据当前语言设置格式化数字。例如,英语中千位分隔符为逗号,中文中千位分隔符为空。在语言文件中:
    • en.yml
en:
  number:
    format:
      delimiter: ","
      separator: "."
- `zh.yml`:
zh:
  number:
    format:
      delimiter: ""
      separator: "."

在视图中格式化数字:

<%= number_with_delimiter @product.price %>

复杂翻译结构

  1. 命名空间:当应用规模较大时,为了更好地组织翻译,可以使用命名空间。例如,将用户相关的翻译放在 user 命名空间下:
    • en.yml
en:
  user:
    login: "Login"
    logout: "Logout"
    profile: "Profile"
- `zh.yml`:
zh:
  user:
    login: "登录"
    logout: "注销"
    profile: "个人资料"

在视图中使用:

<%= t('user.login') %>
  1. 嵌套翻译:可以有多层嵌套的翻译结构。例如,在电商应用中,将产品相关的翻译进一步细分:
    • 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) %>

动态语言切换

  1. 用户界面提供语言切换功能:在应用的用户界面上,通常需要提供一个语言切换按钮或菜单。可以通过在视图中添加链接来实现。例如,在布局文件 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>
  1. 控制器处理语言切换:在控制器中定义处理语言切换的方法。例如,在 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

国际化与表单

  1. 表单标签的国际化:在表单中,标签文本也需要国际化。例如,创建用户表单中用户名和密码的标签:
    • 在语言文件中:
      • 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 %>
  1. 错误消息的国际化:当表单验证失败时,错误消息也应该是国际化的。Rails 会自动根据当前语言从语言文件中获取对应的错误消息。例如,在 en.yml 中:
en:
  errors:
    messages:
      blank: "can't be blank"

zh.yml 中:

zh:
  errors:
    messages:
      blank: "不能为空"

如果用户没有填写用户名,在英语环境下会显示 “Username can't be blank”,在中文环境下会显示 “用户名不能为空”。

国际化测试

  1. 单元测试:在测试中,可以使用 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
  1. 集成测试:在集成测试中,也可以模拟用户切换语言并验证界面上的文本是否正确翻译。例如,使用 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 插件

  1. 一些插件对国际化的支持:许多 Rails 插件也支持国际化。例如,Devise 是一个常用的用户认证插件,它允许开发者覆盖其默认的翻译文本。可以在语言文件中添加 Devise 相关的翻译。例如,在 en.yml 中:
en:
  devise:
    sessions:
      new:
        title: "Log in"

zh.yml 中:

zh:
  devise:
    sessions:
      new:
        title: "登录"
  1. 自定义插件的国际化:如果开发自己的 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: "这是来自我的插件的通知"

部署与国际化

  1. 预编译语言文件:在部署 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

在控制器和视图中,根据当前语言选择相应的字段进行显示。

国际化的高级技巧

  1. 复数形式翻译:在不同语言中,名词的复数形式可能有不同的规则。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) %>
  1. 根据地区进行翻译:有些语言在不同地区可能有一些差异。例如,英语在英国和美国可能有一些词汇的不同。可以通过在语言代码后添加地区代码来区分。例如,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 的国际化支持有了深入的理解,可以为你的应用添加强大的多语言功能,满足全球用户的需求。