para-i18n 0.3.2 → 0.5.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (31) hide show
  1. checksums.yaml +5 -5
  2. data/app/helpers/para/i18n/form_helper.rb +13 -0
  3. data/app/views/para/admin/resources/_translations_fields.html.haml +9 -0
  4. data/app/views/para/admin/resources/_translations_form.html.haml +8 -2
  5. data/config/locales/para-i18n.fr.yml +1 -0
  6. data/lib/generators/para/i18n/base_form_generator.rb +28 -0
  7. data/lib/generators/para/i18n/form/form_generator.rb +3 -14
  8. data/lib/generators/para/i18n/form/templates/_translations_form.html.haml +8 -2
  9. data/lib/generators/para/i18n/nested_fields/nested_fields_generator.rb +18 -0
  10. data/lib/generators/para/i18n/nested_fields/templates/_translations_fields.html.haml +11 -0
  11. data/lib/generators/para/i18n/translate/templates/model_migration.rb.erb +1 -1
  12. data/lib/para/i18n.rb +8 -0
  13. data/lib/para/i18n/attribute_translation.rb +26 -0
  14. data/lib/para/i18n/attribute_translation/attachment.rb +58 -0
  15. data/lib/para/i18n/attribute_translation/base.rb +23 -0
  16. data/lib/para/i18n/attribute_translation/simple_attribute.rb +37 -0
  17. data/lib/para/i18n/engine.rb +2 -2
  18. data/lib/para/i18n/fallbacks.rb +11 -2
  19. data/lib/para/i18n/form_builder.rb +10 -0
  20. data/lib/para/i18n/form_builder/nested_form.rb +46 -0
  21. data/lib/para/i18n/form_builder/translations_form.rb +42 -0
  22. data/lib/para/i18n/friendly_id.rb +9 -0
  23. data/lib/para/i18n/helpers/translations_helper.rb +9 -0
  24. data/lib/para/i18n/i18n_input.rb +5 -5
  25. data/lib/para/i18n/inputs.rb +4 -0
  26. data/lib/para/i18n/inputs/nested_many_input.rb +41 -0
  27. data/lib/para/i18n/model.rb +47 -28
  28. data/lib/para/i18n/resources_buttons.rb +1 -1
  29. data/lib/para/i18n/version.rb +1 -1
  30. data/para-i18n.gemspec +1 -1
  31. metadata +27 -8
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 7debf4be928d56fb8b0e9bf814ee6fd09422b036
4
- data.tar.gz: b7b0c7bf833da338a617d40b7ed49e87a3ff995f
2
+ SHA256:
3
+ metadata.gz: 90d12992580fc4a99c6c61436e3fda627f33c8064316d72d9dac154234bf7e58
4
+ data.tar.gz: 4592e7c3895bc9200f212879171f5b039d75884bd0dfa73f576a8624346fbd5d
5
5
  SHA512:
6
- metadata.gz: e40bacf82951a1c80f5f3079fd4d244007a9cf6dbfc9d1dfcc96770011a34564871e687176b31c2704b74c0305dbd52c536210e3d8ba5e81f7db00bef87f04fd
7
- data.tar.gz: 90b24e6e7a78d8622c232796bc93acc6e4a32a1773462ce6dd7023d7173b38241c39721bd42a163b06975351ae37f85588fd30af5f681c3da57b986cbcb7e426
6
+ metadata.gz: 2cf9a1a632377a4d9d4f0780401028e4fd44b6991427a96af28e9ea21414d804a3ad97d0ca552b051fe43848a0c98f5df703a999e104bd0a8eae9309a3b7d69c
7
+ data.tar.gz: f676eac78ac6492fc3a283a162a0e06874d55873ead0e5a0c429ed93cc2445e6dfa2f0491e51e08626eca37dbcc59c08eaba07a083248c843d9d84c67a9bd8af
@@ -0,0 +1,13 @@
1
+ module Para
2
+ module I18n
3
+ module FormHelper
4
+ def para_translations_form_for(resource, options = {}, &block)
5
+ extended_options = options.reverse_merge(
6
+ Para::I18n::FormBuilder::TranslationsForm::TRANSLATIONS_FORM_PARAM_KEY => true
7
+ )
8
+
9
+ para_form_for(resource, extended_options, &block)
10
+ end
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,9 @@
1
+ = form.fieldset do
2
+ - I18n.with_locale(@target_locale) do
3
+ = form.input :_disabled_for_locale, as: :boolean, label: t("para.i18n.disabled_for_locale")
4
+
5
+ - translated_model_fields_for(form.object.class).each do |field|
6
+ = form.input field.field_name, as: :i18n
7
+
8
+ - nested_relations_attributes_for(form.object.class).each do |field|
9
+ = form.input field.field_name, as: field.field_type
@@ -1,8 +1,14 @@
1
- = para_form_for(resource, url: @component.relation_path(resource, :translation)) do |form|
1
+ = para_translations_form_for(resource, url: @component.relation_path(resource, :translation), locale: @target_locale) do |form|
2
2
  = target_locale_select
