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 pt-BR NumberToWords localisation #194

Closed
wants to merge 10 commits into from
2 changes: 2 additions & 0 deletions release_notes.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
###In Development
- [#186](https://github.com/Mehdik/Humanizer/pull/186): Refactored 'ToOrdinalWords` to use existing `NumberToWordsExtension` to prepare for Ordinal localization.
- [#194](https://github.com/MehdiK/Humanizer/pull/194): Added pt-BR NumberToWords localisation

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

###v1.20.2 - 2014-04-11
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 @@ -88,9 +88,11 @@
<Compile Include="Localisation\invariant\ToQuantityTests.cs" />
<Compile Include="Localisation\es\NumberToWordsTests.cs" />
<Compile Include="Localisation\nb-NO\TimeSpanHumanizeTests.cs" />
<Compile Include="Localisation\NumberToWordsFactoryTests.cs" />
<Compile Include="Localisation\pl\DateHumanizeTests.cs" />
<Compile Include="Localisation\pl\NumberToWordsTests.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
46 changes: 46 additions & 0 deletions src/Humanizer.Tests/Localisation/NumberToWordsFactoryTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
using Xunit;

namespace Humanizer.Tests.Localisation
{
public class NumberToWordsFactoryTests
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think this class provides much benefit as everything asserted here is already being tested much more thoroughly elsewhere. So removing it.

{
[Fact]
public void CanGetTwoLetterIsoLanguageSpecificFactory()
{
using (new AmbientCulture("ar"))
{
string result = 1000000000.ToWords();
Assert.NotEqual("1000000000", result);
}
}

[Fact]
public void CanGetRfcStandardLanguageSpecificFactory()
{
using (new AmbientCulture("pt-BR"))
{
string result = 1000000000.ToWords();
Assert.NotEqual("1000000000", result);
}
}

[Fact]
public void CanGetCorrectRfcStandardLanguageSpecificFactory()
{
string resultPtBr;
const int number = 1000000000;
using (new AmbientCulture("pt-BR"))
{
resultPtBr = number.ToWords();
}

string resultPtPt;
using (new AmbientCulture("pt-PT"))
{
resultPtPt = number.ToWords();
}

Assert.NotEqual(resultPtBr, resultPtPt);
}
}
}
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());
}
}
}
1 change: 1 addition & 0 deletions src/Humanizer/Humanizer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,7 @@
<AssemblyOriginatorKeyFile>Humanizer.snk</AssemblyOriginatorKeyFile>
</PropertyGroup>
<ItemGroup>
<Compile Include="Localisation\NumberToWords\BrazilianPortugueseNumberToWordsConverter.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,100 @@
using Humanizer.Localisation.NumberToWords;
using System;
using System.Collections.Generic;

namespace Humanizer.Localisation.NumberToWords
{
internal class BrazilianPortugueseNumberToWordsConverter : DefaultNumberToWordsConverter
{
private static readonly string[] portugueseUnitsMap = { "zero", "um", "dois", "três", "quatro", "cinco", "seis", "sete", "oito", "nove", "dez", "onze", "doze", "treze", "quatorze", "quinze", "dezesseis", "dezessete", "dezoito", "dezenove" };
private static readonly string[] portugueseTensMap = { "zero", "dez", "vinte", "trinta", "quarenta", "cinquenta", "sessenta", "setenta", "oitenta", "noventa" };
private static readonly string[] portugueseHundredsMap = { "zero", "cento", "duzentos", "trezentos", "quatrocentos", "quinhentos", "seiscentos", "setecentos", "oitocentos", "novecentos" };

public override string Convert(int number)
{
if (number == 0)
return "zero";

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

var parts = new List<string>();

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

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

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

number %= 1000;
}

if ((number / 100) > 0)
{
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");

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());
}
}
}
12 changes: 9 additions & 3 deletions src/Humanizer/NumberToWordsExtension.cs
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
using Humanizer.Localisation.NumberToWords;
using System;
using System.Collections.Generic;
using System.Globalization;
using Humanizer.Localisation.NumberToWords;

namespace Humanizer {
namespace Humanizer
{
/// <summary>
/// Transform a number into words; e.g. 1 => one
/// </summary>
Expand All @@ -15,7 +16,8 @@ public static class NumberToWordsExtension {
{ "ar", () => new ArabicNumberToWordsConverter() },
{ "fa", () => new FarsiNumberToWordsConverter() },
{ "es", () => new SpanishNumberToWordsConverter() },
{ "pl", () => new PolishNumberToWordsConverter() }
{ "pl", () => new PolishNumberToWordsConverter() },
{ "pt-BR", () => new BrazilianPortugueseNumberToWordsConverter() }
};

/// <summary>
Expand Down Expand Up @@ -43,6 +45,10 @@ private static INumberToWordsConverter Converter
get
{
Func<INumberToWordsConverter> converterFactory;

if (ConverterFactories.TryGetValue(CultureInfo.CurrentUICulture.Name, out converterFactory))
return converterFactory();

if (ConverterFactories.TryGetValue(CultureInfo.CurrentUICulture.TwoLetterISOLanguageName, out converterFactory))
return converterFactory();

Expand Down