Rails 4 Active Record Enum 은 훌륭하지만 i18n으로 번역하는 데 적합한 패턴은 무엇입니까?
Rails 4 Active Record Enum 은 훌륭하지만 i18n으로 번역하는 데 적합한 패턴은 무엇입니까?
답변:
Rails 5부터 모든 모델은 ApplicationRecord
.
class User < ApplicationRecord
enum status: [:active, :pending, :archived]
end
이 수퍼 클래스를 사용하여 열거 형 번역을위한 일반 솔루션을 구현합니다.
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
그런 다음 .yml
파일에 번역을 추가 합니다.
en:
activerecord:
attributes:
user:
statuses:
active: "Active"
pending: "Pending"
archived: "Archived"
마지막으로 번역을 얻으려면 다음을 사용합니다.
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)
. 코드는 send(enum_name.to_s.pluralize).keys.collect { |val| [human_enum_name(enum_name, val), val] }
다음은보기입니다.
select_tag :gender, options_for_select(Profile.gender_attributes_for_select)
여기 모델이 있습니다 (실제로이 코드를 도우미 또는 데코레이터로 이동할 수 있습니다)
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
다음은 로케일 파일입니다.
en:
activerecord:
attributes:
profile:
genders:
male: Male
female: Female
trans: Trans
.human_attribute_name('genders.male')
하지 작업 할
국제화를 다른 속성과 유사하게 유지하기 위해 여기에서 볼 수 있듯이 중첩 속성 방식을 따랐 습니다 .
수업이있는 경우 User
:
class User < ActiveRecord::Base
enum role: [ :teacher, :coordinator ]
end
그리고 다음 yml
과 같이 :
pt-BR:
activerecord:
attributes:
user/role: # You need to nest the values under model_name/attribute_name
coordinator: Coordenador
teacher: Professor
당신이 사용할 수있는:
User.human_attribute_name("role.#{@user.role}")
activerecord.attributes.<fieldname>
되는 label
형태 헬퍼 번역
role
키 를 사용하지 않고 작동 합니다. 당신은 둥지 수 coordinator
와 teacher
직접 아래 user
.
모델:
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
장소:
checkpoint_stages:
starting: Saída
course: Percurso
ending: Chegada
그리고보기 (.slim)에서 :
= f.input_field :stage, collection: Checkpoint.i18n_stages, as: :radio_buttons
user3647358의 답변을 자세히 설명하면 속성 이름을 번역 할 때 익숙한 것과 매우 유사하게 수행 할 수 있습니다.
로케일 파일 :
en:
activerecord:
attributes:
profile:
genders:
male: Male
female: Female
trans: Trans
I18n # t를 호출하여 번역 :
profile = Profile.first
I18n.t(profile.gender, scope: [:activerecord, :attributes, :profile, :genders])
이러한 목적으로 TranslateEnum gem을 사용해보십시오.
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
나는 이것을 위해 보석을 만들었습니다.
http://rubygems.org/gems/translated_attribute_value
gemfile에 추가하세요 :
gem 'translated_attribute_value'
사용자에 대한 상태 필드가있는 경우 :
pt-BR:
activerecord:
attributes:
user:
status_translation:
value1: 'Translation for value1'
value2: 'Translation for value2'
그리고 당신의 관점에서 다음과 같이 부를 수 있습니다.
user.status_translated
활성 레코드, mongoid 또는 getter / setter가있는 다른 클래스에서 작동합니다.
Repolês 및 Aliaksandr 의 답변을 결합하여 Rails 5의 경우 enum 속성에서 단일 값 또는 값 모음을 번역 할 수있는 두 가지 메서드를 빌드 할 수 있습니다.
.yml
파일에 번역을 설정 합니다.
en:
activerecord:
attributes:
user:
statuses:
active: "Active"
pending: "Pending"
archived: "Archived"
ApplicationRecord
모든 모델이 상속 하는 클래스에서 단일 값에 대한 변환을 처리하는 메서드와이를 호출하여 배열을 처리하는 다른 값을 정의합니다.
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
뷰에서 단일 값을 번역 할 수 있습니다.
<p>User Status: <%= User.translate_enum_name :status, @user.status %></p>
또는 열거 형 값의 전체 컬렉션 :
<%= f.select(:status, User.translate_enum_collection :status) %>
여기 t_enum
내가 사용 하는 도우미 방법이 있습니다.
<%= 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"
모델:
class User < ActiveRecord::Base
enum role: [:master, :apprentice]
end
로케일 파일 :
en:
activerecord:
attributes:
user:
master: Master
apprentice: Apprentice
용법:
User.human_attribute_name(:master) # => Master
User.human_attribute_name(:apprentice) # => Apprentice
@user.role
그것이 주요 문제이기 때문에 어떻습니까 ?
나는 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
그런 다음 내 YML 파일에서 :
fr:
activerecord:
attributes:
my_model:
my_enum_plural:
pending: "En cours"
accepted: "Accepté"
refused: "Refusé"
또 다른 방법은 모델의 관심사를 사용하여 좀 더 편리하다는 것입니다.
우려 사항 :
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"
보기 :
<% @campaigns.each do |c| %>
<%= c.t_enum("status") %>
<% end %>
모델에 관심을 추가하는 것을 잊지 마십시오.
class Campaign < ActiveRecord::Base
include EnumTranslation
enum status: [:designed, :created, :active, :failed, :success]
end
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}
하고 쓴t_enum(model, enum, value)
열거 번역 레이블 번역에 인접 할 수 있도록 도우미 메서드를