From 58afe4199bdf561f902ca1d61c06c7954d14746b Mon Sep 17 00:00:00 2001 From: Tigran Topchyan Date: Sun, 26 Apr 2020 02:07:06 +0400 Subject: [PATCH 1/4] Added Armenian language support --- .../Humanizer.Tests.Shared.projitems | 4 + .../Localisation/hy/DateHumanizeTests.cs | 143 ++++++++++ .../Localisation/hy/NumberToWordsTests.cs | 162 ++++++++++++ .../Localisation/hy/OrdinalizeTests.cs | 42 +++ .../Localisation/hy/TimeSpanHumanizeTests.cs | 154 +++++++++++ .../Configuration/FormatterRegistry.cs | 1 + .../NumberToWordsConverterRegistry.cs | 1 + .../Configuration/OrdinalizerRegistry.cs | 1 + .../ArmenianNumberToWordsConverter.cs | 183 +++++++++++++ .../Ordinalizers/ArmenianOrdinalizer.cs | 19 ++ src/Humanizer/Properties/Resources.hy.resx | 246 ++++++++++++++++++ 11 files changed, 956 insertions(+) create mode 100644 src/Humanizer.Tests.Shared/Localisation/hy/DateHumanizeTests.cs create mode 100644 src/Humanizer.Tests.Shared/Localisation/hy/NumberToWordsTests.cs create mode 100644 src/Humanizer.Tests.Shared/Localisation/hy/OrdinalizeTests.cs create mode 100644 src/Humanizer.Tests.Shared/Localisation/hy/TimeSpanHumanizeTests.cs create mode 100644 src/Humanizer/Localisation/NumberToWords/ArmenianNumberToWordsConverter.cs create mode 100644 src/Humanizer/Localisation/Ordinalizers/ArmenianOrdinalizer.cs create mode 100644 src/Humanizer/Properties/Resources.hy.resx diff --git a/src/Humanizer.Tests.Shared/Humanizer.Tests.Shared.projitems b/src/Humanizer.Tests.Shared/Humanizer.Tests.Shared.projitems index 2730edc2c..c39bb923a 100644 --- a/src/Humanizer.Tests.Shared/Humanizer.Tests.Shared.projitems +++ b/src/Humanizer.Tests.Shared/Humanizer.Tests.Shared.projitems @@ -87,6 +87,10 @@ + + + + diff --git a/src/Humanizer.Tests.Shared/Localisation/hy/DateHumanizeTests.cs b/src/Humanizer.Tests.Shared/Localisation/hy/DateHumanizeTests.cs new file mode 100644 index 000000000..903330831 --- /dev/null +++ b/src/Humanizer.Tests.Shared/Localisation/hy/DateHumanizeTests.cs @@ -0,0 +1,143 @@ +using Humanizer.Localisation; +using Xunit; + +namespace Humanizer.Tests.Localisation.hy +{ + [UseCulture("hy")] + public class DateHumanizeTests + { + + [Theory] + [InlineData(1, "մեկ վայրկյան առաջ")] + [InlineData(2, "2 վայրկյան առաջ")] + [InlineData(3, "3 վայրկյան առաջ")] + [InlineData(4, "4 վայրկյան առաջ")] + [InlineData(11, "11 վայրկյան առաջ")] + [InlineData(21, "21 վայրկյան առաջ")] + [InlineData(24, "24 վայրկյան առաջ")] + [InlineData(40, "40 վայրկյան առաջ")] + public void SecondsAgo(int seconds, string expected) + { + DateHumanize.Verify(expected, seconds, TimeUnit.Second, Tense.Past); + } + + [Theory] + [InlineData(1, "մեկ վայրկյանից")] + [InlineData(2, "2 վայրկյանից")] + [InlineData(11, "11 վայրկյանից")] + [InlineData(20, "20 վայրկյանից")] + [InlineData(40, "40 վայրկյանից")] + public void SecondsFromNow(int seconds, string expected) + { + DateHumanize.Verify(expected, seconds, TimeUnit.Second, Tense.Future); + } + + [Theory] + [InlineData(1, "մեկ րոպե առաջ")] + [InlineData(2, "2 րոպե առաջ")] + [InlineData(10, "10 րոպե առաջ")] + [InlineData(25, "25 րոպե առաջ")] + [InlineData(40, "40 րոպե առաջ")] + [InlineData(60, "մեկ ժամ առաջ")] + public void MinutesAgo(int minutes, string expected) + { + DateHumanize.Verify(expected, minutes, TimeUnit.Minute, Tense.Past); + } + + [Theory] + [InlineData(1, "մեկ րոպեից")] + [InlineData(2, "2 րոպեից")] + [InlineData(19, "19 րոպեից")] + [InlineData(25, "25 րոպեից")] + [InlineData(40, "40 րոպեից")] + public void MinutesFromNow(int minutes, string expected) + { + DateHumanize.Verify(expected, minutes, TimeUnit.Minute, Tense.Future); + } + + [Theory] + [InlineData(1, "մեկ ժամ առաջ")] + [InlineData(2, "2 ժամ առաջ")] + [InlineData(19, "19 ժամ առաջ")] + [InlineData(20, "20 ժամ առաջ")] + public void HoursAgo(int hours, string expected) + { + DateHumanize.Verify(expected, hours, TimeUnit.Hour, Tense.Past); + } + + [Theory] + [InlineData(1, "մեկ ժամից")] + [InlineData(5, "5 ժամից")] + [InlineData(23, "23 ժամից")] + public void HoursFromNow(int hours, string expected) + { + DateHumanize.Verify(expected, hours, TimeUnit.Hour, Tense.Future); + } + + [Theory] + [InlineData(1, "երեկ")] + [InlineData(2, "2 օր առաջ")] + [InlineData(25, "25 օր առաջ")] + public void DaysAgo(int days, string expected) + { + DateHumanize.Verify(expected, days, TimeUnit.Day, Tense.Past); + } + + [Theory] + [InlineData(1, "վաղը")] + [InlineData(2, "2 օրից")] + [InlineData(25, "25 օրից")] + public void DaysFromNow(int days, string expected) + { + DateHumanize.Verify(expected, days, TimeUnit.Day, Tense.Future); + } + + [Theory] + [InlineData(1, "մեկ ամիս առաջ")] + [InlineData(11, "11 ամիս առաջ")] + public void MonthsAgo(int months, string expected) + { + DateHumanize.Verify(expected, months, TimeUnit.Month, Tense.Past); + } + + [Theory] + [InlineData(1, "մեկ ամսից")] + [InlineData(11, "11 ամսից")] + public void MonthsFromNow(int months, string expected) + { + DateHumanize.Verify(expected, months, TimeUnit.Month, Tense.Future); + } + + [Theory] + [InlineData(1, "մեկ տարի առաջ")] + [InlineData(2, "2 տարի առաջ")] + [InlineData(21, "21 տարի առաջ")] + [InlineData(111, "111 տարի առաջ")] + [InlineData(121, "121 տարի առաջ")] + [InlineData(222, "222 տարի առաջ")] + [InlineData(325, "325 տարի առաջ")] + public void YearsAgo(int years, string expected) + { + DateHumanize.Verify(expected, years, TimeUnit.Year, Tense.Past); + } + + [Theory] + [InlineData(1, "մեկ տարուց")] + [InlineData(2, "2 տարուց")] + [InlineData(21, "21 տարուց")] + [InlineData(111, "111 տարուց")] + [InlineData(121, "121 տարուց")] + [InlineData(222, "222 տարուց")] + [InlineData(325, "325 տարուց")] + public void YearsFromNow(int years, string expected) + { + DateHumanize.Verify(expected, years, TimeUnit.Year, Tense.Future); + } + + [Fact] + public void Now() + { + DateHumanize.Verify("հիմա", 0, TimeUnit.Day, Tense.Past); + } + } +} diff --git a/src/Humanizer.Tests.Shared/Localisation/hy/NumberToWordsTests.cs b/src/Humanizer.Tests.Shared/Localisation/hy/NumberToWordsTests.cs new file mode 100644 index 000000000..5815fcdb7 --- /dev/null +++ b/src/Humanizer.Tests.Shared/Localisation/hy/NumberToWordsTests.cs @@ -0,0 +1,162 @@ +using Xunit; + +namespace Humanizer.Tests.Localisation.hy +{ + [UseCulture("hy")] + public class NumberToWordsTests + { + [Theory] + [InlineData(0, "զրո")] + [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(1000, "հազար")] + [InlineData(2000, "երկու հազար")] + [InlineData(3000, "երեք հազար")] + [InlineData(4000, "չորս հազար")] + [InlineData(5000, "հինգ հազար")] + [InlineData(10000, "տաս հազար")] + [InlineData(100000, "հարյուր հազար")] + [InlineData(1000000, "մեկ միլիոն")] + [InlineData(2000000, "երկու միլիոն")] + [InlineData(10000000, "տաս միլիոն")] + [InlineData(100000000, "հարյուր միլիոն")] + [InlineData(1000000000, "մեկ միլիարդ")] + [InlineData(2000000000, "երկու միլիարդ")] + [InlineData(3000000000, "երեք միլիարդ")] + [InlineData(4000000000, "չորս միլիարդ")] + [InlineData(122, "հարյուր քսաներկու")] + [InlineData(3501, "երեք հազար հինգ հարյուր մեկ")] + [InlineData(111, "հարյուր տասնմեկ")] + [InlineData(1112, "հազար հարյուր տասներկու")] + [InlineData(11213, "տասնմեկ հազար երկու հարյուր տասներեք")] + [InlineData(121314, "հարյուր քսանմեկ հազար երեք հարյուր տասնչորս")] + [InlineData(2132415, "երկու միլիոն հարյուր երեսուներկու հազար չորս հարյուր տասնհինգ")] + [InlineData(12345516, "տասներկու միլիոն երեք հարյուր քառասունհինգ հազար հինգ հարյուր տասնվեց")] + [InlineData(751633617, "յոթ հարյուր հիսունմեկ միլիոն վեց հարյուր երեսուներեք հազար վեց հարյուր տասնյոթ")] + [InlineData(1111111118, "մեկ միլիարդ հարյուր տասնմեկ միլիոն հարյուր տասնմեկ հազար հարյուր տասնութ")] + [InlineData(4111111118, "չորս միլիարդ հարյուր տասնմեկ միլիոն հարյուր տասնմեկ հազար հարյուր տասնութ")] + [InlineData(-751633617, "մինուս յոթ հարյուր հիսունմեկ միլիոն վեց հարյուր երեսուներեք հազար վեց հարյուր տասնյոթ")] + [InlineData(999999999999, "ինը հարյուր իննսունինը միլիարդ ինը հարյուր իննսունինը միլիոն ինը հարյուր իննսունինը հազար ինը հարյուր իննսունինը")] + [InlineData(1_000_000_000_000, "մեկ տրիլիոն")] + [InlineData(3_000_000_000_000, "երեք տրիլիոն")] + [InlineData(5_000_000_000_000, "հինգ տրիլիոն")] + [InlineData(999_000_000_000_000, "ինը հարյուր իննսունինը տրիլիոն")] + [InlineData( + long.MaxValue, + "ինը քվինտիլիոն " + + "երկու հարյուր քսաներեք կվադրիլիոն " + + "երեք հարյուր յոթանասուներկու տրիլիոն " + + "երեսունվեց միլիարդ " + + "ութ հարյուր հիսունչորս միլիոն " + + "յոթ հարյուր յոթանասունհինգ հազար " + + "ութ հարյուր յոթ")] + [InlineData( + long.MinValue, + "մինուս ինը քվինտիլիոն " + + "երկու հարյուր քսաներեք կվադրիլիոն " + + "երեք հարյուր յոթանասուներկու տրիլիոն " + + "երեսունվեց միլիարդ " + + "ութ հարյուր հիսունչորս միլիոն " + + "յոթ հարյուր յոթանասունհինգ հազար " + + "ութ հարյուր ութ")] + public void ToWords(long number, string expected) + { + Assert.Equal(expected, number.ToWords()); + } + + [Theory] + [InlineData(0, "զրոյական")] + [InlineData(1, "առաջին")] + [InlineData(2, "երկրորդ")] + [InlineData(3, "երրորդ")] + [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(1000, "հազարերորդ")] + [InlineData(2000, "երկու հազարերորդ")] + [InlineData(3000, "երեք հազարերորդ")] + [InlineData(4000, "չորս հազարերորդ")] + [InlineData(5000, "հինգ հազարերորդ")] + [InlineData(10000, "տաս հազարերորդ")] + [InlineData(21000, "քսանմեկ հազարերորդ")] + [InlineData(100000, "հարյուր հազարերորդ")] + [InlineData(101000, "հարյուր մեկ հազարերորդ")] + [InlineData(1000000, "մեկ միլիոներորդ")] + [InlineData(121000, "հարյուր քսանմեկ հազարերորդ")] + [InlineData(200000, "երկու հարյուր հազարերորդ")] + [InlineData(2000000, "երկու միլիոներորդ")] + [InlineData(10000000, "տաս միլիոներորդ")] + [InlineData(21000000, "քսանմեկ միլիոներորդ")] + [InlineData(100000000, "հարյուր միլիոներորդ")] + [InlineData(230000000, "երկու հարյուր երեսուն միլիոներորդ")] + [InlineData(1000000000, "մեկ միլիարդերորդ")] + [InlineData(2000000000, "երկու միլիարդերորդ")] + [InlineData(122, "հարյուր քսաներկուերորդ")] + [InlineData(3501, "երեք հազար հինգ հարյուր մեկերորդ")] + [InlineData(111, "հարյուր տասնմեկերորդ")] + [InlineData(1112, "հազար հարյուր տասներկուերորդ")] + [InlineData(11213, "տասնմեկ հազար երկու հարյուր տասներեքերորդ")] + [InlineData(121314, "հարյուր քսանմեկ հազար երեք հարյուր տասնչորսերորդ")] + [InlineData(2132415, "երկու միլիոն հարյուր երեսուներկու հազար չորս հարյուր տասնհինգերորդ")] + [InlineData(12345516, "տասներկու միլիոն երեք հարյուր քառասունհինգ հազար հինգ հարյուր տասնվեցերորդ")] + [InlineData(751633617, "յոթ հարյուր հիսունմեկ միլիոն վեց հարյուր երեսուներեք հազար վեց հարյուր տասնյոթերորդ")] + [InlineData(1111111118, "մեկ միլիարդ հարյուր տասնմեկ միլիոն հարյուր տասնմեկ հազար հարյուր տասնութերորդ")] + [InlineData(1111111000, "մեկ միլիարդ հարյուր տասնմեկ միլիոն հարյուր տասնմեկ հազարերորդ")] + [InlineData(1234567000, "մեկ միլիարդ երկու հարյուր երեսունչորս միլիոն հինգ հարյուր վաթսունյոթ հազարերորդ")] + [InlineData(-751633617, "մինուս յոթ հարյուր հիսունմեկ միլիոն վեց հարյուր երեսուներեք հազար վեց հարյուր տասնյոթերորդ")] + public void ToOrdinalWords(int number, string expected) + { + Assert.Equal(expected, number.ToOrdinalWords()); + } + } +} diff --git a/src/Humanizer.Tests.Shared/Localisation/hy/OrdinalizeTests.cs b/src/Humanizer.Tests.Shared/Localisation/hy/OrdinalizeTests.cs new file mode 100644 index 000000000..8f93d03ce --- /dev/null +++ b/src/Humanizer.Tests.Shared/Localisation/hy/OrdinalizeTests.cs @@ -0,0 +1,42 @@ +using Xunit; + +namespace Humanizer.Tests.Localisation.hy +{ + [UseCulture("hy")] + public class OrdinalizeTests + { + + [Theory] + [InlineData("0", "0-րդ")] + [InlineData("1", "1-ին")] + [InlineData("2", "2-րդ")] + [InlineData("103", "103-րդ")] + [InlineData("1001", "1001-րդ")] + public void OrdinalizeStringMasculine(string number, string ordinalized) + { + Assert.Equal(number.Ordinalize(GrammaticalGender.Masculine), ordinalized); + } + + [Theory] + [InlineData("0", "0-րդ")] + [InlineData("1", "1-ին")] + [InlineData("2", "2-րդ")] + [InlineData("103", "103-րդ")] + [InlineData("1001", "1001-րդ")] + public void OrdinalizeStringFeminine(string number, string ordinalized) + { + Assert.Equal(number.Ordinalize(GrammaticalGender.Feminine), ordinalized); + } + + [Theory] + [InlineData("0", "0-րդ")] + [InlineData("1", "1-ին")] + [InlineData("2", "2-րդ")] + [InlineData("103", "103-րդ")] + [InlineData("1001", "1001-րդ")] + public void OrdinalizeStringNeuter(string number, string ordinalized) + { + Assert.Equal(number.Ordinalize(GrammaticalGender.Neuter), ordinalized); + } + } +} diff --git a/src/Humanizer.Tests.Shared/Localisation/hy/TimeSpanHumanizeTests.cs b/src/Humanizer.Tests.Shared/Localisation/hy/TimeSpanHumanizeTests.cs new file mode 100644 index 000000000..617f88d81 --- /dev/null +++ b/src/Humanizer.Tests.Shared/Localisation/hy/TimeSpanHumanizeTests.cs @@ -0,0 +1,154 @@ +using System; +using Xunit; + +namespace Humanizer.Tests.Localisation.hy +{ + [UseCulture("hy")] + public class TimeSpanHumanizeTests + { + + [Theory] + [Trait("Translation", "Native speaker")] + [InlineData(366, "մեկ տարի")] + [InlineData(731, "2 տարի")] + [InlineData(1096, "3 տարի")] + [InlineData(4018, "11 տարի")] + public void Years(int days, string expected) + { + Assert.Equal(expected, TimeSpan.FromDays(days).Humanize(maxUnit: Humanizer.Localisation.TimeUnit.Year)); + } + + [Theory] + [Trait("Translation", "Native speaker")] + [InlineData(31, "մեկ ամիս")] + [InlineData(61, "2 ամիս")] + [InlineData(92, "3 ամիս")] + [InlineData(335, "11 ամիս")] + public void Months(int days, string expected) + { + Assert.Equal(expected, TimeSpan.FromDays(days).Humanize(maxUnit: Humanizer.Localisation.TimeUnit.Year)); + } + + [Theory] + [InlineData(7, "մեկ շաբաթ")] + [InlineData(14, "2 շաբաթ")] + [InlineData(21, "3 շաբաթ")] + [InlineData(28, "4 շաբաթ")] + [InlineData(35, "5 շաբաթ")] + [InlineData(77, "11 շաբաթ")] + public void Weeks(int days, string expected) + { + Assert.Equal(expected, TimeSpan.FromDays(days).Humanize()); + } + + [Theory] + [InlineData(1, "մեկ օր")] + [InlineData(2, "2 օր")] + [InlineData(3, "3 օր")] + [InlineData(4, "4 օր")] + [InlineData(5, "5 օր")] + [InlineData(6, "6 օր")] + public void Days(int days, string expected) + { + Assert.Equal(expected, TimeSpan.FromDays(days).Humanize()); + } + + [Theory] + [InlineData(1, "մեկ ժամ")] + [InlineData(2, "2 ժամ")] + [InlineData(3, "3 ժամ")] + [InlineData(4, "4 ժամ")] + [InlineData(5, "5 ժամ")] + [InlineData(6, "6 ժամ")] + [InlineData(10, "10 ժամ")] + [InlineData(11, "11 ժամ")] + [InlineData(19, "19 ժամ")] + [InlineData(20, "20 ժամ")] + [InlineData(21, "21 ժամ")] + [InlineData(22, "22 ժամ")] + [InlineData(23, "23 ժամ")] + public void Hours(int hours, string expected) + { + Assert.Equal(expected, TimeSpan.FromHours(hours).Humanize()); + } + + [Theory] + [InlineData(1, "մեկ րոպե")] + [InlineData(2, "2 րոպե")] + [InlineData(3, "3 րոպե")] + [InlineData(4, "4 րոպե")] + [InlineData(5, "5 րոպե")] + [InlineData(6, "6 րոպե")] + [InlineData(10, "10 րոպե")] + [InlineData(11, "11 րոպե")] + [InlineData(19, "19 րոպե")] + [InlineData(20, "20 րոպե")] + [InlineData(21, "21 րոպե")] + [InlineData(22, "22 րոպե")] + [InlineData(23, "23 րոպե")] + [InlineData(24, "24 րոպե")] + [InlineData(25, "25 րոպե")] + [InlineData(40, "40 րոպե")] + public void Minutes(int minutes, string expected) + { + Assert.Equal(expected, TimeSpan.FromMinutes(minutes).Humanize()); + } + + [Theory] + [InlineData(1, "մեկ վայրկյան")] + [InlineData(2, "2 վայրկյան")] + [InlineData(3, "3 վայրկյան")] + [InlineData(4, "4 վայրկյան")] + [InlineData(5, "5 վայրկյան")] + [InlineData(6, "6 վայրկյան")] + [InlineData(10, "10 վայրկյան")] + [InlineData(11, "11 վայրկյան")] + [InlineData(19, "19 վայրկյան")] + [InlineData(20, "20 վայրկյան")] + [InlineData(21, "21 վայրկյան")] + [InlineData(22, "22 վայրկյան")] + [InlineData(23, "23 վայրկյան")] + [InlineData(24, "24 վայրկյան")] + [InlineData(25, "25 վայրկյան")] + [InlineData(40, "40 վայրկյան")] + public void Seconds(int seconds, string expected) + { + Assert.Equal(expected, TimeSpan.FromSeconds(seconds).Humanize()); + } + + [Theory] + [InlineData(1, "մեկ միլիվայրկյան")] + [InlineData(2, "2 միլիվայրկյան")] + [InlineData(3, "3 միլիվայրկյան")] + [InlineData(4, "4 միլիվայրկյան")] + [InlineData(5, "5 միլիվայրկյան")] + [InlineData(6, "6 միլիվայրկյան")] + [InlineData(10, "10 միլիվայրկյան")] + [InlineData(11, "11 միլիվայրկյան")] + [InlineData(19, "19 միլիվայրկյան")] + [InlineData(20, "20 միլիվայրկյան")] + [InlineData(21, "21 միլիվայրկյան")] + [InlineData(22, "22 միլիվայրկյան")] + [InlineData(23, "23 միլիվայրկյան")] + [InlineData(24, "24 միլիվայրկյան")] + [InlineData(25, "25 միլիվայրկյան")] + [InlineData(40, "40 միլիվայրկյան")] + public void Milliseconds(int milliseconds, string expected) + { + Assert.Equal(expected, TimeSpan.FromMilliseconds(milliseconds).Humanize()); + } + + [Fact] + public void NoTime() + { + Assert.Equal("0 միլիվայրկյան", TimeSpan.Zero.Humanize()); + } + + [Fact] + public void NoTimeToWords() + { + // This one doesn't make a lot of sense but ... w/e + Assert.Equal("ժամանակը բացակայում է", TimeSpan.Zero.Humanize(toWords: true)); + } + } +} diff --git a/src/Humanizer/Configuration/FormatterRegistry.cs b/src/Humanizer/Configuration/FormatterRegistry.cs index 719b82758..2b048cfdb 100644 --- a/src/Humanizer/Configuration/FormatterRegistry.cs +++ b/src/Humanizer/Configuration/FormatterRegistry.cs @@ -34,6 +34,7 @@ public FormatterRegistry() : base(new DefaultFormatter("en-US")) RegisterDefaultFormatter("fa"); RegisterDefaultFormatter("fi-FI"); RegisterDefaultFormatter("hu"); + RegisterDefaultFormatter("hy"); RegisterDefaultFormatter("id"); RegisterDefaultFormatter("ja"); Register("mt", new MalteseFormatter("mt")); diff --git a/src/Humanizer/Configuration/NumberToWordsConverterRegistry.cs b/src/Humanizer/Configuration/NumberToWordsConverterRegistry.cs index 4fead6259..5e1603d76 100644 --- a/src/Humanizer/Configuration/NumberToWordsConverterRegistry.cs +++ b/src/Humanizer/Configuration/NumberToWordsConverterRegistry.cs @@ -43,6 +43,7 @@ public NumberToWordsConverterRegistry() Register("vi", new VietnameseNumberToWordsConverter()); Register("zh-CN", new ChineseNumberToWordsConverter()); Register("bg", new BulgarianNumberToWordsConverter()); + Register("hy", new ArmenianNumberToWordsConverter()); } } } diff --git a/src/Humanizer/Configuration/OrdinalizerRegistry.cs b/src/Humanizer/Configuration/OrdinalizerRegistry.cs index cee400fb7..ba3224c68 100644 --- a/src/Humanizer/Configuration/OrdinalizerRegistry.cs +++ b/src/Humanizer/Configuration/OrdinalizerRegistry.cs @@ -17,6 +17,7 @@ public OrdinalizerRegistry() : base(new DefaultOrdinalizer()) Register("ru", new RussianOrdinalizer()); Register("tr", new TurkishOrdinalizer()); Register("uk", new UkrainianOrdinalizer()); + Register("hy", new ArmenianOrdinalizer()); } } } diff --git a/src/Humanizer/Localisation/NumberToWords/ArmenianNumberToWordsConverter.cs b/src/Humanizer/Localisation/NumberToWords/ArmenianNumberToWordsConverter.cs new file mode 100644 index 000000000..14ccb0006 --- /dev/null +++ b/src/Humanizer/Localisation/NumberToWords/ArmenianNumberToWordsConverter.cs @@ -0,0 +1,183 @@ +using System; +using System.Collections.Generic; + +namespace Humanizer.Localisation.NumberToWords +{ + internal class ArmenianNumberToWordsConverter : GenderlessNumberToWordsConverter + { + private static readonly string[] UnitsMap = { "զրո", "մեկ", "երկու", "երեք", "չորս", "հինգ", "վեց", "յոթ", "ութ", "ինը", "տաս", "տասնմեկ", "տասներկու", "տասներեք", "տասնչորս", "տասնհինգ", "տասնվեց", "տասնյոթ", "տասնութ", "տասնինը" }; + private static readonly string[] TensMap = { "զրո", "տաս", "քսան", "երեսուն", "քառասուն", "հիսուն", "վաթսուն", "յոթանասուն", "ութսուն", "իննսուն" }; + + private static readonly Dictionary OrdinalExceptions = new Dictionary + { + {0, "զրոյական"}, + {1, "առաջին"}, + {2, "երկրորդ"}, + {3, "երրորդ"}, + {4, "չորրորդ"} + }; + + public override string Convert(long number) + { + return Convert(number, false); + } + + public override string ConvertToOrdinal(int number) + { + if (ExceptionNumbersToWords(number, out var exceptionString)) + { + return exceptionString; + } + + return Convert(number, true); + } + + private string Convert(long number, bool isOrdinal) + { + if (number == 0) + { + return GetUnitValue(0, isOrdinal); + } + + if (number == long.MinValue) + { + return "մինուս ինը քվինտիլիոն " + + "երկու հարյուր քսաներեք կվադրիլիոն " + + "երեք հարյուր յոթանասուներկու տրիլիոն " + + "երեսունվեց միլիարդ " + + "ութ հարյուր հիսունչորս միլիոն " + + "յոթ հարյուր յոթանասունհինգ հազար " + + "ութ հարյուր ութ"; + } + + if (number < 0) + { + return string.Format("մինուս {0}", Convert(-number, isOrdinal)); + } + + var parts = new List(); + + if ((number / 1000000000000000000) > 0) + { + parts.Add(string.Format("{0} քվինտիլիոն", Convert(number / 1000000000000000000))); + number %= 1000000000000000000; + } + + if ((number / 1000000000000000) > 0) + { + parts.Add(string.Format("{0} կվադրիլիոն", Convert(number / 1000000000000000))); + number %= 1000000000000000; + } + + if ((number / 1000000000000) > 0) + + { + parts.Add(string.Format("{0} տրիլիոն", Convert(number / 1000000000000))); + number %= 1000000000000; + } + + if ((number / 1000000000) > 0) + { + parts.Add(string.Format("{0} միլիարդ", Convert(number / 1000000000))); + number %= 1000000000; + } + + if ((number / 1000000) > 0) + { + parts.Add(string.Format("{0} միլիոն", Convert(number / 1000000))); + number %= 1000000; + } + + if ((number / 1000) > 0) + { + if ((number / 1000) == 1) + { + parts.Add("հազար"); + } + else + { + parts.Add(string.Format("{0} հազար", Convert(number / 1000))); + } + + number %= 1000; + } + + if ((number / 100) > 0) + { + if ((number / 100) == 1) + { + parts.Add("հարյուր"); + } + else + { + parts.Add(string.Format("{0} հարյուր", Convert(number / 100))); + } + + number %= 100; + } + + if (number > 0) + { + if (number < 20) + { + parts.Add(GetUnitValue(number, isOrdinal)); + } + else + { + var lastPart = TensMap[number / 10]; + if ((number % 10) > 0) + { + lastPart += string.Format("{0}", GetUnitValue(number % 10, isOrdinal)); + } + else if (isOrdinal) + { + lastPart += "երորդ"; + } + + parts.Add(lastPart); + } + } + else if (isOrdinal) + { + parts[parts.Count - 1] += "երորդ"; + } + + var toWords = string.Join(" ", parts.ToArray()); + + //if (isOrdinal) + //{ + // toWords = RemoveOnePrefix(toWords); + //} + + return toWords; + } + + private static string GetUnitValue(long number, bool isOrdinal) + { + if (isOrdinal) + { + return UnitsMap[number] + "երորդ"; + } + else + { + return UnitsMap[number]; + } + } + + private static string RemoveOnePrefix(string toWords) + { + // one hundred => hundredth + if (toWords.IndexOf("մեկ", StringComparison.Ordinal) == 0) + { + toWords = toWords.Remove(0, 4); + } + + return toWords; + } + + private static bool ExceptionNumbersToWords(long number, out string words) + { + return OrdinalExceptions.TryGetValue(number, out words); + } + } +} diff --git a/src/Humanizer/Localisation/Ordinalizers/ArmenianOrdinalizer.cs b/src/Humanizer/Localisation/Ordinalizers/ArmenianOrdinalizer.cs new file mode 100644 index 000000000..6417deb84 --- /dev/null +++ b/src/Humanizer/Localisation/Ordinalizers/ArmenianOrdinalizer.cs @@ -0,0 +1,19 @@ +using System; +using System.Collections.Generic; +using System.Text; + +namespace Humanizer.Localisation.Ordinalizers +{ + internal class ArmenianOrdinalizer : DefaultOrdinalizer + { + public override string Convert(int number, string numberString) + { + if (number == 1 || number == -1) + { + return numberString + "-ին"; + } + + return numberString + "-րդ"; + } + } +} diff --git a/src/Humanizer/Properties/Resources.hy.resx b/src/Humanizer/Properties/Resources.hy.resx new file mode 100644 index 000000000..39b0cc98e --- /dev/null +++ b/src/Humanizer/Properties/Resources.hy.resx @@ -0,0 +1,246 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + text/microsoft-resx + + + 2.0 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + մեկ վայրկյան առաջ + + + մեկ րոպե առաջ + + + մեկ ժամ առաջ + + + երեկ + + + մեկ ամիս առաջ + + + մեկ տարի առաջ + + + {0} ժամ առաջ + + + {0} րոպե առաջ + + + {0} ամիս առաջ + + + {0} վայրկյան առաջ + + + {0} տարի առաջ + + + {0} օր առաջ + + + հիմա + + + {0} օր + + + {0} ժամ + + + {0} միլիվայրկյան + + + {0} րոպե + + + {0} վայրկյան + + + {0} շաբաթ + + + մեկ օր + + + մեկ ժամ + + + մեկ միլիվայրկյան + + + մեկ րոպե + + + մեկ վայրկյան + + + մեկ շաբաթ + + + ժամանակը բացակայում է + + + {0} օրից + + + {0} ժամից + + + {0} րոպեից + + + {0} ամսից + + + {0} վայրկյանից + + + {0} տարուց + + + վաղը + + + մեկ ժամից + + + մեկ րոպեից + + + մեկ ամսից + + + մեկ վայրկյանից + + + մեկ տարուց + + + {0} ամիս + + + {0} տարի + + + մեկ ամիս + + + մեկ տարի + + \ No newline at end of file From 9889bf1395590faaf4d3b0c598d3993a3b0b1ab6 Mon Sep 17 00:00:00 2001 From: Tigran Topchyan Date: Tue, 28 Apr 2020 09:24:42 +0400 Subject: [PATCH 2/4] Added NuSpec for Armenian language --- NuSpecs/Humanizer.Core.hy.nuspec | 25 +++++++++++++++++++++++++ src/Humanizer.sln | 1 + 2 files changed, 26 insertions(+) create mode 100644 NuSpecs/Humanizer.Core.hy.nuspec diff --git a/NuSpecs/Humanizer.Core.hy.nuspec b/NuSpecs/Humanizer.Core.hy.nuspec new file mode 100644 index 000000000..fa29282ea --- /dev/null +++ b/NuSpecs/Humanizer.Core.hy.nuspec @@ -0,0 +1,25 @@ + + + + Humanizer.Core.ru + $version$ + Humanizer Locale (ru) + Mehdi Khalili, Claire Novotny + https://github.com/Humanizr/Humanizer + logo.png + false + Humanizer Locale Armenian (hy) + Copyright (c) .NET Foundation and Contributors + MIT + + ru + + + + + + + + + + \ No newline at end of file diff --git a/src/Humanizer.sln b/src/Humanizer.sln index 3271244c4..c633f5497 100644 --- a/src/Humanizer.sln +++ b/src/Humanizer.sln @@ -52,6 +52,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "NuSpecs", "NuSpecs", "{AA44 ..\NuSpecs\Humanizer.Core.he.nuspec = ..\NuSpecs\Humanizer.Core.he.nuspec ..\NuSpecs\Humanizer.Core.hr.nuspec = ..\NuSpecs\Humanizer.Core.hr.nuspec ..\NuSpecs\Humanizer.Core.hu.nuspec = ..\NuSpecs\Humanizer.Core.hu.nuspec + ..\NuSpecs\Humanizer.Core.hy.nuspec = ..\NuSpecs\Humanizer.Core.hy.nuspec ..\NuSpecs\Humanizer.Core.id.nuspec = ..\NuSpecs\Humanizer.Core.id.nuspec ..\NuSpecs\Humanizer.Core.it.nuspec = ..\NuSpecs\Humanizer.Core.it.nuspec ..\NuSpecs\Humanizer.Core.ja.nuspec = ..\NuSpecs\Humanizer.Core.ja.nuspec From 78901fedacf937ac1f56bcd2e841c1aefa294e29 Mon Sep 17 00:00:00 2001 From: Tigran Topchyan Date: Wed, 29 Apr 2020 18:39:18 +0400 Subject: [PATCH 3/4] Update NuSpecs/Humanizer.Core.hy.nuspec Co-Authored-By: Claire Novotny --- NuSpecs/Humanizer.Core.hy.nuspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/NuSpecs/Humanizer.Core.hy.nuspec b/NuSpecs/Humanizer.Core.hy.nuspec index fa29282ea..7f97e698e 100644 --- a/NuSpecs/Humanizer.Core.hy.nuspec +++ b/NuSpecs/Humanizer.Core.hy.nuspec @@ -3,7 +3,7 @@ Humanizer.Core.ru $version$ - Humanizer Locale (ru) + Humanizer Locale (hy) Mehdi Khalili, Claire Novotny https://github.com/Humanizr/Humanizer logo.png @@ -22,4 +22,4 @@ - \ No newline at end of file + From e3913584170eeec04bd220a29be36b5476d3aca2 Mon Sep 17 00:00:00 2001 From: Tigran Topchyan Date: Wed, 29 Apr 2020 18:39:26 +0400 Subject: [PATCH 4/4] Update NuSpecs/Humanizer.Core.hy.nuspec Co-Authored-By: Claire Novotny --- NuSpecs/Humanizer.Core.hy.nuspec | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/NuSpecs/Humanizer.Core.hy.nuspec b/NuSpecs/Humanizer.Core.hy.nuspec index 7f97e698e..0e3bdce76 100644 --- a/NuSpecs/Humanizer.Core.hy.nuspec +++ b/NuSpecs/Humanizer.Core.hy.nuspec @@ -1,7 +1,7 @@  - Humanizer.Core.ru + Humanizer.Core.hy $version$ Humanizer Locale (hy) Mehdi Khalili, Claire Novotny