From aeb01875f2590336c63d2d4e6ca6791e38c6b0ef Mon Sep 17 00:00:00 2001 From: Hisham Bin Ateya Date: Mon, 18 Mar 2024 23:44:59 +0300 Subject: [PATCH 1/2] Remove warnings --- src/My.Extensions.Localization.Json/JsonStringLocalizer.cs | 2 +- .../JsonStringLocalizerFactoryTests.cs | 4 ++-- .../JsonStringLocalizerTests.cs | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) diff --git a/src/My.Extensions.Localization.Json/JsonStringLocalizer.cs b/src/My.Extensions.Localization.Json/JsonStringLocalizer.cs index d60aff8..2d45c7c 100644 --- a/src/My.Extensions.Localization.Json/JsonStringLocalizer.cs +++ b/src/My.Extensions.Localization.Json/JsonStringLocalizer.cs @@ -19,7 +19,7 @@ public class JsonStringLocalizer : IStringLocalizer private readonly IResourceStringProvider _resourceStringProvider; private readonly ILogger _logger; - private string _searchedLocation; + private string _searchedLocation = string.Empty; public JsonStringLocalizer( JsonResourceManager jsonResourceManager, diff --git a/test/My.Extensions.Localization.Json.Tests/JsonStringLocalizerFactoryTests.cs b/test/My.Extensions.Localization.Json.Tests/JsonStringLocalizerFactoryTests.cs index 1bf46c9..2687450 100644 --- a/test/My.Extensions.Localization.Json.Tests/JsonStringLocalizerFactoryTests.cs +++ b/test/My.Extensions.Localization.Json.Tests/JsonStringLocalizerFactoryTests.cs @@ -95,7 +95,7 @@ public async Task LocalizerReturnsTranslationFromInnerClass() { app.UseRequestLocalization("en", "ar"); - app.Run(context => + app.Run(async context => { var localizer = context.RequestServices.GetService>(); @@ -103,7 +103,7 @@ public async Task LocalizerReturnsTranslationFromInnerClass() Assert.Equal("مرحباً", localizer["Hello"]); - return Task.FromResult(0); + await Task.CompletedTask; }); }); diff --git a/test/My.Extensions.Localization.Json.Tests/JsonStringLocalizerTests.cs b/test/My.Extensions.Localization.Json.Tests/JsonStringLocalizerTests.cs index a2f7765..5b3cdae 100644 --- a/test/My.Extensions.Localization.Json.Tests/JsonStringLocalizerTests.cs +++ b/test/My.Extensions.Localization.Json.Tests/JsonStringLocalizerTests.cs @@ -149,7 +149,7 @@ public async void CultureBasedResourcesUsesIStringLocalizer() { app.UseRequestLocalization("en-US", "fr-FR"); - app.Run(context => + app.Run(async context => { var localizer = context.RequestServices.GetService>(); @@ -157,7 +157,7 @@ public async void CultureBasedResourcesUsesIStringLocalizer() Assert.Equal("Bonjour", localizer["Hello"]); - return Task.FromResult(0); + await Task.CompletedTask; }); }); From d6088760d6177f3ebbcb43b933a332b00a157c97 Mon Sep 17 00:00:00 2001 From: Hisham Bin Ateya Date: Tue, 19 Mar 2024 00:27:15 +0300 Subject: [PATCH 2/2] Refactoring --- .../Caching/IResourceNamesCache.cs | 9 +- .../Caching/ResourceNamesCache.cs | 15 +- .../Internal/IResourceStringProvider.cs | 9 +- .../Internal/JsonResourceManager.cs | 249 +++++++-------- .../JsonStringLocalizerLoggerExtensions.cs | 29 +- .../Internal/JsonStringProvider.cs | 62 ++-- .../Internal/PathHelpers.cs | 10 +- .../Internal/StringLocalizer.cs | 27 +- .../JsonLocalizationOptions.cs | 9 +- ...LocalizationServiceCollectionExtensions.cs | 84 +++-- .../JsonStringLocalizer.cs | 206 ++++++------ .../JsonStringLocalizerFactory.cs | 196 ++++++------ .../ResourcesType.cs | 11 +- .../StringLocalizerExtensions.cs | 14 +- .../LocalizationMvcSampleTests.cs | 140 ++++----- .../Common/LocalizationHelper.cs | 13 +- .../Common/Test.cs | 7 +- ...izationServiceCollectionExtensionsTests.cs | 79 +++-- .../JsonStringLocalizerFactoryTests.cs | 215 +++++++------ .../JsonStringLocalizerTests.cs | 293 +++++++++--------- .../ServiceCollectionExtensions.cs | 43 ++- 21 files changed, 807 insertions(+), 913 deletions(-) diff --git a/src/My.Extensions.Localization.Json/Caching/IResourceNamesCache.cs b/src/My.Extensions.Localization.Json/Caching/IResourceNamesCache.cs index 06d3933..ab23c6e 100644 --- a/src/My.Extensions.Localization.Json/Caching/IResourceNamesCache.cs +++ b/src/My.Extensions.Localization.Json/Caching/IResourceNamesCache.cs @@ -1,10 +1,9 @@ using System; using System.Collections.Generic; -namespace My.Extensions.Localization.Json.Caching +namespace My.Extensions.Localization.Json.Caching; + +public interface IResourceNamesCache { - public interface IResourceNamesCache - { - IList GetOrAdd(string name, Func> valueFactory); - } + IList GetOrAdd(string name, Func> valueFactory); } diff --git a/src/My.Extensions.Localization.Json/Caching/ResourceNamesCache.cs b/src/My.Extensions.Localization.Json/Caching/ResourceNamesCache.cs index 4d30ba8..0302db2 100644 --- a/src/My.Extensions.Localization.Json/Caching/ResourceNamesCache.cs +++ b/src/My.Extensions.Localization.Json/Caching/ResourceNamesCache.cs @@ -2,15 +2,12 @@ using System.Collections.Concurrent; using System.Collections.Generic; -namespace My.Extensions.Localization.Json.Caching +namespace My.Extensions.Localization.Json.Caching; + +public class ResourceNamesCache : IResourceNamesCache { - public class ResourceNamesCache : IResourceNamesCache - { - private readonly ConcurrentDictionary> _cache = new ConcurrentDictionary>(); + private readonly ConcurrentDictionary> _cache = new(); - public IList GetOrAdd(string name, Func> valueFactory) - { - return _cache.GetOrAdd(name, valueFactory); - } - } + public IList GetOrAdd(string name, Func> valueFactory) + => _cache.GetOrAdd(name, valueFactory); } diff --git a/src/My.Extensions.Localization.Json/Internal/IResourceStringProvider.cs b/src/My.Extensions.Localization.Json/Internal/IResourceStringProvider.cs index 8ffe0f7..3cafc6f 100644 --- a/src/My.Extensions.Localization.Json/Internal/IResourceStringProvider.cs +++ b/src/My.Extensions.Localization.Json/Internal/IResourceStringProvider.cs @@ -1,10 +1,9 @@ using System.Collections.Generic; using System.Globalization; -namespace My.Extensions.Localization.Json.Internal +namespace My.Extensions.Localization.Json.Internal; + +public interface IResourceStringProvider { - public interface IResourceStringProvider - { - IList GetAllResourceStrings(CultureInfo culture, bool throwOnMissing); - } + IList GetAllResourceStrings(CultureInfo culture, bool throwOnMissing); } diff --git a/src/My.Extensions.Localization.Json/Internal/JsonResourceManager.cs b/src/My.Extensions.Localization.Json/Internal/JsonResourceManager.cs index 7022fad..3edb54c 100644 --- a/src/My.Extensions.Localization.Json/Internal/JsonResourceManager.cs +++ b/src/My.Extensions.Localization.Json/Internal/JsonResourceManager.cs @@ -5,193 +5,180 @@ using System.Linq; using System.Text.Json; -namespace My.Extensions.Localization.Json.Internal +namespace My.Extensions.Localization.Json.Internal; + +public class JsonResourceManager(string resourcesPath, string resourceName = null) { - public class JsonResourceManager + private static readonly JsonDocumentOptions _jsonDocumentOptions = new() { - private static readonly JsonDocumentOptions _jsonDocumentOptions = new JsonDocumentOptions - { - CommentHandling = JsonCommentHandling.Skip, - AllowTrailingCommas = true, - }; + CommentHandling = JsonCommentHandling.Skip, + AllowTrailingCommas = true, + }; - private ConcurrentDictionary> _resourcesCache = new ConcurrentDictionary>(); + private readonly ConcurrentDictionary> _resourcesCache = new(); - public JsonResourceManager(string resourcesPath, string resourceName = null) - { - ResourcesPath = resourcesPath; - ResourceName = resourceName; - } + public string ResourceName { get; } = resourceName; - public string ResourceName { get; } + public string ResourcesPath { get; } = resourcesPath; - public string ResourcesPath { get; } + public string ResourcesFilePath { get; private set; } - public string ResourcesFilePath { get; private set; } + public virtual ConcurrentDictionary GetResourceSet(CultureInfo culture, bool tryParents) + { + TryLoadResourceSet(culture); - public virtual ConcurrentDictionary GetResourceSet(CultureInfo culture, bool tryParents) + if (!_resourcesCache.ContainsKey(culture.Name)) { - TryLoadResourceSet(culture); - - if (!_resourcesCache.ContainsKey(culture.Name)) - { - return null; - } + return null; + } - if (tryParents) + if (tryParents) + { + var allResources = new ConcurrentDictionary(); + do { - var allResources = new ConcurrentDictionary(); - do + if (_resourcesCache.TryGetValue(culture.Name, out ConcurrentDictionary resources)) { - if (_resourcesCache.TryGetValue(culture.Name, out ConcurrentDictionary resources)) + foreach (var entry in resources) { - foreach (var entry in resources) - { - allResources.TryAdd(entry.Key, entry.Value); - } + allResources.TryAdd(entry.Key, entry.Value); } + } - culture = culture.Parent; - } while (culture != CultureInfo.InvariantCulture); + culture = culture.Parent; + } while (culture != CultureInfo.InvariantCulture); - return allResources; - } - else - { - _resourcesCache.TryGetValue(culture.Name, out ConcurrentDictionary resources); + return allResources; + } + else + { + _resourcesCache.TryGetValue(culture.Name, out ConcurrentDictionary resources); - return resources; - } + return resources; } + } - public virtual string GetString(string name) - { - var culture = CultureInfo.CurrentUICulture; - GetResourceSet(culture, tryParents: true); + public virtual string GetString(string name) + { + var culture = CultureInfo.CurrentUICulture; + GetResourceSet(culture, tryParents: true); - if (_resourcesCache.Count == 0) - { - return null; - } + if (_resourcesCache.IsEmpty) + { + return null; + } - do + do + { + if (_resourcesCache.ContainsKey(culture.Name)) { - if (_resourcesCache.ContainsKey(culture.Name)) + if (_resourcesCache[culture.Name].TryGetValue(name, out string value)) { - if (_resourcesCache[culture.Name].TryGetValue(name, out string value)) - { - return value; - } + return value; } + } - culture = culture.Parent; - } while (culture != culture.Parent); + culture = culture.Parent; + } while (culture != culture.Parent); + + return null; + } + public virtual string GetString(string name, CultureInfo culture) + { + GetResourceSet(culture, tryParents: true); + + if (_resourcesCache.IsEmpty) + { return null; } - public virtual string GetString(string name, CultureInfo culture) + if (!_resourcesCache.ContainsKey(culture.Name)) { - GetResourceSet(culture, tryParents: true); + return null; + } - if (_resourcesCache.Count == 0) - { - return null; - } + return _resourcesCache[culture.Name].TryGetValue(name, out string value) + ? value + : null; + } - if (!_resourcesCache.ContainsKey(culture.Name)) - { - return null; - } + private void TryLoadResourceSet(CultureInfo culture) + { + if (string.IsNullOrEmpty(ResourceName)) + { + var file = Path.Combine(ResourcesPath, $"{culture.Name}.json"); + var resources = LoadJsonResources(file); - return _resourcesCache[culture.Name].TryGetValue(name, out string value) - ? value - : null; + _resourcesCache.TryAdd(culture.Name, new ConcurrentDictionary(resources.ToDictionary(r => r.Key, r => r.Value))); } - - private void TryLoadResourceSet(CultureInfo culture) + else { - if (string.IsNullOrEmpty(ResourceName)) + var resourceFiles = Enumerable.Empty(); + var rootCulture = culture.Name[..2]; + if (ResourceName.Contains('.')) { - var file = Path.Combine(ResourcesPath, $"{culture.Name}.json"); - var resources = LoadJsonResources(file); + resourceFiles = Directory.EnumerateFiles(ResourcesPath, $"{ResourceName}.{rootCulture}*.json"); - _resourcesCache.TryAdd(culture.Name, new ConcurrentDictionary(resources.ToDictionary(r => r.Key, r => r.Value))); - } - else - { - var resourceFiles = Enumerable.Empty(); - var rootCulture = culture.Name.Substring(0, 2); - if (ResourceName.Contains(".")) - { - resourceFiles = Directory.EnumerateFiles(ResourcesPath, $"{ResourceName}.{rootCulture}*.json"); - - if (resourceFiles.Count() == 0) - { - resourceFiles = GetResourceFiles(rootCulture); - } - } - else + if (!resourceFiles.Any()) { resourceFiles = GetResourceFiles(rootCulture); } + } + else + { + resourceFiles = GetResourceFiles(rootCulture); + } - foreach (var file in resourceFiles) - { - var resources = LoadJsonResources(file); - var fileName = Path.GetFileNameWithoutExtension(file); - var cultureName = fileName.Substring(fileName.LastIndexOf(".") + 1); + foreach (var file in resourceFiles) + { + var resources = LoadJsonResources(file); + var fileName = Path.GetFileNameWithoutExtension(file); + var cultureName = fileName[(fileName.LastIndexOf('.') + 1)..]; - culture = CultureInfo.GetCultureInfo(cultureName); + culture = CultureInfo.GetCultureInfo(cultureName); - if (_resourcesCache.ContainsKey(culture.Name)) - { - foreach (var resource in resources) - { - _resourcesCache[culture.Name].TryAdd(resource.Key, resource.Value); - } - } - else + if (_resourcesCache.TryGetValue(culture.Name, out ConcurrentDictionary value)) + { + foreach (var resource in resources) { - _resourcesCache.TryAdd(culture.Name, new ConcurrentDictionary(resources.ToDictionary(r => r.Key, r => r.Value))); + value.TryAdd(resource.Key, resource.Value); } } - } - - IEnumerable GetResourceFiles(string culture) - { - var resourcePath = ResourceName.Replace('.', Path.AltDirectorySeparatorChar); - var resourcePathLastDirectorySeparatorIndex = resourcePath.LastIndexOf(Path.AltDirectorySeparatorChar); - var resourceName = resourcePath.Substring(resourcePathLastDirectorySeparatorIndex + 1); - string resourcesPath = null; - if (resourcePathLastDirectorySeparatorIndex == -1) - { - resourcesPath = ResourcesPath; - } else { - resourcesPath = Path.Combine(ResourcesPath, resourcePath.Substring(0, resourcePathLastDirectorySeparatorIndex)); + _resourcesCache.TryAdd(culture.Name, new ConcurrentDictionary(resources.ToDictionary(r => r.Key, r => r.Value))); } - - return Directory.Exists(resourcesPath) - ? Directory.EnumerateFiles(resourcesPath, $"{resourceName}.{culture}*.json") - : Enumerable.Empty(); } } - private static IDictionary LoadJsonResources(string filePath) + IEnumerable GetResourceFiles(string culture) { - var resources = new Dictionary(); - if (File.Exists(filePath)) - { - using var reader = new StreamReader(filePath); + var resourcePath = ResourceName.Replace('.', Path.AltDirectorySeparatorChar); + var resourcePathLastDirectorySeparatorIndex = resourcePath.LastIndexOf(Path.AltDirectorySeparatorChar); + var resourceName = resourcePath[(resourcePathLastDirectorySeparatorIndex + 1)..]; + var resourcesPath = resourcePathLastDirectorySeparatorIndex == -1 + ? ResourcesPath + : Path.Combine(ResourcesPath, resourcePath[..resourcePathLastDirectorySeparatorIndex]); + + return Directory.Exists(resourcesPath) + ? Directory.EnumerateFiles(resourcesPath, $"{resourceName}.{culture}*.json") + : []; + } + } - using var document = JsonDocument.Parse(reader.BaseStream, _jsonDocumentOptions); + private static IDictionary LoadJsonResources(string filePath) + { + var resources = new Dictionary(); + if (File.Exists(filePath)) + { + using var reader = new StreamReader(filePath); - resources = document.RootElement.EnumerateObject().ToDictionary(e => e.Name, e => e.Value.ToString()); - } + using var document = JsonDocument.Parse(reader.BaseStream, _jsonDocumentOptions); - return resources; + resources = document.RootElement.EnumerateObject().ToDictionary(e => e.Name, e => e.Value.ToString()); } + + return resources; } } diff --git a/src/My.Extensions.Localization.Json/Internal/JsonStringLocalizerLoggerExtensions.cs b/src/My.Extensions.Localization.Json/Internal/JsonStringLocalizerLoggerExtensions.cs index 0fb2144..74d170b 100644 --- a/src/My.Extensions.Localization.Json/Internal/JsonStringLocalizerLoggerExtensions.cs +++ b/src/My.Extensions.Localization.Json/Internal/JsonStringLocalizerLoggerExtensions.cs @@ -2,23 +2,22 @@ using System.Globalization; using Microsoft.Extensions.Logging; -namespace My.Extensions.Localization.Json.Internal +namespace My.Extensions.Localization.Json.Internal; + +internal static class JsonStringLocalizerLoggerExtensions { - internal static class JsonStringLocalizerLoggerExtensions - { - private static readonly Action _searchedLocation; + private static readonly Action _searchedLocation; - static JsonStringLocalizerLoggerExtensions() - { - _searchedLocation = LoggerMessage.Define( - LogLevel.Debug, - 1, - $"{nameof(JsonStringLocalizer)} searched for '{{Key}}' in '{{LocationSearched}}' with culture '{{Culture}}'."); - } + static JsonStringLocalizerLoggerExtensions() + { + _searchedLocation = LoggerMessage.Define( + LogLevel.Debug, + 1, + $"{nameof(JsonStringLocalizer)} 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); - } + public static void SearchedLocation(this ILogger logger, string key, string searchedLocation, CultureInfo culture) + { + _searchedLocation(logger, key, searchedLocation, culture, null); } } diff --git a/src/My.Extensions.Localization.Json/Internal/JsonStringProvider.cs b/src/My.Extensions.Localization.Json/Internal/JsonStringProvider.cs index e8e28ec..42e8f41 100644 --- a/src/My.Extensions.Localization.Json/Internal/JsonStringProvider.cs +++ b/src/My.Extensions.Localization.Json/Internal/JsonStringProvider.cs @@ -3,53 +3,43 @@ using System.Resources; using My.Extensions.Localization.Json.Caching; -namespace My.Extensions.Localization.Json.Internal +namespace My.Extensions.Localization.Json.Internal; + +public class JsonStringProvider(IResourceNamesCache resourceNamesCache, JsonResourceManager jsonResourceManager) : IResourceStringProvider { - public class JsonStringProvider : IResourceStringProvider + private string GetResourceCacheKey(CultureInfo culture) { - private readonly IResourceNamesCache _resourceNamesCache; - private readonly JsonResourceManager _jsonResourceManager; - - public JsonStringProvider(IResourceNamesCache resourceCache, JsonResourceManager jsonResourceManager) - { - _jsonResourceManager = jsonResourceManager; - _resourceNamesCache = resourceCache; - } + var resourceName = jsonResourceManager.ResourceName; - private string GetResourceCacheKey(CultureInfo culture) - { - var resourceName = _jsonResourceManager.ResourceName; + return $"Culture={culture.Name};resourceName={resourceName}"; + } - return $"Culture={culture.Name};resourceName={resourceName}"; - } + public IList GetAllResourceStrings(CultureInfo culture, bool throwOnMissing) + { + var cacheKey = GetResourceCacheKey(culture); - public IList GetAllResourceStrings(CultureInfo culture, bool throwOnMissing) + return resourceNamesCache.GetOrAdd(cacheKey, _ => { - var cacheKey = GetResourceCacheKey(culture); - - return _resourceNamesCache.GetOrAdd(cacheKey, _ => + var resourceSet = jsonResourceManager.GetResourceSet(culture, tryParents: false); + if (resourceSet == null) { - var resourceSet = _jsonResourceManager.GetResourceSet(culture, tryParents: false); - if (resourceSet == null) + if (throwOnMissing) { - if (throwOnMissing) - { - throw new MissingManifestResourceException($"The manifest resource for the culture '{culture.Name}' is missing."); - } - else - { - return null; - } + throw new MissingManifestResourceException($"The manifest resource for the culture '{culture.Name}' is missing."); } - - var names = new List(); - foreach (var entry in resourceSet) + else { - names.Add(entry.Key); + return null; } + } + + var names = new List(); + foreach (var entry in resourceSet) + { + names.Add(entry.Key); + } - return names; - }); - } + return names; + }); } } diff --git a/src/My.Extensions.Localization.Json/Internal/PathHelpers.cs b/src/My.Extensions.Localization.Json/Internal/PathHelpers.cs index cbf4bb5..da3c598 100644 --- a/src/My.Extensions.Localization.Json/Internal/PathHelpers.cs +++ b/src/My.Extensions.Localization.Json/Internal/PathHelpers.cs @@ -1,11 +1,9 @@ using System.IO; using System.Reflection; -namespace My.Extensions.Localization.Json.Internal +namespace My.Extensions.Localization.Json.Internal; + +public static class PathHelpers { - public static class PathHelpers - { - public static string GetApplicationRoot() - => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); - } + public static string GetApplicationRoot() => Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location); } \ No newline at end of file diff --git a/src/My.Extensions.Localization.Json/Internal/StringLocalizer.cs b/src/My.Extensions.Localization.Json/Internal/StringLocalizer.cs index 9e348f4..636cde6 100644 --- a/src/My.Extensions.Localization.Json/Internal/StringLocalizer.cs +++ b/src/My.Extensions.Localization.Json/Internal/StringLocalizer.cs @@ -2,23 +2,22 @@ using System.Reflection; using Microsoft.Extensions.Localization; -namespace My.Extensions.Localization.Json.Internal +namespace My.Extensions.Localization.Json.Internal; + +internal class StringLocalizer : IStringLocalizer { - internal class StringLocalizer : IStringLocalizer - { - private IStringLocalizer _localizer; + private readonly IStringLocalizer _localizer; - public StringLocalizer(IStringLocalizerFactory factory) - { - var type = typeof(StringLocalizer); - var assemblyName = new AssemblyName(type.GetTypeInfo().Assembly.FullName); - _localizer = factory.Create(string.Empty, assemblyName.FullName); - } + public StringLocalizer(IStringLocalizerFactory factory) + { + var type = typeof(StringLocalizer); + var assemblyName = new AssemblyName(type.GetTypeInfo().Assembly.FullName); + _localizer = factory.Create(string.Empty, assemblyName.FullName); + } - public LocalizedString this[string name] => _localizer[name]; + public LocalizedString this[string name] => _localizer[name]; - public LocalizedString this[string name, params object[] arguments] => _localizer[name, arguments]; + public LocalizedString this[string name, params object[] arguments] => _localizer[name, arguments]; - public IEnumerable GetAllStrings(bool includeParentCultures) => _localizer.GetAllStrings(includeParentCultures); - } + public IEnumerable GetAllStrings(bool includeParentCultures) => _localizer.GetAllStrings(includeParentCultures); } \ No newline at end of file diff --git a/src/My.Extensions.Localization.Json/JsonLocalizationOptions.cs b/src/My.Extensions.Localization.Json/JsonLocalizationOptions.cs index 1dca2ab..4eb1cae 100644 --- a/src/My.Extensions.Localization.Json/JsonLocalizationOptions.cs +++ b/src/My.Extensions.Localization.Json/JsonLocalizationOptions.cs @@ -1,9 +1,8 @@ using Microsoft.Extensions.Localization; -namespace My.Extensions.Localization.Json +namespace My.Extensions.Localization.Json; + +public class JsonLocalizationOptions : LocalizationOptions { - public class JsonLocalizationOptions : LocalizationOptions - { - public ResourcesType ResourcesType { get; set; } = ResourcesType.TypeBased; - } + public ResourcesType ResourcesType { get; set; } = ResourcesType.TypeBased; } \ No newline at end of file diff --git a/src/My.Extensions.Localization.Json/JsonLocalizationServiceCollectionExtensions.cs b/src/My.Extensions.Localization.Json/JsonLocalizationServiceCollectionExtensions.cs index 5078640..9bc278a 100644 --- a/src/My.Extensions.Localization.Json/JsonLocalizationServiceCollectionExtensions.cs +++ b/src/My.Extensions.Localization.Json/JsonLocalizationServiceCollectionExtensions.cs @@ -4,56 +4,42 @@ using My.Extensions.Localization.Json; using My.Extensions.Localization.Json.Internal; -namespace Microsoft.Extensions.DependencyInjection +namespace Microsoft.Extensions.DependencyInjection; + +public static class JsonLocalizationServiceCollectionExtensions { - public static class JsonLocalizationServiceCollectionExtensions + public static IServiceCollection AddJsonLocalization(this IServiceCollection services) + { + ArgumentNullException.ThrowIfNull(services); + + services.AddOptions(); + + AddJsonLocalizationServices(services); + + return services; + } + + public static IServiceCollection AddJsonLocalization(this IServiceCollection services, Action setupAction) + { + ArgumentNullException.ThrowIfNull(services); + + ArgumentNullException.ThrowIfNull(setupAction); + + AddJsonLocalizationServices(services, setupAction); + + return services; + } + + internal static void AddJsonLocalizationServices(IServiceCollection services) + { + services.TryAddSingleton(); + services.TryAddTransient(typeof(IStringLocalizer<>), typeof(StringLocalizer<>)); + services.TryAddTransient(typeof(IStringLocalizer), typeof(StringLocalizer)); + } + + internal static void AddJsonLocalizationServices(IServiceCollection services, Action setupAction) { - public static IServiceCollection AddJsonLocalization(this IServiceCollection services) - { - if (services == null) - { - throw new ArgumentNullException(nameof(services)); - } - - services.AddOptions(); - - AddJsonLocalizationServices(services); - - return services; - } - - public static IServiceCollection AddJsonLocalization( - this IServiceCollection services, - Action setupAction) - { - if (services == null) - { - throw new ArgumentNullException(nameof(services)); - } - - if (setupAction == null) - { - throw new ArgumentNullException(nameof(setupAction)); - } - - AddJsonLocalizationServices(services, setupAction); - - return services; - } - - internal static void AddJsonLocalizationServices(IServiceCollection services) - { - services.TryAddSingleton(); - services.TryAddTransient(typeof(IStringLocalizer<>), typeof(StringLocalizer<>)); - services.TryAddTransient(typeof(IStringLocalizer), typeof(StringLocalizer)); - } - - internal static void AddJsonLocalizationServices( - IServiceCollection services, - Action setupAction) - { - AddJsonLocalizationServices(services); - services.Configure(setupAction); - } + AddJsonLocalizationServices(services); + services.Configure(setupAction); } } \ No newline at end of file diff --git a/src/My.Extensions.Localization.Json/JsonStringLocalizer.cs b/src/My.Extensions.Localization.Json/JsonStringLocalizer.cs index 2d45c7c..58e2c83 100644 --- a/src/My.Extensions.Localization.Json/JsonStringLocalizer.cs +++ b/src/My.Extensions.Localization.Json/JsonStringLocalizer.cs @@ -7,150 +7,136 @@ using Microsoft.Extensions.Logging; using My.Extensions.Localization.Json.Internal; -namespace My.Extensions.Localization.Json -{ - using My.Extensions.Localization.Json.Caching; +namespace My.Extensions.Localization.Json; + +using My.Extensions.Localization.Json.Caching; - public class JsonStringLocalizer : IStringLocalizer +public class JsonStringLocalizer : IStringLocalizer +{ + private readonly ConcurrentDictionary _missingManifestCache = new(); + private readonly JsonResourceManager _jsonResourceManager; + private readonly IResourceStringProvider _resourceStringProvider; + private readonly ILogger _logger; + + private string _searchedLocation = string.Empty; + + public JsonStringLocalizer( + JsonResourceManager jsonResourceManager, + IResourceNamesCache resourceNamesCache, + ILogger logger) + : this(jsonResourceManager, + new JsonStringProvider(resourceNamesCache, jsonResourceManager), + resourceNamesCache, + logger) { - private readonly ConcurrentDictionary _missingManifestCache = new ConcurrentDictionary(); - private readonly IResourceNamesCache _resourceNamesCache; - private readonly JsonResourceManager _jsonResourceManager; - private readonly IResourceStringProvider _resourceStringProvider; - private readonly ILogger _logger; - - private string _searchedLocation = string.Empty; - - public JsonStringLocalizer( - JsonResourceManager jsonResourceManager, - IResourceNamesCache resourceNamesCache, - ILogger logger) - : this(jsonResourceManager, - new JsonStringProvider(resourceNamesCache, jsonResourceManager), - resourceNamesCache, - logger) - { - } + } - public JsonStringLocalizer( - JsonResourceManager jsonResourceManager, - IResourceStringProvider resourceStringProvider, - IResourceNamesCache resourceNamesCache, - ILogger logger) - { - _jsonResourceManager = jsonResourceManager ?? throw new ArgumentNullException(nameof(jsonResourceManager)); - _resourceStringProvider = resourceStringProvider ?? throw new ArgumentNullException(nameof(resourceStringProvider)); - _resourceNamesCache = resourceNamesCache ?? throw new ArgumentNullException(nameof(resourceNamesCache)); - _logger = logger ?? throw new ArgumentNullException(nameof(logger)); - } + public JsonStringLocalizer( + JsonResourceManager jsonResourceManager, + IResourceStringProvider resourceStringProvider, + IResourceNamesCache resourceNamesCache, + ILogger logger) + { + _jsonResourceManager = jsonResourceManager ?? throw new ArgumentNullException(nameof(jsonResourceManager)); + _resourceStringProvider = resourceStringProvider ?? throw new ArgumentNullException(nameof(resourceStringProvider)); + _logger = logger ?? throw new ArgumentNullException(nameof(logger)); + } - public LocalizedString this[string name] + public LocalizedString this[string name] + { + get { - get - { - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } + ArgumentNullException.ThrowIfNull(name); - var value = GetStringSafely(name, null); + var value = GetStringSafely(name, null); - return new LocalizedString(name, value ?? name, resourceNotFound: value == null, searchedLocation: _searchedLocation); - } + return new LocalizedString(name, value ?? name, resourceNotFound: value == null, searchedLocation: _searchedLocation); } + } - public LocalizedString this[string name, params object[] arguments] + public LocalizedString this[string name, params object[] arguments] + { + get { - get - { - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } + ArgumentNullException.ThrowIfNull(name); - var format = GetStringSafely(name, null); - var value = string.Format(format ?? name, arguments); + var format = GetStringSafely(name, null); + var value = string.Format(format ?? name, arguments); - return new LocalizedString(name, value, resourceNotFound: format == null, searchedLocation: _searchedLocation); - } + return new LocalizedString(name, value, resourceNotFound: format == null, searchedLocation: _searchedLocation); } + } - public virtual IEnumerable GetAllStrings(bool includeParentCultures) => - GetAllStrings(includeParentCultures, CultureInfo.CurrentUICulture); + public virtual IEnumerable GetAllStrings(bool includeParentCultures) => + GetAllStrings(includeParentCultures, CultureInfo.CurrentUICulture); - public IStringLocalizer WithCulture(CultureInfo culture) => this; + [Obsolete("This method is obsolete and will be removed in a future version.")] + public IStringLocalizer WithCulture(CultureInfo culture) => this; - protected virtual IEnumerable GetAllStrings(bool includeParentCultures, CultureInfo culture) - { - if (culture == null) - { - throw new ArgumentNullException(nameof(culture)); - } + protected virtual IEnumerable GetAllStrings(bool includeParentCultures, CultureInfo culture) + { + ArgumentNullException.ThrowIfNull(culture); - var resourceNames = includeParentCultures - ? GetResourceNamesFromCultureHierarchy(culture) - : _resourceStringProvider.GetAllResourceStrings(culture, true); + var resourceNames = includeParentCultures + ? GetResourceNamesFromCultureHierarchy(culture) + : _resourceStringProvider.GetAllResourceStrings(culture, true); - foreach (var name in resourceNames) - { - var value = GetStringSafely(name, culture); - yield return new LocalizedString(name, value ?? name, resourceNotFound: value == null, searchedLocation: _searchedLocation); - } + foreach (var name in resourceNames) + { + var value = GetStringSafely(name, culture); + yield return new LocalizedString(name, value ?? name, resourceNotFound: value == null, searchedLocation: _searchedLocation); } + } - protected string GetStringSafely(string name, CultureInfo culture) - { - if (name == null) - { - throw new ArgumentNullException(nameof(name)); - } + protected string GetStringSafely(string name, CultureInfo culture) + { + ArgumentNullException.ThrowIfNull(name); - var keyCulture = culture ?? CultureInfo.CurrentUICulture; - var cacheKey = $"name={name}&culture={keyCulture.Name}"; + var keyCulture = culture ?? CultureInfo.CurrentUICulture; + var cacheKey = $"name={name}&culture={keyCulture.Name}"; - _logger.SearchedLocation(name, _jsonResourceManager.ResourcesFilePath, keyCulture); + _logger.SearchedLocation(name, _jsonResourceManager.ResourcesFilePath, keyCulture); - if (_missingManifestCache.ContainsKey(cacheKey)) - { - return null; - } + if (_missingManifestCache.ContainsKey(cacheKey)) + { + return null; + } - try - { - return culture == null - ? _jsonResourceManager.GetString(name) - : _jsonResourceManager.GetString(name, culture); - } - catch (MissingManifestResourceException) - { - _missingManifestCache.TryAdd(cacheKey, null); - - return null; - } + try + { + return culture == null + ? _jsonResourceManager.GetString(name) + : _jsonResourceManager.GetString(name, culture); + } + catch (MissingManifestResourceException) + { + _missingManifestCache.TryAdd(cacheKey, null); + + return null; } + } + + private IEnumerable GetResourceNamesFromCultureHierarchy(CultureInfo startingCulture) + { + var currentCulture = startingCulture; + var resourceNames = new HashSet(); - private IEnumerable GetResourceNamesFromCultureHierarchy(CultureInfo startingCulture) + while (currentCulture != currentCulture.Parent) { - var currentCulture = startingCulture; - var resourceNames = new HashSet(); + var cultureResourceNames = _resourceStringProvider.GetAllResourceStrings(currentCulture, false); - while (currentCulture != currentCulture.Parent) + if (cultureResourceNames != null) { - var cultureResourceNames = _resourceStringProvider.GetAllResourceStrings(currentCulture, false); - - if (cultureResourceNames != null) + foreach (var resourceName in cultureResourceNames) { - foreach (var resourceName in cultureResourceNames) - { - resourceNames.Add(resourceName); - } + resourceNames.Add(resourceName); } - - currentCulture = currentCulture.Parent; } - return resourceNames; + currentCulture = currentCulture.Parent; } + + return resourceNames; } } diff --git a/src/My.Extensions.Localization.Json/JsonStringLocalizerFactory.cs b/src/My.Extensions.Localization.Json/JsonStringLocalizerFactory.cs index 7f4feca..a45a9ea 100644 --- a/src/My.Extensions.Localization.Json/JsonStringLocalizerFactory.cs +++ b/src/My.Extensions.Localization.Json/JsonStringLocalizerFactory.cs @@ -8,139 +8,125 @@ using Microsoft.Extensions.Options; using My.Extensions.Localization.Json.Internal; -namespace My.Extensions.Localization.Json +namespace My.Extensions.Localization.Json; + +using My.Extensions.Localization.Json.Caching; + +public class JsonStringLocalizerFactory : IStringLocalizerFactory { - using My.Extensions.Localization.Json.Caching; + private readonly IResourceNamesCache _resourceNamesCache = new ResourceNamesCache(); + private readonly ConcurrentDictionary _localizerCache = new(); + private readonly string _resourcesRelativePath; + private readonly ResourcesType _resourcesType = ResourcesType.TypeBased; + private readonly ILoggerFactory _loggerFactory; + + public JsonStringLocalizerFactory( + IOptions localizationOptions, + ILoggerFactory loggerFactory) + { + ArgumentNullException.ThrowIfNull(localizationOptions); - public class JsonStringLocalizerFactory : IStringLocalizerFactory + _resourcesRelativePath = localizationOptions.Value.ResourcesPath ?? string.Empty; + _resourcesType = localizationOptions.Value.ResourcesType; + _loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory)); + } + + public IStringLocalizer Create(Type resourceSource) { - private readonly IResourceNamesCache _resourceNamesCache = new ResourceNamesCache(); - private readonly ConcurrentDictionary _localizerCache = new ConcurrentDictionary(); - private readonly string _resourcesRelativePath; - private readonly ResourcesType _resourcesType = ResourcesType.TypeBased; - private readonly ILoggerFactory _loggerFactory; - - public JsonStringLocalizerFactory( - IOptions localizationOptions, - ILoggerFactory loggerFactory) - { - if (localizationOptions == null) - { - throw new ArgumentNullException(nameof(localizationOptions)); - } + ArgumentNullException.ThrowIfNull(resourceSource); - _resourcesRelativePath = localizationOptions.Value.ResourcesPath ?? string.Empty; - _resourcesType = localizationOptions.Value.ResourcesType; - _loggerFactory = loggerFactory ?? throw new ArgumentNullException(nameof(loggerFactory)); - } + string resourcesPath = string.Empty; - public IStringLocalizer Create(Type resourceSource) + // TODO: Check why an exception happen before the host build + if (resourceSource.Name == "Controller") { - if (resourceSource == null) - { - throw new ArgumentNullException(nameof(resourceSource)); - } - - string resourcesPath = string.Empty; + resourcesPath = Path.Combine(PathHelpers.GetApplicationRoot(), GetResourcePath(resourceSource.Assembly)); + + return _localizerCache.GetOrAdd(resourceSource.Name, _ => CreateJsonStringLocalizer(resourcesPath, TryFixInnerClassPath("Controller"))); + } - // TODO: Check why an exception happen before the host build - if (resourceSource.Name == "Controller") - { - resourcesPath = Path.Combine(PathHelpers.GetApplicationRoot(), GetResourcePath(resourceSource.Assembly)); - - return _localizerCache.GetOrAdd(resourceSource.Name, _ => CreateJsonStringLocalizer(resourcesPath, TryFixInnerClassPath("Controller"))); - } + var typeInfo = resourceSource.GetTypeInfo(); + var assembly = typeInfo.Assembly; + var assemblyName = resourceSource.Assembly.GetName().Name; + var typeName = $"{assemblyName}.{typeInfo.Name}" == typeInfo.FullName + ? typeInfo.Name + : TrimPrefix(typeInfo.FullName, assemblyName + "."); - var typeInfo = resourceSource.GetTypeInfo(); - var assembly = typeInfo.Assembly; - var assemblyName = resourceSource.Assembly.GetName().Name; - var typeName = $"{assemblyName}.{typeInfo.Name}" == typeInfo.FullName - ? typeInfo.Name - : TrimPrefix(typeInfo.FullName, assemblyName + "."); + resourcesPath = Path.Combine(PathHelpers.GetApplicationRoot(), GetResourcePath(assembly)); + typeName = TryFixInnerClassPath(typeName); - resourcesPath = Path.Combine(PathHelpers.GetApplicationRoot(), GetResourcePath(assembly)); - typeName = TryFixInnerClassPath(typeName); + return _localizerCache.GetOrAdd($"culture={CultureInfo.CurrentUICulture.Name}, typeName={typeName}", _ => CreateJsonStringLocalizer(resourcesPath, typeName)); + } - return _localizerCache.GetOrAdd($"culture={CultureInfo.CurrentUICulture.Name}, typeName={typeName}", _ => CreateJsonStringLocalizer(resourcesPath, typeName)); - } + public IStringLocalizer Create(string baseName, string location) + { + ArgumentNullException.ThrowIfNull(baseName); + ArgumentNullException.ThrowIfNull(location); - public IStringLocalizer Create(string baseName, string location) + return _localizerCache.GetOrAdd($"baseName={baseName},location={location}", _ => { - if (baseName == null) + var assemblyName = new AssemblyName(location); + var assembly = Assembly.Load(assemblyName); + var resourcesPath = Path.Combine(PathHelpers.GetApplicationRoot(), GetResourcePath(assembly)); + string resourceName = null; + if (baseName == string.Empty) { - throw new ArgumentNullException(nameof(baseName)); - } + resourceName = baseName; - if (location == null) - { - throw new ArgumentNullException(nameof(location)); + return CreateJsonStringLocalizer(resourcesPath, resourceName); } - return _localizerCache.GetOrAdd($"baseName={baseName},location={location}", _ => + if (_resourcesType == ResourcesType.TypeBased) { - var assemblyName = new AssemblyName(location); - var assembly = Assembly.Load(assemblyName); - var resourcesPath = Path.Combine(PathHelpers.GetApplicationRoot(), GetResourcePath(assembly)); - string resourceName = null; - if (baseName == string.Empty) - { - resourceName = baseName; - - return CreateJsonStringLocalizer(resourcesPath, resourceName); - } - - if (_resourcesType == ResourcesType.TypeBased) - { - baseName = TryFixInnerClassPath(baseName); - resourceName = TrimPrefix(baseName, location + "."); - } + baseName = TryFixInnerClassPath(baseName); + resourceName = TrimPrefix(baseName, location + "."); + } - return CreateJsonStringLocalizer(resourcesPath, resourceName); - }); - } + return CreateJsonStringLocalizer(resourcesPath, resourceName); + }); + } - protected virtual JsonStringLocalizer CreateJsonStringLocalizer( - string resourcesPath, - string resourceName) - { - var resourceManager = _resourcesType == ResourcesType.TypeBased - ? new JsonResourceManager(resourcesPath, resourceName) - : new JsonResourceManager(resourcesPath); - var logger = _loggerFactory.CreateLogger(); + protected virtual JsonStringLocalizer CreateJsonStringLocalizer( + string resourcesPath, + string resourceName) + { + var resourceManager = _resourcesType == ResourcesType.TypeBased + ? new JsonResourceManager(resourcesPath, resourceName) + : new JsonResourceManager(resourcesPath); + var logger = _loggerFactory.CreateLogger(); - return new JsonStringLocalizer(resourceManager, _resourceNamesCache, logger); - } + return new JsonStringLocalizer(resourceManager, _resourceNamesCache, logger); + } - private string GetResourcePath(Assembly assembly) - { - var resourceLocationAttribute = assembly.GetCustomAttribute(); + private string GetResourcePath(Assembly assembly) + { + var resourceLocationAttribute = assembly.GetCustomAttribute(); - return resourceLocationAttribute == null - ? _resourcesRelativePath - : resourceLocationAttribute.ResourceLocation; - } + return resourceLocationAttribute == null + ? _resourcesRelativePath + : resourceLocationAttribute.ResourceLocation; + } - private static string TrimPrefix(string name, string prefix) + private static string TrimPrefix(string name, string prefix) + { + if (name.StartsWith(prefix, StringComparison.Ordinal)) { - if (name.StartsWith(prefix, StringComparison.Ordinal)) - { - return name.Substring(prefix.Length); - } - - return name; + return name[prefix.Length..]; } - private string TryFixInnerClassPath(string path) - { - const char innerClassSeparator = '+'; - var fixedPath = path; + return name; + } - if (path.Contains(innerClassSeparator.ToString())) - { - fixedPath = path.Replace(innerClassSeparator, '.'); - } + private static string TryFixInnerClassPath(string path) + { + const char innerClassSeparator = '+'; + var fixedPath = path; - return fixedPath; + if (path.Contains(innerClassSeparator.ToString())) + { + fixedPath = path.Replace(innerClassSeparator, '.'); } + + return fixedPath; } } \ No newline at end of file diff --git a/src/My.Extensions.Localization.Json/ResourcesType.cs b/src/My.Extensions.Localization.Json/ResourcesType.cs index e9042af..d320d16 100644 --- a/src/My.Extensions.Localization.Json/ResourcesType.cs +++ b/src/My.Extensions.Localization.Json/ResourcesType.cs @@ -1,8 +1,7 @@ -namespace My.Extensions.Localization.Json +namespace My.Extensions.Localization.Json; + +public enum ResourcesType { - public enum ResourcesType - { - CultureBased, - TypeBased - } + CultureBased, + TypeBased } \ No newline at end of file diff --git a/src/My.Extensions.Localization.Json/StringLocalizerExtensions.cs b/src/My.Extensions.Localization.Json/StringLocalizerExtensions.cs index 3b2fd5c..8d0516a 100644 --- a/src/My.Extensions.Localization.Json/StringLocalizerExtensions.cs +++ b/src/My.Extensions.Localization.Json/StringLocalizerExtensions.cs @@ -2,13 +2,11 @@ using System; using System.Linq.Expressions; -namespace My.Extensions.Localization.Json +namespace My.Extensions.Localization.Json; + +public static class StringLocalizerExtensions { - public static class StringLocalizerExtensions - { - public static LocalizedString GetString( - this IStringLocalizer stringLocalizer, - Expression> propertyExpression) - => stringLocalizer[(propertyExpression.Body as MemberExpression).Member.Name]; - } + public static LocalizedString GetString( + this IStringLocalizer stringLocalizer, + Expression> propertyExpression) => stringLocalizer[(propertyExpression.Body as MemberExpression).Member.Name]; } \ No newline at end of file diff --git a/test/My.Extensions.Localization.Json.FunctionalTests/LocalizationMvcSampleTests.cs b/test/My.Extensions.Localization.Json.FunctionalTests/LocalizationMvcSampleTests.cs index 679eca5..9e3037f 100644 --- a/test/My.Extensions.Localization.Json.FunctionalTests/LocalizationMvcSampleTests.cs +++ b/test/My.Extensions.Localization.Json.FunctionalTests/LocalizationMvcSampleTests.cs @@ -5,92 +5,86 @@ using Microsoft.AspNetCore.Mvc.Testing; using Xunit; -namespace LocalizationSample.Mvc.FunctionalTest -{ - public class LocalizationMvcSampleTests : IClassFixture> - { - private readonly HttpClient _client; +namespace LocalizationSample.Mvc.FunctionalTest; - public LocalizationMvcSampleTests(WebApplicationFactory factory) - { - _client = factory.CreateClient(); - } +public class LocalizationMvcSampleTests(WebApplicationFactory factory) : IClassFixture> +{ + private readonly HttpClient _client = factory.CreateClient(); - [Theory] - [InlineData("en-US", "Privacy Policy")] - [InlineData("fr-FR", "Politique de confidentialité")] - public async Task LocalizePrivacyView(string culture, string expected) - { - // Arrange - var url = "/Home/Privacy"; - var request = new HttpRequestMessage(HttpMethod.Get, url); - var cookieValue = $"c={culture}|uic={culture}"; - request.Headers.Add("Cookie", $"{CookieRequestCultureProvider.DefaultCookieName}={cookieValue}"); + [Theory] + [InlineData("en-US", "Privacy Policy")] + [InlineData("fr-FR", "Politique de confidentialité")] + public async Task LocalizePrivacyView(string culture, string expected) + { + // Arrange + var url = "/Home/Privacy"; + var request = new HttpRequestMessage(HttpMethod.Get, url); + var cookieValue = $"c={culture}|uic={culture}"; + request.Headers.Add("Cookie", $"{CookieRequestCultureProvider.DefaultCookieName}={cookieValue}"); - // Act - var response = await _client.SendAsync(request); - var content = await response.Content.ReadAsStringAsync(); + // Act + var response = await _client.SendAsync(request); + var content = await response.Content.ReadAsStringAsync(); - // Assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Contains(expected, content); - } + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Contains(expected, content); + } - [Fact] - public async Task LocalizeRegisterViewModel() - { - // Arrange - var request = new HttpRequestMessage(HttpMethod.Get, "/Account/Register"); - var culture = "fr-FR"; - var cookieValue = $"c={culture}|uic={culture}"; - request.Headers.Add("Cookie", $"{CookieRequestCultureProvider.DefaultCookieName}={cookieValue}"); + [Fact] + public async Task LocalizeRegisterViewModel() + { + // Arrange + var request = new HttpRequestMessage(HttpMethod.Get, "/Account/Register"); + var culture = "fr-FR"; + var cookieValue = $"c={culture}|uic={culture}"; + request.Headers.Add("Cookie", $"{CookieRequestCultureProvider.DefaultCookieName}={cookieValue}"); - // Act - var response = await _client.SendAsync(request); - var content = await response.Content.ReadAsStringAsync(); + // Act + var response = await _client.SendAsync(request); + var content = await response.Content.ReadAsStringAsync(); - // Assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Contains("Mot de passe", content); - Assert.Contains("Confirmez le mot de passe", content); - } + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Contains("Mot de passe", content); + Assert.Contains("Confirmez le mot de passe", content); + } - [Fact] - public async Task LocalizeViewWithPathConventions() - { - // Arrange - var request = new HttpRequestMessage(HttpMethod.Get, "/"); - var culture = "fr-FR"; - var cookieValue = $"c={culture}|uic={culture}"; - request.Headers.Add("Cookie", $"{CookieRequestCultureProvider.DefaultCookieName}={cookieValue}"); + [Fact] + public async Task LocalizeViewWithPathConventions() + { + // Arrange + var request = new HttpRequestMessage(HttpMethod.Get, "/"); + var culture = "fr-FR"; + var cookieValue = $"c={culture}|uic={culture}"; + request.Headers.Add("Cookie", $"{CookieRequestCultureProvider.DefaultCookieName}={cookieValue}"); - // Act - var response = await _client.SendAsync(request); - var content = await response.Content.ReadAsStringAsync(); + // Act + var response = await _client.SendAsync(request); + var content = await response.Content.ReadAsStringAsync(); - // Assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Contains("Bienvenu", content); - } + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Contains("Bienvenu", content); + } - [Fact] - public async Task StringLocalizeShouldWorkWithControllersPrefix() - { - // Arrange - var url = "/Home/Privacy"; - var request = new HttpRequestMessage(HttpMethod.Get, url); - var culture = "fr-FR"; - var cookieValue = $"c={culture}|uic={culture}"; - request.Headers.Add("Cookie", $"{CookieRequestCultureProvider.DefaultCookieName}={cookieValue}"); + [Fact] + public async Task StringLocalizeShouldWorkWithControllersPrefix() + { + // Arrange + var url = "/Home/Privacy"; + var request = new HttpRequestMessage(HttpMethod.Get, url); + var culture = "fr-FR"; + var cookieValue = $"c={culture}|uic={culture}"; + request.Headers.Add("Cookie", $"{CookieRequestCultureProvider.DefaultCookieName}={cookieValue}"); - // Act - var response = await _client.SendAsync(request); - var content = await response.Content.ReadAsStringAsync(); + // Act + var response = await _client.SendAsync(request); + var content = await response.Content.ReadAsStringAsync(); - // Assert - Assert.Equal(HttpStatusCode.OK, response.StatusCode); - Assert.Contains("Utilisez cette page pour détailler la politique de confidentialité de votre site.", WebUtility.HtmlDecode(content)); - } + // Assert + Assert.Equal(HttpStatusCode.OK, response.StatusCode); + Assert.Contains("Utilisez cette page pour détailler la politique de confidentialité de votre site.", WebUtility.HtmlDecode(content)); } } diff --git a/test/My.Extensions.Localization.Json.Tests/Common/LocalizationHelper.cs b/test/My.Extensions.Localization.Json.Tests/Common/LocalizationHelper.cs index 9462f99..d45d01f 100644 --- a/test/My.Extensions.Localization.Json.Tests/Common/LocalizationHelper.cs +++ b/test/My.Extensions.Localization.Json.Tests/Common/LocalizationHelper.cs @@ -1,13 +1,12 @@ using System.Globalization; -namespace My.Extensions.Localization.Json.Tests.Common +namespace My.Extensions.Localization.Json.Tests.Common; + +public static class LocalizationHelper { - public static class LocalizationHelper + public static void SetCurrentCulture(string culture) { - public static void SetCurrentCulture(string culture) - { - CultureInfo.CurrentCulture = new CultureInfo(culture); - CultureInfo.CurrentUICulture = new CultureInfo(culture); - } + CultureInfo.CurrentCulture = new CultureInfo(culture); + CultureInfo.CurrentUICulture = new CultureInfo(culture); } } \ No newline at end of file diff --git a/test/My.Extensions.Localization.Json.Tests/Common/Test.cs b/test/My.Extensions.Localization.Json.Tests/Common/Test.cs index a768116..cdf3f34 100644 --- a/test/My.Extensions.Localization.Json.Tests/Common/Test.cs +++ b/test/My.Extensions.Localization.Json.Tests/Common/Test.cs @@ -1,7 +1,6 @@ -namespace My.Extensions.Localization.Json.Tests.Common +namespace My.Extensions.Localization.Json.Tests.Common; + +internal class Test { - internal class Test - { - } } diff --git a/test/My.Extensions.Localization.Json.Tests/JsonLocalizationServiceCollectionExtensionsTests.cs b/test/My.Extensions.Localization.Json.Tests/JsonLocalizationServiceCollectionExtensionsTests.cs index 1de228b..c79c89e 100644 --- a/test/My.Extensions.Localization.Json.Tests/JsonLocalizationServiceCollectionExtensionsTests.cs +++ b/test/My.Extensions.Localization.Json.Tests/JsonLocalizationServiceCollectionExtensionsTests.cs @@ -4,47 +4,46 @@ using Microsoft.Extensions.Options; using Xunit; -namespace My.Extensions.Localization.Json.Tests +namespace My.Extensions.Localization.Json.Tests; + +public class JsonLocalizationServiceCollectionExtensionsTests { - public class JsonLocalizationServiceCollectionExtensionsTests + [Fact] + public void AddJsonLocalization() + { + // Arrange + var services = new ServiceCollection(); + + // Act + JsonLocalizationServiceCollectionExtensions.AddJsonLocalization(services); + + // Assert + Assert.Equal(1, services.Count()); + Assert.Equal(1, services.Count(typeof(IStringLocalizer<>), typeof(StringLocalizer<>))); + } + + [Fact] + public void AddJsonLocalizationWithOptions() { - [Fact] - public void AddJsonLocalization() - { - // Arrange - var services = new ServiceCollection(); - - // Act - JsonLocalizationServiceCollectionExtensions.AddJsonLocalization(services); - - // Assert - Assert.Equal(1, services.Count()); - Assert.Equal(1, services.Count(typeof(IStringLocalizer<>), typeof(StringLocalizer<>))); - } - - [Fact] - public void AddJsonLocalizationWithOptions() - { - // Arrange - var services = new ServiceCollection(); - var localizationOptions = new JsonLocalizationOptions(); - - // Act - JsonLocalizationServiceCollectionExtensions.AddJsonLocalization(services, - options => options.ResourcesPath = "Resources"); - - var localizationConfigureOptions = (ConfigureNamedOptions)services - .SingleOrDefault(sd => sd.ServiceType == typeof(IConfigureOptions)) - ?.ImplementationInstance; - - // Assert - Assert.Equal(1, services.Count(typeof(IStringLocalizerFactory), typeof(JsonStringLocalizerFactory))); - Assert.Equal(1, services.Count(typeof(IStringLocalizer<>), typeof(StringLocalizer<>))); - Assert.NotNull(localizationConfigureOptions); - - localizationConfigureOptions.Action.Invoke(localizationOptions); - - Assert.Equal("Resources", localizationOptions.ResourcesPath); - } + // Arrange + var services = new ServiceCollection(); + var localizationOptions = new JsonLocalizationOptions(); + + // Act + JsonLocalizationServiceCollectionExtensions.AddJsonLocalization(services, + options => options.ResourcesPath = "Resources"); + + var localizationConfigureOptions = (ConfigureNamedOptions)services + .SingleOrDefault(sd => sd.ServiceType == typeof(IConfigureOptions)) + ?.ImplementationInstance; + + // Assert + Assert.Equal(1, services.Count(typeof(IStringLocalizerFactory), typeof(JsonStringLocalizerFactory))); + Assert.Equal(1, services.Count(typeof(IStringLocalizer<>), typeof(StringLocalizer<>))); + Assert.NotNull(localizationConfigureOptions); + + localizationConfigureOptions.Action.Invoke(localizationOptions); + + Assert.Equal("Resources", localizationOptions.ResourcesPath); } } \ No newline at end of file diff --git a/test/My.Extensions.Localization.Json.Tests/JsonStringLocalizerFactoryTests.cs b/test/My.Extensions.Localization.Json.Tests/JsonStringLocalizerFactoryTests.cs index 2687450..8e230dc 100644 --- a/test/My.Extensions.Localization.Json.Tests/JsonStringLocalizerFactoryTests.cs +++ b/test/My.Extensions.Localization.Json.Tests/JsonStringLocalizerFactoryTests.cs @@ -14,143 +14,140 @@ using My.Extensions.Localization.Json.Tests.Common; using Xunit; -namespace My.Extensions.Localization.Json.Tests +namespace My.Extensions.Localization.Json.Tests; + +public class JsonStringLocalizerFactoryTests { - public class JsonStringLocalizerFactoryTests + private readonly Mock> _localizationOptions; + private readonly ILoggerFactory _loggerFactory; + + public JsonStringLocalizerFactoryTests() { - private readonly Mock> _localizationOptions; - private readonly ILoggerFactory _loggerFactory; + _localizationOptions = new Mock>(); + _loggerFactory = NullLoggerFactory.Instance; + } - public JsonStringLocalizerFactoryTests() - { - _localizationOptions = new Mock>(); - _loggerFactory = NullLoggerFactory.Instance; - } + [Fact] + public void JsonStringLocalizerFactory_CreateLocalizerWithType() + { + SetupLocalizationOptions("Resources"); + LocalizationHelper.SetCurrentCulture("fr-FR"); - [Fact] - public void JsonStringLocalizerFactory_CreateLocalizerWithType() - { - SetupLocalizationOptions("Resources"); - LocalizationHelper.SetCurrentCulture("fr-FR"); + // Arrange + var localizerFactory = new JsonStringLocalizerFactory(_localizationOptions.Object, _loggerFactory); - // Arrange - var localizerFactory = new JsonStringLocalizerFactory(_localizationOptions.Object, _loggerFactory); + // Act + var localizer = localizerFactory.Create(typeof(Test)); - // Act - var localizer = localizerFactory.Create(typeof(Test)); + // Assert + Assert.NotNull(localizer); + Assert.Equal("Bonjour", localizer["Hello"]); + } - // Assert - Assert.NotNull(localizer); - Assert.Equal("Bonjour", localizer["Hello"]); - } + [Theory] + [InlineData(typeof(string))] + [InlineData(typeof(Test))] + public void CreateLocalizerWithTypeSucceeds(Type type) + { + SetupLocalizationOptions("Resources"); + LocalizationHelper.SetCurrentCulture("fr-FR"); - [Theory] - [InlineData(typeof(string))] - [InlineData(typeof(Test))] - public void CreateLocalizerWithTypeSucceeds(Type type) - { - SetupLocalizationOptions("Resources"); - LocalizationHelper.SetCurrentCulture("fr-FR"); + // Arrange + var localizerFactory = new JsonStringLocalizerFactory(_localizationOptions.Object, _loggerFactory); - // Arrange - var localizerFactory = new JsonStringLocalizerFactory(_localizationOptions.Object, _loggerFactory); + // Act + localizerFactory.Create(type); - // Act - localizerFactory.Create(type); + // Assert + // Should not throw an exception + } - // Assert - // Should not throw an exception - } + [Theory] + [InlineData(ResourcesType.TypeBased)] + [InlineData(ResourcesType.CultureBased)] + public void CreateLocalizerWithBasenameAndLocation(ResourcesType resourcesType) + { + SetupLocalizationOptions("Resources", resourcesType); + LocalizationHelper.SetCurrentCulture("fr-FR"); - [Theory] - [InlineData(ResourcesType.TypeBased)] - [InlineData(ResourcesType.CultureBased)] - public void CreateLocalizerWithBasenameAndLocation(ResourcesType resourcesType) - { - SetupLocalizationOptions("Resources", resourcesType); - LocalizationHelper.SetCurrentCulture("fr-FR"); + // Arrange + var localizerFactory = new JsonStringLocalizerFactory(_localizationOptions.Object, _loggerFactory); + var location = "My.Extensions.Localization.Json.Tests"; + var basename = $"{location}.Common.{nameof(Test)}"; - // Arrange - var localizerFactory = new JsonStringLocalizerFactory(_localizationOptions.Object, _loggerFactory); - var location = "My.Extensions.Localization.Json.Tests"; - var basename = $"{location}.Common.{nameof(Test)}"; + // Act + var localizer = localizerFactory.Create(basename, location); - // Act - var localizer = localizerFactory.Create(basename, location); + // Assert + Assert.NotNull(localizer); + Assert.Equal("Bonjour", localizer["Hello"]); + } - // Assert - Assert.NotNull(localizer); - Assert.Equal("Bonjour", localizer["Hello"]); - } + [Fact] + public async Task LocalizerReturnsTranslationFromInnerClass() + { + var webHostBuilder = new WebHostBuilder() + .ConfigureServices(services => + { + services.AddJsonLocalization(options => options.ResourcesPath = "Resources"); + }) + .Configure(app => + { + app.UseRequestLocalization("en", "ar"); - [Fact] - public async Task LocalizerReturnsTranslationFromInnerClass() - { - var webHostBuilder = new WebHostBuilder() - .ConfigureServices(services => - { - services.AddJsonLocalization(options => options.ResourcesPath = "Resources"); - }) - .Configure(app => + app.Run(async context => { - app.UseRequestLocalization("en", "ar"); + var localizer = context.RequestServices.GetService>(); - app.Run(async context => - { - var localizer = context.RequestServices.GetService>(); + LocalizationHelper.SetCurrentCulture("ar"); - LocalizationHelper.SetCurrentCulture("ar"); + Assert.Equal("مرحباً", localizer["Hello"]); - Assert.Equal("مرحباً", localizer["Hello"]); - - await Task.CompletedTask; - }); + await Task.CompletedTask; }); + }); - using (var server = new TestServer(webHostBuilder)) - { - var client = server.CreateClient(); - var response = await client.GetAsync("/"); - } - } + using var server = new TestServer(webHostBuilder); + var client = server.CreateClient(); + var response = await client.GetAsync("/"); + } - private void SetupLocalizationOptions(string resourcesPath, ResourcesType resourcesType = ResourcesType.TypeBased) - => _localizationOptions.Setup(o => o.Value) - .Returns(() => new JsonLocalizationOptions { - ResourcesPath = resourcesPath, - ResourcesType = resourcesType - }); + private void SetupLocalizationOptions(string resourcesPath, ResourcesType resourcesType = ResourcesType.TypeBased) + => _localizationOptions.Setup(o => o.Value) + .Returns(() => new JsonLocalizationOptions { + ResourcesPath = resourcesPath, + ResourcesType = resourcesType + }); - public class InnerClassStartup + public class InnerClassStartup + { + public void ConfigureServices(IServiceCollection services) { - public void ConfigureServices(IServiceCollection services) - { - services.AddMvc(); - services.AddLocalization(); - services.AddJsonLocalization(options => options.ResourcesPath = "Resources"); - } - - public void Configure(IApplicationBuilder app, IStringLocalizer localizer) - { - var supportedCultures = new[] { "ar", "en" }; - app.UseRequestLocalization(options => - options - .AddSupportedCultures(supportedCultures) - .AddSupportedUICultures(supportedCultures) - .SetDefaultCulture("ar") - ); - - app.Run(async (context) => - { - var loc = localizer["Hello"]; - await context.Response.WriteAsync(localizer["Hello"]); - }); - } + services.AddMvc(); + services.AddLocalization(); + services.AddJsonLocalization(options => options.ResourcesPath = "Resources"); } - public class Model + public void Configure(IApplicationBuilder app, IStringLocalizer localizer) { - public string Hello { get; set; } + var supportedCultures = new[] { "ar", "en" }; + app.UseRequestLocalization(options => + options + .AddSupportedCultures(supportedCultures) + .AddSupportedUICultures(supportedCultures) + .SetDefaultCulture("ar") + ); + + app.Run(async (context) => + { + var loc = localizer["Hello"]; + await context.Response.WriteAsync(localizer["Hello"]); + }); } } + + public class Model + { + public string Hello { get; set; } + } } \ No newline at end of file diff --git a/test/My.Extensions.Localization.Json.Tests/JsonStringLocalizerTests.cs b/test/My.Extensions.Localization.Json.Tests/JsonStringLocalizerTests.cs index 5b3cdae..efec31d 100644 --- a/test/My.Extensions.Localization.Json.Tests/JsonStringLocalizerTests.cs +++ b/test/My.Extensions.Localization.Json.Tests/JsonStringLocalizerTests.cs @@ -12,167 +12,158 @@ using My.Extensions.Localization.Json.Tests.Common; using Xunit; -namespace My.Extensions.Localization.Json.Tests +namespace My.Extensions.Localization.Json.Tests; + +public class JsonStringLocalizerTests { - public class JsonStringLocalizerTests + private readonly IStringLocalizer _localizer; + + public JsonStringLocalizerTests() { - private readonly IStringLocalizer _localizer; - - public JsonStringLocalizerTests() - { - var _localizationOptions = new Mock>(); - _localizationOptions.Setup(o => o.Value) - .Returns(() => new JsonLocalizationOptions { ResourcesPath = "Resources" }); - var localizerFactory = new JsonStringLocalizerFactory(_localizationOptions.Object, NullLoggerFactory.Instance); - var location = "My.Extensions.Localization.Json.Tests"; - var basename = $"{location}.Common.{nameof(Test)}"; - _localizer = localizerFactory.Create(basename, location); - } - - [Theory] - [InlineData("fr-FR", "Hello", "Bonjour")] - [InlineData("fr-FR", "Bye", "Bye")] - [InlineData("ar", "Hello", "مرحبا")] - [InlineData("ar", "Bye", "Bye")] - public void GetTranslation(string culture, string name, string expected) - { - // Arrange - string translation = null; - - // Act - LocalizationHelper.SetCurrentCulture(culture); - translation = _localizer[name]; - - // Assert - Assert.Equal(expected, translation); - } - - [Theory] - [InlineData("fr-FR", "Hello, {0}", "Bonjour, Hisham", "Hisham")] - [InlineData("fr-FR", "Bye {0}", "Bye Hisham", "Hisham")] - [InlineData("ar", "Hello, {0}", "مرحبا, هشام", "هشام")] - [InlineData("ar", "Bye {0}", "Bye هشام", "هشام")] - public void GetTranslationWithArgs(string culture, string name, string expected, string arg) - { - // Arrange - string translation = null; - - // Act - LocalizationHelper.SetCurrentCulture(culture); - translation = _localizer[name, arg]; - - // Assert - Assert.Equal(expected, translation); - } - - [Theory] - [InlineData("fr-FR", "Hello", "Bonjour")] - [InlineData("fr-FR", "Hello, {0}", "Bonjour, {0}")] - [InlineData("fr-FR", "Yes", "Oui")] - [InlineData("fr-FR", "No", "No")] - [InlineData("fr", "Hello", "Bonjour")] - [InlineData("fr", "Yes", "Oui")] - [InlineData("fr", "No", "No")] - public void GetTranslationWithCultureFallback(string culture, string name, string expected) - { - // Arrange - string translation = null; - - // Act - LocalizationHelper.SetCurrentCulture(culture); - translation = _localizer[name]; - - // Assert - Assert.Equal(expected, translation); - } - - - [Theory] - [InlineData("zh-CN", "Hello", "你好")] - [InlineData("zh-CN", "Hello, {0}", "你好,{0}")] - public void GetTranslationWithCommentsOrCommas(string culture, string name, string expected) - { - // Arrange - string translation = null; - - // Act - LocalizationHelper.SetCurrentCulture(culture); - translation = _localizer[name]; - - // Assert - Assert.Equal(expected, translation); - } - - [Fact] - public void GetTranslation_StronglyTypeResourceName() - { - // Arrange - string translation = null; - - // Act - LocalizationHelper.SetCurrentCulture("ar"); - translation = _localizer.GetString(r => r.Hello); - - // Assert - Assert.Equal("مرحبا", translation); - } - - [Theory] - [InlineData(true, 3)] - [InlineData(false, 2)] - public void JsonStringLocalizer_GetAllStrings(bool includeParent, int expected) - { - // Arrange - IEnumerable localizedStrings = null; - - // Act - LocalizationHelper.SetCurrentCulture("fr-FR"); - localizedStrings = _localizer.GetAllStrings(includeParent); - - // Assert - Assert.Equal(expected, localizedStrings.Count()); - } - - [Fact] - public async void CultureBasedResourcesUsesIStringLocalizer() - { - var webHostBuilder = new WebHostBuilder() - .ConfigureServices(services => - { - services.AddJsonLocalization(options => - { - options.ResourcesPath = "Resources"; - options.ResourcesType = ResourcesType.CultureBased; - }); - }) - .Configure(app => + var _localizationOptions = new Mock>(); + _localizationOptions.Setup(o => o.Value) + .Returns(() => new JsonLocalizationOptions { ResourcesPath = "Resources" }); + var localizerFactory = new JsonStringLocalizerFactory(_localizationOptions.Object, NullLoggerFactory.Instance); + var location = "My.Extensions.Localization.Json.Tests"; + var basename = $"{location}.Common.{nameof(Test)}"; + _localizer = localizerFactory.Create(basename, location); + } + + [Theory] + [InlineData("fr-FR", "Hello", "Bonjour")] + [InlineData("fr-FR", "Bye", "Bye")] + [InlineData("ar", "Hello", "مرحبا")] + [InlineData("ar", "Bye", "Bye")] + public void GetTranslation(string culture, string name, string expected) + { + // Arrange + LocalizationHelper.SetCurrentCulture(culture); + + // Act + string translation = _localizer[name]; + + // Assert + Assert.Equal(expected, translation); + } + + [Theory] + [InlineData("fr-FR", "Hello, {0}", "Bonjour, Hisham", "Hisham")] + [InlineData("fr-FR", "Bye {0}", "Bye Hisham", "Hisham")] + [InlineData("ar", "Hello, {0}", "مرحبا, هشام", "هشام")] + [InlineData("ar", "Bye {0}", "Bye هشام", "هشام")] + public void GetTranslationWithArgs(string culture, string name, string expected, string arg) + { + // Arrange + LocalizationHelper.SetCurrentCulture(culture); + + // Act + string translation = _localizer[name, arg]; + + // Assert + Assert.Equal(expected, translation); + } + + [Theory] + [InlineData("fr-FR", "Hello", "Bonjour")] + [InlineData("fr-FR", "Hello, {0}", "Bonjour, {0}")] + [InlineData("fr-FR", "Yes", "Oui")] + [InlineData("fr-FR", "No", "No")] + [InlineData("fr", "Hello", "Bonjour")] + [InlineData("fr", "Yes", "Oui")] + [InlineData("fr", "No", "No")] + public void GetTranslationWithCultureFallback(string culture, string name, string expected) + { + // Arrange + LocalizationHelper.SetCurrentCulture(culture); + + // Act + string translation = _localizer[name]; + + // Assert + Assert.Equal(expected, translation); + } + + + [Theory] + [InlineData("zh-CN", "Hello", "你好")] + [InlineData("zh-CN", "Hello, {0}", "你好,{0}")] + public void GetTranslationWithCommentsOrCommas(string culture, string name, string expected) + { + // Arrange + LocalizationHelper.SetCurrentCulture(culture); + + // Act + string translation = _localizer[name]; + + // Assert + Assert.Equal(expected, translation); + } + + [Fact] + public void GetTranslation_StronglyTypeResourceName() + { + // Arrange + LocalizationHelper.SetCurrentCulture("ar"); + + // Act + var translation = _localizer.GetString(r => r.Hello); + + // Assert + Assert.Equal("مرحبا", translation); + } + + [Theory] + [InlineData(true, 3)] + [InlineData(false, 2)] + public void JsonStringLocalizer_GetAllStrings(bool includeParent, int expected) + { + // Arrange + LocalizationHelper.SetCurrentCulture("fr-FR"); + + // Act + var localizedStrings = _localizer.GetAllStrings(includeParent); + + // Assert + Assert.Equal(expected, localizedStrings.Count()); + } + + [Fact] + public async void CultureBasedResourcesUsesIStringLocalizer() + { + var webHostBuilder = new WebHostBuilder() + .ConfigureServices(services => + { + services.AddJsonLocalization(options => { - app.UseRequestLocalization("en-US", "fr-FR"); + options.ResourcesPath = "Resources"; + options.ResourcesType = ResourcesType.CultureBased; + }); + }) + .Configure(app => + { + app.UseRequestLocalization("en-US", "fr-FR"); - app.Run(async context => - { - var localizer = context.RequestServices.GetService>(); + app.Run(async context => + { + var localizer = context.RequestServices.GetService>(); - LocalizationHelper.SetCurrentCulture("fr-FR"); + LocalizationHelper.SetCurrentCulture("fr-FR"); - Assert.Equal("Bonjour", localizer["Hello"]); + Assert.Equal("Bonjour", localizer["Hello"]); - await Task.CompletedTask; - }); + await Task.CompletedTask; }); + }); - using (var server = new TestServer(webHostBuilder)) - { - var client = server.CreateClient(); - var response = await client.GetAsync("/"); - } - } + using var server = new TestServer(webHostBuilder); + var client = server.CreateClient(); + var response = await client.GetAsync("/"); + } - private class SharedResource - { - public string Hello { get; set; } + private class SharedResource + { + public string Hello { get; set; } - public string Bye { get; set; } - } + public string Bye { get; set; } } } \ No newline at end of file diff --git a/test/My.Extensions.Localization.Json.Tests/ServiceCollectionExtensions.cs b/test/My.Extensions.Localization.Json.Tests/ServiceCollectionExtensions.cs index 239d849..1ce830c 100644 --- a/test/My.Extensions.Localization.Json.Tests/ServiceCollectionExtensions.cs +++ b/test/My.Extensions.Localization.Json.Tests/ServiceCollectionExtensions.cs @@ -1,37 +1,30 @@ using System; using System.Linq; -namespace Microsoft.Extensions.DependencyInjection +namespace Microsoft.Extensions.DependencyInjection; + +public static class ServiceCollectionExtensions { - public static class ServiceCollectionExtensions + internal static int Count(this IServiceCollection services) + where TService : class + where TImplementation : class, TService + => Count(services, typeof(TService), typeof(TImplementation)); + + internal static int Count(this IServiceCollection services, Type serviceType, Type implementationType) { - internal static int Count(this IServiceCollection services) - where TService : class - where TImplementation : class, TService - => Count(services, typeof(TService), typeof(TImplementation)); + ArgumentNullException.ThrowIfNull(services); - internal static int Count(this IServiceCollection services, Type serviceType, Type implementationType) + if (serviceType == null) { - if (services == null) - { - throw new ArgumentNullException(nameof(services)); - } - - if (serviceType == null) - { - throw new ArgumentNullException(nameof(serviceType)); - } + throw new ArgumentNullException(nameof(serviceType)); + } - if (implementationType == null) - { - throw new ArgumentNullException(nameof(implementationType)); - } + ArgumentNullException.ThrowIfNull(implementationType); - var matches = services - .Where(sd => sd.ServiceType == serviceType && sd.ImplementationType == implementationType) - .ToArray(); + var matches = services + .Where(sd => sd.ServiceType == serviceType && sd.ImplementationType == implementationType) + .ToArray(); - return matches.Length; - } + return matches.Length; } } \ No newline at end of file