Примечание
Для доступа к этой странице требуется авторизация. Вы можете попробовать войти или изменить каталоги.
Для доступа к этой странице требуется авторизация. Вы можете попробовать изменить каталоги.
Приложения используют диспетчер ресурсов .NET Framework, представленный ResourceManager классом, для получения локализованных ресурсов. В Resource Manager предполагается, что для упаковки и развертывания ресурсов используется модель концентратора и периферийной модели. Концентратор — это основная сборка, содержащая нелокализуемый исполняемый код и ресурсы для одной культуры, называемой нейтральной или культурой по умолчанию. Язык и региональные параметры по умолчанию служат запасным вариантом для приложения; используются ресурсы той культуры, если локализованные ресурсы не найдены. Каждая спица подключается к спутниковой сборке, содержащей ресурсы для одной культуры, но не содержащей никакого кода.
Существует несколько преимуществ для этой модели:
- Вы можете постепенно добавлять ресурсы для новых культур после развертывания приложения. Так как последующие разработки ресурсов, относящихся к культурным особенностям, могут потребовать значительного времени, это позволяет сначала выпустить основное приложение и предоставить ресурсы, зависящие от языка и региона, на более позднюю дату.
- Вы можете обновлять и изменять вспомогательные сборки приложения без повторной компиляции приложения.
- Приложение должно загружать только те сателлитные сборки, которые содержат ресурсы, необходимые для определенной культуры. Это может значительно сократить использование системных ресурсов.
Однако существуют также недостатки этой модели:
- Необходимо управлять несколькими наборами ресурсов.
- Начальная стоимость тестирования приложения увеличивается, так как необходимо протестировать несколько конфигураций. Обратите внимание, что в долгосрочной перспективе будет проще и менее дорого протестировать одно основное приложение с несколькими спутниками, чем тестировать и поддерживать несколько параллельных международных версий.
Соглашения об именовании ресурсов
При упаковке ресурсов приложения необходимо задать имена в соответствии с соглашениями об именовании ресурсов, которые ожидает общая языковая среда выполнения (CLR). Среда выполнения определяет ресурс по имени культуры. Каждой культуре присваивается уникальное имя, которое обычно представляет собой сочетание двухбуквенного, строчного названия культуры, связанного с языком, и, если необходимо, двухбуквенного, заглавного названия подкультуры, связанного со страной или регионом. Название подкультуры следует за названием культуры, разделённое дефисом (-). Примеры включают ja-JP для японского языка, как говорят в Японии, en-US для английского языка, как говорился в Соединенных Штатах, de-DE для немецкого языка, как говорился в Германии, или de-AT для немецкого языка, как говорился в Австрии. См. столбец тега языка в списке имен языков или регионов, поддерживаемых Windows. Названия культур следуют стандарту, определенному BCP 47.
Замечание
Существуют некоторые исключения для двухбуквенных названий культур, например zh-Hans
для китайского (Упрощенного).
Для получения дополнительной информации см. Создание файлов ресурсов и Создание вспомогательных сборок.
Процесс резервного переключения ресурсов
Модель концентратора и периферийной модели упаковки и развертывания ресурсов использует резервный процесс для поиска соответствующих ресурсов. Если запрошенный приложением локализованный ресурс недоступен, общая языковая среда выполнения ищет в иерархии культур подходящий резервный ресурс, который наиболее точно соответствует запросу приложения пользователя и выбрасывает исключение только в крайнем случае. На каждом уровне иерархии, если найден соответствующий ресурс, среда выполнения использует его. Если ресурс не найден, поиск продолжается на следующем уровне.
Чтобы повысить производительность поиска, примените атрибут NeutralResourcesLanguageAttribute к основной сборке и укажите в нём название нейтрального языка, который будет взаимодействовать с вашей основной сборкой.
Процесс резервирования ресурсов .NET Framework
Процесс резервного восстановления ресурсов .NET Framework включает в себя следующие действия.
Подсказка
Можно использовать <элемент конфигурации relativeBindForResources> для оптимизации процесса отката ресурсов и процесса, с помощью которого среда выполнения ищет сборки ресурсов. Дополнительные сведения см. в разделе "Оптимизация резервного процесса ресурсов".
Среда выполнения сначала проверяет глобальный кэш сборок на наличие сборки, которая соответствует запрошенной культуре вашего приложения.
Глобальный кэш сборок может хранить сборки ресурсов, совместно используемые многими приложениями. Это освобождает вас от необходимости включать определенные наборы ресурсов в структуру каталогов каждого создаваемого приложения. Если среда выполнения находит ссылку на сборку, она выполняет поиск сборки для запрошенного ресурса. Если запись найдена в сборке, используется запрошенный ресурс. Если запись не находится, она продолжает поиск.
Среда выполнения далее проверяет каталог текущей выполняемой сборки для подкаталога, соответствующего запрашиваемой культуре. Если он находит подкаталог, он ищет в этом подкаталоге правильную вспомогательную сборку для запрошенного языка и региональных параметров. Затем среда выполнения осуществляет поиск сателлитной сборки для запрашиваемого ресурса. Если он находит ресурс в сборке, он использует его. Если ресурс не находится, он продолжает поиск.
Среда выполнения запрашивает установщик Windows, чтобы определить, следует ли устанавливать сборку-сателлит по запросу. В этом случае он обрабатывает установку, загружает сборку и выполняет поиск в ней или запрошенный ресурс. Если он находит ресурс в сборке, он использует его. Если ресурс не находится, он продолжает поиск.
Среда выполнения вызывает AppDomain.AssemblyResolve событие, указывающее, что не удается найти спутниковую сборку. Если вы решили обработать событие, обработчик событий может вернуть ссылку на спутниковую сборку, ресурсы которой будут использоваться для поиска. В противном случае обработчик событий возвращает
null
, и поиск продолжается.При времени выполнения снова осуществляется поиск в глобальном кэше сборок, на этот раз для родительской сборки запрошенной культуры. Если родительская сборка существует в глобальном кэше сборок, среда выполнения выполняет поиск сборки для запрошенного ресурса.
Родительская культура определяется как соответствующая резервная культура. Рассмотрим родителей как резервных кандидатов, так как предоставление любого ресурса предпочтительнее, чем исключение. Этот процесс также позволяет повторно использовать ресурсы. Необходимо включить определенный ресурс на родительском уровне только в том случае, если дочерняя культура не требует локализации запрошенного ресурса. Например, если вы предоставляете локализованные сборки для
en
(нейтрального английского языка),en-GB
(английского языка, используемого в Соединенном Королевстве), иen-US
(английского языка, используемого в Соединенных Штатах), то сборкаen
будет содержать общую терминологию, а сборкиen-GB
иen-US
могут предоставлять переопределения только для тех терминов, которые отличаются.Среда выполнения затем проверяет каталог текущей выполняемой сборки, чтобы узнать, содержит ли он родительский каталог. Если родительский каталог существует, среда выполнения ищет в каталоге соответствующую спутниковую сборку для родительской культуры. Если она находит сборку, среда выполнения выполняет поиск сборки для запрошенного ресурса. Если он находит ресурс, он использует его. Если ресурс не находится, он продолжает поиск.
Среда выполнения затем обращается к установщику Windows, чтобы определить, следует ли устанавливать родительскую спутниковую сборку по запросу. В этом случае он обрабатывает установку, загружает сборку и выполняет поиск в ней или запрошенный ресурс. Если он находит ресурс в сборке, он использует его. Если ресурс не находится, он продолжает поиск.
Среда выполнения вызывает AppDomain.AssemblyResolve событие, указывающее, что не удается найти соответствующий резервный ресурс. Если вы решили обработать событие, обработчик событий может вернуть ссылку на спутниковую сборку, ресурсы которой будут использоваться для поиска. В противном случае обработчик событий возвращает
null
, и поиск продолжается.Среда выполнения затем осуществляет поиск родительских сборок, как и в предыдущих трех шагах, на различных потенциальных уровнях. Каждая культура имеет только одного родителя, который определяется свойством CultureInfo.Parent, но у родителя может быть свой собственный родитель. Поиск родительских культур прекращается, когда свойство Parent возвращает CultureInfo.InvariantCulture; для резервного доступа к ресурсам инвариантная культура не считается родительской культурой и не может иметь собственные ресурсы.
Если указанная изначально культура и все её предки были проверены, но ресурс всё равно не найден, используется ресурс в культуре по умолчанию (запасной). Как правило, ресурсы для культуры по умолчанию включены в основную сборку приложения. Однако можно указать значение Satellite свойства Location атрибута NeutralResourcesLanguageAttribute , указывающее, что конечное резервное расположение ресурсов является вспомогательной сборкой, а не основной сборкой.
Замечание
Ресурс по умолчанию — единственный ресурс, который можно скомпилировать с помощью основной сборки. Если вы не указываете спутниковую сборку с помощью атрибута NeutralResourcesLanguageAttribute, то это является последним резервным вариантом. Поэтому мы рекомендуем всегда включать набор ресурсов по умолчанию в основную сборку. Это помогает предотвратить создание исключений. Включение ресурса по умолчанию, файла, предоставляет резервный вариант для всех ресурсов и гарантирует, что для пользователя всегда присутствует как минимум один ресурс, даже если он не является специфичным для данной культуры.
Наконец, если среда выполнения не находит ресурс для культуры по умолчанию (резервная версия), создается исключение MissingManifestResourceException или MissingSatelliteAssemblyException, указывающее, что ресурс не найден.
Например, предположим, что приложение запрашивает ресурс, локализованный для испанской (Мексика) культуры (es-MX
). Среда выполнения сначала выполняет поиск глобального кэша сборок для сборки, которая соответствует es-MX
, но не находит ее. Затем среда выполнения ищет в каталоге текущей сборки на предмет наличия каталога es-MX
. Если это не удается, среда выполнения снова ищет в глобальном кэше сборок родительскую сборку, которая отражает соответствующую резервную культуру — в этом случае es
(испанский). Если родительская сборка не найдена, среда выполнения осуществляет поиск во всех возможных уровнях родительских сборок для es-MX
культуры, пока не найдет соответствующий ресурс. Если ресурс не найден, система использует ресурс для культуры по умолчанию.
Оптимизация процесса резервного использования ресурсов .NET Framework
В следующих условиях можно оптимизировать процесс, с помощью которого среда выполнения ищет ресурсы в вспомогательных сборках:
Сателлитные сборки развертываются в том же местоположении, что и сборка кода. Если сборка кода установлена в глобальном кэше сборок, то спутниковые сборки также устанавливаются в глобальный кэш сборок. Если компонент установлен в каталоге, сателлитные сборки устанавливаются в культурно-специфичные папки этого каталога.
Сателлитные сборки не устанавливаются по запросу.
Код приложения не обрабатывает AppDomain.AssemblyResolve событие.
Вы оптимизируете пробу для сателлитных сборок, включив <элемент relativeBindForResources> и задав его enabled
атрибут true
в файле конфигурации приложения, как показано в следующем примере.
<configuration>
<runtime>
<relativeBindForResources enabled="true" />
</runtime>
</configuration>
Оптимизированный зонд для спутниковых сборок — это опциональная функция. То есть среда выполнения выполняет шаги, описанные в резервном процессе ресурса , если <в файле конфигурации приложения отсутствует относительный элементBindForResources> , а его enabled
атрибут имеет значение true
. Если это так, процесс проверки для вспомогательной сборки изменяется следующим образом:
Среда выполнения использует расположение родительской сборки кода для поиска вспомогательной сборки. Если родительская сборка установлена в глобальном кэше сборок, среда выполнения проверяет только глобальный кэш сборок, но не каталог приложения. Если родительская сборка установлена в каталоге приложений, среда выполнения проверяет каталог приложения, но не в глобальном кэше сборок.
Среда выполнения не запрашивает установщик Windows для установки сателлитных сборок по требованию.
Если проверка для конкретной сборки ресурсов заканчивается неудачей, время выполнения не вызывает событие AppDomain.AssemblyResolve.
Резервный процесс ресурсов .NET Core
Резервный процесс ресурсов .NET Core включает в себя следующие действия.
Среда выполнения пытается загрузить спутниковую сборку для запрошенной культуры.
Проверяет каталог исполняемой в данный момент сборки на наличие подкаталога, соответствующего запрашиваемой культуре. Если он находит подкаталог, он ищет в этом подкаталоге верную вспомогательную сборку для запрашиваемой культуры и загружает её.
Замечание
В операционных системах с файловыми системами, чувствительными к регистру (то есть, Linux и macOS), поиск подкаталогов с названиями культур чувствителен к регистру. Имя подкаталога CultureInfo.Name должно точно соответствовать регистру (например,
es
илиes-MX
).Замечание
Если программист произвел пользовательский контекст загрузки сборки из AssemblyLoadContext, ситуация усложняется. Если выполняющаяся сборка была загружена в пользовательский контекст, среда выполнения загружает спутниковую сборку в пользовательский контекст. Детали выходят за рамки этого документа. См. AssemblyLoadContext.
Если спутниковая сборка не найдена, AssemblyLoadContext вызывает событие AssemblyLoadContext.Resolving, чтобы указать, что не удается найти спутниковую сборку. Если вы решили обработать событие, ваш обработчик событий может загрузить и вернуть ссылку на вспомогательную сборку.
Если сопутствующая сборка по-прежнему не найдена, AssemblyLoadContext вызывает событие AppDomain.AssemblyResolve, указывающее, что не удается найти эту сопутствующую сборку. Если вы решили обработать событие, ваш обработчик событий может загрузить и вернуть ссылку на вспомогательную сборку.
Если обнаружена сателлитная сборка, среда выполнения ищет в ней запрошенный ресурс. Если он находит ресурс в сборке, он использует его. Если ресурс не находится, он продолжает поиск.
Замечание
Чтобы найти ресурс в спутниковой сборке, среда исполнения выполняет поиск файла ресурса, запрошенного ResourceManager для текущего CultureInfo.Name. В файле ресурса выполняется поиск запрошенного имени ресурса. Если это не найдено, ресурс обрабатывается как не найден.
Среда выполнения затем ищет родительские сборки культур через множество возможных уровней, каждый раз повторяя шаги 1 и 2.
Родительская культура определяется как соответствующая резервная культура. Рассмотрим родителей как резервных кандидатов, так как предоставление любого ресурса предпочтительнее, чем исключение. Этот процесс также позволяет повторно использовать ресурсы. Необходимо включить определенный ресурс на родительском уровне только в том случае, если дочерняя культура не требует локализации запрошенного ресурса. Например, если вы предоставляете вспомогательные сборки для
en
(нейтрального английского языка),en-GB
(английского, как говорят в Соединенном Королевстве) иen-US
(английского, как говорят в Соединенных Штатах), то спутникen
содержит общую терминологию, а спутникиen-GB
иen-US
предоставляют переопределения только для тех терминов, которые отличаются.Каждая культура имеет только одного родителя, который определяется свойством CultureInfo.Parent, но у родителя может быть свой собственный родитель. Поиск родительских культур останавливается, когда свойство культуры Parent возвращает CultureInfo.InvariantCulture. Для резервирования ресурсов инвариантная культура не считается основной культурой или культурой, которая может иметь ресурсы.
Если указанная изначально культура и все её предки были проверены, но ресурс всё равно не найден, используется ресурс в культуре по умолчанию (запасной). Как правило, ресурсы для культуры по умолчанию включены в основную сборку приложения. Однако можно указать значение Satellite свойства Location , указывающее, что конечное резервное расположение ресурсов является вспомогательной сборкой, а не основной сборкой.
Замечание
Ресурс по умолчанию — единственный ресурс, который можно скомпилировать с помощью основной сборки. Если вы не указываете спутниковую сборку с помощью атрибута NeutralResourcesLanguageAttribute, то это является последним резервным вариантом. Поэтому мы рекомендуем всегда включать набор ресурсов по умолчанию в основную сборку. Это помогает предотвратить создание исключений. Включив файл ресурсов по умолчанию, вы предоставляете резерв для всех ресурсов и гарантируете, что для пользователя всегда присутствует хотя бы один ресурс, даже если он не учитывает культурные особенности.
Наконец, если среда выполнения не находит файл ресурсов для культуры по умолчанию, возникает исключение MissingManifestResourceException или MissingSatelliteAssemblyException, указывающее, что ресурс не найден. Если файл ресурса найден, но запрошенный ресурс отсутствует, запрос возвращает
null
.
Окончательный резервный переход к сателлитному сборочному блоку
При необходимости можно удалить ресурсы из основной сборки и указать, что среда выполнения должна загружать последние резервные ресурсы из спутниковой сборки, соответствующей определённой культуре. Чтобы управлять резервным процессом, используйте NeutralResourcesLanguageAttribute(String, UltimateResourceFallbackLocation) конструктор и укажите значение параметра UltimateResourceFallbackLocation , указывающее, следует ли Resource Manager извлекать резервные ресурсы из основной сборки или из вспомогательной сборки.
В следующем примере .NET Framework используемый атрибут NeutralResourcesLanguageAttribute применяется для хранения резервных ресурсов приложения в сателлитной сборке для французского языка (fr
). В примере есть два текстовых файла ресурсов, которые определяют один строковый ресурс с именем Greeting
. Первый, resources.fr.txt, содержит ресурс французского языка.
Greeting=Bon jour!
Во-вторых, ресурсru.txtсодержит ресурс на русском языке.
Greeting=Добрый день
Эти два файла компилируются в файлы ресурсов путем запуска генератора файлов ресурсов (resgen.exe) из командной строки. Команда для ресурса на французском языке:
resgen.exe resources.fr.txt
Для ресурса на русском языке команда следующая:
resgen.exe resources.ru.txt
Файлы .resources внедряются в библиотеки динамической компоновки, выполняя Компоновщик сборок (al.exe) из командной строки для ресурсов французского языка следующим образом:
al /t:lib /embed:resources.fr.resources /culture:fr /out:fr\Example1.resources.dll
и для ресурса русского языка следующим образом:
al /t:lib /embed:resources.ru.resources /culture:ru /out:ru\Example1.resources.dll
Исходный код приложения находится в файле с именем Example1.cs или Example1.vb. Он включает атрибут, указывающий NeutralResourcesLanguageAttribute , что ресурс приложения по умолчанию находится в подкаталоге fr. Он создает экземпляр Resource Manager, извлекает значение Greeting
ресурса и отображает его в консоли.
using System;
using System.Reflection;
using System.Resources;
[assembly:NeutralResourcesLanguage("fr", UltimateResourceFallbackLocation.Satellite)]
public class Example
{
public static void Main()
{
ResourceManager rm = new ResourceManager("resources",
typeof(Example).Assembly);
string greeting = rm.GetString("Greeting");
Console.WriteLine(greeting);
}
}
Imports System.Reflection
Imports System.Resources
<Assembly: NeutralResourcesLanguage("fr", UltimateResourceFallbackLocation.Satellite)>
Module Example
Public Sub Main()
Dim rm As New ResourceManager("resources", GetType(Example).Assembly)
Dim greeting As String = rm.GetString("Greeting")
Console.WriteLine(greeting)
End Sub
End Module
Затем можно скомпилировать исходный код C# из командной строки следующим образом:
csc Example1.cs
Команда компилятора Visual Basic очень похожа:
vbc Example1.vb
Так как в основной сборке нет ресурсов, вам не нужно компилировать программу, используя параметр /resource
.
При запуске примера из системы, язык которой отличается от русского, отображается следующий результат:
Bon jour!
Рекомендуемая альтернатива упаковки
Ограничения времени или бюджета могут препятствовать созданию набора ресурсов для каждой подкультуры, которую поддерживает ваше приложение. Вместо этого можно создать одну дочернюю сборку для родительской культуры, которую могут использовать все связанные дочерние культуры. Например, можно предоставить одну англоязычную спутниковую сборку (en), которая извлекается пользователями, запрашивающими ресурсы английского языка для конкретного региона, а также одну немецкую спутниковую сборку (de) для пользователей, запрашивающих ресурсы немецкого языка для конкретного региона. Например, запросы на немецкий язык, как он используется в Германии (de-DE), Австрии (de-AT) и Швейцарии (de-CH), будут ссылаться на немецкую вспомогательную сборку (de). Ресурсы по умолчанию являются окончательным резервным вариантом и поэтому должны быть ресурсами, которые будут запрашиваться большинством пользователей приложения, поэтому тщательно выбирайте эти ресурсы. Этот подход развертывает ресурсы, которые являются менее культурными, но могут значительно снизить затраты на локализацию приложения.