locale detection and selection, refs #4994
Change-Id: I0f1e50d912ba7ac81b9ceb3ae95baaba3a12425b Reviewed-on: https://gerrit.instructure.com/4661 Tested-by: Hudson <hudson@instructure.com> Reviewed-by: Zach Wily <zach@instructure.com>
This commit is contained in:
parent
b5035fe0d4
commit
5e66286c14
|
@ -23,7 +23,9 @@ class ApplicationController < ActionController::Base
|
|||
|
||||
attr_accessor :active_tab
|
||||
|
||||
before_filter :set_locale
|
||||
include LocaleSelection
|
||||
around_filter :set_locale
|
||||
|
||||
add_crumb "home", :root_path, :class => "home"
|
||||
helper :all
|
||||
filter_parameter_logging :password
|
||||
|
@ -43,8 +45,15 @@ class ApplicationController < ActionController::Base
|
|||
protected
|
||||
|
||||
def set_locale
|
||||
# if params[:locale] is nil then I18n.default_locale will be used
|
||||
I18n.locale = params[:locale] && I18n.available_locales.include?(params[:locale].to_sym) ? params[:locale] : nil
|
||||
I18n.localizer = lambda {
|
||||
infer_locale :context => @context,
|
||||
:user => @current_user,
|
||||
:root_account => @domain_root_account,
|
||||
:accept_language => request.headers['Accept-Language']
|
||||
}
|
||||
yield if block_given?
|
||||
ensure
|
||||
I18n.localizer = nil
|
||||
end
|
||||
|
||||
def init_body_classes_and_active_tab
|
||||
|
|
|
@ -19,6 +19,7 @@
|
|||
# Methods added to this helper will be available to all templates in the application.
|
||||
module ApplicationHelper
|
||||
include TextHelper
|
||||
include LocaleSelection
|
||||
|
||||
# Admins of the given context can see the User.name attribute,
|
||||
# but everyone else sees the User.short_name attribute.
|
||||
|
|
|
@ -21,7 +21,7 @@ class Account < ActiveRecord::Base
|
|||
attr_accessible :name, :turnitin_account_id,
|
||||
:turnitin_shared_secret, :turnitin_comments, :turnitin_pledge,
|
||||
:default_time_zone, :parent_account, :settings, :default_storage_quota,
|
||||
:default_storage_quota_mb, :storage_quota, :ip_filters
|
||||
:default_storage_quota_mb, :storage_quota, :ip_filters, :default_locale
|
||||
|
||||
include Workflow
|
||||
belongs_to :parent_account, :class_name => 'Account'
|
||||
|
@ -81,6 +81,13 @@ class Account < ActiveRecord::Base
|
|||
|
||||
scopes_custom_fields
|
||||
|
||||
validates_locale :default_locale, :allow_nil => true
|
||||
|
||||
def default_locale(recurse = false)
|
||||
read_attribute(:default_locale) ||
|
||||
(recurse && parent_account ? parent_account.default_locale(true) : nil)
|
||||
end
|
||||
|
||||
cattr_accessor :account_settings_options
|
||||
self.account_settings_options = {}
|
||||
|
||||
|
|
|
@ -57,7 +57,8 @@ class Course < ActiveRecord::Base
|
|||
:storage_quota_mb,
|
||||
:restrict_enrollments_to_course_dates,
|
||||
:grading_standard,
|
||||
:grading_standard_enabled
|
||||
:grading_standard_enabled,
|
||||
:locale
|
||||
|
||||
serialize :tab_configuration
|
||||
belongs_to :root_account, :class_name => 'Account'
|
||||
|
@ -155,6 +156,7 @@ class Course < ActiveRecord::Base
|
|||
after_save :update_account_associations_if_changed
|
||||
before_validation :verify_unique_sis_source_id
|
||||
validates_length_of :syllabus_body, :maximum => maximum_long_text_length, :allow_nil => true, :allow_blank => true
|
||||
validates_locale :allow_nil => true
|
||||
|
||||
sanitize_field :syllabus_body, Instructure::SanitizeField::SANITIZE
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
class User < ActiveRecord::Base
|
||||
include Context
|
||||
|
||||
attr_accessible :name, :short_name, :time_zone, :show_user_services, :gender, :visible_inbox_types, :avatar_image, :subscribe_to_emails
|
||||
attr_accessible :name, :short_name, :time_zone, :show_user_services, :gender, :visible_inbox_types, :avatar_image, :subscribe_to_emails, :locale
|
||||
attr_accessor :original_id
|
||||
|
||||
before_save :infer_defaults
|
||||
|
@ -170,6 +170,7 @@ class User < ActiveRecord::Base
|
|||
has_a_broadcast_policy
|
||||
|
||||
validates_length_of :name, :maximum => maximum_string_length, :allow_nil => true
|
||||
validates_locale :locale, :browser_locale, :allow_nil => true
|
||||
|
||||
before_save :assign_uuid
|
||||
before_save :update_avatar_image
|
||||
|
|
|
@ -69,6 +69,16 @@
|
|||
</td>
|
||||
<td><%= t(:megabytes_field, "%{text_field} megabytes", :text_field => f.text_field(:default_storage_quota_mb, :style => "width: 50px;", :title => t(:megabytes_tooltip, "megabytes"))) %></td>
|
||||
</tr>
|
||||
<% if available_locales.size > 1 %>
|
||||
<tr>
|
||||
<td><%= f.blabel :default_locale, :default_language, :en => "Default Language" %></td>
|
||||
<td>
|
||||
<% no_language = t(:no_language_preference, "Not set (defaults to %{language})", :language => available_locales[infer_locale(:context => @context.parent_account)]) %>
|
||||
<%= f.select :default_locale, [[no_language, nil]] + available_locales.invert.sort, :selected => @context.default_locale %>
|
||||
<p style="font-size: 0.9em;"><%= t(:default_language_description, "This will override any browser/OS language settings. Preferred languages can still be set at the course/user level.") %></p>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<% if @account.root_account_id == nil %>
|
||||
<tr>
|
||||
<td><%= f.blabel :default_time_zone, :en => "Default Time Zone" %></td>
|
||||
|
|
|
@ -233,6 +233,20 @@ Hashtags should consist of letters, numbers, dashes and underscores (no spaces).
|
|||
<%= @context.restrict_enrollments_to_course_dates ? t('date_restricted', "Users can only access the course between these dates") : t('not_date_restricted', "These dates will not affect course availability") %>
|
||||
</div>
|
||||
</td>
|
||||
<% if available_locales.size > 1 %>
|
||||
</tr><tr>
|
||||
<td style="width: 10%;"><%= f.blabel :locale, :language, :en => "Language" %></td>
|
||||
<td>
|
||||
<span class="course_form">
|
||||
<% no_language = t(:no_language_preference, "Not set (user-configurable, defaults to %{language})", :language => available_locales[infer_locale(:context => @context.account)]) %>
|
||||
<%= f.select :locale, [[no_language, nil]] + available_locales.invert.sort, :selected => @context.locale %>
|
||||
<div style="font-size: 0.8em;">
|
||||
<%= t('language_overrides_preferences', "This will override any user/system language preferences. This is only recommended for foreign language courses") %>
|
||||
</div>
|
||||
</span>
|
||||
<span class="course_info locale"><%= @context.locale ? available_locales[@context.locale] : no_language %></span>
|
||||
</td>
|
||||
<% end %>
|
||||
</tr><tr>
|
||||
<td style="width: 10%;"><%= f.blabel :storage_quota_mb, :storage_quota, :en => "File Storage" %></td>
|
||||
<td>
|
||||
|
|
|
@ -49,10 +49,22 @@
|
|||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<% if available_locales.size > 1 %>
|
||||
<tr>
|
||||
<td><%= f.blabel :locale, :en => "Language" %></td>
|
||||
<td>
|
||||
<% no_language = t(:no_language_preference, "System Default (%{language})", :language => available_locales[infer_locale(:root_account => @domain_root_account, :accept_language => request.headers['Accept-Language'])]) %>
|
||||
<span class="locale display_data"><%= @user.locale ? available_locales[@user.locale] : no_language %></span>
|
||||
<span class="edit_data"><%= f.select :locale, [[no_language, nil]] + available_locales.invert.sort, :selected => @user.locale %>
|
||||
<span style="font-size: 0.8em; color: #888;"><br/><%= t('hints.language', "This will override any browser or account settings.") %></span>
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
<% end %>
|
||||
<tr>
|
||||
<td><%= f.blabel :time_zone, :en => "Time Zone" %></td>
|
||||
<td>
|
||||
<span class="time_zone display_data"><%= @user.time_zone || "None" %></span>
|
||||
<span class="time_zone display_data"><%= @user.time_zone || t(:none, "None") %></span>
|
||||
<span class="edit_data"><%= f.time_zone_select :time_zone, ActiveSupport::TimeZone.us_zones, :model => I18nTimeZone, :default => ((@domain_root_account && @domain_root_account.default_time_zone) || "Mountain Time (US & Canada)") %><%# that default time zone is a value, not text %></span>
|
||||
</td>
|
||||
</tr>
|
||||
|
|
|
@ -73,6 +73,8 @@ end
|
|||
|
||||
I18n.class_eval do
|
||||
class << self
|
||||
attr_writer :localizer
|
||||
|
||||
include ::ActionView::Helpers::TextHelper
|
||||
# if one of the interpolated values is a SafeBuffer (e.g. the result of a
|
||||
# link_to call) or the string itself is, we don't want anything to get
|
||||
|
@ -96,6 +98,11 @@ I18n.class_eval do
|
|||
alias_method_chain :localize, :whitespace_removal
|
||||
|
||||
def translate_with_default_and_count_magic(key, *args)
|
||||
if @localizer
|
||||
self.locale = @localizer.call
|
||||
@localizer = nil
|
||||
end
|
||||
|
||||
default = args.shift if args.first.is_a?(String) || args.size > 1
|
||||
options = args.shift || {}
|
||||
options[:default] ||= if options[:count]
|
||||
|
@ -178,6 +185,21 @@ ActiveRecord::Base.class_eval do
|
|||
I18n.translate(key, default, options)
|
||||
end
|
||||
alias :t :translate
|
||||
|
||||
def validates_locale(*args)
|
||||
options = args.last.is_a?(Hash) ? args.pop : {}
|
||||
args << :locale if args.empty?
|
||||
if options[:allow_nil] && !options[:allow_empty]
|
||||
before_validation do |record|
|
||||
args.each do |field|
|
||||
record.write_attribute(field, nil) if record.read_attribute(field) == ''
|
||||
end
|
||||
end
|
||||
end
|
||||
args.each do |field|
|
||||
validates_inclusion_of field, options.merge(:in => I18n.available_locales.map(&:to_s))
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
en:
|
||||
locales:
|
||||
en: English
|
||||
#es:
|
||||
# locales:
|
||||
# es: Español
|
|
@ -0,0 +1,15 @@
|
|||
class LocalePrefs < ActiveRecord::Migration
|
||||
def self.up
|
||||
add_column :users, :locale, :string
|
||||
add_column :users, :browser_locale, :string
|
||||
add_column :courses, :locale, :string
|
||||
add_column :accounts, :default_locale, :string
|
||||
end
|
||||
|
||||
def self.down
|
||||
remove_column :users, :locale
|
||||
remove_column :users, :browser_locale
|
||||
remove_column :courses, :locale
|
||||
remove_column :accounts, :default_locale
|
||||
end
|
||||
end
|
|
@ -0,0 +1,76 @@
|
|||
module LocaleSelection
|
||||
def infer_locale(options = {})
|
||||
context = options[:context]
|
||||
user = options[:user]
|
||||
root_account = options[:root_account]
|
||||
accept_language = options[:accept_language]
|
||||
|
||||
if context && context.is_a?(Course) && context.locale
|
||||
context.locale
|
||||
elsif user && user.locale
|
||||
user.locale
|
||||
elsif context && context.is_a?(Course) && context.account && (account_locale = context.account.default_locale(true))
|
||||
account_locale
|
||||
elsif context && context.is_a?(Account) && (account_locale = context.default_locale(true))
|
||||
account_locale
|
||||
elsif root_account && root_account.default_locale
|
||||
root_account.default_locale
|
||||
elsif accept_language
|
||||
locale = infer_browser_locale(accept_language, I18n.available_locales)
|
||||
user.update_attribute(:browser_locale, locale) if user && locale && user.browser_locale != locale
|
||||
locale
|
||||
end || I18n.default_locale.to_s
|
||||
end
|
||||
|
||||
QUALITY_VALUE = /;q=([01]\.(\d{0,3})?)/
|
||||
LANGUAGE_RANGE = /([a-zA-Z]{1,8}(-[a-zA-Z]{1,8})*|\*)(#{QUALITY_VALUE})?/
|
||||
SEPARATOR = /\s*,\s*/
|
||||
ACCEPT_LANGUAGE = /\A#{LANGUAGE_RANGE}(#{SEPARATOR}#{LANGUAGE_RANGE})*\z/
|
||||
|
||||
def infer_browser_locale(accept_language, supported_locales)
|
||||
return nil unless accept_language =~ ACCEPT_LANGUAGE
|
||||
supported_locales = supported_locales.map(&:to_s)
|
||||
|
||||
ranges = accept_language.downcase.split(SEPARATOR).map{ |range|
|
||||
quality = (range =~ QUALITY_VALUE) ? $1.to_f : 1
|
||||
[range.sub(/\s*;.*/, ''), quality]
|
||||
}
|
||||
ranges = ranges.sort_by{ |r,| r == '*' ? 1 : -r.count('-') }
|
||||
# we want the longest ranges first (and * last of all), since the "quality
|
||||
# factor assigned to a [language] ... is the quality value of the longest
|
||||
# language-range ... that matches", e.g.
|
||||
# given that i accept 'en, es;q=0.9, en-US;q=0.8'
|
||||
# and canvas is localized in 'en-US' and 'es'
|
||||
# then i should get 'es' (en and en-US ranges both match en-US, and
|
||||
# en-US range is a longer match, so it loses)
|
||||
|
||||
best_locales = supported_locales.inject([]) { |ary, locale|
|
||||
if best_range = ranges.detect { |r, q| r + '-' == (locale.downcase + '-')[0..r.size] || r == '*' }
|
||||
ary << [locale, best_range.last] unless best_range.last == 0
|
||||
end
|
||||
ary
|
||||
}.sort_by{ |l, q| [-q, l.count('-'), l]}
|
||||
# wrt the sorting here, rfc2616 doesn't specify which tag is preferable
|
||||
# if there is a quality tie (due to prefix matching or otherwise).
|
||||
# technically they are equally acceptable, though we'll just always go
|
||||
# with the shorter one (and then alphabetical). this seems reasonable for
|
||||
# scenarios like the following:
|
||||
# given that i accept 'en'
|
||||
# and canvas is localized in 'en-US', 'en-GB-oy' and 'en-CA-eh'
|
||||
# then i should get 'en-US'
|
||||
|
||||
best_locales.first && best_locales.first.first
|
||||
end
|
||||
|
||||
# gives you a hash of localized locales, e.g. {:en => "English", :es => "Español" }
|
||||
# if the locale name is not yet translated, it won't be included (even if
|
||||
# there are other translations for that locale)
|
||||
def available_locales
|
||||
I18n.available_locales.inject({}) do |hash, locale|
|
||||
name = I18n.send(:t, "locales", :locale => locale)[locale]
|
||||
hash[locale.to_s] = name if name
|
||||
hash
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
@ -268,7 +268,6 @@ I18n.scoped('course_details', function(I18n) {
|
|||
$(".course_form_more_options").hide();
|
||||
},
|
||||
success: function(data) {
|
||||
$(this).loadingImage('remove');
|
||||
var course = data.course;
|
||||
course.start_at = $.parseFromISO(course.start_at).datetime_formatted;
|
||||
course.conclude_at = $.parseFromISO(course.conclude_at).datetime_formatted;
|
||||
|
@ -276,6 +275,12 @@ I18n.scoped('course_details', function(I18n) {
|
|||
course.indexed = course.indexed ? I18n.t('indexed_course', "Included in public course index") : "";
|
||||
course.grading_scheme_set = course.grading_standard_title || (course.grading_standard_id ? I18n.t('grading_standard_set', "Currently Set") : I18n.t('grading_standard_unset', "Not Set"));
|
||||
course.restrict_dates = course.restrict_enrollments_to_course_dates ? I18n.t('course_dates_enforced', "Users can only access the course between these dates") : I18n.t('course_dates_unenforced', "These dates will not affect course availability");
|
||||
course.locale = $("#course_locale option[value='" + (course.locale || '') + "']").text();
|
||||
if (course.locale != $course_form.find('.locale').text()) {
|
||||
location.reload();
|
||||
return;
|
||||
}
|
||||
$(this).loadingImage('remove');
|
||||
$("#course_form .public_options").showIf(course.is_public);
|
||||
$("#course_form .self_enrollment_message").css('display', course.self_enrollment ? '' : 'none');
|
||||
$("#course_form").fillTemplateData({data: course});
|
||||
|
|
|
@ -74,6 +74,16 @@ $(function() {
|
|||
},
|
||||
success: function(data) {
|
||||
var user = data.user;
|
||||
var templateData = {
|
||||
short_name: user.short_name,
|
||||
full_name: user.name,
|
||||
time_zone: user.time_zone,
|
||||
locale: $("#user_locale option[value='" + user.locale + "']").text()
|
||||
};
|
||||
if (templateData.locale != $update_profile_form.find('.locale').text()) {
|
||||
location.reload();
|
||||
return;
|
||||
}
|
||||
$update_profile_form.loadingImage('remove');
|
||||
if ($default_email_id.length > 0) {
|
||||
var default_email = $default_email_id.find('option:selected').text();
|
||||
|
@ -81,11 +91,6 @@ $(function() {
|
|||
}
|
||||
$('.channel').removeClass('default');
|
||||
$("#channel_" + user.communication_channel.id).addClass('default');
|
||||
var templateData = {
|
||||
short_name: user.short_name,
|
||||
full_name: user.name,
|
||||
time_zone: user.time_zone
|
||||
};
|
||||
$update_profile_form.fillTemplateData({
|
||||
data: templateData
|
||||
}).find(".cancel_button").click();
|
||||
|
|
|
@ -0,0 +1,47 @@
|
|||
#
|
||||
# Copyright (C) 2011 Instructure, Inc.
|
||||
#
|
||||
# This file is part of Canvas.
|
||||
#
|
||||
# Canvas is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU Affero General Public License as published by the Free
|
||||
# Software Foundation, version 3 of the License.
|
||||
#
|
||||
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
||||
|
||||
describe "locale_selection" do
|
||||
before do
|
||||
I18n.stub!(:available_locales).and_return([:en, :es, :fr])
|
||||
end
|
||||
|
||||
after do
|
||||
I18n.locale = nil
|
||||
end
|
||||
|
||||
it "should set the locale when authenticated" do
|
||||
course_with_teacher(:active_all => true, :user => user_with_pseudonym)
|
||||
user_session(@user, @pseudonym)
|
||||
@user.update_attribute :locale, 'es'
|
||||
get dashboard_url
|
||||
response.should be_success
|
||||
I18n.locale.should eql(:es)
|
||||
end
|
||||
|
||||
it "should set the locale when not authenticated" do
|
||||
account = Account.default
|
||||
account.update_attribute :default_locale, 'fr'
|
||||
get login_url
|
||||
response.should be_success
|
||||
I18n.locale.should eql(:fr)
|
||||
end
|
||||
|
||||
end
|
|
@ -0,0 +1,153 @@
|
|||
#
|
||||
# Copyright (C) 2011 Instructure, Inc.
|
||||
#
|
||||
# This file is part of Canvas.
|
||||
#
|
||||
# Canvas is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU Affero General Public License as published by the Free
|
||||
# Software Foundation, version 3 of the License.
|
||||
#
|
||||
# Canvas is distributed in the hope that it will be useful, but WITHOUT ANY
|
||||
# WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR
|
||||
# A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
|
||||
# details.
|
||||
#
|
||||
# You should have received a copy of the GNU Affero General Public License along
|
||||
# with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
#
|
||||
|
||||
require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
|
||||
|
||||
describe LocaleSelection do
|
||||
class TestClassForMixins
|
||||
extend LocaleSelection
|
||||
end
|
||||
|
||||
def ls
|
||||
TestClassForMixins
|
||||
end
|
||||
|
||||
context 'accept-language' do
|
||||
it "should ignore malformed accept-language headers" do
|
||||
ls.infer_browser_locale("en not valid", ['en']).should be_nil
|
||||
end
|
||||
|
||||
it "should match valid locale ranges" do
|
||||
ls.infer_browser_locale("en", ['en']).should eql('en')
|
||||
end
|
||||
|
||||
it "should not match invalid locale ranges" do
|
||||
ls.infer_browser_locale("it", ['en']).should be_nil
|
||||
end
|
||||
|
||||
it "should do case-insensitive matching" do
|
||||
ls.infer_browser_locale("en-us", ['en-US']).should eql('en-US')
|
||||
end
|
||||
|
||||
# see rfc2616 ... en means any en(-.*)? is acceptable
|
||||
it "should do range prefix-matching" do
|
||||
ls.infer_browser_locale("en", ['en-US']).should eql('en-US')
|
||||
end
|
||||
|
||||
# while tag prefix-matching might be desirable (sometimes), it should not
|
||||
# be done automatically on the server-side (though the user-agent can do
|
||||
# it). from the rfc:
|
||||
# [U]sers might [incorrectly] assume that on selecting "en-gb", they
|
||||
# will be served any kind of English document if British English is not
|
||||
# available. A user agent might suggest in such a case to add "en" to
|
||||
# get the best matching behavior.
|
||||
it "should not do tag prefix-matching" do
|
||||
ls.infer_browser_locale("en-US", ['en']).should be_nil
|
||||
end
|
||||
|
||||
it "should assign quality values based on the best match" do
|
||||
ls.infer_browser_locale("en-US, es;q=0.9, en;q=0.8", ['en-US', 'es']).should eql('en-US')
|
||||
|
||||
# no tag prefix-matching
|
||||
ls.infer_browser_locale("en-US, es;q=0.9, en;q=0.8", ['en', 'es']).should eql('es')
|
||||
|
||||
# order doesn't matter
|
||||
ls.infer_browser_locale("es;q=0.9, en", ['en', 'es']).should eql('en')
|
||||
|
||||
# although the en range matches the en-US tag, the en-US range is
|
||||
# a better (read: longer) match. so the es tag ends up with a higher
|
||||
# quality value than en-US tag
|
||||
ls.infer_browser_locale("en, es;q=0.9, en-US;q=0.8", ['en-US', 'es']).should eql('es')
|
||||
end
|
||||
|
||||
it "should understand wildcards" do
|
||||
ls.infer_browser_locale("*, pt;q=0.8", ['ru', 'pt']).should eql('ru')
|
||||
ls.infer_browser_locale("*, pt;q=0.8, ru;q=0.7", ['ru', 'pt']).should eql('pt')
|
||||
# the pt range is explicitly rejected, so we don't get a locale
|
||||
ls.infer_browser_locale("pt-BR, *;q=0.9, pt;q=0", ['pt']).should be_nil
|
||||
# no pt variants supported, so we get the first alternative
|
||||
ls.infer_browser_locale("pt-BR, pt;q=0.9, *;q=0.8", ['es', 'fr']).should eql('es')
|
||||
end
|
||||
end
|
||||
|
||||
context "locale matching" do
|
||||
before do
|
||||
I18n.stub!(:available_locales).and_return([:en, :it, :es, :fr, :de, :pt])
|
||||
@root_account = Account.create
|
||||
@account = Account.create(:parent_account => @root_account)
|
||||
user
|
||||
course
|
||||
@course.account = @account
|
||||
@course.save
|
||||
end
|
||||
|
||||
it "should use the default locale if there is no other context" do
|
||||
ls.infer_locale.should eql('en')
|
||||
ls.infer_locale(:root_account => @root_account).should eql('en')
|
||||
ls.infer_locale(:root_account => @root_account, :user => @user).should eql('en')
|
||||
ls.infer_locale(:root_account => @root_account, :user => @user, :context => @course).should eql('en')
|
||||
end
|
||||
|
||||
it "should infer the locale from the accept_language" do
|
||||
ls.infer_locale(:accept_language => "it", :root_account => @root_account).should eql('it')
|
||||
@user.browser_locale.should be_nil
|
||||
ls.infer_locale(:accept_language => "it", :root_account => @root_account, :user => @user).should eql('it')
|
||||
@user.browser_locale.should eql('it')
|
||||
ls.infer_locale(:accept_language => "it", :root_account => @root_account, :user => @user, :context => @account).should eql('it')
|
||||
ls.infer_locale(:accept_language => "it", :root_account => @root_account, :user => @user, :context => @course).should eql('it')
|
||||
end
|
||||
|
||||
it "should infer the locale from the root account" do
|
||||
@root_account.update_attribute(:default_locale, 'es')
|
||||
|
||||
ls.infer_locale(:accept_language => "it", :root_account => @root_account, :user => @user).should eql('es')
|
||||
ls.infer_locale(:accept_language => "it", :root_account => @root_account, :user => @user, :context => @account).should eql('es')
|
||||
ls.infer_locale(:accept_language => "it", :root_account => @root_account, :user => @user, :context => @course).should eql('es')
|
||||
end
|
||||
|
||||
it "should infer the locale from the account" do
|
||||
@root_account.update_attribute(:default_locale, 'es')
|
||||
@account.update_attribute(:default_locale, 'fr')
|
||||
|
||||
ls.infer_locale(:accept_language => "it", :root_account => @root_account, :user => @user).should eql('es')
|
||||
ls.infer_locale(:accept_language => "it", :root_account => @root_account, :user => @user, :context => @account).should eql('fr')
|
||||
ls.infer_locale(:accept_language => "it", :root_account => @root_account, :user => @user, :context => @course).should eql('fr')
|
||||
end
|
||||
|
||||
it "should infer the locale from the user" do
|
||||
@root_account.update_attribute(:default_locale, 'es')
|
||||
@account.update_attribute(:default_locale, 'fr')
|
||||
@user.update_attribute(:locale, 'de')
|
||||
|
||||
ls.infer_locale(:accept_language => "it", :root_account => @root_account, :user => @user).should eql('de')
|
||||
ls.infer_locale(:accept_language => "it", :root_account => @root_account, :user => @user, :context => @account).should eql('de')
|
||||
ls.infer_locale(:accept_language => "it", :root_account => @root_account, :user => @user, :context => @course).should eql('de')
|
||||
end
|
||||
|
||||
it "should infer the locale from the course" do
|
||||
@root_account.update_attribute(:default_locale, 'es')
|
||||
@account.update_attribute(:default_locale, 'fr')
|
||||
@user.update_attribute(:locale, 'de')
|
||||
@course.update_attribute(:locale, 'pt')
|
||||
|
||||
ls.infer_locale(:accept_language => "it", :root_account => @root_account, :user => @user).should eql('de')
|
||||
ls.infer_locale(:accept_language => "it", :root_account => @root_account, :user => @user, :context => @account).should eql('de')
|
||||
ls.infer_locale(:accept_language => "it", :root_account => @root_account, :user => @user, :context => @course).should eql('pt')
|
||||
end
|
||||
end
|
||||
end
|
Loading…
Reference in New Issue