Add a form to edit available locales
We're using different controls depending on the number of available
locales.
When there are only a few locales, the solution is obvious: radio
buttons to select the default language, and checkboxes to select the
available ones are simple and intuitive.
With many languages, showing two consecutive lists of 30 languages could
be confusing, though, particularly on small devices, where scrolling
through both lists could be hard.
So, in this case, we're rendering a <select> to choose the default
language. For selecting the available languages, however, we're sticking
to checkboxes because all the other existing options (like multiple
selects) are hard to use. We think it's OK because the form doesn't have
any additional fields, and there's only one big list of options to
scroll through.
While testing the application, we noticed that if we use the
`admin-fieldset-separator` styles when there's only one fieldset, it's
harder to notice that there's an additional field to select the default
language. So we're only using the `admin-fieldset-separator` styles when
all the fields are grouped in fieldsets.
Regarding the help text for the fieldset, if we leave the help text
outside the <legend> tag, people using screen readers won't hear about
this content. However, if we include it inside the <legend> tag, some
screen readers might read it every time they move to a different
checkbox (or radio button), which can be annoying. Since I don't think
these help messages are really essential, I'm leaving them out of the
<legend> tag. It's also easier to style them if they're outside the
<legend> tag.
Note we're using `display: table` for the labels, for the reasons
mentioned in commit 923c2a7ee.
Also note that, when there's only one available locale, this section is
useless. In this case, we aren't disabling it for now because there's a
chance people see it in the official Consul Democracy demo and then
wonder why it isn't available on their installation. We might disable it
in the future, though.
This commit is contained in:
26
app/assets/stylesheets/admin/locales/form.scss
Normal file
26
app/assets/stylesheets/admin/locales/form.scss
Normal file
@@ -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;
|
||||
}
|
||||
}
|
||||
40
app/components/admin/locales/form_component.html.erb
Normal file
40
app/components/admin/locales/form_component.html.erb
Normal file
@@ -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") %>
|
||||
<p class="help-text"><%= sanitize(t("admin.locales.default_help_text")) %></p>
|
||||
<%= select_tag "default_locale", locales_options %>
|
||||
<% else %>
|
||||
<fieldset>
|
||||
<legend><%= t("admin.locales.default") %></legend>
|
||||
<p class="help-text"><%= sanitize(t("admin.locales.default_help_text")) %></p>
|
||||
|
||||
<div class="collection-radio-buttons">
|
||||
<% 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 %>
|
||||
</div>
|
||||
</fieldset>
|
||||
<% end %>
|
||||
|
||||
<fieldset>
|
||||
<legend><%= t("admin.locales.enabled") %></legend>
|
||||
<p class="help-text"><%= t("admin.locales.enabled_help_text") %></p>
|
||||
|
||||
<div class="collection-check-boxes">
|
||||
<% 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 %>
|
||||
</div>
|
||||
</fieldset>
|
||||
|
||||
<%= submit_tag %>
|
||||
<% end %>
|
||||
30
app/components/admin/locales/form_component.rb
Normal file
30
app/components/admin/locales/form_component.rb
Normal file
@@ -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
|
||||
4
app/components/admin/locales/show_component.html.erb
Normal file
4
app/components/admin/locales/show_component.html.erb
Normal file
@@ -0,0 +1,4 @@
|
||||
<%= header %>
|
||||
<% provide :main_class, "admin-locales-show" %>
|
||||
|
||||
<%= render Admin::Locales::FormComponent.new(locales, default: default) %>
|
||||
13
app/components/admin/locales/show_component.rb
Normal file
13
app/components/admin/locales/show_component.rb
Normal file
@@ -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
|
||||
@@ -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"),
|
||||
|
||||
15
app/controllers/admin/locales_controller.rb
Normal file
15
app/controllers/admin/locales_controller.rb
Normal file
@@ -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
|
||||
1
app/views/admin/locales/show.html.erb
Normal file
1
app/views/admin/locales/show.html.erb
Normal file
@@ -0,0 +1 @@
|
||||
<%= render Admin::Locales::ShowComponent.new(@enabled_locales, default: @default_locale) %>
|
||||
@@ -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 <strong>affect every user</strong> 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
|
||||
|
||||
@@ -710,6 +710,13 @@ es:
|
||||
milestones:
|
||||
index:
|
||||
title: Seguimiento
|
||||
locales:
|
||||
default: Idioma por defecto
|
||||
default_help_text: "Cambiar el idioma por defecto <strong>afectará a todos los usuarios</strong> 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
|
||||
|
||||
@@ -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
|
||||
|
||||
39
spec/components/admin/locales/form_component_spec.rb
Normal file
39
spec/components/admin/locales/form_component_spec.rb
Normal file
@@ -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
|
||||
54
spec/system/admin/locales_spec.rb
Normal file
54
spec/system/admin/locales_spec.rb
Normal file
@@ -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
|
||||
Reference in New Issue
Block a user