From aff99acfaeb04f43bb8118eefdd030768ffc802a Mon Sep 17 00:00:00 2001 From: Ben Date: Wed, 12 Feb 2025 20:18:10 +0800 Subject: [PATCH 1/2] Fix #5054: resolve the issue in fa-IR language. --- .../ApplicationBuilderExtensions.cs | 9 +++ .../Localization/PersianCalendar.cs | 77 +++++++++++++++++++ .../Localization/PersianCulture.cs | 70 +++++++++++++++++ 3 files changed, 156 insertions(+) create mode 100644 Oqtane.Server/Infrastructure/Localization/PersianCalendar.cs create mode 100644 Oqtane.Server/Infrastructure/Localization/PersianCulture.cs diff --git a/Oqtane.Server/Extensions/ApplicationBuilderExtensions.cs b/Oqtane.Server/Extensions/ApplicationBuilderExtensions.cs index 3e466a20..87bf5305 100644 --- a/Oqtane.Server/Extensions/ApplicationBuilderExtensions.cs +++ b/Oqtane.Server/Extensions/ApplicationBuilderExtensions.cs @@ -34,6 +34,15 @@ namespace Oqtane.Extensions options.SetDefaultCulture(defaultCulture) .AddSupportedCultures(supportedCultures) .AddSupportedUICultures(supportedCultures); + + for (var i = 0; i < options.SupportedCultures.Count; i++) + { + if (options.SupportedCultures[i].Name.Equals("fa-IR", StringComparison.OrdinalIgnoreCase)) + { + options.SupportedCultures[i] = PersianCulture.GetPersianCultureInfo(); + break; + } + } }); return app; diff --git a/Oqtane.Server/Infrastructure/Localization/PersianCalendar.cs b/Oqtane.Server/Infrastructure/Localization/PersianCalendar.cs new file mode 100644 index 00000000..1b900031 --- /dev/null +++ b/Oqtane.Server/Infrastructure/Localization/PersianCalendar.cs @@ -0,0 +1,77 @@ +using System; + +namespace Oqtane.Infrastructure +{ + public class PersianCalendar : System.Globalization.PersianCalendar + { + public override int GetYear(DateTime time) + { + try + { + return base.GetYear(time); + } + catch + { + // ignore + } + + return time.Year; + } + + public override int GetMonth(DateTime time) + { + try + { + return base.GetMonth(time); + } + catch + { + // ignore + } + + return time.Month; + } + + public override int GetDayOfMonth(DateTime time) + { + try + { + return base.GetDayOfMonth(time); + } + catch + { + // ignore + } + + return time.Day; + } + + public override int GetDayOfYear(DateTime time) + { + try + { + return base.GetDayOfYear(time); + } + catch + { + // ignore + } + + return time.DayOfYear; + } + + public override DayOfWeek GetDayOfWeek(DateTime time) + { + try + { + return base.GetDayOfWeek(time); + } + catch + { + // ignore + } + + return time.DayOfWeek; + } + } +} diff --git a/Oqtane.Server/Infrastructure/Localization/PersianCulture.cs b/Oqtane.Server/Infrastructure/Localization/PersianCulture.cs new file mode 100644 index 00000000..addd73a2 --- /dev/null +++ b/Oqtane.Server/Infrastructure/Localization/PersianCulture.cs @@ -0,0 +1,70 @@ +using System; +using System.Globalization; +using System.Reflection; + +namespace Oqtane.Infrastructure +{ + public class PersianCulture + { + public static CultureInfo GetPersianCultureInfo() + { + var persianCultureInfo = new CultureInfo("fa-IR"); + + SetPersianDateTimeFormatInfo(persianCultureInfo.DateTimeFormat); + SetNumberFormatInfo(persianCultureInfo.NumberFormat); + + var cal = new PersianCalendar(); + + FieldInfo fieldInfo = persianCultureInfo.GetType().GetField("_calendar", BindingFlags.NonPublic | BindingFlags.Instance); + if (fieldInfo != null) + { + fieldInfo.SetValue(persianCultureInfo, cal); + } + + FieldInfo info = persianCultureInfo.DateTimeFormat.GetType().GetField("calendar", BindingFlags.NonPublic | BindingFlags.Instance); + if (info != null) + { + info.SetValue(persianCultureInfo.DateTimeFormat, cal); + } + + return persianCultureInfo; + } + + public static void SetPersianDateTimeFormatInfo(DateTimeFormatInfo persianDateTimeFormatInfo) + { + persianDateTimeFormatInfo.MonthNames = new[] { "فروردین", "اردیبهشت", "خرداد", "تیر", "مرداد", "شهریور", "مهر", "آبان", "آذر", "دی", "بهمن", "اسفند", string.Empty }; + persianDateTimeFormatInfo.MonthGenitiveNames = persianDateTimeFormatInfo.MonthNames; + persianDateTimeFormatInfo.AbbreviatedMonthNames = persianDateTimeFormatInfo.MonthNames; + persianDateTimeFormatInfo.AbbreviatedMonthGenitiveNames = persianDateTimeFormatInfo.MonthNames; + + persianDateTimeFormatInfo.DayNames = new[] { "یکشنبه", "دوشنبه", "ﺳﻪشنبه", "چهارشنبه", "پنجشنبه", "جمعه", "شنبه" }; + persianDateTimeFormatInfo.AbbreviatedDayNames = new[] { "ی", "د", "س", "چ", "پ", "ج", "ش" }; + persianDateTimeFormatInfo.ShortestDayNames = persianDateTimeFormatInfo.AbbreviatedDayNames; + persianDateTimeFormatInfo.FirstDayOfWeek = DayOfWeek.Saturday; + + persianDateTimeFormatInfo.AMDesignator = "ق.ظ"; + persianDateTimeFormatInfo.PMDesignator = "ب.ظ"; + + persianDateTimeFormatInfo.DateSeparator = "/"; + persianDateTimeFormatInfo.TimeSeparator = ":"; + + persianDateTimeFormatInfo.FullDateTimePattern = "tt hh:mm:ss yyyy mmmm dd dddd"; + persianDateTimeFormatInfo.YearMonthPattern = "yyyy, MMMM"; + persianDateTimeFormatInfo.MonthDayPattern = "dd MMMM"; + + persianDateTimeFormatInfo.LongDatePattern = "dddd, dd MMMM,yyyy"; + persianDateTimeFormatInfo.ShortDatePattern = "yyyy/MM/dd"; + + persianDateTimeFormatInfo.LongTimePattern = "hh:mm:ss tt"; + persianDateTimeFormatInfo.ShortTimePattern = "hh:mm tt"; + } + + public static void SetNumberFormatInfo(NumberFormatInfo persianNumberFormatInfo) + { + persianNumberFormatInfo.NumberDecimalSeparator = "/"; + persianNumberFormatInfo.DigitSubstitution = DigitShapes.NativeNational; + persianNumberFormatInfo.NumberNegativePattern = 0; + persianNumberFormatInfo.NegativeSign = "-"; + } + } +} From 94b03d2a6b97b02371e0ee32e819bfeae8626d49 Mon Sep 17 00:00:00 2001 From: Ben Date: Sun, 16 Feb 2025 10:25:43 +0800 Subject: [PATCH 2/2] update settings for all RTL languages. --- .../ApplicationBuilderExtensions.cs | 7 +- .../Localization/PersianCulture.cs | 70 ------------------- .../Localization/RightToLeftCulture.cs | 42 +++++++++++ ...endar.cs => RightToLeftCultureCalendar.cs} | 2 +- 4 files changed, 46 insertions(+), 75 deletions(-) delete mode 100644 Oqtane.Server/Infrastructure/Localization/PersianCulture.cs create mode 100644 Oqtane.Server/Infrastructure/Localization/RightToLeftCulture.cs rename Oqtane.Server/Infrastructure/Localization/{PersianCalendar.cs => RightToLeftCultureCalendar.cs} (94%) diff --git a/Oqtane.Server/Extensions/ApplicationBuilderExtensions.cs b/Oqtane.Server/Extensions/ApplicationBuilderExtensions.cs index 87bf5305..4225f0b8 100644 --- a/Oqtane.Server/Extensions/ApplicationBuilderExtensions.cs +++ b/Oqtane.Server/Extensions/ApplicationBuilderExtensions.cs @@ -35,12 +35,11 @@ namespace Oqtane.Extensions .AddSupportedCultures(supportedCultures) .AddSupportedUICultures(supportedCultures); - for (var i = 0; i < options.SupportedCultures.Count; i++) + foreach(var culture in options.SupportedCultures) { - if (options.SupportedCultures[i].Name.Equals("fa-IR", StringComparison.OrdinalIgnoreCase)) + if (culture.TextInfo.IsRightToLeft) { - options.SupportedCultures[i] = PersianCulture.GetPersianCultureInfo(); - break; + RightToLeftCulture.ResolveFormat(culture); } } }); diff --git a/Oqtane.Server/Infrastructure/Localization/PersianCulture.cs b/Oqtane.Server/Infrastructure/Localization/PersianCulture.cs deleted file mode 100644 index addd73a2..00000000 --- a/Oqtane.Server/Infrastructure/Localization/PersianCulture.cs +++ /dev/null @@ -1,70 +0,0 @@ -using System; -using System.Globalization; -using System.Reflection; - -namespace Oqtane.Infrastructure -{ - public class PersianCulture - { - public static CultureInfo GetPersianCultureInfo() - { - var persianCultureInfo = new CultureInfo("fa-IR"); - - SetPersianDateTimeFormatInfo(persianCultureInfo.DateTimeFormat); - SetNumberFormatInfo(persianCultureInfo.NumberFormat); - - var cal = new PersianCalendar(); - - FieldInfo fieldInfo = persianCultureInfo.GetType().GetField("_calendar", BindingFlags.NonPublic | BindingFlags.Instance); - if (fieldInfo != null) - { - fieldInfo.SetValue(persianCultureInfo, cal); - } - - FieldInfo info = persianCultureInfo.DateTimeFormat.GetType().GetField("calendar", BindingFlags.NonPublic | BindingFlags.Instance); - if (info != null) - { - info.SetValue(persianCultureInfo.DateTimeFormat, cal); - } - - return persianCultureInfo; - } - - public static void SetPersianDateTimeFormatInfo(DateTimeFormatInfo persianDateTimeFormatInfo) - { - persianDateTimeFormatInfo.MonthNames = new[] { "فروردین", "اردیبهشت", "خرداد", "تیر", "مرداد", "شهریور", "مهر", "آبان", "آذر", "دی", "بهمن", "اسفند", string.Empty }; - persianDateTimeFormatInfo.MonthGenitiveNames = persianDateTimeFormatInfo.MonthNames; - persianDateTimeFormatInfo.AbbreviatedMonthNames = persianDateTimeFormatInfo.MonthNames; - persianDateTimeFormatInfo.AbbreviatedMonthGenitiveNames = persianDateTimeFormatInfo.MonthNames; - - persianDateTimeFormatInfo.DayNames = new[] { "یکشنبه", "دوشنبه", "ﺳﻪشنبه", "چهارشنبه", "پنجشنبه", "جمعه", "شنبه" }; - persianDateTimeFormatInfo.AbbreviatedDayNames = new[] { "ی", "د", "س", "چ", "پ", "ج", "ش" }; - persianDateTimeFormatInfo.ShortestDayNames = persianDateTimeFormatInfo.AbbreviatedDayNames; - persianDateTimeFormatInfo.FirstDayOfWeek = DayOfWeek.Saturday; - - persianDateTimeFormatInfo.AMDesignator = "ق.ظ"; - persianDateTimeFormatInfo.PMDesignator = "ب.ظ"; - - persianDateTimeFormatInfo.DateSeparator = "/"; - persianDateTimeFormatInfo.TimeSeparator = ":"; - - persianDateTimeFormatInfo.FullDateTimePattern = "tt hh:mm:ss yyyy mmmm dd dddd"; - persianDateTimeFormatInfo.YearMonthPattern = "yyyy, MMMM"; - persianDateTimeFormatInfo.MonthDayPattern = "dd MMMM"; - - persianDateTimeFormatInfo.LongDatePattern = "dddd, dd MMMM,yyyy"; - persianDateTimeFormatInfo.ShortDatePattern = "yyyy/MM/dd"; - - persianDateTimeFormatInfo.LongTimePattern = "hh:mm:ss tt"; - persianDateTimeFormatInfo.ShortTimePattern = "hh:mm tt"; - } - - public static void SetNumberFormatInfo(NumberFormatInfo persianNumberFormatInfo) - { - persianNumberFormatInfo.NumberDecimalSeparator = "/"; - persianNumberFormatInfo.DigitSubstitution = DigitShapes.NativeNational; - persianNumberFormatInfo.NumberNegativePattern = 0; - persianNumberFormatInfo.NegativeSign = "-"; - } - } -} diff --git a/Oqtane.Server/Infrastructure/Localization/RightToLeftCulture.cs b/Oqtane.Server/Infrastructure/Localization/RightToLeftCulture.cs new file mode 100644 index 00000000..8d07220b --- /dev/null +++ b/Oqtane.Server/Infrastructure/Localization/RightToLeftCulture.cs @@ -0,0 +1,42 @@ +using System; +using System.Globalization; +using System.Reflection; + +namespace Oqtane.Infrastructure +{ + public class RightToLeftCulture + { + public static CultureInfo ResolveFormat(CultureInfo cultureInfo) + { + SetNumberFormatInfo(cultureInfo.NumberFormat); + SetCalenar(cultureInfo); + + return cultureInfo; + } + + private static void SetCalenar(CultureInfo cultureInfo) + { + var calendar = new RightToLeftCultureCalendar(); + + var fieldInfo = cultureInfo.GetType().GetField("_calendar", BindingFlags.NonPublic | BindingFlags.Instance); + if (fieldInfo != null) + { + fieldInfo.SetValue(cultureInfo, calendar); + } + + var info = cultureInfo.DateTimeFormat.GetType().GetField("calendar", BindingFlags.NonPublic | BindingFlags.Instance); + if (info != null) + { + info.SetValue(cultureInfo.DateTimeFormat, calendar); + } + } + + public static void SetNumberFormatInfo(NumberFormatInfo persianNumberFormatInfo) + { + persianNumberFormatInfo.NumberDecimalSeparator = "."; + persianNumberFormatInfo.DigitSubstitution = DigitShapes.NativeNational; + persianNumberFormatInfo.NumberNegativePattern = 0; + persianNumberFormatInfo.NegativeSign = "-"; + } + } +} diff --git a/Oqtane.Server/Infrastructure/Localization/PersianCalendar.cs b/Oqtane.Server/Infrastructure/Localization/RightToLeftCultureCalendar.cs similarity index 94% rename from Oqtane.Server/Infrastructure/Localization/PersianCalendar.cs rename to Oqtane.Server/Infrastructure/Localization/RightToLeftCultureCalendar.cs index 1b900031..56b420d9 100644 --- a/Oqtane.Server/Infrastructure/Localization/PersianCalendar.cs +++ b/Oqtane.Server/Infrastructure/Localization/RightToLeftCultureCalendar.cs @@ -2,7 +2,7 @@ using System; namespace Oqtane.Infrastructure { - public class PersianCalendar : System.Globalization.PersianCalendar + public class RightToLeftCultureCalendar : System.Globalization.PersianCalendar { public override int GetYear(DateTime time) {