今天要來介紹多國語系的處理,想要建立一個國際化網站,多國語系可以說是基本需求,那我們就來看如何在 Blazor 中實現吧!
除了數字與日期格式有原先 .NET 框架的文化特性外,其他都要自己來處理多國語系的範本,這也是理所當然的,除非機器翻譯的準確率接近完美,否則公司大可花錢請人翻譯,以免在公開網站出現奇葩內容。
那麼我們該如何在 Blazor wasm 中實現多國語系呢?很遺憾官方目前並沒有提供一份詳細的文件,但留了一個 Repository 來供我們參考,讓我們以pranavkm/LocSample的方式來當作多國語系的處理吧!
首先針對需要多國語系的元件建立資源檔,其檔案名稱如 {Component}.{Culture}.resx
,Component
為使用此資源檔的元件名稱,需確保名稱與元件名稱一致,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