Rails 4 Active Record Enums rất tuyệt, nhưng đâu là mẫu phù hợp để dịch với i18n?
Rails 4 Active Record Enums rất tuyệt, nhưng đâu là mẫu phù hợp để dịch với i18n?
Câu trả lời:
Bắt đầu từ Rails 5, tất cả các mô hình sẽ kế thừa từ ApplicationRecord
.
class User < ApplicationRecord
enum status: [:active, :pending, :archived]
end
Tôi sử dụng lớp cha này để triển khai một giải pháp chung để dịch các enum:
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
def self.human_enum_name(enum_name, enum_value)
I18n.t("activerecord.attributes.#{model_name.i18n_key}.#{enum_name.to_s.pluralize}.#{enum_value}")
end
end
Sau đó, tôi thêm các bản dịch vào .yml
tệp của mình :
en:
activerecord:
attributes:
user:
statuses:
active: "Active"
pending: "Pending"
archived: "Archived"
Cuối cùng, để có được bản dịch tôi sử dụng:
User.human_enum_name(:status, :pending)
=> "Pending"
<%= f.select :status, User.statuses.keys.collect { |status| [User.human_enum_name(:status, status), status] } %>
.
human_enum_name(@user, :status)
self.human_enum_collection(enum_name)
. Mã sẽ là send(enum_name.to_s.pluralize).keys.collect { |val| [human_enum_name(enum_name, val), val] }
Đây là một cái nhìn:
select_tag :gender, options_for_select(Profile.gender_attributes_for_select)
Đây là một mô hình (bạn có thể chuyển mã này thành một người trợ giúp hoặc một người trang trí trên thực tế)
class Profile < ActiveRecord::Base
enum gender: {male: 1, female: 2, trans: 3}
# @return [Array<Array>]
def self.gender_attributes_for_select
genders.map do |gender, _|
[I18n.t("activerecord.attributes.#{model_name.i18n_key}.genders.#{gender}"), gender]
end
end
end
Và đây là tệp ngôn ngữ:
en:
activerecord:
attributes:
profile:
genders:
male: Male
female: Female
trans: Trans
.human_attribute_name('genders.male')
không hoạt động
Để giữ cho việc quốc tế hóa tương tự như bất kỳ thuộc tính nào khác, tôi đã làm theo cách thuộc tính lồng nhau như bạn có thể thấy ở đây .
Nếu bạn có một lớp học User
:
class User < ActiveRecord::Base
enum role: [ :teacher, :coordinator ]
end
Và yml
như thế này:
pt-BR:
activerecord:
attributes:
user/role: # You need to nest the values under model_name/attribute_name
coordinator: Coordenador
teacher: Professor
Bạn có thể dùng:
User.human_attribute_name("role.#{@user.role}")
activerecord.attributes.<fieldname>
là label
bản dịch cho người trợ giúp biểu mẫu
role
chìa khóa. Bạn có thể lồng coordinator
và teacher
trực tiếp dưới user
.
Mô hình:
enum stage: { starting: 1, course: 2, ending: 3 }
def self.i18n_stages(hash = {})
stages.keys.each { |key| hash[I18n.t("checkpoint_stages.#{key}")] = key }
hash
end
Ngôn ngữ:
checkpoint_stages:
starting: Saída
course: Percurso
ending: Chegada
Và trên chế độ xem (.slim):
= f.input_field :stage, collection: Checkpoint.i18n_stages, as: :radio_buttons
Dựa trên câu trả lời của user3647358, bạn có thể hoàn thành điều đó rất gần với những gì bạn đã quen khi dịch tên thuộc tính.
Tệp ngôn ngữ:
en:
activerecord:
attributes:
profile:
genders:
male: Male
female: Female
trans: Trans
Dịch bằng cách gọi I18n # t:
profile = Profile.first
I18n.t(profile.gender, scope: [:activerecord, :attributes, :profile, :genders])
Hãy thử sử dụng đá quý TranslateEnum cho những mục đích này
class Post < ActiveRecord::Base
enum status: { published: 0, archive: 1 }
translate_enum :status
end
Post.translated_status(:published)
Post.translated_statuses
@post = Post.new(status: :published)
@post.translated_status
Tôi đã tạo ra một viên ngọc cho việc này.
http://rubygems.org/gems/translated_attribute_value
Thêm vào tệp gem của bạn:
gem 'translated_attribute_value'
Nếu bạn có trường trạng thái cho người dùng:
pt-BR:
activerecord:
attributes:
user:
status_translation:
value1: 'Translation for value1'
value2: 'Translation for value2'
Và theo quan điểm của bạn, bạn có thể gọi như thế này:
user.status_translated
Nó hoạt động với bản ghi hoạt động, mongoid hoặc bất kỳ lớp nào khác với getter / setters:
Kết hợp các câu trả lời từ Repolês và Aliaksandr , đối với Rails 5, chúng ta có thể xây dựng 2 phương thức cho phép bạn dịch một giá trị đơn lẻ hoặc một tập hợp các giá trị từ một thuộc tính enum.
Thiết lập các bản dịch trong .yml
tệp của bạn :
en:
activerecord:
attributes:
user:
statuses:
active: "Active"
pending: "Pending"
archived: "Archived"
Trong ApplicationRecord
lớp, từ đó tất cả các mô hình kế thừa, chúng tôi xác định một phương thức xử lý các bản dịch cho một giá trị duy nhất và một phương thức khác xử lý các mảng bằng cách gọi nó:
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
def self.translate_enum_name(enum_name, enum_value)
I18n.t("activerecord.attributes.#{model_name.i18n_key}.#{enum_name.to_s.pluralize}.#{enum_value}")
end
def self.translate_enum_collection(enum_name)
enum_values = self.send(enum_name.to_s.pluralize).keys
enum_values.map do |enum_value|
self.translate_enum_name enum_name, enum_value
end
end
end
Theo quan điểm của chúng tôi, sau đó chúng tôi có thể dịch các giá trị đơn lẻ:
<p>User Status: <%= User.translate_enum_name :status, @user.status %></p>
Hoặc toàn bộ tập hợp các giá trị enum:
<%= f.select(:status, User.translate_enum_collection :status) %>
Đây là một t_enum
phương pháp trợ giúp mà tôi sử dụng.
<%= t_enum(@user, :status) %>
enum_helper.rb :
module EnumHelper
def t_enum(inst, enum)
value = inst.send(enum);
t_enum_class(inst.class, enum, value)
end
def t_enum_class(klass, enum, value)
unless value.blank?
I18n.t("activerecord.enums.#{klass.to_s.demodulize.underscore}.#{enum}.#{value}")
end
end
end
user.rb :
class User < ActiveRecord::Base
enum status: [:active, :pending, :archived]
end
en.yml :
en:
activerecord:
enums:
user:
status:
active: "Active"
pending: "Pending..."
archived: "Archived"
Ngươi mâu:
class User < ActiveRecord::Base
enum role: [:master, :apprentice]
end
Tệp ngôn ngữ:
en:
activerecord:
attributes:
user:
master: Master
apprentice: Apprentice
Sử dụng:
User.human_attribute_name(:master) # => Master
User.human_attribute_name(:apprentice) # => Apprentice
@user.role
, bởi vì đó là vấn đề chính.
Tôi thích một người trợ giúp đơn giản trong application_helper
def translate_enum(object, enum_name)
I18n.t("activerecord.attributes.#{object.model_name.i18n_key}.#{enum_name.to_s.pluralize}.#{object.send(enum_name)}")
end
Sau đó, trong tệp YML của tôi:
fr:
activerecord:
attributes:
my_model:
my_enum_plural:
pending: "En cours"
accepted: "Accepté"
refused: "Refusé"
Tuy nhiên, theo một cách khác, tôi thấy thuận tiện hơn một chút khi sử dụng mối quan tâm trong các mô hình
Liên quan :
module EnumTranslation
extend ActiveSupport::Concern
def t_enum(enum)
I18n.t "activerecord.attributes.#{self.class.name.underscore}.enums.#{enum}.#{self.send(enum)}"
end
end
YML:
fr:
activerecord:
attributes:
campaign:
title: Titre
short_description: Description courte
enums:
status:
failed: "Echec"
Lượt xem :
<% @campaigns.each do |c| %>
<%= c.t_enum("status") %>
<% end %>
Đừng quên thêm mối quan tâm vào mô hình của bạn:
class Campaign < ActiveRecord::Base
include EnumTranslation
enum status: [:designed, :created, :active, :failed, :success]
end
Bạn chỉ cần thêm một người trợ giúp:
def my_something_list
modes = 'activerecord.attributes.mymodel.my_somethings'
I18n.t(modes).map {|k, v| [v, k]}
end
và thiết lập nó như thường lệ:
en:
activerecord:
attributes:
mymodel:
my_somethings:
my_enum_value: "My enum Value!"
sau đó sử dụng nó với lựa chọn của bạn: my_something_list
class ApplicationRecord < ActiveRecord::Base
self.abstract_class = true
def self.enum(definitions)
defind_i18n_text(definitions) if definitions.delete(:_human)
super(definitions)
end
def self.defind_i18n_text(definitions)
scope = i18n_scope
definitions.each do |name, values|
next if name.to_s.start_with?('_')
define_singleton_method("human_#{name.to_s.tableize}") do
p values
values.map { |key, _value| [key, I18n.t("#{scope}.enums.#{model_name.i18n_key}.#{name}.#{key}")] }.to_h
end
define_method("human_#{name}") do
I18n.t("#{scope}.enums.#{model_name.i18n_key}.#{name}.#{send(name)}")
end
end
end
end
en:
activerecord:
enums:
mymodel:
my_somethings:
my_enum_value: "My enum Value!"
enum status: [:unread, :down], _human: true
{locale}.activerecord.attributes.{model}.{attribute}
và viết mộtt_enum(model, enum, value)
phương pháp helper nên dịch enum sẽ tiếp giáp với dịch nhãn