diff --git a/app/assets/stylesheets/admin/locales/form.scss b/app/assets/stylesheets/admin/locales/form.scss new file mode 100644 index 000000000..fee54929c --- /dev/null +++ b/app/assets/stylesheets/admin/locales/form.scss @@ -0,0 +1,26 @@ +.admin .locales-form { + label { + display: table; + } + + select { + width: auto; + } + + > select + fieldset, + > fieldset + fieldset { + margin-top: $line-height / 2; + } + + > [type="hidden"] + fieldset, + > fieldset + fieldset { + @include admin-fieldset-separator; + padding-top: calc(#{$line-height} / 4); + } + + [type="submit"] { + @include regular-button; + display: block; + margin-top: $line-height; + } +} diff --git a/app/components/admin/locales/form_component.html.erb b/app/components/admin/locales/form_component.html.erb new file mode 100644 index 000000000..109960c97 --- /dev/null +++ b/app/components/admin/locales/form_component.html.erb @@ -0,0 +1,40 @@ +<%= form_tag admin_locales_path, method: :patch, class: "locales-form" do %> + <% if many_available_locales? %> + <%= label_tag "default_locale", t("admin.locales.default") %> +

<%= sanitize(t("admin.locales.default_help_text")) %>

+ <%= select_tag "default_locale", locales_options %> + <% else %> +
+ <%= t("admin.locales.default") %> +

<%= sanitize(t("admin.locales.default_help_text")) %>

+ +
+ <% available_locales.each do |locale| %> + <%= label_tag "default_locale_#{locale}" do %> + <%= radio_button_tag "default_locale", locale, locale == default %> + <%= name_for_locale(locale) %> + <% end %> + <% end %> +
+
+ <% end %> + +
+ <%= t("admin.locales.enabled") %> +

<%= t("admin.locales.enabled_help_text") %>

+ +
+ <% available_locales.each do |locale| %> + <%= label_tag "enabled_locales_#{locale}" do %> + <%= check_box_tag "enabled_locales[]", + locale, + enabled_locales.include?(locale), + id: "enabled_locales_#{locale}" %> + <%= name_for_locale(locale) %> + <% end %> + <% end %> +
+
+ + <%= submit_tag %> +<% end %> diff --git a/app/components/admin/locales/form_component.rb b/app/components/admin/locales/form_component.rb new file mode 100644 index 000000000..6e96e0b8b --- /dev/null +++ b/app/components/admin/locales/form_component.rb @@ -0,0 +1,30 @@ +class Admin::Locales::FormComponent < ApplicationComponent + attr_reader :enabled_locales, :default + use_helpers :name_for_locale + + def initialize(enabled_locales, default:) + @enabled_locales = enabled_locales + @default = default + end + + private + + def available_locales + I18n.available_locales + end + + def many_available_locales? + available_locales.count > select_field_threshold + end + + def locales_options + options_for_select( + available_locales.map { |locale| [name_for_locale(locale), locale] }, + default + ) + end + + def select_field_threshold + 10 + end +end diff --git a/app/components/admin/locales/show_component.html.erb b/app/components/admin/locales/show_component.html.erb new file mode 100644 index 000000000..399df83cf --- /dev/null +++ b/app/components/admin/locales/show_component.html.erb @@ -0,0 +1,4 @@ +<%= header %> +<% provide :main_class, "admin-locales-show" %> + +<%= render Admin::Locales::FormComponent.new(locales, default: default) %> diff --git a/app/components/admin/locales/show_component.rb b/app/components/admin/locales/show_component.rb new file mode 100644 index 000000000..2625d049f --- /dev/null +++ b/app/components/admin/locales/show_component.rb @@ -0,0 +1,13 @@ +class Admin::Locales::ShowComponent < ApplicationComponent + include Header + attr_reader :locales, :default + + def initialize(locales, default:) + @locales = locales + @default = default + end + + def title + t("admin.menu.locales") + end +end diff --git a/app/components/admin/menu_component.rb b/app/components/admin/menu_component.rb index 480be1b89..2fb97d858 100644 --- a/app/components/admin/menu_component.rb +++ b/app/components/admin/menu_component.rb @@ -54,7 +54,7 @@ class Admin::MenuComponent < ApplicationComponent end def settings? - controllers_names = ["settings", "tenants", "tags", "geozones", "local_census_records", "imports"] + controllers_names = %w[settings tenants tags locales geozones local_census_records imports] controllers_names.include?(controller_name) end @@ -462,6 +462,7 @@ class Admin::MenuComponent < ApplicationComponent settings_link, tenants_link, tags_link, + locales_link, geozones_link, local_census_records_link ) @@ -494,6 +495,14 @@ class Admin::MenuComponent < ApplicationComponent ] end + def locales_link + [ + t("admin.menu.locales"), + admin_locales_path, + controller_name == "locales" + ] + end + def geozones_link [ t("admin.menu.geozones"), diff --git a/app/controllers/admin/locales_controller.rb b/app/controllers/admin/locales_controller.rb new file mode 100644 index 000000000..5d0088393 --- /dev/null +++ b/app/controllers/admin/locales_controller.rb @@ -0,0 +1,15 @@ +class Admin::LocalesController < Admin::BaseController + def show + @enabled_locales = Setting.enabled_locales + @default_locale = Setting.default_locale + end + + def update + Setting.transaction do + Setting["locales.default"] = params["default_locale"] + Setting["locales.enabled"] = [params["default_locale"], *params["enabled_locales"]].join(" ") + end + + redirect_to admin_locales_path, notice: t("admin.locales.update.notice") + end +end diff --git a/app/views/admin/locales/show.html.erb b/app/views/admin/locales/show.html.erb new file mode 100644 index 000000000..bb4561ded --- /dev/null +++ b/app/views/admin/locales/show.html.erb @@ -0,0 +1 @@ +<%= render Admin::Locales::ShowComponent.new(@enabled_locales, default: @default_locale) %> diff --git a/config/locales/en/admin.yml b/config/locales/en/admin.yml index 09d07d33a..736f767fe 100644 --- a/config/locales/en/admin.yml +++ b/config/locales/en/admin.yml @@ -710,6 +710,13 @@ en: milestones: index: title: Following + locales: + default: Default language + default_help_text: "This is the default language of the application, and changing it will affect every user visiting the website for the first time." + enabled: Enabled languages + enabled_help_text: The default language, selected above, will be included automatically. + update: + notice: Languages updated successfully managers: index: title: Managers @@ -732,6 +739,7 @@ en: proposals_topics: Proposals topics budgets: Participatory budgets geozones: Geozones + locales: Languages hidden_comments: Hidden comments hidden_debates: Hidden debates hidden_proposals: Hidden proposals diff --git a/config/locales/es/admin.yml b/config/locales/es/admin.yml index e5d11242c..7c90832be 100644 --- a/config/locales/es/admin.yml +++ b/config/locales/es/admin.yml @@ -710,6 +710,13 @@ es: milestones: index: title: Seguimiento + locales: + default: Idioma por defecto + default_help_text: "Cambiar el idioma por defecto afectará a todos los usuarios que visiten la página por primera vez." + enabled: Idiomas habilitados + enabled_help_text: El idioma por defecto, seleccionado con anterioridad, se habilitará automáticamente. + update: + notice: Idiomas actualizados con éxito managers: index: title: Gestores @@ -732,6 +739,7 @@ es: proposals_topics: Temas de propuestas budgets: Presupuestos participativos geozones: Zonas + locales: Idiomas hidden_comments: Comentarios ocultos hidden_debates: Debates ocultos hidden_proposals: Propuestas ocultas diff --git a/config/routes/admin.rb b/config/routes/admin.rb index 4e72dae01..c38eaf672 100644 --- a/config/routes/admin.rb +++ b/config/routes/admin.rb @@ -242,6 +242,7 @@ namespace :admin do end resources :geozones, only: [:index, :new, :create, :edit, :update, :destroy] + resource :locales, only: [:show, :update] namespace :site_customization do resources :pages, except: [:show] do diff --git a/spec/components/admin/locales/form_component_spec.rb b/spec/components/admin/locales/form_component_spec.rb new file mode 100644 index 000000000..2cb7e4ace --- /dev/null +++ b/spec/components/admin/locales/form_component_spec.rb @@ -0,0 +1,39 @@ +require "rails_helper" + +describe Admin::Locales::FormComponent do + let(:default_locale) { :nl } + let(:enabled_locales) { %i[en nl] } + + let(:component) do + Admin::Locales::FormComponent.new(enabled_locales, default: default_locale) + end + + describe "default language selector" do + before { allow(I18n).to receive(:available_locales).and_return(%i[de en es nl]) } + + it "renders radio buttons when there are only a few locales" do + render_inline component + + page.find(:fieldset, "Default language") do |fieldset| + expect(fieldset).to have_checked_field "Nederlands", type: :radio + expect(fieldset).to have_unchecked_field "English", type: :radio + expect(fieldset).to have_unchecked_field "Español", type: :radio + expect(fieldset).to have_unchecked_field "Deutsch", type: :radio + end + + expect(page).not_to have_select + end + + it "renders a select when there are many locales" do + allow(component).to receive(:select_field_threshold).and_return(3) + + render_inline component + + expect(page).not_to have_field type: :radio + + expect(page).to have_select "Default language", + options: %w[English Español Deutsch Nederlands], + selected: "Nederlands" + end + end +end diff --git a/spec/system/admin/locales_spec.rb b/spec/system/admin/locales_spec.rb new file mode 100644 index 000000000..46b5ee2a2 --- /dev/null +++ b/spec/system/admin/locales_spec.rb @@ -0,0 +1,54 @@ +require "rails_helper" + +describe "Locales management", :admin do + scenario "Navigate to languages page and update them" do + allow(I18n).to receive(:available_locales).and_return(%i[de en es fr]) + Setting["locales.default"] = "en" + Setting["locales.enabled"] = "en de" + + visit admin_root_path + + within ".locale" do + expect(page).to have_css "[aria-current]", exact_text: "English" + + expect(page).to have_link "English" + expect(page).to have_link "Deutsch" + expect(page).not_to have_link "Français" + expect(page).not_to have_link "Español" + end + + within "#admin_menu" do + expect(page).not_to have_link "Languages" + + click_button "Settings" + click_link "Languages" + + expect(page).to have_css "[aria-current]", exact_text: "Languages" + expect(page).to have_link "Languages" + end + + within_fieldset "Default language" do + expect(page).to have_checked_field "English" + + choose "Español" + end + + within_fieldset "Enabled languages" do + uncheck "English" + check "Français" + end + + click_button "Save changes" + + expect(page).to have_content "Languages updated successfully" + + within ".locale" do + expect(page).to have_css "[aria-current]", exact_text: "Español" + + expect(page).to have_link "Français" + expect(page).to have_link "Español" + expect(page).to have_link "Deutsch" + expect(page).not_to have_link "English" + end + end +end