1、前言
当软件需要在多个国家和地区使用时,对系统进行国际化多语言处理就成了顺理成章的事情。针对多语言场景,ASP.NET Core 提供了一种基于资源文件(*.resx )的多语言实现方法,下面开始介绍。
2、初级方法实现多语言
在Controller 的方法中,我们经常需要输出一些有意义的文本信息对用户进行提示,下面代码演示了根据不同的id 值输出不同的提示信息:
using Microsoft.AspNetCore.Mvc;
namespace App.Controllers
{
[Route("api/[controller]/[action]")]
[ApiController]
public class HomeController : ControllerBase
{
[HttpGet]
public ActionResult<string> Get(int id = 1)
{
if (id > 0)
{
return Ok("查询成功");
}
else if (id == 0)
{
return NotFound("查询不到数据");
}
else
{
return BadRequest("参数错误");
}
}
}
}
对于咱们来说,看懂上面的提示信息根本不是问题。现在问题来了:该应用需要添加英文(en-US)支持,以便外国人理解 。大多数人的第一想法肯定是根据不同的语言环境生成不同的提示信息,也就是最基础的if...else ,其代码如下所示:
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Configuration;
namespace App.Controllers
{
[Route("api/[controller]/[action]")]
[ApiController]
public class HomeController : ControllerBase
{
private readonly IConfiguration configuration;
public HomeController(IConfiguration configuration)
{
this.configuration = configuration;
}
[HttpGet]
public ActionResult<string> Get(int id = 1)
{
string language = configuration["DefaultLanguage"].ToString();
if (id > 0)
{
if (language == "zh-CN")
{
return Ok("查询成功");
}
else
{
return Ok("Search successful");
}
}
else if (id == 0)
{
if (language == "zh-CN")
{
return NotFound("查询不到数据");
}
else
{
return Ok("Can't find data");
}
}
else
{
if (language == "zh-CN")
{
return BadRequest("参数错误");
}
else
{
return Ok("Parameter error");
}
}
}
}
}
上面的代码中注入了一个IConfiguration 接口用来读取当前语言环境,然后根据语言环境输出对应的提示信息。虽然上面的方法实现了多语言,但相信你也应该看出来了,该方法毫无扩展性,如果后续还需要引入越南语、韩语、蒙古语等诸多语言,那么上面的代码将会是灾难性的。
3、使用资源文件实现多语言
3.1、添加资源文件
下面来看看如何利用资源文件(*.resx )实现多语言。首先创建一个Resources 文件夹,然后在该文件夹中创建一个Controllers 文件夹,添加两个资源文件,如下图所示:
- HomeController.en-US.resx
- HomeController.zh-CN.resx
我们可以在资源文件中添加一些测试文本数据,如下图所示:
3.2、添加多语言支持
在Startup.cs 文件中添加多语言模块的支持,代码如下:
using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Localization;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using System.Collections.Generic;
using System.Globalization;
namespace App
{
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.AddControllers();
services.AddLocalization(options =>
{
options.ResourcesPath = "Resources";
});
}
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
var supportedCultures = new List<CultureInfo>
{
new CultureInfo("en-US"),
new CultureInfo("zh-CN"),
};
app.UseRequestLocalization(new RequestLocalizationOptions
{
DefaultRequestCulture = new RequestCulture("zh-CN"),
SupportedCultures = supportedCultures,
SupportedUICultures = supportedCultures
});
app.UseHttpsRedirection();
app.UseRouting();
app.UseAuthorization();
app.UseEndpoints(endpoints =>
{
endpoints.MapControllers();
});
}
}
}
3.3、注入IStringLocalizer接口
ASP.NET Core 中主要使用IStringLocalizer 读取多语言文本,只需要在控制器的构造函数中将其注入即可,其代码如下所示:
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Localization;
namespace App.Controllers
{
[Route("api/[controller]/[action]")]
[ApiController]
public class HomeController : ControllerBase
{
private readonly IStringLocalizer<HomeController> localizer;
public HomeController(IStringLocalizer<HomeController> localizer)
{
this.localizer = localizer;
}
[HttpGet]
public ActionResult<string> Get()
{
return localizer.GetString("Hello").Value;
}
}
}
将URL 改为https://localhost:5001/api/Home/Get?ui-culture=zh-CN ,运行结果如下图所示: 将URL 改为https://localhost:5001/api/Home/Get?ui-culture=en-US ,运行结果如下图所示: 到此为止,基于资源文件的多语言就完成了。
4、设置语言文化提供器
ASP.NET Core 的国际化多语言中间件默认支持3 种语言文化提供器:
- URL中的查询字符串
- Cookie
- Header请求头
4.1、URL中的查询字符串
上面代码虽然实现了多语言,但你可能会有一个疑问:IStringLocalizer 是如何定位到对应语言的资源文件的?其实这是由ASP.NET Core 中资源文件的命名约定决定的。
4.1.1、指定文件夹
首先看如下代码,这段代码表示到Resources 文件夹中去找多语言资源文件。
services.AddLocalization(options =>
{
options.ResourcesPath = "Resources";
});
4.1.2、指定控制器
接着是控制器中的多语言访问器IStringLocalizer ,其泛型参数为HomeController ,由于该控制器位于工程中的Controllers 文件夹,因此这也就告诉程序到Resources 文件夹下的Controllers 文件夹中去寻找一个名称为HomeController 的资源文件。
private readonly IStringLocalizer<HomeController> localizer;
4.1.3、指定语言环境
名称为HomeController 的资源文件有两个,分别以zh-CN.resx 和en-US.resx 结尾。如果URL 中的ui-culture 值为en-US ,则读取HomeController.en-US.resx ,反之则读取HomeController.zh-CN.resx 。
https://localhost:5001/api/Home/Get?ui-culture=en-US
4.2、Cookie设置多语言
如果不想在每个URL 中添加ui-culture 参数,那么也可以考虑使用Cookie 的方式来实现多语言。在当前网页中添加一个Cookie ,名称为.AspNetCore.Culture ,值为c=zh-CN|uic=zh-CN ,则运行结果如下图所示:
如果将.AspNetCore.Culture 的值设置为c=zh-CN|uic=zh-CN ,则运行结果如下图所示:
4.3、Header请求头设置多语言
ASP.NET Core 也支持在请求头中指定语言文化,这里以Edge 浏览器为例。当前浏览器的默认语言为简体中文,因此请求头中的accept-language 值为zh-CN,zh;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6 ,如下图所示: 此时程序会读取HomeController.zh-CN.resx ,因此输出结果为中文,如下图所示: 现在我们将Edge 浏览器改为英文模式,如下图所示: 再次运行程序,发现accept-language 值更改了,如下图所示: 此时程序会读取HomeController.en-US.resx ,因此输出结果为英文,如下图所示:
5、结语
本文主要介绍了ASP.NET Core 中基于资源文件的多语言实现方法。这里需要注意:上面只是为了演示,因此Cookie 是我手动添加进去的,实际开发过程中还是需要使用HttpContext 操作Cookie 。
|