diff --git a/src/Humanizer.Tests.Shared/Humanizer.Tests.Shared.projitems b/src/Humanizer.Tests.Shared/Humanizer.Tests.Shared.projitems
index e317f1043..48b40e429 100644
--- a/src/Humanizer.Tests.Shared/Humanizer.Tests.Shared.projitems
+++ b/src/Humanizer.Tests.Shared/Humanizer.Tests.Shared.projitems
@@ -53,6 +53,7 @@
+
diff --git a/src/Humanizer.Tests.Shared/Localisation/eo/NumberToWordTests.cs b/src/Humanizer.Tests.Shared/Localisation/eo/NumberToWordTests.cs
new file mode 100644
index 000000000..81b8abb33
--- /dev/null
+++ b/src/Humanizer.Tests.Shared/Localisation/eo/NumberToWordTests.cs
@@ -0,0 +1,100 @@
+using System.Globalization;
+using Xunit;
+
+namespace Humanizer.Tests.Localisation.eo
+{
+ [UseCulture ("eo-Eo")]
+ public class NumberToWordsTests
+ {
+ [Theory]
+ [InlineData (-42, "minus kvardek du")]
+ [InlineData (-1, "minus unu")]
+ [InlineData (0, "nul")]
+ [InlineData (1, "unu")]
+ [InlineData (2, "du")]
+ [InlineData (3, "tri")]
+ [InlineData (4, "kvar")]
+ [InlineData (5, "kvin")]
+ [InlineData (6, "ses")]
+ [InlineData (7, "sep")]
+ [InlineData (8, "ok")]
+ [InlineData (9, "naŭ")]
+ [InlineData (10, "dek")]
+ [InlineData (11, "dek unu")]
+ [InlineData (15, "dek kvin")]
+ [InlineData (17, "dek sep")]
+ [InlineData (20, "dudek")]
+ [InlineData (25, "dudek kvin")]
+ [InlineData (31, "tridek unu")]
+ [InlineData (71, "sepdek unu")]
+ [InlineData (122, "cent dudek du")]
+ [InlineData (256, "ducent kvindek ses")]
+ [InlineData (3501, "trimil kvincent unu")]
+ [InlineData (100, "cent")]
+ [InlineData (1000, "mil")]
+ [InlineData (10000, "dek mil")]
+ [InlineData (100000, "cent mil")]
+ [InlineData (1000000, "miliono")]
+ [InlineData (10000000, "dek miliono")]
+ [InlineData (100000000, "cent miliono")]
+ [InlineData (1000000000, "miliardo")]
+ [InlineData (110, "cent dek")]
+ [InlineData (1100, "mil cent")]
+ [InlineData (11000, "dek unu mil")]
+ [InlineData (111, "cent dek unu")]
+ [InlineData (1111, "mil cent dek unu")]
+ [InlineData (111111, "cent dek unu mil cent dek unu")]
+ [InlineData (1111111, "miliono cent dek unu mil cent dek unu")]
+ [InlineData (11111111, "dek unu miliono cent dek unu mil cent dek unu")]
+ [InlineData (111111111, "cent dek unu miliono cent dek unu mil cent dek unu")]
+ [InlineData (1111111111, "miliardo cent dek unu miliono cent dek unu mil cent dek unu")]
+ [InlineData (123, "cent dudek tri")]
+ [InlineData (1234, "mil ducent tridek kvar")]
+ [InlineData (12345, "dek dumil tricent kvardek kvin")]
+ [InlineData (123456, "cent dudek trimil kvarcent kvindek ses")]
+ [InlineData (1234567, "miliono ducent tridek kvarmil kvincent sesdek sep")]
+ [InlineData (12345678, "dek du miliono tricent kvardek kvinmil sescent sepdek ok")]
+ [InlineData (123456789, "cent dudek tri miliono kvarcent kvindek sesmil sepcent okdek naŭ")]
+ [InlineData (1234567890, "miliardo ducent tridek kvar miliono kvincent sesdek sepmil okcent naŭdek")]
+ [InlineData (1234567899, "miliardo ducent tridek kvar miliono kvincent sesdek sepmil okcent naŭdek naŭ")]
+ [InlineData (223, "ducent dudek tri")]
+ [InlineData (1999, "mil naŭcent naŭdek naŭ")]
+ [InlineData (2014, "dumil dek kvar")]
+ [InlineData (2048, "dumil kvardek ok")]
+ [InlineData (31786, "tridek unu mil sepcent okdek ses")]
+ [InlineData (30786, "tridek mil sepcent okdek ses")]
+ public void ToWords(int number, string words)
+ {
+ Assert.Equal (words, number.ToWords(new CultureInfo("eo")));
+ }
+
+ [Theory]
+ [InlineData (0, "nula")]
+ [InlineData (1, "unua")]
+ [InlineData (2, "dua")]
+ [InlineData (3, "tria")]
+ [InlineData (4, "kvara")]
+ [InlineData (5, "kvina")]
+ [InlineData (6, "sesa")]
+ [InlineData (7, "sepa")]
+ [InlineData (8, "oka")]
+ [InlineData (9, "naŭa")]
+ [InlineData (10, "deka")]
+ [InlineData (100, "centa")]
+ [InlineData (120, "cent dudeka")]
+ [InlineData (121, "cent dudek unua")]
+ [InlineData (1000, "mila")]
+ [InlineData (1001, "mil unua")]
+ [InlineData (1021, "mil dudek unua")]
+ [InlineData (3000, "trimila")]
+ [InlineData (10000, "dek mila")]
+ [InlineData (10121, "dek mil cent dudek unua")]
+ [InlineData (100000, "cent mila")]
+ [InlineData (1000000, "milionoa")]
+ [InlineData (1000000000, "miliardoa")]
+ public void ToOrdinalWords(int number, string words)
+ {
+ Assert.Equal (words, number.ToOrdinalWords());
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Humanizer/Configuration/NumberToWordsConverterRegistry.cs b/src/Humanizer/Configuration/NumberToWordsConverterRegistry.cs
index cd8aa262e..989467991 100644
--- a/src/Humanizer/Configuration/NumberToWordsConverterRegistry.cs
+++ b/src/Humanizer/Configuration/NumberToWordsConverterRegistry.cs
@@ -11,7 +11,8 @@ public NumberToWordsConverterRegistry()
Register("en", new EnglishNumberToWordsConverter());
Register("ar", new ArabicNumberToWordsConverter());
Register("fa", new FarsiNumberToWordsConverter());
- Register("es", new SpanishNumberToWordsConverter());
+ Register("eo", new EsperantoNumberToWordsConverter());
+ Register("es", new SpanishNumberToWordsConverter ());
Register("pl", (culture) => new PolishNumberToWordsConverter(culture));
Register("pt-BR", new BrazilianPortugueseNumberToWordsConverter());
Register("ro", new RomanianNumberToWordsConverter());
diff --git a/src/Humanizer/Humanizer.csproj b/src/Humanizer/Humanizer.csproj
index 0e260c3b4..e4bbb5511 100644
--- a/src/Humanizer/Humanizer.csproj
+++ b/src/Humanizer/Humanizer.csproj
@@ -80,6 +80,7 @@
+
diff --git a/src/Humanizer/Localisation/NumberToWords/EsperantoNumberToWordsConverter.cs b/src/Humanizer/Localisation/NumberToWords/EsperantoNumberToWordsConverter.cs
new file mode 100644
index 000000000..3cd75ad47
--- /dev/null
+++ b/src/Humanizer/Localisation/NumberToWords/EsperantoNumberToWordsConverter.cs
@@ -0,0 +1,85 @@
+// Wrote by Alois de Gouvello https://github.com/aloisdg
+
+// The MIT License (MIT)
+
+// Copyright (c) 2015 Alois de Gouvello
+
+// Permission is hereby granted, free of charge, to any person obtaining a copy of
+// this software and associated documentation files (the "Software"), to deal in
+// the Software without restriction, including without limitation the rights to
+// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
+// the Software, and to permit persons to whom the Software is furnished to do so,
+// subject to the following conditions:
+
+// The above copyright notice and this permission notice shall be included in all
+// copies or substantial portions of the Software.
+
+// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
+// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
+// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
+// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+using System;
+using System.Collections.Generic;
+using System.Linq;
+
+namespace Humanizer.Localisation.NumberToWords
+{
+ internal class EsperantoNumberToWordsConverter : GenderlessNumberToWordsConverter
+ {
+ private static readonly string[] UnitsMap =
+ {
+ "nul", "unu", "du", "tri", "kvar", "kvin", "ses", "sep", "ok", "naŭ"
+ };
+
+ private static readonly Dictionary TensMap = new Dictionary
+ {
+ { 1000000000, " miliardo" }, { 1000000 , " miliono" }, { 1000, " mil" }, { 100, "cent" }, { 10, "dek" }, { 1, null }
+ };
+
+ private const string Minus = "minus";
+
+ public override string ConvertToOrdinal(int number)
+ {
+ return Convert(number) + "a";
+ }
+
+ public override string Convert(int number)
+ {
+ var words = number < 0 ? Minus + " " : string.Empty;
+ number = Math.Abs (number);
+ words += number <= 1 ? UnitsMap[number] : ConvertInside(number);
+ return words;
+ }
+
+ private static string ConvertInside(int number)
+ {
+ if (number == 1)
+ return string.Empty;
+
+ var parts = new List ();
+ foreach (var item in TensMap.Where(x => number / x.Key > 0))
+ {
+ parts.Add(!string.IsNullOrEmpty(item.Value)
+ ? $"{ConvertInside (number / item.Key)}{TrimMil (item, number)}"
+ : UnitsMap[number]);
+ number %= item.Key;
+ }
+
+ var toWords = string.Join(" ", parts.ToArray ()).TrimStart(' ');
+ return toWords;
+ }
+
+ private static string TrimMil(KeyValuePair item, int number)
+ {
+ if (item.Key != 1000)
+ return item.Value;
+ var quotient = number / item.Key % 10;
+ return quotient < 2 || quotient > 9
+ ? item.Value
+ : item.Value.TrimStart(' ');
+ }
+ }
+}