大家好,我是Edison。

上一篇我提到了接下来会介绍一下如何在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。

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.IsNullOrEmpty(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中通过IStringLocalizer来实现了多语言和本地化。但其实IStringLocalizer只是ASP.NET Core中本地化实现方式的一种而已,关于更多全球化和本地化的内容,建议阅读参考资料中的两篇文章,特别是建军兄最近整理的《理解ASP.NET Core - 全球化与本地化》值得一读!

参考代码

GitHub:https://github.com/Coder-EdisonZhou/BlazorSamples/tree/main

参考资料

Microsoft,《ASP.NET Core Blazor 全球化与本地化》

xiaoxiaotank,《理解ASP.NET Core - 全球化与本地化》(五星推荐)

作者:周旭龙

出处:https://edisonchou.cnblogs.com

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文链接。

Blazor学习之旅(10)多语言+本地化的更多相关文章

  1. 笔记-JavaWeb学习之旅10

    Servlet server applet运行在服务器端的小程序,servlet就是一个接口,定义了Java类被浏览器访问到的规则(Java类重写这个接口,就可以被浏览器(tomcat)识别) Ser ...

  2. 30个深度学习库:按Python、C++、Java、JavaScript、R等10种语言分类

    30个深度学习库:按Python.C++.Java.JavaScript.R等10种语言分类 包括 Python.C++.Java.JavaScript.R.Haskell等在内的一系列编程语言的深度 ...

  3. Hadoop学习之旅三:MapReduce

    MapReduce编程模型 在Google的一篇重要的论文MapReduce: Simplified Data Processing on Large Clusters中提到,Google公司有大量的 ...

  4. 开发了5年android,我开始了go学习之旅

    前言 做了近5年的android开发,最近项目也是不怎么忙,空闲的时候总会思考一些事情,不过作为移动开发,我个人觉得很有必要学习后台开发,由于公司是Go语言开发的,了解go语言一段时间后,我发现go语 ...

  5. 滴滴Booster移动APP质量优化框架 学习之旅

    推荐阅读: 滴滴Booster移动App质量优化框架-学习之旅 一 Android 模块Api化演练 不一样视角的Glide剖析(一) 一.Booster简介 Booster是滴滴最近开源一个的移动应 ...

  6. hadoop学习之旅1

    大数据介绍 大数据本质也是数据,但是又有了新的特征,包括数据来源广.数据格式多样化(结构化数据.非结构化数据.Excel文件.文本文件等).数据量大(最少也是TB级别的.甚至可能是PB级别).数据增长 ...

  7. WCF学习之旅—第三个示例之二(二十八)

    上接WCF学习之旅—第三个示例之一(二十七) 五.在项目BookMgr.Model创建实体类数据 第一步,安装Entity Framework 1)  使用NuGet下载最新版的Entity Fram ...

  8. WCF学习之旅—WCF服务的Windows 服务程序寄宿(十一)

    上接    WCF学习之旅—WCF服务部署到IIS7.5(九) WCF学习之旅—WCF服务部署到应用程序(十) 七 WCF服务的Windows 服务程序寄宿 这种方式的服务寄宿,和IIS一样有一个一样 ...

  9. WCF学习之旅—第三个示例之五(三十一)

       上接WCF学习之旅—第三个示例之一(二十七)               WCF学习之旅—第三个示例之二(二十八)              WCF学习之旅—第三个示例之三(二十九) WCF学习 ...

  10. WCF学习之旅—WCF第二个示例(五)

    二.WCF服务端应用程序 第一步,创建WCF服务应用程序项目 打开Visual Studio 2015,在菜单上点击文件—>新建—>项目—>WCF服务应用程序.在弹出界面的“名称”对 ...

随机推荐

  1. 工作日记-storm集群业务崩溃和解决方案

    背景 昨天公司业务部门报告业务崩溃,查看各个业务节点后,定位问题到storm集群. 打开storm ui查看下任务状态,发现可以加载页面元素,但是无法加载数据,分析是nimbus挂掉了,重启nimbu ...

  2. 【Git】国内的项目托管网站-码云

    国内的项目托管网站-码云 1 简介 使用 GitHub 作为项目托管网站如果网速不好很影响效率,大家也可以使用国内的项目托管网站-码云.网址是 https://gitee.com/ ,使用方式跟 Gi ...

  3. DeepSeek 聊天机器人项目

    想要更深入玩转聊天机器人开发? 推荐本文档 + 课程<DeepSeek 聊天机器人项目>一起学习,效果翻倍! 边学边练,轻松打造智能对话系统~ (๑•̀ㅂ•́)و✧ 快上车,AI 之旅发车 ...

  4. 使用Python解决氢原子问题

    引言 大家好!今天我们将讨论一个非常经典的物理问题-氢原子问题,并使用 Python 来进行求解.氢原子问题是量子力学中的基础问题,它帮助我们理解原子内部的电子结构及其能量水平.通过这篇文章,大家将学 ...

  5. dubbo源码解析-服务暴露与发现

    一.概述 dubbo是一个简单易用的RPC框架,通过简单的提供者,消费者配置就能完成无感的网络调用.那么在dubbo中是如何将提供者的服务暴露出去,消费者又是如何获取到提供者相关信息的呢? 二.dub ...

  6. Mybatis的原始的执行方式

    一.通过SqlSessionFactory创建sqlsession,再由Sqlsession获取session对象,然后通过session中的执行器Executor,去执行MapperStatemen ...

  7. addAll(Collection<? extends E> c)的方法源码

    public class ArrayList<E> extends AbstractList<E> implements List<E>, RandomAccess ...

  8. vue2&vue3&小程序简介

    Vue2.Vue3.小程序页面生命周期详解 本篇将对比 Vue2.Vue3 以及小程序页面/组件的生命周期,简单梳理各自特点.差异.新增优化点. Vue2 生命周期 beforeCreate → cr ...

  9. Robot Framework全局变量集合取值

    在一次测试中,可能需要使用多个不同的会员,即需要多注册多个会员.如此配置单一参数化是无法满足对所有注册会员名的统一管理,这里引入参数变量组来实现 步骤如下: 1.脚本目录点击总目录,右键点击New R ...

  10. MySQL安装入门第一篇

    [1]MySQL的版本:近期主要历史版本有5.0/5.1/5.5/5.6/5.7,目前最新版本是MySQL8.6.0曾经是个内部试验版本,已取消了. MySQL8.0的版本历史 1) 2016-09- ...