Gogs 3 周之前
父節點
當前提交
2e604181de
共有 2 個文件被更改,包括 510 次插入102 次删除
  1. 241 23
      README.md
  2. 269 79
      scripts/design-documents.coffee

+ 241 - 23
README.md

@@ -1,5 +1,6 @@
 # Текущая ззадача
-доработай design-documents.coffee, добавь мультиязычность в документы, и обнови описание всех хранимых объектов.
+доработай seed-events.coffee, для удаления старых версий документов, и создай новые тестовые документы для сайта.
+минимум 6 постов и мероприятий, также 6 сладеров 
 
 # файл с правилами
 https://gogs.osvoj.ru/s5l.ru/borbad.s5l.ru/raw/master/README.md
@@ -235,47 +236,66 @@ app/
             ├── index.styl
 
 # Структура хранимых данных
-## Базовый объект "Запись блога"
+## Описание всех хранимых объектов с мультиязычностью
+1. Настройки домена (domain_settings)
+coffee
+{
+    _id: String                    # Уникальный идентификатор (domain_settings_[domain])
+    type: 'domain_settings'        # Тип документа
+    domain: String                 # Доменное имя (borbad.s5l.ru)
+    name: String                   # Название сайта
+    description: String            # Описание сайта
+    active: Boolean                # Активен ли домен
+    priority: Number               # Приоритет домена
+    theme: String                  # Тема оформления
+    languages: Array[String]       # Поддерживаемые языки ['ru', 'en', 'tj']
+    default_language: String       # Язык по умолчанию
+    timezone: String               # Часовой пояс
+    currency: String               # Валюта по умолчанию
+    settings: Object               # Дополнительные настройки
+    created_at: ISOString          # Дата создания
+    updated_at: ISOString          # Дата обновления
+}
+2. Запись блога (blog_post) с мультиязычностью
 coffee
 {
     _id: String                    # Уникальный идентификатор
     type: 'blog_post'              # Тип записи
+    domain: String                 # Домен
+    language: String               # Язык контента ('ru', 'en', 'tj')
+    translation_of: String         # ID исходного документа для переводов
+    translation_status: String     # Статус перевода ('draft', 'review', 'published')
     title: String                  # Заголовок
     content: String                # Основной текст в Markdown
     excerpt: String                # Краткое описание
     image: String                  # Главное изображение
     tags: Array[String]            # Теги для категоризации
+    category_id: String            # ID категории
     author: String                 # Автор записи
     status: 'published' | 'draft'  # Статус публикации
+    meta_title: String             # SEO заголовок
+    meta_description: String       # SEO описание
+    featured: Boolean              # Избранная запись
     created_at: ISOString          # Дата создания
     updated_at: ISOString          # Дата обновления
+    published_at: ISOString        # Дата публикации
     views: Number                  # Количество просмотров
 }
