Skip to content

Commit

Permalink
Added Spanish toWords
Browse files Browse the repository at this point in the history
  • Loading branch information
thunsaker committed Apr 9, 2014
1 parent 6e9bcb2 commit 4b54aea
Show file tree
Hide file tree
Showing 3 changed files with 128 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/Humanizer.Tests/Humanizer.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@
<Compile Include="DateHumanize.cs" />
<Compile Include="Localisation\cs\DateHumanizeTests.cs" />
<Compile Include="Localisation\cs\TimeSpanHumanizeTests.cs" />
<Compile Include="Localisation\es\NumberToWordsTests.cs" />
<Compile Include="Localisation\nb-NO\TimeSpanHumanizeTests.cs" />
<Compile Include="Localisation\pl\DateHumanizeTests.cs" />
<Compile Include="Localisation\pl\TimeSpanHumanizeTests.cs" />
Expand Down
51 changes: 51 additions & 0 deletions src/Humanizer.Tests/Localisation/es/NumberToWordsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
using Xunit;
using Xunit.Extensions;

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

[InlineData(0, "cero")]
[InlineData(1, "uno")]
[InlineData(10, "diez")]
[InlineData(11, "once")]
[InlineData(122, "ciento veinte dos")]
[InlineData(3501, "trés mil quinientos uno")]
[InlineData(100, "cien")]
[InlineData(1000, "un mil")]
[InlineData(100000, "cien mil")]
[InlineData(1000000, "un millón")]
[InlineData(10000000, "diez millones")]
[InlineData(100000000, "cien millones")]
[InlineData(1000000000, "un mil millones")]
[InlineData(111, "ciento once")]
[InlineData(1111, "mil ciento once")]
[InlineData(111111, "ciento once mil ciento once")]
[InlineData(1111111, "millón ciento once mil ciento once")]
[InlineData(11111111, "once millones ciento once mil ciento once")]
[InlineData(111111111, "ciento once millones ciento once mil ciento once")]
[InlineData(1111111111, "mil millones ciento once millones ciento once mil ciento once")]

This comment has been minimized.

Copy link
@francisconoriega

francisconoriega Apr 10, 2014

Here it changes a bit, and you only use millions once, so it should be: mil ciento once millones.
This continues all the way until a million millions (billón), so it would continue to look like this:
once mil ciento once millones =>11,111,000,000
ciento once mil ciento once millones => 111,111,000,000
un millon de millones / un billón = > 1 000 000 000 000
un millon mil ciento once mil ciento millones = > 1 111 111 000 000

after thinking about it, even as a native speaker it starts to get confusing when you get to this kind of numbers. But taking the 'un' out of 'un mil' and 'un mil millones' is the main point for now :P

This comment has been minimized.

Copy link
@thunsaker

thunsaker Apr 10, 2014

Author Owner

Nice catch.
So 11,111,111,111 in English = eleven billion one hundred eleven million...
but Spanish is eleven thousand hundred million...not eleven billion [mil milliones]...?
That is slightly confusing.

Luckily int only goes to +/-2,147,483,647 so we don't need to worry about them yet. :)

I'll take care of the "un"s.

This comment has been minimized.

Copy link
@francisconoriega

francisconoriega Apr 10, 2014

correct, billion in Spanish is a Million Millions, not a Thousand Millions, like in English.

[InlineData(123, "ciento veinte trés")]
[InlineData(1234, "mil doscientos treinta y cuatro")]
[InlineData(12345, "doce mil trescientos cuarenta y cinco")]
[InlineData(123456, "ciento veinte trés mil cuatrocientos cincuenta y seis")]
[InlineData(1234567, "millón doscientos treinta y cuatro mil quinientos sesenta y siete")]
[InlineData(12345678, "doce millones trescientos cuarenta y cinco mil seiscientos setenta y ocho")]
[InlineData(123456789, "ciento veinte trés millones cuatrocientos cincuenta y seis mil setecientos ochenta y nueve")]
[InlineData(1234567890, "mil millones doscientos treinta y cuatro millones quinientos sesenta y siete mil ochocientos noventa")]
[InlineData(15, "quince")]
[InlineData(16, "dieciséis")]
[InlineData(25, "veinte cinco")]
[InlineData(35, "treinta y cinco")]
[InlineData(1999, "mil novecientos noventa y nueve")]
[InlineData(2014, "dos mil catorce")]
[InlineData(2048, "dos mil cuarenta y ocho")]
[Theory]
public void ToWords(int number, string expected)
{
Assert.Equal(expected, number.ToWords());
}
}
}
76 changes: 76 additions & 0 deletions src/Humanizer/NumberToWordsExtension.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,8 @@ public static string ToWords(this int number)
return ToArabicWords(number);
case "fa":
return ToFarsiWords(number);
case "es":
return ToSpanishWords(number);
default:
return ToEnglishWords(number);
}
Expand Down Expand Up @@ -232,5 +234,79 @@ private static string ToFarsiWords(int number)

