Рельсы заставляют все переводы
Я использую globalize3
с rails_admin
благодаря этой сути. Что меня беспокоит, так это то, что пользователь может добавить столько переводов, сколько захочет.
Более того, он не обязан переводить контент в каждой локали (как в I18n.available_locales
). Я хотел бы, что. Как вы можете справиться с такой ситуацией?
Модели (сокращенно):
class Project < ActiveRecord::Base
has_many :project_translations, :dependent => :destroy, :inverse_of => :project
accepts_nested_attributes_for :project_translations, :allow_destroy => true
class ProjectTranslation < ActiveRecord::Base
belongs_to :project
2 ответа
В итоге я выбрал Active Admin плюс activeadmin-globalize3. Намного легче.
Это тоже меня раздражало, поэтому я создал собственный тип поля, который не позволяет этого.
Основной класс:
module RailsAdmin
module Config
module Fields
module Types
class GlobalizeTabs < RailsAdmin::Config::Fields::Association
RailsAdmin::Config::Fields::Types::register(:globalize_tabs, self)
register_instance_option :partial do
:form_globalize_tabs
end
def method_name
"#{super}_attributes".to_sym
end
# Reader for validation errors of the bound object
def errors
bindings[:object].errors[name]
end
def available_locales
I18n.available_locales
end
def current_locale
I18n.locale
end
# Returns array of Translation objects
# It gets existing or creates new empty translation for every locale
# It's used in fields_for method in partial
def translations
translated_locales = @bindings[:object].translated_locales
available_locales.collect do |locale|
translated_locales.include?(locale) ? @bindings[:object].translation_for(locale) : @bindings[:object].translations.new({ locale: locale })
end
end
end
end
end
end
end
Наследуется от RailsAdmin::Config::Fields::Association
класс, потому что он использует очень похоже на _form_nested_many
частичное (используется в типе has_many).
Частичное:
.controls
= form.errors_for(field)
%ul.nav.nav-tabs{ :style => 'margin-top:5px' }
- field.available_locales.each do |locale|
%li{ class: ( 'active' if locale == field.current_locale ) }
%a{ href: "##{locale}", data: { toggle: "tab" } }= locale
.tab-content
= form.fields_for field.name, field.translations, wrapper: false do |nested_form|
.fields.tab-pane{ id: nested_form.object.locale, class: ( 'active' if nested_form.object.locale == field.current_locale ) }
= nested_form.generate({:action => :nested, :model_config => field.associated_model_config, :nested_in => field.name })
= form.help_for(field)
Оно использует field.translations
метод из класса пользовательских полей, который возвращает массив объектов Translation. Каждый объект перевода соответствует доступной локали, и это либо существующий объект из базы данных (если перевод уже существует), либо новый пустой объект перевода.
Например
У вас есть доступные локали:
I18n.available_locales = [:en, :cz, :ru]
У вас есть модель страницы, которая включает некоторые переведенные поля.
Кроме того, у вас есть объект класса Page (строка в базе данных), у которого есть переводы для: en и: cz locales, но отсутствует объект для: ru.
Так, field.translations
метод внутри _form_globalize_tabs
частичное возвращает массив, который содержит: 2 существующих перевода для: en и: cz и 1 только что инициализированный перевод для: ru.
В частичном я передаю этот массив в fields_for
вспомогательный метод из nested_form
gem, который возвращает 3 набора полей для каждого объекта перевода.
Вы можете использовать этот драгоценный камень, если вы не хотите возиться с кодом самостоятельно: https://github.com/scarfaceDeb/rails_admin_globalize_field