天天看點

Blazor學習之旅 (10) 多語言+本地化

作者:opendotnet

【Blazor】| 總結/Edison Zhou

大家好,我是Edison。

很久沒有更新Blazor這個系列了,在上一篇我提到了接下來會介紹一下如何在Blazor中實作多語言,這就安排上了。

多語言+本地化的背景

在Web應用開發中,我們可能會有一些需要多語言+本地化的場景,特别在一些國際化的外資企業當中特别常見。例如,Edison所在的IT開發團隊,就需要英語,中文和德語三種語言的支援,使用者可以通過“切換頁面語言”這個功能來切換到适合他的語言來浏覽頁面的内容。是以,為Web應用提供多語言,頁面内容可以本地化,會擴充我們的IT系統閱聽人範圍,提升一點使用者體驗。

是以,如何在Blazor中實作多語言+本地化就被提上議程。

一些基本的名詞術語

為了更好地了解下面的内容,我們先來了解一下行業内通用的名詞術語:

  • Globalization (G11N):全球化,即使應用支援不同語言和區域的過程。G11N 是首字母、尾字母和它們之間字母的個數組成的,下同,不再贅述。
  • Localization (L10N):本地化,即針對特定語言和區域自定義全球化應用的過程。
  • Internationalization (I18N):國際化,又稱為多語言,包含了全球化和本地化。
  • Culture:區域性,即一種語言文化或區域。
  • Neutral Culture:非特定區域性,即具有指定語言但不具有區域的區域性。例如“zh”、“en”,僅僅表示中文或英文,并沒有包含指定地區,如大陸、香港、台灣等。
  • Specific Culture: 特定區域性,即具有指定語言和區域的區域性。例如“zh-CN”、“zh-HK”。
  • Parent Culture: 父區域性,例如“zh”就是“zh-CN”和“zh-HK”的父區域性。

在Blazor中實作本地化的方式

在Blaozr中實作本地化的方式,其實也就是ASP.NET Core提供的那些本地化工具:

  • IStringLocalizer
  • IStringLocalizerFactory
  • IHtmlLocalizer
  • IViewLocalizer

在Blazor中,我們最常用的就是IStringLocalizer,它可以在運作時提供區域性資源,使用非常簡單,就像操作字典一樣,提供一個 Key,就能擷取到指定區域的資源。

接下來,我就以IStringLocalizer為例,介紹如何通過它來在Blazor應用中實作多語言和本地化。

在Blazor中實作本地化的步驟

(1)準備工作

假設我們已經有了一個Blazor應用程式,并且有一個Home.razor的頁面,需要支援中文(預設語言)、英語和德語。

(2)建立三個資源檔案

在根目錄下建立一個Resources目錄,再建立一個Pages子目錄,然後再建立三個resx資源檔案。這裡我們可以使用一個資源檔案來覆寫所有頁面的本地化内容,也可以針對多個頁面配置多個資源檔案。為了示範,這裡隻有一個資源檔案Home.resx應對示範頁面Home.razor。

Blazor學習之旅 (10) 多語言+本地化
key:HelloWorldTip, value: 你好,世界 -- 中文              key:HelloWorldTip, value: Hello, World! -- 英語              key:HelloWorldTip, value: Hallo, welt! -- 德語           

補充:如果你習慣使用json作為資源檔案,也可以使用My.Extensions.Localization.Json 這個包來将resx換為json檔案。

(3)在Programs.cs中注冊和使用本地化

添加本地化服務,并指向我們剛剛建立的Resources目錄,并聲明系統需要支援三種語言,中文為預設的語言。