3
3
 
4
4
  = form.fieldset do
5
+ - I18n.with_locale(@target_locale) do
6
+ = form.input :_disabled_for_locale, as: :boolean, label: t("para.i18n.disabled_for_locale")
7
+
5
8
  - translated_model_fields_for(resource.class).each do |field|
6
- = form.input field.field_name, as: :i18n, locale: @target_locale
9
+ = form.input field.field_name, as: :i18n
10
+
11
+ - nested_relations_attributes_for(resource.class).each do |field|
12
+ = form.input field.field_name, as: field.field_type
7
13
 
8
14
  = form.actions(except: :submit_and_add_another)
@@ -4,3 +4,4 @@ fr:
4
4
  translate: "Traduire"
5
5
  translation: "Traduction"
6
6
  choose_locale: "Traduire en :"
7
+ disabled_for_locale: "Masquer pour la langue en cours"
@@ -0,0 +1,28 @@
1
+ module Para
2
+ module I18n
3
+ module FormGeneratorConcern
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ include Para::Admin::BaseHelper
8
+ include Para::Generators::FieldHelpers
9
+ include Para::ModelHelper
10
+ include Para::I18n::Helpers::TranslationsHelper
11
+ end
12
+
13
+ private
14
+
15
+ def translated_attributes
16
+ translated_model_fields_for(model)
17
+ end
18
+
19
+ def nested_relations_attributes
20
+ nested_relations_attributes_for(model)
21
+ end
22
+
23
+ def model
24
+ @model ||= class_name.constantize
25
+ end
26
+ end
27
+ end
28
+ end
@@ -1,10 +1,9 @@
1
+ require "generators/para/i18n/base_form_generator"
2
+
1
3
  module Para
2
4
  module I18n
3
5
  class FormGenerator < Para::Generators::NamedBase
4
- include Para::Admin::BaseHelper
5
- include Para::Generators::FieldHelpers
6
- include Para::ModelHelper
7
- include Para::I18n::Helpers::TranslationsHelper
6
+ include Para::I18n::FormGeneratorConcern
8
7
 
9
8
  source_root File.expand_path("../templates", __FILE__)
10
9
 
@@ -14,16 +13,6 @@ module Para
14
13
  "app/views/admin/#{ plural_namespaced_path }/_translations_form.html.haml"
15
14
  )
16
15
  end
17
-
18
- private
19
-
20
- def translated_attributes
21
- translated_model_fields_for(model)
22
- end
23
-
24
- def model
25
- @model ||= class_name.constantize
26
- end
27
16
  end
28
17
  end
29
18
  end
@@ -1,9 +1,15 @@
1
- = para_form_for(resource, url: @component.relation_path(resource, :translation)) do |form|
1
+ = para_translations_form_for(resource, url: @component.relation_path(resource, :translation), locale: @target_locale) do |form|
2
2
  = target_locale_select
3
3
 
4
4
  = form.fieldset do
5
+ - I18n.with_locale(@target_locale) do
6
+ = form.input :_disabled_for_locale, as: :boolean, label: t("para.i18n.disabled_for_locale")
7
+
5
8
  <%- translated_attributes.each do |field| -%>
6
- = form.input :<%= field.field_name %>, as: :i18n, locale: @target_locale
9
+ = form.input :<%= field.field_name %>, as: :i18n
10
+ <%- end -%>
11
+ <%- nested_relations_attributes.each do |field| -%>
12
+ = form.input :<%= field.field_name %>, as: :<%= field.field_type %>
7
13
  <%- end -%>
