From f0abbad937322435248ac707ed670428af3e8a38 Mon Sep 17 00:00:00 2001 From: Benau Date: Mon, 14 Dec 2015 02:56:16 +0800 Subject: [PATCH] Fix plural forms --- src/tinygettext/plural_forms.cpp | 66 +++++++++++++++++++------------- src/utils/translation.cpp | 3 +- 2 files changed, 41 insertions(+), 28 deletions(-) diff --git a/src/tinygettext/plural_forms.cpp b/src/tinygettext/plural_forms.cpp index 3ac31f43c..fec54cfec 100644 --- a/src/tinygettext/plural_forms.cpp +++ b/src/tinygettext/plural_forms.cpp @@ -30,19 +30,28 @@ namespace tinygettext { * msgstr[1] = "You got %d errors"; * ^-- return value of plural function */ +// Base on Unicode CLDR (http://mlocati.github.io/cldr-to-gettext-plural-rules/) unsigned int plural1(int ) { return 0; } + unsigned int plural2_1(int n) { return (n != 1); } unsigned int plural2_2(int n) { return (n > 1); } +unsigned int plural2_is(int n) { return n % 10 != 1 || n % 100 == 11; } unsigned int plural2_mk(int n) { return n==1 || n%10==1 ? 0 : 1; } -unsigned int plural3_lv(int n) { return static_cast(n%10==1 && n%100!=11 ? 0 : n != 0 ? 1 : 2); } -unsigned int plural3_ga(int n) { return static_cast(n==1 ? 0 : n==2 ? 1 : 2); } -unsigned int plural3_lt(int n) { return static_cast(n%10==1 && n%100!=11 ? 0 : n%10>=2 && (n%100<10 || n%100>=20) ? 1 : 2); } -unsigned int plural3_1(int n) { return static_cast(n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2); } -unsigned int plural3_sk(int n) { return static_cast( (n==1) ? 0 : (n>=2 && n<=4) ? 1 : 2 ); } -unsigned int plural3_pl(int n) { return static_cast(n==1 ? 0 : n%10>=2 && n%10<=4 && (n%100<10 || n%100>=20) ? 1 : 2); } -unsigned int plural3_sl(int n) { return static_cast(n%100==1 ? 0 : n%100==2 ? 1 : n%100==3 || n%100==4 ? 2 : 3); } -unsigned int plural4_ar(int n) { return static_cast( n==1 ? 0 : n==2 ? 1 : n>=3 && n<=10 ? 2 : 3 ); } -unsigned int plural4_gd(int n) { return static_cast( n==1 || n==11) ? 0 : (n==2 || n==12) ? 1 : (n > 2 && n < 20) ? 2 : 3; } + +unsigned int plural3_be(int n) { return static_cast(n % 10 == 1 && n % 100 != 11) ? 0 : ((n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14)) ? 1 : 2); } +unsigned int plural3_kw(int n) { return static_cast(n == 1) ? 0 : ((n == 2) ? 1 : 2); } +unsigned int plural3_lv(int n) { return static_cast(n % 10 == 0 || (n % 100 >= 11 && n % 100 <= 19)) ? 0 : ((n % 10 == 1 && n % 100 != 11) ? 1 : 2); } +unsigned int plural3_lt(int n) { return static_cast(n % 10 == 1 && (n % 100 < 11 || n % 100 > 19)) ? 0 : ((n % 10 >= 2 && n % 10 <= 9 && (n % 100 < 11 || n % 100 > 19)) ? 1 : 2); } +unsigned int plural3_pl(int n) { return static_cast(n == 1) ? 0 : ((n % 10 >= 2 && n % 10 <= 4 && (n % 100 < 12 || n % 100 > 14)) ? 1 : 2); } +unsigned int plural3_ro(int n) { return static_cast(n == 1) ? 0 : ((n == 0 || (n != 1 && n % 100 >= 1 && n % 100 <= 19)) ? 1 : 2); } +unsigned int plural3_sk(int n) { return static_cast(n == 1) ? 0 : ((n >= 2 && n <= 4) ? 1 : 2); } + +unsigned int plural4_gd(int n) { return static_cast(n == 1 || n == 11) ? 0 : ((n == 2 || n == 12) ? 1 : (((n >= 3 && n <= 10) || (n >= 13 && n <= 19)) ? 2 : 3)); } +unsigned int plural4_sl(int n) { return static_cast(n % 100 == 1) ? 0 : ((n % 100 == 2) ? 1 : ((n % 100 == 3 || n % 100 == 4) ? 2 : 3)); } + +unsigned int plural5_ga(int n) { return static_cast(n == 1) ? 0 : ((n == 2) ? 1 : ((n >= 3 && n <= 6) ? 2 : ((n >= 7 && n <= 10) ? 3 : 4))); } + +unsigned int plural6_ar(int n) { return static_cast(n == 0) ? 0 : ((n == 1) ? 1 : ((n == 2) ? 2 : ((n % 100 >= 3 && n % 100 <= 10) ? 3 : ((n % 100 >= 11 && n % 100 <= 99) ? 4 : 5)))); } typedef std::map tPluralForms; @@ -54,31 +63,34 @@ PluralForms::from_string(const std::string& str) if (plural_forms.empty()) { // Note that the plural forms here shouldn't contain any spaces + // Some strings are specific to STK po file + // TODO in the future, map language code to plural form instead? plural_forms["Plural-Forms:nplurals=1;plural=0;"] = PluralForms(1, plural1); + plural_forms["Plural-Forms:nplurals=2;plural=(n!=1);"] = PluralForms(2, plural2_1); plural_forms["Plural-Forms:nplurals=2;plural=n!=1;"] = PluralForms(2, plural2_1); plural_forms["Plural-Forms:nplurals=2;plural=(n>1);"] = PluralForms(2, plural2_2); - plural_forms["Plural-Forms:nplurals=2;plural=n>1;"] = PluralForms(2, plural2_2); - plural_forms["Plural-Forms:nplurals=2;plural=(n==1||n%10==1?0:1);"] = PluralForms(2, plural2_mk); + plural_forms["Plural-Forms:nplurals=2;plural=(n%10!=1||n%100==11);"] = PluralForms(2, plural2_is); plural_forms["Plural-Forms:nplurals=2;plural=n==1||n%10==1?0:1;"] = PluralForms(2, plural2_mk); - plural_forms["Plural-Forms:nplurals=3;plural=(n%10==1&&n%100!=11?0:n!=0?1:2);"] = PluralForms(2, plural3_lv); - plural_forms["Plural-Forms:nplurals=3;plural=n%10==1&&n%100!=11?0:n!=0?1:2;"] = PluralForms(2, plural3_lv); - plural_forms["Plural-Forms:nplurals=3;plural=(n==1?0:n==2?1:2);"] = PluralForms(3, plural3_ga); - plural_forms["Plural-Forms:nplurals=3;plural=n==1?0:n==2?1:2;"] = PluralForms(3, plural3_ga); + + //FIXME wrong plural equation in be/ru translation files! (transifex error?) nplurals of be/ru is 3 indeed. + plural_forms["Plural-Forms:nplurals=4;plural=(n%10==1&&n%100!=11?0:n%10>=2&&n%10<=4&&(n%100<12||n%100>14)?1:n%10==0||(n%10>=5&&n%10<=9)||(n%100>=11&&n%100<=14)?2:3);"] = PluralForms(3, plural3_be); + plural_forms["Plural-Forms:nplurals=3;plural=n%10==1&&n%100!=11?0:n%10>=2&&n%10<=4&&(n%100<10||n%100>=20)?1:2;"] = PluralForms(3, plural3_be); + plural_forms["Plural-Forms:nplurals=3;plural=(n%10==1&&n%100!=11?0:n%10>=2&&n%10<=4&&(n%100<10||n%100>=20)?1:2);"] = PluralForms(3, plural3_be); + //FIXME wrong again + plural_forms["Plural-Forms:nplurals=4;plural=(n==1)?0:(n==2)?1:(n==3)?2:3;"] = PluralForms(3, plural3_kw); + plural_forms["Plural-Forms:nplurals=3;plural=(n%10==1&&n%100!=11?0:n!=0?1:2);"] = PluralForms(3, plural3_lv); plural_forms["Plural-Forms:nplurals=3;plural=(n%10==1&&n%100!=11?0:n%10>=2&&(n%100<10||n%100>=20)?1:2);"] = PluralForms(3, plural3_lt); - plural_forms["Plural-Forms:nplurals=3;plural=n%10==1&&n%100!=11?0:n%10>=2&&(n%100<10||n%100>=20)?1:2;"] = PluralForms(3, plural3_lt); - plural_forms["Plural-Forms:nplurals=3;plural=(n%10==1&&n%100!=11?0:n%10>=2&&n%10<=4&&(n%100<10||n%100>=20)?1:2);"] = PluralForms(3, plural3_1); - plural_forms["Plural-Forms:nplurals=3;plural=n%10==1&&n%100!=11?0:n%10>=2&&n%10<=4&&(n%100<10||n%100>=20)?1:2;"] = PluralForms(3, plural3_1); - plural_forms["Plural-Forms:nplurals=3;plural=((n==1)?0:(n>=2&&n<=4)?1:2);"] = PluralForms(3, plural3_sk); - plural_forms["Plural-Forms:nplurals=3;plural=(n==1)?0:(n>=2&&n<=4)?1:2;"] = PluralForms(3, plural3_sk); plural_forms["Plural-Forms:nplurals=3;plural=(n==1?0:n%10>=2&&n%10<=4&&(n%100<10||n%100>=20)?1:2);"] = PluralForms(3, plural3_pl); - plural_forms["Plural-Forms:nplurals=3;plural=n==1?0:n%10>=2&&n%10<=4&&(n%100<10||n%100>=20)?1:2;"] = PluralForms(3, plural3_pl); - plural_forms["Plural-Forms:nplurals=3;plural=(n%100==1?0:n%100==2?1:n%100==3||n%100==4?2:3);"] = PluralForms(3, plural3_sl); - plural_forms["Plural-Forms:nplurals=3;plural=n%100==1?0:n%100==2?1:n%100==3||n%100==4?2:3;"] = PluralForms(3, plural3_sl); - plural_forms["Plural-Forms:nplurals=4;plural=(n==1?0:n==2?1:n>=3&&n<=10?2:3);"]=PluralForms(4, plural4_ar); - plural_forms["Plural-Forms:nplurals=4;plural=n==1?0:n==2?1:n>=3&&n<=10?2:3;"]=PluralForms(4, plural4_ar); - plural_forms["Plural-Forms:nplurals=4;plural=((n==1||n==11)?0:(n==2||n==12)?1:(n>2&&n<20)?2:3);"]=PluralForms(4, plural4_gd); - plural_forms["Plural-Forms:nplurals=4;plural=(n==1||n==11)?0:(n==2||n==12)?1:(n>2&&n<20)?2:3;"]=PluralForms(4, plural4_gd); + plural_forms["Plural-Forms:nplurals=3;plural=(n==1?0:(((n%100>19)||((n%100==0)&&(n!=0)))?2:1));"] = PluralForms(3, plural3_ro); + plural_forms["Plural-Forms:nplurals=3;plural=(n==1)?0:(n>=2&&n<=4)?1:2;"] = PluralForms(3, plural3_sk); + + plural_forms["Plural-Forms:nplurals=4;plural=(n%100==1?0:n%100==2?1:n%100==3||n%100==4?2:3);"] = PluralForms(4, plural4_sl); + plural_forms["Plural-Forms:nplurals=4;plural=(n==1||n==11)?0:(n==2||n==12)?1:(n>2&&n<20)?2:3;"] = PluralForms(4, plural4_gd); + + plural_forms["Plural-Forms:nplurals=5;plural=(n==1?0:n==2?1:n<7?2:n<11?3:4);"] = PluralForms(5, plural5_ga); + + plural_forms["Plural-Forms:nplurals=6;plural=n==0?0:n==1?1:n==2?2:n%100>=3&&n%100<=10?3:n%100>=11&&n%100<=99?4:5;"] = PluralForms(6, plural6_ar); } // Remove spaces from string before lookup diff --git a/src/utils/translation.cpp b/src/utils/translation.cpp index 13ed04dea..ee6f05f6e 100644 --- a/src/utils/translation.cpp +++ b/src/utils/translation.cpp @@ -524,7 +524,8 @@ const wchar_t* Translations::w_ngettext(const char* singular, const char* plural m_dictionary.translate_plural(singular, plural, num) : m_dictionary.translate_ctxt_plural(context, singular, plural, num)); - static core::stringw str_buffer = StringUtils::utf8ToWide(res); + static core::stringw str_buffer; + str_buffer = StringUtils::utf8ToWide(res); const wchar_t* out_ptr = str_buffer.c_str(); if (REMOVE_BOM) out_ptr++;