mirror of
https://github.com/Prowlarr/Prowlarr.git
synced 2025-10-03 01:01:34 +02:00
Initial support to use named tokens for backend translations
(cherry picked from commit 11f96c31048c2d1aafca0c91736d439f7f9a95a8)
This commit is contained in:
@@ -29,19 +29,22 @@ namespace NzbDrone.Core.Test.Localization
|
|||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_get_string_in_default_dictionary_if_no_lang_exists_and_string_exists()
|
public void should_get_string_in_french()
|
||||||
{
|
{
|
||||||
var localizedString = Subject.GetLocalizedString("BackupNow", "an");
|
Mocker.GetMock<IConfigService>().Setup(m => m.UILanguage).Returns("fr_fr");
|
||||||
|
|
||||||
localizedString.Should().Be("Backup Now");
|
var localizedString = Subject.GetLocalizedString("BackupNow");
|
||||||
|
|
||||||
|
localizedString.Should().Be("Sauvegarder maintenant");
|
||||||
|
|
||||||
ExceptionVerification.ExpectedErrors(1);
|
ExceptionVerification.ExpectedErrors(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
[Test]
|
[Test]
|
||||||
public void should_get_string_in_default_dictionary_if_lang_empty_and_string_exists()
|
public void should_get_string_in_default_dictionary_if_unknown_language_and_string_exists()
|
||||||
{
|
{
|
||||||
var localizedString = Subject.GetLocalizedString("BackupNow", "");
|
Mocker.GetMock<IConfigService>().Setup(m => m.UILanguage).Returns("");
|
||||||
|
var localizedString = Subject.GetLocalizedString("BackupNow");
|
||||||
|
|
||||||
localizedString.Should().Be("Backup Now");
|
localizedString.Should().Be("Backup Now");
|
||||||
}
|
}
|
||||||
@@ -49,7 +52,7 @@ namespace NzbDrone.Core.Test.Localization
|
|||||||
[Test]
|
[Test]
|
||||||
public void should_return_argument_if_string_doesnt_exists()
|
public void should_return_argument_if_string_doesnt_exists()
|
||||||
{
|
{
|
||||||
var localizedString = Subject.GetLocalizedString("BadString", "en");
|
var localizedString = Subject.GetLocalizedString("BadString");
|
||||||
|
|
||||||
localizedString.Should().Be("BadString");
|
localizedString.Should().Be("BadString");
|
||||||
}
|
}
|
||||||
|
@@ -1,12 +1,13 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Text.Json;
|
using System.Text.Json;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using NLog;
|
using NLog;
|
||||||
using NzbDrone.Common.Cache;
|
using NzbDrone.Common.Cache;
|
||||||
using NzbDrone.Common.EnvironmentInfo;
|
using NzbDrone.Common.EnvironmentInfo;
|
||||||
using NzbDrone.Common.Extensions;
|
|
||||||
using NzbDrone.Core.Configuration;
|
using NzbDrone.Core.Configuration;
|
||||||
using NzbDrone.Core.Configuration.Events;
|
using NzbDrone.Core.Configuration.Events;
|
||||||
using NzbDrone.Core.Messaging.Events;
|
using NzbDrone.Core.Messaging.Events;
|
||||||
@@ -16,14 +17,17 @@ namespace NzbDrone.Core.Localization
|
|||||||
public interface ILocalizationService
|
public interface ILocalizationService
|
||||||
{
|
{
|
||||||
Dictionary<string, string> GetLocalizationDictionary();
|
Dictionary<string, string> GetLocalizationDictionary();
|
||||||
|
|
||||||
string GetLocalizedString(string phrase);
|
string GetLocalizedString(string phrase);
|
||||||
string GetLocalizedString(string phrase, string language);
|
string GetLocalizedString(string phrase, Dictionary<string, object> tokens);
|
||||||
IEnumerable<LocalizationOption> GetLocalizationOptions();
|
IEnumerable<LocalizationOption> GetLocalizationOptions();
|
||||||
}
|
}
|
||||||
|
|
||||||
public class LocalizationService : ILocalizationService, IHandleAsync<ConfigSavedEvent>
|
public class LocalizationService : ILocalizationService, IHandleAsync<ConfigSavedEvent>
|
||||||
{
|
{
|
||||||
private const string DefaultCulture = "en";
|
private const string DefaultCulture = "en";
|
||||||
|
private static readonly Regex TokenRegex = new Regex(@"(?:\{)(?<token>[a-z0-9]+)(?:\})",
|
||||||
|
RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant);
|
||||||
|
|
||||||
private readonly ICached<Dictionary<string, string>> _cache;
|
private readonly ICached<Dictionary<string, string>> _cache;
|
||||||
|
|
||||||
@@ -44,30 +48,25 @@ namespace NzbDrone.Core.Localization
|
|||||||
|
|
||||||
public Dictionary<string, string> GetLocalizationDictionary()
|
public Dictionary<string, string> GetLocalizationDictionary()
|
||||||
{
|
{
|
||||||
var language = _configService.UILanguage;
|
var language = GetLanguageFileName();
|
||||||
|
|
||||||
return GetLocalizationDictionary(language);
|
return GetLocalizationDictionary(language);
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetLocalizedString(string phrase)
|
public string GetLocalizedString(string phrase)
|
||||||
{
|
{
|
||||||
var language = _configService.UILanguage;
|
return GetLocalizedString(phrase, new Dictionary<string, object>());
|
||||||
|
|
||||||
return GetLocalizedString(phrase, language);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public string GetLocalizedString(string phrase, string language)
|
public string GetLocalizedString(string phrase, Dictionary<string, object> tokens)
|
||||||
{
|
{
|
||||||
|
var language = GetLanguageFileName();
|
||||||
|
|
||||||
if (string.IsNullOrEmpty(phrase))
|
if (string.IsNullOrEmpty(phrase))
|
||||||
{
|
{
|
||||||
throw new ArgumentNullException(nameof(phrase));
|
throw new ArgumentNullException(nameof(phrase));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (language.IsNullOrWhiteSpace())
|
|
||||||
{
|
|
||||||
language = _configService.UILanguage;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (language == null)
|
if (language == null)
|
||||||
{
|
{
|
||||||
language = DefaultCulture;
|
language = DefaultCulture;
|
||||||
@@ -77,7 +76,7 @@ namespace NzbDrone.Core.Localization
|
|||||||
|
|
||||||
if (dictionary.TryGetValue(phrase, out var value))
|
if (dictionary.TryGetValue(phrase, out var value))
|
||||||
{
|
{
|
||||||
return value;
|
return ReplaceTokens(value, tokens);
|
||||||
}
|
}
|
||||||
|
|
||||||
return phrase;
|
return phrase;
|
||||||
@@ -130,6 +129,30 @@ namespace NzbDrone.Core.Localization
|
|||||||
yield return new LocalizationOption("漢語 (繁体字)", "zh_TW");
|
yield return new LocalizationOption("漢語 (繁体字)", "zh_TW");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public string GetLanguageIdentifier()
|
||||||
|
{
|
||||||
|
return GetLocalizationOptions().FirstOrDefault(l => l.Value == _configService.UILanguage)?.Value ?? DefaultCulture;
|
||||||
|
}
|
||||||
|
|
||||||
|
private string ReplaceTokens(string input, Dictionary<string, object> tokens)
|
||||||
|
{
|
||||||
|
tokens.TryAdd("appName", "Prowlarr");
|
||||||
|
|
||||||
|
return TokenRegex.Replace(input, match =>
|
||||||
|
{
|
||||||
|
var tokenName = match.Groups["token"].Value;
|
||||||
|
|
||||||
|
tokens.TryGetValue(tokenName, out var token);
|
||||||
|
|
||||||
|
return token?.ToString() ?? $"{{{tokenName}}}";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private string GetLanguageFileName()
|
||||||
|
{
|
||||||
|
return GetLanguageIdentifier().Replace("-", "_").ToLowerInvariant();
|
||||||
|
}
|
||||||
|
|
||||||
private Dictionary<string, string> GetLocalizationDictionary(string language)
|
private Dictionary<string, string> GetLocalizationDictionary(string language)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(language))
|
if (string.IsNullOrEmpty(language))
|
||||||
|
Reference in New Issue
Block a user