para-i18n 0.3.5 → 0.4.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA256:
3
- metadata.gz: 3c4c76be23e0dc2fcfb13e839d1c2089bfe2eab1b16519e54e78bd75bcda5c12
4
- data.tar.gz: 8d881ca0a6c73df1f8c2f555bb2d3bfa8bed18bee79c4bf7330f3b950f53ab77
2
+ SHA1:
3
+ metadata.gz: bffd454f68783dc4413fab9cff53b3c899b0f908
4
+ data.tar.gz: 783928239cee302a6e963057cc8f68becd744c8c
5
5
  SHA512:
6
- metadata.gz: c5c3d41e097f5d2e9a680e1676265a9e67a1d0b9070c558d859f912422716bedb2a0a15bf24804e38a2cdea1caff4ebce6165ad34b6af74983088780964d49b3
7
- data.tar.gz: 689ad5412cf0ec59571abd312fb75f4ca176c0909074e48325cc7ee25410f8ff469930c50fcc6cf63be15fdf5ed0ae92beaac3ad1131a8989512a44fe1f8ecea
6
+ metadata.gz: aa848897075a6d40a94d92451e3b660e1c18aade214e90ca0a394d066b58dd03f3d143f6457f29e469b805215f37e451f21a093443f67cc7298b2bd8a7a047de
7
+ data.tar.gz: 3ce0e4a22d344090a9d98ba86fb505b778549e2a230d8e981b9288af8b0d16da180e8993d1b828c7d795d867092d01575c3a040e43e74f6f2c3c05ade9eaa975
@@ -8,6 +8,11 @@ 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
+
11
16
  require 'para/i18n/friendly_id'
12
17
 
13
18
  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
@@ -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,27 +9,11 @@ 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 && field != :_disabled_for_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 && field != :_disabled_for_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
@@ -43,7 +27,7 @@ module Para
43
27
  end
44
28
 
45
29
  def translation_for(locale)
46
- case locale
30
+ case locale.to_sym
47
31
  when I18n.default_locale then default_locale_translations
48
32
  else model_translations[locale.to_s] || {}
49
33
  end.with_indifferent_access
@@ -53,8 +37,10 @@ module Para
53
37
  self.class.translates? && _disabled_for_locale
54
38
  end
55
39
 
56
- private
57
-
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
+ #
58
44
  def read_plain_or_store_attribute(field)
59
45
  if plain_column?(field)
60
46
  read_attribute(field)
@@ -75,6 +61,8 @@ module Para
75
61
  end
76
62
  end
77
63
 
64
+ private
65
+
78
66
  def plain_column?(field)
79
67
  self.class.columns_hash.key?(field.to_s)
80
68
  end
@@ -99,13 +87,7 @@ module Para
99
87
  self.translatable = true
100
88
 
101
89
  fields.each do |field|
102
- define_method field do
103
- read_translated_attribute(field)
104
- end
105
-
106
- define_method :"#{ field }=" do |value|
107
- write_translated_attribute(field, value)
108
- end
90
+ prepare_attribute_translation(field)
109
91
  end
110
92
 
111
93
  define_method(:_disabled_for_locale) do
@@ -120,6 +102,22 @@ module Para
120
102
  def translates?
121
103
  translatable
122
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
123
121
  end
124
122
  end
125
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.5"
3
+ VERSION = "0.4.1"
4
4
  end
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: para-i18n
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.5
4
+ version: 0.4.1
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-06-18 00:00:00.000000000 Z
11
+ date: 2020-09-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: para
@@ -94,6 +94,10 @@ files:
94
94
  - lib/generators/para/i18n/translate/templates/model_migration.rb.erb
95
95
  - lib/generators/para/i18n/translate/translate_generator.rb
96
96
  - lib/para/i18n.rb
97
+ - lib/para/i18n/attribute_translation.rb
98
+ - lib/para/i18n/attribute_translation/attachment.rb
99
+ - lib/para/i18n/attribute_translation/base.rb
100
+ - lib/para/i18n/attribute_translation/simple_attribute.rb
97
101
  - lib/para/i18n/engine.rb
98
102
  - lib/para/i18n/fallbacks.rb
99
103
  - lib/para/i18n/friendly_id.rb
@@ -125,7 +129,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
125
129
  - !ruby/object:Gem::Version
126
130
  version: '0'
127
131
  requirements: []
128
- rubygems_version: 3.0.3
132
+ rubyforge_project:
133
+ rubygems_version: 2.6.11
129
134
  signing_key:
130
135
  specification_version: 4
131
136
  summary: Para CMS I18n admin module for models