Глобализация и локализация в ASP.NET Core Blazor

Примечание.

Это не последняя версия этой статьи. В текущем выпуске см . версию .NET 8 этой статьи.

Предупреждение

Эта версия ASP.NET Core больше не поддерживается. Дополнительные сведения см. в статье о политике поддержки .NET и .NET Core. В текущем выпуске см . версию .NET 8 этой статьи.

Внимание

Эта информация относится к предварительному выпуску продукта, который может быть существенно изменен до его коммерческого выпуска. Майкрософт не предоставляет никаких гарантий, явных или подразумеваемых, относительно приведенных здесь сведений.

В текущем выпуске см . версию .NET 8 этой статьи.

В этой статье вы узнаете, как визуализировать глобализованное и локализованное содержимое для пользователей на разных языках с разными региональными параметрами.

Глобализация и локализация

Для глобализации Blazor предоставляет форматирование чисел и дат. Для локализации Blazor отображает содержимое с помощью системы ресурсов .NET.

Поддерживается ограниченный набор функций локализации ASP.NET Core:

и IStringLocalizer<T> поддерживается в Blazor приложениях.

Не поддерживается: IHtmlLocalizerи IViewLocalizerлокализация примечаний к данным ASP.NET функции Core MVC и не поддерживаются в Blazor приложениях.

В этой статье описывается, как использовать функции глобализации и локализации Blazor на основе следующих элементов:

  • заголовка Accept-Language, который задается браузером на основе языковых настроек пользователя в параметрах браузера;
  • языка и региональных параметров, заданных приложением, которые не основаны на значении заголовка Accept-Language. Параметр может быть статическим для всех пользователей или динамическим в зависимости от логики приложения. Если параметр основан на предпочтениях пользователя, он обычно сохраняется для повторной загрузки при последующих посещениях.

Дополнительные общие сведения см. в следующих ресурсах:

Часто термины язык и язык и региональные параметры взаимозаменяемы, когда речь идет о концепциях глобализации и локализации.

В этой статье язык относится к выбору, сделанному пользователем в параметрах браузера. Выбранные пользователем языки отправляются в запросах браузера в заголовке Accept-Language. В параметрах пользовательского интерфейса браузера обычно используется слово "язык".

Язык и региональные параметры относится к элементам .NET и API Blazor. Например, запрос пользователя может содержать заголовок Accept-Language с указанием языка с точки зрения пользователя, но в конечном итоге приложение устанавливает свойство CurrentCulture (язык и региональные параметры) для языка, запрашиваемого пользователем. В названиях элементов API обычно используется термин "язык и региональные параметры".

Руководство в этой статье не охватывает настройку атрибута языка HTML страницы (<html lang="...">), который использует средства доступа. Значение можно задать статически, назначив язык lang атрибуту тега <html> или document.documentElement.lang в JavaScript. Вы можете динамически задать значение document.documentElement.lang взаимодействияJS.

Примечание.

Примеры кода в этой статье используют типы ссылок, допускающие значение NULL (NRTs) и статический анализ состояния .NET компилятора NULL, которые поддерживаются в ASP.NET Core в .NET 6 или более поздней версии. При назначении 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 предоставляет встроенную поддержку отображения значений в текущем языке и региональных параметрах. Поэтому при @bind:culture использовании типов полей и региональных параметров не рекомендуется указывать язык и number региональные date параметры.

Следующие типы полей имеют определенные требования к форматированию и не поддерживаются всеми основными браузерами, поэтому они не поддерживаются:Blazor

  • datetime-local
  • month
  • week

Сведения о поддержке предыдущих типов в браузере см. на этой странице.

Глобализация .NET и международные компоненты для поддержки Юникода (ICU) (Blazor WebAssembly)

Blazor WebAssembly использует сокращенный API глобализации и набор встроенных международных компонентов для языковых стандартов Юникода (ICU). Дополнительные сведения см. в разделе глобализации .NET и ICU: ICU в WebAssembly.

