Allow for newsletter localization

This commit is contained in:
Florian Dupret 2022-01-19 12:14:40 +01:00
commit 45c5c1e0a2
11 changed files with 487 additions and 13 deletions

View file

@ -36,6 +36,7 @@
<ProjectReference Include="..\Ombi.Api.Trakt\Ombi.Api.Trakt.csproj" /> <ProjectReference Include="..\Ombi.Api.Trakt\Ombi.Api.Trakt.csproj" />
<ProjectReference Include="..\Ombi.Api.TvMaze\Ombi.Api.TvMaze.csproj" /> <ProjectReference Include="..\Ombi.Api.TvMaze\Ombi.Api.TvMaze.csproj" />
<ProjectReference Include="..\Ombi.Helpers\Ombi.Helpers.csproj" /> <ProjectReference Include="..\Ombi.Helpers\Ombi.Helpers.csproj" />
<ProjectReference Include="..\Ombi.I18n\Ombi.I18n.csproj" />
<ProjectReference Include="..\Ombi.Notifications\Ombi.Notifications.csproj" /> <ProjectReference Include="..\Ombi.Notifications\Ombi.Notifications.csproj" />
<ProjectReference Include="..\Ombi.Settings\Ombi.Settings.csproj" /> <ProjectReference Include="..\Ombi.Settings\Ombi.Settings.csproj" />
<ProjectReference Include="..\Ombi.Store\Ombi.Store.csproj" /> <ProjectReference Include="..\Ombi.Store\Ombi.Store.csproj" />

View file

@ -0,0 +1,17 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>net6.0</TargetFramework>
<AssemblyVersion>3.0.0.0</AssemblyVersion>
<FileVersion>3.0.0.0</FileVersion>
<Version></Version>
<PackageVersion></PackageVersion>
<LangVersion>8.0</LangVersion>
<Configurations>Debug;Release;NonUiBuild</Configurations>
</PropertyGroup>
<ItemGroup>
<Content Include="Resources\*.*">
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>

144
src/Ombi.I18n/Resources/Texts.Designer.cs generated Normal file
View file

@ -0,0 +1,144 @@
//------------------------------------------------------------------------------
// <auto-generated>
// Ce code a été généré par un outil.
// Version du runtime :4.0.30319.42000
//
// Les modifications apportées à ce fichier peuvent provoquer un comportement incorrect et seront perdues si
// le code est régénéré.
// </auto-generated>
//------------------------------------------------------------------------------
namespace Ombi.I18n.Resources {
using System;
/// <summary>
/// Une classe de ressource fortement typée destinée, entre autres, à la consultation des chaînes localisées.
/// </summary>
// Cette classe a été générée automatiquement par la classe StronglyTypedResourceBuilder
// à l'aide d'un outil, tel que ResGen ou Visual Studio.
// Pour ajouter ou supprimer un membre, modifiez votre fichier .ResX, puis réexécutez ResGen
// avec l'option /str ou régénérez votre projet VS.
[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() {
}
/// <summary>
/// Retourne l'instance ResourceManager mise en cache utilisée par cette classe.
/// </summary>
[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;
}
}
/// <summary>
/// Remplace la propriété CurrentUICulture du thread actuel pour toutes
/// les recherches de ressources à l'aide de cette classe de ressource fortement typée.
/// </summary>
[global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState.Advanced)]
public static global::System.Globalization.CultureInfo Culture {
get {
return resourceCulture;
}
set {
resourceCulture = value;
}
}
/// <summary>
/// Recherche une chaîne localisée semblable à Type:.
/// </summary>
public static string AlbumTypeLabel {
get {
return ResourceManager.GetString("AlbumTypeLabel", resourceCulture);
}
}
/// <summary>
/// Recherche une chaîne localisée semblable à Episodes:.
/// </summary>
public static string EpisodesLabel {
get {
return ResourceManager.GetString("EpisodesLabel", resourceCulture);
}
}
/// <summary>
/// Recherche une chaîne localisée semblable à Genres:.
/// </summary>
public static string GenresLabel {
get {
return ResourceManager.GetString("GenresLabel", resourceCulture);
}
}
/// <summary>
/// Recherche une chaîne localisée semblable à New Albums.
/// </summary>
public static string NewAlbums {
get {
return ResourceManager.GetString("NewAlbums", resourceCulture);
}
}
/// <summary>
/// Recherche une chaîne localisée semblable à New Movies.
/// </summary>
public static string NewMovies {
get {
return ResourceManager.GetString("NewMovies", resourceCulture);
}
}
/// <summary>
/// Recherche une chaîne localisée semblable à New TV.
/// </summary>
public static string NewTV {
get {
return ResourceManager.GetString("NewTV", resourceCulture);
}
}
/// <summary>
/// Recherche une chaîne localisée semblable à Powered by.
/// </summary>
public static string PoweredBy {
get {
return ResourceManager.GetString("PoweredBy", resourceCulture);
}
}
/// <summary>
/// Recherche une chaîne localisée semblable à Season:.
/// </summary>
public static string SeasonLabel {
get {
return ResourceManager.GetString("SeasonLabel", resourceCulture);
}
}
/// <summary>
/// Recherche une chaîne localisée semblable à Unsubscribe.
/// </summary>
public static string Unsubscribe {
get {
return ResourceManager.GetString("Unsubscribe", resourceCulture);
}
}
}
}

