-
Notifications
You must be signed in to change notification settings - Fork 967
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
add russian translation for ToWords #147
Changes from all commits
1ef992c
b9de703
c68c123
a5e8703
3f6022e
3ed2e70
70f671e
86639b3
ae307cf
3038f61
4881068
5726da0
9564796
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
using Xunit; | ||
using Xunit.Extensions; | ||
|
||
namespace Humanizer.Tests.Localisation.ruRU | ||
{ | ||
public class NumberToWordsTests : AmbientCulture | ||
{ | ||
public NumberToWordsTests() : base("ru-RU") { } | ||
|
||
[Theory] | ||
[InlineData(0, "ноль")] | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Holy crap!! ;) |
||
[InlineData(1, "один")] | ||
[InlineData(10, "десять")] | ||
[InlineData(11, "одиннадцать")] | ||
[InlineData(12, "двенадцать")] | ||
[InlineData(13, "тринадцать")] | ||
[InlineData(14, "четырнадцать")] | ||
[InlineData(15, "пятнадцать")] | ||
[InlineData(16, "шестнадцать")] | ||
[InlineData(17, "семнадцать")] | ||
[InlineData(18, "восемнадцать")] | ||
[InlineData(19, "девятнадцать")] | ||
[InlineData(20, "двадцать")] | ||
[InlineData(30, "тридцать")] | ||
[InlineData(40, "сорок")] | ||
[InlineData(50, "пятьдесят")] | ||
[InlineData(60, "шестьдесят")] | ||
[InlineData(70, "семьдесят")] | ||
[InlineData(80, "восемьдесят")] | ||
[InlineData(90, "девяносто")] | ||
[InlineData(100, "сто")] | ||
[InlineData(200, "двести")] | ||
[InlineData(300, "триста")] | ||
[InlineData(400, "четыреста")] | ||
[InlineData(500, "пятьсот")] | ||
[InlineData(600, "шестьсот")] | ||
[InlineData(700, "семьсот")] | ||
[InlineData(800, "восемьсот")] | ||
[InlineData(900, "девятьсот")] | ||
[InlineData(1000, "одна тысяча")] | ||
[InlineData(2000, "две тысячи")] | ||
[InlineData(3000, "три тысячи")] | ||
[InlineData(4000, "четыре тысячи")] | ||
[InlineData(5000, "пять тысячь")] | ||
[InlineData(10000, "десять тысячь")] | ||
[InlineData(100000, "сто тысячь")] | ||
[InlineData(1000000, "один миллион")] | ||
[InlineData(2000000, "два миллиона")] | ||
[InlineData(10000000, "десять миллионов")] | ||
[InlineData(100000000, "сто миллионов")] | ||
[InlineData(1000000000, "один миллиард")] | ||
[InlineData(2000000000, "два миллиарда")] | ||
[InlineData(122, "сто двадцать два")] | ||
[InlineData(3501, "три тысячи пятьсот один")] | ||
[InlineData(111, "сто одиннадцать")] | ||
[InlineData(1112, "одна тысяча сто двенадцать")] | ||
[InlineData(11213, "одиннадцать тысячь двести тринадцать")] | ||
[InlineData(121314, "сто двадцать одна тысяча триста четырнадцать")] | ||
[InlineData(2132415, "два миллиона сто тридцать две тысячи четыреста пятнадцать")] | ||
[InlineData(12345516, "двенадцать миллионов триста сорок пять тысячь пятьсот шестнадцать")] | ||
[InlineData(751633617, "семьсот пятьдесят один миллион шестьсот тридцать три тысячи шестьсот семнадцать")] | ||
[InlineData(1111111118, "один миллиард сто одиннадцать миллионов сто одиннадцать тысячь сто восемнадцать")] | ||
[InlineData(-751633617, "минус семьсот пятьдесят один миллион шестьсот тридцать три тысячи шестьсот семнадцать")] | ||
public void ToWords(int number, string expected) | ||
{ | ||
Assert.Equal(expected, number.ToWords()); | ||
} | ||
|
||
[Theory] | ||
[InlineData(122, "сто двадцать две", GrammaticalGender.Feminine)] | ||
[InlineData(3501, "три тысячи пятьсот одна", GrammaticalGender.Feminine)] | ||
[InlineData(3501, "три тысячи пятьсот одно", GrammaticalGender.Neuter)] | ||
public void ToWordsWithGender(int number, string expected, GrammaticalGender gender) | ||
{ | ||
Assert.Equal(expected, number.ToWords(gender)); | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,33 @@ | ||
namespace Humanizer | ||
{ | ||
/// <summary> | ||
/// Options for specifying the desired grammatical case for the output words | ||
/// </summary> | ||
public enum GrammaticalCase | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Cool. Thanks for promoting this. |
||
{ | ||
/// <summary> | ||
/// Indicates the subject of a finite verb | ||
/// </summary> | ||
Nominative, | ||
/// <summary> | ||
/// Indicates the possessor of another noun | ||
/// </summary> | ||
Genitive, | ||
/// <summary> | ||
/// Indicates the indirect object of a verb | ||
/// </summary> | ||
Dative, | ||
/// <summary> | ||
/// Indicates the direct object of a verb | ||
/// </summary> | ||
Accusative, | ||
/// <summary> | ||
/// Indicates an object used in performing an action | ||
/// </summary> | ||
Instrumental, | ||
/// <summary> | ||
/// Indicates the object of a preposition | ||
/// </summary> | ||
Prepositional, | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,21 @@ | ||
namespace Humanizer | ||
{ | ||
/// <summary> | ||
/// Options for specifying the desired grammatical gender for the output words | ||
/// </summary> | ||
public enum GrammaticalGender | ||
{ | ||
/// <summary> | ||
/// Indicates masculine grammatical gender | ||
/// </summary> | ||
Masculine, | ||
/// <summary> | ||
/// Indicates feminine grammatical gender | ||
/// </summary> | ||
Feminine, | ||
/// <summary> | ||
/// Indicates neuter grammatical gender | ||
/// </summary> | ||
Neuter | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,25 +1,23 @@ | ||
namespace Humanizer.Localisation.Formatters | ||
using Humanizer.Localisation.GrammaticalNumber; | ||
|
||
namespace Humanizer.Localisation.Formatters | ||
{ | ||
internal class RussianFormatter : DefaultFormatter | ||
{ | ||
private const string SingularPostfix = "_Singular"; | ||
private const string PaucalPostfix = "_Paucal"; | ||
|
||
protected override string GetResourceKey(string resourceKey, int number) | ||
{ | ||
var mod100 = number%100; | ||
if (mod100/10 != 1) | ||
{ | ||
var mod10 = number%10; | ||
|
||
if (mod10 == 1) // 1, 21, 31, 41 ... 91, 101, 121 .. | ||
return resourceKey + SingularPostfix; | ||
var grammaticalNumber = RussianGrammaticalNumberDetector.Detect(number); | ||
var suffix = GetSuffix(grammaticalNumber); | ||
return resourceKey + suffix; | ||
} | ||
|
||
if (mod10 > 1 && mod10 < 5) // 2, 3, 4, 22, 23, 24 ... | ||
return resourceKey + PaucalPostfix; | ||
} | ||
|
||
return resourceKey; | ||
private string GetSuffix(RussianGrammaticalNumber grammaticalNumber) | ||
{ | ||
if (grammaticalNumber == RussianGrammaticalNumber.Singular) | ||
return "_Singular"; | ||
if (grammaticalNumber == RussianGrammaticalNumber.Paucal) | ||
return "_Paucal"; | ||
return ""; | ||
} | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
|
||
namespace Humanizer.Localisation.GrammaticalNumber | ||
{ | ||
internal enum RussianGrammaticalNumber | ||
{ | ||
Singular, | ||
Paucal, | ||
Plural | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
namespace Humanizer.Localisation.GrammaticalNumber | ||
{ | ||
internal static class RussianGrammaticalNumberDetector | ||
{ | ||
public static RussianGrammaticalNumber Detect(int number) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Nice :) |
||
{ | ||
var tens = number % 100 / 10; | ||
if (tens != 1) | ||
{ | ||
var unity = number % 10; | ||
|
||
if (unity == 1) // 1, 21, 31, 41 ... 91, 101, 121 ... | ||
return RussianGrammaticalNumber.Singular; | ||
|
||
if (unity > 1 && unity < 5) // 2, 3, 4, 22, 23, 24 ... | ||
return RussianGrammaticalNumber.Paucal; | ||
} | ||
|
||
return RussianGrammaticalNumber.Plural; | ||
} | ||
} | ||
} |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,11 @@ | |
{ | ||
internal class DefaultNumberToWordsConverter : INumberToWordsConverter | ||
{ | ||
public virtual string Convert(int number, GrammaticalGender gender) | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, as mentioned above, this is unnecessary API change that would be good if we could avoid. |
||
{ | ||
return Convert(number); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is much neater. Thanks. |
||
} | ||
|
||
public virtual string Convert(int number) | ||
{ | ||
return number.ToString(); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -3,7 +3,7 @@ | |
/// <summary> | ||
/// An abstraction to convert number to words | ||
/// </summary> | ||
public interface INumberToWordsConverter | ||
internal interface INumberToWordsConverter | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Now I am wondering why we even need this interface anymore, as it could be a bit confusing. Keeping it there for now; but may drop it later. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, you're right it's the same as |
||
{ | ||
/// <summary> | ||
/// 3501.ToWords() -> "three thousand five hundred and one" | ||
|
@@ -12,6 +12,16 @@ public interface INumberToWordsConverter | |
/// <returns></returns> | ||
string Convert(int number); | ||
|
||
/// <summary> | ||
/// for Russian locale | ||
/// 1.ToWords(GrammaticalGender.Masculine) -> "один" | ||
/// 1.ToWords(GrammaticalGender.Feminine) -> "одна" | ||
/// </summary> | ||
/// <param name="number">Number to be turned to words</param> | ||
/// <param name="gender">The grammatical gender to use for output words</param> | ||
/// <returns></returns> | ||
string Convert(int number, GrammaticalGender gender); | ||
|
||
/// <summary> | ||
/// 1.ToOrdinalWords() -> "first" | ||
/// </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.
Thanks for this :)