Чтобы загрузить пользовательский файл данных ICU для управления языковыми стандартами приложения, см. раздел Icu глобализации WASM. В настоящее время требуется создание пользовательского файла данных ICU вручную. Средства .NET для упрощения процесса создания файла планируется в .NET 9 в ноябре 2024 года.

Blazor WebAssembly использует сокращенный API глобализации и набор встроенных международных компонентов для языковых стандартов Юникода (ICU). Дополнительные сведения см. в разделе глобализации .NET и ICU: ICU в WebAssembly.

Загрузка настраиваемого Blazor WebAssembly подмножества языковых стандартов в приложении поддерживается в .NET 8 или более поздней версии. Дополнительные сведения см. в этом разделе для версии 8.0 или более поздней версии этой статьи.

Инвариантная глобализация

Этот раздел относится только к сценариям на стороне Blazor клиента.

Если приложению не требуется локализация, можно настроить поддержку инвариантных языка и региональных параметров, зачастую основанных на английском языке (США) (en-US). Использование инвариантной глобализации сокращает размер загрузки приложения и приводит к более быстрому запуску приложения. Задайте для свойства InvariantGlobalization значение true в файле проекта приложения (.csproj):

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

Кроме того, инвариантную глобализацию можно настроить с помощью следующих подходов.

  • В runtimeconfig.json:

    {
      "runtimeOptions": {
        "configProperties": {
          "System.Globalization.Invariant": true
        }
      }
    }
    
  • С переменной среды:

    • Ключ: DOTNET_SYSTEM_GLOBALIZATION_INVARIANT.
    • Значение: true или 1

Дополнительные сведения см. в статье Параметры конфигурации времени выполнения для глобализации.

Сведения о часовом поясе

Этот раздел относится только к сценариям на стороне Blazor клиента.

Внедрение инвариантной глобализации приводит только к использованию не локализованных имен часовых поясов. Чтобы обрезать код часового пояса и данные, что сокращает размер загрузки приложения и приводит к более быстрому запуску приложения, примените <InvariantTimezone> свойство MSBuild со значением true в файле проекта приложения:

<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;
}

Числовой формат строки (N2) в предыдущем примере (.ToString("N2")) является стандартным описателем числового формата .NET. Формат N2 поддерживается для всех числовых типов, содержит разделитель групп и преобразовывает для просмотра до двух десятичных разрядов.

При необходимости добавьте элемент меню в навигацию в NavMenu компоненте (NavMenu.razor) для CultureExample1 компонента.

Динамическое задание языка и региональных параметров из заголовка Accept-Language

Добавьте пакет Microsoft.Extensions.Localization в приложение.

ЗаголовокAccept-Language задается браузером и управляется на основе языковых настроек пользователя в параметрах браузера. В параметрах браузера пользователь задает один или несколько необходимых языков в порядке предпочтения. Порядок предпочтения используется браузером для задания значений качества (q, 0–1) для каждого языка в заголовке. В следующем примере указывается США английский, английский и костариканский испанский с предпочтениями США английский или английский:

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

Язык и региональные параметры приложения задаются путем сопоставления первого запрошенного языка, который соответствует поддерживаемому языку и региональным параметрам приложения.

В клиентской разработке задайте BlazorWebAssemblyLoadAllGlobalizationData свойство true в файле проекта клиентского приложения (.csproj):

<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) в языковых параметрах браузера. Снова запросите веб-страницу.

Примечание.

В некоторых браузерах принудительно используются настройки языка по умолчанию как для запросов, так и для собственных параметров пользовательского интерфейса в браузере. Это может затруднить смену языка на тот, который вы понимаете, поскольку все экраны пользовательского интерфейса настроек могут оказаться на языке, который вы не можете прочитать. Браузер, такой как Opera, хорошо подходит для тестирования, так как он позволяет задать язык по умолчанию для запросов веб-страниц, но оставить пользовательский интерфейс параметров браузера на вашем языке.

