Skip to content

Commit

Permalink
Add language switching mechanism
Browse files Browse the repository at this point in the history
Continuing to add support for #233, this commit adds a language switcher
element to the secondary navigation bar. The base application controller
now inspects the user's language choice, whether by URL parameter or by
HTTP header, and sets the `I18n.locale` accordingly.
  • Loading branch information
ijdickinson committed Aug 4, 2020
1 parent f0ae10f commit f164aae
Show file tree
Hide file tree
Showing 13 changed files with 119 additions and 4 deletions.
1 change: 1 addition & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ gem 'sentry-raven'

gem 'faraday'
gem 'faraday_middleware'
gem 'http_accept_language'
gem 'puma'
gem 'yajl-ruby', require: 'yajl'

Expand Down
2 changes: 2 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -134,6 +134,7 @@ GEM
haml (>= 4.0, < 6)
nokogiri (>= 1.6.0)
ruby_parser (~> 3.5)
http_accept_language (2.1.1)
i18n (1.8.5)
concurrent-ruby (~> 1.0)
js-routes (1.4.9)
Expand Down Expand Up @@ -322,6 +323,7 @@ DEPENDENCIES
govuk_template
haml-lint
haml-rails
http_accept_language
js-routes
json_expressions
m
Expand Down
6 changes: 6 additions & 0 deletions app/assets/stylesheets/_ukhpi-header.scss
Original file line number Diff line number Diff line change
Expand Up @@ -40,3 +40,9 @@
.u-active {
border-bottom: 2px solid $black;
}

.o-secondary-banner {
display: flex;
flex-direction: row;
justify-content: space-between;
}
15 changes: 15 additions & 0 deletions app/controllers/application_controller.rb
Original file line number Diff line number Diff line change
Expand Up @@ -5,4 +5,19 @@ class ApplicationController < ActionController::Base
# Prevent CSRF attacks by raising an exception.
# For APIs, you may want to use :null_session instead.
protect_from_forgery with: :exception

before_action :set_locale

private

# Set the user's preferred locale. An explicit locale set via
# the URL param `lang` is preeminent, otherwise we look to the
# user's preferred language specified via browser headers
def set_locale
user_locale =
params['lang'] ||
http_accept_language.compatible_language_from(I18n.available_locales)

I18n.locale = user_locale if user_locale
end
end
16 changes: 16 additions & 0 deletions app/models/concerns/user_language.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,16 @@
# frozen_string_literal: true

# Shared code for working with user lanuage choices
module UserLanguage
def english?
I18n.locale != :cy
end

def welsh?
I18n.locale == :cy
end

def alternative_language_params
with('lang', english? ? 'cy' : 'en')
end
end
2 changes: 2 additions & 0 deletions app/models/user_compare_selections.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
# each other
class UserCompareSelections
include UserChoices
include UserLanguage

DEFAULT_INDICATOR = 'hpi'
DEFAULT_STATISTIC = 'all'
Expand All @@ -16,6 +17,7 @@ class UserCompareSelections
'to' => Struct::UserParam.new(Time.zone.today, false, nil),
'st' => Struct::UserParam.new(DEFAULT_STATISTIC, false, nil),
'in' => Struct::UserParam.new(DEFAULT_INDICATOR, false, nil),
'lang' => Struct::UserParam.new(:en, false, nil),

# used by selections update form
'form-action' => Struct::UserParam.new(nil, false, nil),
Expand Down
3 changes: 3 additions & 0 deletions app/models/user_selections.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@
class UserSelections # rubocop:disable Metrics/ClassLength
include UserChoices
include UserSelectionValidations
include UserLanguage

DEFAULT_INDICATORS = %w[hpi avg pmc pac].freeze
DEFAULT_STATISTICS = %w[all].freeze
DEFAULT_NON_PT_INDICATORS = %w[salesVolume].freeze
DEFAULT_REGION = 'http://landregistry.data.gov.uk/id/region/united-kingdom'
DEFAULT_REGION_TYPE = 'country'
DEFAULT_THEMES = %w[property_type volume].freeze
DEFAULT_LANGUAGE = 'en'

