feat(i18n): Russian locale — missing strings (#1181)

This commit is contained in:
kilyabin
2026-06-26 01:22:45 +04:00
committed by GitHub
parent eb42a32315
commit afe5b377e0
13 changed files with 84 additions and 28 deletions
+7
View File
@@ -147,6 +147,13 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
* **Settings → Personalisation** gains a **Queue Settings** category that brings the queue display mode, the queue toolbar customizer, and the **Preserve "Play Next" order** toggle (moved here from Audio) together in one place.
* On macOS, the **Audio Output Device** category is now hidden rather than showing a notice — playback there always follows the system output device.
### Russian locale — missing strings and phrasing cleanup
**By [@kilyabin](https://github.com/kilyabin), PR [#1181](https://github.com/Psychotoxical/psysonic/pull/1181)**
* Fifty strings that still fell back to English in the Russian UI are now translated — macOS in-place updater, device sync file migration, fullscreen lyrics, and statistics share-image export.
* User-facing descriptions in Russian and English no longer mention WebKitGTK or FisherYates internals; several Russian labels and section titles read more naturally (settings casing, smart playlists, track transitions, and home rails).
## Fixed
+1
View File
@@ -196,6 +196,7 @@ const CONTRIBUTOR_ENTRIES = [
'Golos Text and Unbounded fonts with Cyrillic support (PR #206)',
'Fullscreen & sidebar lyrics: duration-based ease-out scroll animator replacing spring physics; bottom fade for plain lyrics (PR #214)',
'Sidebar lyrics: YouLy+ source strings render in a single line (PR #215)',
'Russian locale — 50 missing strings and ru/en phrasing cleanup (PR #1181)',
],
},
{
+1 -1
View File
@@ -134,7 +134,7 @@ export const orbit = {
settingAutoApprove: 'Auto-approve suggestions',
settingAutoApproveHint: "Guest suggestions land in your queue instantly. Off: they stay in the session list for you to review later.",
settingAutoShuffle: 'Automatic reshuffle',
settingAutoShuffleHint: "Periodic FisherYates shuffle of the upcoming queue. Off: order only changes when you rearrange it.",
settingAutoShuffleHint: "Periodically reshuffles the upcoming queue. Off: order only changes when you rearrange it manually.",
settingShuffleInterval: 'Reshuffle every',
settingShuffleIntervalHint: 'How often the upcoming queue gets reshuffled while the session runs.',
suggestBlockedMuted: 'The host muted you for this session — suggestions are off.',
+2 -2
View File
@@ -278,10 +278,10 @@ export const settings = {
linuxWebkitSmoothScroll: 'Smooth wheel (Linux)',
linuxWebkitSmoothScrollDesc: 'On: inertial scroll. Off: line-by-line, GTK-style.',
linuxWebkitInputForceRepaint: 'Repaint inputs on focus (Linux)',
linuxWebkitInputForceRepaintDesc: 'Workaround for WebKitGTK 2.50.x where text fields freeze when clicked. Search icons flicker briefly on focus.',
linuxWebkitInputForceRepaintDesc: 'Fixes text fields that freeze when clicked. Search icons may flicker briefly on focus.',
linuxWaylandTextRender: 'Wayland text rendering (Linux)',
linuxWaylandTextRenderDesc:
'Font smoothing in the UI updates immediately. WebKit hardware acceleration (sharp / GPU presets) is saved and applied on the next app start — changing it live can freeze WebKitGTK on some setups.',
'Font smoothing updates immediately. The acceleration preset (Sharp / GPU) takes effect after restarting the app.',
linuxWaylandTextRenderBalanced: 'Balanced',
linuxWaylandTextRenderSharp: 'Sharp (CPU-friendly)',
linuxWaylandTextRenderGpu: 'GPU-first',
+10
View File
@@ -9,6 +9,7 @@ export const common = {
downloadZip: 'Скачать (ZIP)',
back: 'Назад',
backToTop: 'Наверх',
close: 'Закрыть',
cancel: 'Отмена',
save: 'Сохранить',
delete: 'Удалить',
@@ -49,6 +50,15 @@ export const common = {
updaterAurHint: 'Установить обновление через AUR:',
updaterErrorMsg: 'Ошибка загрузки',
updaterRetryBtn: 'Повторить',
updaterInstallNow: 'Установить сейчас',
updaterMacReadyTitle: 'Готово к установке',
updaterMacReady: 'Обновление загружается, проверяется и применяется автоматически — DMG не нужен. После завершения приложение перезапустится само.',
updaterTrustNotarized: 'Нотаризовано Apple',
updaterTrustSignature: 'Подпись проверена',
updaterMacDoneTitle: 'Обновление установлено',
updaterRestartingIn: 'Перезапуск через {{n}} с…',
updaterRestarting: 'Перезапуск…',
updaterRestartNow: 'Перезапустить сейчас',
durationHoursMinutes: '{{hours}}ч {{minutes}}мин',
durationMinutesOnly: '{{minutes}}мин',
updaterOpenGitHub: 'Открыть на GitHub',
+18 -1
View File
@@ -9,8 +9,25 @@ export const deviceSync = {
free: 'свободно',
notMountedVolume: 'Цель не находится на смонтированном томе. Диск мог быть отключён.',
chooseFolder: 'Выбрать…',
filenameTemplate: 'Шаблон имени файла',
targetDevice: 'Целевое устройство',
schemaLabel: 'Схема именования',
schemaHint: 'Фиксированная схема для надёжной синхронизации между ОС. Плейлисты сохраняются как .m3u8 со ссылками на треки альбома — дубликатов на устройстве не будет.',
migrateButton: 'Реорганизовать существующие файлы…',
migrateTooltip: 'Переименовать существующие файлы на устройстве по новой схеме (со старого шаблона имён).',
migrateTitle: 'Реорганизация существующих файлов',
migrateLoading: 'Анализ существующих файлов…',
migrateNothingToDo: 'Все файлы уже соответствуют новой схеме — делать нечего.',
migrateNoTemplate: 'На устройстве не найден старый шаблон имён. Миграция применяется только если устройство синхронизировалось версией Psysonic с поддержкой пользовательских шаблонов.',
migrateFilesToRename: 'файлов будет переименовано',
migrateUnchanged: '{{n}} файлов уже находятся по правильному пути',
migrateCollisions: '{{n}} файлов невозможно переименовать автоматически (несколько треков ведут к одному пути). Они останутся нетронутыми — следующая синхронизация скачает их в нужное место.',
migratePreviewNote: 'Старый шаблон: {{tpl}}',
migrateExecuting: 'Переименование файлов…',
migrateSuccess: '{{n}} файлов успешно переименовано',
migrateFailed: '{{n}} переименований завершились ошибкой',
migrateShowErrors: 'Показать ошибки',
migrateStart: 'Начать переименование',
scanningDevice: 'Сканирование устройства…',
templateHint: 'Переменные: {artist}, {album}, {title}, {track_number}, {disc_number}, {year}',
cleanupButton: 'Удалить файлы вне выборки',
cleanupNothingToDelete: 'Нечего удалять — устройство уже синхронизировано.',
+4 -4
View File
@@ -5,13 +5,13 @@ export const home = {
recentlyPlayed: 'Недавно проиграно',
losslessAlbums: 'Lossless-альбомы',
discover: 'Обзор',
discoverSongs: 'Открыть треки',
discoverSongs: 'Откройте для себя',
loadMore: 'Ещё',
discoverMore: 'Смотреть ещё',
discoverArtists: 'Исполнители',
discoverArtistsMore: 'Все исполнители',
becauseYouLike: 'Потому что вы слушали…',
becauseYouLikeFor: 'Потому что вы слушали {{artist}}',
becauseYouLike: 'Поскольку вы слушали…',
becauseYouLikeFor: 'Поскольку вы слушали {{artist}}',
similarTo: 'Похоже на {{artist}}',
becauseYouLikeTracks_one: '{{count}} трек',
becauseYouLikeTracks_few: '{{count}} трека',
@@ -19,5 +19,5 @@ export const home = {
becauseYouLikeTracks_other: '{{count}} треков',
mainstageEmptyTitle: 'Раздел «Для вас» пуст',
mainstageEmptyBody: 'Все разделы отключены. Включите разделы снова или скройте «Для вас» из боковой панели.',
mainstageEmptyCta: 'Открыть Персонализацию',
mainstageEmptyCta: 'Открыть персонализацию',
};
+2 -2
View File
@@ -40,7 +40,7 @@ export const orbit = {
btnStarting: 'Запуск…',
btnStart: 'Запустить Orbit',
btnCopyAndStart: 'Копировать ссылку и запустить',
errNameRequired: 'Пожалуйста, дай сессии название.',
errNameRequired: 'Пожалуйста, дай название сессии.',
errStartFailed: 'Не удалось запустить.',
hostLabel: 'Хост: {{name}}',
participantsTooltip: 'Участники',
@@ -134,7 +134,7 @@ export const orbit = {
settingAutoApprove: 'Автоматически принимать предложения',
settingAutoApproveHint: 'Предложения гостей сразу попадают в твою очередь. Выкл.: они остаются в списке сессии для последующего просмотра.',
settingAutoShuffle: 'Автоперемешивание',
settingAutoShuffleHint: 'Периодическое Fisher-Yates перемешивание предстоящей очереди. Выкл.: порядок меняется только при ручной перестановке.',
settingAutoShuffleHint: 'Периодически перемешивает предстоящую очередь. Выкл.: порядок меняется только при ручной перестановке.',
settingShuffleInterval: 'Перемешивать каждые',
settingShuffleIntervalHint: 'Как часто предстоящая очередь перемешивается во время сессии.',
suggestBlockedMuted: 'Хост отключил тебе предложение треков на этой сессии.',
+3
View File
@@ -59,8 +59,11 @@ export const player = {
lyricsLoading: 'Загрузка текста…',
lyricsNotFound: 'Текст не найден',
lyricsNoSources: 'Источники текста не выбраны — включите их в Настройки → Текст',
lyricsSourceServer: 'Источник: Сервер',
lyricsSourceLrclib: 'Источник: LRCLIB',
lyricsSourceNetease: 'Источник: Netease',
lyricsSourceLyricsplus: 'Источник: YouLyPlus',
fsLyricsToggle: 'Текст в полноэкранном режиме',
showDuration: 'Показать длительность',
showRemainingTime: 'Показать оставшееся время',
};
+15 -15
View File
@@ -43,7 +43,7 @@ export const settings = {
serverUsername: 'Логин',
serverPassword: 'Пароль',
customHeadersTitle: 'Пользовательские HTTP-заголовки',
customHeadersHelp: 'Для reverse-proxy (Pangolin, Cloudflare Access). Отправляются только на ваш сервер — не сторонним сервисам.',
customHeadersHelp: 'Используются для reverse-proxy (Pangolin, Cloudflare Access). Отправляются только на ваш сервер — не сторонним сервисам.',
customHeadersNamePlaceholder: 'Имя заголовка',
customHeadersValuePlaceholder: 'Значение заголовка',
customHeadersAddRow: 'Добавить заголовок',
@@ -239,7 +239,7 @@ export const settings = {
hiResTitle: 'Нативное воспроизведение Hi-Res',
hiResEnabled: 'Включить нативное Hi-Res воспроизведение',
hiResDesc: "Воспроизводит каждый трек с его исходной частотой дискретизации вместо передискретизации всего в 44,1 кГц, переключая устройство вывода под частоту файла (88,2 кГц и выше). Включайте только если оборудование и сеть надёжно справляются с высокими частотами.",
hiResCrossfadeResampleTitle: 'Частота сведения Crossfade / AutoDJ / Gapless',
hiResCrossfadeResampleTitle: 'Частота сведения при переходах',
hiResCrossfadeResampleDesc: 'Когда соседние треки имеют разную частоту дискретизации, обе стороны передискретизируются на эту частоту во время кроссфейда, AutoDJ и gapless-переходов.',
hiResCrossfadeResample44: '44,1 кГц',
hiResCrossfadeResample88: '88,2 кГц',
@@ -277,10 +277,10 @@ export const settings = {
linuxWebkitSmoothScroll: 'Плавное колесо (Linux)',
linuxWebkitSmoothScrollDesc: 'Вкл — инерция. Выкл — по шагам, как в GTK.',
linuxWebkitInputForceRepaint: 'Перерисовывать поля ввода при фокусе (Linux)',
linuxWebkitInputForceRepaintDesc: 'Обход проблемы WebKitGTK 2.50.x, когда текстовые поля зависают при клике. Иконки поиска кратко мигают при фокусе.',
linuxWebkitInputForceRepaintDesc: 'Исправляет зависание текстовых полей при клике. Иконки поиска могут кратко мигать при фокусе.',
linuxWaylandTextRender: 'Рендеринг текста Wayland (Linux)',
linuxWaylandTextRenderDesc:
'Сглаживание в интерфейсе меняется сразу. Политику ускорения WebKit (чёткий / GPU) сохраняем и применяем при следующем запуске — переключение на лету на части сборок зависает в WebKitGTK.',
'Сглаживание меняется сразу. Пресет ускорения (Чёткий / GPU) применяется после перезапуска приложения.',
linuxWaylandTextRenderBalanced: 'Сбалансированный',
linuxWaylandTextRenderSharp: 'Чёткий (меньше GPU)',
linuxWaylandTextRenderGpu: 'С приоритетом GPU',
@@ -417,7 +417,7 @@ export const settings = {
analyticsStrategyClearError: 'Не удалось очистить анализ для удалённого сервера.',
analyticsStrategyProgressEmptyAfterFailed: '100% (0/0, треки помечены как проблемные)',
analyticsFailedTracksOpenTitle: 'Проблемных треков: {{count}}',
analyticsFailedTracksTitle: 'Проблемные треки анализа — {{server}}',
analyticsFailedTracksTitle: 'Проблемные треки при анализе — {{server}}',
analyticsFailedTracksDesc: 'Эти треки многократно падали на decode/enrichment и исключены из фонового автоанализа.',
analyticsFailedTracksLoading: 'Загрузка списка проблемных треков…',
analyticsFailedTracksEmpty: 'Для этого сервера проблемных треков нет.',
@@ -425,9 +425,9 @@ export const settings = {
analyticsFailedTracksExport: 'Экспорт списка',
analyticsFailedTracksExportSuccess: 'Список проблемных треков экспортирован ({{count}}).',
analyticsFailedTracksExportError: 'Не удалось экспортировать список проблемных треков.',
analyticsFailedTracksRescan: 'Рескан проблемных треков',
analyticsFailedTracksRescanSuccess: 'Рескан запланирован для {{count}} проблемных треков.',
analyticsFailedTracksRescanError: 'Не удалось запустить рескан проблемных треков.',
analyticsFailedTracksRescan: 'Повторное сканирование проблемных треков',
analyticsFailedTracksRescanSuccess: 'Повторное сканирование запланировано для {{count}} проблемных треков.',
analyticsFailedTracksRescanError: 'Не удалось запустить повторное сканирование проблемных треков.',
analyticsFailedTracksLoadError: 'Не удалось загрузить список проблемных треков.',
randomMixTitle: 'Чёрный список случайного микса',
luckyMixMenuTitle: 'Показывать «Мне повезёт» в меню',
@@ -579,7 +579,7 @@ export const settings = {
tabUsers: 'Пользователи',
tabSystem: 'Система',
loggingTitle: 'Логирование',
loggingModeDesc: 'Управляет подробностью логов backend в терминале.',
loggingModeDesc: 'Управляет подробностью логов бэкенда в терминале.',
loggingModeOff: 'Выключено',
loggingModeNormal: 'Обычное',
loggingModeDebug: 'Дебаг',
@@ -701,7 +701,7 @@ export const settings = {
autodjOverlapCapAuto: 'Авто',
autodjOverlapCapLimit: 'Лимит',
autodjOverlapCapSecs: '{{n}} с',
gapless: 'Без пауз между треками',
gapless: 'Без пауз',
transitionsTitle: 'Переходы между треками',
transitionsDesc: 'Как соединяются идущие подряд треки. Одновременно может быть активен только один режим.',
transitionOff: 'Выкл.',
@@ -724,7 +724,7 @@ export const settings = {
trackPreviewLocation_playlists: 'В плейлистах',
trackPreviewLocation_favorites: 'В избранном',
trackPreviewLocation_artist: 'В топ-треках исполнителя',
trackPreviewLocation_randomMix: 'В Random Mix',
trackPreviewLocation_randomMix: 'В случайном миксе',
nextTrackBufferingTitle: 'Буферизация',
infiniteQueue: 'Бесконечная очередь',
infiniteQueueDesc: 'Подмешивать случайные треки, когда очередь закончится',
@@ -766,12 +766,12 @@ export const settings = {
themeSchedulerLightTheme: 'Светлая тема',
themeSchedulerDarkTheme: 'Тёмная тема',
themeSchedulerSystemRestartHint: 'Изменение светлой/тёмной настройки системы вступит в силу после перезапуска приложения.',
visualOptionsTitle: 'Визуальные Настройки',
coverArtBackground: 'Фон Обложки',
visualOptionsTitle: 'Визуальные настройки',
coverArtBackground: 'Фон обложки',
coverArtBackgroundSub: 'Показывать размытую обложку как фон в заголовках альбомов и плейлистов',
playlistCoverPhoto: 'Обложка Плейлиста',
playlistCoverPhoto: 'Обложка плейлиста',
playlistCoverPhotoSub: 'Показывать сетку обложек в детальном виде плейлиста',
showBitrate: 'Показывать Битрейт',
showBitrate: 'Показывать битрейт',
showBitrateSub: 'Отображать битрейт аудио в списках треков',
floatingPlayerBar: 'Плавающая панель плеера',
floatingPlayerBarSub: 'Держать панель плеера плавающей над содержимым',
+1 -1
View File
@@ -25,7 +25,7 @@ export const sidebar = {
genres: 'Жанры',
tracks: 'Треки',
playlists: 'Плейлисты',
smartPlaylists: 'Смарт-плейлисты',
smartPlaylists: 'Умные плейлисты',
mostPlayed: 'Популярное',
losslessAlbums: 'Lossless',
radio: 'Онлайн-радио',
+18
View File
@@ -84,4 +84,22 @@ export const statistics = {
playerListenedMinDecimal: '{{minutes}} мин',
completionFull: 'Прослушано',
completionPartial: 'Частично',
exportShare: 'Поделиться',
exportTitle: 'Поделиться топ-альбомами',
exportSubtitle: 'Создайте изображение с вашими самыми прослушиваемыми альбомами.',
exportFormat: 'Формат',
exportFormatStory: 'История',
exportFormatSquare: 'Квадрат',
exportFormatTwitter: 'Twitter Card',
exportGrid: 'Сетка',
exportGridLabel: '{{n}}×{{n}}',
exportPreview: 'Предпросмотр',
exportGenerate: 'Создать',
exportSave: 'Сохранить изображение…',
exportCancel: 'Отмена',
exportFooterLabel: 'Топ альбомов',
exportNotEnough: 'Нужно не менее {{count}} альбомов в библиотеке для сетки {{n}}×{{n}}.',
exportSaving: 'Сохранение…',
exportSaved: 'Сохранено.',
exportSaveFailed: 'Не удалось сохранить изображение.',
};
+2 -2
View File
@@ -1,7 +1,7 @@
export const tracks = {
title: 'Треки',
subtitle: 'Листать. Искать. Открывать.',
heroEyebrow: 'Трек момента',
subtitle: 'Листай. Ищи. Открывай.',
heroEyebrow: 'Рекомендуем',
heroReroll: 'Выбрать другой',
playSong: 'Воспроизвести',
enqueueSong: 'В очередь',