var builder = WebApplication.CreateBuilder(args);              ......              // Add Localization              builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");                  var app = builder.Build();              ......              app.MapControllers();              app.MapBlazorHub();              app.MapFallbackToPage("/_Host");                  // Use Localization              const string CULTURE_CHINESE = "zh-CN";              const string CULTURE_ENGLISTH = "en-US";              const string CULTURE_GERMAN = "de-DE";              app.UseRequestLocalization(options =>              {              var cultures = new[] { CULTURE_CHINESE, CULTURE_ENGLISTH, CULTURE_GERMAN };              options.AddSupportedCultures(cultures);              options.AddSupportedUICultures(cultures);              options.SetDefaultCulture(CULTURE_CHINESE);              // 當Http響應時,将 目前區域資訊 設定到 Response Header:Content-Language 中              options.ApplyCurrentCultureToResponseHeaders = true;              });              ......           

(4)在_Imports.razor中添加全局注入

為了友善後續的使用,我們直接将IStringLocalizer和NavigationManager進行全局的注入。

......              @using Microsoft.AspNetCore.Localization              @using System.Globalization                  @inject IStringLocalizer<Home> _translator;              @inject NavigationManager _navigation;              ......           

(5)建立一個CultureController用于Culture的切換

為了讓頁面上的語言切換能夠更新系統的目前Culture,我們讓其通過調用API的方式來實作。

namespace EDT.BlazorServer.App.Controllers              {              [Route("[controller]/[action]")]              public class CultureController : Controller              {              public IActionResult Set(string culture, string redirectUri)              {              if (!string.IsOrEmpty(culture))              {              HttpContext.Response.Cookies.Append(              CookieRequestCultureProvider.DefaultCookieName,              CookieRequestCultureProvider.MakeCookieValue(              new RequestCulture(culture, culture)),               new CookieOptions { Secure = true, HttpOnly = true });              }                  return LocalRedirect(redirectUri);              }              }              }           

(6)改造Home.razor讓其可以實作本地化

這裡我們在頁面上使用IStringLocalizer對象來實作一個内容的切換。

@page "/home"                  <PageTitle>Index</PageTitle>                  <h1>@_translator["HelloWorldTip"]</h1>              <p>              <label>              Select your locale:              <select @bind="Culture">              @foreach (var culture in supportedCultures)              {              <option value="@culture">@culture.DisplayName</option>              }              </select>              </label>              </p>                  @code {              private CultureInfo[] supportedCultures = new[]              {              new CultureInfo("zh-CN"),              new CultureInfo("en-US"),              new CultureInfo("de-DE")              };                  protected override void OnInitialized()              {              Culture = CultureInfo.CurrentCulture;              }                  public CultureInfo Culture               {              get => CultureInfo.CurrentCulture;              set              {              if (CultureInfo.CurrentCulture != value)              {              var uri = new Uri(_navigation.Uri)              .GetComponents(UriComponents.PathAndQuery, UriFormat.Unescaped);              var cultureEscaped = Uri.EscapeDataString(value.Name);              var uriEscaped = Uri.EscapeDataString(uri);                  _navigation.NavigateTo(              $"Culture/Set?culture={cultureEscaped}&redirectUri={uriEscaped}",              forceLoad: true);              }              }              }              }           

(7)效果示範

如下圖所示:

Blazor學習之旅 (10) 多語言+本地化

小結

本篇,我們在Blazor中通過IStringLocalizer來實作了多語言和本地化。但其實IStringLocalizer隻是ASP.NET Core中本地化實作方式的一種而已,關于更多全球化和本地化的内容,建議閱讀參考資料中的兩篇文章,特别是建軍兄最近整理的《了解ASP.NET Core - 全球化與本地化》值得一讀!

參考代碼

GitHub:https://github.com/EdisonChou/BlazorSamples/tree/main

參考資料

Microsoft,《ASP.NET Core Blazor 全球化與本地化》xiaoxiaotank,《了解ASP.NET Core - 全球化與本地化》(五星推薦)

年終總結:Edison的2021年終總結數字化轉型:我在傳統企業做數字化轉型C#刷題:C#刷劍指Offer算法題系列文章目錄.NET面試:.NET開發面試知識體系.NET大會:2020年中國.NET開發者大會PDF資料

Blazor學習之旅 (10) 多語言+本地化