Allow different locales per tenant
Note that, currently, we take these settings from the database but we
don't provide a way to edit them through the admin interface, so the
locales must be manually introduced through a Rails console.
While we did consider using a comma-separated list, we're using spaces
in order to be consistent with the way we store the allowed content
types settings.
The `enabled_locales` nomenclature, which contrasts with
`available_locales`, is probably subconsciously based on similar
patterns like the one Nginx uses to enable sites.
Note that we aren't using `Setting.enabled_locales` in the globalize
initializer when setting the fallbacks. This means the following test
(which we could add to the shared globalizable examples) would fail:
```
it "Falls back to an enabled locale if the fallback is not enabled" do
Setting["locales.default"] = "en"
Setting["locales.enabled"] = "fr en"
allow(I18n.fallbacks).to receive(:[]).and_return([:fr, :es])
Globalize.set_fallbacks_to_all_available_locales
I18n.with_locale(:fr) do
expect(record.send(attribute)).to eq "In English"
end
end
```
The reason is that the code making this test pass could be:
```
def Globalize.set_fallbacks_to_all_available_locales
Globalize.fallbacks = I18n.available_locales.index_with do |locale|
((I18n.fallbacks[locale] & Setting.enabled_locales) + Setting.enabled_locales).uniq
end
end
```
However, this would make it impossible to run `rake db:migrate` on new
applications because the initializer would try to load the `Setting`
model but the `settings` table wouldn't exist at that point.
Besides, this is a really rare case that IMHO we don't need to support.
For this scenario, an installation would have to enable a locale, create
records with contents in that locale, then disable that locale and have
that locale as a fallback for a language where content for that record
wasn't created. If that happened, it would be solved by creating content
for that record in every enabled language.
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
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
<%= 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">
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
</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 %>
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<%= 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 %>
|
||||
|
||||
@@ -11,4 +11,8 @@ class Admin::SiteCustomization::InformationTexts::FormComponent < ApplicationCom
|
||||
def translation_enabled_tag(locale, enabled)
|
||||
hidden_field_tag("enabled_translations[#{locale}]", (enabled ? 1 : 0))
|
||||
end
|
||||
|
||||
def enabled_locales
|
||||
Setting.enabled_locales
|
||||
end
|
||||
end
|
||||
|
||||
@@ -12,7 +12,7 @@ class Layout::LocaleSwitcherComponent < ApplicationComponent
|
||||
end
|
||||
|
||||
def locales
|
||||
I18n.available_locales
|
||||
Setting.enabled_locales
|
||||
end
|
||||
|
||||
def label
|
||||
|
||||
@@ -13,7 +13,7 @@
|
||||
<%= 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(locale),
|
||||
class: "delete js-delete-language js-delete-#{locale}",
|
||||
|
||||
@@ -15,7 +15,7 @@ class Shared::GlobalizeLocalesComponent < ApplicationComponent
|
||||
end
|
||||
|
||||
def available_locales
|
||||
I18n.available_locales.select { |locale| enabled_locale?(resource, locale) }.map do |locale|
|
||||
Setting.enabled_locales.select { |locale| enabled_locale?(resource, locale) }.map do |locale|
|
||||
[name_for_locale(locale), locale, { data: { locale: locale }}]
|
||||
end
|
||||
end
|
||||
@@ -84,7 +84,7 @@ class Shared::GlobalizeLocalesComponent < ApplicationComponent
|
||||
end
|
||||
|
||||
def all_language_options
|
||||
I18n.available_locales.map do |locale|
|
||||
Setting.enabled_locales.map do |locale|
|
||||
[name_for_locale(locale), locale]
|
||||
end
|
||||
end
|
||||
|
||||
@@ -51,9 +51,9 @@ class ApplicationController < ActionController::Base
|
||||
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
|
||||
|
||||
@@ -40,7 +40,7 @@ class Management::BaseController < ActionController::Base
|
||||
end
|
||||
|
||||
def switch_locale(&action)
|
||||
if params[:locale] && I18n.available_locales.include?(params[:locale].to_sym)
|
||||
if params[:locale] && Setting.enabled_locales.include?(params[:locale].to_sym)
|
||||
session[:locale] = params[:locale].to_s
|
||||
end
|
||||
|
||||
|
||||
@@ -38,6 +38,6 @@ class SubscriptionsController < ApplicationController
|
||||
end
|
||||
|
||||
def find_locale
|
||||
I18n.available_locales.find { |locale| locale == @user.locale&.to_sym } || I18n.locale
|
||||
Setting.enabled_locales.find { |locale| locale == @user.locale&.to_sym } || I18n.locale
|
||||
end
|
||||
end
|
||||
|
||||
@@ -63,7 +63,7 @@ class TranslatableFormBuilder < ConsulFormBuilder
|
||||
|
||||
def visible_locales
|
||||
if @template.translations_interface_enabled?
|
||||
@object.globalize_locales
|
||||
Setting.enabled_locales & @object.globalize_locales
|
||||
else
|
||||
[I18n.locale]
|
||||
end
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
|
||||
@@ -95,6 +95,7 @@ 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,
|
||||
"map.latitude": 51.48,
|
||||
"map.longitude": 0.0,
|
||||
"map.zoom": 10,
|
||||
@@ -219,5 +220,11 @@ 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)
|
||||
|
||||
(locales & I18n.available_locales).presence || I18n.available_locales
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
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)
|
||||
|
||||
@@ -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)
|
||||
[
|
||||
I18n.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
|
||||
|
||||
@@ -0,0 +1,18 @@
|
||||
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.enabled"] = "de fr"
|
||||
|
||||
render_inline component
|
||||
|
||||
expect(page).to have_select "locale", options: ["de", "fr"]
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -0,0 +1,18 @@
|
||||
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.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,20 @@ 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.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
|
||||
@@ -54,6 +54,22 @@ describe ApplicationController do
|
||||
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) }
|
||||
|
||||
@@ -64,5 +64,21 @@ describe Management::BaseController do
|
||||
|
||||
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
|
||||
|
||||
@@ -28,8 +28,10 @@ describe SubscriptionsController do
|
||||
expect(session[:locale]).to eq "es"
|
||||
end
|
||||
|
||||
it "only accepts available locales" do
|
||||
create(:user, locale: "wl", subscriptions_token: "mytoken")
|
||||
it "only accepts enabled locales" do
|
||||
Setting["locales.enabled"] = "en nl"
|
||||
|
||||
create(:user, locale: "es", subscriptions_token: "mytoken")
|
||||
|
||||
get :edit, params: { token: "mytoken" }
|
||||
|
||||
|
||||
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
|
||||
@@ -20,6 +20,14 @@ describe Budget::ContentBlock do
|
||||
expect(valid_block).to be_valid
|
||||
end
|
||||
|
||||
it "is not valid with a disabled locale" do
|
||||
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"))
|
||||
|
||||
@@ -160,6 +160,16 @@ RSpec.describe I18nContent do
|
||||
end
|
||||
|
||||
it "does not store new keys for disabled translations" do
|
||||
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
|
||||
|
||||
@@ -258,4 +258,50 @@ describe Setting do
|
||||
expect(Setting.force_presence_postal_code?).to be true
|
||||
end
|
||||
end
|
||||
|
||||
describe ".available_locales" do
|
||||
before { allow(I18n).to receive(:available_locales).and_return(%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 "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 es 1234 en SuperCool"
|
||||
|
||||
expect(Setting.enabled_locales).to eq %i[es 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
|
||||
end
|
||||
|
||||
@@ -27,4 +27,12 @@ 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.enabled"] = "nl pt-BR"
|
||||
|
||||
block.locale = "en"
|
||||
|
||||
expect(block).not_to be_valid
|
||||
end
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user