Если для языка и региональных параметров выбран английский язык (США) (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

Статически задать язык и региональные параметры на стороне клиента

Задайте для свойства BlazorWebAssemblyLoadAllGlobalizationData значение true в файле проекта приложения (.csproj):

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

Конфигурация компоновщика промежуточного языка (IL) для отрисовки на стороне клиента удаляет сведения о интернационализации, за исключением явно запрошенных языковых стандартов. Дополнительные сведения см. в статье Настройка компоновщика для ASP.NET Core Blazor.

Язык и региональные параметры приложения можно задать в JavaScript, если Blazor начинается с параметра запуска applicationCulture Blazor. В следующем примере приложение настраивается для запуска с использованием языка и региональных параметров: английский язык (США) (en-US).

Запретить Blazor автозапуск, добавивBlazor<script> autostart="false" в тег:

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

В предыдущем примере {BLAZOR SCRIPT} заполнитель — это путь к скрипту Blazor и имя файла. Сведения о расположении скрипта см. в разделе ASP.NET Структура проекта CoreBlazor.

Добавьте следующий <script> блок после Blazorтега <script> и перед закрывающим </body> тегом:

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#. Задайте CultureInfo.DefaultThreadCurrentCulture и в файле один и CultureInfo.DefaultThreadCurrentUICulture тот же язык и региональные Program параметры.

Добавьте пространство имен в 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 только на основе текущего языка и региональных параметров (текущий язык и региональные параметры пользовательского интерфейса не учитывается) (dotnet/aspnetcore #56824).

Используйте компонент CultureExample1, показанный в разделе Демонстрационный компонент, чтобы изучить принцип работы глобализации. Выполните запрос на английском языке (США) (en-US). Перейдите на Коста-Риканский испанский (es-CR) в языковых параметрах браузера. Снова запросите веб-страницу. Если запрошенный язык является коста-риканским испанским, язык и региональные параметры приложения остаются США английский (en-US).

Статически задать язык и региональные параметры на стороне сервера

Серверные приложения локализованы с помощью ПО промежуточного слоя локализации. Добавьте службы локализации в приложение с помощью AddLocalization.

В файле Program:

builder.Services.AddLocalization();

Укажите статический язык и региональные параметры в Program файле перед любым ПО промежуточного слоя, которое может проверить язык и региональные параметры запроса. Как правило, поместите ПО промежуточного слоя локализации запросов непосредственно перед MapRazorComponents. В следующем примере настраивается английский язык (США):

Укажите статический Program язык и региональные параметры в файле сразу после добавления по промежуточного слоя маршрутизации вUseRouting конвейер обработки. В следующем примере настраивается английский язык (США):

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 см. в разделе Порядок ПО промежуточного слоя.

Используйте компонент CultureExample1, показанный в разделе Демонстрационный компонент, чтобы изучить принцип работы глобализации. Выполните запрос на английском языке (США) (en-US). Перейдите на Коста-Риканский испанский (es-CR) в языковых параметрах браузера. Снова запросите веб-страницу. Если запрошенный язык является коста-риканским испанским, язык и региональные параметры приложения остаются США английский (en-US).

Динамически задать язык и региональные параметры на стороне клиента по предпочтениям пользователя

Примеры расположений, в которых приложение может хранить предпочтения пользователя в локальном хранилище браузера (обычно для клиентских сценариев), локализации cookie или базы данных (обычно для сценариев на стороне сервера) или во внешней службе, подключенной к внешней базе данных и доступу к веб-API. В следующем примере показано использование локального хранилища в браузере.

Добавьте пакет Microsoft.Extensions.Localization в приложение.

Примечание.

Рекомендации по добавлению пакетов в приложения .NET см. в разделе Способы установки пакетов NuGet в статье Рабочий процесс использования пакета (документация по NuGet). Проверьте правильность версий пакета на сайте NuGet.org.

Задайте для свойства BlazorWebAssemblyLoadAllGlobalizationData значение true в файле проекта:

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

Язык и региональные параметры приложения для отрисовки на стороне клиента задаются с помощью Blazor API платформы. Выбор языка и региональных параметров пользователя можно сохранить в локальном хранилище браузера.

Предоставьте JS функции после Blazorтега<script>, чтобы получить и задать выбор языка и региональных параметров пользователя с локальным хранилищем браузера:

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

Примечание.

В предыдущем примере клиент загрязняет глобальные функции. Более эффективный подход для приложений в рабочей среде приведен в разделе Изоляция JavaScript в модулях JavaScript.

Добавьте пространства имен для System.Globalization и Microsoft.JSInterop в начало Program файла:

using System.Globalization;
using Microsoft.JSInterop;

Удалите следующую строку:

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

Замените указанную выше строку следующим кодом. Код добавляет службу локализации Blazor в коллекцию служб приложения с помощью AddLocalization и использует взаимодействие с JS для вызова 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 только на основе текущего языка и региональных параметров (текущий язык и региональные параметры пользовательского интерфейса не учитывается) (dotnet/aspnetcore #56824).

В следующем компоненте CultureSelector показано, как выполнять следующие действия.

  • Настройка выбора языка и региональных параметров пользователя в локальном хранилище браузера с помощью взаимодействия с JS.
  • Перезагрузка запрошенного компонента (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);
        }
    }
}

