From 39aa9438abbaac7a25230dec7d2af4da2a8023bf Mon Sep 17 00:00:00 2001 From: Ryan Brandenburg Date: Fri, 24 Feb 2017 10:54:03 -0800 Subject: [PATCH] Add location to LocalizedString and add logging (#331) --- .../LocalizedString.cs | 18 ++++ ...eManagerStringLocalizerLoggerExtensions.cs | 27 ++++++ .../Microsoft.Extensions.Localization.csproj | 1 + .../ResourceManagerStringLocalizer.cs | 42 ++++++--- .../ResourceManagerStringLocalizerFactory.cs | 16 +++- ...sourceManagerWithCultureStringLocalizer.cs | 13 ++- ...osoft.AspNetCore.Localization.Tests.csproj | 1 + ...osoft.Extensions.Localization.Tests.csproj | 2 + ...sourceManagerStringLocalizerFactoryTest.cs | 40 ++++++--- .../ResourceManagerStringLocalizerTest.cs | 89 +++++++++++++++++-- 10 files changed, 213 insertions(+), 36 deletions(-) create mode 100644 src/Microsoft.Extensions.Localization/Internal/ResourceManagerStringLocalizerLoggerExtensions.cs diff --git a/src/Microsoft.Extensions.Localization.Abstractions/LocalizedString.cs b/src/Microsoft.Extensions.Localization.Abstractions/LocalizedString.cs index d119f4f..6556da4 100644 --- a/src/Microsoft.Extensions.Localization.Abstractions/LocalizedString.cs +++ b/src/Microsoft.Extensions.Localization.Abstractions/LocalizedString.cs @@ -27,6 +27,18 @@ namespace Microsoft.Extensions.Localization /// The actual string. /// Whether the string was not found in a resource. Set this to true to indicate an alternate string value was used. public LocalizedString(string name, string value, bool resourceNotFound) + : this(name, value, resourceNotFound, searchedLocation: null) + { + } + + /// + /// Creates a new . + /// + /// The name of the string in the resource it was loaded from. + /// The actual string. + /// Whether the string was not found in a resource. Set this to true to indicate an alternate string value was used. + /// The location which was searched for a localization value. + public LocalizedString(string name, string value, bool resourceNotFound, string searchedLocation) { if (name == null) { @@ -41,6 +53,7 @@ namespace Microsoft.Extensions.Localization Name = name; Value = value; ResourceNotFound = resourceNotFound; + SearchedLocation = searchedLocation; } public static implicit operator string(LocalizedString localizedString) @@ -63,6 +76,11 @@ namespace Microsoft.Extensions.Localization /// public bool ResourceNotFound { get; } + /// + /// The location which was searched for a localization value. + /// + public string SearchedLocation { get; } + /// /// Returns the actual string. /// diff --git a/src/Microsoft.Extensions.Localization/Internal/ResourceManagerStringLocalizerLoggerExtensions.cs b/src/Microsoft.Extensions.Localization/Internal/ResourceManagerStringLocalizerLoggerExtensions.cs new file mode 100644 index 0000000..456e070 --- /dev/null +++ b/src/Microsoft.Extensions.Localization/Internal/ResourceManagerStringLocalizerLoggerExtensions.cs @@ -0,0 +1,27 @@ +// Copyright (c) .NET Foundation. All rights reserved. +// Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. + +using System; +using System.Globalization; +using Microsoft.Extensions.Logging; + +namespace Microsoft.Extensions.Localization.Internal +{ + internal static class ResourceManagerStringLocalizerLoggerExtensions + { + private static readonly Action _searchedLocation; + + static ResourceManagerStringLocalizerLoggerExtensions() + { + _searchedLocation = LoggerMessage.Define( + LogLevel.Debug, + 1, + $"{nameof(ResourceManagerStringLocalizer)} searched for '{{Key}}' in '{{LocationSearched}}' with culture '{{Culture}}'."); + } + + public static void SearchedLocation(this ILogger logger, string key, string searchedLocation, CultureInfo culture) + { + _searchedLocation(logger, key, searchedLocation, culture, null); + } + } +} diff --git a/src/Microsoft.Extensions.Localization/Microsoft.Extensions.Localization.csproj b/src/Microsoft.Extensions.Localization/Microsoft.Extensions.Localization.csproj index 1918881..3ff4dbd 100644 --- a/src/Microsoft.Extensions.Localization/Microsoft.Extensions.Localization.csproj +++ b/src/Microsoft.Extensions.Localization/Microsoft.Extensions.Localization.csproj @@ -15,6 +15,7 @@ + diff --git a/src/Microsoft.Extensions.Localization/ResourceManagerStringLocalizer.cs b/src/Microsoft.Extensions.Localization/ResourceManagerStringLocalizer.cs index 74611a2..3d9a295 100644 --- a/src/Microsoft.Extensions.Localization/ResourceManagerStringLocalizer.cs +++ b/src/Microsoft.Extensions.Localization/ResourceManagerStringLocalizer.cs @@ -8,6 +8,7 @@ using System.Globalization; using System.Reflection; using System.Resources; using Microsoft.Extensions.Localization.Internal; +using Microsoft.Extensions.Logging; namespace Microsoft.Extensions.Localization { @@ -23,6 +24,7 @@ namespace Microsoft.Extensions.Localization private readonly ResourceManager _resourceManager; private readonly IResourceStringProvider _resourceStringProvider; private readonly string _resourceBaseName; + private readonly ILogger _logger; /// /// Creates a new . @@ -31,16 +33,19 @@ namespace Microsoft.Extensions.Localization /// The that contains the strings as embedded resources. /// The base name of the embedded resource that contains the strings. /// Cache of the list of strings for a given resource assembly name. + /// The . public ResourceManagerStringLocalizer( ResourceManager resourceManager, Assembly resourceAssembly, string baseName, - IResourceNamesCache resourceNamesCache) + IResourceNamesCache resourceNamesCache, + ILogger logger) : this( resourceManager, new AssemblyWrapper(resourceAssembly), baseName, - resourceNamesCache) + resourceNamesCache, + logger) { } @@ -51,12 +56,14 @@ namespace Microsoft.Extensions.Localization ResourceManager resourceManager, AssemblyWrapper resourceAssemblyWrapper, string baseName, - IResourceNamesCache resourceNamesCache) + IResourceNamesCache resourceNamesCache, + ILogger logger) : this( resourceManager, new AssemblyResourceStringProvider(resourceNamesCache, resourceAssemblyWrapper, baseName), baseName, - resourceNamesCache) + resourceNamesCache, + logger) { } @@ -67,7 +74,8 @@ namespace Microsoft.Extensions.Localization ResourceManager resourceManager, IResourceStringProvider resourceStringProvider, string baseName, - IResourceNamesCache resourceNamesCache) + IResourceNamesCache resourceNamesCache, + ILogger logger) { if (resourceManager == null) { @@ -89,10 +97,16 @@ namespace Microsoft.Extensions.Localization throw new ArgumentNullException(nameof(resourceNamesCache)); } + if (logger == null) + { + throw new ArgumentNullException(nameof(logger)); + } + _resourceStringProvider = resourceStringProvider; _resourceManager = resourceManager; _resourceBaseName = baseName; _resourceNamesCache = resourceNamesCache; + _logger = logger; } /// @@ -107,7 +121,7 @@ namespace Microsoft.Extensions.Localization var value = GetStringSafely(name, null); - return new LocalizedString(name, value ?? name, resourceNotFound: value == null); + return new LocalizedString(name, value ?? name, resourceNotFound: value == null, searchedLocation: _resourceBaseName); } } @@ -124,7 +138,7 @@ namespace Microsoft.Extensions.Localization var format = GetStringSafely(name, null); var value = string.Format(format ?? name, arguments); - return new LocalizedString(name, value, resourceNotFound: format == null); + return new LocalizedString(name, value, resourceNotFound: format == null, searchedLocation: _resourceBaseName); } } @@ -140,13 +154,15 @@ namespace Microsoft.Extensions.Localization _resourceManager, _resourceStringProvider, _resourceBaseName, - _resourceNamesCache) + _resourceNamesCache, + _logger) : new ResourceManagerWithCultureStringLocalizer( _resourceManager, _resourceStringProvider, _resourceBaseName, _resourceNamesCache, - culture); + culture, + _logger); } /// @@ -173,7 +189,7 @@ namespace Microsoft.Extensions.Localization foreach (var name in resourceNames) { var value = GetStringSafely(name, culture); - yield return new LocalizedString(name, value ?? name, resourceNotFound: value == null); + yield return new LocalizedString(name, value ?? name, resourceNotFound: value == null, searchedLocation: _resourceBaseName); } } @@ -191,7 +207,11 @@ namespace Microsoft.Extensions.Localization throw new ArgumentNullException(nameof(name)); } - var cacheKey = $"name={name}&culture={(culture ?? CultureInfo.CurrentUICulture).Name}"; + var keyCulture = culture ?? CultureInfo.CurrentUICulture; + + var cacheKey = $"name={name}&culture={keyCulture.Name}"; + + _logger.SearchedLocation(name, _resourceBaseName, keyCulture); if (_missingManifestCache.ContainsKey(cacheKey)) { diff --git a/src/Microsoft.Extensions.Localization/ResourceManagerStringLocalizerFactory.cs b/src/Microsoft.Extensions.Localization/ResourceManagerStringLocalizerFactory.cs index 51fe250..4a8b43b 100644 --- a/src/Microsoft.Extensions.Localization/ResourceManagerStringLocalizerFactory.cs +++ b/src/Microsoft.Extensions.Localization/ResourceManagerStringLocalizerFactory.cs @@ -6,6 +6,7 @@ using System.Collections.Concurrent; using System.IO; using System.Reflection; using System.Resources; +using Microsoft.Extensions.Logging; using Microsoft.Extensions.Options; namespace Microsoft.Extensions.Localization @@ -24,20 +25,30 @@ namespace Microsoft.Extensions.Localization private readonly ConcurrentDictionary _localizerCache = new ConcurrentDictionary(); private readonly string _resourcesRelativePath; + private readonly ILoggerFactory _loggerFactory; /// /// Creates a new . /// /// The . + /// The . public ResourceManagerStringLocalizerFactory( - IOptions localizationOptions) + IOptions localizationOptions, + ILoggerFactory loggerFactory) { if (localizationOptions == null) { throw new ArgumentNullException(nameof(localizationOptions)); } + if (loggerFactory == null) + { + throw new ArgumentNullException(nameof(loggerFactory)); + } + _resourcesRelativePath = localizationOptions.Value.ResourcesPath ?? string.Empty; + _loggerFactory = loggerFactory; + if (!string.IsNullOrEmpty(_resourcesRelativePath)) { _resourcesRelativePath = _resourcesRelativePath.Replace(Path.AltDirectorySeparatorChar, '.') @@ -180,7 +191,8 @@ namespace Microsoft.Extensions.Localization new ResourceManager(baseName, assembly), assembly, baseName, - _resourceNamesCache); + _resourceNamesCache, + _loggerFactory.CreateLogger()); } /// diff --git a/src/Microsoft.Extensions.Localization/ResourceManagerWithCultureStringLocalizer.cs b/src/Microsoft.Extensions.Localization/ResourceManagerWithCultureStringLocalizer.cs index 3cd0b89..c6c7b37 100644 --- a/src/Microsoft.Extensions.Localization/ResourceManagerWithCultureStringLocalizer.cs +++ b/src/Microsoft.Extensions.Localization/ResourceManagerWithCultureStringLocalizer.cs @@ -7,6 +7,7 @@ using System.Globalization; using System.Reflection; using System.Resources; using Microsoft.Extensions.Localization.Internal; +using Microsoft.Extensions.Logging; namespace Microsoft.Extensions.Localization { @@ -26,13 +27,15 @@ namespace Microsoft.Extensions.Localization /// The base name of the embedded resource that contains the strings. /// Cache of the list of strings for a given resource assembly name. /// The specific to use. + /// The . internal ResourceManagerWithCultureStringLocalizer( ResourceManager resourceManager, IResourceStringProvider resourceStringProvider, string baseName, IResourceNamesCache resourceNamesCache, - CultureInfo culture) - : base(resourceManager, resourceStringProvider, baseName, resourceNamesCache) + CultureInfo culture, + ILogger logger) + : base(resourceManager, resourceStringProvider, baseName, resourceNamesCache, logger) { if (resourceManager == null) { @@ -70,13 +73,15 @@ namespace Microsoft.Extensions.Localization /// The base name of the embedded resource that contains the strings. /// Cache of the list of strings for a given resource assembly name. /// The specific to use. + /// The . public ResourceManagerWithCultureStringLocalizer( ResourceManager resourceManager, Assembly resourceAssembly, string baseName, IResourceNamesCache resourceNamesCache, - CultureInfo culture) - : base(resourceManager, resourceAssembly, baseName, resourceNamesCache) + CultureInfo culture, + ILogger logger) + : base(resourceManager, resourceAssembly, baseName, resourceNamesCache, logger) { if (resourceManager == null) { diff --git a/test/Microsoft.AspNetCore.Localization.Tests/Microsoft.AspNetCore.Localization.Tests.csproj b/test/Microsoft.AspNetCore.Localization.Tests/Microsoft.AspNetCore.Localization.Tests.csproj index 4271e2a..56e06f7 100644 --- a/test/Microsoft.AspNetCore.Localization.Tests/Microsoft.AspNetCore.Localization.Tests.csproj +++ b/test/Microsoft.AspNetCore.Localization.Tests/Microsoft.AspNetCore.Localization.Tests.csproj @@ -10,6 +10,7 @@ + diff --git a/test/Microsoft.Extensions.Localization.Tests/Microsoft.Extensions.Localization.Tests.csproj b/test/Microsoft.Extensions.Localization.Tests/Microsoft.Extensions.Localization.Tests.csproj index 0d5670a..deac0c5 100644 --- a/test/Microsoft.Extensions.Localization.Tests/Microsoft.Extensions.Localization.Tests.csproj +++ b/test/Microsoft.Extensions.Localization.Tests/Microsoft.Extensions.Localization.Tests.csproj @@ -9,7 +9,9 @@ + + diff --git a/test/Microsoft.Extensions.Localization.Tests/ResourceManagerStringLocalizerFactoryTest.cs b/test/Microsoft.Extensions.Localization.Tests/ResourceManagerStringLocalizerFactoryTest.cs index 2643ab1..01b495b 100644 --- a/test/Microsoft.Extensions.Localization.Tests/ResourceManagerStringLocalizerFactoryTest.cs +++ b/test/Microsoft.Extensions.Localization.Tests/ResourceManagerStringLocalizerFactoryTest.cs @@ -4,6 +4,8 @@ using System; using System.IO; using System.Reflection; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Testing; using Microsoft.Extensions.Options; using Moq; using Xunit; @@ -19,8 +21,9 @@ namespace Microsoft.Extensions.Localization.Tests public TestResourceManagerStringLocalizerFactory( IOptions localizationOptions, - ResourceLocationAttribute resourceLocationAttribute) - : base(localizationOptions) + ResourceLocationAttribute resourceLocationAttribute, + ILoggerFactory loggerFactory) + : base(localizationOptions, loggerFactory) { _resourceLocationAttribute = resourceLocationAttribute; } @@ -50,12 +53,15 @@ namespace Microsoft.Extensions.Localization.Tests options.Setup(o => o.Value).Returns(locOptions); var resourceLocationAttribute = new ResourceLocationAttribute(Path.Combine("My", "Resources")); + var loggerFactory = NullLoggerFactory.Instance; var typeFactory = new TestResourceManagerStringLocalizerFactory( options.Object, - resourceLocationAttribute); + resourceLocationAttribute, + loggerFactory); var stringFactory = new TestResourceManagerStringLocalizerFactory( options.Object, - resourceLocationAttribute); + resourceLocationAttribute, + loggerFactory); var type = typeof(ResourceManagerStringLocalizerFactoryTest); var assemblyName = new AssemblyName(type.GetTypeInfo().Assembly.FullName); @@ -75,7 +81,8 @@ namespace Microsoft.Extensions.Localization.Tests var locOptions = new LocalizationOptions(); var options = new Mock>(); options.Setup(o => o.Value).Returns(locOptions); - var factory = new ResourceManagerStringLocalizerFactory(localizationOptions: options.Object); + var loggerFactory = NullLoggerFactory.Instance; + var factory = new ResourceManagerStringLocalizerFactory(localizationOptions: options.Object, loggerFactory: loggerFactory); // Act var result1 = factory.Create(typeof(ResourceManagerStringLocalizerFactoryTest)); @@ -92,7 +99,8 @@ namespace Microsoft.Extensions.Localization.Tests var locOptions = new LocalizationOptions(); var options = new Mock>(); options.Setup(o => o.Value).Returns(locOptions); - var factory = new ResourceManagerStringLocalizerFactory(localizationOptions: options.Object); + var loggerFactory = NullLoggerFactory.Instance; + var factory = new ResourceManagerStringLocalizerFactory(localizationOptions: options.Object, loggerFactory: loggerFactory); // Act var result1 = factory.Create(typeof(ResourceManagerStringLocalizerFactoryTest)); @@ -110,9 +118,11 @@ namespace Microsoft.Extensions.Localization.Tests locOptions.ResourcesPath = Path.Combine("My", "Resources"); var options = new Mock>(); options.Setup(o => o.Value).Returns(locOptions); + var loggerFactory = NullLoggerFactory.Instance; var factory = new TestResourceManagerStringLocalizerFactory( options.Object, - resourceLocationAttribute: null); + resourceLocationAttribute: null, + loggerFactory: loggerFactory); // Act factory.Create(typeof(ResourceManagerStringLocalizerFactoryTest)); @@ -128,7 +138,8 @@ namespace Microsoft.Extensions.Localization.Tests var locOptions = new LocalizationOptions(); var options = new Mock>(); options.Setup(o => o.Value).Returns(locOptions); - var factory = new ResourceManagerStringLocalizerFactory(localizationOptions: options.Object); + var loggerFactory = NullLoggerFactory.Instance; + var factory = new ResourceManagerStringLocalizerFactory(localizationOptions: options.Object, loggerFactory: loggerFactory); var location = typeof(ResourceManagerStringLocalizer).GetTypeInfo().Assembly.FullName; // Act @@ -146,7 +157,8 @@ namespace Microsoft.Extensions.Localization.Tests var locOptions = new LocalizationOptions(); var options = new Mock>(); options.Setup(o => o.Value).Returns(locOptions); - var factory = new ResourceManagerStringLocalizerFactory(localizationOptions: options.Object); + var loggerFactory = NullLoggerFactory.Instance; + var factory = new ResourceManagerStringLocalizerFactory(localizationOptions: options.Object, loggerFactory: loggerFactory); var location = typeof(ResourceManagerStringLocalizer).GetTypeInfo().Assembly.FullName; // Act @@ -164,7 +176,8 @@ namespace Microsoft.Extensions.Localization.Tests var locOptions = new LocalizationOptions(); var options = new Mock>(); options.Setup(o => o.Value).Returns(locOptions); - var factory = new ResourceManagerStringLocalizerFactory(localizationOptions: options.Object); + var loggerFactory = NullLoggerFactory.Instance; + var factory = new ResourceManagerStringLocalizerFactory(localizationOptions: options.Object, loggerFactory: loggerFactory); var location1 = new AssemblyName(typeof(ResourceManagerStringLocalizer).GetTypeInfo().Assembly.FullName).Name; var location2 = new AssemblyName(typeof(ResourceManagerStringLocalizerFactoryTest).GetTypeInfo().Assembly.FullName).Name; @@ -184,9 +197,11 @@ namespace Microsoft.Extensions.Localization.Tests locOptions.ResourcesPath = Path.Combine("My", "Resources"); var options = new Mock>(); options.Setup(o => o.Value).Returns(locOptions); + var loggerFactory = NullLoggerFactory.Instance; var factory = new TestResourceManagerStringLocalizerFactory( options.Object, - resourceLocationAttribute: null); + resourceLocationAttribute: null, + loggerFactory: loggerFactory); // Act var result1 = factory.Create("baseName", location: "Microsoft.Extensions.Localization.Tests"); @@ -202,7 +217,8 @@ namespace Microsoft.Extensions.Localization.Tests var locOptions = new LocalizationOptions(); var options = new Mock>(); options.Setup(o => o.Value).Returns(locOptions); - var factory = new ResourceManagerStringLocalizerFactory(localizationOptions: options.Object); + var loggerFactory = NullLoggerFactory.Instance; + var factory = new ResourceManagerStringLocalizerFactory(localizationOptions: options.Object, loggerFactory: loggerFactory); // Act & Assert Assert.Throws(() => factory.Create("baseName", location: null)); diff --git a/test/Microsoft.Extensions.Localization.Tests/ResourceManagerStringLocalizerTest.cs b/test/Microsoft.Extensions.Localization.Tests/ResourceManagerStringLocalizerTest.cs index a3fada4..ed68111 100644 --- a/test/Microsoft.Extensions.Localization.Tests/ResourceManagerStringLocalizerTest.cs +++ b/test/Microsoft.Extensions.Localization.Tests/ResourceManagerStringLocalizerTest.cs @@ -1,13 +1,15 @@ // Copyright (c) .NET Foundation. All rights reserved. // Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. -using System; using System.Globalization; using System.IO; using System.Linq; using System.Reflection; using System.Resources; +using Microsoft.AspNetCore.Testing; using Microsoft.Extensions.Localization.Internal; +using Microsoft.Extensions.Logging; +using Microsoft.Extensions.Logging.Testing; using Xunit; namespace Microsoft.Extensions.Localization.Tests @@ -23,14 +25,17 @@ namespace Microsoft.Extensions.Localization.Tests var resourceAssembly = new TestAssemblyWrapper(); var resourceManager = new TestResourceManager(baseName, resourceAssembly.Assembly); var resourceStreamManager = new TestResourceStringProvider(resourceNamesCache, resourceAssembly, baseName); + var logger = Logger; var localizer1 = new ResourceManagerStringLocalizer(resourceManager, resourceStreamManager, baseName, - resourceNamesCache); + resourceNamesCache, + logger); var localizer2 = new ResourceManagerStringLocalizer(resourceManager, resourceStreamManager, baseName, - resourceNamesCache); + resourceNamesCache, + logger); // Act for (int i = 0; i < 5; i++) @@ -56,16 +61,19 @@ namespace Microsoft.Extensions.Localization.Tests var resourceManager2 = new TestResourceManager(baseName, resourceAssembly2.Assembly); var resourceStreamManager1 = new TestResourceStringProvider(resourceNamesCache, resourceAssembly1, baseName); var resourceStreamManager2 = new TestResourceStringProvider(resourceNamesCache, resourceAssembly2, baseName); + var logger = Logger; var localizer1 = new ResourceManagerStringLocalizer( resourceManager1, resourceStreamManager1, baseName, - resourceNamesCache); + resourceNamesCache, + logger); var localizer2 = new ResourceManagerStringLocalizer( resourceManager2, resourceStreamManager2, baseName, - resourceNamesCache); + resourceNamesCache, + logger); // Act localizer1.GetAllStrings().ToList(); @@ -77,6 +85,57 @@ namespace Microsoft.Extensions.Localization.Tests Assert.Equal(expectedCallCount, resourceAssembly2.GetManifestResourceStreamCallCount); } + [Fact] + public void GetString_PopulatesSearchedLocationOnLocalizedString() + { + // Arrange + var baseName = "Resources.TestResource"; + var resourceNamesCache = new ResourceNamesCache(); + var resourceAssembly = new TestAssemblyWrapper(); + var resourceManager = new TestResourceManager(baseName, resourceAssembly.Assembly); + var resourceStreamManager = new TestResourceStringProvider(resourceNamesCache, resourceAssembly, baseName); + var logger = Logger; + var localizer = new ResourceManagerStringLocalizer( + resourceManager, + resourceStreamManager, + baseName, + resourceNamesCache, + logger); + + // Act + var value = localizer["name"]; + + // Assert + Assert.Equal("Resources.TestResource", value.SearchedLocation); + } + + [Fact] + [ReplaceCulture("en-US", "en-US")] + public void GetString_LogsLocationSearched() + { + // Arrange + var baseName = "Resources.TestResource"; + var resourceNamesCache = new ResourceNamesCache(); + var resourceAssembly = new TestAssemblyWrapper(); + var resourceManager = new TestResourceManager(baseName, resourceAssembly.Assembly); + var resourceStreamManager = new TestResourceStringProvider(resourceNamesCache, resourceAssembly, baseName); + var logger = Logger; + + var localizer = new ResourceManagerStringLocalizer( + resourceManager, + resourceStreamManager, + baseName, + resourceNamesCache, + logger); + + // Act + var value = localizer["a key!"]; + + // Assert + Assert.Equal(1, Sink.Writes.Count); + Assert.Equal("ResourceManagerStringLocalizer searched for 'a key!' in 'Resources.TestResource' with culture 'en-US'.", Sink.Writes.First().State.ToString()); + } + [Theory] [InlineData(true)] [InlineData(false)] @@ -88,11 +147,13 @@ namespace Microsoft.Extensions.Localization.Tests var resourceAssembly = new TestAssemblyWrapper(); var resourceManager = new TestResourceManager(baseName, resourceAssembly.Assembly); var resourceStreamManager = new TestResourceStringProvider(resourceNamesCache, resourceAssembly, baseName); + var logger = Logger; var localizer = new ResourceManagerStringLocalizer( resourceManager, resourceStreamManager, baseName, - resourceNamesCache); + resourceNamesCache, + logger); // Act // We have to access the result so it evaluates. @@ -113,12 +174,15 @@ namespace Microsoft.Extensions.Localization.Tests var baseName = "testington"; var resourceAssembly = new TestAssemblyWrapper("Assembly1"); var resourceManager = new TestResourceManager(baseName, resourceAssembly.Assembly); + var logger = Logger; + var localizer = new ResourceManagerWithCultureStringLocalizer( resourceManager, resourceAssembly.Assembly, baseName, resourceNamesCache, - CultureInfo.CurrentCulture); + CultureInfo.CurrentCulture, + logger); // Act & Assert var exception = Assert.Throws(() => @@ -162,6 +226,17 @@ namespace Microsoft.Extensions.Localization.Tests return result; } + + private TestSink Sink { get; } = new TestSink(); + + private ILogger Logger + { + get + { + return new TestLoggerFactory(Sink, true).CreateLogger(); + } + } + public class TestResourceManager : ResourceManager { public TestResourceManager(string baseName, Assembly assembly)