diff --git a/release_notes.md b/release_notes.md
index 18274410a..41ca0e28e 100644
--- a/release_notes.md
+++ b/release_notes.md
@@ -1,6 +1,7 @@
###In Development
[Commits](https://github.com/MehdiK/Humanizer/compare/v1.35.0...master)
+ - [#414](https://github.com/MehdiK/Humanizer/pull/414): Add Ukraininan language
###v1.35.0 - 2015-03-29
- [#399](https://github.com/MehdiK/Humanizer/pull/399): Added support for humanizing DateTimeOffset
diff --git a/src/Humanizer.Tests/Humanizer.Tests.csproj b/src/Humanizer.Tests/Humanizer.Tests.csproj
index 2e9aa81c0..9e869e501 100644
--- a/src/Humanizer.Tests/Humanizer.Tests.csproj
+++ b/src/Humanizer.Tests/Humanizer.Tests.csproj
@@ -140,6 +140,10 @@
+
+
+
+
diff --git a/src/Humanizer.Tests/Localisation/uk-UA/DateHumanizeTests.cs b/src/Humanizer.Tests/Localisation/uk-UA/DateHumanizeTests.cs
new file mode 100644
index 000000000..78145369b
--- /dev/null
+++ b/src/Humanizer.Tests/Localisation/uk-UA/DateHumanizeTests.cs
@@ -0,0 +1,258 @@
+using Humanizer.Localisation;
+using Xunit;
+using Xunit.Extensions;
+
+namespace Humanizer.Tests.Localisation.ukUA
+{
+ public class DateHumanizeTests : AmbientCulture
+ {
+ public DateHumanizeTests()
+ : base("uk-UA")
+ {
+ }
+
+ [Theory]
+ [InlineData(1, "секунду тому")]
+ [InlineData(2, "2 секунди тому")]
+ [InlineData(3, "3 секунди тому")]
+ [InlineData(4, "4 секунди тому")]
+ [InlineData(5, "5 секунд тому")]
+ [InlineData(6, "6 секунд тому")]
+ [InlineData(10, "10 секунд тому")]
+ [InlineData(11, "11 секунд тому")]
+ [InlineData(19, "19 секунд тому")]
+ [InlineData(20, "20 секунд тому")]
+ [InlineData(21, "21 секунду тому")]
+ [InlineData(22, "22 секунди тому")]
+ [InlineData(23, "23 секунди тому")]
+ [InlineData(24, "24 секунди тому")]
+ [InlineData(25, "25 секунд тому")]
+ [InlineData(40, "40 секунд тому")]
+ public void SecondsAgo(int seconds, string expected)
+ {
+ DateHumanize.Verify(expected, seconds, TimeUnit.Second, Tense.Past);
+ }
+
+ [Theory]
+ [InlineData(1, "через секунду")]
+ [InlineData(2, "через 2 секунди")]
+ [InlineData(3, "через 3 секунди")]
+ [InlineData(4, "через 4 секунди")]
+ [InlineData(5, "через 5 секунд")]
+ [InlineData(6, "через 6 секунд")]
+ [InlineData(10, "через 10 секунд")]
+ [InlineData(11, "через 11 секунд")]
+ [InlineData(19, "через 19 секунд")]
+ [InlineData(20, "через 20 секунд")]
+ [InlineData(21, "через 21 секунду")]
+ [InlineData(22, "через 22 секунди")]
+ [InlineData(23, "через 23 секунди")]
+ [InlineData(24, "через 24 секунди")]
+ [InlineData(25, "через 25 секунд")]
+ [InlineData(40, "через 40 секунд")]
+ public void SecondsFromNow(int seconds, string expected)
+ {
+ DateHumanize.Verify(expected, seconds, TimeUnit.Second, Tense.Future);
+ }
+
+ [Theory]
+ [InlineData(1, "хвилину тому")]
+ [InlineData(2, "2 хвилини тому")]
+ [InlineData(3, "3 хвилини тому")]
+ [InlineData(4, "4 хвилини тому")]
+ [InlineData(5, "5 хвилин тому")]
+ [InlineData(6, "6 хвилин тому")]
+ [InlineData(10, "10 хвилин тому")]
+ [InlineData(11, "11 хвилин тому")]
+ [InlineData(19, "19 хвилин тому")]
+ [InlineData(20, "20 хвилин тому")]
+ [InlineData(21, "21 хвилину тому")]
+ [InlineData(22, "22 хвилини тому")]
+ [InlineData(23, "23 хвилини тому")]
+ [InlineData(24, "24 хвилини тому")]
+ [InlineData(25, "25 хвилин тому")]
+ [InlineData(40, "40 хвилин тому")]
+ [InlineData(60, "годину тому")]
+ public void MinutesAgo(int minutes, string expected)
+ {
+ DateHumanize.Verify(expected, minutes, TimeUnit.Minute, Tense.Past);
+ }
+
+ [Theory]
+ [InlineData(1, "через хвилину")]
+ [InlineData(2, "через 2 хвилини")]
+ [InlineData(3, "через 3 хвилини")]
+ [InlineData(4, "через 4 хвилини")]
+ [InlineData(5, "через 5 хвилин")]
+ [InlineData(6, "через 6 хвилин")]
+ [InlineData(10, "через 10 хвилин")]
+ [InlineData(11, "через 11 хвилин")]
+ [InlineData(19, "через 19 хвилин")]
+ [InlineData(20, "через 20 хвилин")]
+ [InlineData(21, "через 21 хвилину")]
+ [InlineData(22, "через 22 хвилини")]
+ [InlineData(23, "через 23 хвилини")]
+ [InlineData(24, "через 24 хвилини")]
+ [InlineData(25, "через 25 хвилин")]
+ [InlineData(40, "через 40 хвилин")]
+ public void MinutesFromNow(int minutes, string expected)
+ {
+ DateHumanize.Verify(expected, minutes, TimeUnit.Minute, Tense.Future);
+ }
+
+ [Theory]
+ [InlineData(1, "годину тому")]
+ [InlineData(2, "2 години тому")]
+ [InlineData(3, "3 години тому")]
+ [InlineData(4, "4 години тому")]
+ [InlineData(5, "5 годин тому")]
+ [InlineData(6, "6 годин тому")]
+ [InlineData(10, "10 годин тому")]
+ [InlineData(11, "11 годин тому")]
+ [InlineData(19, "19 годин тому")]
+ [InlineData(20, "20 годин тому")]
+ [InlineData(21, "21 годину тому")]
+ [InlineData(22, "22 години тому")]
+ [InlineData(23, "23 години тому")]
+ public void HoursAgo(int hours, string expected)
+ {
+ DateHumanize.Verify(expected, hours, TimeUnit.Hour, Tense.Past);
+ }
+
+ [Theory]
+ [InlineData(1, "через годину")]
+ [InlineData(2, "через 2 години")]
+ [InlineData(3, "через 3 години")]
+ [InlineData(4, "через 4 години")]
+ [InlineData(5, "через 5 годин")]
+ [InlineData(6, "через 6 годин")]
+ [InlineData(10, "через 10 годин")]
+ [InlineData(11, "через 11 годин")]
+ [InlineData(19, "через 19 годин")]
+ [InlineData(20, "через 20 годин")]
+ [InlineData(21, "через 21 годину")]
+ [InlineData(22, "через 22 години")]
+ [InlineData(23, "через 23 години")]
+ public void HoursFromNow(int hours, string expected)
+ {
+ DateHumanize.Verify(expected, hours, TimeUnit.Hour, Tense.Future);
+ }
+
+ [Theory]
+ [InlineData(1, "вчора")]
+ [InlineData(2, "2 дні тому")]
+ [InlineData(3, "3 дні тому")]
+ [InlineData(4, "4 дні тому")]
+ [InlineData(5, "5 днів тому")]
+ [InlineData(6, "6 днів тому")]
+ [InlineData(10, "10 днів тому")]
+ [InlineData(11, "11 днів тому")]
+ [InlineData(19, "19 днів тому")]
+ [InlineData(20, "20 днів тому")]
+ [InlineData(21, "21 день тому")]
+ [InlineData(22, "22 дні тому")]
+ [InlineData(23, "23 дні тому")]
+ [InlineData(24, "24 дні тому")]
+ [InlineData(25, "25 днів тому")]
+ public void DaysAgo(int days, string expected)
+ {
+ DateHumanize.Verify(expected, days, TimeUnit.Day, Tense.Past);
+ }
+
+ [Theory]
+ [InlineData(1, "завтра")]
+ [InlineData(2, "через 2 дні")]
+ [InlineData(3, "через 3 дні")]
+ [InlineData(4, "через 4 дні")]
+ [InlineData(5, "через 5 днів")]
+ [InlineData(6, "через 6 днів")]
+ [InlineData(10, "через 10 днів")]
+ [InlineData(11, "через 11 днів")]
+ [InlineData(19, "через 19 днів")]
+ [InlineData(20, "через 20 днів")]
+ [InlineData(21, "через 21 день")]
+ [InlineData(22, "через 22 дні")]
+ [InlineData(23, "через 23 дні")]
+ [InlineData(24, "через 24 дні")]
+ [InlineData(25, "через 25 днів")]
+ public void DaysFromNow(int days, string expected)
+ {
+ DateHumanize.Verify(expected, days, TimeUnit.Day, Tense.Future);
+ }
+
+ [Theory]
+ [InlineData(1, "місяць тому")]
+ [InlineData(2, "2 місяці тому")]
+ [InlineData(3, "3 місяці тому")]
+ [InlineData(4, "4 місяці тому")]
+ [InlineData(5, "5 місяців тому")]
+ [InlineData(6, "6 місяців тому")]
+ [InlineData(10, "10 місяців тому")]
+ [InlineData(11, "11 місяців тому")]
+ public void MonthsAgo(int months, string expected)
+ {
+ DateHumanize.Verify(expected, months, TimeUnit.Month, Tense.Past);
+ }
+
+ [Theory]
+ [InlineData(1, "через місяць")]
+ [InlineData(2, "через 2 місяці")]
+ [InlineData(3, "через 3 місяці")]
+ [InlineData(4, "через 4 місяці")]
+ [InlineData(5, "через 5 місяців")]
+ [InlineData(6, "через 6 місяців")]
+ [InlineData(10, "через 10 місяців")]
+ [InlineData(11, "через 11 місяців")]
+ public void MonthsFromNow(int months, string expected)
+ {
+ DateHumanize.Verify(expected, months, TimeUnit.Month, Tense.Future);
+ }
+
+ [Theory]
+ [InlineData(1, "рік тому")]
+ [InlineData(2, "2 роки тому")]
+ [InlineData(3, "3 роки тому")]
+ [InlineData(4, "4 роки тому")]
+ [InlineData(5, "5 років тому")]
+ [InlineData(6, "6 років тому")]
+ [InlineData(10, "10 років тому")]
+ [InlineData(11, "11 років тому")]
+ [InlineData(19, "19 років тому")]
+ [InlineData(21, "21 рік тому")]
+ [InlineData(111, "111 років тому")]
+ [InlineData(121, "121 рік тому")]
+ [InlineData(222, "222 роки тому")]
+ [InlineData(325, "325 років тому")]
+ public void YearsAgo(int years, string expected)
+ {
+ DateHumanize.Verify(expected, years, TimeUnit.Year, Tense.Past);
+ }
+
+ [Theory]
+ [InlineData(1, "через рік")]
+ [InlineData(2, "через 2 роки")]
+ [InlineData(3, "через 3 роки")]
+ [InlineData(4, "через 4 роки")]
+ [InlineData(5, "через 5 років")]
+ [InlineData(6, "через 6 років")]
+ [InlineData(10, "через 10 років")]
+ [InlineData(11, "через 11 років")]
+ [InlineData(19, "через 19 років")]
+ [InlineData(20, "через 20 років")]
+ [InlineData(21, "через 21 рік")]
+ [InlineData(111, "через 111 років")]
+ [InlineData(121, "через 121 рік")]
+ [InlineData(222, "через 222 роки")]
+ [InlineData(325, "через 325 років")]
+ 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);
+ }
+ }
+}
diff --git a/src/Humanizer.Tests/Localisation/uk-UA/NumberToWordsTests.cs b/src/Humanizer.Tests/Localisation/uk-UA/NumberToWordsTests.cs
new file mode 100644
index 000000000..011b1c75b
--- /dev/null
+++ b/src/Humanizer.Tests/Localisation/uk-UA/NumberToWordsTests.cs
@@ -0,0 +1,241 @@
+using Xunit;
+using Xunit.Extensions;
+
+namespace Humanizer.Tests.Localisation.ukUA
+{
+ public class NumberToWordsTests : AmbientCulture
+ {
+ public NumberToWordsTests()
+ : base("uk-UA")
+ {
+ }
+
+ [Theory]
+ [InlineData(0, "нуль")]
+ [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));
+ }
+
+ [Theory]
+ [InlineData(0, "нульовий")]
+ [InlineData(1, "перший")]
+ [InlineData(2, "другий")]
+ [InlineData(3, "третій")]
+ [InlineData(4, "четвертий")]
+ [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(101, "сто перший")]
+ [InlineData(140, "сто сороковий")]
+ [InlineData(200, "двохсотий")]
+ [InlineData(300, "трьохсотий")]
+ [InlineData(400, "чотирьохсотий")]
+ [InlineData(500, "п'ятисотий")]
+ [InlineData(600, "шестисотий")]
+ [InlineData(700, "семисотий")]
+ [InlineData(800, "восьмисотий")]
+ [InlineData(900, "дев'ятисотий")]
+ [InlineData(1000, "тисячний")]
+ [InlineData(1001, "одна тисяча перший")]
+ [InlineData(1040, "одна тисяча сороковий")]
+ [InlineData(2000, "двохтисячний")]
+ [InlineData(3000, "трьохтисячний")]
+ [InlineData(4000, "чотирьохтисячний")]
+ [InlineData(5000, "п'ятитисячний")]
+ [InlineData(10000, "десятитисячний")]
+ [InlineData(21000, "двадцятиоднотисячний")]
+ [InlineData(100000, "стотисячний")]
+ [InlineData(101000, "стооднотисячний")]
+ [InlineData(121000, "стодвадцятиоднотисячний")]
+ [InlineData(200000, "двохсоттисячний")]
+ [InlineData(1000000, "мільйонний")]
+ [InlineData(2000000, "двохмільйонний")]
+ [InlineData(10000000, "десятимільйонний")]
+ [InlineData(21000000, "двадцятиодномільйонний")]
+ [InlineData(100000000, "стомільйонний")]
+ [InlineData(230000000, "двохсоттридцятимільйонний")]
+ [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(1111111000, "один мільярд сто одинадцять мільйонів стоодинадцятитисячний")]
+ [InlineData(1234567000, "один мільярд двісті тридцять чотири мільйона п'ятисотшістдесятисемитисячний")]
+ [InlineData(2000000000, "двохмільярдний")]
+ [InlineData(-751633617, "мінус сімсот п'ятдесят один мільйон шістсот тридцять три тисячі шістсот сімнадцятий")]
+ public void ToOrdinalWords(int number, string expected)
+ {
+ Assert.Equal(expected, number.ToOrdinalWords());
+ }
+
+ [Theory]
+ [InlineData(0, "нульова")]
+ [InlineData(1, "перша")]
+ [InlineData(2, "друга")]
+ [InlineData(3, "третя")]
+ [InlineData(4, "четверта")]
+ [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(90000, "дев'яностотисячна")]
+ [InlineData(100000, "стотисячна")]
+ [InlineData(990000, "дев'ятисотдев'яностотисячна")]
+ [InlineData(990001, "дев'ятсот дев'яносто тисяч перша")]
+ [InlineData(1000000, "мільйонна")]
+ [InlineData(2000000, "двохмільйонна")]
+ [InlineData(10000000, "десятимільйонна")]
+ [InlineData(100000000, "стомільйонна")]
+ [InlineData(1000000000, "мільярдна")]
+ [InlineData(2000000000, "двохмільярдна")]
+ [InlineData(122, "сто двадцять друга")]
+ [InlineData(3501, "три тисячі п'ятсот перша")]
+ [InlineData(111, "сто одинадцята")]
+ [InlineData(1112, "одна тисяча сто дванадцята")]
+ [InlineData(11000, "одинадцятитисячна")]
+ [InlineData(11001, "одинадцять тисяч перша")]
+ [InlineData(11213, "одинадцять тисяч двісті тринадцята")]
+ [InlineData(15000, "п'ятнадцятитисячна")]
+ [InlineData(20000, "двадцятитисячна")]
+ [InlineData(121314, "сто двадцять одна тисяча триста чотирнадцята")]
+ [InlineData(2132415, "два мільйона сто тридцять дві тисячі чотириста п'ятнадцята")]
+ [InlineData(12345516, "дванадцять мільйонів триста сорок п'ять тисяч п'ятсот шістнадцята")]
+ [InlineData(751633617, "сімсот п'ятдесят один мільйон шістсот тридцять три тисячі шістсот сімнадцята")]
+ [InlineData(1111111118, "один мільярд сто одинадцять мільйонів сто одинадцять тисяч сто вісімнадцята")]
+ [InlineData(-751633617, "мінус сімсот п'ятдесят один мільйон шістсот тридцять три тисячі шістсот сімнадцята")]
+ public void ToOrdinalWordsFeminine(int number, string expected)
+ {
+ Assert.Equal(expected, number.ToOrdinalWords(GrammaticalGender.Feminine));
+ }
+
+ [Theory]
+ [InlineData(3, "третє")]
+ [InlineData(111, "сто одинадцяте")]
+ [InlineData(1112, "одна тисяча сто дванадцяте")]
+ [InlineData(11213, "одинадцять тисяч двісті тринадцяте")]
+ [InlineData(121314, "сто двадцять одна тисяча триста чотирнадцяте")]
+ [InlineData(2132415, "два мільйона сто тридцять дві тисячі чотириста п'ятнадцяте")]
+ [InlineData(12345516, "дванадцять мільйонів триста сорок п'ять тисяч п'ятсот шістнадцяте")]
+ [InlineData(751633617, "сімсот п'ятдесят один мільйон шістсот тридцять три тисячі шістсот сімнадцяте")]
+ [InlineData(1111111118, "один мільярд сто одинадцять мільйонів сто одинадцять тисяч сто вісімнадцяте")]
+ [InlineData(-751633617, "мінус сімсот п'ятдесят один мільйон шістсот тридцять три тисячі шістсот сімнадцяте")]
+ public void ToOrdinalWordsNeuter(int number, string expected)
+ {
+ Assert.Equal(expected, number.ToOrdinalWords(GrammaticalGender.Neuter));
+ }
+ }
+}
diff --git a/src/Humanizer.Tests/Localisation/uk-UA/OrdinalizeTests.cs b/src/Humanizer.Tests/Localisation/uk-UA/OrdinalizeTests.cs
new file mode 100644
index 000000000..cac60d7d3
--- /dev/null
+++ b/src/Humanizer.Tests/Localisation/uk-UA/OrdinalizeTests.cs
@@ -0,0 +1,129 @@
+using Xunit;
+using Xunit.Extensions;
+
+namespace Humanizer.Tests.Localisation.ukUA
+{
+ public class OrdinalizeTests : AmbientCulture
+ {
+ public OrdinalizeTests()
+ : base("uk-UA")
+ {
+ }
+
+ [Theory]
+ [InlineData("0", "0-й")]
+ [InlineData("1", "1-й")]
+ [InlineData("2", "2-й")]
+ [InlineData("3", "3-й")]
+ [InlineData("4", "4-й")]
+ [InlineData("5", "5-й")]
+ [InlineData("6", "6-й")]
+ [InlineData("23", "23-й")]
+ [InlineData("100", "100-й")]
+ [InlineData("101", "101-й")]
+ [InlineData("102", "102-й")]
+ [InlineData("103", "103-й")]
+ [InlineData("1001", "1001-й")]
+ public void OrdinalizeString(string number, string ordinalized)
+ {
+ Assert.Equal(number.Ordinalize(GrammaticalGender.Masculine), ordinalized);
+ }
+
+ [Theory]
+ [InlineData("0", "0-а")]
+ [InlineData("1", "1-а")]
+ [InlineData("2", "2-а")]
+ [InlineData("3", "3-я")]
+ [InlineData("4", "4-а")]
+ [InlineData("5", "5-а")]
+ [InlineData("6", "6-а")]
+ [InlineData("23", "23-я")]
+ [InlineData("100", "100-а")]
+ [InlineData("101", "101-а")]
+ [InlineData("102", "102-а")]
+ [InlineData("103", "103-я")]
+ [InlineData("1001", "1001-а")]
+ public void OrdinalizeStringFeminine(string number, string ordinalized)
+ {
+ Assert.Equal(number.Ordinalize(GrammaticalGender.Feminine), ordinalized);
+ }
+
+ [Theory]
+ [InlineData("0", "0-е")]
+ [InlineData("1", "1-е")]
+ [InlineData("2", "2-е")]
+ [InlineData("3", "3-є")]
+ [InlineData("4", "4-е")]
+ [InlineData("5", "5-е")]
+ [InlineData("6", "6-е")]
+ [InlineData("23", "23-є")]
+ [InlineData("100", "100-е")]
+ [InlineData("101", "101-е")]
+ [InlineData("102", "102-е")]
+ [InlineData("103", "103-є")]
+ [InlineData("1001", "1001-е")]
+ public void OrdinalizeStringNeuter(string number, string ordinalized)
+ {
+ Assert.Equal(number.Ordinalize(GrammaticalGender.Neuter), ordinalized);
+ }
+
+ [Theory]
+ [InlineData(0, "0-й")]
+ [InlineData(1, "1-й")]
+ [InlineData(2, "2-й")]
+ [InlineData(3, "3-й")]
+ [InlineData(4, "4-й")]
+ [InlineData(5, "5-й")]
+ [InlineData(6, "6-й")]
+ [InlineData(10, "10-й")]
+ [InlineData(23, "23-й")]
+ [InlineData(100, "100-й")]
+ [InlineData(101, "101-й")]
+ [InlineData(102, "102-й")]
+ [InlineData(103, "103-й")]
+ [InlineData(1001, "1001-й")]
+ public void OrdinalizeNumber(int number, string ordinalized)
+ {
+ Assert.Equal(number.Ordinalize(GrammaticalGender.Masculine), ordinalized);
+ }
+
+ [Theory]
+ [InlineData(0, "0-а")]
+ [InlineData(1, "1-а")]
+ [InlineData(2, "2-а")]
+ [InlineData(3, "3-я")]
+ [InlineData(4, "4-а")]
+ [InlineData(5, "5-а")]
+ [InlineData(6, "6-а")]
+ [InlineData(10, "10-а")]
+ [InlineData(23, "23-я")]
+ [InlineData(100, "100-а")]
+ [InlineData(101, "101-а")]
+ [InlineData(102, "102-а")]
+ [InlineData(103, "103-я")]
+ [InlineData(1001, "1001-а")]
+ public void OrdinalizeNumberFeminine(int number, string ordinalized)
+ {
+ Assert.Equal(number.Ordinalize(GrammaticalGender.Feminine), ordinalized);
+ }
+
+ [Theory]
+ [InlineData(0, "0-е")]
+ [InlineData(1, "1-е")]
+ [InlineData(2, "2-е")]
+ [InlineData(3, "3-є")]
+ [InlineData(4, "4-е")]
+ [InlineData(5, "5-е")]
+ [InlineData(6, "6-е")]
+ [InlineData(23, "23-є")]
+ [InlineData(100, "100-е")]
+ [InlineData(101, "101-е")]
+ [InlineData(102, "102-е")]
+ [InlineData(103, "103-є")]
+ [InlineData(1001, "1001-е")]
+ public void OrdinalizeNumberNeuter(int number, string ordinalized)
+ {
+ Assert.Equal(number.Ordinalize(GrammaticalGender.Neuter), ordinalized);
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Humanizer.Tests/Localisation/uk-UA/TimeSpanHumanizeTests.cs b/src/Humanizer.Tests/Localisation/uk-UA/TimeSpanHumanizeTests.cs
new file mode 100644
index 000000000..cf9806bc3
--- /dev/null
+++ b/src/Humanizer.Tests/Localisation/uk-UA/TimeSpanHumanizeTests.cs
@@ -0,0 +1,129 @@
+using System;
+using Xunit;
+using Xunit.Extensions;
+
+namespace Humanizer.Tests.Localisation.ukUA
+{
+ public class TimeSpanHumanizeTests : AmbientCulture
+ {
+ public TimeSpanHumanizeTests()
+ : base("uk-UA")
+ {
+ }
+
+ [Theory]
+ [InlineData(7, "один тиждень")]
+ [InlineData(14, "2 тижні")]
+ [InlineData(21, "3 тижні")]
+ [InlineData(28, "4 тижні")]
+ [InlineData(35, "5 тижнів")]
+ [InlineData(77, "11 тижнів")]
+ public void Weeks(int days, string expected)
+ {
+ Assert.Equal(expected, TimeSpan.FromDays(days).Humanize());
+ }
+
+ [Theory]
+ [InlineData(1, "один день")]
+ [InlineData(2, "2 дні")]
+ [InlineData(3, "3 дні")]
+ [InlineData(4, "4 дні")]
+ [InlineData(5, "5 днів")]
+ [InlineData(6, "6 днів")]
+ public void Days(int days, string expected)
+ {
+ Assert.Equal(expected, TimeSpan.FromDays(days).Humanize());
+ }
+
+ [Theory]
+ [InlineData(1, "одна година")]
+ [InlineData(2, "2 години")]
+ [InlineData(3, "3 години")]
+ [InlineData(4, "4 години")]
+ [InlineData(5, "5 годин")]
+ [InlineData(6, "6 годин")]
+ [InlineData(10, "10 годин")]
+ [InlineData(11, "11 годин")]
+ [InlineData(19, "19 годин")]
+ [InlineData(20, "20 годин")]
+ [InlineData(21, "21 година")]
+ [InlineData(22, "22 години")]
+ [InlineData(23, "23 години")]
+ public void Hours(int hours, string expected)
+ {
+ Assert.Equal(expected, TimeSpan.FromHours(hours).Humanize());
+ }
+
+ [Theory]
+ [InlineData(1, "одна хвилина")]
+ [InlineData(2, "2 хвилини")]
+ [InlineData(3, "3 хвилини")]
+ [InlineData(4, "4 хвилини")]
+ [InlineData(5, "5 хвилин")]
+ [InlineData(6, "6 хвилин")]
+ [InlineData(10, "10 хвилин")]
+ [InlineData(11, "11 хвилин")]
+ [InlineData(19, "19 хвилин")]
+ [InlineData(20, "20 хвилин")]
+ [InlineData(21, "21 хвилина")]
+ [InlineData(22, "22 хвилини")]
+ [InlineData(23, "23 хвилини")]
+ [InlineData(24, "24 хвилини")]
+ [InlineData(25, "25 хвилин")]
+ [InlineData(40, "40 хвилин")]
+ public void Minutes(int minutes, string expected)
+ {
+ Assert.Equal(expected, TimeSpan.FromMinutes(minutes).Humanize());
+ }
+
+ [Theory]
+ [InlineData(1, "одна секунда")]
+ [InlineData(2, "2 секунди")]
+ [InlineData(3, "3 секунди")]
+ [InlineData(4, "4 секунди")]
+ [InlineData(5, "5 секунд")]
+ [InlineData(6, "6 секунд")]
+ [InlineData(10, "10 секунд")]
+ [InlineData(11, "11 секунд")]
+ [InlineData(19, "19 секунд")]
+ [InlineData(20, "20 секунд")]
+ [InlineData(21, "21 секунда")]
+ [InlineData(22, "22 секунди")]
+ [InlineData(23, "23 секунди")]
+ [InlineData(24, "24 секунди")]
+ [InlineData(25, "25 секунд")]
+ [InlineData(40, "40 секунд")]
+ public void Seconds(int seconds, string expected)
+ {
+ Assert.Equal(expected, TimeSpan.FromSeconds(seconds).Humanize());
+ }
+
+ [Theory]
+ [InlineData(1, "одна мілісекунда")]
+ [InlineData(2, "2 мілісекунди")]
+ [InlineData(3, "3 мілісекунди")]
+ [InlineData(4, "4 мілісекунди")]
+ [InlineData(5, "5 мілісекунд")]
+ [InlineData(6, "6 мілісекунд")]
+ [InlineData(10, "10 мілісекунд")]
+ [InlineData(11, "11 мілісекунд")]
+ [InlineData(19, "19 мілісекунд")]
+ [InlineData(20, "20 мілісекунд")]
+ [InlineData(21, "21 мілісекунда")]
+ [InlineData(22, "22 мілісекунди")]
+ [InlineData(23, "23 мілісекунди")]
+ [InlineData(24, "24 мілісекунди")]
+ [InlineData(25, "25 мілісекунд")]
+ [InlineData(40, "40 мілісекунд")]
+ public void Milliseconds(int milliseconds, string expected)
+ {
+ Assert.Equal(expected, TimeSpan.FromMilliseconds(milliseconds).Humanize());
+ }
+
+ [Fact]
+ public void NoTime()
+ {
+ Assert.Equal("без часу", TimeSpan.Zero.Humanize());
+ }
+ }
+}
diff --git a/src/Humanizer/Configuration/FormatterRegistry.cs b/src/Humanizer/Configuration/FormatterRegistry.cs
index 59f296d81..4c0552eb3 100644
--- a/src/Humanizer/Configuration/FormatterRegistry.cs
+++ b/src/Humanizer/Configuration/FormatterRegistry.cs
@@ -13,6 +13,7 @@ public FormatterRegistry() : base(new DefaultFormatter("en-US"))
Register("sl", new SlovenianFormatter());
Register("sr", new SerbianFormatter("sr"));
Register("sr-Latn", new SerbianFormatter("sr-Latn"));
+ Register("uk", new UkrainianFormatter());
RegisterCzechSlovakPolishFormatter("cs");
RegisterCzechSlovakPolishFormatter("pl");
RegisterCzechSlovakPolishFormatter("sk");
diff --git a/src/Humanizer/Configuration/NumberToWordsConverterRegistry.cs b/src/Humanizer/Configuration/NumberToWordsConverterRegistry.cs
index 16e0e9a7b..bd45d0271 100644
--- a/src/Humanizer/Configuration/NumberToWordsConverterRegistry.cs
+++ b/src/Humanizer/Configuration/NumberToWordsConverterRegistry.cs
@@ -21,6 +21,7 @@ internal class NumberToWordsConverterRegistry : LocaliserRegistry
+
@@ -98,6 +99,7 @@
+
@@ -110,6 +112,7 @@
+
@@ -185,6 +188,7 @@
+
diff --git a/src/Humanizer/Localisation/Formatters/UkrainianFormatter.cs b/src/Humanizer/Localisation/Formatters/UkrainianFormatter.cs
new file mode 100644
index 000000000..23d2e102b
--- /dev/null
+++ b/src/Humanizer/Localisation/Formatters/UkrainianFormatter.cs
@@ -0,0 +1,28 @@
+using Humanizer.Localisation.GrammaticalNumber;
+
+namespace Humanizer.Localisation.Formatters
+{
+ internal class UkrainianFormatter : DefaultFormatter
+ {
+ public UkrainianFormatter()
+ : base("uk")
+ {
+ }
+
+ protected override string GetResourceKey(string resourceKey, int number)
+ {
+ var grammaticalNumber = RussianGrammaticalNumberDetector.Detect(number);
+ var suffix = GetSuffix(grammaticalNumber);
+ return resourceKey + suffix;
+ }
+
+ private string GetSuffix(RussianGrammaticalNumber grammaticalNumber)
+ {
+ if (grammaticalNumber == RussianGrammaticalNumber.Singular)
+ return "_Singular";
+ if (grammaticalNumber == RussianGrammaticalNumber.Paucal)
+ return "_Paucal";
+ return "";
+ }
+ }
+}
\ No newline at end of file
diff --git a/src/Humanizer/Localisation/NumberToWords/UkrainianNumberToWordsConverter.cs b/src/Humanizer/Localisation/NumberToWords/UkrainianNumberToWordsConverter.cs
new file mode 100644
index 000000000..8473421a9
--- /dev/null
+++ b/src/Humanizer/Localisation/NumberToWords/UkrainianNumberToWordsConverter.cs
@@ -0,0 +1,209 @@
+using System;
+using System.Collections.Generic;
+using Humanizer.Localisation.GrammaticalNumber;
+
+namespace Humanizer.Localisation.NumberToWords
+{
+ internal class UkrainianNumberToWordsConverter : GenderedNumberToWordsConverter
+ {
+ private static readonly string[] HundredsMap = { "нуль", "сто", "двісті", "триста", "чотириста", "п'ятсот", "шістсот", "сімсот", "вісімсот", "дев'ятсот" };
+ private static readonly string[] TensMap = { "нуль", "десять", "двадцять", "тридцять", "сорок", "п'ятдесят", "шістдесят", "сімдесят", "вісімдесят", "дев'яносто" };
+ private static readonly string[] UnitsMap = { "нуль", "один", "два", "три", "чотири", "п'ять", "шість", "сім", "вісім", "дев'ять", "десять", "одинадцять", "дванадцять", "тринадцять", "чотирнадцять", "п'ятнадцять", "шістнадцять", "сімнадцять", "вісімнадцять", "дев'ятнадцять" };
+ private static readonly string[] UnitsOrdinalPrefixes = { string.Empty, string.Empty, "двох", "трьох", "чотирьох", "п'яти", "шести", "семи", "восьми", "дев'яти", "десяти", "одинадцяти", "дванадцяти", "тринадцяти", "чотирнадцяти", "п'ятнадцяти", "шістнадцяти", "сімнадцяти", "вісімнадцяти", "дев'ятнадцяти", "двадцяти" };
+ private static readonly string[] TensOrdinalPrefixes = { string.Empty, "десяти", "двадцяти", "тридцяти", "сорока", "п'ятдесяти", "шістдесяти", "сімдесяти", "вісімдесяти", "дев'яносто" };
+ private static readonly string[] TensOrdinal = { string.Empty, "десят", "двадцят", "тридцят", "сороков", "п'ятдесят", "шістдесят", "сімдесят", "вісімдесят", "дев'яност" };
+ private static readonly string[] UnitsOrdinal = { "нульов", "перш", "друг", "трет", "четверт", "п'ят", "шост", "сьом", "восьм", "дев'ят", "десят", "одинадцят", "дванадцят", "тринадцят", "чотирнадцят", "п'ятнадцят", "шістнадцят", "сімнадцят", "вісімнадцят", "дев'ятнадцят" };
+
+ public override string Convert(int number, GrammaticalGender gender)
+ {
+ if (number == 0)
+ return "нуль";
+
+ var parts = new List();
+
+ if (number < 0)
+ {
+ parts.Add("мінус");
+ number = -number;
+ }
+
+ CollectParts(parts, ref number, 1000000000, GrammaticalGender.Masculine, "мільярд", "мільярда", "мільярдів");
+ CollectParts(parts, ref number, 1000000, GrammaticalGender.Masculine, "мільйон", "мільйона", "мільйонів");
+ CollectParts(parts, ref number, 1000, GrammaticalGender.Feminine, "тисяча", "тисячі", "тисяч");
+
+ if (number > 0)
+ CollectPartsUnderOneThousand(parts, number, gender);
+
+ return string.Join(" ", parts);
+ }
+
+ public override string ConvertToOrdinal(int number, GrammaticalGender gender)
+ {
+ if (number == 0)
+ return "нульов" + GetEndingForGender(gender, number);
+
+ var parts = new List();
+
+ if (number < 0)
+ {
+ parts.Add("мінус");
+ number = -number;
+ }
+
+ CollectOrdinalParts(parts, ref number, 1000000000, GrammaticalGender.Masculine, "мільярдн" + GetEndingForGender(gender, number), "мільярд", "мільярда", "мільярдів");
+ CollectOrdinalParts(parts, ref number, 1000000, GrammaticalGender.Masculine, "мільйонн" + GetEndingForGender(gender, number), "мільйон", "мільйона", "мільйонів");
+ CollectOrdinalParts(parts, ref number, 1000, GrammaticalGender.Feminine, "тисячн" + GetEndingForGender(gender, number), "тисяча", "тисячі", "тисяч");
+
+ if (number >= 100)
+ {
+ var ending = GetEndingForGender(gender, number);
+ var hundreds = number/100;
+ number %= 100;
+ if (number == 0)
+ parts.Add(UnitsOrdinalPrefixes[hundreds] + "сот" + ending);
+ else
+ parts.Add(HundredsMap[hundreds]);
+ }
+
+ if (number >= 20)
+ {
+ var ending = GetEndingForGender(gender, number);
+ var tens = number/10;
+ number %= 10;
+ if (number == 0)
+ parts.Add(TensOrdinal[tens] + ending);
+ else
+ parts.Add(TensMap[tens]);
+ }
+
+ if (number > 0)
+ parts.Add(UnitsOrdinal[number] + GetEndingForGender(gender, number));
+
+ return string.Join(" ", parts);
+ }
+
+ private static void CollectPartsUnderOneThousand(ICollection parts, int number, GrammaticalGender gender)
+ {
+ if (number >= 100)
+ {
+ var hundreds = number/100;
+ number %= 100;
+ parts.Add(HundredsMap[hundreds]);
+ }
+
+ if (number >= 20)
+ {
+ var tens = number/10;
+ parts.Add(TensMap[tens]);
+ number %= 10;
+ }
+
+ if (number > 0)
+ {
+ if (number == 1 && gender == GrammaticalGender.Feminine)
+ parts.Add("одна");
+ else if (number == 1 && gender == GrammaticalGender.Neuter)
+ parts.Add("одне");
+ else if (number == 2 && gender == GrammaticalGender.Feminine)
+ parts.Add("дві");
+ else if (number < 20)
+ parts.Add(UnitsMap[number]);
+ }
+ }
+
+ private static string GetPrefix(int number)
+ {
+ var parts = new List();
+
+ if (number >= 100)
+ {
+ var hundreds = number/100;
+ number %= 100;
+ if (hundreds != 1)
+ parts.Add(UnitsOrdinalPrefixes[hundreds] + "сот");
+ else
+ parts.Add("сто");
+ }
+
+ if (number >= 20)
+ {
+ var tens = number/10;
+ number %= 10;
+ parts.Add(TensOrdinalPrefixes[tens]);
+ }
+
+ if (number > 0)
+ {
+ parts.Add(number == 1 ? "одно" : UnitsOrdinalPrefixes[number]);
+ }
+
+ return string.Join("", parts);
+ }
+
+ private static void CollectParts(ICollection parts, ref int number, int divisor, GrammaticalGender gender, params string[] forms)
+ {
+ if (number < divisor) return;
+ var result = number/divisor;
+ number %= divisor;
+
+ CollectPartsUnderOneThousand(parts, result, gender);
+ parts.Add(ChooseOneForGrammaticalNumber(result, forms));
+ }
+
+ private static void CollectOrdinalParts(ICollection parts, ref int number, int divisor, GrammaticalGender gender, string prefixedForm, params string[] forms)
+ {
+ if (number < divisor) return;
+ var result = number/divisor;
+ number %= divisor;
+ if (number == 0)
+ {
+ if (result == 1)
+ parts.Add(prefixedForm);
+ else
+ parts.Add(GetPrefix(result) + prefixedForm);
+ }
+ else
+ {
+ CollectPartsUnderOneThousand(parts, result, gender);
+ parts.Add(ChooseOneForGrammaticalNumber(result, forms));
+ }
+ }
+
+ private static int GetIndex(RussianGrammaticalNumber number)
+ {
+ if (number == RussianGrammaticalNumber.Singular)
+ return 0;
+
+ if (number == RussianGrammaticalNumber.Paucal)
+ return 1;
+
+ return 2;
+ }
+
+ private static string ChooseOneForGrammaticalNumber(int number, string[] forms)
+ {
+ return forms[GetIndex(RussianGrammaticalNumberDetector.Detect(number))];
+ }
+
+ private static string GetEndingForGender(GrammaticalGender gender, int number)
+ {
+ switch (gender)
+ {
+ case GrammaticalGender.Masculine:
+ if (number == 3)
+ return "ій";
+ return "ий";
+ case GrammaticalGender.Feminine:
+ if (number == 3)
+ return "я";
+ return "а";
+ case GrammaticalGender.Neuter:
+ if (number == 3)
+ return "є";
+ return "е";
+ default:
+ throw new ArgumentOutOfRangeException("gender");
+ }
+ }
+ }
+}
diff --git a/src/Humanizer/Localisation/Ordinalizers/UkrainianOrdinalizer.cs b/src/Humanizer/Localisation/Ordinalizers/UkrainianOrdinalizer.cs
new file mode 100644
index 000000000..64990ea9c
--- /dev/null
+++ b/src/Humanizer/Localisation/Ordinalizers/UkrainianOrdinalizer.cs
@@ -0,0 +1,30 @@
+namespace Humanizer.Localisation.Ordinalizers
+{
+ internal class UkrainianOrdinalizer : DefaultOrdinalizer
+ {
+ public override string Convert(int number, string numberString)
+ {
+ return Convert(number, numberString, GrammaticalGender.Masculine);
+ }
+
+ public override string Convert(int number, string numberString, GrammaticalGender gender)
+ {
+
+ if (gender == GrammaticalGender.Masculine)
+ return numberString + "-й";
+
+ if (gender == GrammaticalGender.Feminine)
+ {
+ if (number % 10 == 3)
+ return numberString + "-я";
+ return numberString + "-а";
+ }
+
+ if (gender == GrammaticalGender.Neuter)
+ if (number % 10 == 3)
+ return numberString + "-є";
+
+ return numberString + "-е";
+ }
+ }
+}
diff --git a/src/Humanizer/Properties/Resources.uk.resx b/src/Humanizer/Properties/Resources.uk.resx
new file mode 100644
index 000000000..dc3481968
--- /dev/null
+++ b/src/Humanizer/Properties/Resources.uk.resx
@@ -0,0 +1,342 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ text/microsoft-resx
+
+
+ 2.0
+
+
+ System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089
+
+
+ секунду тому
+
+
+ хвилину тому
+
+
+ годину тому
+
+
+ вчора
+
+
+ місяць тому
+
+
+ рік тому
+
+
+ {0} день тому
+
+
+ {0} годин тому
+
+
+ {0} хвилин тому
+
+
+ {0} місяців тому
+
+
+ {0} секунд тому
+
+
+ {0} років тому
+
+
+ {0} днів тому
+
+
+ {0} дні тому
+
+
+ {0} години тому
+
+
+ {0} годину тому
+
+
+ {0} хвилини тому
+
+
+ {0} хвилину тому
+
+
+ {0} місяці тому
+
+
+ {0} місяць тому
+
+
+ {0} секунди тому
+
+
+ {0} секунду тому
+
+
+ {0} роки тому
+
+
+ {0} рік тому
+
+
+ зараз
+
+
+ {0} днів
+
+
+ {0} дні
+
+
+ {0} день
+
+
+ {0} годин
+
+
+ {0} години
+
+
+ {0} година
+
+
+ {0} мілісекунд
+
+
+ {0} мілісекунди
+
+
+ {0} мілісекунда
+
+
+ {0} хвилин
+
+
+ {0} хвилини
+
+
+ {0} хвилина
+
+
+ {0} секунд
+
+
+ {0} секунди
+
+
+ {0} секунда
+
+
+ {0} тижнів
+
+
+ {0} тижні
+
+
+ {0} тиждень
+
+
+ один день
+
+
+ одна година
+
+
+ одна мілісекунда
+
+
+ одна хвилина
+
+
+ одна секунда
+
+
+ один тиждень
+
+
+ без часу
+
+
+ через {0} днів
+
+
+ через {0} дні
+
+
+ через {0} день
+
+
+ через {0} годин
+
+
+ через {0} години
+
+
+ через {0} годину
+
+
+ через {0} хвилин
+
+
+ через {0} хвилини
+
+
+ через {0} хвилину
+
+
+ через {0} місяців
+
+
+ через {0} місяці
+
+
+ через {0} місяць
+
+
+ через {0} секунд
+
+
+ через {0} секунди
+
+
+ через {0} секунду
+
+
+ через {0} років
+
+
+ через {0} роки
+
+
+ через {0} рік
+
+
+ завтра
+
+
+ через годину
+
+
+ через хвилину
+
+
+ через місяць
+
+
+ через секунду
+
+
+ через рік
+
+