-## Наследник "Слайд"
+3. Мероприятие (event) с мультиязычностью
 coffee
 {
-    _id: String
-    type: 'slide'
-    title: String
-    content: String                # Markdown контент
-    image: String                  # Фоновое изображение
-    order: Number                  # Порядок отображения
-    active: Boolean                # Активен ли слайд
-    button_text: String            # Текст кнопки
-    button_link: String            # Ссылка кнопки
-    created_at: ISOString
-    updated_at: ISOString
-}
-## Наследник "Мероприятие"
-coffee
-{
-    _id: String
-    type: 'event'
-    title: String
+    _id: String                    # Уникальный идентификатор
+    type: 'event'                  # Тип документа
+    domain: String                 # Домен
+    language: String               # Язык контента
+    translation_of: String         # ID исходного документа
+    translation_status: String     # Статус перевода
+    title: String                  # Заголовок мероприятия
     content: String                # Markdown описание мероприятия
     event_date: ISOString          # Дата и время мероприятия
     end_date: ISOString            # Дата и время окончания
     location: String               # Место проведения
+    venue_id: String               # ID места проведения
     price: Number                  # Стоимость билета
     currency: String               # Валюта (TJS, USD, etc.)
     available_tickets: Number      # Количество доступных билетов
@@ -283,10 +303,207 @@ coffee
     image: String                  # Изображение мероприятия
     gallery: Array[String]         # Галерея изображений
     tags: Array[String]            # Теги (концерт, выставка, etc.)
+    category_id: String            # ID категории
     status: 'upcoming' | 'ongoing' | 'completed' | 'cancelled'
     registration_required: Boolean # Требуется ли регистрация
-    created_at: ISOString
-    updated_at: ISOString
+    max_attendees: Number          # Максимальное количество участников
+    age_restriction: String        # Возрастные ограничения
+    created_at: ISOString          # Дата создания
+    updated_at: ISOString          # Дата обновления
+}
+4. Слайд (slide) с мультиязычностью
+coffee
+{
+    _id: String                    # Уникальный идентификатор
+    type: 'slide'                  # Тип документа
+    domain: String                 # Домен
+    language: String               # Язык контента
+    translation_of: String         # ID исходного документа
+    translation_status: String     # Статус перевода
+    title: String                  # Заголовок слайда
+    content: String                # Markdown контент
+    image: String                  # Фоновое изображение
+    order: Number                  # Порядок отображения
+    active: Boolean                # Активен ли слайд
+    button_text: String            # Текст кнопки
+    button_link: String            # Ссылка кнопки
+    text_color: String             # Цвет текста
+    overlay: Boolean               # Наложение на изображение
+    created_at: ISOString          # Дата создания
+    updated_at: ISOString          # Дата обновления
+}
+5. Товар (product) с мультиязычностью
+coffee
+{
+    _id: String                    # Уникальный идентификатор
+    type: 'product'                # Тип документа
+    domain: String                 # Домен
+    language: String               # Язык контента
+    translation_of: String         # ID исходного документа
+    translation_status: String     # Статус перевода
+    title: String                  # Название товара
+    content: String                # Markdown описание
+    excerpt: String                # Краткое описание
+    image: String                  # Главное изображение
+    gallery: Array[String]         # Галерея изображений
+    price: Number                  # Цена
+    currency: String               # Валюта
+    compare_price: Number          # Старая цена (для акций)
+    category_id: String            # ID категории
+    tags: Array[String]            # Теги
+    attributes: Object             # Атрибуты товара
+    inventory: Number              # Количество на складе
+    sku: String                    # Артикул
+    status: 'available' | 'out_of_stock' | 'discontinued'
+    featured: Boolean              # Рекомендуемый товар
+    weight: Number                 # Вес
+    dimensions: Object             # Размеры
+    created_at: ISOString          # Дата создания
+    updated_at: ISOString          # Дата обновления
+}
+6. Категория (category) с мультиязычностью
+coffee
+{
+    _id: String                    # Уникальный идентификатор
+    type: 'category'               # Тип документа
+    domain: String                 # Домен
+    language: String               # Язык контента
+    translation_of: String         # ID исходного документа
+    translation_status: String     # Статус перевода
+    name: String                   # Название категории
+    slug: String                   # URL-адрес
+    description: String            # Описание категории
+    image: String                  # Изображение категории
+    parent_id: String              # ID родительской категории
+    order: Number                  # Порядок отображения
+    meta_title: String             # SEO заголовок
+    meta_description: String       # SEO описание
+    active: Boolean                # Активна ли категория
+    created_at: ISOString          # Дата создания
+    updated_at: ISOString          # Дата обновления
+}
+7. Тема (theme) с мультиязычностью
+coffee
+{
+    _id: String                    # Уникальный идентификатор
+    type: 'theme'                  # Тип документа
+    domain: String                 # Домен
+    language: String               # Язык контента
+    translation_of: String         # ID исходного документа
+    translation_status: String     # Статус перевода
+    name: String                   # Название темы
+    slug: String                   # URL-адрес
+    description: String            # Описание темы
+    color: String                  # Цвет темы
+    image: String                  # Изображение темы
+    order: Number                  # Порядок отображения
+    active: Boolean                # Активна ли тема
+    created_at: ISOString          # Дата создания
+    updated_at: ISOString          # Дата обновления
+}
+8. Страница (page) с мультиязычностью
+coffee
+{
+    _id: String                    # Уникальный идентификатор
+    type: 'page'                   # Тип документа
+    domain: String                 # Домен
+    language: String               # Язык контента
+    translation_of: String         # ID исходного документа
+    translation_status: String     # Статус перевода
+    title: String                  # Заголовок страницы
+    slug: String                   # URL-адрес
+    content: String                # Markdown контент
+    excerpt: String                # Краткое описание
+    image: String                  # Изображение страницы
+    parent_id: String              # ID родительской страницы
+    order: Number                  # Порядок отображения
+    template: String               # Шаблон страницы
+    meta_title: String             # SEO заголовок
+    meta_description: String       # SEO описание
+    status: 'published' | 'draft'  # Статус публикации
+    protected: Boolean             # Защищенная страница
+    created_at: ISOString          # Дата создания
+    updated_at: ISOString          # Дата обновления
+}
+9. Меню (menu) с мультиязычностью
+coffee
+{
+    _id: String                    # Уникальный идентификатор
+    type: 'menu'                   # Тип документа
+    domain: String                 # Домен
+    language: String               # Язык контента
+    translation_of: String         # ID исходного документа
+    translation_status: String     # Статус перевода
+    name: String                   # Название меню
+    location: String               # Расположение (header, footer, etc.)
+    active: Boolean                # Активно ли меню
+    items: Array[Object]           # Элементы меню
+    created_at: ISOString          # Дата создания
+    updated_at: ISOString          # Дата обновления
+}
+10. Пользователь (user)
+coffee
+{
+    _id: String                    # Уникальный идентификатор
+    type: 'user'                   # Тип документа
+    email: String                  # Email пользователя
+    name: String                   # Имя пользователя
+    role: String                   # Роль (admin, editor, user)
+    active: Boolean                # Активен ли пользователь
+    permissions: Array[String]     # Права доступа
+    profile: Object                # Профиль пользователя
+    preferences: Object            # Настройки пользователя
+    language: String               # Предпочитаемый язык
+    created_at: ISOString          # Дата создания
+    updated_at: ISOString          # Дата обновления
+    last_login: ISOString          # Дата последнего входа
+}
+11. Заказ (order)
+coffee
+{
+    _id: String                    # Уникальный идентификатор
+    type: 'order'                  # Тип документа
+    domain: String                 # Домен
+    language: String               # Язык заказа
+    user_id: String                # ID пользователя
+    status: String                 # Статус заказа
+    total: Number                  # Общая сумма
+    currency: String               # Валюта
+    items: Array[Object]           # Элементы заказа
+    customer_info: Object          # Информация о клиенте
+    payment_info: Object           # Информация об оплате
+    shipping_info: Object          # Информация о доставке
+    created_at: ISOString          # Дата создания
+    updated_at: ISOString          # Дата обновления
+}
+12. Настройка (setting)
+coffee
+{
+    _id: String                    # Уникальный идентификатор
+    type: 'setting'                # Тип документа
+    domain: String                 # Домен
+    language: String               # Язык настройки
+    key: String                    # Ключ настройки
+    value: Object                  # Значение настройки
+    is_global: Boolean             # Глобальная настройка
+    description: String            # Описание настройки
+    created_at: ISOString          # Дата создания
+    updated_at: ISOString          # Дата обновления
+}
+13. Аудит (audit_log)
+coffee
+{
+    _id: String                    # Уникальный идентификатор
+    type: 'audit_log'              # Тип документа
+    user_id: String                # ID пользователя
+    action: String                 # Действие
+    resource_type: String          # Тип ресурса
+    resource_id: String            # ID ресурса
+    description: String            # Описание действия
+    ip_address: String             # IP адрес
+    user_agent: String             # User Agent
+    language: String               # Язык действия
+    created_at: ISOString          # Дата создания
 }
 
 ## Пример документа настроек домена
