From d56a3d015b4aea8f7c1af8ee3efd2a1b04654805 Mon Sep 17 00:00:00 2001 From: John Preston Date: Sun, 21 Oct 2018 13:28:06 +0400 Subject: [PATCH] Add more plural rules support. --- Telegram/SourceFiles/lang/lang_tag.cpp | 897 +++++++++++++++++++++++-- 1 file changed, 840 insertions(+), 57 deletions(-) diff --git a/Telegram/SourceFiles/lang/lang_tag.cpp b/Telegram/SourceFiles/lang/lang_tag.cpp index db2dffe9f..53160f4a5 100644 --- a/Telegram/SourceFiles/lang/lang_tag.cpp +++ b/Telegram/SourceFiles/lang/lang_tag.cpp @@ -39,7 +39,422 @@ constexpr auto kShiftOther = ushort(5); using ChoosePluralMethod = ushort (*)(int n, int i, int v, int w, int f, int t); -ushort ChoosePluralAr(int n, int i, int v, int w, int f, int t) { +ushort ChoosePlural1(int n, int i, int v, int w, int f, int t) { + return kShiftOther; +} + +ushort ChoosePlural2fil(int n, int i, int v, int w, int f, int t) { + if (v == 0) { + const auto mod10 = (i % 10); + if (i == 1 || i == 2 || i == 3) { + return kShiftOne; + } else if (mod10 != 4 && mod10 != 6 && mod10 != 9) { + return kShiftOne; + } + return kShiftOther; + } + const auto mod10 = (f % 10); + if (mod10 != 4 && mod10 != 6 && mod10 != 9) { + return kShiftOne; + } + return kShiftOther; +} + +ushort ChoosePlural2tzm(int n, int i, int v, int w, int f, int t) { + if (n == 0 || n == 1) { + return kShiftOne; + } else if (n >= 11 && n <= 99) { + return kShiftOne; + } + return kShiftOther; +} + +ushort ChoosePlural2is(int n, int i, int v, int w, int f, int t) { + if (t == 0) { + const auto mod10 = (i % 10); + const auto mod100 = (i % 100); + if (mod10 == 1 && mod100 != 11) { + return kShiftOne; + } + return kShiftOther; + } + return kShiftOne; +} + +ushort ChoosePlural2mk(int n, int i, int v, int w, int f, int t) { + if (v == 0) { + const auto mod10 = (i % 10); + const auto mod100 = (i % 100); + if (mod10 == 1 && mod100 != 11) { + return kShiftOne; + } + } + const auto mod10 = (f % 10); + const auto mod100 = (f % 100); + if ((mod10 == 1) && (mod100 != 11)) { + return kShiftOne; + } + return kShiftOther; +} + +ushort ChoosePlural2ak(int n, int i, int v, int w, int f, int t) { + if (n == 0 || n == 1) { + return kShiftOne; + } + return kShiftOther; +} + +ushort ChoosePlural2am(int n, int i, int v, int w, int f, int t) { + if (i == 0 || n == 1) { + return kShiftOne; + } + return kShiftOther; +} + +ushort ChoosePlural2hy(int n, int i, int v, int w, int f, int t) { + if (i == 0 || i == 1) { + return kShiftOne; + } + return kShiftOther; +} + +ushort ChoosePlural2si(int n, int i, int v, int w, int f, int t) { + if (n == 0 || n == 1) { + return kShiftOne; + } else if (i == 0 && f == 1) { + return kShiftOne; + } + return kShiftOther; +} + +ushort ChoosePlural2bh(int n, int i, int v, int w, int f, int t) { + // not documented + if (n == 0 || n == 1) { + return kShiftOne; + } + return kShiftOther; +} + +ushort ChoosePlural2af(int n, int i, int v, int w, int f, int t) { + if (n == 1) { + return kShiftOne; + } + return kShiftOther; +} + +ushort ChoosePlural2ast(int n, int i, int v, int w, int f, int t) { + if (i == 1 && v == 0) { + return kShiftOne; + } + return kShiftOther; +} + +ushort ChoosePlural2da(int n, int i, int v, int w, int f, int t) { + if (n == 1) { + return kShiftOne; + } else if (t != 0 && ((i == 0) || (i == 1))) { + return kShiftOne; + } + return kShiftOther; +} + +ushort ChoosePlural3lv(int n, int i, int v, int w, int f, int t) { + const auto nmod10 = (n % 10); + const auto nmod100 = (n % 100); + const auto fmod10 = (f % 10); + const auto fmod100 = (f % 100); + if (nmod10 == 0) { + return kShiftZero; + } else if ((nmod100 >= 11) && (nmod100 <= 19)) { + return kShiftZero; + } else if ((v == 2) && (fmod100 >= 11) && (fmod100 <= 19)) { + return kShiftZero; + } else if ((nmod10 == 1) && (nmod100 != 11)) { + return kShiftOne; + } else if ((v == 2) && (fmod10 == 1) && (fmod100 != 11)) { + return kShiftOne; + } else if ((v != 2) && (fmod10 == 1)) { + return kShiftOne; + } + return kShiftOther; +} + +ushort ChoosePlural3ksh(int n, int i, int v, int w, int f, int t) { + if (n == 0) { + return kShiftZero; + } else if (n == 1) { + return kShiftOne; + } + return kShiftOther; +} + +ushort ChoosePlural3lag(int n, int i, int v, int w, int f, int t) { + if (n == 0) { + return kShiftZero; + } else if ((n != 0) && ((i == 0) || (i == 1))) { + return kShiftOne; + } + return kShiftOther; +} + +ushort ChoosePlural3kw(int n, int i, int v, int w, int f, int t) { + if (n == 1) { + return kShiftOne; + } else if (n == 2) { + return kShiftTwo; + } + return kShiftOther; +} + +ushort ChoosePlural3bs(int n, int i, int v, int w, int f, int t) { + if (v == 0) { + const auto mod10 = (i % 10); + const auto mod100 = (i % 100); + if ((mod10 >= 2) && (mod10 <= 4) && (mod100 < 12 || mod100 > 14)) { + return kShiftFew; + } else if ((mod10 == 1) && (mod100 != 11)) { + return kShiftOne; + } + return kShiftOther; + } + const auto mod10 = (f % 10); + const auto mod100 = (f % 100); + if ((mod10 >= 2) && (mod10 <= 4) && (mod100 < 12 || mod100 > 14)) { + return kShiftFew; + } else if ((mod10 == 1) && (mod100 != 11)) { + return kShiftOne; + } + return kShiftOther; +} + +ushort ChoosePlural3shi(int n, int i, int v, int w, int f, int t) { + if (i == 0 || n == 1) { + return kShiftOne; + } else if (n >= 2 && n <= 10) { + return kShiftFew; + } + return kShiftOther; +} + +ushort ChoosePlural3mo(int n, int i, int v, int w, int f, int t) { + if (v == 0) { + const auto mod100 = (n % 100); + if (i == 1) { + return kShiftOne; + } else if (n == 0) { + return kShiftFew; + } else if ((n != 1) && (mod100 >= 1) && (mod100 <= 19)) { + return kShiftFew; + } + return kShiftOther; + } + return kShiftFew; +} + +ushort ChoosePlural4be(int n, int i, int v, int w, int f, int t) { + const auto mod10 = (n % 10); + const auto mod100 = (n % 100); + if ((mod10 >= 2) && (mod10 <= 4) && (mod100 < 12 || mod100 > 14)) { + return kShiftFew; + } else if ((mod10 == 1) && (mod100 != 11)) { + return kShiftOne; + } else if (mod10 == 0) { + return kShiftMany; + } else if ((mod10 >= 5) && (mod10 <= 9)) { + return kShiftMany; + } else if ((mod100 >= 11) && (mod100 <= 14)) { + return kShiftMany; + } + return kShiftOther; +} + +ushort ChoosePlural4ru(int n, int i, int v, int w, int f, int t) { + if (v == 0) { + const auto mod10 = (i % 10); + const auto mod100 = (i % 100); + if ((mod10 >= 2) && (mod10 <= 4) && (mod100 < 12 || mod100 > 14)) { + return kShiftFew; + } else if ((mod10 == 1) && (mod100 != 11)) { + return kShiftOne; + } + return kShiftMany; + } + return kShiftOther; +} + +ushort ChoosePlural4pl(int n, int i, int v, int w, int f, int t) { + if (v == 0) { + if (i == 1) { + return kShiftOne; + } + const auto mod10 = (i % 10); + const auto mod100 = (i % 100); + if ((mod10 >= 2) && (mod10 <= 4) && (mod100 < 12 || mod100 > 14)) { + return kShiftFew; + } else { + return kShiftMany; + } + } + return kShiftOther; +} + +ushort ChoosePlural4lt(int n, int i, int v, int w, int f, int t) { + const auto mod10 = (n % 10); + const auto mod100 = (n % 100); + if ((mod10 >= 2) && (mod10 <= 9) && (mod100 < 11 || mod100 > 19)) { + return kShiftFew; + } else if ((mod10 == 1) && (mod100 != 11)) { + return kShiftOne; + } else if (f != 0) { + return kShiftMany; + } + return kShiftOther; +} + +ushort ChoosePlural4cs(int n, int i, int v, int w, int f, int t) { + if (v == 0) { + if (i == 1) { + return kShiftOne; + } else if (i >= 2 && i <= 4) { + return kShiftFew; + } + return kShiftOther; + } + return kShiftMany; +} + +ushort ChoosePlural4gd(int n, int i, int v, int w, int f, int t) { + if (n == 1 || n == 11) { + return kShiftOne; + } else if (n == 2 || n == 12) { + return kShiftTwo; + } else if (n >= 3 && n <= 10) { + return kShiftFew; + } else if (n >= 13 && n <= 19) { + return kShiftFew; + } + return kShiftOther; +} + +ushort ChoosePlural4dsb(int n, int i, int v, int w, int f, int t) { + if (v == 0) { + const auto imod100 = (i % 100); + if (imod100 == 1) { + return kShiftOne; + } else if (imod100 == 2) { + return kShiftTwo; + } else if (imod100 == 3 || imod100 == 4) { + return kShiftFew; + } + } + const auto fmod100 = (f % 100); + if (fmod100 == 1) { + return kShiftOne; + } else if (fmod100 == 2) { + return kShiftTwo; + } else if (fmod100 == 3 || fmod100 == 4) { + return kShiftFew; + } + return kShiftOther; +} + +ushort ChoosePlural4sl(int n, int i, int v, int w, int f, int t) { + if (v == 0) { + const auto imod100 = (i % 100); + if (imod100 == 3 || imod100 == 4) { + return kShiftFew; + } else if (imod100 == 1) { + return kShiftOne; + } else if (imod100 == 2) { + return kShiftTwo; + } + return kShiftOther; + } + return kShiftFew; +} + +ushort ChoosePlural4he(int n, int i, int v, int w, int f, int t) { + if (v == 0) { + if (i == 1) { + return kShiftOne; + } else if (i == 2) { + return kShiftTwo; + } else if ((n != 0) && (n != 10) && ((n % 10) == 0)) { + return kShiftMany; + } + return kShiftOther; + } + return kShiftOther; +} + +ushort ChoosePlural4mt(int n, int i, int v, int w, int f, int t) { + const auto mod100 = (n % 100); + if (n == 1) { + return kShiftOne; + } else if (n == 0) { + return kShiftFew; + } else if (mod100 >= 2 && mod100 <= 10) { + return kShiftFew; + } else if (mod100 >= 11 && mod100 <= 19) { + return kShiftMany; + } + return kShiftOther; +} + +ushort ChoosePlural5gv(int n, int i, int v, int w, int f, int t) { + if (v == 0) { + const auto mod10 = (i % 10); + const auto mod20 = (i % 20); + if (mod10 == 1) { + return kShiftOne; + } else if (mod10 == 2) { + return kShiftTwo; + } else if (mod20 == 0) { + return kShiftFew; + } + return kShiftOther; + } + return kShiftMany; +} + +ushort ChoosePlural5br(int n, int i, int v, int w, int f, int t) { + const auto mod10 = (n % 10); + const auto mod100 = (n % 100); + if ((mod10 == 1) + && (mod100 != 11) + && (mod100 != 71) + && (mod100 != 91)) { + return kShiftOne; + } else if ((mod10 == 2) + && (mod100 != 12) + && (mod100 != 72) + && (mod100 != 92)) { + return kShiftTwo; + } else if (((mod10 == 3) || (mod10 == 4) || (mod10 == 9)) + && ((mod100 < 10) || (mod100 > 19)) + && ((mod100 < 70) || (mod100 > 79)) + && ((mod100 < 90) || (mod100 > 99))) { + return kShiftFew; + } else if ((n != 0) && (n % 1000000 == 0)) { + return kShiftMany; + } + return kShiftOther; +} + +ushort ChoosePlural5ga(int n, int i, int v, int w, int f, int t) { + if (n == 1) { + return kShiftOne; + } else if (n == 2) { + return kShiftTwo; + } else if (n >= 3 && n <= 6) { + return kShiftFew; + } else if (n >= 7 && n <= 10) { + return kShiftMany; + } + return kShiftOther; +} + +ushort ChoosePlural6ar(int n, int i, int v, int w, int f, int t) { if (n == 0) { return kShiftZero; } else if (n == 1) { @@ -49,7 +464,7 @@ ushort ChoosePluralAr(int n, int i, int v, int w, int f, int t) { } else if (n < 0) { return kShiftOther; } - auto mod100 = (n % 100); + const auto mod100 = (n % 100); if (mod100 >= 3 && mod100 <= 10) { return kShiftFew; } else if (mod100 >= 11 && mod100 <= 99) { @@ -58,62 +473,390 @@ ushort ChoosePluralAr(int n, int i, int v, int w, int f, int t) { return kShiftOther; } -ushort ChoosePluralEn(int n, int i, int v, int w, int f, int t) { - if (i == 1 && v == 0) { +ushort ChoosePlural6cy(int n, int i, int v, int w, int f, int t) { + if (n == 0) { + return kShiftZero; + } else if (n == 1) { return kShiftOne; + } else if (n == 2) { + return kShiftTwo; + } else if (n == 3) { + return kShiftFew; + } else if (n == 6) { + return kShiftMany; } return kShiftOther; } -ushort ChoosePluralPt(int n, int i, int v, int w, int f, int t) { - if (i == 0 || i == 1) { - return kShiftOne; +struct PluralsKey { + PluralsKey(uint64 key); + PluralsKey(const char *value); + + inline operator uint64() const { + return data; } - return kShiftOther; + + uint64 data = 0; +}; + +PluralsKey::PluralsKey(uint64 key) : data(key) { } -ushort ChoosePluralEs(int n, int i, int v, int w, int f, int t) { - if (n == 1) { - return kShiftOne; +PluralsKey::PluralsKey(const char *value) { + for (auto ch = *value; ch; ch = *++value) { + data = (data << 8) | uint64(ch); } - return kShiftOther; } -ushort ChoosePluralKo(int n, int i, int v, int w, int f, int t) { - return kShiftOther; +std::map GeneratePluralRulesMap() { + return { + //{ "bm", ChoosePlural1 }, + //{ "my", ChoosePlural1 }, + //{ "yue", ChoosePlural1 }, + //{ "zh", ChoosePlural1 }, + //{ "dz", ChoosePlural1 }, + //{ "ig", ChoosePlural1 }, + //{ "id", ChoosePlural1 }, + //{ "in", ChoosePlural1 }, // same as "id" + //{ "ja", ChoosePlural1 }, + //{ "jv", ChoosePlural1 }, + //{ "jw", ChoosePlural1 }, // same as "jv" + //{ "kea", ChoosePlural1 }, + //{ "km", ChoosePlural1 }, + //{ "ko", ChoosePlural1 }, + //{ "ses", ChoosePlural1 }, + //{ "lkt", ChoosePlural1 }, + //{ "lo", ChoosePlural1 }, + //{ "jbo", ChoosePlural1 }, + //{ "kde", ChoosePlural1 }, + //{ "ms", ChoosePlural1 }, + //{ "nqo", ChoosePlural1 }, + //{ "sah", ChoosePlural1 }, + //{ "sg", ChoosePlural1 }, + //{ "ii", ChoosePlural1 }, + //{ "th", ChoosePlural1 }, + //{ "bo", ChoosePlural1 }, + //{ "to", ChoosePlural1 }, + //{ "vi", ChoosePlural1 }, + //{ "wo", ChoosePlural1 }, + //{ "yo", ChoosePlural1 }, + //{ default, ChoosePlural1 }, + { "fil", ChoosePlural2fil }, + { "tl", ChoosePlural2fil }, + { "tzm", ChoosePlural2tzm }, + { "is", ChoosePlural2is }, + { "mk", ChoosePlural2mk }, + { "ak", ChoosePlural2ak }, + { "guw", ChoosePlural2ak }, + { "ln", ChoosePlural2ak }, + { "mg", ChoosePlural2ak }, + { "nso", ChoosePlural2ak }, + { "pa", ChoosePlural2ak }, + { "ti", ChoosePlural2ak }, + { "wa", ChoosePlural2ak }, + { "am", ChoosePlural2am }, + { "as", ChoosePlural2am }, + { "bn", ChoosePlural2am }, + { "gu", ChoosePlural2am }, + { "hi", ChoosePlural2am }, + { "kn", ChoosePlural2am }, + { "mr", ChoosePlural2am }, + { "fa", ChoosePlural2am }, + { "zu", ChoosePlural2am }, + { "hy", ChoosePlural2hy }, + { "fr", ChoosePlural2hy }, + { "ff", ChoosePlural2hy }, + { "kab", ChoosePlural2hy }, + { "pt", ChoosePlural2hy }, + { "si", ChoosePlural2si }, + { "bh", ChoosePlural2bh }, + { "bho", ChoosePlural2bh }, + { "af", ChoosePlural2af }, + { "sq", ChoosePlural2af }, + { "asa", ChoosePlural2af }, + { "az", ChoosePlural2af }, + { "eu", ChoosePlural2af }, + { "bem", ChoosePlural2af }, + { "bez", ChoosePlural2af }, + { "brx", ChoosePlural2af }, + { "bg", ChoosePlural2af }, + { "ckb", ChoosePlural2af }, + { "ce", ChoosePlural2af }, + { "chr", ChoosePlural2af }, + { "cgg", ChoosePlural2af }, + { "dv", ChoosePlural2af }, + { "eo", ChoosePlural2af }, + { "ee", ChoosePlural2af }, + { "fo", ChoosePlural2af }, + { "fur", ChoosePlural2af }, + { "ka", ChoosePlural2af }, + { "el", ChoosePlural2af }, + { "ha", ChoosePlural2af }, + { "haw", ChoosePlural2af }, + { "hu", ChoosePlural2af }, + { "kaj", ChoosePlural2af }, + { "kkj", ChoosePlural2af }, + { "kl", ChoosePlural2af }, + { "ks", ChoosePlural2af }, + { "kk", ChoosePlural2af }, + { "ku", ChoosePlural2af }, + { "ky", ChoosePlural2af }, + { "lb", ChoosePlural2af }, + { "jmc", ChoosePlural2af }, + { "ml", ChoosePlural2af }, + { "mas", ChoosePlural2af }, + { "mgo", ChoosePlural2af }, + { "mn", ChoosePlural2af }, + { "nah", ChoosePlural2af }, + { "ne", ChoosePlural2af }, + { "nnh", ChoosePlural2af }, + { "jgo", ChoosePlural2af }, + { "nd", ChoosePlural2af }, + { "no", ChoosePlural2af }, + { "nb", ChoosePlural2af }, + { "nn", ChoosePlural2af }, + { "ny", ChoosePlural2af }, + { "nyn", ChoosePlural2af }, + { "or", ChoosePlural2af }, + { "om", ChoosePlural2af }, + { "os", ChoosePlural2af }, + { "pap", ChoosePlural2af }, + { "ps", ChoosePlural2af }, + { "rm", ChoosePlural2af }, + { "rof", ChoosePlural2af }, + { "rwk", ChoosePlural2af }, + { "ssy", ChoosePlural2af }, + { "saq", ChoosePlural2af }, + { "seh", ChoosePlural2af }, + { "ksb", ChoosePlural2af }, + { "sn", ChoosePlural2af }, + { "sd", ChoosePlural2af }, + { "xog", ChoosePlural2af }, + { "so", ChoosePlural2af }, + { "nr", ChoosePlural2af }, + { "sdh", ChoosePlural2af }, + { "st", ChoosePlural2af }, + { "es", ChoosePlural2af }, + { "ss", ChoosePlural2af }, + { "gsw", ChoosePlural2af }, + { "syr", ChoosePlural2af }, + { "ta", ChoosePlural2af }, + { "te", ChoosePlural2af }, + { "teo", ChoosePlural2af }, + { "tig", ChoosePlural2af }, + { "ts", ChoosePlural2af }, + { "tn", ChoosePlural2af }, + { "tr", ChoosePlural2af }, + { "tk", ChoosePlural2af }, + { "kcg", ChoosePlural2af }, + { "ug", ChoosePlural2af }, + { "uz", ChoosePlural2af }, + { "ve", ChoosePlural2af }, + { "vo", ChoosePlural2af }, + { "vun", ChoosePlural2af }, + { "wae", ChoosePlural2af }, + { "xh", ChoosePlural2af }, + { "", ChoosePlural2ast }, + { "ast", ChoosePlural2ast }, + { "ca", ChoosePlural2ast }, + { "nl", ChoosePlural2ast }, + { "en", ChoosePlural2ast }, + { "et", ChoosePlural2ast }, + { "pt_PT", ChoosePlural2ast }, + { "fi", ChoosePlural2ast }, + { "gl", ChoosePlural2ast }, + { "lg", ChoosePlural2ast }, + { "de", ChoosePlural2ast }, + { "io", ChoosePlural2ast }, + { "ia", ChoosePlural2ast }, + { "it", ChoosePlural2ast }, + { "sc", ChoosePlural2ast }, + { "scn", ChoosePlural2ast }, + { "sw", ChoosePlural2ast }, + { "sv", ChoosePlural2ast }, + { "ur", ChoosePlural2ast }, + { "fy", ChoosePlural2ast }, + { "ji", ChoosePlural2ast }, + { "yi", ChoosePlural2ast }, // same as "ji" + { "da", ChoosePlural2da }, + { "lv", ChoosePlural3lv }, + { "prg", ChoosePlural3lv }, + { "ksh", ChoosePlural3ksh }, + { "lag", ChoosePlural3lag }, + { "kw", ChoosePlural3kw }, + { "smn", ChoosePlural3kw }, + { "iu", ChoosePlural3kw }, + { "smj", ChoosePlural3kw }, + { "naq", ChoosePlural3kw }, + { "se", ChoosePlural3kw }, + { "smi", ChoosePlural3kw }, + { "sms", ChoosePlural3kw }, + { "sma", ChoosePlural3kw }, + { "bs", ChoosePlural3bs }, + { "hr", ChoosePlural3bs }, + { "sr", ChoosePlural3bs }, + { "sh", ChoosePlural3bs }, + { "sr_Latn", ChoosePlural3bs }, // same as "sh" + { "shi", ChoosePlural3shi }, + { "mo", ChoosePlural3mo }, + { "ro_MD", ChoosePlural3mo }, // same as "mo" + { "ro", ChoosePlural3mo }, + { "be", ChoosePlural4be }, + { "ru", ChoosePlural4ru }, + { "uk", ChoosePlural4ru }, + { "pl", ChoosePlural4pl }, + { "lt", ChoosePlural4lt }, + { "cs", ChoosePlural4cs }, + { "sk", ChoosePlural4cs }, + { "gd", ChoosePlural4gd }, + { "dsb", ChoosePlural4dsb }, + { "hsb", ChoosePlural4dsb }, + { "sl", ChoosePlural4sl }, + { "he", ChoosePlural4he }, + { "iw", ChoosePlural4he }, // same as "he" + { "mt", ChoosePlural4mt }, + { "gv", ChoosePlural5gv }, + { "br", ChoosePlural5br }, + { "ga", ChoosePlural5ga }, + { "ar", ChoosePlural6ar }, + { "ars", ChoosePlural6ar }, + { "cy", ChoosePlural6cy }, + }; + //return { + // //{ "af", ChoosePluralEn }, + // { "ak", ChoosePluralPt }, + // { "am", ChoosePluralPt }, + // { "ar", ChoosePluralAr }, + // { "as", ChoosePluralPt }, + // { "az", ChoosePluralEs }, + // { "be", ChoosePluralRu }, // should be different + // { "bg", ChoosePluralEs }, + // { "bh", ChoosePluralPt }, + // { "bm", ChoosePluralKo }, + // { "bn", ChoosePluralPt }, + // { "bo", ChoosePluralKo }, + // { "bs", ChoosePluralSr }, + // //{ "ca", ChoosePluralEn }, + // //{ "ce", ChoosePluralEn }, + // { "cs", ChoosePluralSk }, + // { "da", ChoosePluralDa }, + // //{ "de", ChoosePluralEn }, + // //{ "dv", ChoosePluralEn }, + // { "dz", ChoosePluralKo }, + // //{ "ee", ChoosePluralEn }, + // { "el", ChoosePluralEs }, + // //{ "en", ChoosePluralEn }, + // { "es", ChoosePluralEs }, + // { "eo", ChoosePluralEs }, + // //{ "et", ChoosePluralEn }, + // { "eu", ChoosePluralEs }, + // { "fa", ChoosePluralPt }, + // { "ff", ChoosePluralPt }, + // //{ "fi", ChoosePluralEn }, + // //{ "fo", ChoosePluralEn }, + // { "fr", ChoosePluralPt }, + // //{ "fy", ChoosePluralEn }, + // //{ "gl", ChoosePluralEn }, + // { "gu", ChoosePluralPt }, + // //{ "ha", ChoosePluralEn }, + // { "he", ChoosePluralHe }, + // { "hi", ChoosePluralPt }, + // { "hr", ChoosePluralSr }, + // { "hu", ChoosePluralEs }, + // { "hy", ChoosePluralPt }, + // //{ "ia", ChoosePluralEn }, + // { "ig", ChoosePluralKo }, + // { "ii", ChoosePluralKo }, + // { "in", ChoosePluralKo }, + // //{ "io", ChoosePluralEn }, + // { "is", ChoosePluralIs }, + // //{ "it", ChoosePluralEn }, + // { "ja", ChoosePluralKo }, + // { "jw", ChoosePluralKo }, + // //{ "ka", ChoosePluralEn }, + // //{ "kk", ChoosePluralEn }, + // //{ "kl", ChoosePluralEn }, + // { "km", ChoosePluralKo }, + // { "kn", ChoosePluralPt }, + // { "ko", ChoosePluralKo }, + // //{ "ks", ChoosePluralEn }, + // //{ "ku", ChoosePluralEn }, + // //{ "ky", ChoosePluralEn }, + // //{ "lb", ChoosePluralEn }, + // //{ "lg", ChoosePluralEn }, + // { "ln", ChoosePluralPt }, + // { "lo", ChoosePluralKo }, + // { "mg", ChoosePluralPt }, + // { "mk", ChoosePluralIs }, + // //{ "ml", ChoosePluralEn }, + // //{ "mn", ChoosePluralEn }, + // { "mo", ChoosePluralRo }, + // { "mr", ChoosePluralPt }, + // { "ms", ChoosePluralKo }, + // { "mt", ChoosePluralMt }, + // { "my", ChoosePluralKo }, + // { "nb", ChoosePluralEs }, + // //{ "nd", ChoosePluralEn }, + // //{ "ne", ChoosePluralEn }, + // //{ "nl", ChoosePluralEn }, + // //{ "nn", ChoosePluralEn }, + // //{ "no", ChoosePluralEn }, + // //{ "nr", ChoosePluralEn }, + // //{ "ny", ChoosePluralEn }, + // //{ "om", ChoosePluralEn }, + // //{ "or", ChoosePluralEn }, + // //{ "os", ChoosePluralEn }, + // { "pa", ChoosePluralPt }, + // //{ "ps", ChoosePluralEn }, + // { "pt", ChoosePluralPt }, + // //{ "pt_PT", ChoosePluralEn }, // not supported + // //{ "rm", ChoosePluralEn }, + // { "ro", ChoosePluralRo }, + // { "ru", ChoosePluralRu }, + // //{ "sc", ChoosePluralEn }, + // //{ "sd", ChoosePluralEn }, + // { "sg", ChoosePluralKo }, + // { "sk", ChoosePluralSk }, + // //{ "sn", ChoosePluralEn }, + // //{ "so", ChoosePluralEn }, + // { "sh", ChoosePluralSr }, + // { "si", ChoosePluralPt }, + // { "sr", ChoosePluralSr }, + // //{ "ss", ChoosePluralEn }, + // //{ "st", ChoosePluralEn }, + // //{ "sv", ChoosePluralEn }, + // //{ "sw", ChoosePluralEn }, + // { "ta", ChoosePluralEs }, + // //{ "te", ChoosePluralEn }, + // { "th", ChoosePluralKo }, + // { "ti", ChoosePluralPt }, + // { "tk", ChoosePluralEs }, + // { "tl", ChoosePluralTl }, + // //{ "tn", ChoosePluralEn }, + // { "to", ChoosePluralKo }, + // { "tr", ChoosePluralEs }, + // //{ "ts", ChoosePluralEn }, + // //{ "ug", ChoosePluralEn }, + // { "uk", ChoosePluralRu }, + // //{ "ur", ChoosePluralEn }, + // { "uz", ChoosePluralEs }, + // { "pl", ChoosePluralPl }, + // { "sq", ChoosePluralEs }, + // //{ "ve", ChoosePluralEn }, + // { "vi", ChoosePluralKo }, + // //{ "vo", ChoosePluralEn }, + // { "wa", ChoosePluralPt }, + // { "wo", ChoosePluralKo }, + // //{ "xh", ChoosePluralEn }, + // //{ "yi", ChoosePluralEn }, + // { "yo", ChoosePluralKo }, + // { "zh", ChoosePluralKo }, + // { "zu", ChoosePluralPt }, + //}; } -ushort ChoosePluralRu(int n, int i, int v, int w, int f, int t) { - if (v == 0) { - auto mod10 = (i % 10); - auto mod100 = (i % 100); - if ((mod10 == 1) && (mod100 != 11)) { - return kShiftOne; - } else if ((mod10 >= 2) && (mod10 <= 4) && (mod100 < 12 || mod100 > 14)) { - return kShiftFew; - } else { - return kShiftMany; - } - } - return kShiftMany;// kShiftOther; -} - -QMap GeneratePluralRulesMap() { - auto result = QMap(); - result.insert(qsl("ar"), ChoosePluralAr); -// result.insert(qsl("de"), ChoosePluralEn); -// result.insert(qsl("en"), ChoosePluralEn); // En is default, so we don't fill it inside the map. - result.insert(qsl("es"), ChoosePluralEs); -// result.insert(qsl("it"), ChoosePluralEn); - result.insert(qsl("ko"), ChoosePluralKo); -// result.insert(qsl("nl"), ChoosePluralEn); - result.insert(qsl("pt"), ChoosePluralPt); - result.insert(qsl("ru"), ChoosePluralRu); - result.insert(qsl("uk"), ChoosePluralRu); - return result; -} - -ChoosePluralMethod ChoosePlural = ChoosePluralEn; +const auto ChoosePluralDefault = &ChoosePlural2ast; +auto ChoosePlural = ChoosePluralDefault; } // namespace @@ -142,29 +885,69 @@ int FindTagReplacementPosition(const QString &original, ushort tag) { } +QString FormatDouble(float64 value) { + auto result = QString::number(value, 'f', 6); + while (result.endsWith('0')) { + result.chop(1); + } + if (result.endsWith('.')) { + result.chop(1); + } + return result; +} + +int NonZeroPartToInt(QString value) { + auto zeros = 0; + for (const auto ch : value) { + if (ch == '0') { + ++zeros; + } else { + break; + } + } + return (zeros > 0) + ? (zeros < value.size() ? value.midRef(zeros).toInt() : 0) + : (value.isEmpty() ? 0 : value.toInt()); +} + PluralResult Plural(ushort keyBase, float64 value) { // Simplified. - auto n = qAbs(value); - auto i = qFloor(n); - auto integer = (qCeil(n) == i); - auto v = integer ? 0 : 6; - auto w = v; - auto f = integer ? 0 : 111111; - auto t = integer ? 0 : 111111; + const auto n = qAbs(value); + const auto i = qFloor(n); + const auto integer = (qCeil(n) == i); + const auto formatted = integer ? QString() : FormatDouble(n); + const auto dot = formatted.indexOf('.'); + const auto fraction = (dot >= 0) ? formatted.mid(dot + 1) : QString(); + const auto v = fraction.size(); + const auto w = v; + const auto f = NonZeroPartToInt(fraction); + const auto t = f; auto &langpack = Lang::Current(); - auto useNonDefaultPlural = (ChoosePlural != ChoosePluralEn && langpack.isNonDefaultPlural(LangKey(keyBase))); - auto shift = (useNonDefaultPlural ? ChoosePlural : ChoosePluralEn)((integer ? i : -1), i, v, w, f, t); + auto useNonDefaultPlural = (ChoosePlural != ChoosePluralDefault) + && langpack.isNonDefaultPlural(LangKey(keyBase)); + auto shift = (useNonDefaultPlural ? ChoosePlural : ChoosePluralDefault)( + (integer ? i : -1), + i, + v, + w, + f, + t); auto string = langpack.getValue(LangKey(keyBase + shift)); - if (i == qCeil(n)) { + if (integer) { return { string, QString::number(qRound(value)) }; } - return { string, QString::number(value) }; + return { string, FormatDouble(value) }; } void UpdatePluralRules(const QString &languageId) { static auto kMap = GeneratePluralRulesMap(); - ChoosePlural = kMap.value(languageId.toLower(), ChoosePluralEn); + auto key = uint64(0); + for (const auto ch : languageId) { + key = (key << 8) | ch.unicode(); + } + const auto i = kMap.find(key); + ChoosePlural = (i == end(kMap)) ? ChoosePlural1 : i->second; } QString ReplaceTag::Replace(QString &&original, const QString &replacement, int replacementPosition) {