多国语系魔术

今天要来介绍多国语系的处理,想要建立一个国际化网站,多国语系可以说是基本需求,那我们就来看如何在 Blazor 中实现吧!


除了数字与日期格式有原先 .NET 框架的文化特性外,其他都要自己来处理多国语系的范本,这也是理所当然的,除非机器翻译的准确率接近完美,否则公司大可花钱请人翻译,以免在公开网站出现奇葩内容。

那麽我们该如何在 Blazor wasm 中实现多国语系呢?很遗憾官方目前并没有提供一份详细的文件,但留了一个 Repository 来供我们参考,让我们以pranavkm/LocSample的方式来当作多国语系的处理吧!

首先针对需要多国语系的元件建立资源档,其档案名称如 {Component}.{Culture}.resxComponent 为使用此资源档的元件名称,需确保名称与元件名称一致,Culture 为文化特性的值,若不加则代表预设的资源档。

因为 .resx 属於 XML 格式的档案,所以这边就不贴 Code 了,建立 {Component.resx} 且拥有 Greetings 栏位其值为 你好!,并建立 {Component}.en.resx 且拥有 Greetings 栏位其值为 Hello!

Component 使用资源档前,需要先从 Nuget 安装 Microsoft.Extensions.Localization,我们需要透过其命名空间下的 IStringLocalizer<T> 物件来取得资源档内容,安装完毕後记得注册服务 builder.Services.AddLocalization();,注册时 AddLocalization 方法也提供 LocalizationOptions 来设定额外内容,虽然目前只有提供 ResourcesPath 来修改资源档定位的相关路径。

然後就可以在元件注入 IStringLocalizer<T> 来存取相关的资源档,如:

@* Day27Sample.razor *@
@inject Microsoft.Extensions.Localization.IStringLocalizer<Day27Sample> Loc
<h1>@Loc["Greetings"]</h1>

为了提供使用者切换文化特性,需要建立一个选择文化特性的元件:

@* CultureSelector.razor *@
@using  System.Globalization
@inject IJSRuntime JSRuntime
@inject NavigationManager Nav

<strong>Culture:</strong>
<select @bind="Culture">
    @foreach (var culture in supportedCultures)
    {
        <option value="@culture">@culture.DisplayName</option>
    }
</select>

@code
{
  CultureInfo[] supportedCultures = new[]
  {
    new CultureInfo("zh-TW"),
    new CultureInfo("en-US"),
  };

  CultureInfo Culture
  {
    get => CultureInfo.CurrentCulture;
    set
    {
      if (CultureInfo.CurrentCulture != value)
      {
        var js = (IJSInProcessRuntime)JSRuntime;
        js.InvokeVoid("blazorCulture.set", value.Name);
        Nav.NavigateTo(Nav.Uri, forceLoad: true);
      }
    }
  }
}

但因为注入後就会被初始化,所以我们一定要透过网页重启,来使文化特性在初始化时能以使用者选择的文化特性,所以我们需要藉由 localStorage 来保存使用者修改文化特性时的值,并且在重新启动时取得该值:

// Program.cs
var host = builder.Build();
var jsInterop = host.Services.GetRequiredService<IJSRuntime>();
var result = await jsInterop.InvokeAsync<string>("blazorCulture.get");
if (result != null)
{
  var culture = new CultureInfo(result);
  CultureInfo.DefaultThreadCurrentCulture = culture;
  CultureInfo.DefaultThreadCurrentUICulture = culture;
}

JS 内容为:

window.blazorCulture = {
    get: () => window.localStorage['BlazorCulture'],
    set: (value) => window.localStorage['BlazorCulture'] = value
};

这样只要在合适的地方使用 CultureSelector 元件选择文化特性,就能透过重新载入的方式使全站语系变更,且之後的每一次进入都可以看到相同的内容,除非使用者自行清除。


以上就是多国语系的处理方式,美中不足的是这套一定要使用 .resx 来当作资源档,没办法使用 .json 来处理,但 Blazor 也算是个新兴框架吧?相信未来会有更多的解决办法!完整程序码在范本程序码 - day27

感谢大家的阅读,我们明天见。

参考资料
ASP.NET Core Blazor 全球化和当地语系化
pranavkm/LocSample


<<:  Day36 - 「登愣登愣,登愣登登登」~ 隐挑战 Day12 ─ 果然我的青春写扣喜剧搞错了。完

>>:  Day 27: Incremental build

Day19 - 【概念篇】OAuth flows: Device Code(1)

本系列文之後也会置於个人网站 +----------+ +----------------+ | ...

[Day18] Esp32用STA mode + Relay - (程序码讲解)

1.前言 今天就不废话拉,直接进入主题(大家应该都去报复性出游了吧)。 2.html 其实HTML目...

DAY20-网站构思之进阶figma

前言: 昨天我们使用了几个基本的方法设计了网页的首页,今天阿森要来进一步介绍一些figma pro...

Day 7 - 拯救落後的专案能撑一天是一天(前端篇)

一个大包的专案程序码解压缩後看着满满的程序码思考着我可以实现计画案的目标吗...。接下来这三天会将专...

Day 7:设定你的 Hexo 布景主题:Next(下)

由於篇幅太长,所以拆分成上下篇啦!经过昨天的一些设定,相信大家已经慢慢上手了。接着今天也要接续昨天没...