Skip to content

Commit de1b5b1

Browse files
authored
feat(JsonLocalizationOptions): add DisableGetLocalizerFromService parameter (#5164)
* chore: 增加配置项 * feat: 增加 DisableGetLocalizerFromService 配置项 * feat: 增加本地化获取逻辑 * test: 更新单元测试 * test: 更新单元测试 * chore: bump version 9.2.9-beta01
1 parent e0f6516 commit de1b5b1

File tree

8 files changed

+109
-57
lines changed

8 files changed

+109
-57
lines changed

src/BootstrapBlazor.Server/appsettings.json

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,8 @@
4242
}
4343
},
4444
"IgnoreLocalizerMissing": true,
45+
"DisableGetLocalizerFromService": true,
46+
"DisableGetLocalizerFromResourceManager": true,
4547
"StepSettings": {
4648
"Short": "1",
4749
"Int": "1",

src/BootstrapBlazor/BootstrapBlazor.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
<Project Sdk="Microsoft.NET.Sdk.Razor">
22

33
<PropertyGroup>
4-
<Version>9.2.8</Version>
4+
<Version>9.2.9-beta01</Version>
55
</PropertyGroup>
66

77
<ItemGroup>

src/BootstrapBlazor/Localization/Json/JsonLocalizationOptions.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,16 @@ public class JsonLocalizationOptions : LocalizationOptions
4848
/// </summary>
4949
public bool UseKeyWhenValueIsNull { get; set; }
5050

51+
/// <summary>
52+
/// 获得/设置 是否禁用从服务中获取本地化资源 默认 false 未禁用
53+
/// </summary>
54+
public bool DisableGetLocalizerFromService { get; set; }
55+
56+
/// <summary>
57+
/// 获得/设置 是否禁用获取 <see cref="ResourceManagerStringLocalizer"/> 类型本地化资源 默认 false 未禁用
58+
/// </summary>
59+
public bool DisableGetLocalizerFromResourceManager { get; set; }
60+
5161
/// <summary>
5262
/// 获得/设置 资源文件是否热加载 默认 false
5363
/// </summary>

src/BootstrapBlazor/Localization/Json/JsonStringLocalizer.cs

Lines changed: 41 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -18,11 +18,11 @@ namespace BootstrapBlazor.Components;
1818
/// <param name="assembly"></param>
1919
/// <param name="typeName"></param>
2020
/// <param name="baseName"></param>
21-
/// <param name="ignoreLocalizerMissing"></param>
21+
/// <param name="jsonLocalizationOptions"></param>
2222
/// <param name="logger"></param>
2323
/// <param name="resourceNamesCache"></param>
2424
/// <param name="localizationMissingItemHandler"></param>
25-
internal class JsonStringLocalizer(Assembly assembly, string typeName, string baseName, bool ignoreLocalizerMissing, ILogger logger, IResourceNamesCache resourceNamesCache, ILocalizationMissingItemHandler localizationMissingItemHandler) : ResourceManagerStringLocalizer(new ResourceManager(baseName, assembly), assembly, baseName, resourceNamesCache, logger)
25+
internal class JsonStringLocalizer(Assembly assembly, string typeName, string baseName, JsonLocalizationOptions jsonLocalizationOptions, ILogger logger, IResourceNamesCache resourceNamesCache, ILocalizationMissingItemHandler localizationMissingItemHandler) : ResourceManagerStringLocalizer(new ResourceManager(baseName, assembly), assembly, baseName, resourceNamesCache, logger)
2626
{
2727
private Assembly Assembly { get; } = assembly;
2828

@@ -72,26 +72,39 @@ public override LocalizedString this[string name]
7272
}
7373
}
7474

75-
private string? GetStringSafely(string name) => GetStringFromService(name) ?? GetStringSafely(name, null) ?? GetStringSafelyFromJson(name);
75+
private string? GetStringSafely(string name) => GetStringFromService(name) ?? GetStringFromResourceManager(name) ?? GetStringFromJson(name);
7676

7777
private string? GetStringFromService(string name)
7878
{
7979
// get string from inject service
8080
string? ret = null;
81-
var localizer = Utility.GetStringLocalizerFromService(Assembly, typeName);
82-
if (localizer != null && localizer is not JsonStringLocalizer)
81+
if (jsonLocalizationOptions.DisableGetLocalizerFromService == false)
8382
{
84-
var l = localizer[name];
85-
if (!l.ResourceNotFound)
83+
var localizer = Utility.GetStringLocalizerFromService(Assembly, typeName);
84+
if (localizer != null && localizer is not JsonStringLocalizer)
8685
{
87-
ret = l.Value;
86+
var l = localizer[name];
87+
if (!l.ResourceNotFound)
88+
{
89+
ret = l.Value;
90+
}
8891
}
8992
}
9093
return ret;
9194
}
9295

