Сообщество программистов Autodesk в СНГ

ADN Club => Revit API => Тема начата: Андрей Бушман от 18-01-2017, 23:49:55

Название: Локализация интерфейса через файл манифеста
Отправлено: Андрей Бушман от 18-01-2017, 23:49:55
Revit 2017.1.1

В официальной документации по Revit API присутствует информация о том, как можно выполнять локализацию (http://help.autodesk.com/view/RVT/2017/ENU/?guid=GUID-74C35C7C-22E8-4F7F-844F-E602EF45CFA2) внешних команд и внешних приложений Revit посредством файла манифеста, ссылаясь в нём на соответствующие записи файла локализованных ресурсов. Информация достаточно простая и понятная, как показалось на первый взгляд. Однако моя попытка применить это на практике положительных результатов не дала...

В обозначенной заметке присутствует ссылка на Walkthrough: Creating Managed Satellite DLLs (https://msdn.microsoft.com/en-us/library/e9zazcx5.aspx), где рассказывается о том, как в Visual Studio 2013 на основе шаблона Visual Studio Add-in создать управляемую сборку-сателит, содержащую ресурсы, доступные для использования внешним сборкам. Однако у меня Visual Studio 2015 и обозначенного шаблона я в ней не нашёл. В виду этого сгенерировал файлы ресурсов таким же способом, каким успешно делаю это уже многие годы...

Обычно я работаю с локализованными ресурсами посредством ResourceManager, однако обозначенный в документации способ мне был доселе не знаком и потому я решил попробовать этот новый способ...

В Walkthrough: Creating Managed Satellite DLLs (https://msdn.microsoft.com/en-us/library/e9zazcx5.aspx) имеется такой фрагмент текста:
Цитировать
17. In Solution Explorer, right-click Resource1.resx and then click Properties.

18. In the Properties window, change Build Action from Embedded Resource to None.

This prevents the resource from being built into the add-in assembly.

Если это выполнить, то при компиляции локализованные ресурсы создаваться не будут и потребуется вручную выполнять пункты 20-22. Насколько я понимаю, выполнение этих пунктов даёт в итоге тот же результат, который получается при значении Embedded Resource для файлов Resource1.en.resx и Resource1.ru.resx, с той лишь разницей, что результат будет получен вручную, а не сгенерирован автоматически.

Встраивание ресурсов в основную сборку происходит только для resx-файлов, не имеющих в составе своего имени суффикса, указывающего на локализацию (en, ru, en-US, ru-RU). Это так называемые default-локализации, которые используются в том случае, когда не найдены ресурсы с нужной локализацией. А ежели суффикс с локализацией присутствует у resx-файла, то на его основе создаётся ресурсный файл и помещается в подкаталог, имеющий имя суффикса локализации.

Ок, всё же пробуем выполнить вручную то, что советуют в обозначенной статье:

cd /D "C:\Users\root\Documents\visual studio 2015\Projects\HelloWorld"
Resgen Resource1.resx
AL.exe /embed:Resource1.resources /culture:en /out:HelloWorld.resources.dll

(https://s30.postimg.org/qb1fw1oq9/image.png)

Однако сгенерированные таким образом (п.20-22) файлы и закинутые по подкаталогам en и ru в основном каталоге внешней команды, проблему не решили - ресурсы по прежнему не задействованы манифестом. В виду этого я для RESX-файлов вернул обратно значение Embedded Resource вместо None.

Полный исходный код своего примера HelloWorld я опубликовал на BitBucket (https://bitbucket.org/Andrey-Bushman/helloworld). Обращаю ваше внимание на то, что в указанной версии дистрибутива RESX-файлам назначено свойство Embedded Resource вместо None, и соответственно локализованные ресурсы генерируются автоматически.

Файл манифеста такой:

Код - XML [Выбрать]
  1. <?xml version="1.0" encoding="utf-8" standalone="no"?>
  2. <RevitAddIns>
  3.   <AddIn Type="Command">
  4.     <Assembly>HelloWorld\HelloWorld.dll</Assembly>
  5.     <AddInId>{39E8DC8B-DC8F-44A5-ABC9-39442B5031ED}</AddInId>
  6.     <FullClassName>HelloWorld.ExternalCommand</FullClassName>
  7.     <Text>@Text</Text>
  8.     <VendorId>@VendorId</VendorId>
  9.     <VendorDescription>@VendorDescription</VendorDescription>
  10.     <VisibilityMode>NotVisibleInFamily</VisibilityMode>
  11.     <Discipline>Structure</Discipline>
  12.     <Discipline>Architecture</Discipline>
  13.     <AvailabilityClassName>HelloWorld.ExternalCommandAvailability</AvailabilityClassName>
  14.     <LongDescription>@LongDescription</LongDescription>
  15.     <TooltipImage>@TooltipImage</TooltipImage>
  16.     <LargeImage>@LargeImage</LargeImage>
  17.   </AddIn>
  18. </RevitAddIns>

Пара скринов, показывающих состав ресурсов:

(https://s27.postimg.org/xskuahe2b/image.png)

(https://s23.postimg.org/fnmcodo7f/image.png)

Результат выглядит следующим образом:

(https://s29.postimg.org/f7bapowjr/image.png)

Как видим, ресурсы не используются.

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

Как добиться ожидаемого результата, воспользовавшись обозначенным в документации (http://help.autodesk.com/view/RVT/2017/ENU/?guid=GUID-74C35C7C-22E8-4F7F-844F-E602EF45CFA2) способом локализации интерфейса?

Может быть способ локализации интерфейсов внешних команд и приложений посредством привязки файла манифеста к записям локализованных ресурсов всё же не работает в Revit?
Название: Re: Локализация интерфейса через файл манифеста
Отправлено: Александр Ривилис от 19-01-2017, 01:19:57
Однако сгенерированные таким образом (п.20-22) файлы и закинутые по подкаталогам en и ru в основном каталоге внешней команды, проблему не решили - ресурсы по прежнему не задействованы манифестом.
Судя по документации эти подкаталоги должны быть en-US и ru-RU.
Название: Re: Локализация интерфейса через файл манифеста
Отправлено: Андрей Бушман от 19-01-2017, 01:25:33
Судя по документации эти подкаталоги должны быть en-US и ru-RU.
В MSDN и книжках можно прочесть о том, что суффиксы локализации можно указывать по разному. Например, если ресурсу указать суффикс en-US, то использоваться такие ресурсы будут только для американской локализации. Однако если создать локализацию с суффиксом en, то такой ресурс уже сможет использоваться как для локализации en-US, так и для en-GB (и всех прочих en-*). Если вдруг для американской (к примеру) локализации не будут найдены ресурсы ни с суффиксом en-US, ни с суффиксом en, то будет выполнена попытка найти ресурс со встроенной default-локализацией. Ежели и его не получится найти, то тогда уж будет сгенерировано исключение.

Это правила поиска ресурсов, используемые по умолчанию и "зашитые" в .NET Framework.

Поэтому в своих приложениях я, как правило, указываю именно en и ru, вместо en-US и ru-RU.
Название: Re: Локализация интерфейса через файл манифеста
Отправлено: Андрей Бушман от 19-01-2017, 01:33:21
Кстати, и в документации Autodesk написано (http://help.autodesk.com/view/RVT/2017/ENU/?guid=GUID-74C35C7C-22E8-4F7F-844F-E602EF45CFA2) на эту тему:

Цитировать
The Satellite DLLs are expected to be in a directory with the name of the language of the language-culture, such as en or en-US.
Название: Re: Локализация интерфейса через файл манифеста
Отправлено: Андрей Бушман от 19-01-2017, 10:42:26
В соответствии с предположением (http://forums.autodesk.com/t5/revit-api-forum/manifest-localization/m-p/6814103#M20538) Jeremy Tammik я попробовал разместить каталог HelloWorld, содержащий результат компиляции, в директории "C:\Program Files\Autodesk\Revit 2017\AddIns\". При этом файл манифеста "C:\Users\developer\AppData\Roaming\Autodesk\Revit\Addins\2017\HelloWorld.addin" был отредактирован соответствующим образом:

Код - XML [Выбрать]
  1. <?xml version="1.0" encoding="utf-8" standalone="no"?>
  2. <RevitAddIns>
  3.   <AddIn Type="Command">
  4.     <Assembly>C:\Program Files\Autodesk\Revit 2017\AddIns\HelloWorld\HelloWorld.dll</Assembly>
  5.     <AddInId>{39E8DC8B-DC8F-44A5-ABC9-39442B5031ED}</AddInId>
  6.     <FullClassName>HelloWorld.ExternalCommand</FullClassName>
  7.     <Text>@Text</Text>
  8.     <VendorId>@VendorId</VendorId>
  9.     <VendorDescription>@VendorDescription</VendorDescription>
  10.     <VisibilityMode>NotVisibleInFamily</VisibilityMode>
  11.     <Discipline>Structure</Discipline>
  12.     <Discipline>Architecture</Discipline>
  13.     <AvailabilityClassName>HelloWorld.ExternalCommandAvailability</AvailabilityClassName>
  14.     <LongDescription>@LongDescription</LongDescription>
  15.     <TooltipImage>@TooltipImage</TooltipImage>
  16.     <LargeImage>@LargeImage</LargeImage>
  17.   </AddIn>
  18. </RevitAddIns>

Однако это не помогло - результат всё тот же.