8
14
 
9
15
  = form.actions(except: :submit_and_add_another)
@@ -0,0 +1,18 @@
1
+ require "generators/para/i18n/base_form_generator"
2
+
3
+ module Para
4
+ module I18n
5
+ class NestedFieldsGenerator < Para::Generators::NamedBase
6
+ include Para::I18n::FormGeneratorConcern
7
+
8
+ source_root File.expand_path("../templates", __FILE__)
9
+
10
+ def generate_nested_fields
11
+ template(
12
+ "_translations_fields.html.haml",
13
+ "app/views/admin/#{ plural_namespaced_path }/_translations_fields.html.haml"
14
+ )
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,11 @@
1
+ = form.fieldset do
2
+ - I18n.with_locale(@target_locale) do
3
+ = form.input :_disabled_for_locale, as: :boolean, label: t("para.i18n.disabled_for_locale")
4
+
5
+ <%- translated_attributes.each do |field| -%>
6
+ = form.input :<%= field.field_name %>, as: :i18n
7
+ <%- end -%>
8
+ <%- nested_relations_attributes.each do |field| -%>
9
+ = form.input :<%= field.field_name %>, as: :<%= field.field_type %>
10
+ <%- end -%>
11
+
@@ -1,4 +1,4 @@
1
- class Translate<%= table_name.camelize %> < ActiveRecord::Migration
1
+ class Translate<%= table_name.camelize %> < ActiveRecord::Migration<%= "[#{Rails.version.to_f}]" if Rails.version.to_i >= 5 %>
2
2
  def change
3
3
  add_column :<%= table_name %>, :_translations, :jsonb
4
4
  end
data/lib/para/i18n.rb CHANGED
@@ -8,6 +8,14 @@ require 'para/i18n/model'
8
8
  require 'para/i18n/resources_table'
9
9
  require 'para/i18n/resources_buttons'
10
10
 
11
+ require 'para/i18n/attribute_translation'
12
+ require 'para/i18n/attribute_translation/base'
13
+ require 'para/i18n/attribute_translation/simple_attribute'
14
+ require 'para/i18n/attribute_translation/attachment'
15
+
16
+ require 'para/i18n/form_builder'
17
+ require 'para/i18n/inputs'
18
+
11
19
  require 'para/i18n/friendly_id'
12
20
 
13
21
  require 'para/i18n/i18n_input'
