Zwei Fehler, beide durch Messen gefunden statt durch Raten — und einer davon war meine eigene fehlerhafte Diagnose: `log show` wurde von zsh abgefangen, ich hatte stderr umgeleitet und die Fehlermeldung nie gesehen. Meine Aussage "keine TCC-Einträge, also wurde nie gefragt" stützte sich damit auf einen Befehl, der gar nicht lief. Einstellungsfenster: SwiftUIs Settings-Szene wird über den privaten Selektor showSettingsWindow: geöffnet, dessen Name sich zwischen macOS-Versionen schon geändert hat und der bei .accessory-Apps ohne Menüleiste unzuverlässig ankommt. Der Menüeintrag tat schlicht nichts. Jetzt ein eigenes NSWindow. Kalenderberechtigung, zwei Ursachen übereinander: Xcode lagert im Debug-Build den Programmcode in eine eigene dylib aus (für SwiftUI-Vorschauen). Das Hauptprogramm ist dann nur ein Rumpf, und TCC ordnete die Anfrage dem Rumpf zu — kTCCServiceCalendar erreichte tccd überhaupt nicht. ENABLE_DEBUG_DYLIB = NO behebt das; danach erscheint die Anfrage im Protokoll. Danach immer noch kein Dialog: promptType 1, aber promptPolicy 0. TCC bereitet den Dialog vor und entscheidet sich dagegen, weil keine App im Vordergrund ist, an die er gehören könnte. NSApp.activate davor hilft nicht — Aktivierung wirkt asynchron und ist beim Aufruf noch nicht durch. Deshalb wird beim ersten Start das Einstellungsfenster auf dem Reiter Berechtigungen geöffnet: dort steht ein echtes Fenster im Vordergrund, und der Nutzer weiß, warum gefragt wird. Folgefehler dabei: ohne Berechtigung zeigte das Widget "Nichts mehr für heute" — eine Aussage, die es ohne Zugriff gar nicht treffen kann. refresh() fragt jetzt nicht mehr selbst nach und meldet ohne Berechtigung ehrlich `denied`. Fehler aus requestFullAccessToEvents werden nicht mehr mit try? verschluckt.
453 lines
11 KiB
Plaintext
453 lines
11 KiB
Plaintext
{
|
||
"sourceLanguage": "en",
|
||
"strings": {
|
||
"menu.openPanel": {
|
||
"extractionState": "stale",
|
||
"localizations": {
|
||
"de": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Panel öffnen"
|
||
}
|
||
},
|
||
"en": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Open Panel"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"menu.quit": {
|
||
"extractionState": "stale",
|
||
"localizations": {
|
||
"de": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Onyx beenden"
|
||
}
|
||
},
|
||
"en": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Quit Onyx"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"menu.settings": {
|
||
"extractionState": "stale",
|
||
"localizations": {
|
||
"de": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Einstellungen …"
|
||
}
|
||
},
|
||
"en": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Settings…"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"settings.display.all": {
|
||
"localizations": {
|
||
"de": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Allen Displays"
|
||
}
|
||
},
|
||
"en": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "All displays"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"settings.display.builtInOnly": {
|
||
"localizations": {
|
||
"de": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Nur dem internen Display"
|
||
}
|
||
},
|
||
"en": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Built-in display only"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"settings.display.hint": {
|
||
"localizations": {
|
||
"de": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Auf Displays ohne echte Notch erscheint oben mittig ein Balken, der sich genauso verhält. Ist der Deckel geschlossen und kein internes Display vorhanden, erscheint das Panel trotzdem auf einem externen — sonst wäre Onyx nicht erreichbar."
|
||
}
|
||
},
|
||
"en": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "On displays without a real notch, a bar appears at the top centre and behaves the same. With the lid closed and no built-in display present, the panel still appears on an external one — otherwise Onyx would be unreachable."
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"settings.display.menuBarIcon": {
|
||
"extractionState": "stale",
|
||
"localizations": {
|
||
"de": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Symbol in der Menüleiste anzeigen"
|
||
}
|
||
},
|
||
"en": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Show icon in the menu bar"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"settings.display.menuBarIcon.hint": {
|
||
"localizations": {
|
||
"de": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Über das Symbol erreichst du Panel, Einstellungen und Beenden. Ohne es kommst du nur über die Notch an Onyx heran."
|
||
}
|
||
},
|
||
"en": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "The icon gives you the panel, settings and quit. Without it, the notch is the only way to reach Onyx."
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"settings.display.policy": {
|
||
"extractionState": "stale",
|
||
"localizations": {
|
||
"de": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Panel anzeigen auf"
|
||
}
|
||
},
|
||
"en": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Show panel on"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"settings.size.large": {
|
||
"extractionState": "stale",
|
||
"localizations": {
|
||
"de": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Groß (2×2)"
|
||
}
|
||
},
|
||
"en": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Large (2×2)"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"settings.size.medium": {
|
||
"extractionState": "stale",
|
||
"localizations": {
|
||
"de": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Mittel (2×1)"
|
||
}
|
||
},
|
||
"en": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Medium (2×1)"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"settings.size.small": {
|
||
"extractionState": "stale",
|
||
"localizations": {
|
||
"de": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Klein (1×1)"
|
||
}
|
||
},
|
||
"en": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Small (1×1)"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"settings.size.wide": {
|
||
"extractionState": "stale",
|
||
"localizations": {
|
||
"de": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Breit (4×1)"
|
||
}
|
||
},
|
||
"en": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Wide (4×1)"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"settings.tab.display": {
|
||
"extractionState": "stale",
|
||
"localizations": {
|
||
"de": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Anzeige"
|
||
}
|
||
},
|
||
"en": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Display"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"settings.tab.widgets": {
|
||
"extractionState": "stale",
|
||
"localizations": {
|
||
"de": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Widgets"
|
||
}
|
||
},
|
||
"en": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Widgets"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"settings.widgets.add": {
|
||
"extractionState": "stale",
|
||
"localizations": {
|
||
"de": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Hinzufügen"
|
||
}
|
||
},
|
||
"en": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Add"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"settings.widgets.available": {
|
||
"extractionState": "stale",
|
||
"localizations": {
|
||
"de": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Verfügbar"
|
||
}
|
||
},
|
||
"en": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Available"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"settings.widgets.empty": {
|
||
"localizations": {
|
||
"de": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Keine Widgets im Panel. Das Panel bleibt leer, bis du eins hinzufügst."
|
||
}
|
||
},
|
||
"en": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "No widgets in the panel. It stays empty until you add one."
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"settings.widgets.hint": {
|
||
"localizations": {
|
||
"de": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Die Reihenfolge bestimmt die Anordnung im Panel. Jedes Widget rückt an die erste Stelle, an die es passt."
|
||
}
|
||
},
|
||
"en": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "The order determines the arrangement in the panel. Each widget takes the first spot it fits into."
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"settings.widgets.inPanel": {
|
||
"extractionState": "stale",
|
||
"localizations": {
|
||
"de": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Im Panel"
|
||
}
|
||
},
|
||
"en": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "In the panel"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"settings.widgets.remove": {
|
||
"extractionState": "stale",
|
||
"localizations": {
|
||
"de": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Aus dem Panel entfernen"
|
||
}
|
||
},
|
||
"en": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Remove from panel"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"settings.tab.permissions": {
|
||
"localizations": {
|
||
"de": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Berechtigungen"
|
||
}
|
||
},
|
||
"en": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Permissions"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"settings.permissions.calendar": {
|
||
"localizations": {
|
||
"de": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Kalender"
|
||
}
|
||
},
|
||
"en": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Calendar"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"settings.permissions.granted": {
|
||
"localizations": {
|
||
"de": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Erteilt"
|
||
}
|
||
},
|
||
"en": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Granted"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"settings.permissions.request": {
|
||
"localizations": {
|
||
"de": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Anfragen"
|
||
}
|
||
},
|
||
"en": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Request"
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"settings.permissions.calendar.why": {
|
||
"localizations": {
|
||
"de": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Onyx zeigt deine Termine im Kalender-Widget an. Es wird ausschließlich gelesen, nie geschrieben."
|
||
}
|
||
},
|
||
"en": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Onyx shows your events in the calendar widget. It only ever reads, never writes."
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"settings.permissions.openSystem": {
|
||
"localizations": {
|
||
"de": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Systemeinstellungen öffnen"
|
||
}
|
||
},
|
||
"en": {
|
||
"stringUnit": {
|
||
"state": "translated",
|
||
"value": "Open System Settings"
|
||
}
|
||
}
|
||
}
|
||
}
|
||
},
|
||
"version": "1.0"
|
||
} |