среда, 12 сентября 2012 г.

Создание многоязычного сайта в Composite C1 CMS (9). Поля без локализации

Итак, вы знаете, что в Composite C1 можно осуществлять локализацию динамических данных. В этом случае каждый элемент данных будет иметь копию для каждого языка сайта.

После перевода копии такого элемента данных, она (копия) начинает жить своей жизнью. То есть изменения в поле элемента данных на одном языке не будут отражаться на значении этого поля на другом языке. Копии будет объединять только идентификатор, который будет один и тот же для всех языковых копий.

Именно благодаря этому вы можете создать тип данных, например, "Города" и хранить там названия городов - для каждой языковой копии сайта на его языке.

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

И если такое значение изменить в элементе данных на одном языке, то его нужно будет изменить для того же значения на других языках. Хорошо, если такое "внеязыковое", "общее" поле одно в типе данных, и изменить нужно пару элементов данных, и языков на сайте два.

А если в типе данных несколько таких "общих" полей? И элементов, где нужно эти поля менять несколько десятков или сотен? Да и сайт переведен на 10 языков?

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

В Composite C1 CMS на уровне поля не предусмотрена локализация, только на уровне типа данных. (Вы, кстати, можете проголосовать за запрашиваемую функцию локализации полей здесь.)

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

Вам просто нужно подписаться на событие OnAfterUpdate для нужного типа данных и в обработчике этого события пройтись по языковым копиям изменяемого элемента, сохраняя одинаковое значение для нужного поля.

(Пример далее взят из официального FAQ: How can I update a field across languages?)

Создайте глобальный тип данных с локализацией, у которого одно поле будет общим для всех языковых версий:
  1. В разделе "Данные" создайте тип данных:
    1. Название: Города
    2. Имя типа: City
    3. Пространство имен типа: Demo
  2. Также на вкладке "Настройке" поставьте "птичку" в опции "Поддержка локализации".
  3. Добавьте поля:
    1. Имя: Name
      1. Надпись: Название
      2. Тип поля: Строка
    2. Имя: Population
      1. Надпись: Население
      2. Тип поля: Целое число
    3. Имя: Country
      1. Надпись: Страна
      2. Тип поля: Строка
  4. Сохраните тип данных.
  5. Добавьте один или больше элементов данных в этот тип.
  6. Переключитесь в другой язык и переведите добавленные элементы на соответствующий язык.
Теперь мы решили, что у нашего типа данных должно быть общим (без локализации) поле "Население" (Population). Мы хотим, чтобы меняя значение этого поля у одного элемента в одном языке, мы получали такое же значение этого поля и для других языков автоматически:
  1. В папке /App_Code вашего сайта создайте .cs-файл, например, UpdateGlobalFields.cs.
  2. Добавьте в этот файл такой код:


    using System;
    using System.Globalization;
    using System.Linq;
    using Composite.Core.Application;
    using Composite.Data;
    using Composite.Data.Types;
    using Composite.Data.ProcessControlled;
    namespace Samples
    {
        [ApplicationStartup]
        public class UpdateGlobalFields
        {
            public UpdateGlobalFields()
            {
            }

            public static void OnBeforeInitialize()
            {
            }

            public static void OnInitialized()
            {
                DataEvents<Samples.City>.OnAfterUpdate += new DataEventHandler(OnAfterUpdateHandler);
            }

            private static void  OnAfterUpdateHandler(object sender, DataEventArgs dataEventArgs)
            {
                if (LocalizedDataUpdateManager.IsBeingUpdated)
                    return;

                // избегаем бесконечного цикла обновления
                using  (new LocalizedDataUpdateManager())
                {
                    Samples.City updatedCity = (Samples.City)dataEventArgs.Data;

                    // убеждаемся, что типа данных поддерживает локализацию
                    if  (updatedCity is ILocalizedControlled)
                    {
                        foreach  (CultureInfo ci in DataLocalizationFacade.ActiveLocalizationCultures)
                        {
                            // не обновляем значение общего поля для текущего языка
                            if  ((updatedCity as ILocalizedControlled).CultureName == ci.Name)
                                continue;
                            using  (DataConnection connection = new DataConnection(ci))
                            {
                                Samples.City city =
                                    (from c in connection.Get<Samples.City>()
                                     where c.Id == updatedCity.Id
                                     select c).FirstOrDefault();
                                // убеждаемся, что элемент данных существует
                                if  (city != null)
                                {
                                    city.Population = updatedCity.Population;
                                    connection.Update<Samples.City>(city);
                                }
                            }
                        }
                    }
                }
            }
        }



    // используется для избежания зацикливания при обновлении данных 


        internal class LocalizedDataUpdateManager : IDisposable
        {
            [ThreadStatic]
            private static int _counter = 0;
            public static bool IsBeingUpdated
            {
                get
                {
                    return _counter > 0;
                }
            }
            public LocalizedDataUpdateManager()
            {
                _counter++;
            }
            public void Dispose()
            {
                _counter--;
            }
        }
    }
  3. Сохраните файл.
Можете проверить:
  1. Измените значение поля "Население" у элемента данных на одном языке.
  2. Переключитесь на другой язык и проверьте значение в этом же поле. Оно должно измениться соответственно.

Предыдущие сообщения:

Комментариев нет:

Отправить комментарий