FEATURE: English locale with international date formats

Makes en_US the new default locale
This commit is contained in:
Gerhard Schlager 2019-05-15 23:43:00 +02:00
parent a58aa9b4bf
commit b788948985
44 changed files with 274 additions and 90 deletions

View File

@ -13,8 +13,8 @@ This PR doesn't match our required code formatting standards, as enforced by pre
}) })
end end
locales_changes = git.modified_files.grep(/config\/locales/) locales_changes = git.modified_files.grep(%r{config/locales})
has_non_en_locales_changes = locales_changes.grep_v(/config\/locales\/(client|server)\.en\.yml/).any? has_non_en_locales_changes = locales_changes.grep_v(%r{config/locales/(?:client|server)\.(?:en|en_US)\.yml}).any?
if locales_changes.any? && has_non_en_locales_changes if locales_changes.any? && has_non_en_locales_changes
fail("Please submit your non-English translation updates via [Transifex](https://www.transifex.com/discourse/discourse-org/). You can read more on how to contribute translations [here](https://meta.discourse.org/t/contribute-a-translation-to-discourse/14882).") fail("Please submit your non-English translation updates via [Transifex](https://www.transifex.com/discourse/discourse-org/). You can read more on how to contribute translations [here](https://meta.discourse.org/t/contribute-a-translation-to-discourse/14882).")

View File

@ -0,0 +1,5 @@
//= depend_on 'client.en_US.yml'
//= require locales/i18n
<% JsLocaleHelper.reloadable_plugins(:en_US, self) %>
<%= JsLocaleHelper.output_locale(:en_US) %>

View File

@ -17,7 +17,7 @@
//= require_tree ./acceptance //= require_tree ./acceptance
//= require_tree ./models //= require_tree ./models
//= require_tree ./components //= require_tree ./components
//= require locales/en //= require locales/en_US
//= require fake_xml_http_request //= require fake_xml_http_request
//= require route-recognizer/dist/route-recognizer //= require route-recognizer/dist/route-recognizer
//= require pretender/pretender //= require pretender/pretender

View File

@ -324,7 +324,7 @@ class ApplicationController < ActionController::Base
locale = current_user.effective_locale locale = current_user.effective_locale
end end
I18n.locale = I18n.locale_available?(locale) ? locale : :en I18n.locale = I18n.locale_available?(locale) ? locale : SiteSettings::DefaultsProvider::DEFAULT_LOCALE
I18n.ensure_all_loaded! I18n.ensure_all_loaded!
end end

View File

@ -221,7 +221,7 @@ module Jobs
RailsMultisite::ConnectionManagement.with_connection(db) do RailsMultisite::ConnectionManagement.with_connection(db) do
job_instrumenter = JobInstrumenter.new(job_class: self.class, opts: opts, db: db, jid: jid) job_instrumenter = JobInstrumenter.new(job_class: self.class, opts: opts, db: db, jid: jid)
begin begin
I18n.locale = SiteSetting.default_locale || "en" I18n.locale = SiteSetting.default_locale || SiteSettings::DefaultsProvider::DEFAULT_LOCALE
I18n.ensure_all_loaded! I18n.ensure_all_loaded!
begin begin
logster_env = {} logster_env = {}

View File

@ -57,7 +57,14 @@ class LocaleSiteSetting < EnumSiteSetting
end end
end end
FALLBACKS ||= {
en_US: :en
}
def self.fallback_locale(locale) def self.fallback_locale(locale)
fallback_locale = FALLBACKS[locale.to_sym]
return fallback_locale if fallback_locale
plugin_locale = DiscoursePluginRegistry.locales[locale.to_s] plugin_locale = DiscoursePluginRegistry.locales[locale.to_s]
plugin_locale ? plugin_locale[:fallbackLocale]&.to_sym : nil plugin_locale ? plugin_locale[:fallbackLocale]&.to_sym : nil
end end

View File

@ -66,8 +66,7 @@ class TranslationOverride < ActiveRecord::Base
def check_interpolation_keys def check_interpolation_keys
original_text = I18n.overrides_disabled do original_text = I18n.overrides_disabled do
# lookup is protected I18n.t(translation_key, locale: :en)
I18n.backend.send(:lookup, self.locale, self.translation_key)
end end
if original_text if original_text

View File

