Skip to main content

Rails i18n: Hướng dẫn quốc tế hóa Ruby on Rails toàn diện

Từ tệp ngôn ngữ đầu tiên đến môi trường sản xuất: cấu hình Rails I18n, dùng trình trợ giúp t(), xử lý dạng số nhiều CLDR, khắc phục các lỗi thường gặp và thêm chuỗi dự phòng ngôn ngữ thông minh.

1

Tìm hiểu kiến trúc Rails I18n

Rails tích hợp sẵn gem I18n. Các tệp bản dịch nằm trong config/locales/ dưới dạng tệp YAML (mặc định) hoặc Ruby. Framework cung cấp trình trợ giúp t() (bí danh của I18n.translate) trong khung nhìn, trình điều khiển, mô hình và trình gửi thư. Rails I18n được thiết kế đơn giản — hỗ trợ sẵn bản dịch cơ bản, phép nội suy và dạng số nhiều.

config/application.rb
# Rails includes i18n out of the box via the i18n gem
# config/application.rb
module MyApp
  class Application < Rails::Application
    # Default locale
    config.i18n.default_locale = :en

    # Available locales
    config.i18n.available_locales = [:en, :de, :ja, :es, :fr, :'pt-BR']

    # Fallback to default locale when translation is missing
    config.i18n.fallbacks = true

    # Load translations from nested directories
    config.i18n.load_path += Dir[Rails.root.join('config', 'locales', '**', '*.{rb,yml}')]
  end
end
config/routes.rb
# config/routes.rb
Rails.application.routes.draw do
  scope "/:locale", locale: /en|de|ja|es|fr|pt-BR/ do
    root "home#index"
    resources :products
  end

  root "home#index"
end

# app/controllers/application_controller.rb
class ApplicationController < ActionController::Base
  around_action :switch_locale

  private

  def switch_locale(&action)
    locale = params[:locale] || I18n.default_locale
    I18n.with_locale(locale, &action)
  end

  def default_url_options
    { locale: I18n.locale }
  end
end
Rails tự động tải mọi tệp .yml và .rb trong config/locales/. Bạn có thể sắp xếp theo bất kỳ cách nào — theo ngôn ngữ (en.yml, de.yml), theo tính năng (en/users.yml, en/orders.yml) hoặc kết hợp cả hai (en/users.yml, de/users.yml). Rails hợp nhất mọi tệp khi khởi động.
2

Cấu hình cài đặt ngôn ngữ

Đặt default_locale, available_locales và hành vi dự phòng trong config/application.rb hoặc trình khởi tạo. Cấu hình tính năng phát hiện ngôn ngữ trong ApplicationController bằng before_action để đặt ngôn ngữ từ URL, phiên, cookie hoặc tiêu đề Accept-Language.

config/locales/en.yml
# config/locales/en.yml
en:
  nav:
    home: "Home"
    about: "About"
    settings: "Settings"
  greeting: "Hello, %{name}!"
  cart:
    item_count:
      one: "%{count} item"
      other: "%{count} items"

# config/locales/de.yml
de:
  nav:
    home: "Startseite"
    about: "Über uns"
    settings: "Einstellungen"
  greeting: "Hallo, %{name}!"
  cart:
    item_count:
      one: "%{count} Artikel"
      other: "%{count} Artikel"
Việc đặt I18n.locale trong before_action an toàn cho từng yêu cầu nhưng đặt I18n.default_locale trong thời gian chạy là thao tác toàn cục và ảnh hưởng đến mọi luồng. Luôn dùng I18n.locale (cục bộ theo luồng) cho thay đổi ngôn ngữ trong phạm vi yêu cầu, tuyệt đối không dùng I18n.default_locale.
3

Dùng trình trợ giúp t()

Trình trợ giúp t() có sẵn ở mọi nơi trong Rails — khung nhìn, trình điều khiển, mô hình, trình gửi thư và tác vụ. Hàm nhận một khóa, các biến nội suy tùy chọn và những tùy chọn như giá trị mặc định cùng phạm vi. Trong khung nhìn, Rails hỗ trợ truy vấn lười để tự động xác định phạm vi khóa theo trình điều khiển và hành động hiện tại.

app/views/example.html.erb
# In views (ERB)
<h1><%= t('nav.home') %></h1>
<p><%= t('greeting', name: @user.name) %></p>

# In controllers
flash[:notice] = t('flash.product_created')

# In models
validates :name, presence: { message: I18n.t('errors.blank') }

# With HTML (safe)
<%= t('terms_html', link: link_to(t('terms_link'), '/terms')) %>
4

Xử lý dạng số nhiều

Rails I18n dùng các nhóm số nhiều CLDR: zero, one, two, few, many, other. Tiếng Anh chỉ cần one và other nhưng các ngôn ngữ khác cần nhiều dạng hơn. Hãy định nghĩa bản dịch số nhiều dưới dạng khóa YAML lồng nhau trong những nhóm số đếm mà ngôn ngữ đích yêu cầu.

Plural forms
# In YAML:
en:
  cart:
    item_count:
      zero: "No items"
      one: "%{count} item"
      other: "%{count} items"

