From be80973e447bb8bd369acc7cfc9f8d4393c5ffdd Mon Sep 17 00:00:00 2001 From: voodoorai2000 Date: Thu, 27 Sep 2018 18:11:28 +0200 Subject: [PATCH] Avoid InvalidPluralizationData exception when missing translations We work with many languages using Crowdin[1] Sometimes translators forget to fill in all the necessary plural forms of a translation (zero, one, other) and in those cases we were seing the exception InvalidPluralizationData being raised There are a number of approches to fix this... from being more strict when approving translations, to automatically extrapolating what those plural forms should be For now, we've gone for a simple approach to display the actual count(0,1,2,3,4, etc) instead of the whole translation So, if the plural form of "1 comment" is missing, just a "1" will be displayed and no exceptions raised Note: The first two specs, test what is really Rails' functionalities. However as we are monkey patching the pluralize method, I thought it was appropriate to doble check it [1]https://crowdin.com/project/consul --- config/initializers/i18n_pluralize.rb | 19 +++++++++++ spec/i18n_spec.rb | 48 ++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 1 deletion(-) create mode 100644 config/initializers/i18n_pluralize.rb diff --git a/config/initializers/i18n_pluralize.rb b/config/initializers/i18n_pluralize.rb new file mode 100644 index 000000000..609a14ad7 --- /dev/null +++ b/config/initializers/i18n_pluralize.rb @@ -0,0 +1,19 @@ +### From official I18n::Backend::Base +### https://github.com/svenfuchs/i18n/blob/f35b839693c5ecc7ea0ff0f57c5cbf6db1dd73f9/lib/i18n/backend/base.rb#L155 +### Just changed one line to return `count` instead of raising the exception `InvalidPluralizationData` + +module I18n + module Backend + module Base + + def pluralize(locale, entry, count) + return entry unless entry.is_a?(Hash) && count + + key = pluralization_key(entry, count) + return count unless entry.has_key?(key) + entry[key] + end + + end + end +end \ No newline at end of file diff --git a/spec/i18n_spec.rb b/spec/i18n_spec.rb index 5237b7240..7fb59edde 100644 --- a/spec/i18n_spec.rb +++ b/spec/i18n_spec.rb @@ -1,6 +1,7 @@ +require 'rails_helper' require 'i18n/tasks' -RSpec.describe 'I18n' do +describe 'I18n' do let(:i18n) { I18n::Tasks::BaseTask.new } let(:missing_keys) { i18n.missing_keys } let(:unused_keys) { i18n.unused_keys } @@ -14,4 +15,49 @@ RSpec.describe 'I18n' do expect(unused_keys).to be_empty, "#{unused_keys.leaves.count} unused i18n keys, run `i18n-tasks unused' to show them" end + + context "Plurals" do + + after do + I18n.backend.reload! + end + + it "returns plural rule if translation present" do + keys = { zero: "No comments", + one: "1 comment", + other: "%{count} comments" } + + I18n.backend.store_translations(:en, { test_plural: keys }) + + expect(I18n.t("test_plural", count: 0)).to eq("No comments") + expect(I18n.t("test_plural", count: 1)).to eq("1 comment") + expect(I18n.t("test_plural", count: 2)).to eq("2 comments") + end + + it "returns default locale's plural rule if whole translation not present" do + keys = { zero: "No comments", + one: "1 comment", + other: "%{count} comments" } + + I18n.backend.store_translations(I18n.default_locale, { test_plural: keys }) + I18n.backend.store_translations(:zz, {} ) + + I18n.enforce_available_locales = false + I18n.locale = :zz + + expect(I18n.t("test_plural", count: 0)).to eq("No comments") + expect(I18n.t("test_plural", count: 1)).to eq("1 comment") + expect(I18n.t("test_plural", count: 2)).to eq("2 comments") + end + + it "returns count if specific plural rule not present" do + keys = { zero: "No comments" } + I18n.backend.store_translations(:en, { test_plural: keys }) + + expect(I18n.t("test_plural", count: 0)).to eq("No comments") + expect(I18n.t("test_plural", count: 1)).to eq(1) + expect(I18n.t("test_plural", count: 2)).to eq(2) + end + + end end