neputa note

Blazor WebAssemblyの多言語対応

初稿:

更新:

- 4 min read -

img of Blazor WebAssemblyの多言語対応

経緯と目的

以前、個人で日々の睡眠を記録する簡易なアプリを開発し公開した。

アラフォー初心者だけどスマホアプリを開発~リリースまでがんばってみた【Android・Xamarin.Forms】

この度、素人ながらスマホアプリ開発に挑戦してみました。今回の記事では概要と経緯について書き綴ってみたいと思います。実際に行った作業の詳細は、今後それぞれ記事を書き、こちらにリンクを追記します。作ったアプリ「OneThird」の概要 毎日の睡眠を入力によって記録するアプリです。寝た時間、起きた時間

PCでも読み書きできるようにWeb版をBlazor WebAssemblyで作成することにした。

ASP.NET Core Blazor

ASP.NET Core アプリ内に .NET を使った対話型のクライアント側 Web UI を構築する方法である、ASP.NET Core Blazor について調べます。

スマホアプリで多言語対応をしているので、Web版でも同様するべく調べたことを備忘録として残す。

環境

  • OS:Windows 10
  • .NET:6.0
  • Framework:Blazor WebAssembly

仕様

  • 英語と日本語の2か国語に対応し、これら以外の場合は英語表示となる
  • Webストレージを使用し、ユーザの選択言語をローカル保存する
  • 初回やローカルデータ消去後は、ブラウザのLocaleから言語を選択する
  • ユーザはUIのSelectorで言語を切り替えることができる

実装手順

Nugetパッケージ「Microsoft.Extensions.Localization」をインストールする

Microsoft.Extensions.Localization 8.0.6

Application localization services and default implementation based on ResourceManager to load localized assembly resources.This package was built from the source code at https://github.com/dotnet/aspnetcore/tree/b8139c5ee58f1708b0e3368a1b241400edd6cbc4

Projectファイル「.csproj」に以下を追加する

code
<PropertyGroup>
    <BlazorWebAssemblyLoadAllGlobalizationData>true</BlazorWebAssemblyLoadAllGlobalizationData>
</PropertyGroup>

wwwroot配下にあるindex.htmlのbodyタグの終了タグ直前に以下のスクリプトを設置する。

code
<script>
  function getBrowserLocale() {
    return navigator.languages && navigator.languages.length
      ? navigator.languages[0]
      : navigator.userLanguage || navigator.language || navigator.browserLanguage || 'en'
  }
  window.blazorCulture = {
    get: () => window.localStorage['BlazorCulture'],
    set: (value) => (window.localStorage['BlazorCulture'] = value)
  }
</script>
  • getBrowserLocaleメソッドは、ブラウザからLocaleを取得するため
  • blazorCultureプロパティは、CultureをWebストレージに出し入れするため

Program.csのawait builder.Build().RunAsync();を削除し、Cultureの設定処理を追加する。全体は以下のとおり。

code
using BlazorApp1;
using Microsoft.AspNetCore.Components.Web;
using Microsoft.AspNetCore.Components.WebAssembly.Hosting;
using Microsoft.JSInterop;
using System.Globalization;

var builder = WebAssemblyHostBuilder.CreateDefault(args);
builder.RootComponents.Add<App>("#app");
builder.RootComponents.Add<HeadOutlet>("head::after");

builder.Services.AddScoped(sp => new HttpClient { BaseAddress = new Uri(builder.HostEnvironment.BaseAddress) });

// await builder.Build().RunAsync();

// 以下Cultureの設定
builder.Services.AddLocalization();

var host = builder.Build();

CultureInfo culture;
var js = host.Services.GetRequiredService<IJSRuntime>();
var result = await js.InvokeAsync<string>("blazorCulture.get");

// Webストレージにデータがあればそれを、無ければBrowserのLocaleを読み込む
if (result != null)
{
    culture = new CultureInfo(result);
}
else
{
    var localCal = await js.InvokeAsync<string>("getBrowserLocale");
    culture = new CultureInfo(localCal);
    await js.InvokeVoidAsync("blazorCulture.set", culture.Name);
}

CultureInfo.DefaultThreadCurrentCulture = culture;
CultureInfo.DefaultThreadCurrentUICulture = culture;

await host.RunAsync();

Sharedフォルダに「CultureSelector.razor」の名前でヘッダーに設置する言語セレクターコンポーネントを作成する

code
@using System.Globalization
@using BlazorApp1.Properties
@inject IStringLocalizer<Resource> Loc
@inject IJSRuntime JSRuntime
@inject NavigationManager Nav

@Loc["SelectLanguage"] :
<select @bind="Culture">
    @foreach (var culture in supportedCultures)
    {
        <option value="@culture">@culture.DisplayName</option>
    }
</select>

@code
{
    private CultureInfo[] supportedCultures = new[]
    {
        new CultureInfo("en-US"),
        new CultureInfo("ja-JP"),
    };

    private CultureInfo Culture
    {
        get => CultureInfo.CurrentCulture;
        set
        {
            if (CultureInfo.CurrentCulture != value)
            {
                var js = (IJSInProcessRuntime)JSRuntime;
                js.InvokeVoid("blazorCulture.set", value.Name);

                Nav.NavigateTo(Nav.Uri, forceLoad: true);
            }
        }
    }
}

MainLayout.razorに <CultureSelector /> を追加し、ヘッダに言語セレクターを設置する

code
@inherits LayoutComponentBase

<div class="page">
    <div class="sidebar">
        <NavMenu />
    </div>

    <main>
        <div class="top-row px-4">
            <CultureSelector />
            <a href="https://docs.microsoft.com/aspnet/" target="_blank">About</a>
        </div>

        <article class="content px-4">
            @Body
        </article>
    </main>
</div>

Propertiesフォルダに、リソースファイルResource.resxとResource.ja.resxを作成し、以下のキーバリューを追加する

KeyNeutral日本語
GreetingHello World !こんにちは、世界!
SelectLanguageSelect your language言語選択

ちなみにResourceファイルの編集は、拡張機能「ResXManager」が便利ですね

ResXManagerスクリーンショット

デバッグ実行し、初回起動時にブラウザLocaleから日本語表示、セレクター切り替えで英語表示になることを確認

Blazor デモ画面

Blazor デモ画面

参考

目次