共用方式為


ASP.NET Core Blazor 全球化和當地語系化

注意

這不是這篇文章的最新版本。 如需目前的版本,請參閱 本文的 .NET 9 版本。

警告

不再支援此版本的 ASP.NET Core。 如需詳細資訊,請參閱 .NET 和 .NET Core 支援原則。 如需目前版本,請參閱本文的 .NET 8 版本

重要

這些發行前產品的相關資訊在產品正式發行前可能會有大幅修改。 Microsoft 對此處提供的資訊,不做任何明確或隱含的瑕疵擔保。

如需目前的版本,請參閱 本文的 .NET 9 版本。

本文說明如何將全球化和當地語系化的內容轉譯給不同文化特性和語言的使用者。

全球化和當地語系化

針對全球化,Blazor 提供數字和日期格式化。 針對當地語系化,Blazor 會使用 .NET 資源系統轉譯內容。

支援一組有限的 ASP.NET Core 當地語系化功能:

支援:Blazor 應用程式中支援 IStringLocalizerIStringLocalizer<T>

不支援: IHtmlLocalizerIViewLocalizer資料註釋當地語系化是 ASP.NET Core MVC 功能,且在 Blazor 應用程式中不受支援。

本文描述如何使用 Blazor 的全球化和當地語系化功能,其依據如下:

  • Accept-Language 標頭,其是由瀏覽器根據瀏覽器設定中使用者的語言喜好設定所設定。
  • 應用程式所設定的文化特性,不是以 Accept-Language 標頭的值為基礎。 此設定可以是所有使用者的靜態設定,或根據應用程式邏輯成為動態設定。 當設定是以使用者的喜好設定為基礎時,通常會儲存此設定以供日後造訪時重新載入。

如需其他一般資訊,請參閱下列資源:

通常,在處理全球化和當地語系化概念時,「語言」和「文化特性」這兩個術語會交換使用。

在本文中,「語言」是指使用者在其瀏覽器設定中所做的選項。 使用者的語言選項是以 Accept-Language 標頭中的瀏覽器要求提交。 瀏覽器設定通常會在 UI 中使用「語言」一詞。

「文化特性」與 .NET 和 Blazor API 的成員有關。 例如,使用者的要求可以包含 Accept-Language 標頭,從使用者的觀點指定「語言」,但應用程式最終會從使用者要求的語言設定 CurrentCulture ("culture") 屬性。 API 通常會在其成員名稱中使用「文化特性」一詞。

本文中的指導未涵蓋設定頁面的 HTML 語言屬性 (<html lang="...">),其為協助工具使用。 您可以將語言指派給 <html> 標記的 lang 屬性,或在 document.documentElement.lang JavaScript 中以靜態方式設定值。 您可以使用 JSinteropdocument.documentElement.lang 動態設定 的值。

注意

本文中的程式碼範例採用 可為 Null 的參考型別 (NRT) 和 .NET 編譯器 Null 狀態靜態分析,這在 .NET 6 或更新版本的 ASP.NET Core 中受到支援。 以 ASP.NET Core 5.0 或更早版本為目標時,請從本文範例中移除 Null 類型指定 (?)。

全球化

@bind 屬性指示詞會根據使用者第一個受應用程式支援的慣用語言套用格式和剖析值以供顯示。 @bind 支援 @bind:culture 參數,提供用於剖析和格式化一值的 System.Globalization.CultureInfo

您可以從 System.Globalization.CultureInfo.CurrentCulture 屬性存取目前的文化特性。

CultureInfo.InvariantCulture 用於下列欄位類型 (<input type="{TYPE}" />,其中 {TYPE} 預留位置為類型):

  • date
  • number

上述欄位類型:

  • 使用其適當的瀏覽器型格式化規則來顯示。
  • 無法包含自由格式文字。
  • 根據瀏覽器的實作提供使用者互動特性。

Blazor 提供內建支援,以轉譯目前文化特性中的值。 因此,在使用 datenumber 欄位類型時,不建議使用 @bind:culture 來指定文化特性。

下列欄位類型具有特定的格式需求,且不受所有主要瀏覽器支援,因此目前不受 Blazor支援:

  • datetime-local
  • month
  • week

如需上述類型的目前瀏覽器支援,請參閱我可以使用

支援 Unicode (ICU) 的 .NET 全球化和國際化元件 (Blazor WebAssembly)

Blazor WebAssembly 會使用縮減的全球化 API 和一組適用於 Unicode (ICU) 地區設定的內建國際化元件。 如需詳細資訊,請參閱 .NET 全球化和 ICU:WebAssembly 上的 ICU

若要載入自訂 ICU 資料檔案來控制應用程式的地區設定,請參閱 WASM 全球化 ICU。 目前,需要手動建置自訂 ICU 資料檔案。 .NET 工具可簡化在 2025 年 11 月針對 .NET 10 建立檔案的程式。

Blazor WebAssembly 會使用縮減的全球化 API 和一組適用於 Unicode (ICU) 地區設定的內建國際化元件。 如需詳細資訊,請參閱 .NET 全球化和 ICU:WebAssembly 上的 ICU

.NET 8 或更新版本中支援在 Blazor WebAssembly 應用程式中載入自訂的地區設定子集。 如需詳細資訊,請存取此區段以取得本文的 8.0 或更新版本。

不因全球化而異

本節僅適用於用戶端 Blazor 案例。

如果應用程式不需要當地語系化,請將應用程式設定為支援不因文化特性而異,這通常以美國英文 (en-US) 為基礎。 使用不可變的全球化,可降低應用程式的下載大小,並讓應用程式啟動速度更快。 將 InvariantGlobalization 屬性設定為應用程式專案檔 (.csproj) 中的 true

<PropertyGroup>
  <InvariantGlobalization>true</InvariantGlobalization>
</PropertyGroup>

或者,使用下列方法設定不因全球化而異:

  • runtimeconfig.json 中:

    {
      "runtimeOptions": {
        "configProperties": {
          "System.Globalization.Invariant": true
        }
      }
    }
    
  • 使用環境變數:

    • 機碼:DOTNET_SYSTEM_GLOBALIZATION_INVARIANT
    • 值:true1

如需詳細資訊,請參閱適用於全球化的執行階段設定選項 (.NET 文件)

時區資訊

本節僅適用於用戶端 Blazor 案例。

採用不可變的全球化,只會使用非當地語系化的時區名稱。 若要修剪時區代碼和資料,藉以降低應用程式的下載大小並讓應用程式啟動速度更快,請使用應用程式專案檔中的 true 值套用 <InvariantTimezone> MSBuild 屬性:

<PropertyGroup>
  <InvariantTimezone>true</InvariantTimezone>
</PropertyGroup>

注意

<BlazorEnableTimeZoneSupport> 會覆寫先前的 <InvariantTimezone> 設定。 建議您移除 <BlazorEnableTimeZoneSupport> 設定。

納入資料檔案以正確顯示時區資訊。 如果應用程式不需要此功能,請考慮將應用程式專案檔中的 <BlazorEnableTimeZoneSupport> MSBuild 屬性設定為 false 來停用此功能:

