Локализация общих параметров
Создавая приложения и 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’ом что и было в семействе до замены на локализованный параметр.
Нас удовлетворил такой метод, где нужно проделать лишнюю работу, заменяя параметр дважды. Правда он возможно не совсем оптимальный с точки зрения производительности.
Код:
- private static void AdaptSharedParameterFile(
- Application app,
- DefinitionFile originalFile)
- {
- // В этом методе создайте новый файл общих параметров
- // с помощью метода Definitions.Create(
- // String, ParameterType, bool, GUID)
- // с тем же самым GUID что и в оригинальном файле
- // Используйте Definition.GUID чтобы получить текущий GUID
- // общего параметра
- }
- private static void DummySharedParameterFile(
- Application app,
- DefinitionFile originalFile)
- {
- // В этом методе нужно создать файл общих параметров
- // с "левыми" GUID'ами
- }
- public Result Execute(
- ExternalCommandData commandData,
- ref string message,
- ElementSet elements)
- {
- Application app = commandData.Application.Application;
- Document doc = commandData.Application.ActiveUIDocument.Document;
- DefinitionFile originalFile = app.OpenSharedParameterFile();
- AdaptSharedParameterFile(app, originalFile);
- DummySharedParameterFile(app, originalFile);
- using (Transaction t = new Transaction(doc))
- {
- t.Start("Replace Parameter");
- // Извлекаем нужный параметр семейства.
- FamilyParameter fp = doc.FamilyManager.get_Parameter(new Guid("GUID параметра"));
- // Открываем промежуточный файл общих параметров
- // и получаем оттуда нужно определение параметра
- app.SharedParametersFilename
- = sharedParameterFile;
- DefinitionFile dummyDefFile
- = app.OpenSharedParameterFile();
- ExternalDefinition dummyDef
- = dummyDefFile.Groups.get_Item(myGroup.Name)
- .Definitions.get_Item(myAdaptedName)
- as ExternalDefinition;
- // Заменям нужный параметр на
- // параметр из промежуточного файла
- // Для смены GUID
- doc.FamilyManager.ReplaceParameter(fp,
- dummyDef, fp.Definition.ParameterGroup,
- fp.IsInstance);
- // Открываем файл общих параметров с "правильными" GUID'ами
- app.SharedParametersFilename
- = sharedParameterFile;
- DefinitionFile targetDefFile
- = app.OpenSharedParameterFile();
- ExternalDefinition targetDef
- = targetDefFile.Groups.get_Item(myGroup.Name)
- .Definitions.get_Item(myAdaptedName)
- as ExternalDefinition;
- // Заменяем промежуточный параметр
- // на правильный параметр с тем же самым GUID
- // что и до первой замены
- doc.FamilyManager.ReplaceParameter(fp,
- targetDef, fp.Definition.ParameterGroup,
- fp.IsInstance);
- t.Commit();
- }
- return Result.Succeeded;
- }
Большое спасибо Джасперу за интересное рассуждение и решение!
Источник: 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