@ -38,31 +38,31 @@ en:
millions: "{{number}}M" millions: "{{number}}M"
dates: dates:
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/ # Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
time: "h:mm a" time: "HH:mm"
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/ # Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
timeline_date: "MMM YYYY" timeline_date: "MMM YYYY"
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/ # Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
long_no_year: "MMM D h:mm a" long_no_year: "D MMM HH:mm"
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/ # Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
long_no_year_no_time: "MMM D" long_no_year_no_time: "D MMM"
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/ # Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
full_no_year_no_time: "MMMM Do" full_no_year_no_time: "Do MMMM"
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/ # Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
long_with_year: "MMM D, YYYY h:mm a" long_with_year: "D MMM YYYY HH:mm"
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/ # Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
long_with_year_no_time: "MMM D, YYYY" long_with_year_no_time: "D MMM YYYY"
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/ # Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
full_with_year_no_time: "MMMM Do, YYYY" full_with_year_no_time: "D MMMM YYYY"
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/ # Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
long_date_with_year: "MMM D, 'YY LT" long_date_with_year: "D MMM 'YY LT"
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/ # Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
long_date_without_year: "MMM D, LT" long_date_without_year: "D MMM LT"
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/ # Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
long_date_with_year_without_time: "MMM D, 'YY" long_date_with_year_without_time: "D MMM 'YY"
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/ # Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
long_date_without_year_with_linebreak: "MMM D <br/>LT" long_date_without_year_with_linebreak: "D MMM <br/>LT"
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/ # Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
long_date_with_year_with_linebreak: "MMM D, 'YY <br/>LT" long_date_with_year_with_linebreak: "D MMM 'YY <br/>LT"
wrap_ago: "%{date} ago" wrap_ago: "%{date} ago"
@ -98,7 +98,9 @@ en:
almost_x_years: almost_x_years:
one: "1y" one: "1y"
other: "%{count}y" other: "%{count}y"
date_month: "MMM D" # Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
date_month: "D MMM"
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
date_year: "MMM 'YY" date_year: "MMM 'YY"
medium: medium:
x_minutes: x_minutes:
@ -110,7 +112,8 @@ en:
x_days: x_days:
one: "1 day" one: "1 day"
other: "%{count} days" other: "%{count} days"
date_year: "MMM D, 'YY" # Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
date_year: "D MMM 'YY"
medium_with_ago: medium_with_ago:
x_minutes: x_minutes:
one: "1 min ago" one: "1 min ago"

View File

@ -0,0 +1,38 @@
en_US:
js:
dates:
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
time: "h:mm a"
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
timeline_date: "MMM YYYY"
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
long_no_year: "MMM D h:mm a"
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
long_no_year_no_time: "MMM D"
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
full_no_year_no_time: "MMMM Do"
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
long_with_year: "MMM D, YYYY h:mm a"
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
long_with_year_no_time: "MMM D, YYYY"
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
full_with_year_no_time: "MMMM Do, YYYY"
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
long_date_with_year: "MMM D, 'YY LT"
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
long_date_without_year: "MMM D, LT"
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
long_date_with_year_without_time: "MMM D, 'YY"
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
long_date_without_year_with_linebreak: "MMM D <br/>LT"
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
long_date_with_year_with_linebreak: "MMM D, 'YY <br/>LT"
tiny:
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
date_month: "MMM D"
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
date_year: "MMM 'YY"
medium:
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
date_year: "MMM D, 'YY"

View File

@ -113,6 +113,9 @@ el:
en: en:
name: English name: English
nativeName: English nativeName: English
en_US:
name: English (United States)
nativeName: English (United States)
eo: eo:
name: Esperanto name: Esperanto
nativeName: Esperanto nativeName: Esperanto

View File

@ -19,21 +19,21 @@ en:
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/ # Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
short_date_no_year: "D MMM" short_date_no_year: "D MMM"
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/ # Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
short_date: "D MMM, YYYY" short_date: "D MMM YYYY"
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/ # Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
long_date: "MMMM D, YYYY h:mma" long_date: "D MMMM YYYY LT"
datetime_formats: &datetime_formats datetime_formats: &datetime_formats
formats: formats:
# Format directives: https://ruby-doc.org/core-2.6.1/Time.html#method-i-strftime # Format directives: https://ruby-doc.org/core/Time.html#method-i-strftime
short: "%m-%d-%Y" short: "%d-%m-%Y"
# Format directives: https://ruby-doc.org/core-2.6.1/Time.html#method-i-strftime # Format directives: https://ruby-doc.org/core/Time.html#method-i-strftime
short_no_year: "%B %-d" short_no_year: "%-d %B"
# Format directives: https://ruby-doc.org/core-2.6.1/Time.html#method-i-strftime # Format directives: https://ruby-doc.org/core/Time.html#method-i-strftime
date_only: "%B %-d, %Y" date_only: "%-d %B %Y"
# Format directives: https://ruby-doc.org/core-2.6.1/Time.html#method-i-strftime # Format directives: https://ruby-doc.org/core/Time.html#method-i-strftime
long: "%B %-d, %Y, %l:%M%P" long: "%-d %B %Y %H:%M"
# Format directives: https://ruby-doc.org/core-2.6.1/Time.html#method-i-strftime # Format directives: https://ruby-doc.org/core/Time.html#method-i-strftime
no_day: "%B %Y" no_day: "%B %Y"
date: date:
# Do not remove the brackets and commas and do not translate the first month name. It should be "null". # Do not remove the brackets and commas and do not translate the first month name. It should be "null".
@ -1710,6 +1710,7 @@ en:
max_image_megapixels: "Maximum number of megapixels allowed for an image." max_image_megapixels: "Maximum number of megapixels allowed for an image."
title_prettify: "Prevent common title typos and errors, including all caps, lowercase first character, multiple ! and ?, extra . at end, etc." title_prettify: "Prevent common title typos and errors, including all caps, lowercase first character, multiple ! and ?, extra . at end, etc."
title_remove_extraneous_space: "Remove leading whitespaces in front of the end punctiation."
topic_views_heat_low: "After this many views, the views field is slightly highlighted." topic_views_heat_low: "After this many views, the views field is slightly highlighted."
topic_views_heat_medium: "After this many views, the views field is moderately highlighted." topic_views_heat_medium: "After this many views, the views field is moderately highlighted."

