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

Made Configurator.FormatterFactories public #227

Closed
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
10 changes: 8 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ Humanizer meets all your .NET needs for manipulating and displaying strings, enu
- [Number to ordinal words](#number-to-ordinal-words)
- [Roman numerals](#roman-numerals)
- [ByteSize](#bytesize)
- [Configuration](#configuration)
- [Mix this into your framework to simplify your life](#mix-this-into-your-framework-to-simplify-your-life)
- [How to contribute?](#how-to-contribute)
- [Contribution guideline](#contribution-guideline)
Expand Down Expand Up @@ -679,6 +680,11 @@ ByteSize.Parse("1.55 tB");
ByteSize.Parse("1.55 tb");
```

##<a id="configuration">Configuration</a>

Custom factories for `Formatter`s, `NumberToWordsConverter`s, and `Ordinalizer`s may be added or updated via `FormatterFactoryManager`, `NumberToWordsConverterFactoryManager`, and `OrdinalizerFactoryManager` using the `SetFactory` method.


##<a id="mix-this-into-your-framework-to-simplify-your-life">Mix this into your framework to simplify your life</a>
This is just a baseline and you can use this to simplify your day to day job. For example, in Asp.Net MVC we keep chucking `Display` attribute on ViewModel properties so `HtmlHelper` can generate correct labels for us; but, just like enums, in vast majority of cases we just need a space between the words in property name - so why not use `"string".Humanize` for that?!

Expand Down Expand Up @@ -828,7 +834,7 @@ Then you return an instance of your class in the [Configurator](https://github.c
Translations for `ToWords` and `ToOrdinalWords` methods are currently done in code as there is a huge difference between the way different languages deal with number words.
Check out [Dutch](https://github.com/MehdiK/Humanizer/blob/master/src/Humanizer/Localisation/NumberToWords/DutchNumberToWordsConverter.cs) and
[Russian](https://github.com/MehdiK/Humanizer/blob/master/src/Humanizer/Localisation/NumberToWords/RussianNumberToWordsConverter.cs) localisations for examples of how you can write a Converter for your language.
You should then register your converter in the [ConverterFactory](https://github.com/MehdiK/Humanizer/blob/master/src/Humanizer/NumberToWordsExtension.cs#L13) for it to kick in on your locale.
You should then register your converter in the [NumberToWordsConverterFactoryManager](https://github.com/MehdiK/Humanizer/blob/master/src/Humanizer/Configuration/NumberToWordsConverterFactoryManager.cs#L35) for it to kick in on your locale.

Don't forget to write tests for your localisations. Check out the existing [DateHumanizeTests](https://github.com/MehdiK/Humanizer/blob/master/src/Humanizer.Tests/Localisation/ru-RU/DateHumanizeTests.cs), [TimeSpanHumanizeTests](https://github.com/MehdiK/Humanizer/blob/master/src/Humanizer.Tests/Localisation/ru-RU/TimeSpanHumanizeTests.cs) and [NumberToWordsTests](https://github.com/MehdiK/Humanizer/blob/master/src/Humanizer.Tests/Localisation/ru-RU/NumberToWordsTests.cs).

Expand All @@ -848,4 +854,4 @@ Alexander I. Zaytsev ([@hazzik](https://github.com/hazzik))
Humanizer is released under the MIT License. See the [bundled LICENSE](https://github.com/MehdiK/Humanizer/blob/master/LICENSE) file for details.

##<a id="icon">Icon</a>
Icon created by [Tyrone Rieschiek](https://twitter.com/Inkventive)
Icon created by [Tyrone Rieschiek](https://twitter.com/Inkventive)
2 changes: 1 addition & 1 deletion release_notes.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
- [#232](https://github.com/Mehdik/Humanizer/pull/232): Adding code & tests to handle Arabic numbers to ordinal
- [#235](https://github.com/Mehdik/Humanizer/pull/235): Fixed the conversion for "1 millon" in SpanishNumberToWordsConverter
- [#233](https://github.com/Mehdik/Humanizer/pull/233): Added build.cmd and Verify build configuration for strict project build and analysis
- [#227](https://github.com/MehdiK/Humanizer/pull/227): Moved factory collections to their own classes, allowed public access via Configurator, and made the default factories lazy loaded

[Commits](https://github.com/MehdiK/Humanizer/compare/v1.23.1...v1.24.1)

Expand All @@ -18,7 +19,6 @@
- [#231](https://github.com/Mehdik/Humanizer/pull/231): Added more settings for FromNow, Dual and Plural (Arabic)
- [#222](https://github.com/Mehdik/Humanizer/pull/222): Updated Ordinalize and ToOrdinalWords to account for special exceptions with 1 and 3.


[Commits](https://github.com/MehdiK/Humanizer/compare/v1.22.1...v1.23.1)

###v1.22.1 - 2014-04-14
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,17 @@ public class CasingExtensions
public class Configurator
{
public Humanizer.DateTimeHumanizeStrategy.IDateTimeHumanizeStrategy DateTimeHumanizeStrategy { get; set; }
public Humanizer.Localisation.Formatters.IFormatter Formatter { get; }
public Humanizer.Configuration.FactoryManager<Humanizer.Localisation.Formatters.IFormatter> FormatterFactoryManager { get; }
public Humanizer.Configuration.FactoryManager<Humanizer.Localisation.NumberToWords.INumberToWordsConverter> NumberToWordsConverterFactoryManager { get; }
public Humanizer.Configuration.FactoryManager<Humanizer.Localisation.Ordinalizers.IOrdinalizer> OrdinalizerFactoryManager { get; }
}

public class FactoryManager`1
{
public FactoryManager`1(System.Collections.Generic.IDictionary<, > factories) { }
public System.Func<> GetFactory(System.Globalization.CultureInfo culture) { }
public void SetDefaultFactory(System.Func<> factory) { }
public void SetFactory(System.Func<> factory, System.Globalization.CultureInfo culture) { }
}

public class DateHumanizeExtensions
Expand Down Expand Up @@ -200,6 +210,20 @@ public interface IFormatter
string TimeSpanHumanize_Zero();
}

public interface INumberToWordsConverter
{
string Convert(int number);
string Convert(int number, Humanizer.GrammaticalGender gender);
string ConvertToOrdinal(int number);
string ConvertToOrdinal(int number, Humanizer.GrammaticalGender gender);
}

public interface IOrdinalizer
{
string Convert(int number, string numberString);
string Convert(int number, string numberString, Humanizer.GrammaticalGender gender);
}

public class ResourceKeys
{
public ResourceKeys() { }
Expand Down
62 changes: 46 additions & 16 deletions src/Humanizer/Configuration/Configurator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
using System.Globalization;
using Humanizer.DateTimeHumanizeStrategy;
using Humanizer.Localisation.Formatters;
using Humanizer.Localisation.NumberToWords;
using Humanizer.Localisation.Ordinalizers;

namespace Humanizer.Configuration
{
Expand All @@ -11,32 +13,60 @@ namespace Humanizer.Configuration
/// </summary>
public static class Configurator
{
private static readonly IDictionary<string, Func<IFormatter>> FormatterFactories =
new Dictionary<string, Func<IFormatter>>(StringComparer.OrdinalIgnoreCase)

private static FactoryManager<IFormatter> _formatterFactoryManager = new FormatterFactoryManager();

public static FactoryManager<IFormatter> FormatterFactoryManager
{
get { return _formatterFactoryManager; }
}

private static FactoryManager<INumberToWordsConverter> _numberToWordsConverterFactoryManager = new NumberToWordsConverterFactoryManager();

public static FactoryManager<INumberToWordsConverter> NumberToWordsConverterFactoryManager
{
get { return _numberToWordsConverterFactoryManager; }
}

private static FactoryManager<IOrdinalizer> _ordinalizerFactoryManager = new OrdinalizerFactoryManager();

public static FactoryManager<IOrdinalizer> OrdinalizerFactoryManager
{
{ "ro", () => new RomanianFormatter() },
{ "ru", () => new RussianFormatter() },
{ "ar", () => new ArabicFormatter() },
{ "he", () => new HebrewFormatter() },
{ "sk", () => new CzechSlovakPolishFormatter() },
{ "cs", () => new CzechSlovakPolishFormatter() },
{ "pl", () => new CzechSlovakPolishFormatter() }
};
get { return _ordinalizerFactoryManager; }
}

private static IDateTimeHumanizeStrategy _dateTimeHumanizeStrategy = new DefaultDateTimeHumanizeStrategy();

/// <summary>
/// The formatter to be used
/// </summary>
public static IFormatter Formatter
internal static IFormatter Formatter
{
get
{
return FormatterFactoryManager.GetFactory()();
}
}

/// <summary>
/// The converter to be used
/// </summary>
internal static INumberToWordsConverter NumberToWordsConverter
{
get
{
return NumberToWordsConverterFactoryManager.GetFactory()();
}
}

/// <summary>
/// The ordinalizer to be used
/// </summary>
internal static IOrdinalizer Ordinalizer
{
get
{
Func<IFormatter> formatterFactory;
if (FormatterFactories.TryGetValue(CultureInfo.CurrentUICulture.TwoLetterISOLanguageName, out formatterFactory))
return formatterFactory();

return new DefaultFormatter();
return OrdinalizerFactoryManager.GetFactory()();
}
}

Expand Down
56 changes: 56 additions & 0 deletions src/Humanizer/Configuration/FactoryManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,56 @@
using System;
using System;
using System.Collections.Generic;
using System.Globalization;

namespace Humanizer.Configuration
{
public class FactoryManager<T>
{
private IDictionary<string, Func<T>> _factories;

public FactoryManager(IDictionary<string, Func<T>> factories)
{
_factories = factories;
}

/// <summary>
/// Gets the factory for the CultureInfo provided.
/// If no culture is provided, CultureInfo.CurrentUICulture will be used
/// </summary>
public Func<T> GetFactory(CultureInfo culture = null)
{
culture = culture ?? CultureInfo.CurrentUICulture;

Func<T> factory;

if (_factories.TryGetValue(culture.Name, out factory))
return factory;

if (_factories.TryGetValue(culture.TwoLetterISOLanguageName, out factory))
return factory;

return _factories["default"];
}

/// <summary>
/// Set the factory for the culture provided.
/// </summary>
public void SetFactory(Func<T> factory, CultureInfo culture = null)
{
culture = culture ?? CultureInfo.CurrentUICulture;

_factories[culture.Name] = factory;
}

/// <summary>
/// Set the default factory for when a culture does not have a
/// specific factory set.
/// </summary>
public void SetDefaultFactory(Func<T> factory)
{
_factories["default"] = factory;
}

}
}
33 changes: 33 additions & 0 deletions src/Humanizer/Configuration/FormatterFactoryManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using Humanizer.Localisation.Formatters;

namespace Humanizer.Configuration
{
internal class FormatterFactoryManager : FactoryManager<IFormatter>
{
private static readonly Lazy<RomanianFormatter> _lazyRomanianFormatter = new Lazy<RomanianFormatter>();
private static readonly Lazy<RussianFormatter> _lazyRussianFormatter = new Lazy<RussianFormatter>();
private static readonly Lazy<ArabicFormatter> _lazyArabicFormatter = new Lazy<ArabicFormatter>();
private static readonly Lazy<HebrewFormatter> _lazyHebrewFormatter = new Lazy<HebrewFormatter>();
private static readonly Lazy<CzechSlovakPolishFormatter> _lazyCzechSlovakPolishFormatter = new Lazy<CzechSlovakPolishFormatter>();
private static readonly Lazy<DefaultFormatter> _defaultFormatter = new Lazy<DefaultFormatter>();

public FormatterFactoryManager()
: base(
new Dictionary<string, Func<IFormatter>>
{
{ "ro", () => _lazyRomanianFormatter.Value },
{ "ru", () => _lazyRussianFormatter.Value },
{ "ar", () => _lazyArabicFormatter.Value },
{ "he", () => _lazyHebrewFormatter.Value },
{ "sk", () => _lazyCzechSlovakPolishFormatter.Value },
{ "cs", () => _lazyCzechSlovakPolishFormatter.Value },
{ "pl", () => _lazyCzechSlovakPolishFormatter.Value }
})
{
SetDefaultFactory(() => _defaultFormatter.Value);
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using Humanizer.Localisation.NumberToWords;

namespace Humanizer.Configuration
{
internal class NumberToWordsConverterFactoryManager : FactoryManager<INumberToWordsConverter>
{
private static readonly Lazy<EnglishNumberToWordsConverter> _lazyEnglishNumberToWordsConverter = new Lazy<EnglishNumberToWordsConverter>();
private static readonly Lazy<ArabicNumberToWordsConverter> _lazyArabicNumberToWordsConverter = new Lazy<ArabicNumberToWordsConverter>();
private static readonly Lazy<FarsiNumberToWordsConverter> _lazyFarsiNumberToWordsConverter = new Lazy<FarsiNumberToWordsConverter>();
private static readonly Lazy<SpanishNumberToWordsConverter> _lazySpanishNumberToWordsConverter = new Lazy<SpanishNumberToWordsConverter>();
private static readonly Lazy<PolishNumberToWordsConverter> _lazyPolishNumberToWordsConverter = new Lazy<PolishNumberToWordsConverter>();
private static readonly Lazy<BrazilianPortugueseNumberToWordsConverter> _lazyBrazilianPortugueseNumberToWordsConverter = new Lazy<BrazilianPortugueseNumberToWordsConverter>();
private static readonly Lazy<RussianNumberToWordsConverter> _lazyRussianNumberToWordsConverter = new Lazy<RussianNumberToWordsConverter>();
private static readonly Lazy<FrenchNumberToWordsConverter> _lazyFrenchNumberToWordsConverter = new Lazy<FrenchNumberToWordsConverter>();
private static readonly Lazy<DutchNumberToWordsConverter> _lazyDutchNumberToWordsConverter = new Lazy<DutchNumberToWordsConverter>();
private static readonly Lazy<HebrewNumberToWordsConverter> _lazyHebrewNumberToWordsConverter = new Lazy<HebrewNumberToWordsConverter>();
private static readonly Lazy<DefaultNumberToWordsConverter> _lazyDefaultNumberToWordsConverter = new Lazy<DefaultNumberToWordsConverter>();

public NumberToWordsConverterFactoryManager()
: base(
new Dictionary<string, Func<INumberToWordsConverter>>
{
{"en", () => _lazyEnglishNumberToWordsConverter.Value},
{"ar", () => _lazyArabicNumberToWordsConverter.Value},
{"fa", () => _lazyFarsiNumberToWordsConverter.Value},
{"es", () => _lazySpanishNumberToWordsConverter.Value},
{"pl", () => _lazyPolishNumberToWordsConverter.Value},
{"pt-BR", () => _lazyBrazilianPortugueseNumberToWordsConverter.Value},
{"ru", () => _lazyRussianNumberToWordsConverter.Value},
{"fr", () => _lazyFrenchNumberToWordsConverter.Value},
{"nl", () => _lazyDutchNumberToWordsConverter.Value},
{"he", () => _lazyHebrewNumberToWordsConverter.Value}
})
{
SetDefaultFactory(() => _lazyDefaultNumberToWordsConverter.Value);
}
}
}
29 changes: 29 additions & 0 deletions src/Humanizer/Configuration/OrdinalizerFactoryManager.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
using System;
using System.Collections.Generic;
using System.Globalization;
using Humanizer.Localisation.Ordinalizers;

namespace Humanizer.Configuration
{
internal class OrdinalizerFactoryManager : FactoryManager<IOrdinalizer>
{
private static Lazy<EnglishOrdinalizer> _lazyEnglishOrdinalizer = new Lazy<EnglishOrdinalizer>();
private static Lazy<SpanishOrdinalizer> _lazySpanishOrdinalizer = new Lazy<SpanishOrdinalizer>();
private static Lazy<BrazilianPortugueseOrdinalizer> _lazyBrazilianPortugueseOrdinalizer = new Lazy<BrazilianPortugueseOrdinalizer>();
private static Lazy<RussianOrdinalizer> _lazyRussianOrdinalizer = new Lazy<RussianOrdinalizer>();
private static Lazy<DefaultOrdinalizer> _lazyDefaultOrdinalizer = new Lazy<DefaultOrdinalizer>();

public OrdinalizerFactoryManager()
: base(
new Dictionary<string, Func<IOrdinalizer>>
{
{"en", () => _lazyEnglishOrdinalizer.Value},
{"es", () => _lazySpanishOrdinalizer.Value},
{"pt-BR", () => _lazyBrazilianPortugueseOrdinalizer.Value},
{"ru", () => _lazyRussianOrdinalizer.Value}
})
{
SetDefaultFactory(() => _lazyDefaultOrdinalizer.Value);
}
}
}
6 changes: 6 additions & 0 deletions src/Humanizer/Humanizer.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,10 @@
<DebugSymbols>true</DebugSymbols>
</PropertyGroup>
<ItemGroup>
<Compile Include="Configuration\FactoryManager.cs" />
<Compile Include="Configuration\FormatterFactoryManager.cs" />
<Compile Include="Configuration\NumberToWordsConverterFactoryManager.cs" />
<Compile Include="Configuration\OrdinalizerFactoryManager.cs" />
<Compile Include="Localisation\NumberToWords\BrazilianPortugueseNumberToWordsConverter.cs" />
<Compile Include="GrammaticalCase.cs" />
<Compile Include="GrammaticalGender.cs" />
Expand All @@ -80,9 +84,11 @@
<Compile Include="DateTimeHumanizeStrategy\DefaultDateTimeHumanizeStrategy.cs" />
<Compile Include="DateTimeHumanizeStrategy\IDateTimeHumanizeStrategy.cs" />
<Compile Include="DateTimeHumanizeStrategy\PrecisionDateTimeHumanizeStrategy.cs" />
<Compile Include="Localisation\NumberToWords\INumberToWordsConverter.cs" />
<Compile Include="Localisation\NumberToWords\PolishNumberToWordsConverter.cs" />
<Compile Include="Localisation\NumberToWords\RussianNumberToWordsConverter.cs" />
<Compile Include="Localisation\Formatters\HebrewFormatter.cs" />
<Compile Include="Localisation\Ordinalizers\IOrdinalizer.cs" />
<Compile Include="Localisation\Ordinalizers\RussianOrdinalizer.cs" />
<Compile Include="Localisation\Ordinalizers\SpanishOrdinalizer.cs" />
<Compile Include="Localisation\Ordinalizers\DefaultOrdinalizer.cs" />
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace Humanizer.Localisation.NumberToWords
{
internal class DefaultNumberToWordsConverter
internal class DefaultNumberToWordsConverter : INumberToWordsConverter
{
/// <summary>
/// for Russian locale
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;
namespace Humanizer.Localisation.NumberToWords
{
public interface INumberToWordsConverter
{
string Convert(int number);
string Convert(int number, Humanizer.GrammaticalGender gender);
string ConvertToOrdinal(int number);
string ConvertToOrdinal(int number, Humanizer.GrammaticalGender gender);
}
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
namespace Humanizer.Localisation.Ordinalizers
{
internal class DefaultOrdinalizer
internal class DefaultOrdinalizer : IOrdinalizer
{
public virtual string Convert(int number, string numberString, GrammaticalGender gender)
{
Expand Down
Loading