天天看点

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) 多语言+本地化