Merge pull request #5243 from consuldemocracy/tenant_locales
Allow different locales per tenant
This commit is contained in:
@@ -574,6 +574,7 @@ RSpec/InstanceVariable:
|
||||
Enabled: true
|
||||
Exclude:
|
||||
- spec/controllers/concerns/has_orders_spec.rb
|
||||
- spec/form_builders/translatable_form_builder_spec.rb
|
||||
|
||||
RSpec/LetBeforeExamples:
|
||||
Enabled: true
|
||||
|
||||
43
app/assets/stylesheets/admin/locales/form.scss
Normal file
43
app/assets/stylesheets/admin/locales/form.scss
Normal file
@@ -0,0 +1,43 @@
|
||||
.admin .locales-form {
|
||||
label {
|
||||
display: table;
|
||||
}
|
||||
|
||||
select {
|
||||
width: auto;
|
||||
}
|
||||
|
||||
.help-text {
|
||||
display: block;
|
||||
}
|
||||
|
||||
> select + fieldset,
|
||||
> fieldset + fieldset {
|
||||
margin-top: $line-height / 2;
|
||||
}
|
||||
|
||||
> [type="hidden"] + fieldset,
|
||||
> fieldset + fieldset {
|
||||
@include admin-fieldset-separator;
|
||||
padding-top: calc(#{$line-height} / 4);
|
||||
}
|
||||
|
||||
.collection-radio-buttons,
|
||||
.collection-check-boxes {
|
||||
column-gap: rem-calc(map-get($grid-column-gutter, medium));
|
||||
column-width: 13rem;
|
||||
max-width: max-content;
|
||||
|
||||
@each $elements in 10, 15, 20, 25, 30 {
|
||||
&:has(label:nth-of-type(#{$elements})) {
|
||||
column-count: calc(#{$elements} / 5);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[type="submit"] {
|
||||
@include regular-button;
|
||||
display: block;
|
||||
margin-top: $line-height;
|
||||
}
|
||||
}
|
||||
39
app/components/admin/locales/form_component.html.erb
Normal file
39
app/components/admin/locales/form_component.html.erb
Normal file
@@ -0,0 +1,39 @@
|
||||
<%= form_for locales_settings, url: admin_locales_path, html: { class: "locales-form" } do |f| %>
|
||||
<% if many_available_locales? %>
|
||||
<%= f.select :default, locales_options, hint: sanitize(t("admin.locales.default_help_text")) %>
|
||||
<% else %>
|
||||
<fieldset>
|
||||
<legend><%= attribute_name(:default) %></legend>
|
||||
<p class="help-text"><%= sanitize(t("admin.locales.default_help_text")) %></p>
|
||||
|
||||
<div class="collection-radio-buttons">
|
||||
<%= f.collection_radio_buttons(
|
||||
:default,
|
||||
available_locales,
|
||||
:to_sym,
|
||||
->(locale) { name_for_locale(locale) }
|
||||
) do |b| %>
|
||||
<%= b.label { b.radio_button + b.text } %>
|
||||
<% end %>
|
||||
</div>
|
||||
</fieldset>
|
||||
<% end %>
|
||||
|
||||
<fieldset>
|
||||
<legend><%= attribute_name(:enabled) %></legend>
|
||||
<p class="help-text"><%= t("admin.locales.enabled_help_text") %></p>
|
||||
|
||||
<div class="collection-check-boxes">
|
||||
<%= f.collection_check_boxes(
|
||||
:enabled,
|
||||
available_locales,
|
||||
:to_sym,
|
||||
->(locale) { name_for_locale(locale) }
|
||||
) do |b| %>
|
||||
<%= b.label { b.check_box + b.text } %>
|
||||
<% 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 :locales_settings
|
||||
use_helpers :name_for_locale
|
||||
|
||||
def initialize(locales_settings)
|
||||
@locales_settings = locales_settings
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def available_locales
|
||||
I18n.available_locales
|
||||
end
|
||||
|
||||
def many_available_locales?
|
||||
available_locales.count > select_field_threshold
|
||||
end
|
||||
|
||||
def locales_options
|
||||
available_locales.map { |locale| [name_for_locale(locale), locale] }
|
||||
end
|
||||
|
||||
def select_field_threshold
|
||||
10
|
||||
end
|
||||
|
||||
def attribute_name(...)
|
||||
locales_settings.class.human_attribute_name(...)
|
||||
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_settings) %>
|
||||
12
app/components/admin/locales/show_component.rb
Normal file
12
app/components/admin/locales/show_component.rb
Normal file
@@ -0,0 +1,12 @@
|
||||
class Admin::Locales::ShowComponent < ApplicationComponent
|
||||
include Header
|
||||
attr_reader :locales_settings
|
||||
|
||||
def initialize(locales_settings)
|
||||
@locales_settings = locales_settings
|
||||
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"),
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<%= form_for [:admin, @content_block], html: { class: "edit_page" } do |f| %>
|
||||
<%= form_for [:admin, content_block], html: { class: "edit_page" } do |f| %>
|
||||
|
||||
<%= render "shared/errors", resource: @content_block %>
|
||||
<%= render "shared/errors", resource: content_block %>
|
||||
|
||||
<div class="small-12 medium-6 column">
|
||||
<%= f.select :name, options_for_select(valid_blocks, @selected_content_block) %>
|
||||
<%= f.select :name, options_for_select(valid_blocks, selected_content_block) %>
|
||||
</div>
|
||||
<div class="small-12 medium-6 column">
|
||||
<%= f.select :locale, I18n.available_locales %>
|
||||
<%= f.select :locale, Setting.enabled_locales %>
|
||||
</div>
|
||||
|
||||
<div class="small-12 column">
|
||||
@@ -0,0 +1,14 @@
|
||||
class Admin::SiteCustomization::ContentBlocks::FormContentBlockComponent < ApplicationComponent
|
||||
attr_reader :content_block
|
||||
use_helpers :valid_blocks
|
||||
|
||||
def initialize(content_block)
|
||||
@content_block = content_block
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def selected_content_block
|
||||
content_block.name
|
||||
end
|
||||
end
|
||||
@@ -1,17 +1,17 @@
|
||||
<%= form_tag(admin_site_customization_update_heading_content_block_path(@content_block.id), method: "put") do %>
|
||||
<%= render "shared/errors", resource: @content_block %>
|
||||
<%= form_tag(admin_site_customization_update_heading_content_block_path(content_block.id), method: "put") do %>
|
||||
<%= render "shared/errors", resource: content_block %>
|
||||
|
||||
<div class="small-12 medium-6 column">
|
||||
<%= label_tag :name %>
|
||||
<%= select_tag :name, options_for_select(valid_blocks, @selected_content_block) %>
|
||||
<%= select_tag :name, options_for_select(valid_blocks, selected_content_block) %>
|
||||
</div>
|
||||
<div class="small-12 medium-6 column">
|
||||
<%= label_tag :locale %>
|
||||
<%= select_tag :locale, options_for_select(I18n.available_locales, @content_block.locale.to_sym) %>
|
||||
<%= select_tag :locale, options_for_select(Setting.enabled_locales, content_block.locale.to_sym) %>
|
||||
</div>
|
||||
<div class="small-12 column">
|
||||
<%= label_tag :body %>
|
||||
<%= text_area_tag :body, @content_block.body, rows: 10 %>
|
||||
<%= text_area_tag :body, content_block.body, rows: 10 %>
|
||||
<div class="small-12 medium-6 large-3">
|
||||
<%= button_tag t("admin.menu.site_customization.buttons.content_block.update"), class: "button success expanded" %>
|
||||
</div>
|
||||
@@ -0,0 +1,14 @@
|
||||
class Admin::SiteCustomization::ContentBlocks::FormHeadingContentBlockComponent < ApplicationComponent
|
||||
attr_reader :content_block
|
||||
use_helpers :valid_blocks
|
||||
|
||||
def initialize(content_block)
|
||||
@content_block = content_block
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def selected_content_block
|
||||
"hcb_#{content_block.heading_id}"
|
||||
end
|
||||
end
|
||||
@@ -1,13 +1,13 @@
|
||||
<%= render "globalize_locales" %>
|
||||
<%= render Shared::GlobalizeLocalesComponent.new %>
|
||||
|
||||
<%= form_tag admin_site_customization_information_texts_path do %>
|
||||
<% I18n.available_locales.each do |l| %>
|
||||
<% enabled_locales.each do |l| %>
|
||||
<%= translation_enabled_tag l, site_customization_enable_translation?(l) %>
|
||||
<% end %>
|
||||
<% contents.each do |group| %>
|
||||
<% group.each do |content| %>
|
||||
<b><%= content.key %></b>
|
||||
<% content.globalize_locales.each do |locale| %>
|
||||
<% (content.globalize_locales & enabled_locales.map(&:to_sym)).each do |locale| %>
|
||||
<%= render Admin::SiteCustomization::InformationTexts::FormFieldComponent.new(content, locale: locale) %>
|
||||
<% end %>
|
||||
<% end %>
|
||||
@@ -0,0 +1,18 @@
|
||||
class Admin::SiteCustomization::InformationTexts::FormComponent < ApplicationComponent
|
||||
attr_reader :contents
|
||||
use_helpers :site_customization_enable_translation?
|
||||
|
||||
def initialize(contents)
|
||||
@contents = contents
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def translation_enabled_tag(locale, enabled)
|
||||
hidden_field_tag("enabled_translations[#{locale}]", (enabled ? 1 : 0))
|
||||
end
|
||||
|
||||
def enabled_locales
|
||||
Setting.enabled_locales
|
||||
end
|
||||
end
|
||||
@@ -4,6 +4,6 @@
|
||||
text,
|
||||
rows: 5,
|
||||
class: "js-globalize-attribute",
|
||||
style: site_customization_display_translation_style(locale),
|
||||
style: site_customization_display_translation_style,
|
||||
data: { locale: locale } %>
|
||||
<% end %>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
class Admin::SiteCustomization::InformationTexts::FormFieldComponent < ApplicationComponent
|
||||
attr_reader :i18n_content, :locale
|
||||
use_helpers :globalize, :site_customization_display_translation_style
|
||||
use_helpers :globalize, :site_customization_enable_translation?
|
||||
|
||||
def initialize(i18n_content, locale:)
|
||||
@i18n_content = i18n_content
|
||||
@@ -22,4 +22,8 @@ class Admin::SiteCustomization::InformationTexts::FormFieldComponent < Applicati
|
||||
def i18n_text
|
||||
I18n.translate(i18n_content.key, locale: locale)
|
||||
end
|
||||
|
||||
def site_customization_display_translation_style
|
||||
site_customization_enable_translation?(locale) ? "" : "display: none;"
|
||||
end
|
||||
end
|
||||
|
||||
@@ -12,7 +12,7 @@ class Layout::LocaleSwitcherComponent < ApplicationComponent
|
||||
end
|
||||
|
||||
def locales
|
||||
I18n.available_locales
|
||||
Setting.enabled_locales
|
||||
end
|
||||
|
||||
def label
|
||||
|
||||
@@ -3,19 +3,19 @@
|
||||
<span class="small">
|
||||
<strong class="js-languages-description"
|
||||
data-texts="<%= t("shared.translations.languages_in_use").to_json %>">
|
||||
<%= selected_languages_description(resource) %>
|
||||
<%= selected_languages_description %>
|
||||
</strong>
|
||||
</span>
|
||||
<%= select_tag :select_language,
|
||||
options_for_select_language(resource),
|
||||
options_for_select_language,
|
||||
prompt: t("shared.translations.select_language_prompt"),
|
||||
class: "js-select-language" %>
|
||||
<%= select_language_error(resource) %>
|
||||
<%= select_language_error %>
|
||||
<div class="margin-bottom">
|
||||
<% if manage_languages %>
|
||||
<% I18n.available_locales.each do |locale| %>
|
||||
<% Setting.enabled_locales.each do |locale| %>
|
||||
<%= link_to t("shared.translations.remove_language"), "#",
|
||||
style: display_destroy_locale_style(resource, locale),
|
||||
style: display_destroy_locale_style(locale),
|
||||
class: "delete js-delete-language js-delete-#{locale}",
|
||||
data: { locale: locale } %>
|
||||
<% end %>
|
||||
95
app/components/shared/globalize_locales_component.rb
Normal file
95
app/components/shared/globalize_locales_component.rb
Normal file
@@ -0,0 +1,95 @@
|
||||
class Shared::GlobalizeLocalesComponent < ApplicationComponent
|
||||
attr_reader :resource, :manage_languages
|
||||
use_helpers :first_translation, :first_marked_for_destruction_translation,
|
||||
:enabled_locale?, :name_for_locale, :highlight_translation_html_class
|
||||
|
||||
def initialize(resource = nil, manage_languages: true)
|
||||
@resource = resource
|
||||
@manage_languages = manage_languages
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def options_for_select_language
|
||||
options_for_select(available_locales, selected_locale)
|
||||
end
|
||||
|
||||
def available_locales
|
||||
Setting.enabled_locales.select { |locale| enabled_locale?(resource, locale) }.map do |locale|
|
||||
[name_for_locale(locale), locale, { data: { locale: locale }}]
|
||||
end
|
||||
end
|
||||
|
||||
def selected_locale
|
||||
return first_i18n_content_locale if resource.blank?
|
||||
|
||||
if resource.locales_not_marked_for_destruction.any?
|
||||
first_translation(resource)
|
||||
elsif resource.locales_persisted_and_marked_for_destruction.any?
|
||||
first_marked_for_destruction_translation(resource)
|
||||
else
|
||||
I18n.locale
|
||||
end
|
||||
end
|
||||
|
||||
def first_i18n_content_locale
|
||||
if i18n_content_locales.empty? || i18n_content_locales.include?(I18n.locale)
|
||||
I18n.locale
|
||||
else
|
||||
i18n_content_locales.first
|
||||
end
|
||||
end
|
||||
|
||||
def selected_languages_description
|
||||
sanitize(t("shared.translations.languages_in_use", count: active_locales_count))
|
||||
end
|
||||
|
||||
def select_language_error
|
||||
return if resource.blank?
|
||||
|
||||
current_translation = resource.translation_for(selected_locale)
|
||||
if current_translation.errors.added? :base, :translations_too_short
|
||||
tag.div class: "small error" do
|
||||
current_translation.errors[:base].join(", ")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def active_locales_count
|
||||
if active_locales.size > 0
|
||||
active_locales.size
|
||||
else
|
||||
1
|
||||
end
|
||||
end
|
||||
|
||||
def active_locales
|
||||
if resource.present?
|
||||
resource.locales_not_marked_for_destruction
|
||||
else
|
||||
i18n_content_locales
|
||||
end
|
||||
end
|
||||
|
||||
def display_destroy_locale_style(locale)
|
||||
"display: none;" unless display_destroy_locale_link?(locale)
|
||||
end
|
||||
|
||||
def display_destroy_locale_link?(locale)
|
||||
selected_locale == locale
|
||||
end
|
||||
|
||||
def options_for_add_language
|
||||
options_for_select(all_language_options, nil)
|
||||
end
|
||||
|
||||
def all_language_options
|
||||
Setting.enabled_locales.map do |locale|
|
||||
[name_for_locale(locale), locale]
|
||||
end
|
||||
end
|
||||
|
||||
def i18n_content_locales
|
||||
I18nContentTranslation.existing_locales
|
||||
end
|
||||
end
|
||||
27
app/controllers/admin/locales_controller.rb
Normal file
27
app/controllers/admin/locales_controller.rb
Normal file
@@ -0,0 +1,27 @@
|
||||
class Admin::LocalesController < Admin::BaseController
|
||||
before_action :set_locales_settings
|
||||
authorize_resource :locales_settings
|
||||
|
||||
def show
|
||||
end
|
||||
|
||||
def update
|
||||
@locales_settings.update!(locales_settings_params)
|
||||
|
||||
redirect_to admin_locales_path, notice: t("admin.locales.update.notice")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def locales_settings_params
|
||||
params.require(:setting_locales_settings).permit(allowed_params)
|
||||
end
|
||||
|
||||
def allowed_params
|
||||
[:default, enabled: []]
|
||||
end
|
||||
|
||||
def set_locales_settings
|
||||
@locales_settings = Setting::LocalesSettings.new
|
||||
end
|
||||
end
|
||||
@@ -11,6 +11,9 @@ class Admin::SiteCustomization::ContentBlocksController < Admin::SiteCustomizati
|
||||
@headings_content_blocks = Budget::ContentBlock.all
|
||||
end
|
||||
|
||||
def new
|
||||
end
|
||||
|
||||
def create
|
||||
if is_heading_content_block?(@content_block.name)
|
||||
heading_content_block = new_heading_content_block
|
||||
@@ -31,11 +34,6 @@ class Admin::SiteCustomization::ContentBlocksController < Admin::SiteCustomizati
|
||||
end
|
||||
|
||||
def edit
|
||||
if @content_block.is_a? SiteCustomization::ContentBlock
|
||||
@selected_content_block = @content_block.name
|
||||
else
|
||||
@selected_content_block = "hcb_#{@content_block.heading_id}"
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
@@ -72,11 +70,6 @@ class Admin::SiteCustomization::ContentBlocksController < Admin::SiteCustomizati
|
||||
|
||||
def edit_heading_content_block
|
||||
@content_block = Budget::ContentBlock.find(params[:id])
|
||||
if @content_block.is_a? Budget::ContentBlock
|
||||
@selected_content_block = "hcb_#{@content_block.heading_id}"
|
||||
else
|
||||
@selected_content_block = @content_block.name
|
||||
end
|
||||
@is_heading_content_block = true
|
||||
render :edit
|
||||
end
|
||||
|
||||
@@ -46,17 +46,17 @@ class ApplicationController < ActionController::Base
|
||||
current_user.update(locale: locale)
|
||||
end
|
||||
|
||||
session[:locale] = locale
|
||||
session[:locale] = locale.to_s
|
||||
I18n.with_locale(locale, &action)
|
||||
end
|
||||
|
||||
def current_locale
|
||||
if I18n.available_locales.include?(params[:locale]&.to_sym)
|
||||
if Setting.enabled_locales.include?(params[:locale]&.to_sym)
|
||||
params[:locale]
|
||||
elsif I18n.available_locales.include?(session[:locale]&.to_sym)
|
||||
elsif Setting.enabled_locales.include?(session[:locale]&.to_sym)
|
||||
session[:locale]
|
||||
else
|
||||
I18n.default_locale
|
||||
Setting.default_locale
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
@@ -40,11 +40,11 @@ class Management::BaseController < ActionController::Base
|
||||
end
|
||||
|
||||
def switch_locale(&action)
|
||||
if params[:locale] && I18n.available_locales.include?(params[:locale].to_sym)
|
||||
session[:locale] = params[:locale]
|
||||
if params[:locale] && Setting.enabled_locales.include?(params[:locale].to_sym)
|
||||
session[:locale] = params[:locale].to_s
|
||||
end
|
||||
|
||||
session[:locale] ||= I18n.default_locale
|
||||
session[:locale] ||= Setting.default_locale.to_s
|
||||
|
||||
I18n.with_locale(session[:locale], &action)
|
||||
end
|
||||
|
||||
@@ -32,8 +32,12 @@ class SubscriptionsController < ApplicationController
|
||||
|
||||
def set_user_locale(&action)
|
||||
if params[:locale].blank?
|
||||
session[:locale] = I18n.available_locales.find { |locale| locale == @user.locale&.to_sym }
|
||||
session[:locale] = find_locale.to_s
|
||||
end
|
||||
I18n.with_locale(session[:locale], &action)
|
||||
end
|
||||
|
||||
def find_locale
|
||||
Setting.enabled_locales.find { |locale| locale == @user.locale&.to_sym } || I18n.locale
|
||||
end
|
||||
end
|
||||
|
||||
0
app/form_builders/custom/.keep
Normal file
0
app/form_builders/custom/.keep
Normal file
71
app/form_builders/translatable_form_builder.rb
Normal file
71
app/form_builders/translatable_form_builder.rb
Normal file
@@ -0,0 +1,71 @@
|
||||
class TranslatableFormBuilder < ConsulFormBuilder
|
||||
attr_accessor :translations
|
||||
|
||||
def translatable_fields(&)
|
||||
@translations = {}
|
||||
visible_locales.map do |locale|
|
||||
@translations[locale] = translation_for(locale)
|
||||
end
|
||||
safe_join(visible_locales.map do |locale|
|
||||
Globalize.with_locale(locale) { fields_for_locale(locale, &) }
|
||||
end)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def fields_for_locale(locale)
|
||||
fields_for_translation(@translations[locale]) do |translations_form|
|
||||
@template.tag.div(**translations_options(translations_form.object, locale)) do
|
||||
@template.concat translations_form.hidden_field(
|
||||
:_destroy,
|
||||
value: !@template.enabled_locale?(translations_form.object.globalized_model, locale),
|
||||
data: { locale: locale }
|
||||
)
|
||||
|
||||
@template.concat translations_form.hidden_field(:locale, value: locale)
|
||||
|
||||
yield translations_form
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def fields_for_translation(translation, &)
|
||||
fields_for(:translations, translation, builder: TranslationsFieldsFormBuilder, &)
|
||||
end
|
||||
|
||||
def translation_for(locale)
|
||||
existing_translation_for(locale) || new_translation_for(locale)
|
||||
end
|
||||
|
||||
def existing_translation_for(locale)
|
||||
@object.translations.find { |translation| translation.locale == locale }
|
||||
end
|
||||
|
||||
def new_translation_for(locale)
|
||||
@object.translations.new(locale: locale).tap(&:mark_for_destruction)
|
||||
end
|
||||
|
||||
def highlight_translation_html_class
|
||||
@template.highlight_translation_html_class
|
||||
end
|
||||
|
||||
def translations_options(resource, locale)
|
||||
{
|
||||
class: "translatable-fields js-globalize-attribute #{highlight_translation_html_class}",
|
||||
style: @template.display_translation_style(resource.globalized_model, locale),
|
||||
data: { locale: locale }
|
||||
}
|
||||
end
|
||||
|
||||
def no_other_translations?(translation)
|
||||
(@object.translations - [translation]).reject(&:_destroy).empty?
|
||||
end
|
||||
|
||||
def visible_locales
|
||||
if @template.translations_interface_enabled?
|
||||
Setting.enabled_locales & @object.globalize_locales
|
||||
else
|
||||
[I18n.locale]
|
||||
end
|
||||
end
|
||||
end
|
||||
5
app/form_builders/translations_fields_form_builder.rb
Normal file
5
app/form_builders/translations_fields_form_builder.rb
Normal file
@@ -0,0 +1,5 @@
|
||||
class TranslationsFieldsFormBuilder < ConsulFormBuilder
|
||||
def locale
|
||||
@object.locale
|
||||
end
|
||||
end
|
||||
@@ -46,8 +46,8 @@ module ApplicationHelper
|
||||
end
|
||||
end
|
||||
|
||||
def content_block(name, locale = I18n.locale)
|
||||
SiteCustomization::ContentBlock.block_for(name, locale)
|
||||
def content_block(...)
|
||||
SiteCustomization::ContentBlock.block_for(...)
|
||||
end
|
||||
|
||||
def self.asset_data_base64(path)
|
||||
|
||||
@@ -1,14 +1,4 @@
|
||||
module GlobalizeHelper
|
||||
def options_for_select_language(resource)
|
||||
options_for_select(available_locales(resource), selected_locale(resource))
|
||||
end
|
||||
|
||||
def available_locales(resource)
|
||||
I18n.available_locales.select { |locale| enabled_locale?(resource, locale) }.map do |locale|
|
||||
[name_for_locale(locale), locale, { data: { locale: locale }}]
|
||||
end
|
||||
end
|
||||
|
||||
def enabled_locale?(resource, locale)
|
||||
return site_customization_enable_translation?(locale) if resource.blank?
|
||||
|
||||
@@ -21,27 +11,6 @@ module GlobalizeHelper
|
||||
end
|
||||
end
|
||||
|
||||
def selected_locale(resource)
|
||||
return first_i18n_content_translation_locale if resource.blank?
|
||||
|
||||
if resource.locales_not_marked_for_destruction.any?
|
||||
first_translation(resource)
|
||||
elsif resource.locales_persisted_and_marked_for_destruction.any?
|
||||
first_marked_for_destruction_translation(resource)
|
||||
else
|
||||
I18n.locale
|
||||
end
|
||||
end
|
||||
|
||||
def first_i18n_content_translation_locale
|
||||
if I18nContentTranslation.existing_languages.count == 0 ||
|
||||
I18nContentTranslation.existing_languages.include?(I18n.locale)
|
||||
I18n.locale
|
||||
else
|
||||
I18nContentTranslation.existing_languages.first
|
||||
end
|
||||
end
|
||||
|
||||
def first_translation(resource)
|
||||
if resource.locales_not_marked_for_destruction.include? I18n.locale
|
||||
I18n.locale
|
||||
@@ -58,40 +27,6 @@ module GlobalizeHelper
|
||||
end
|
||||
end
|
||||
|
||||
def translations_for_locale?(resource)
|
||||
resource.locales_not_marked_for_destruction.any?
|
||||
end
|
||||
|
||||
def selected_languages_description(resource)
|
||||
sanitize(t("shared.translations.languages_in_use", count: active_languages_count(resource)))
|
||||
end
|
||||
|
||||
def select_language_error(resource)
|
||||
return if resource.blank?
|
||||
|
||||
current_translation = resource.translation_for(selected_locale(resource))
|
||||
if current_translation.errors.added? :base, :translations_too_short
|
||||
tag.div class: "small error" do
|
||||
current_translation.errors[:base].join(", ")
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def active_languages_count(resource)
|
||||
if resource.blank?
|
||||
no_resource_languages_count
|
||||
elsif resource.locales_not_marked_for_destruction.size > 0
|
||||
resource.locales_not_marked_for_destruction.size
|
||||
else
|
||||
1
|
||||
end
|
||||
end
|
||||
|
||||
def no_resource_languages_count
|
||||
count = I18nContentTranslation.existing_languages.count
|
||||
count > 0 ? count : 1
|
||||
end
|
||||
|
||||
def display_translation_style(resource, locale)
|
||||
"display: none;" unless display_translation?(resource, locale)
|
||||
end
|
||||
@@ -108,28 +43,6 @@ module GlobalizeHelper
|
||||
end
|
||||
end
|
||||
|
||||
def display_destroy_locale_style(resource, locale)
|
||||
"display: none;" unless display_destroy_locale_link?(resource, locale)
|
||||
end
|
||||
|
||||
def display_destroy_locale_link?(resource, locale)
|
||||
selected_locale(resource) == locale
|
||||
end
|
||||
|
||||
def options_for_add_language
|
||||
options_for_select(all_language_options, nil)
|
||||
end
|
||||
|
||||
def all_language_options
|
||||
I18n.available_locales.map do |locale|
|
||||
[name_for_locale(locale), locale]
|
||||
end
|
||||
end
|
||||
|
||||
def translation_enabled_tag(locale, enabled)
|
||||
hidden_field_tag("enabled_translations[#{locale}]", (enabled ? 1 : 0))
|
||||
end
|
||||
|
||||
def globalize(locale, &)
|
||||
Globalize.with_locale(locale, &)
|
||||
end
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
module SiteCustomizationHelper
|
||||
def site_customization_enable_translation?(locale)
|
||||
I18nContentTranslation.existing_languages.include?(locale) || locale == I18n.locale
|
||||
end
|
||||
|
||||
def site_customization_display_translation_style(locale)
|
||||
site_customization_enable_translation?(locale) ? "" : "display: none;"
|
||||
I18nContentTranslation.existing_locales.include?(locale) || locale == I18n.locale
|
||||
end
|
||||
|
||||
def information_texts_tabs
|
||||
|
||||
@@ -14,82 +14,4 @@ module TranslatableFormHelper
|
||||
def highlight_translation_html_class
|
||||
"highlight" if translations_interface_enabled?
|
||||
end
|
||||
|
||||
class TranslatableFormBuilder < ConsulFormBuilder
|
||||
attr_accessor :translations
|
||||
|
||||
def translatable_fields(&)
|
||||
@translations = {}
|
||||
visible_locales.map do |locale|
|
||||
@translations[locale] = translation_for(locale)
|
||||
end
|
||||
safe_join(visible_locales.map do |locale|
|
||||
Globalize.with_locale(locale) { fields_for_locale(locale, &) }
|
||||
end)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def fields_for_locale(locale)
|
||||
fields_for_translation(@translations[locale]) do |translations_form|
|
||||
@template.tag.div **translations_options(translations_form.object, locale) do
|
||||
@template.concat translations_form.hidden_field(
|
||||
:_destroy,
|
||||
value: !@template.enabled_locale?(translations_form.object.globalized_model, locale),
|
||||
data: { locale: locale }
|
||||
)
|
||||
|
||||
@template.concat translations_form.hidden_field(:locale, value: locale)
|
||||
|
||||
yield translations_form
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
def fields_for_translation(translation, &)
|
||||
fields_for(:translations, translation, builder: TranslationsFieldsBuilder, &)
|
||||
end
|
||||
|
||||
def translation_for(locale)
|
||||
existing_translation_for(locale) || new_translation_for(locale)
|
||||
end
|
||||
|
||||
def existing_translation_for(locale)
|
||||
@object.translations.find { |translation| translation.locale == locale }
|
||||
end
|
||||
|
||||
def new_translation_for(locale)
|
||||
@object.translations.new(locale: locale).tap(&:mark_for_destruction)
|
||||
end
|
||||
|
||||
def highlight_translation_html_class
|
||||
@template.highlight_translation_html_class
|
||||
end
|
||||
|
||||
def translations_options(resource, locale)
|
||||
{
|
||||
class: "translatable-fields js-globalize-attribute #{highlight_translation_html_class}",
|
||||
style: @template.display_translation_style(resource.globalized_model, locale),
|
||||
data: { locale: locale }
|
||||
}
|
||||
end
|
||||
|
||||
def no_other_translations?(translation)
|
||||
(@object.translations - [translation]).reject(&:_destroy).empty?
|
||||
end
|
||||
|
||||
def visible_locales
|
||||
if @template.translations_interface_enabled?
|
||||
@object.globalize_locales
|
||||
else
|
||||
[I18n.locale]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
class TranslationsFieldsBuilder < ConsulFormBuilder
|
||||
def locale
|
||||
@object.locale
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -37,7 +37,7 @@ module SearchDictionarySelector
|
||||
private
|
||||
|
||||
def find_from_i18n_default
|
||||
key_to_lookup = I18n.default_locale.to_s.split("-").first.to_sym
|
||||
key_to_lookup = Setting.default_locale.to_s.split("-").first.to_sym
|
||||
|
||||
dictionary = I18N_TO_DICTIONARY[key_to_lookup]
|
||||
dictionary ||= "simple"
|
||||
|
||||
@@ -76,7 +76,7 @@ class Mailer < ApplicationMailer
|
||||
def user_invite(email)
|
||||
@email_to = email
|
||||
|
||||
I18n.with_locale(I18n.default_locale) do
|
||||
I18n.with_locale(Setting.default_locale) do
|
||||
mail(to: @email_to, subject: t("mailers.user_invite.subject", org_name: Setting["org_name"]))
|
||||
end
|
||||
end
|
||||
|
||||
@@ -134,6 +134,8 @@ module Abilities
|
||||
can [:deliver], Newsletter, hidden_at: nil
|
||||
can [:manage], Dashboard::AdministratorTask
|
||||
|
||||
can :manage, Setting::LocalesSettings
|
||||
|
||||
can :manage, LocalCensusRecord
|
||||
can [:create, :read], LocalCensusRecords::Import
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
class Budget
|
||||
class ContentBlock < ApplicationRecord
|
||||
validates :locale, presence: true, inclusion: { in: I18n.available_locales.map(&:to_s) }
|
||||
validates :locale, presence: true, inclusion: { in: ->(*) { Setting.enabled_locales.map(&:to_s) }}
|
||||
validates :heading, presence: true, uniqueness: { scope: :locale }
|
||||
|
||||
belongs_to :heading
|
||||
|
||||
@@ -13,10 +13,6 @@ module Globalizable
|
||||
translations.reject(&:marked_for_destruction?).map(&:locale)
|
||||
end
|
||||
|
||||
def locales_marked_for_destruction
|
||||
I18n.available_locales - locales_not_marked_for_destruction
|
||||
end
|
||||
|
||||
def locales_persisted_and_marked_for_destruction
|
||||
translations.select { |t| t.persisted? && t.marked_for_destruction? }.map(&:locale)
|
||||
end
|
||||
@@ -86,7 +82,7 @@ module Globalizable
|
||||
translation_class.instance_eval do
|
||||
validates method,
|
||||
length: options[:length],
|
||||
if: lambda { |translation| translation.locale == I18n.default_locale }
|
||||
if: lambda { |translation| translation.locale == Setting.default_locale }
|
||||
end
|
||||
if options.count > 1
|
||||
translation_class.instance_eval do
|
||||
|
||||
@@ -119,7 +119,7 @@ class I18nContent < ApplicationRecord
|
||||
end
|
||||
end
|
||||
|
||||
def self.update(contents, enabled_translations = I18n.available_locales)
|
||||
def self.update(contents, enabled_translations = Setting.enabled_locales)
|
||||
contents.each do |content|
|
||||
values = content[:values].slice(*translation_params(enabled_translations))
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
class I18nContentTranslation < ApplicationRecord
|
||||
def self.existing_languages
|
||||
self.select(:locale).distinct.map { |l| l.locale.to_sym }.to_a
|
||||
def self.existing_locales
|
||||
distinct.pluck(:locale).map(&:to_sym)
|
||||
end
|
||||
end
|
||||
|
||||
@@ -95,6 +95,8 @@ class Setting < ApplicationRecord
|
||||
"html.per_page_code_body": "",
|
||||
# Code to be included at the top (inside <head>) of every page (useful for tracking)
|
||||
"html.per_page_code_head": "",
|
||||
"locales.enabled": nil,
|
||||
"locales.default": nil,
|
||||
"map.latitude": 51.48,
|
||||
"map.longitude": 0.0,
|
||||
"map.zoom": 10,
|
||||
@@ -219,5 +221,20 @@ class Setting < ApplicationRecord
|
||||
def archived_proposals_date_limit
|
||||
Setting["months_to_archive_proposals"].to_i.months.ago
|
||||
end
|
||||
|
||||
def enabled_locales
|
||||
locales = Setting["locales.enabled"].to_s.split.map(&:to_sym)
|
||||
|
||||
[
|
||||
default_locale,
|
||||
*((locales & I18n.available_locales).presence || I18n.available_locales)
|
||||
].uniq
|
||||
end
|
||||
|
||||
def default_locale
|
||||
locale = Setting["locales.default"].to_s.strip.to_sym
|
||||
|
||||
([locale] & I18n.available_locales).first || I18n.default_locale
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
23
app/models/setting/locales_settings.rb
Normal file
23
app/models/setting/locales_settings.rb
Normal file
@@ -0,0 +1,23 @@
|
||||
class Setting
|
||||
class LocalesSettings
|
||||
include ActiveModel::Model
|
||||
include ActiveModel::Attributes
|
||||
|
||||
attribute :enabled, array: true, default: -> { Setting.enabled_locales }
|
||||
attribute :default, default: -> { Setting.default_locale }
|
||||
|
||||
def persisted?
|
||||
true
|
||||
end
|
||||
|
||||
def update(attributes)
|
||||
assign_attributes(attributes)
|
||||
|
||||
Setting.transaction do
|
||||
Setting["locales.default"] = default
|
||||
Setting["locales.enabled"] = [default, *enabled].join(" ")
|
||||
end
|
||||
end
|
||||
alias_method :update!, :update
|
||||
end
|
||||
end
|
||||
@@ -1,11 +1,10 @@
|
||||
class SiteCustomization::ContentBlock < ApplicationRecord
|
||||
VALID_BLOCKS = %w[top_links footer footer_legal subnavigation_left subnavigation_right].freeze
|
||||
|
||||
validates :locale, presence: true, inclusion: { in: I18n.available_locales.map(&:to_s) }
|
||||
validates :locale, presence: true, inclusion: { in: ->(*) { Setting.enabled_locales.map(&:to_s) }}
|
||||
validates :name, presence: true, uniqueness: { scope: :locale }, inclusion: { in: ->(*) { VALID_BLOCKS }}
|
||||
|
||||
def self.block_for(name, locale)
|
||||
locale ||= I18n.default_locale
|
||||
def self.block_for(name, locale = I18n.locale)
|
||||
find_by(name: name, locale: locale)&.body
|
||||
end
|
||||
end
|
||||
|
||||
@@ -339,7 +339,7 @@ class User < ApplicationRecord
|
||||
end
|
||||
|
||||
def locale
|
||||
self[:locale] || I18n.default_locale.to_s
|
||||
self[:locale] || Setting.default_locale.to_s
|
||||
end
|
||||
|
||||
def confirmation_required?
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
<%= render "shared/globalize_locales",
|
||||
resource: @process,
|
||||
display_style: lambda { |locale| enable_translation_style(@process, locale) },
|
||||
manage_languages: false %>
|
||||
<%= render "shared/globalize_locales", resource: @process, manage_languages: false %>
|
||||
|
||||
<%= translatable_form_for [:admin, @process], url: url do |f| %>
|
||||
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
<%= render "shared/globalize_locales",
|
||||
resource: @process,
|
||||
display_style: lambda { |locale| enable_translation_style(@process, locale) },
|
||||
manage_languages: false %>
|
||||
<%= render "shared/globalize_locales", resource: @process, manage_languages: false %>
|
||||
|
||||
<%= translatable_form_for [:admin, @process] do |f| %>
|
||||
<div class="row">
|
||||
|
||||
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(@locales_settings) %>
|
||||
@@ -1,5 +1,5 @@
|
||||
<% if @is_heading_content_block %>
|
||||
<%= render "form_heading_content_block" %>
|
||||
<%= render Admin::SiteCustomization::ContentBlocks::FormHeadingContentBlockComponent.new(@content_block) %>
|
||||
<% else %>
|
||||
<%= render "form_content_block" %>
|
||||
<%= render Admin::SiteCustomization::ContentBlocks::FormContentBlockComponent.new(@content_block) %>
|
||||
<% end %>
|
||||
|
||||
@@ -1,4 +0,0 @@
|
||||
<%= render "shared/common_globalize_locales",
|
||||
resource: nil,
|
||||
display_style: lambda { |locale| site_customization_display_translation_style(locale) },
|
||||
manage_languages: defined?(manage_languages) ? manage_languages : true %>
|
||||
@@ -4,7 +4,6 @@
|
||||
<%= render "tabs" %>
|
||||
|
||||
<div class="tabs-panel is-active" role="tab">
|
||||
<%= render "form", contents: [@content] %>
|
||||
<%= render Admin::SiteCustomization::InformationTexts::FormComponent.new([@content]) %>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<% if translations_interface_enabled? %>
|
||||
<%= render "shared/common_globalize_locales",
|
||||
resource: resource,
|
||||
display_style: lambda { |locale| enable_translation_style(resource, locale) },
|
||||
manage_languages: defined?(manage_languages) ? manage_languages : true %>
|
||||
<%= render Shared::GlobalizeLocalesComponent.new(
|
||||
resource,
|
||||
manage_languages: defined?(manage_languages) ? manage_languages : true
|
||||
) %>
|
||||
<% end %>
|
||||
|
||||
@@ -136,6 +136,7 @@ module Consul
|
||||
[
|
||||
"app/components/custom",
|
||||
"app/controllers/custom",
|
||||
"app/form_builders/custom",
|
||||
"app/graphql/custom",
|
||||
"app/lib/custom",
|
||||
"app/mailers/custom",
|
||||
|
||||
@@ -38,6 +38,9 @@ en:
|
||||
year_of_birth: "Year born"
|
||||
local_census_records/import:
|
||||
file: File
|
||||
setting/locales_settings:
|
||||
default: Default language
|
||||
enabled: Enabled languages
|
||||
errors:
|
||||
models:
|
||||
local_census_records/import:
|
||||
|
||||
@@ -710,6 +710,11 @@ en:
|
||||
milestones:
|
||||
index:
|
||||
title: Following
|
||||
locales:
|
||||
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_help_text: The default language, selected above, will be included automatically.
|
||||
update:
|
||||
notice: Languages updated successfully
|
||||
managers:
|
||||
index:
|
||||
title: Managers
|
||||
@@ -727,11 +732,12 @@ en:
|
||||
menu:
|
||||
activity: Moderator activity
|
||||
admin: Admin menu
|
||||
banner: Manage banners
|
||||
banner: Banners
|
||||
proposals: Proposals
|
||||
proposals_topics: Proposals topics
|
||||
budgets: Participatory budgets
|
||||
geozones: Manage geozones
|
||||
geozones: Geozones
|
||||
locales: Languages
|
||||
hidden_comments: Hidden comments
|
||||
hidden_debates: Hidden debates
|
||||
hidden_proposals: Hidden proposals
|
||||
@@ -752,7 +758,7 @@ en:
|
||||
polls: Polls
|
||||
poll_booths: Booths location
|
||||
poll_booth_assignments: Booths Assignments
|
||||
poll_shifts: Manage shifts
|
||||
poll_shifts: Shifts Assignments
|
||||
officials: Officials
|
||||
organizations: Organisations
|
||||
settings: Global settings
|
||||
@@ -794,7 +800,7 @@ en:
|
||||
dashboard_actions: Resources and actions
|
||||
debates: "Debates"
|
||||
comments: "Comments"
|
||||
local_census_records: Manage local census
|
||||
local_census_records: Local census
|
||||
machine_learning: "AI / Machine learning"
|
||||
multitenancy: Multitenancy
|
||||
administrators:
|
||||
@@ -1232,7 +1238,7 @@ en:
|
||||
show:
|
||||
location: "Location"
|
||||
booth:
|
||||
shifts: "Manage shifts"
|
||||
shifts: "Shifts Assignments"
|
||||
officials:
|
||||
edit:
|
||||
destroy: Remove "Official" status
|
||||
@@ -1713,7 +1719,7 @@ en:
|
||||
empty: "There are no changes logged"
|
||||
local_census_records:
|
||||
index:
|
||||
title: Manage local census
|
||||
title: Local census
|
||||
create: Create new local census record
|
||||
no_local_census_records: There are no local census records.
|
||||
document_type: Document type
|
||||
@@ -1738,7 +1744,7 @@ en:
|
||||
create:
|
||||
notice: Local census records import process executed successfully!
|
||||
show:
|
||||
title: Manage local census
|
||||
title: Local census
|
||||
subtitle: Import process results
|
||||
import: Import again
|
||||
errored: Errored rows
|
||||
|
||||
@@ -38,6 +38,9 @@ es:
|
||||
year_of_birth: "Año de nacimiento"
|
||||
local_census_records/import:
|
||||
file: Archivo
|
||||
setting/locales_settings:
|
||||
default: Idioma por defecto
|
||||
enabled: Idiomas habilitados
|
||||
errors:
|
||||
models:
|
||||
local_census_records/import:
|
||||
|
||||
@@ -710,6 +710,11 @@ es:
|
||||
milestones:
|
||||
index:
|
||||
title: Seguimiento
|
||||
locales:
|
||||
default_help_text: "Cambiar el idioma por defecto <strong>afectará a todos los usuarios</strong> que visiten la página por primera vez."
|
||||
enabled_help_text: El idioma por defecto, seleccionado con anterioridad, se habilitará automáticamente.
|
||||
update:
|
||||
notice: Idiomas actualizados con éxito
|
||||
managers:
|
||||
index:
|
||||
title: Gestores
|
||||
@@ -727,11 +732,12 @@ es:
|
||||
menu:
|
||||
activity: Actividad de moderadores
|
||||
admin: Menú de administración
|
||||
banner: Gestionar banners
|
||||
banner: Banners
|
||||
proposals: Propuestas
|
||||
proposals_topics: Temas de propuestas
|
||||
budgets: Presupuestos participativos
|
||||
geozones: Gestionar zonas
|
||||
geozones: Zonas
|
||||
locales: Idiomas
|
||||
hidden_comments: Comentarios ocultos
|
||||
hidden_debates: Debates ocultos
|
||||
hidden_proposals: Propuestas ocultas
|
||||
@@ -794,7 +800,7 @@ es:
|
||||
dashboard_actions: Recursos y acciones
|
||||
debates: "Debates"
|
||||
comments: "Comentarios"
|
||||
local_census_records: Gestionar censo local
|
||||
local_census_records: Censo local
|
||||
machine_learning: "IA / Machine learning"
|
||||
multitenancy: Multientidad
|
||||
administrators:
|
||||
@@ -1713,7 +1719,7 @@ es:
|
||||
empty: "No hay cambios registrados"
|
||||
local_census_records:
|
||||
index:
|
||||
title: Gestionar censo local
|
||||
title: Censo local
|
||||
create: Crear nuevo registro en el censo local
|
||||
no_local_census_records: No hay registros de censo local
|
||||
document_type: Tipo de documento
|
||||
@@ -1738,7 +1744,7 @@ es:
|
||||
create:
|
||||
notice: ¡Proceso de import de registros del censo local ejecutado correctamente!
|
||||
show:
|
||||
title: Gestionar censo local
|
||||
title: Censo local
|
||||
subtitle: Resultados del proceso de importación
|
||||
import: Importar otro fichero
|
||||
errored: Filas erróneas
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -23,7 +23,11 @@ def log(msg)
|
||||
end
|
||||
|
||||
def random_locales
|
||||
[I18n.default_locale, *(I18n.available_locales & %i[en es]), *I18n.available_locales.sample(4)].uniq.take(5)
|
||||
[
|
||||
Setting.default_locale,
|
||||
*(Setting.enabled_locales & %i[en es]),
|
||||
*Setting.enabled_locales.sample(4)
|
||||
].uniq.take(5)
|
||||
end
|
||||
|
||||
def random_locales_attributes(**attribute_names_with_values)
|
||||
|
||||
@@ -9,7 +9,7 @@ section "Creating banners" do
|
||||
post_started_at: rand((1.week.ago)..(1.day.ago)),
|
||||
post_ended_at: rand((1.day.ago)..(1.week.from_now)),
|
||||
created_at: rand((1.week.ago)..Time.current))
|
||||
I18n.available_locales.map do |locale|
|
||||
Setting.enabled_locales.map do |locale|
|
||||
Globalize.with_locale(locale) do
|
||||
banner.description = "Description for locale #{locale}"
|
||||
banner.title = "Title for locale #{locale}"
|
||||
|
||||
@@ -41,7 +41,7 @@ section "Creating polls" do
|
||||
|
||||
Poll.find_each do |poll|
|
||||
name = poll.name
|
||||
I18n.available_locales.map do |locale|
|
||||
Setting.enabled_locales.map do |locale|
|
||||
Globalize.with_locale(locale) do
|
||||
poll.name = "#{name} (#{locale})"
|
||||
poll.summary = "Summary for locale #{locale}"
|
||||
@@ -59,7 +59,7 @@ section "Creating Poll Questions & Answers" do
|
||||
question = Poll::Question.new(author: User.sample,
|
||||
title: question_title,
|
||||
poll: poll)
|
||||
I18n.available_locales.map do |locale|
|
||||
Setting.enabled_locales.map do |locale|
|
||||
Globalize.with_locale(locale) do
|
||||
question.title = "#{question_title} (#{locale})"
|
||||
end
|
||||
@@ -71,7 +71,7 @@ section "Creating Poll Questions & Answers" do
|
||||
title: title.capitalize,
|
||||
description: description,
|
||||
given_order: index + 1)
|
||||
I18n.available_locales.map do |locale|
|
||||
Setting.enabled_locales.map do |locale|
|
||||
Globalize.with_locale(locale) do
|
||||
answer.title = "#{title} (#{locale})"
|
||||
answer.description = "#{description} (#{locale})"
|
||||
@@ -235,7 +235,7 @@ section "Creating Poll Questions from Proposals" do
|
||||
question = Poll::Question.new(poll: poll)
|
||||
question.copy_attributes_from_proposal(proposal)
|
||||
question_title = question.title
|
||||
I18n.available_locales.map do |locale|
|
||||
Setting.enabled_locales.map do |locale|
|
||||
Globalize.with_locale(locale) do
|
||||
question.title = "#{question_title} (#{locale})"
|
||||
end
|
||||
@@ -247,7 +247,7 @@ section "Creating Poll Questions from Proposals" do
|
||||
title: title.capitalize,
|
||||
description: description,
|
||||
given_order: index + 1)
|
||||
I18n.available_locales.map do |locale|
|
||||
Setting.enabled_locales.map do |locale|
|
||||
Globalize.with_locale(locale) do
|
||||
answer.title = "#{title} (#{locale})"
|
||||
answer.description = "#{description} (#{locale})"
|
||||
@@ -265,7 +265,7 @@ section "Creating Successful Proposals" do
|
||||
question = Poll::Question.new(poll: poll)
|
||||
question.copy_attributes_from_proposal(proposal)
|
||||
question_title = question.title
|
||||
I18n.available_locales.map do |locale|
|
||||
Setting.enabled_locales.map do |locale|
|
||||
Globalize.with_locale(locale) do
|
||||
question.title = "#{question_title} (#{locale})"
|
||||
end
|
||||
@@ -277,7 +277,7 @@ section "Creating Successful Proposals" do
|
||||
title: title.capitalize,
|
||||
description: description,
|
||||
given_order: index + 1)
|
||||
I18n.available_locales.map do |locale|
|
||||
Setting.enabled_locales.map do |locale|
|
||||
Globalize.with_locale(locale) do
|
||||
answer.title = "#{title} (#{locale})"
|
||||
answer.description = "#{description} (#{locale})"
|
||||
|
||||
@@ -104,7 +104,7 @@ end
|
||||
|
||||
if SiteCustomization::Page.find_by(slug: "accessibility").nil?
|
||||
page = SiteCustomization::Page.new(slug: "accessibility", status: "published")
|
||||
I18n.available_locales.each do |locale|
|
||||
Setting.enabled_locales.each do |locale|
|
||||
I18n.with_locale(locale) { generate_content(page) }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -7,7 +7,7 @@ end
|
||||
if SiteCustomization::Page.find_by(slug: "census_terms").nil?
|
||||
page = SiteCustomization::Page.new(slug: "census_terms", status: "published")
|
||||
page.print_content_flag = true
|
||||
I18n.available_locales.each do |locale|
|
||||
Setting.enabled_locales.each do |locale|
|
||||
I18n.with_locale(locale) { generate_content(page) }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -8,7 +8,7 @@ end
|
||||
if SiteCustomization::Page.find_by(slug: "conditions").nil?
|
||||
page = SiteCustomization::Page.new(slug: "conditions", status: "published")
|
||||
page.print_content_flag = true
|
||||
I18n.available_locales.each do |locale|
|
||||
Setting.enabled_locales.each do |locale|
|
||||
I18n.with_locale(locale) { generate_content(page) }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -5,7 +5,7 @@ def generate_content(page)
|
||||
end
|
||||
if SiteCustomization::Page.find_by(slug: "faq").nil?
|
||||
page = SiteCustomization::Page.new(slug: "faq", status: "published")
|
||||
I18n.available_locales.each do |locale|
|
||||
Setting.enabled_locales.each do |locale|
|
||||
I18n.with_locale(locale) { generate_content(page) }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -7,7 +7,7 @@ end
|
||||
if SiteCustomization::Page.find_by(slug: "privacy").nil?
|
||||
page = SiteCustomization::Page.new(slug: "privacy", status: "published")
|
||||
page.print_content_flag = true
|
||||
I18n.available_locales.each do |locale|
|
||||
Setting.enabled_locales.each do |locale|
|
||||
I18n.with_locale(locale) { generate_content(page) }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -17,7 +17,7 @@ end
|
||||
|
||||
if SiteCustomization::Page.find_by(slug: "welcome_level_three_verified").nil?
|
||||
page = SiteCustomization::Page.new(slug: "welcome_level_three_verified", status: "published")
|
||||
I18n.available_locales.each do |locale|
|
||||
Setting.enabled_locales.each do |locale|
|
||||
I18n.with_locale(locale) { generate_content(page) }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -22,7 +22,7 @@ def generate_content(page)
|
||||
end
|
||||
if SiteCustomization::Page.find_by(slug: "welcome_level_two_verified").nil?
|
||||
page = SiteCustomization::Page.new(slug: "welcome_level_two_verified", status: "published")
|
||||
I18n.available_locales.each do |locale|
|
||||
Setting.enabled_locales.each do |locale|
|
||||
I18n.with_locale(locale) { generate_content(page) }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -22,7 +22,7 @@ def generate_content(page)
|
||||
end
|
||||
if SiteCustomization::Page.find_by(slug: "welcome_not_verified").nil?
|
||||
page = SiteCustomization::Page.new(slug: "welcome_not_verified", status: "published")
|
||||
I18n.available_locales.each do |locale|
|
||||
Setting.enabled_locales.each do |locale|
|
||||
I18n.with_locale(locale) { generate_content(page) }
|
||||
end
|
||||
end
|
||||
|
||||
37
spec/components/admin/locales/form_component_spec.rb
Normal file
37
spec/components/admin/locales/form_component_spec.rb
Normal file
@@ -0,0 +1,37 @@
|
||||
require "rails_helper"
|
||||
|
||||
describe Admin::Locales::FormComponent do
|
||||
let(:default_locale) { :nl }
|
||||
let(:enabled_locales) { %i[en nl] }
|
||||
let(:locales_settings) { Setting::LocalesSettings.new(default: default_locale, enabled: enabled_locales) }
|
||||
let(:component) { Admin::Locales::FormComponent.new(locales_settings) }
|
||||
|
||||
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
|
||||
@@ -0,0 +1,19 @@
|
||||
require "rails_helper"
|
||||
|
||||
describe Admin::SiteCustomization::ContentBlocks::FormContentBlockComponent do
|
||||
describe "locale selector" do
|
||||
let(:content_block) { create(:site_customization_content_block, locale: "de") }
|
||||
let(:component) do
|
||||
Admin::SiteCustomization::ContentBlocks::FormContentBlockComponent.new(content_block)
|
||||
end
|
||||
|
||||
it "only includes enabled settings" do
|
||||
Setting["locales.default"] = "de"
|
||||
Setting["locales.enabled"] = "de fr"
|
||||
|
||||
render_inline component
|
||||
|
||||
expect(page).to have_select "locale", options: ["de", "fr"]
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,19 @@
|
||||
require "rails_helper"
|
||||
|
||||
describe Admin::SiteCustomization::ContentBlocks::FormHeadingContentBlockComponent do
|
||||
describe "locale selector" do
|
||||
let(:content_block) { create(:heading_content_block, locale: "de") }
|
||||
let(:component) do
|
||||
Admin::SiteCustomization::ContentBlocks::FormHeadingContentBlockComponent.new(content_block)
|
||||
end
|
||||
|
||||
it "only includes enabled settings" do
|
||||
Setting["locales.default"] = "de"
|
||||
Setting["locales.enabled"] = "de fr"
|
||||
|
||||
render_inline component
|
||||
|
||||
expect(page).to have_select "locale", options: ["de", "fr"]
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,29 @@
|
||||
require "rails_helper"
|
||||
|
||||
describe Admin::SiteCustomization::InformationTexts::FormComponent do
|
||||
describe "enabled_translations fields" do
|
||||
it "renders fields for enabled locales" do
|
||||
Setting["locales.enabled"] = "en es"
|
||||
content = create(:i18n_content)
|
||||
|
||||
render_inline Admin::SiteCustomization::InformationTexts::FormComponent.new([[content]])
|
||||
|
||||
expect(page).to have_css "input[name^='enabled_translations']", count: 2, visible: :all
|
||||
expect(page).to have_css "input[name='enabled_translations[en]']", visible: :hidden
|
||||
expect(page).to have_css "input[name='enabled_translations[es]']", visible: :hidden
|
||||
end
|
||||
end
|
||||
|
||||
describe "text fields" do
|
||||
it "renders fields for enabled locales" do
|
||||
Setting["locales.enabled"] = "en es"
|
||||
content = create(:i18n_content, key: "system.failure")
|
||||
|
||||
render_inline Admin::SiteCustomization::InformationTexts::FormComponent.new([[content]])
|
||||
|
||||
expect(page).to have_css "textarea[name^='contents[content_system.failure]']", count: 2, visible: :all
|
||||
expect(page).to have_field "contents[content_system.failure]values[value_en]"
|
||||
expect(page).to have_field "contents[content_system.failure]values[value_es]"
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -97,4 +97,21 @@ describe Layout::LocaleSwitcherComponent do
|
||||
expect(page).to have_css "[href='/?locale=en'][data-turbolinks=true]"
|
||||
end
|
||||
end
|
||||
|
||||
context "when not all available locales are enabled" do
|
||||
before do
|
||||
allow(I18n).to receive(:available_locales).and_return(%i[en es fr])
|
||||
Setting["locales.default"] = "es"
|
||||
Setting["locales.enabled"] = "es fr"
|
||||
end
|
||||
|
||||
it "displays the enabled locales" do
|
||||
render_inline component
|
||||
|
||||
expect(page).to have_link count: 2
|
||||
expect(page).to have_link "Español"
|
||||
expect(page).to have_link "Français"
|
||||
expect(page).not_to have_link "English"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
49
spec/components/shared/globalize_locales_component_spec.rb
Normal file
49
spec/components/shared/globalize_locales_component_spec.rb
Normal file
@@ -0,0 +1,49 @@
|
||||
require "rails_helper"
|
||||
|
||||
describe Shared::GlobalizeLocalesComponent do
|
||||
describe "Language selector" do
|
||||
it "only includes enabled locales" do
|
||||
Setting["locales.enabled"] = "en nl"
|
||||
|
||||
I18n.with_locale(:en) do
|
||||
render_inline Shared::GlobalizeLocalesComponent.new
|
||||
|
||||
expect(page).to have_select options: ["Choose language", "English"]
|
||||
end
|
||||
|
||||
I18n.with_locale(:es) do
|
||||
render_inline Shared::GlobalizeLocalesComponent.new
|
||||
|
||||
expect(page).to have_select options: ["Seleccionar idioma"]
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "links to destroy languages" do
|
||||
it "only includes enabled locales" do
|
||||
Setting["locales.enabled"] = "en nl"
|
||||
|
||||
I18n.with_locale(:en) do
|
||||
render_inline Shared::GlobalizeLocalesComponent.new
|
||||
|
||||
expect(page).to have_css "a[data-locale]", count: 1
|
||||
end
|
||||
|
||||
I18n.with_locale(:es) do
|
||||
render_inline Shared::GlobalizeLocalesComponent.new
|
||||
|
||||
expect(page).not_to have_css "a[data-locale]"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "Add language selector" do
|
||||
it "only includes enabled locales" do
|
||||
Setting["locales.enabled"] = "en nl"
|
||||
|
||||
render_inline Shared::GlobalizeLocalesComponent.new
|
||||
|
||||
expect(page).to have_select options: ["Add language", "English", "Nederlands"]
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,6 +1,14 @@
|
||||
require "rails_helper"
|
||||
|
||||
describe ApplicationController do
|
||||
controller do
|
||||
skip_authorization_check
|
||||
|
||||
def index
|
||||
render plain: I18n.locale
|
||||
end
|
||||
end
|
||||
|
||||
describe "#current_budget" do
|
||||
it "returns the last budget that is not in draft phase" do
|
||||
create(:budget, :finished, created_at: 2.years.ago, name: "Old")
|
||||
@@ -12,4 +20,68 @@ describe ApplicationController do
|
||||
expect(budget.name).to eq("Current")
|
||||
end
|
||||
end
|
||||
|
||||
describe "#switch_locale" do
|
||||
it "uses the default locale by default" do
|
||||
Setting["locales.default"] = "pt-BR"
|
||||
|
||||
get :index
|
||||
|
||||
expect(response.body).to eq "pt-BR"
|
||||
end
|
||||
|
||||
it "uses the locale in the parameters when it's there" do
|
||||
get :index, params: { locale: :es }
|
||||
|
||||
expect(response.body).to eq "es"
|
||||
end
|
||||
|
||||
it "uses the locale in the session if there are no parameters" do
|
||||
get :index, params: { locale: :es }
|
||||
|
||||
expect(response.body).to eq "es"
|
||||
|
||||
get :index
|
||||
|
||||
expect(response.body).to eq "es"
|
||||
end
|
||||
|
||||
it "uses the locale in the parameters even when it's in the session" do
|
||||
get :index
|
||||
|
||||
expect(response.body).to eq "en"
|
||||
|
||||
get :index, params: { locale: :es }
|
||||
|
||||
expect(response.body).to eq "es"
|
||||
end
|
||||
|
||||
it "only accepts enabled locales" do
|
||||
Setting["locales.enabled"] = "en es fr"
|
||||
|
||||
get :index, params: { locale: :es }
|
||||
|
||||
expect(response.body).to eq "es"
|
||||
|
||||
get :index, params: { locale: :de }
|
||||
|
||||
expect(response.body).to eq "es"
|
||||
|
||||
get :index, params: { locale: :fr }
|
||||
|
||||
expect(response.body).to eq "fr"
|
||||
end
|
||||
|
||||
context "authenticated user" do
|
||||
let(:user) { create(:user) }
|
||||
before { sign_in(user) }
|
||||
|
||||
it "updates the prefered locale when it's in the parameters" do
|
||||
get :index, params: { locale: :es }
|
||||
|
||||
expect(user.reload.locale).to eq "es"
|
||||
expect(response.body).to eq "es"
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,6 +1,16 @@
|
||||
require "rails_helper"
|
||||
|
||||
describe Management::BaseController do
|
||||
before { session[:manager] = double }
|
||||
|
||||
controller do
|
||||
skip_authorization_check
|
||||
|
||||
def index
|
||||
render plain: I18n.locale
|
||||
end
|
||||
end
|
||||
|
||||
describe "managed_user" do
|
||||
it "returns existent user with session document info if present" do
|
||||
session[:document_type] = "1"
|
||||
@@ -21,4 +31,56 @@ describe Management::BaseController do
|
||||
expect(managed_user.document_number).to eq "333333333E"
|
||||
end
|
||||
end
|
||||
|
||||
describe "#switch_locale" do
|
||||
it "uses the default locale by default" do
|
||||
Setting["locales.default"] = "pt-BR"
|
||||
|
||||
get :index
|
||||
|
||||
expect(response.body).to eq "pt-BR"
|
||||
end
|
||||
|
||||
it "uses the locale in the parameters when it's there" do
|
||||
get :index, params: { locale: :es }
|
||||
|
||||
expect(response.body).to eq "es"
|
||||
end
|
||||
|
||||
it "uses the locale in the session if there are no parameters" do
|
||||
get :index, params: { locale: :es }
|
||||
|
||||
expect(response.body).to eq "es"
|
||||
|
||||
get :index
|
||||
|
||||
expect(response.body).to eq "es"
|
||||
end
|
||||
|
||||
it "uses the locale in the parameters even when it's in the session" do
|
||||
get :index
|
||||
|
||||
expect(response.body).to eq "en"
|
||||
|
||||
get :index, params: { locale: :es }
|
||||
|
||||
expect(response.body).to eq "es"
|
||||
end
|
||||
|
||||
it "only accepts enabled locales" do
|
||||
Setting["locales.enabled"] = "en es fr"
|
||||
|
||||
get :index, params: { locale: :es }
|
||||
|
||||
expect(response.body).to eq "es"
|
||||
|
||||
get :index, params: { locale: :de }
|
||||
|
||||
expect(response.body).to eq "es"
|
||||
|
||||
get :index, params: { locale: :fr }
|
||||
|
||||
expect(response.body).to eq "fr"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -19,5 +19,24 @@ describe SubscriptionsController do
|
||||
expect(response).to redirect_to "/"
|
||||
expect(flash[:alert]).to eq "No tienes permiso para acceder a esta página."
|
||||
end
|
||||
|
||||
it "uses the user locale where there's no locale in the parameters" do
|
||||
create(:user, locale: "es", subscriptions_token: "mytoken")
|
||||
|
||||
get :edit, params: { token: "mytoken" }
|
||||
|
||||
expect(session[:locale]).to eq "es"
|
||||
end
|
||||
|
||||
it "only accepts enabled locales" do
|
||||
Setting["locales.default"] = "fr"
|
||||
Setting["locales.enabled"] = "fr nl"
|
||||
|
||||
create(:user, locale: "es", subscriptions_token: "mytoken")
|
||||
|
||||
get :edit, params: { token: "mytoken" }
|
||||
|
||||
expect(session[:locale]).to eq "fr"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
46
spec/form_builders/translatable_form_builder_spec.rb
Normal file
46
spec/form_builders/translatable_form_builder_spec.rb
Normal file
@@ -0,0 +1,46 @@
|
||||
require "rails_helper"
|
||||
|
||||
describe TranslatableFormBuilder do
|
||||
before do
|
||||
dummy_banner = Class.new(ApplicationRecord) do
|
||||
def self.name
|
||||
"DummyBanner"
|
||||
end
|
||||
self.table_name = "banners"
|
||||
|
||||
translates :title, touch: true
|
||||
include Globalizable
|
||||
has_many :translations, class_name: "DummyBanner::Translation", foreign_key: "banner_id"
|
||||
end
|
||||
|
||||
stub_const("DummyBanner", dummy_banner)
|
||||
end
|
||||
|
||||
let(:builder) do
|
||||
TranslatableFormBuilder.new(:dummy, DummyBanner.new, ApplicationController.new.view_context, {})
|
||||
end
|
||||
|
||||
describe "#translatable_fields" do
|
||||
it "renders fields for the enabled locales when the translation interface is enabled" do
|
||||
Setting["feature.translation_interface"] = true
|
||||
Setting["locales.enabled"] = "en fr"
|
||||
|
||||
builder.translatable_fields do |translations_builder|
|
||||
render translations_builder.text_field :title
|
||||
end
|
||||
|
||||
expect(page).to have_field "Title", count: 2
|
||||
end
|
||||
end
|
||||
|
||||
attr_reader :content
|
||||
|
||||
def render(content)
|
||||
@content ||= ""
|
||||
@content << content
|
||||
end
|
||||
|
||||
def page
|
||||
Capybara::Node::Simple.new(content)
|
||||
end
|
||||
end
|
||||
@@ -3,27 +3,23 @@ require "rails_helper"
|
||||
describe SearchDictionarySelector do
|
||||
context "from I18n default locale" do
|
||||
before { allow(subject).to receive(:call).and_call_original }
|
||||
around do |example|
|
||||
original_i18n_default = I18n.default_locale
|
||||
begin
|
||||
example.run
|
||||
ensure
|
||||
I18n.default_locale = original_i18n_default
|
||||
end
|
||||
end
|
||||
|
||||
it "returns correct dictionary for simple locale" do
|
||||
I18n.default_locale = :es
|
||||
Setting["locales.default"] = "es"
|
||||
|
||||
expect(subject.call).to eq("spanish")
|
||||
end
|
||||
|
||||
it "returns correct dictionary for compound locale" do
|
||||
I18n.default_locale = :"pt-BR"
|
||||
Setting["locales.default"] = "pt-BR"
|
||||
|
||||
expect(subject.call).to eq("portuguese")
|
||||
end
|
||||
|
||||
it "returns simple for unsupported locale" do
|
||||
expect(I18n).to receive(:default_locale).and_return(:pl) # avoiding I18n::InvalidLocale
|
||||
allow(I18n).to receive(:available_locales).and_return(%i[en pl])
|
||||
Setting["locales.default"] = "pl"
|
||||
|
||||
expect(subject.call).to eq("simple")
|
||||
end
|
||||
end
|
||||
|
||||
@@ -30,6 +30,16 @@ describe Mailer do
|
||||
end
|
||||
end
|
||||
|
||||
describe "#user_invite" do
|
||||
it "uses the default locale setting" do
|
||||
Setting["locales.default"] = "es"
|
||||
|
||||
Mailer.user_invite("invited@consul.dev").deliver_now
|
||||
|
||||
expect(ActionMailer::Base.deliveries.last.body.to_s).to match "<html lang=\"es\""
|
||||
end
|
||||
end
|
||||
|
||||
describe "#manage_subscriptions_token" do
|
||||
let(:user) { create(:user) }
|
||||
let(:proposal) { create(:proposal, author: user) }
|
||||
|
||||
@@ -20,6 +20,15 @@ describe Budget::ContentBlock do
|
||||
expect(valid_block).to be_valid
|
||||
end
|
||||
|
||||
it "is not valid with a disabled locale" do
|
||||
Setting["locales.default"] = "pt-BR"
|
||||
Setting["locales.enabled"] = "nl pt-BR"
|
||||
|
||||
block.locale = "en"
|
||||
|
||||
expect(block).not_to be_valid
|
||||
end
|
||||
|
||||
describe "#name" do
|
||||
it "uses the heading name" do
|
||||
block = Budget::ContentBlock.new(heading: Budget::Heading.new(name: "Central"))
|
||||
|
||||
47
spec/models/globalizable_spec.rb
Normal file
47
spec/models/globalizable_spec.rb
Normal file
@@ -0,0 +1,47 @@
|
||||
require "rails_helper"
|
||||
|
||||
describe Globalizable do
|
||||
before do
|
||||
dummy_banner = Class.new(ApplicationRecord) do
|
||||
def self.name
|
||||
"DummyBanner"
|
||||
end
|
||||
self.table_name = "banners"
|
||||
|
||||
translates :title, touch: true
|
||||
include Globalizable
|
||||
has_many :translations, class_name: "DummyBanner::Translation", foreign_key: "banner_id"
|
||||
|
||||
validates_translation :title, length: { minimum: 7 }
|
||||
end
|
||||
|
||||
stub_const("DummyBanner", dummy_banner)
|
||||
end
|
||||
|
||||
describe ".validates_translation" do
|
||||
it "validates length for the default locale" do
|
||||
Setting["locales.default"] = "es"
|
||||
|
||||
dummy = DummyBanner.new
|
||||
dummy.translations.build(locale: "es", title: "Short")
|
||||
dummy.translations.build(locale: "fr", title: "Long enough")
|
||||
|
||||
I18n.with_locale(:fr) do
|
||||
expect(dummy).not_to be_valid
|
||||
end
|
||||
end
|
||||
|
||||
it "does not validate length for other locales" do
|
||||
Setting["locales.default"] = "es"
|
||||
|
||||
dummy = DummyBanner.new
|
||||
dummy.translations.build(locale: "es", title: "Long enough")
|
||||
dummy.translations.build(locale: "fr", title: "Long enough")
|
||||
dummy.translations.build(locale: "en", title: "Short")
|
||||
|
||||
I18n.with_locale(:fr) do
|
||||
expect(dummy).to be_valid
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -160,6 +160,17 @@ RSpec.describe I18nContent do
|
||||
end
|
||||
|
||||
it "does not store new keys for disabled translations" do
|
||||
Setting["locales.default"] = "es"
|
||||
Setting["locales.enabled"] = "es"
|
||||
|
||||
I18nContent.update([{ id: "shared.yes", values: { "value_en" => "Oh, yeah" }}])
|
||||
|
||||
expect(I18nContent.all).to be_empty
|
||||
end
|
||||
|
||||
it "uses different enabled translations when given a parameter" do
|
||||
Setting["locales.enabled"] = "en es"
|
||||
|
||||
I18nContent.update([{ id: "shared.yes", values: { "value_en" => "Oh, yeah" }}], [:es])
|
||||
|
||||
expect(I18nContent.all).to be_empty
|
||||
|
||||
13
spec/models/setting/locales_settings_spec.rb
Normal file
13
spec/models/setting/locales_settings_spec.rb
Normal file
@@ -0,0 +1,13 @@
|
||||
require "rails_helper"
|
||||
|
||||
describe Setting::LocalesSettings do
|
||||
describe "#update!" do
|
||||
it "saves the default locale in the enabled ones when nothing is enabled" do
|
||||
Setting::LocalesSettings.new.update!(default: "es", enabled: %w[])
|
||||
updated_locales_settings = Setting::LocalesSettings.new
|
||||
|
||||
expect(updated_locales_settings.default).to eq :es
|
||||
expect(updated_locales_settings.enabled).to match_array [:es]
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -258,4 +258,96 @@ describe Setting do
|
||||
expect(Setting.force_presence_postal_code?).to be true
|
||||
end
|
||||
end
|
||||
|
||||
describe ".available_locales" do
|
||||
before { allow(I18n).to receive_messages(default_locale: :de, available_locales: %i[de en es pt-BR]) }
|
||||
|
||||
it "uses I18n available locales by default" do
|
||||
Setting["locales.enabled"] = ""
|
||||
|
||||
expect(Setting.enabled_locales).to eq %i[de en es pt-BR]
|
||||
end
|
||||
|
||||
it "defines available locales with a space-separated list" do
|
||||
Setting["locales.enabled"] = "de es"
|
||||
|
||||
expect(Setting.enabled_locales).to eq %i[de es]
|
||||
end
|
||||
|
||||
it "handles locales which include a dash" do
|
||||
Setting["locales.enabled"] = "de en pt-BR"
|
||||
|
||||
expect(Setting.enabled_locales).to eq %i[de en pt-BR]
|
||||
end
|
||||
|
||||
it "adds the default locale to the list of available locales" do
|
||||
Setting["locales.enabled"] = "en es"
|
||||
|
||||
expect(Setting.enabled_locales).to eq %i[de en es]
|
||||
end
|
||||
|
||||
it "ignores extra whitespace between locales" do
|
||||
Setting["locales.enabled"] = " de en pt-BR "
|
||||
|
||||
expect(Setting.enabled_locales).to eq %i[de en pt-BR]
|
||||
end
|
||||
|
||||
it "ignores locales which aren't available" do
|
||||
Setting["locales.enabled"] = "de es en-US fr zh-CN"
|
||||
|
||||
expect(Setting.enabled_locales).to eq %i[de es]
|
||||
end
|
||||
|
||||
it "ignores words that don't make sense in this context" do
|
||||
Setting["locales.enabled"] = "yes de 1234 en SuperCool"
|
||||
|
||||
expect(Setting.enabled_locales).to eq %i[de en]
|
||||
end
|
||||
|
||||
it "uses I18n available locales when no locale is available" do
|
||||
Setting["locales.enabled"] = "nl fr zh-CN"
|
||||
|
||||
expect(Setting.enabled_locales).to eq %i[de en es pt-BR]
|
||||
end
|
||||
end
|
||||
|
||||
describe ".default_locale" do
|
||||
before { allow(I18n).to receive_messages(default_locale: :en, available_locales: %i[de en es pt-BR]) }
|
||||
|
||||
it "uses I18n default locale by default" do
|
||||
Setting["locales.default"] = ""
|
||||
|
||||
expect(Setting.default_locale).to eq :en
|
||||
end
|
||||
|
||||
it "allows defining the default locale" do
|
||||
Setting["locales.default"] = "de"
|
||||
|
||||
expect(Setting.default_locale).to eq :de
|
||||
end
|
||||
|
||||
it "handles locales which include a dash" do
|
||||
Setting["locales.default"] = "pt-BR"
|
||||
|
||||
expect(Setting.default_locale).to eq :"pt-BR"
|
||||
end
|
||||
|
||||
it "ignores extra whitespace in the locale name" do
|
||||
Setting["locales.default"] = " es "
|
||||
|
||||
expect(Setting.default_locale).to eq :es
|
||||
end
|
||||
|
||||
it "ignores locales which aren't available" do
|
||||
Setting["locales.default"] = "fr"
|
||||
|
||||
expect(Setting.default_locale).to eq :en
|
||||
end
|
||||
|
||||
it "ignores an array of several locales" do
|
||||
Setting["locales.default"] = "de es"
|
||||
|
||||
expect(Setting.default_locale).to eq :en
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -27,4 +27,13 @@ RSpec.describe SiteCustomization::ContentBlock do
|
||||
block.name = "top_links"
|
||||
expect(block).not_to be_valid
|
||||
end
|
||||
|
||||
it "is not valid with a disabled locale" do
|
||||
Setting["locales.default"] = "nl"
|
||||
Setting["locales.enabled"] = "nl pt-BR"
|
||||
|
||||
block.locale = "en"
|
||||
|
||||
expect(block).not_to be_valid
|
||||
end
|
||||
end
|
||||
|
||||
@@ -81,6 +81,16 @@ describe User do
|
||||
end
|
||||
end
|
||||
|
||||
describe "#locale" do
|
||||
it "defaults to the default locale setting" do
|
||||
Setting["locales.default"] = "nl"
|
||||
|
||||
user = build(:user, locale: nil)
|
||||
|
||||
expect(user.locale).to eq "nl"
|
||||
end
|
||||
end
|
||||
|
||||
describe "preferences" do
|
||||
describe "email_on_comment" do
|
||||
it "is false by default" do
|
||||
|
||||
@@ -65,7 +65,7 @@ describe "Admin banners magement", :admin do
|
||||
|
||||
within("#side_menu") do
|
||||
click_button "Site content"
|
||||
click_link "Manage banners"
|
||||
click_link "Banners"
|
||||
end
|
||||
|
||||
click_link "Create banner"
|
||||
@@ -134,7 +134,7 @@ describe "Admin banners magement", :admin do
|
||||
|
||||
within("#side_menu") do
|
||||
click_button "Site content"
|
||||
click_link "Manage banners"
|
||||
click_link "Banners"
|
||||
end
|
||||
|
||||
click_link "Edit"
|
||||
|
||||
@@ -16,7 +16,7 @@ describe "Admin geozones", :admin do
|
||||
|
||||
within("#side_menu") do
|
||||
click_button "Settings"
|
||||
click_link "Manage geozones"
|
||||
click_link "Geozones"
|
||||
end
|
||||
|
||||
click_link "Create geozone"
|
||||
|
||||
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
|
||||
@@ -39,7 +39,7 @@ describe "Admin booths", :admin do
|
||||
|
||||
within("#side_menu") do
|
||||
click_button "Voting booths"
|
||||
click_link "Manage shifts"
|
||||
click_link "Shifts Assignments"
|
||||
end
|
||||
|
||||
expect(page).to have_css(".booth", count: 1)
|
||||
@@ -80,7 +80,7 @@ describe "Admin booths", :admin do
|
||||
visit admin_booths_path
|
||||
|
||||
within("#booth_#{booth.id}") do
|
||||
expect(page).not_to have_link "Manage shifts"
|
||||
expect(page).not_to have_link "Shifts Assignments"
|
||||
click_link "Edit"
|
||||
end
|
||||
|
||||
@@ -105,7 +105,7 @@ describe "Admin booths", :admin do
|
||||
visit available_admin_booths_path
|
||||
|
||||
within("#booth_#{booth.id}") do
|
||||
click_link "Manage shifts"
|
||||
click_link "Shifts Assignments"
|
||||
end
|
||||
|
||||
click_link "Go back"
|
||||
|
||||
@@ -44,7 +44,7 @@ describe "Admin shifts", :admin do
|
||||
visit available_admin_booths_path
|
||||
|
||||
within("#booth_#{booth.id}") do
|
||||
click_link "Manage shifts"
|
||||
click_link "Shifts Assignments"
|
||||
end
|
||||
|
||||
expect(page).to have_content "This booth has no shifts"
|
||||
@@ -71,7 +71,7 @@ describe "Admin shifts", :admin do
|
||||
visit available_admin_booths_path
|
||||
|
||||
within("#booth_#{booth.id}") do
|
||||
click_link "Manage shifts"
|
||||
click_link "Shifts Assignments"
|
||||
end
|
||||
|
||||
expect(page).to have_css(".shift", count: 1)
|
||||
@@ -117,7 +117,7 @@ describe "Admin shifts", :admin do
|
||||
visit available_admin_booths_path
|
||||
|
||||
within("#booth_#{booth.id}") do
|
||||
click_link "Manage shifts"
|
||||
click_link "Shifts Assignments"
|
||||
end
|
||||
|
||||
expect(page).to have_css(".shift", count: 2)
|
||||
@@ -159,7 +159,7 @@ describe "Admin shifts", :admin do
|
||||
visit available_admin_booths_path
|
||||
|
||||
within("#booth_#{booth.id}") do
|
||||
click_link "Manage shifts"
|
||||
click_link "Shifts Assignments"
|
||||
end
|
||||
|
||||
expect(page).to have_content "This booth has no shifts"
|
||||
@@ -182,7 +182,7 @@ describe "Admin shifts", :admin do
|
||||
visit available_admin_booths_path
|
||||
|
||||
within("#booth_#{booth.id}") do
|
||||
click_link "Manage shifts"
|
||||
click_link "Shifts Assignments"
|
||||
end
|
||||
|
||||
expect(page).to have_css(".shift", count: 1)
|
||||
@@ -208,7 +208,7 @@ describe "Admin shifts", :admin do
|
||||
visit available_admin_booths_path
|
||||
|
||||
within("#booth_#{booth.id}") do
|
||||
click_link "Manage shifts"
|
||||
click_link "Shifts Assignments"
|
||||
end
|
||||
|
||||
expect(page).to have_css(".shift", count: 1)
|
||||
@@ -237,7 +237,7 @@ describe "Admin shifts", :admin do
|
||||
visit available_admin_booths_path
|
||||
|
||||
within("#booth_#{booth.id}") do
|
||||
click_link "Manage shifts"
|
||||
click_link "Shifts Assignments"
|
||||
end
|
||||
|
||||
expect(page).to have_css(".shift", count: 1)
|
||||
|
||||
Reference in New Issue
Block a user