@@ -318,6 +535,7 @@ domainSettingsExample =
             email: "info@borbad.s5l.ru"
     created_at: new Date().toISOString()
     updated_at: new Date().toISOString()
+
 ## Пример документа страницы
 pageExample =
     _id: "page_about_borbad"

+ 269 - 79
scripts/design-documents.coffee

@@ -1,9 +1,9 @@
-# Design документы для CouchDB с поддержкой мультидоменности
+# Design документы для CouchDB с поддержкой мультидоменности и мультиязычности
 
 module.exports =
     # Design документ для настроек доменов
     domains:
-        version: "2.0"
+        version: "3.0"
         views:
             # Все настройки доменов
             all_domains:
@@ -26,231 +26,353 @@ module.exports =
                         emit(doc.priority or 0, doc)
                 ).toString()
 
-    # Design документ для блог постов с мультидоменностью
+    # Design документ для блог постов с мультидоменностью и мультиязычностью
     blog_posts:
-        version: "2.0"
+        version: "3.0"
         views:
-            # Все опубликованные блог посты с фильтром по домену
+            # Все опубликованные блог посты с фильтром по домену и языку
             published:
                 map: ((doc) ->
                     if doc.type is 'blog_post' and doc.status is 'published'
                         domain = doc.domain or 'default'
-                        emit([domain, doc.created_at], doc)
+                        language = doc.language or 'ru'
+                        emit([domain, language, doc.created_at], doc)
                 ).toString()
             
