From ab97a901b35e3c6f6f4d84b19b5c8c085878e335 Mon Sep 17 00:00:00 2001 From: Max Malook Date: Thu, 1 May 2014 13:26:07 +0200 Subject: [PATCH 1/4] add german localization for ToOrdinalWords --- .../Localisation/de/NumberToWordsTests.cs | 46 +++++++++++++ .../GermanNumberToWordsConverter.cs | 69 +++++++++++++++++++ 2 files changed, 115 insertions(+) diff --git a/src/Humanizer.Tests/Localisation/de/NumberToWordsTests.cs b/src/Humanizer.Tests/Localisation/de/NumberToWordsTests.cs index d707f5019..7d602c3aa 100644 --- a/src/Humanizer.Tests/Localisation/de/NumberToWordsTests.cs +++ b/src/Humanizer.Tests/Localisation/de/NumberToWordsTests.cs @@ -52,5 +52,51 @@ public void ToWords(int number, string expected) { Assert.Equal(expected, number.ToWords()); } + + [Theory] + [InlineData(0, "nullter")] + [InlineData(1, "erster")] + [InlineData(2, "zweiter")] + [InlineData(3, "dritter")] + [InlineData(4, "vierter")] + [InlineData(5, "fünfter")] + [InlineData(6, "sechster")] + [InlineData(7, "siebter")] + [InlineData(8, "achter")] + [InlineData(9, "neunter")] + [InlineData(10, "zehnter")] + [InlineData(20, "zwanzigster")] + [InlineData(30, "dreißigster")] + [InlineData(40, "vierzigster")] + [InlineData(50, "fünfzigster")] + [InlineData(60, "sechzigster")] + [InlineData(70, "siebzigster")] + [InlineData(80, "achtzigster")] + [InlineData(90, "neunzigster")] + [InlineData(100, "einhundertster")] + [InlineData(200, "zweihundertster")] + [InlineData(1000, "eintausendster")] + [InlineData(10000, "zehntausendster")] + [InlineData(100000, "einhunderttausendster")] + [InlineData(1000000, "einmillionster")] + [InlineData(10000000, "zehnmillionster")] + [InlineData(100000000, "einhundertmillionster")] + [InlineData(1000000000, "einmilliardster")] + [InlineData(2000000000, "zweimilliardster")] + [InlineData(122, "einhundertzweiundzwanzigster")] + [InlineData(3501, "dreitausendfünfhunderterster")] + [InlineData(111, "einhundertelfter")] + [InlineData(1112, "eintausendeinhundertzwölfter")] + [InlineData(11213, "elftausendzweihundertdreizehnter")] + [InlineData(121314, "einhunderteinundzwanzigtausenddreihundertvierzehnter")] + [InlineData(2132415, "zweimillioneneinhundertzweiunddreißigtausendvierhundertfünfzehnter")] + [InlineData(12345516, "zwölfmillionendreihundertfünfundvierzigtausendfünfhundertsechzehnter")] + [InlineData(751633617, "siebenhunderteinundfünfzigmillionensechshundertdreiunddreißigtausendsechshundertsiebzehnter")] + [InlineData(1111111118, "einemilliardeeinhundertelfmillioneneinhundertelftausendeinhundertachtzehnter")] + [InlineData(-751633619, "minus siebenhunderteinundfünfzigmillionensechshundertdreiunddreißigtausendsechshundertneunzehnter")] + public void ToOrdinalWords(int number, string expected) + { + Assert.Equal(expected, number.ToOrdinalWords()); + } } } diff --git a/src/Humanizer/Localisation/NumberToWords/GermanNumberToWordsConverter.cs b/src/Humanizer/Localisation/NumberToWords/GermanNumberToWordsConverter.cs index 053bfc9c3..3b3a4034b 100644 --- a/src/Humanizer/Localisation/NumberToWords/GermanNumberToWordsConverter.cs +++ b/src/Humanizer/Localisation/NumberToWords/GermanNumberToWordsConverter.cs @@ -6,6 +6,11 @@ internal class GermanNumberToWordsConverter : DefaultNumberToWordsConverter { private static readonly string[] UnitsMap = { "null", "ein", "zwei", "drei", "vier", "fünf", "sechs", "sieben", "acht", "neun", "zehn", "elf", "zwölf", "dreizehn", "vierzehn", "fünfzehn", "sechzehn", "siebzehn", "achtzehn", "neunzehn" }; private static readonly string[] TensMap = { "null", "zehn", "zwanzig", "dreißig", "vierzig", "fünfzig", "sechzig", "siebzig", "achtzig", "neunzig" }; + private static readonly string[] UnitsOrdinal = { string.Empty, "erster", "zweiter", "dritter", "vierter", "fünfter", "sechster", "siebter", "achter", "neunter", "zehnter", "elfter", "zwölfter", "dreizehnter", "vierzehnter", "fünfzehnter", "sechzehnter", "siebzehnter", "achtzehnter", "neunzehnter" }; + private static readonly string[] MillionOrdinalSingular = { "einmillion", "einemillion" }; + private static readonly string[] MillionOrdinalPlural = { "{0}million", "{0}millionen" }; + private static readonly string[] BillionOrdinalSingular = { "einmilliard", "einemilliarde" }; + private static readonly string[] BillionOrdinalPlural = { "{0}milliard", "{0}milliarden" }; public override string Convert(int number) { @@ -71,6 +76,70 @@ public override string Convert(int number) return string.Join("", parts); } + public override string ConvertToOrdinal(int number) + { + if (number == 0) + return "nullter"; + + var parts = new List(); + if (number < 0) + { + parts.Add("minus "); + number = -number; + } + + var billions = number / 1000000000; + if (billions > 0) + { + number %= 1000000000; + var noRest = number == 0 ? 0 : 1; + parts.Add(Part(BillionOrdinalPlural[noRest], BillionOrdinalSingular[noRest], billions)); + } + + var millions = number / 1000000; + if (millions > 0) + { + number %= 1000000; + var noRest = number == 0 ? 0 : 1; + parts.Add(Part(MillionOrdinalPlural[noRest], MillionOrdinalSingular[noRest], millions)); + } + + var thousands = number / 1000; + if (thousands > 0) + { + parts.Add(Part("{0}tausend", "eintausend", thousands)); + number %= 1000; + } + + var hundreds = number / 100; + if (hundreds > 0) + { + parts.Add(Part("{0}hundert", "einhundert", hundreds)); + number %= 100; + } + + if (number > 0) + { + if (number < 20) + { + parts.Add(UnitsOrdinal[number]); + } + else + { + var units = number%10; + if (units > 0) + parts.Add(string.Format("{0}und", UnitsMap[units])); + + parts.Add(TensMap[number/10]); + } + } + + if (number == 0 || number >= 20) + parts.Add("ster"); + + return string.Join("", parts); + } + private string Part(string pluralFormat, string singular, int number) { if (number == 1) From a99fea2a52bd5a4cb67a0c350fec2fcb1ea61735 Mon Sep 17 00:00:00 2001 From: Max Malook Date: Thu, 1 May 2014 13:47:38 +0200 Subject: [PATCH 2/4] add grammatical cases to german localization for ToOrdinalWords --- .../Localisation/de/NumberToWordsTests.cs | 52 ++++++++++++ .../GermanNumberToWordsConverter.cs | 83 +++++++++++-------- 2 files changed, 101 insertions(+), 34 deletions(-) diff --git a/src/Humanizer.Tests/Localisation/de/NumberToWordsTests.cs b/src/Humanizer.Tests/Localisation/de/NumberToWordsTests.cs index 7d602c3aa..f50c9a438 100644 --- a/src/Humanizer.Tests/Localisation/de/NumberToWordsTests.cs +++ b/src/Humanizer.Tests/Localisation/de/NumberToWordsTests.cs @@ -98,5 +98,57 @@ public void ToOrdinalWords(int number, string expected) { Assert.Equal(expected, number.ToOrdinalWords()); } + + [Theory] + [InlineData(0, "nullte")] + [InlineData(1, "erste")] + [InlineData(2, "zweite")] + [InlineData(3, "dritte")] + [InlineData(4, "vierte")] + [InlineData(5, "fünfte")] + [InlineData(6, "sechste")] + [InlineData(7, "siebte")] + [InlineData(8, "achte")] + [InlineData(9, "neunte")] + [InlineData(10, "zehnte")] + [InlineData(111, "einhundertelfte")] + [InlineData(1112, "eintausendeinhundertzwölfte")] + [InlineData(11213, "elftausendzweihundertdreizehnte")] + [InlineData(121314, "einhunderteinundzwanzigtausenddreihundertvierzehnte")] + [InlineData(2132415, "zweimillioneneinhundertzweiunddreißigtausendvierhundertfünfzehnte")] + [InlineData(12345516, "zwölfmillionendreihundertfünfundvierzigtausendfünfhundertsechzehnte")] + [InlineData(751633617, "siebenhunderteinundfünfzigmillionensechshundertdreiunddreißigtausendsechshundertsiebzehnte")] + [InlineData(1111111118, "einemilliardeeinhundertelfmillioneneinhundertelftausendeinhundertachtzehnte")] + [InlineData(-751633619, "minus siebenhunderteinundfünfzigmillionensechshundertdreiunddreißigtausendsechshundertneunzehnte")] + public void ToOrdinalWordsFeminine(int number, string expected) + { + Assert.Equal(expected, number.ToOrdinalWords(GrammaticalGender.Feminine)); + } + + [Theory] + [InlineData(0, "nulltes")] + [InlineData(1, "erstes")] + [InlineData(2, "zweites")] + [InlineData(3, "drittes")] + [InlineData(4, "viertes")] + [InlineData(5, "fünftes")] + [InlineData(6, "sechstes")] + [InlineData(7, "siebtes")] + [InlineData(8, "achtes")] + [InlineData(9, "neuntes")] + [InlineData(10, "zehntes")] + [InlineData(111, "einhundertelftes")] + [InlineData(1112, "eintausendeinhundertzwölftes")] + [InlineData(11213, "elftausendzweihundertdreizehntes")] + [InlineData(121314, "einhunderteinundzwanzigtausenddreihundertvierzehntes")] + [InlineData(2132415, "zweimillioneneinhundertzweiunddreißigtausendvierhundertfünfzehntes")] + [InlineData(12345516, "zwölfmillionendreihundertfünfundvierzigtausendfünfhundertsechzehntes")] + [InlineData(751633617, "siebenhunderteinundfünfzigmillionensechshundertdreiunddreißigtausendsechshundertsiebzehntes")] + [InlineData(1111111118, "einemilliardeeinhundertelfmillioneneinhundertelftausendeinhundertachtzehntes")] + [InlineData(-751633619, "minus siebenhunderteinundfünfzigmillionensechshundertdreiunddreißigtausendsechshundertneunzehntes")] + public void ToOrdinalWordsNeuter(int number, string expected) + { + Assert.Equal(expected, number.ToOrdinalWords(GrammaticalGender.Neuter)); + } } } diff --git a/src/Humanizer/Localisation/NumberToWords/GermanNumberToWordsConverter.cs b/src/Humanizer/Localisation/NumberToWords/GermanNumberToWordsConverter.cs index 3b3a4034b..99f0bb877 100644 --- a/src/Humanizer/Localisation/NumberToWords/GermanNumberToWordsConverter.cs +++ b/src/Humanizer/Localisation/NumberToWords/GermanNumberToWordsConverter.cs @@ -1,4 +1,5 @@ -using System.Collections.Generic; +using System; +using System.Collections.Generic; namespace Humanizer.Localisation.NumberToWords { @@ -6,11 +7,11 @@ internal class GermanNumberToWordsConverter : DefaultNumberToWordsConverter { private static readonly string[] UnitsMap = { "null", "ein", "zwei", "drei", "vier", "fünf", "sechs", "sieben", "acht", "neun", "zehn", "elf", "zwölf", "dreizehn", "vierzehn", "fünfzehn", "sechzehn", "siebzehn", "achtzehn", "neunzehn" }; private static readonly string[] TensMap = { "null", "zehn", "zwanzig", "dreißig", "vierzig", "fünfzig", "sechzig", "siebzig", "achtzig", "neunzig" }; - private static readonly string[] UnitsOrdinal = { string.Empty, "erster", "zweiter", "dritter", "vierter", "fünfter", "sechster", "siebter", "achter", "neunter", "zehnter", "elfter", "zwölfter", "dreizehnter", "vierzehnter", "fünfzehnter", "sechzehnter", "siebzehnter", "achtzehnter", "neunzehnter" }; - private static readonly string[] MillionOrdinalSingular = { "einmillion", "einemillion" }; - private static readonly string[] MillionOrdinalPlural = { "{0}million", "{0}millionen" }; - private static readonly string[] BillionOrdinalSingular = { "einmilliard", "einemilliarde" }; - private static readonly string[] BillionOrdinalPlural = { "{0}milliard", "{0}milliarden" }; + private static readonly string[] UnitsOrdinal = { string.Empty, "ers", "zwei", "drit", "vier", "fünf", "sechs", "sieb", "ach", "neun", "zehn", "elf", "zwölf", "dreizehn", "vierzehn", "fünfzehn", "sechzehn", "siebzehn", "achtzehn", "neunzehn" }; + private static readonly string[] MillionOrdinalSingular = {"einmillion", "einemillion"}; + private static readonly string[] MillionOrdinalPlural = {"{0}million", "{0}millionen"}; + private static readonly string[] BillionOrdinalSingular = {"einmilliard", "einemilliarde"}; + private static readonly string[] BillionOrdinalPlural = {"{0}milliard", "{0}milliarden"}; public override string Convert(int number) { @@ -22,7 +23,7 @@ public override string Convert(int number) var parts = new List(); - var billions = number / 1000000000; + var billions = number/1000000000; if (billions > 0) { parts.Add(Part("{0} Milliarden", "eine Milliarde", billions)); @@ -31,7 +32,7 @@ public override string Convert(int number) parts.Add(" "); } - var millions = number / 1000000; + var millions = number/1000000; if (millions > 0) { parts.Add(Part("{0} Millionen", "eine Million", millions)); @@ -40,14 +41,14 @@ public override string Convert(int number) parts.Add(" "); } - var thousands = number / 1000; + var thousands = number/1000; if (thousands > 0) { parts.Add(Part("{0}tausend", "eintausend", thousands)); number %= 1000; } - var hundreds = number / 100; + var hundreds = number/100; if (hundreds > 0) { parts.Add(Part("{0}hundert", "einhundert", hundreds)); @@ -65,11 +66,11 @@ public override string Convert(int number) } else { - var units = number % 10; + var units = number%10; if (units > 0) parts.Add(string.Format("{0}und", UnitsMap[units])); - parts.Add(TensMap[number / 10]); + parts.Add(TensMap[number/10]); } } @@ -77,9 +78,14 @@ public override string Convert(int number) } public override string ConvertToOrdinal(int number) + { + return ConvertToOrdinal(number, GrammaticalGender.Masculine); + } + + public override string ConvertToOrdinal(int number, GrammaticalGender gender) { if (number == 0) - return "nullter"; + return "null" + GetEndingForGender(gender); var parts = new List(); if (number < 0) @@ -88,30 +94,30 @@ public override string ConvertToOrdinal(int number) number = -number; } - var billions = number / 1000000000; + var billions = number/1000000000; if (billions > 0) { number %= 1000000000; - var noRest = number == 0 ? 0 : 1; + var noRest = NoRestIndex(number); parts.Add(Part(BillionOrdinalPlural[noRest], BillionOrdinalSingular[noRest], billions)); } - var millions = number / 1000000; + var millions = number/1000000; if (millions > 0) { number %= 1000000; - var noRest = number == 0 ? 0 : 1; + var noRest = NoRestIndex(number); parts.Add(Part(MillionOrdinalPlural[noRest], MillionOrdinalSingular[noRest], millions)); } - var thousands = number / 1000; + var thousands = number/1000; if (thousands > 0) { parts.Add(Part("{0}tausend", "eintausend", thousands)); number %= 1000; } - var hundreds = number / 100; + var hundreds = number/100; if (hundreds > 0) { parts.Add(Part("{0}hundert", "einhundert", hundreds)); @@ -119,23 +125,12 @@ public override string ConvertToOrdinal(int number) } if (number > 0) - { - if (number < 20) - { - parts.Add(UnitsOrdinal[number]); - } - else - { - var units = number%10; - if (units > 0) - parts.Add(string.Format("{0}und", UnitsMap[units])); - - parts.Add(TensMap[number/10]); - } - } + parts.Add(number < 20 ? UnitsOrdinal[number] : Convert(number)); if (number == 0 || number >= 20) - parts.Add("ster"); + parts.Add("s"); + + parts.Add(GetEndingForGender(gender)); return string.Join("", parts); } @@ -146,5 +141,25 @@ private string Part(string pluralFormat, string singular, int number) return singular; return string.Format(pluralFormat, Convert(number)); } + + private static int NoRestIndex(int number) + { + return number == 0 ? 0 : 1; + } + + private static string GetEndingForGender(GrammaticalGender gender) + { + switch (gender) + { + case GrammaticalGender.Masculine: + return "ter"; + case GrammaticalGender.Feminine: + return "te"; + case GrammaticalGender.Neuter: + return "tes"; + default: + throw new ArgumentOutOfRangeException("gender"); + } + } } } \ No newline at end of file From 630ea97f10d2b5f74e6b30339220a13c72eddab7 Mon Sep 17 00:00:00 2001 From: Max Malook Date: Thu, 1 May 2014 14:01:36 +0200 Subject: [PATCH 3/4] add german localisation for Ordinalize --- src/Humanizer.Tests/Humanizer.Tests.csproj | 1 + .../Localisation/de/OrdinalizeTests.cs | 29 +++++++++++++++++++ .../Configuration/OrdinalizerRegistry.cs | 1 + src/Humanizer/Humanizer.csproj | 1 + .../Ordinalizers/GermanOrdinalizer.cs | 10 +++++++ 5 files changed, 42 insertions(+) create mode 100644 src/Humanizer.Tests/Localisation/de/OrdinalizeTests.cs create mode 100644 src/Humanizer/Localisation/Ordinalizers/GermanOrdinalizer.cs diff --git a/src/Humanizer.Tests/Humanizer.Tests.csproj b/src/Humanizer.Tests/Humanizer.Tests.csproj index adf8dae7a..1af33bcef 100644 --- a/src/Humanizer.Tests/Humanizer.Tests.csproj +++ b/src/Humanizer.Tests/Humanizer.Tests.csproj @@ -69,6 +69,7 @@ + diff --git a/src/Humanizer.Tests/Localisation/de/OrdinalizeTests.cs b/src/Humanizer.Tests/Localisation/de/OrdinalizeTests.cs new file mode 100644 index 000000000..9ad403270 --- /dev/null +++ b/src/Humanizer.Tests/Localisation/de/OrdinalizeTests.cs @@ -0,0 +1,29 @@ +using Xunit; +using Xunit.Extensions; + +namespace Humanizer.Tests.Localisation.de +{ + public class OrdinalizeTests : AmbientCulture + { + public OrdinalizeTests() : base("de-DE") { } + + [Theory] + [InlineData("0", "0.")] + [InlineData("1", "1.")] + [InlineData("2", "2.")] + [InlineData("3", "3.")] + [InlineData("4", "4.")] + [InlineData("5", "5.")] + [InlineData("6", "6.")] + [InlineData("23", "23.")] + [InlineData("100", "100.")] + [InlineData("101", "101.")] + [InlineData("102", "102.")] + [InlineData("103", "103.")] + [InlineData("1001", "1001.")] + public void OrdinalizeString(string number, string ordinalized) + { + Assert.Equal(number.Ordinalize(), ordinalized); + } + } +} \ No newline at end of file diff --git a/src/Humanizer/Configuration/OrdinalizerRegistry.cs b/src/Humanizer/Configuration/OrdinalizerRegistry.cs index 757a029a5..39d05d674 100644 --- a/src/Humanizer/Configuration/OrdinalizerRegistry.cs +++ b/src/Humanizer/Configuration/OrdinalizerRegistry.cs @@ -10,6 +10,7 @@ public OrdinalizerRegistry() : base(new DefaultOrdinalizer()) Register("es"); Register("ru"); Register("pt-BR"); + Register("de"); } } } \ No newline at end of file diff --git a/src/Humanizer/Humanizer.csproj b/src/Humanizer/Humanizer.csproj index 08bd6bd53..bfb39f502 100644 --- a/src/Humanizer/Humanizer.csproj +++ b/src/Humanizer/Humanizer.csproj @@ -83,6 +83,7 @@ + diff --git a/src/Humanizer/Localisation/Ordinalizers/GermanOrdinalizer.cs b/src/Humanizer/Localisation/Ordinalizers/GermanOrdinalizer.cs new file mode 100644 index 000000000..e59deab4b --- /dev/null +++ b/src/Humanizer/Localisation/Ordinalizers/GermanOrdinalizer.cs @@ -0,0 +1,10 @@ +namespace Humanizer.Localisation.Ordinalizers +{ + internal class GermanOrdinalizer : DefaultOrdinalizer + { + public override string Convert(int number, string numberString) + { + return numberString + "."; + } + } +} \ No newline at end of file From 1361cba5dd9a5008c78e440bfc9318b2caa71d67 Mon Sep 17 00:00:00 2001 From: Max Malook Date: Thu, 1 May 2014 14:06:39 +0200 Subject: [PATCH 4/4] add PR to release notes --- release_notes.md | 1 + 1 file changed, 1 insertion(+) diff --git a/release_notes.md b/release_notes.md index 8039bdd8d..83338a10d 100644 --- a/release_notes.md +++ b/release_notes.md @@ -1,4 +1,5 @@ ###In Development + - [#257](https://github.com/Mehdik/Humanizer/pull/257): Added German localisation for ToOrdinalWords and Ordinalize [Commits](https://github.com/MehdiK/Humanizer/compare/v1.25.4...master)