# Компонент LanguageSwitcher - Полная документация ## Назначение компонента `LanguageSwitcher` - компонент для переключения языков интерфейса в мультиязычном приложении. Интегрируется с глобальной системой мультиязычности, обеспечивает удобный интерфейс выбора языка и сохраняет предпочтения пользователя. ## git репозитарий https://gogs.osvoj.ru/s5l.ru/borbad.s5l.ru/src/master/vue/app/shared/LanguageSwitcher/ ## Импорт и регистрация ```coffee # В основном файле приложения (app/temp.coffee) components: 'language-switcher': require 'app/shared/LanguageSwitcher' ``` ## Базовое использование ```pug //- Минимальное использование language-switcher //- В навигационной панели div(class="flex items-center space-x-4") language-switcher themetoggle ``` ## Полный список props ### `size` (опциональный) - **Тип:** `String` - **По умолчанию:** `'md'` - **Допустимые значения:** `'sm'`, `'md'`, `'lg'` - **Описание:** Размер переключателя - **Пример:** ```pug language-switcher(size="sm") language-switcher(size="lg") ``` ### `variant` (опциональный) - **Тип:** `String` - **По умолчанию:** `'dropdown'` - **Допустимые значения:** `'dropdown'`, `'buttons'`, `'select'`, `'flags'` - **Описание:** Вариант отображения переключателя - **Пример:** ```pug language-switcher(variant="buttons") language-switcher(variant="flags") ``` ### `showNativeNames` (опциональный) - **Тип:** `Boolean` - **По умолчанию:** `true` - **Описание:** Показывать названия на родном языке - **Пример:** ```pug language-switcher(:showNativeNames="false") ``` ### `showFlags` (опциональный) - **Тип:** `Boolean` - **По умолчанию:** `true` - **Описание:** Показывать флаги (для соответствующих вариантов) - **Пример:** ```pug language-switcher(:showFlags="false") ``` ### `position` (опциональный) - **Тип:** `String` - **По умолчанию:** `'bottom-start'` - **Допустимые значения:** `'top'`, `'top-start'`, `'top-end'`, `'bottom'`, `'bottom-start'`, `'bottom-end'`, `'left'`, `'right'` - **Описание:** Позиция выпадающего списка - **Пример:** ```pug language-switcher(position="bottom-end") ``` ### `languages` (опциональный) - **Тип:** `Array` - **По умолчанию:** `[{ code: 'ru', name: 'Russian', native: 'Русский', flag: '🇷🇺' }, { code: 'en', name: 'English', native: 'English', flag: '🇺🇸' }, { code: 'tj', name: 'Tajik', native: 'Тоҷикӣ', flag: '🇹🇯' }]` - **Описание:** Список доступных языков - **Пример:** ```pug language-switcher(:languages="customLanguages") ``` ### `storageKey` (опциональный) - **Тип:** `String` - **По умолчанию:** `'borbad-language'` - **Описание:** Ключ для сохранения в localStorage - **Пример:** ```pug language-switcher(storageKey="my-app-language") ``` ### `autoClose` (опциональный) - **Тип:** `Boolean` - **По умолчанию:** `true` - **Описание:** Автоматически закрывать после выбора - **Пример:** ```pug language-switcher(:autoClose="false") ``` ### `class` (опциональный) - **Тип:** `String | Object | Array` - **По умолчанию:** `''` - **Описание:** Дополнительные CSS классы - **Пример:** ```pug language-switcher(class="border border-gray-300 rounded-lg") ``` ## События (Events) ### `@change` - **Описание:** Событие смены языка - **Payload:** `{ language: String, previousLanguage: String }` - **Пример:** ```pug language-switcher(@change="handleLanguageChange") ``` ### `@open` - **Описание:** Событие открытия переключателя - **Payload:** `None` - **Пример:** ```pug language-switcher(@open="handleLanguageSwitcherOpen") ``` ### `@close` - **Описание:** Событие закрытия переключателя - **Payload:** `None` - **Пример:** ```pug language-switcher(@close="handleLanguageSwitcherClose") ``` ## Слоты (Slots) ### `[button-content]` - **Описание:** Кастомное содержимое кнопки переключателя - **Пример:** ```pug language-switcher template([button-content]) div(class="flex items-center space-x-2") icon(name="globe") span Язык ``` ### `[language-option]` - **Описание:** Кастомное отображение опции языка - **Scope:** `{ language: Object, isActive: Boolean }` - **Пример:** ```pug language-switcher template([language-option]="{ language, isActive }") div(class="flex items-center space-x-3 p-2") span(class="text-lg") {{ language.flag }} div(class="flex flex-col") span(class="font-medium") {{ language.native }} span(class="text-sm text-gray-500") {{ language.name }} span( v-if="isActive" class="text-green-500 ml-auto" ) ✓ ``` ### `[before-options]` - **Описание:** Контент перед списком языков - **Пример:** ```pug language-switcher template([before-options]) div(class="p-3 border-b border-gray-200 dark:border-gray-700") h3(class="font-semibold") Выберите язык ``` ### `[after-options]` - **Описание:** Контент после списка языков - **Пример:** ```pug language-switcher template([after-options]) div(class="p-3 border-t border-gray-200 dark:border-gray-700") p(class="text-sm text-gray-500") Помогите с переводом ``` ## Поддерживаемые языки по умолчанию ### Русский (`ru`) - **Название:** Russian - **Родное название:** Русский - **Флаг:** 🇷🇺 ### Английский (`en`) - **Название:** English - **Родное название:** English - **Флаг:** 🇺🇸 ### Таджикский (`tj`) - **Название:** Tajik - **Родное название:** Тоҷикӣ - **Флаг:** 🇹🇯 ## Примеры использования ### 1. Базовые варианты отображения ```pug //- Выпадающий список (по умолчанию) language-switcher //- Кнопки language-switcher(variant="buttons") //- Select элемент language-switcher(variant="select") //- Флаги language-switcher(variant="flags") //- Разные размеры div(class="flex space-x-2 items-center") language-switcher(size="sm") language-switcher(size="md") language-switcher(size="lg") ``` ### 2. Кастомные языки ```pug language-switcher( :languages="[ { code: 'ru', name: 'Russian', native: 'Русский', flag: '🇷🇺' }, { code: 'en', name: 'English', native: 'English', flag: '🇺🇸' }, { code: 'de', name: 'German', native: 'Deutsch', flag: '🇩🇪' }, { code: 'fr', name: 'French', native: 'Français', flag: '🇫🇷' } ]" ) ``` ### 3. Интеграция с навигацией ```pug header(class="bg-white dark:bg-gray-800 shadow-sm") div(class="container mx-auto px-4") div(class="flex justify-between items-center py-4") //- Логотип app-link(to="/" class="text-xl font-bold") Борбад //- Навигация с переключателями div(class="flex items-center space-x-4") nav(class="flex space-x-6") app-link(to="/events") Мероприятия app-link(to="/blog") Блог //- Переключатели language-switcher( variant="flags" size="sm" :showNativeNames="false" ) themetoggle(variant="icon-only") ``` ### 4. В мобильном меню ```pug div(class="mobile-menu bg-white dark:bg-gray-800 p-6") div(class="space-y-4") app-link(to="/" class="block py-2") Главная app-link(to="/events" class="block py-2") Мероприятия //- Переключатель языка div(class="pt-4 border-t dark:border-gray-700") language-switcher( variant="buttons" class="w-full" ) ``` ### 5. С кастомными слотами ```pug language-switcher template([button-content]) div(class="flex items-center space-x-2") icon(name="translate" class="w-4 h-4") span {{ _.currentLanguage.toUpperCase() }} template([before-options]) div(class="p-3 bg-blue-50 dark:bg-blue-900") p(class="text-sm text-blue-700 dark:text-blue-300") Выберите язык интерфейса template([language-option]="{ language, isActive }") div( :class="[ 'flex items-center space-x-3 p-3 rounded-lg transition-colors', isActive ? 'bg-blue-100 dark:bg-blue-800' : 'hover:bg-gray-100 dark:hover:bg-gray-700' ]" ) span(class="text-xl") {{ language.flag }} div(class="flex-1") div(class="font-medium") {{ language.native }} div(class="text-sm text-gray-500 dark:text-gray-400") {{ language.name }} icon( v-if="isActive" name="check" class="w-4 h-4 text-blue-600 dark:text-blue-400" ) ``` ### 6. С обработкой событий ```pug language-switcher( @change="onLanguageChange" @open="onLanguageSwitcherOpen" @close="onLanguageSwitcherClose" ) //- В methods компонента methods: onLanguageChange: ({ language, previousLanguage }) -> debug.log "Язык изменен: "+previousLanguage+" -> "+language # Аналитика analytics.track('language_changed', { new_language: language, previous_language: previousLanguage }) # Обновление мета-тегов @updateHtmlLang(language) onLanguageSwitcherOpen: -> debug.log "Переключатель языка открыт" analytics.track('language_switcher_opened') onLanguageSwitcherClose: -> debug.log "Переключатель языка закрыт" ``` ## Программное взаимодействие ### Получение текущего языка ```coffee # Через глобальный объект currentLanguage = _.currentLanguage # Через AppDB currentLanguage = AppDB.multilingual.currentLanguage # Через EventBus EventBus.on 'language_changed', (language) -> debug.log "Текущий язык: "+language ``` ### Установка языка программно ```coffee # Через глобальный объект _.changeLanguage('en') # Через AppDB AppDB.multilingual.setLanguage('tj') # Через EventBus EventBus.emit('set_language', 'ru') ``` ### Подписка на изменения языка ```coffee # В компоненте beforeMount: -> EventBus.on 'language_changed', @handleLanguageChange methods: handleLanguageChange: (language) -> # Перезагрузка данных на новом языке @loadDataForLanguage(language) # Обновление контента @updateContent() ``` ## Методы API ### `setLanguage(languageCode)` - **Описание:** Устанавливает указанный язык - **Параметры:** `languageCode` - код языка ('ru', 'en', 'tj') - **Пример:** ```coffee @$refs.languageSwitcher.setLanguage('en') ``` ### `getCurrentLanguage()` - **Описание:** Возвращает текущий активный язык - **Возвращает:** `String` - **Пример:** ```coffee currentLang = @$refs.languageSwitcher.getCurrentLanguage() ``` ### `open()` - **Описание:** Программно открывает переключатель - **Пример:** ```coffee @$refs.languageSwitcher.open() ``` ### `close()` - **Описание:** Программно закрывает переключатель - **Пример:** ```coffee @$refs.languageSwitcher.close() ``` ### `getAvailableLanguages()` - **Описание:** Возвращает список доступных языков - **Возвращает:** `Array` - **Пример:** ```coffee languages = @$refs.languageSwitcher.getAvailableLanguages() ``` ## Интеграция с мультиязычной системой ### С AppDB ```coffee # Компонент автоматически интегрируется с AppDB.multilingual languageSwitcher.setLanguage('en') # Эквивалентно: AppDB.multilingual.setLanguage('en') ``` ### С глобальным состоянием ```coffee # Изменение языка через компонент обновляет глобальное состояние _.changeLanguage('tj') ``` ### С загрузкой данных ```coffee methods: handleLanguageChange: (language) -> # Перезагрузка контента на новом языке promises = [ AppDB.getBlogPosts({ language: language }) AppDB.getEvents({ language: language }) AppDB.getCategories({ language: language }) ] await Promise.all(promises) EventBus.emit('content_updated') ``` ## Стили и кастомизация ### CSS-классы компонента ```styl .language-switcher // Основной контейнер &__container @apply relative inline-block // Кнопка переключателя &__button @apply flex items-center space-x-2 px-3 py-2 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 text-gray-700 dark:text-gray-300 hover:bg-gray-50 dark:hover:bg-gray-700 transition-colors // Выпадающий список &__dropdown @apply absolute z-50 mt-2 w-48 bg-white dark:bg-gray-800 rounded-lg shadow-lg border border-gray-200 dark:border-gray-700 py-1 // Опция языка &__option @apply flex items-center space-x-3 px-4 py-2 text-sm text-gray-700 dark:text-gray-300 hover:bg-gray-100 dark:hover:bg-gray-700 transition-colors cursor-pointer &--active @apply bg-blue-50 dark:bg-blue-900 text-blue-600 dark:text-blue-400 // Вариант с кнопками &--buttons @apply flex space-x-1 .language-switcher__button @apply rounded-none border-r-0 &:first-child @apply rounded-l-lg &:last-child @apply rounded-r-lg border-r // Вариант с флагами &--flags .language-switcher__button @apply p-1 .language-switcher__option @apply px-3 py-1 ``` ### Кастомные стили ```styl // Переопределение стандартных стилей .language-switcher--custom .language-switcher__button @apply bg-gradient-to-r from-purple-500 to-pink-500 text-white border-transparent &:hover @apply from-purple-600 to-pink-600 .language-switcher__option &:hover @apply bg-gradient-to-r from-purple-50 to-pink-50 text-purple-700 &--active @apply bg-gradient-to-r from-purple-100 to-pink-100 text-purple-800 ``` ### Темная тема ```styl @media (prefers-color-scheme: dark) .language-switcher &__button @apply bg-gray-800 border-gray-600 text-gray-300 &:hover @apply bg-gray-700 &__dropdown @apply bg-gray-800 border-gray-700 &__option @apply text-gray-300 &:hover @apply bg-gray-700 &--active @apply bg-blue-900 text-blue-400 ``` ## Особенности работы ### Определение языка по умолчанию ```coffee # Приоритеты определения языка: # 1. Сохраненный выбор пользователя (localStorage) # 2. Язык браузера # 3. Язык по умолчанию (ru) ``` ### Синхронизация между вкладками ```coffee # Слушает события storage для синхронизации window.addEventListener('storage', (event) -> if event.key == @storageKey @setLanguage(event.newValue, false) # false - не сохранять снова ) ``` ### Интеграция с SEO ```coffee methods: updateHtmlLang: (language) -> # Обновление атрибута lang у html элемента document.documentElement.lang = language # Обновление hreflang meta-тегов @updateHreflangTags(language) ``` ## Обработка ошибок ### Валидация языка ```coffee # Проверка поддерживаемых языков if !@availableLanguages.find((lang) -> lang.code == language) throw new Error("Неподдерживаемый язык: "+language) ``` ### Fallback для localStorage ```coffee try localStorage.setItem(@storageKey, language) catch error # Используем cookie как fallback document.cookie = @storageKey+"="+language+"; path=/; max-age=31536000" ``` ## Примеры интеграции ### 1. С аналитикой ```coffee methods: handleLanguageChange: ({ language, previousLanguage }) -> # Отправка в аналитику gtag('event', 'language_change', { event_category: 'ui', event_label: language, value: 1 }) ``` ### 2. С синхронизацией с сервером ```coffee methods: handleLanguageChange: (language) -> # Сохранение на сервере (если пользователь авторизован) if @user await @api.saveUserPreferences({ language: language }) ``` ### 3. С динамической загрузкой переводов ```coffee methods: handleLanguageChange: (language) -> # Загрузка файлов переводов try translations = await import('../locales/'+language+'.json') AppDB.multilingual.setTranslations(language, translations) catch error debug.log "Ошибка загрузки переводов: "+error ``` ## Best Practices ### 1. Всегда предоставляйте понятные названия ```pug //- Правильно - показываем родные названия language-switcher(showNativeNames="true") //- Неправильно - только коды language-switcher(:showNativeNames="false") ``` ### 2. Используйте флаги аккуратно ```pug //- Флаги помогают визуальной идентификации language-switcher(showFlags="true") //- Но могут быть спорными для некоторых языков ``` ### 3. Сохраняйте состояние пользователя ```pug //- Автоматически сохраняет в localStorage language-switcher ``` ### 4. Обеспечивайте доступность ```pug //- Правильные ARIA-атрибуты language-switcher(aria-label="Переключение языка") ``` ### 5. Тестируйте все варианты ```coffee # В тестах describe('LanguageSwitcher', -> it('should switch between languages', -> switcher.setLanguage('en') expect(switcher.getCurrentLanguage()).toBe('en') switcher.setLanguage('ru') expect(switcher.getCurrentLanguage()).toBe('ru') ) ) ``` ### 6. Учитывайте RTL языки ```coffee methods: handleLanguageChange: (language) -> # Для RTL языков (арабский, иврит и т.д.) if @isRtlLanguage(language) document.documentElement.dir = 'rtl' else document.documentElement.dir = 'ltr' ``` Компонент LanguageSwitcher предоставляет полнофункциональное решение для управления языками в мультиязычном приложении с поддержкой доступности, сохранения состояния и интеграции с глобальной системой мультиязычности.