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 Bulgarian localization, date and timespan tests #181

Closed
wants to merge 30 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
30 commits
Select commit Hold shift + click to select a range
dc90d4e
Added Bulgarian localization, date and timespan tests
ivanst-stoyanov Apr 11, 2014
18c51a1
Added PR to the release notes
ivanst-stoyanov Apr 12, 2014
93b8aee
Revert "Added PR to the release notes"
ivanst-stoyanov Apr 12, 2014
f06e119
Add NumberToWordsTests for invariant culture
hazzik Apr 10, 2014
e0cefdc
Add ToQuantityTests for invariant culture
hazzik Apr 10, 2014
75ab297
(re)setting CurrentCulture on ambient culture
MehdiK Apr 11, 2014
476b159
Added Spanish toWords
thunsaker Apr 9, 2014
d4c99e2
Adding PR to release notes
thunsaker Apr 9, 2014
acc4a07
Cleaning up my braces
thunsaker Apr 11, 2014
1193722
tidying up ToWords converter particularly Spanish
MehdiK Apr 11, 2014
d59b5d3
Added Polish translation for ToWords
mnowacki Apr 10, 2014
58f59c5
Added Polish localization test for Now and NoTime
mnowacki Apr 10, 2014
002f557
Added PR to the release notes
mnowacki Apr 11, 2014
e4952b0
minor cleanup
MehdiK Apr 11, 2014
2e63de8
lifted the contribution guideline & fixed #154
MehdiK Apr 11, 2014
8f4cf15
Including namespaces in MVC ModelMetadataProvider example
danmalcolm Apr 11, 2014
967bedb
changed the Model Binding sentence a bit
MehdiK Apr 11, 2014
6139bf5
Fixed spelling error with forth/fourth in EnglishNumberToWordsConverter
thunsaker Apr 11, 2014
0954ae6
Updated release notes
thunsaker Apr 11, 2014
60ca6f1
releasing v1.20.2
MehdiK Apr 11, 2014
97bf7aa
Refactor ToOrdinalWords to use existing NumberToWordsExtension instea…
thunsaker Apr 11, 2014
5b9615e
Updated readme with ToOrdinalWords refactoring
thunsaker Apr 11, 2014
6666678
Moved PR to In Dev section
thunsaker Apr 11, 2014
212adc2
fixes the null exception on date humanize
MehdiK Apr 12, 2014
3e2fbfa
added the PR to release notes
MehdiK Apr 12, 2014
72fa521
released v1.20.15
MehdiK Apr 12, 2014
fb80710
correct inline code escaping
mexx Apr 12, 2014
fc824d2
fixed conflicts
ivanst-stoyanov Apr 12, 2014
bd4ed1a
fixed conflicts
ivanst-stoyanov Apr 12, 2014
8346c23
Added PR to the release notes
ivanst-stoyanov Apr 12, 2014
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
100 changes: 59 additions & 41 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -568,49 +568,60 @@ You may find an Asp.Net MVC sample [in the code](https://github.com/MehdiK/Human
This is achieved using a custom `DataAnnotationsModelMetadataProvider` I called [HumanizerMetadataProvider](https://github.com/MehdiK/Humanizer/blob/master/src/Humanizer.MvcSample/HumanizerMetadataProvider.cs). It is small enough to repeat here; so here we go:

```C#
public class HumanizerMetadataProvider : DataAnnotationsModelMetadataProvider
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Web.Mvc;
using Humanizer;

namespace YourApp
{
protected override ModelMetadata CreateMetadata(
IEnumerable<Attribute> attributes,
Type containerType,
Func<object> modelAccessor,
Type modelType,
string propertyName)
public class HumanizerMetadataProvider : DataAnnotationsModelMetadataProvider
{
var propertyAttributes = attributes.ToList();
var modelMetadata = base.CreateMetadata(propertyAttributes, containerType, modelAccessor, modelType, propertyName);

if (IsTransformRequired(modelMetadata, propertyAttributes))
modelMetadata.DisplayName = modelMetadata.PropertyName.Humanize();

return modelMetadata;
}

private static bool IsTransformRequired(ModelMetadata modelMetadata, IList<Attribute> propertyAttributes)
{
if (string.IsNullOrEmpty(modelMetadata.PropertyName))
return false;

if (propertyAttributes.OfType<DisplayNameAttribute>().Any())
return false;

if (propertyAttributes.OfType<DisplayAttribute>().Any())
return false;

return true;
protected override ModelMetadata CreateMetadata(
IEnumerable<Attribute> attributes,
Type containerType,
Func<object> modelAccessor,
Type modelType,
string propertyName)
{
var propertyAttributes = attributes.ToList();
var modelMetadata = base.CreateMetadata(propertyAttributes, containerType, modelAccessor, modelType, propertyName);

if (IsTransformRequired(modelMetadata, propertyAttributes))
modelMetadata.DisplayName = modelMetadata.PropertyName.Humanize();

return modelMetadata;
}

private static bool IsTransformRequired(ModelMetadata modelMetadata, IList<Attribute> propertyAttributes)
{
if (string.IsNullOrEmpty(modelMetadata.PropertyName))
return false;

if (propertyAttributes.OfType<DisplayNameAttribute>().Any())
return false;

if (propertyAttributes.OfType<DisplayAttribute>().Any())
return false;

return true;
}
}
}
```

This class calls the base class to extract the metadata and then, if required, humanizes the property name. It is checking if the property already has a `DisplayName` or `Display` attribute on it in which case the metadata provider will just honor the attribute and leave the property alone. For other properties it will Humanize the property name. That is all.

Now I need to register this metadata provider with Asp.Net MVC:
Now you need to register this metadata provider with Asp.Net MVC. Make sure you use System.Web.Mvc.ModelMetadataProviders, not System.Web.ModelBinding.ModelMetadataProviders):

```C#
ModelMetadataProviders.Current = new HumanizerMetadataProvider();
```

... and now I can replace:
... and now you can replace:

```C#
public class RegisterModel
Expand Down Expand Up @@ -656,17 +667,24 @@ I have also flagged some of the easier issues as 'jump in' so you can start with
I use [GitHub flow](http://scottchacon.com/2011/08/31/github-flow.html) for pull requests.
So if you want to contribute, fork the repo, preferrably create a local branch to avoid conflicts with other activities, fix an issue and send a PR.

Pull requests are code reviewed. Here is what I look for in your pull request:

- Clean implementation
- Very little or no comments because comments shouldn't be needed if you write clean code
- Xml documentation for new extensions or updating the existing documentation when you make a change
- Proper unit test coverage
- Adherence to the existing coding styles
- Updated readme if you change an existing feature or add something
- Add an entry in the release_notes.md file in the 'In Development' section with a link to your PR link and description of what's changed. Please follow the wording style for the description.

Also please link to the issue(s) you're fixing from your PR description.
Pull requests are code reviewed. Here is a checklist you should tick through before submitting a pull request:

- [ ] Implementation is clean
- [ ] Code adheres to the existing coding standards; e.g. no curlies for one-line blocks & no redundant empty lines between methods or code blocks
- [ ] No ReSharper warnings
- [ ] There is proper unit test coverage
- [ ] If the code is copied from StackOverflow (or a blog or OSS) full disclosure is included. That includes required license files and/or file headers explaining where the code came from with proper attribution
- [ ] There is very little or no comments (because comments shouldn't be needed if you write clean code)
- [ ] Xml documentation is added/updated for the addition/change
- [ ] Your PR is (re)based on top of the latest commits (more info below)
- [ ] Link to the issue(s) you're fixing from your PR description. Use `fixes #<the issue number>`
- [ ] Readme is updated if you change an existing feature or add a new one
- [ ] An entry is added in the release_notes.md file in the 'In Development' section with a link to your PR and a description of what's changed. Please follow the wording style for the description.

Please rebase your code on top of the latest commits.
Before working on your fork make sure you pull the latest so you work on top of the latest commits to avoid merge conflicts.
Also before sending the pull request pleast rebase your code as there is a chance there has been a few commits pushed up after you pulled last.
Please refer to [this guide](https://gist.github.com/jbenet/ee6c9ac48068889b0912#the-workflow) if you're new to git.

###<a id="need-your-help-with-localisation">Need your help with localisation</a>
One area Humanizer could always use your help is localisation.
Expand Down
12 changes: 11 additions & 1 deletion release_notes.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,15 @@
###In Development
- [#181](https://github.com/Mehdik/Humanizer/pull/181): Added Bulgarian localization, date and timespan tests

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

###v1.20.15 - 2014-04-12
- [#186](https://github.com/Mehdik/Humanizer/pull/186): Refactored `ToOrdinalWords` to use existing `NumberToWordsExtension` to prepare for Ordinal localization
- [#193](https://github.com/Mehdik/Humanizer/pull/193): Fixed the NullException error on DateTime.Humanize

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

###v1.20.2 - 2014-04-11
- [#171](https://github.com/MehdiK/Humanizer/pull/171): T4-Template fix: Using EnglishNumberToWordsConverter instead of 'ToWords()' while dogfooding the template with the library.
- [#165](https://github.com/MehdiK/Humanizer/pull/165): Added precision based `DateTime.Humanize` strategy
- [#155](https://github.com/MehdiK/Humanizer/pull/155): French and Belgian French localisation
Expand Down Expand Up @@ -145,4 +156,3 @@ fix it based on your requirements.

###v1.0.0 - 2013-11-10
No release history before this point: check out http://www.mehdi-khalili.com/humanizer-v1 for the feature-set at V1

1 change: 1 addition & 0 deletions src/Humanizer.Tests/AmbientCulture.cs
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ public AmbientCulture(string cultureName)
public void Dispose()
{
Thread.CurrentThread.CurrentUICulture = _culture;
Thread.CurrentThread.CurrentCulture = _culture;
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -181,13 +181,6 @@ public interface IFormatter
string TimeSpanHumanize_Zero();
}

public class EnglishNumberToWordsConverter
{
public EnglishNumberToWordsConverter() { }
public string Convert(int number) { }
public string ConvertToOrdinal(int number) { }
}

public interface INumberToWordsConverter
{
string Convert(int number);
Expand Down Expand Up @@ -231,11 +224,6 @@ public class NoMatchFoundException
public NoMatchFoundException(string message, System.Exception inner) { }
}

public class NumberToOrdinalWordsExtension
{
public string ToOrdinalWords(int number) { }
}

public class NumberToTimeSpanExtensions
{
public System.TimeSpan Days(int days) { }
Expand All @@ -248,6 +236,7 @@ public class NumberToTimeSpanExtensions

public class NumberToWordsExtension
{
public string ToOrdinalWords(int number) { }
public string ToWords(int number) { }
}

Expand Down
6 changes: 6 additions & 0 deletions src/Humanizer.Tests/Humanizer.Tests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,8 @@
<Compile Include="Bytes\ToStringTests.cs" />
<Compile Include="CasingTests.cs" />
<Compile Include="DateHumanize.cs" />
<Compile Include="Localisation\bg\DateHumanizeTests.cs" />
<Compile Include="Localisation\bg\TimeSpanHumanizeTests.cs" />
<Compile Include="Localisation\cs\DateHumanizeTests.cs" />
<Compile Include="Localisation\cs\TimeSpanHumanizeTests.cs" />
<Compile Include="Localisation\da\DateHumanizeTests.cs" />
Expand All @@ -84,8 +86,12 @@
<Compile Include="Localisation\fr-BE\TimeSpanHumanizeTests.cs" />
<Compile Include="Localisation\fr\DateHumanizeTests.cs" />
<Compile Include="Localisation\fr\TimeSpanHumanizeTests.cs" />
<Compile Include="Localisation\invariant\NumberToWordsTests.cs" />
<Compile Include="Localisation\invariant\ToQuantityTests.cs" />
<Compile Include="Localisation\es\NumberToWordsTests.cs" />
<Compile Include="Localisation\nb-NO\TimeSpanHumanizeTests.cs" />
<Compile Include="Localisation\pl\DateHumanizeTests.cs" />
<Compile Include="Localisation\pl\NumberToWordsTests.cs" />
<Compile Include="Localisation\pl\TimeSpanHumanizeTests.cs" />
<Compile Include="Localisation\ru-RU\TimeSpanHumanizeTests.cs" />
<Compile Include="Localisation\sk\DateHumanizeTests.cs" />
Expand Down
115 changes: 115 additions & 0 deletions src/Humanizer.Tests/Localisation/bg/DateHumanizeTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
using Humanizer.Localisation;
using Xunit;
using Xunit.Extensions;

namespace Humanizer.Tests.Localisation.bg
{
public class DateHumanizeTests : AmbientCulture
{
public DateHumanizeTests() : base("bg-BG")
{
}

[Theory]
[InlineData(1, "преди секунда")]
[InlineData(2, "преди 2 секунди")]
public void SecondsAgo(int seconds, string expected)
{
DateHumanize.Verify(expected, seconds, TimeUnit.Second, Tense.Past);
}

[Theory]
[InlineData(1, "след секунда")]
[InlineData(2, "след 2 секунди")]
public void SecondsFromNow(int seconds, string expected)
{
DateHumanize.Verify(expected, seconds, TimeUnit.Second, Tense.Future);
}

[Theory]
[InlineData(1, "преди минута")]
[InlineData(2, "преди 2 минути")]
public void MinutesAgo(int minutes, string expected)
{
DateHumanize.Verify(expected, minutes, TimeUnit.Minute, Tense.Past);
}

[Theory]
[InlineData(1, "след минута")]
[InlineData(2, "след 2 минути")]
public void MinutesFromNow(int minutes, string expected)
{
DateHumanize.Verify(expected, minutes, TimeUnit.Minute, Tense.Future);
}

[Theory]
[InlineData(1, "преди час")]
[InlineData(2, "преди 2 часа")]
public void HoursAgo(int hours, string expected)
{
DateHumanize.Verify(expected, hours, TimeUnit.Hour, Tense.Past);
}

[Theory]
[InlineData(1, "след час")]
[InlineData(2, "след 2 часа")]
public void HoursFromNow(int hours, string expected)
{
DateHumanize.Verify(expected, hours, TimeUnit.Hour, Tense.Future);
}

[Theory]
[InlineData(1, "вчера")]
[InlineData(2, "преди 2 дена")]
public void DaysAgo(int days, string expected)
{
DateHumanize.Verify(expected, days, TimeUnit.Day, Tense.Past);
}

[Theory]
[InlineData(1, "утре")]
[InlineData(2, "след 2 дена")]
public void DaysFromNow(int days, string expected)
{
DateHumanize.Verify(expected, days, TimeUnit.Day, Tense.Future);
}

[Theory]
[InlineData(1, "преди месец")]
[InlineData(2, "преди 2 месеца")]
public void MonthsAgo(int months, string expected)
{
DateHumanize.Verify(expected, months, TimeUnit.Month, Tense.Past);
}

[Theory]
[InlineData(1, "след месец")]
[InlineData(2, "след 2 месеца")]
public void MonthsFromNow(int months, string expected)
{
DateHumanize.Verify(expected, months, TimeUnit.Month, Tense.Future);
}

[Theory]
[InlineData(1, "преди година")]
[InlineData(2, "преди 2 години")]
public void YearsAgo(int years, string expected)
{
DateHumanize.Verify(expected, years, TimeUnit.Year, Tense.Past);
}

[Theory]
[InlineData(1, "след година")]
[InlineData(2, "след 2 години")]
public void YearsFromNow(int years, string expected)
{
DateHumanize.Verify(expected, years, TimeUnit.Year, Tense.Future);
}

[Fact]
public void Now()
{
DateHumanize.Verify("сега", 0, TimeUnit.Day, Tense.Past);
}
}
}
66 changes: 66 additions & 0 deletions src/Humanizer.Tests/Localisation/bg/TimeSpanHumanizeTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
using System;
using Xunit;
using Xunit.Extensions;

namespace Humanizer.Tests.Localisation.bg
{
public class TimeSpanHumanizeTests : AmbientCulture
{
public TimeSpanHumanizeTests() : base("bg-BG") { }

[Theory]
[InlineData(7, "една седмица")]
[InlineData(14, "2 седмици")]
public void Weeks(int days, string expected)
{
Assert.Equal(expected, TimeSpan.FromDays(days).Humanize());
}

[Theory]
[InlineData(1, "един ден")]
[InlineData(2, "2 дена")]
public void Days(int days, string expected)
{
Assert.Equal(expected, TimeSpan.FromDays(days).Humanize());
}

[Theory]
[InlineData(1, "един час")]
[InlineData(2, "2 часа")]
public void Hours(int hours, string expected)
{
Assert.Equal(expected, TimeSpan.FromHours(hours).Humanize());
}

[Theory]
[InlineData(1, "една минута")]
[InlineData(2, "2 минути")]
public void Minutes(int minutes, string expected)
{
Assert.Equal(expected, TimeSpan.FromMinutes(minutes).Humanize());
}

[Theory]
[InlineData(1, "една секунда")]
[InlineData(2, "2 секунди")]
public void Seconds(int seconds, string expected)
{
Assert.Equal(expected, TimeSpan.FromSeconds(seconds).Humanize());
}

[Theory]
[InlineData(1, "една милисекунда")]
[InlineData(2, "2 милисекунди")]
public void Milliseconds(int milliseconds, string expected)
{
Assert.Equal(expected, TimeSpan.FromMilliseconds(milliseconds).Humanize());
}

[Fact]
public void NoTime()
{
// This one doesn't make a lot of sense but ... w/e
Assert.Equal("няма време", TimeSpan.Zero.Humanize());
}
}
}
Loading