目录
在本教程中,我们将实现三个步骤来实现ASP.NET Web API 6本地化,即,将本地化配置应用到中间件,创建所需的资源文件,最后使用IStringLocalizer访问资源文件的条目。
当您计划构建面向多种文化和语言的应用程序或网站时,本地化是一个非常重要的主题。您必须准备好您的应用程序或网站,以准备好根据用户的相关文化显示所有信息,这对于获得更广泛的受众非常关键。
想象一下,您正在为一个说阿拉伯语的国家/地区构建一个应用程序,但该应用程序的主要语言是英语。这样一来,您的应用程序将不会对目标市场的大部分有用,并且您将大量失去受众,因此您的应用程序将被放弃,没有回头客。
您的内容越本地化,您的应用程序或网站的可用性就越好。您应该始终以完全本地化为目标,以保证与您的产品的无摩擦交互。
在本教程中,我们将通过添加阿拉伯语资源文件来学习如何在ASP.NET Core Web API中应用本地化。我们将使用最新版本的.NET 6和Visual Studio 2022构建RESTful API,因此在继续本教程之前继续安装VS 2022。最后,我们将使用Postman测试API。
创建本地化项目
启动Visual Studio 2022并创建一个新项目——ASP.NET Core Web API
给它起一个名字,比如“LocalizationInAspNetCoreWebApi”
然后选择.NET 6并按Create。
与往常一样,请确保删除模板WeatherForecast控制器和实体。
ASP.NET Core Web API本地化的3个步骤
现在要将本地化应用到ASP.NET Core Web API项目,需要遵循三个主要步骤:
- 将本地化包含到API项目中间件中
- 添加所需的本地化资源文件
- 使用IStringLocalizer访问资源文件
现在让我们在完成教程的同时详细解释每个步骤。
1. 将本地化纳入API中间件
我们需要让ASP.NET Core Web API知道我们将通过指定资源文件路径位于资源文件夹中的选项来进行本地化,我们将在本教程后面创建。
因此,让我们在调用CreateBuilder(args)之后添加以下代码:
builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");
此外,我们必须将本地化配置注入API中间件,以使其了解我们试图本地化到哪种文化,当然,如果您在本地化中针对两种或多种文化,您可以指定多个语言环境。
在您的program.cs文件中,让我们在builder.build()方法调用之后添加以下代码:
var supportedCultures = new[] { "en-US", "ar" };
var localizationOptions =
new RequestLocalizationOptions().SetDefaultCulture(supportedCultures[0])
.AddSupportedCultures(supportedCultures)
.AddSupportedUICultures(supportedCultures);
app.UseRequestLocalization(localizationOptions);
在这里,我们说我们将支持两种文化或语言环境,即“en-US”和“ar”,如果没有来自http请求的指令,则“en-US”将是默认设置。
2.添加需要的本地化资源文件
在本教程中,我们将学习如何通过两种方式在ASP.NET Core Web API中创建和使用资源文件:
- 使用控制器资源结构
- 使用共享资源结构
让我们在名为“Resources”的项目下创建一个新文件夹。
我们将使用此文件夹来托管其中的所有.resx文件。
使用控制器资源结构
通过使用控制器资源结构,您可以为每个控制器分配一个资源文件,这将允许您将资源结构化和分区到多个文件中。
在此之前,让我们确保我们已经创建了Controller,以便我们可以创建与其名称匹配的资源文件。
在Controllers文件夹中,添加一个名为PostsController的新Controller ,并将其设为Empty API Controller:
现在,让我们保留这个控制器。我们稍后会回来开发它,以便它可以从资源文件中读取。
在您的Resources文件夹中,右键单击并创建一个名为“Controllers”的新文件夹,然后在这个新的“Controllers”文件夹中,创建一个名为“ PostsController.ar.resx ”的新Resource。
这将用作post控制器的阿拉伯语本地化文件。在ASP.NET Core中,不需要为默认区域设置或区域性添加本地化文件,这是因为在本地化文件中,您将使用名称作为默认值,并且值将是本地化值,如果StringLocalizer不是能够找到给定的条目string,然后将返回string本身。
此外,您不需要通过StringLocalizer以外的其他方式访问Resource文件。
现在回到我们的新资源文件。在这个文件中,让我们添加一些示例数据,以便稍后测试我们的工作。
让我们看看资源文件夹的样子:
您也可以从Resources文件夹中删除Controllers文件夹并依赖Dot命名结构,这样资源文件名将包含Controllers作为前缀,如下所示:
Resources\Controllers.PostsController.ar.resx
但是,我更喜欢使用文件夹结构,因为它看起来更有条理且更具可读性。
使用共享资源结构
这样,我们可以依靠一个文件来包含所有本地化条目,因此该文件可以在多个控制器或其他类之间使用。
让我们添加一个名为SharedResource.ar.resx的新资源文件。
为了简单起见,在内部,我们将在PostsController资源文件中添加之前添加的相同条目:
现在要让它作为一个实际的共享资源工作,我们需要创建一个具有相同名称“SharedResource”的空类或虚拟类,并且我们应该将它放在Resources文件夹之外的其他位置,我们可以在项目下创建一个新文件夹命名实体并将其放在那里:
namespace LocalizationInAspNetCoreWebApi
{
public class SharedResource
{
}
}
我们已经准备好了需要的本地化文件,现在是时候看看我们如何从控制器使用和访问这些资源了。
3. 使用IStringLocalizer访问资源文件
最后一步是访问这些资源文件,这可以在ASP.NET Core中通过其构造函数注入到Controller中的IStringLocalizer而发生。
让我们看看下面的PostsController代码:
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Localization;
namespace LocalizationInAspNetCoreWebApi.Controllers
{
[Route("api/[controller]")]
[ApiController]
public class PostsController : ControllerBase
{
private readonly IStringLocalizer<PostsController> stringLocalizer;
private readonly IStringLocalizer<SharedResource> sharedResourceLocalizer;
public PostsController(IStringLocalizer<PostsController> postsControllerLocalizer,
IStringLocalizer<SharedResource> sharedResourceLocalizer)
{
this.stringLocalizer = postsControllerLocalizer;
this.sharedResourceLocalizer = sharedResourceLocalizer;
}
/// <summary>
/// This endpoint will access the PostsController
/// Resource to retrieve the localized data ...
/// </summary>
/// <returns></returns>
[HttpGet]
[Route("PostsControllerResource")]
public IActionResult GetUsingPostsControllerResource()
{
var article = stringLocalizer["Article"];
var postName = stringLocalizer.GetString("Welcome").Value ?? "";
return Ok(new { PostType = article.Value, PostName = postName });
}
/// <summary>
/// This endpoint will access the SharedResourece to retrieve the localized data ...
/// </summary>
/// <returns></returns>
[HttpGet]
[Route("SharedResource")]
public IActionResult GetUsingSharedResource()
{
var article = sharedResourceLocalizer["Article"];
var postName = sharedResourceLocalizer.GetString("Welcome").Value ?? "";
return Ok(new { PostType = article.Value, PostName = postName });
}
}
}
首先,在构造函数中,我们为IStringLocalizer注入了两个实例:一个将用于访问PostsController资源文件,另一个实例将访问SharedResource文件,注意每个实例使用的类型不同。
接下来,我们定义了两个端点来展示PostsController资源与共享资源之间的访问差异。
此外,我们可以通过使用字典的键名或使用GetString方法来访问资源文件条目。两者都是有效的并返回相同的结果。
如果资源字典中不存在搜索到的条目名称,stringLocalizer则将返回ResourceNotFound true标志。
运行项目并确保浏览器显示端点的Swagger文档。
在Postman上进行测试
打开 Postman 并创建一个新请求,将其分配给您在运行应用程序后拥有的 url 以及您拥有的api/method路由,并在标头中添加Accept-Language值为 ' ar' 的标头。
PostsController资源——ar
PostsController资源——zh
共享资源——ar
共享资源——zh
在响应标头中添加内容语言
最后要测试的一件事是在响应头中添加Content-Language,这主要用于为用户描述响应的内容语言。
打开程序文件,在app.UseRequestLocalization(localizationOptions)前面添加以下行:
localizationOptions.ApplyCurrentCultureToResponseHeaders = true;
再次运行您的API,然后切换回Postman。
尝试调用其中一个API请求:
请注意,一旦端点返回结果,在Response部分的Headers选项卡中,您将看到一个名为Content-Language且值为'ar'的新标头,这意味着返回的内容位于ar语言环境中。
概括
在本教程中,我们学习了如何在ASP.NET Core Web API 6中进行本地化。我们实现了三个步骤来实现本地化:将本地化配置应用到中间件,创建所需的资源文件,最后,使用IStringLocalizer访问资源文件。
此外,我们了解到有两种方法可以为控制器添加资源文件:控制器结构资源和共享资源,基于在本教程中,我们实现了这两种策略并创建了两个端点来访问每个资源文件的资源。
最终,我们设法使用Postman测试了我们所有的用例,并测试了响应的Content-Language标头,以便我们可以广播或告诉用户响应是在请求的语言环境中返回的。
本地化应该在多个层上进行;在UI上,您应该确保将所有标签、占位符、标题、前端验证消息等本地化。然后,在API端,您必须确保使用代码和消息返回正确的异常,以便UI可以将代码翻译成UI上的本地化消息。此外,您的API应该为任何需要的翻译字符串定义具有预期本地化的资源文件,最后,您应该为本地化的固定或不太频繁更改的内容(例如国家、城市、类别、类型等)保留单独的表格。
如果您正在开发大型产品,您可能需要咨询专业文案或营销专家,为您提供建议并为您提供针对您的目标文化的最佳本地化策略,并准备文化上准确的本地化文本和措辞,这些文本和措辞会显得原生且无缝被您的目标用户理解。
参考
您可以在我的GitHub 帐户中找到代码。
有关ASP.NET Core本地化的更多信息,您可以查看Microsoft的官方文档。
要进一步阅读有关本地化的一般信息,您可以查看这篇文章。
https://www.codeproject.com/Articles/5324504/Localization-in-ASP-NET-Core-Web-API