【发布时间】:2021-05-15 05:08:41
【问题描述】:
我正在使用 IStringLocalizer 方法来本地化我的 Blazor 应用程序,如 here 所述。
在剃须刀页面上注入IStringLocalizer 效果很好。我还需要它来本地化一些服务 - 无论是范围服务还是单例服务。
使用构造函数注入将我的IStringLocalizer 服务注入到服务中。但是,当用户通过 UI 更改语言时,服务(无论是单例还是作用域)保持 initial IStringLocalizer - 即启动时使用 original 语言的服务应用程序,而不是用户选择的更新语言。
从代码中检索更新的IStringLocalizer 的建议方法是什么?
编辑
为了防止更多细节,这里有一些代码。
首先,我添加一个Resources 文件夹并在其中创建一个默认的LocaleResources.resx(带有公共修饰符)和一个LocaleResources.fr.resx 文件,其中包含每种语言的键值对。
支持的文化在appsettings.json 文件中定义为
"Cultures": {
"en-US": "English",
"fr": "Français (Suisse)",
...
}
在启动时,我注册了Resources 文件夹和支持的文化:
public void ConfigureServices(IServiceCollection services {
...
services.AddLocalization(options => options.ResourcesPath = "Resources");
...
services.AddSingleton<MySingletonService>();
services.AddScoped<MyScopedService>();
}
// --- helper method to retrieve the Cultures from appsettings.json
protected RequestLocalizationOptions GetLocalizationOptions() {
var cultures = Configuration.GetSection("Cultures")
.GetChildren().ToDictionary(x => x.Key, x => x.Value);
var supportedCultures = cultures.Keys.ToArray();
var localizationOptions = new RequestLocalizationOptions()
.AddSupportedCultures(supportedCultures)
.AddSupportedUICultures(supportedCultures);
return localizationOptions;
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
...
app.UseRequestLocalization(GetLocalizationOptions());
...
app.UseEndpoints(endpoints => {
endpoints.MapControllers();
endpoints.MapBlazorHub();
endpoints.MapFallbackToPage("/_Host");
});
}
我在项目的根目录下创建了一个空的LocaleResources.razor 控件(这是用于将单个资源文件注入所有组件的技巧)。
我包含了一个路由控制器来更改语言:
[Route("[controller]/[action]")]
public class CultureController : Controller {
public IActionResult SetCulture(string culture, string redirectUri) {
if (culture != null) {
HttpContext.Response.Cookies.Append(
CookieRequestCultureProvider.DefaultCookieName,
CookieRequestCultureProvider.MakeCookieValue(
new RequestCulture(culture)));
}
return LocalRedirect(redirectUri);
}
}
语言 UI 切换器看起来像这样(我在这里使用 SyncFusion 控件,但实际上它可以是任何查找,这并不重要)
@inject NavigationManager NavigationManager
@inject IConfiguration Configuration
<SfComboBox TValue="string" TItem="Tuple<string, string>" Placeholder="Select language" DataSource="@Cultures"
@bind-Value="selectedCulture" CssClass="lan-switch" Width="80%">
<ComboBoxFieldSettings Text="Item2" Value="Item1"></ComboBoxFieldSettings>
</SfComboBox>
<style>
.lan-switch {
margin-left: 5%;
}
</style>
@code {
string _activeCulture = System.Threading.Thread.CurrentThread.CurrentCulture.Name;
private string selectedCulture {
get => _activeCulture;
set {
_activeCulture = value;
SelectionChanged(value);
}
}
List<Tuple<string, string>> Cultures;
protected override void OnInitialized() {
var cultures = Configuration.GetSection("Cultures")
.GetChildren().ToDictionary(x => x.Key, x => x.Value);
Cultures = cultures.Select(p => Tuple.Create<string, string>(p.Key, p.Value)).ToList();
}
protected override void OnAfterRender(bool firstRender) {
if (firstRender && selectedCulture != AgendaSettings.SelectedLanguage) {
selectedCulture = AgendaSettings.SelectedLanguage;
}
}
private void SelectionChanged(string culture) {
if (string.IsNullOrWhiteSpace(culture)) {
return;
}
AgendaSettings.SelectedLanguage = culture;
var uri = new Uri(NavigationManager.Uri)
.GetComponents(UriComponents.PathAndQuery, UriFormat.Unescaped);
var query = $"?culture={Uri.EscapeDataString(culture)}&" +
$"redirectUri={Uri.EscapeDataString(uri)}";
NavigationManager.NavigateTo("/Culture/SetCulture" + query, forceLoad: true);
}
}
最后,到了注入。我将IStringLocalizer 注入页面如下,它在剃须刀控件上运行良好:
@inject IStringLocalizer<LocaleResources> _loc
<h2>@_loc["hello world"]</h2>
以上,当我更改语言时,页面显示相应资源文件中的值。
现在,对于服务:MySingletonService 和 MyScopedService 在启动时注册。他们都有一个像
protected IStringLocalizer<LocaleResources> _loc;
public MySingletonService(IStringLocalizer<LocaleResources> loc) {
_loc = loc;
}
public void someMethod() {
Console.WriteLine(_loc["hello world"])
}
我在计时器上运行someMethod。奇怪的是,当我打破上述行时,结果似乎摇摆不定:一旦它返回默认语言的值,一旦本地化......!
【问题讨论】:
-
我认为问题在于语言更改逻辑,而不是 IStringLocalizer。但这很难说,你需要提供更多关于代码到底在做什么的信息。
-
您没有提供足够的信息(至少对我而言)来了解
IStringLocalizer如何基于用户选择的语言。所选语言是IStringLocalizer实例的构造函数参数吗?如果是这样,则意味着您的服务可能超出了包含语言更改的范围。但是你真的需要在这里提供一个更具体(而且仍然很简短)的例子。 -
好的,让我调整一下问题,让它足够清楚!
标签: dependency-injection localization blazor