View File

@ -0,0 +1,25 @@
en_US:
dates:
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
short_date_no_year: "D MMM"
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
short_date: "D MMM, YYYY"
# Use Moment.js format string: https://momentjs.com/docs/#/displaying/format/
long_date: "MMMM D, YYYY h:mma"
datetime_formats: &datetime_formats
formats:
# Format directives: https://ruby-doc.org/core/Time.html#method-i-strftime
short: "%m-%d-%Y"
# Format directives: https://ruby-doc.org/core/Time.html#method-i-strftime
short_no_year: "%B %-d"
# Format directives: https://ruby-doc.org/core/Time.html#method-i-strftime
date_only: "%B %-d, %Y"
# Format directives: https://ruby-doc.org/core/Time.html#method-i-strftime
long: "%B %-d, %Y, %l:%M%P"
# Format directives: https://ruby-doc.org/core/Time.html#method-i-strftime
no_day: "%B %Y"
date:
<<: *datetime_formats
time:
<<: *datetime_formats

View File

@ -639,6 +639,11 @@ posting:
ja: false ja: false
zh_CN: false zh_CN: false
zh_TW: false zh_TW: false
title_remove_extraneous_space:
default: false
locale_default:
en: true
en_US: true
title_fancy_entities: true title_fancy_entities: true
min_personal_message_title_length: min_personal_message_title_length:
client: true client: true

View File

@ -0,0 +1,55 @@
# frozen_string_literal: true
class MigrateEnglishLocale < ActiveRecord::Migration[5.2]
def up
execute <<~SQL
UPDATE users
SET locale = 'en_US'
WHERE locale = 'en'
SQL
execute <<~SQL
UPDATE site_settings
SET value = 'en_US'
WHERE name = 'default_locale' AND value = 'en'
SQL
execute <<~SQL
UPDATE translation_overrides
SET locale = 'en_US'
WHERE locale = 'en'
SQL
execute <<~SQL
UPDATE theme_translation_overrides
SET locale = 'en_US'
WHERE locale = 'en'
SQL
end
def down
execute <<~SQL
UPDATE users
SET locale = 'en'
WHERE locale = 'en_US'
SQL
execute <<~SQL
UPDATE site_settings
SET value = 'en'
WHERE name = 'default_locale' AND value = 'en_US'
SQL
execute <<~SQL
UPDATE translation_overrides
SET locale = 'en'
WHERE locale = 'en_US'
SQL
execute <<~SQL
UPDATE theme_translation_overrides
SET locale = 'en'
WHERE locale = 'en_US'
SQL
end
end

View File

@ -127,8 +127,7 @@ module JsLocaleHelper
fallback_locale_str = LocaleSiteSetting.fallback_locale(locale_str)&.to_s fallback_locale_str = LocaleSiteSetting.fallback_locale(locale_str)&.to_s
translations = Marshal.load(Marshal.dump(translations_for(locale_str))) translations = Marshal.load(Marshal.dump(translations_for(locale_str)))
message_formats = strip_out_message_formats!(translations[locale_str]['js']) message_formats = remove_message_formats!(translations, locale)
message_formats.merge!(strip_out_message_formats!(translations[locale_str]['admin_js']))
mf_locale, mf_filename = find_message_format_locale([locale_str], fallback_to_english: true) mf_locale, mf_filename = find_message_format_locale([locale_str], fallback_to_english: true)
result = generate_message_format(message_formats, mf_locale, mf_filename) result = generate_message_format(message_formats, mf_locale, mf_filename)
@ -155,7 +154,8 @@ module JsLocaleHelper
end end
MOMENT_LOCALE_MAPPING ||= { MOMENT_LOCALE_MAPPING ||= {
"hy" => "hy-am" "hy" => "hy-am",
"en" => "en-gb"
} }
def self.find_moment_locale(locale_chain, timezone_names: false) def self.find_moment_locale(locale_chain, timezone_names: false)
@ -259,18 +259,33 @@ module JsLocaleHelper
"function(){ return #{message.inspect};}" "function(){ return #{message.inspect};}"
end end
def self.strip_out_message_formats!(hash, prefix = "", rval = {}) def self.remove_message_formats!(translations, locale)
message_formats = {}
I18n.fallbacks[locale].map(&:to_s).each do |l|
next unless translations.key?(l)
%w{js admin_js}.each do |k|
message_formats.merge!(strip_out_message_formats!(translations[l][k]))
end
end
message_formats
end
def self.strip_out_message_formats!(hash, prefix = "", message_formats = {})
if hash.is_a?(Hash) if hash.is_a?(Hash)
hash.each do |key, value| hash.each do |key, value|
if value.is_a?(Hash) if value.is_a?(Hash)
rval.merge!(strip_out_message_formats!(value, prefix + (prefix.length > 0 ? "." : "") << key, rval)) message_formats.merge!(strip_out_message_formats!(value, join_key(prefix, key), message_formats))
elsif key.to_s.end_with?("_MF") elsif key.to_s.end_with?("_MF")
rval[prefix + (prefix.length > 0 ? "." : "") << key] = value message_formats[join_key(prefix, key)] = value
hash.delete(key) hash.delete(key)
end end
end end
end end
rval message_formats
end end
def self.join_key(prefix, key)
prefix.blank? ? key : "#{prefix}.#{key}"
end
end end