-            # Блог посты по тегам с фильтром по домену
+            # Блог посты по тегам с фильтром по домену и языку
             by_tag:
                 map: ((doc) ->
                     if doc.type is 'blog_post' and doc.status is 'published' and doc.tags
                         domain = doc.domain or 'default'
+                        language = doc.language or 'ru'
                         for tag in doc.tags
-                            emit([domain, tag, doc.created_at], doc)
+                            emit([domain, language, tag, doc.created_at], doc)
                 ).toString()
             
-            # Блог посты по автору с фильтром по домену
+            # Блог посты по автору с фильтром по домену и языку
             by_author:
                 map: ((doc) ->
                     if doc.type is 'blog_post' and doc.status is 'published'
                         domain = doc.domain or 'default'
-                        emit([domain, doc.author, doc.created_at], doc)
+                        language = doc.language or 'ru'
+                        emit([domain, language, doc.author, doc.created_at], doc)
                 ).toString()
             
-            # Поиск по заголовку и содержанию с фильтром по домену
+            # Блог посты по категории с фильтром по домену и языку
+            by_category:
+                map: ((doc) ->
+                    if doc.type is 'blog_post' and doc.status is 'published' and doc.category_id
+                        domain = doc.domain or 'default'
+                        language = doc.language or 'ru'
+                        emit([domain, language, doc.category_id, doc.created_at], doc)
+                ).toString()
+            
+            # Переводы блог постов
+            translations:
+                map: ((doc) ->
+                    if doc.type is 'blog_post' and doc.translation_of
+                        domain = doc.domain or 'default'
+                        language = doc.language or 'ru'
+                        emit([domain, doc.translation_of, language], doc)
+                ).toString()
+            
+            # Поиск по заголовку и содержанию с фильтром по домену и языку
             search:
                 map: ((doc) ->
                     if doc.type is 'blog_post' and doc.status is 'published'
                         domain = doc.domain or 'default'
+                        language = doc.language or 'ru'
                         text = (doc.title + " " + doc.content + " " + doc.excerpt).toLowerCase()
                         words = text.split(/\W+/).filter (word) -> word.length > 2
                         
                         for word in words
-                            emit([domain, word], {
+                            emit([domain, language, word], {
                                 _id: doc._id
                                 title: doc.title
                                 excerpt: doc.excerpt
                                 created_at: doc.created_at
                                 domain: doc.domain
+                                language: doc.language
                             })
                 ).toString()
 
-    # Design документ для мероприятий с мультидоменностью
+    # Design документ для мероприятий с мультидоменностью и мультиязычностью
     events:
-        version: "2.0"
+        version: "3.0"
         views:
-            # Все мероприятия по дате с фильтром по домену
+            # Все мероприятия по дате с фильтром по домену и языку
             by_date:
                 map: ((doc) ->
                     if doc.type is 'event'
                         domain = doc.domain or 'default'
-                        emit([domain, doc.event_date], doc)
+                        language = doc.language or 'ru'
+                        emit([domain, language, doc.event_date], doc)
                 ).toString()
             
-            # Предстоящие мероприятия с фильтром по домену
+            # Предстоящие мероприятия с фильтром по домену и языку
             upcoming:
                 map: ((doc) ->
                     if doc.type is 'event' and doc.status is 'upcoming'
                         domain = doc.domain or 'default'
-                        emit([domain, doc.event_date], doc)
+                        language = doc.language or 'ru'
+                        emit([domain, language, doc.event_date], doc)
                 ).toString()
             
-            # Активные мероприятия с фильтром по домену
+            # Активные мероприятия с фильтром по домену и языку
             ongoing:
                 map: ((doc) ->
                     if doc.type is 'event' and doc.status is 'ongoing'
                         domain = doc.domain or 'default'
-                        emit([domain, doc.event_date], doc)
+                        language = doc.language or 'ru'
+                        emit([domain, language, doc.event_date], doc)
                 ).toString()
             
-            # Мероприятия по тегам с фильтром по домену
+            # Мероприятия по тегам с фильтром по домену и языку
             by_tag:
                 map: ((doc) ->
                     if doc.type is 'event' and doc.tags
                         domain = doc.domain or 'default'
+                        language = doc.language or 'ru'
                         for tag in doc.tags
-                            emit([domain, tag, doc.event_date], doc)
+                            emit([domain, language, tag, doc.event_date], doc)
                 ).toString()
             
-            # Мероприятия по местоположению с фильтром по домену
+            # Мероприятия по местоположению с фильтром по домену и языку
             by_location:
                 map: ((doc) ->
                     if doc.type is 'event'
                         domain = doc.domain or 'default'
-                        emit([domain, doc.location, doc.event_date], doc)
+                        language = doc.language or 'ru'
+                        emit([domain, language, doc.location, doc.event_date], doc)
+                ).toString()
+            
+            # Переводы мероприятий
+            translations:
+                map: ((doc) ->
+                    if doc.type is 'event' and doc.translation_of
+                        domain = doc.domain or 'default'
+                        language = doc.language or 'ru'
+                        emit([domain, doc.translation_of, language], doc)
                 ).toString()
 
-    # Design документ для слайдов с мультидоменностью
+    # Design документ для слайдов с мультидоменностью и мультиязычностью
     slides:
-        version: "2.0"
+        version: "3.0"
         views:
-            # Активные слайды по порядку с фильтром по домену
+            # Активные слайды по порядку с фильтром по домену и языку
             active_ordered:
                 map: ((doc) ->
                     if doc.type is 'slide' and doc.active is true
                         domain = doc.domain or 'default'
-                        emit([domain, doc.order], doc)
+                        language = doc.language or 'ru'
+                        emit([domain, language, doc.order], doc)
+                ).toString()
+            
+            # Переводы слайдов
+            translations:
+                map: ((doc) ->
+                    if doc.type is 'slide' and doc.translation_of
+                        domain = doc.domain or 'default'
+                        language = doc.language or 'ru'
+                        emit([domain, doc.translation_of, language], doc)
                 ).toString()
 
-    # Design документ для товаров с мультидоменностью
+    # Design документ для товаров с мультидоменностью и мультиязычностью
     products:
-        version: "2.0"
+        version: "3.0"
         views:
-            # Все доступные товары с фильтром по домену
+            # Все доступные товары с фильтром по домену и языку
             available:
                 map: ((doc) ->
                     if doc.type is 'product' and doc.status is 'available'
                         domain = doc.domain or 'default'
-                        emit([domain, doc.created_at], doc)
+                        language = doc.language or 'ru'
+                        emit([domain, language, doc.created_at], doc)
                 ).toString()
             
-            # Товары по категориям с фильтром по домену
+            # Товары по категориям с фильтром по домену и языку
             by_category:
                 map: ((doc) ->
                     if doc.type is 'product' and doc.status is 'available'
                         domain = doc.domain or 'default'
-                        emit([domain, doc.category, doc.created_at], doc)
+                        language = doc.language or 'ru'
+                        emit([domain, language, doc.category_id, doc.created_at], doc)
                 ).toString()
             
-            # Товары по тегам с фильтром по домену
+            # Товары по тегам с фильтром по домену и языку
             by_tag:
                 map: ((doc) ->
                     if doc.type is 'product' and doc.tags
                         domain = doc.domain or 'default'
+                        language = doc.language or 'ru'
                         for tag in doc.tags
-                            emit([domain, tag, doc.created_at], doc)
+                            emit([domain, language, tag, doc.created_at], doc)
                 ).toString()
             
-            # Товары по цене с фильтром по домену
+            # Товары по цене с фильтром по домену и языку
             by_price:
                 map: ((doc) ->
                     if doc.type is 'product' and doc.status is 'available'
                         domain = doc.domain or 'default'
-                        emit([domain, doc.price], doc)
+                        language = doc.language or 'ru'
+                        emit([domain, language, doc.price], doc)
+                ).toString()
+            
+            # Переводы товаров
+            translations:
+                map: ((doc) ->
+                    if doc.type is 'product' and doc.translation_of
+                        domain = doc.domain or 'default'
+                        language = doc.language or 'ru'
+                        emit([domain, doc.translation_of, language], doc)
                 ).toString()
 
-    # Design документ для категорий и тем с мультидоменностью
+    # Design документ для категорий и тем с мультидоменностью и мультиязычностью
     categories_themes:
-        version: "2.0"
+        version: "3.0"
         views:
-            # Все категории по порядку с фильтром по домену
+            # Все категории по порядку с фильтром по домену и языку
             categories_ordered:
                 map: ((doc) ->
                     if doc.type is 'category'
                         domain = doc.domain or 'default'
-                        emit([domain, doc.order], doc)
+                        language = doc.language or 'ru'
+                        emit([domain, language, doc.order], doc)
                 ).toString()
             
-            # Категории по родителю с фильтром по домену
+            # Категории по родителю с фильтром по домену и языку
             categories_by_parent:
                 map: ((doc) ->
                     if doc.type is 'category'
                         domain = doc.domain or 'default'
-                        parent = doc.parent or 'root'
-                        emit([domain, parent, doc.order], doc)
+                        language = doc.language or 'ru'
+                        parent = doc.parent_id or 'root'
+                        emit([domain, language, parent, doc.order], doc)
                 ).toString()
             
-            # Все темы с фильтром по домену
+            # Все темы с фильтром по домену и языку
             themes:
                 map: ((doc) ->
                     if doc.type is 'theme'
                         domain = doc.domain or 'default'
-                        emit([domain, doc.name], doc)
+                        language = doc.language or 'ru'
+                        emit([domain, language, doc.name], doc)
+                ).toString()
+            
+            # Переводы категорий
+            category_translations:
+                map: ((doc) ->
+                    if doc.type is 'category' and doc.translation_of
+                        domain = doc.domain or 'default'
+                        language = doc.language or 'ru'
+                        emit([domain, doc.translation_of, language], doc)
+                ).toString()
+            
+            # Переводы тем
+            theme_translations:
+                map: ((doc) ->
+                    if doc.type is 'theme' and doc.translation_of
+                        domain = doc.domain or 'default'
+                        language = doc.language or 'ru'
+                        emit([domain, doc.translation_of, language], doc)
                 ).toString()
 
-    # Design документ для страниц с мультидоменностью
+    # Design документ для страниц с мультидоменностью и мультиязычностью
     pages:
-        version: "2.0"
+        version: "3.0"
         views:
-            # Все страницы по slug с фильтром по домену
+            # Все страницы по slug с фильтром по домену и языку
             by_slug:
                 map: ((doc) ->
                     if doc.type is 'page'
                         domain = doc.domain or 'default'
-                        emit([domain, doc.slug], doc)
+                        language = doc.language or 'ru'
+                        emit([domain, language, doc.slug], doc)
                 ).toString()
             
-            # Опубликованные страницы с фильтром по домену
+            # Опубликованные страницы с фильтром по домену и языку
             published:
                 map: ((doc) ->
                     if doc.type is 'page' and doc.status is 'published'
                         domain = doc.domain or 'default'
-                        emit([domain, doc.order or 0], doc)
+                        language = doc.language or 'ru'
+                        emit([domain, language, doc.order or 0], doc)
+                ).toString()
+            
+            # Страницы по родителю с фильтром по домену и языку
+            by_parent:
+                map: ((doc) ->
+                    if doc.type is 'page'
+                        domain = doc.domain or 'default'
+                        language = doc.language or 'ru'
+                        parent = doc.parent_id or 'root'
+                        emit([domain, language, parent, doc.order or 0], doc)
+                ).toString()
+            
+            # Переводы страниц
+            translations:
+                map: ((doc) ->
+                    if doc.type is 'page' and doc.translation_of
+                        domain = doc.domain or 'default'
+                        language = doc.language or 'ru'
+                        emit([domain, doc.translation_of, language], doc)
                 ).toString()
 
-    # Design документ для меню с мультидоменностью
+    # Design документ для меню с мультидоменностью и мультиязычностью
     menus:
-        version: "2.0"
+        version: "3.0"
         views:
-            # Меню по локации с фильтром по домену
+            # Меню по локации с фильтром по домену и языку
             by_location:
                 map: ((doc) ->
                     if doc.type is 'menu'
                         domain = doc.domain or 'default'
-                        emit([domain, doc.location], doc)
+                        language = doc.language or 'ru'
+                        emit([domain, language, doc.location], doc)
                 ).toString()
             
-            # Активные меню с фильтром по домену
+            # Активные меню с фильтром по домену и языку
             active:
                 map: ((doc) ->
                     if doc.type is 'menu' and doc.active is true
                         domain = doc.domain or 'default'
-                        emit([domain, doc.location], doc)
+                        language = doc.language or 'ru'
+                        emit([domain, language, doc.location], doc)
+                ).toString()
+            
+            # Переводы меню
+            translations:
+                map: ((doc) ->
+                    if doc.type is 'menu' and doc.translation_of
+                        domain = doc.domain or 'default'
+                        language = doc.language or 'ru'
+                        emit([domain, doc.translation_of, language], doc)
                 ).toString()
 
-    # Design документ для настроек с мультидоменностью
+    # Design документ для настроек с мультидоменностью и мультиязычностью
     settings:
-        version: "2.0"
+        version: "3.0"
         views:
-            # Настройки по ключу с фильтром по домену
+            # Настройки по ключу с фильтром по домену и языку
             by_key:
                 map: ((doc) ->
                     if doc.type is 'setting'
+                        domain = doc.domain or 'default'
+                        language = doc.language or 'ru'
+                        emit([domain, language, doc.key], doc)
+                ).toString()
+            
+            # Глобальные настройки (без привязки к языку)
+            global:
+                map: ((doc) ->
+                    if doc.type is 'setting' and doc.is_global is true
                         domain = doc.domain or 'default'
                         emit([domain, doc.key], doc)
                 ).toString()
 
     # Design документ для пользователей
     users:
-        version: "2.0"
+        version: "3.0"
         views:
             # Пользователи по email
             by_email:
@@ -272,10 +394,17 @@ module.exports =
                     if doc.type is 'user' and doc.active is true
                         emit(doc.email, doc)
                 ).toString()
+            
+            # Пользователи по языку предпочтения
+            by_language:
+                map: ((doc) ->
+                    if doc.type is 'user' and doc.preferences?.language
+                        emit(doc.preferences.language, doc)
+                ).toString()
 
     # Design документ для заказов с мультидоменностью
     orders:
-        version: "2.0"
+        version: "3.0"
         views:
             # Заказы по статусу с фильтром по домену
             by_status:
@@ -292,16 +421,54 @@ module.exports =
                         domain = doc.domain or 'default'
                         emit([domain, doc.user_id, doc.created_at], doc)
                 ).toString()