@@ -0,0 +1,26 @@
1
+ module Para
2
+ module I18n
3
+ # This module redirects the reading and writing of the translated attributes to the
4
+ # right attribute translation class
5
+ #
6
+ module AttributeTranslation
7
+ def self.read(locale, resource, attribute)
8
+ attribute_translation_class(locale, resource.class, attribute).read(resource)
9
+ end
10
+
11
+ def self.write(locale, resource, attribute, value)
12
+ attribute_translation_class(locale, resource.class, attribute).write(resource, value)
13
+ end
14
+
15
+ def self.attribute_translation_class(locale, model, attribute)
16
+ attribute_translation_class = if AttributeTranslation::Attachment.matches?(model, attribute)
17
+ AttributeTranslation::Attachment.new(locale, model, attribute)
18
+ else
19
+ AttributeTranslation::SimpleAttribute.new(locale, model, attribute)
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
25
+
26
+
@@ -0,0 +1,58 @@
1
+ module Para
2
+ module I18n
3
+ module AttributeTranslation
4
+ class Attachment < Para::I18n::AttributeTranslation::Base
5
+ def read(resource)
6
+ attachment = resource.public_send(reflection_name)
7
+
8
+ if default_locale? || attachment.attached? || !fallback_locale
9
+ attachment
10
+ elsif fallback_locale
11
+ self.class.new(fallback_locale, model, attribute).read(resource)
12
+ end
13
+ end
14
+
15
+ def write(resource, value)
16
+ resource.public_send(:"#{reflection_name}=", value)
17
+ end
18
+
19
+ def self.matches?(model, attribute)
20
+ model.reflections.key?("#{attribute}_attachment") &&
21
+ model.reflections.key?("#{attribute}_blob")
22
+ end
23
+
24
+ def self.prepare(model, attribute)
25
+ return unless matches?(model, attribute)
26
+
27
+ (I18n.available_locales - [I18n.default_locale]).each do |locale|
28
+ new(locale, model, attribute).prepare_translated_attachment
29
+ end
30
+ end
31
+
32
+ def prepare_translated_attachment
33
+ model.alias_method(untranslated_getter_name, attribute)
34
+ model.alias_method(untranslated_setter_name, :"#{attribute}=")
35
+ model.has_one_attached(reflection_name)
36
+ end
37
+
38
+ private
39
+
40
+ def reflection_name
41
+ @reflection_name ||= if default_locale?
42
+ untranslated_getter_name
43
+ else
44
+ [attribute, locale, "translation"].join("_")
45
+ end
46
+ end
47
+
48
+ def untranslated_getter_name
49
+ @untranslated_getter_name ||= :"untranslated_#{attribute}"
50
+ end
51
+
52
+ def untranslated_setter_name
53
+ @untranslated_setter_name ||= :"untranslated_#{attribute}="
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,23 @@
1
+ module Para
2
+ module I18n
3
+ module AttributeTranslation
4
+ class Base
5
+ attr_reader :locale, :model, :attribute
6
+
7
+ def initialize(locale, model, attribute)
8
+ @locale = locale.to_s
9
+ @model = model
10
+ @attribute = attribute.to_s
11
+ end
12
+
13
+ def default_locale?
14
+ @default_locale ||= locale == I18n.default_locale.to_s
15
+ end
16
+
17
+ def fallback_locale
18
+ @fallback_locale ||= Para::I18n::Fallbacks.i18n_fallback_for(locale.to_sym)
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,37 @@
1
+ module Para
2
+ module I18n
3
+ module AttributeTranslation
4
+ class SimpleAttribute < Para::I18n::AttributeTranslation::Base
5
+ def read(resource)
6
+ # Directly read the plain column / store accessor if the current locale is the
7
+ # default one..
8
+ if default_locale? && attribute != "_disabled_for_locale"
9
+ return resource.read_plain_or_store_attribute(attribute)
10
+ end
11
+
12
+ translations = resource.model_translations[locale]
13
+
14
+ if translations && (translation = translations[attribute])
15
+ translation
16
+ elsif fallback_locale
17
+ # If no translation was returned, try to fallback to the next locale
18
+ self.class.new(fallback_locale, model, attribute).read(resource)
19
+ end
20
+ end
21
+
22
+ def write(resource, value)
23
+ if default_locale? && attribute != "_disabled_for_locale"
24
+ return resource.write_plain_or_store_attribute(attribute, value)
25
+ end
26
+
27
+ # did not us ||= here to fix first assignation.
28
+ # Did not investigate on why ||= does not work
29
+ resource.model_translations[locale] = {} unless resource.model_translations[locale]
30
+ resource.model_translations[locale][attribute] = value
31
+ resource._translations_will_change!
32
+ value
33
+ end
34
+ end
35
+ end
36
+ end
37
+ end
@@ -11,7 +11,7 @@ module Para
11
11
  ::Para.config.routes.extend_routes_for(:component) do
12
12
  resource :translation, only: [:edit, :update], controller: '/para/admin/translations'
13
13
  end
14
-
14
+
15
15
  ::Para.config.routes.extend_routes_for(:crud_component) do
16
16
  resource :translation, only: [:edit, :update], controller: '/para/admin/translations'
17
17
  end
@@ -41,7 +41,7 @@ module Para
41
41
  icon: 'globe',
42
42
  label: ::I18n.t('para.i18n.translate'),
43
43
  url: @component.relation_path(resource, :translation, action: :edit)
44
- } if resource.class.translates?
44
+ } if resource.class.translates? && can?(:translate, resource)
45
45
  end
46
46
  end
47
47
  end
@@ -1,12 +1,21 @@
1
1
  module Para
2
2
  module I18n
3
3
  module Fallbacks
4
+ mattr_accessor :_disable_fallbacks
5
+
6
+ def self.without_i18n_fallbacks(&block)
7
+ self._disable_fallbacks = true
8
+ block.call
9
+ ensure
10
+ self._disable_fallbacks = false
11
+ end
12
+
4
13
  def self.i18n_fallback_for(locale)
5
- return unless ::I18n.respond_to?(:fallbacks)
14
+ return if _disable_fallbacks || !::I18n.respond_to?(:fallbacks)
6
15
 
