-
Notifications
You must be signed in to change notification settings - Fork 965
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 optional Culture parameter to NumberToWords #300
Conversation
2) Explicitly registering DefaultFormatter's for the supported languages in FormatterRegistry's constructor
Conflicts: readme.md src/Humanizer.Tests/ApiApprover/PublicApiApprovalTest.approve_public_api.approved.txt src/Humanizer.Tests/DateHumanizeDefaultStrategyTests.cs src/Humanizer.Tests/TimeSpanHumanizeTests.cs src/Humanizer/Configuration/FormatterRegistry.cs src/Humanizer/Configuration/LocaliserRegistry.cs
Also, culture to use can be specified explicitly. If it is not, current thread's current UI culture is used. Here's an example: | ||
|
||
```C# | ||
11.ToWords(new CultureInfo("ru")) => "eleven" |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The example is not correct, either it should be new CultureInfo("en")
or the result "одинадцать"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thx, i've fixed it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
С двумя "н"
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@@ -104,6 +107,11 @@ public override string Convert(int number, GrammaticalGender gender) | |||
return string.Join(" ", parts); | |||
} | |||
|
|||
public override string ConvertToOrdinal(int number, GrammaticalGender gender) | |||
{ | |||
return number.ToString(_culture); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If we request 1234.ToWords(new CultureInfo("he-IL"))
the _culture
really used for formatting would be "he"
. Same applies to "pl"
and "sl"
.
I think we should use the requested culture, maybe the formatting would deliver another result as the statically defined culture.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You are right. Let me explain my thoughts here:
- We've discussed similar issue while i was working on DateTime.Humanize. It seems that @MehdiK decided that it's not important and merged DateTime.Humanize as it was.
- The only reason we use "_culture" here is that HebrewNumberToWordsConverter misses ConvertToOrdinal implementation. Once that is implemented, issue will disappear.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
For me it's something different as with DateTime.Humanize. In it we use the resources defined in our assembly and in here we utilize the standard functionality of the framework.
For DateTime.Humanize our implementation defined that the localization for region specific locale should be the same as for region unspecific one.
For our case we did not made such a decision, so we should use the specific locale.
Further it would preserve the current functionality, as currently number.ToString()
is used, the specific culture if set as CurrentUICulture
will be used.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@mexx I see your point. To work this around, we may pass the "culture" to the HebrewNumberToWordsConverter's constructor. But this means, that object have to be created each time number.ToWords() is called. Another option might be to pass "culture" to ConvertToOrdinal calls. Again, we discussed pros/cons in DateTime.Humanize()'s thread.
Personally, i do not think there is any real problem with creating new object on each call.
So, if @MehdiK agrees on this, i will change it accordingly.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think either there is a problem of creating new object on each call, and it's already done for default localiser.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ah, I see the problem.
Maybe instead of creating the converters on each call we can register HebrewNumberToWordsConverter
with both "he" and "he-IL" passing the culture to the converter to be cached by the converter locally? That way the same class is used for both locales while the class still uses the provided culture.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe instead of creating the converters on each call we can register HebrewNumberToWordsConverter with both "he" and "he-IL" passing the culture to the converter to be cached by the converter locally?
Sure, we can do this. But this does not solve issue for the default converter. Obviously, we can not pre-register an instance for each unsupported culture :).
Basically, if you remember my initial implementation of DateTime.Humanize ... i used to pass the culture object directly to the converter's methods. This solves issue with many-small-objects-have-to-be-created + we always can use actual culture instead of made-up one. But then people did not like it actively and we decided to pass the culture to the converter's constructor. So... what i think here... may be that was not that bad idea at all and we can do it that way? :)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we need to have a cache based on culture, then we can solve all the issues. Sure, it will require to write some code, but the proper working solution would be much better than incorrect one
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@hazzik I do not think that cache is that good idea here, as we then have to take care of race conditions and stuff like that, which will make the library less usable with multithreaded server code (this is my primary area of interest and that's why i initially wanted to have this explicit culture support).
To be fair, i do not think that introducing locks just to avoid passing additional parameter makes any viable sense.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
"may be that was not that bad idea at all and we can do it that way?"
I have to say, in the hindsight this is hard to argue with.
{ | ||
internal class DefaultNumberToWordsConverter : INumberToWordsConverter | ||
internal sealed class DefaultNumberToWordsConverter : GenderlessNumberToWordsConverter |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why did you make this class sealed?
P.S. In fact I've never found a legitimate case to create a sealed class.
{ | ||
/// <summary> | ||
/// Converts the number to string using | ||
/// </summary> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
using what?
Added optional Culture parameter to NumberToWords
I am merging this as is. We can tackle the localisers in a separate PR. |
For some reason I thought this was rebased and by merging it from GitHub I made a huge mess of the commit graph. Do'h. Sorry guys. @dmitry-gokun please rebase your code before creating PRs. Thanks. |
This is now released to NuGet as v1.27.0. Thanks for your contribution. |
@MehdiK i'm sorry for this mess. I'm new to github, so i will try to be more careful :(
So, if i understand you correctly, we should go with passing "culture" as a parameter to converter's methods (same for DateTime formatters)? Plz confirm and i will work on a PR for this.
Thanks 👍 |
No worries. That's alright. I should've checked before merging.
I'd rather not pass culture to every method tbh; but so far that seems like the cleanest option. I would like to hear what @mexx and @hazzik think about this too. |
Actually I don't experience any issues with current design. |
No description provided.