From dbdbad1aa4e229a339fc84b45e907fadd6e7e2f3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ivan=20Verg=C3=A9s?= Date: Thu, 1 Feb 2024 14:21:00 +0100 Subject: [PATCH] enforce original locale in amendments --- README.md | 1 + .../concerns/amendments_enforce_locale.rb | 24 ++++++++++++++ config/initializers/gpc_overrides.rb | 3 ++ config/locales/en.yml | 1 + config/secrets.yml | 1 + spec/spec_helper.rb | 4 +-- spec/system/limit_amendments_spec.rb | 33 ++++++++++++++++++- 7 files changed, 64 insertions(+), 3 deletions(-) create mode 100644 app/controllers/concerns/amendments_enforce_locale.rb diff --git a/README.md b/README.md index b578da9f..aa5daf90 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,7 @@ These ENV vars modifies the behavior of the application in some ways: | `PROCESS_POLICY` | If defined, shows a menu directly to the process indicated. Use to be `Policy2021` | | `ASSEMBLY_LEADERSHIP` | If defined, shows a menu directly to that assembly (used when leadership race is on). It also applies some custom design to the assembly children (each being an assembly contestant), particularly, it adds a "donate" button. Used to be `leadership-campaigns` | | `ASSEMBLY_LEADERSHIP_EVENTS` | If defined, redirects the specified assembly to the first published component instead of showing the main info page of the assembly. Used to be `events` | +| `ENFORCE_ORIGINAL_AMENDMENTS_LOCALE` | If defined, when creating an amendment it will enforce users to do it in the same language as the original proposal | | `CONTESTANTS_COMPONENTS` | IDs of components (separated by spaces) that will hold contestants. This applies a special design to the proposals page, removing filters for instance. It also adds a link to "donate" money to this particular candidate. | | `ALWAYS_SHOW_DONATE_BUTTON` | if `true`, all proposals will show a generic donate button in the sidebar | | `TRANSLATOR_API_KEY` | If defined, automatic translations are enabled. We use [DeepL API](https://www.deepl.com/pro-api) service, only api keys from there are valid | diff --git a/app/controllers/concerns/amendments_enforce_locale.rb b/app/controllers/concerns/amendments_enforce_locale.rb new file mode 100644 index 00000000..ed4e4b5f --- /dev/null +++ b/app/controllers/concerns/amendments_enforce_locale.rb @@ -0,0 +1,24 @@ +# frozen_string_literal: true + +module AmendmentsEnforceLocale + extend ActiveSupport::Concern + + included do + # rubocop:disable Rails/LexicallyScopedActionFilter + before_action :enforce_locale, only: [:new, :create] + # rubocop:enable Rails/LexicallyScopedActionFilter + + def enforce_locale + return unless amendable.component.settings.try(:amendments_enabled) + return unless amendable.component.current_settings.try(:amendment_creation_enabled) + return unless Rails.application.secrets.enforce_original_amendments_locale + + amendable_locale = amendable.title.keys.first + return if locale.to_s == amendable_locale + + # flash[:alert] = t("pending_limit_reached", scope: "decidim.decidim_awesome.amendments", emendation: translated_attribute(emendation.title)) + flash[:alert] = t("gpc.amendments.enforced_locale", locale: amendable_locale) + redirect_to new_amend_path(amendable_gid: amendable_gid, locale: amendable.title.keys.first) + end + end +end diff --git a/config/initializers/gpc_overrides.rb b/config/initializers/gpc_overrides.rb index 49ae26a8..4bf3bfbc 100644 --- a/config/initializers/gpc_overrides.rb +++ b/config/initializers/gpc_overrides.rb @@ -11,6 +11,9 @@ # disables inviting external users if enabled Decidim::Meetings::Admin::InvitesController.include(InvitesControllerOverride) + # ensures same language is enforce on amendments to proposals + Decidim::AmendmentsController.include(AmendmentsEnforceLocale) + # sends notifications for answering surveys Decidim::Forms::AnswerQuestionnaire.include(AnswerQuestionnaireOverride) diff --git a/config/locales/en.yml b/config/locales/en.yml index d3a6dcff..1f40bae7 100644 --- a/config/locales/en.yml +++ b/config/locales/en.yml @@ -26,6 +26,7 @@ en: email_not_registered: Sorry, the email %{email} is not registered. Only existing users are allowed to login. gpc: amendments: + enforced_locale: This proposal was originally created in %{locale}. You can only submit amendments in the same language. limit_modal: extra_html: You can also be notified when the current amendment is accepted or rejected by following this proposal (you will receive a notification/email when the amendment is accepted or rejected depending on your notification preferences). campaign_space: "%{name} Campaign" diff --git a/config/secrets.yml b/config/secrets.yml index 0e2691ba..53df4d9a 100644 --- a/config/secrets.yml +++ b/config/secrets.yml @@ -122,6 +122,7 @@ default: &default disable_external_invites: <%= ENV["DISABLE_EXTERNAL_INVITES"] %> questionnaire_notify_emails: <%= Decidim::Env.new("QUESTIONNAIRE_NOTIFY_EMAILS").to_array(separator: ' ').to_json %> always_show_donate_button: <%= Decidim::Env.new("ALWAYS_SHOW_DONATE_BUTTON", true).to_boolean_string %> + enforce_original_amendments_locale: <%= Decidim::Env.new("ENFORCE_ORIGINAL_AMENDMENTS_LOCALE", true).to_boolean_string %> components: contestants: <%= Decidim::Env.new("CONTESTANTS_COMPONENTS").to_array(separator: ' ').map(&:to_i).to_json %> processes: diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index f3f7399a..e0620615 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -96,9 +96,9 @@ config.order = :random config.before do - I18n.available_locales = [:en, :es, :ca] + I18n.available_locales = [:en, :fr, :ca] I18n.default_locale = :en - Decidim.available_locales = [:en, :es, :ca] + Decidim.available_locales = [:en, :fr, :ca] Decidim.default_locale = :en Capybara.server = :puma end diff --git a/spec/system/limit_amendments_spec.rb b/spec/system/limit_amendments_spec.rb index 97eff3e0..89fb122e 100644 --- a/spec/system/limit_amendments_spec.rb +++ b/spec/system/limit_amendments_spec.rb @@ -31,12 +31,13 @@ let(:amendments_enabled) { true } let(:amendment_creation_enabled) { true } let(:logged_user) { user } + let(:enforce_locale) { true } before do + allow(Rails.application.secrets).to receive(:enforce_original_amendments_locale).and_return(enforce_locale) switch_to_host(organization.host) login_as logged_user, scope: :user visit_component - click_link proposal.title["en"] end def visit_component @@ -49,6 +50,7 @@ def amendment_path context "when there's pending amendments" do it "cannot create a new one" do + click_link proposal.title["en"] expect(page).to have_content(proposal.title["en"]) expect(page).to have_content(emendation.title["en"]) click_link "Amend" @@ -65,6 +67,7 @@ def amendment_path let(:logged_user) { creator } it "can be accepted" do + click_link proposal.title["en"] click_link "An emendation for the proposal" click_link "Accept" perform_enqueued_jobs do @@ -84,6 +87,7 @@ def amendment_path end it "can be rejected" do + click_link proposal.title["en"] click_link "An emendation for the proposal" perform_enqueued_jobs do click_link "Reject" @@ -105,7 +109,32 @@ def amendment_path context "when amendments are not limited" do let(:limit_pending_amendments) { false } + context "when proposal original locale is not the users locale" do + let(:proposal) { create :proposal, users: [creator], component: component, title: { fr: "Proposal in french" } } + + it "Enforces the original locale" do + click_link proposal.title["fr"] + click_link "Amend" + + expect(page).not_to have_content("CREATE AMENDMENT DRAFT") + expect(page).to have_content("CRÉER UN PROJET D'AMENDEMENT") + end + + context "and not enforced" do + let(:enforce_locale) { false } + + it "does not enforce the original locale" do + click_link proposal.title["fr"] + click_link "Amend" + + expect(page).to have_content("CREATE AMENDMENT DRAFT") + expect(page).not_to have_content("CRÉER UN PROJET D'AMENDEMENT") + end + end + end + it "can create a new one" do + click_link proposal.title["en"] expect(page).to have_content(proposal.title["en"]) expect(page).to have_content(emendation.title["en"]) click_link "Amend" @@ -119,6 +148,7 @@ def amendment_path let(:logged_user) { creator } it "can be accepted" do + click_link proposal.title["en"] click_link "An emendation for the proposal" click_link "Accept" perform_enqueued_jobs do @@ -133,6 +163,7 @@ def amendment_path end it "can be rejected" do + click_link proposal.title["en"] click_link "An emendation for the proposal" perform_enqueued_jobs do click_link "Reject"