Translating with Globalize
Bài đăng này đã không được cập nhật trong 3 năm
Mở đầu
Dự án mình làm về book tour du lịch, như vậy có nhiều người nước ngoài đến từ nhiều nước khác nhau sẽ sử dụng trang web. Có nhiều tour trong trang web mỗi tour có các thông tin mô tả các lịch trình của tour. và Web cung cấp xem trên nhiều ngôn ngữ khác nhau. Như vậy với mỗi tour trên các ngôn ngữ khác nhau chúng ta cần có bản dịch cho chúng. Mình muốn dịch nội dung đó sang nhiều ngôn ngữ và Quan Trọng muốn làm điều đó mà k phải refactor toàn bộ logic hiện tại để xử lý 1 ngôn ngữ mới. Gem Globalize là một giải pháp tối ưu giúp dịch các nội dung do người sử dụng tạo ra.
Như vậy
post = Post.first
post.title
sẽ trả về title của Post, Globalize sẽ trả về nội dung ứng với ngôn ngữ đang xem
I18n.locale = :en
post.title
#=> "Globalize: quality of being changeable, adaptable or versatile"
I18n.locale = :ja
post.title
#=> "Globalize:動きやすさ、可動性"
Ta có thể cập nhập bản ghi dịch bằng cách
I18n.locale = :en
post.title = "Translating with Globalize"
post.save
Như vậy bản ghi tiếng anh đã bị thay đổi còn tiếng nhật thì không
post = Post.first
post.title
#=> "Translating with Globalize"
I18n.locale = :ja
post.title
#=> "Globalize:動きやすさ、可動性"
Globalize
Cài đặt
Ta có thể install bằng cách:
gem install globalize
Sau đó bundle
Tạo bảng dịch
Ta có các bảng có các trường cần dịch: Với mỗi một bảng ta tạo 1 bảng dịch tương ứng
Tạo trường title và text là trường dịch cho bảng Post
class CreatePosts < ActiveRecord::Migration
def change
create_table :posts do |t|
t.timestamps
end
reversible do |dir|
dir.up do
Post.create_translation_table! :title => :string, :text => :text
end
dir.down do
Post.drop_translation_table!
end
end
end
end
Ở model post.rb. Ta cần khai báo những trường dịch
translates :title, :text
Tạo các bản ghi dịch
class Post < ActiveRecord::Base
translates :title, :name
end
Globalize.fallbacks = {:en => [:en, :pl], :pl => [:pl, :en]}
I18n.locale = :en
en_post = Post.create(:title => 'en_title')
I18n.locale = :pl
pl_post = Post.create(:title => 'pl_title')
en_post.title # => 'en_title'
I18n.locale = :en
en_post.title # => 'en_title'
pl_post.title # => 'pl_title'
Xem các bản ghi
p = Tour.first
p.translations
//Hiển thị danh sách toàn bộ các bản ghi dịch
[#<Tour::Translation:0x00000017c7cd30
id: 1,
tour_id: 1,
locale: "ja",
main_title: "main title japan",
description: "description japan",
#<Tour::Translation:0x00000017c7cb28
id: 61,
tour_id: 1,
locale: "en",
main_title: "main title english",
description: "description english"
p.translations.with_locale("en")
//Hiển thị bản ghi tiếng anh
[#<Tour::Translation:0x00000017c7cb28
id: 61,
tour_id: 1,
locale: "en",
main_title: "main title english",
description: "description english"]
Building the controller and view
Ở controller
: Build account với 2 ngôn ngữ có locale là :en và :de
def new
@account = Account.new
@account.translations.build locale: :en
@account.translations.build locale: :de
end
Ở View: Dùng fields_for để render ra field tương ứng với các locale.
<%= form_for @account do |f| %>
<%= f.fields_for :translations do |translation_fields| %>
<%= translation_fields.hidden_field :locale %>
<%= translation_fields.label :name %>
<%= translation_fields.text_field :name %>
<% end %>
<% end %>
hidden_field locale giúp khi tạo nó sẽ biết tạo cho ngôn ngữ nào
Một cách khác để dịch cho account model, bằng cách sử dụng Rails Internationalization (I18n) API
# config/locales/en.yml
en:
activerecord:
attributes:
account:
name: Name (in %{lang})
locale_name:
en: English
de: German
#config/locales/de.yml
activerecord:
attributes:
account:
name: Name (in %{lang})
locale_name:
en: Englisch
de: Deutsch
Validate các trường dịch
Chúng ta có thể dùng custom validations trong Rails. Tạo một class extends ActiveModel::EachValidator
# app/validators/translation_presence_validator.rb
class TranslationPresenceValidator < ActiveModel::EachValidator
LOCALES = [:en, :de]
def validate_each(record, attribute, value)
if values_for_locales(record, attribute).any?(&:blank?)
record.errors.add attribute, options[:message] || :blank
end
end
private
def values_for_locales(record, attribute)
LOCALES.map { |locale| record.read_attribute(attribute, locale: locale) }
end
end
read_attribute
sẽ cho ta value tương ứng với localevalues_for_locales
: phương thức sẽ trả về 1 mảng các giá trị của tất cả locale sử dụng- Nếu có bất kì value nào
blank
error sẽ được add vào record.
Ở model Account
Ta thêm validation
validates :name, translation_presence: true
Thật đơn giản và dễ dàng đúng không. Hi vọng bài viết hữu ích với bạn!
Nguồn:
https://github.com/globalize/globalize https://blog.robustastudio.com/web-development/localize-model-fields-using-rails/
All rights reserved