Кастомизация
09
Мар
0

Язык лукапа

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

Поэтому нарисуем плагин, который в зависимости от языковых настроек текущего пользователя будет выводить в лукапах «основной» атрибут на соответствующем языке.
Суть маневра заключается в том, чтобы добавить на нужный объект столько дополнительных полей, сколько языков у Вас установлено – по одному на каждый язык. И при их заполнении конкатенировать всех их в стандартный основной атрибут. А когда происходит Retrieve или Retrieve-Multiple, в зависимости от текущих языковых настроек, распарсивать его и оставлять только значение на нужном языке.

В качестве примера рассмотрим как это работает для Продуктов и Продуктов для возможной сделки.

Подготовка:

  • Добавьте атрибут «new_name_en» «new_name_ru» на объект Продукта (и у Вас должны быть установлены оба эти языка);
  • При создании или обновлении Продукта, каждый из языков конкатенируется в поле Название. Это сделано для того чтобы не выполнять дополнительные запросы, а все необходимые значения были доступны сразу. Каждый раз при запросе Названия мы будем парсить его, вычленять название на нужном языке и перезаписываем его в Называние. Поэтому увеличьте длину Названия до 4000 символов.

Итак:

  • Создайте плагин с таким кодом:
    using System;
    using System.Collections.Generic;
    using System.Text;
    using System.ServiceModel;
    using Microsoft.Xrm.Sdk;
    using Microsoft.Xrm.Sdk.Query;
    
    namespace MultiLanguage
    {
        public class PackNameTranslations : IPlugin 
        {
            private readonly string[] languages = new string[] { "ru", "en" }; // Возможные языки
            static public int[] locales = new int[] { 1049, 1033 }; // LCID'ы каждого из языков
            
            // При создании или обновлении Продукта конкатенируем названия на разных языках в поле name
            public void Execute(IServiceProvider serviceProvider)
            {
                IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
                Entity target = context.InputParameters["Target"] as Entity;
                Entity preImage = (context.PreEntityImages != null && context.PreEntityImages.Contains("PreImage")) ? context.PreEntityImages["PreImage"] : null;
    
                string[] names = new string[languages.Length];
    
                for (int i = 0; i < languages.Length; i++)
                    names[i] = Common.GetAttributeValue("new_name_" + languages[i], preImage, target);
    
                target["name"] = string.Join(",", names);
            }
        }
    
        public class UnpackNameOnRetrieve : IPlugin
        {
            // Подставляем нужное название при возвращении продукта
            public void Execute(IServiceProvider serviceProvider)
            {
                IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
                Entity target = (Entity)context.OutputParameters["BusinessEntity"];
    
                // Разделяем языки
                string[] labels = ((string)target["name"]).Split(',');
                // Возвращаем индек нужного языка
                int labelIndex = Common.LanguageIndex(context, serviceProvider);
    
                // Перезаписываем поле Навзание
                target["name"] = labels[labelIndex];
            }
        }
    
        public class UnpackNameOnRetrieveMultiple : IPlugin
        {
            // Подставляем нужное название при возвращении множества Продуктов
            public void Execute(IServiceProvider serviceProvider)
            {
                IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
                EntityCollection collection = (EntityCollection)context.OutputParameters["BusinessEntityCollection"];
    
                // Возвращаем индек нужного языка
                int labelIndex = Common.LanguageIndex(context, serviceProvider);
    
                foreach (Entity e in collection.Entities)
                    if (e.Attributes.ContainsKey("name"))
                    {
                        // Разделяем языки
                        string[] labels = ((string)e["name"]).Split(',');
                        // Перезаписываем поле Навзание
                        e["name"] = labels[labelIndex];
                    }
            }
        }
    
        public class UnpackNameOnRetrieveMultipleRelated : IPlugin
        {
            // Подставляем нужное название в столбец Название при отображении связанных Продуктой для возможных сделок
            public void Execute(IServiceProvider serviceProvider)
            {
                IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
                EntityCollection collection = (EntityCollection)context.OutputParameters["BusinessEntityCollection"];
    
                // Возвращаем индек нужного языка
                int labelIndex = Common.LanguageIndex(context, serviceProvider);
    
                foreach (Entity e in collection.Entities)
                    if (e.Attributes.ContainsKey("productid"))
                    {
                        // Разделяем языки
                        string[] labels = (((EntityReference)e["productid"]).Name).Split(',');
                        // Перезаписываем  Навзание
                        ((EntityReference)e["productid"]).Name = labels[labelIndex];
                    }
            }
        }
    
        public class UnpackNameOnRetrieveRelated : IPlugin
        {
            // Unpack the product lookup name when Opportunity Products are retrieved via lookup searches or advanced find
            public void Execute(IServiceProvider serviceProvider)
            {
                IPluginExecutionContext context = (IPluginExecutionContext)serviceProvider.GetService(typeof(IPluginExecutionContext));
                Entity target = (Entity)context.OutputParameters["BusinessEntity"];
    
                if (target.Attributes.ContainsKey("productid"))
                {
                    // Разделяем языки
                    string[] labels = (((EntityReference)target["productid"]).Name).Split(',');
                    // Возвращаем индек нужного языка
                    int labelIndex = Common.LanguageIndex(context, serviceProvider); 
                    // Подменяем Название
                    ((EntityReference)target["productid"]).Name = labels[labelIndex];
                }
            }
        }
    
        public class Common
        {
            // Разбиваем название на состовляющие и возвращаем на нужно языке
            public static int LanguageIndex(IPluginExecutionContext context, IServiceProvider serviceProvider)
            {
                IOrganizationServiceFactory serviceFactory = (IOrganizationServiceFactory)serviceProvider.GetService(typeof(IOrganizationServiceFactory));
                IOrganizationService service = serviceFactory.CreateOrganizationService(context.UserId);
    
                // Получаем язык текущего пользователя
                int userLanguageId = 0;
                // ... либо из контекста (если есть)
                if (context.SharedVariables.ContainsKey("UserLocaleId"))
                {
                    userLanguageId = (int)context.SharedVariables["UserLocaleId"];
                }
                // ... либо из личных настроек пользователя
                else
                {
                    Entity userSettings = service.Retrieve("usersettings", context.InitiatingUserId, new ColumnSet("uilanguageid"));
                    userLanguageId = (int)userSettings.Attributes["uilanguageid"];
                }
    
                // Определяем порядковый номер языка из массива и возвращаем его
                return Array.IndexOf(PackNameTranslations.locales, userLanguageId);
            }
    
            public static string GetAttributeValue(string attributeName, Entity preImage, Entity targetImage)
            {
                if (targetImage.Contains(attributeName))
                {
                    return (string)targetImage[attributeName];
                }
                else if (preImage != null)
                    return (string)preImage[attributeName];
                else
                    return "";
            }
        }
    }
    

    Тут у нас несколько функций. Пять полезных и две вспомогательные. Полезные регистрируются на разные событий системы и на разные объекты (в которых так или иначе задействован Продукт) и выполняют парсинг. А вспомогательные: одна определяет язык текущего пользователя, а вторая возвращает значений из заполенного Entity (таргета или пре-снимка);

  • Подпишите сборку и подключите к проекту «обычные» библиотеки;
  • Регистрируем плагин:
    • PackNameTranslations:
      • Событие: Create, Update
      • Стадия: Pre
      • Объект: product
    • UnpackNameOnRetrieve
      • Событие: Retrieve
      • Стадия: Post
      • Объект: product
    • UnpackNameOnRetrieveMultiple
      • Событие: RetrieveMultiple
      • Стадия: Post
      • Объект: product
    • UnpackNameOnRetrieveRelated
      • Событие: Retrieve
      • Стадия: Post
      • Объект: opportunityproduct
    • UnpackNameOnRetrieveMultipleRelated
      • Событие: RetrieveMultiple
      • Стадия: Post
      • Объект: opportunityproduct

Готово.

По аналогии можете зарегистрировать UnpackNameOnRetrieveRelated и UnpackNameOnRetrieveMultipleRelated для Предложений, Заказов и Прайс листов.



Комментарии (0)

*

code