Add internationalization (i18n) support with English and Russian locales
- Add translation JSON files (en.json, ru.json) with 110+ strings each - Implement locale auto-detection from browser settings - Add locale toggle button (EN/RU) with localStorage persistence - Translate all user-facing text: auth, player, scripts, callbacks - Fix dynamic content translation on locale switch (playback state, track title) - Add comprehensive i18n documentation to CLAUDE.md - Follow existing theme toggle pattern for consistency Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>
This commit is contained in:
109
media_server/static/locales/en.json
Normal file
109
media_server/static/locales/en.json
Normal file
@@ -0,0 +1,109 @@
|
||||
{
|
||||
"app.title": "Media Server",
|
||||
"auth.message": "Enter your API token to connect to the media server.",
|
||||
"auth.placeholder": "Enter API Token",
|
||||
"auth.connect": "Connect",
|
||||
"auth.help": "To get your token, run:",
|
||||
"auth.logout": "Logout",
|
||||
"auth.logout.title": "Clear saved token",
|
||||
"auth.invalid": "Invalid token. Please try again.",
|
||||
"auth.cleared": "Token cleared. Please enter a new token.",
|
||||
"auth.required": "Please enter a token",
|
||||
"player.theme": "Toggle theme",
|
||||
"player.locale": "Change language",
|
||||
"player.previous": "Previous",
|
||||
"player.play": "Play/Pause",
|
||||
"player.next": "Next",
|
||||
"player.mute": "Mute",
|
||||
"player.status.connected": "Connected",
|
||||
"player.status.disconnected": "Disconnected",
|
||||
"player.no_media": "No media playing",
|
||||
"player.source": "Source:",
|
||||
"player.unknown_source": "Unknown",
|
||||
"state.playing": "Playing",
|
||||
"state.paused": "Paused",
|
||||
"state.stopped": "Stopped",
|
||||
"state.idle": "Idle",
|
||||
"scripts.quick_actions": "Quick Actions",
|
||||
"scripts.no_scripts": "No scripts configured",
|
||||
"scripts.management": "Script Management",
|
||||
"scripts.add": "Add",
|
||||
"scripts.table.name": "Name",
|
||||
"scripts.table.label": "Label",
|
||||
"scripts.table.command": "Command",
|
||||
"scripts.table.timeout": "Timeout",
|
||||
"scripts.table.actions": "Actions",
|
||||
"scripts.empty": "No scripts configured. Click 'Add' to create one.",
|
||||
"scripts.dialog.add": "Add Script",
|
||||
"scripts.dialog.edit": "Edit Script",
|
||||
"scripts.field.name": "Script Name *",
|
||||
"scripts.field.label": "Label",
|
||||
"scripts.field.command": "Command *",
|
||||
"scripts.field.description": "Description",
|
||||
"scripts.field.icon": "Icon (MDI)",
|
||||
"scripts.field.timeout": "Timeout (seconds)",
|
||||
"scripts.placeholder.name": "Only letters, numbers, and underscores allowed",
|
||||
"scripts.placeholder.label": "Human-readable name",
|
||||
"scripts.placeholder.command": "e.g., shutdown /s /t 0",
|
||||
"scripts.placeholder.description": "What does this script do?",
|
||||
"scripts.placeholder.icon": "e.g., mdi:power",
|
||||
"scripts.button.cancel": "Cancel",
|
||||
"scripts.button.save": "Save",
|
||||
"scripts.button.edit": "Edit",
|
||||
"scripts.button.delete": "Delete",
|
||||
"scripts.msg.executed": "{name} executed successfully",
|
||||
"scripts.msg.execute_failed": "Failed to execute {name}",
|
||||
"scripts.msg.execute_error": "Error executing {name}",
|
||||
"scripts.msg.created": "Script created successfully",
|
||||
"scripts.msg.updated": "Script updated successfully",
|
||||
"scripts.msg.create_failed": "Failed to create script",
|
||||
"scripts.msg.update_failed": "Failed to update script",
|
||||
"scripts.msg.deleted": "Script deleted successfully",
|
||||
"scripts.msg.delete_failed": "Failed to delete script",
|
||||
"scripts.msg.not_found": "Script not found",
|
||||
"scripts.msg.load_failed": "Failed to load script details",
|
||||
"scripts.msg.list_failed": "Failed to load scripts",
|
||||
"scripts.confirm.delete": "Are you sure you want to delete the script \"{name}\"?",
|
||||
"callbacks.management": "Callback Management",
|
||||
"callbacks.description": "Callbacks are scripts triggered automatically by media control events (play, pause, stop, etc.)",
|
||||
"callbacks.add": "Add",
|
||||
"callbacks.table.event": "Event",
|
||||
"callbacks.table.command": "Command",
|
||||
"callbacks.table.timeout": "Timeout",
|
||||
"callbacks.table.actions": "Actions",
|
||||
"callbacks.empty": "No callbacks configured. Click 'Add' to create one.",
|
||||
"callbacks.dialog.add": "Add Callback",
|
||||
"callbacks.dialog.edit": "Edit Callback",
|
||||
"callbacks.field.event": "Event *",
|
||||
"callbacks.field.command": "Command *",
|
||||
"callbacks.field.timeout": "Timeout (seconds)",
|
||||
"callbacks.field.workdir": "Working Directory",
|
||||
"callbacks.placeholder.event": "Select event...",
|
||||
"callbacks.placeholder.command": "e.g., shutdown /s /t 0",
|
||||
"callbacks.placeholder.workdir": "Optional",
|
||||
"callbacks.button.cancel": "Cancel",
|
||||
"callbacks.button.save": "Save",
|
||||
"callbacks.button.edit": "Edit",
|
||||
"callbacks.button.delete": "Delete",
|
||||
"callbacks.event.on_play": "on_play - After play succeeds",
|
||||
"callbacks.event.on_pause": "on_pause - After pause succeeds",
|
||||
"callbacks.event.on_stop": "on_stop - After stop succeeds",
|
||||
"callbacks.event.on_next": "on_next - After next track succeeds",
|
||||
"callbacks.event.on_previous": "on_previous - After previous track succeeds",
|
||||
"callbacks.event.on_volume": "on_volume - After volume change",
|
||||
"callbacks.event.on_mute": "on_mute - After mute toggle",
|
||||
"callbacks.event.on_seek": "on_seek - After seek succeeds",
|
||||
"callbacks.event.on_turn_on": "on_turn_on - Callback-only action",
|
||||
"callbacks.event.on_turn_off": "on_turn_off - Callback-only action",
|
||||
"callbacks.event.on_toggle": "on_toggle - Callback-only action",
|
||||
"callbacks.msg.created": "Callback created successfully",
|
||||
"callbacks.msg.updated": "Callback updated successfully",
|
||||
"callbacks.msg.create_failed": "Failed to create callback",
|
||||
"callbacks.msg.update_failed": "Failed to update callback",
|
||||
"callbacks.msg.deleted": "Callback deleted successfully",
|
||||
"callbacks.msg.delete_failed": "Failed to delete callback",
|
||||
"callbacks.msg.not_found": "Callback not found",
|
||||
"callbacks.msg.load_failed": "Failed to load callback details",
|
||||
"callbacks.msg.list_failed": "Failed to load callbacks",
|
||||
"callbacks.confirm.delete": "Are you sure you want to delete the callback \"{name}\"?"
|
||||
}
|
||||
109
media_server/static/locales/ru.json
Normal file
109
media_server/static/locales/ru.json
Normal file
@@ -0,0 +1,109 @@
|
||||
{
|
||||
"app.title": "Медиа Сервер",
|
||||
"auth.message": "Введите API токен для подключения к медиа серверу.",
|
||||
"auth.placeholder": "Введите API токен",
|
||||
"auth.connect": "Подключиться",
|
||||
"auth.help": "Чтобы получить токен, выполните:",
|
||||
"auth.logout": "Выйти",
|
||||
"auth.logout.title": "Очистить сохраненный токен",
|
||||
"auth.invalid": "Неверный токен. Пожалуйста, попробуйте снова.",
|
||||
"auth.cleared": "Токен очищен. Пожалуйста, введите новый токен.",
|
||||
"auth.required": "Пожалуйста, введите токен",
|
||||
"player.theme": "Переключить тему",
|
||||
"player.locale": "Изменить язык",
|
||||
"player.previous": "Предыдущий",
|
||||
"player.play": "Воспроизвести/Пауза",
|
||||
"player.next": "Следующий",
|
||||
"player.mute": "Без звука",
|
||||
"player.status.connected": "Подключено",
|
||||
"player.status.disconnected": "Отключено",
|
||||
"player.no_media": "Медиа не воспроизводится",
|
||||
"player.source": "Источник:",
|
||||
"player.unknown_source": "Неизвестно",
|
||||
"state.playing": "Воспроизведение",
|
||||
"state.paused": "Пауза",
|
||||
"state.stopped": "Остановлено",
|
||||
"state.idle": "Ожидание",
|
||||
"scripts.quick_actions": "Быстрые Действия",
|
||||
"scripts.no_scripts": "Скрипты не настроены",
|
||||
"scripts.management": "Управление Скриптами",
|
||||
"scripts.add": "Добавить",
|
||||
"scripts.table.name": "Имя",
|
||||
"scripts.table.label": "Метка",
|
||||
"scripts.table.command": "Команда",
|
||||
"scripts.table.timeout": "Таймаут",
|
||||
"scripts.table.actions": "Действия",
|
||||
"scripts.empty": "Скрипты не настроены. Нажмите 'Добавить' для создания.",
|
||||
"scripts.dialog.add": "Добавить Скрипт",
|
||||
"scripts.dialog.edit": "Редактировать Скрипт",
|
||||
"scripts.field.name": "Имя Скрипта *",
|
||||
"scripts.field.label": "Метка",
|
||||
"scripts.field.command": "Команда *",
|
||||
"scripts.field.description": "Описание",
|
||||
"scripts.field.icon": "Иконка (MDI)",
|
||||
"scripts.field.timeout": "Таймаут (секунды)",
|
||||
"scripts.placeholder.name": "Только буквы, цифры и подчеркивания",
|
||||
"scripts.placeholder.label": "Человеко-читаемое имя",
|
||||
"scripts.placeholder.command": "например, shutdown /s /t 0",
|
||||
"scripts.placeholder.description": "Что делает этот скрипт?",
|
||||
"scripts.placeholder.icon": "например, mdi:power",
|
||||
"scripts.button.cancel": "Отмена",
|
||||
"scripts.button.save": "Сохранить",
|
||||
"scripts.button.edit": "Редактировать",
|
||||
"scripts.button.delete": "Удалить",
|
||||
"scripts.msg.executed": "{name} выполнен успешно",
|
||||
"scripts.msg.execute_failed": "Не удалось выполнить {name}",
|
||||
"scripts.msg.execute_error": "Ошибка выполнения {name}",
|
||||
"scripts.msg.created": "Скрипт создан успешно",
|
||||
"scripts.msg.updated": "Скрипт обновлен успешно",
|
||||
"scripts.msg.create_failed": "Не удалось создать скрипт",
|
||||
"scripts.msg.update_failed": "Не удалось обновить скрипт",
|
||||
"scripts.msg.deleted": "Скрипт удален успешно",
|
||||
"scripts.msg.delete_failed": "Не удалось удалить скрипт",
|
||||
"scripts.msg.not_found": "Скрипт не найден",
|
||||
"scripts.msg.load_failed": "Не удалось загрузить данные скрипта",
|
||||
"scripts.msg.list_failed": "Не удалось загрузить скрипты",
|
||||
"scripts.confirm.delete": "Вы уверены, что хотите удалить скрипт \"{name}\"?",
|
||||
"callbacks.management": "Управление Обратными Вызовами",
|
||||
"callbacks.description": "Обратные вызовы - это скрипты, автоматически запускаемые при событиях управления медиа (воспроизведение, пауза, остановка и т.д.)",
|
||||
"callbacks.add": "Добавить",
|
||||
"callbacks.table.event": "Событие",
|
||||
"callbacks.table.command": "Команда",
|
||||
"callbacks.table.timeout": "Таймаут",
|
||||
"callbacks.table.actions": "Действия",
|
||||
"callbacks.empty": "Обратные вызовы не настроены. Нажмите 'Добавить' для создания.",
|
||||
"callbacks.dialog.add": "Добавить Обратный Вызов",
|
||||
"callbacks.dialog.edit": "Редактировать Обратный Вызов",
|
||||
"callbacks.field.event": "Событие *",
|
||||
"callbacks.field.command": "Команда *",
|
||||
"callbacks.field.timeout": "Таймаут (секунды)",
|
||||
"callbacks.field.workdir": "Рабочая Директория",
|
||||
"callbacks.placeholder.event": "Выберите событие...",
|
||||
"callbacks.placeholder.command": "например, shutdown /s /t 0",
|
||||
"callbacks.placeholder.workdir": "Опционально",
|
||||
"callbacks.button.cancel": "Отмена",
|
||||
"callbacks.button.save": "Сохранить",
|
||||
"callbacks.button.edit": "Редактировать",
|
||||
"callbacks.button.delete": "Удалить",
|
||||
"callbacks.event.on_play": "on_play - После успешного воспроизведения",
|
||||
"callbacks.event.on_pause": "on_pause - После успешной паузы",
|
||||
"callbacks.event.on_stop": "on_stop - После успешной остановки",
|
||||
"callbacks.event.on_next": "on_next - После успешного перехода к следующему",
|
||||
"callbacks.event.on_previous": "on_previous - После успешного перехода к предыдущему",
|
||||
"callbacks.event.on_volume": "on_volume - После изменения громкости",
|
||||
"callbacks.event.on_mute": "on_mute - После переключения звука",
|
||||
"callbacks.event.on_seek": "on_seek - После успешной перемотки",
|
||||
"callbacks.event.on_turn_on": "on_turn_on - Действие только для обратных вызовов",
|
||||
"callbacks.event.on_turn_off": "on_turn_off - Действие только для обратных вызовов",
|
||||
"callbacks.event.on_toggle": "on_toggle - Действие только для обратных вызовов",
|
||||
"callbacks.msg.created": "Обратный вызов создан успешно",
|
||||
"callbacks.msg.updated": "Обратный вызов обновлен успешно",
|
||||
"callbacks.msg.create_failed": "Не удалось создать обратный вызов",
|
||||
"callbacks.msg.update_failed": "Не удалось обновить обратный вызов",
|
||||
"callbacks.msg.deleted": "Обратный вызов удален успешно",
|
||||
"callbacks.msg.delete_failed": "Не удалось удалить обратный вызов",
|
||||
"callbacks.msg.not_found": "Обратный вызов не найден",
|
||||
"callbacks.msg.load_failed": "Не удалось загрузить данные обратного вызова",
|
||||
"callbacks.msg.list_failed": "Не удалось загрузить обратные вызовы",
|
||||
"callbacks.confirm.delete": "Вы уверены, что хотите удалить обратный вызов \"{name}\"?"
|
||||
}
|
||||
Reference in New Issue
Block a user