96+
private string? GetStringFromResourceManager(string name)
97+
{
98+
string? ret = null;
99+
if (jsonLocalizationOptions.DisableGetLocalizerFromResourceManager == false)
100+
{
101+
ret = GetStringSafely(name, CultureInfo.CurrentUICulture);
102+
}
103+
return ret;
104+
}
105+
93106
private readonly ConcurrentDictionary<string, object?> _missingManifestCache = [];
94-
private string? GetStringSafelyFromJson(string name)
107+
private string? GetStringFromJson(string name)
95108
{
96109
// get string from json localization file
97110
var localizerStrings = MegerResolveLocalizers(CacheManager.GetAllStringsByTypeName(Assembly, typeName));
@@ -114,22 +127,18 @@ public override LocalizedString this[string name]
114127

115128
private List<LocalizedString> MegerResolveLocalizers(IEnumerable<LocalizedString>? localizerStrings)
116129
{
117-
var localizers = new List<LocalizedString>();
118-
var resolveLocalizers = CacheManager.GetTypeStringsFromResolve(typeName);
119-
localizers.AddRange(resolveLocalizers);
120-
130+
var localizers = new List<LocalizedString>(CacheManager.GetTypeStringsFromResolve(typeName));
121131
if (localizerStrings != null)
122132
{
123133
localizers.AddRange(localizerStrings);
124134
}
125135
return localizers;
126136
}
127137

128-
129138
private void HandleMissingResourceItem(string name)
130139
{
131140
localizationMissingItemHandler.HandleMissingItem(name, typeName, CultureInfo.CurrentUICulture.Name);
132-
if (!ignoreLocalizerMissing)
141+
if (jsonLocalizationOptions.IgnoreLocalizerMissing == false)
133142
{
134143
Logger.LogInformation("{JsonStringLocalizerName} searched for '{Name}' in '{TypeName}' with culture '{CultureName}' not found.", nameof(JsonStringLocalizer), name, typeName, CultureInfo.CurrentUICulture.Name);
135144
}
@@ -160,10 +169,13 @@ public override IEnumerable<LocalizedString> GetAllStrings(bool includeParentCul
160169
IEnumerable<LocalizedString>? GetAllStringsFromService()
161170
{
162171
IEnumerable<LocalizedString>? ret = null;
163-
var localizer = Utility.GetStringLocalizerFromService(Assembly, typeName);
164-
if (localizer != null && localizer is not JsonStringLocalizer)
172+
if (jsonLocalizationOptions.DisableGetLocalizerFromService == false)
165173
{
166-
ret = localizer.GetAllStrings(includeParentCultures);
174+
var localizer = Utility.GetStringLocalizerFromService(Assembly, typeName);
175+
if (localizer != null && localizer is not JsonStringLocalizer)
176+
{
177+
ret = localizer.GetAllStrings(includeParentCultures);
178+
}
167179
}
168180
return ret;
169181
}
@@ -172,14 +184,18 @@ public override IEnumerable<LocalizedString> GetAllStrings(bool includeParentCul
172184
// get all strings from base json localization factory
173185
IEnumerable<LocalizedString>? GetAllStringsFromBase()
174186
{
175-
IEnumerable<LocalizedString>? ret = base.GetAllStrings(includeParentCultures);
176-
try
177-
{
178-
CheckMissing();
179-
}
180-
catch (MissingManifestResourceException)
187+
IEnumerable<LocalizedString>? ret = null;
188+
if (jsonLocalizationOptions.DisableGetLocalizerFromResourceManager == false)
181189
{
182-
ret = null;
190+
ret = base.GetAllStrings(includeParentCultures);
191+
try
192+
{
193+
CheckMissing();
194+
}
195+
catch (MissingManifestResourceException)
196+
{
197+
ret = null;
198+
}
183199
}
184200
return ret;
185201

src/BootstrapBlazor/Localization/Json/JsonStringLocalizerFactory.cs

Lines changed: 21 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,10 @@ namespace BootstrapBlazor.Components;
1414
/// </summary>
1515
internal class JsonStringLocalizerFactory : ResourceManagerStringLocalizerFactory
1616
{
17-
private ILoggerFactory LoggerFactory { get; set; }
18-
19-
private ILocalizationMissingItemHandler LocalizationMissingItemHandler { get; set; }
20-
21-
[NotNull]
22-
private string? TypeName { get; set; }
23-
24-
private bool IgnoreLocalizerMissing { get; set; }
17+
private readonly ILoggerFactory _loggerFactory;
18+
private readonly JsonLocalizationOptions _jsonLocalizationOptions;
19+
private readonly ILocalizationMissingItemHandler _localizationMissingItemHandler;
20+
private string? _typeName;
2521

2622
/// <summary>
2723
/// 构造函数
@@ -35,7 +31,7 @@ internal class JsonStringLocalizerFactory : ResourceManagerStringLocalizerFactor
3531
public JsonStringLocalizerFactory(
3632
ICacheManager cacheManager,
3733
ILocalizationMissingItemHandler localizationMissingItemHandler,
38-
IOptionsMonitor<BootstrapBlazorOptions> options,
34+
IOptions<BootstrapBlazorOptions> options,
3935
IOptions<JsonLocalizationOptions> jsonLocalizationOptions,
4036
IOptions<LocalizationOptions> localizationOptions,
4137
ILoggerFactory loggerFactory) : base(localizationOptions, loggerFactory)
@@ -44,28 +40,23 @@ public JsonStringLocalizerFactory(
4440
// 为了保证 CacheManager 内部 Instance 可用这里需要使 ICacheManager 先实例化
4541
cacheManager.SetStartTime();
4642

47-
jsonLocalizationOptions.Value.FallbackCulture = options.CurrentValue.FallbackCulture;
48-
jsonLocalizationOptions.Value.EnableFallbackCulture = options.CurrentValue.EnableFallbackCulture;
49-
if (options.CurrentValue.IgnoreLocalizerMissing.HasValue)
43+
jsonLocalizationOptions.Value.FallbackCulture = options.Value.FallbackCulture;
44+
jsonLocalizationOptions.Value.EnableFallbackCulture = options.Value.EnableFallbackCulture;
45+
if (options.Value.IgnoreLocalizerMissing.HasValue)
5046
{
51-
jsonLocalizationOptions.Value.IgnoreLocalizerMissing = options.CurrentValue.IgnoreLocalizerMissing.Value;
47+
jsonLocalizationOptions.Value.IgnoreLocalizerMissing = options.Value.IgnoreLocalizerMissing.Value;
5248
}
53-
IgnoreLocalizerMissing = jsonLocalizationOptions.Value.IgnoreLocalizerMissing;
54-
LocalizationMissingItemHandler = localizationMissingItemHandler;
55-
LoggerFactory = loggerFactory;
56-
options.OnChange(OnChange);
57-
58-
[ExcludeFromCodeCoverage]
59-
void OnChange(BootstrapBlazorOptions op)
49+
if (options.Value.DisableGetLocalizerFromService.HasValue)
50+
{
51+
jsonLocalizationOptions.Value.DisableGetLocalizerFromService = options.Value.DisableGetLocalizerFromService.Value;
52+
}
53+
if (options.Value.DisableGetLocalizerFromResourceManager.HasValue)
6054
{
61-
jsonLocalizationOptions.Value.EnableFallbackCulture = op.EnableFallbackCulture;
62-
jsonLocalizationOptions.Value.FallbackCulture = op.FallbackCulture;
63-
if (op.IgnoreLocalizerMissing.HasValue)
64-
{
65-
jsonLocalizationOptions.Value.IgnoreLocalizerMissing = op.IgnoreLocalizerMissing.Value;
66-
IgnoreLocalizerMissing = op.IgnoreLocalizerMissing.Value;
67-
}
55+
jsonLocalizationOptions.Value.DisableGetLocalizerFromResourceManager = options.Value.DisableGetLocalizerFromResourceManager.Value;
6856
}
57+
_localizationMissingItemHandler = localizationMissingItemHandler;
58+
_loggerFactory = loggerFactory;
59+
_jsonLocalizationOptions = jsonLocalizationOptions.Value;
6960
}
7061

7162
/// <summary>
@@ -86,7 +77,7 @@ protected override string GetResourcePrefix(TypeInfo typeInfo)
8677
var index = typeName.IndexOf('`');
8778
typeName = typeName[..index];
8879
}
89-
TypeName = typeName;
80+
_typeName = typeName;
9081

9182
return base.GetResourcePrefix(typeInfo);
9283
}
@@ -101,7 +92,7 @@ protected override string GetResourcePrefix(string baseResourceName, string base
10192
{
10293
// https://gitee.com/LongbowEnterprise/BootstrapBlazor/issues/I5SRA1
10394
var resourcePrefix = base.GetResourcePrefix(baseResourceName, baseNamespace);
104-
TypeName = $"{baseNamespace}.{baseResourceName}";
95+
_typeName = $"{baseNamespace}.{baseResourceName}";
10596

10697
return resourcePrefix;
10798
}
@@ -114,5 +105,5 @@ protected override string GetResourcePrefix(string baseResourceName, string base
114105
/// <param name="assembly">The assembly to create a <see cref="ResourceManagerStringLocalizer"/> for</param>
115106
/// <param name="baseName">The base name of the resource to search for</param>
116107
/// <returns></returns>
117-
protected override ResourceManagerStringLocalizer CreateResourceManagerStringLocalizer(Assembly assembly, string baseName) => new JsonStringLocalizer(assembly, TypeName, baseName, IgnoreLocalizerMissing, LoggerFactory.CreateLogger<JsonStringLocalizer>(), ResourceNamesCache, LocalizationMissingItemHandler);
108+
protected override ResourceManagerStringLocalizer CreateResourceManagerStringLocalizer(Assembly assembly, string baseName) => new JsonStringLocalizer(assembly, _typeName!, baseName, _jsonLocalizationOptions, _loggerFactory.CreateLogger<JsonStringLocalizer>(), ResourceNamesCache, _localizationMissingItemHandler);
118109
}

src/BootstrapBlazor/Options/BootstrapBlazorOptions.cs

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// See the LICENSE file in the project root for more information.
44
// Maintainer: Argo Zhang([email protected]) Website: https://www.blazor.zone
55

6+
using Microsoft.Extensions.Localization;
67
using System.Globalization;
78

89
namespace BootstrapBlazor.Components;
@@ -58,6 +59,16 @@ public class BootstrapBlazorOptions : IOptions<BootstrapBlazorOptions>
5859
/// <remarks>使用 <see cref="JsonLocalizationOptions.IgnoreLocalizerMissing"/> 默认值</remarks>
5960
public bool? IgnoreLocalizerMissing { get; set; }
6061

62+
/// <summary>
63+
/// 获得/设置 是否禁用从服务中获取本地化资源 默认 false 未禁用
64+
/// </summary>
65+
public bool? DisableGetLocalizerFromService { get; set; }
66+
67+
/// <summary>
68+
/// 获得/设置 是否禁用获取 <see cref="ResourceManagerStringLocalizer"/> 类型本地化资源 默认 false 未禁用
69+
/// </summary>
70+
public bool? DisableGetLocalizerFromResourceManager { get; set; }
71+
6172
/// <summary>
6273
/// 获得/设置 默认文化信息
6374
/// </summary>

test/UnitTest/Components/SelectGenericTest.cs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,6 @@ namespace UnitTest.Components;
1313

1414
public class SelectGenericTest : BootstrapBlazorTestBase
1515
{
16-
1716
[Fact]
1817
public void ScrollIntoViewBehavior_Ok()
1918
{

test/UnitTest/Localization/JsonStringLocalizerTest.cs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// See the LICENSE file in the project root for more information.
44
// Maintainer: Argo Zhang([email protected]) Website: https://www.blazor.zone
55

6+
using Microsoft.Extensions.Configuration;
67
using Microsoft.Extensions.DependencyInjection;
78
using Microsoft.Extensions.Localization;
89
using System.ComponentModel.DataAnnotations;
@@ -175,6 +176,27 @@ public void GetAllStrings_FromBase()
175176
Assert.Empty(items);
176177
}
177178

179+
[Fact]
180+
public void DisableGetLocalizerFromResourceManager_Ok()
181+
{
182+
var sc = new ServiceCollection();
183+
var builder = new ConfigurationBuilder();
184+
builder.AddJsonFile("appsettings.json");
185+
builder.AddInMemoryCollection(new Dictionary<string, string?>()
186+
{
187+
["BootstrapBlazorOptions:DisableGetLocalizerFromService"] = "true",
188+
["BootstrapBlazorOptions:DisableGetLocalizerFromResourceManager"] = "true"
189+
});
190+
var config = builder.Build();
191+
sc.AddSingleton<IConfiguration>(config);
192+
sc.AddBootstrapBlazor();
193+
194+
var provider = sc.BuildServiceProvider();
195+
var localizer = provider.GetRequiredService<IStringLocalizer<Dummy>>();
196+
var items = localizer.GetAllStrings(false);
197+
Assert.Empty(items);
198+
}
199+
178200
[Fact]
179201
public void GetAllStrings_FromResource()
180202
{
@@ -243,6 +265,7 @@ public void HandleMissingItem()
243265
var provider = sc.BuildServiceProvider();
244266
var localizer = provider.GetRequiredService<IStringLocalizer<Foo>>();
245267
var val = localizer["missing-item"];
268+
Assert.True(val.ResourceNotFound);
246269

247270
var handler = provider.GetRequiredService<ILocalizationMissingItemHandler>();
248271
MockLocalizationMissingItemHandler? mockHandler = null;

0 commit comments

Comments
 (0)