From e79d47fcc89d150a4c62b263738286d810745fee Mon Sep 17 00:00:00 2001 From: Oxana Miheeva Date: Sun, 9 Jun 2019 14:51:42 +0300 Subject: [PATCH] add BolgarianNumberToWordsConverter --- .../Localisation/bg/NumberToWordsTests.cs | 161 ++++++++++++++++++ .../NumberToWordsConverterRegistry.cs | 1 + .../BolgarianNumberToWordsConverter.cs | 125 ++++++++++++++ 3 files changed, 287 insertions(+) create mode 100644 src/Humanizer.Tests.Shared/Localisation/bg/NumberToWordsTests.cs create mode 100644 src/Humanizer/Localisation/NumberToWords/BolgarianNumberToWordsConverter.cs diff --git a/src/Humanizer.Tests.Shared/Localisation/bg/NumberToWordsTests.cs b/src/Humanizer.Tests.Shared/Localisation/bg/NumberToWordsTests.cs new file mode 100644 index 000000000..15f1d179c --- /dev/null +++ b/src/Humanizer.Tests.Shared/Localisation/bg/NumberToWordsTests.cs @@ -0,0 +1,161 @@ +using Xunit; + +namespace Humanizer.Tests.Localisation.bg +{ + [UseCulture("bg")] + public class NumberToWordsTests + { + + [Theory] + [InlineData(0, "noly")] + [InlineData(1, "един")] + [InlineData(10, "десет")] + [InlineData(11, "единадесет")] + [InlineData(12, "дванадесет")] + [InlineData(13, "тринадесет")] + [InlineData(14, "четиринадесет")] + [InlineData(15, "петнадесет")] + [InlineData(16, "шестнадесет")] + [InlineData(17, "седемнадесет")] + [InlineData(18, "осемнадесет")] + [InlineData(19, "деветнадесет")] + [InlineData(20, "двадесет")] + [InlineData(30, "тридесет")] + [InlineData(40, "четиридесет")] + [InlineData(50, "петдесет")] + [InlineData(60, "шейсет")] + [InlineData(70, "седемдесет")] + [InlineData(80, "осемдесет")] + [InlineData(90, "деветдесет")] + [InlineData(100, "сто")] + [InlineData(200, "двеста")] + [InlineData(300, "триста")] + [InlineData(400, "че́тиристотин")] + [InlineData(500, "петстотин")] + [InlineData(600, "шестстотин")] + [InlineData(700, "седемстотин")] + [InlineData(800, "осемстотин")] + [InlineData(900, "деветстотин")] + [InlineData(122, " сто двадесет и две")] + [InlineData(111, "сто единадесет")] + [InlineData(55, "петдесет и пет")] + + public void ToWords(long number, string expected) + { + Assert.Equal(expected, number.ToWords()); + } + + + [Theory] + [InlineData(0, "нула")] + [InlineData(1, "първи")] + [InlineData(2, "втори")] + [InlineData(3, "трети")] + [InlineData(4, "четвърти")] + [InlineData(5, "пети")] + [InlineData(6, "шести")] + [InlineData(7, "седми")] + [InlineData(8, "осми")] + [InlineData(9, "девяти")] + [InlineData(10, "десяти")] + [InlineData(11, "единадесети")] + [InlineData(12, "дванадесети")] + [InlineData(13, "тринадесети")] + [InlineData(14, "четиринадесети")] + [InlineData(15, "петнадесети")] + [InlineData(16, "шестнадесети")] + [InlineData(17, "седемнадесети")] + [InlineData(18, "осемнадесети")] + [InlineData(19, "деветнадесети")] + [InlineData(20, "двадесети")] + [InlineData(30, "тридесети")] + [InlineData(40, "четиридесети")] + [InlineData(50, "петдесети")] + [InlineData(60, "шейсети")] + [InlineData(70, "седемдесети")] + [InlineData(80, "осемдесети")] + [InlineData(90, "деветдесети")] + [InlineData(21, "двадесет и първи")] + [InlineData(22, "двадесет и втори")] + [InlineData(35, "тридесет и пети")] + public void ToOrdinalWordsMasculine(int number, string expected) + { + Assert.Equal(expected, number.ToOrdinalWords(GrammaticalGender.Masculine)); + } + + [Theory] + [InlineData(0, "нула")] + [InlineData(1, "първа")] + [InlineData(2, "втора")] + [InlineData(3, "трета")] + [InlineData(4, "четвърта")] + [InlineData(5, "пета")] + [InlineData(6, "шеста")] + [InlineData(7, "седма")] + [InlineData(8, "осма")] + [InlineData(9, "девята")] + [InlineData(10, "десята")] + [InlineData(11, "единадесета")] + [InlineData(12, "дванадесета")] + [InlineData(13, "тринадесета")] + [InlineData(14, "четиринадесета")] + [InlineData(15, "петнадесета")] + [InlineData(16, "шестнадесета")] + [InlineData(17, "седемнадесета")] + [InlineData(18, "осемнадесета")] + [InlineData(19, "деветнадесета")] + [InlineData(20, "двадесета")] + [InlineData(30, "тридесета")] + [InlineData(40, "четиридесета")] + [InlineData(50, "петдесета")] + [InlineData(60, "шейсета")] + [InlineData(70, "седемдесета")] + [InlineData(80, "осемдесета")] + [InlineData(90, "деветдесета")] + [InlineData(21, "двадесет и първа")] + [InlineData(22, "двадесет и втора")] + [InlineData(35, "тридесет и пета")] + public void ToOrdinalWordsFeminine(int number, string expected) + { + Assert.Equal(expected, number.ToOrdinalWords(GrammaticalGender.Feminine)); + } + + + [Theory] + [InlineData(0, "нула")] + [InlineData(1, "първо")] + [InlineData(2, "второ")] + [InlineData(3, "трето")] + [InlineData(4, "четвърто")] + [InlineData(5, "пето")] + [InlineData(6, "шесто")] + [InlineData(7, "седмо")] + [InlineData(8, "осмо")] + [InlineData(9, "девято")] + [InlineData(10, "десято")] + [InlineData(11, "единадесето")] + [InlineData(12, "дванадесето")] + [InlineData(13, "тринадесето")] + [InlineData(14, "четиринадесето")] + [InlineData(15, "петнадесето")] + [InlineData(16, "шестнадесето")] + [InlineData(17, "седемнадесето")] + [InlineData(18, "осемнадесето")] + [InlineData(19, "деветнадесето")] + [InlineData(20, "двадесето")] + [InlineData(30, "тридесето")] + [InlineData(40, "четиридесето")] + [InlineData(50, "петдесето")] + [InlineData(60, "шейсето")] + [InlineData(70, "седемдесето")] + [InlineData(80, "осемдесето")] + [InlineData(90, "деветдесето")] + [InlineData(21, "двадесет и първо")] + [InlineData(22, "двадесет и второ")] + [InlineData(35, "тридесет и пето")] + public void ToOrdinalWordsNeuter(int number, string expected) + { + Assert.Equal(expected, number.ToOrdinalWords(GrammaticalGender.Neuter)); + } + } +} diff --git a/src/Humanizer/Configuration/NumberToWordsConverterRegistry.cs b/src/Humanizer/Configuration/NumberToWordsConverterRegistry.cs index f0af8bd3f..dbec634a1 100644 --- a/src/Humanizer/Configuration/NumberToWordsConverterRegistry.cs +++ b/src/Humanizer/Configuration/NumberToWordsConverterRegistry.cs @@ -37,6 +37,7 @@ public NumberToWordsConverterRegistry() Register("sr-Latn", (culture) => new SerbianNumberToWordsConverter(culture)); Register("nb", new NorwegianBokmalNumberToWordsConverter()); Register("zh-CN", new ChineseNumberToWordsConverter()); + Register("bg", new BolgarianNumberToWordsConverter()); } } } diff --git a/src/Humanizer/Localisation/NumberToWords/BolgarianNumberToWordsConverter.cs b/src/Humanizer/Localisation/NumberToWords/BolgarianNumberToWordsConverter.cs new file mode 100644 index 000000000..caaa75927 --- /dev/null +++ b/src/Humanizer/Localisation/NumberToWords/BolgarianNumberToWordsConverter.cs @@ -0,0 +1,125 @@ +using System; +using System.Collections.Generic; +using System.Globalization; + +namespace Humanizer.Localisation.NumberToWords +{ + internal class BolgarianNumberToWordsConverter : GenderedNumberToWordsConverter + { + private static readonly string[] UnitsMap = { "нула", "един", "две", "три", "четири", "пет", "шест", "седем", "осем", "девет", "десет", "единадесет", "дванадесет", "тринадесет", "четиринадесет", "петнадесет", "шестнадесет", "седемнадесет", "осемнадесет", "деветнадесет" }; + private static readonly string[] TensMap = { "нула", "десет", "двадесет", "тридесет", "четиридесет", "петдесет", "шейсет", "седемдесет", "осемдесет", "деветдесет" }; + private static readonly string[] HundredsMap = { "нула", "сто", "двеста", "триста", "че́тиристотин", "петстотин", "шестстотин", "седемстотин", "осемстотин", "деветстотин" }; + + private static readonly string[] TensOrdinal = { string.Empty, "десет", "двадесет", "тридесет", "четиридесет", "петдесет", "шейсет", "седемдесет", "осемдесет", "деветдесет" }; + private static readonly string[] UnitsOrdinal = { string.Empty, "първ", "втор", "трет", "четвърт", "пет", "шест", "седм", "осм", "девят", "десят", "единадесет", "дванадесет", "тринадесет", "четиринадесет", "петнадесет", "шестнадесет", "седемнадесет", "осемнадесет", "деветнадесет" }; + + public override string Convert(long input, GrammaticalGender gender) + { + if (input > Int32.MaxValue || input < Int32.MinValue) + { + throw new NotImplementedException(); + } + + if (input == 0) + { + return "нула"; + } + + var parts = new List(); + + if (input < 0) + { + parts.Add("минус"); + input = -input; + } + + var hundreds = input / 100; + + if (hundreds > 0) + { + parts.Add(HundredsMap[input / 100]); + input %= 100; + if (hundreds > 0) + { + parts.Add(""); + } + } + + if (input > 0) + { + if (input < 20) + { + parts.Add(UnitsMap[input]); + } + else + { + + parts.Add(TensMap[input / 10]); + + var units = input % 10; + + if (units > 0) + { + parts.Add(string.Format("и {0}", UnitsMap[units])); + } + } + } + + return string.Join(" ", parts); + } + + public override string ConvertToOrdinal(int input, GrammaticalGender gender) + { + if (input == 0) + { + return "нула"; + } + + var parts = new List(); + + if (input < 0) + { + parts.Add("минус"); + input = -input; + } + + if (input >= 20) + { + var ending = GetEndingForGender(gender, input); + var tens = input / 10; + input %= 10; + if (input == 0) + { + parts.Add(TensOrdinal[tens] + ending); + } + else + { + parts.Add(string.Format("{0} и", TensMap[tens])); + } + } + + if (input > 0) + { + parts.Add(UnitsOrdinal[input] + GetEndingForGender(gender, input)); + } + + return string.Join(" ", parts); + } + + private static string GetEndingForGender(GrammaticalGender gender, long number) + { + switch (gender) + { + case GrammaticalGender.Masculine: + return "и"; + case GrammaticalGender.Feminine: + return "а"; + case GrammaticalGender.Neuter: + return "о"; + default: + throw new ArgumentOutOfRangeException(nameof(gender)); + } + } + + } +}