Поделиться через


Локализация строк в пользовательском интерфейсе и манифесте пакета приложения

Дополнительные сведения о ценности локализации приложения SDK для Приложений Windows см. в статье "Глобализация и локализация".

Если вы хотите, чтобы ваше приложение поддерживало разные языки интерфейса, а в вашем коде или разметке XAML либо манифесте пакета приложения есть строковые литералы, переместите эти строки из кода или разметки в файл ресурсов (RESW-файл). Затем можно создать переведенную копию этого файла ресурсов для каждого языка, поддерживаемого вашим приложением.

Жестко закодированные строковые литералы могут отображаться в императивном коде или в разметке XAML, например в качестве свойства Text элемента TextBlock. Они также могут отображаться в исходном файле манифеста пакета приложения ( Package.appxmanifest файл), например в качестве значения отображаемого имени на вкладке "Приложение" конструктора манифестов Visual Studio. Переместите эти строки в файл ресурсов (RESW) и замените жестко закодированные строковые литералы в приложении и в манифесте ссылками на идентификаторы ресурсов.

В отличие от ресурсов изображений, где в файле ресурсов образа содержится только один ресурс образа, в файле строкового ресурса содержится несколько строковых ресурсов. Строковый файл ресурсов — это файл ресурсов (RESW), который обычно создается в папке \Strings в проекте. Дополнительные сведения об использовании квалификаторов в именах файлов ресурсов (RESW) см. в разделе "Настройка ресурсов" для языка, масштабирования и других квалификаторов.

Хранение строк в файле ресурсов

  1. Задайте язык приложения по умолчанию.

    1. Когда ваше решение открыто в Visual Studio, откройте Package.appxmanifest.
    2. На вкладке "Приложение" убедитесь, что язык по умолчанию задан соответствующим образом (например, en или en-US). Остальные шаги предполагают, что для языка по умолчанию задано значение en-US.

    Примечание.

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

  2. Создайте файл ресурсов (RESW) для языка по умолчанию.

    1. В узле проекта создайте папку и назовите ее Strings.
    2. В разделе Stringsсоздайте вложенную папку и назовите ее en-US.
    3. В разделе en-USсоздайте файл ресурсов (resw) (под типами файлов WinUI в диалоговом окне добавления нового элемента ) и убедитесь, что он называется Resources.resw.

    Примечание.

    Если у вас есть файлы ресурсов .NET (.resx), которые вы хотите перенести, см. Перенос XAML и пользовательского интерфейса.

  3. Откройте Resources.resw и добавьте эти строковые ресурсы.

    Strings/en-US/Resources.resw

    Снимок экрана: таблица добавления ресурсов файла Strings > E N U > Resources.resw.

    В этом примере "Приветствие" является строковым идентификатором ресурса, на который вы можете ссылаться из вашей разметки, как мы покажем. Для идентификатора "Приветствие" строка предоставляется для свойства Text, а строка предоставляется для свойства Width. "Greeting.Text" является примером идентификатора свойства, так как он соответствует свойству элемента пользовательского интерфейса. Кроме того, можно добавить "Greeting.Foreground" в столбец "Имя" и задать для него значение "Красный". Идентификатор "Прощание" — это простой строковый идентификатор ресурса; Он не имеет вложенных свойств, и его можно загрузить из императивного кода, как показано ниже. Столбец комментариев является хорошим местом для предоставления каких-либо специальных инструкций переводчикам.

    В этом примере, так как у нас есть простая запись идентификатора ресурса строки с именем "Farewell", мы также не можем иметь идентификаторы свойств на основе этого же идентификатора. Итак, добавление "Farewell.Text" приведет к ошибке дублирования записи при сборке Resources.resw.

    Идентификаторы ресурсов являются нечувствительными к регистру и должны быть уникальными для каждого файла ресурсов. Не забудьте использовать значимые идентификаторы ресурсов для предоставления дополнительного контекста для переводчиков. И не изменяйте идентификаторы ресурсов после отправки строковых ресурсов для перевода. Команды локализации используют идентификатор ресурса для отслеживания добавлений, удалений и обновлений в ресурсах. Изменения в идентификаторах ресурсов, которые также называются "сдвигом идентификаторов ресурсов", требуют повторной передачи строк, так как они будут отображаться, как будто строки были удалены и другие добавлены.

Ссылка на строковый идентификатор ресурса из XAML

Директива x:Uid используется для связывания элемента управления или другого элемента в разметке со строковым идентификатором ресурса.

<TextBlock x:Uid="Greeting"/>

