From d2756b275b2e9d382cb53d208a717e8d23e5eddf Mon Sep 17 00:00:00 2001 From: Ahmed EL-Harouny Date: Tue, 7 Jan 2014 10:25:49 +1100 Subject: [PATCH 1/4] Add Arabic Formatter, resources for Arabic dual date units and unit tests for Arabic Date Humanize --- src/Humanizer.Tests/Humanizer.Tests.csproj | 1 + .../Localisation/ar/DateHumanizeTests.cs | 65 +++++++++++++++++++ .../Localisation/ar/TimeSpanTests.cs | 7 ++ src/Humanizer/Configuration/Configurator.cs | 3 +- src/Humanizer/Humanizer.csproj | 1 + src/Humanizer/Localisation/ArabicFormatter.cs | 16 +++++ src/Humanizer/Properties/Resources.ar.resx | 28 ++++++++ 7 files changed, 120 insertions(+), 1 deletion(-) create mode 100644 src/Humanizer.Tests/Localisation/ar/DateHumanizeTests.cs create mode 100644 src/Humanizer/Localisation/ArabicFormatter.cs diff --git a/src/Humanizer.Tests/Humanizer.Tests.csproj b/src/Humanizer.Tests/Humanizer.Tests.csproj index aaa08543a..bc0b22120 100644 --- a/src/Humanizer.Tests/Humanizer.Tests.csproj +++ b/src/Humanizer.Tests/Humanizer.Tests.csproj @@ -71,6 +71,7 @@ + diff --git a/src/Humanizer.Tests/Localisation/ar/DateHumanizeTests.cs b/src/Humanizer.Tests/Localisation/ar/DateHumanizeTests.cs new file mode 100644 index 000000000..396c24d04 --- /dev/null +++ b/src/Humanizer.Tests/Localisation/ar/DateHumanizeTests.cs @@ -0,0 +1,65 @@ +using System; +using Xunit; +using Xunit.Extensions; + +namespace Humanizer.Tests.Localisation.ar +{ + public class DateHumanizeTests : AmbientCulture + { + public DateHumanizeTests() : base("ar") { } + + [Theory] + [InlineData(-2, "منذ يومين")] + [InlineData(-1, "أمس")] + public void DaysAgo(int days, string expected) + { + Assert.Equal(expected, DateTime.UtcNow.AddDays(days).Humanize()); + } + + [Theory] + [InlineData(-2, "منذ ساعتين")] + [InlineData(-1, "منذ ساعة واحدة")] + public void HoursAgo(int hours, string expected) + { + Assert.Equal(expected, DateTime.UtcNow.AddHours(hours).Humanize()); + } + + [Theory] + [InlineData(-2, "منذ دقيقتين")] + [InlineData(-1, "منذ دقيقة واحدة")] + public void MinutesAgo(int minutes, string expected) + { + Assert.Equal(expected, DateTime.UtcNow.AddMinutes(minutes).Humanize()); + } + + [Theory] + [InlineData(-2, "منذ شهرين")] + [InlineData(-1, "منذ شهر واحد")] + public void MonthsAgo(int months, string expected) + { + Assert.Equal(expected, DateTime.UtcNow.AddMonths(months).Humanize()); + } + + [Theory] + [InlineData(-2, "منذ ثانيتين")] + [InlineData(-1, "منذ ثانية واحدة")] + public void SecondsAgo(int seconds, string expected) + { + Assert.Equal(expected, DateTime.UtcNow.AddSeconds(seconds).Humanize()); + } + + [Theory] + [InlineData(-2, "منذ سنتين")] + [InlineData(-1, "العام السابق")] + public void YearsAgo(int years, string expected) + { + Assert.Equal(expected, DateTime.UtcNow.AddYears(years).Humanize()); + } + + [Fact] + public void NotYet() + { + Assert.Equal("ليس بعد", DateTime.UtcNow.AddDays(1).Humanize()); + } + } +} diff --git a/src/Humanizer.Tests/Localisation/ar/TimeSpanTests.cs b/src/Humanizer.Tests/Localisation/ar/TimeSpanTests.cs index f86fbb301..a8b0f12a3 100644 --- a/src/Humanizer.Tests/Localisation/ar/TimeSpanTests.cs +++ b/src/Humanizer.Tests/Localisation/ar/TimeSpanTests.cs @@ -13,6 +13,13 @@ public void OneWeek() Assert.Equal("أسبوع واحد", TimeSpan.FromDays(7).Humanize()); } + [Fact] + public void TwoWeeks() + { + Assert.Equal("أسبوعين", TimeSpan.FromDays(14).Humanize()); + } + + [Fact] public void OneDay() { diff --git a/src/Humanizer/Configuration/Configurator.cs b/src/Humanizer/Configuration/Configurator.cs index aa3a838d2..463f8e889 100644 --- a/src/Humanizer/Configuration/Configurator.cs +++ b/src/Humanizer/Configuration/Configurator.cs @@ -14,7 +14,8 @@ public static class Configurator new Dictionary>(StringComparer.OrdinalIgnoreCase) { { "ro", () => new RomanianFormatter() }, - { "ru", () => new RussianFormatter() } + { "ru", () => new RussianFormatter() }, + { "ar", () => new ArabicFormatter() }, }; /// diff --git a/src/Humanizer/Humanizer.csproj b/src/Humanizer/Humanizer.csproj index e62b5864e..96decf244 100644 --- a/src/Humanizer/Humanizer.csproj +++ b/src/Humanizer/Humanizer.csproj @@ -82,6 +82,7 @@ True On.Days.tt + diff --git a/src/Humanizer/Localisation/ArabicFormatter.cs b/src/Humanizer/Localisation/ArabicFormatter.cs new file mode 100644 index 000000000..d9002fd42 --- /dev/null +++ b/src/Humanizer/Localisation/ArabicFormatter.cs @@ -0,0 +1,16 @@ +namespace Humanizer.Localisation +{ + internal class ArabicFormatter : DefaultFormatter + { + private const string DualPostfix = "_Dual"; + + protected override string GetResourceKey(string resourceKey, int number) + { + if (number == 2) + { + return resourceKey + DualPostfix; + } + return resourceKey; + } + } +} diff --git a/src/Humanizer/Properties/Resources.ar.resx b/src/Humanizer/Properties/Resources.ar.resx index b0ffcc3dc..5aeff289f 100644 --- a/src/Humanizer/Properties/Resources.ar.resx +++ b/src/Humanizer/Properties/Resources.ar.resx @@ -197,4 +197,32 @@ حالاً no time + + منذ يومين + two days ago + + + منذ ساعتين + two hours ago + + + منذ دقيقتين + two minutes ago + + + منذ شهرين + two months ago + + + منذ ثانيتين + two seconds ago + + + منذ سنتين + two years ago + + + أسبوعين + two weeks + \ No newline at end of file From 63f61761f5d302c33e1b5b3d9485633d8acb2031 Mon Sep 17 00:00:00 2001 From: Ahmed EL-Harouny Date: Tue, 7 Jan 2014 10:58:24 +1100 Subject: [PATCH 2/4] Add Arabic localization for dual time span units --- .../Localisation/ar/TimeSpanTests.cs | 56 +++++++++++-------- src/Humanizer/Properties/Resources.ar.resx | 20 +++++++ 2 files changed, 52 insertions(+), 24 deletions(-) diff --git a/src/Humanizer.Tests/Localisation/ar/TimeSpanTests.cs b/src/Humanizer.Tests/Localisation/ar/TimeSpanTests.cs index a8b0f12a3..547a92192 100644 --- a/src/Humanizer.Tests/Localisation/ar/TimeSpanTests.cs +++ b/src/Humanizer.Tests/Localisation/ar/TimeSpanTests.cs @@ -1,5 +1,6 @@ using System; using Xunit; +using Xunit.Extensions; namespace Humanizer.Tests.Localisation.ar { @@ -7,47 +8,54 @@ public class TimeSpanHumanizeExtensionsTests : AmbientCulture { public TimeSpanHumanizeExtensionsTests() : base("ar") { } - [Fact] - public void OneWeek() - { - Assert.Equal("أسبوع واحد", TimeSpan.FromDays(7).Humanize()); - } - - [Fact] - public void TwoWeeks() + [Theory] + [InlineData(7, "أسبوع واحد")] + [InlineData(14, "أسبوعين")] + public void Weeks(int days, string expected) { - Assert.Equal("أسبوعين", TimeSpan.FromDays(14).Humanize()); + Assert.Equal(expected, TimeSpan.FromDays(days).Humanize()); } - [Fact] - public void OneDay() + [Theory] + [InlineData(1, "يوم واحد")] + [InlineData(2, "يومين")] + public void Days(int days, string expected) { - Assert.Equal("يوم واحد", TimeSpan.FromDays(1).Humanize()); + Assert.Equal(expected, TimeSpan.FromDays(days).Humanize()); } - [Fact] - public void OneHour() + [Theory] + [InlineData(1, "ساعة واحدة")] + [InlineData(2, "ساعتين")] + public void Hours(int hours, string expected) { - Assert.Equal("ساعة واحدة", TimeSpan.FromHours(1).Humanize()); + Assert.Equal(expected, TimeSpan.FromHours(hours).Humanize()); } - [Fact] - public void OneMinute() + [Theory] + [InlineData(1, "دقيقة واحدة")] + [InlineData(2, "دقيقتين")] + public void Minutes(int minutes, string expected) { - Assert.Equal("دقيقة واحدة", TimeSpan.FromMinutes(1).Humanize()); + Assert.Equal(expected, TimeSpan.FromMinutes(minutes).Humanize()); } - [Fact] - public void OneSecond() + + [Theory] + [InlineData(1, "ثانية واحدة")] + [InlineData(2, "ثانيتين")] + public void Seconds(int seconds, string expected) { - Assert.Equal("ثانية واحدة", TimeSpan.FromSeconds(1).Humanize()); + Assert.Equal(expected, TimeSpan.FromSeconds(seconds).Humanize()); } - [Fact] - public void OneMillisecond() + [Theory] + [InlineData(1, "جزء من الثانية")] + [InlineData(2, "جزئين من الثانية")] + public void Milliseconds(int milliseconds, string expected) { - Assert.Equal("جزء من الثانية", TimeSpan.FromMilliseconds(1).Humanize()); + Assert.Equal(expected, TimeSpan.FromMilliseconds(milliseconds).Humanize()); } [Fact] diff --git a/src/Humanizer/Properties/Resources.ar.resx b/src/Humanizer/Properties/Resources.ar.resx index 5aeff289f..2439663a1 100644 --- a/src/Humanizer/Properties/Resources.ar.resx +++ b/src/Humanizer/Properties/Resources.ar.resx @@ -225,4 +225,24 @@ أسبوعين two weeks + + يومين + two days + + + ساعتين + two hours + + + جزئين من الثانية + two milliseconds + + + دقيقتين + two minutes + + + ثانيتين + two seconds + \ No newline at end of file From 4bfe27b33a4051aea9745f0f4e4ffd576cd6d8ed Mon Sep 17 00:00:00 2001 From: Ahmed EL-Harouny Date: Wed, 8 Jan 2014 12:22:54 +1100 Subject: [PATCH 3/4] Fixing a review issue - codebase convention --- src/Humanizer/Localisation/ArabicFormatter.cs | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/Humanizer/Localisation/ArabicFormatter.cs b/src/Humanizer/Localisation/ArabicFormatter.cs index d9002fd42..3f48bccd8 100644 --- a/src/Humanizer/Localisation/ArabicFormatter.cs +++ b/src/Humanizer/Localisation/ArabicFormatter.cs @@ -7,9 +7,8 @@ internal class ArabicFormatter : DefaultFormatter protected override string GetResourceKey(string resourceKey, int number) { if (number == 2) - { return resourceKey + DualPostfix; - } + return resourceKey; } } From 711e270deafd8717ad92239865d1a7bf73949911 Mon Sep 17 00:00:00 2001 From: Ahmed EL-Harouny Date: Thu, 9 Jan 2014 23:19:19 +1100 Subject: [PATCH 4/4] Add Arabic (more than 2) units support for TimeSpan and DateHumanize --- .../Localisation/ar/DateHumanizeTests.cs | 17 +++- .../Localisation/ar/TimeSpanTests.cs | 11 +++ src/Humanizer/Localisation/ArabicFormatter.cs | 6 ++ src/Humanizer/Properties/Resources.ar.resx | 86 +++++++++++++++++-- 4 files changed, 111 insertions(+), 9 deletions(-) diff --git a/src/Humanizer.Tests/Localisation/ar/DateHumanizeTests.cs b/src/Humanizer.Tests/Localisation/ar/DateHumanizeTests.cs index 396c24d04..e5670ea82 100644 --- a/src/Humanizer.Tests/Localisation/ar/DateHumanizeTests.cs +++ b/src/Humanizer.Tests/Localisation/ar/DateHumanizeTests.cs @@ -8,9 +8,12 @@ public class DateHumanizeTests : AmbientCulture { public DateHumanizeTests() : base("ar") { } + [Theory] - [InlineData(-2, "منذ يومين")] [InlineData(-1, "أمس")] + [InlineData(-2, "منذ يومين")] + [InlineData(-3, "منذ 3 أيام")] + [InlineData(-11, "منذ 11 يوم")] public void DaysAgo(int days, string expected) { Assert.Equal(expected, DateTime.UtcNow.AddDays(days).Humanize()); @@ -19,6 +22,8 @@ public void DaysAgo(int days, string expected) [Theory] [InlineData(-2, "منذ ساعتين")] [InlineData(-1, "منذ ساعة واحدة")] + [InlineData(-3, "منذ 3 ساعات")] + [InlineData(-11, "منذ 11 ساعة")] public void HoursAgo(int hours, string expected) { Assert.Equal(expected, DateTime.UtcNow.AddHours(hours).Humanize()); @@ -27,6 +32,8 @@ public void HoursAgo(int hours, string expected) [Theory] [InlineData(-2, "منذ دقيقتين")] [InlineData(-1, "منذ دقيقة واحدة")] + [InlineData(-3, "منذ 3 دقائق")] + [InlineData(-11, "منذ 11 دقيقة")] public void MinutesAgo(int minutes, string expected) { Assert.Equal(expected, DateTime.UtcNow.AddMinutes(minutes).Humanize()); @@ -35,6 +42,8 @@ public void MinutesAgo(int minutes, string expected) [Theory] [InlineData(-2, "منذ شهرين")] [InlineData(-1, "منذ شهر واحد")] + [InlineData(-3, "منذ 3 أشهر")] + [InlineData(-11, "منذ 11 شهر")] public void MonthsAgo(int months, string expected) { Assert.Equal(expected, DateTime.UtcNow.AddMonths(months).Humanize()); @@ -43,14 +52,18 @@ public void MonthsAgo(int months, string expected) [Theory] [InlineData(-2, "منذ ثانيتين")] [InlineData(-1, "منذ ثانية واحدة")] + [InlineData(-3, "منذ 3 ثوان")] + [InlineData(-11, "منذ 11 ثانية")] public void SecondsAgo(int seconds, string expected) { Assert.Equal(expected, DateTime.UtcNow.AddSeconds(seconds).Humanize()); } [Theory] - [InlineData(-2, "منذ سنتين")] + [InlineData(-2, "منذ عامين")] [InlineData(-1, "العام السابق")] + [InlineData(-3, "منذ 3 أعوام")] + [InlineData(-11, "منذ 11 عام")] public void YearsAgo(int years, string expected) { Assert.Equal(expected, DateTime.UtcNow.AddYears(years).Humanize()); diff --git a/src/Humanizer.Tests/Localisation/ar/TimeSpanTests.cs b/src/Humanizer.Tests/Localisation/ar/TimeSpanTests.cs index 547a92192..a4b73fd1f 100644 --- a/src/Humanizer.Tests/Localisation/ar/TimeSpanTests.cs +++ b/src/Humanizer.Tests/Localisation/ar/TimeSpanTests.cs @@ -11,6 +11,8 @@ public TimeSpanHumanizeExtensionsTests() : base("ar") { } [Theory] [InlineData(7, "أسبوع واحد")] [InlineData(14, "أسبوعين")] + [InlineData(21, "3 أسابيع")] + [InlineData(77, "11 أسبوع")] public void Weeks(int days, string expected) { Assert.Equal(expected, TimeSpan.FromDays(days).Humanize()); @@ -20,6 +22,7 @@ public void Weeks(int days, string expected) [Theory] [InlineData(1, "يوم واحد")] [InlineData(2, "يومين")] + [InlineData(3, "3 أيام")] public void Days(int days, string expected) { Assert.Equal(expected, TimeSpan.FromDays(days).Humanize()); @@ -28,6 +31,8 @@ public void Days(int days, string expected) [Theory] [InlineData(1, "ساعة واحدة")] [InlineData(2, "ساعتين")] + [InlineData(3, "3 ساعات")] + [InlineData(11, "11 ساعة")] public void Hours(int hours, string expected) { Assert.Equal(expected, TimeSpan.FromHours(hours).Humanize()); @@ -36,6 +41,8 @@ public void Hours(int hours, string expected) [Theory] [InlineData(1, "دقيقة واحدة")] [InlineData(2, "دقيقتين")] + [InlineData(3, "3 دقائق")] + [InlineData(11, "11 دقيقة")] public void Minutes(int minutes, string expected) { Assert.Equal(expected, TimeSpan.FromMinutes(minutes).Humanize()); @@ -45,6 +52,8 @@ public void Minutes(int minutes, string expected) [Theory] [InlineData(1, "ثانية واحدة")] [InlineData(2, "ثانيتين")] + [InlineData(3, "3 ثوان")] + [InlineData(11, "11 ثانية")] public void Seconds(int seconds, string expected) { Assert.Equal(expected, TimeSpan.FromSeconds(seconds).Humanize()); @@ -53,6 +62,8 @@ public void Seconds(int seconds, string expected) [Theory] [InlineData(1, "جزء من الثانية")] [InlineData(2, "جزئين من الثانية")] + [InlineData(3, "3 أجزاء من الثانية")] + [InlineData(11, "11 جزء من الثانية")] public void Milliseconds(int milliseconds, string expected) { Assert.Equal(expected, TimeSpan.FromMilliseconds(milliseconds).Humanize()); diff --git a/src/Humanizer/Localisation/ArabicFormatter.cs b/src/Humanizer/Localisation/ArabicFormatter.cs index 3f48bccd8..44081c622 100644 --- a/src/Humanizer/Localisation/ArabicFormatter.cs +++ b/src/Humanizer/Localisation/ArabicFormatter.cs @@ -3,12 +3,18 @@ internal class ArabicFormatter : DefaultFormatter { private const string DualPostfix = "_Dual"; + private const string PluralPostfix = "_Plural"; protected override string GetResourceKey(string resourceKey, int number) { + //In Arabic pluralization 2 entities gets a different word. if (number == 2) return resourceKey + DualPostfix; + //In Arabic pluralization entities where the count is between 3 and 10 gets a different word. + if (number >= 3 && number <= 10 ) + return resourceKey + PluralPostfix; + return resourceKey; } } diff --git a/src/Humanizer/Properties/Resources.ar.resx b/src/Humanizer/Properties/Resources.ar.resx index 2439663a1..8a69e9931 100644 --- a/src/Humanizer/Properties/Resources.ar.resx +++ b/src/Humanizer/Properties/Resources.ar.resx @@ -126,7 +126,7 @@ one second ago - منذ {0} ثوان + منذ {0} ثانية {0} seconds ago @@ -134,7 +134,7 @@ a minute ago - منذ {0} دقائق + منذ {0} دقيقة {0} minutes ago @@ -142,7 +142,7 @@ an hour ago - منذ {0} ساعات + منذ {0} ساعة {0} hours ago @@ -150,7 +150,7 @@ yesterday - منذ {0} أيام + منذ {0} يوم {0} days ago @@ -158,7 +158,7 @@ one month ago - منذ {0} أشهر + منذ {0} شهر {0} months ago @@ -166,7 +166,7 @@ one year ago - منذ {0} سنوات + منذ {0} عام {0} years ago @@ -218,7 +218,7 @@ two seconds ago - منذ سنتين + منذ عامين two years ago @@ -245,4 +245,76 @@ ثانيتين two seconds + + {0} يوم + {0} days + + + {0} أيام + {0} days + + + {0} ساعة + {0} hours + + + {0} ساعات + {0} hours + + + {0} جزء من الثانية + {0} milliseconds + + + {0} أجزاء من الثانية + {0} milliseconds + + + {0} دقيقة + {0} minutes + + + {0} دقائق + {0} minutes + + + {0} ثانية + {0} seconds + + + {0} ثوان + {0} seconds + + + {0} أسبوع + {0} weeks + + + {0} أسابيع + {0} weeks + + + منذ {0} أيام + {0} days ago + + + منذ {0} ساعات + {0} hours ago + + + منذ {0} دقائق + {0} minutes ago + + + منذ {0} أشهر + {0} months ago + + + منذ {0} ثوان + {0} seconds ago + + + منذ {0} أعوام + {0} years ago + \ No newline at end of file