Skip to content
Closed
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
1 change: 1 addition & 0 deletions src/Humanizer.Tests/Humanizer.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@
<Compile Include="Localisation\nb-NO\TimeSpanHumanizeTests.cs" />
<Compile Include="Localisation\pl\DateHumanizeTests.cs" />
<Compile Include="Localisation\pl\TimeSpanHumanizeTests.cs" />
<Compile Include="Localisation\pt-BR\NumberToWordsTests.cs" />
<Compile Include="Localisation\ru-RU\TimeSpanHumanizeTests.cs" />
<Compile Include="Localisation\sk\DateHumanizeTests.cs" />
<Compile Include="Localisation\ar\DateHumanizeTests.cs" />
Expand Down
47 changes: 47 additions & 0 deletions src/Humanizer.Tests/Localisation/pt-BR/NumberToWordsTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
using Xunit;
using Xunit.Extensions;

namespace Humanizer.Tests.Localisation.ptBR
{
public class NumberToWordsTests : AmbientCulture
{
public NumberToWordsTests() : base("pt-BR") { }

[Theory]
[InlineData(1, "um")]
[InlineData(10, "dez")]
[InlineData(11, "onze")]
[InlineData(122, "cento e vinte e dois")]
[InlineData(3501, "três mil quinhentos e um")]
[InlineData(100, "cem")]
[InlineData(1000, "mil")]
[InlineData(100000, "cem mil")]
[InlineData(1000000, "um milhão")]
[InlineData(10000000, "dez milhões")]
[InlineData(100000000, "cem milhões")]
[InlineData(1000000000, "um bilhão")]
[InlineData(111, "cento e onze")]
[InlineData(1111, "mil cento e onze")]
[InlineData(111111, "cento e onze mil cento e onze")]
[InlineData(1111111, "um milhão cento e onze mil cento e onze")]
[InlineData(11111111, "onze milhões cento e onze mil cento e onze")]
[InlineData(111111111, "cento e onze milhões cento e onze mil cento e onze")]
[InlineData(1111111111, "um bilhão cento e onze milhões cento e onze mil cento e onze")]
[InlineData(123, "cento e vinte e três")]
[InlineData(1234, "mil duzentos e trinta e quatro")]
[InlineData(8100, "oito mil e cem")]
[InlineData(12345, "doze mil trezentos e quarenta e cinco")]
[InlineData(123456, "cento e vinte e três mil quatrocentos e cinquenta e seis")]
[InlineData(1234567, "um milhão duzentos e trinta e quatro mil quinhentos e sessenta e sete")]
[InlineData(12345678, "doze milhões trezentos e quarenta e cinco mil seiscentos e setenta e oito")]
[InlineData(123456789, "cento e vinte e três milhões quatrocentos e cinquenta e seis mil setecentos e oitenta e nove")]
[InlineData(1234567890, "um bilhão duzentos e trinta e quatro milhões quinhentos e sessenta e sete mil oitocentos e noventa")]
[InlineData(1999, "mil novecentos e noventa e nove")]
[InlineData(2014, "dois mil e quatorze")]
[InlineData(2048, "dois mil e quarenta e oito")]
public void ToWordsPortuguese(int number, string expected)
{
Assert.Equal(expected, number.ToWords());
}
}
}
93 changes: 93 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 "pt":
return ToPortugueseWords(number);
default:
return ToEnglishWords(number);
}
Expand Down Expand Up @@ -232,5 +234,96 @@ private static string ToFarsiWords(int number)

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

private static string ToPortugueseWords(int number)
{
if (number == 0)
return "zero";

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

var parts = new List<string>();

if ((number / 1000000000) > 0)
{
if (number / 1000000000 > 2)
{
parts.Add(string.Format("{0} bilhões", ToWords(number / 1000000000)));
}
else
{
parts.Add(string.Format("{0} bilhão", ToWords(number / 1000000000)));
}
number %= 1000000000;
}

if ((number / 1000000) > 0)
{
if (number / 1000000 > 2)
{
parts.Add(string.Format("{0} milhões", ToWords(number / 1000000)));
}
else
{
parts.Add(string.Format("{0} milhão", ToWords(number / 1000000)));
}
number %= 1000000;
}

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

number %= 1000;
}

if ((number / 100) > 0) {
var portugueseHundredsMap = new[] { "zero", "cento", "duzentos", "trezentos", "quatrocentos", "quinhentos", "seiscentos", "setecentos", "oitocentos", "novecentos" };

if (number == 100)
{
if (parts.Count > 0)
{
parts.Add("e cem");
}
else
{
parts.Add("cem");
}
}
else
{
parts.Add(portugueseHundredsMap[(number / 100)]);
}

number %= 100;
}

if (number > 0)
{
if (parts.Count != 0)
parts.Add("e");

var portugueseUnitsMap = new[] { "zero", "um", "dois", "três", "quatro", "cinco", "seis", "sete", "oito", "nove", "dez", "onze", "doze", "treze", "quatorze", "quinze", "dezesseis", "dezessete", "dezoito", "dezenove" };
var portugueseTensMap = new[] { "zero", "dez", "vinte", "trinta", "quarenta", "cinquenta", "sessenta", "setenta", "oitenta", "noventa" };

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

parts.Add(lastPart);
}
}

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