Примечание.

Дополнительные сведения о IJSInProcessRuntime см. в статье Вызов функций JavaScript из методов .NET в ASP.NET Core Blazor.

В закрывающий тег </main> элемента компонента MainLayout (MainLayout.razor) добавьте CultureSelector этот компонент:

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

Используйте компонент CultureExample1, показанный в разделе Демонстрационный компонент, чтобы изучить принцип работы предыдущих примеров.

Динамически задать язык и региональные параметры на стороне сервера по предпочтениям пользователя

Примеры расположений, в которых приложение может хранить предпочтения пользователя в локальном хранилище браузера (обычно для клиентских сценариев), локализации cookie или базы данных (обычно для сценариев на стороне сервера) или во внешней службе, подключенной к внешней базе данных и доступу к веб-API. В следующем примере демонстрируется использование локализации cookie.

Примечание.

В следующем примере предполагается, что приложение принимает глобальное взаимодействие, указывая интерактивную отрисовку на стороне сервера (интерактивный SSR) для Routes компонента в App компоненте (Components/App.razor):

<Routes @rendermode="InteractiveServer" />

Если приложение принимает интерактивность на страницу или компонент , ознакомьтесь с замечаниями в конце этого раздела, чтобы изменить режимы отрисовки компонентов примера.

Добавьте пакет Microsoft.Extensions.Localization в приложение.

Примечание.

