diff --git a/Onyx/Localizable.xcstrings b/Onyx/Localizable.xcstrings index 9c29b0a..fb8f3ef 100644 --- a/Onyx/Localizable.xcstrings +++ b/Onyx/Localizable.xcstrings @@ -1,2009 +1,2015 @@ { - "sourceLanguage": "en", - "strings": { - "%@": { - "comment": "A label showing the minimum RPM of a fan.", - "isCommentAutoGenerated": true, - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "%@" + "sourceLanguage" : "en", + "strings" : { + "%@" : { + "comment" : "A label showing the minimum RPM of a fan.", + "isCommentAutoGenerated" : true, + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "%@" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@" } } } }, - "%@ U/min": { - "comment": "A label that shows the current speed of a fan. The argument is the current speed of the fan.", - "isCommentAutoGenerated": true, - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "%@ U/min" + "%@ °C" : { + "comment" : "A label showing the temperature of the hottest fan in the report, in degrees Celsius. The argument is the temperature in degrees Celsius.", + "isCommentAutoGenerated" : true, + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ °C" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "%@ U/min" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ °C" } } } }, - "%@ °C": { - "comment": "A label showing the temperature of the hottest fan in the report, in degrees Celsius. The argument is the temperature in degrees Celsius.", - "isCommentAutoGenerated": true, - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "%@ °C" + "%@ U/min" : { + "comment" : "A label that shows the current speed of a fan. The argument is the current speed of the fan.", + "isCommentAutoGenerated" : true, + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ U/min" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "%@ °C" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ U/min" } } } }, - "%@°": { - "comment": "A temperature in °C.", - "isCommentAutoGenerated": true, - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "%@°" + "%@°" : { + "comment" : "A temperature in °C.", + "isCommentAutoGenerated" : true, + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@°" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "%@°" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@°" } } } }, - "charge.limit": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Ladelimit" + "charge.limit" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ladelimit" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Charge limit" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Charge limit" } } } }, - "charge.limit.hint": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Ein Akku, der dauerhaft bei 100 % am Netz hängt, altert schneller. 80 bis 100 % ist der Bereich, den macOS selbst anbietet — darunter ist für dieses Gerät ungemessen." + "charge.limit.hint" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ein Akku, der dauerhaft bei 100 % am Netz hängt, altert schneller. 80 bis 100 % ist der Bereich, den macOS selbst anbietet — darunter ist für dieses Gerät ungemessen." } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "A battery kept at 100 % on power ages faster. 80 to 100 % is the range macOS itself offers — below that is untested for this machine." + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "A battery kept at 100 % on power ages faster. 80 to 100 % is the range macOS itself offers — below that is untested for this machine." } } } }, - "charge.limit.off": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Aus" + "charge.limit.off" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aus" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Off" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Off" } } } }, - "charge.section": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Akku" + "charge.section" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Akku" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Battery" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Battery" } } } }, - "fans.approval.needed": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "macOS wartet auf deine Freigabe. Öffne die Systemeinstellungen und erlaube den Hintergrunddienst von Onyx." + "fans.approval.needed" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "macOS wartet auf deine Freigabe. Öffne die Systemeinstellungen und erlaube den Hintergrunddienst von Onyx." } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "macOS is waiting for your approval. Open System Settings and allow Onyx's background service." + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "macOS is waiting for your approval. Open System Settings and allow Onyx's background service." } } } }, - "fans.approval.open": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Systemeinstellungen öffnen" + "fans.approval.open" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Systemeinstellungen öffnen" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Open System Settings" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Open System Settings" } } } }, - "fans.approval.recheck": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Erneut prüfen" + "fans.approval.recheck" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Erneut prüfen" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Check again" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Check again" } } } }, - "fans.auto": { - "comment": "A button to set a fan to automatic mode.", - "isCommentAutoGenerated": true, - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Auto" + "fans.auto" : { + "comment" : "A button to set a fan to automatic mode.", + "isCommentAutoGenerated" : true, + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Auto" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Auto" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Auto" } } } }, - "fans.connecting": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Verbinde mit dem Hilfsdienst …" + "fans.connecting" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Verbinde mit dem Hilfsdienst …" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Connecting to the helper…" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Connecting to the helper…" } } } }, - "fans.fan %@": { - "comment": "A label showing the index of a fan. The argument is the index of the fan.", - "isCommentAutoGenerated": true, - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Lüfter %@" + "fans.fan %@" : { + "comment" : "A label showing the index of a fan. The argument is the index of the fan.", + "isCommentAutoGenerated" : true, + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lüfter %@" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Fan %@" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fan %@" } } } }, - "fans.fan %lld": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Lüfter %lld" + "fans.fan %lld" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lüfter %lld" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Fan %lld" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fan %lld" } } } }, - "fans.hottest": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Wärmster Kern" + "fans.hottest" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Wärmster Kern" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Hottest core" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hottest core" } } } }, - "fans.install": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Installieren" + "fans.install" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Installieren" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Install" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Install" } } } }, - "fans.intro": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Onyx kann die Lüfterdrehzahl fest vorgeben, statt sie macOS zu überlassen. Dafür wird ein Hilfsdienst mit Systemrechten eingerichtet — Schreibzugriff auf den SMC geht nicht anders." + "fans.intro" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Onyx kann die Lüfterdrehzahl fest vorgeben, statt sie macOS zu überlassen. Dafür wird ein Hilfsdienst mit Systemrechten eingerichtet — Schreibzugriff auf den SMC geht nicht anders." } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Onyx can set a fixed fan speed instead of leaving it to macOS. This requires a helper service with system privileges — writing to the SMC is not possible otherwise." + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Onyx can set a fixed fan speed instead of leaving it to macOS. This requires a helper service with system privileges — writing to the SMC is not possible otherwise." } } } }, - "fans.left": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Lüfter links" + "fans.left" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lüfter links" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Left fan" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Left fan" } } } }, - "fans.manual": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Manuell" + "fans.manual" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Manuell" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Manual" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Manual" } } } }, - "fans.menubar.short": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Lüfter" + "fans.menubar.short" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lüfter" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Fan" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fan" } } } }, - "fans.mode.auto": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Automatik" + "fans.mode.auto" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Automatik" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Automatic" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Automatic" } } } }, - "fans.mode.manual": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Manuell" + "fans.mode.manual" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Manuell" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Manual" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Manual" } } } }, - "fans.noData": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Noch keine Lüfterdaten." + "fans.noData" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Noch keine Lüfterdaten." } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "No fan data yet." + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No fan data yet." } } } }, - "fans.noRange": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Kein Regelbereich" + "fans.noRange" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kein Regelbereich" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "No adjustable range" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "No adjustable range" } } } }, - "fans.notInstalled": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Die Lüftersteuerung braucht einen kleinen privilegierten Dienst." + "fans.notInstalled" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Die Lüftersteuerung braucht einen kleinen privilegierten Dienst." } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Fan control needs a small privileged service." + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fan control needs a small privileged service." } } } }, - "fans.reason.noTemperature": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Zurück auf Automatik: keine Temperatur messbar, damit lässt sich Sicherheit nicht beurteilen." + "fans.reason.noTemperature" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Zurück auf Automatik: keine Temperatur messbar, damit lässt sich Sicherheit nicht beurteilen." } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Back to automatic: no temperature reading, so safety cannot be judged." + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Back to automatic: no temperature reading, so safety cannot be judged." } } } }, - "fans.reason.other": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Zurück auf Automatik." + "fans.reason.other" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Zurück auf Automatik." } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Back to automatic." + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Back to automatic." } } } }, - "fans.reason.temperature": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Zurück auf Automatik: zu heiß für eine feste Drehzahl." + "fans.reason.temperature" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Zurück auf Automatik: zu heiß für eine feste Drehzahl." } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Back to automatic: too hot for a fixed speed." + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Back to automatic: too hot for a fixed speed." } } } }, - "fans.reason.unknownLimits": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Zurück auf Automatik: der erlaubte Drehzahlbereich ist nicht lesbar." + "fans.reason.unknownLimits" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Zurück auf Automatik: der erlaubte Drehzahlbereich ist nicht lesbar." } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Back to automatic: the permitted speed range cannot be read." + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Back to automatic: the permitted speed range cannot be read." } } } }, - "fans.reason.watchdog": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Zurück auf Automatik: Onyx hat sich zu lange nicht gemeldet." + "fans.reason.watchdog" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Zurück auf Automatik: Onyx hat sich zu lange nicht gemeldet." } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Back to automatic: Onyx went silent for too long." + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Back to automatic: Onyx went silent for too long." } } } }, - "fans.right": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Lüfter rechts" + "fans.right" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lüfter rechts" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Right fan" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Right fan" } } } }, - "fans.rpm %lld": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "%lld U/min" + "fans.rpm %@" : { + "comment" : "A label displaying the current RPM of a fan. The argument is the current RPM.", + "isCommentAutoGenerated" : true + }, + "fans.rpm %lld" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld U/min" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "%lld rpm" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld rpm" } } } }, - "fans.safety": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Deshalb greift ein Sicherheitsnetz, das sich nicht abschalten lässt: nie unter das Minimum der Firmware, Rückfall auf Automatik ab 95 °C, Rückfall wenn Onyx sich fünf Sekunden nicht meldet, und Rückfall beim Beenden." + "fans.safety" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Deshalb greift ein Sicherheitsnetz, das sich nicht abschalten lässt: nie unter das Minimum der Firmware, Rückfall auf Automatik ab 95 °C, Rückfall wenn Onyx sich fünf Sekunden nicht meldet, und Rückfall beim Beenden." } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "A safety net you cannot switch off is therefore always active: never below the firmware minimum, back to automatic above 95 °C, back to automatic if Onyx goes silent for five seconds, and back to automatic on quit." + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "A safety net you cannot switch off is therefore always active: never below the firmware minimum, back to automatic above 95 °C, back to automatic if Onyx goes silent for five seconds, and back to automatic on quit." } } } }, - "fans.safety.active": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Das Sicherheitsnetz läuft im Hilfsdienst, nicht in Onyx. Es greift auch dann, wenn Onyx abstürzt oder beendet wird." + "fans.safety.active" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Das Sicherheitsnetz läuft im Hilfsdienst, nicht in Onyx. Es greift auch dann, wenn Onyx abstürzt oder beendet wird." } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "The safety net runs in the helper, not in Onyx. It works even if Onyx crashes or is quit." + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "The safety net runs in the helper, not in Onyx. It works even if Onyx crashes or is quit." } } } }, - "fans.uninstall": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Hilfsdienst entfernen" + "fans.uninstall" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hilfsdienst entfernen" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Remove helper" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Remove helper" } } } }, - "fans.warning": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Eine zu niedrige Drehzahl kann den Rechner überhitzen lassen. Die Automatik regelt nach Temperatur, ein fester Wert nicht." + "fans.warning" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Eine zu niedrige Drehzahl kann den Rechner überhitzen lassen. Die Automatik regelt nach Temperatur, ein fester Wert nicht." } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "A fan speed set too low can let the Mac overheat. The automatic control adjusts to temperature; a fixed value does not." + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "A fan speed set too low can let the Mac overheat. The automatic control adjusts to temperature; a fixed value does not." } } } }, - "menu.openPanel": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Panel öffnen" + "menu.openPanel" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Panel öffnen" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Open Panel" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Open Panel" } } } }, - "menu.quit": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Onyx beenden" + "menu.quit" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Onyx beenden" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Quit Onyx" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Quit Onyx" } } } }, - "menu.settings": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Einstellungen …" + "menu.settings" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Einstellungen …" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Settings…" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Settings…" } } } }, - "metric.battery": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Akku" + "metric.battery" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Akku" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Battery" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Battery" } } } }, - "metric.cpu": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "CPU" + "metric.cpu" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "CPU" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "CPU" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "CPU" } } } }, - "metric.gpu": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "GPU" + "metric.gpu" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "GPU" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "GPU" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "GPU" } } } }, - "metric.memory": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Speicher" + "metric.memory" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Speicher" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Memory" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Memory" } } } }, - "metric.mode.temperature": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Temperatur" + "metric.mode.temperature" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Temperatur" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Temperature" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Temperature" } } } }, - "metric.mode.usage": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Auslastung" + "metric.mode.usage" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Auslastung" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Usage" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Usage" } } } }, - "metric.sensors": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Sensoren" + "metric.sensors" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sensoren" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Sensors" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sensors" } } } }, - "mixer.menubar.name": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Lautstärkemixer" + "mixer.menubar.name" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lautstärkemixer" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Volume mixer" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Volume mixer" } } } }, - "mixer.menubar.short": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Mix" + "mixer.menubar.short" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mix" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Mix" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mix" } } } }, - "network.name": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Netzwerk" + "network.name" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Netzwerk" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Network" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Network" } } } }, - "onboarding.allow": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Erlauben" + "onboarding.allow" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Erlauben" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Allow" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Allow" } } } }, - "onboarding.audio": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Systemton" + "onboarding.audio" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Systemton" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "System audio" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "System audio" } } } }, - "onboarding.audio.why": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Nötig für die Lautstärke einzelner Programme. Onyx leitet den Ton der geregelten Programme um — und nur deren." + "onboarding.audio.why" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nötig für die Lautstärke einzelner Programme. Onyx leitet den Ton der geregelten Programme um — und nur deren." } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Needed for per-app volume. Onyx routes the audio of the apps you control, and only those." + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Needed for per-app volume. Onyx routes the audio of the apps you control, and only those." } } } }, - "onboarding.calendar": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Kalender" + "onboarding.calendar" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kalender" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Calendar" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Calendar" } } } }, - "onboarding.calendar.why": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Zeigt deine Termine im Panel. Nur lesend — Onyx ändert nie einen Kalender." + "onboarding.calendar.why" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Zeigt deine Termine im Panel. Nur lesend — Onyx ändert nie einen Kalender." } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Shows your appointments in the panel. Read-only — Onyx never changes a calendar." + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Shows your appointments in the panel. Read-only — Onyx never changes a calendar." } } } }, - "onboarding.done": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Fertig" + "onboarding.done" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fertig" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Done" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Done" } } } }, - "onboarding.helper": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Lüftersteuerung" + "onboarding.helper" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lüftersteuerung" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Fan control" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fan control" } } } }, - "onboarding.helper.why": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Installiert einen kleinen privilegierten Dienst. Er setzt nur Lüfterdrehzahlen und fällt auf Automatik zurück, wenn Onyx schweigt." + "onboarding.helper.why" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Installiert einen kleinen privilegierten Dienst. Er setzt nur Lüfterdrehzahlen und fällt auf Automatik zurück, wenn Onyx schweigt." } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Installs a small privileged service. It only sets fan speeds and falls back to automatic if Onyx goes silent." + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Installs a small privileged service. It only sets fan speeds and falls back to automatic if Onyx goes silent." } } } }, - "onboarding.launchAtLogin": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Onyx beim Anmelden starten" + "onboarding.launchAtLogin" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Onyx beim Anmelden starten" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Start Onyx at login" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Start Onyx at login" } } } }, - "onboarding.location": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Standort" + "onboarding.location" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Standort" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Location" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Location" } } } }, - "onboarding.location.why": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Wetter für deinen Aufenthaltsort. Alternativ lässt sich je Widget ein fester Ort einstellen." + "onboarding.location.why" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Wetter für deinen Aufenthaltsort. Alternativ lässt sich je Widget ein fester Ort einstellen." } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Weather for where you are. You can also set a fixed place per widget instead." + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Weather for where you are. You can also set a fixed place per widget instead." } } } }, - "onboarding.openSettings": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Systemeinstellungen öffnen" + "onboarding.openSettings" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Systemeinstellungen öffnen" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Open System Settings" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Open System Settings" } } } }, - "onboarding.subtitle": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Onyx braucht vier Dinge vom System. Jedes für etwas anderes, und keines davon ist Pflicht — erlaube, was du nutzen möchtest." + "onboarding.subtitle" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Onyx braucht vier Dinge vom System. Jedes für etwas anderes, und keines davon ist Pflicht — erlaube, was du nutzen möchtest." } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Onyx needs four things from the system. Each one is for something different, and none of them is required — grant what you want to use." + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Onyx needs four things from the system. Each one is for something different, and none of them is required — grant what you want to use." } } } }, - "onboarding.title": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Willkommen bei Onyx" + "onboarding.title" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Willkommen bei Onyx" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Welcome to Onyx" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Welcome to Onyx" } } } }, - "settings.display.all": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Allen Displays" + "settings.display.all" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Allen Displays" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "All displays" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "All displays" } } } }, - "settings.display.builtInOnly": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Nur dem internen Display" + "settings.display.builtInOnly" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nur dem internen Display" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Built-in display only" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Built-in display only" } } } }, - "settings.display.dockIcon": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Symbol im Dock anzeigen" + "settings.display.dockIcon" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Symbol im Dock anzeigen" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Show icon in the Dock" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Show icon in the Dock" } } } }, - "settings.display.dockIcon.hint": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Standardmäßig aus. Onyx lebt in der Notch und in der Menüleiste und hat kein Hauptfenster — im Dock wäre es ein Symbol, das beim Anklicken nichts öffnet, und es stünde im Programmumschalter zwischen den Programmen, mit denen du arbeitest." + "settings.display.dockIcon.hint" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Standardmäßig aus. Onyx lebt in der Notch und in der Menüleiste und hat kein Hauptfenster — im Dock wäre es ein Symbol, das beim Anklicken nichts öffnet, und es stünde im Programmumschalter zwischen den Programmen, mit denen du arbeitest." } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Off by default. Onyx lives in the notch and the menu bar and has no main window — in the Dock it would be an icon that opens nothing, and it would sit in the app switcher among the apps you actually work with." + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Off by default. Onyx lives in the notch and the menu bar and has no main window — in the Dock it would be an icon that opens nothing, and it would sit in the app switcher among the apps you actually work with." } } } }, - "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." + "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." + "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" + "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" + "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." + "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." + "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" + "settings.display.policy" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Panel anzeigen auf" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Show panel on" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Show panel on" } } } }, - "settings.general": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Allgemein" + "settings.general" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Allgemein" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "General" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "General" } } } }, - "settings.launchAtLogin": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Beim Anmelden starten" + "settings.launchAtLogin" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Beim Anmelden starten" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Start at login" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Start at login" } } } }, - "settings.launchAtLogin.blocked": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Anmeldeobjekte wurden für Onyx in den Systemeinstellungen abgeschaltet." + "settings.launchAtLogin.blocked" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Anmeldeobjekte wurden für Onyx in den Systemeinstellungen abgeschaltet." } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Login items were turned off for Onyx in System Settings." + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Login items were turned off for Onyx in System Settings." } } } }, - "settings.menubar.bars": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Balken" + "settings.menubar.bars" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Balken" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Bars" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Bars" } } } }, - "settings.menubar.graph": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Verlauf" + "settings.menubar.graph" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Verlauf" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Graph" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Graph" } } } }, - "settings.menubar.hint": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Jedes Modul erscheint als eigenes Symbol in der Menüleiste und teilt sich die Messung mit dem Widget im Panel. Standardmäßig ist keines an — die Menüleiste ist knapp, auf einem Notch-Display zusätzlich in der Mitte blockiert." + "settings.menubar.hint" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Jedes Modul erscheint als eigenes Symbol in der Menüleiste und teilt sich die Messung mit dem Widget im Panel. Standardmäßig ist keines an — die Menüleiste ist knapp, auf einem Notch-Display zusätzlich in der Mitte blockiert." } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Each module appears as its own menu bar icon and shares its measurement with the panel widget. None are on by default — the menu bar is tight, and on a notched display the middle is blocked as well." + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Each module appears as its own menu bar icon and shares its measurement with the panel widget. None are on by default — the menu bar is tight, and on a notched display the middle is blocked as well." } } } }, - "settings.menubar.labelAndValue": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Kürzel + Wert" + "settings.menubar.labelAndValue" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kürzel + Wert" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Label + value" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Label + value" } } } }, - "settings.menubar.sensor": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Sensor" + "settings.menubar.sensor" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sensor" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Sensor" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sensor" } } } }, - "settings.menubar.sensor.hottest": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Wärmster Punkt" + "settings.menubar.sensor.hottest" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Wärmster Punkt" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Hottest point" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hottest point" } } } }, - "settings.menubar.symbol": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Nur Symbol" + "settings.menubar.symbol" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nur Symbol" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Symbol only" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Symbol only" } } } }, - "settings.menubar.symbolAndValue": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Symbol + Wert" + "settings.menubar.symbolAndValue" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Symbol + Wert" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Symbol + value" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Symbol + value" } } } }, - "settings.menubar.value": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Wert" + "settings.menubar.value" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Wert" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Value" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Value" } } } }, - "settings.menubar.valueAndGraph": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Wert und Verlauf" + "settings.menubar.valueAndGraph" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Wert und Verlauf" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Value and graph" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Value and graph" } } } }, - "settings.onboarding.show": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Einrichtung erneut zeigen" + "settings.onboarding.show" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Einrichtung erneut zeigen" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Show setup again" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Show setup again" } } } }, - "settings.permissions.calendar": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Kalender" + "settings.permissions.calendar" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Kalender" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Calendar" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Calendar" } } } }, - "settings.permissions.calendar.why": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Onyx zeigt deine Termine im Kalender-Widget an. Es wird ausschließlich gelesen, nie geschrieben." + "settings.permissions.calendar.why" : { + "extractionState" : "stale", + "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." + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Onyx shows your events in the calendar widget. It only ever reads, never writes." } } } }, - "settings.permissions.granted": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Erteilt" + "settings.permissions.granted" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Erteilt" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Granted" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Granted" } } } }, - "settings.permissions.location": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Standort" + "settings.permissions.location" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Standort" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Location" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Location" } } } }, - "settings.permissions.location.why": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Onyx zeigt das Wetter an deinem aktuellen Standort. Ohne Zugriff kannst du stattdessen einen festen Ort wählen." + "settings.permissions.location.why" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Onyx zeigt das Wetter an deinem aktuellen Standort. Ohne Zugriff kannst du stattdessen einen festen Ort wählen." } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Onyx shows the weather for your current location. Without access you can pick a fixed place instead." + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Onyx shows the weather for your current location. Without access you can pick a fixed place instead." } } } }, - "settings.permissions.openSystem": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Systemeinstellungen öffnen" + "settings.permissions.openSystem" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Systemeinstellungen öffnen" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Open System Settings" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Open System Settings" } } } }, - "settings.permissions.request": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Anfragen" + "settings.permissions.request" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Anfragen" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Request" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Request" } } } }, - "settings.shelf.cleanup": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Automatisch löschen" + "settings.shelf.cleanup" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Automatisch löschen" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Delete automatically" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Delete automatically" } } } }, - "settings.shelf.count %@": { - "comment": "A label showing the number of items in the shelf. The argument is the number of items in the shelf.", - "isCommentAutoGenerated": true, - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "%@ Dateien abgelegt" + "settings.shelf.count %@" : { + "comment" : "A label showing the number of items in the shelf. The argument is the number of items in the shelf.", + "isCommentAutoGenerated" : true, + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ Dateien abgelegt" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "%@ files parked" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%@ files parked" } } } }, - "settings.shelf.count %lld": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "%lld Dateien abgelegt" + "settings.shelf.count %lld" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld Dateien abgelegt" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "%lld files parked" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "%lld files parked" } } } }, - "settings.shelf.days %@": { - "comment": "A label that lets the user select how many days to wait before automatically removing items from the shelf. The argument is the number of days.", - "isCommentAutoGenerated": true, - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Nach %@ Tagen" + "settings.shelf.days %@" : { + "comment" : "A label that lets the user select how many days to wait before automatically removing items from the shelf. The argument is the number of days.", + "isCommentAutoGenerated" : true, + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nach %@ Tagen" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "After %@ days" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "After %@ days" } } } }, - "settings.shelf.days %lld": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Nach %lld Tagen" + "settings.shelf.days %lld" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nach %lld Tagen" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "After %lld days" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "After %lld days" } } } }, - "settings.shelf.never": { - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Nie" + "settings.shelf.never" : { + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Nie" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Never" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Never" } } } }, - "settings.shelf.reveal": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Im Finder zeigen" + "settings.shelf.reveal" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Im Finder zeigen" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Show in Finder" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Show in Finder" } } } }, - "settings.shelf.title": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Ablage" + "settings.shelf.title" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Ablage" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Shelf" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Shelf" } } } }, - "settings.size.large": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Groß (2×2)" + "settings.size.large" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Groß (2×2)" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Large (2×2)" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Large (2×2)" } } } }, - "settings.size.medium": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Mittel (2×1)" + "settings.size.medium" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Mittel (2×1)" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Medium (2×1)" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Medium (2×1)" } } } }, - "settings.size.small": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Klein (1×1)" + "settings.size.small" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Klein (1×1)" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Small (1×1)" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Small (1×1)" } } } }, - "settings.size.wide": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Breit (4×1)" + "settings.size.wide" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Breit (4×1)" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Wide (4×1)" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Wide (4×1)" } } } }, - "settings.tab.display": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Anzeige" + "settings.tab.display" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Anzeige" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Display" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Display" } } } }, - "settings.tab.fans": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Lüfter" + "settings.tab.fans" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lüfter" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Fans" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fans" } } } }, - "settings.tab.menubar": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Menüleiste" + "settings.tab.menubar" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Menüleiste" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Menu bar" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Menu bar" } } } }, - "settings.tab.permissions": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Berechtigungen" + "settings.tab.permissions" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Berechtigungen" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Permissions" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Permissions" } } } }, - "settings.tab.sources": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Quellen" + "settings.tab.sources" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Quellen" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Sources" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Sources" } } } }, - "settings.tab.widgets": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Widgets" + "settings.tab.widgets" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Widgets" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Widgets" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Widgets" } } } }, - "settings.widgets.add": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Hinzufügen" + "settings.widgets.add" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Hinzufügen" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Add" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Add" } } } }, - "settings.widgets.available": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Verfügbar" + "settings.widgets.available" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Verfügbar" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Available" + "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." + "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." + "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." + "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." + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "The order determines the arrangement in the panel. Each widget takes the first spot it fits into." } } } }, - "settings.widgets.hint.order": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Alle Kacheln sind gleich groß. Die Reihenfolge hier ist die Reihenfolge im Panel — zum Sortieren ziehen." + "settings.widgets.hint.order" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Alle Kacheln sind gleich groß. Die Reihenfolge hier ist die Reihenfolge im Panel — zum Sortieren ziehen." } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "All tiles are the same size. The order here is the order in the panel — drag to sort." + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "All tiles are the same size. The order here is the order in the panel — drag to sort." } } } }, - "settings.widgets.inPanel": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Im Panel" + "settings.widgets.inPanel" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Im Panel" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "In the panel" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "In the panel" } } } }, - "settings.widgets.remove": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Aus dem Panel entfernen" + "settings.widgets.remove" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Aus dem Panel entfernen" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Remove from panel" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Remove from panel" } } } }, - "widget.fans.name": { - "extractionState": "stale", - "localizations": { - "de": { - "stringUnit": { - "state": "translated", - "value": "Lüfter" + "widget.fans.name" : { + "extractionState" : "stale", + "localizations" : { + "de" : { + "stringUnit" : { + "state" : "translated", + "value" : "Lüfter" } }, - "en": { - "stringUnit": { - "state": "translated", - "value": "Fans" + "en" : { + "stringUnit" : { + "state" : "translated", + "value" : "Fans" } } } } }, - "version": "1.1" -} + "version" : "1.1" +} \ No newline at end of file diff --git a/Packages/OnyxKit/Sources/MetricsProvider/BatterySymbol.swift b/Packages/OnyxKit/Sources/MetricsProvider/BatterySymbol.swift new file mode 100644 index 0000000..0c0d83e --- /dev/null +++ b/Packages/OnyxKit/Sources/MetricsProvider/BatterySymbol.swift @@ -0,0 +1,35 @@ +import Foundation + +/// Das Akkusymbol zum jeweiligen Zustand. +/// +/// Ein Symbol, das bei 5 % genauso aussieht wie bei 95 %, ist Dekoration und +/// keine Anzeige — es beantwortet die eine Frage nicht, für die es da ist. Wer +/// in der Menüleiste nur das Symbol stehen hat, will es auf einen Blick lesen +/// können, ohne die Zahl daneben. +public enum BatterySymbol { + + /// Kein Akku da — oder keiner zu lesen. + public static let unavailable = "batteryblock.slash" + + /// Der Blitz beim Laden — **getrennt** vom Füllstand. + /// + /// Nachgemessen, nicht angenommen: von den kombinierten Symbolen existiert + /// allein `battery.100percent.bolt`. Für 0, 25, 50 und 75 Prozent gibt es + /// keine Blitz-Variante, und `battery.slash` gibt es auch nicht. + /// + /// Den Füllstand beim Laden gegen einen Blitz einzutauschen wäre die + /// falsche Wahl: dass geladen wird, sieht man am Netzstecker; **wie weit** + /// es ist, sieht man nirgends sonst. Also bleibt der Füllstand, und der + /// Blitz kommt als kleines Zeichen darüber. + public static let chargingBolt = "bolt.fill" + + /// SF Symbols kennt fünf Füllstufen. Gerundet wird zur nächsten: 60 % soll + /// nicht halbleer aussehen und 40 % nicht dreiviertel voll. + private static let steps = [0, 25, 50, 75, 100] + + public static func name(charge: Double) -> String { + let percent = Int((min(max(charge, 0), 1) * 100).rounded()) + let step = steps.min { abs($0 - percent) < abs($1 - percent) } ?? 0 + return "battery.\(step)percent" + } +} diff --git a/Packages/OnyxKit/Sources/MetricsProvider/MetricMenuBarModule.swift b/Packages/OnyxKit/Sources/MetricsProvider/MetricMenuBarModule.swift index 08b5c8b..d1dd1e2 100644 --- a/Packages/OnyxKit/Sources/MetricsProvider/MetricMenuBarModule.swift +++ b/Packages/OnyxKit/Sources/MetricsProvider/MetricMenuBarModule.swift @@ -123,7 +123,7 @@ final class MetricStatusView: NSView, WidthReporting { private var width: CGFloat { switch presentation { case .symbol: max(MenuBarText.minimumWidth, - MenuBarText.symbolWidth(metric.symbolName, height: 15) + 4) + MenuBarText.symbolWidth(currentSymbol, height: 15) + 4) case .graph: 28 case .bars: barsWidth case .value: MenuBarText.width(for: reference) @@ -131,7 +131,7 @@ final class MetricStatusView: NSView, WidthReporting { case .labelAndValue: MenuBarText.width(for: "\(label) \(reference)") case .symbolAndValue: MenuBarText.width(for: reference) - + MenuBarText.symbolWidth(metric.symbolName, height: 13) + + MenuBarText.symbolWidth(currentSymbol, height: 13) + MenuBarText.innerGap } } @@ -200,10 +200,10 @@ final class MetricStatusView: NSView, WidthReporting { drawText("\(label) \(displayValue)", color: color) case .symbolAndValue: - let glyph = MenuBarText.symbolWidth(metric.symbolName, height: 13) - MenuBarText.drawSymbol(metric.symbolName, color: color, - in: NSRect(x: 0, y: bounds.midY - 6.5, - width: glyph, height: 13)) + let glyph = MenuBarText.symbolWidth(currentSymbol, height: 13) + let symbolRect = NSRect(x: 0, y: bounds.midY - 6.5, width: glyph, height: 13) + MenuBarText.drawSymbol(currentSymbol, color: color, in: symbolRect) + drawChargingBolt(color: color, over: symbolRect) drawText(displayValue, color: color, in: NSRect(x: glyph + MenuBarText.innerGap, y: 0, width: bounds.width - glyph - MenuBarText.innerGap, @@ -225,9 +225,33 @@ final class MetricStatusView: NSView, WidthReporting { private func drawSymbol(color: NSColor) { let side: CGFloat = 15 - MenuBarText.drawSymbol(metric.symbolName, color: color, - in: NSRect(x: bounds.midX - side / 2, - y: bounds.midY - side / 2, + let width = MenuBarText.symbolWidth(currentSymbol, height: side) + let rect = NSRect(x: bounds.midX - width / 2, y: bounds.midY - side / 2, + width: width, height: side) + MenuBarText.drawSymbol(currentSymbol, color: color, in: rect) + drawChargingBolt(color: color, over: rect) + } + + /// Das Symbol zum **Zustand**, nicht zur Metrik. + /// + /// Beim Akku ändert es sich mit dem Ladestand und zeigt beim Laden einen + /// Blitz — ein Symbol, das bei 5 % genauso aussieht wie bei 95 %, ist + /// Dekoration. Die übrigen Messgrößen haben nichts, was sich sinnvoll im + /// Glyph abbilden ließe. + private var currentSymbol: String { + guard metric == .battery else { return metric.symbolName } + guard let battery = snapshot.battery else { return BatterySymbol.unavailable } + return BatterySymbol.name(charge: battery.charge) + } + + /// Beim Laden ein kleiner Blitz über dem Füllstand. Zwei Zeichnungen statt + /// eines Symbols, weil es die kombinierten Glyphen nur bei 100 % gibt. + private func drawChargingBolt(color: NSColor, over rect: NSRect) { + guard metric == .battery, snapshot.battery?.isCharging == true else { return } + let side: CGFloat = 8 + MenuBarText.drawSymbol(BatterySymbol.chargingBolt, color: color, + in: NSRect(x: rect.maxX - side * 0.75, + y: rect.maxY - side * 0.7, width: side, height: side)) } diff --git a/Packages/OnyxKit/Sources/MetricsProvider/MetricWidgets.swift b/Packages/OnyxKit/Sources/MetricsProvider/MetricWidgets.swift index 67f0ef0..5f3e981 100644 --- a/Packages/OnyxKit/Sources/MetricsProvider/MetricWidgets.swift +++ b/Packages/OnyxKit/Sources/MetricsProvider/MetricWidgets.swift @@ -336,15 +336,24 @@ private struct BatteryTile: View { let battery = model.snapshot.battery VStack(alignment: .leading, spacing: 8) { - HStack(alignment: .firstTextBaseline, spacing: 6) { + HStack(alignment: .firstTextBaseline, spacing: 7) { + // Das Symbol folgt dem Ladestand — sonst zeigt es bei 5 % + // dasselbe wie bei 95 % und trägt nichts bei. + Image(systemName: battery.map { BatterySymbol.name(charge: $0.charge) } + ?? BatterySymbol.unavailable) + .font(.system(size: 13)) + .foregroundStyle(tint(battery)) + .overlay(alignment: .topTrailing) { + if battery?.isCharging == true { + Image(systemName: BatterySymbol.chargingBolt) + .font(.system(size: 7)) + .foregroundStyle(Onyx.Color.positive) + .offset(x: 3, y: -3) + } + } Text(MetricFormat.percent(battery?.charge ?? 0)) .font(Onyx.Font.metric).monospacedDigit() .foregroundStyle(tint(battery)) - if let battery, battery.isCharging { - Image(systemName: "bolt.fill") - .font(.system(size: 11)) - .foregroundStyle(Onyx.Color.positive) - } Spacer(minLength: 0) } diff --git a/Packages/OnyxKit/Tests/MetricsProviderTests/BatterySymbolTests.swift b/Packages/OnyxKit/Tests/MetricsProviderTests/BatterySymbolTests.swift new file mode 100644 index 0000000..555546b --- /dev/null +++ b/Packages/OnyxKit/Tests/MetricsProviderTests/BatterySymbolTests.swift @@ -0,0 +1,52 @@ +import Testing +import AppKit +@testable import MetricsProvider + +// Ein Akkusymbol, das immer gleich aussieht, ist Dekoration und keine +// Anzeige — es beantwortet die eine Frage nicht, für die es da ist. + +@Suite("Akkusymbol") +struct BatterySymbolTests { + + @Test("Der Füllstand steht im Symbol") + func fillFollowsCharge() { + #expect(BatterySymbol.name(charge: 0.05) == "battery.0percent") + #expect(BatterySymbol.name(charge: 0.25) == "battery.25percent") + #expect(BatterySymbol.name(charge: 0.50) == "battery.50percent") + #expect(BatterySymbol.name(charge: 0.75) == "battery.75percent") + #expect(BatterySymbol.name(charge: 1.00) == "battery.100percent") + } + + @Test("Die Stufen liegen zwischen den Marken, nicht darauf") + func stepsRoundToNearest() { + // 60 % soll nicht als halbleer erscheinen, 40 % nicht als dreiviertel + // voll. Gerundet wird zur nächsten Stufe. + #expect(BatterySymbol.name(charge: 0.60) == "battery.50percent") + #expect(BatterySymbol.name(charge: 0.64) == "battery.75percent") + #expect(BatterySymbol.name(charge: 0.40) == "battery.50percent") + } + + @Test("Leer und voll bleiben in ihren Grenzen") + func extremesAreClamped() { + // Ein Messfehler darf keinen Symbolnamen erzeugen, den es nicht gibt. + #expect(BatterySymbol.name(charge: -1) == "battery.0percent") + #expect(BatterySymbol.name(charge: 5) == "battery.100percent") + } + + @Test("Jeder erzeugte Name existiert auch wirklich") + func everyNameResolves() { + // Der Grund für diesen Test: die erste Fassung setzte beim Laden ein + // „.bolt" an den Füllstand an. Von diesen kombinierten Symbolen gibt es + // aber nur `battery.100percent.bolt` — der Rest wäre ein leeres Feld + // in der Menüleiste gewesen. + for percent in stride(from: 0.0, through: 1.0, by: 0.05) { + let name = BatterySymbol.name(charge: percent) + #expect(NSImage(systemSymbolName: name, accessibilityDescription: nil) != nil, + "\(name) gibt es nicht") + } + #expect(NSImage(systemSymbolName: BatterySymbol.unavailable, + accessibilityDescription: nil) != nil) + #expect(NSImage(systemSymbolName: BatterySymbol.chargingBolt, + accessibilityDescription: nil) != nil) + } +}