Rails 4 Active Record Enums отличные, но каков правильный шаблон для перевода с i18n?
Как использовать i18n с Rails 4 перечислениями
Ответ 1
Я тоже не нашел определенного шаблона, поэтому я просто добавил:
en:
user_status:
active: Active
pending: Pending...
archived: Archived
к произвольному .yml файлу. Тогда в моих взглядах:
I18n.t :"user_status.#{user.status}"
Ответ 2
Начиная с 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"
Ответ 3
Вот представление:
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
Ответ 4
Чтобы интернационализация была похожа на любой другой атрибут, я следил за вложенным атрибутом, как вы можете видеть здесь.
Если у вас есть класс User
:
class User < ActiveRecord::Base
enum role: [ :teacher, :coordinator ]
end
И a 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}")
Ответ 5
Модель:
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
Ответ 6
Я создал для этого камень.
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/seters:
Ответ 7
Разрабатывая ответ 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])
Ответ 8
Объединив ответы Repolês и Aliaksandr, для Rails 5 мы можем построить 2 метода, которые позволяют вы должны перевести одно значение или набор значений из атрибута 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) %>
Ответ 9
Попробуйте enum_help gem. Из описания:
Справка ActiveRecord:: Enum для работы с I18n и simple_form.
Ответ 10
Heres a 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"
Ответ 11
Модель:
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
Ответ 12
Я предпочитаю простой помощник в 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é"
Ответ 13
Еще один способ, я считаю его более удобным, используя проблему в моделях
Концерн:
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
Ответ 14
Вы можете просто добавить помощника:
def my_something_list
modes = 'activerecord.attributes.mymodel.my_somethings'
I18n.t(modes).map {|k, v| [v, k]}
end
и установите его как обычно:
en:
activerecord:
attributes:
mymodel:
my_somethings:
my_enum_value: "My enum Value!"
затем используйте его с вашим выбором: my_something_list
Ответ 15
Попробуйте использовать TranslateEnum для этих целей
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
Ответ 16
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