diff --git a/app/services/discourse_translator/post_locale_detector.rb b/app/services/discourse_translator/post_locale_detector.rb index a4c348c9..ee264d5e 100644 --- a/app/services/discourse_translator/post_locale_detector.rb +++ b/app/services/discourse_translator/post_locale_detector.rb @@ -7,8 +7,9 @@ def self.detect_locale(post) translator = DiscourseTranslator::Provider::TranslatorProvider.get detected_locale = translator.detect!(post) - post.update!(locale: detected_locale) - detected_locale + locale = LocaleNormalizer.normalize_to_i18n(detected_locale) + post.update!(locale:) + locale end end end diff --git a/lib/discourse_translator/locale_normalizer.rb b/lib/discourse_translator/locale_normalizer.rb new file mode 100644 index 00000000..b6a907ab --- /dev/null +++ b/lib/discourse_translator/locale_normalizer.rb @@ -0,0 +1,41 @@ +# frozen_string_literal: true + +module DiscourseTranslator + class LocaleNormalizer + # Normalizes locale string, matching the list of I18n.locales where possible + # @param locale [String,Symbol] the locale to normalize + # @return [String] the normalized locale + def self.normalize_to_i18n(locale) + return nil if locale.blank? + locale = locale.to_s.gsub("-", "_") + + i18n_pairs.each { |downcased, value| return value if locale.downcase == downcased } + + locale + end + + private + + def self.i18n_pairs + # they should look like this for the input to match against: + # { + # "lowercased" => "actual", + # "en" => "en", + # "zh_cn" => "zh_CN", + # "zh" => "zh_CN", + # } + @locale_map ||= + I18n + .available_locales + .reduce({}) do |output, sym| + locale = sym.to_s + output[locale.downcase] = locale + if locale.include?("_") + short = locale.split("_").first + output[short] = locale if output[short].blank? + end + output + end + end + end +end diff --git a/spec/lib/locale_normalizer_spec.rb b/spec/lib/locale_normalizer_spec.rb new file mode 100644 index 00000000..e76686fa --- /dev/null +++ b/spec/lib/locale_normalizer_spec.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +describe DiscourseTranslator::LocaleNormalizer do + it "matches input locales to i18n locales" do + expect(described_class.normalize_to_i18n("en-GB")).to eq("en_GB") + expect(described_class.normalize_to_i18n("en")).to eq("en") + expect(described_class.normalize_to_i18n("zh")).to eq("zh_CN") + expect(described_class.normalize_to_i18n("tr")).to eq("tr_TR") + end + + it "converts dashes to underscores" do + expect(described_class.normalize_to_i18n("a-b")).to eq("a_b") + end +end diff --git a/spec/services/post_locale_detector_spec.rb b/spec/services/post_locale_detector_spec.rb index daebab7b..bcb15392 100644 --- a/spec/services/post_locale_detector_spec.rb +++ b/spec/services/post_locale_detector_spec.rb @@ -13,14 +13,14 @@ end it "calls detect! on the provider with the post" do - translator.expects(:detect!).with(post).returns("ja") - expect(described_class.detect_locale(post)).to eq("ja") + translator.expects(:detect!).with(post).returns("zh") + expect(described_class.detect_locale(post)).to eq("zh_CN") end it "updates the post locale with the detected locale" do - translator.stubs(:detect!).with(post).returns("ja") + translator.stubs(:detect!).with(post).returns("zh") expect { described_class.detect_locale(post) }.to change { post.reload.locale }.from(nil).to( - "ja", + "zh_CN", ) end end