From b5ec5562435021ea4b8af07c9b64a3f7249b570a Mon Sep 17 00:00:00 2001 From: sephrat <34862846+sephrat@users.noreply.github.com> Date: Tue, 1 Feb 2022 21:32:13 +0100 Subject: [PATCH] feat(newsletter): Started to localize the newsletter (#4485) * Abstract media servers content into interfaces * Media server entities into abstract classes * Abstract media server content repository * First pass at newsletter refactoring * Minor code clean up * Attempt at abstracting repositories (WIP) * Fixed cast issue * Corrected the other properties * A step towards newsletter refactoring * Clean up leftovers * Fix broken episodes db interaction * Save absolute URL for Plex content Let's be consistent with Emby and Jellyfin * Fix broken integration with Plex libraries * Fix error when multiple media servers configured * Fix newsletter being sent if no movies or episodes * Fix broken tests * Remove unneccesary logs * Allow for newsletter localization * Generate file in English * Fix unsubscribe text unlocalized by messy merge * Fix indentation Co-authored-by: tidusjar --- src/Ombi.Core/Ombi.Core.csproj | 1 + src/Ombi.I18n/Ombi.I18n.csproj | 30 ++++ src/Ombi.I18n/Resources/Texts.Designer.cs | 144 +++++++++++++++++ src/Ombi.I18n/Resources/Texts.fr.resx | 147 ++++++++++++++++++ src/Ombi.I18n/Resources/Texts.resx | 147 ++++++++++++++++++ .../NewsletterTemplate.cs | 5 +- .../Ombi.Notifications.Templates.csproj | 1 + .../Templates/NewsletterTemplate.html | 2 +- src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs | 15 +- src/Ombi.Settings/Ombi.Settings.csproj | 1 + .../Settings/Models/OmbiSettings.cs | 14 +- 11 files changed, 496 insertions(+), 11 deletions(-) create mode 100644 src/Ombi.I18n/Ombi.I18n.csproj create mode 100644 src/Ombi.I18n/Resources/Texts.Designer.cs create mode 100644 src/Ombi.I18n/Resources/Texts.fr.resx create mode 100644 src/Ombi.I18n/Resources/Texts.resx diff --git a/src/Ombi.Core/Ombi.Core.csproj b/src/Ombi.Core/Ombi.Core.csproj index 359792e0d..0f7ca6845 100644 --- a/src/Ombi.Core/Ombi.Core.csproj +++ b/src/Ombi.Core/Ombi.Core.csproj @@ -36,6 +36,7 @@ + diff --git a/src/Ombi.I18n/Ombi.I18n.csproj b/src/Ombi.I18n/Ombi.I18n.csproj new file mode 100644 index 000000000..f44037974 --- /dev/null +++ b/src/Ombi.I18n/Ombi.I18n.csproj @@ -0,0 +1,30 @@ + + + + net6.0 + 3.0.0.0 + 3.0.0.0 + + + 8.0 + Debug;Release;NonUiBuild + + + + Always + + + + + True + True + Texts.resx + + + + + PublicResXFileCodeGenerator + Texts.Designer.cs + + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.Designer.cs b/src/Ombi.I18n/Resources/Texts.Designer.cs new file mode 100644 index 000000000..2f589c022 --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.Designer.cs @@ -0,0 +1,144 @@ +//------------------------------------------------------------------------------ +// +// This code was generated by a tool. +// Runtime Version:4.0.30319.42000 +// +// Changes to this file may cause incorrect behavior and will be lost if +// the code is regenerated. +// +//------------------------------------------------------------------------------ + +namespace Ombi.I18n.Resources { + using System; + + + /// + /// A strongly-typed resource class, for looking up localized strings, etc. + /// + // This class was auto-generated by the StronglyTypedResourceBuilder + // class via a tool like ResGen or Visual Studio. + // To add or remove a member, edit your .ResX file then rerun ResGen + // with the /str option, or rebuild your VS project. + [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", "17.0.0.0")] + [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] + [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] + public class Texts { + + private static global::System.Resources.ResourceManager resourceMan; + + private static global::System.Globalization.CultureInfo resourceCulture; + + [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", "CA1811:AvoidUncalledPrivateCode")] + internal Texts() { + } + + /// + /// Returns the cached ResourceManager instance used by this class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Resources.ResourceManager ResourceManager { + get { + if (object.ReferenceEquals(resourceMan, null)) { + global::System.Resources.ResourceManager temp = new global::System.Resources.ResourceManager("Ombi.I18n.Resources.Texts", typeof(Texts).Assembly); + resourceMan = temp; + } + return resourceMan; + } + } + + /// + /// Overrides the current thread's CurrentUICulture property for all + /// resource lookups using this strongly typed resource class. + /// + [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)] + public static global::System.Globalization.CultureInfo Culture { + get { + return resourceCulture; + } + set { + resourceCulture = value; + } + } + + /// + /// Looks up a localized string similar to Type:. + /// + public static string AlbumTypeLabel { + get { + return ResourceManager.GetString("AlbumTypeLabel", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Episodes:. + /// + public static string EpisodesLabel { + get { + return ResourceManager.GetString("EpisodesLabel", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Genres:. + /// + public static string GenresLabel { + get { + return ResourceManager.GetString("GenresLabel", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to New Albums. + /// + public static string NewAlbums { + get { + return ResourceManager.GetString("NewAlbums", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to New Movies. + /// + public static string NewMovies { + get { + return ResourceManager.GetString("NewMovies", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to New TV. + /// + public static string NewTV { + get { + return ResourceManager.GetString("NewTV", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Powered by. + /// + public static string PoweredBy { + get { + return ResourceManager.GetString("PoweredBy", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Season:. + /// + public static string SeasonLabel { + get { + return ResourceManager.GetString("SeasonLabel", resourceCulture); + } + } + + /// + /// Looks up a localized string similar to Unsubscribe. + /// + public static string Unsubscribe { + get { + return ResourceManager.GetString("Unsubscribe", resourceCulture); + } + } + } +} diff --git a/src/Ombi.I18n/Resources/Texts.fr.resx b/src/Ombi.I18n/Resources/Texts.fr.resx new file mode 100644 index 000000000..ea90dda73 --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.fr.resx @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + Nouveaux Albums + + + Nouveaux Films + + + Nouvelles séries + + + Genres : + + + Type : + + + Saison : + + + Épisodes : + + + Propulsé par + + + Se désinscrire + + \ No newline at end of file diff --git a/src/Ombi.I18n/Resources/Texts.resx b/src/Ombi.I18n/Resources/Texts.resx new file mode 100644 index 000000000..421371dcb --- /dev/null +++ b/src/Ombi.I18n/Resources/Texts.resx @@ -0,0 +1,147 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + 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 + + + New Albums + + + New Movies + + + New TV + + + Genres: + + + Type: + + + Season: + + + Episodes: + + + Powered by + + + Unsubscribe + + \ No newline at end of file diff --git a/src/Ombi.Notifications.Templates/NewsletterTemplate.cs b/src/Ombi.Notifications.Templates/NewsletterTemplate.cs index aeaeb40c6..9d3b1632a 100644 --- a/src/Ombi.Notifications.Templates/NewsletterTemplate.cs +++ b/src/Ombi.Notifications.Templates/NewsletterTemplate.cs @@ -1,6 +1,7 @@ using System; using System.IO; using System.Text; +using Ombi.I18n.Resources; namespace Ombi.Notifications.Templates { @@ -31,6 +32,7 @@ namespace Ombi.Notifications.Templates private const string IntroText = "{@INTRO}"; private const string Unsubscribe = "{@UNSUBSCRIBE}"; private const string UnsubscribeText = "{@UNSUBSCRIBETEXT}"; + private const string PoweredByText = "{@POWEREDBYTEXT}"; public string LoadTemplate(string subject, string intro, string tableHtml, string logo, string unsubscribeLink) @@ -42,7 +44,8 @@ namespace Ombi.Notifications.Templates sb.Replace(DateKey, DateTime.Now.ToString("f")); sb.Replace(Logo, string.IsNullOrEmpty(logo) ? OmbiLogo : logo); sb.Replace(Unsubscribe, string.IsNullOrEmpty(unsubscribeLink) ? string.Empty : unsubscribeLink); - sb.Replace(UnsubscribeText, string.IsNullOrEmpty(unsubscribeLink) ? string.Empty : "Unsubscrible"); + sb.Replace(UnsubscribeText, string.IsNullOrEmpty(unsubscribeLink) ? string.Empty : Texts.Unsubscribe); + sb.Replace(PoweredByText, Texts.PoweredBy); return sb.ToString(); } diff --git a/src/Ombi.Notifications.Templates/Ombi.Notifications.Templates.csproj b/src/Ombi.Notifications.Templates/Ombi.Notifications.Templates.csproj index 33088a591..87a876caa 100644 --- a/src/Ombi.Notifications.Templates/Ombi.Notifications.Templates.csproj +++ b/src/Ombi.Notifications.Templates/Ombi.Notifications.Templates.csproj @@ -17,6 +17,7 @@ Always + \ No newline at end of file diff --git a/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html b/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html index befb4dfa3..fdafdb609 100644 --- a/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html +++ b/src/Ombi.Notifications.Templates/Templates/NewsletterTemplate.html @@ -458,7 +458,7 @@ - Powered by Ombi + {@POWEREDBYTEXT} Ombi diff --git a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs index 59aabe873..f965625f6 100644 --- a/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs +++ b/src/Ombi.Schedule/Jobs/Ombi/NewsletterJob.cs @@ -16,6 +16,7 @@ using Ombi.Core.Settings; using Ombi.Core.Settings.Models.External; using Ombi.Helpers; using Ombi.Hubs; +using Ombi.I18n.Resources; using Ombi.Notifications; using Ombi.Notifications.Models; using Ombi.Notifications.Templates; @@ -440,7 +441,7 @@ namespace Ombi.Schedule.Jobs.Ombi if (movies.Any() && !settings.DisableMovies) { - sb.Append("

New Movies



"); + sb.Append($"

{Texts.NewMovies}



"); sb.Append( ""); sb.Append(""); @@ -457,7 +458,7 @@ namespace Ombi.Schedule.Jobs.Ombi if (episodes.Any() && !settings.DisableTv) { - sb.Append("

New TV



"); + sb.Append($"

{Texts.NewTV}



"); sb.Append( "
"); sb.Append(""); @@ -475,7 +476,7 @@ namespace Ombi.Schedule.Jobs.Ombi if (albums.Any() && !settings.DisableMusic) { - sb.Append("

New Albums



"); + sb.Append($"

{Texts.NewAlbums}



"); sb.Append( "
"); sb.Append(""); @@ -601,7 +602,7 @@ namespace Ombi.Schedule.Jobs.Ombi if (info.Genres.Any()) { - AddGenres($"Genres: {string.Join(", ", info.Genres.Select(x => x.Name.ToString()).ToArray())}"); + AddGenres($"{Texts.GenresLabel} {string.Join(", ", info.Genres.Select(x => x.Name.ToString()).ToArray())}"); } } @@ -637,7 +638,7 @@ namespace Ombi.Schedule.Jobs.Ombi } AddParagraph(summary); - AddGenres($"Type: {info.albumType}"); + AddGenres($"{Texts.AlbumTypeLabel} {info.albumType}"); } private async Task ProcessTv(IEnumerable episodes, string languageCode) @@ -742,7 +743,7 @@ namespace Ombi.Schedule.Jobs.Ombi var orderedEpisodes = epInformation.Episodes.OrderBy(x => x.EpisodeNumber).ToList(); var episodeString = StringHelper.BuildEpisodeList(orderedEpisodes.Select(x => x.EpisodeNumber)); var episodeAirDate = epInformation.EpisodeAirDate; - finalsb.Append($"Season: {epInformation.SeasonNumber} - Episodes: {episodeString} {episodeAirDate}"); + finalsb.Append($"{Texts.SeasonLabel} {epInformation.SeasonNumber} - {Texts.EpisodesLabel} {episodeString} {episodeAirDate}"); finalsb.Append("
"); } @@ -794,7 +795,7 @@ namespace Ombi.Schedule.Jobs.Ombi if (tvInfo.genres.Any()) { - AddGenres($"Genres: {string.Join(", ", tvInfo.genres.Select(x => x.name.ToString()).ToArray())}"); + AddGenres($"{Texts.GenresLabel} {string.Join(", ", tvInfo.genres.Select(x => x.name.ToString()).ToArray())}"); } } diff --git a/src/Ombi.Settings/Ombi.Settings.csproj b/src/Ombi.Settings/Ombi.Settings.csproj index b39c123e2..4b3aa4c60 100644 --- a/src/Ombi.Settings/Ombi.Settings.csproj +++ b/src/Ombi.Settings/Ombi.Settings.csproj @@ -18,6 +18,7 @@ + diff --git a/src/Ombi.Settings/Settings/Models/OmbiSettings.cs b/src/Ombi.Settings/Settings/Models/OmbiSettings.cs index ba460a2bd..e224b5c70 100644 --- a/src/Ombi.Settings/Settings/Models/OmbiSettings.cs +++ b/src/Ombi.Settings/Settings/Models/OmbiSettings.cs @@ -1,7 +1,10 @@ -namespace Ombi.Settings.Settings.Models +using Ombi.I18n.Resources; +using System.Globalization; +namespace Ombi.Settings.Settings.Models { public class OmbiSettings : Settings { + private string defaultLanguageCode = "en"; public string BaseUrl { get; set; } public bool CollectAnalyticData { get; set; } public bool Wizard { get; set; } @@ -9,7 +12,14 @@ public bool DoNotSendNotificationsForAutoApprove { get; set; } public bool HideRequestsUsers { get; set; } public bool DisableHealthChecks { get; set; } - public string DefaultLanguageCode { get; set; } = "en"; + public string DefaultLanguageCode + { + get => defaultLanguageCode; + set { + defaultLanguageCode = value; + Texts.Culture = new CultureInfo(value); + } + } public bool AutoDeleteAvailableRequests { get; set; } public int AutoDeleteAfterDays { get; set; } public Branch Branch { get; set; }