今天要來介紹多國語系的處理,想要建立一個國際化網站,多國語系可以說是基本需求,那我們就來看如何在 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> 來存取相關的資源檔,如:

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

為了提供使用者切換文化特性,需要建立一個選擇文化特性的元件:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
@* 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 來保存使用者修改文化特性時的值,並且在重新啟動時取得該值:

1
2
3
4
5
6
7
8
9
10
// 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 內容為:

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

這樣只要在合適的地方使用 CultureSelector 元件選擇文化特性,就能透過重新載入的方式使全站語系變更,且之後的每一次進入都可以看到相同的內容,除非使用者自行清除。


以上就是多國語系的處理方式,美中不足的是這套一定要使用 .resx 來當作資源檔,沒辦法使用 .json 來處理,但 Blazor 也算是個新興框架吧?相信未來會有更多的解決辦法!完整程式碼在範本程式碼 - Day27

感謝大家的閱讀,我們明天見。

參考資料
ASP.NET Core Blazor 全球化和當地語系化
pranavkm/LocSample