7
16
  if (fallbacks = ::I18n.fallbacks[locale]) && fallbacks.length > 1
8
17
  fallbacks[1]
9
- else
18
+ elsif locale != ::I18n.default_locale
10
19
  ::I18n.default_locale
11
20
  end
12
21
  end
@@ -0,0 +1,10 @@
1
+ require 'para/form_builder'
2
+
3
+ require 'para/i18n/form_builder/nested_form'
4
+ require 'para/i18n/form_builder/translations_form'
5
+
6
+ # Extend the para extended simple_form form builder to included translations related
7
+ # methods.
8
+ #
9
+ SimpleForm::FormBuilder.prepend(Para::I18n::FormBuilder::NestedForm)
10
+ SimpleForm::FormBuilder.prepend(Para::I18n::FormBuilder::TranslationsForm)
@@ -0,0 +1,46 @@
1
+ # frozen_string_literals: true
2
+
3
+ module Para
4
+ module I18n
5
+ module FormBuilder
6
+ # Thid module provides methods to extend the para's nested form functionality by
7
+ # extending the SimpleForm::FormBuilder.
8
+ #
9
+ module NestedForm
10
+ # Traverses the parent_builder chain until the top of the builder chain returning
11
+ # the top-most form builder which represents the one created through the
12
+ # `form_for` like helper.
13
+ #
14
+ # Note that this could go into the Para::FormBuilder::NestedForm module, but it's
15
+ # not used inside Para, so we keep it here for now.
16
+ #
17
+ def top_level_form_builder
18
+ parent_builder = options[:parent_builder]
19
+
20
+ while parent_builder && parent_builder.options[:parent_builder]
21
+ parent_builder = parent_builder.options[:parent_builder]
22
+ end
23
+
24
+ parent_builder || self
25
+ end
26
+
27
+ # Don't allow nested fields destruction if we're in a translations form as this is
28
+ # the method used by the FormBuilder#remove_association_button method to check
29
+ # whether it's allowed to render the remove button or not.
30
+ #
31
+ def allow_destroy?
32
+ return false if translations_form?
33
+
34
+ super
35
+ end
36
+
37
+ # Overrides the Para::FormBuilder::NestedForm#fields_partial_name method to render
38
+ # a different nested fields partial when the builder is a translations form
39
+ #
40
+ def nested_fields_partial_name
41
+ translations_form? ? :translations_fields : :fields
42
+ end
43
+ end
44
+ end
45
+ end
46
+ end
@@ -0,0 +1,42 @@
1
+ # frozen_string_literals: true
2
+
3
+ module Para
4
+ module I18n
5
+ module FormBuilder
6
+ # Thid module extends the Para overriden SimpleForm::FormBuilder to include some
7
+ # trnaslations form related methods and overrides, allowing a simple use of
8
+ # translations forms with the para-i18n gem.
9
+ #
10
+ module TranslationsForm
11
+ TRANSLATIONS_FORM_PARAM_KEY = :_translations_form
12
+
13
+ # Allows storing a gobal reference to the target locale of the translations form,
14
+ # which allows input objects to fetch it directly, without having to provide
15
+ # manually the :locale parameter for each input
16
+ #
17
+ # Example :
18
+ #
19
+ # = para_translations_form_for(resource, locale: @target_Locale) do |form|
20
+ # = form.input :title, as: :i18n # No need to pass `:locale` option here.
21
+ #
22
+ def target_locale
23
+ top_level_form_builder.options.with_indifferent_access[:locale]
24
+ end
25
+
26
+ # Allows checking if the current form builder is a translations form, depending
27
+ # on the passed TRANSLATIONS_FORM_PARAM_KEY option. This is automatically passed
28
+ # to the form builder when using the `para_translations_form_for` helper.
29
+ #
30
+ # Example :
31
+ #
32
+ # para_translations_form_for(resource)
33
+ # # OR
34
+ # para_form_for(resource, _translations_form: true)
35
+ #
36
+ def translations_form?
37
+ !!top_level_form_builder.options.with_indifferent_access[TRANSLATIONS_FORM_PARAM_KEY]
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -10,6 +10,15 @@ module FriendlyId
10
10
  def included(model_class)
11
11
  model_class.extend(ClassMethods)