View File

@ -4,7 +4,7 @@ module SiteSettings; end
# A cache for providing default value based on site locale # A cache for providing default value based on site locale
class SiteSettings::DefaultsProvider class SiteSettings::DefaultsProvider
DEFAULT_LOCALE = 'en' DEFAULT_LOCALE = 'en_US'
def initialize(site_setting) def initialize(site_setting)
@site_setting = site_setting @site_setting = site_setting

View File

@ -17,7 +17,7 @@ class TextCleaner
replace_all_upper_case: SiteSetting.title_prettify && !SiteSetting.allow_uppercase_posts, replace_all_upper_case: SiteSetting.title_prettify && !SiteSetting.allow_uppercase_posts,
capitalize_first_letter: SiteSetting.title_prettify, capitalize_first_letter: SiteSetting.title_prettify,
remove_all_periods_from_the_end: SiteSetting.title_prettify, remove_all_periods_from_the_end: SiteSetting.title_prettify,
remove_extraneous_space: SiteSetting.title_prettify && SiteSetting.default_locale == "en", remove_extraneous_space: SiteSetting.title_prettify && SiteSetting.title_remove_extraneous_space,
fixes_interior_spaces: true, fixes_interior_spaces: true,
strip_whitespaces: true, strip_whitespaces: true,
strip_zero_width_spaces: true strip_zero_width_spaces: true

View File