USER_PARAMS_MODEL = {
'location' => Struct::UserParam.new(DEFAULT_REGION, false, nil),
Expand All @@ -31,6 +33,7 @@ class UserSelections # rubocop:disable Metrics/ClassLength
'st' => Struct::UserParam.new(DEFAULT_STATISTICS, true, nil),
'in' => Struct::UserParam.new(DEFAULT_INDICATORS, true, nil),
'thm' => Struct::UserParam.new(DEFAULT_THEMES, true, nil),
'lang' => Struct::UserParam.new(DEFAULT_LANGUAGE, false, nil),

# used by selections update form
'form-action' => Struct::UserParam.new(nil, false, nil),
Expand Down
1 change: 1 addition & 0 deletions app/presenters/compare_locations_presenter.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ class CompareLocationsPresenter # rubocop:disable Metrics/ClassLength
include LocationsTable

attr_reader :user_compare_selections, :query_results
alias user_selections user_compare_selections

def initialize(user_compare_selections, query_results)
@user_compare_selections = user_compare_selections
Expand Down
5 changes: 5 additions & 0 deletions app/services/language_selector.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
# frozen_string_literal: true

# Shared service for managing user language selection
class LanguageSelector
end
17 changes: 14 additions & 3 deletions app/views/common/_header.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,20 @@
.o-lr-top-bar

.container.o-container
.o-beta-banner
%p
.o-secondary-banner
.o-secondary-banner__phase-tag
%strong.o-beta-tag
= t('common.header.beta_tag')
%span.text-muted
= t('common.header.feedback_request').html_safe
= t('common.header.feedback_request').html_safe

.o-secondary-banner__lang-select
- if @view_state.user_selections.english?
English
- else
= link_to('English', @view_state.user_selections.alternative_language_params.params)
|
- if @view_state.user_selections.welsh?
Cymraeg
- else
= link_to('Cymraeg', @view_state.user_selections.alternative_language_params.params)
2 changes: 1 addition & 1 deletion app/views/layouts/application.html.haml
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
= render partial: 'common/flash_message'

%main.container.o-container
.o-beta-banner
.o-secondary-banner
%p
%strong.o-beta-tag BETA
%span.text-muted
Expand Down
6 changes: 6 additions & 0 deletions config/locales/cy.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
cy:
common:
header:
home_link: "!!! Go to the UK HPI homepage"
app_title: "!!! UK House Price Index"
beta_tag: "!!! BETA"
47 changes: 47 additions & 0 deletions test/models/user_selections_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -230,5 +230,52 @@ class UserSelectionsTest < ActiveSupport::TestCase
_(selections.valid?).must_equal(false)
end
end

describe 'language handling' do
it 'should return English as the default' do
selections = user_selections({})
assert selections.english?
assert_not selections.welsh?
end

it 'should return Welsh when that language is selected' do
selections = user_selections('lang' => 'cy')
assert_not selections.english?
assert selections.welsh?
end

it 'should return English when that language is selected' do
selections = user_selections('lang' => 'en')
assert selections.english?
assert_not selections.welsh?
end

it 'should ignore other languages' do
selections = user_selections('lang' => 'fr')
assert selections.english?
assert_not selections.welsh?
end

it 'should generate the correct Welsh language options' do
selections = user_selections(
'from' => '2017-01'
)

alt_params = selections.alternative_language_params
_(alt_params.params['from']).must_equal('2017-01')
_(alt_params.params['lang']).must_equal('cy')
end

it 'should generate the correct English language options' do
selections = user_selections(
'from' => '2017-01',
'lang' => 'cy'
)

alt_params = selections.alternative_language_params
_(alt_params.params['from']).must_equal('2017-01')
_(alt_params.params['lang']).must_equal('en')
end
end
end
end

0 comments on commit f164aae

Please sign in to comment.