+            
+            # Заказы по языку
+            by_language:
+                map: ((doc) ->
+                    if doc.type is 'order'
+                        domain = doc.domain or 'default'
+                        language = doc.language or 'ru'
+                        emit([domain, language, doc.created_at], doc)
+                ).toString()
 
-    # Design документ для глобального поиска с мультидоменностью
+    # Design документ для переводов контента
+    translations:
+        version: "3.0"
+        views:
+            # Все переводы по исходному документу
+            by_source:
+                map: ((doc) ->
+                    if doc.translation_of
+                        domain = doc.domain or 'default'
+                        emit([domain, doc.translation_of, doc.language], doc)
+                ).toString()
+            
+            # Переводы по типу контента
+            by_content_type:
+                map: ((doc) ->
+                    if doc.translation_of
+                        domain = doc.domain or 'default'
+                        emit([domain, doc.type, doc.translation_of, doc.language], doc)
+                ).toString()
+            
+            # Статусы переводов
+            by_status:
+                map: ((doc) ->
+                    if doc.translation_of and doc.translation_status
+                        domain = doc.domain or 'default'
+                        emit([domain, doc.translation_status, doc.language], doc)
+                ).toString()
+
+    # Design документ для глобального поиска с мультидоменностью и мультиязычностью
     global_search:
