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

28/11/2013

Локализация общих параметров

Создавая приложения и add-in'ы, необходимо помнить, что их могут использовать на компьютере с языком интерфейса отличным от вашего. Или в Revit c другим языком интерфейса.

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

Revit API поддерживает создание таких надстроек. Яркий пример – использование, к примеру, перечисления BuiltInParameters и BuiltInCategories, вместо использования локализованных названий параметров и категорий, для работы со встроенными в Revit параметрами и категориями.

Есть и методы для извлечения локализованных названий. Класс LabelUtils содержит методы, с помощью которых можно получить название встроенной категории на том же языке, что и сам Revit.

Но, к сожалению, в целом система работы с параметрами была задумана для конечных пользователей, а не для разработчиков. По этой причине API предоставляет слабую поддержку для создания собственных параметров на нескольких языках.

Джаспер Десмет (Jasper Desmet) в очередной раз сделал попытку обратить внимание на этот недостаток, столкнувшись с подобной проблемой и предоставив свое решение.

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

Суть проблемы: файлы общих параметров, содержащие названия на нужных языках, содержат одинаковые GUID’ы. То есть изменены только названия. Для замены параметра на новый параметр с переведенных названием мы хотели воспользоваться методом Document.FamilyManager.ReplaceParameter, но, так как GUID’ы параметров одинаковые, то метод оказался бесполезным. Как мы поняли, данный метод проверяет GUID параметра перед заменой и если он одинаковый с заменяемым параметром, то предполагается что параметры одинаковые и замены не происходит.

Для решения нашей проблемы по пошли следующим путем. Мы использовали два файла общих параметров с переведенными названиями: один с «левыми» GUID’ами, и другой с правильными GUID’ами. С помощью такого подхода, мы сначала заменяем параметры семейства на параметры с «левыми» GUID’ами, а затем уже меняем на нужный параметр с тем же самым GUID’ом что и было в семействе до замены на локализованный параметр.

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

Код:

Код - C#: [Выделить]
  1.         private static void AdaptSharedParameterFile(
  2.                            Application app,
  3.                            DefinitionFile originalFile)
  4.         {
  5.             // В этом методе создайте новый файл общих параметров
  6.             // с помощью метода Definitions.Create(
  7.             // String, ParameterType, bool, GUID)
  8.             // с тем же самым GUID что и в оригинальном файле
  9.             // Используйте Definition.GUID чтобы получить текущий GUID
  10.             // общего параметра   
  11.         }
  12.  
  13.         private static void DummySharedParameterFile(
  14.                       Application app,
  15.                       DefinitionFile originalFile)
  16.         {
  17.  
  18.             // В этом методе нужно создать файл общих параметров
  19.             // с "левыми" GUID'ами   
  20.         }
  21.  
  22.         public Result Execute(
  23.             ExternalCommandData commandData,
  24.             ref string message,
  25.             ElementSet elements)
  26.         {
  27.             Application app = commandData.Application.Application;
  28.             Document doc = commandData.Application.ActiveUIDocument.Document;
  29.             DefinitionFile originalFile = app.OpenSharedParameterFile();
  30.  
  31.             AdaptSharedParameterFile(app, originalFile);
  32.             DummySharedParameterFile(app, originalFile);
  33.  
  34.             using (Transaction t = new Transaction(doc))
  35.             {
  36.                 t.Start("Replace Parameter");
  37.  
  38.                 // Извлекаем нужный параметр семейства.
  39.                 FamilyParameter fp = doc.FamilyManager.get_Parameter(new Guid("GUID параметра"));
  40.  
  41.                 // Открываем промежуточный файл общих параметров
  42.                 // и получаем оттуда нужно определение параметра
  43.  
  44.                 app.SharedParametersFilename
  45.                     = sharedParameterFile;
  46.  
  47.                 DefinitionFile dummyDefFile
  48.                     = app.OpenSharedParameterFile();
  49.  
  50.                 ExternalDefinition dummyDef
  51.                     = dummyDefFile.Groups.get_Item(myGroup.Name)
  52.                         .Definitions.get_Item(myAdaptedName)
  53.                         as ExternalDefinition;
  54.  
  55.                 // Заменям нужный параметр на 
  56.                 // параметр из промежуточного файла
  57.                 // Для смены GUID
  58.  
  59.                 doc.FamilyManager.ReplaceParameter(fp,
  60.                     dummyDef, fp.Definition.ParameterGroup,
  61.                     fp.IsInstance);
  62.  
  63.                 // Открываем файл общих параметров с "правильными" GUID'ами
  64.  
  65.                 app.SharedParametersFilename
  66.                     = sharedParameterFile;
  67.  
  68.                 DefinitionFile targetDefFile
  69.                     = app.OpenSharedParameterFile();
  70.  
  71.                 ExternalDefinition targetDef
  72.                     = targetDefFile.Groups.get_Item(myGroup.Name)
  73.                         .Definitions.get_Item(myAdaptedName)
  74.                         as ExternalDefinition;
  75.  
  76.                 // Заменяем промежуточный параметр
  77.                 // на правильный параметр с тем же самым GUID
  78.                 // что и до первой замены
  79.  
  80.                 doc.FamilyManager.ReplaceParameter(fp,
  81.                     targetDef, fp.Definition.ParameterGroup,
  82.                     fp.IsInstance);
  83.  
  84.                 t.Commit();
  85.             }
  86.             return Result.Succeeded;
  87.         }

Большое спасибо Джасперу за интересное рассуждение и решение!

Источник: http://thebuildingcoder.typepad.com/blog/2013/11/translated-shared-parameter-guid-consolidation.html

Обсуждение: http://adn-cis.org/forum/index.php?topic=356

Опубликовано 28.11.2013
Отредактировано 28.11.2013 в 18:32:27