ASP.NET Coreのローカリゼーション周りのメモ

# ASP.NET Coreのローカリゼーション周りのメモ
ASP.NET Core のローカリゼーション回りのソースを読んだのでメモ

調べたバージョンはASP.NET Core 3.1

`IStringLocalizer`, `IStringLocalizerFactory` あたりは今回は触れません。
ここではミドルウェア周りについて触れます

## 使い方
詳細は[こちら](https://docs.microsoft.com/ja-jp/aspnet/core/fundamentals/localization?view=aspnetcore-3.1) に書いているので
ここではさらっと触れるのみとします。

```cs:startup.cs
public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        //省略...

        //ローカリゼーション周りのクラスをDIコンテナに登録する。
        //.resxファイルはResourcesフォルダに配置するのでResourcesPathを変更
        services.AddLocalization(options => options.ResourcesPath = "Resources");
    }

    public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
    {
        //省略...

        //ミドルウェアの登録及び、オプションの設定
        app.UseRequestLocalization(options =>
        {
            //サポートするカルチャの設定
            string[] supportedCultures = new string[] {"ja", "en"};

            options
                .AddSupportedCultures(supportedCultures)
                .AddSupportedUICultures(supportedCultures)
                .SetDefaultCulture(supportedCultures[0])
                ;
        });
        //省略...
    }
}
```

あとは利用側で`IStringLocalizer<T>` をインジェクションし、`T` に相当するクラス及び`Resources/T.ja.resx`, `Resources/T.en.resx` を用意すればよいです。

## `RequestLocalizationMiddleware` クラス
[ApplicationBuilderExtensions](https://github.com/dotnet/aspnetcore/blob/v3.1.5/src/Middleware/Localization/src/ApplicationBuilderExtensions.cs)クラスの`UseRequestLocalization` メソッドを実行する事で登録されます。

`RequestLocalizationMiddleware` クラスのソースは[こちら](https://github.com/dotnet/aspnetcore/blob/v3.1.5/src/Middleware/Localization/src/RequestLocalizationMiddleware.cs)

`HttpContext`から カルチャーに関する情報を取得し [SetCurrentThreadCulture](https://github.com/dotnet/aspnetcore/blob/v3.1.5/src/Middleware/Localization/src/RequestLocalizationMiddleware.cs#L152)メソッドで `CultureInfo.CurrentCulture`, `CultureInfo.CurrentUICulture`にセットしています。

カルチャーに関する情報はデフォルトでは

1. クエリストリング
1. Cookie
1. `Accept-Language` リクエストヘッダー

の順序で解決が行われます。
これらの内容は `RequestLocalizationOptions` で設定を行います。

## `RequestLocalizationOptions` クラス
ソースは[こちら](https://github.com/dotnet/aspnetcore/blob/v3.1.5/src/Middleware/Localization/src/RequestLocalizationOptions.cs)

上記の `RequestLocalizationMiddleware` でカルチャの解決に使用するオプションを定義しています。

これらのプロパティについて紹介します。

### `RequestCultureProviders` プロパティ
`HttpContext` からカルチャの解決を行っているものの正体です。

デフォルトでは

1. [QueryStringRequestCultureProvider](https://github.com/dotnet/aspnetcore/blob/v3.1.5/src/Middleware/Localization/src/QueryStringRequestCultureProvider.cs)
1. [CookieRequestCultureProvider](https://github.com/dotnet/aspnetcore/blob/v3.1.5/src/Middleware/Localization/src/CookieRequestCultureProvider.cs)
1. [AcceptLanguageHeaderRequestCultureProvider](https://github.com/dotnet/aspnetcore/blob/v3.1.5/src/Middleware/Localization/src/AcceptLanguageHeaderRequestCultureProvider.cs)

の3つがListの要素に設定されています。

解決に用いるキーの名前はインスタンスプロパティとして定義されているので変更することができます。
(例 `CookieRequestCultureProvider`のCookie名が `.AspNetCore.Culture` という値であり `ASP.NET Core` を使用している事を外部に公開していることになるので、この名前を変更したい という要望に対応することができます。 )

この`RequestCultureProviders`プロパティを変更することで、解決の順序を変更することや、新しいカルチャ解決の方法を追加することも可能です
(例. `HttpContext` が渡されているので `Claim` から解決することもおそらく可能ではないかと思います。)

新しいカルチャ解決の方法を実装する際は[RequestCultureProvider](https://github.com/dotnet/aspnetcore/blob/v3.1.5/src/Middleware/Localization/src/RequestCultureProvider.cs)を継承
もしくは[CustomRequestCultureProvider](https://github.com/dotnet/aspnetcore/blob/v3.1.5/src/Middleware/Localization/src/CustomRequestCultureProvider.cs)
に直接ラムダ式を記述すれば可能です。

[AddInitialRequestCultureProvider](https://github.com/dotnet/aspnetcore/blob/v3.1.5/src/Middleware/Localization/src/RequestLocalizationOptionsExtensions.cs#L21)拡張メソッドを呼ぶことで、先頭に追加することも可能です。

### `SupportedCultures`, `SupportedUICultures`, `DefaultRequestCulture` プロパティ

サポートしているカルチャの一覧です。

`DefaultRequestCulture` はカルチャが解決できなかった時に使用されるデフォルトのカルチャです。

プロパティに直接セットすることも可能ですが
`AddSupportedCultures`, `AddSupportedUICultures`, `SetDefaultCulture`メソッドを呼ぶことでもセット可能です。
(`Add`という名前で始まっていますがソースを見た感じ総入れ替えが行われているように見える..🤔)

### `FallBackToParentCultures`, `FallBackToParentUICultures` プロパティ
カルチャが見つからなかったときにフォールバックするか？の設定のようです。

例えば
- `SupportedCultures`が`ja`
- リクエストから解決したカルチャが`ja-JP`

のときに`ja` を使うといったことが可能なようです。

`RequestLocalizationMiddleware`クラスの[GetCultureInfo](https://github.com/dotnet/aspnetcore/blob/v3.1.5/src/Middleware/Localization/src/RequestLocalizationMiddleware.cs#L199)
メソッドあたりで使われています。

## 終わりに
今回はカルチャの解決方法について注目してソースを確認しました。

次は利用する側(`IStringLocalizer`, `IStringLocalizerFactory`) について見てみようと思います。