Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

added Dutch numbers to words support #166

Merged
merged 7 commits into from
Apr 12, 2014
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 3 additions & 1 deletion release_notes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
###In Development

- [#166](https://github.com/MehdiK/Humanizer/pull/166): Added Dutch (NL) Number to words and ordinals

[Commits](https://github.com/MehdiK/Humanizer/compare/v1.21.15...master)

###v1.21.1 - 2014-04-12
Expand Down Expand Up @@ -35,6 +36,7 @@
- [#143](https://github.com/MehdiK/Humanizer/pull/143): Added Russian translation for future DateTime, TimeSpan and Now
- [#144](https://github.com/MehdiK/Humanizer/pull/144): Added Danish localization (strings, tests)
- [#146](https://github.com/MehdiK/Humanizer/pull/146): Added Spanish translation for future DateTime, TimeSpan and Now


[Commits](https://github.com/MehdiK/Humanizer/compare/v1.18.1...v1.19.1)

Expand Down
2 changes: 2 additions & 0 deletions src/Humanizer.Tests/Humanizer.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,8 @@
<Compile Include="Localisation\he\DateHumanizeTests.cs" />
<Compile Include="Localisation\ar\TimeSpanHumanizeTests.cs" />
<Compile Include="Localisation\nb-NO\TimeSpanHumanizeTests.cs" />
<Compile Include="Localisation\nl\NumberToOrdinalWordsTests.cs" />
<Compile Include="Localisation\nl\NumberToWordsTests.cs" />
<Compile Include="Localisation\pl\DateHumanizeTests.cs" />
<Compile Include="Localisation\pl\NumberToWordsTests.cs" />
<Compile Include="Localisation\pl\TimeSpanHumanizeTests.cs" />
Expand Down
67 changes: 67 additions & 0 deletions src/Humanizer.Tests/Localisation/nl/NumberToOrdinalWordsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,67 @@
using Xunit;
using Xunit.Extensions;

namespace Humanizer.Tests.Localisation.nl
{
public class NumberToOrdinalWordsTests : AmbientCulture
{
public NumberToOrdinalWordsTests() : base("nl-NL") { }

[Theory]
[InlineData(0, "nulde")]
[InlineData(1, "eerste")]
[InlineData(2, "tweede")]
[InlineData(3, "derde")]
[InlineData(4, "vierde")]
[InlineData(5, "vijfde")]
[InlineData(6, "zesde")]
[InlineData(7, "zevende")]
[InlineData(8, "achtste")]
[InlineData(9, "negende")]
[InlineData(10, "tiende")]
[InlineData(11, "elfde")]
[InlineData(12, "twaalfde")]
[InlineData(13, "dertiende")]
[InlineData(14, "veertiende")]
[InlineData(15, "vijftiende")]
[InlineData(16, "zestiende")]
[InlineData(17, "zeventiende")]
[InlineData(18, "achttiende")]
[InlineData(19, "negentiende")]
[InlineData(20, "twintigste")]
[InlineData(21, "eenentwintigste")]
[InlineData(22, "tweeëntwintigste")]
[InlineData(30, "dertigste")]
[InlineData(40, "veertigste")]
[InlineData(50, "vijftigste")]
[InlineData(60, "zestigste")]
[InlineData(70, "zeventigste")]
[InlineData(80, "tachtigste")]
[InlineData(90, "negentigste")]
[InlineData(95, "vijfennegentigste")]
[InlineData(96, "zesennegentigste")]
[InlineData(100, "honderdste")]
[InlineData(101, "honderdeerste")]
[InlineData(106, "honderdzesde")]
[InlineData(108, "honderdachtste")]
[InlineData(112, "honderdtwaalfde")]
[InlineData(120, "honderdtwintigste")]
[InlineData(121, "honderdeenentwintigste")]
[InlineData(1000, "duizendste")]
[InlineData(1001, "duizend eerste")]
[InlineData(1005, "duizend vijfde")]
[InlineData(1008, "duizend achtste")]
[InlineData(1012, "duizend twaalfde")]
[InlineData(1021, "duizend eenentwintigste")]
[InlineData(10000, "tienduizendste")]
[InlineData(10121, "tienduizend honderdeenentwintigste")]
[InlineData(100000, "honderdduizendste")]
[InlineData(100001, "honderdduizend eerste")]
[InlineData(1000000, "een miljoenste")]
[InlineData(1000001, "een miljoen eerste")]
public void ToOrdinalWords(int number, string words)
{
Assert.Equal(words, number.ToOrdinalWords());
}
}
}
57 changes: 57 additions & 0 deletions src/Humanizer.Tests/Localisation/nl/NumberToWordsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using Xunit;
using Xunit.Extensions;

namespace Humanizer.Tests.Localisation.nl
{
public class NumberToWordsTests : AmbientCulture
{
public NumberToWordsTests() : base("nl-NL") { }

[InlineData(0, "nul")]
[InlineData(1, "een")]
[InlineData(-10, "min tien")]
[InlineData(10, "tien")]
[InlineData(11, "elf")]
[InlineData(122, "honderdtweeëntwintig")]
[InlineData(3501, "drieduizend vijfhonderdeen")]
[InlineData(100, "honderd")]
[InlineData(1000, "duizend")]
[InlineData(100000, "honderdduizend")]
[InlineData(1000000, "een miljoen")]
[InlineData(10000000, "tien miljoen")]
[InlineData(100000000, "honderd miljoen")]
[InlineData(1000000000, "een miljard")]
[InlineData(111, "honderdelf")]
[InlineData(1111, "duizend honderdelf")]
[InlineData(111111, "honderdelfduizend honderdelf")]
[InlineData(1111111, "een miljoen honderdelfduizend honderdelf")]
[InlineData(11111111, "elf miljoen honderdelfduizend honderdelf")]
[InlineData(111111111, "honderdelf miljoen honderdelfduizend honderdelf")]
[InlineData(1111111111, "een miljard honderdelf miljoen honderdelfduizend honderdelf")]
[InlineData(123, "honderddrieëntwintig")]
[InlineData(124, "honderdvierentwintig")]
[InlineData(1234, "duizend tweehonderdvierendertig")]
[InlineData(12345, "twaalfduizend driehonderdvijfenveertig")]
[InlineData(123456, "honderddrieëntwintigduizend vierhonderdzesenvijftig")]
[InlineData(1234567, "een miljoen tweehonderdvierendertigduizend vijfhonderdzevenenzestig")]
[InlineData(12345678, "twaalf miljoen driehonderdvijfenveertigduizend zeshonderdachtenzeventig")]
[InlineData(123456789, "honderddrieëntwintig miljoen vierhonderdzesenvijftigduizend zevenhonderdnegenentachtig")]
[InlineData(1234567890, "een miljard tweehonderdvierendertig miljoen vijfhonderdzevenenzestigduizend achthonderdnegentig")]
[InlineData(1234567899, "een miljard tweehonderdvierendertig miljoen vijfhonderdzevenenzestigduizend achthonderdnegenennegentig")]

[InlineData(108, "honderdacht")]
[InlineData(678, "zeshonderdachtenzeventig")]
[InlineData(2013, "tweeduizend dertien")]
[InlineData(2577, "tweeduizend vijfhonderdzevenenzeventig")]
[InlineData(17053980, "zeventien miljoen drieënvijftigduizend negenhonderdtachtig")]

[InlineData(415618, "vierhonderdvijftienduizend zeshonderdachttien")]
[InlineData(16415618, "zestien miljoen vierhonderdvijftienduizend zeshonderdachttien")]
[InlineData(322, "driehonderdtweeëntwintig")]
[Theory]
public void ToWords(int number, string expected)
{
Assert.Equal(expected, number.ToWords());
}
}
}
1 change: 1 addition & 0 deletions src/Humanizer/Humanizer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,7 @@
<Compile Include="GrammaticalGender.cs" />
<Compile Include="Localisation\GrammaticalNumber\RussianGrammaticalNumber.cs" />
<Compile Include="Localisation\GrammaticalNumber\RussianGrammaticalNumberDetector.cs" />
<Compile Include="Localisation\NumberToWords\DutchNumberToWordsConverter.cs" />
<Compile Include="Localisation\NumberToWords\DefaultNumberToWordsConverter.cs" />
<Compile Include="Localisation\NumberToWords\FarsiNumberToWordsConverter.cs" />
<Compile Include="Localisation\NumberToWords\ArabicNumberToWordsConverter.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
using System.Collections.Generic;
using System.Linq;

namespace Humanizer.Localisation.NumberToWords
{
/// <summary>
/// Dutch spelling of numbers is not really officially regulated.
/// There are a few different rules that can be applied.
/// Used the rules as stated here.
/// http://www.beterspellen.nl/website/?pag=110
/// </summary>
internal class DutchNumberToWordsConverter : DefaultNumberToWordsConverter
{
private static readonly string[] UnitsMap = { "nul", "een", "twee", "drie", "vier", "vijf", "zes", "zeven", "acht", "negen", "tien", "elf", "twaalf", "dertien", "veertien", "vijftien", "zestien", "zeventien", "achttien", "negentien" };
private static readonly string[] TensMap = { "nul", "tien", "twintig", "dertig", "veertig", "vijftig", "zestig", "zeventig", "tachtig", "negentig" };

class Fact
{
public int Value { get; set; }
public string Name { get; set; }
public string Prefix { get; set; }
public string Postfix { get; set; }
public bool DisplayOneUnit { get; set; }
}

private static readonly Fact[] Hunderds =
{
new Fact {Value = 1000000000, Name = "miljard", Prefix = " ", Postfix = " ", DisplayOneUnit = true},
new Fact {Value = 1000000, Name = "miljoen", Prefix = " ", Postfix = " ", DisplayOneUnit = true},
new Fact {Value = 1000, Name = "duizend", Prefix = "", Postfix = " ", DisplayOneUnit = false},
new Fact {Value = 100, Name = "honderd", Prefix = "", Postfix = "", DisplayOneUnit = false}
};

public override string Convert(int number)
{
if (number == 0)
return UnitsMap[0];

if (number < 0)
return string.Format("min {0}", Convert(-number));

var word = "";

foreach (var m in Hunderds)
{
var divided = number / m.Value;

if (divided <= 0) continue;

if (divided == 1 && !m.DisplayOneUnit)
{
word += m.Name;
}
else
{
word += Convert(divided) + m.Prefix + m.Name;
}

number %= m.Value;
if (number > 0)
{
word += m.Postfix;
}
}

if (number > 0)
{
if (number < 20)
{
word += UnitsMap[number];
}
else
{
var tens = TensMap[number / 10];
var unit = number % 10;
if (unit > 0)
{
var units = UnitsMap[unit];
var trema = units.EndsWith("e");
word += units + (trema ? "�n" : "en") + tens;
}
else
{
word += tens;
}
}
}

return word;
}

private static readonly Dictionary<string, string> OrdinalExceptions = new Dictionary<string, string>
{
{"een", "eerste"},
{"drie", "derde"},
{"miljoen", "miljoenste"},
};

private static readonly char[] EndingCharForSte = {'t', 'g', 'd'};

public override string ConvertToOrdinal(int number)
{
var word = Convert(number);

// exceptions
foreach (var kv in OrdinalExceptions.Where(kv => word.EndsWith(kv.Key)))
{
// replace word with exception
return word.Substring(0, word.Length - kv.Key.Length) + kv.Value;
}

// achtste
// twintigste, dertigste, veertigste, ...
// honderdste, duizendste, ...
if (word.LastIndexOfAny(EndingCharForSte) == (word.Length - 1))
{
return word + "ste";
}

// anything else
return word + "de";
}
}
}
3 changes: 2 additions & 1 deletion src/Humanizer/NumberToWordsExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@ public static class NumberToWordsExtension
{"pl", () => new PolishNumberToWordsConverter()},
{"pt-BR", () => new BrazilianPortugueseNumberToWordsConverter()},
{"ru", () => new RussianNumberToWordsConverter()},
{"fr", () => new FrenchNumberToWordsConverter()}
{"fr", () => new FrenchNumberToWordsConverter()},
{"nl", () => new DutchNumberToWordsConverter()}
};

/// <summary>
Expand Down