<PropertyGroup>
  <BlazorEnableTimeZoneSupport>false</BlazorEnableTimeZoneSupport>
</PropertyGroup>

示範元件

下列 CultureExample1 元件可用來示範本文所涵蓋的 Blazor 全球化和當地語系化概念。

CultureExample1.razor

@page "/culture-example-1"
@using System.Globalization

<h1>Culture Example 1</h1>

<ul>
    <li><b>CurrentCulture</b>: @CultureInfo.CurrentCulture</li>
    <li><b>CurrentUICulture</b>: @CultureInfo.CurrentUICulture</li>
</ul>

<h2>Rendered values</h2>

<ul>
    <li><b>Date</b>: @dt</li>
    <li><b>Number</b>: @number.ToString("N2")</li>
</ul>

<h2><code>&lt;input&gt;</code> elements that don't set a <code>type</code></h2>

<p>
    The following <code>&lt;input&gt;</code> elements use
    <code>CultureInfo.CurrentCulture</code>.
</p>

<ul>
    <li><label><b>Date:</b> <input @bind="dt" /></label></li>
    <li><label><b>Number:</b> <input @bind="number" /></label></li>
</ul>

<h2><code>&lt;input&gt;</code> elements that set a <code>type</code></h2>

<p>
    The following <code>&lt;input&gt;</code> elements use
    <code>CultureInfo.InvariantCulture</code>.
</p>

<ul>
    <li><label><b>Date:</b> <input type="date" @bind="dt" /></label></li>
    <li><label><b>Number:</b> <input type="number" @bind="number" /></label></li>
</ul>

@code {
    private DateTime dt = DateTime.Now;
    private double number = 1999.69;
}

上述範例 (.ToString("N2")) 中的數字字串格式 (N2) 是標準 .NET 數值格式規範。 所有數數值型別都支援 N2 格式 (包括群組分隔符號),並轉譯最多兩個小數位數。

或者,針對 CultureExample1 元件將功能表項目新增至 NavMenu 元件 (NavMenu.razor) 中的導覽。

Accept-Language 標頭動態設定文化特性

Microsoft.Extensions.Localization 套件新增至應用程式。

Accept-Language 標頭 是由瀏覽器所設定,並由瀏覽器設定中使用者的語言喜好設定所控制。 在瀏覽器設定中,使用者會依喜好順序設定一或多個慣用的語言。 瀏覽器會使用喜好順序來設定標頭中每個語言的品質值 (q,0-1)。 下列範例會指定美國英文、英文和哥斯大黎加西班牙文,但優先使用美國英文或英文:

Accept-Language:en-US,en;q=0.9,es-CR;q=0.8

設定應用程式文化特性的方式是比對第一個要求的語言,其會比對應用程式支援的文化特性。

在「用戶端開發」中,於用戶端應用程式的專案檔 (.csproj) 中將 BlazorWebAssemblyLoadAllGlobalizationData 屬性設定為 true

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

在「用戶端開發」中,不支援從 Accept-Language 標頭動態設定文化特性。

注意

如果應用程式的規格需要將支援的文化特性限制為明確清單,請參閱本文的透過使用者喜好設定動態設定用戶端文化特性一節。

應用程式會使用當地語系化中介軟體進行當地語系化。 使用 AddLocalization 將當地語系化服務新增至應用程式。

將下列這一行新增至服務註冊所在的 Program 檔案:

builder.Services.AddLocalization();

伺服器端開發中,請在任何可能檢查要求文化特性的中間件之前,指定應用程式支援的文化特性。 一般而言,請先將要求本地化中間件放在呼叫 MapRazorComponents之前。 下列範例會設定美國英文和哥斯大黎加西班牙文支援的文化特性:

伺服器端開發中,在路由中間件 (UseRouting) 新增至處理管線之後,立即指定應用程式支援的文化特性。 下列範例會設定美國英文和哥斯大黎加西班牙文支援的文化特性:

app.UseRequestLocalization(new RequestLocalizationOptions()
    .AddSupportedCultures(new[] { "en-US", "es-CR" })
    .AddSupportedUICultures(new[] { "en-US", "es-CR" }));

如需在 Program 檔案的中介軟體管線中排序當地語系化中介軟體的相關資訊,請參閱 ASP.NET Core 中介軟體

使用示範元件一節中顯示的 CultureExample1 元件來研究全球化的運作方式。 使用美國英文發出要求 (en-US)。 在瀏覽器的語言設定中切換至哥斯大黎加西班牙文 (es-CR)。 再次要求網頁。

注意

某些瀏覽器會強制您將預設語言設定同時用於要求和瀏覽器本身的 UI 設定。 這可能會使將語言變回您難以理解的語言,因為所有設定 UI 畫面最終都可能以您無法閱讀的語言顯示。 Opera 等瀏覽器是測試的好選擇,因為其可讓您設定網頁要求的預設語言,但將瀏覽器的設定 UI 保留為您的語言。

當文化特性是美國英文 (en-US) 時,轉譯的元件會使用月/日日期格式 (6/7)、12 小時制 (AM/PM),以及在數字中使用逗號分隔符號,以點表示小數值 (1,999.69):

  • 日期:6/7/2021 6:45:22 AM
  • 數字:1,999.69

當文化特性是哥斯大黎加西班牙文 (es-CR) 時,轉譯的元件會使用日/月日期格式 (7/6)、24 小時制,以及在數字中使用句點分隔符號,以逗號表示小數值 (1.999,69):

  • 日期:7/6/2021 6:49:38
  • 數字:1.999,69

以靜態方式設定用戶端文化特性

在應用程式的專案檔 (.csproj) 中將 BlazorWebAssemblyLoadAllGlobalizationData 屬性設定為 true

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

用戶端轉譯的中繼語言 (IL) 連結器設定會去除國際化資訊,但明確要求的地區設定除外。 如需詳細資訊,請參閱設定 ASP.NET Core Blazor 的連結器

當 Blazor 使用 applicationCultureBlazor 啟動選項啟動時,您可以在 JavaScript 中設定應用程式的文化特性。 下列範例會將應用程式設定為使用美國英文 (en-US) 文化特性啟動。

autostart="false" 新增至 Blazor 的 <script> 標籤,以防止 Blazor 自動啟動:

<script src="{BLAZOR SCRIPT}" autostart="false"></script>

在上述範例中,{BLAZOR SCRIPT} 預留位置是 Blazor 指令碼路徑和檔案名稱。 如需指令碼的位置,請參閱 ASP.NET Core Blazor 專案結構

Blazor 的 <script> 標籤後面、結尾 </body> 標籤前面,新增下列 <script> 區塊:

Blazor Web App:

<script>
  Blazor.start({
    webAssembly: {
      applicationCulture: 'en-US'
    }
  });
</script>

獨立 Blazor WebAssembly:

<script>
  Blazor.start({
    applicationCulture: 'en-US'
  });
</script>

applicationCulture 的值必須符合 BCP-47 語言標籤格式。 如需關於 Blazor 啟動的詳細資訊,請參閱 ASP.NET Core Blazor 啟動