@ -8,7 +8,7 @@ module DiscourseNarrativeBot
def self.generate(user) def self.generate(user)
quote, author = quote, author =
if user.effective_locale != 'en' if !user.effective_locale.start_with?('en')
translation_key = "discourse_narrative_bot.quote.#{rand(1..10)}" translation_key = "discourse_narrative_bot.quote.#{rand(1..10)}"
[ [

View File

@ -105,7 +105,7 @@ class BulkImport::Base
def preload_i18n def preload_i18n
puts "Preloading I18n..." puts "Preloading I18n..."
I18n.locale = ENV.fetch("LOCALE") { "en" }.to_sym I18n.locale = ENV.fetch("LOCALE") { SiteSettings::DefaultsProvider::DEFAULT_LOCALE }.to_sym
I18n.t("test") I18n.t("test")
ActiveSupport::Inflector.transliterate("test") ActiveSupport::Inflector.transliterate("test")
end end

View File

@ -16,7 +16,7 @@ end
def supported_locales def supported_locales
Dir.glob(expand_path('config/locales/client.*.yml')) Dir.glob(expand_path('config/locales/client.*.yml'))
.map { |x| x.split('.')[-2] } .map { |x| x.split('.')[-2] }
.select { |x| x != 'en' } .reject { |x| x.start_with?('en') }
.sort - TranslationsManager::BROKEN_LOCALES .sort - TranslationsManager::BROKEN_LOCALES
end end

View File

@ -89,6 +89,8 @@ describe "translate accelerator" do
end end
describe "with overrides" do describe "with overrides" do
before { I18n.locale = :en }
it "returns the overridden key" do it "returns the overridden key" do
override_translation('en', 'foo', 'Overwritten foo') override_translation('en', 'foo', 'Overwritten foo')
expect(I18n.t('foo')).to eq('Overwritten foo') expect(I18n.t('foo')).to eq('Overwritten foo')

View File

@ -20,7 +20,6 @@ describe JsLocaleHelper do
JsLocaleHelper.extend StubLoadTranslations JsLocaleHelper.extend StubLoadTranslations
after do after do
I18n.locale = :en
JsLocaleHelper.clear_cache! JsLocaleHelper.clear_cache!
end end
@ -119,6 +118,16 @@ describe JsLocaleHelper do
message = JsLocaleHelper.compile_message_format(message_format_filename('ru'), 'ru', 'format') message = JsLocaleHelper.compile_message_format(message_format_filename('ru'), 'ru', 'format')
expect(message).not_to match 'Plural Function not found' expect(message).not_to match 'Plural Function not found'
end end
it "includes uses message formats from fallback locale" do
translations = JsLocaleHelper.translations_for(:en_US)
en_us_message_formats = JsLocaleHelper.remove_message_formats!(translations, :en_US)
expect(en_us_message_formats).to_not be_empty
translations = JsLocaleHelper.translations_for(:en)
en_message_formats = JsLocaleHelper.remove_message_formats!(translations, :en)
expect(en_us_message_formats).to eq(en_message_formats)
end
end end
it 'performs fallbacks to english if a translation is not available' do it 'performs fallbacks to english if a translation is not available' do
@ -190,7 +199,7 @@ describe JsLocaleHelper do
it "finds moment.js locale file for #{locale[:value]}" do it "finds moment.js locale file for #{locale[:value]}" do
content = JsLocaleHelper.moment_locale(locale[:value]) content = JsLocaleHelper.moment_locale(locale[:value])
if (locale[:value] == 'en') if (locale[:value] == SiteSettings::DefaultsProvider::DEFAULT_LOCALE)
expect(content).to eq('') expect(content).to eq('')
else else
expect(content).to_not eq('') expect(content).to_not eq('')

View File

@ -766,7 +766,7 @@ describe SiteSettingExtension do
describe '.default_locale' do describe '.default_locale' do
it 'is always loaded' do it 'is always loaded' do
expect(settings.default_locale).to eq 'en' expect(settings.default_locale).to eq('en_US')
end end
end end
@ -833,7 +833,7 @@ describe SiteSettingExtension do
settings.refresh! settings.refresh!
expect(settings.client_settings_json_uncached).to eq( expect(settings.client_settings_json_uncached).to eq(
%Q|{"default_locale":"en","upload_type":"#{upload.url}","string_type":"haha"}| %Q|{"default_locale":"#{SiteSetting.default_locale}","upload_type":"#{upload.url}","string_type":"haha"}|
) )
end end
end end

View File

@ -196,7 +196,11 @@ describe TextCleaner do
end end
it "removes extraneous space before the end punctuation" do it "removes extraneous space before the end punctuation" do
SiteSetting.title_remove_extraneous_space = true
expect(TextCleaner.clean_title("Hello there ?")).to eq("Hello there?") expect(TextCleaner.clean_title("Hello there ?")).to eq("Hello there?")
SiteSetting.title_remove_extraneous_space = false
expect(TextCleaner.clean_title("Hello there ?")).to eq("Hello there ?")
end end
it "replaces all upper case unicode text with regular unicode case letters" do it "replaces all upper case unicode text with regular unicode case letters" do

View File

@ -109,7 +109,7 @@ describe ThemeStore::TgzExporter do
# Theme field names should be sanitized before writing to the database, # Theme field names should be sanitized before writing to the database,
# but protection is in place 'just in case' # but protection is in place 'just in case'
expect do expect do
theme.set_field(target: :translations, name: "en", value: "hacked") theme.set_field(target: :translations, name: SiteSetting.default_locale, value: "hacked")
ThemeField.any_instance.stubs(:file_path).returns("../../malicious") ThemeField.any_instance.stubs(:file_path).returns("../../malicious")
theme.save! theme.save!
package package

View File

@ -15,7 +15,8 @@ describe Wizard::StepUpdater do
context "locale" do context "locale" do
it "does not require refresh when the language stays the same" do it "does not require refresh when the language stays the same" do
updater = wizard.create_updater('locale', default_locale: 'en') locale = SiteSettings::DefaultsProvider::DEFAULT_LOCALE
updater = wizard.create_updater('locale', default_locale: locale)
updater.update updater.update
expect(updater.refresh_required?).to eq(false) expect(updater.refresh_required?).to eq(false)
expect(wizard.completed_steps?('locale')).to eq(true) expect(wizard.completed_steps?('locale')).to eq(true)

View File

@ -90,8 +90,11 @@ describe "i18n integrity checks" do
expect(yaml.keys).to eq([locale]) expect(yaml.keys).to eq([locale])
expect(yaml[locale]["js"]).to be expect(yaml[locale]["js"]).to be
expect(yaml[locale]["admin_js"]).to be
# expect(yaml[locale]["wizard_js"]).to be if !LocaleSiteSetting.fallback_locale(locale)
expect(yaml[locale]["admin_js"]).to be
expect(yaml[locale]["wizard_js"]).to be
end
end end
end end

View File

@ -13,6 +13,14 @@ describe I18n::Backend::FallbackLocaleList do
expect(list[:en]).to eq([:en]) expect(list[:en]).to eq([:en])
end end
it "works when default_locale is English (United States)" do
SiteSetting.default_locale = :en_US
expect(list[:ru]).to eq([:ru, :en_US, :en])
expect(list[:en_US]).to eq([:en_US, :en])
expect(list[:en]).to eq([:en])
end
it "works when default_locale is not English" do it "works when default_locale is not English" do
SiteSetting.default_locale = :de SiteSetting.default_locale = :de

View File

@ -787,7 +787,7 @@ describe UserNotifications do
before do before do
TranslationOverride.upsert!( TranslationOverride.upsert!(
"en", SiteSetting.default_locale,
"#{mail_template}.text_body_template", "#{mail_template}.text_body_template",
custom_body custom_body
) )
@ -901,7 +901,6 @@ describe UserNotifications do
context "user locale is allowed" do context "user locale is allowed" do
before do before do
SiteSetting.default_locale = "en"
SiteSetting.allow_user_locale = true SiteSetting.allow_user_locale = true
end end
@ -919,7 +918,6 @@ describe UserNotifications do
context "user locale is not allowed" do context "user locale is not allowed" do
before do before do
SiteSetting.default_locale = "en"
SiteSetting.allow_user_locale = false SiteSetting.allow_user_locale = false
end end
@ -929,7 +927,7 @@ describe UserNotifications do
let(:locale) { "fr" } let(:locale) { "fr" }
let(:mail_type) { mail_type } let(:mail_type) { mail_type }
it "sets the locale" do it "sets the locale" do
expects_build_with(has_entry(:locale, "en")) expects_build_with(has_entry(:locale, "en_US"))
end end
end end
end end

View File

@ -20,12 +20,8 @@ describe Badge do
badge = Badge.find_by_name("Basic User") badge = Badge.find_by_name("Basic User")
name_english = badge.name name_english = badge.name
begin I18n.with_locale(:fr) do
I18n.locale = 'fr'
expect(badge.display_name).not_to eq(name_english) expect(badge.display_name).not_to eq(name_english)
ensure
I18n.locale = :en
end end
end end

View File

@ -13,7 +13,7 @@ describe LocaleSiteSetting do
value[:name] value[:name]
end end
describe 'valid_value?' do describe '.valid_value?' do
it 'returns true for a locale that we have translations for' do it 'returns true for a locale that we have translations for' do
expect(LocaleSiteSetting.valid_value?('en')).to eq(true) expect(LocaleSiteSetting.valid_value?('en')).to eq(true)
end end
@ -23,7 +23,7 @@ describe LocaleSiteSetting do
end end
end end
describe 'values' do describe '.values' do
it 'returns all the locales that we have translations for' do it 'returns all the locales that we have translations for' do
expect(LocaleSiteSetting.values.map { |x| x[:value] }).to include(*core_locales) expect(LocaleSiteSetting.values.map { |x| x[:value] }).to include(*core_locales)
end end
@ -52,7 +52,7 @@ describe LocaleSiteSetting do
DiscoursePluginRegistry.reset! DiscoursePluginRegistry.reset!
end end
describe 'valid_value?' do describe '.valid_value?' do
it 'returns true for locales from core' do it 'returns true for locales from core' do
expect(LocaleSiteSetting.valid_value?('en')).to eq(true) expect(LocaleSiteSetting.valid_value?('en')).to eq(true)
expect(LocaleSiteSetting.valid_value?('de')).to eq(true) expect(LocaleSiteSetting.valid_value?('de')).to eq(true)
@ -64,7 +64,7 @@ describe LocaleSiteSetting do
end end
end end
describe 'values' do describe '.values' do
it 'returns native names added by plugin' do it 'returns native names added by plugin' do
expect(native_locale_name('foo')).to eq('Native Foo') expect(native_locale_name('foo')).to eq('Native Foo')
expect(native_locale_name('bar')).to eq('Native Bar') expect(native_locale_name('bar')).to eq('Native Bar')
@ -79,7 +79,7 @@ describe LocaleSiteSetting do
end end
end end
describe 'fallback_locale' do describe '.fallback_locale' do
it 'returns the fallback locale registered by plugin' do it 'returns the fallback locale registered by plugin' do
expect(LocaleSiteSetting.fallback_locale('de_AT')).to eq(:de) expect(LocaleSiteSetting.fallback_locale('de_AT')).to eq(:de)
expect(LocaleSiteSetting.fallback_locale(:de_AT)).to eq(:de) expect(LocaleSiteSetting.fallback_locale(:de_AT)).to eq(:de)
@ -88,6 +88,16 @@ describe LocaleSiteSetting do
it 'returns nothing when no fallback locale was registered' do it 'returns nothing when no fallback locale was registered' do
expect(LocaleSiteSetting.fallback_locale('foo')).to be_nil expect(LocaleSiteSetting.fallback_locale('foo')).to be_nil
end end
it 'returns English for English (United States)' do
expect(LocaleSiteSetting.fallback_locale('en_US')).to eq(:en)
end
end
end
describe '.fallback_locale' do
it 'returns English for English (United States)' do
expect(LocaleSiteSetting.fallback_locale('en_US')).to eq(:en)
end end
end end
end end

View File

@ -239,8 +239,8 @@ HTML
let!(:theme3) { Fabricate(:theme) } let!(:theme3) { Fabricate(:theme) }
let!(:en1) { let!(:en1) {
ThemeField.create!(theme: theme, target_id: Theme.targets[:translations], name: "en", ThemeField.create!(theme: theme, target_id: Theme.targets[:translations], name: "en_US",
value: { en: { somestring1: "helloworld", group: { key1: "enval1" } } } value: { en_US: { somestring1: "helloworld", group: { key1: "enval1" } } }
.deep_stringify_keys.to_yaml .deep_stringify_keys.to_yaml
) )
} }
@ -251,21 +251,21 @@ HTML
) )
} }
let!(:fr2) { ThemeField.create!(theme: theme2, target_id: Theme.targets[:translations], name: "fr", value: "") } let!(:fr2) { ThemeField.create!(theme: theme2, target_id: Theme.targets[:translations], name: "fr", value: "") }
let!(:en2) { ThemeField.create!(theme: theme2, target_id: Theme.targets[:translations], name: "en", value: "") } let!(:en2) { ThemeField.create!(theme: theme2, target_id: Theme.targets[:translations], name: "en_US", value: "") }
let!(:ca3) { ThemeField.create!(theme: theme3, target_id: Theme.targets[:translations], name: "ca", value: "") } let!(:ca3) { ThemeField.create!(theme: theme3, target_id: Theme.targets[:translations], name: "ca", value: "") }
let!(:en3) { ThemeField.create!(theme: theme3, target_id: Theme.targets[:translations], name: "en", value: "") } let!(:en3) { ThemeField.create!(theme: theme3, target_id: Theme.targets[:translations], name: "en_US", value: "") }
describe "scopes" do describe "scopes" do
it "filter_locale_fields returns results in the correct order" do it "filter_locale_fields returns results in the correct order" do
expect(ThemeField.find_by_theme_ids([theme3.id, theme.id, theme2.id]) expect(ThemeField.find_by_theme_ids([theme3.id, theme.id, theme2.id])
.filter_locale_fields( .filter_locale_fields(
["en", "fr"] ["en_US", "fr"]
)).to eq([en3, en1, fr1, en2, fr2]) )).to eq([en3, en1, fr1, en2, fr2])
end end
it "find_first_locale_fields returns only the first locale for each theme" do it "find_first_locale_fields returns only the first locale for each theme" do
expect(ThemeField.find_first_locale_fields( expect(ThemeField.find_first_locale_fields(
[theme3.id, theme.id, theme2.id], ["ca", "en", "fr"] [theme3.id, theme.id, theme2.id], ["ca", "en_US", "fr"]
)).to eq([ca3, en1, en2]) )).to eq([ca3, en1, en2])
end end
end end
@ -296,7 +296,7 @@ HTML
it "loads correctly" do it "loads correctly" do
expect(fr1.translation_data).to eq( expect(fr1.translation_data).to eq(
fr: { somestring1: "bonjourworld", group: { key2: "frval2" } }, fr: { somestring1: "bonjourworld", group: { key2: "frval2" } },
en: { somestring1: "helloworld", group: { key1: "enval1" } } en_US: { somestring1: "helloworld", group: { key1: "enval1" } }
) )
end end
@ -318,7 +318,7 @@ HTML
theme.reload theme.reload
expect(fr1.translation_data).to eq( expect(fr1.translation_data).to eq(
fr: { somestring1: "bonjourworld", group: { key2: "frval2" } }, fr: { somestring1: "bonjourworld", group: { key2: "frval2" } },
en: { somestring1: "helloworld", group: { key1: "overriddentest1" } } en_US: { somestring1: "helloworld", group: { key1: "overriddentest1" } }
) )
end end
end end