12
12
 
13
+ # Support for I18n finder methods on ActiveRecord::Relation of the including
14
+ # model. Example :
15
+ model_class.instance_eval do
16
+ relation.class.send(:include, ClassMethods)
17
+ if (ActiveRecord::VERSION::MAJOR == 4 && ActiveRecord::VERSION::MINOR == 2) || ActiveRecord::VERSION::MAJOR >= 5
18
+ model_class.send(:extend, ClassMethods)
19
+ end
20
+ end
21
+
13
22
  # Support for friendly finds on associations for Rails 4.0.1 and above.
14
23
  #
15
24
  # Borrowed from FriendlyId::Finders module
@@ -9,6 +9,15 @@ module Para
9
9
  model.translated_attribute_names.include?(field.name.to_sym)
10
10
  end
11
11
  end
12
+
13
+ def nested_relations_attributes_for(model)
14
+ model_field_mappings(model).fields.select do |field|
15
+ next unless field.field_type.in?(["nested_one", "nested_many"])
16
+
17
+ # This returns nil if the target model is not translated
18
+ model.reflect_on_association(field.name).klass.translatable?
19
+ end
20
+ end
12
21
  end
13
22
  end
14
23
  end
@@ -26,11 +26,11 @@ module Para
26
26
  private
27
27
 
28
28
  def locale
29
- if (locale = options[:locale])
30
- locale
31
- else
32
- raise 'Missing `:locale` option passed to :i18n input.'
33
- end
29
+ locale = options.fetch(:locale, @builder.target_locale)
30
+ return locale if locale.present?
31
+
32
+ raise 'No target locale for the current i18n input. Please provide a `:locale`' \
33
+ 'option to the :i18n input or the `para_translations_form_for` method'
34
34
  end
35
35
 
36
36
  def original_content
@@ -0,0 +1,4 @@
1
+ require "para/inputs/nested_many_input"
2
+ require 'para/i18n/inputs/nested_many_input'
3
+
4
+ Para::Inputs::NestedManyInput.prepend(Para::I18n::Inputs::NestedManyInput)
@@ -0,0 +1,41 @@
1
+ module Para
2
+ module I18n
3
+ module Inputs
4
+ module NestedManyInput
5
+ def input(_wrapper_options = nil)
6
+ # Disable the add button and orderable features of the input.
7
+ # Note : The remove button disabling is done by the
8
+ # Para::I18n::FormBuilder::TranslationsForm extension
9
+ if within_translations_form?
10
+ options[:add_button] = false
11
+ options[:orderable] = false
12
+ end
13
+
14
+ super
15
+ end
16
+ private
17
+
18
+ def within_translations_form?
19
+ @builder.translations_form?
20
+ end
21
+
22
+ # Extend remote partial params with the :_translations_form key if we're in the
23
+ # context of a translations form builder.
24
+ #
25
+ def remote_partial_params
26
+ super.tap do |remote_partial_params|
27
+ if within_translations_form?
28
+ remote_partial_params.deep_merge!(
29
+ builder_options: {
30
+ Para::I18n::FormBuilder::TranslationsForm::TRANSLATIONS_FORM_PARAM_KEY => true,
31
+ locale: @builder.target_locale
32
+ }
33
+ )
34
+ end
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
41
+
@@ -9,33 +9,17 @@ module Para
9
9
  end
10
10
 
11
11
  def read_translated_attribute(field, locale = ::I18n.locale)
12
- return read_plain_or_store_attribute(field) if locale == ::I18n.default_locale
13
-
14
- if model_translations[locale.to_s]
15
- if (translation = model_translations[locale.to_s][field.to_s])
16
- return translation
17
- end
18
- end
19
-
20
- # If no translation was returned, try to fallback to the next locale
21
- if (fallback_locale = Fallbacks.i18n_fallback_for(locale))
22
- read_translated_attribute(field, fallback_locale)
23
- end
12
+ Para::I18n::AttributeTranslation.read(locale, self, field)
24
13
  end
25
14
 
