Initial support to use named tokens for backend translations

(cherry picked from commit 11f96c31048c2d1aafca0c91736d439f7f9a95a8)
pull/1934/head
Mark McDowall 1 year ago committed by Bogdan
parent 9c243c7e0d
commit fab4bd5ead

@ -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))

Loading…
Cancel
Save