View file

@ -0,0 +1,147 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="NewAlbums" xml:space="preserve">
<value>Nouveaux Albums</value>
</data>
<data name="NewMovies" xml:space="preserve">
<value>Nouveaux Films</value>
</data>
<data name="NewTV" xml:space="preserve">
<value>Nouvelles séries</value>
</data>
<data name="GenresLabel" xml:space="preserve">
<value>Genres :</value>
</data>
<data name="AlbumTypeLabel" xml:space="preserve">
<value>Type :</value>
</data>
<data name="SeasonLabel" xml:space="preserve">
<value>Saison :</value>
</data>
<data name="EpisodesLabel" xml:space="preserve">
<value>Épisodes :</value>
</data>
<data name="PoweredBy" xml:space="preserve">
<value>Propulsé par</value>
</data>
<data name="Unsubscribe" xml:space="preserve">
<value>Se désinscrire</value>
</data>
</root>

View file

@ -0,0 +1,147 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<data name="NewAlbums" xml:space="preserve">
<value>New Albums</value>
</data>
<data name="NewMovies" xml:space="preserve">
<value>New Movies</value>
</data>
<data name="NewTV" xml:space="preserve">
<value>New TV</value>
</data>
<data name="GenresLabel" xml:space="preserve">
<value>Genres:</value>
</data>
<data name="AlbumTypeLabel" xml:space="preserve">
<value>Type:</value>
</data>
<data name="SeasonLabel" xml:space="preserve">
<value>Season:</value>
</data>
<data name="EpisodesLabel" xml:space="preserve">
<value>Episodes:</value>
</data>
<data name="PoweredBy" xml:space="preserve">
<value>Powered by</value>
</data>
<data name="Unsubscribe" xml:space="preserve">
<value>Unsubscribe</value>
</data>
</root>

View file

@ -1,6 +1,7 @@
using System; using System;
using System.IO; using System.IO;
using System.Text; using System.Text;
using Ombi.I18n.Resources;
namespace Ombi.Notifications.Templates namespace Ombi.Notifications.Templates
{ {
@ -30,6 +31,8 @@ namespace Ombi.Notifications.Templates
private const string TableLocation = "{@RECENTLYADDED}"; private const string TableLocation = "{@RECENTLYADDED}";
private const string IntroText = "{@INTRO}"; private const string IntroText = "{@INTRO}";
private const string Unsubscribe = "{@UNSUBSCRIBE}"; 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) public string LoadTemplate(string subject, string intro, string tableHtml, string logo, string unsubscribeLink)
@ -41,6 +44,8 @@ namespace Ombi.Notifications.Templates
sb.Replace(DateKey, DateTime.Now.ToString("f")); sb.Replace(DateKey, DateTime.Now.ToString("f"));
sb.Replace(Logo, string.IsNullOrEmpty(logo) ? OmbiLogo : logo); sb.Replace(Logo, string.IsNullOrEmpty(logo) ? OmbiLogo : logo);
sb.Replace(Unsubscribe, string.IsNullOrEmpty(unsubscribeLink) ? string.Empty : unsubscribeLink); sb.Replace(Unsubscribe, string.IsNullOrEmpty(unsubscribeLink) ? string.Empty : unsubscribeLink);
sb.Replace(UnsubscribeText, Texts.Unsubscribe);
sb.Replace(PoweredByText, Texts.PoweredBy);
return sb.ToString(); return sb.ToString();
} }

View file

@ -17,6 +17,7 @@
<None Update="Templates\BasicTemplate.html"> <None Update="Templates\BasicTemplate.html">
<CopyToOutputDirectory>Always</CopyToOutputDirectory> <CopyToOutputDirectory>Always</CopyToOutputDirectory>
</None> </None>
<ProjectReference Include="..\Ombi.I18n\Ombi.I18n.csproj" />
</ItemGroup> </ItemGroup>
</Project> </Project>