View File

@ -599,8 +599,8 @@ HTML
end end
it "can create a hash of overridden values" do it "can create a hash of overridden values" do
en_translation = ThemeField.create!(theme_id: theme.id, name: "en", type_id: ThemeField.types[:yaml], target_id: Theme.targets[:translations], value: <<~YAML) en_translation = ThemeField.create!(theme_id: theme.id, name: "en_US", type_id: ThemeField.types[:yaml], target_id: Theme.targets[:translations], value: <<~YAML)
en: en_US:
group_of_translations: group_of_translations:
translation1: en test1 translation1: en test1
YAML YAML
@ -610,7 +610,7 @@ HTML
theme.update_translation("group_of_translations.translation1", "overriddentest2") theme.update_translation("group_of_translations.translation1", "overriddentest2")
theme.reload theme.reload
expect(theme.translation_override_hash).to eq( expect(theme.translation_override_hash).to eq(
"en" => { "en_US" => {
"group_of_translations" => { "group_of_translations" => {
"translation1" => "overriddentest1" "translation1" => "overriddentest1"
} }

View File

@ -6,7 +6,7 @@ describe TranslationOverride do
context 'validations' do context 'validations' do
describe '#value' do describe '#value' do
before do before do
I18n.backend.store_translations(:en, some_key: '%{first} %{second}') I18n.backend.store_translations(I18n.locale, some_key: '%{first} %{second}')
end end
describe 'when interpolation keys are missing' do describe 'when interpolation keys are missing' do

View File

@ -15,7 +15,7 @@ RSpec.describe 'Multisite SiteSettings', type: :multisite do
describe '#default_locale' do describe '#default_locale' do
it 'should return the right locale' do it 'should return the right locale' do
test_multisite_connection('default') do test_multisite_connection('default') do
expect(SiteSetting.default_locale).to eq('en') expect(SiteSetting.default_locale).to eq('en_US')
end end
test_multisite_connection('second') do test_multisite_connection('second') do
@ -25,7 +25,7 @@ RSpec.describe 'Multisite SiteSettings', type: :multisite do
end end
test_multisite_connection('default') do test_multisite_connection('default') do
expect(SiteSetting.default_locale).to eq('en') expect(SiteSetting.default_locale).to eq('en_US')
SiteSetting.default_locale = 'ja' SiteSetting.default_locale = 'ja'

View File

@ -108,7 +108,7 @@ module TestSetup
Discourse.clear_readonly! Discourse.clear_readonly!
Sidekiq::Worker.clear_all Sidekiq::Worker.clear_all
I18n.locale = :en I18n.locale = SiteSettings::DefaultsProvider::DEFAULT_LOCALE
RspecErrorTracker.last_exception = nil RspecErrorTracker.last_exception = nil

View File

@ -271,7 +271,7 @@ RSpec.describe Admin::SiteTextsController do
end end
it "returns the right error message" do it "returns the right error message" do
I18n.backend.store_translations(:en, some_key: '%{first} %{second}') I18n.backend.store_translations(SiteSetting.default_locale, some_key: '%{first} %{second}')
put "/admin/customize/site_texts/some_key.json", params: { put "/admin/customize/site_texts/some_key.json", params: {
site_text: { value: 'hello %{key} %{omg}' } site_text: { value: 'hello %{key} %{omg}' }

View File

@ -27,11 +27,8 @@ describe ExtraLocalesController do
end end
it "includes plugin translations" do it "includes plugin translations" do
I18n.locale = :en
I18n.reload!
JsLocaleHelper.expects(:plugin_translations) JsLocaleHelper.expects(:plugin_translations)
.with(I18n.locale.to_s) .with(any_of("en", "en_US"))
.returns("admin_js" => { .returns("admin_js" => {
"admin" => { "admin" => {
"site_settings" => { "site_settings" => {

View File

@ -102,7 +102,7 @@ describe SearchIndexer do
raw_data, locale, version = PostSearchData.where(post_id: post_id).pluck(:raw_data, :locale, :version)[0] raw_data, locale, version = PostSearchData.where(post_id: post_id).pluck(:raw_data, :locale, :version)[0]
expect(raw_data).to eq("This is a test") expect(raw_data).to eq("This is a test")
expect(locale).to eq("en") expect(locale).to eq(SiteSetting.default_locale)
expect(version).to eq(SearchIndexer::INDEX_VERSION) expect(version).to eq(SearchIndexer::INDEX_VERSION)
SearchIndexer.update_posts_index(post_id, "tester", "", nil, nil) SearchIndexer.update_posts_index(post_id, "tester", "", nil, nil)

View File

@ -646,7 +646,7 @@ componentTest("clicking the toggle-direction button toggles the direction", {
template: "{{d-editor value=value}}", template: "{{d-editor value=value}}",
beforeEach() { beforeEach() {
this.siteSettings.support_mixed_text_direction = true; this.siteSettings.support_mixed_text_direction = true;
this.siteSettings.default_locale = "en"; this.siteSettings.default_locale = "en_US";
}, },
async test(assert) { async test(assert) {

View File

@ -20,7 +20,7 @@ export default {
description: description:
"Discussion about the next-generation open source Discourse forum software", "Discussion about the next-generation open source Discourse forum software",
title: "Discourse Meta", title: "Discourse Meta",
locale: "en", locale: "en_US",
version: "2.2.0.beta8", version: "2.2.0.beta8",
https: true, https: true,
admins: [ admins: [

View File

@ -16,7 +16,7 @@
//= require preload-store //= require preload-store
//= require locales/i18n //= require locales/i18n
//= require locales/en //= require locales/en_US
// Stuff we need to load first // Stuff we need to load first
//= require vendor //= require vendor