return string.Join(" و ", parts);
}

private static string ToSpanishWords(int number) {
if (number == 0)
return "cero";

if (number < 0)
return string.Format("menos {0}", ToWords(Math.Abs(number)));

var parts = new List<string>();

if ((number / 1000000000) > 0) {
if (number == 1000000000)
parts.Add(string.Format("un mil millones", ToWords(number / 1000000000)));

This comment has been minimized.

Copy link
@francisconoriega

francisconoriega Apr 10, 2014

'un' is not used for mil

else if (number / 1000000000 == 1)
parts.Add(string.Format("mil millones", ToWords(number / 1000000000)));
else
parts.Add(string.Format("{0} mil millones", ToWords(number / 1000000000)));
number %= 1000000000;
}

if ((number / 1000000) > 0) {
if (number == 1000000)
parts.Add(string.Format("un millón", ToWords(number / 1000000)));
else if (number / 1000000 == 1)
parts.Add(string.Format("millón", ToWords(number / 1000000)));
else
parts.Add(string.Format("{0} millones", ToWords(number / 1000000)));
number %= 1000000;
}

if ((number / 1000) > 0) {
if (number == 1000)
parts.Add(string.Format("un mil", ToWords(number / 1000)));
else if (number / 1000 == 1)
parts.Add(string.Format("mil", ToWords(number / 1000)));
else
parts.Add(string.Format("{0} mil", ToWords(number / 1000)));
number %= 1000;
}

if ((number / 100) > 0) {
var hundredsMap = new[] { "ciento", "doscientos", "trescientos", "cuatrocientos", "quinientos", "seiscientos", "setecientos", "ochocientos", "novecientos" };

if (number == 100)
parts.Add(string.Format("cien", ToWords(number / 100)));

This comment has been minimized.

Copy link
@akamud

akamud Apr 10, 2014

I noticed a test which may need an extra "if" in this part.
Try 8100, in portuguese it should be "oito mil e cem" and if my spanish doesn't fail me, I think it should be "ocho mil y cien", but I think your code will output "ocho mil cien".

Correct me if I'm wrong

This comment has been minimized.

Copy link
@thunsaker

thunsaker Apr 10, 2014

Author Owner

As a non-native Spanish speaker I don't know the answer. It sounds correct to me when I hear it and Google Translate likes it. I'm leaving it as is, maybe someone else can come in later and double-check my translations.

This comment has been minimized.

Copy link
@francisconoriega

francisconoriega Apr 10, 2014

Native speaker here, "ocho mil cien" is correct.

else
parts.Add(hundredsMap[(number / 100) - 1]);

number %= 100;
}

if (number > 0) {
var unitsMap = new[] { "cero", "uno", "dos", "trés", "cuatro", "cinco", "seis", "siete", "ocho", "nueve", "diez", "once", "doce", "trece", "catorce", "quince", "dieciséis", "diecisiete", "dieciocho", "diecinueve" };

This comment has been minimized.

Copy link
@francisconoriega

francisconoriega Apr 10, 2014

It should be "tres", not "trés"

var tensMap = new[] { "cero", "diez", "veinte", "treinta", "cuarenta", "cincuenta", "sesenta", "setenta", "ochenta", "noventa" };

if (number < 20)
parts.Add(unitsMap[number]);
else if (number > 20 && number < 30) {
var lastPart = tensMap[number / 10];
if ((number % 10) > 0)
lastPart += string.Format(" {0}", unitsMap[number % 10]);

parts.Add(lastPart);
} else {
var lastPart = tensMap[number / 10];
if ((number % 10) > 0)
lastPart += string.Format(" y {0}", unitsMap[number % 10]);

parts.Add(lastPart);
}
}

return string.Join(" ", parts.ToArray());
}
}
}

0 comments on commit 4b54aea

Please sign in to comment.