如果要支持Blazor WebAssembly的本地化,應該如何實現呢?下麵,我們就按照本地化問題操作中所涉及的所有主要問題以提問的方式進行說明。 1.本地化的核心原理是什麼? 答:就是顯式地在Program.Main方法中設置 CultureInfo.DefaultThreadCurrentCul ...
如果要支持Blazor WebAssembly的本地化,應該如何實現呢?下麵,我們就按照本地化問題操作中所涉及的所有主要問題以提問的方式進行說明。
1.本地化的核心原理是什麼?
答:就是顯式地在Program.Main方法中設置 CultureInfo.DefaultThreadCurrentCulture和CultureInfo.DefaultThreadCurrentUICulture這兩個屬性。
2. 用戶選擇的本地化語言設置的值存放在哪裡?
有三種主要方式,第一種是存放在本地,這種優點是不涉及與伺服器的網路交互,能節省一點的伺服器端和網路的資源消耗,缺點是,換了客戶端就要重新設置。
第二種是存放在伺服器端。這種方式優點是語言本地化設置不隨著客戶端的變更而變更,客戶體驗好,缺點就是與伺服器有資源消化,在服務端不但要寫Api介面,還要存儲,還要考慮負載等一系列問題。
第三種,就是將前面兩種方式都結合起來,服務端和客戶端都存儲,如果換了客戶端,客戶端沒有存儲,就去服務端查找相應設置。客戶端有,就不去查詢伺服器設置。這種方式結合了前面兩種的優點,算是比較完美的方案。
因為第一種方式的影響甚微,相對一直使用一種客戶端的用戶來說,用戶換客戶端的機會相對較少。通常對於用戶來說,也是可以接受的,我在這裡採取第一種方式首先予以說明。
3. 那麼我們要將本地化設置要存放在本地瀏覽器的什麼地方,如何實現呢?
答案是localStorage,我們只需要在wwwroot/index.html文件中加入一段js代碼,就可以搞定這一步。
<script> window.blazorCulture = { get: () => window.localStorage['BlazorCulture'], set: (value) => window.localStorage['BlazorCulture'] = value }; </script>
4. 如何將第三個問題存放的設置取出來,賦給第一步說到的兩個屬性,以便本地化起作用?
通過在Program.Main方法中,可以通過C#與js的交互來獲取到相應設置。只要在host.RunAsync()之前調用下麵定義的這個方法就完成了相關操作:
static async Task GetCulture(WebAssemblyHost host) { 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; } }
調用上段方法具體為:
builder.Services.AddApiAuthorization(); var host = builder.Build(); await GetCulture(host); await host.RunAsync();
5.第四個問題說到了本地化設置的獲取,沒有提到設置並保存,那麼應該怎樣設置和保存?
要選擇和設置本地化語言,當然就要給用戶提供交互UI界面,要提供這樣的界面,可以定義一個Blazor組件,如命名為CultureSelector.razor,將其添加到Shared文件夾中。
首先,這個組件要選擇語言選項,那麼肯定需要一個選擇列表來列出相關語言以便供選擇,這就用到了html中的<select>標簽。
再者,還要將用戶所選選項值保存,又要調用第三個問題中js代碼,這就涉及到了C#與js的交互。
最後,設置完了,並保持了,你需要刷新你的頁面,以便你的本地化設置生效,並呈現給用戶,這就需要強制刷新。
上面所涉及到的,都需要在CultureSelector.razor這個組件中完成,具體的代碼如下所示。最後,將組件的標簽<CultureSelector />寫在你的目標頁面的具體位置以給用戶呈現。
@using System.Globalization @inject IJSRuntime JSRuntime @inject NavigationManager Nav <select @bind="Culture"> @foreach (var culture in supportedCultures) { <option value="@culture">@culture.Name.Split()[0]</option> } </select> @code { CultureInfo[] supportedCultures = new[] { new CultureInfo("en-US"), new CultureInfo("zh-CN"), }; 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); } } } }
6. 頁面的內容的本地化資源如何存放?
內容的本地化資源,只需要你添加與你要本地化的razor頁面同名的.resx資源文件,併在其中定義你的本地化內容即可。例如:我要本地化Pages文件夾中BranchPage.razor頁面,預設內容是英文的,我現在要將其支持可以本地化為中文,那我就添加資源文件名BranchPage.zh-CN.resx。併在裡面將英文作為鍵,中文作為值進行存放即可。如果作為鍵,英文太長的話,可以定義關鍵字作為鍵,並且需要你再添加預設的BranchPage.resx資源文件作為英文資源文件。
7. 內容本地化資源信息存好了,如何在頁面中調用?
還是以上面的BranchPage.razor為例,要在其中調用資源文件中的信息,就需要以下幾步:
(1)在Program.Main中添加本地化服務
builder.Services.AddLocalization();
(2)在BranchPage.razor中進行下列本地化註入。
@inject IStringLocalizer<BranchPage> localizer
(3)用上面定義的localizer來進行調用
<tr> <th>@localizer["ID"]</th> <th>@localizer["Code"]</th> <th>@localizer["Name"]</th> <th>@localizer["Description"]</th> </tr>
至此,涉及本地化的主要步驟和關鍵點就完成了,你就可以測試您的代碼了。