View file

@ -453,12 +453,12 @@
<tbody> <tbody>
<tr> <tr>
<td class="content-block powered-by" valign="top" align="center" style="font-family: sans-serif; vertical-align: top; padding-bottom: 10px; padding-top: 10px; color: #999999; font-size: 12px; text-align: center;"> <td class="content-block powered-by" valign="top" align="center" style="font-family: sans-serif; vertical-align: top; padding-bottom: 10px; padding-top: 10px; color: #999999; font-size: 12px; text-align: center;">
<a href="{@UNSUBSCRIBE}" style="font-weight: 400; font-size: 12px; text-align: center; color: #ff761b;">Unsubscribe</a> <a href="{@UNSUBSCRIBE}" style="font-weight: 400; font-size: 12px; text-align: center; color: #ff761b;">{@UNSUBSCRIBETEXT}</a>
</td> </td>
</tr> </tr>
<tr> <tr>
<td class="content-block powered-by" valign="top" align="center" style="font-family: sans-serif; vertical-align: top; padding-bottom: 10px; padding-top: 10px; color: #999999; font-size: 12px; text-align: center;"> <td class="content-block powered-by" valign="top" align="center" style="font-family: sans-serif; vertical-align: top; padding-bottom: 10px; padding-top: 10px; color: #999999; font-size: 12px; text-align: center;">
Powered by <a href="https://github.com/Ombi-app/Ombi" style="font-weight: 400; font-size: 12px; text-align: center; text-decoration: none; color: #ff761b;">Ombi</a> {@POWEREDBYTEXT} <a href="https://github.com/Ombi-app/Ombi" style="font-weight: 400; font-size: 12px; text-align: center; text-decoration: none; color: #ff761b;">Ombi</a>
</td> </td>
</tr> </tr>
</tbody> </tbody>

View file