Рекомендации по добавлению пакетов в приложения .NET см. в разделе Способы установки пакетов NuGet в статье Рабочий процесс использования пакета (документация по 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 Middleware.

В следующем примере показано, как задать текущий язык и региональные параметры в файле 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 Middleware.

Если приложение не настроено для обработки действий контроллера:

  • Добавьте службы MVC, вызвав AddControllers коллекцию служб в Program файле:

    builder.Services.AddControllers();
    
  • Добавьте маршрутизацию конечных точек контроллера в Program файл, вызвав MapControllers IEndpointRouteBuilderapp():

    app.MapControllers();
    

Чтобы предоставить пользовательский интерфейс, позволяющий пользователю выбрать язык и региональные параметры, рекомендуется подход на основе перенаправления при локализации cookie. Приложение сохраняет выбранный язык и региональные параметры пользователя с помощью перенаправления к контроллеру. Контроллер устанавливает выбранный язык и региональные параметры пользователя в файл cookie и перенаправляет пользователя обратно в исходный URI. Процесс аналогичен тому, что происходит в веб-приложении, когда пользователь пытается получить доступ к защищенному ресурсу, где пользователь перенаправляется на страницу входа, а затем обратно к исходному ресурсу.

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 показано, как вызвать метод Set для CultureController с новым языком и региональными параметрами. Компонент помещается в папку 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 компонент. Поместите следующую разметку внутри закрывающего </main> тега Components/Layout/MainLayout.razor в файле:

CultureSelector Добавьте компонент в MainLayout компонент. Поместите следующую разметку внутри закрывающего </main> тега Shared/MainLayout.razor в файле:

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

Используйте компонент CultureExample1, показанный в разделе Демонстрационный компонент, чтобы изучить принцип работы предыдущих примеров.

В предыдущем примере предполагается, что приложение принимает глобальное взаимодействие, указывая режим отрисовки интерактивного сервера на Routes компоненте App (Components/App.razor):

<Routes @rendermode="InteractiveServer" />

Если приложение принимает интерактивность на страницу или компонент , внесите следующие изменения:

  • Добавьте режим отрисовки интерактивного CultureExample1 сервера в верхней части файла компонента (Components/Pages/CultureExample1.razor):

    @rendermode InteractiveServer
    
  • В основном макете приложения (Components/Layout/MainLayout.razor) примените режим отрисовки интерактивного сервера к компоненту CultureSelector :

    <CultureSelector @rendermode="InteractiveServer" />
    

Динамически задать язык и региональные Blazor Web App параметры в предпочтениях пользователя

Этот раздел относится к Blazor Web Apps, которые применяют интерактивность auto (Server и WebAssembly).

Примеры расположений, в которых приложение может хранить предпочтения пользователя в локальном хранилище браузера (обычно для клиентских сценариев), в локализации cookie или базе данных (обычно для сценариев на стороне сервера), локальном хранилище и локализации cookie (Blazor Web Appс компонентами сервера и WebAssembly) или во внешней службе, подключенной к внешней базе данных и доступу к веб-API. В следующем примере показано, как использовать локальное хранилище браузера для клиентских компонентов отрисовки (CSR) и локализацию cookie для компонентов, отрисованных на стороне сервера (SSR).

.Client Обновления проекта

Microsoft.Extensions.Localization Добавьте пакет в .Client проект.

Примечание.

Рекомендации по добавлению пакетов в приложения .NET см. в разделе Способы установки пакетов NuGet в статье Рабочий процесс использования пакета (документация по NuGet). Проверьте правильность версий пакета на сайте NuGet.org.

BlazorWebAssemblyLoadAllGlobalizationData Задайте для свойства true в .Client файле проекта:

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

Добавьте пространства имен для System.Globalization и в начало .Client файла проекта Program Microsoft.JSInterop:

using System.Globalization;
using Microsoft.JSInterop;

Удалите следующую строку:

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

Замените указанную выше строку следующим кодом. Код добавляет службу локализации Blazor в коллекцию служб приложения с помощью AddLocalization и использует взаимодействие с JS для вызова 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 только на основе текущего языка и региональных параметров (текущий язык и региональные параметры пользовательского интерфейса не учитывается) (dotnet/aspnetcore #56824).

Добавьте следующий CultureSelector компонент в .Client проект.

Компонент применяет следующие подходы для работы с компонентами SSR или CSR:

  • Отображаемое имя каждого доступного языка и региональных параметров в раскрывающемся списке предоставляется словарем, так как данные глобализации на стороне клиента включают локализованный текст отображаемых имен языка и региональных параметров, предоставляемых данными глобализации на стороне сервера. Например, локализация на стороне сервера отображается English (United States) при en-US использовании языка и региональных параметров.Ingles () Так как локализация отображаемых имен языка и региональных параметров недоступна с Blazor WebAssembly глобализацией, отображаемое имя для США английского языка на клиенте для любого загруженного языка и региональных параметров простоen-US. Использование пользовательского словаря позволяет компоненту по крайней мере отображать полные имена языков и региональных параметров английского языка.
  • При изменении языка и региональных параметров взаимодействие задает язык и JS региональные параметры в локальном хранилище браузера, а действие контроллера обновляет локализацию 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);
        }
    }
}

Примечание.

Дополнительные сведения о IJSInProcessRuntime см. в статье Вызов функций JavaScript из методов .NET в ASP.NET Core Blazor.

.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). Проверьте правильность версий пакета на сайте 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)));
    }
}

Если серверный проект не настроен для обработки действий контроллера:

  • Добавьте службы MVC, вызвав AddControllers коллекцию служб в Program файле:

    builder.Services.AddControllers();
    
  • Добавьте маршрутизацию конечных точек контроллера в Program файл, вызвав MapControllers IEndpointRouteBuilderapp():

    app.MapControllers();
    

