c# - Blazor - 在运行时更改 UI CultureInfo

标签 c# localization blazor blazor-server-side

我需要根据每种文化的资源文件在运行时更改文化。

预期的

用户单击从当前语言切换到另一种语言的按钮。页面中的文本根据每种文化的资源文件进行刷新。

实际的

用户单击从当前语言切换到另一种语言的按钮。页面中的文本根据每种文化的资源文件进行刷新。一旦用户对任何组件(我有几个单选按钮、按钮和复选框)执行任何操作,文本就会回到第一次编写的内容。就像 CultureInfo 根本没有改变一样。

尝试

创建了一个注入(inject)到组件的 AppState 类

    public class AppState
{
    public CultureInfo currentCulture { get; private set; } = CultureInfo.CurrentCulture;
    public event Action OnChange;
    public void ChangeCulture(CultureInfo newCulture)
    {
        currentCulture = newCulture;
        System.Threading.Thread.CurrentThread.CurrentCulture.ClearCachedData();
        System.Threading.Thread.CurrentThread.CurrentUICulture.ClearCachedData();
        System.Threading.Thread.CurrentThread.CurrentCulture = newCulture;
        System.Threading.Thread.CurrentThread.CurrentUICulture = newCulture;
        NotifyStateChanged();
    }

    public CultureInfo getCurrentCulture()
    {
        if (currentCulture == null)
        {
            ChangeCulture(CultureInfo.CurrentCulture);
        }
        return currentCulture;

    }

    private void NotifyStateChanged() => OnChange?.Invoke();
}

在 startup.cs 和 AppState instante 中为项目添加了本地化
        services.AddScoped<AppState>();
        services.AddMvc().AddMvcLocalization();
        services.AddLocalization();
        var supportedCultures = new List<CultureInfo> { new CultureInfo("en-US"), new CultureInfo("es-ES") };
        services.Configure<RequestLocalizationOptions>(options =>
        {
            options.DefaultRequestCulture = new RequestCulture("es-ES");
            options.SupportedUICultures = supportedCultures;
            options.SupportedCultures = supportedCultures;
        });

组件注入(inject)了 AppState 以及 IStringLocalizer 对象以从资源文件中获取字符串。
@inject AppState state
@inject IStringLocalizer<Index> _localizer

@implements IDisposable

<div class="uk-container" id="data_container">
    <button @onclick="e => CambiarIdioma()">Holadenuevo</button>

    <TablaReconocimientos @ref="tablaReconocimientos" searchText="@navigatableSearchInput"></TablaReconocimientos>
</div>

然后设置事件
    protected override void OnInitialized()
    {
        _lematizador = new LematizadorService();

        state.OnChange += OnCultureChange;
    }

    public void Dispose()
    {
        state.OnChange -= OnCultureChange;
    }
    private void CambiarIdioma()
    {
        if (state.getCurrentCulture().Equals(new CultureInfo("es-ES")))
        {
            state.ChangeCulture(new CultureInfo("en-US"));
        }
        else
        {
            state.ChangeCulture(new CultureInfo("es-ES"));
        }
    }

    private void OnCultureChange()
    {
        CultureInfo.CurrentCulture = state.currentCulture;
        CultureInfo.CurrentUICulture = state.currentCulture;

        StateHasChanged();
    }

因此,现在单击触发 CambiarIdioma() 的按钮时,该项目可以正常工作。但是,只要在组件内完成任何操作(假设我检查了 TablaReconocimientos 组件内的某些内容或单击单选按钮),文本就会恢复为其原始字符串。

每个需要本地化文本的组件都注入(inject)了 AppState 并实现了以下功能:
@inject AppState state
@inject IStringLocalizer<TablaModos> _localizer

@implements IDisposable


@*Component stuff*@

@functions{
    protected override void OnInitialized()
    {
        state.OnChange += OnCultureChange;
    }

    public void Dispose()
    {
        state.OnChange -= OnCultureChange;
    }

    private void OnCultureChange()
    {
        CultureInfo.CurrentCulture = state.currentCulture;
        CultureInfo.CurrentUICulture = state.currentCulture;

        StateHasChanged();
    }

}

