ASP.NET Core のWebアプリケーションで国際化対応したければこのドキュメントに従えばよい。
アクセスしてきているユーザーの言語向けの表示を行うことができる。
今回、ユーザーの言語でなく任意の言語で表示したかったのだけれど、すんなりはできなかったのでメモしておく。
カルチャ指定インタフェースが変化している
.NET Core 2 までは IStringLocalizer
などのローカライズした文字列を得るためのインタフェースに WithCulture
という任意のカルチャを指定してそのカルチャでローカライズするインスタンスを取得することができた。
これは .NET Core 3 で非推奨になり、.NET 5 で消えてしまった。
IStringLocalizer.WithCulture(CultureInfo) メソッド (Microsoft.Extensions.Localization) | Microsoft Docs
ではどうやってローカライズされる言語が決まるのかというとこういうことらしい。
This method is obsolete. Use CurrentCulture and CurrentUICulture instead.
CurrentCulture
や CurrentUICulture
を設定しておくとそのカルチャでローカライズされるらしい。これは System.Globalization.CultureInfo
の静的なプロパティとしてアクセスでき、実体はスレッドごとに管理されているようだ。
CultureInfo.CurrentCulture プロパティ (System.Globalization) | Microsoft Docs
本気か? 現在のカルチャで解決されるのは親切だとしても、任意のカルチャでローカライズするインタフェースが消え去るとかある? マジで?
スレッド毎管理に注意する
現在のカルチャはスレッド毎に管理されるので、昨今の非同期処理が頻繁に登場するプログラムではローカライズを実行するスレッドと、カルチャを設定するスレッドに気を使う必要がある。
特に ASP.NET Core MVC の非同期なコントローラメソッド内で CurrentCulture
を設定しても、Razorテンプレートのレンダリング時には反映されない。何故ならスレッドが違うからだ。
- CurrentUICulture/CurrentCulture not working in Razor view rendering with asynchronuous controller actions · Issue #3117 · dotnet/aspnetcore · GitHub
- c# - ASP.NET MVC (Async) CurrentCulture is not shared between Controller and View - Stack Overflow
気をつけられたい。
僕は面倒くさかったのでテンプレートの側で CurrentCulture
を設定することで任意のカルチャでローカライズした。
抜粋するとこんな感じ。
@inject IHtmlLocalizer<SharedResource> SharedLocalizer @{ // レンダリング時に使うカルチャを指定する CultureInfo.CurrentCulture = new CultureInfo("ja"); CultureInfo.CurrentUICulture = new CultureInfo("ja"); } @SharedLocalizer["This is a pen."]
本気か? まぁ期待通りのローカライズにはなったのでよし。