Чтобы разрешить пользователю выбирать язык и региональные параметры для компонентов SSR, используйте подход на основе перенаправления с локализацией cookie. Приложение сохраняет выбранный язык и региональные параметры пользователя с помощью перенаправления к контроллеру. Контроллер устанавливает выбранный язык и региональные параметры пользователя в файл cookie и перенаправляет пользователя обратно в исходный URI. Процесс аналогичен тому, что происходит в веб-приложении, когда пользователь пытается получить доступ к защищенному ресурсу, где пользователь перенаправляется на страницу входа, а затем обратно к исходному ресурсу.

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 компонент. Поместите следующую разметку внутри закрывающего </main> тега Components/Layout/MainLayout.razor в файле:

<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;
}

Добавьте оба CultureClient CultureServer компонента в навигацию на боковой панели: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). Проверьте правильность версий пакета на сайте NuGet.org.

Локализация на стороне клиента

Задайте для свойства BlazorWebAssemblyLoadAllGlobalizationData значение true в файле проекта приложения (.csproj):

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

Program В файле добавьте пространство System.Globalization имен в начало файла:

using System.Globalization;

Добавьте Blazorслужбу локализации в коллекцию служб приложения с помощью AddLocalization:

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 Middleware.

  • Добавьте службы локализации в приложение с помощью AddLocalization.
  • Задайте для приложения стандартные и поддерживаемые языки и региональные параметры в Startup.Configure (Startup.cs). В следующем примере настраивается поддерживаемые языкы и региональные параметры для США английского и костариканского испанского языка.

В Startup.ConfigureServices (Startup.cs):

services.AddLocalization();

Сразу Startup.Configure после добавления по промежуточного слоя маршрутизации вUseRouting конвейер обработки:

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

app.UseRequestLocalization(localizationOptions);

Сведения об упорядочении ПО промежуточного слоя для локализации в конвейере ПО промежуточного слоя Startup.Configure см. в разделе Порядок ПО промежуточного слоя.

Если приложение должно локализовать ресурсы на основе сохраненных параметров языка и региональных параметров пользователя, используйте язык и региональные параметры локализации cookie. Использование файла cookie гарантирует, что соединение WebSocket сможет правильно распространить языковые и региональные параметры. Если схема локализации основана на URL-адресе или строке запроса, она может не поддерживать работу с WebSockets и не сможет сохранить язык и региональные параметры. Поэтому рекомендуемым подходом для локализации является использование файла cookie языка и региональных параметров. Сведения о динамическом настройке языка и региональных параметров на стороне сервера см. в разделе предпочтения пользователя, чтобы просмотреть пример Razor выражения, сохраняющего выбор языка и региональных параметров пользователя.

Пример локализованных ресурсов

Пример локализованных ресурсов в этом разделе работает с более ранними примерами в этой статье, где поддерживаемые языки и региональные параметры приложения — английский язык (en) в качестве языкового стандарта по умолчанию и испанский язык (es) в качестве альтернативного языкового стандарта, выбираемого пользователем или браузером.

Создайте файл ресурса для каждого языкового стандарта. В следующем примере ресурсы создаются для Greeting строки на английском и испанском языках:

  • Английский (en): Hello, World!
  • Испанский (es): ¡Hola, Mundo!

Примечание.

Следующий файл ресурсов можно добавить в Visual Studio, щелкнув Pages правой кнопкой мыши папку и выбрав команду Добавить>файл ресурсов нового элемента.> Назовите файл CultureExample2.resx. Когда откроется редактор, укажите данные для новой записи. Задайте Greeting для свойства имени и Hello, World! для значения. Сохраните файл.

При использовании Visual Studio Code рекомендуется установить средство просмотра resX и редактора Тима Хауэра. Добавьте пустой CultureExample2.resx файл в папку Pages . Расширение автоматически берет на себя управление файлом в пользовательском интерфейсе. Нажмите кнопку "Добавить новый ресурс ". Следуйте инструкциям, чтобы добавить запись ( Greeting ключ), Hello, World! (значение) и None (комментарий). Сохраните файл. При закрытии и повторном открытии файла вы увидите Greeting ресурс.