Во время выполнения загружается \Strings\en-US\Resources.resw (так как в настоящее время это единственный файл ресурсов в проекте). Директива x:Uid в TextBlock приводит к тому, что поиск будет выполняться, чтобы найти идентификаторы свойств внутри Resources.resw , в котором содержится строковый идентификатор ресурса "Приветствие". Идентификаторы свойств "Greeting.Text" и "Greeting.Width" найдены, а их значения применяются к TextBlock, переопределяя значения, заданные локально в разметке. Если вы добавили это, будет применено значение "Приветствие.Foreground". Но для установки свойств на элементы разметки XAML используются только идентификаторы свойств, поэтому установка x:Uid на "Farewell" на этом TextBlock не даст никакого эффекта. Resources.resw содержит идентификатор строкового ресурса "Farewell", но он не содержит идентификаторов свойств для него.

При назначении строкового идентификатора ресурса элементу XAML убедитесь, что все идентификаторы свойств для этого идентификатора подходят для элемента XAML. Например, если задано x:Uid="Greeting" в TextBlock, то "Приветствие.Текст" будет разрешаться, так как тип TextBlock имеет свойство Text. Но если вы установите x:Uid="Greeting" на кнопку, то "Приветствие.Текст" приведет к ошибке времени выполнения, так как тип Button не имеет свойства Text. Решением этой задачи является создание идентификатора свойства с именем "ButtonGreeting.Content" и установка x:Uid="ButtonGreeting" на кнопке.

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

Примечание.

Для присоединенных свойств требуется специальный синтаксис в столбце Name файла RESW. Например, чтобы задать значение для присоединенного свойства AutomationProperties.Name для идентификатора "Приветствие", это то, что вы введете в столбец "Имя".

Greeting.[using:Microsoft.UI.Xaml.Automation]AutomationProperties.Name

Ссылка на строковый идентификатор ресурса из кода

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

var resourceLoader = new Microsoft.Windows.ApplicationModel.Resources.ResourceLoader();
this.myXAMLTextBlockElement.Text = resourceLoader.GetString("Farewell");

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

Если имя ресурса сегментировано (оно содержит символы "." ), замените точки косой чертой ("/") в имени ресурса. Идентификаторы свойств, например, содержат точки; поэтому для загрузки одного из них из кода необходимо выполнить подстановку.

this.myXAMLTextBlockElement.Text = resourceLoader.GetString("Fare/Well"); // <data name="Fare.Well" ...> ...

Если вы сомневаетесь, вы можете использовать MakePri.exe для создания дампа файла PRI приложения. Каждый ресурс uri отображается в дамповом файле.

<ResourceMapSubtree name="Fare"><NamedResource name="Well" uri="ms-resource://<GUID>/Resources/Fare/Well">...

Обратитесь к строковому идентификатору ресурса из манифеста пакета вашего приложения

  1. Откройте исходный файл манифеста пакета приложения (Package.appxmanifest файл), в котором по умолчанию приложение Display name выражается как строковый литерал.

    Снимок экрана файла Package.appxmanifest, показывающий вкладку

  2. Чтобы сделать локализованную версию этой строки, откройте Resources.resw и добавьте новый строковый ресурс с именем AppDisplayName и значением Adventure Works Cycles.

  3. Замените строковый литерал отображаемого имени на ссылку на идентификатор строкового ресурса, который вы только что создали ("AppDisplayName"). Для этого используется схема URI (универсальный ms-resource идентификатор ресурса).

    Снимок экрана файла Package.appxmanifest, который показывает вкладку

  4. Повторите этот процесс для каждой строки в манифесте, которую необходимо локализовать. Например, короткое имя приложения (которое можно настроить для отображения на плитке приложения на начальном экране). Список всех элементов в манифесте пакета приложения, который можно локализовать, см. в разделе "Локализуемые элементы манифеста".

Локализация строковых ресурсов

  1. Создайте копию файла ресурсов (RESW) для другого языка.

    1. В разделе "Строки" создайте новую вложенную папку и назовите её "de-DE" для Deutsch (Deutschland).

    Примечание.

    Для имени папки можно использовать любой тег языка BCP-47. См. "Настройка ресурсов для языка, масштаба и других квалификаторов" для получения подробной информации о квалификаторе языка и списке распространенных языковых тегов. 2. Создайте копию Strings/en-US/Resources.resw в папке Strings/de-DE .

  2. Переведите строки.

    1. Откройте Strings/de-DE/Resources.resw и переведите значения в столбце "Value". Вам не нужно переводить комментарии.

    Strings/de-DE/Resources.resw

    добавить ресурс, немецкий язык

При желании можно повторить шаги 1 и 2 для дальнейшего языка.

Strings/fr-FR/Resources.resw

добавление ресурса, французский

Тестирование приложения