26
- def write_translated_attribute field, value, locale = ::I18n.locale
27
- return write_plain_or_store_attribute(field, value) if locale == ::I18n.default_locale
28
-
29
- # did not us ||= here to fix first assignation.
30
- # Did not investigate on why ||= does not work
31
- model_translations[locale.to_s] = {} unless model_translations[locale.to_s]
32
- model_translations[locale.to_s][field.to_s] = value
15
+ def write_translated_attribute(field, value, locale = ::I18n.locale)
16
+ Para::I18n::AttributeTranslation.write(locale, self, field, value)
33
17
  end
34
18
 
35
19
  def model_translations
36
20
  unless respond_to?(:_translations)
37
21
  raise "The model #{ self.class.name } is not translatable. " +
38
- "Please run `rails g i18n_admin:translate #{ self.model_name.element }` " +
22
+ "Please run `rails g para:i18n:translate #{ self.model_name.element }` " +
39
23
  "generator to create the model's migration."
40
24
  end
41
25
 
@@ -43,11 +27,20 @@ module Para
43
27
  end
44
28
 
45
29
  def translation_for(locale)
46
- model_translations[locale.to_s] || {}
30
+ case locale.to_sym
31
+ when I18n.default_locale then default_locale_translations
32
+ else model_translations[locale.to_s] || {}
33
+ end.with_indifferent_access
47
34
  end
48
35
 
49
- private
36
+ def disabled_for_locale?
37
+ self.class.translates? && _disabled_for_locale
38
+ end
50
39
 
40
+ # This method allows reading an attribute from the ActiveRecord table, whether it's
41
+ # a plain column of the table, or a field of a store (hash, json etc.) of the table,
42
+ # accessed through the ActiveRecord.store_accessor interface.
43
+ #
51
44
  def read_plain_or_store_attribute(field)
52
45
  if plain_column?(field)
53
46
  read_attribute(field)
@@ -68,6 +61,8 @@ module Para
68
61
  end
69
62
  end
70
63
 
64
+ private
65
+
71
66
  def plain_column?(field)
72
67
  self.class.columns_hash.key?(field.to_s)
73
68
  end
@@ -80,25 +75,49 @@ module Para
80
75
  store.first if store
81
76
  end
82
77
 
78
+ def default_locale_translations
79
+ translated_attribute_names.each_with_object({}) do |attribute_name, hash|
80
+ hash[attribute_name] = read_plain_or_store_attribute(attribute_name)
81
+ end
82
+ end
83
+
83
84
  module ClassMethods
84
85
  def translates(*fields)
85
86
  self.translated_attribute_names = fields.map(&:to_sym)
86
87
  self.translatable = true
87
88
 
88
89
  fields.each do |field|
89
- define_method field do
90
- read_translated_attribute(field)
91
- end
90
+ prepare_attribute_translation(field)
91
+ end
92
+
93
+ define_method(:_disabled_for_locale) do
94
+ read_translated_attribute(:_disabled_for_locale) == "1"
95
+ end
92
96
 
93
- define_method :"#{ field }=" do |value|
94
- write_translated_attribute(field, value)
95
- end
97
+ define_method(:_disabled_for_locale=) do |value|
98
+ write_translated_attribute(:_disabled_for_locale, value)
96
99
  end
97
100
  end
98
101
 
99
102
  def translates?
100
103
  translatable
101
104
  end
105
+
106
+ private
107
+
108
+ def prepare_attribute_translation(attribute)
109
+ # Let the Para::I18n::AttributeTranslation::Attachment module handle
110
+ # ActiveStorage attachment fields translation preparation.
111
+ Para::I18n::AttributeTranslation::Attachment.prepare(self, attribute)
112
+
113
+ define_method(attribute) do
114
+ read_translated_attribute(attribute)
115
+ end
116
+
117
+ define_method(:"#{attribute}=") do |value|
118
+ write_translated_attribute(attribute, value)
119
+ end
120
+ end
102
121
  end
103
122
  end
104
123
  end
@@ -2,7 +2,7 @@ module Para
2
2
  module I18n
3
3
  module ResourcesButtons
4
4
  def translate_button(resource)
5
- return unless resource.class.translates?
5
+ return unless resource.class.translates? && view.can?(:translate, resource)
6
6
 
7
7
  path = component.relation_path(resource, :translation, action: :edit)
8
8
  options = { class: 'btn btn-default' }
@@ -1,5 +1,5 @@
1
1
  module Para
2
2
  module I18n
3
- VERSION = "0.3.2"
3
+ VERSION = "0.5.0"
4
4
  end
