decidim-term_customizer 0.16.3 → 0.16.5

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6e1966c6d76f52620be03f12e047aaae93afeb95fe0514dc4710d89a6f3bfdfd
4
- data.tar.gz: 325607f77cf3ac7760e86ca9a8d29a16dcedfcfcc2b3cb971eb4ab048f49211a
3
+ metadata.gz: b9473c65d949ac1f1c14f152bad4cd0c04ffcff5f2a9ad377dc470f2af4fc256
4
+ data.tar.gz: 64b870998a9239a6242ea2bd1ebe0ac1e00b1bcb9812d7b5bd3efa2618dbbb68
5
5
  SHA512:
6
- metadata.gz: b8020b5e16df220bf10b4daf420a05ae5547eb79eb3a5473b4cb9c1200d6ac5ec6ecd71a85000463459a9abc6057226d9a019c77225956fec165971e546e73a1
7
- data.tar.gz: fb719d2024b32369669f7c62c7aa9b7960d57e79d812299e7498e9b08308767e10f087077dcfdea14eb9b3f4a5b5c5f05df0d28e5b7cd74a71e97767b3d20e0f
6
+ metadata.gz: '08f642fc149b9d8664081607afe9fb167fcc42dc7f6e2f02a8b73c0a0efd746f2c015e0023d46b5e6d4241e342bb13dbf7a2e2087508c850060a44378435933f'
7
+ data.tar.gz: c6648b9f8d3e89a7308d4b320a4bf96b6e09fa5d958a5005b343832534eae8c827d8171fa7a9f0bb669d9f6c350dcdb46bfc5b92986b39e3610ae0491d3ad944
@@ -38,20 +38,19 @@ module Decidim
38
38
  attr_reader :form
39
39
 
40
40
  def create_translations
41
- form.keys.each do |key|
42
- form.current_organization.available_locales.each do |locale|
41
+ items = form.keys.map do |key|
42
+ form.current_organization.available_locales.map do |locale|
43
43
  attrs = {
44
- translation_set: form.translation_set,
45
44
  key: key,
46
45
  locale: locale
47
46
  }
48
47
  next unless TermCustomizer::Translation.find_by(attrs).nil?
49
48
 
50
- TermCustomizer::Translation.create!(
51
- attrs.merge(value: I18n.t(key, locale: locale, default: ""))
52
- )
49
+ attrs.merge(value: I18n.t(key, locale: locale, default: ""))
53
50
  end
54
51
  end.flatten
52
+
53
+ form.translation_set.translations.create!(items)
55
54
  end
56
55
  end
57
56
  end
@@ -0,0 +1,24 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module TermCustomizer
5
+ module Admin
6
+ class CachesController < TermCustomizer::Admin::ApplicationController
7
+ def index
8
+ enforce_permission_to :update, :organization
9
+
10
+ redirect_to translation_sets_path
11
+ end
12
+
13
+ def clear
14
+ enforce_permission_to :update, :organization
15
+
16
+ TermCustomizer.loader.clear_cache
17
+ flash[:notice] = I18n.t("caches.clear.success", scope: "decidim.term_customizer.admin")
18
+
19
+ redirect_to translation_sets_path
20
+ end
21
+ end
22
+ end
23
+ end
24
+ end
@@ -88,7 +88,10 @@ module Decidim
88
88
  end
89
89
 
90
90
  def translations
91
- @translations ||= SetTranslations.new(translation_set, current_locale)
91
+ @translations ||= SetTranslations.new(
92
+ translation_set,
93
+ current_locale
94
+ ).query.page(params[:page]).per(30)
92
95
  end
93
96
 
94
97
  def translation
@@ -1,10 +1,20 @@
1
1
  <div class="card" id="translation_sets">
2
2
  <div class="card-divider">
3
- <h2 class="card-title">
4
- <%= t "decidim.admin.titles.translation_sets" %>
5
- <% if allowed_to? :create, :translation_set %>
6
- <%= link_to t("actions.new_translation_set", scope: "decidim.admin"), new_translation_set_path, class: "button tiny button--title" %>
7
- <% end %>
3
+ <h2 class="card-title flex--sbc">
4
+ <div>
5
+ <%= t "decidim.admin.titles.translation_sets" %>
6
+ </div>
7
+
8
+ <div class="flex--cc flex-gap--1">
9
+ <div id="js-other-actions-wrapper">
10
+ <% if allowed_to? :create, :translation_set %>
11
+ <%= link_to t("actions.new_translation_set", scope: "decidim.admin"), new_translation_set_path, class: "button tiny button--simple" %>
12
+ <% end %>
13
+ <% if allowed_to? :update, :organization %>
14
+ <%= link_to t("actions.clear_cache", scope: "decidim.admin"), clear_caches_path, method: :delete, class: "button tiny button--simple", data: { confirm: t("actions.confirm_destroy", scope: "decidim.admin") } %>
15
+ <% end %>
16
+ </div>
17
+ </div>
8
18
  </h2>