Протестируйте приложение для языка отображения по умолчанию. Затем вы можете изменить язык отображения в Настройки>Время и язык>Регион и язык>Языки и повторно протестировать ваше приложение. Просмотрите строки в пользовательском интерфейсе, а также в оболочке (например, строка заголовка — отображаемое имя) и короткое имя на плитках.

Примечание.

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

Факторирование строк в несколько файлов ресурсов

Вы можете хранить все строки в одном файле ресурсов (resw) или распределить их по нескольким файлам ресурсов. Например, может потребоваться сохранить сообщения об ошибках в одном файле ресурсов, строки манифеста пакета приложения в другом и строки пользовательского интерфейса в третьем. Это то, как будет выглядеть структура папок в этом случае.

Снимок экрана панели Решений, показывающий папку

Чтобы определить область ссылки на строковый идентификатор ресурса для определенного файла, достаточно добавить /<resources-file-name>/ перед идентификатором. В приведенном ниже примере разметки предполагается, что ErrorMessages.resw содержит ресурс, имя которого — PasswordTooWeak.Text и значение которого описывает ошибку.

<TextBlock x:Uid="/ErrorMessages/PasswordTooWeak"/>

Необходимо добавить /<resources-file-name>/ только до строкового идентификатора ресурса для файлов ресурсов, отличных отResources.resw. Это связано с тем, что "Resources.resw" — это имя файла по умолчанию, поэтому предполагается, что вы опустите имя файла (как и в предыдущих примерах в этом разделе).

В приведенном ниже примере кода предполагается, что ErrorMessages.resw содержит ресурс, имя которого — "MismatchedPasswords" и значение которого описывает ошибку.

var resourceLoader = new Microsoft.Windows.ApplicationModel.Resources.ResourceLoader("ErrorMessages");
this.myXAMLTextBlockElement.Text = resourceLoader.GetString("MismatchedPasswords");

Если вы переместите ресурс "AppDisplayName" из Resources.resw в ManifestResources.resw, тогда в манифесте пакета вашего приложения вы измените ms-resource:AppDisplayName на ms-resource:/ManifestResources/AppDisplayName.

Если имя файла ресурса сегментировано (оно содержит символы "." ), оставьте точки в имени при его ссылке. Не заменяйте точки символами косой черты ("/"), как это делается для имени ресурса.

var resourceLoader = new Microsoft.Windows.ApplicationModel.Resources.ResourceLoader("Err.Msgs");

Если вы сомневаетесь, вы можете использовать MakePri.exe, чтобы создать дамп файла PRI вашего приложения. В файле дампа показан uri каждого ресурса.

<ResourceMapSubtree name="Err.Msgs"><NamedResource name="MismatchedPasswords" uri="ms-resource://<GUID>/Err.Msgs/MismatchedPasswords">...

Загрузка строки для определенного языка или другого контекста

ResourceContext по умолчанию (полученный при создании ResourceLoader) содержит значение квалификатора для каждого имени квалификатора, представляющего контекст среды выполнения по умолчанию (иными словами, параметры текущего пользователя и компьютера). Файлы ресурсов (.resw) сопоставляются на основе квалификаторов в их именах со значениями квалификатора в контексте среды выполнения.

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

Это можно сделать, создав новый ResourceContext, изменив его значения, а затем используя этот объект контекста в поисках строк. Аналогичный пример использования ресурсов изображений см. в разделе "Загрузка изображения" для определенного языка или другого контекста.

var resourceManager = new Microsoft.Windows.ApplicationModel.Resources.ResourceManager();
var resourceContext = resourceManager.CreateResourceContext();
resourceContext.QualifierValues["Language"] = "de-DE";
var resourceMap = resourceManager.MainResourceMap.GetSubtree("Resources");
this.myXAMLTextBlockElement.Text = resourceMap.GetValue("Farewell", resourceContext).ValueAsString;

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

resourceContext.Languages = new string[] { "de-DE" };

Загрузка строк из библиотеки классов

Строковые ресурсы библиотеки классов, на которые ссылается ссылка, обычно добавляются в вложенную папку пакета, в который они включены во время процесса сборки. Идентификатор ресурса такой строки обычно принимает форму НазваниеБиблиотеки/ИмяФайлаРесурсов/ИдентификаторРесурса.

Библиотека может получить ResourceLoader для своих собственных ресурсов. Например, в следующем коде показано, как библиотека или приложение, ссылающееся на него, может получить ResourceLoader для строковых ресурсов библиотеки.

var resourceLoader = new Microsoft.Windows.ApplicationModel.Resources.ResourceLoader("ContosoControl/Resources");
this.myXAMLTextBlockElement.Text = resourceLoader.GetString("exampleResourceName");