图像作为目前发生的事情的例子:
enter image description here

最佳答案

您需要使用 Cookie 来存储所选的文化。请参阅 Microsoft 文档。
https://docs.microsoft.com/en-us/aspnet/core/blazor/globalization-localization?view=aspnetcore-5.0#cookies
从文档中:
Blazor 服务器
Blazor 服务器应用使用本地化中间件进行本地化。中间件为从应用程序请求资源的用户选择适当的文化。
可以使用以下方法之一设置区域性:
cookies
提供 UI 以选择文化
有关详细信息和示例,请参阅 ASP.NET Core 中的全局化和本地化。
cookies
本地化文化 cookie 可以保留用户的文化。本地化中间件在后续请求中读取 cookie 以设置用户的文化。
使用 cookie 可确保 WebSocket 连接可以正确传播文化。如果本地化方案基于 URL 路径或查询字符串,则该方案可能无法与 WebSockets 一起使用,因此无法保持文化。因此,推荐使用本地化文化 cookie。
如果文化持续存在于本地化 cookie 中,则可以使用任何技术来分配文化。如果应用已经为服务器端 ASP.NET Core 建立了本地化方案,请继续使用应用现有的本地化基础结构并在应用的方案中设置本地化文化 cookie。
以下示例显示了如何在本地化中间件可以读取的 cookie 中设置当前文化。在开始标记内的 Pages/_Host.cshtml 文件中创建 Razor 表达式:
CSHTML
复制

@using System.Globalization
@using Microsoft.AspNetCore.Localization

...

<body>
    @{
        this.HttpContext.Response.Cookies.Append(
            CookieRequestCultureProvider.DefaultCookieName,
            CookieRequestCultureProvider.MakeCookieValue(
                new RequestCulture(
                    CultureInfo.CurrentCulture,
                    CultureInfo.CurrentUICulture)));
    }

    ...
</body>
本地化由应用程序按以下事件序列处理:
浏览器向应用程序发送初始 HTTP 请求。
文化由本地化中间件分配。
_Host 页面 (_Host.cshtml) 中的 Razor 表达式将区域性保留在 cookie 中作为响应的一部分。
浏览器打开 WebSocket 连接以创建交互式 Blazor 服务器 session 。
本地化中间件读取 cookie 并分配文化。
Blazor 服务器 session 以正确的区域性开始。
使用 RazorPage 时,请使用 Context 属性:
Razor
复制
@{
    this.Context.Response.Cookies.Append(
        CookieRequestCultureProvider.DefaultCookieName,
        CookieRequestCultureProvider.MakeCookieValue(
            new RequestCulture(
                CultureInfo.CurrentCulture,
                CultureInfo.CurrentUICulture)));
}
提供 UI 以选择文化
为了提供 UI 以允许用户选择文化,建议使用基于重定向的方法。该过程类似于用户尝试访问安全资源时在 Web 应用程序中发生的情况。用户被重定向到登录页面,然后被重定向回原始资源。
该应用程序通过重定向到 Controller 来保留用户选择的文化。 Controller 将用户选择的文化设置到 cookie 中,并将用户重定向回原始 URI。
在服务器上建立一个 HTTP 端点以在 cookie 中设置用户选择的文化并执行重定向回原始 URI:
C#
复制
[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);
    }
}

关于c# - Blazor - 在运行时更改 UI CultureInfo,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61100991/

相关文章:

c# - 无法从 BlobItem 检索元数据

ios - 在应用商店上按国家/地区本地化应用名称

iphone - Interface Builder 文件中的未知类 <MyViewController> + 本地化问题

asp.net-core - 是什么导致 __builder 在编译器的当前上下文错误中不存在?

c# - Microsoft 的数字库的名称是什么?

c# - 如何在 Java 客户端的 WCF 服务中使用 C#-Properties

c# - 多个对象上的多个独立锁

ios - 在 iOS 的本地化选择中包含区域

c# - [Inject] 出现问题,无法在 C# 类 (Blazor) 中工作

javascript - Blazor javascript interop - 从 js 到 .NET 的对象转换