Translating with Globalize
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 ...
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:動きやすさ、可動性"
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 locale
- values_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/