@ -17,6 +17,7 @@ using Ombi.Core.Settings;
using Ombi.Core.Settings.Models.External; using Ombi.Core.Settings.Models.External;
using Ombi.Helpers; using Ombi.Helpers;
using Ombi.Hubs; using Ombi.Hubs;
using Ombi.I18n.Resources;
using Ombi.Notifications; using Ombi.Notifications;
using Ombi.Notifications.Models; using Ombi.Notifications.Models;
using Ombi.Notifications.Templates; using Ombi.Notifications.Templates;
@ -264,7 +265,7 @@ namespace Ombi.Schedule.Jobs.Ombi
recentlyAddedLog.Add(new RecentlyAddedLog recentlyAddedLog.Add(new RecentlyAddedLog
{ {
AddedAt = DateTime.Now, AddedAt = DateTime.Now,
Type = p.Series.RecentlyAddedType, Type = p.Series.RecentlyAddedType,
ContentType = ContentType.Episode, ContentType = ContentType.Episode,
ContentId = StringHelper.IntParseLinq(p.Series.TvDbId), ContentId = StringHelper.IntParseLinq(p.Series.TvDbId),
EpisodeNumber = p.EpisodeNumber, EpisodeNumber = p.EpisodeNumber,
@ -311,7 +312,7 @@ namespace Ombi.Schedule.Jobs.Ombi
private HashSet<IMediaServerEpisode> GetSeriesContent<T>(IMediaServerContentRepository<T> repository, bool test) where T : class, IMediaServerContent private HashSet<IMediaServerEpisode> GetSeriesContent<T>(IMediaServerContentRepository<T> repository, bool test) where T : class, IMediaServerContent
{ {
var content = repository.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.Series.AddedAt).AsNoTracking(); var content = repository.GetAllEpisodes().Include(x => x.Series).OrderByDescending(x => x.Series.AddedAt).AsNoTracking();
HashSet<IMediaServerEpisode> episodesToSend; HashSet<IMediaServerEpisode> episodesToSend;
if (test) if (test)
{ {
@ -443,7 +444,7 @@ namespace Ombi.Schedule.Jobs.Ombi
if (movies.Any() && !settings.DisableMovies) if (movies.Any() && !settings.DisableMovies)
{ {
sb.Append("<h1 style=\"text-align: center; max-width: 1042px;\">New Movies</h1><br /><br />"); sb.Append($"<h1 style=\"text-align: center; max-width: 1042px;\">{Texts.NewMovies}</h1><br /><br />");
sb.Append( sb.Append(
"<table class=\"movies-table\" style=\"border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; \">"); "<table class=\"movies-table\" style=\"border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; \">");
sb.Append("<tr>"); sb.Append("<tr>");
@ -460,7 +461,7 @@ namespace Ombi.Schedule.Jobs.Ombi
if (episodes.Any() && !settings.DisableTv) if (episodes.Any() && !settings.DisableTv)
{ {
sb.Append("<br /><br /><h1 style=\"text-align: center; max-width: 1042px;\">New TV</h1><br /><br />"); sb.Append($"<br /><br /><h1 style=\"text-align: center; max-width: 1042px;\">{Texts.NewTV}</h1><br /><br />");
sb.Append( sb.Append(
"<table class=\"tv-table\" style=\"border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; \">"); "<table class=\"tv-table\" style=\"border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; \">");
sb.Append("<tr>"); sb.Append("<tr>");
@ -478,7 +479,7 @@ namespace Ombi.Schedule.Jobs.Ombi
if (albums.Any() && !settings.DisableMusic) if (albums.Any() && !settings.DisableMusic)
{ {
sb.Append("<h1 style=\"text-align: center; max-width: 1042px;\">New Albums</h1><br /><br />"); sb.Append($"<h1 style=\"text-align: center; max-width: 1042px;\">{Texts.NewAlbums}</h1><br /><br />");
sb.Append( sb.Append(
"<table class=\"movies-table\" style=\"border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; \">"); "<table class=\"movies-table\" style=\"border-collapse: separate; mso-table-lspace: 0pt; mso-table-rspace: 0pt; width: 100%; \">");
sb.Append("<tr>"); sb.Append("<tr>");
@ -602,7 +603,7 @@ namespace Ombi.Schedule.Jobs.Ombi
if (info.Genres.Any()) 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())}");
} }
} }
@ -638,7 +639,7 @@ namespace Ombi.Schedule.Jobs.Ombi
} }
AddParagraph(summary); AddParagraph(summary);
AddGenres($"Type: {info.albumType}"); AddGenres($"{Texts.AlbumTypeLabel} {info.albumType}");
} }
private async Task ProcessTv(IEnumerable<IMediaServerEpisode> episodes, string languageCode) private async Task ProcessTv(IEnumerable<IMediaServerEpisode> episodes, string languageCode)
@ -740,7 +741,7 @@ namespace Ombi.Schedule.Jobs.Ombi
var orderedEpisodes = epInformation.Episodes.OrderBy(x => x.EpisodeNumber).ToList(); var orderedEpisodes = epInformation.Episodes.OrderBy(x => x.EpisodeNumber).ToList();
var episodeString = StringHelper.BuildEpisodeList(orderedEpisodes.Select(x => x.EpisodeNumber)); var episodeString = StringHelper.BuildEpisodeList(orderedEpisodes.Select(x => x.EpisodeNumber));
var episodeAirDate = epInformation.EpisodeAirDate; var episodeAirDate = epInformation.EpisodeAirDate;
finalsb.Append($"Season: {epInformation.SeasonNumber} - Episodes: {episodeString} {episodeAirDate}"); finalsb.Append($"{Texts.SeasonLabel} {epInformation.SeasonNumber} - {Texts.EpisodesLabel} {episodeString} {episodeAirDate}");
finalsb.Append("<br />"); finalsb.Append("<br />");
} }
@ -792,7 +793,7 @@ namespace Ombi.Schedule.Jobs.Ombi
if (tvInfo.genres.Any()) 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())}");
} }
} }

View file

@ -18,6 +18,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\Ombi.Helpers\Ombi.Helpers.csproj" /> <ProjectReference Include="..\Ombi.Helpers\Ombi.Helpers.csproj" />
<ProjectReference Include="..\Ombi.I18n\Ombi.I18n.csproj" />
<ProjectReference Include="..\Ombi.Store\Ombi.Store.csproj" /> <ProjectReference Include="..\Ombi.Store\Ombi.Store.csproj" />
</ItemGroup> </ItemGroup>

View file

@ -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 public class OmbiSettings : Settings
{ {
private string defaultLanguageCode = "en";
public string BaseUrl { get; set; } public string BaseUrl { get; set; }
public bool CollectAnalyticData { get; set; } public bool CollectAnalyticData { get; set; }
public bool Wizard { get; set; } public bool Wizard { get; set; }
@ -9,7 +12,14 @@
public bool DoNotSendNotificationsForAutoApprove { get; set; } public bool DoNotSendNotificationsForAutoApprove { get; set; }
public bool HideRequestsUsers { get; set; } public bool HideRequestsUsers { get; set; }
public bool DisableHealthChecks { 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 bool AutoDeleteAvailableRequests { get; set; }
public int AutoDeleteAfterDays { get; set; } public int AutoDeleteAfterDays { get; set; }
public Branch Branch { get; set; } public Branch Branch { get; set; }