Если вы сомневаетесь в пути, можно указать параметры MakePri.exe чтобы осуществить дамп файла PRI вашего компонента или библиотеки. Каждый ресурс uri отображается в дамповом файле.

<NamedResource name="exampleResourceName" uri="ms-resource://Contoso.Control/Contoso.Control/ReswFileName/exampleResourceName">...

Загрузка строк из других пакетов

Ресурсы для пакета приложений управляются и получают доступ через собственный ресурс верхнего уровня пакета, доступный из ResourceManager. В каждом пакете различные компоненты могут иметь собственные поддеревья ResourceMap, к которым можно получить доступ с помощью ResourceMap.GetSubtree.

Пакет фреймворка может получить доступ к собственным ресурсам с помощью абсолютного URI ресурса. См. также URI схемы в документации по UWP для получения дополнительной информации.

Загрузка строк в распакованных приложениях

Начиная с Windows версии 1903 (обновление за май 2019 г.), распакованные приложения также могут использовать систему управления ресурсами.

Просто создайте пользовательские элементы управления и библиотеки пакета SDK для Приложений Windows и сохраните все строки в файле ресурсов. Затем можно ссылаться на строковый идентификатор ресурса из XAML, ссылаться на строковый идентификатор ресурса из кода или загружать строки из библиотеки классов.

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

  1. Используйте перегруженный конструктор ResourceManager для передачи имени файла pri-файла приложения при разрешении ресурсов из кода, так как представление по умолчанию в неупакованных сценариях отсутствует.
  2. Используйте MakePri.exe для создания файла resources.pri приложения вручную.
    • Выполнить makepri new /pr <PROJECTROOT> /cf <PRICONFIG> /of resources.pri
    • <PRICONFIG> должен исключить раздел "<упаковка>", чтобы все ресурсы были собраны в один файл resources.pri. При использовании файла конфигурации MakePri.exe, созданного по умолчанию с помощью createconfig, вам нужно вручную удалить раздел "<packaging>" после его создания.
    • <PRICONFIG> должен содержать все соответствующие индексаторы, необходимые для объединения всех ресурсов в проекте в один файл resources.pri. Файл конфигурации по умолчанию MakePri.exe, созданный с помощью createconfig, включает все индексаторы.
    • Если вы не используете конфигурацию по умолчанию, убедитесь, что индексатор PRI включен (ознакомьтесь с конфигурацией по умолчанию, чтобы узнать, как это сделать), чтобы объединить PRI, найденные из ссылок на проекты, ссылки NuGet и т. д., которые находятся в корневом каталоге проекта.

      Примечание.

      Пропуская /IndexName, и если у проекта нет манифеста приложения, пространству имен IndexName/root файла PRI автоматически присваивается значение Application, которое понимается средой выполнения для распакованных приложений (это устраняет прежнюю жесткую зависимость от идентификатора пакета). При указании URI ресурсов ms-resource:/// ссылки, которые опускают корневое пространство имен, предполагают Application в качестве корневого пространства имен для распакованных приложений (или вы можете явно указать Application как в ms-resource://Application/).

  3. Скопируйте файл PRI в выходной каталог сборки .exe
  4. Запустите .exe

    Примечание.

    Система управления ресурсами использует язык отображения системы, а не список предпочитаемых пользователем языков при разрешении ресурсов на основе языка в распакованных приложениях. Список предпочитаемых пользователем языков используется только для упакованных приложений пакета SDK для Приложений Windows.

Внимание

При изменении ресурсов необходимо вручную перестроить файлы PRI. Рекомендуется использовать скрипт после сборки, который обрабатывает команду MakePri.exe и копирует выходные данные resources.pri в каталог .exe.

Локализация упаковаемого приложения WinUI 3

Чтобы обеспечить правильную локализацию упаковаемого классического приложения WinUI 3, объявите каждый поддерживаемый язык в файле package.appxmanifest проекта. При сборке проекта указанные языки добавляются в созданный манифест приложения (AppxManifest.xml). При этом используются соответствующие ресурсы.

Примечание.

Распаковка приложений WinUI (см. раздел "Создание первого проекта WinUI") не содержит package.appxmanifest файл, поэтому после добавления соответствующих ресурсов в проект никаких дополнительных действий не требуется.

  1. .wapproj Откройте package.appxmanifest в текстовом редакторе и найдите следующий раздел:

    <Resources>
        <Resource Language="x-generate"/>
    </Resources>
    
  2. Замените <Resource Language="x-generate"> элементами <Resource /> для каждого из поддерживаемых языков. Например, в следующей разметке указано, что доступны локализованные ресурсы en-US и es-ES:

    <Resources>
        <Resource Language="en-US"/>
        <Resource Language="es-ES"/>
    </Resources>
    

Важные API

См. также