From 7ba8cfd3b25f4bcdbf11eb6006520e9e2918d76d Mon Sep 17 00:00:00 2001 From: Teesofttech Date: Tue, 23 Jun 2026 06:46:04 +0100 Subject: [PATCH] Add six localized cron languages --- CronCraft.Test/CronHelperTest.cs | 87 ++++++++++++ CronCraft/Extensions/CronHelper.cs | 179 +++++++++++++++++++++---- CronCraft/Models/CronSettings.cs | 3 +- CronCraft/Providers/DayNameProvider.cs | 66 +++++++++ CronCraft/README.md | 6 + README.md | 6 + 6 files changed, 321 insertions(+), 26 deletions(-) diff --git a/CronCraft.Test/CronHelperTest.cs b/CronCraft.Test/CronHelperTest.cs index 2b79849..66c8ffd 100644 --- a/CronCraft.Test/CronHelperTest.cs +++ b/CronCraft.Test/CronHelperTest.cs @@ -358,4 +358,91 @@ public void Test_Hash_QuartzSixPart_FirstTuesday() string result = CronHelper.ToHumanReadable("0 0 9 ? * 3#1", settings); Assert.AreEqual("Every first Tuesday of the month at 09:00 AM", result); } + + [DataTestMethod] + [DataRow("*/5 * * * *", "short", "Alle 5 Minuten")] + [DataRow("0 */2 * * *", "short", "Alle 2 Stunden")] + [DataRow("0 9 * * 1", "full", "Jeden Montag um 09:00 Uhr")] + [DataRow("0 9 * * 1", "short", "Jeden Mo um 09:00 Uhr")] + [DataRow("0 9 * * 1", "single", "Jeden M um 09:00 Uhr")] + [DataRow("0 9 15 * *", "short", "Jeden Monat am 15. um 09:00 Uhr")] + public void Test_GermanLocalization(string cron, string dayNameFormat, string expected) + { + AssertLocalized("de", cron, dayNameFormat, expected); + } + + [DataTestMethod] + [DataRow("*/5 * * * *", "short", "A cada 5 minutos")] + [DataRow("0 */2 * * *", "short", "A cada 2 horas")] + [DataRow("0 9 * * 1", "full", "Em Segunda-feira às 09:00")] + [DataRow("0 9 * * 1", "short", "Em Seg às 09:00")] + [DataRow("0 9 * * 1", "single", "Em S às 09:00")] + [DataRow("0 9 15 * *", "short", "Todo mês no dia 15º às 09:00")] + public void Test_PortugueseLocalization(string cron, string dayNameFormat, string expected) + { + AssertLocalized("pt", cron, dayNameFormat, expected); + } + + [DataTestMethod] + [DataRow("*/5 * * * *", "short", "Ogni 5 minuti")] + [DataRow("0 */2 * * *", "short", "Ogni 2 ore")] + [DataRow("0 9 * * 1", "full", "Ogni Lunedì alle 09:00")] + [DataRow("0 9 * * 1", "short", "Ogni Lun alle 09:00")] + [DataRow("0 9 * * 1", "single", "Ogni L alle 09:00")] + [DataRow("0 9 15 * *", "short", "Ogni mese il giorno 15 alle 09:00")] + public void Test_ItalianLocalization(string cron, string dayNameFormat, string expected) + { + AssertLocalized("it", cron, dayNameFormat, expected); + } + + [DataTestMethod] + [DataRow("*/5 * * * *", "short", "Elke 5 minuten")] + [DataRow("0 */2 * * *", "short", "Elke 2 uur")] + [DataRow("0 9 * * 1", "full", "Elke Maandag om 09:00")] + [DataRow("0 9 * * 1", "short", "Elke Ma om 09:00")] + [DataRow("0 9 * * 1", "single", "Elke M om 09:00")] + [DataRow("0 9 15 * *", "short", "Elke maand op de 15e om 09:00")] + public void Test_DutchLocalization(string cron, string dayNameFormat, string expected) + { + AssertLocalized("nl", cron, dayNameFormat, expected); + } + + [DataTestMethod] + [DataRow("*/5 * * * *", "short", "每 5 分钟")] + [DataRow("0 */2 * * *", "short", "每 2 小时")] + [DataRow("0 9 * * 1", "full", "每星期一 09:00")] + [DataRow("0 9 * * 1", "short", "每周一 09:00")] + [DataRow("0 9 * * 1", "single", "每一 09:00")] + [DataRow("0 9 15 * *", "short", "每月第 15 天 09:00")] + public void Test_ChineseLocalization(string cron, string dayNameFormat, string expected) + { + AssertLocalized("zh", cron, dayNameFormat, expected); + } + + [DataTestMethod] + [DataRow("*/5 * * * *", "short", "5分ごと")] + [DataRow("0 */2 * * *", "short", "2時間ごと")] + [DataRow("0 9 * * 1", "full", "毎週月曜日 09:00に")] + [DataRow("0 9 * * 1", "short", "毎週月曜 09:00に")] + [DataRow("0 9 * * 1", "single", "毎週月 09:00に")] + [DataRow("0 9 15 * *", "short", "毎月15日 09:00に")] + public void Test_JapaneseLocalization(string cron, string dayNameFormat, string expected) + { + AssertLocalized("ja", cron, dayNameFormat, expected); + } + + private static void AssertLocalized( + string language, + string cron, + string dayNameFormat, + string expected) + { + var settings = new CronSettings + { + Language = language, + DayNameFormat = dayNameFormat + }; + + Assert.AreEqual(expected, CronHelper.ToHumanReadable(cron, settings)); + } } diff --git a/CronCraft/Extensions/CronHelper.cs b/CronCraft/Extensions/CronHelper.cs index be137cb..3540346 100644 --- a/CronCraft/Extensions/CronHelper.cs +++ b/CronCraft/Extensions/CronHelper.cs @@ -24,6 +24,12 @@ public static string ToHumanReadable(this string cronExpression, CronSettings se { "es" => ToHumanReadableSpanish(cronExpression, settings, timeZone), "fr" => ToHumanReadableFrench(cronExpression, settings, timeZone), + "de" => ToHumanReadableGerman(cronExpression, settings, timeZone), + "pt" => ToHumanReadablePortuguese(cronExpression, settings, timeZone), + "it" => ToHumanReadableItalian(cronExpression, settings, timeZone), + "nl" => ToHumanReadableDutch(cronExpression, settings, timeZone), + "zh" => ToHumanReadableChinese(cronExpression, settings, timeZone), + "ja" => ToHumanReadableJapanese(cronExpression, settings, timeZone), _ => ToHumanReadableEnglish(cronExpression, settings, timeZone) }; } @@ -38,7 +44,10 @@ private static string ToHumanReadableEnglish(string cron, CronSettings settings, ["EveryXHours"] = "Every {0} hours", ["EveryXHoursOn"] = "Every {0} hours on {1}", ["EveryMonthOnDay"] = "Every month on the {0}", - ["OnDayAndWeek"] = "On {0} and {1}" + ["OnDayAndWeek"] = "On {0} and {1}", + ["EveryDayOfWeek"] = "Every {0}", + ["EveryXMonthsOnDay"] = "Every {0} months on the {1}", + ["TimeFormat"] = "12" }); } @@ -52,7 +61,10 @@ private static string ToHumanReadableSpanish(string cron, CronSettings settings, ["EveryXHours"] = "Cada {0} horas", ["EveryXHoursOn"] = "Cada {0} horas los {1}", ["EveryMonthOnDay"] = "Cada mes el día {0}", - ["OnDayAndWeek"] = "El {0} y los {1}" + ["OnDayAndWeek"] = "El {0} y los {1}", + ["EveryDayOfWeek"] = "Cada {0}", + ["EveryXMonthsOnDay"] = "Cada {0} meses el día {1}", + ["TimeFormat"] = "12" }); } @@ -66,10 +78,103 @@ private static string ToHumanReadableFrench(string cron, CronSettings settings, ["EveryXHours"] = "Toutes les {0} heures", ["EveryXHoursOn"] = "Toutes les {0} heures le {1}", ["EveryMonthOnDay"] = "Chaque mois le {0}", - ["OnDayAndWeek"] = "Le {0} et le {1}" + ["OnDayAndWeek"] = "Le {0} et le {1}", + ["EveryDayOfWeek"] = "Chaque {0}", + ["EveryXMonthsOnDay"] = "Tous les {0} mois le {1}", + ["TimeFormat"] = "12" }); } + private static string ToHumanReadableGerman(string cron, CronSettings settings, TimeZoneInfo? timeZone) => + BuildHumanReadable(cron, settings, timeZone, new Dictionary + { + ["EveryDay"] = "Jeden Tag", + ["AtTime"] = "um {0} Uhr", + ["EveryXMinutes"] = "Alle {0} Minuten", + ["EveryXHours"] = "Alle {0} Stunden", + ["EveryXHoursOn"] = "Alle {0} Stunden am {1}", + ["EveryMonthOnDay"] = "Jeden Monat am {0}", + ["OnDayAndWeek"] = "Am {0} und am {1}", + ["EveryDayOfWeek"] = "Jeden {0}", + ["EveryXMonthsOnDay"] = "Alle {0} Monate am {1}", + ["TimeFormat"] = "24" + }); + + private static string ToHumanReadablePortuguese(string cron, CronSettings settings, TimeZoneInfo? timeZone) => + BuildHumanReadable(cron, settings, timeZone, new Dictionary + { + ["EveryDay"] = "Todos os dias", + ["AtTime"] = "às {0}", + ["EveryXMinutes"] = "A cada {0} minutos", + ["EveryXHours"] = "A cada {0} horas", + ["EveryXHoursOn"] = "A cada {0} horas em {1}", + ["EveryMonthOnDay"] = "Todo mês no dia {0}", + ["OnDayAndWeek"] = "No dia {0} e em {1}", + ["EveryDayOfWeek"] = "Em {0}", + ["EveryXMonthsOnDay"] = "A cada {0} meses no dia {1}", + ["TimeFormat"] = "24" + }); + + private static string ToHumanReadableItalian(string cron, CronSettings settings, TimeZoneInfo? timeZone) => + BuildHumanReadable(cron, settings, timeZone, new Dictionary + { + ["EveryDay"] = "Ogni giorno", + ["AtTime"] = "alle {0}", + ["EveryXMinutes"] = "Ogni {0} minuti", + ["EveryXHours"] = "Ogni {0} ore", + ["EveryXHoursOn"] = "Ogni {0} ore di {1}", + ["EveryMonthOnDay"] = "Ogni mese il giorno {0}", + ["OnDayAndWeek"] = "Il giorno {0} e di {1}", + ["EveryDayOfWeek"] = "Ogni {0}", + ["EveryXMonthsOnDay"] = "Ogni {0} mesi il giorno {1}", + ["TimeFormat"] = "24" + }); + + private static string ToHumanReadableDutch(string cron, CronSettings settings, TimeZoneInfo? timeZone) => + BuildHumanReadable(cron, settings, timeZone, new Dictionary + { + ["EveryDay"] = "Elke dag", + ["AtTime"] = "om {0}", + ["EveryXMinutes"] = "Elke {0} minuten", + ["EveryXHours"] = "Elke {0} uur", + ["EveryXHoursOn"] = "Elke {0} uur op {1}", + ["EveryMonthOnDay"] = "Elke maand op de {0}", + ["OnDayAndWeek"] = "Op de {0} en op {1}", + ["EveryDayOfWeek"] = "Elke {0}", + ["EveryXMonthsOnDay"] = "Elke {0} maanden op de {1}", + ["TimeFormat"] = "24" + }); + + private static string ToHumanReadableChinese(string cron, CronSettings settings, TimeZoneInfo? timeZone) => + BuildHumanReadable(cron, settings, timeZone, new Dictionary + { + ["EveryDay"] = "每天", + ["AtTime"] = "{0}", + ["EveryXMinutes"] = "每 {0} 分钟", + ["EveryXHours"] = "每 {0} 小时", + ["EveryXHoursOn"] = "每 {0} 小时({1})", + ["EveryMonthOnDay"] = "每月第 {0} 天", + ["OnDayAndWeek"] = "每月第 {0} 天和{1}", + ["EveryDayOfWeek"] = "每{0}", + ["EveryXMonthsOnDay"] = "每 {0} 个月的第 {1} 天", + ["TimeFormat"] = "24" + }); + + private static string ToHumanReadableJapanese(string cron, CronSettings settings, TimeZoneInfo? timeZone) => + BuildHumanReadable(cron, settings, timeZone, new Dictionary + { + ["EveryDay"] = "毎日", + ["AtTime"] = "{0}に", + ["EveryXMinutes"] = "{0}分ごと", + ["EveryXHours"] = "{0}時間ごと", + ["EveryXHoursOn"] = "{1}に{0}時間ごと", + ["EveryMonthOnDay"] = "毎月{0}日", + ["OnDayAndWeek"] = "毎月{0}日と{1}", + ["EveryDayOfWeek"] = "毎週{0}", + ["EveryXMonthsOnDay"] = "{0}か月ごとの{1}日", + ["TimeFormat"] = "24" + }); + private static string BuildHumanReadable( string cron, CronSettings settings, @@ -90,7 +195,7 @@ private static string BuildHumanReadable( string month = parts[3]; string dayOfWeek = parts[4]; - string time = FormatTime(hour, minute, timeZone); + string time = FormatTime(hour, minute, timeZone, phrases); string Phrase(string key, params object[] args) => phrases.TryGetValue(key, out var value) @@ -127,19 +232,19 @@ string Phrase(string key, params object[] args) => // day-of-month: 15W → "Nearest weekday to the 15th" if (dayOfMonth.EndsWith('W')) { - var baseDay = Ordinal(dayOfMonth.TrimEnd('W')); + var baseDay = Ordinal(dayOfMonth.TrimEnd('W'), settings.Language); return $"Nearest weekday to the {baseDay} of the month {Phrase("AtTime", time)}"; } // --- Range and list patterns --- - if (TryDescribeTimePattern(hour, minute, timeZone, out var timePattern)) + if (TryDescribeTimePattern(hour, minute, timeZone, phrases, out var timePattern)) { if (dayOfWeek != "*" && dayOfWeek != "?") return $"{timePattern} on {JoinDays(dayOfWeek, daysMap)}"; if (dayOfMonth != "*") - return $"{timePattern} on the {DescribeOrdinals(dayOfMonth)} of every month"; + return $"{timePattern} on the {DescribeOrdinals(dayOfMonth, settings.Language)} of every month"; return timePattern.StartsWith("At ", StringComparison.Ordinal) ? $"Every day at {timePattern[3..]}" @@ -148,7 +253,7 @@ string Phrase(string key, params object[] args) => if (dayOfMonth.Contains('-') && (dayOfWeek == "*" || dayOfWeek == "?")) { - var dayRange = DescribeOrdinals(dayOfMonth); + var dayRange = DescribeOrdinals(dayOfMonth, settings.Language); return $"Every day from the {dayRange} {Phrase("AtTime", time)}"; } @@ -167,19 +272,19 @@ string Phrase(string key, params object[] args) => return Phrase("EveryDay") + " " + Phrase("AtTime", time); if (dayOfWeek != "*" && dayOfMonth == "*") - return $"Every {JoinDays(dayOfWeek, daysMap)} {Phrase("AtTime", time)}"; + return $"{Phrase("EveryDayOfWeek", JoinDays(dayOfWeek, daysMap))} {Phrase("AtTime", time)}"; if (dayOfMonth != "*" && (dayOfWeek == "*" || dayOfWeek == "?")) { - string monthDesc = month.StartsWith("*/") - ? $"Every {month.Replace("*/", "")} months" - : "Every month"; + var ordinal = DescribeOrdinals(dayOfMonth, settings.Language); - return $"{monthDesc} on the {DescribeOrdinals(dayOfMonth)} {Phrase("AtTime", time)}"; + return month.StartsWith("*/") + ? $"{Phrase("EveryXMonthsOnDay", month.Replace("*/", ""), ordinal)} {Phrase("AtTime", time)}" + : $"{Phrase("EveryMonthOnDay", ordinal)} {Phrase("AtTime", time)}"; } if (dayOfMonth != "*" && dayOfWeek != "*") - return Phrase("OnDayAndWeek", DescribeOrdinals(dayOfMonth), JoinDays(dayOfWeek, daysMap)) + return Phrase("OnDayAndWeek", DescribeOrdinals(dayOfMonth, settings.Language), JoinDays(dayOfWeek, daysMap)) + " " + Phrase("AtTime", time); return cron; @@ -224,15 +329,23 @@ private static string ConvertQuartzToCronos(string quartzCron) return quartzCron; } - private static string FormatTime(string hour, string minute, TimeZoneInfo? timeZone) + private static string FormatTime( + string hour, + string minute, + TimeZoneInfo? timeZone, + Dictionary phrases) { int h = int.TryParse(hour.Replace("*/", "0"), out var hParsed) ? hParsed : 0; int m = int.TryParse(minute.Replace("*/", "0"), out var mParsed) ? mParsed : 0; - return FormatTime(h, m, timeZone); + return FormatTime(h, m, timeZone, phrases); } - private static string FormatTime(int hour, int minute, TimeZoneInfo? timeZone) + private static string FormatTime( + int hour, + int minute, + TimeZoneInfo? timeZone, + Dictionary phrases) { DateTime utcTime = new DateTime(2000, 1, 1, hour, minute, 0, DateTimeKind.Utc); @@ -240,10 +353,13 @@ private static string FormatTime(int hour, int minute, TimeZoneInfo? timeZone) ? TimeZoneInfo.ConvertTimeFromUtc(utcTime, timeZone) : utcTime; - return localTime.ToString("hh:mm tt", System.Globalization.CultureInfo.InvariantCulture); + var format = phrases.TryGetValue("TimeFormat", out var timeFormat) && timeFormat == "24" + ? "HH:mm" + : "hh:mm tt"; + return localTime.ToString(format, System.Globalization.CultureInfo.InvariantCulture); } - private static string Ordinal(string number) + private static string Ordinal(string number, string language = "en") { if (number.Contains("/")) number = number.Split('/')[0]; @@ -251,6 +367,18 @@ private static string Ordinal(string number) if (!int.TryParse(number, out int n)) return number; + return language.ToLowerInvariant() switch + { + "de" => $"{n}.", + "pt" => $"{n}º", + "it" or "zh" or "ja" => n.ToString(), + "nl" => $"{n}e", + _ => EnglishOrdinal(n) + }; + } + + private static string EnglishOrdinal(int n) + { return n switch { int _ when n % 100 is >= 11 and <= 13 => $"{n}th", @@ -261,7 +389,7 @@ private static string Ordinal(string number) }; } - private static string DescribeOrdinals(string expression) + private static string DescribeOrdinals(string expression, string language = "en") { var descriptions = expression .Split(',', StringSplitOptions.RemoveEmptyEntries | StringSplitOptions.TrimEntries) @@ -269,8 +397,8 @@ private static string DescribeOrdinals(string expression) { var bounds = part.Split('-', StringSplitOptions.TrimEntries); return bounds.Length == 2 - ? $"{Ordinal(bounds[0])} through the {Ordinal(bounds[1])}" - : Ordinal(part); + ? $"{Ordinal(bounds[0], language)} through the {Ordinal(bounds[1], language)}" + : Ordinal(part, language); }) .ToList(); @@ -281,6 +409,7 @@ private static bool TryDescribeTimePattern( string hour, string minute, TimeZoneInfo? timeZone, + Dictionary phrases, out string description) { description = string.Empty; @@ -293,7 +422,7 @@ private static bool TryDescribeTimePattern( int.TryParse(bounds[1], out var endHour)) { description = - $"Every hour from {FormatTime(startHour, fixedMinute, timeZone)} to {FormatTime(endHour, fixedMinute, timeZone)}"; + $"Every hour from {FormatTime(startHour, fixedMinute, timeZone, phrases)} to {FormatTime(endHour, fixedMinute, timeZone, phrases)}"; return true; } } @@ -306,7 +435,7 @@ private static bool TryDescribeTimePattern( int.TryParse(bounds[1], out var endMinute)) { description = - $"Every minute from {FormatTime(fixedHour, startMinute, timeZone)} to {FormatTime(fixedHour, endMinute, timeZone)}"; + $"Every minute from {FormatTime(fixedHour, startMinute, timeZone, phrases)} to {FormatTime(fixedHour, endMinute, timeZone, phrases)}"; return true; } } @@ -318,7 +447,7 @@ private static bool TryDescribeTimePattern( var times = ( from parsedHour in hours from parsedMinute in minutes - select FormatTime(parsedHour, parsedMinute, timeZone)) + select FormatTime(parsedHour, parsedMinute, timeZone, phrases)) .ToList(); description = $"At {JoinDescriptions(times)}"; diff --git a/CronCraft/Models/CronSettings.cs b/CronCraft/Models/CronSettings.cs index f17789c..dcfe2e7 100644 --- a/CronCraft/Models/CronSettings.cs +++ b/CronCraft/Models/CronSettings.cs @@ -6,7 +6,8 @@ public class CronSettings { /// - /// Language used for output formatting (e.g., "en", "es", "fr"). + /// Language used for output formatting. + /// Supported values: "en", "es", "fr", "de", "pt", "it", "nl", "zh", and "ja". /// Default is "en". /// public string Language { get; set; } = "en"; diff --git a/CronCraft/Providers/DayNameProvider.cs b/CronCraft/Providers/DayNameProvider.cs index 22bb8ae..78b1ea1 100644 --- a/CronCraft/Providers/DayNameProvider.cs +++ b/CronCraft/Providers/DayNameProvider.cs @@ -4,6 +4,12 @@ namespace CronCraft.Providers; public static class DayNameProvider { + private static Dictionary CreateDayMap(params string[] names) => new() + { + { "0", names[0] }, { "1", names[1] }, { "2", names[2] }, { "3", names[3] }, + { "4", names[4] }, { "5", names[5] }, { "6", names[6] }, { "7", names[0] } + }; + private static readonly Dictionary SingleEnglish = new() { { "0", "S" }, { "1", "M" }, { "2", "T" }, { "3", "W" }, @@ -60,6 +66,48 @@ public static class DayNameProvider { "4", "J" }, { "5", "V" }, { "6", "S" }, { "7", "D" } }; + private static readonly Dictionary FullGerman = + CreateDayMap("Sonntag", "Montag", "Dienstag", "Mittwoch", "Donnerstag", "Freitag", "Samstag"); + private static readonly Dictionary ShortGerman = + CreateDayMap("So", "Mo", "Di", "Mi", "Do", "Fr", "Sa"); + private static readonly Dictionary SingleGerman = + CreateDayMap("S", "M", "D", "M", "D", "F", "S"); + + private static readonly Dictionary FullPortuguese = + CreateDayMap("Domingo", "Segunda-feira", "Terça-feira", "Quarta-feira", "Quinta-feira", "Sexta-feira", "Sábado"); + private static readonly Dictionary ShortPortuguese = + CreateDayMap("Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb"); + private static readonly Dictionary SinglePortuguese = + CreateDayMap("D", "S", "T", "Q", "Q", "S", "S"); + + private static readonly Dictionary FullItalian = + CreateDayMap("Domenica", "Lunedì", "Martedì", "Mercoledì", "Giovedì", "Venerdì", "Sabato"); + private static readonly Dictionary ShortItalian = + CreateDayMap("Dom", "Lun", "Mar", "Mer", "Gio", "Ven", "Sab"); + private static readonly Dictionary SingleItalian = + CreateDayMap("D", "L", "M", "M", "G", "V", "S"); + + private static readonly Dictionary FullDutch = + CreateDayMap("Zondag", "Maandag", "Dinsdag", "Woensdag", "Donderdag", "Vrijdag", "Zaterdag"); + private static readonly Dictionary ShortDutch = + CreateDayMap("Zo", "Ma", "Di", "Wo", "Do", "Vr", "Za"); + private static readonly Dictionary SingleDutch = + CreateDayMap("Z", "M", "D", "W", "D", "V", "Z"); + + private static readonly Dictionary FullChinese = + CreateDayMap("星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六"); + private static readonly Dictionary ShortChinese = + CreateDayMap("周日", "周一", "周二", "周三", "周四", "周五", "周六"); + private static readonly Dictionary SingleChinese = + CreateDayMap("日", "一", "二", "三", "四", "五", "六"); + + private static readonly Dictionary FullJapanese = + CreateDayMap("日曜日", "月曜日", "火曜日", "水曜日", "木曜日", "金曜日", "土曜日"); + private static readonly Dictionary ShortJapanese = + CreateDayMap("日曜", "月曜", "火曜", "水曜", "木曜", "金曜", "土曜"); + private static readonly Dictionary SingleJapanese = + CreateDayMap("日", "月", "火", "水", "木", "金", "土"); + public static Dictionary GetDayMap(CronSettings settings) { var format = settings.DayNameFormat?.ToLowerInvariant() ?? "short"; @@ -80,10 +128,28 @@ public static Dictionary GetDayMap(CronSettings settings) { ("single", "es") => SingleSpanish, ("single", "fr") => SingleFrench, + ("single", "de") => SingleGerman, + ("single", "pt") => SinglePortuguese, + ("single", "it") => SingleItalian, + ("single", "nl") => SingleDutch, + ("single", "zh") => SingleChinese, + ("single", "ja") => SingleJapanese, ("short", "es") => ShortSpanish, ("short", "fr") => ShortFrench, + ("short", "de") => ShortGerman, + ("short", "pt") => ShortPortuguese, + ("short", "it") => ShortItalian, + ("short", "nl") => ShortDutch, + ("short", "zh") => ShortChinese, + ("short", "ja") => ShortJapanese, ("full", "es") => FullSpanish, ("full", "fr") => FullFrench, + ("full", "de") => FullGerman, + ("full", "pt") => FullPortuguese, + ("full", "it") => FullItalian, + ("full", "nl") => FullDutch, + ("full", "zh") => FullChinese, + ("full", "ja") => FullJapanese, ("full", _) => FullEnglish, ("single", _) => SingleEnglish, _ => ShortEnglish diff --git a/CronCraft/README.md b/CronCraft/README.md index c965a5c..bda5b40 100644 --- a/CronCraft/README.md +++ b/CronCraft/README.md @@ -117,6 +117,12 @@ Press Enter to exit... - English (`en`) - Spanish (`es`) - French (`fr`) +- German (`de`) +- Portuguese (`pt`) +- Italian (`it`) +- Dutch (`nl`) +- Simplified Chinese (`zh`) +- Japanese (`ja`) - Easily extendable via custom mappings --- diff --git a/README.md b/README.md index a34513f..d1c6bbf 100644 --- a/README.md +++ b/README.md @@ -117,6 +117,12 @@ Press Enter to exit... - English (`en`) - Spanish (`es`) - French (`fr`) +- German (`de`) +- Portuguese (`pt`) +- Italian (`it`) +- Dutch (`nl`) +- Simplified Chinese (`zh`) +- Japanese (`ja`) - Easily extendable via custom mappings ---