9
19
  </div>
10
20
  <div class="card-section">
@@ -51,6 +51,7 @@
51
51
  <% end %>
52
52
  </tbody>
53
53
  </table>
54
+ <%= paginate @translations, theme: "decidim" %>
54
55
  </div>
55
56
  </div>
56
57
  </div>
@@ -15,6 +15,7 @@ ca:
15
15
  actions:
16
16
  add_multiple_translations: Afegir múltiples
17
17
  back: Enrere
18
+ clear_cache: Clear cache
18
19
  new_translation_set: Nou set/joc de traducció
19
20
  new_translation: Nova traducció
20
21
  models:
@@ -35,6 +36,9 @@ ca:
35
36
  index:
36
37
  add: Afegir
37
38
  search: Buscar
39
+ caches:
40
+ clear:
41
+ success: Cache cleared successfully
38
42
  translation_sets:
39
43
  constraint_fields:
40
44
  constraint: Obligatori
@@ -15,6 +15,7 @@ en:
15
15
  actions:
16
16
  add_multiple_translations: Add multiple
17
17
  back: Back
18
+ clear_cache: Clear cache
18
19
  new_translation_set: New translation set
19
20
  new_translation: New translation
20
21
  models:
@@ -35,6 +36,9 @@ en:
35
36
  index:
36
37
  add: Add
37
38
  search: Search
39
+ caches:
40
+ clear:
41
+ success: Cache cleared successfully
38
42
  translation_sets:
39
43
  constraint_fields:
40
44
  constraint: Constraint
@@ -15,6 +15,7 @@ es:
15
15
  actions:
16
16
  add_multiple_translations: Agregar varios
17
17
  back: Volver
18
+ clear_cache: Clear cache
18
19
  new_translation_set: Nuevo grupo de traducciones
19
20
  new_translation: Nueva traducción
20
21
  models:
@@ -35,6 +36,9 @@ es:
35
36
  index:
36
37
  add: Añadir
37
38
  search: Buscar
39
+ caches:
40
+ clear:
41
+ success: Cache cleared successfully
38
42
  translation_sets:
39
43
  constraint_fields:
40
44
  constraint: Ámbito
@@ -15,6 +15,7 @@ fi:
15
15
  actions:
16
16
  add_multiple_translations: Lisää useita
17
17
  back: Takaisin
18
+ clear_cache: Tyhjennä välimuisti
18
19
  new_translation_set: Uusi käännöspaketti
19
20
  new_translation: Uusi käännös
20
21
  models:
@@ -35,6 +36,9 @@ fi:
35
36
  index:
36
37
  add: Lisää
37
38
  search: Hae
39
+ caches:
40
+ clear:
41
+ success: Välimuistin tyhjennys onnistui
38
42
  translation_sets:
39
43
  constraint_fields:
40
44
  constraint: Rajaussääntö
@@ -15,6 +15,7 @@ sv:
15
15
  actions:
16
16
  add_multiple_translations: Add multiple
17
17
  back: Back
18
+ clear_cache: Clear cache
18
19
  new_translation_set: New translation set
19
20
  new_translation: New translation
20
21
  models:
@@ -35,6 +36,9 @@ sv:
35
36
  index:
36
37
  add: Add
37
38
  search: Search
39
+ caches:
40
+ clear:
41
+ success: Cache cleared successfully
38
42
  translation_sets:
39
43
  constraint_fields:
40
44
  constraint: Constraint
@@ -18,6 +18,12 @@ module Decidim
18
18
  end
19
19
  end
20
20
 
21
+ resources :caches, only: [:index] do
22
+ collection do
23
+ delete :clear
24
+ end
25
+ end
26
+
21
27
  root to: "translation_sets#index"
22
28
  end
23
29
 
@@ -18,17 +18,69 @@ module Decidim
18
18
  # environment variables within Decidim.
19
19
  ActiveSupport::Notifications.subscribe "start_processing.action_controller" do |_name, _started, _finished, _unique_id, data|
20
20
  env = data[:headers].env
