diff --git a/src/NzbDrone.Core.Test/Localization/LocalizationServiceFixture.cs b/src/NzbDrone.Core.Test/Localization/LocalizationServiceFixture.cs new file mode 100644 index 000000000..afe51b669 --- /dev/null +++ b/src/NzbDrone.Core.Test/Localization/LocalizationServiceFixture.cs @@ -0,0 +1,81 @@ +using System; +using FluentAssertions; +using NUnit.Framework; +using NzbDrone.Common.EnvironmentInfo; +using NzbDrone.Core.Configuration; +using NzbDrone.Core.Languages; +using NzbDrone.Core.Localization; +using NzbDrone.Core.Test.Framework; +using NzbDrone.Test.Common; + +namespace NzbDrone.Core.Test.Localization +{ + [TestFixture] + public class LocalizationServiceFixture : CoreTest + { + [SetUp] + public void Setup() + { + Mocker.GetMock().Setup(m => m.UILanguage).Returns((int)Language.English); + + Mocker.GetMock().Setup(m => m.StartUpFolder).Returns(TestContext.CurrentContext.TestDirectory); + } + + [Test] + public void should_get_string_in_dictionary_if_lang_exists_and_string_exists() + { + var localizedString = Subject.GetLocalizedString("UiLanguage"); + + localizedString.Should().Be("UI Language"); + } + + [Test] + public void should_get_string_in_french() + { + Mocker.GetMock().Setup(m => m.UILanguage).Returns((int)Language.French); + + var localizedString = Subject.GetLocalizedString("UiLanguage"); + + localizedString.Should().Be("Langue de l'IU"); + + ExceptionVerification.ExpectedErrors(1); + } + + [Test] + public void should_get_string_in_default_dictionary_if_unknown_language_and_string_exists() + { + Mocker.GetMock().Setup(m => m.UILanguage).Returns(0); + var localizedString = Subject.GetLocalizedString("UiLanguage"); + + localizedString.Should().Be("UI Language"); + } + + [Test] + public void should_return_argument_if_string_doesnt_exists() + { + var localizedString = Subject.GetLocalizedString("badString"); + + localizedString.Should().Be("badString"); + } + + [Test] + public void should_return_argument_if_string_doesnt_exists_default_lang() + { + var localizedString = Subject.GetLocalizedString("badString"); + + localizedString.Should().Be("badString"); + } + + [Test] + public void should_throw_if_empty_string_passed() + { + Assert.Throws(() => Subject.GetLocalizedString("")); + } + + [Test] + public void should_throw_if_null_string_passed() + { + Assert.Throws(() => Subject.GetLocalizedString(null)); + } + } +} diff --git a/src/NzbDrone.Core/Localization/LocalizationService.cs b/src/NzbDrone.Core/Localization/LocalizationService.cs index 1a7675253..b62e9c661 100644 --- a/src/NzbDrone.Core/Localization/LocalizationService.cs +++ b/src/NzbDrone.Core/Localization/LocalizationService.cs @@ -2,6 +2,7 @@ using System; using System.Collections.Generic; using System.IO; using System.Text.Json; +using System.Text.RegularExpressions; using System.Threading.Tasks; using NLog; using NzbDrone.Common.Cache; @@ -18,13 +19,16 @@ 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); } 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; @@ -52,22 +56,17 @@ namespace NzbDrone.Core.Localization public string GetLocalizedString(string phrase) { - var language = GetSetLanguageFileName(); - - return GetLocalizedString(phrase, language); + return GetLocalizedString(phrase, new Dictionary()); } - public string GetLocalizedString(string phrase, string language) + public string GetLocalizedString(string phrase, Dictionary tokens) { if (string.IsNullOrEmpty(phrase)) { throw new ArgumentNullException(nameof(phrase)); } - if (language.IsNullOrWhiteSpace()) - { - language = GetSetLanguageFileName(); - } + var language = GetSetLanguageFileName(); if (language == null) { @@ -78,12 +77,26 @@ namespace NzbDrone.Core.Localization if (dictionary.TryGetValue(phrase, out var value)) { - return value; + return ReplaceTokens(value, tokens); } return phrase; } + private string ReplaceTokens(string input, Dictionary tokens) + { + tokens.TryAdd("appName", "Readarr"); + + return TokenRegex.Replace(input, (match) => + { + var tokenName = match.Groups["token"].Value; + + tokens.TryGetValue(tokenName, out var token); + + return token?.ToString() ?? $"{{{tokenName}}}"; + }); + } + private string GetSetLanguageFileName() { var isoLanguage = IsoLanguages.Get((Language)_configService.UILanguage);