diff --git a/src/NzbDrone.Core.Test/Localization/LocalizationServiceFixture.cs b/src/NzbDrone.Core.Test/Localization/LocalizationServiceFixture.cs index e49b0592d..9e8ee6d94 100644 --- a/src/NzbDrone.Core.Test/Localization/LocalizationServiceFixture.cs +++ b/src/NzbDrone.Core.Test/Localization/LocalizationServiceFixture.cs @@ -29,19 +29,22 @@ namespace NzbDrone.Core.Test.Localization } [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().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); } [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().Setup(m => m.UILanguage).Returns(""); + var localizedString = Subject.GetLocalizedString("BackupNow"); localizedString.Should().Be("Backup Now"); } @@ -49,7 +52,7 @@ namespace NzbDrone.Core.Test.Localization [Test] public void should_return_argument_if_string_doesnt_exists() { - var localizedString = Subject.GetLocalizedString("BadString", "en"); + var localizedString = Subject.GetLocalizedString("BadString"); localizedString.Should().Be("BadString"); } diff --git a/src/NzbDrone.Core/Localization/LocalizationService.cs b/src/NzbDrone.Core/Localization/LocalizationService.cs index a73cdc9bf..c534336f3 100644 --- a/src/NzbDrone.Core/Localization/LocalizationService.cs +++ b/src/NzbDrone.Core/Localization/LocalizationService.cs @@ -1,12 +1,13 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using System.Text.Json; +using System.Text.RegularExpressions; using System.Threading.Tasks; using NLog; using NzbDrone.Common.Cache; using NzbDrone.Common.EnvironmentInfo; -using NzbDrone.Common.Extensions; using NzbDrone.Core.Configuration; using NzbDrone.Core.Configuration.Events; using NzbDrone.Core.Messaging.Events; @@ -16,14 +17,17 @@ namespace NzbDrone.Core.Localization public interface ILocalizationService { Dictionary GetLocalizationDictionary(); + string GetLocalizedString(string phrase); - string GetLocalizedString(string phrase, string language); + string GetLocalizedString(string phrase, Dictionary tokens); IEnumerable GetLocalizationOptions(); } public class LocalizationService : ILocalizationService, IHandleAsync { private const string DefaultCulture = "en"; + private static readonly Regex TokenRegex = new Regex(@"(?:\{)(?[a-z0-9]+)(?:\})", + RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); private readonly ICached> _cache; @@ -44,30 +48,25 @@ namespace NzbDrone.Core.Localization public Dictionary GetLocalizationDictionary() { - var language = _configService.UILanguage; + var language = GetLanguageFileName(); return GetLocalizationDictionary(language); } public string GetLocalizedString(string phrase) { - var language = _configService.UILanguage; - - return GetLocalizedString(phrase, language); + return GetLocalizedString(phrase, new Dictionary()); } - public string GetLocalizedString(string phrase, string language) + public string GetLocalizedString(string phrase, Dictionary tokens) { + var language = GetLanguageFileName(); + if (string.IsNullOrEmpty(phrase)) { throw new ArgumentNullException(nameof(phrase)); } - if (language.IsNullOrWhiteSpace()) - { - language = _configService.UILanguage; - } - if (language == null) { language = DefaultCulture; @@ -77,7 +76,7 @@ namespace NzbDrone.Core.Localization if (dictionary.TryGetValue(phrase, out var value)) { - return value; + return ReplaceTokens(value, tokens); } return phrase; @@ -130,6 +129,30 @@ namespace NzbDrone.Core.Localization 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 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 GetLocalizationDictionary(string language) { if (string.IsNullOrEmpty(language))