設定文化特性 Blazor 的啟動選項的替代方法是在 C# 程式碼中設定文化特性。 將 Program 檔案中的 CultureInfo.DefaultThreadCurrentCultureCultureInfo.DefaultThreadCurrentUICulture 設定為相同的文化特性。

System.Globalization 命名空間新增至 Program 檔案:

using System.Globalization;

在建置並執行 WebAssemblyHostBuilder (await builder.Build().RunAsync();) 的那一行前面新增文化特性設定:

CultureInfo.DefaultThreadCurrentCulture = new CultureInfo("en-US");
CultureInfo.DefaultThreadCurrentUICulture = new CultureInfo("en-US");

注意

目前,Blazor WebAssembly 應用程式只會根據 DefaultThreadCurrentCulture 載入資源。 如需詳細資訊,請參閱 Blazor WASM 僅依賴目前的文化特性 (未遵守目前的 UI 文化特性) (dotnet/aspnetcore #56824)

使用示範元件一節中顯示的 CultureExample1 元件來研究全球化的運作方式。 使用美國英文發出要求 (en-US)。 在瀏覽器的語言設定中切換至哥斯大黎加西班牙文 (es-CR)。 再次要求網頁。 當要求的語言是哥斯大黎加西班牙文時,應用程式的文化特性仍然是美國英文 (en-US)。

以靜態方式設定伺服器端文化特性

伺服器端應用程式是使用當地語系化中介軟體進行當地語系化。 使用 AddLocalization 將當地語系化服務新增至應用程式。

Program 檔案中:

builder.Services.AddLocalization();

在檔案中 Program 指定靜態文化特性,再檢查要求文化特性的任何中間件。 一般而言,請將要求當地語系化中間件放在 緊接在 之前 MapRazorComponents。 下列範例會設定美國英文:

在路由中間件 (UseRouting) 新增至處理管線之後,立即在檔案中Program指定靜態文化特性。 下列範例會設定美國英文:

app.UseRequestLocalization("en-US");

UseRequestLocalization 的文化特性值必須符合 BCP-47 語言標籤格式

如需在 Program 檔案的中介軟體管線中排序當地語系化中介軟體的相關資訊,請參閱 ASP.NET Core 中介軟體

伺服器端應用程式是使用當地語系化中介軟體進行當地語系化。 使用 AddLocalization 將當地語系化服務新增至應用程式。

Startup.ConfigureServices (Startup.cs) 中:

services.AddLocalization();

在路由中介軟體新增至處理管線之後,立即在 Startup.Configure (Startup.cs) 中指定靜態文化特性。 下列範例會設定美國英文:

app.UseRequestLocalization("en-US");

UseRequestLocalization 的文化特性值必須符合 BCP-47 語言標籤格式

如需在 Startup.Configure 的中介軟體管線中排序當地語系化中介軟體的相關資訊,請參閱 ASP.NET Core 中介軟體

使用示範元件一節中顯示的 CultureExample1 元件來研究全球化的運作方式。 使用美國英文發出要求 (en-US)。 在瀏覽器的語言設定中切換至哥斯大黎加西班牙文 (es-CR)。 再次要求網頁。 當要求的語言是哥斯大黎加西班牙文時,應用程式的文化特性仍然是美國英文 (en-US)。

依使用者喜好設定動態設定用戶端文化特性

應用程式可能會在其中儲存使用者喜好設定的位置範例,包含在瀏覽器本機儲存體 (常見於用戶端案例)、當地語系化 cookie 或資料庫 (常見於伺服器端案例),或附加至外部資料庫並由 Web API 存取的外部服務中。 下列範例示範如何使用瀏覽器本機儲存體。

Microsoft.Extensions.Localization 套件新增至應用程式。

注意

如需將套件新增至 .NET 應用程式的指引,請參閱在套件取用工作流程 (NuGet 文件)安裝及管理套件底下的文章。 在 NuGet.org 確認正確的套件版本。

在專案檔中,將 BlazorWebAssemblyLoadAllGlobalizationData 屬性設定為 true

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

應用程式用於用戶端轉譯的文化特性是使用 Blazor 架構的 API 來設定。 使用者的文化特性選取項目可以保存在瀏覽器本機儲存體中。

Blazor 的 <script> 標籤後面提供 JS 函式,以使用瀏覽器本機儲存體來取得和設定使用者的文化特性選取項目:

<script>
  window.blazorCulture = {
    get: () => window.localStorage['BlazorCulture'],
    set: (value) => window.localStorage['BlazorCulture'] = value
  };
</script>

注意

上述範例會使用全域函式敗壞用戶端。 如需更適合生產應用程式的方法,請參閱 JavaScript 模組中的 JavaScript 隔離

System.GlobalizationMicrosoft.JSInterop 的命名空間新增至 Program 檔案頂端:

using System.Globalization;
using Microsoft.JSInterop;

移除下列程式碼:

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

將上述一行取代為下列程式碼。 此程式碼會使用 AddLocalization 將 Blazor 的當地語系化服務新增至應用程式的服務集合,並使用 JS Interop 來呼叫 JS,然後從本機儲存體擷取使用者的文化特性選取項目。 如果本機儲存體未包含使用者的文化特性,程式碼會設定預設值,即美國英文 (en-US)。

builder.Services.AddLocalization();

var host = builder.Build();

const string defaultCulture = "en-US";

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

if (result == null)
{
    await js.InvokeVoidAsync("blazorCulture.set", defaultCulture);
}

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

await host.RunAsync();

注意

目前,Blazor WebAssembly 應用程式只會根據 DefaultThreadCurrentCulture 載入資源。 如需詳細資訊,請參閱 Blazor WASM 僅依賴目前的文化特性 (未遵守目前的 UI 文化特性) (dotnet/aspnetcore #56824)

下列 CultureSelector 元件展示如何執行下列動作:

  • 透過 JS Interop 將使用者的文化特性選取項目設定為瀏覽器本機儲存體。
  • 重新載入其所要求的元件 (forceLoad: true),這會使用更新的文化特性。

CultureSelector.razor

@using System.Globalization
@inject IJSRuntime JS
@inject NavigationManager Navigation

<p>
    <label>
        Select your locale:
        <select @bind="selectedCulture" @bind:after="ApplySelectedCultureAsync">
            @foreach (var culture in supportedCultures)
            {
                <option value="@culture">@culture.DisplayName</option>
            }
        </select>
    </label>
</p>

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

    private CultureInfo? selectedCulture;

    protected override void OnInitialized()
    {
        selectedCulture = CultureInfo.CurrentCulture;
    }

    private async Task ApplySelectedCultureAsync()
    {
        if (CultureInfo.CurrentCulture != selectedCulture)
        {
            await JS.InvokeVoidAsync("blazorCulture.set", selectedCulture!.Name);

            Navigation.NavigateTo(Navigation.Uri, forceLoad: true);
        }
    }
}
@using System.Globalization
@inject IJSRuntime JS
@inject NavigationManager Navigation

<p>
    <label>
        Select your locale:
        <select value="@selectedCulture" @onchange="HandleSelectedCultureChanged">
            @foreach (var culture in supportedCultures)
            {
                <option value="@culture">@culture.DisplayName</option>
            }
        </select>
    </label>
</p>

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

    private CultureInfo? selectedCulture;

    protected override void OnInitialized()
    {
        selectedCulture = CultureInfo.CurrentCulture;
    }

    private async Task HandleSelectedCultureChanged(ChangeEventArgs args)
    {
        selectedCulture = CultureInfo.GetCultureInfo((string)args.Value!);

        if (CultureInfo.CurrentCulture != selectedCulture)
        {
            await JS.InvokeVoidAsync("blazorCulture.set", selectedCulture!.Name);

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

MainLayout 元件 (MainLayout.razor) 中 </main> 元素的結束標籤內,新增 CultureSelector 元件:

<article class="bottom-row px-4">
    <CultureSelector />
</article>

使用示範元件一節中顯示的 CultureExample1 元件來研究上述範例的運作方式。

依使用者喜好設定動態設定伺服器端文化特性

應用程式可能會在其中儲存使用者喜好設定的位置範例,包含在瀏覽器本機儲存體 (常見於用戶端案例)、當地語系化 cookie 或資料庫 (常見於伺服器端案例),或附加至外部資料庫並由 Web API 存取的外部服務中。 下列範例示範如何使用當地語系化 cookie。

注意

下列範例假設應用程式會藉由在 App 元件 (Components/App.razor) 中的 Routes 元件上指定互動式伺服器端轉譯 (互動式 SSR),採用全域互動功能:

<Routes @rendermode="InteractiveServer" />

如果應用程式採用每頁/元件互動功能,請參閱本節結尾的備註,修改範例元件的轉譯模式。

Microsoft.Extensions.Localization 套件新增至應用程式。

注意

如需將套件新增至 .NET 應用程式的指引,請參閱在套件取用工作流程 (NuGet 文件)安裝及管理套件底下的文章。 在 NuGet.org 確認正確的套件版本。

伺服器端應用程式是使用當地語系化中介軟體進行當地語系化。 使用 AddLocalization 將當地語系化服務新增至應用程式。

Program 檔案中:

builder.Services.AddLocalization();

使用 RequestLocalizationOptions 設定應用程式的預設和受支援文化特性。

在要求處理管線中的 MapRazorComponents 呼叫之前,放置下列程式碼:

將路由中間件 (UseRouting) 新增至要求處理管線之後,請放置下列程式代碼:

var supportedCultures = new[] { "en-US", "es-CR" };
var localizationOptions = new RequestLocalizationOptions()
    .SetDefaultCulture(supportedCultures[0])
    .AddSupportedCultures(supportedCultures)
    .AddSupportedUICultures(supportedCultures);

app.UseRequestLocalization(localizationOptions);

如需在中介軟體管線中排序當地語系化中介軟體的相關資訊,請參閱 ASP.NET Core 中介軟體

下列範例展示如何在 cookie 中設定當地語系化中介軟體可以讀取的目前文化特性。

App 元件需要下列命名空間:

將下列內容新增至 App 元件檔案 (Components/App.razor) 的頂端:

@using System.Globalization
@using Microsoft.AspNetCore.Localization

將下列 @code 區塊新增至 App 元件檔案底部:

@code {
    [CascadingParameter]
    public HttpContext? HttpContext { get; set; }

    protected override void OnInitialized()
    {
        HttpContext?.Response.Cookies.Append(
            CookieRequestCultureProvider.DefaultCookieName,
            CookieRequestCultureProvider.MakeCookieValue(
                new RequestCulture(
                    CultureInfo.CurrentCulture,
                    CultureInfo.CurrentUICulture)));
    }
}

修改 Pages/_Host.cshtml 檔案需要下列命名空間:

將下列內容加入至檔案中:

@using System.Globalization
@using Microsoft.AspNetCore.Localization
@{
    this.HttpContext.Response.Cookies.Append(
        CookieRequestCultureProvider.DefaultCookieName,
        CookieRequestCultureProvider.MakeCookieValue(
            new RequestCulture(
                CultureInfo.CurrentCulture,
                CultureInfo.CurrentUICulture)));
}

如需在中介軟體管線中排序當地語系化中介軟體的相關資訊,請參閱 ASP.NET Core 中介軟體

如果應用程式未設定為處理控制器動作:

  • Program 檔案的服務集合上呼叫 AddControllers,以新增 MVC 服務:

    builder.Services.AddControllers();
    
  • Program 檔案中新增控制器端點路由,方法是在 IEndpointRouteBuilder (app) 上呼叫 MapControllers

    app.MapControllers();
    

若要提供 UI 以允許使用者選取文化特性,請使用重新導向型方法搭配當地語系化 cookie。 應用程式會透過重新導向至控制器來保存使用者選取的文化特性。 控制器會將使用者選取的文化特性設定為 cookie,並將使用者重新導向回原始 URI。 此流程類似於當使用者嘗試存取安全資源時,Web 應用程式中發生的情況,其中使用者會重新導向至登入頁面,然後重新導向回原始資源。

Controllers/CultureController.cs

using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc;

[Route("[controller]/[action]")]
public class CultureController : Controller
{
    public IActionResult Set(string culture, string redirectUri)
    {
        if (culture != null)
        {
            HttpContext.Response.Cookies.Append(
                CookieRequestCultureProvider.DefaultCookieName,
                CookieRequestCultureProvider.MakeCookieValue(
                    new RequestCulture(culture, culture)));
        }

        return LocalRedirect(redirectUri);
    }
}

警告

使用 LocalRedirect 動作結果 (如上述範例所示),防止開放式重新導向攻擊。 如需詳細資訊,請參閱防止 ASP.NET Core 中的開放式重新導向攻擊

下列 CultureSelector 元件展示如何使用新的文化特性呼叫 CultureControllerSet 方法。 此元件會放在 Shared 資料夾中,供整個應用程式使用。

CultureSelector.razor

@using System.Globalization
@inject IJSRuntime JS
@inject NavigationManager Navigation

<p>
    <label>
        Select your locale:
        <select @bind="selectedCulture" @bind:after="ApplySelectedCultureAsync">
            @foreach (var culture in supportedCultures)
            {
                <option value="@culture">@culture.DisplayName</option>
            }
        </select>
    </label>
</p>

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

    private CultureInfo? selectedCulture;

    protected override void OnInitialized()
    {
        selectedCulture = CultureInfo.CurrentCulture;
    }

    private async Task ApplySelectedCultureAsync()
    {
        if (CultureInfo.CurrentCulture != selectedCulture)
        {
            var uri = new Uri(Navigation.Uri)
                .GetComponents(UriComponents.PathAndQuery, UriFormat.Unescaped);
            var cultureEscaped = Uri.EscapeDataString(selectedCulture.Name);
            var uriEscaped = Uri.EscapeDataString(uri);

            Navigation.NavigateTo(
                $"Culture/Set?culture={cultureEscaped}&redirectUri={uriEscaped}",
                forceLoad: true);
        }
    }
}
@using System.Globalization
@inject IJSRuntime JS
@inject NavigationManager Navigation

<p>
    <label>
        Select your locale:
        <select value="@selectedCulture" @onchange="HandleSelectedCultureChanged">
            @foreach (var culture in supportedCultures)
            {
                <option value="@culture">@culture.DisplayName</option>
            }
        </select>
    </label>
</p>

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

    private CultureInfo? selectedCulture;

    protected override void OnInitialized()
    {
        selectedCulture = CultureInfo.CurrentCulture;
    }

    private async Task HandleSelectedCultureChanged(ChangeEventArgs args)
    {
        selectedCulture = CultureInfo.GetCultureInfo((string)args.Value!);

        if (CultureInfo.CurrentCulture != selectedCulture)
        {
            var uri = new Uri(Navigation.Uri)
                .GetComponents(UriComponents.PathAndQuery, UriFormat.Unescaped);
            var cultureEscaped = Uri.EscapeDataString(selectedCulture.Name);
            var uriEscaped = Uri.EscapeDataString(uri);

            Navigation.NavigateTo(
                $"Culture/Set?culture={cultureEscaped}&redirectUri={uriEscaped}",
                forceLoad: true);
        }
    }
}

CultureSelector 元件新增至 MainLayout 元件。 將下列標記放在 Components/Layout/MainLayout.razor 檔案的結尾 </main> 標記內:

CultureSelector 元件新增至 MainLayout 元件。 將下列標記放在 Shared/MainLayout.razor 檔案的結尾 </main> 標記內:

<article class="bottom-row px-4">
    <CultureSelector />
</article>

使用示範元件一節中顯示的 CultureExample1 元件來研究上述範例的運作方式。

上述範例假設應用程式會藉由在 App 元件 (Components/App.razor) 中的 Routes 元件上指定互動式伺服器轉譯模式,採用全域互動功能:

<Routes @rendermode="InteractiveServer" />

如果應用程式採用每頁/元件互動功能,請進行下列變更:

  • CultureExample1 元件檔案 (Components/Pages/CultureExample1.razor) 頂端新增互動式伺服器轉譯模式:

    @rendermode InteractiveServer
    
  • 在應用程式的主要配置 (Components/Layout/MainLayout.razor) 中,將互動式伺服器轉譯模式套用至 CultureSelector 元件:

    <CultureSelector @rendermode="InteractiveServer" />
    

依使用者喜好設定動態設定 Blazor Web App 中的文化特性

本節適用於採用自動 (伺服器和 WebAssembly) 互動功能的 Blazor Web App。

應用程式可能會在其中儲存使用者喜好設定的位置範例,包括瀏覽器本機儲存體 (常見於用戶端案例)、當地語系化 cookie 或資料庫 (常見於伺服器端案例)、本機儲存體與當地語系化 cookie (具有伺服器和 WebAssembly 元件的Blazor Web App),或附加至外部資料庫並由 Web API 存取的外部服務。 下列範例示範如何將瀏覽器本機儲存體用於用戶端轉譯 (CSR) 元件,以及將當地語系化 cookie 用於伺服器端轉譯 (SSR) 元件。

.Client 專案的更新

Microsoft.Extensions.Localization 套件新增至 .Client 專案。

注意

如需將套件新增至 .NET 應用程式的指引,請參閱在套件取用工作流程 (NuGet 文件)安裝及管理套件底下的文章。 在 NuGet.org 確認正確的套件版本。

.Client 專案檔中,將 BlazorWebAssemblyLoadAllGlobalizationData 屬性設定為 true

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

System.GlobalizationMicrosoft.JSInterop 的命名空間新增至 .Client 專案的 Program 檔案頂端:

using System.Globalization;
using Microsoft.JSInterop;

移除下列程式碼:

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

將上述一行取代為下列程式碼。 此程式碼會使用 AddLocalization 將 Blazor 的當地語系化服務新增至應用程式的服務集合,並使用 JS Interop 來呼叫 JS,然後從本機儲存體擷取使用者的文化特性選取項目。 如果本機儲存體未包含使用者的文化特性,程式碼會設定預設值,即美國英文 (en-US)。

builder.Services.AddLocalization();

var host = builder.Build();

const string defaultCulture = "en-US";

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

if (result == null)
{
    await js.InvokeVoidAsync("blazorCulture.set", defaultCulture);
}

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

await host.RunAsync();

注意

目前,Blazor WebAssembly 應用程式只會根據 DefaultThreadCurrentCulture 載入資源。 如需詳細資訊,請參閱 Blazor WASM 僅依賴目前的文化特性 (未遵守目前的 UI 文化特性) (dotnet/aspnetcore #56824)

將下列 CultureSelector 元件新增至 .Client 專案。

此元件採用下列方法來處理 SSR 或 CSR 元件:

  • 下拉式清單中每個可用文化特性的顯示名稱均由字典提供,因為用戶端全球化資料包含伺服器端全球化資料所提供的文化特性顯示名稱的當地語系化文字。 例如,當 en-US 是文化特性時,伺服器端當地語系化會顯示 English (United States),使用不同的文化特性時則顯示 Ingles ()。 由於文化特性顯示名稱無法透過 Blazor WebAssembly 全球化進行當地語系化,因此,無論載入的文化特性為何,用戶端上的美國英文顯示名稱都只是 en-US。 使用自訂字典可讓元件至少顯示完整的英文文化特性名稱。
  • 當使用者變更文化特性時,JS Interop 會在本機瀏覽器儲存體中設定文化特性,而控制器動作會使用文化特性來更新當地語系化 cookie。 控制器會在後續的伺服器專案更新小節中新增至應用程式。

Pages/CultureSelector.razor

@using System.Globalization
@inject IJSRuntime JS
@inject NavigationManager Navigation

<p>
    <label>
        Select your locale:
        <select @bind="@selectedCulture" @bind:after="ApplySelectedCultureAsync">
            @foreach (var culture in supportedCultures)
            {
                <option value="@culture">@cultureDict[culture.Name]</option>
            }
        </select>
    </label>
</p>

@code
{
    private Dictionary<string, string> cultureDict = 
        new()
        {
            { "en-US", "English (United States)" },
            { "es-CR", "Spanish (Costa Rica)" }
        };

    private CultureInfo[] supportedCultures = new[]
    {
        new CultureInfo("en-US"),
        new CultureInfo("es-CR"),
    };

    private CultureInfo? selectedCulture;

    protected override void OnInitialized()
    {
        selectedCulture = CultureInfo.CurrentCulture;
    }

    private async Task ApplySelectedCultureAsync()
    {
        if (CultureInfo.CurrentCulture != selectedCulture)
        {
            await JS.InvokeVoidAsync("blazorCulture.set", selectedCulture!.Name);

            var uri = new Uri(Navigation.Uri)
                .GetComponents(UriComponents.PathAndQuery, UriFormat.Unescaped);
            var cultureEscaped = Uri.EscapeDataString(selectedCulture.Name);
            var uriEscaped = Uri.EscapeDataString(uri);

            Navigation.NavigateTo(
                $"Culture/Set?culture={cultureEscaped}&redirectUri={uriEscaped}",
                forceLoad: true);
        }
    }
}

.Client 專案中放置下列 CultureClient 元件,以研究全球化對 CSR 元件的作用。

Pages/CultureClient.razor

@page "/culture-client"
@rendermode InteractiveWebAssembly
@using System.Globalization

<PageTitle>Culture Client</PageTitle>

<h1>Culture Client</h1>

<ul>
    <li><b>CurrentCulture</b>: @CultureInfo.CurrentCulture</li>
    <li><b>CurrentUICulture</b>: @CultureInfo.CurrentUICulture</li>
</ul>

<h2>Rendered values</h2>

<ul>
    <li><b>Date</b>: @dt</li>
    <li><b>Number</b>: @number.ToString("N2")</li>
</ul>

<h2><code>&lt;input&gt;</code> elements that don't set a <code>type</code></h2>

<p>
    The following <code>&lt;input&gt;</code> elements use
    <code>CultureInfo.CurrentCulture</code>.
</p>

<ul>
    <li><label><b>Date:</b> <input @bind="dt" /></label></li>
    <li><label><b>Number:</b> <input @bind="number" /></label></li>
</ul>

<h2><code>&lt;input&gt;</code> elements that set a <code>type</code></h2>

<p>
    The following <code>&lt;input&gt;</code> elements use
    <code>CultureInfo.InvariantCulture</code>.
</p>

<ul>
    <li><label><b>Date:</b> <input type="date" @bind="dt" /></label></li>
    <li><label><b>Number:</b> <input type="number" @bind="number" /></label></li>
</ul>

@code {
    private DateTime dt = DateTime.Now;
    private double number = 1999.69;
}

伺服器專案更新

Microsoft.Extensions.Localization 套件新增至伺服器專案。

注意

如需將套件新增至 .NET 應用程式的指引,請參閱在套件取用工作流程 (NuGet 文件)安裝及管理套件底下的文章。 在 NuGet.org 確認正確的套件版本。

伺服器端應用程式是使用當地語系化中介軟體進行當地語系化。 使用 AddLocalization 將當地語系化服務新增至應用程式。

在服務註冊所在的伺服器專案 Program 檔案中:

builder.Services.AddLocalization();

使用 RequestLocalizationOptions 設定應用程式的預設和受支援文化特性。

在要求處理管線中的 MapRazorComponents 呼叫之前,放置下列程式碼:

var supportedCultures = new[] { "en-US", "es-CR" };
var localizationOptions = new RequestLocalizationOptions()
    .SetDefaultCulture(supportedCultures[0])
    .AddSupportedCultures(supportedCultures)
    .AddSupportedUICultures(supportedCultures);

app.UseRequestLocalization(localizationOptions);

下列範例展示如何在 cookie 中設定當地語系化中介軟體可以讀取的目前文化特性。

App 元件需要下列命名空間:

將下列內容新增至 App 元件檔案 (Components/App.razor) 的頂端:

@using System.Globalization
@using Microsoft.AspNetCore.Localization

應用程式用於用戶端轉譯的文化特性是使用 Blazor 架構的 API 來設定。 使用者的文化特性選取項目可以保存在 CSR 元件的瀏覽器本機儲存體中。

Blazor 的 <script> 標籤後面提供 JS 函式,以使用瀏覽器本機儲存體來取得和設定使用者的文化特性選取項目:

<script>
  window.blazorCulture = {
    get: () => window.localStorage['BlazorCulture'],
    set: (value) => window.localStorage['BlazorCulture'] = value
  };
</script>

注意

上述範例會使用全域函式敗壞用戶端。 如需更適合生產應用程式的方法,請參閱 JavaScript 模組中的 JavaScript 隔離

將下列 @code 區塊新增至 App 元件檔案底部:

@code {
    [CascadingParameter]
    public HttpContext? HttpContext { get; set; }

    protected override void OnInitialized()
    {
        HttpContext?.Response.Cookies.Append(
            CookieRequestCultureProvider.DefaultCookieName,
            CookieRequestCultureProvider.MakeCookieValue(
                new RequestCulture(
                    CultureInfo.CurrentCulture,
                    CultureInfo.CurrentUICulture)));
    }
}

如果伺服器專案未設定為處理控制器動作:

  • Program 檔案的服務集合上呼叫 AddControllers,以新增 MVC 服務:

    builder.Services.AddControllers();
    
  • Program 檔案中新增控制器端點路由,方法是在 IEndpointRouteBuilder (app) 上呼叫 MapControllers

    app.MapControllers();
    

若要允許使用者選取 CSR 元件的文化特性,請使用重新導向型方法搭配當地語系化 cookie。 應用程式會透過重新導向至控制器來保存使用者選取的文化特性。 控制器會將使用者選取的文化特性設定為 cookie,並將使用者重新導向回原始 URI。 此流程類似於當使用者嘗試存取安全資源時,Web 應用程式中發生的情況,其中使用者會重新導向至登入頁面,然後重新導向回原始資源。

Controllers/CultureController.cs

using Microsoft.AspNetCore.Localization;
using Microsoft.AspNetCore.Mvc;

[Route("[controller]/[action]")]
public class CultureController : Controller
{
    public IActionResult Set(string culture, string redirectUri)
    {
        if (culture != null)
        {
            HttpContext.Response.Cookies.Append(
                CookieRequestCultureProvider.DefaultCookieName,
                CookieRequestCultureProvider.MakeCookieValue(
                    new RequestCulture(culture, culture)));
        }

        return LocalRedirect(redirectUri);
    }
}

警告

使用 LocalRedirect 動作結果 (如上述範例所示),防止開放式重新導向攻擊。 如需詳細資訊,請參閱防止 ASP.NET Core 中的開放式重新導向攻擊

CultureSelector 元件新增至 MainLayout 元件。 將下列標記放在 Components/Layout/MainLayout.razor 檔案的結尾 </main> 標記內:

<article class="bottom-row px-4">
    <CultureSelector @rendermode="InteractiveAuto" />
</article>

使用示範元件一節中顯示的 CultureExample1 元件來研究上述範例的運作方式。

在伺服器專案中放置下列 CultureServer 元件,以研究全球化對 SSR 元件的作用。

Components/Pages/CultureServer.razor

@page "/culture-server"
@rendermode InteractiveServer
@using System.Globalization

<PageTitle>Culture Server</PageTitle>

<h1>Culture Server</h1>

<ul>
    <li><b>CurrentCulture</b>: @CultureInfo.CurrentCulture</li>
    <li><b>CurrentUICulture</b>: @CultureInfo.CurrentUICulture</li>
</ul>

<h2>Rendered values</h2>

<ul>
    <li><b>Date</b>: @dt</li>
    <li><b>Number</b>: @number.ToString("N2")</li>
</ul>

<h2><code>&lt;input&gt;</code> elements that don't set a <code>type</code></h2>

<p>
    The following <code>&lt;input&gt;</code> elements use
    <code>CultureInfo.CurrentCulture</code>.
</p>

<ul>
    <li><label><b>Date:</b> <input @bind="dt" /></label></li>
    <li><label><b>Number:</b> <input @bind="number" /></label></li>
</ul>

<h2><code>&lt;input&gt;</code> elements that set a <code>type</code></h2>

<p>
    The following <code>&lt;input&gt;</code> elements use
    <code>CultureInfo.InvariantCulture</code>.
</p>

<ul>
    <li><label><b>Date:</b> <input type="date" @bind="dt" /></label></li>
    <li><label><b>Number:</b> <input type="number" @bind="number" /></label></li>
</ul>

@code {
    private DateTime dt = DateTime.Now;
    private double number = 1999.69;
}

CultureClientCultureServer 元件都新增至 Components/Layout/NavMenu.razor 中的提要欄導覽:

<div class="nav-item px-3">
    <NavLink class="nav-link" href="culture-server">
        <span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Culture (Server)
    </NavLink>
</div>
<div class="nav-item px-3">
    <NavLink class="nav-link" href="culture-client">
        <span class="bi bi-list-nested-nav-menu" aria-hidden="true"></span> Culture (Client)
    </NavLink>
</div>

互動式自動元件

本節中的指引也適用於採用互動式自動轉譯模式的元件:

@rendermode InteractiveAuto

當地語系化

如果應用程式尚未支援動態文化特性選取項目,請將 Microsoft.Extensions.Localization 套件新增至應用程式。

注意

如需將套件新增至 .NET 應用程式的指引,請參閱在套件取用工作流程 (NuGet 文件)安裝及管理套件底下的文章。 在 NuGet.org 確認正確的套件版本。

用戶端當地語系化

在應用程式的專案檔 (.csproj) 中將 BlazorWebAssemblyLoadAllGlobalizationData 屬性設定為 true

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

Program 檔案中,將 System.Globalization 的命名空間新增至檔案頂端:

using System.Globalization;

使用 AddLocalization 將 Blazor 的當地語系化服務新增至應用程式的服務集合:

builder.Services.AddLocalization();

伺服器端當地語系化

使用當地語系化中介軟體來設定應用程式的文化特性。

如果應用程式尚未支援動態文化特性選取項目:

  • 使用 AddLocalization 將當地語系化服務新增至應用程式。
  • Program 檔案中指定應用程式的預設和受支援文化特性。 下列範例會設定美國英文和哥斯大黎加西班牙文支援的文化特性。
builder.Services.AddLocalization();

將要求當地語系化中間件放在任何可能檢查要求文化特性的中間件之前。 一般而言,請先將中間件放在呼叫 MapRazorComponents之前:

在路由中間件 (UseRouting) 新增至處理管線之後立即:

var supportedCultures = new[] { "en-US", "es-CR" };
var localizationOptions = new RequestLocalizationOptions()
    .SetDefaultCulture(supportedCultures[0])
    .AddSupportedCultures(supportedCultures)
    .AddSupportedUICultures(supportedCultures);

app.UseRequestLocalization(localizationOptions);

如需在中介軟體管線中排序當地語系化中介軟體的相關資訊,請參閱 ASP.NET Core 中介軟體

  • 使用 AddLocalization 將當地語系化服務新增至應用程式。
  • Startup.Configure (Startup.cs) 中指定應用程式的預設和受支援文化特性。 下列範例會設定美國英文和哥斯大黎加西班牙文支援的文化特性。

Startup.ConfigureServices (Startup.cs) 中:

services.AddLocalization();

在路由中間件 (UseRouting) 新增至處理管線之後的 中Startup.Configure

var supportedCultures = new[] { "en-US", "es-CR" };
var localizationOptions = new RequestLocalizationOptions()
    .SetDefaultCulture(supportedCultures[0])
    .AddSupportedCultures(supportedCultures)
    .AddSupportedUICultures(supportedCultures);

app.UseRequestLocalization(localizationOptions);

如需在 Startup.Configure 的中介軟體管線中排序當地語系化中介軟體的相關資訊,請參閱 ASP.NET Core 中介軟體

如果應用程式應該根據儲存使用者的文化特性設定,將資源當地語系化,請使用當地語系化文化特性 cookie。 使用 cookie 可確保 WebSocket 連線可以正確地傳播文化特性。 如果當地語系化配置是以 URL 路徑或查詢字串為基礎,則配置可能無法使用 WebSockets,從而無法保存文化特性。 因此,建議的方法是使用當地語系化文化特性 cookie。 請參閱本文的依使用者喜好設定動態設定伺服器端文化特性一節,以查看保存使用者文化特性選取項目的範例 Razor 運算式。

當地語系化資源的範例

本節中當地語系化資源的範例會使用本文中先前的範例,其中應用程式支援的文化特性是英文 (en) 作為預設地區設定,以及西班牙文 (es) 作為使用者可選取或瀏覽器指定的替代地區設定。

為每個地區設定建立資源檔。 在下列範例中,會為英文和西班牙文的 Greeting 字串建立資源:

  • 英文 (en):Hello, World!
  • 西班牙文 (es):¡Hola, Mundo!

注意

以滑鼠右鍵按一下 Pages,並選取 [新增]>[新增項目]>[資源檔案],即可在 Visual Studio 中新增下列資源檔。 將檔案命名為 CultureExample2.resx。 當編輯器出現時,請提供新項目的資料。 將 [名稱] 設定為 Greeting,並將 [值] 設定為 Hello, World!。 儲存檔案。

如果使用 Visual Studio Code,建議您安裝 Tim Heuer 的 ResX 檢視器和編輯器。 將空的 CultureExample2.resx 檔案新增至 Pages 資料夾。 延伸模組會自動接管在 UI 中管理檔案的工作。 選取 [新增資源] 按鈕。 請依照指示新增 Greeting (索引鍵)、Hello, World! (值) 和 None (註解) 的項目。 儲存檔案。 如果您將檔案關閉並重新開啟,就可以看到 Greeting 資源。

Tim Heuer 的 ResX 檢視器和編輯器並非由 Microsoft 擁有或維護,且並未涵蓋於任何 Microsoft 支援服務合約或授權內。

以下示範一般資源檔。 如果您不想使用整合式開發環境 (IDE) 的內建工具 (例如,Visual Studio 的內建資源檔編輯器,或有延伸模組可建立和編輯資源檔的 Visual Studio Code),您可以手動將資源檔放入應用程式的 Pages 資料夾中。

Pages/CultureExample2.resx

<?xml version="1.0" encoding="utf-8"?>
<root>
  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
    <xsd:element name="root" msdata:IsDataSet="true">
      <xsd:complexType>
        <xsd:choice maxOccurs="unbounded">
          <xsd:element name="metadata">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" />
              </xsd:sequence>
              <xsd:attribute name="name" use="required" type="xsd:string" />
              <xsd:attribute name="type" type="xsd:string" />
              <xsd:attribute name="mimetype" type="xsd:string" />
              <xsd:attribute ref="xml:space" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="assembly">
            <xsd:complexType>
              <xsd:attribute name="alias" type="xsd:string" />
              <xsd:attribute name="name" type="xsd:string" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="data">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
              <xsd:attribute ref="xml:space" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="resheader">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" use="required" />
            </xsd:complexType>
          </xsd:element>
        </xsd:choice>
      </xsd:complexType>
    </xsd:element>
  </xsd:schema>
  <resheader name="resmimetype">
    <value>text/microsoft-resx</value>
  </resheader>
  <resheader name="version">
    <value>2.0</value>
  </resheader>
  <resheader name="reader">
    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
  <resheader name="writer">
    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
  <data name="Greeting" xml:space="preserve">
    <value>Hello, World!</value>
  </data>
</root>

注意

以滑鼠右鍵按一下 Pages,並選取 [新增]>[新增項目]>[資源檔案],即可在 Visual Studio 中新增下列資源檔。 將檔案命名為 CultureExample2.es.resx。 當編輯器出現時,請提供新項目的資料。 將 [名稱] 設定為 Greeting,並將 [值] 設定為 ¡Hola, Mundo!。 儲存檔案。

如果使用 Visual Studio Code,建議您安裝 Tim Heuer 的 ResX 檢視器和編輯器。 將空的 CultureExample2.resx 檔案新增至 Pages 資料夾。 延伸模組會自動接管在 UI 中管理檔案的工作。 選取 [新增資源] 按鈕。 請依照指示新增 Greeting (索引鍵)、¡Hola, Mundo! (值) 和 None (註解) 的項目。 儲存檔案。 如果您將檔案關閉並重新開啟,就可以看到 Greeting 資源。

以下示範一般資源檔。 如果您不想使用整合式開發環境 (IDE) 的內建工具 (例如,Visual Studio 的內建資源檔編輯器,或有延伸模組可建立和編輯資源檔的 Visual Studio Code),您可以手動將資源檔放入應用程式的 Pages 資料夾中。

Pages/CultureExample2.es.resx

<?xml version="1.0" encoding="utf-8"?>
<root>
  <xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
    <xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
    <xsd:element name="root" msdata:IsDataSet="true">
      <xsd:complexType>
        <xsd:choice maxOccurs="unbounded">
          <xsd:element name="metadata">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" />
              </xsd:sequence>
              <xsd:attribute name="name" use="required" type="xsd:string" />
              <xsd:attribute name="type" type="xsd:string" />
              <xsd:attribute name="mimetype" type="xsd:string" />
              <xsd:attribute ref="xml:space" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="assembly">
            <xsd:complexType>
              <xsd:attribute name="alias" type="xsd:string" />
              <xsd:attribute name="name" type="xsd:string" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="data">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
                <xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
              <xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
              <xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
              <xsd:attribute ref="xml:space" />
            </xsd:complexType>
          </xsd:element>
          <xsd:element name="resheader">
            <xsd:complexType>
              <xsd:sequence>
                <xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
              </xsd:sequence>
              <xsd:attribute name="name" type="xsd:string" use="required" />
            </xsd:complexType>
          </xsd:element>
        </xsd:choice>
      </xsd:complexType>
    </xsd:element>
  </xsd:schema>
  <resheader name="resmimetype">
    <value>text/microsoft-resx</value>
  </resheader>
  <resheader name="version">
    <value>2.0</value>
  </resheader>
  <resheader name="reader">
    <value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
  <resheader name="writer">
    <value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
  </resheader>
  <data name="Greeting" xml:space="preserve">
    <value>¡Hola, Mundo!</value>
  </data>
</root>

下列元件示範如何使用當地語系化的 Greeting 字串搭配 IStringLocalizer<T>。 下列範例中的 Razor 標記 @Loc["Greeting"] 會將鍵入的字串當地語系化為 Greeting 值,其是在上述資源檔案中設定的。

Microsoft.Extensions.Localization 的命名空間新增至應用程式的 _Imports.razor 檔案:

@using Microsoft.Extensions.Localization

CultureExample2.razor

@page "/culture-example-2"
@using System.Globalization
@inject IStringLocalizer<CultureExample2> Loc

<h1>Culture Example 2</h1>

<ul>
    <li><b>CurrentCulture</b>: @CultureInfo.CurrentCulture</li>
    <li><b>CurrentUICulture</b>: @CultureInfo.CurrentUICulture</li>
</ul>

<h2>Greeting</h2>

<p>
    @Loc["Greeting"]
</p>

<p>
    @greeting
</p>

@code {
    private string? greeting;

    protected override void OnInitialized()
    {
        greeting = Loc["Greeting"];
    }
}

或者,將 CultureExample2 元件的功能表項目新增至元件 NavMenu (NavMenu.razor) 中的導覽。

WebAssembly 文化特性提供者參考來源

若要進一步了解 Blazor 架構如何處理當地語系化,請參閱 ASP.NET Core 參考來源中的 WebAssemblyCultureProvider 類別

注意

.NET 參考來源的文件連結通常會載入存放庫的預設分支,這表示下一版 .NET 的目前開發。 若要選取特定版本的標籤,請使用 [切換分支或標籤] 下拉式清單。 如需詳細資訊,請參閱如何選取 ASP.NET Core 原始程式碼 (dotnet/AspNetCore.Docs #26205) 的版本標籤

共用的資源

若要建立當地語系化共用資源,請採用下列方法。

  • 使用任意類別名稱建立虛擬類別。 在以下範例中:

    • 應用程式會使用 BlazorSample 命名空間,而當地語系化資產則會使用 BlazorSample.Localization 命名空間。
    • 虛擬類別名為 SharedResource
    • 類別檔案放在應用程式根目錄的 Localization 資料夾中。

    Localization/SharedResource.cs

    namespace BlazorSample.Localization;
    
    public class SharedResource
    {
    }
    
  • 使用 Embedded resource建置動作建立共用資源檔。 在以下範例中:

    • 檔案放在具有虛擬 SharedResource 類別 (Localization/SharedResource.cs) 的 Localization 資料夾中。

    • 命名資源檔以符合虛擬類別的名稱。 下列範例檔案包含預設當地語系化檔案,以及西班牙文 (es) 當地語系化的檔案。

    • Localization/SharedResource.resx

    • Localization/SharedResource.es.resx

    警告

    遵循本節中的方法時,您無法同時設定 LocalizationOptions.ResourcesPath 並使用 IStringLocalizerFactory.Create 來載入資源。

  • 若要參考 Razor 元件中所插入 IStringLocalizer<T> 的虛擬類別,請為當地語系化命名空間放置 @using 指示詞,或在虛擬類別參考中包含當地語系化命名空間。 在下列範例中:

    • 第一個範例會使用 @using 指示詞,說明 SharedResource 虛擬類別的 Localization 命名空間。
    • 第二個範例會明確地說明 SharedResource 虛擬類別的命名空間。

    在 Razor 元件中,請使用下列任一種方法:

    @using Localization
    @inject IStringLocalizer<SharedResource> Loc
    
    @inject IStringLocalizer<Localization.SharedResource> Loc
    

如需其他指引,請參閱 ASP.NET Core 中的全球化和當地語系化

開發人員工具中使用 [感應器] 窗格的位置覆寫

透過 Google Chrome 或 Microsoft Edge 開發人員工具中的 [感應器] 窗格使用位置覆寫時,會在預先呈現之後重設後援語言。 避免在測試時使用 [感應器] 窗格來設定語言。 使用瀏覽器的語言設定來設定語言。

如需詳細資訊,請參閱 Blazor 當地語系化不適用於 InteractiveServer (dotnet/aspnetcore #53707)

其他資源