# Arabic (6 forms):
ar:
  cart:
    item_count:
      zero: "لا عناصر"
      one: "عنصر واحد"
      two: "عنصران"
      few: "%{count} عناصر"
      many: "%{count} عنصرًا"
      other: "%{count} عنصر"

# Usage in views:
<%= t('cart.item_count', count: @cart.items.size) %>
Rails phát sinh I18n::InvalidPluralizationData nếu ngôn ngữ đang hoạt động thiếu một nhóm số nhiều bắt buộc. Nếu bản dịch tiếng Nga chỉ định nghĩa one và other (sao chép từ tiếng Anh), các số đếm như 2, 3, 4 sẽ làm ứng dụng gặp sự cố vì tiếng Nga cần nhóm few. Luôn định nghĩa đầy đủ mọi nhóm CLDR cho từng ngôn ngữ.
5

Thêm chuỗi dự phòng ngôn ngữ

I18n.fallbacks tích hợp trong Rails chỉ cung cấp cơ chế dự phòng cơ bản từ ngôn ngữ vùng miền sang ngôn ngữ mặc định. Người dùng pt-BR gặp khóa bị thiếu sẽ thấy tiếng Anh thay vì pt-PT. rails-locale-chain bổ sung chuỗi hợp nhất sâu có thể cấu hình để người dùng từng vùng luôn thấy bản dịch gần nhất hiện có.

Lazy lookups
# Lazy lookups use the controller/action as scope
# app/views/products/index.html.erb
# Instead of t('products.index.title'), just use:
<h1><%= t('.title') %></h1>
<p><%= t('.description') %></p>

# Rails looks up: products.index.title and products.index.description

# config/locales/en.yml
en:
  products:
    index:
      title: "All Products"
      description: "Browse our catalog"
rails-locale-chain tích hợp sẵn hơn 75 chuỗi dự phòng, bao phủ 11 họ ngôn ngữ. Thêm gem này vào Gemfile, cấu hình trong trình khởi tạo và người dùng từng vùng sẽ thấy ngay bản dịch của ngôn ngữ cha thay cho các khoảng trống tiếng Anh.
6

Tự động hóa bản dịch

Sau khi hoàn tất thiết lập Rails I18n, hãy dùng AI để dịch các tệp ngôn ngữ YAML. i18n Agent hỗ trợ trực tiếp YAML — trỏ công cụ đến tệp ngôn ngữ nguồn để tạo mọi ngôn ngữ đích mà vẫn giữ nguyên khóa lồng nhau, biến nội suy và dạng số nhiều.

config/initializers/locale_chain.rb
# Gemfile
gem 'rails-locale-chain'

# config/initializers/locale_chain.rb
Rails.application.config.i18n.fallbacks = {
  'pt-BR': ['pt', 'en'],
  'zh-Hant-TW': ['zh-Hant', 'zh', 'en'],
  'es-419': ['es', 'en'],
}

# The gem deep-merges translations across the chain
# pt-BR -> pt -> en
# Missing keys in pt-BR are filled from pt, then en
Dịch tăng dần — khi thêm khóa mới, chỉ dịch phần khác biệt. Cách này bảo toàn bản dịch hiện có và tránh tạo lại các chuỗi không đổi.

Các lỗi thường gặp

Lỗi InvalidPluralizationData

Rails gặp sự cố với I18n::InvalidPluralizationData khi thiếu một nhóm số nhiều CLDR bắt buộc. Lỗi thường xảy ra nhất khi sao chép các dạng số nhiều tiếng Anh (one/other) sang ngôn ngữ cần nhiều nhóm hơn (tiếng Nga cần few, tiếng Ả Rập cần zero/two/few/many). Hãy cài đặt rails-i18n để có quy tắc CLDR chính xác và định nghĩa đầy đủ mọi nhóm.

Truy vấn lười bên ngoài khung nhìn

Truy vấn lười (t('.key')) chỉ hoạt động trong khung nhìn, nơi Rails biết trình điều khiển và hành động. Dùng t('.key') trong mô hình, trình gửi thư hoặc đối tượng dịch vụ sẽ trả về lỗi thiếu bản dịch. Hãy dùng khóa đầy đủ (t('users.show.key')) bên ngoài khung nhìn.

Lỗi cú pháp YAML làm hỏng mọi bản dịch

Chỉ một lỗi cú pháp YAML (thụt lề sai, ký tự đặc biệt không có dấu ngoặc kép, dùng tab thay cho dấu cách) cũng khiến toàn bộ tệp ngôn ngữ không tải được. Mọi bản dịch trong tệp đó đều trả về lỗi thiếu khóa. Hãy dùng trình kiểm tra cú pháp để xác thực tệp YAML trong CI và đặt các chuỗi chứa dấu hai chấm, dấu ngoặc hoặc ký tự đặc biệt ở đầu trong dấu ngoặc kép.

Dùng thử i18n Agent ngay

Thả tệp bản dịch của bạn vào đây

JSON, YAML, PO, XML, CSV, Markdown, Properties

hoặc nhấp để duyệt

Ngôn ngữ đích

Không cần đăng kýBáo giá tức thì

Câu hỏi thường gặp về Rails i18n