Add location to LocalizedString and add logging (#331)

This commit is contained in:
Ryan Brandenburg 2017-02-24 10:54:03 -08:00 коммит произвёл GitHub
Родитель 970e2e0782
Коммит 39aa9438ab
10 изменённых файлов: 213 добавлений и 36 удалений

Просмотреть файл

@ -27,6 +27,18 @@ namespace Microsoft.Extensions.Localization
/// <param name="value">The actual string.</param> /// <param name="value">The actual string.</param>
/// <param name="resourceNotFound">Whether the string was not found in a resource. Set this to <c>true</c> to indicate an alternate string value was used.</param> /// <param name="resourceNotFound">Whether the string was not found in a resource. Set this to <c>true</c> to indicate an alternate string value was used.</param>
public LocalizedString(string name, string value, bool resourceNotFound) public LocalizedString(string name, string value, bool resourceNotFound)
: this(name, value, resourceNotFound, searchedLocation: null)
{
}
/// <summary>
/// Creates a new <see cref="LocalizedString"/>.
/// </summary>
/// <param name="name">The name of the string in the resource it was loaded from.</param>
/// <param name="value">The actual string.</param>
/// <param name="resourceNotFound">Whether the string was not found in a resource. Set this to <c>true</c> to indicate an alternate string value was used.</param>
/// <param name="searchedLocation">The location which was searched for a localization value.</param>
public LocalizedString(string name, string value, bool resourceNotFound, string searchedLocation)
{ {
if (name == null) if (name == null)
{ {
@ -41,6 +53,7 @@ namespace Microsoft.Extensions.Localization
Name = name; Name = name;
Value = value; Value = value;
ResourceNotFound = resourceNotFound; ResourceNotFound = resourceNotFound;
SearchedLocation = searchedLocation;
} }
public static implicit operator string(LocalizedString localizedString) public static implicit operator string(LocalizedString localizedString)
@ -63,6 +76,11 @@ namespace Microsoft.Extensions.Localization
/// </summary> /// </summary>
public bool ResourceNotFound { get; } public bool ResourceNotFound { get; }
/// <summary>
/// The location which was searched for a localization value.
/// </summary>
public string SearchedLocation { get; }
/// <summary> /// <summary>
/// Returns the actual string. /// Returns the actual string.
/// </summary> /// </summary>

Просмотреть файл

@ -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<ILogger, string, string, CultureInfo, Exception> _searchedLocation;
static ResourceManagerStringLocalizerLoggerExtensions()
{
_searchedLocation = LoggerMessage.Define<string, string, CultureInfo>(
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);
}
}
}

Просмотреть файл

@ -15,6 +15,7 @@
<ProjectReference Include="..\Microsoft.Extensions.Localization.Abstractions\Microsoft.Extensions.Localization.Abstractions.csproj" /> <ProjectReference Include="..\Microsoft.Extensions.Localization.Abstractions\Microsoft.Extensions.Localization.Abstractions.csproj" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="1.2.0-*" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="1.2.0-*" />
<PackageReference Include="Microsoft.Extensions.Options" Version="1.2.0-*" /> <PackageReference Include="Microsoft.Extensions.Options" Version="1.2.0-*" />
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="1.2.0-*" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' "> <ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' ">

Просмотреть файл

@ -8,6 +8,7 @@ using System.Globalization;
using System.Reflection; using System.Reflection;
using System.Resources; using System.Resources;
using Microsoft.Extensions.Localization.Internal; using Microsoft.Extensions.Localization.Internal;
using Microsoft.Extensions.Logging;
namespace Microsoft.Extensions.Localization namespace Microsoft.Extensions.Localization
{ {
@ -23,6 +24,7 @@ namespace Microsoft.Extensions.Localization
private readonly ResourceManager _resourceManager; private readonly ResourceManager _resourceManager;
private readonly IResourceStringProvider _resourceStringProvider; private readonly IResourceStringProvider _resourceStringProvider;
private readonly string _resourceBaseName; private readonly string _resourceBaseName;
private readonly ILogger _logger;
/// <summary> /// <summary>
/// Creates a new <see cref="ResourceManagerStringLocalizer"/>. /// Creates a new <see cref="ResourceManagerStringLocalizer"/>.
@ -31,16 +33,19 @@ namespace Microsoft.Extensions.Localization
/// <param name="resourceAssembly">The <see cref="Assembly"/> that contains the strings as embedded resources.</param> /// <param name="resourceAssembly">The <see cref="Assembly"/> that contains the strings as embedded resources.</param>
/// <param name="baseName">The base name of the embedded resource that contains the strings.</param> /// <param name="baseName">The base name of the embedded resource that contains the strings.</param>
/// <param name="resourceNamesCache">Cache of the list of strings for a given resource assembly name.</param> /// <param name="resourceNamesCache">Cache of the list of strings for a given resource assembly name.</param>
/// <param name="logger">The <see cref="ILogger"/>.</param>
public ResourceManagerStringLocalizer( public ResourceManagerStringLocalizer(
ResourceManager resourceManager, ResourceManager resourceManager,
Assembly resourceAssembly, Assembly resourceAssembly,
string baseName, string baseName,
IResourceNamesCache resourceNamesCache) IResourceNamesCache resourceNamesCache,
ILogger logger)
: this( : this(
resourceManager, resourceManager,
new AssemblyWrapper(resourceAssembly), new AssemblyWrapper(resourceAssembly),
baseName, baseName,
resourceNamesCache) resourceNamesCache,
logger)
{ {
} }
@ -51,12 +56,14 @@ namespace Microsoft.Extensions.Localization
ResourceManager resourceManager, ResourceManager resourceManager,
AssemblyWrapper resourceAssemblyWrapper, AssemblyWrapper resourceAssemblyWrapper,
string baseName, string baseName,
IResourceNamesCache resourceNamesCache) IResourceNamesCache resourceNamesCache,
ILogger logger)
: this( : this(
resourceManager, resourceManager,
new AssemblyResourceStringProvider(resourceNamesCache, resourceAssemblyWrapper, baseName), new AssemblyResourceStringProvider(resourceNamesCache, resourceAssemblyWrapper, baseName),
baseName, baseName,
resourceNamesCache) resourceNamesCache,
logger)
{ {
} }
@ -67,7 +74,8 @@ namespace Microsoft.Extensions.Localization
ResourceManager resourceManager, ResourceManager resourceManager,
IResourceStringProvider resourceStringProvider, IResourceStringProvider resourceStringProvider,
string baseName, string baseName,
IResourceNamesCache resourceNamesCache) IResourceNamesCache resourceNamesCache,
ILogger logger)
{ {
if (resourceManager == null) if (resourceManager == null)
{ {
@ -89,10 +97,16 @@ namespace Microsoft.Extensions.Localization
throw new ArgumentNullException(nameof(resourceNamesCache)); throw new ArgumentNullException(nameof(resourceNamesCache));
} }
if (logger == null)
{
throw new ArgumentNullException(nameof(logger));
}
_resourceStringProvider = resourceStringProvider; _resourceStringProvider = resourceStringProvider;
_resourceManager = resourceManager; _resourceManager = resourceManager;
_resourceBaseName = baseName; _resourceBaseName = baseName;
_resourceNamesCache = resourceNamesCache; _resourceNamesCache = resourceNamesCache;
_logger = logger;
} }
/// <inheritdoc /> /// <inheritdoc />
@ -107,7 +121,7 @@ namespace Microsoft.Extensions.Localization
var value = GetStringSafely(name, null); 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 format = GetStringSafely(name, null);
var value = string.Format(format ?? name, arguments); 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, _resourceManager,
_resourceStringProvider, _resourceStringProvider,
_resourceBaseName, _resourceBaseName,
_resourceNamesCache) _resourceNamesCache,
_logger)
: new ResourceManagerWithCultureStringLocalizer( : new ResourceManagerWithCultureStringLocalizer(
_resourceManager, _resourceManager,
_resourceStringProvider, _resourceStringProvider,
_resourceBaseName, _resourceBaseName,
_resourceNamesCache, _resourceNamesCache,
culture); culture,
_logger);
} }
/// <inheritdoc /> /// <inheritdoc />
@ -173,7 +189,7 @@ namespace Microsoft.Extensions.Localization
foreach (var name in resourceNames) foreach (var name in resourceNames)
{ {
var value = GetStringSafely(name, culture); 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)); 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)) if (_missingManifestCache.ContainsKey(cacheKey))
{ {

Просмотреть файл

@ -6,6 +6,7 @@ using System.Collections.Concurrent;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using System.Resources; using System.Resources;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
namespace Microsoft.Extensions.Localization namespace Microsoft.Extensions.Localization
@ -24,20 +25,30 @@ namespace Microsoft.Extensions.Localization
private readonly ConcurrentDictionary<string, ResourceManagerStringLocalizer> _localizerCache = private readonly ConcurrentDictionary<string, ResourceManagerStringLocalizer> _localizerCache =
new ConcurrentDictionary<string, ResourceManagerStringLocalizer>(); new ConcurrentDictionary<string, ResourceManagerStringLocalizer>();
private readonly string _resourcesRelativePath; private readonly string _resourcesRelativePath;
private readonly ILoggerFactory _loggerFactory;
/// <summary> /// <summary>
/// Creates a new <see cref="ResourceManagerStringLocalizer"/>. /// Creates a new <see cref="ResourceManagerStringLocalizer"/>.
/// </summary> /// </summary>
/// <param name="localizationOptions">The <see cref="IOptions{LocalizationOptions}"/>.</param> /// <param name="localizationOptions">The <see cref="IOptions{LocalizationOptions}"/>.</param>
/// <param name="loggerFactory">The <see cref="ILoggerFactory"/>.</param>
public ResourceManagerStringLocalizerFactory( public ResourceManagerStringLocalizerFactory(
IOptions<LocalizationOptions> localizationOptions) IOptions<LocalizationOptions> localizationOptions,
ILoggerFactory loggerFactory)
{ {
if (localizationOptions == null) if (localizationOptions == null)
{ {
throw new ArgumentNullException(nameof(localizationOptions)); throw new ArgumentNullException(nameof(localizationOptions));
} }
if (loggerFactory == null)
{
throw new ArgumentNullException(nameof(loggerFactory));
}
_resourcesRelativePath = localizationOptions.Value.ResourcesPath ?? string.Empty; _resourcesRelativePath = localizationOptions.Value.ResourcesPath ?? string.Empty;
_loggerFactory = loggerFactory;
if (!string.IsNullOrEmpty(_resourcesRelativePath)) if (!string.IsNullOrEmpty(_resourcesRelativePath))
{ {
_resourcesRelativePath = _resourcesRelativePath.Replace(Path.AltDirectorySeparatorChar, '.') _resourcesRelativePath = _resourcesRelativePath.Replace(Path.AltDirectorySeparatorChar, '.')
@ -180,7 +191,8 @@ namespace Microsoft.Extensions.Localization
new ResourceManager(baseName, assembly), new ResourceManager(baseName, assembly),
assembly, assembly,
baseName, baseName,
_resourceNamesCache); _resourceNamesCache,
_loggerFactory.CreateLogger<ResourceManagerStringLocalizer>());
} }
/// <summary> /// <summary>

Просмотреть файл

@ -7,6 +7,7 @@ using System.Globalization;
using System.Reflection; using System.Reflection;
using System.Resources; using System.Resources;
using Microsoft.Extensions.Localization.Internal; using Microsoft.Extensions.Localization.Internal;
using Microsoft.Extensions.Logging;
namespace Microsoft.Extensions.Localization namespace Microsoft.Extensions.Localization
{ {
@ -26,13 +27,15 @@ namespace Microsoft.Extensions.Localization
/// <param name="baseName">The base name of the embedded resource that contains the strings.</param> /// <param name="baseName">The base name of the embedded resource that contains the strings.</param>
/// <param name="resourceNamesCache">Cache of the list of strings for a given resource assembly name.</param> /// <param name="resourceNamesCache">Cache of the list of strings for a given resource assembly name.</param>
/// <param name="culture">The specific <see cref="CultureInfo"/> to use.</param> /// <param name="culture">The specific <see cref="CultureInfo"/> to use.</param>
/// <param name="logger">The <see cref="ILogger"/>.</param>
internal ResourceManagerWithCultureStringLocalizer( internal ResourceManagerWithCultureStringLocalizer(
ResourceManager resourceManager, ResourceManager resourceManager,
IResourceStringProvider resourceStringProvider, IResourceStringProvider resourceStringProvider,
string baseName, string baseName,
IResourceNamesCache resourceNamesCache, IResourceNamesCache resourceNamesCache,
CultureInfo culture) CultureInfo culture,
: base(resourceManager, resourceStringProvider, baseName, resourceNamesCache) ILogger logger)
: base(resourceManager, resourceStringProvider, baseName, resourceNamesCache, logger)
{ {
if (resourceManager == null) if (resourceManager == null)
{ {
@ -70,13 +73,15 @@ namespace Microsoft.Extensions.Localization
/// <param name="baseName">The base name of the embedded resource that contains the strings.</param> /// <param name="baseName">The base name of the embedded resource that contains the strings.</param>
/// <param name="resourceNamesCache">Cache of the list of strings for a given resource assembly name.</param> /// <param name="resourceNamesCache">Cache of the list of strings for a given resource assembly name.</param>
/// <param name="culture">The specific <see cref="CultureInfo"/> to use.</param> /// <param name="culture">The specific <see cref="CultureInfo"/> to use.</param>
/// <param name="logger">The <see cref="ILogger"/>.</param>
public ResourceManagerWithCultureStringLocalizer( public ResourceManagerWithCultureStringLocalizer(
ResourceManager resourceManager, ResourceManager resourceManager,
Assembly resourceAssembly, Assembly resourceAssembly,
string baseName, string baseName,
IResourceNamesCache resourceNamesCache, IResourceNamesCache resourceNamesCache,
CultureInfo culture) CultureInfo culture,
: base(resourceManager, resourceAssembly, baseName, resourceNamesCache) ILogger logger)
: base(resourceManager, resourceAssembly, baseName, resourceNamesCache, logger)
{ {
if (resourceManager == null) if (resourceManager == null)
{ {

Просмотреть файл

@ -10,6 +10,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.AspNetCore.Localization\Microsoft.AspNetCore.Localization.csproj" /> <ProjectReference Include="..\..\src\Microsoft.AspNetCore.Localization\Microsoft.AspNetCore.Localization.csproj" />
<PackageReference Include="Microsoft.AspNetCore.TestHost" Version="1.2.0-*" /> <PackageReference Include="Microsoft.AspNetCore.TestHost" Version="1.2.0-*" />
<PackageReference Include="Microsoft.Extensions.Logging" Version="1.2.0-*" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0-*" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0-*" />
<PackageReference Include="xunit" Version="2.2.0-*" /> <PackageReference Include="xunit" Version="2.2.0-*" />
<PackageReference Include="xunit.runner.visualstudio" Version="2.2.0-*" /> <PackageReference Include="xunit.runner.visualstudio" Version="2.2.0-*" />

Просмотреть файл

@ -9,7 +9,9 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\src\Microsoft.Extensions.Localization\Microsoft.Extensions.Localization.csproj" /> <ProjectReference Include="..\..\src\Microsoft.Extensions.Localization\Microsoft.Extensions.Localization.csproj" />
<PackageReference Include="Microsoft.AspNetCore.Testing" Version="1.2.0-*" />
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="1.2.0-*" /> <PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="1.2.0-*" />
<PackageReference Include="Microsoft.Extensions.Logging.Testing" Version="1.2.0-*" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0-*" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="15.0.0-*" />
<PackageReference Include="Moq" Version="4.6.36-*" /> <PackageReference Include="Moq" Version="4.6.36-*" />
<PackageReference Include="xunit" Version="2.2.0-*" /> <PackageReference Include="xunit" Version="2.2.0-*" />

Просмотреть файл

@ -4,6 +4,8 @@
using System; using System;
using System.IO; using System.IO;
using System.Reflection; using System.Reflection;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Testing;
using Microsoft.Extensions.Options; using Microsoft.Extensions.Options;
using Moq; using Moq;
using Xunit; using Xunit;
@ -19,8 +21,9 @@ namespace Microsoft.Extensions.Localization.Tests
public TestResourceManagerStringLocalizerFactory( public TestResourceManagerStringLocalizerFactory(
IOptions<LocalizationOptions> localizationOptions, IOptions<LocalizationOptions> localizationOptions,
ResourceLocationAttribute resourceLocationAttribute) ResourceLocationAttribute resourceLocationAttribute,
: base(localizationOptions) ILoggerFactory loggerFactory)
: base(localizationOptions, loggerFactory)
{ {
_resourceLocationAttribute = resourceLocationAttribute; _resourceLocationAttribute = resourceLocationAttribute;
} }
@ -50,12 +53,15 @@ namespace Microsoft.Extensions.Localization.Tests
options.Setup(o => o.Value).Returns(locOptions); options.Setup(o => o.Value).Returns(locOptions);
var resourceLocationAttribute = new ResourceLocationAttribute(Path.Combine("My", "Resources")); var resourceLocationAttribute = new ResourceLocationAttribute(Path.Combine("My", "Resources"));
var loggerFactory = NullLoggerFactory.Instance;
var typeFactory = new TestResourceManagerStringLocalizerFactory( var typeFactory = new TestResourceManagerStringLocalizerFactory(
options.Object, options.Object,
resourceLocationAttribute); resourceLocationAttribute,
loggerFactory);
var stringFactory = new TestResourceManagerStringLocalizerFactory( var stringFactory = new TestResourceManagerStringLocalizerFactory(
options.Object, options.Object,
resourceLocationAttribute); resourceLocationAttribute,
loggerFactory);
var type = typeof(ResourceManagerStringLocalizerFactoryTest); var type = typeof(ResourceManagerStringLocalizerFactoryTest);
var assemblyName = new AssemblyName(type.GetTypeInfo().Assembly.FullName); var assemblyName = new AssemblyName(type.GetTypeInfo().Assembly.FullName);
@ -75,7 +81,8 @@ namespace Microsoft.Extensions.Localization.Tests
var locOptions = new LocalizationOptions(); var locOptions = new LocalizationOptions();
var options = new Mock<IOptions<LocalizationOptions>>(); var options = new Mock<IOptions<LocalizationOptions>>();
options.Setup(o => o.Value).Returns(locOptions); 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 // Act
var result1 = factory.Create(typeof(ResourceManagerStringLocalizerFactoryTest)); var result1 = factory.Create(typeof(ResourceManagerStringLocalizerFactoryTest));
@ -92,7 +99,8 @@ namespace Microsoft.Extensions.Localization.Tests
var locOptions = new LocalizationOptions(); var locOptions = new LocalizationOptions();
var options = new Mock<IOptions<LocalizationOptions>>(); var options = new Mock<IOptions<LocalizationOptions>>();
options.Setup(o => o.Value).Returns(locOptions); 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 // Act
var result1 = factory.Create(typeof(ResourceManagerStringLocalizerFactoryTest)); var result1 = factory.Create(typeof(ResourceManagerStringLocalizerFactoryTest));
@ -110,9 +118,11 @@ namespace Microsoft.Extensions.Localization.Tests
locOptions.ResourcesPath = Path.Combine("My", "Resources"); locOptions.ResourcesPath = Path.Combine("My", "Resources");
var options = new Mock<IOptions<LocalizationOptions>>(); var options = new Mock<IOptions<LocalizationOptions>>();
options.Setup(o => o.Value).Returns(locOptions); options.Setup(o => o.Value).Returns(locOptions);
var loggerFactory = NullLoggerFactory.Instance;
var factory = new TestResourceManagerStringLocalizerFactory( var factory = new TestResourceManagerStringLocalizerFactory(
options.Object, options.Object,
resourceLocationAttribute: null); resourceLocationAttribute: null,
loggerFactory: loggerFactory);
// Act // Act
factory.Create(typeof(ResourceManagerStringLocalizerFactoryTest)); factory.Create(typeof(ResourceManagerStringLocalizerFactoryTest));
@ -128,7 +138,8 @@ namespace Microsoft.Extensions.Localization.Tests
var locOptions = new LocalizationOptions(); var locOptions = new LocalizationOptions();
var options = new Mock<IOptions<LocalizationOptions>>(); var options = new Mock<IOptions<LocalizationOptions>>();
options.Setup(o => o.Value).Returns(locOptions); 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; var location = typeof(ResourceManagerStringLocalizer).GetTypeInfo().Assembly.FullName;
// Act // Act
@ -146,7 +157,8 @@ namespace Microsoft.Extensions.Localization.Tests
var locOptions = new LocalizationOptions(); var locOptions = new LocalizationOptions();
var options = new Mock<IOptions<LocalizationOptions>>(); var options = new Mock<IOptions<LocalizationOptions>>();
options.Setup(o => o.Value).Returns(locOptions); 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; var location = typeof(ResourceManagerStringLocalizer).GetTypeInfo().Assembly.FullName;
// Act // Act
@ -164,7 +176,8 @@ namespace Microsoft.Extensions.Localization.Tests
var locOptions = new LocalizationOptions(); var locOptions = new LocalizationOptions();
var options = new Mock<IOptions<LocalizationOptions>>(); var options = new Mock<IOptions<LocalizationOptions>>();
options.Setup(o => o.Value).Returns(locOptions); 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 location1 = new AssemblyName(typeof(ResourceManagerStringLocalizer).GetTypeInfo().Assembly.FullName).Name;
var location2 = new AssemblyName(typeof(ResourceManagerStringLocalizerFactoryTest).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"); locOptions.ResourcesPath = Path.Combine("My", "Resources");
var options = new Mock<IOptions<LocalizationOptions>>(); var options = new Mock<IOptions<LocalizationOptions>>();
options.Setup(o => o.Value).Returns(locOptions); options.Setup(o => o.Value).Returns(locOptions);
var loggerFactory = NullLoggerFactory.Instance;
var factory = new TestResourceManagerStringLocalizerFactory( var factory = new TestResourceManagerStringLocalizerFactory(
options.Object, options.Object,
resourceLocationAttribute: null); resourceLocationAttribute: null,
loggerFactory: loggerFactory);
// Act // Act
var result1 = factory.Create("baseName", location: "Microsoft.Extensions.Localization.Tests"); var result1 = factory.Create("baseName", location: "Microsoft.Extensions.Localization.Tests");
@ -202,7 +217,8 @@ namespace Microsoft.Extensions.Localization.Tests
var locOptions = new LocalizationOptions(); var locOptions = new LocalizationOptions();
var options = new Mock<IOptions<LocalizationOptions>>(); var options = new Mock<IOptions<LocalizationOptions>>();
options.Setup(o => o.Value).Returns(locOptions); 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 // Act & Assert
Assert.Throws<ArgumentNullException>(() => factory.Create("baseName", location: null)); Assert.Throws<ArgumentNullException>(() => factory.Create("baseName", location: null));

Просмотреть файл

@ -1,13 +1,15 @@
// Copyright (c) .NET Foundation. All rights reserved. // 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. // 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.Globalization;
using System.IO; using System.IO;
using System.Linq; using System.Linq;
using System.Reflection; using System.Reflection;
using System.Resources; using System.Resources;
using Microsoft.AspNetCore.Testing;
using Microsoft.Extensions.Localization.Internal; using Microsoft.Extensions.Localization.Internal;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Logging.Testing;
using Xunit; using Xunit;
namespace Microsoft.Extensions.Localization.Tests namespace Microsoft.Extensions.Localization.Tests
@ -23,14 +25,17 @@ namespace Microsoft.Extensions.Localization.Tests
var resourceAssembly = new TestAssemblyWrapper(); var resourceAssembly = new TestAssemblyWrapper();
var resourceManager = new TestResourceManager(baseName, resourceAssembly.Assembly); var resourceManager = new TestResourceManager(baseName, resourceAssembly.Assembly);
var resourceStreamManager = new TestResourceStringProvider(resourceNamesCache, resourceAssembly, baseName); var resourceStreamManager = new TestResourceStringProvider(resourceNamesCache, resourceAssembly, baseName);
var logger = Logger;
var localizer1 = new ResourceManagerStringLocalizer(resourceManager, var localizer1 = new ResourceManagerStringLocalizer(resourceManager,
resourceStreamManager, resourceStreamManager,
baseName, baseName,
resourceNamesCache); resourceNamesCache,
logger);
var localizer2 = new ResourceManagerStringLocalizer(resourceManager, var localizer2 = new ResourceManagerStringLocalizer(resourceManager,
resourceStreamManager, resourceStreamManager,
baseName, baseName,
resourceNamesCache); resourceNamesCache,
logger);
// Act // Act
for (int i = 0; i < 5; i++) for (int i = 0; i < 5; i++)
@ -56,16 +61,19 @@ namespace Microsoft.Extensions.Localization.Tests
var resourceManager2 = new TestResourceManager(baseName, resourceAssembly2.Assembly); var resourceManager2 = new TestResourceManager(baseName, resourceAssembly2.Assembly);
var resourceStreamManager1 = new TestResourceStringProvider(resourceNamesCache, resourceAssembly1, baseName); var resourceStreamManager1 = new TestResourceStringProvider(resourceNamesCache, resourceAssembly1, baseName);
var resourceStreamManager2 = new TestResourceStringProvider(resourceNamesCache, resourceAssembly2, baseName); var resourceStreamManager2 = new TestResourceStringProvider(resourceNamesCache, resourceAssembly2, baseName);
var logger = Logger;
var localizer1 = new ResourceManagerStringLocalizer( var localizer1 = new ResourceManagerStringLocalizer(
resourceManager1, resourceManager1,
resourceStreamManager1, resourceStreamManager1,
baseName, baseName,
resourceNamesCache); resourceNamesCache,
logger);
var localizer2 = new ResourceManagerStringLocalizer( var localizer2 = new ResourceManagerStringLocalizer(
resourceManager2, resourceManager2,
resourceStreamManager2, resourceStreamManager2,
baseName, baseName,
resourceNamesCache); resourceNamesCache,
logger);
// Act // Act
localizer1.GetAllStrings().ToList(); localizer1.GetAllStrings().ToList();
@ -77,6 +85,57 @@ namespace Microsoft.Extensions.Localization.Tests
Assert.Equal(expectedCallCount, resourceAssembly2.GetManifestResourceStreamCallCount); 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] [Theory]
[InlineData(true)] [InlineData(true)]
[InlineData(false)] [InlineData(false)]
@ -88,11 +147,13 @@ namespace Microsoft.Extensions.Localization.Tests
var resourceAssembly = new TestAssemblyWrapper(); var resourceAssembly = new TestAssemblyWrapper();
var resourceManager = new TestResourceManager(baseName, resourceAssembly.Assembly); var resourceManager = new TestResourceManager(baseName, resourceAssembly.Assembly);
var resourceStreamManager = new TestResourceStringProvider(resourceNamesCache, resourceAssembly, baseName); var resourceStreamManager = new TestResourceStringProvider(resourceNamesCache, resourceAssembly, baseName);
var logger = Logger;
var localizer = new ResourceManagerStringLocalizer( var localizer = new ResourceManagerStringLocalizer(
resourceManager, resourceManager,
resourceStreamManager, resourceStreamManager,
baseName, baseName,
resourceNamesCache); resourceNamesCache,
logger);
// Act // Act
// We have to access the result so it evaluates. // We have to access the result so it evaluates.
@ -113,12 +174,15 @@ namespace Microsoft.Extensions.Localization.Tests
var baseName = "testington"; var baseName = "testington";
var resourceAssembly = new TestAssemblyWrapper("Assembly1"); var resourceAssembly = new TestAssemblyWrapper("Assembly1");
var resourceManager = new TestResourceManager(baseName, resourceAssembly.Assembly); var resourceManager = new TestResourceManager(baseName, resourceAssembly.Assembly);
var logger = Logger;
var localizer = new ResourceManagerWithCultureStringLocalizer( var localizer = new ResourceManagerWithCultureStringLocalizer(
resourceManager, resourceManager,
resourceAssembly.Assembly, resourceAssembly.Assembly,
baseName, baseName,
resourceNamesCache, resourceNamesCache,
CultureInfo.CurrentCulture); CultureInfo.CurrentCulture,
logger);
// Act & Assert // Act & Assert
var exception = Assert.Throws<MissingManifestResourceException>(() => var exception = Assert.Throws<MissingManifestResourceException>(() =>
@ -162,6 +226,17 @@ namespace Microsoft.Extensions.Localization.Tests
return result; return result;
} }
private TestSink Sink { get; } = new TestSink();
private ILogger Logger
{
get
{
return new TestLoggerFactory(Sink, true).CreateLogger<ResourceManagerStringLocalizer>();
}
}
public class TestResourceManager : ResourceManager public class TestResourceManager : ResourceManager
{ {
public TestResourceManager(string baseName, Assembly assembly) public TestResourceManager(string baseName, Assembly assembly)