diff --git a/DynamicIsland/DynamicIslandApp.swift b/DynamicIsland/DynamicIslandApp.swift index d84ee76..c5f22a5 100644 --- a/DynamicIsland/DynamicIslandApp.swift +++ b/DynamicIsland/DynamicIslandApp.swift @@ -159,6 +159,9 @@ class AppDelegate: NSObject, NSApplicationDelegate { windowSizeUpdateWorkItem?.cancel() NotificationCenter.default.removeObserver(self) extensionXPCServiceHost.stop() + + // Restore Lunar's native OSD if integration was active + LunarManager.shared.appWillTerminate() } @objc func onScreenLocked(_: Notification) { @@ -415,6 +418,9 @@ class AppDelegate: NSObject, NSApplicationDelegate { // Setup BetterDisplay integration BetterDisplayManager.shared.configure(coordinator: coordinator) + + // Setup Lunar integration + LunarManager.shared.configure(coordinator: coordinator) // Setup ScreenRecording Manager if Defaults[.enableScreenRecordingDetection] { diff --git a/DynamicIsland/Localizable.xcstrings b/DynamicIsland/Localizable.xcstrings index e68f7ec..cfca853 100644 --- a/DynamicIsland/Localizable.xcstrings +++ b/DynamicIsland/Localizable.xcstrings @@ -103,13 +103,6 @@ }, " – %lld" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : " – %lld" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -184,7 +177,7 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : " – %lld" } }, @@ -265,13 +258,6 @@ }, "'Now Playing' was the only option on previous versions and works with all media apps." : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "'Сейчас воспроизводится' был единственным вариантом в предыдущих версиях, он работает со всеми медиа приложениями." - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -346,8 +332,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "'Сейчас играть' была единственной опцией в предыдущих версиях и работает со всеми медиа-приложениями." + "state" : "translated", + "value" : "'Сейчас воспроизводится' был единственным вариантом в предыдущих версиях, он работает со всеми медиа приложениями." } }, "tr" : { @@ -372,13 +358,6 @@ }, "(%@)" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "(%@)" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -453,7 +432,7 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "(%@)" } }, @@ -479,13 +458,6 @@ }, "%.0f seconds" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "%.0f секунд" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -560,8 +532,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "%.0f секунды" + "state" : "translated", + "value" : "%.0f секунд" } }, "tr" : { @@ -586,13 +558,6 @@ }, "%.1fs" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "%.1fс" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -667,8 +632,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "%.1fs" + "state" : "translated", + "value" : "%.1fс" } }, "tr" : { @@ -694,13 +659,6 @@ "%@" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "%@" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -775,7 +733,7 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "%@" } }, @@ -803,13 +761,6 @@ "comment" : "A secondary line of text that provides additional information about the air quality index, including its scale label and category name.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "%1$@ · %2$@" - } - }, - "en" : { "stringUnit" : { "state" : "new", @@ -821,6 +772,12 @@ "state" : "translated", "value" : "%1$@ · %2$@" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "%1$@ · %2$@" + } } } }, @@ -880,18 +837,17 @@ "comment" : "A row that combines a calendar event with a focus indicator. The first argument is the text of the calendar event. The second argument is the name of the focus.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "%1$@. Активный фокус: %2$@" - } - }, - "en" : { "stringUnit" : { "state" : "new", "value" : "%1$@. Focus active: %2$@" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "%1$@. Активный фокус: %2$@" + } } } }, @@ -909,13 +865,6 @@ }, "%d%%" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "%d%%" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -990,7 +939,7 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "%d%%" } }, @@ -1021,25 +970,17 @@ "comment" : "A text label showing the number of apps with which the current app has granted permissions. The argument is the count of such apps.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "%1$lld %2$@" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "%lld" - } - }, - "en" : { "stringUnit" : { "state" : "new", "value" : "%1$lld %2$@" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "%1$lld %2$@" + } } }, "shouldTranslate" : false @@ -1094,18 +1035,17 @@ "comment" : "Text that appears in the \"Time\" column of the \"Account History\" view, indicating how long ago a particular event occurred. The number in the parentheses is replaced with the actual number of days.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "%1$lld дней%2$@ назад" - } - }, - "en" : { "stringUnit" : { "state" : "new", "value" : "%1$lld day%2$@ ago" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "%1$lld дней%2$@ назад" + } } } }, @@ -1113,18 +1053,17 @@ "comment" : "Text for a time string, showing how many hours have passed since a given date.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "%1$lld часов%2$@ назад" - } - }, - "en" : { "stringUnit" : { "state" : "new", "value" : "%1$lld hour%2$@ ago" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "%1$lld часов%2$@ назад" + } } } }, @@ -1137,25 +1076,17 @@ "comment" : "A string describing how long ago a particular event occurred, based on the number of minutes that have passed.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "%1$lld минут%2$@ назад" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "%lld мин" - } - }, - "en" : { "stringUnit" : { "state" : "new", "value" : "%1$lld minute%2$@ ago" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "%1$lld минут%2$@ назад" + } } } }, @@ -1177,51 +1108,22 @@ "comment" : "A label displaying the number of enabled tabs, the recommended minimum notch width, and a button to reset the notch width to its recommended minimum value. The first argument is the count of enabled tabs. The second argument is the recommended minimum notch width as a formatted pixel count.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "%1$lld вкладок%2$@ включено · мин %3$lld пкс" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "%lld с" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "%lld пкс" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "%lld пт" - } - }, - "en" : { "stringUnit" : { "state" : "new", "value" : "%1$lld tab%2$@ enabled · min %3$lld px" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "%1$lld вкладок%2$@ включено · мин %3$lld пкс" + } } } }, "%lld%%" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "%lld%%" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -1296,7 +1198,7 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "%lld%%" } }, @@ -1343,46 +1245,17 @@ }, "%lldx" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "%lldм назад" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "%lldм" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "%lldч назад" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "%lldч" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "%lldд назад" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", "value" : "%lld fois" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lldм назад" + } } }, "shouldTranslate" : false @@ -1402,13 +1275,6 @@ }, "• Bug fixes" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "• Исправления ошибок" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -1483,7 +1349,7 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "• Исправления ошибок" } }, @@ -1521,13 +1387,6 @@ }, "• Improved performance" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "• Улучшена производительность" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -1602,8 +1461,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "• повышение эффективности" + "state" : "translated", + "value" : "• Улучшена производительность" } }, "tr" : { @@ -1640,13 +1499,6 @@ }, "• New feature 1" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "• Новая функция 1" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -1721,8 +1573,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "• New feature 1" + "state" : "translated", + "value" : "• Новая функция 1" } }, "tr" : { @@ -1789,13 +1641,6 @@ }, "+%lld more" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "••••••••" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", @@ -1807,6 +1652,12 @@ "state" : "translated", "value" : "+%lld mais" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "••••••••" + } } } }, @@ -1838,53 +1689,17 @@ "1x" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "1 мин" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "1 час" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "00:05:00" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "00" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "±10 Секунд" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", "value" : "1x" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "1 мин" + } } } }, @@ -1893,13 +1708,6 @@ }, "3 items" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "2 часа" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", @@ -1911,6 +1719,12 @@ "state" : "translated", "value" : "3 Itens" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "2 часа" + } } } }, @@ -1951,13 +1765,6 @@ }, "7 items" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "5 мин" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", @@ -1969,6 +1776,12 @@ "state" : "translated", "value" : "7 Itens" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "5 мин" + } } } }, @@ -2009,13 +1822,6 @@ }, "15 colors" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "10 мин" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", @@ -2027,6 +1833,12 @@ "state" : "translated", "value" : "15 Cores" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "10 мин" + } } } }, @@ -2036,18 +1848,17 @@ "20" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "15 мин" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", "value" : "20" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "15 мин" + } } } }, @@ -2091,45 +1902,23 @@ }, "100%" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "100" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "45 мин" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "30 мин" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", "value" : "100%" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "100" + } } }, "shouldTranslate" : false }, "About" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "О программе" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -2204,8 +1993,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "About" + "state" : "translated", + "value" : "О программе" } }, "tr" : { @@ -2234,20 +2023,6 @@ }, "Accent color" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Выделяющий цвет" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Акцент" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -2322,8 +2097,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Accent color" + "state" : "translated", + "value" : "Выделяющий цвет" } }, "tr" : { @@ -2360,13 +2135,6 @@ }, "Access Denied" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Доступ запрещён" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -2441,8 +2209,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Access Denied" + "state" : "translated", + "value" : "Доступ запрещён" } }, "tr" : { @@ -2604,20 +2372,6 @@ }, "Add" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Добавить" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Адаптивный градиент" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -2692,8 +2446,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Add" + "state" : "translated", + "value" : "Добавить" } }, "tr" : { @@ -2780,20 +2534,6 @@ "Add manually" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Добавить вручную" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Добавить значок" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -2868,8 +2608,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Add manually" + "state" : "translated", + "value" : "Добавить вручную" } }, "tr" : { @@ -2912,13 +2652,6 @@ }, "Add new visualizer" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Добавить новую визуализацию" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -2993,8 +2726,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Add new visualizer" + "state" : "translated", + "value" : "Добавить новую визуализацию" } }, "tr" : { @@ -3031,13 +2764,6 @@ }, "Additional features" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Дополнительные функции" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -3112,8 +2838,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Additional features" + "state" : "translated", + "value" : "Дополнительные функции" } }, "tr" : { @@ -3141,18 +2867,17 @@ }, "Adds a notch HUD when Caps Lock is enabled, with optional label and tint controls." : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Включить выпадающий терминал в стиле Guake. Сессия терминала сохраняется при сворачивании/разворачивании выреза." - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Adiciona um HUD no notch quando o Caps Lock está ativado, com controles opcionais de etiqueta e tonalidade." } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Включить выпадающий терминал в стиле Guake. Сессия терминала сохраняется при сворачивании/разворачивании выреза." + } } } }, @@ -3267,13 +2992,6 @@ "Air quality index %d, %@" : { "comment" : "Air quality accessibility label", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Индекс качества воздуха %1$d, %2$@" - } - }, - "en" : { "stringUnit" : { "state" : "new", @@ -3285,6 +3003,12 @@ "state" : "translated", "value" : "Nível de qualidade de ar %1$d, %2$@" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Индекс качества воздуха %1$d, %2$@" + } } } }, @@ -3310,13 +3034,6 @@ }, "AirDrop" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "AirDrop" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -3391,7 +3108,7 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "AirDrop" } }, @@ -3418,13 +3135,6 @@ }, "AirDrop service not available" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Служба AirDrop недоступна" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -3499,8 +3209,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "AirDrop service not available" + "state" : "translated", + "value" : "Служба AirDrop недоступна" } }, "tr" : { @@ -3528,30 +3238,22 @@ }, "All" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Выравнивание" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Tudo" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Выравнивание" + } } } }, "All-day" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Весь день" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -3626,8 +3328,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "All-day" + "state" : "translated", + "value" : "Весь день" } }, "tr" : { @@ -3664,13 +3366,6 @@ }, "Allow Access" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Разрешить доступ" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -3745,8 +3440,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Allow Access" + "state" : "translated", + "value" : "Разрешить доступ" } }, "tr" : { @@ -3796,53 +3491,17 @@ "comment" : "A label describing the allowed features for an app extension.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Разрешить отправку сообщений о действиях мыши" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Разрешить упрощенные переопределения/настройки" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Разрешить интерактивный веб-контент" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Разрешить функции выреза в расширениях" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Разрешить виджеты расширений на экране блокировки" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Разрешить эфиры активности расширений" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Recursos Permitidos" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Разрешить отправку сообщений о действиях мыши" + } } } }, @@ -3853,20 +3512,6 @@ }, "Always hide in fullscreen" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Всегда скрывать в полноэкранном режиме" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Альфа" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -3941,8 +3586,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Always hide in fullscreen" + "state" : "translated", + "value" : "Всегда скрывать в полноэкранном режиме" } }, "tr" : { @@ -3967,13 +3612,6 @@ }, "Always show tabs" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Всегда показывать вкладки" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -4048,8 +3686,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Always show tabs" + "state" : "translated", + "value" : "Всегда показывать вкладки" } }, "tr" : { @@ -4141,13 +3779,6 @@ }, "App icon" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Значок приложения" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -4222,8 +3853,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "App icon" + "state" : "translated", + "value" : "Значок приложения" } }, "tr" : { @@ -4260,13 +3891,6 @@ }, "Appearance" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Внешний вид" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -4341,8 +3965,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Appearance" + "state" : "translated", + "value" : "Внешний вид" } }, "tr" : { @@ -4371,18 +3995,17 @@ }, "Applies the notch-style parallax effect to the lock screen media widget album art." : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Apple Music" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Aplica o efeito de paralaxe ao notch à arte do álbum do widget de mídia da tela de bloqueio." } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Apple Music" + } } } }, @@ -4405,13 +4028,6 @@ "Are you sure you want to delete \"%@\"?" : { "comment" : "A confirmation prompt asking the user to confirm the deletion of a custom idle animation. The placeholder text inside the quotation marks should be replaced with the name of the animation.", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "AQI" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", @@ -4423,6 +4039,12 @@ "state" : "translated", "value" : "Tem certeza de que deseja excluir “%@”?" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "AQI" + } } } }, @@ -4566,13 +4188,6 @@ }, "Automatically check for updates" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Автоматически проверять обновления" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -4647,8 +4262,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Automatically check for updates" + "state" : "translated", + "value" : "Автоматически проверять обновления" } }, "tr" : { @@ -4673,13 +4288,6 @@ }, "Automatically download updates" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Автоматически загружать уведомления" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -4754,8 +4362,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Automatically download updates" + "state" : "translated", + "value" : "Автоматически загружать уведомления" } }, "tr" : { @@ -4803,18 +4411,17 @@ "comment" : "A control for adjusting the keyboard backlight intensity.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Фон" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Luz de Fundi" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Фон" + } } } }, @@ -4824,20 +4431,6 @@ }, "Battery" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Батарея" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Полоса" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -4912,8 +4505,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Battery" + "state" : "translated", + "value" : "Батарея" } }, "tr" : { @@ -4994,13 +4587,6 @@ }, "Battery Information" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Информация о батарее" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -5075,8 +4661,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Battery Information" + "state" : "translated", + "value" : "Информация о батарее" } }, "tr" : { @@ -5101,13 +4687,6 @@ }, "Battery Settings" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Настройки батареи" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -5182,8 +4761,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Battery Settings" + "state" : "translated", + "value" : "Настройки батареи" } }, "tr" : { @@ -5218,13 +4797,6 @@ }, "Battery Status" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Статус батареи" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -5299,8 +4871,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Battery Status" + "state" : "translated", + "value" : "Статус батареи" } }, "tr" : { @@ -5352,10 +4924,6 @@ "comment" : "The name of the BetterDisplay integration option.", "isCommentAutoGenerated" : true }, - "BetterDisplay Integration" : { - "comment" : "The header text for the \"BetterDisplay Integration\" section in the settings view.", - "isCommentAutoGenerated" : true - }, "BetterDisplay is installed but not currently running. Launch BetterDisplay to enable integration." : { }, @@ -5365,41 +4933,6 @@ "Blue dashed box shows actual size in Atoll" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Экранные индикаторы BetterDisplay будут отображаться в активном стиле панели Atoll. Убедитесь, что интеграция индикатора включена в BetterDisplay: Настройки › Приложение › Интеграция." - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "BetterDisplay установлен, но не включен. Запустите BetterDisplay для работы интеграции." - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Интеграция BetterDisplay" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "BetterDisplay" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Бета" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", @@ -5411,6 +4944,12 @@ "state" : "translated", "value" : "A caixa tracelhada azul mostra o tamanho real no Atol" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Экранные индикаторы BetterDisplay будут отображаться в активном стиле панели Atoll. Убедитесь, что интеграция индикатора включена в BetterDisplay: Настройки › Приложение › Интеграция." + } } } }, @@ -5447,13 +4986,6 @@ "Bluetooth device %@ at %d percent" : { "comment" : "Bluetooth device battery", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Bluetooth-устройство %1$@ на %2$d %" - } - }, - "en" : { "stringUnit" : { "state" : "new", @@ -5465,6 +4997,12 @@ "state" : "translated", "value" : "Dispositivo Bluetooth %1$@ em %2$d por cento" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bluetooth-устройство %1$@ на %2$d %" + } } } }, @@ -5473,20 +5011,6 @@ }, "Boost your productivity with Clipboard Manager" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Повысьте свою продуктивность с помощью менеджера буфера обмена." - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Жирный текст как яркие цвета" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -5561,8 +5085,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Boost your productivity with Clipboard Manager" + "state" : "translated", + "value" : "Повысьте свою продуктивность с помощью менеджера буфера обмена." } }, "tr" : { @@ -5588,13 +5112,6 @@ "Both" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Оба" - } - }, - "en" : { "stringUnit" : { "state" : "translated", @@ -5612,6 +5129,12 @@ "state" : "translated", "value" : "Ambos" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Оба" + } } } }, @@ -5623,13 +5146,6 @@ "comment" : "A label displayed above the breakdown of memory usage.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Перерыв" - } - }, - "de" : { "stringUnit" : { "state" : "translated", @@ -5647,6 +5163,12 @@ "state" : "needs_review", "value" : "Breakdown" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Перерыв" + } } } }, @@ -5654,18 +5176,17 @@ "comment" : "A control that adjusts the brightness of the device.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Пауза" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Brilho" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Пауза" + } } } }, @@ -5761,13 +5282,6 @@ }, "Calendar" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Календарь" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -5842,8 +5356,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Calendar" + "state" : "translated", + "value" : "Календарь" } }, "tr" : { @@ -5869,13 +5383,6 @@ "Calendar access is denied. Please enable it in System Settings." : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Доступ к календарю запрещен. Пожалуйста, включите его в настройках системы." - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -5950,8 +5457,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Calendar access is denied. Please enable it in System Settings." + "state" : "translated", + "value" : "Доступ к календарю запрещен. Пожалуйста, включите его в настройках системы." } }, "tr" : { @@ -5997,13 +5504,6 @@ }, "Calendars" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Виджет календаря" - } - }, - "de" : { "stringUnit" : { "state" : "translated", @@ -6021,6 +5521,12 @@ "state" : "translated", "value" : "Calendários" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Виджет календаря" + } } } }, @@ -6094,13 +5600,6 @@ }, "Cancel" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Отмена" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -6175,8 +5674,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Cancel" + "state" : "translated", + "value" : "Отмена" } }, "tr" : { @@ -6204,18 +5703,17 @@ }, "Caps Lock color" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Caps Lock" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Cor do Caps Lock" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Caps Lock" + } } } }, @@ -6271,13 +5769,6 @@ "Charging" : { "comment" : "Charging fallback label when no estimate is available", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Зарядка" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -6352,8 +5843,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Charging" + "state" : "translated", + "value" : "Зарядка" } }, "tr" : { @@ -6382,20 +5873,6 @@ }, "Charging on Hold: Desktop Mode" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Зарядка приостановлена: Настольный режим" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Зарядка батареи" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -6470,8 +5947,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Charging on Hold: Desktop Mode" + "state" : "translated", + "value" : "Зарядка приостановлена: Настольный режим" } }, "tr" : { @@ -6496,13 +5973,6 @@ }, "Check for Updates…" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Проверить обновления..." - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -6577,8 +6047,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Check for Updates…" + "state" : "translated", + "value" : "Проверить обновления..." } }, "tr" : { @@ -6632,13 +6102,6 @@ }, "Choose a Music Source" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Выберите источник музыки" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -6713,8 +6176,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Choose a Music Source" + "state" : "translated", + "value" : "Выберите источник музыки" } }, "tr" : { @@ -6885,13 +6348,6 @@ }, "Circle" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Круг" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -6966,8 +6422,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Circle" + "state" : "translated", + "value" : "Круг" } }, "tr" : { @@ -7002,25 +6458,17 @@ "comment" : "A description of the \"Classic mode\" option in the Lock Screen Integration settings.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Классический" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Круговой" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "O modo clássico mantém o fundo preto translúcido original." } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Классический" + } } } }, @@ -7031,13 +6479,6 @@ "Clear" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Классическая форма выреза, плавно переходящая в верхний край экрана" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", @@ -7049,6 +6490,12 @@ "state" : "translated", "value" : "Limpar" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Классическая форма выреза, плавно переходящая в верхний край экрана" + } } } }, @@ -7362,13 +6809,6 @@ }, "Close" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Закрыть" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -7443,8 +6883,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Close" + "state" : "translated", + "value" : "Закрыть" } }, "tr" : { @@ -7491,18 +6931,17 @@ "comment" : "A footer for the \"Diagnostics\" section of the lock screen settings.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Разработка и отладка: цветовая пипетка, мониторинг статистики и экранный помощник." - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Colete o relatório de falhas mais recente para compartilhar com o desenvolvedor ao relatar problemas de tela de bloqueio ou sobreposição." } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Разработка и отладка: цветовая пипетка, мониторинг статистики и экранный помощник." + } } } }, @@ -7675,20 +7114,6 @@ }, "Coming soon" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Скоро будет" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Цвета" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -7763,8 +7188,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Coming soon" + "state" : "translated", + "value" : "Скоро будет" } }, "tr" : { @@ -7870,6 +7295,10 @@ } } }, + "Connected to Lunar's DDC socket. Brightness, contrast, and volume adjustments will be shown through Atoll's HUD." : { + "comment" : "A description of what happens when the user enables the Lunar integration in the settings.", + "isCommentAutoGenerated" : true + }, "Connects directly to the Apple Music app." : { }, @@ -7878,27 +7307,6 @@ }, "Continue" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Продолжить" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Подключается напрямую к приложению Spotify." - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Подключается напрямую к приложению Apple Music." - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -7973,8 +7381,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Continue" + "state" : "translated", + "value" : "Продолжить" } }, "tr" : { @@ -8050,18 +7458,17 @@ }, "Controls the optional timer widget that floats above the media panel, including its classic, frosted, or liquid glass surface independent of the global material setting." : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Управляет областью напоминаний на экране блокировки и её расположением." - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Controla o widget de temporizador opcional que flutua acima do painel de mídia, incluindo sua superfície de vidro clássico, fosco ou líquido, independentemente da configuração global do material." } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Управляет областью напоминаний на экране блокировки и её расположением." + } } } }, @@ -8190,13 +7597,6 @@ }, "CPU Usage" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "ЦП" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", @@ -8208,6 +7608,12 @@ "state" : "translated", "value" : "Uso de CPU" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "ЦП" + } } } }, @@ -8217,18 +7623,17 @@ }, "Create from Clipboard" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Создание и дизайн: пипетка, зеркало, визуальные эффекты" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Criar a partir da Área de Transferência" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Создание и дизайн: пипетка, зеркало, визуальные эффекты" + } } } }, @@ -8338,38 +7743,23 @@ "Custom" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Стиль указателя" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Указатель" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", "value" : "Personnalisé" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Стиль указателя" + } } } }, "Custom color" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Пользовательский цвет" - } - }, - "en" : { "stringUnit" : { "state" : "translated", @@ -8381,18 +7771,17 @@ "state" : "translated", "value" : "Couleur personnalisée" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Пользовательский цвет" + } } } }, "Custom height" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Пользовательская высота" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -8467,8 +7856,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Custom height" + "state" : "translated", + "value" : "Пользовательская высота" } }, "tr" : { @@ -8498,18 +7887,17 @@ "comment" : "A description of the custom liquid blur option in the media settings.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Настраиваемая жидкость" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "O Liquid Glass personalizado já renderiza com o Liquid Glass da Apple, então essa opção é gerenciada automaticamente." } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Настраиваемая жидкость" + } } } }, @@ -8518,18 +7906,17 @@ }, "Custom Liquid settings require the Liquid Glass material." : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Настраиваемая жидкость доступна на macOS 26+" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "As configurações do Liquid Glass personalizadas requerem o material de Liquid Glass." } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Настраиваемая жидкость доступна на macOS 26+" + } } } }, @@ -8538,20 +7925,6 @@ }, "Custom music live activity animation" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Пользовательская анимация эфира активности музыки" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Свой вариант жидкости" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -8626,8 +7999,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Custom music live activity animation" + "state" : "translated", + "value" : "Пользовательская анимация эфира активности музыки" } }, "tr" : { @@ -8652,13 +8025,6 @@ }, "Custom notch size - %.0f" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Пользовательский размер выреза - %.0f" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -8733,8 +8099,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Custom notch size - %.0f" + "state" : "translated", + "value" : "Пользовательский размер выреза - %.0f" } }, "tr" : { @@ -8810,13 +8176,6 @@ }, "Custom vizualizers (Lottie)" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Пользовательская визуализация (Lottie)" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -8891,8 +8250,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Custom vizualizers (Lottie)" + "state" : "translated", + "value" : "Пользовательская визуализация (Lottie)" } }, "tr" : { @@ -8961,13 +8320,6 @@ }, "Customize in Settings" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Персонализировать в Настройках" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -9042,8 +8394,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Customize in Settings" + "state" : "translated", + "value" : "Персонализировать в Настройках" } }, "tr" : { @@ -9084,20 +8436,6 @@ }, "Default" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "По умолчанию" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Концентрация" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -9172,8 +8510,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Default" + "state" : "translated", + "value" : "По умолчанию" } }, "tr" : { @@ -9200,18 +8538,17 @@ "comment" : "A label displayed above the section that lets users configure a custom timer.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Стандартный" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Temporizador Personalizado Padrão" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Стандартный" + } } } }, @@ -9318,13 +8655,6 @@ "Description" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Описание" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -9399,8 +8729,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Description" + "state" : "translated", + "value" : "Описание" } }, "tr" : { @@ -9434,20 +8764,6 @@ "comment" : "The header for a section that displays whether the screen recording detection feature is currently active or inactive.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Дизайнер" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Отменить всё выделение" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", @@ -9459,6 +8775,12 @@ "state" : "translated", "value" : "Status de Detecção" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Дизайнер" + } } } }, @@ -9470,18 +8792,17 @@ "comment" : "The title of the \"Devices\" section in the settings menu.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Разработчик" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Dispositivos" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Разработчик" + } } } }, @@ -9503,31 +8824,23 @@ }, "Dimensions" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Цифровой" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Dimensões" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Цифровой" + } } } }, "Disable" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Отключить" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -9602,8 +8915,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Disable" + "state" : "translated", + "value" : "Отключить" } }, "tr" : { @@ -9631,20 +8944,6 @@ }, "Disabled" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Отключено" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Отключите минималистичный интерфейс для настройки стандартных элементов управления медиа в вырезе" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -9719,8 +9018,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Disabled" + "state" : "translated", + "value" : "Отключено" } }, "tr" : { @@ -9743,25 +9042,24 @@ } } }, - "Disabled while BetterDisplay integration is active — BetterDisplay uses Cmd+Brightness keys for its own controls." : { + "Disabled while external display integration is active — brightness keys are handled by the external app." : { }, "Discrete transitions snap between Green (0–60%), Yellow (60–85%), and Red (85–100%)." : { "comment" : "A description of how the color-coded progress bars work when not using smooth transitions.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Отключено при активной интеграции BetterDisplay — приложение использует Cmd+Клавиши яркости для своего управления." - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Transições discretas se encaixam entre Verde (0–60%), Amarelo (60–85%) e Vermelho (85–100%)." } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Отключено при активной интеграции BetterDisplay — приложение использует Cmd+Клавиши яркости для своего управления." + } } } }, @@ -9771,13 +9069,6 @@ }, "Disk Read" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Диск" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", @@ -9789,6 +9080,12 @@ "state" : "translated", "value" : "Leitura em Disco" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Диск" + } } } }, @@ -9842,13 +9139,6 @@ "comment" : "A footer for the \"Bluetooth Audio Devices\" section in the HUD settings.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Стиль дисплея" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", @@ -9860,6 +9150,12 @@ "state" : "translated", "value" : "Exibe uma notificação HUD quando os dispositivos de áudio Bluetooth (fones de ouvido, AirPods, alto-falantes) se conectam, mostrando o nome do dispositivo e o nível da bateria." } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Стиль дисплея" + } } } }, @@ -9888,18 +9184,17 @@ }, "Do Not Disturb" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Отображает ближайшее предстоящее событие календаря над или под виджетом погоды. Выбор календаря здесь не зависит от фильтра календаря в динамическом острове." - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Não Perturbe" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Отображает ближайшее предстоящее событие календаря над или под виджетом погоды. Выбор календаря здесь не зависит от фильтра календаря в динамическом острове." + } } } }, @@ -9911,30 +9206,22 @@ "comment" : "A button label that indicates that the user has finished editing a note.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Поддержать" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Feito" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Поддержать" + } } } }, "Download" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Загрузка" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -10009,8 +9296,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Download" + "state" : "translated", + "value" : "Загрузка" } }, "tr" : { @@ -10049,13 +9336,6 @@ "Download icon style" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Стиль значка загрузки" - } - }, - "en" : { "stringUnit" : { "state" : "translated", @@ -10073,18 +9353,17 @@ "state" : "translated", "value" : "Estilo do ícone de download" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Стиль значка загрузки" + } } } }, "Download indicator style" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Стиль индикатора загрузки" - } - }, - "en" : { "stringUnit" : { "state" : "translated", @@ -10102,6 +9381,12 @@ "state" : "translated", "value" : "Estilo do indicador de download" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Стиль индикатора загрузки" + } } } }, @@ -10118,13 +9403,6 @@ }, "Downloads" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Загрузки" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -10199,8 +9477,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Downloads" + "state" : "translated", + "value" : "Загрузки" } }, "tr" : { @@ -10265,20 +9543,6 @@ }, "Drop files here" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Перетащите файлы сюда" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Перетащите файл PNG, JPEG, TIFF или ICNS, чтобы добавить его в библиотеку значков." - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -10353,8 +9617,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Drop files here" + "state" : "translated", + "value" : "Перетащите файлы сюда" } }, "tr" : { @@ -10385,18 +9649,17 @@ "comment" : "A section header that lists the options for customizing the appearance of the progress bars displayed by Dynamic Island.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Динамический остров" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Barra de Progresso da Dynamic Island" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Динамический остров" + } } } }, @@ -10405,18 +9668,17 @@ }, "dynamic.island" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Видимость динамического острова" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", "value" : "dynamic.island" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Видимость динамического острова" + } } }, "shouldTranslate" : false @@ -10443,20 +9705,6 @@ }, "Easily copy, store, and manage your most-used content. Upgrade now for advanced features like multi-item storage and quick access!" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Легко копируйте, храните и управляйте наиболее часто используемым контентом. Обновите подписку прямо сейчас, чтобы получить доступ к расширенным функциям, таким как мульи-элементное хранение и быстрый доступ!" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "EAQI" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -10531,8 +9779,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Easily copy, store, and manage your most-used content. Upgrade now for advanced features like multi-item storage and quick access!" + "state" : "translated", + "value" : "Легко копируйте, храните и управляйте наиболее часто используемым контентом. Обновите подписку прямо сейчас, чтобы получить доступ к расширенным функциям, таким как мульи-элементное хранение и быстрый доступ!" } }, "tr" : { @@ -10573,13 +9821,6 @@ }, "Edit layout" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Редактировать макет" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -10654,8 +9895,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Edit layout" + "state" : "translated", + "value" : "Редактировать макет" } }, "tr" : { @@ -10758,13 +9999,6 @@ "Enable colored spectrograms" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Включить цветную спектрограмму" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -10839,8 +10073,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Enable colored spectrograms" + "state" : "translated", + "value" : "Включить цветную спектрограмму" } }, "tr" : { @@ -10902,25 +10136,17 @@ "comment" : "A footer text that explains the purpose of enabling extensions.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Включить журнал диагностики для расширений" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Включить элементы управления медиа в динамическом острове для управления панелью на экране блокировки." - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Ative extensões para permitir que aplicativos de terceiros exibam atividades ao vivo e widgets de tela de bloqueio no Atoll." } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Включить журнал диагностики для расширений" + } } } }, @@ -10949,13 +10175,6 @@ "Enable haptics" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Включить тактильную обратную связь" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -11030,8 +10249,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Enable haptics" + "state" : "translated", + "value" : "Включить тактильную обратную связь" } }, "tr" : { @@ -11057,13 +10276,6 @@ "Enable HUD replacement" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Включить замену системной панели" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -11138,8 +10350,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Enable HUD replacement" + "state" : "translated", + "value" : "Включить замену системной панели" } }, "tr" : { @@ -11169,30 +10381,22 @@ "comment" : "A toggle switch that enables or disables the blur effect on the media panel.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Включите в Настройках → Терминал" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Ativar desfoque do painel de mídia" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Включите в Настройках → Терминал" + } } } }, "Enable music live activity" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Включить эфир активности для музыки" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -11267,8 +10471,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Enable music live activity" + "state" : "translated", + "value" : "Включить эфир активности для музыки" } }, "tr" : { @@ -11377,18 +10581,17 @@ }, "Enable timer live activity" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Включить сторонние расширения" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Habilitar a atividade ao vivo do temporizador" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Включить сторонние расширения" + } } } }, @@ -11396,20 +10599,23 @@ "comment" : "A description of the benefit of enabling BetterDisplay integration.", "isCommentAutoGenerated" : true }, + "Enable to route Lunar's DDC brightness, contrast, and volume changes through Atoll's HUD." : { + "comment" : "A description of the functionality of enabling the integration with Lunar.", + "isCommentAutoGenerated" : true + }, "Enable when scaling beyond 30x20px so the Atoll opens gracefully." : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Включите, чтобы отображать изменения яркости и громкости BetterDisplay через панель Atoll вместо системных экранных индикаторов." - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Ative ao escalar além de 30x20 px para que o Atol abra graciosamente." } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Включите, чтобы отображать изменения яркости и громкости BetterDisplay через панель Atoll вместо системных экранных индикаторов." + } } } }, @@ -11433,13 +10639,6 @@ }, "Enhance your experience with HUDs" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Повысьте удобство работы с панелями" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -11514,8 +10713,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Enhance your experience with HUDs" + "state" : "translated", + "value" : "Повысьте удобство работы с панелями" } }, "tr" : { @@ -11540,13 +10739,6 @@ }, "Enjoy your free time!" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Наслаждайтесь свободным временем!" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -11621,8 +10813,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Enjoy your free time!" + "state" : "translated", + "value" : "Наслаждайтесь свободным временем!" } }, "tr" : { @@ -11663,13 +10855,6 @@ }, "Error" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ошибка" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -11744,8 +10929,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Error" + "state" : "translated", + "value" : "Ошибка" } }, "tr" : { @@ -11776,31 +10961,23 @@ "comment" : "A section header in the calendar settings view, describing the list of calendar events.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Цвет события" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Lista de eventos" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Цвет события" + } } } }, "Exclude apps" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Исключить приложения" - } - }, - "en" : { "stringUnit" : { "state" : "translated", @@ -11812,18 +10989,17 @@ "state" : "translated", "value" : "Exclure des applications" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Исключить приложения" + } } } }, "Exit" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Выход" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -11898,8 +11074,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Exit" + "state" : "translated", + "value" : "Выход" } }, "tr" : { @@ -11970,13 +11146,6 @@ }, "Extensions" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Расширения" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -12051,8 +11220,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Extensions" + "state" : "translated", + "value" : "Расширения" } }, "tr" : { @@ -12109,32 +11278,17 @@ "comment" : "A description below the currently selected quick share provider, explaining that files dropped on the shelf will be shared via that provider.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Файл" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Избранное" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Стиль на внешнем дисплее" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Os arquivos deixados na prateleira serão compartilhados através deste serviço" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Файл" + } } } }, @@ -12150,13 +11304,6 @@ }, "Finish" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Завершить" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -12231,8 +11378,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Finish" + "state" : "translated", + "value" : "Завершить" } }, "tr" : { @@ -12285,18 +11432,17 @@ "comment" : "An accessibility label for the focus widget, describing the currently active focus mode.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Фокус" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Foc ativo: %@" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Фокус" + } } } }, @@ -12306,18 +11452,17 @@ }, "Focus Status" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Режим обнаружения фокуса" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Status do Foco" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Режим обнаружения фокуса" + } } } }, @@ -12342,20 +11487,6 @@ "comment" : "A label displaying the amount of free storage on a disk device. The argument is the number of free bytes on the disk.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Текст" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Размер шрифта" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", @@ -12367,6 +11498,12 @@ "state" : "translated", "value" : "Livre · %@" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Текст" + } } } }, @@ -12381,25 +11518,17 @@ "Full Disk Access required" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Заряжено" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Матовое стекло" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Acesso completo ao disco necessário" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Заряжено" + } } } }, @@ -12432,13 +11561,6 @@ }, "General" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Общие" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -12513,8 +11635,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "General" + "state" : "translated", + "value" : "Общие" } }, "tr" : { @@ -12539,13 +11661,6 @@ }, "Gesture control" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Управление жестами" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -12620,8 +11735,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Gesture control" + "state" : "translated", + "value" : "Управление жестами" } }, "tr" : { @@ -12646,13 +11761,6 @@ }, "Gesture sensitivity" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Чувствительность жестов" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -12727,8 +11835,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Gesture sensitivity" + "state" : "translated", + "value" : "Чувствительность жестов" } }, "tr" : { @@ -12765,13 +11873,6 @@ }, "Get started" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Приступить" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -12846,8 +11947,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Get started" + "state" : "translated", + "value" : "Приступить" } }, "tr" : { @@ -12888,13 +11989,6 @@ }, "GitHub" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "GitHub" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -12969,7 +12063,7 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "GitHub" } }, @@ -13000,18 +12094,17 @@ }, "Glass mode" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Стекло" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Modo Vidro" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Стекло" + } } } }, @@ -13029,13 +12122,6 @@ }, "Got it!" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Есть!" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -13110,8 +12196,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Got it!" + "state" : "translated", + "value" : "Есть!" } }, "tr" : { @@ -13140,13 +12226,6 @@ }, "GPU Usage" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "ГП" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", @@ -13158,18 +12237,17 @@ "state" : "translated", "value" : "Uso de GPU" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "ГП" + } } } }, "Gradient" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Градиент" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -13244,8 +12322,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Gradient" + "state" : "translated", + "value" : "Градиент" } }, "tr" : { @@ -13291,13 +12369,6 @@ "Height:" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Зелёный" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", @@ -13309,6 +12380,12 @@ "state" : "translated", "value" : "Altura:" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Зелёный" + } } } }, @@ -13383,20 +12460,6 @@ }, "Hide only when NowPlaying app is in fullscreen" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Скрывать только во время полноэкранного режима медиа приложения" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Скрыть предварительный просмотр экрана блокировки" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -13471,8 +12534,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Hide only when NowPlaying app is in fullscreen" + "state" : "translated", + "value" : "Скрывать только во время полноэкранного режима медиа приложения" } }, "tr" : { @@ -13497,13 +12560,6 @@ }, "Hierarchical" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ступенчатый" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -13578,8 +12634,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Hierarchical" + "state" : "translated", + "value" : "Ступенчатый" } }, "tr" : { @@ -13605,13 +12661,6 @@ "High" : { "comment" : "High battery level label", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Высокий" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -13686,8 +12735,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "High" + "state" : "translated", + "value" : "Высокий" } }, "tr" : { @@ -13726,13 +12775,6 @@ }, "History Size" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "История" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", @@ -13744,6 +12786,12 @@ "state" : "translated", "value" : "Tamanho do Histórico" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "История" + } } } }, @@ -13774,13 +12822,6 @@ }, "https://github.com/th-ch/youtube-music" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "https://github.com/th-ch/youtube-music" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -13855,7 +12896,7 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", + "state" : "translated", "value" : "https://github.com/th-ch/youtube-music" } }, @@ -13886,30 +12927,22 @@ }, "HUD Position" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Стиль значка в панели" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Posição do HUD" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Стиль значка в панели" + } } } }, "HUD style" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Стиль панели" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -13984,8 +13017,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "HUD style" + "state" : "translated", + "value" : "Стиль панели" } }, "tr" : { @@ -14011,13 +13044,6 @@ "HUDs" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Панели" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -14092,8 +13118,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "HUDs" + "state" : "translated", + "value" : "Панели" } }, "tr" : { @@ -14171,13 +13197,6 @@ }, "Import" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Изображение" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", @@ -14189,6 +13208,12 @@ "state" : "translated", "value" : "Importar" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Изображение" + } } } }, @@ -14230,13 +13255,6 @@ }, "In progress" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "В процессе" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -14311,8 +13329,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "In progress" + "state" : "translated", + "value" : "В процессе" } }, "tr" : { @@ -14353,13 +13371,6 @@ }, "Inline" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Строкой" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -14434,8 +13445,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Inline" + "state" : "translated", + "value" : "Строкой" } }, "tr" : { @@ -14475,30 +13486,13 @@ "comment" : "A description of the benefits of installing BetterDisplay.", "isCommentAutoGenerated" : true }, + "Install [Lunar](https://lunar.fyi) to control external display brightness, contrast, and volume through Atoll's HUD via DDC." : { + "comment" : "A description of how to install Lunar on a device.", + "isCommentAutoGenerated" : true + }, "Install updates automatically" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Автоматически устанавливать обновления" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Установите [BetterDisplay](https://betterdisplay.pro) для управления яркостью и громкостью внешнего дисплея через панель Atoll." - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ввод" - } - }, - "en" : { "stringUnit" : { "state" : "translated", @@ -14510,19 +13504,18 @@ "state" : "translated", "value" : "Installer les mises à jour automatiquement" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Автоматически устанавливать обновления" + } } } }, "Installed extensions" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Установленные расширения" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -14597,8 +13590,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Installed extensions" + "state" : "translated", + "value" : "Установленные расширения" } }, "tr" : { @@ -14680,20 +13673,6 @@ }, "Keyboard Backlight HUD" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Только что" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "только что" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", @@ -14705,6 +13684,12 @@ "state" : "translated", "value" : "HUD de Brilho do Teclado" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Только что" + } } } }, @@ -14778,13 +13763,6 @@ }, "Later" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Позже" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -14859,8 +13837,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Later" + "state" : "translated", + "value" : "Позже" } }, "tr" : { @@ -14890,18 +13868,17 @@ }, "Layout Preview" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Макет" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Pré-vizualização do Layout" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Макет" + } } } }, @@ -14932,18 +13909,17 @@ }, "Line Width: %lldpx" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Лёгкий режим" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Largura da Linha: %lld px" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Лёгкий режим" + } } } }, @@ -14965,13 +13941,6 @@ }, "Liquid Glass requires macOS 26 or later." : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Жидкое стекло" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", @@ -14983,6 +13952,12 @@ "state" : "translated", "value" : "O Liquid Glass requer MacOS 26 ou posterior." } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Жидкое стекло" + } } } }, @@ -15107,13 +14082,6 @@ }, "Lock Screen" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Загрузка..." - } - }, - "fr" : { "stringUnit" : { "state" : "translated", @@ -15125,6 +14093,12 @@ "state" : "translated", "value" : "Tela de Bloqueio" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Загрузка..." + } } } }, @@ -15240,13 +14214,6 @@ }, "Lottie JSON URL" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ссылка на JSON Lottie" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -15321,8 +14288,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Lottie JSON URL" + "state" : "translated", + "value" : "Ссылка на JSON Lottie" } }, "tr" : { @@ -15348,13 +14315,6 @@ "Low" : { "comment" : "Low battery level label", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Низкий" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -15429,8 +14389,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Low" + "state" : "translated", + "value" : "Низкий" } }, "tr" : { @@ -15459,20 +14419,6 @@ }, "Low Power Mode" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Режим энергосбережения" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Низкий заряд батареи" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -15547,8 +14493,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Low Power Mode" + "state" : "translated", + "value" : "Режим энергосбережения" } }, "tr" : { @@ -15575,21 +14521,32 @@ "comment" : "Text displayed in a status label at the top of the screen indicating whether low power mode is on or off.", "isCommentAutoGenerated" : true }, + "Lunar" : { + "comment" : "The name of the Lunar display integration option.", + "isCommentAutoGenerated" : true + }, + "Lunar is installed but not currently running. Launch Lunar to enable integration." : { + "comment" : "A message displayed in the \"Lunar\" section of the settings, explaining that Lunar is installed but not currently running and that launching it will enable integration.", + "isCommentAutoGenerated" : true + }, + "Lunar is running but the socket connection is not yet established. It will connect automatically." : { + "comment" : "A description of what will happen when the user enables the Lunar integration in the settings.", + "isCommentAutoGenerated" : true + }, "Mac battery at %d percent" : { "comment" : "Mac battery gauge accessibility label", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Режим энергосбережения: %@" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Bateria do Mac em %d porcento" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Режим энергосбережения: %d" + } } } }, @@ -15624,18 +14581,17 @@ "comment" : "A description of how to manage the microphone privacy indicator preferences.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Стиль главного экрана" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Gerencie as preferências do indicador em Configurações → Privacidade. Não é necessário alternar manualmente o microfone." } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Стиль главного экрана" + } } } }, @@ -15665,13 +14621,6 @@ }, "Match menubar height" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Соответствовать высоте строки меню" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -15746,8 +14695,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Match menubar height" + "state" : "translated", + "value" : "Соответствовать высоте строки меню" } }, "tr" : { @@ -15772,13 +14721,6 @@ }, "Match real notch size" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Соответствовать реальным размерам выреза" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -15853,8 +14795,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Match real notch size" + "state" : "translated", + "value" : "Соответствовать реальным размерам выреза" } }, "tr" : { @@ -15886,30 +14828,22 @@ "comment" : "A label describing the material options for the custom OSD.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Материал" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Opções de Material:" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Материал" + } } } }, "Max Capacity: %lld%%" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Максимальная ёмкость: %lld%%" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -15984,8 +14918,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Max Capacity: %lld%%" + "state" : "translated", + "value" : "Максимальная ёмкость: %lld%%" } }, "tr" : { @@ -16014,20 +14948,6 @@ }, "Media" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Медиа" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Максимальная высота" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -16102,8 +15022,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Media" + "state" : "translated", + "value" : "Медиа" } }, "tr" : { @@ -16131,20 +15051,6 @@ "extractionState" : "stale", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Средний" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Переключение медиа с помощью горизонтальных жестов" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -16219,8 +15125,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Media change with horizontal gestures" + "state" : "translated", + "value" : "Средний" } }, "tr" : { @@ -16245,13 +15151,6 @@ }, "Media controls" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Элементы управления медиа" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -16326,8 +15225,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Media controls" + "state" : "translated", + "value" : "Элементы управления медиа" } }, "tr" : { @@ -16352,13 +15251,6 @@ }, "Media inactivity timeout" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Таймаут отсутствия активности медиа" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -16433,8 +15325,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Media inactivity timeout" + "state" : "translated", + "value" : "Таймаут отсутствия активности медиа" } }, "tr" : { @@ -16495,13 +15387,6 @@ }, "Media playback live activity" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Эфир активности воспроизведения медиа" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -16576,8 +15461,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Media playback live activity" + "state" : "translated", + "value" : "Эфир активности воспроизведения медиа" } }, "tr" : { @@ -16602,13 +15487,6 @@ }, "Media Source" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Источник медиа" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -16683,8 +15561,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Media Source" + "state" : "translated", + "value" : "Источник медиа" } }, "tr" : { @@ -16824,13 +15702,6 @@ }, "Memory Usage" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Память" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", @@ -16842,19 +15713,18 @@ "state" : "translated", "value" : "Uso de Memória" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Память" + } } } }, "Menubar icon" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Значок в строке меню" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -16929,8 +15799,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Menubar icon" + "state" : "translated", + "value" : "Значок в строке меню" } }, "tr" : { @@ -16973,20 +15843,6 @@ "Mic %@" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Микро %@" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Микро" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -17061,8 +15917,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Mic %@" + "state" : "translated", + "value" : "Микро %@" } }, "tr" : { @@ -17194,13 +16050,6 @@ }, "Minimum hover duration" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Минимальная длительность наведения курсора" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -17275,8 +16124,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Minimum hover duration" + "state" : "translated", + "value" : "Минимальная длительность наведения курсора" } }, "tr" : { @@ -17311,13 +16160,6 @@ }, "Mirror" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Зеркало" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -17392,8 +16234,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Mirror" + "state" : "translated", + "value" : "Зеркало" } }, "tr" : { @@ -17430,13 +16272,6 @@ }, "Mirror shape" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Форма зеркала" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -17511,8 +16346,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Mirror shape" + "state" : "translated", + "value" : "Форма зеркала" } }, "tr" : { @@ -17606,13 +16441,6 @@ }, "More" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Больше" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -17687,8 +16515,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "More" + "state" : "translated", + "value" : "Больше" } }, "tr" : { @@ -17747,13 +16575,6 @@ }, "Music Source" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Источник музыки" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -17828,8 +16649,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Music Source" + "state" : "translated", + "value" : "Источник музыки" } }, "tr" : { @@ -17854,13 +16675,6 @@ }, "muted" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "без звука" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -17935,8 +16749,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "muted" + "state" : "translated", + "value" : "без звука" } }, "tr" : { @@ -17979,13 +16793,6 @@ }, "Name" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Название" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -18060,8 +16867,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Name" + "state" : "translated", + "value" : "Название" } }, "tr" : { @@ -18102,13 +16909,6 @@ }, "Need Restart" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Требуется перезапуск" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -18183,8 +16983,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Need Restart" + "state" : "translated", + "value" : "Требуется перезапуск" } }, "tr" : { @@ -18213,13 +17013,6 @@ }, "Network Download" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Сеть" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", @@ -18231,6 +17024,12 @@ "state" : "translated", "value" : "Download de Rede" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Сеть" + } } } }, @@ -18252,13 +17051,6 @@ }, "Never hide" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Никогда не скрывать" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -18333,8 +17125,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Never hide" + "state" : "translated", + "value" : "Никогда не скрывать" } }, "tr" : { @@ -18459,13 +17251,6 @@ }, "No custom animation available" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Нет пользовательских анимаций" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -18540,8 +17325,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "No custom animation available" + "state" : "translated", + "value" : "Нет пользовательских анимаций" } }, "tr" : { @@ -18566,13 +17351,6 @@ }, "No custom visualizer" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Нет пользовательских визуализаций" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -18647,8 +17425,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "No custom visualizer" + "state" : "translated", + "value" : "Нет пользовательских визуализаций" } }, "tr" : { @@ -18685,13 +17463,6 @@ }, "No events today" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Сегодня нет событий" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -18766,8 +17537,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "No events today" + "state" : "translated", + "value" : "Сегодня нет событий" } }, "tr" : { @@ -18793,31 +17564,23 @@ "No excludes" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Исключений нет" - } - }, - "en" : { "stringUnit" : { "state" : "translated", "value" : "No excludes" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Исключений нет" + } } } }, "No extension installed" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Расширения не установлены" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -18892,8 +17655,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "No extension installed" + "state" : "translated", + "value" : "Расширения не установлены" } }, "tr" : { @@ -19036,13 +17799,6 @@ }, "Non-notch display height" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Высота для дисплеев без выреза" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -19117,8 +17873,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Non-notch display height" + "state" : "translated", + "value" : "Высота для дисплеев без выреза" } }, "tr" : { @@ -19165,20 +17921,6 @@ }, "Not Now" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Не сейчас" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Не заряжается" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -19253,8 +17995,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Not Now" + "state" : "translated", + "value" : "Не сейчас" } }, "tr" : { @@ -19289,13 +18031,6 @@ }, "Notch behavior" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Поведение выреза" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -19370,8 +18105,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Notch behavior" + "state" : "translated", + "value" : "Поведение выреза" } }, "tr" : { @@ -19396,13 +18131,6 @@ }, "Notch display height" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Высота выреза" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -19477,8 +18205,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Notch display height" + "state" : "translated", + "value" : "Высота выреза" } }, "tr" : { @@ -19508,20 +18236,6 @@ }, "Notch Height" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Высота выреза" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Функция динамического острова" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -19596,8 +18310,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Notch Height" + "state" : "translated", + "value" : "Высота выреза" } }, "tr" : { @@ -19652,18 +18366,17 @@ "comment" : "A label describing the slider that allows the user to set a reminder lead time.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ничего не воспроизводится" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Notificar antes" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ничего не воспроизводится" + } } } }, @@ -19680,34 +18393,6 @@ }, "OK" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "ОК" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Отключён" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Количество строк, сохраняемых в буфере обратной прокрутки. Большие значения используют больше памяти." - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Сейчас воспроизводится" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -19782,8 +18467,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "OK" + "state" : "translated", + "value" : "ОК" } }, "tr" : { @@ -19813,20 +18498,6 @@ }, "One or more files failed to load" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Не удалось загрузить один или несколько файлов" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Включён" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -19901,8 +18572,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "One or more files failed to load" + "state" : "translated", + "value" : "Не удалось загрузить один или несколько файлов" } }, "tr" : { @@ -19928,18 +18599,17 @@ "Only app icon" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Только значок приложения" - } - }, - "en" : { "stringUnit" : { "state" : "translated", "value" : "Only app icon" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Только значок приложения" + } } } }, @@ -19970,18 +18640,17 @@ "Only download icon" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Только значок загрузки" - } - }, - "en" : { "stringUnit" : { "state" : "translated", "value" : "Only download icon" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Только значок загрузки" + } } } }, @@ -20032,18 +18701,17 @@ }, "Opens the AI assistant panel for file analysis and conversation. Default is Cmd+Shift+A. Only works when screen assistant feature is enabled." : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Открывает прозрачное окно предварительного просмотра с имитаций данных, отражающих текущую конфигурацию виджета экрана блокировки." - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Abre o painel do assistente de IA para análise e conversação de arquivos. O padrão é Cmd+Shift+A. Só funciona quando o recurso de assistente de tela está ativado." } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Открывает прозрачное окно предварительного просмотра с имитаций данных, отражающих текущую конфигурацию виджета экрана блокировки." + } } } }, @@ -20080,25 +18748,17 @@ "comment" : "Section title for the list of available audio output devices in the media output selector.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Использование Option в качестве Meta клавиши отправляет Esc+клавишу вместо специальных символов macOS. Отправка сообщений о действиях мыши передаёт события мыши приложениям терминала, например vim или tmux." - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Использовать Option в качестве Meta клавиши" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Dispositivo de Saída" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Использование Option в качестве Meta клавиши отправляет Esc+клавишу вместо специальных символов macOS. Отправка сообщений о действиях мыши передаёт события мыши приложениям терминала, например vim или tmux." + } } } }, @@ -20134,18 +18794,17 @@ "comment" : "A description of the \"Panel\" clipboard display mode.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Панель" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "O modo painel mostra a área de transferência em uma janela flutuante perto do notch." } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Панель" + } } } }, @@ -20186,18 +18845,17 @@ }, "Percentage" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Процент" - } - }, - "en" : { "stringUnit" : { "state" : "translated", "value" : "Percentage" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Процент" + } } } }, @@ -20279,18 +18937,17 @@ }, "Pin items from history to save them here" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Остров с закруглёнными углами, похожий на динамический остров iPhone" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Fixe itens do histórico para salvá-los aqui" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Остров с закруглёнными углами, похожий на динамический остров iPhone" + } } } }, @@ -20348,13 +19005,6 @@ }, "Plugged In" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Подключено" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -20429,8 +19079,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Plugged In" + "state" : "translated", + "value" : "Подключено" } }, "tr" : { @@ -20461,18 +19111,17 @@ "comment" : "A description of the \"Popover mode\" in the Clipboard Settings view.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Всплывающее окно" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "O modo popover mostra a área de transferência como um menu suspenso anexado ao botão da área de transferência." } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Всплывающее окно" + } } } }, @@ -20592,18 +19241,17 @@ "comment" : "A label describing the zoom control for the animation preview.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Предпросмотр виджетов экрана блокировки" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Zoom de visualização" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Предпросмотр виджетов экрана блокировки" + } } } }, @@ -20638,25 +19286,17 @@ "Progress bar" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Индикатор прогресса" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Прогресс" - } - }, - "en" : { "stringUnit" : { "state" : "translated", "value" : "Progress bar" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Индикатор прогресса" + } } } }, @@ -20672,13 +19312,6 @@ }, "Progressbar style" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Стиль индикатора прогресса" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -20753,8 +19386,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Progressbar style" + "state" : "translated", + "value" : "Стиль индикатора прогресса" } }, "tr" : { @@ -20802,30 +19435,22 @@ "comment" : "A picker that lets the user select a quick share service to use when sharing files from the shelf.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Быстрая отправка" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Serviço de Quick Share" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Быстрая отправка" + } } } }, "Quit" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Закрыть" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -20900,8 +19525,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Quit" + "state" : "translated", + "value" : "Закрыть" } }, "tr" : { @@ -20926,13 +19551,6 @@ }, "Quit app" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Закрыть приложение" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -21007,8 +19625,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Quit app" + "state" : "translated", + "value" : "Закрыть приложение" } }, "tr" : { @@ -21034,13 +19652,6 @@ "Quit boring.notch" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Закрыть boring.notch" - } - }, - "en" : { "stringUnit" : { "state" : "translated", @@ -21052,6 +19663,12 @@ "state" : "translated", "value" : "Quitter boring.notch" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Закрыть boring.notch" + } } } }, @@ -21063,18 +19680,17 @@ "comment" : "A button that re-authorizes an app when pressed.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ч " - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Autorizar Novamente" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ч " + } } } }, @@ -21212,20 +19828,6 @@ }, "Release name" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Название релиза" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Обновить статус обнаружения" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -21300,8 +19902,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Release name" + "state" : "translated", + "value" : "Название релиза" } }, "tr" : { @@ -21326,13 +19928,6 @@ }, "Remember last tab" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Запомнить последнюю вкладку" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -21407,8 +20002,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Remember last tab" + "state" : "translated", + "value" : "Запомнить последнюю вкладку" } }, "tr" : { @@ -21448,13 +20043,6 @@ }, "Reminders" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Виджет напоминаний" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", @@ -21466,6 +20054,12 @@ "state" : "translated", "value" : "Lembretes" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Виджет напоминаний" + } } } }, @@ -21518,13 +20112,6 @@ }, "Request Access" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Удалить выбранное" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", @@ -21536,6 +20123,12 @@ "state" : "translated", "value" : "Requer Acesso" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Удалить выбранное" + } } } }, @@ -21545,18 +20138,17 @@ }, "Requires Accessibility permission so Dynamic Island can intercept the hardware volume keys." : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Требуется сторонний клиент с включенным плагином API." - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Requer permissão de Acessibilidade para que a Dynamic Island possa interceptar as teclas de volume do hardware." } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Требуется сторонний клиент с включенным плагином API." + } } } }, @@ -21683,13 +20275,6 @@ "Restart" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Перезапустить" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -21764,8 +20349,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Restart" + "state" : "translated", + "value" : "Перезапустить" } }, "tr" : { @@ -21820,32 +20405,17 @@ "comment" : "The text for a button that restores default settings.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Перезапускает процессы оболочки. Любые несохраненные данные в терминале будут потеряны." - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Перезапустить оболочку" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Перезапустить оболочку" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Redefinir" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Перезапускает процессы оболочки. Любые несохраненные данные в терминале будут потеряны." + } } } }, @@ -21907,18 +20477,17 @@ }, "Right" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Форматированный текст" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Direita" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Форматированный текст" + } } } }, @@ -21929,31 +20498,23 @@ "Rotation:" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Кольцо" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", "value" : "Rotation:" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Кольцо" + } } } }, "Running" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Запущено" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -22028,8 +20589,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Running" + "state" : "translated", + "value" : "Запущено" } }, "tr" : { @@ -22261,20 +20822,6 @@ }, "Search clipboard..." : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Строк обратной прокрутки" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Обратная прокрутка" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", @@ -22286,6 +20833,12 @@ "state" : "translated", "value" : "Pesquisar Área de Transferência" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Строк обратной прокрутки" + } } } }, @@ -22360,13 +20913,6 @@ "seconds" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "секунды" - } - }, - "en" : { "stringUnit" : { "state" : "translated", @@ -22378,6 +20924,12 @@ "state" : "translated", "value" : "secondes" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "секунды" + } } } }, @@ -22460,13 +21012,6 @@ }, "Select the music source you want to use. You can change this later in the app settings." : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Выберите желаемый источник музыки. Вы сможете изменить его позже в настройках приложения." - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -22541,8 +21086,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Select the music source you want to use. You can change this later in the app settings." + "state" : "translated", + "value" : "Выберите желаемый источник музыки. Вы сможете изменить его позже в настройках приложения." } }, "tr" : { @@ -22567,13 +21112,6 @@ }, "selected" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "выбрано" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -22648,8 +21186,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "selected" + "state" : "translated", + "value" : "выбрано" } }, "tr" : { @@ -22692,13 +21230,6 @@ }, "Selected animation" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Выбранная анимация" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -22773,8 +21304,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Selected animation" + "state" : "translated", + "value" : "Выбранная анимация" } }, "tr" : { @@ -22816,18 +21347,17 @@ "comment" : "A description of the \"Separate Tab\" clipboard display mode.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Отдельная вкладка" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "O modo Abas Separadas integra Itens Copiados e Notas em uma única visualização. Se ambos estiverem ativados, o Notes aparecerá à direita e a Área de Transferência à esquerda." } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Отдельная вкладка" + } } } }, @@ -22835,13 +21365,6 @@ "comment" : "A row displaying the total downloaded and uploaded bytes for the network session.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Сессия · ↓ %1$@ · ↑ %2$@" - } - }, - "en" : { "stringUnit" : { "state" : "new", @@ -22859,6 +21382,12 @@ "state" : "translated", "value" : "Sessão · ↓ %1$@ · ↑ %2$@" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Сессия · ↓ %1$@ · ↑ %2$@" + } } } }, @@ -22880,13 +21409,6 @@ }, "Settings" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Настройки" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -22961,8 +21483,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Settings" + "state" : "translated", + "value" : "Настройки" } }, "tr" : { @@ -22999,13 +21521,6 @@ }, "Shelf" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Панель файлов" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -23080,8 +21595,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Shelf" + "state" : "translated", + "value" : "Панель файлов" } }, "tr" : { @@ -23113,27 +21628,6 @@ }, "Shortcuts" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Сочетания клавиш" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Путь командной оболочки" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Оболочка" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -23208,8 +21702,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Shortcuts" + "state" : "translated", + "value" : "Сочетания клавиш" } }, "tr" : { @@ -23235,13 +21729,6 @@ "Show battery indicator" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Показать индикатор заряда батареи" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -23316,8 +21803,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Show battery indicator" + "state" : "translated", + "value" : "Показать индикатор заряда батареи" } }, "tr" : { @@ -23343,13 +21830,6 @@ "Show charging indicator" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Показать индикатор зарядки" - } - }, - "en" : { "stringUnit" : { "state" : "translated", @@ -23361,6 +21841,12 @@ "state" : "translated", "value" : "Afficher l’indicateur de charge" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Показать индикатор зарядки" + } } } }, @@ -23393,13 +21879,6 @@ "Show cool face animation while inactivity" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Показать прикольную анимацию лица при бездействия" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -23474,8 +21953,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Show cool face animation while inactivity" + "state" : "translated", + "value" : "Показать прикольную анимацию лица при бездействия" } }, "tr" : { @@ -23511,13 +21990,6 @@ "Show download progress" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Показать прогресс загрузки" - } - }, - "en" : { "stringUnit" : { "state" : "translated", @@ -23535,6 +22007,12 @@ "state" : "translated", "value" : "Mostrar o progresso do download" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Показать прогресс загрузки" + } } } }, @@ -23553,39 +22031,17 @@ }, "Show floating pause/stop controls" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Показать вкладки расширений" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Показать события в течение следующих" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Показать события из всех календарей" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Показать событие после его начала" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Mostrar controles flutuantes de pausa/parada" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Показать вкладки расширений" + } } } }, @@ -23603,13 +22059,6 @@ }, "Show on a specific display" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Показать на определённом дисплее" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -23684,8 +22133,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Show on a specific display" + "state" : "translated", + "value" : "Показать на определённом дисплее" } }, "tr" : { @@ -23710,13 +22159,6 @@ }, "Show on all displays" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Показать на всех дисплеях" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -23791,8 +22233,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Show on all displays" + "state" : "translated", + "value" : "Показать на всех дисплеях" } }, "tr" : { @@ -23850,13 +22292,6 @@ "Show shuffle and repeat buttons" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Показать кнопки перемешивания и повтора" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -23931,8 +22366,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Show shuffle and repeat buttons" + "state" : "translated", + "value" : "Показать кнопки перемешивания и повтора" } }, "tr" : { @@ -24009,20 +22444,6 @@ }, "Shows the model's reasoning process before the final answer" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Показывает экранный помощник во всплывающей панели рядом с вырезом" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Показывает экранный помощник в выпадающем списке, прикреплённом к кнопке ИИ" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", @@ -24034,6 +22455,12 @@ "state" : "translated", "value" : "Mostra o processo de raciocínio do modelo antes da resposta final" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Показывает экранный помощник во всплывающей панели рядом с вырезом" + } } } }, @@ -24053,18 +22480,17 @@ "Size & Scale" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Простой и минималистичный интерфейс с самым необходимым для повседневных задач." - } - }, - "fr" : { "stringUnit" : { "state" : "translated", "value" : "Taille et échelle" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Простой и минималистичный интерфейс с самым необходимым для повседневных задач." + } } } }, @@ -24096,20 +22522,6 @@ }, "Slider color" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Цвет ползунка" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Промотать вперёд или назад на 10 секунд" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -24184,8 +22596,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Slider color" + "state" : "translated", + "value" : "Цвет ползунка" } }, "tr" : { @@ -24244,13 +22656,6 @@ }, "Sneak Peek shows the media title and artist under the notch for a few seconds." : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "В режиме предварительного просмотра под вырезом в течение нескольких секунд отображается название медиа и исполнителя" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -24325,8 +22730,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Sneak Peek shows the media title and artist under the notch for a few seconds." + "state" : "translated", + "value" : "В режиме предварительного просмотра под вырезом в течение нескольких секунд отображается название медиа и исполнителя" } }, "tr" : { @@ -24351,13 +22756,6 @@ }, "Sneak Peek Style" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Стиль предварительного просмотра" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -24432,8 +22830,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Sneak Peek Style" + "state" : "translated", + "value" : "Стиль предварительного просмотра" } }, "tr" : { @@ -24471,13 +22869,6 @@ }, "Software updates" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Обновления ПО" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -24552,8 +22943,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Software updates" + "state" : "translated", + "value" : "Обновления ПО" } }, "tr" : { @@ -24588,13 +22979,6 @@ }, "Speed" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Скорость" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -24669,8 +23053,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Speed" + "state" : "translated", + "value" : "Скорость" } }, "tr" : { @@ -24710,20 +23094,6 @@ }, "Square" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Квадрат" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Spotify" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -24798,8 +23168,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Square" + "state" : "translated", + "value" : "Квадрат" } }, "tr" : { @@ -24841,34 +23211,6 @@ }, "Start" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Стандартные элементы управления предыдущим/следующим треком" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Стандартные элементы управления медиа скрыты. Включите переключатель выше заново, чтобы их восстановить." - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Стандартные элементы управления медиа в вырезе скрыты, когда этот переключатель отключен." - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Стандартный вырез" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", @@ -24880,6 +23222,12 @@ "state" : "translated", "value" : "Começar " } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Стандартные элементы управления предыдущим/следующим треком" + } } } }, @@ -25131,20 +23479,6 @@ }, "Stop" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Держите дела под контролем с календарём, таймером и мониторингом батареи." - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Статус:" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", @@ -25156,6 +23490,12 @@ "state" : "translated", "value" : "Parar" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Держите дела под контролем с календарём, таймером и мониторингом батареи." + } } } }, @@ -25193,13 +23533,6 @@ }, "Stopped" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Остановлено" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -25274,8 +23607,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Stopped" + "state" : "translated", + "value" : "Остановлено" } }, "tr" : { @@ -25304,18 +23637,17 @@ }, "Style" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Студент" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Estilo" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Студент" + } } } }, @@ -25334,13 +23666,6 @@ "Support Us" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Поддержать нас" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -25415,8 +23740,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Support Us" + "state" : "translated", + "value" : "Поддержать нас" } }, "tr" : { @@ -25506,13 +23831,6 @@ }, "System features" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Системные функции" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -25587,8 +23905,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "System features" + "state" : "translated", + "value" : "Системные функции" } }, "tr" : { @@ -25628,13 +23946,6 @@ }, "Take area screenshot" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Вкладка" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", @@ -25646,6 +23957,12 @@ "state" : "translated", "value" : "Captura de tela da área" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Вкладка" + } } } }, @@ -25686,53 +24003,17 @@ }, "These controls sit beside the notch while a timer runs. They require the timer name to stay hidden for spacing." : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Эти элементы управления дублируют вкладку «Экран блокировки», позволяя настроить панель медиа с акцентом на параметры воспроизведения." - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Динамический остров" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Текст" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Непрозрачность терминала" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Терминал отключён" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Терминал" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Esses controles ficam ao lado do notch enquanto um cronômetro é executado. Eles exigem que o nome do temporizador permaneça oculto para o espaçamento." } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Эти элементы управления дублируют вкладку «Экран блокировки», позволяя настроить панель медиа с акцентом на параметры воспроизведения." + } } } }, @@ -25775,18 +24056,17 @@ }, "This permanently removes every saved note and its attachments." : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Это необязательный параметр. Вы можете изменить его в любое время в строке меню." - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Isso remove permanentemente todas as notas salvas e seus anexos." } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Это необязательный параметр. Вы можете изменить его в любое время в строке меню." + } } } }, @@ -25815,13 +24095,6 @@ }, "Time to Full Charge: %lld min" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Время до полной зарядки: %lld минут" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -25896,8 +24169,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Time to Full Charge: %lld min" + "state" : "translated", + "value" : "Время до полной зарядки: %lld минут" } }, "tr" : { @@ -26106,13 +24379,6 @@ }, "Toggle Notch Open:" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Переключить открытие выреза:" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -26187,8 +24453,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Toggle Notch Open:" + "state" : "translated", + "value" : "Переключить открытие выреза:" } }, "tr" : { @@ -26213,13 +24479,6 @@ }, "Toggle Sneak Peek:" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Переключить предварительный просмотр:" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -26294,8 +24553,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Toggle Sneak Peek:" + "state" : "translated", + "value" : "Переключить предварительный просмотр:" } }, "tr" : { @@ -26360,18 +24619,17 @@ "Transform" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Пропустить" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", "value" : "Transformez" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Пропустить" + } } } }, @@ -26425,18 +24683,17 @@ "comment" : "A description of the feature that allows users to rearrange the order of media buttons.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Отключите 'Показывать событие всю его длительность', чтобы использовать опцию отображения времени с начала события." - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Ative os controles personalizáveis para reorganizar os botões de mídia." } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Отключите 'Показывать событие всю его длительность', чтобы использовать опцию отображения времени с начала события." + } } } }, @@ -26456,13 +24713,6 @@ "comment" : "A footer text explaining the gesture control functionality.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Сделайте свайп двумя пальцами вверх, чтобы свернуть вырез и вниз - чтобы его развернуть, когда функция **Развернуть вырез при наведении курсора\" отключена" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -26537,8 +24787,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Two-finger swipe up on notch to close, two-finger swipe down on notch to open when **Open notch on hover** option is disabled" + "state" : "translated", + "value" : "Сделайте свайп двумя пальцами вверх, чтобы свернуть вырез и вниз - чтобы его развернуть, когда функция **Развернуть вырез при наведении курсора\" отключена" } }, "tr" : { @@ -26580,13 +24830,6 @@ "Uninstall" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Удалить" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -26661,8 +24904,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Uninstall" + "state" : "translated", + "value" : "Удалить" } }, "tr" : { @@ -26691,20 +24934,6 @@ }, "Unlock advanced features and improve your experience. Upgrade now for more customizations!" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Откройте для себя расширенные возможности и улучшите свой пользовательский опыт. Обновите подписку прямо сейчас, чтобы получить больше настроек!" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Неизвестно" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -26779,8 +25008,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Unlock advanced features and improve your experience. Upgrade now for more customizations!" + "state" : "translated", + "value" : "Откройте для себя расширенные возможности и улучшите свой пользовательский опыт. Обновите подписку прямо сейчас, чтобы получить больше настроек!" } }, "tr" : { @@ -26805,13 +25034,6 @@ }, "unmuted" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "незаглушенный" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -26886,8 +25108,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "unmuted" + "state" : "translated", + "value" : "незаглушенный" } }, "tr" : { @@ -26916,18 +25138,17 @@ }, "Update interval" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Отключено" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Intervalo de atualização" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Отключено" + } } } }, @@ -26950,13 +25171,6 @@ }, "Upgrade to Pro" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Обновиться до Pro" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -27031,8 +25245,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Upgrade to Pro" + "state" : "translated", + "value" : "Обновиться до Pro" } }, "tr" : { @@ -27082,13 +25296,6 @@ "comment" : "A label displayed above the CPU usage statistics.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ссылка" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", @@ -27100,6 +25307,12 @@ "state" : "translated", "value" : "Uso" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ссылка" + } } } }, @@ -27137,20 +25350,6 @@ }, "Use music visualizer spectrogram" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Использовать визуализацию музыки (спектрограмму)" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Использовать инструменты разработчика (DevTools)" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -27225,8 +25424,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Use music visualizer spectrogram" + "state" : "translated", + "value" : "Использовать визуализацию музыки (спектрограмму)" } }, "tr" : { @@ -27279,13 +25478,6 @@ "comment" : "A label describing the percentage of memory that is currently in use.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Использовать без инструментов разработчика (DevTools)" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", @@ -27297,6 +25489,12 @@ "state" : "translated", "value" : "Usado" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Использовать без инструментов разработчика (DevTools)" + } } } }, @@ -27371,13 +25569,6 @@ }, "Version" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Версия" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -27452,8 +25643,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Version" + "state" : "translated", + "value" : "Версия" } }, "tr" : { @@ -27478,13 +25669,6 @@ }, "Version info" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Информация о версии" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -27559,8 +25743,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Version info" + "state" : "translated", + "value" : "Информация о версии" } }, "tr" : { @@ -27589,13 +25773,6 @@ "Vertical:" : { "extractionState" : "stale", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Вертикальный отступ" - } - }, - "fr" : { "stringUnit" : { "state" : "translated", @@ -27607,19 +25784,18 @@ "state" : "translated", "value" : "Vertical:" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Вертикальный отступ" + } } }, "shouldTranslate" : false }, "View on GitHub: th-ch/youtube-music" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Посмотреть на GitHub: th-ch/youtube-music" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -27694,8 +25870,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "View on GitHub: th-ch/youtube-music" + "state" : "translated", + "value" : "Посмотреть на GitHub: th-ch/youtube-music" } }, "tr" : { @@ -27766,18 +25942,17 @@ "comment" : "A label and its accompanying text displayed in a lock screen panel.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "З " - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Tempo" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "З " + } } } }, @@ -27806,13 +25981,6 @@ "Weather: %@ %@" : { "comment" : "Weather description and temperature", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Погода: %1$@ %2$@" - } - }, - "en" : { "stringUnit" : { "state" : "new", @@ -27824,19 +25992,18 @@ "state" : "translated", "value" : "Tempo: %1$@ %2$@" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Погода: %1$@ %2$@" + } } } }, "Weather: %@ %@ in %@" : { "comment" : "Weather description, temperature, and location", "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Погода: %1$@ %2$@ в %3$@" - } - }, - "en" : { "stringUnit" : { "state" : "new", @@ -27848,18 +26015,17 @@ "state" : "translated", "value" : "Tempo: %1$@ %2$@ in %3$@" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Погода: %1$@ %2$@ в %3$@" + } } } }, "Welcome" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Добро пожаловать" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -27934,8 +26100,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "Welcome" + "state" : "translated", + "value" : "Добро пожаловать" } }, "tr" : { @@ -27960,13 +26126,6 @@ }, "What's New" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Что нового" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -28041,8 +26200,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "What's New" + "state" : "translated", + "value" : "Что нового" } }, "tr" : { @@ -28070,41 +26229,42 @@ }, "When disabled, all keyboard shortcuts will be inactive. You can still use the UI controls." : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Когда параметр «Жирный текст как яркие цвета» отключён, он отображается более толстым начертанием шрифта вместо использования ярких ANSI-цветов." - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Quando desativado, todos os atalhos de teclado estarão inativos. Você ainda pode usar os controles da interface do usuário." } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Когда параметр «Жирный текст как яркие цвета» отключён, он отображается более толстым начертанием шрифта вместо использования ярких ANSI-цветов." + } } } }, - "When enabled, Atoll listens for OSD notifications from BetterDisplay and displays them using your selected HUD style above. This works alongside the existing media key interception — BetterDisplay handles external display controls while Atoll provides the visual feedback." : { - "comment" : "A footer description for the \"BetterDisplay Integration\" section in the settings view.", + "When enabled, Atoll connects to Lunar's TCP socket and displays DDC brightness, contrast, and volume events using your selected HUD style above." : { + + }, + "When enabled, Atoll listens for OSD notifications from BetterDisplay and displays them using your selected HUD style above." : { + "comment" : "A footer text for the \"BetterDisplay\" section in the \"External Display Integrations\" settings.", "isCommentAutoGenerated" : true }, "When enabled, Focus appears briefly (on/off) and then collapses instead of staying visible." : { "comment" : "A help text for the setting that allows the focus indicator to collapse instead of staying visible.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "При включении, Atoll будет получать экранные уведомления от BetterDisplay и отображать их в выбранном выше стиле панели. Это работает вместе с существующим перехватом мультимедийных клавиш — BetterDisplay управляет внешними дисплеями, а Atoll обеспечивает визуальную индикацию." - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Quando ativado, o Foco aparece brevemente (ligado/desligado) e depois fecha em vez de permanecer visível." } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "При включении, Atoll будет получать экранные уведомления от BetterDisplay и отображать их в выбранном выше стиле панели. Это работает вместе с существующим перехватом мультимедийных клавиш — BetterDisplay управляет внешними дисплеями, а Atoll обеспечивает визуальную индикацию." + } } } }, @@ -28124,18 +26284,17 @@ }, "When enabled, the Stats tab will display real-time system performance graphs. This feature requires system permissions and may use additional battery." : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "При включении, вырез на экране сдвигается вверх и скрывается на внешних (не имеющих выреза) дисплеях, пока вы не наведете на него курсор." - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Quando ativada, a guia Estatísticas exibirá gráficos de desempenho do sistema em tempo real. Esse recurso requer permissões do sistema e pode usar bateria adicional." } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "При включении, вырез на экране сдвигается вверх и скрывается на внешних (не имеющих выреза) дисплеях, пока вы не наведете на него курсор." + } } } }, @@ -28146,18 +26305,17 @@ "comment" : "A label describing the number of times the extension has updated its widget.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Белый" - } - }, - "pt-BR" : { "stringUnit" : { "state" : "translated", "value" : "Atualizações dos Widgets" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Белый" + } } } }, @@ -28206,13 +26364,6 @@ "comment" : "A label for the write section of the disk overview.", "isCommentAutoGenerated" : true, "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Работает со всеми медиа приложениями, включая браузеры, определяя, что воспроизводится. Заметка: функция может быть удалена в будущих версиях macOS." - } - }, - "fr" : { "stringUnit" : { "state" : "translated", @@ -28224,6 +26375,12 @@ "state" : "translated", "value" : "Escrever" } + }, + "ru" : { + "stringUnit" : { + "state" : "translated", + "value" : "Работает со всеми медиа приложениями, включая браузеры, определяя, что воспроизводится. Заметка: функция может быть удалена в будущих версиях macOS." + } } } }, @@ -28245,13 +26402,6 @@ }, "You can now enjoy the app. If you want to tweak things further, you can always visit the settings." : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Теперь Вы можете пользоваться приложением. Если хотите внести дополнительные изменения, Вы всегда можете сделать это в настройках." - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -28326,8 +26476,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "You can now enjoy the app. If you want to tweak things further, you can always visit the settings." + "state" : "translated", + "value" : "Теперь Вы можете пользоваться приложением. Если хотите внести дополнительные изменения, Вы всегда можете сделать это в настройках." } }, "tr" : { @@ -28352,13 +26502,6 @@ }, "You're All Set!" : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Всё готово!" - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -28433,8 +26576,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "You're All Set!" + "state" : "translated", + "value" : "Всё готово!" } }, "tr" : { @@ -28487,27 +26630,6 @@ }, "YouTube Music requires this third-party app to be installed: " : { "localizations" : { - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Для работы YouTube Music необходимо установить следующее стороннее приложение: " - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "YouTube Music" - } - }, - - "ru" : { - "stringUnit" : { - "state" : "translated", - "value" : "Ваша поддержка финансирует обучение разработке программного обеспечения для учащихся 9-12 классов." - } - }, - "ar" : { "stringUnit" : { "state" : "needs_review", @@ -28582,8 +26704,8 @@ }, "ru" : { "stringUnit" : { - "state" : "needs_review", - "value" : "YouTube Music requires this third-party app to be installed: " + "state" : "translated", + "value" : "Для работы YouTube Music необходимо установить следующее стороннее приложение: " } }, "tr" : { @@ -28608,4 +26730,4 @@ } }, "version" : "1.2" -} +} \ No newline at end of file diff --git a/DynamicIsland/components/Settings/SettingsView.swift b/DynamicIsland/components/Settings/SettingsView.swift index 0a1c2f6..e9eaa79 100644 --- a/DynamicIsland/components/Settings/SettingsView.swift +++ b/DynamicIsland/components/Settings/SettingsView.swift @@ -740,6 +740,7 @@ struct SettingsView: View { SettingsSearchEntry(tab: .hudAndOSD, title: "Material", keywords: ["material", "frosted", "liquid", "glass", "solid", "osd"], highlightID: SettingsTab.hudAndOSD.highlightID(for: "Material")), SettingsSearchEntry(tab: .hudAndOSD, title: "Icon & Progress Color", keywords: ["color", "icon", "white", "black", "gray", "osd"], highlightID: SettingsTab.hudAndOSD.highlightID(for: "Icon & Progress Color")), SettingsSearchEntry(tab: .hudAndOSD, title: "BetterDisplay integration", keywords: ["betterdisplay", "external", "display", "brightness", "integration", "third party"], highlightID: SettingsTab.hudAndOSD.highlightID(for: "BetterDisplay integration")), + SettingsSearchEntry(tab: .hudAndOSD, title: "Lunar integration", keywords: ["lunar", "ddc", "external", "display", "brightness", "contrast", "integration", "third party"], highlightID: SettingsTab.hudAndOSD.highlightID(for: "Lunar integration")), // Media SettingsSearchEntry(tab: .media, title: "Music Source", keywords: ["media source", "controller"], highlightID: SettingsTab.media.highlightID(for: "Music Source")), @@ -1495,6 +1496,7 @@ private struct HUDAndOSDSettingsView: View { @Default(.enableBrightnessHUD) var enableBrightnessHUD @Default(.enableKeyboardBacklightHUD) var enableKeyboardBacklightHUD @Default(.enableBetterDisplayIntegration) var enableBetterDisplayIntegration + @Default(.enableLunarIntegration) var enableLunarIntegration @Default(.verticalHUDShowValue) var verticalHUDShowValue @Default(.verticalHUDInteractive) var verticalHUDInteractive @Default(.verticalHUDHeight) var verticalHUDHeight @@ -1730,7 +1732,7 @@ private struct HUDAndOSDSettingsView: View { } case .vertical: Form { - if !accessibilityPermission.isAuthorized && !enableBetterDisplayIntegration { + if !accessibilityPermission.isAuthorized && !enableBetterDisplayIntegration && !enableLunarIntegration { Section { SettingsPermissionCallout( message: "Accessibility permission is needed to intercept system controls for the Vertical HUD.", @@ -1746,13 +1748,13 @@ private struct HUDAndOSDSettingsView: View { } } - if accessibilityPermission.isAuthorized || enableBetterDisplayIntegration { + if accessibilityPermission.isAuthorized || enableBetterDisplayIntegration || enableLunarIntegration { Section { Toggle("Volume HUD", isOn: $enableVolumeHUD) Toggle("Brightness HUD", isOn: $enableBrightnessHUD) Toggle("Keyboard Backlight HUD", isOn: $enableKeyboardBacklightHUD) - .disabled(enableBetterDisplayIntegration) - .help(enableBetterDisplayIntegration ? "Disabled while BetterDisplay integration is active — BetterDisplay uses Cmd+Brightness keys for its own controls." : "") + .disabled(enableBetterDisplayIntegration || enableLunarIntegration) + .help((enableBetterDisplayIntegration || enableLunarIntegration) ? "Disabled while external display integration is active — brightness keys are handled by the external app." : "") } header: { Text("Controls") } footer: { @@ -1847,7 +1849,7 @@ private struct HUDAndOSDSettingsView: View { case .circular: Form { - if !accessibilityPermission.isAuthorized && !enableBetterDisplayIntegration { + if !accessibilityPermission.isAuthorized && !enableBetterDisplayIntegration && !enableLunarIntegration { Section { SettingsPermissionCallout( message: "Accessibility permission is needed to intercept system controls for the Circular HUD.", @@ -1863,13 +1865,13 @@ private struct HUDAndOSDSettingsView: View { } } - if accessibilityPermission.isAuthorized || enableBetterDisplayIntegration { + if accessibilityPermission.isAuthorized || enableBetterDisplayIntegration || enableLunarIntegration { Section { Toggle("Volume HUD", isOn: $enableVolumeHUD) Toggle("Brightness HUD", isOn: $enableBrightnessHUD) Toggle("Keyboard Backlight HUD", isOn: $enableKeyboardBacklightHUD) - .disabled(enableBetterDisplayIntegration) - .help(enableBetterDisplayIntegration ? "Disabled while BetterDisplay integration is active — BetterDisplay uses Cmd+Brightness keys for its own controls." : "") + .disabled(enableBetterDisplayIntegration || enableLunarIntegration) + .help((enableBetterDisplayIntegration || enableLunarIntegration) ? "Disabled while external display integration is active — brightness keys are handled by the external app." : "") } header: { Text("Controls") } footer: { @@ -1909,8 +1911,8 @@ private struct HUDAndOSDSettingsView: View { } } - // BetterDisplay Integration (shared across all HUD variants) - BetterDisplayIntegrationSection() + // Third-party display integrations (shared across all HUD variants) + ExternalDisplayIntegrationsSection() } .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top) .background(paneBackgroundColor) @@ -1924,93 +1926,175 @@ private struct HUDAndOSDSettingsView: View { } } -// MARK: - BetterDisplay Integration Settings Section +// MARK: - External Display Integrations Settings Section -private struct BetterDisplayIntegrationSection: View { +private struct ExternalDisplayIntegrationsSection: View { @Default(.enableBetterDisplayIntegration) var enableBetterDisplayIntegration + @Default(.enableLunarIntegration) var enableLunarIntegration @ObservedObject private var betterDisplayManager = BetterDisplayManager.shared + @ObservedObject private var lunarManager = LunarManager.shared + + @State private var isBetterDisplayExpanded = false + @State private var isLunarExpanded = false private func highlightID(_ title: String) -> String { SettingsTab.hudAndOSD.highlightID(for: title) } - private var statusText: String { - if betterDisplayManager.isRunning { - return "Running" - } else if betterDisplayManager.isDetected { - return "Not running" - } else { - return "Not detected" - } + // MARK: BetterDisplay helpers + + private var bdStatusText: String { + if betterDisplayManager.isRunning { return "Running" } + if betterDisplayManager.isDetected { return "Not running" } + return "Not detected" } - private var statusColor: Color { - if betterDisplayManager.isRunning { - return .green - } else if betterDisplayManager.isDetected { - return .orange - } else { - return .secondary - } + private var bdStatusColor: Color { + if betterDisplayManager.isRunning { return .green } + if betterDisplayManager.isDetected { return .orange } + return .secondary + } + + // MARK: Lunar helpers + + private var lunarStatusText: String { + if lunarManager.isConnected { return "Connected" } + if lunarManager.isRunning { return "Running" } + if lunarManager.isDetected { return "Not running" } + return "Not detected" + } + + private var lunarStatusColor: Color { + if lunarManager.isConnected { return .green } + if lunarManager.isRunning { return .orange } + if lunarManager.isDetected { return .orange } + return .secondary } var body: some View { Form { + // MARK: - BetterDisplay + Section { - HStack { - VStack(alignment: .leading, spacing: 2) { + DisclosureGroup(isExpanded: $isBetterDisplayExpanded) { + HStack { + VStack(alignment: .leading, spacing: 2) { + Text(bdStatusText) + .font(.caption) + .foregroundStyle(bdStatusColor) + } + Spacer() + Toggle("", isOn: $enableBetterDisplayIntegration) + .toggleStyle(.switch) + .labelsHidden() + .disabled(!betterDisplayManager.isDetected) + } + .settingsHighlight(id: highlightID("BetterDisplay integration")) + + if !betterDisplayManager.isDetected { + Text("Install [BetterDisplay](https://betterdisplay.pro) to control external display brightness and volume through Atoll's HUD.") + .font(.caption) + .foregroundStyle(.secondary) + } else if !betterDisplayManager.isRunning { + Text("BetterDisplay is installed but not currently running. Launch BetterDisplay to enable integration.") + .font(.caption) + .foregroundStyle(.secondary) + } else if enableBetterDisplayIntegration { + Text("BetterDisplay OSD events will be routed through Atoll's active HUD style. Make sure BetterDisplay's OSD integration is enabled in its Settings › Application › Integration.") + .font(.caption) + .foregroundStyle(.secondary) + } else { + Text("Enable to route BetterDisplay's brightness and volume changes through Atoll's HUD instead of the system OSD.") + .font(.caption) + .foregroundStyle(.secondary) + } + + if betterDisplayManager.isDetected { + Button { + betterDisplayManager.refreshDetectionStatus() + } label: { + Label("Refresh detection", systemImage: "arrow.clockwise") + .font(.caption) + } + .buttonStyle(.link) + } + } label: { + HStack(spacing: 6) { + Image(systemName: "display.2") Text("BetterDisplay") .font(.system(size: 13, weight: .medium)) - Text(statusText) - .font(.caption) - .foregroundStyle(statusColor) } - - Spacer() - - Toggle("", isOn: $enableBetterDisplayIntegration) - .toggleStyle(.switch) - .labelsHidden() - .disabled(!betterDisplayManager.isDetected) - } - .settingsHighlight(id: highlightID("BetterDisplay integration")) - - if !betterDisplayManager.isDetected { - Text("Install [BetterDisplay](https://betterdisplay.pro) to control external display brightness and volume through Atoll's HUD.") - .font(.caption) - .foregroundStyle(.secondary) - } else if !betterDisplayManager.isRunning { - Text("BetterDisplay is installed but not currently running. Launch BetterDisplay to enable integration.") - .font(.caption) - .foregroundStyle(.secondary) - } else if enableBetterDisplayIntegration { - Text("BetterDisplay OSD events will be routed through Atoll's active HUD style. Make sure BetterDisplay's OSD integration is enabled in its Settings › Application › Integration.") - .font(.caption) - .foregroundStyle(.secondary) - } else { - Text("Enable to route BetterDisplay's brightness and volume changes through Atoll's HUD instead of the system OSD.") - .font(.caption) - .foregroundStyle(.secondary) - } - - if betterDisplayManager.isDetected { - Button { - betterDisplayManager.refreshDetectionStatus() - } label: { - Label("Refresh detection", systemImage: "arrow.clockwise") - .font(.caption) - } - .buttonStyle(.link) - } - } header: { - HStack(spacing: 6) { - Image(systemName: "display.2") - Text("BetterDisplay Integration") } } footer: { - Text("When enabled, Atoll listens for OSD notifications from BetterDisplay and displays them using your selected HUD style above. This works alongside the existing media key interception — BetterDisplay handles external display controls while Atoll provides the visual feedback.") - .foregroundStyle(.secondary) - .font(.caption) + if isBetterDisplayExpanded { + Text("When enabled, Atoll listens for OSD notifications from BetterDisplay and displays them using your selected HUD style above.") + .foregroundStyle(.secondary) + .font(.caption) + } + } + + // MARK: - Lunar + + Section { + DisclosureGroup(isExpanded: $isLunarExpanded) { + HStack { + VStack(alignment: .leading, spacing: 2) { + Text(lunarStatusText) + .font(.caption) + .foregroundStyle(lunarStatusColor) + } + Spacer() + Toggle("", isOn: $enableLunarIntegration) + .toggleStyle(.switch) + .labelsHidden() + .disabled(!lunarManager.isDetected) + } + .settingsHighlight(id: highlightID("Lunar integration")) + + if !lunarManager.isDetected { + Text("Install [Lunar](https://lunar.fyi) to control external display brightness, contrast, and volume through Atoll's HUD via DDC.") + .font(.caption) + .foregroundStyle(.secondary) + } else if !lunarManager.isRunning { + Text("Lunar is installed but not currently running. Launch Lunar to enable integration.") + .font(.caption) + .foregroundStyle(.secondary) + } else if lunarManager.isConnected && enableLunarIntegration { + Text("Connected to Lunar's DDC socket. Brightness, contrast, and volume adjustments will be shown through Atoll's HUD.") + .font(.caption) + .foregroundStyle(.secondary) + } else if enableLunarIntegration { + Text("Lunar is running but the socket connection is not yet established. It will connect automatically.") + .font(.caption) + .foregroundStyle(.secondary) + } else { + Text("Enable to route Lunar's DDC brightness, contrast, and volume changes through Atoll's HUD.") + .font(.caption) + .foregroundStyle(.secondary) + } + + if lunarManager.isDetected { + Button { + lunarManager.refreshDetectionStatus() + } label: { + Label("Refresh detection", systemImage: "arrow.clockwise") + .font(.caption) + } + .buttonStyle(.link) + } + } label: { + HStack(spacing: 6) { + Image(systemName: "moon.fill") + Text("Lunar") + .font(.system(size: 13, weight: .medium)) + } + } + } footer: { + if isLunarExpanded { + Text("When enabled, Atoll connects to Lunar's TCP socket and displays DDC brightness, contrast, and volume events using your selected HUD style above.") + .foregroundStyle(.secondary) + .font(.caption) + } } } } @@ -2158,6 +2242,7 @@ struct HUD: View { @Default(.enableBrightnessHUD) var enableBrightnessHUD @Default(.enableKeyboardBacklightHUD) var enableKeyboardBacklightHUD @Default(.enableBetterDisplayIntegration) var enableBetterDisplayIntegration + @Default(.enableLunarIntegration) var enableLunarIntegration @Default(.systemHUDSensitivity) var systemHUDSensitivity @ObservedObject var coordinator = DynamicIslandViewCoordinator.shared @ObservedObject private var accessibilityPermission = AccessibilityPermissionStore.shared @@ -2176,7 +2261,7 @@ struct HUD: View { var body: some View { Form { - if !hasAccessibilityPermission && !enableBetterDisplayIntegration { + if !hasAccessibilityPermission && !enableBetterDisplayIntegration && !enableLunarIntegration { Section { SettingsPermissionCallout( message: "Accessibility permission lets Dynamic Island replace the native volume, brightness, and keyboard HUDs.", @@ -2190,13 +2275,13 @@ struct HUD: View { - if enableSystemHUD && !Defaults[.enableCustomOSD] && (hasAccessibilityPermission || enableBetterDisplayIntegration) { + if enableSystemHUD && !Defaults[.enableCustomOSD] && (hasAccessibilityPermission || enableBetterDisplayIntegration || enableLunarIntegration) { Section { Toggle("Volume HUD", isOn: $enableVolumeHUD) Toggle("Brightness HUD", isOn: $enableBrightnessHUD) Toggle("Keyboard Backlight HUD", isOn: $enableKeyboardBacklightHUD) - .disabled(enableBetterDisplayIntegration) - .help(enableBetterDisplayIntegration ? "Disabled while BetterDisplay integration is active \u{2014} BetterDisplay uses Cmd+Brightness keys for its own controls." : "") + .disabled(enableBetterDisplayIntegration || enableLunarIntegration) + .help((enableBetterDisplayIntegration || enableLunarIntegration) ? "Disabled while external display integration is active \u{2014} brightness keys are handled by the external app." : "") } header: { Text("Controls") } footer: { @@ -6909,6 +6994,7 @@ struct CustomOSDSettings: View { @Default(.enableOSDBrightness) var enableOSDBrightness @Default(.enableOSDKeyboardBacklight) var enableOSDKeyboardBacklight @Default(.enableBetterDisplayIntegration) var enableBetterDisplayIntegration + @Default(.enableLunarIntegration) var enableLunarIntegration @Default(.osdMaterial) var osdMaterial @Default(.osdLiquidGlassCustomizationMode) var osdLiquidGlassCustomizationMode @Default(.osdLiquidGlassVariant) var osdLiquidGlassVariant @@ -6951,7 +7037,7 @@ struct CustomOSDSettings: View { var body: some View { Form { - if !hasAccessibilityPermission && !enableBetterDisplayIntegration { + if !hasAccessibilityPermission && !enableBetterDisplayIntegration && !enableLunarIntegration { Section { SettingsPermissionCallout( message: "Accessibility permission is needed to intercept system controls for the Custom OSD.", @@ -6963,7 +7049,7 @@ struct CustomOSDSettings: View { } } - if hasAccessibilityPermission || enableBetterDisplayIntegration { + if hasAccessibilityPermission || enableBetterDisplayIntegration || enableLunarIntegration { Section { Toggle("Volume OSD", isOn: $enableOSDVolume) .settingsHighlight(id: highlightID("Volume OSD")) @@ -6971,8 +7057,8 @@ struct CustomOSDSettings: View { .settingsHighlight(id: highlightID("Brightness OSD")) Toggle("Keyboard Backlight OSD", isOn: $enableOSDKeyboardBacklight) .settingsHighlight(id: highlightID("Keyboard Backlight OSD")) - .disabled(enableBetterDisplayIntegration) - .help(enableBetterDisplayIntegration ? "Disabled while BetterDisplay integration is active \u{2014} BetterDisplay uses Cmd+Brightness keys for its own controls." : "") + .disabled(enableBetterDisplayIntegration || enableLunarIntegration) + .help((enableBetterDisplayIntegration || enableLunarIntegration) ? "Disabled while external display integration is active \u{2014} brightness keys are handled by the external app." : "") } header: { Text("Controls") } footer: { diff --git a/DynamicIsland/managers/LunarManager.swift b/DynamicIsland/managers/LunarManager.swift new file mode 100644 index 0000000..2085fb0 --- /dev/null +++ b/DynamicIsland/managers/LunarManager.swift @@ -0,0 +1,505 @@ +/* + * Atoll (DynamicIsland) + * Copyright (C) 2024-2026 Atoll Contributors + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +@preconcurrency import Foundation +import AppKit +import Combine +import Defaults +import Network + +// MARK: - Lunar Display Data Model + +/// Matches the JSON structure streamed by Lunar's socket listener. +struct LunarDisplayData: Codable { + var brightness: Float? + var contrast: Float? + var volume: Float? + var mute: Bool? + var nits: Float? + var display: Int +} + +// MARK: - Lunar Control Category + +enum LunarControlCategory { + case brightness + case contrast + case volume +} + +// MARK: - Lunar Manager + +/// Manages integration with the Lunar app (fyi.lunar.Lunar). +/// +/// Responsibilities: +/// - Detect whether Lunar is installed and running +/// - Observe app launch / termination to connect / disconnect automatically +/// - Connect to Lunar's TCP socket on localhost:23803 and listen for DDC changes +/// - Route brightness / contrast / volume events to Atoll's HUD pipeline +@MainActor +final class LunarManager: ObservableObject { + static let shared = LunarManager() + + /// Bundle identifier of the Lunar app. + nonisolated static let bundleID = "fyi.lunar.Lunar" + + /// UserDefaults suite used by Lunar to store its API key. + private static let lunarDomain = "fyi.lunar.Lunar" + private static let apiKeyKey = "apiKey" + + // MARK: Published state + + /// Whether Lunar is currently detected (installed) on this machine. + @Published private(set) var isDetected: Bool = false + + /// Whether Lunar is currently running. + @Published private(set) var isRunning: Bool = false + + /// Whether the TCP socket connection to Lunar is active. + @Published private(set) var isConnected: Bool = false + + // MARK: Private + + private var connection: NWConnection? + private var workspaceLaunchObserver: NSObjectProtocol? + private var workspaceTermObserver: NSObjectProtocol? + private var cancellables = Set() + private weak var coordinator: DynamicIslandViewCoordinator? + + /// Reconnection back-off state. + private var reconnectTask: Task? + private var reconnectAttempts: Int = 0 + private static let maxReconnectAttempts = 5 + private static let baseReconnectDelay: UInt64 = 2_000_000_000 // 2 seconds + + private init() { + isDetected = Self.checkInstallation() + isRunning = Self.checkRunning() + setupWorkspaceObservers() + setupSettingsObserver() + } + + // MARK: - Public API + + /// Configure with the view coordinator for HUD dispatch. + func configure(coordinator: DynamicIslandViewCoordinator) { + self.coordinator = coordinator + + if Defaults[.enableLunarIntegration] && isRunning { + connectToLunar() + } + } + + /// Called when Atoll is about to quit so Lunar's native OSD is restored. + func appWillTerminate() { + setLunarHideOSD(false) + } + + /// Refresh detection status (e.g. after manual check from Settings). + func refreshDetectionStatus() { + let wasRunning = isRunning + isDetected = Self.checkInstallation() + isRunning = Self.checkRunning() + if wasRunning && !isRunning { + disconnect() + } else if !wasRunning && isRunning && Defaults[.enableLunarIntegration] { + connectToLunar() + } + } + + // MARK: - Detection + + /// Check if Lunar is installed by looking for its bundle ID. + nonisolated static func checkInstallation() -> Bool { + if NSWorkspace.shared.runningApplications.contains(where: { $0.bundleIdentifier == bundleID }) { + return true + } + if let url = NSWorkspace.shared.urlForApplication(withBundleIdentifier: bundleID) { + return FileManager.default.fileExists(atPath: url.path) + } + return false + } + + /// Check if Lunar is currently running. + nonisolated static func checkRunning() -> Bool { + NSWorkspace.shared.runningApplications.contains(where: { $0.bundleIdentifier == bundleID }) + } + + // MARK: - Socket Connection + + private func connectToLunar() { + guard connection == nil else { return } + guard let apiKey = Self.retrieveAPIKey() else { + NSLog("⚠️ Lunar: failed to retrieve API key from UserDefaults suite '\(Self.lunarDomain)'") + return + } + + setLunarHideOSD(true) + + let host = NWEndpoint.Host("localhost") + let port = NWEndpoint.Port(23803) + let conn = NWConnection(host: host, port: port, using: .tcp) + + conn.stateUpdateHandler = { [weak self] state in + Task { @MainActor in + self?.handleConnectionState(state, apiKey: apiKey) + } + } + + connection = conn + conn.start(queue: DispatchQueue.global(qos: .utility)) + NSLog("🌙 Lunar: connecting to socket on \(host):\(port)…") + } + + private func disconnect() { + reconnectTask?.cancel() + reconnectTask = nil + reconnectAttempts = 0 + + if let conn = connection { + conn.stateUpdateHandler = nil + conn.cancel() + connection = nil + } + isConnected = false + setLunarHideOSD(false) + NSLog("⏹ Lunar: socket disconnected") + } + + private func handleConnectionState(_ state: NWConnection.State, apiKey: String) { + switch state { + case .ready: + isConnected = true + reconnectAttempts = 0 + NSLog("🌙 Lunar: connected to socket") + sendListenCommand(apiKey: apiKey) + receiveMessages() + + case .failed(let error): + NSLog("🌙 Lunar: connection failed — \(error.localizedDescription)") + isConnected = false + connection?.cancel() + connection = nil + scheduleReconnect() + + case .cancelled: + isConnected = false + + case .waiting(let error): + NSLog("🌙 Lunar: connection waiting — \(error.localizedDescription)") + + default: + break + } + } + + /// Send Lunar's listen command with the API key. + private func sendListenCommand(apiKey: String) { + guard let conn = connection else { return } + + let separator = String(UnicodeScalar(0x01)) + let message = [apiKey, "listen", "--json", "--only-user-adjustments"] + .joined(separator: separator) + + guard let data = message.data(using: .utf8) else { + NSLog("⚠️ Lunar: failed to encode listen command") + return + } + + conn.send(content: data, completion: .contentProcessed { error in + if let error { + NSLog("⚠️ Lunar: failed to send listen command — \(error.localizedDescription)") + } else { + NSLog("🌙 Lunar: listen command sent") + } + }) + } + + /// Receive JSON messages from Lunar's socket in a loop. + private func receiveMessages() { + guard let conn = connection else { return } + + conn.receive(minimumIncompleteLength: 1, maximumLength: 4096) { [weak self] data, _, isComplete, error in + if let data, !data.isEmpty { + Task { @MainActor in + self?.handleReceivedData(data) + } + } + + if isComplete { + NSLog("🌙 Lunar: stream ended") + Task { @MainActor in + self?.isConnected = false + self?.connection?.cancel() + self?.connection = nil + self?.scheduleReconnect() + } + } else if let error { + NSLog("⚠️ Lunar: receive error — \(error.localizedDescription)") + Task { @MainActor in + self?.isConnected = false + self?.connection?.cancel() + self?.connection = nil + self?.scheduleReconnect() + } + } else { + // Continue reading + Task { @MainActor in + self?.receiveMessages() + } + } + } + } + + private func handleReceivedData(_ data: Data) { + guard Defaults[.enableLunarIntegration], isRunning else { return } + + do { + let displayData = try JSONDecoder().decode(LunarDisplayData.self, from: data) + NSLog("🌙 Lunar: display=\(displayData.display) brightness=\(displayData.brightness ?? -1) contrast=\(displayData.contrast ?? -1) volume=\(displayData.volume ?? -1) mute=\(displayData.mute.map(String.init) ?? "nil")") + routeToHUD(displayData) + } catch { + // Lunar may send multi-line JSON or partial data; try splitting by newlines + let rawString = String(data: data, encoding: .utf8) ?? "" + let lines = rawString.components(separatedBy: .newlines).filter { !$0.isEmpty } + for line in lines { + guard let lineData = line.data(using: .utf8) else { continue } + if let displayData = try? JSONDecoder().decode(LunarDisplayData.self, from: lineData) { + NSLog("🌙 Lunar: display=\(displayData.display) brightness=\(displayData.brightness ?? -1) contrast=\(displayData.contrast ?? -1) volume=\(displayData.volume ?? -1)") + routeToHUD(displayData) + } + } + } + } + + // MARK: - HUD Routing + + private func routeToHUD(_ data: LunarDisplayData) { + let targetScreen = resolveScreen(for: data.display) + let isExternal = isExternalDisplay(data.display) + + // Nits-only events are informational (no user-facing HUD needed). + let hasActionableChange = data.brightness != nil || data.contrast != nil || data.volume != nil || data.mute != nil + guard hasActionableChange else { return } + + // Brightness — values arrive in 0…1 range from Lunar + if let brightness = data.brightness { + let value = CGFloat(brightness) + let icon = isExternal ? "display" : "" + dispatchBrightnessHUD(value: value, icon: icon, onScreen: targetScreen) + } + + // Contrast — show as brightness-style HUD with a contrast icon + if let contrast = data.contrast { + let value = CGFloat(contrast) + dispatchBrightnessHUD(value: value, icon: "circle.righthalf.filled", onScreen: targetScreen) + } + + // Volume + if let volume = data.volume { + let value = CGFloat(volume) + let isMuted = data.mute ?? false + dispatchVolumeHUD(value: value, isMuted: isMuted, onScreen: targetScreen) + } else if let mute = data.mute { + // Mute toggle without a volume value + dispatchVolumeHUD(value: mute ? 0 : 1, isMuted: mute, onScreen: targetScreen) + } + } + + // MARK: - HUD Dispatch (mirrors BetterDisplayManager / SystemChangesObserver logic) + + private func dispatchVolumeHUD(value: CGFloat, isMuted: Bool, onScreen targetScreen: NSScreen? = nil) { + if HUDSuppressionCoordinator.shared.shouldSuppressVolumeHUD { return } + + if Defaults[.enableCircularHUD] { + CircularHUDWindowManager.shared.show(type: .volume, value: value, onScreen: targetScreen) + return + } + if Defaults[.enableVerticalHUD] { + VerticalHUDWindowManager.shared.show(type: .volume, value: value, icon: "", onScreen: targetScreen) + return + } + if Defaults[.enableCustomOSD] && Defaults[.enableOSDVolume] { + CustomOSDWindowManager.shared.showVolume(value: value, onScreen: targetScreen) + } + if Defaults[.enableSystemHUD] && !Defaults[.enableCustomOSD] && !Defaults[.enableVerticalHUD] && !Defaults[.enableCircularHUD] { + coordinator?.toggleSneakPeek( + status: true, + type: .volume, + value: value, + icon: "" + ) + } + } + + private func dispatchBrightnessHUD(value: CGFloat, icon: String = "", onScreen targetScreen: NSScreen? = nil) { + if Defaults[.enableCircularHUD] { + CircularHUDWindowManager.shared.show(type: .brightness, value: value, icon: icon, onScreen: targetScreen) + return + } + if Defaults[.enableVerticalHUD] { + VerticalHUDWindowManager.shared.show(type: .brightness, value: value, icon: icon, onScreen: targetScreen) + return + } + if Defaults[.enableCustomOSD] && Defaults[.enableOSDBrightness] { + CustomOSDWindowManager.shared.showBrightness(value: value, icon: icon, onScreen: targetScreen) + } + if Defaults[.enableSystemHUD] && !Defaults[.enableCustomOSD] && !Defaults[.enableVerticalHUD] && !Defaults[.enableCircularHUD] { + coordinator?.toggleSneakPeek( + status: true, + type: .brightness, + value: value, + icon: icon + ) + } + } + + // MARK: - Helpers + + /// Retrieve the Lunar API key from its UserDefaults suite. + nonisolated private static func retrieveAPIKey() -> String? { + UserDefaults(suiteName: lunarDomain)?.string(forKey: apiKeyKey) + } + + /// Resolve a Lunar display ID (CGDirectDisplayID) to the matching NSScreen. + private func resolveScreen(for displayID: Int) -> NSScreen? { + let target = UInt32(displayID) + return NSScreen.screens.first { screen in + guard let num = screen.deviceDescription[NSDeviceDescriptionKey("NSScreenNumber")] as? NSNumber else { return false } + return num.uint32Value == target + } + } + + /// Whether the given displayID refers to an external (non-built-in) display. + private func isExternalDisplay(_ displayID: Int) -> Bool { + CGDisplayIsBuiltin(UInt32(displayID)) == 0 + } + + // MARK: - Reconnection + + private func scheduleReconnect() { + guard Defaults[.enableLunarIntegration], isRunning else { return } + guard reconnectAttempts < Self.maxReconnectAttempts else { + NSLog("🌙 Lunar: max reconnect attempts reached, giving up") + return + } + + reconnectTask?.cancel() + let attempt = reconnectAttempts + reconnectAttempts += 1 + + let delay = Self.baseReconnectDelay * UInt64(1 << min(attempt, 3)) // exponential back-off, max 16s + + reconnectTask = Task { @MainActor in + try? await Task.sleep(nanoseconds: delay) + guard !Task.isCancelled, self.isRunning, Defaults[.enableLunarIntegration] else { return } + NSLog("🌙 Lunar: reconnect attempt \(attempt + 1)/\(Self.maxReconnectAttempts)") + self.connectToLunar() + } + } + + // MARK: - Workspace Observers (detect Lunar launch / quit) + + private func setupWorkspaceObservers() { + let lunarBundleID = Self.bundleID + + workspaceLaunchObserver = NSWorkspace.shared.notificationCenter.addObserver( + forName: NSWorkspace.didLaunchApplicationNotification, + object: nil, + queue: .main + ) { [weak self] notification in + guard let app = notification.userInfo?[NSWorkspace.applicationUserInfoKey] as? NSRunningApplication, + app.bundleIdentifier == lunarBundleID + else { return } + Task { @MainActor in + NSLog("🟢 Lunar launched (pid: \(app.processIdentifier))") + self?.isDetected = true + self?.isRunning = true + self?.reconnectAttempts = 0 + if Defaults[.enableLunarIntegration] { + // Give Lunar a moment to start its socket server + try? await Task.sleep(nanoseconds: 1_500_000_000) + self?.connectToLunar() + } + } + } + + workspaceTermObserver = NSWorkspace.shared.notificationCenter.addObserver( + forName: NSWorkspace.didTerminateApplicationNotification, + object: nil, + queue: .main + ) { [weak self] notification in + guard let app = notification.userInfo?[NSWorkspace.applicationUserInfoKey] as? NSRunningApplication, + app.bundleIdentifier == lunarBundleID + else { return } + Task { @MainActor in + NSLog("🔴 Lunar terminated (pid: \(app.processIdentifier))") + self?.isRunning = false + self?.disconnect() + } + } + } + + // MARK: - Settings Observer + + private func setupSettingsObserver() { + Defaults.publisher(.enableLunarIntegration, options: []) + .sink { [weak self] change in + Task { @MainActor in + guard let self else { return } + if change.newValue && self.isRunning { + self.connectToLunar() + } else { + self.disconnect() + } + } + } + .store(in: &cancellables) + } + + deinit { + // Restore Lunar's native OSD synchronously on teardown + LunarManager.writeLunarDefault(hideOSD: false) + connection?.cancel() + reconnectTask?.cancel() + if let workspaceLaunchObserver { + NSWorkspace.shared.notificationCenter.removeObserver(workspaceLaunchObserver) + } + if let workspaceTermObserver { + NSWorkspace.shared.notificationCenter.removeObserver(workspaceTermObserver) + } + cancellables.removeAll() + } + + // MARK: - Lunar OSD Suppression + + /// Tell Lunar to hide (or show) its own native OSD by writing to its UserDefaults. + private func setLunarHideOSD(_ hide: Bool) { + Self.writeLunarDefault(hideOSD: hide) + } + + /// Synchronous, nonisolated helper so it can also be called from `deinit`. + nonisolated private static func writeLunarDefault(hideOSD hide: Bool) { + guard let defaults = UserDefaults(suiteName: lunarDomain) else { + NSLog("⚠️ Lunar: unable to open UserDefaults suite '\(lunarDomain)' to set hideOSD") + return + } + defaults.set(hide, forKey: "hideOSD") + NSLog("🌙 Lunar: hideOSD set to \(hide)") + } +} diff --git a/DynamicIsland/managers/SystemHUDManager.swift b/DynamicIsland/managers/SystemHUDManager.swift index efc7893..34192cf 100644 --- a/DynamicIsland/managers/SystemHUDManager.swift +++ b/DynamicIsland/managers/SystemHUDManager.swift @@ -188,6 +188,14 @@ class SystemHUDManager { await self.startSystemObserver() } }.store(in: &cancellables) + + // When Lunar integration toggled, restart observer to update brightness key interception + Defaults.publisher(.enableLunarIntegration, options: []).sink { [weak self] _ in + guard let self = self, self.isSetupComplete else { return } + Task { @MainActor in + await self.startSystemObserver() + } + }.store(in: &cancellables) } private var cancellables = Set() @@ -240,9 +248,9 @@ class SystemHUDManager { keyboardBacklightEnabled = Defaults[.enableKeyboardBacklightHUD] } - // When BetterDisplay integration is on, stop intercepting brightness and - // Cmd+Brightness keys so BetterDisplay receives them and sends OSD notifications. - if Defaults[.enableBetterDisplayIntegration] { + // When BetterDisplay or Lunar integration is on, stop intercepting brightness and + // Cmd+Brightness keys so the external app receives them and sends DDC/OSD events. + if Defaults[.enableBetterDisplayIntegration] || Defaults[.enableLunarIntegration] { brightnessEnabled = false keyboardBacklightEnabled = false } diff --git a/DynamicIsland/models/Constants.swift b/DynamicIsland/models/Constants.swift index 347335c..2a4b0d3 100644 --- a/DynamicIsland/models/Constants.swift +++ b/DynamicIsland/models/Constants.swift @@ -1029,6 +1029,9 @@ extension Defaults.Keys { // MARK: BetterDisplay Integration static let enableBetterDisplayIntegration = Key("enableBetterDisplayIntegration", default: false) + + // MARK: Lunar Integration + static let enableLunarIntegration = Key("enableLunarIntegration", default: false) static let hasSeenOSDAlphaWarning = Key("hasSeenOSDAlphaWarning", default: false) static let enableOSDVolume = Key("enableOSDVolume", default: true)