ASP.NET Core Web API 多語系(i18n) 共用資源檔

之前有寫過一篇 ASP.NET Core Web API 多語系(i18n) 的示範,但是他的缺點就是需要依照功能拆分資源檔。例如 UserController.cs 和 RoleController.cs 的 i18n 多語系資源檔要放在 UserController.resx 和 RoleController.resx 中,非常不方便。
本篇就來示範將所有多語系資源放在同一個資源檔的方式(不同語系還是會放在不同的資源檔中)

在上一篇中有提到資源檔的檔名要依照使用的位置來命名,例如要在 Controllers 資料夾內的 UserController.cs 檔案使用則檔名就要叫做 Controllers.UserController.resx。

所以這裡我們就在專案最外層建立 SharedResources.cs 檔案,用來對應到同名的資源檔用的,裡面不需要有其他內容:
    
public class SharedResources
{
}
    

然後使用上面的 SharedResources 類別名稱建立同名的資源檔:
SharedResources.resx
    
Hello		Hello
Hello_Name	Hello {0}!
    

SharedResources.zh-TW.resx
    
Hello		哈囉
Hello_Name	哈囉 {0}!
    

在 Program.cs 中加入以下程式碼:
    
var builder = WebApplication.CreateBuilder(args);
builder.Services.AddControllers();

builder.Services.AddLocalization(options => options.ResourcesPath = "Resources");

builder.Services.Configure<RequestLocalizationOptions>(options =>
{
    // 預設語言 (不指定就會使用裝置的預設語系)
    options.DefaultRequestCulture = new RequestCulture("zh-TW");
    
    // 支援的語言
    var supportedCultures = new[]
    {
        new CultureInfo("en-US"),
        new CultureInfo("zh-TW"),
    };
    options.SupportedCultures = supportedCultures;
    options.SupportedUICultures = supportedCultures;
});

var app = builder.Build();

app.UseRequestLocalization();

app.Run();
    

依照語系替換內容

這裡最簡單示範單純替換文字和可以帶入參數替換的兩種多語系替換方式:
    
using System.Globalization;
using Microsoft.AspNetCore.Mvc;
using Microsoft.Extensions.Localization;


[ApiController]
[Route("[controller]")]
public class UserController : ControllerBase
{
    private readonly IStringLocalizer<SharedResources> _localizer;

    public UserController(IStringLocalizer<SharedResources> localizer)
    {
        _localizer = localizer;
    }

    [HttpGet]
    public IActionResult Get()
    {
        // 取得當前 API 的語系
        Console.WriteLine($"CultureInfo: {CultureInfo.CurrentCulture}");

        var hello = _localizer["Hello"].Value;
        Console.WriteLine($"Hello: {hello}");

        string input = "Ruyut";
        var helloName = _localizer["Hello_Name", input].Value;
        Console.WriteLine($"Hello_Name: {helloName}");

        return Ok(helloName);
    }
}
    

API 指定語言

在呼叫 API 時,可以在 QueryString 中帶入 culture 參數來指定語言,下面示範將語言指定為 en-us :
    
http://localhost:5202/User?culture=en-us
    

也可以透過 Header 加入 Accept-Language 參數來達成:
    
curl --location 'http://localhost:5202/User' \
--header 'Accept-Language: en-us'
    

註:在筆者的測試中發現不區分大小寫, en-US 和 en-us 相同,zh-tw 和 zh-TW 也是相同。

參考資料:
Microsoft.Learn - Make an ASP.NET Core app's content localizable
StackOverflow - ASP.NET Core Localization with help of SharedResources

留言