Blazor WASM App 實作多國語系紀錄
多國語系開發筆記
參考文件
多國語言實作前期
必需在系統初期就把多國語系框架定案。否則後期很難再加入多國語系機制。
必需決定多國語言支援的程度。這影嚮實作方法。 想要支援幾個國定地區,如:只有二國:中文/英文,或三、四國。 想要支援語系文化差異程度,如:中東地區由右往左排版的大問題。 若多國語系框架良好事後增加幾個國定地區都不難,除了『文化與 UI 習慣』完全相異以外。
多國語言系統開發主要步驟
安裝相關套件
啟用
設定多國語系支援程度
指定(預設)語系
切換語系介面
套用多國語系機制
FluentValidation 多國語系支援部份 (option)
相關重要指令
IStringLocalizer<T> nterface
// 自『多國語系資源區』依當時語系取值。
開發環境
平台: .NET6 IDE: Visual Studio 2022 框架: Blazor WASM App
安裝相關套件
PM> NuGet\Install-Package Microsoft.Extensions.Localization
啟用多國語系
using [...略...]
//## 多國語系 - FluentValidation
FluentValidation.ValidatorOptions.Global.DisplayNameResolver = (type, member, expression) => GT.ResolveDisplayName(member);
var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");
//## 啟用多國語系
builder.Services.AddLocalization(options =>
{
options.ResourcesPath = "Resources"; // 指定『多國語系資源區』
});
builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });
builder.Services.AddMudServices();
builder.Services.AddBlazoredLocalStorageAsSingleton();
[...略...]
//§§ await builder.Build().RunAsync(); ----------------------------------------
var host = builder.Build();
await host.SetDefaultCultureAsync(); // 設定(預設)語系
await host.RunAsync();
設定語系切換機制
語系還是要切換的,在 Blazor WASM App 現在語系設定一般放在 local storage。
設定多國語系支援程度
在設定語系之前要設定多國語系支援程度。
// 指定多國語系支援程度
public static class LocalizerSettings
{
// 預設語系
public static CultureWithName NeutralCulture = new CultureWithName("English", "en-US");
// 指定多國語系支援程度。可事後再多入更多語系。
public static readonly List<CultureWithName> SupportedCulturesWithName = new List<CultureWithName>()
{
new CultureWithName("English", "en-US"),
new CultureWithName("中文","zh-TW")
};
}
// 此資料結構用於管理語系
public record CultureWithName
{
public string Name { get; set; } = default!;
public string Culture { get; set; } = default!;
public CultureWithName(string name, string culture)
{
Name = name;
Culture = culture;
}
}
指定(預設)語系
將自 local storage 取得指定語系開啟畫面。
public static class ThisProjectClassExtensions
{
/// <summary>
/// 設定現在語系:依 localStorage 的 culture 屬性值設定現在語系。
/// </summary>
public async static Task SetDefaultCultureAsync(this WebAssemblyHost host)
{
var localStorage = host.Services.GetRequiredService<ILocalStorageService>();
var cultureString = await localStorage.GetItemAsync<string>("culture");
CultureInfo cultureInfo = !String.IsNullOrWhiteSpace(cultureString)
? new CultureInfo(cultureString)
: new CultureInfo(LocalizerSettings.NeutralCulture.Culture);
CultureInfo.DefaultThreadCurrentCulture = cultureInfo;
CultureInfo.DefaultThreadCurrentUICulture = cultureInfo;
}
}
切換語系介面
雖說是切換語系,大部份的實作其實是指定新語系後重新啟動(程式)畫面,開啟過程中用(新)指定的語系執行。基本上沒有人會不斷切換語系。
製作切換語系的下拉元件,完成後掛到 AppBar 上。
@inject NavigationManager navSvc
@inject ILocalStorageService localStorage
@inject IStringLocalizer<App> loc
<span>
@loc["Language"]:
<select @onchange=HandleCultureChange>
@foreach (var culture in LocalizerSettings.SupportedCulturesWithName)
{
@if (culture.Equals(selectedCulture))
{
<option selected value="@culture.Culture">@culture.Name</option>
}
else
{
<option value="@culture.Culture">@culture.Name</option>
}
}
</select>
</span>
@code {
CultureWithName? selectedCulture = null;
protected override async Task OnInitializedAsync()
{
string culture = await localStorage.GetItemAsync<string>("culture");
selectedCulture = String.IsNullOrEmpty(culture)
? LocalizerSettings.NeutralCulture
: LocalizerSettings.SupportedCulturesWithName.FirstOrDefault(c => c.Culture == culture);
}
/// 切換語系
async Task HandleCultureChange(ChangeEventArgs args)
{
//## 切換語系:將指定的新語系存入 localStorage 然後(刷新)重新開啟現在網址。
string cultureString = args.Value?.ToString()!;
await localStorage.SetItemAsync<string>("culture", cultureString);
navSvc.NavigateTo(navSvc.Uri, true); // refresh current page.
}
}
套用多國語系機制
一、在『多國語系資源區』設定各個多國語系。
在成功套入多語系模組後,就可以在『多國語系資源區』為各個元件設定多國語系。以下圖為例。
在啟動時指定了『多國語系資源區』的位置為"Resources"
。各元的相對位置與目標位置的相對位置是一樣的。語系資料檔名稱格式:<元件名稱>.<語系>.resx
。

二、用 IStringLocalizer<T>
介面取多國語系的值。
以 Counter.rezor 為例。套入IStringLocalizer<T>
後的碼。
@page "/counter"
@inject ILogger<Counter> logger
@inject IStringLocalizer<Counter> loc // 注入多國語系 IStringLocalizer 介面
@inject IStringLocalizer<App> locApp // 可以注入多個 IStringLocalizer 介面
<PageTitle>Counter</PageTitle>
<MudContainer>
<MudText Typo=Typo.h3 GutterBottom>@loc["Counter"]</MudText>
<MudAlert Severity=Severity.Info Class="mb-3">
<span style="font-size:2em">@String.Format(loc["click {0} times"], currentCount)</span>
</MudAlert>
<MudButton Variant=Variant.Filled Color=Color.Primary OnClick=IncrementCount>@loc["Click me"]</MudButton>
</MudContainer>
@code {
int currentCount = 0;
void IncrementCount()
{
currentCount++;
logger.LogInformation("IncrementCount");
}
}
沒圖沒真象
中英語系切換截圖




完整程式碼
(完成)
Last updated