From 657359186189344b975de996aab5489e0a7fdf88 Mon Sep 17 00:00:00 2001 From: barbara oliveira Date: Fri, 5 Sep 2025 17:31:50 +0200 Subject: [PATCH 01/27] docs: add DeepL translator environment variables to .env-emple --- .env-example | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.env-example b/.env-example index 3efc530ff4..9658e90b88 100644 --- a/.env-example +++ b/.env-example @@ -57,3 +57,8 @@ GEOCODER_UNITS=km # Units for geocoder results (e.g., km or m # DECIDIM_AI_BASIC_AUTH=":" Required for the AI Request Handler # DECIDIM_AI_REPORTING_USER_EMAIL="" # DECIDIM_AI_SECRET="" # Not required for the AI Request Handler + +DECIDIM_ENABLE_MACHINE_TRANSLATION=true +TRANSLATOR_API_KEY= +TRANSLATOR_HOST=api-free.deepl.com +TRANSLATOR_DELAY=0 From 8146b2e7749561d7de77a26f58ff6e6ebf99526a Mon Sep 17 00:00:00 2001 From: barbara oliveira Date: Fri, 5 Sep 2025 17:40:47 +0200 Subject: [PATCH 02/27] gem: add deepl-rb gem to integrate DeepL translation API --- Gemfile | 1 + Gemfile.lock | 2 ++ 2 files changed, 3 insertions(+) diff --git a/Gemfile b/Gemfile index fa826d191b..472fbfb979 100644 --- a/Gemfile +++ b/Gemfile @@ -11,6 +11,7 @@ gem "decidim-initiatives", github: "decidim/decidim", tag: DECIDIM_TAG gem "decidim-templates", github: "decidim/decidim", tag: DECIDIM_TAG gem "bootsnap", "~> 1.4", require: false +gem "deepl-rb", require: "deepl" gem "puma", ">= 6.3.1" gem "activerecord-postgis-adapter", "~> 8.0", ">= 8.0.3" diff --git a/Gemfile.lock b/Gemfile.lock index 6fa684936d..073d06b45d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -491,6 +491,7 @@ GEM declarative-builder (0.2.0) trailblazer-option (~> 0.1.0) declarative-option (0.1.0) + deepl-rb (3.2.0) deface (1.9.0) actionview (>= 5.2) nokogiri (>= 1.6) @@ -1131,6 +1132,7 @@ DEPENDENCIES decidim-survey_multiple_answers! decidim-templates! decidim-term_customizer! + deepl-rb deface dotenv-rails (~> 2.7) faker (~> 3.2) From 8fe89d53116adfa0843f5f2db811669f9d696dbb Mon Sep 17 00:00:00 2001 From: barbara oliveira Date: Fri, 5 Sep 2025 17:42:45 +0200 Subject: [PATCH 03/27] config secrets: wire translator settings (enabled, api_key, host, delay) --- config/secrets.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/config/secrets.yml b/config/secrets.yml index 2c912b0e0a..a58552c592 100644 --- a/config/secrets.yml +++ b/config/secrets.yml @@ -132,6 +132,11 @@ default: &default <<: *decidim_default participatory_processes: sort_by_date: <%= ENV.fetch("SORT_PROCESSES_BY_DATE", "false") == "true" %> + translator: + enabled: <%= ENV.fetch("TRANSLATOR_ENABLED", "0") == "1" %> + delay: <%= ENV.fetch("TRANSLATOR_DELAY", "0").to_i.seconds %> + api_key: <%= ENV.fetch("TRANSLATOR_API_KEY", "dummy_key") %> + host: <%= ENV.fetch("TRANSLATOR_HOST", "https://api-free.deepl.com") %> sidekiq: concurrency: <%= Decidim::Env.new('SIDEKIQ_CONCURRENCY', '5').to_i %> max_retries: <%= Decidim::Env.new('SIDEKIQ_MAX_RETRIES', '5').to_i %> From 2777556d1cad46f7f239acf10de9502352777afc Mon Sep 17 00:00:00 2001 From: barbara oliveira Date: Fri, 5 Sep 2025 17:45:10 +0200 Subject: [PATCH 04/27] config initializer: configure DeepL gem with API key and host --- config/initializers/deepl.rb | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 config/initializers/deepl.rb diff --git a/config/initializers/deepl.rb b/config/initializers/deepl.rb new file mode 100644 index 0000000000..77020a557d --- /dev/null +++ b/config/initializers/deepl.rb @@ -0,0 +1,7 @@ +# frozen_string_literal: true + +# Configuration du client DeepL (gem deepl-rb) +DeepL.configure do |config| + config.auth_key = Rails.application.secrets.translator[:api_key] + config.host = Rails.application.secrets.translator[:host] +end From bd20ad680e657a03a020e2b9adb00361e6a8fed4 Mon Sep 17 00:00:00 2001 From: barbara oliveira Date: Fri, 5 Sep 2025 17:49:01 +0200 Subject: [PATCH 05/27] feat helper: add TranslatorConfigurationHelper to manage translation activation checks --- .../translator_configuration_helper.rb | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 lib/decidim/translator_configuration_helper.rb diff --git a/lib/decidim/translator_configuration_helper.rb b/lib/decidim/translator_configuration_helper.rb new file mode 100644 index 0000000000..3ba7b0d303 --- /dev/null +++ b/lib/decidim/translator_configuration_helper.rb @@ -0,0 +1,19 @@ +# frozen_string_literal: true + +module Decidim + module TranslatorConfigurationHelper + def self.able_to_seed? + return true unless translator_activated? + + raise "You can't seed the database with machine translations enabled unless you use a compatible backend" unless compatible_backend? + end + + def self.compatible_backend? + Rails.configuration.active_job.queue_adapter != :async + end + + def self.translator_activated? + Decidim.enable_machine_translations + end + end +end From fd04a417278f3180610b0fa436111a0ed72d224a Mon Sep 17 00:00:00 2001 From: barbara oliveira Date: Fri, 5 Sep 2025 17:49:59 +0200 Subject: [PATCH 06/27] config decidim: enable machine translation and set DeepL as translation service --- config/initializers/decidim.rb | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/config/initializers/decidim.rb b/config/initializers/decidim.rb index a75842b136..3109c1cc62 100644 --- a/config/initializers/decidim.rb +++ b/config/initializers/decidim.rb @@ -496,3 +496,14 @@ # Inform Decidim about the assets folder Decidim.register_assets_path File.expand_path("app/packs", Rails.application.root) + +# Machine Translation Configuration +# +# Enable machine translations +if Rails.application.secrets.translator.present? + Decidim.configure do |config| + config.enable_machine_translations = Rails.application.secrets.translator[:enabled] + config.machine_translation_service = "DeeplTranslator" + config.machine_translation_delay = Rails.application.secrets.translator[:delay] + end +end From 52471b24b9bab94bb8f37d5c06f3fcd8faf10b7d Mon Sep 17 00:00:00 2001 From: barbara oliveira Date: Fri, 5 Sep 2025 17:51:51 +0200 Subject: [PATCH 07/27] feat service: implement DeeplTranslator service to call API and save translation --- app/services/deepl_translator.rb | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 app/services/deepl_translator.rb diff --git a/app/services/deepl_translator.rb b/app/services/deepl_translator.rb new file mode 100644 index 0000000000..8d5db994f3 --- /dev/null +++ b/app/services/deepl_translator.rb @@ -0,0 +1,25 @@ +# frozen_string_literal: true + +class DeeplTranslator + attr_reader :text, :source_locale, :target_locale, :resource, :field_name + + def initialize(resource, field_name, text, target_locale, source_locale) + @resource = resource + @field_name = field_name + @text = text + @target_locale = target_locale + @source_locale = source_locale + end + + def translate + translation = DeepL.translate(text, source_locale.to_s.upcase, target_locale.to_s.upcase) + + Decidim::MachineTranslationSaveJob.perform_later( + resource, + field_name, + target_locale, + translation.text + ) + end +end + From 5f51ad0cd9eee0c77b6e3c424fb50351335fc9d4 Mon Sep 17 00:00:00 2001 From: barbara oliveira Date: Fri, 12 Sep 2025 15:31:32 +0200 Subject: [PATCH 08/27] clean by deleted deepl.rb and helper --- config/initializers/decidim.rb | 10 ---------- config/initializers/deepl.rb | 7 ------- config/secrets.yml | 5 ----- .../translator_configuration_helper.rb | 19 ------------------- 4 files changed, 41 deletions(-) delete mode 100644 config/initializers/deepl.rb delete mode 100644 lib/decidim/translator_configuration_helper.rb diff --git a/config/initializers/decidim.rb b/config/initializers/decidim.rb index 3109c1cc62..9ede043138 100644 --- a/config/initializers/decidim.rb +++ b/config/initializers/decidim.rb @@ -497,13 +497,3 @@ # Inform Decidim about the assets folder Decidim.register_assets_path File.expand_path("app/packs", Rails.application.root) -# Machine Translation Configuration -# -# Enable machine translations -if Rails.application.secrets.translator.present? - Decidim.configure do |config| - config.enable_machine_translations = Rails.application.secrets.translator[:enabled] - config.machine_translation_service = "DeeplTranslator" - config.machine_translation_delay = Rails.application.secrets.translator[:delay] - end -end diff --git a/config/initializers/deepl.rb b/config/initializers/deepl.rb deleted file mode 100644 index 77020a557d..0000000000 --- a/config/initializers/deepl.rb +++ /dev/null @@ -1,7 +0,0 @@ -# frozen_string_literal: true - -# Configuration du client DeepL (gem deepl-rb) -DeepL.configure do |config| - config.auth_key = Rails.application.secrets.translator[:api_key] - config.host = Rails.application.secrets.translator[:host] -end diff --git a/config/secrets.yml b/config/secrets.yml index a58552c592..2c912b0e0a 100644 --- a/config/secrets.yml +++ b/config/secrets.yml @@ -132,11 +132,6 @@ default: &default <<: *decidim_default participatory_processes: sort_by_date: <%= ENV.fetch("SORT_PROCESSES_BY_DATE", "false") == "true" %> - translator: - enabled: <%= ENV.fetch("TRANSLATOR_ENABLED", "0") == "1" %> - delay: <%= ENV.fetch("TRANSLATOR_DELAY", "0").to_i.seconds %> - api_key: <%= ENV.fetch("TRANSLATOR_API_KEY", "dummy_key") %> - host: <%= ENV.fetch("TRANSLATOR_HOST", "https://api-free.deepl.com") %> sidekiq: concurrency: <%= Decidim::Env.new('SIDEKIQ_CONCURRENCY', '5').to_i %> max_retries: <%= Decidim::Env.new('SIDEKIQ_MAX_RETRIES', '5').to_i %> diff --git a/lib/decidim/translator_configuration_helper.rb b/lib/decidim/translator_configuration_helper.rb deleted file mode 100644 index 3ba7b0d303..0000000000 --- a/lib/decidim/translator_configuration_helper.rb +++ /dev/null @@ -1,19 +0,0 @@ -# frozen_string_literal: true - -module Decidim - module TranslatorConfigurationHelper - def self.able_to_seed? - return true unless translator_activated? - - raise "You can't seed the database with machine translations enabled unless you use a compatible backend" unless compatible_backend? - end - - def self.compatible_backend? - Rails.configuration.active_job.queue_adapter != :async - end - - def self.translator_activated? - Decidim.enable_machine_translations - end - end -end From 325fd85aff53e8cdb69ba3db5676066873b4337b Mon Sep 17 00:00:00 2001 From: barbara oliveira Date: Fri, 12 Sep 2025 15:59:52 +0200 Subject: [PATCH 09/27] update deepL gem --- Gemfile | 2 +- Gemfile.lock | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile b/Gemfile index 472fbfb979..769d265704 100644 --- a/Gemfile +++ b/Gemfile @@ -11,7 +11,7 @@ gem "decidim-initiatives", github: "decidim/decidim", tag: DECIDIM_TAG gem "decidim-templates", github: "decidim/decidim", tag: DECIDIM_TAG gem "bootsnap", "~> 1.4", require: false -gem "deepl-rb", require: "deepl" +gem "deepl-rb", "~> 3.2" gem "puma", ">= 6.3.1" gem "activerecord-postgis-adapter", "~> 8.0", ">= 8.0.3" diff --git a/Gemfile.lock b/Gemfile.lock index 073d06b45d..4584be2882 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -1132,7 +1132,7 @@ DEPENDENCIES decidim-survey_multiple_answers! decidim-templates! decidim-term_customizer! - deepl-rb + deepl-rb (~> 3.2) deface dotenv-rails (~> 2.7) faker (~> 3.2) From 0967f23d898e6b9f02d11b2f8d82533689ef65ec Mon Sep 17 00:00:00 2001 From: barbara oliveira Date: Fri, 12 Sep 2025 16:02:22 +0200 Subject: [PATCH 10/27] set machine translation in decidim.rb --- config/initializers/decidim.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/config/initializers/decidim.rb b/config/initializers/decidim.rb index 9ede043138..5a989ae990 100644 --- a/config/initializers/decidim.rb +++ b/config/initializers/decidim.rb @@ -335,7 +335,7 @@ # for more information about how it works and how to set it up. # # Enable machine translations - config.enable_machine_translations = false + config.enable_machine_translations = true # # If you want to enable machine translation you can create your own service # to interact with third party service to translate the user content. @@ -360,7 +360,8 @@ # end # end # - config.machine_translation_service = "Decidim::Dev::DummyTranslator" + config.machine_translation_service = "DeeplTranslator" + config.machine_translation_delay = 0.seconds # Defines the social networking services used for social sharing config.social_share_services = Rails.application.secrets.decidim[:social_share_services] From 29ab8a9d61e079b1da035adccc42a7d26592b073 Mon Sep 17 00:00:00 2001 From: barbara oliveira Date: Fri, 12 Sep 2025 16:04:27 +0200 Subject: [PATCH 11/27] update deepl_translator.rb --- app/services/deepl_translator.rb | 12 +++++++++--- config/initializers/decidim.rb | 1 - 2 files changed, 9 insertions(+), 4 deletions(-) diff --git a/app/services/deepl_translator.rb b/app/services/deepl_translator.rb index 8d5db994f3..8169ff112c 100644 --- a/app/services/deepl_translator.rb +++ b/app/services/deepl_translator.rb @@ -1,7 +1,9 @@ # frozen_string_literal: true +require "deepl" + class DeeplTranslator - attr_reader :text, :source_locale, :target_locale, :resource, :field_name + attr_reader :resource, :field_name, :text, :target_locale, :source_locale def initialize(resource, field_name, text, target_locale, source_locale) @resource = resource @@ -12,7 +14,9 @@ def initialize(resource, field_name, text, target_locale, source_locale) end def translate - translation = DeepL.translate(text, source_locale.to_s.upcase, target_locale.to_s.upcase) + return if text.blank? + + translation = ::DeepL.translate text, source_locale, target_locale Decidim::MachineTranslationSaveJob.perform_later( resource, @@ -20,6 +24,8 @@ def translate target_locale, translation.text ) + rescue => e + Rails.logger.error("[DeeplTranslator] #{e.class} - #{e.message}") + nil end end - diff --git a/config/initializers/decidim.rb b/config/initializers/decidim.rb index 5a989ae990..1be3cf11f3 100644 --- a/config/initializers/decidim.rb +++ b/config/initializers/decidim.rb @@ -497,4 +497,3 @@ # Inform Decidim about the assets folder Decidim.register_assets_path File.expand_path("app/packs", Rails.application.root) - From e08cd19f98987011dad81b529b5cf521449ac7cb Mon Sep 17 00:00:00 2001 From: barbara oliveira Date: Fri, 12 Sep 2025 16:05:47 +0200 Subject: [PATCH 12/27] update .env-example --- .env-example | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/.env-example b/.env-example index 9658e90b88..9155589fe1 100644 --- a/.env-example +++ b/.env-example @@ -58,7 +58,9 @@ GEOCODER_UNITS=km # Units for geocoder results (e.g., km or m # DECIDIM_AI_REPORTING_USER_EMAIL="" # DECIDIM_AI_SECRET="" # Not required for the AI Request Handler +# Machine translation DECIDIM_ENABLE_MACHINE_TRANSLATION=true -TRANSLATOR_API_KEY= -TRANSLATOR_HOST=api-free.deepl.com -TRANSLATOR_DELAY=0 +DECIDIM_MACHINE_TRANSLATION_SERVICE=DeeplTranslator +DEEPL_AUTH_KEY=your_deepl_api_key_here +# Optional: delay before enqueuing translation jobs (default: 0.seconds) +DECIDIM_MACHINE_TRANSLATION_DELAY=0 From 3f14d90ba0b08957d6deee76cc12b335bc5a35c6 Mon Sep 17 00:00:00 2001 From: barbara oliveira Date: Fri, 12 Sep 2025 16:08:00 +0200 Subject: [PATCH 13/27] clean --- app/services/deepl_translator.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/deepl_translator.rb b/app/services/deepl_translator.rb index 8169ff112c..a6d8ae1c88 100644 --- a/app/services/deepl_translator.rb +++ b/app/services/deepl_translator.rb @@ -24,7 +24,7 @@ def translate target_locale, translation.text ) - rescue => e + rescue StandardError => e Rails.logger.error("[DeeplTranslator] #{e.class} - #{e.message}") nil end From 754efe4e2ac55b369dfaf5ababacef3571417e8d Mon Sep 17 00:00:00 2001 From: barbara oliveira Date: Mon, 15 Sep 2025 11:44:42 +0200 Subject: [PATCH 14/27] add test for deepL --- spec/services/deepl_translator_spec.rb | 50 ++++++++++++++++++++++++++ 1 file changed, 50 insertions(+) create mode 100644 spec/services/deepl_translator_spec.rb diff --git a/spec/services/deepl_translator_spec.rb b/spec/services/deepl_translator_spec.rb new file mode 100644 index 0000000000..336e094b35 --- /dev/null +++ b/spec/services/deepl_translator_spec.rb @@ -0,0 +1,50 @@ +# frozen_string_literal: true + +require "spec_helper" +require "deepl" + +module Decidim + describe DeeplTranslator do + let(:title) { { en: "New Title" } } + let(:process) { build(:participatory_process, title:) } + let(:target_locale) { "fr" } + let(:source_locale) { "en" } + let(:translation) { double("translation", text: "Nouveau Titre") } + + before do + allow(Decidim).to receive(:machine_translation_service_klass).and_return(DeeplTranslator) + allow(::DeepL).to receive(:translate) + .with(title[source_locale.to_sym], source_locale.upcase, target_locale.upcase) + .and_return(translation) + end + + describe "When fields job is executed" do + before do + clear_enqueued_jobs + end + + it "calls DeeplTranslator to create machine translations" do + expect(DeeplTranslator) + .to receive(:new) + .with( + process, + "title", + process["title"][source_locale], + target_locale, + source_locale + ) + .and_call_original + + process.save + + MachineTranslationFieldsJob.perform_now( + process, + "title", + process["title"][source_locale], + target_locale, + source_locale + ) + end + end + end +end From ab402705b44e6019ed3443242f95693a340229ac Mon Sep 17 00:00:00 2001 From: barbara oliveira Date: Mon, 15 Sep 2025 15:41:13 +0200 Subject: [PATCH 15/27] fix CI by update deepl_translator file --- app/services/deepl_translator.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/services/deepl_translator.rb b/app/services/deepl_translator.rb index a6d8ae1c88..09f5e595b5 100644 --- a/app/services/deepl_translator.rb +++ b/app/services/deepl_translator.rb @@ -16,7 +16,7 @@ def initialize(resource, field_name, text, target_locale, source_locale) def translate return if text.blank? - translation = ::DeepL.translate text, source_locale, target_locale + translation = ::DeepL.translate text, source_locale.to_s.upcase, target_locale.to_s.upcase Decidim::MachineTranslationSaveJob.perform_later( resource, From 5fe90cd1e52e2cfd19e49f3888069e9ebd549569 Mon Sep 17 00:00:00 2001 From: barbara oliveira Date: Mon, 15 Sep 2025 15:41:35 +0200 Subject: [PATCH 16/27] lint --- spec/services/deepl_translator_spec.rb | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/spec/services/deepl_translator_spec.rb b/spec/services/deepl_translator_spec.rb index 336e094b35..98fb79344e 100644 --- a/spec/services/deepl_translator_spec.rb +++ b/spec/services/deepl_translator_spec.rb @@ -13,9 +13,7 @@ module Decidim before do allow(Decidim).to receive(:machine_translation_service_klass).and_return(DeeplTranslator) - allow(::DeepL).to receive(:translate) - .with(title[source_locale.to_sym], source_locale.upcase, target_locale.upcase) - .and_return(translation) + allow(::DeepL).to receive(:translate).with(title[source_locale.to_sym], source_locale.upcase, target_locale.upcase).and_return(translation) end describe "When fields job is executed" do @@ -24,16 +22,13 @@ module Decidim end it "calls DeeplTranslator to create machine translations" do - expect(DeeplTranslator) - .to receive(:new) - .with( - process, - "title", - process["title"][source_locale], - target_locale, - source_locale - ) - .and_call_original + expect(DeeplTranslator).to receive(:new).with( + process, + "title", + process["title"][source_locale], + target_locale, + source_locale + ).and_call_original process.save From ee5104ae080dd1615183bcc37bc6cecec5f676a3 Mon Sep 17 00:00:00 2001 From: barbara oliveira Date: Mon, 15 Sep 2025 16:28:02 +0200 Subject: [PATCH 17/27] clean --- app/services/deepl_translator.rb | 2 +- spec/services/deepl_translator_spec.rb | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/services/deepl_translator.rb b/app/services/deepl_translator.rb index 09f5e595b5..000799fa90 100644 --- a/app/services/deepl_translator.rb +++ b/app/services/deepl_translator.rb @@ -16,7 +16,7 @@ def initialize(resource, field_name, text, target_locale, source_locale) def translate return if text.blank? - translation = ::DeepL.translate text, source_locale.to_s.upcase, target_locale.to_s.upcase + translation = ::DeepL.translate text, source_locale.to_s, target_locale.to_s Decidim::MachineTranslationSaveJob.perform_later( resource, diff --git a/spec/services/deepl_translator_spec.rb b/spec/services/deepl_translator_spec.rb index 98fb79344e..52aaa75803 100644 --- a/spec/services/deepl_translator_spec.rb +++ b/spec/services/deepl_translator_spec.rb @@ -13,7 +13,7 @@ module Decidim before do allow(Decidim).to receive(:machine_translation_service_klass).and_return(DeeplTranslator) - allow(::DeepL).to receive(:translate).with(title[source_locale.to_sym], source_locale.upcase, target_locale.upcase).and_return(translation) + allow(::DeepL).to receive(:translate).with(title[source_locale.to_sym], source_locale, target_locale).and_return(translation) end describe "When fields job is executed" do From c2f4c3947e17f523aef2a4802072cc6564358ee7 Mon Sep 17 00:00:00 2001 From: barbara oliveira Date: Tue, 16 Sep 2025 14:00:52 +0200 Subject: [PATCH 18/27] clean .env-exemple --- .env-example | 4 ---- 1 file changed, 4 deletions(-) diff --git a/.env-example b/.env-example index 9155589fe1..7a0fb0c573 100644 --- a/.env-example +++ b/.env-example @@ -59,8 +59,4 @@ GEOCODER_UNITS=km # Units for geocoder results (e.g., km or m # DECIDIM_AI_SECRET="" # Not required for the AI Request Handler # Machine translation -DECIDIM_ENABLE_MACHINE_TRANSLATION=true -DECIDIM_MACHINE_TRANSLATION_SERVICE=DeeplTranslator DEEPL_AUTH_KEY=your_deepl_api_key_here -# Optional: delay before enqueuing translation jobs (default: 0.seconds) -DECIDIM_MACHINE_TRANSLATION_DELAY=0 From 9294acc0b01e997274350f8f0ff0fad10c92e484 Mon Sep 17 00:00:00 2001 From: barbara oliveira Date: Tue, 16 Sep 2025 14:05:51 +0200 Subject: [PATCH 19/27] add trad key --- config/locales/en.yml | 2 ++ config/locales/fr.yml | 2 ++ 2 files changed, 4 insertions(+) diff --git a/config/locales/en.yml b/config/locales/en.yml index 089cae034d..4f0e434d26 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -6,6 +6,8 @@ en: copy_landing_page_blocks: Copy landing page blocks participatory_process: copy_landing_page_blocks: Copy landing page blocks + organization: + enable_machine_translations: enable machine translations date: formats: order: "%Y-%m-%d" diff --git a/config/locales/fr.yml b/config/locales/fr.yml index 64d0b8997f..51e457d774 100644 --- a/config/locales/fr.yml +++ b/config/locales/fr.yml @@ -4,6 +4,8 @@ fr: attributes: assembly: copy_landing_page_blocks: Copier les blocs de la page d'accueil + organization: + enable_machine_translations: Activer la traduction automatique participatory_process: copy_landing_page_blocks: Copier les blocs de la page d'accueil date: From 3378ee61441f0b062bfc2ac57add27c1e3450c12 Mon Sep 17 00:00:00 2001 From: barbara oliveira Date: Tue, 16 Sep 2025 14:16:59 +0200 Subject: [PATCH 20/27] fix CI --- config/locales/en.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/config/locales/en.yml b/config/locales/en.yml index 4f0e434d26..c086c41926 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -4,10 +4,10 @@ en: attributes: assembly: copy_landing_page_blocks: Copy landing page blocks - participatory_process: - copy_landing_page_blocks: Copy landing page blocks organization: enable_machine_translations: enable machine translations + participatory_process: + copy_landing_page_blocks: Copy landing page blocks date: formats: order: "%Y-%m-%d" From 980210e3a1d9c02b82528e685de7536f5e26d4b3 Mon Sep 17 00:00:00 2001 From: barbara oliveira Date: Fri, 19 Sep 2025 10:28:56 +0200 Subject: [PATCH 21/27] clean by delete old ENV Deepl api key --- config/i18n-tasks.yml | 3 --- 1 file changed, 3 deletions(-) diff --git a/config/i18n-tasks.yml b/config/i18n-tasks.yml index 83c3742c04..9e4b9977d5 100644 --- a/config/i18n-tasks.yml +++ b/config/i18n-tasks.yml @@ -80,9 +80,6 @@ search: # # Get an API key and set billing info at https://code.google.com/apis/console to use Google Translate # api_key: "AbC-dEf5" -translation: - deepl_api_key: <%= ENV["DEEPL_API_KEY"] %> - # Do not consider these keys missing: ignore_missing: - decidim.admin.assembly_copies.new.select From d88a28138636b6814b079649a19ce020a5e0ab55 Mon Sep 17 00:00:00 2001 From: barbara oliveira Date: Fri, 19 Sep 2025 10:29:26 +0200 Subject: [PATCH 22/27] add trad key in ignore_unused part --- config/i18n-tasks.yml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/config/i18n-tasks.yml b/config/i18n-tasks.yml index 9e4b9977d5..3c02440f08 100644 --- a/config/i18n-tasks.yml +++ b/config/i18n-tasks.yml @@ -101,6 +101,8 @@ ignore_missing: # Consider these keys used: ignore_unused: + - activemodel.attributes.organization.enable_machine_translations + - activemodel.attributes.organization.enable_machine_translations - faker.* - decidim.admin.models.assembly.fields.* - decidim.events.proposals.author_confirmation_proposal_event.* From 9cfe340d18e904fe8c55abca2f17efdd9db1450f Mon Sep 17 00:00:00 2001 From: barbara oliveira Date: Fri, 19 Sep 2025 10:34:43 +0200 Subject: [PATCH 23/27] revert --- config/i18n-tasks.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/config/i18n-tasks.yml b/config/i18n-tasks.yml index 3c02440f08..82966551b1 100644 --- a/config/i18n-tasks.yml +++ b/config/i18n-tasks.yml @@ -79,7 +79,8 @@ search: # translation: # # Get an API key and set billing info at https://code.google.com/apis/console to use Google Translate # api_key: "AbC-dEf5" - +translation: + deepl_api_key: <%= ENV["DEEPL_API_KEY"] %> # Do not consider these keys missing: ignore_missing: - decidim.admin.assembly_copies.new.select From 74cd814769f926e33cb97bb8e73a49de14662213 Mon Sep 17 00:00:00 2001 From: barbara oliveira Date: Fri, 19 Sep 2025 14:24:25 +0200 Subject: [PATCH 24/27] add first letter as capital' q ' q exit --- config/locales/en.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/locales/en.yml b/config/locales/en.yml index c086c41926..be34996125 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -5,7 +5,7 @@ en: assembly: copy_landing_page_blocks: Copy landing page blocks organization: - enable_machine_translations: enable machine translations + enable_machine_translations: Enable machine translations participatory_process: copy_landing_page_blocks: Copy landing page blocks date: From f5cad7990660d698a7728d7a211d448f3ac082e3 Mon Sep 17 00:00:00 2001 From: barbara oliveira Date: Fri, 19 Sep 2025 16:40:07 +0200 Subject: [PATCH 25/27] adding a guard clause --- app/services/deepl_translator.rb | 1 + 1 file changed, 1 insertion(+) diff --git a/app/services/deepl_translator.rb b/app/services/deepl_translator.rb index 000799fa90..2775b687e6 100644 --- a/app/services/deepl_translator.rb +++ b/app/services/deepl_translator.rb @@ -17,6 +17,7 @@ def translate return if text.blank? translation = ::DeepL.translate text, source_locale.to_s, target_locale.to_s + return nil if translation.nil? || translation.text.blank? Decidim::MachineTranslationSaveJob.perform_later( resource, From ba1c030fed6e394883d803a136ad5e772cc412e0 Mon Sep 17 00:00:00 2001 From: barbara oliveira Date: Mon, 22 Sep 2025 12:31:05 +0200 Subject: [PATCH 26/27] add more tests --- spec/services/deepl_translator_spec.rb | 27 +++++++++++++++++++++++--- 1 file changed, 24 insertions(+), 3 deletions(-) diff --git a/spec/services/deepl_translator_spec.rb b/spec/services/deepl_translator_spec.rb index 52aaa75803..0f7ae52f27 100644 --- a/spec/services/deepl_translator_spec.rb +++ b/spec/services/deepl_translator_spec.rb @@ -17,9 +17,7 @@ module Decidim end describe "When fields job is executed" do - before do - clear_enqueued_jobs - end + before { clear_enqueued_jobs } it "calls DeeplTranslator to create machine translations" do expect(DeeplTranslator).to receive(:new).with( @@ -41,5 +39,28 @@ module Decidim ) end end + + describe "#translate" do + subject { described_class.new(process, "title", text, target_locale, source_locale).translate } + let(:text) { title[source_locale.to_sym] } + + context "when translation is nil" do + before { allow(::DeepL).to receive(:translate).and_return(nil) } + + it "does not enqueue a job" do + expect(Decidim::MachineTranslationSaveJob).not_to receive(:perform_later) + expect(subject).to be_nil + end + end + + context "when text is blank" do + let(:text) { "" } + + it "does not enqueue a job" do + expect(Decidim::MachineTranslationSaveJob).not_to receive(:perform_later) + expect(subject).to be_nil + end + end + end end end From 783aea0eac5add378ef2011b52a8c0ad4185fd3d Mon Sep 17 00:00:00 2001 From: barbara oliveira Date: Mon, 22 Sep 2025 15:43:57 +0200 Subject: [PATCH 27/27] Add - when DeepL raises an error logs the error and flow does not break - test --- spec/services/deepl_translator_spec.rb | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/spec/services/deepl_translator_spec.rb b/spec/services/deepl_translator_spec.rb index 0f7ae52f27..47fbb11af6 100644 --- a/spec/services/deepl_translator_spec.rb +++ b/spec/services/deepl_translator_spec.rb @@ -41,7 +41,7 @@ module Decidim end describe "#translate" do - subject { described_class.new(process, "title", text, target_locale, source_locale).translate } + subject { DeeplTranslator.new(process, "title", text, target_locale, source_locale).translate } let(:text) { title[source_locale.to_sym] } context "when translation is nil" do @@ -53,7 +53,7 @@ module Decidim end end - context "when text is blank" do + context "when text is empty" do let(:text) { "" } it "does not enqueue a job" do @@ -61,6 +61,15 @@ module Decidim expect(subject).to be_nil end end + + context "when DeepL raises an error" do + before { allow(::DeepL).to receive(:translate).and_raise(StandardError, "API failure") } + + it "logs the error and flow does not break" do + expect(Rails.logger).to receive(:error).with(/\[DeeplTranslator\] StandardError - API failure/) + expect(subject).to be_nil + end + end end end end