21
+ controller = data[:headers].env["action_controller.instance"]
22
+
23
+ # E.g. at the participatory process controller the
24
+ # `decidim.current_participatory_space` environment variable has not
25
+ # been set. Therefore, we need to fetch it directly from the
26
+ # controller using its private method.
27
+ space =
28
+ if controller.respond_to?(:current_participatory_space, true)
29
+ controller.send(:current_participatory_space)
30
+ else
31
+ env["decidim.current_participatory_space"]
32
+ end
21
33
 
22
34
  # Create a new resolver instance within the current request scope
23
- TermCustomizer.resolver = Resolver.new(
35
+ resolver = Resolver.new(
24
36
  env["decidim.current_organization"],
25
- env["decidim.current_participatory_space"],
37
+ space,
26
38
  env["decidim.current_component"]
27
39
  )
28
40
 
41
+ # Create the loader for the backend to fetch the translations from
42
+ TermCustomizer.loader = Loader.new(resolver)
43
+
29
44
  # Force the backend to reload the translations for the current request
30
45
  customizer_backend.reload!
31
46
  end
47
+
48
+ # The jobs are generally run in different context than the controllers
49
+ # which causes the term customizations not to be active. During the
50
+ # jobs, only the organization and global context translations are loaded
51
+ # because otherwise this would have to be job specific.
52
+ #
53
+ # Currently this has been only tested against the event notification
54
+ # jobs but it may work for other jobs as well. Because the jobs
55
+ # themselves don't carry any other context information than their
56
+ # arguments, it is difficult to resolve their correct context. Note also
57
+ # that e.g. the email notifications are always created through a single
58
+ # job that may be fired by another job (i.e. the notification job is
59
+ # always performed last).
60
+ ActiveSupport::Notifications.subscribe "perform_start.active_job" do |_name, _started, _finished, _unique_id, data|
61
+ # Figure out the organization and user through the job arguments if
62
+ # passed for the job.
63
+ organization = nil
64
+ user = nil
65
+ data[:job].arguments.each do |arg|
66
+ organization = arg if arg.is_a?(Decidim::Organization)
67
+ user = arg if arg.is_a?(Decidim::User)
68
+ end
69
+
70
+ # In case an organization was not passed for the job, check it through
71
+ # the user.
72
+ organization = user.organization if organization.nil? && user
73
+
74
+ # Create resolver for the target organization or global context in
75
+ # case organization was not found
76
+ resolver = Resolver.new(organization, nil, nil)
77
+
78
+ # Create the loader for the backend to fetch the translations from
79
+ TermCustomizer.loader = Loader.new(resolver)
80
+
81
+ # Force the backend to reload the translations for the job
82
+ customizer_backend.reload!
83
+ end
32
84
  end
33
85
  end
34
86
  end
@@ -32,24 +32,9 @@ module Decidim
32
32
 
33
33
  def translations
34
34
  return @translations if @translations
35
- return {} unless TermCustomizer.resolver
35
+ return {} unless TermCustomizer.loader
36
36
 
37
- @translations = {}
38
-
39
- TermCustomizer.resolver.translations.each do |tr|
40
- keyparts = [tr.locale] + tr.key.split(".")
41
- lastkey = keyparts.pop.to_sym
42
-
43
- current = @translations
44
- keyparts.each do |key|
45
- current[key.to_sym] ||= {}
46
- current = current[key.to_sym]
47
- end
48
-
49
- current[lastkey] = tr.value
50
- end
51
-
52
- @translations
37
+ @translations = TermCustomizer.loader.translations_hash
53
38
  end
54
39
 
55
40
  protected
@@ -0,0 +1,86 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Decidim
4
+ module TermCustomizer
5
+ # The loader class is a middleman that converts the Translation model
6
+ # objects to a flat translation hash that can be directly used in the i18n
7
+ # backend. The main purpose of this class is to add caching possibility for
8
+ # the translation hashes.
9
+ class Loader
10
+ def initialize(resolver)
11
+ @resolver = resolver
12
+ end
13
+
14
+ # Converts the translation objects to a flat hash where the keys are
15
+ # the translatable keys used in the i18n backend containing the locales.
16
+ # The values of the hash are the translations for the keys.
17
+ #
18
+ # The final hash looks similar like this:
19
+ # {
20
+ # en: {
21
+ # decidim: {
22
+ # translation: "Term EN"
23
+ # }
24
+ # },
25
+ # fi: {
26
+ # decidim: {
27
+ # translation: "Term FI"
28
+ # }
29
+ # }
30
+ # }
31
+ #
32
+ # This will also cache the results and fetch the result directly from
33
+ # cache on consequent calls until the cache is expired.
34
+ def translations_hash
35
+ @translations_hash ||= Rails.cache.fetch(
36
+ cache_key,
37
+ expires_in: 24.hours
38
+ ) do
39
+ final_hash = {}
40
+ resolver.translations.each do |tr|
41
+ keyparts = [tr.locale] + tr.key.split(".")
42
+ lastkey = keyparts.pop.to_sym
43
+
44
+ current = final_hash
45
+ keyparts.each do |key|
46
+ current[key.to_sym] ||= {}
47
+ current = current[key.to_sym]
48
+ end
49
+
50
+ current[lastkey] = tr.value
51
+ end
52
+ final_hash
53
+ end
54
+ end
55
+
56
+ # Clears the translations cache only for the current context defined by
57
+ # the resolver.
58
+ def clear_cache
59
+ Rails.cache.delete_matched("#{cache_key_base}/*")
60
+ end
61
+
62
+ private
63
+
64
+ attr_reader :resolver
65
+
66
+ def cache_key
67
+ parts = [cache_key_base]
68
+ parts << "space_#{resolver.space.id}" if resolver.space
69
+ parts << "component_#{resolver.component.id}" if resolver.component
70
+
71
+ parts.join("/")
72
+ end
73
+
74
+ def cache_key_base
75
+ main_key =
76
+ if resolver.organization
77
+ "organization_#{resolver.organization.id}"
78
+ else
79
+ "system"
80
+ end
81
+
82
+ "decidim_term_customizer/#{main_key}"
83
+ end
84
+ end
85
+ end
86
+ end
@@ -3,6 +3,8 @@
3
3
  module Decidim
4
4
  module TermCustomizer
5
5
  class Resolver
6
+ attr_reader :organization, :space, :component
7
+
6
8
  def initialize(organization, space, component)
7
9
  @organization = organization
8
10
  @space = space
@@ -19,8 +21,6 @@ module Decidim
19
21
 
20
22
  private
21
23
 
22
- attr_reader :organization, :space, :component
23
-
24
24
  def resolve_translations_query
25
25
  query = translations_base_query
26
26
  translations_add_constraints_query(query)
@@ -2,7 +2,7 @@
2
2
 
3
3
  module Decidim
4
4
  module TermCustomizer
5
- VERSION = "0.16.3"
5
+ VERSION = "0.16.5"
6
6
  DECIDIM_VERSION = "~> 0.16.0"
7
7
  end
8
8
  end
@@ -8,6 +8,7 @@ require_relative "term_customizer/admin_engine"
8
8
  module Decidim
9
9
  module TermCustomizer
10
10
  autoload :I18nBackend, "decidim/term_customizer/i18n_backend"
11
+ autoload :Loader, "decidim/term_customizer/loader"
11
12
  autoload :Resolver, "decidim/term_customizer/resolver"
12
13
  autoload :TranslationDirectory, "decidim/term_customizer/translation_directory"
13
14
  autoload :TranslationStore, "decidim/term_customizer/translation_store"
@@ -15,7 +16,7 @@ module Decidim
15
16
  EMPTY_HASH = {}.freeze
16
17
 
17
18
  class << self
18
- attr_accessor :resolver
19
+ attr_accessor :loader
19
20
  end
20
21
  end
21
22
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: decidim-term_customizer
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.16.3
4
+ version: 0.16.5
5
5
  platform: ruby
6
6
  authors:
7
7
  - Antti Hukkanen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2019-03-07 00:00:00.000000000 Z
11
+ date: 2019-03-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: decidim-admin
@@ -118,6 +118,7 @@ files:
118
118
  - app/commands/decidim/term_customizer/admin/update_translation_set.rb
119
119
  - app/controllers/decidim/term_customizer/admin/add_translations_controller.rb
120
120
  - app/controllers/decidim/term_customizer/admin/application_controller.rb
121
+ - app/controllers/decidim/term_customizer/admin/caches_controller.rb
121
122
  - app/controllers/decidim/term_customizer/admin/translation_sets_controller.rb
122
123
  - app/controllers/decidim/term_customizer/admin/translations_controller.rb
123
124
  - app/forms/decidim/term_customizer/admin/translation_form.rb
@@ -157,6 +158,7 @@ files:
157
158
  - lib/decidim/term_customizer/admin_engine.rb
158
159
  - lib/decidim/term_customizer/engine.rb
159
160
  - lib/decidim/term_customizer/i18n_backend.rb
161
+ - lib/decidim/term_customizer/loader.rb
160
162
  - lib/decidim/term_customizer/resolver.rb
161
163
  - lib/decidim/term_customizer/test/factories.rb
162
164
  - lib/decidim/term_customizer/translation_directory.rb