Средство просмотра ResX и редактора ResX Тима Хауэра не принадлежит корпорации Майкрософт и не распространяется ни на служба поддержки Майкрософт соглашение или лицензию.

Ниже показан типичный файл ресурсов. Вы можете вручную поместить файлы ресурсов в папку приложения Pages , если вы предпочитаете не использовать встроенные средства с интегрированной средой разработки (IDE), например встроенным редактором файлов ресурсов Visual Studio или Visual Studio Code с расширением для создания и редактирования файлов ресурсов.

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>

Примечание.

Следующий файл ресурсов можно добавить в Visual Studio, щелкнув Pages правой кнопкой мыши папку и выбрав команду Добавить>файл ресурсов нового элемента.> Назовите файл CultureExample2.es.resx. Когда откроется редактор, укажите данные для новой записи. Задайте Greeting для свойства имени и ¡Hola, Mundo! для значения. Сохраните файл.

При использовании Visual Studio Code рекомендуется установить средство просмотра resX и редактора Тима Хауэра. Добавьте пустой CultureExample2.resx файл в папку Pages . Расширение автоматически берет на себя управление файлом в пользовательском интерфейсе. Нажмите кнопку "Добавить новый ресурс ". Следуйте инструкциям, чтобы добавить запись ( Greeting ключ), ¡Hola, Mundo! (значение) и None (комментарий). Сохраните файл. При закрытии и повторном открытии файла вы увидите Greeting ресурс.

Ниже показан типичный файл ресурсов. Вы можете вручную поместить файлы ресурсов в папку приложения Pages , если вы предпочитаете не использовать встроенные средства с интегрированной средой разработки (IDE), например встроенным редактором файлов ресурсов Visual Studio или Visual Studio Code с расширением для создания и редактирования файлов ресурсов.

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 обрабатывает локализацию, см. в описании WebAssemblyCultureProviderкласса в справочных данных по ASP.NET Core.

Примечание.

По ссылкам в документации на справочные материалы по .NET обычно загружается ветвь репозитория по умолчанию, которая представляет текущую разработку для следующего выпуска .NET. Чтобы выбрать тег для определенного выпуска, используйте раскрывающийся список Switch branches or tags (Переключение ветвей или тегов). Дополнительные сведения см. в статье Выбор тега версии исходного кода ASP.NET Core (dotnet/AspNetCore.Docs #26205).

Общие ресурсы

Чтобы создать общие ресурсы локализации, выполните следующий подход.

  • Создайте фиктивный класс с произвольным именем класса. В следующем примере :

    • Приложение использует пространство имен, а ресурсы локализации используют BlazorSample BlazorSample.Localization пространство имен.
    • Фиктивный класс называется SharedResource.
    • Файл класса помещается в Localization папку в корне приложения.

    Localization/SharedResource.cs:

    namespace BlazorSample.Localization;
    
    public class SharedResource
    {
    }
    
  • Создайте общие файлы ресурсов с действием сборкиEmbedded resource. В следующем примере :

    • Файлы помещаются в папку Localization с фиктивным SharedResource классом (Localization/SharedResource.cs).

    • Присвойте файлам ресурсов имя фиктивного класса. В приведенных ниже примерах файлов приведен файл локализации по умолчанию и файл для локализации испанского языка .es>.

    • Localization/SharedResource.resx

    • Localization/SharedResource.es.resx

    Предупреждение

    При выполнении подхода в этом разделе невозможно одновременно задать LocalizationOptions.ResourcesPath и использовать IStringLocalizerFactory.Create для загрузки ресурсов.

  • Чтобы ссылаться на фиктивный класс для внедренного IStringLocalizer<T> компонента Razor , можно поместить @using директиву для пространства имен локализации или включить пространство имен локализации в ссылку на фиктивный класс. В примерах ниже сделайте следующее:

    • В первом примере указывается Localization пространство имен для SharedResource фиктивного класса с директивой @using .
    • Второй пример указывает явное 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).

Дополнительные ресурсы