5
5
  end
data/para-i18n.gemspec CHANGED
@@ -19,7 +19,7 @@ Gem::Specification.new do |spec|
19
19
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
20
20
  spec.require_paths = ["lib"]
21
21
 
22
- spec.add_dependency "para", "~> 0.8"
22
+ spec.add_dependency "para", ">= 0.9.2", "<= 1.0"
23
23
 
24
24
  spec.add_development_dependency "bundler", "~> 1.11"
25
25
  spec.add_development_dependency "rake", "~> 10.0"
metadata CHANGED
@@ -1,29 +1,35 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: para-i18n
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.2
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Valentin Ballestrino
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-04-16 00:00:00.000000000 Z
11
+ date: 2021-02-09 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: para
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 0.9.2
20
+ - - "<="
18
21
  - !ruby/object:Gem::Version
19
- version: '0.8'
22
+ version: '1.0'
20
23
  type: :runtime
21
24
  prerelease: false
22
25
  version_requirements: !ruby/object:Gem::Requirement
23
26
  requirements:
24
- - - "~>"
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ version: 0.9.2
30
+ - - "<="
25
31
  - !ruby/object:Gem::Version
26
- version: '0.8'
32
+ version: '1.0'
27
33
  - !ruby/object:Gem::Dependency
28
34
  name: bundler
29
35
  requirement: !ruby/object:Gem::Requirement
@@ -83,24 +89,38 @@ files:
83
89
  - app/assets/javascripts/para/admin/translation.coffee
84
90
  - app/assets/javascripts/para/i18n.coffee
85
91
  - app/controllers/para/admin/translations_controller.rb
92
+ - app/helpers/para/i18n/form_helper.rb
93
+ - app/views/para/admin/resources/_translations_fields.html.haml
86
94
  - app/views/para/admin/resources/_translations_form.html.haml
87
95
  - app/views/para/admin/translations/_target_locale_select.html.haml
88
96
  - app/views/para/admin/translations/edit.html.haml
89
97
  - bin/console
90
98
  - bin/setup
91
99
  - config/locales/para-i18n.fr.yml
100
+ - lib/generators/para/i18n/base_form_generator.rb
92
101
  - lib/generators/para/i18n/form/form_generator.rb
93
102
  - lib/generators/para/i18n/form/templates/_translations_form.html.haml
103
+ - lib/generators/para/i18n/nested_fields/nested_fields_generator.rb
104
+ - lib/generators/para/i18n/nested_fields/templates/_translations_fields.html.haml
94
105
  - lib/generators/para/i18n/translate/templates/model_migration.rb.erb
95
106
  - lib/generators/para/i18n/translate/translate_generator.rb
96
107
  - lib/para/i18n.rb
108
+ - lib/para/i18n/attribute_translation.rb
109
+ - lib/para/i18n/attribute_translation/attachment.rb
110
+ - lib/para/i18n/attribute_translation/base.rb
111
+ - lib/para/i18n/attribute_translation/simple_attribute.rb
97
112
  - lib/para/i18n/engine.rb
98
113
  - lib/para/i18n/fallbacks.rb
114
+ - lib/para/i18n/form_builder.rb
115
+ - lib/para/i18n/form_builder/nested_form.rb
116
+ - lib/para/i18n/form_builder/translations_form.rb
99
117
  - lib/para/i18n/friendly_id.rb
100
118
  - lib/para/i18n/helpers.rb
101
119
  - lib/para/i18n/helpers/translations_form_helper.rb
102
120
  - lib/para/i18n/helpers/translations_helper.rb
103
121
  - lib/para/i18n/i18n_input.rb
122
+ - lib/para/i18n/inputs.rb
123
+ - lib/para/i18n/inputs/nested_many_input.rb
104
124
  - lib/para/i18n/model.rb
105
125
  - lib/para/i18n/resources_buttons.rb
106
126
  - lib/para/i18n/resources_table.rb
@@ -125,8 +145,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
125
145
  - !ruby/object:Gem::Version
126
146
  version: '0'
127
147
  requirements: []
128
- rubyforge_project:
129
- rubygems_version: 2.6.11
148
+ rubygems_version: 3.1.4
130
149
  signing_key:
131
150
  specification_version: 4
132
151
  summary: Para CMS I18n admin module for models