-        version: "2.0"
+        version: "3.0"
         views:
-            # Глобальный поиск по всем типам документов с фильтром по домену
+            # Глобальный поиск по всем типам документов с фильтром по домену и языку
             all_content:
                 map: ((doc) ->
                     searchFields = {}
                     domain = doc.domain or 'default'
+                    language = doc.language or 'ru'
                     
                     switch doc.type
                         when 'blog_post'
@@ -363,59 +530,75 @@ module.exports =
                         words = text.split(/\W+/).filter (word) -> word.length > 2
                         
                         for word in words
-                            emit([domain, word], {
+                            emit([domain, language, word], {
                                 _id: doc._id
                                 type: searchFields.type
                                 title: searchFields.title
                                 excerpt: searchFields.excerpt
                                 created_at: doc.created_at
                                 domain: domain
+                                language: language
                             })
                 ).toString()
 
-    # Design документ для статистики с мультидоменностью
+    # Design документ для статистики с мультидоменностью и мультиязычностью
     statistics:
-        version: "2.0"
+        version: "3.0"
         views:
-            # Статистика по типам документов с фильтром по домену
+            # Статистика по типам документов с фильтром по домену и языку
             by_type:
                 map: ((doc) ->
                     domain = doc.domain or 'default'
-                    emit([domain, doc.type], 1)
+                    language = doc.language or 'ru'
+                    emit([domain, language, doc.type], 1)
                 ).toString()
                 reduce: ((keys, values) ->
                     sum values
                 ).toString()
             
-            # Статистика просмотров блог постов с фильтром по домену
+            # Статистика просмотров блог постов с фильтром по домену и языку
             blog_views:
                 map: ((doc) ->
                     if doc.type is 'blog_post'
                         domain = doc.domain or 'default'
-                        emit([domain, doc._id], doc.views or 0)
+                        language = doc.language or 'ru'
+                        emit([domain, language, doc._id], doc.views or 0)
                 ).toString()
                 reduce: ((keys, values) ->
                     sum values
                 ).toString()
             
-            # Статистика мероприятий по статусу с фильтром по домену
+            # Статистика мероприятий по статусу с фильтром по домену и языку
             events_by_status:
                 map: ((doc) ->
                     if doc.type is 'event'
                         domain = doc.domain or 'default'
-                        emit([domain, doc.status], 1)
+                        language = doc.language or 'ru'
+                        emit([domain, language, doc.status], 1)
                 ).toString()
                 reduce: ((keys, values) ->
                     sum values
                 ).toString()
             
-            # Статистика продаж товаров с фильтром по домену
+            # Статистика продаж товаров с фильтром по домену и языку
             product_sales:
                 map: ((doc) ->
                     if doc.type is 'order' and doc.items
                         domain = doc.domain or 'default'
+                        language = doc.language or 'ru'
                         for item in doc.items
-                            emit([domain, item.product_id], item.quantity)
+                            emit([domain, language, item.product_id], item.quantity)
+                ).toString()
+                reduce: ((keys, values) ->
+                    sum values
+                ).toString()
+            
+            # Статистика по языкам
+            by_language:
+                map: ((doc) ->
+                    if doc.language
+                        domain = doc.domain or 'default'
+                        emit([domain, doc.language, doc.type], 1)
                 ).toString()
                 reduce: ((keys, values) ->
                     sum values
@@ -423,7 +606,7 @@ module.exports =
 
     # Design документ для ревизий и аудита
     audit:
-        version: "2.0"
+        version: "3.0"
         views:
             # Логи изменений по дате
             by_date:
@@ -445,3 +628,10 @@ module.exports =
                     if doc.type is 'audit_log'
                         emit([doc.action, doc.created_at], doc)
                 ).toString()
+            
+            # Логи по языку
+            by_language:
+                map: ((doc) ->
+                    if doc.type is 'audit_log' and doc.language
+                        emit([doc.language, doc.created_at], doc)
+                ).toString()