Show the desktop shell in Chinese under zh_CN
This commit is contained in:
1 parent
e590f22de6
commit
e236713d9f
55 files changed
+867
-331
No files matched your search
@@ -176,7 +176,7 @@ Panel {
|
||||
readonly property bool hasOutput: !!(volumeSink && volumeSink.audio)
|
||||
readonly property bool hasInput: !!(source && source.audio)
|
||||
readonly property bool anyAudible: (hasOutput && !outputMuted) || (hasInput && !inputMuted)
|
||||
readonly property string toggleHint: anyAudible ? "Mute" : "Unmute"
|
||||
readonly property string toggleHint: anyAudible ? I18n.tr("Mute") : I18n.tr("Unmute")
|
||||
|
||||
readonly property color hoverFill: bar
|
||||
? Style.hoverFillFor(bar.foreground, Color.accent)
|
||||
@@ -434,7 +434,7 @@ Panel {
|
||||
// panel's brightnessName ladder; bands are wide enough that small
|
||||
// tweaks don't rename the room you're in.
|
||||
function outputVolumeName(volume, muted) {
|
||||
return Model.outputVolumeName(volume, muted)
|
||||
return I18n.tr(Model.outputVolumeName(volume, muted))
|
||||
}
|
||||
|
||||
function setOutputVolume(v) {
|
||||
@@ -768,7 +768,7 @@ Panel {
|
||||
spacing: Style.space(2)
|
||||
|
||||
Text {
|
||||
text: "Audio"
|
||||
text: I18n.tr("Audio")
|
||||
color: root.bar.foreground
|
||||
font.family: root.bar.fontFamily
|
||||
font.pixelSize: Style.font.title
|
||||
@@ -810,7 +810,7 @@ Panel {
|
||||
|
||||
PanelSectionHeader {
|
||||
id: outputHeader
|
||||
text: "OUTPUT"
|
||||
text: I18n.tr("OUTPUT")
|
||||
foreground: root.bar.foreground
|
||||
fontFamily: root.bar.fontFamily
|
||||
anchors.left: parent.left
|
||||
@@ -897,7 +897,7 @@ Panel {
|
||||
|
||||
PanelSectionHeader {
|
||||
id: microphoneHeader
|
||||
text: "INPUT"
|
||||
text: I18n.tr("INPUT")
|
||||
foreground: root.bar.foreground
|
||||
fontFamily: root.bar.fontFamily
|
||||
anchors.left: parent.left
|
||||
@@ -1000,7 +1000,7 @@ Panel {
|
||||
visible: root.displayAudioStreams.length > 0
|
||||
|
||||
PanelSectionHeader {
|
||||
text: "SOURCES"
|
||||
text: I18n.tr("SOURCES")
|
||||
foreground: root.bar.foreground
|
||||
fontFamily: root.bar.fontFamily
|
||||
}
|
||||
|
||||
@@ -64,19 +64,19 @@ Panel {
|
||||
|
||||
property int phraseIndex: 0
|
||||
readonly property var activePhrases: [
|
||||
"Untangling wires",
|
||||
"Streaming vikings",
|
||||
"Pairing mysteries",
|
||||
"Herding headsets",
|
||||
"Taming radios",
|
||||
"Summoning speakers",
|
||||
"Wrangling codecs",
|
||||
"Polishing packets"
|
||||
I18n.tr("Untangling wires"),
|
||||
I18n.tr("Streaming vikings"),
|
||||
I18n.tr("Pairing mysteries"),
|
||||
I18n.tr("Herding headsets"),
|
||||
I18n.tr("Taming radios"),
|
||||
I18n.tr("Summoning speakers"),
|
||||
I18n.tr("Wrangling codecs"),
|
||||
I18n.tr("Polishing packets")
|
||||
]
|
||||
readonly property bool rotatingPhrases: adapter && adapter.enabled
|
||||
readonly property string heroStatusText: {
|
||||
if (!adapter) return "No adapter"
|
||||
if (!adapter.enabled) return "Turned Off"
|
||||
if (!adapter) return I18n.tr("No adapter")
|
||||
if (!adapter.enabled) return I18n.tr("Turned Off")
|
||||
return activePhrases[phraseIndex % activePhrases.length]
|
||||
}
|
||||
|
||||
@@ -101,7 +101,7 @@ Panel {
|
||||
// sits above the device sections so the adapter can be toggled by keyboard
|
||||
// even when it is off and no device rows exist.
|
||||
readonly property bool headerHasCursor: cursorActive && focusSection === "header"
|
||||
readonly property string toggleHint: root.adapter && root.adapter.enabled ? "Turn Bluetooth off" : "Turn Bluetooth on"
|
||||
readonly property string toggleHint: root.adapter && root.adapter.enabled ? I18n.tr("Turn Bluetooth off") : I18n.tr("Turn Bluetooth on")
|
||||
|
||||
readonly property color hoverFill: bar
|
||||
? Style.hoverFillFor(bar.foreground, Color.accent)
|
||||
@@ -183,7 +183,7 @@ Panel {
|
||||
var rows = scrollRows
|
||||
if (index < 0 || index >= rows.length) return ""
|
||||
if (index > 0 && rows[index - 1].section === rows[index].section) return ""
|
||||
return rows[index].section === "known" ? "PAIRED" : "AVAILABLE"
|
||||
return rows[index].section === "known" ? I18n.tr("PAIRED") : I18n.tr("AVAILABLE")
|
||||
}
|
||||
|
||||
function audioSinks() {
|
||||
@@ -738,7 +738,7 @@ Panel {
|
||||
spacing: Style.space(2)
|
||||
|
||||
Text {
|
||||
text: "Bluetooth"
|
||||
text: I18n.tr("Bluetooth")
|
||||
color: root.bar.foreground
|
||||
font.family: root.bar.fontFamily
|
||||
font.pixelSize: Style.font.title
|
||||
@@ -775,7 +775,7 @@ Panel {
|
||||
spacing: Style.space(10)
|
||||
|
||||
PanelSectionHeader {
|
||||
text: "CONNECTED"
|
||||
text: I18n.tr("CONNECTED")
|
||||
foreground: root.bar.foreground
|
||||
fontFamily: root.bar.fontFamily
|
||||
}
|
||||
@@ -867,9 +867,9 @@ Panel {
|
||||
Text {
|
||||
textFormat: Text.PlainText
|
||||
visible: root.connectedDevices.length === 0 && root.scrollRows.length === 0
|
||||
text: !root.adapter ? "No Bluetooth adapter"
|
||||
: !root.adapter.enabled ? "Turn Bluetooth on to scan"
|
||||
: "Scanning for devices…"
|
||||
text: !root.adapter ? I18n.tr("No Bluetooth adapter")
|
||||
: !root.adapter.enabled ? I18n.tr("Turn Bluetooth on to scan")
|
||||
: I18n.tr("Scanning for devices…")
|
||||
color: Qt.darker(root.bar.foreground, 1.5)
|
||||
font.family: root.bar.fontFamily
|
||||
font.pixelSize: Style.font.bodySmall
|
||||
@@ -894,9 +894,9 @@ Panel {
|
||||
readonly property string action: root.pendingAction(dev ? dev.address : "")
|
||||
readonly property string actionTooltip: {
|
||||
if (!dev) return ""
|
||||
if (isConnected) return "Disconnect"
|
||||
if (isDiscovered) return "Pair"
|
||||
return "Connect"
|
||||
if (isConnected) return I18n.tr("Disconnect")
|
||||
if (isDiscovered) return I18n.tr("Pair")
|
||||
return I18n.tr("Connect")
|
||||
}
|
||||
|
||||
readonly property bool rowSelected: root.cursorActive && root.focusSection === sectionName && root.selectedIndex === rowIndex
|
||||
@@ -911,13 +911,13 @@ Panel {
|
||||
|
||||
readonly property string statusText: {
|
||||
if (!dev) return ""
|
||||
if (action === "forgetting") return "Forgetting…"
|
||||
if (action === "disconnecting" || devState === 2) return "Disconnecting…"
|
||||
if (action === "forgetting") return I18n.tr("Forgetting…")
|
||||
if (action === "disconnecting" || devState === 2) return I18n.tr("Disconnecting…")
|
||||
if (isConnected) {
|
||||
if (dev.batteryAvailable) return Math.round(dev.battery * 100) + "%"
|
||||
return sectionName === "connected" ? "" : "Connected"
|
||||
return sectionName === "connected" ? "" : I18n.tr("Connected")
|
||||
}
|
||||
if (action === "connecting" || devState === 3 || dev.pairing === true) return "Connecting…"
|
||||
if (action === "connecting" || devState === 3 || dev.pairing === true) return I18n.tr("Connecting…")
|
||||
if (isDiscovered) return ""
|
||||
return ""
|
||||
}
|
||||
@@ -994,7 +994,7 @@ Panel {
|
||||
|
||||
Text {
|
||||
textFormat: Text.PlainText
|
||||
text: root.deviceLabel(row.dev) || "Device"
|
||||
text: root.deviceLabel(row.dev) || I18n.tr("Device")
|
||||
color: root.bar.foreground
|
||||
font.family: root.bar.fontFamily
|
||||
font.pixelSize: Style.font.body
|
||||
@@ -1019,7 +1019,7 @@ Panel {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
visible: row.showForgetButton
|
||||
iconText: ""
|
||||
tooltipText: "Forget"
|
||||
tooltipText: I18n.tr("Forget")
|
||||
foreground: root.bar.foreground
|
||||
hoverColor: root.bar.foreground
|
||||
fontFamily: root.bar.fontFamily
|
||||
|
||||
@@ -21,7 +21,7 @@ BarWidget {
|
||||
: setting("format", "dddd HH:mm")
|
||||
readonly property string configuredAltFormat: vertical
|
||||
? setting("verticalFormatAlt", "dd\nMMM\n'W'ww\n''yy")
|
||||
: setting("formatAlt", "d MMMM 'W'ww yyyy")
|
||||
: setting("formatAlt", I18n.chinese ? "yyyy年M月d日 'W'ww" : "d MMMM 'W'ww yyyy")
|
||||
|
||||
readonly property var formatRing: Model.clockFormatRing(configuredFormat, configuredAltFormat, Model.clockFormats(vertical))
|
||||
|
||||
@@ -56,8 +56,10 @@ BarWidget {
|
||||
root.bar.shell.updateEntryInline(root.moduleName, entry)
|
||||
}
|
||||
|
||||
// Qt.formatDateTime is always English; a Chinese session takes day and month names from its locale.
|
||||
function formatted(date) {
|
||||
return Qt.formatDateTime(date, activeFormat.replace(/ww/g, Model.isoWeekLiteral(date.getFullYear(), date.getMonth(), date.getDate())))
|
||||
var format = activeFormat.replace(/ww/g, Model.isoWeekLiteral(date.getFullYear(), date.getMonth(), date.getDate()))
|
||||
return I18n.chinese ? Qt.locale().toString(date, format) : Qt.formatDateTime(date, format)
|
||||
}
|
||||
|
||||
// ---- Calendar popup. Shape contract for shell.summon/hide/toggle
|
||||
@@ -153,7 +155,7 @@ BarWidget {
|
||||
fixedHeight: root.vertical ? root.verticalLines.length * Style.bar.iconSlot : -1
|
||||
horizontalMargin: 8.75
|
||||
verticalPadding: 8.75
|
||||
tooltipText: "Right-click to toggle format"
|
||||
tooltipText: I18n.tr("Right-click to toggle format")
|
||||
|
||||
onPressed: function(b) {
|
||||
if (b === Qt.RightButton) root.cycleFormat()
|
||||
|
||||
@@ -64,10 +64,8 @@ Panel {
|
||||
// convention. Clicking the grid's "W" heading writes the choice back to
|
||||
// shell.json.
|
||||
readonly property int weekStart: Model.normalizedWeekStart(setting("weekStartDay", null), Qt.locale().firstDayOfWeek)
|
||||
// The interface is English throughout, so day names are not taken from the
|
||||
// system locale. Where the week starts still is: that is a regional
|
||||
// convention rather than a translation, and it stays overridable above.
|
||||
readonly property var labelLocale: Qt.locale("en_US")
|
||||
// Day names follow the interface language, not the system locale; the week start above is a regional convention.
|
||||
readonly property var labelLocale: I18n.chinese ? Qt.locale("zh_CN") : Qt.locale("en_US")
|
||||
readonly property string nextWeekStartLabel: labelLocale.dayName(Model.toggledWeekStart(weekStart), Locale.LongFormat)
|
||||
readonly property var weekdays: Model.weekdayOrder(weekStart)
|
||||
readonly property var weeks: Model.monthGrid(viewYear, viewMonth, weekStart, todayKey)
|
||||
@@ -315,7 +313,7 @@ Panel {
|
||||
id: heroDate
|
||||
textFormat: Text.PlainText
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: Qt.formatDate(root.today, "MMMM d")
|
||||
text: I18n.chinese ? root.labelLocale.toString(root.today, "M月d日") : Qt.formatDate(root.today, "MMMM d")
|
||||
color: heroMouse.containsMouse
|
||||
? Style.hoverStateColor(root.contentForeground, Color.accent)
|
||||
: root.contentForeground
|
||||
@@ -338,7 +336,7 @@ Panel {
|
||||
|
||||
PanelToolTip {
|
||||
visible: heroMouse.containsMouse
|
||||
text: "Back to today"
|
||||
text: I18n.tr("Back to today")
|
||||
fontFamily: root.contentFontFamily
|
||||
}
|
||||
}
|
||||
@@ -371,7 +369,7 @@ Panel {
|
||||
|
||||
Text {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: "BORN"
|
||||
text: I18n.tr("BORN")
|
||||
color: Qt.darker(root.contentForeground, 1.5)
|
||||
font.family: root.contentFontFamily
|
||||
font.pixelSize: Style.font.bodySmall
|
||||
@@ -394,7 +392,7 @@ Panel {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.verticalCenterOffset: 0
|
||||
leftPadding: Style.space(6)
|
||||
text: "LIVE TO"
|
||||
text: I18n.tr("LIVE TO")
|
||||
color: Qt.darker(root.contentForeground, 1.5)
|
||||
font.family: root.contentFontFamily
|
||||
font.pixelSize: Style.font.bodySmall
|
||||
@@ -481,7 +479,7 @@ Panel {
|
||||
id: lifeLabel
|
||||
anchors.left: parent.left
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
text: "LIFE"
|
||||
text: I18n.tr("LIFE")
|
||||
color: Qt.darker(root.contentForeground, 1.5)
|
||||
font.family: root.contentFontFamily
|
||||
font.pixelSize: Style.font.bodySmall
|
||||
@@ -600,7 +598,7 @@ Panel {
|
||||
|
||||
PanelToolTip {
|
||||
visible: weekStartMouse.containsMouse
|
||||
text: "Start weeks on " + root.nextWeekStartLabel
|
||||
text: I18n.tr("Start weeks on %1", root.nextWeekStartLabel)
|
||||
fontFamily: root.contentFontFamily
|
||||
}
|
||||
}
|
||||
@@ -723,7 +721,7 @@ Panel {
|
||||
// "MAY 2026" and a "SEPTEMBER 2026".
|
||||
width: Style.space(130)
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
text: Qt.formatDate(root.viewDate, "MMMM yyyy").toUpperCase()
|
||||
text: I18n.chinese ? root.labelLocale.toString(root.viewDate, "yyyy年M月") : Qt.formatDate(root.viewDate, "MMMM yyyy").toUpperCase()
|
||||
color: Qt.darker(root.contentForeground, 1.4)
|
||||
font.family: root.contentFontFamily
|
||||
font.pixelSize: Style.font.body
|
||||
@@ -737,7 +735,7 @@ Panel {
|
||||
anchors.leftMargin: -Style.space(8)
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
iconText: ""
|
||||
tooltipText: "Previous month"
|
||||
tooltipText: I18n.tr("Previous month")
|
||||
foreground: root.contentForeground
|
||||
fontFamily: root.contentFontFamily
|
||||
onClicked: root.moveMonth(-1)
|
||||
@@ -748,7 +746,7 @@ Panel {
|
||||
anchors.rightMargin: -Style.space(8)
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
iconText: ""
|
||||
tooltipText: "Next month"
|
||||
tooltipText: I18n.tr("Next month")
|
||||
foreground: root.contentForeground
|
||||
fontFamily: root.contentFontFamily
|
||||
onClicked: root.moveMonth(1)
|
||||
|
||||
@@ -117,7 +117,7 @@ Item {
|
||||
}
|
||||
|
||||
if (!root.expectedStop && exitCode !== 0) {
|
||||
root.error = root.stderrText || "Disk speed test failed"
|
||||
root.error = root.stderrText || I18n.tr("Disk speed test failed")
|
||||
root.phase = ""
|
||||
root.running = false
|
||||
return
|
||||
@@ -133,10 +133,10 @@ Item {
|
||||
fontFamily: Style.font.family
|
||||
layerNamespace: "omarchy-disk-speedtest"
|
||||
title: root.diskName
|
||||
leftLabel: "READ"
|
||||
rightLabel: "WRITE"
|
||||
leftLabel: I18n.tr("READ")
|
||||
rightLabel: I18n.tr("WRITE")
|
||||
unit: "MB/s"
|
||||
runAgainTooltip: "Measure again"
|
||||
runAgainTooltip: I18n.tr("Measure again")
|
||||
running: root.running
|
||||
leftValue: root.toRate(root.readMBps)
|
||||
rightValue: root.toRate(root.writeMBps)
|
||||
|
||||
@@ -20,16 +20,16 @@ Panel {
|
||||
property int phraseIndex: 0
|
||||
|
||||
readonly property var activePhrases: [
|
||||
"Filing files",
|
||||
"Distributing data",
|
||||
"Shuffling folders",
|
||||
"Boxing bytes",
|
||||
"Sorting stuff",
|
||||
"Syncing secrets",
|
||||
"Packing packets",
|
||||
"Moving memories",
|
||||
"Wrangling revisions",
|
||||
"Cataloging chaos"
|
||||
I18n.tr("Filing files"),
|
||||
I18n.tr("Distributing data"),
|
||||
I18n.tr("Shuffling folders"),
|
||||
I18n.tr("Boxing bytes"),
|
||||
I18n.tr("Sorting stuff"),
|
||||
I18n.tr("Syncing secrets"),
|
||||
I18n.tr("Packing packets"),
|
||||
I18n.tr("Moving memories"),
|
||||
I18n.tr("Wrangling revisions"),
|
||||
I18n.tr("Cataloging chaos")
|
||||
]
|
||||
readonly property string heroPhraseText: activePhrases[phraseIndex % activePhrases.length]
|
||||
readonly property color foreground: bar ? bar.foreground : Color.foreground
|
||||
@@ -37,7 +37,7 @@ Panel {
|
||||
readonly property color dim: Qt.darker(foreground, 1.55)
|
||||
readonly property string fontFamily: bar ? bar.fontFamily : Style.font.family
|
||||
readonly property color iconColor: dropbox.authenticated && dropbox.active ? foreground : dim
|
||||
readonly property string toggleHint: dropbox.active ? "Pause syncing" : "Resume syncing"
|
||||
readonly property string toggleHint: dropbox.active ? I18n.tr("Pause syncing") : I18n.tr("Resume syncing")
|
||||
readonly property color barIconColor: dropbox.authenticated && dropbox.active ? barForeground : Qt.darker(barForeground, 1.55)
|
||||
// Only claim the header cursor when the switch is actually on screen —
|
||||
// "header" stays navigable, but an absent CLI leaves nothing to highlight.
|
||||
@@ -244,7 +244,7 @@ Panel {
|
||||
id: hero
|
||||
width: parent.width
|
||||
title: "Dropbox"
|
||||
meta: dropbox.active ? root.heroPhraseText : "Syncing paused"
|
||||
meta: dropbox.active ? root.heroPhraseText : I18n.tr("Syncing paused")
|
||||
foreground: root.foreground
|
||||
fontFamily: root.fontFamily
|
||||
iconOpacity: dropbox.active ? 1.0 : 0.5
|
||||
@@ -304,7 +304,7 @@ Panel {
|
||||
Column {
|
||||
width: parent.width
|
||||
spacing: Style.spacing.labelGap
|
||||
InfoPair { label: "Stored"; value: Model.usageText(dropbox.usedBytes, dropbox.quotaBytes, dropbox.quotaKnown) }
|
||||
InfoPair { label: I18n.tr("Stored"); value: Model.usageText(dropbox.usedBytes, dropbox.quotaBytes, dropbox.quotaKnown) }
|
||||
}
|
||||
}
|
||||
|
||||
@@ -319,7 +319,7 @@ Panel {
|
||||
spacing: Style.space(10)
|
||||
|
||||
PanelSectionHeader {
|
||||
text: "RECENT FILES"
|
||||
text: I18n.tr("RECENT FILES")
|
||||
foreground: root.foreground
|
||||
fontFamily: root.fontFamily
|
||||
}
|
||||
@@ -327,7 +327,7 @@ Panel {
|
||||
Text {
|
||||
visible: dropbox.files.length === 0
|
||||
width: parent.width
|
||||
text: "No synced files found."
|
||||
text: I18n.tr("No synced files found.")
|
||||
color: root.dim
|
||||
font.family: root.fontFamily
|
||||
font.pixelSize: Style.font.body
|
||||
@@ -424,7 +424,7 @@ Panel {
|
||||
Text {
|
||||
textFormat: Text.PlainText
|
||||
Layout.fillWidth: true
|
||||
text: dropbox.installed ? "Login to Dropbox" : "Dropbox CLI is not installed"
|
||||
text: dropbox.installed ? I18n.tr("Login to Dropbox") : I18n.tr("Dropbox CLI is not installed")
|
||||
color: root.foreground
|
||||
font.family: root.fontFamily
|
||||
font.pixelSize: Style.font.body
|
||||
@@ -434,7 +434,7 @@ Panel {
|
||||
Text {
|
||||
textFormat: Text.PlainText
|
||||
Layout.fillWidth: true
|
||||
text: dropbox.installed ? "Start the authentication flow" : "Install Dropbox from the service menu"
|
||||
text: dropbox.installed ? I18n.tr("Start the authentication flow") : I18n.tr("Install Dropbox from the service menu")
|
||||
color: root.dim
|
||||
font.family: root.fontFamily
|
||||
font.pixelSize: Style.font.caption
|
||||
@@ -457,7 +457,7 @@ Panel {
|
||||
id: fileRow
|
||||
property var file: null
|
||||
property int rowIndex: 0
|
||||
readonly property string fileName: file ? String(file.name || "Untitled") : "Untitled"
|
||||
readonly property string fileName: file ? String(file.name || I18n.tr("Untitled")) : I18n.tr("Untitled")
|
||||
|
||||
hasCursor: root.cursorActive && root.focusSection === "files" && root.fileIndex === rowIndex
|
||||
foreground: root.foreground
|
||||
|
||||
@@ -73,7 +73,7 @@ Column {
|
||||
width: parent.width
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
topPadding: Style.spacing.md
|
||||
text: list.citySearch.loading ? list.citySearch.loadingText : "No matches"
|
||||
text: list.citySearch.loading ? list.citySearch.loadingText : I18n.tr("No matches")
|
||||
color: list.citySearch.fainter
|
||||
}
|
||||
|
||||
|
||||
@@ -300,7 +300,7 @@ Rectangle {
|
||||
color: Model.mix(Color.popups.background, row.foreground, _hot ? 0.24 : 0.14)
|
||||
borderSpec: Border.flat(Model.mix(Color.popups.background, row.foreground, _hot ? 0.65 : 0.35), Style.space(1))
|
||||
iconText: "\u00d7"
|
||||
tooltipText: "Remove"
|
||||
tooltipText: I18n.tr("Remove")
|
||||
foreground: row.dim
|
||||
hoverColor: row.foreground
|
||||
fontFamily: row.fontFamily
|
||||
|
||||
@@ -17,7 +17,7 @@ Column {
|
||||
property var offsetLabel: function(zoneId) { return "" }
|
||||
property bool loading: false
|
||||
property string buttonText: "+ Add a city"
|
||||
property string placeholderText: "Search cities\u2026"
|
||||
property string placeholderText: I18n.tr("Search cities…")
|
||||
property string loadingText: "Loading zones\u2026"
|
||||
property real fontSize: Style.font.bodySmall
|
||||
property color foreground: Color.foreground
|
||||
|
||||
@@ -65,8 +65,8 @@ Item {
|
||||
var out = []
|
||||
var up = Sun.eventMark(sun.riseMinutes)
|
||||
var down = Sun.eventMark(sun.setMinutes)
|
||||
if (up !== null) out.push({ x: up, minutes: sun.riseMinutes, rising: true, name: "Sunrise" })
|
||||
if (down !== null) out.push({ x: down, minutes: sun.setMinutes, rising: false, name: "Sunset" })
|
||||
if (up !== null) out.push({ x: up, minutes: sun.riseMinutes, rising: true, name: I18n.tr("Sunrise") })
|
||||
if (down !== null) out.push({ x: down, minutes: sun.setMinutes, rising: false, name: I18n.tr("Sunset") })
|
||||
return out
|
||||
}
|
||||
|
||||
|
||||
@@ -584,7 +584,7 @@ Item {
|
||||
limit: 5
|
||||
inlineResults: false
|
||||
loading: root.jumpOptions.length === 0
|
||||
buttonText: "Jump to a city"
|
||||
buttonText: I18n.tr("Jump to a city")
|
||||
loadingText: "Loading cities\u2026"
|
||||
offsetLabel: function(zoneId) { return Model.utcOffsetLabel(root.offsets[zoneId]) }
|
||||
foreground: root.foreground
|
||||
|
||||
@@ -72,7 +72,7 @@ Column {
|
||||
anchors.horizontalCenter: parent.horizontalCenter
|
||||
spacing: Style.space(9)
|
||||
|
||||
TitleWord { text: "World" }
|
||||
TitleWord { text: I18n.tr("World") }
|
||||
|
||||
Item {
|
||||
id: heroIcon
|
||||
@@ -150,7 +150,7 @@ Column {
|
||||
}
|
||||
}
|
||||
|
||||
TitleWord { text: "Clock" }
|
||||
TitleWord { text: I18n.tr("Clock") }
|
||||
}
|
||||
|
||||
component TitleWord: Text {
|
||||
|
||||
@@ -334,7 +334,7 @@ Panel {
|
||||
}
|
||||
|
||||
// No full stop: a period hanging off the arc reads as a speck.
|
||||
readonly property string hereLine: "It's " + localTime + " here"
|
||||
readonly property string hereLine: I18n.tr("It's %1 here", localTime)
|
||||
+ (homeCity !== "" ? " in " + homeCity : "")
|
||||
+ (scrubLabel !== "" ? " " + scrubLabel : "")
|
||||
|
||||
@@ -714,7 +714,7 @@ Panel {
|
||||
bar: root.bar
|
||||
slotSize: Style.bar.statusSlot
|
||||
text: ""
|
||||
tooltipText: "World clock"
|
||||
tooltipText: I18n.tr("World clock")
|
||||
onPressed: function(buttonCode) {
|
||||
if (buttonCode === Qt.RightButton || buttonCode === Qt.MiddleButton) root.refresh()
|
||||
else root.toggle()
|
||||
|
||||
@@ -555,7 +555,7 @@ Panel {
|
||||
spacing: Style.space(2)
|
||||
|
||||
Text {
|
||||
text: "Display"
|
||||
text: I18n.tr("Display")
|
||||
color: root.bar.foreground
|
||||
font.family: root.bar.fontFamily
|
||||
font.pixelSize: Style.font.title
|
||||
@@ -569,9 +569,9 @@ Panel {
|
||||
textFormat: Text.PlainText
|
||||
text: {
|
||||
if (root.brightnessAvailable) {
|
||||
return root.brightnessName(brightnessSlider.dragging ? brightnessSlider.liveValue : root.brightnessPercent).toUpperCase()
|
||||
return I18n.tr(root.brightnessName(brightnessSlider.dragging ? brightnessSlider.liveValue : root.brightnessPercent)).toUpperCase()
|
||||
}
|
||||
return "FIXED BRIGHTNESS"
|
||||
return I18n.tr("FIXED BRIGHTNESS")
|
||||
}
|
||||
color: Qt.darker(root.bar.foreground, 1.4)
|
||||
font.family: root.bar.fontFamily
|
||||
@@ -601,7 +601,7 @@ Panel {
|
||||
|
||||
PanelSectionHeader {
|
||||
id: brightnessHeader
|
||||
text: "BRIGHTNESS"
|
||||
text: I18n.tr("BRIGHTNESS")
|
||||
foreground: root.bar.foreground
|
||||
fontFamily: root.bar.fontFamily
|
||||
anchors.left: parent.left
|
||||
@@ -674,7 +674,7 @@ Panel {
|
||||
|
||||
PanelSectionHeader {
|
||||
id: textSizeHeader
|
||||
text: "TEXT SIZE"
|
||||
text: I18n.tr("TEXT SIZE")
|
||||
foreground: root.bar.foreground
|
||||
fontFamily: root.bar.fontFamily
|
||||
anchors.left: parent.left
|
||||
@@ -746,7 +746,7 @@ Panel {
|
||||
|
||||
PanelSectionHeader {
|
||||
id: scaleHeader
|
||||
text: "SCALE"
|
||||
text: I18n.tr("SCALE")
|
||||
foreground: root.bar.foreground
|
||||
fontFamily: root.bar.fontFamily
|
||||
anchors.left: parent.left
|
||||
@@ -808,7 +808,7 @@ Panel {
|
||||
visible: root.displays.length > 1
|
||||
|
||||
PanelSectionHeader {
|
||||
text: "DISPLAYS"
|
||||
text: I18n.tr("DISPLAYS")
|
||||
foreground: root.bar.foreground
|
||||
fontFamily: root.bar.fontFamily
|
||||
}
|
||||
|
||||
@@ -56,13 +56,13 @@ Panel {
|
||||
readonly property bool hasTransferStats: info.rx_bytes !== undefined
|
||||
property int connectionPhraseIndex: 0
|
||||
readonly property var connectionPhrases: [
|
||||
"Wiring bits",
|
||||
"Handling packets",
|
||||
"Sorting frames",
|
||||
"Hauling bytes",
|
||||
"Routing crumbs",
|
||||
"Counting collisions",
|
||||
"Bending light",
|
||||
I18n.tr("Wiring bits"),
|
||||
I18n.tr("Handling packets"),
|
||||
I18n.tr("Sorting frames"),
|
||||
I18n.tr("Hauling bytes"),
|
||||
I18n.tr("Routing crumbs"),
|
||||
I18n.tr("Counting collisions"),
|
||||
I18n.tr("Bending light"),
|
||||
]
|
||||
readonly property string connectionPhrase: connectionPhrases[connectionPhraseIndex % connectionPhrases.length]
|
||||
readonly property bool networkManagerAvailable: Networking.backend === NetworkBackendType.NetworkManager
|
||||
@@ -137,7 +137,7 @@ Panel {
|
||||
readonly property bool qrHeaderHasCursor: cursorActive && focusSection === "header" && headerIndex === qrHeaderIndex
|
||||
readonly property bool speedHeaderHasCursor: cursorActive && focusSection === "header" && headerIndex === speedHeaderIndex
|
||||
readonly property bool toggleHeaderHasCursor: cursorActive && focusSection === "header" && headerIndex === toggleHeaderIndex
|
||||
readonly property string toggleHint: Networking.wifiEnabled ? "Turn Wi-Fi off" : "Turn Wi-Fi on"
|
||||
readonly property string toggleHint: Networking.wifiEnabled ? I18n.tr("Turn Wi-Fi off") : I18n.tr("Turn Wi-Fi on")
|
||||
readonly property var dnsProviders: ["DHCP", "Cloudflare", "Google", "Custom"]
|
||||
property int dnsIndex: 0
|
||||
// ["2.4", "5", ...], or empty when there is nothing to choose between.
|
||||
@@ -159,7 +159,10 @@ Panel {
|
||||
// Under Automatic there is nothing to pick, so the pills collapse away and
|
||||
// the header states the live band instead.
|
||||
readonly property bool bandPillsVisible: canSelectBand && bandPinned
|
||||
readonly property string bandSectionTitle: Model.bandSectionTitle(bandEffective, bandCurrent)
|
||||
readonly property string bandSectionTitle: {
|
||||
var title = Model.bandSectionTitle(bandEffective, bandCurrent)
|
||||
return title.indexOf("WI-FI BAND: ") === 0 ? I18n.tr("WI-FI BAND: %1", title.slice(12)) : I18n.tr(title)
|
||||
}
|
||||
readonly property bool bandBusy: pendingBand !== ""
|
||||
// The speed test needs an interface to test, so its hero action only
|
||||
// appears once there is one.
|
||||
@@ -279,11 +282,12 @@ Panel {
|
||||
}
|
||||
|
||||
function bandLabel(band) {
|
||||
return Model.bandLabel(band)
|
||||
return I18n.tr(Model.bandLabel(band))
|
||||
}
|
||||
|
||||
function bandTooltip(band) {
|
||||
return Model.bandTooltip(band)
|
||||
var tip = Model.bandTooltip(band)
|
||||
return tip.indexOf("Stay on ") === 0 ? I18n.tr("Stay on %1", bandLabel(band)) : I18n.tr(tip)
|
||||
}
|
||||
|
||||
// Single cursor model: exactly one highlighted spot across the whole
|
||||
@@ -662,7 +666,7 @@ Panel {
|
||||
}
|
||||
|
||||
function formatPingLatency(ms) {
|
||||
return Model.formatPingLatency(ms, hasInternetPing)
|
||||
return I18n.tr(Model.formatPingLatency(ms, hasInternetPing))
|
||||
}
|
||||
|
||||
function formatPacketLoss(percent) {
|
||||
@@ -709,7 +713,7 @@ Panel {
|
||||
}
|
||||
|
||||
function wifiSectionTitle(index) {
|
||||
return Model.wifiSectionTitle(wifiNetworks, index)
|
||||
return I18n.tr(Model.wifiSectionTitle(wifiNetworks, index))
|
||||
}
|
||||
|
||||
function wifiIconFor(strength) {
|
||||
@@ -754,7 +758,7 @@ Panel {
|
||||
cancelPasswordPrompt()
|
||||
var connection = ""
|
||||
if (info.type === "wifi") connection = info.ssid || "Wi-Fi"
|
||||
else if (info.type === "ethernet") connection = "Ethernet"
|
||||
else if (info.type === "ethernet") connection = I18n.tr("Ethernet")
|
||||
bar.shell.summon("omarchy.speedtest", connection ? JSON.stringify({ connection: connection }) : "{}")
|
||||
}
|
||||
|
||||
@@ -835,7 +839,7 @@ Panel {
|
||||
if (!network || actionKind === "" || actionSsid !== (network.name || "")) return
|
||||
actionTimeout.stop()
|
||||
failureSsid = actionSsid
|
||||
failureReason = networkFailureReason(reason, requiresCredentials(network.security))
|
||||
failureReason = I18n.tr(networkFailureReason(reason, requiresCredentials(network.security)))
|
||||
actionSsid = ""
|
||||
actionKind = ""
|
||||
refresh()
|
||||
@@ -1062,9 +1066,9 @@ Panel {
|
||||
onTriggered: {
|
||||
if (!root.actionKind) return
|
||||
var reason
|
||||
if (root.actionKind === "connect") reason = "Timed out connecting"
|
||||
else if (root.actionKind === "disconnect") reason = "Timed out disconnecting"
|
||||
else reason = "Timed out forgetting"
|
||||
if (root.actionKind === "connect") reason = I18n.tr("Timed out connecting")
|
||||
else if (root.actionKind === "disconnect") reason = I18n.tr("Timed out disconnecting")
|
||||
else reason = I18n.tr("Timed out forgetting")
|
||||
root.failureSsid = root.actionSsid
|
||||
root.failureReason = reason
|
||||
root.actionSsid = ""
|
||||
@@ -1079,8 +1083,8 @@ Panel {
|
||||
bar: root.bar
|
||||
text: root.icon
|
||||
active: root.restricted
|
||||
tooltipText: root.hasCaptivePortal ? "Sign in to this network"
|
||||
: (root.restricted ? "Limited internet access" : "")
|
||||
tooltipText: root.hasCaptivePortal ? I18n.tr("Sign in to this network")
|
||||
: (root.restricted ? I18n.tr("Limited internet access") : "")
|
||||
|
||||
onPressed: function(b) {
|
||||
if (root.opened) root.close()
|
||||
@@ -1249,7 +1253,7 @@ Panel {
|
||||
id: qrAction
|
||||
visible: root.canShareWifi
|
||||
iconText: ""
|
||||
tooltipText: "Show QR code"
|
||||
tooltipText: I18n.tr("Show QR code")
|
||||
foreground: root.bar.foreground
|
||||
fontFamily: root.bar.fontFamily
|
||||
iconSize: Style.font.subtitle * 1.5
|
||||
@@ -1265,7 +1269,7 @@ Panel {
|
||||
id: speedAction
|
||||
visible: root.canRunSpeedTest
|
||||
iconText: ""
|
||||
tooltipText: "Run a speed test"
|
||||
tooltipText: I18n.tr("Run a speed test")
|
||||
foreground: root.bar.foreground
|
||||
fontFamily: root.bar.fontFamily
|
||||
iconSize: Style.font.subtitle * 1.5
|
||||
@@ -1316,8 +1320,8 @@ Panel {
|
||||
// SSID even before route/details polling has returned anything.
|
||||
if (root.kind === "wifi" && root.connectedWifiNetwork) return root.connectedWifiNetwork.name || "Wi-Fi"
|
||||
if (root.info.type === "wifi") return root.info.ssid || "Wi-Fi"
|
||||
if (root.info.type === "ethernet") return "Ethernet"
|
||||
return root.info.iface || (root.kind === "disconnected" ? "Disconnected" : "No connection")
|
||||
if (root.info.type === "ethernet") return I18n.tr("Ethernet")
|
||||
return root.info.iface || (root.kind === "disconnected" ? I18n.tr("Disconnected") : I18n.tr("No connection"))
|
||||
}
|
||||
readonly property string detail: root.headerDetail()
|
||||
|
||||
@@ -1334,15 +1338,15 @@ Panel {
|
||||
textFormat: Text.PlainText
|
||||
width: parent.width
|
||||
text: {
|
||||
if (root.hasCaptivePortal) return "SIGN-IN REQUIRED"
|
||||
if (root.restricted) return "LIMITED INTERNET ACCESS"
|
||||
if (root.hasCaptivePortal) return I18n.tr("SIGN-IN REQUIRED")
|
||||
if (root.restricted) return I18n.tr("LIMITED INTERNET ACCESS")
|
||||
if (root.info.type === "wifi") {
|
||||
if (root.canDisconnect) return root.connectionPhrase.toUpperCase()
|
||||
if (root.kind === "disconnected") return "NOT CONNECTED"
|
||||
if (root.kind === "disconnected") return I18n.tr("NOT CONNECTED")
|
||||
return ""
|
||||
}
|
||||
if (root.info.type === "ethernet") return root.connectionPhrase.toUpperCase()
|
||||
if (root.kind === "disconnected") return "NOT CONNECTED"
|
||||
if (root.kind === "disconnected") return I18n.tr("NOT CONNECTED")
|
||||
return ""
|
||||
}
|
||||
visible: text !== ""
|
||||
@@ -1365,7 +1369,7 @@ Panel {
|
||||
Button {
|
||||
id: portalAction
|
||||
width: parent.width
|
||||
text: "Open Captive Portal"
|
||||
text: I18n.tr("Open Captive Portal")
|
||||
iconText: ""
|
||||
foreground: root.bar.urgent
|
||||
accent: root.bar.urgent
|
||||
@@ -1384,7 +1388,7 @@ Panel {
|
||||
|
||||
Text {
|
||||
width: parent.width
|
||||
text: "Sign in or accept this network’s terms to access the internet."
|
||||
text: I18n.tr("Sign in or accept this network’s terms to access the internet.")
|
||||
textFormat: Text.PlainText
|
||||
wrapMode: Text.WordWrap
|
||||
color: root.bar.foreground
|
||||
@@ -1410,38 +1414,38 @@ Panel {
|
||||
// opened, once the first probe returned, shoving everything below
|
||||
// them down. They now hold their place and read "--" until there is
|
||||
// a sample.
|
||||
InfoLabel { text: "Ping" }
|
||||
InfoLabel { text: I18n.tr("Ping") }
|
||||
DetailValue {
|
||||
text: root.formatPingLatency(root.internetPingLatency)
|
||||
color: root.internetPingPacketLoss > 0 ? root.bar.urgent : root.bar.foreground
|
||||
}
|
||||
InfoLabel { text: "Packet Loss" }
|
||||
InfoLabel { text: I18n.tr("Packet Loss") }
|
||||
DetailValue {
|
||||
text: root.formatPacketLoss(root.internetPingPacketLoss)
|
||||
color: root.internetPingPacketLoss > 0 ? root.bar.urgent : root.bar.foreground
|
||||
}
|
||||
|
||||
InfoLabel { text: "Receiving" }
|
||||
InfoLabel { text: I18n.tr("Receiving") }
|
||||
DetailValue { text: root.hasTransferStats ? root.formatRate(root.downloadRate) : "--" }
|
||||
InfoLabel { text: "Sending" }
|
||||
InfoLabel { text: I18n.tr("Sending") }
|
||||
DetailValue { text: root.hasTransferStats ? root.formatRate(root.uploadRate) : "--" }
|
||||
|
||||
InfoLabel { text: "Downloaded" }
|
||||
InfoLabel { text: I18n.tr("Downloaded") }
|
||||
DetailValue { text: root.hasTransferStats ? root.formatBytes(parseFloat(root.info.rx_bytes || "0")) : "--" }
|
||||
InfoLabel { text: "Uploaded" }
|
||||
InfoLabel { text: I18n.tr("Uploaded") }
|
||||
DetailValue { text: root.hasTransferStats ? root.formatBytes(parseFloat(root.info.tx_bytes || "0")) : "--" }
|
||||
|
||||
InfoLabel { text: "IP Address" }
|
||||
InfoLabel { text: I18n.tr("IP Address") }
|
||||
DetailValue {
|
||||
text: root.info.ip || "--"
|
||||
copyable: !!root.info.ip
|
||||
tooltipText: "Copy IP"
|
||||
tooltipText: I18n.tr("Copy IP")
|
||||
}
|
||||
InfoLabel { text: "Gateway" }
|
||||
InfoLabel { text: I18n.tr("Gateway") }
|
||||
DetailValue {
|
||||
text: root.info.gateway || "--"
|
||||
copyable: !!root.info.gateway
|
||||
tooltipText: "Copy gateway"
|
||||
tooltipText: I18n.tr("Copy gateway")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1482,7 +1486,7 @@ Panel {
|
||||
|
||||
PanelSectionHeader {
|
||||
id: bandAutoLabel
|
||||
text: "AUTOMATIC"
|
||||
text: I18n.tr("AUTOMATIC")
|
||||
foreground: root.bar.foreground
|
||||
fontFamily: root.bar.fontFamily
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
@@ -1515,8 +1519,8 @@ Panel {
|
||||
PanelToolTip {
|
||||
visible: bandAutoSwitch.containsMouse
|
||||
text: root.bandPinned
|
||||
? "Let Wi-Fi pick the band"
|
||||
: "Stay on " + root.bandLabel(root.bandCurrent)
|
||||
? I18n.tr("Let Wi-Fi pick the band")
|
||||
: I18n.tr("Stay on %1", root.bandLabel(root.bandCurrent))
|
||||
fontFamily: root.bar.fontFamily
|
||||
}
|
||||
}
|
||||
@@ -1587,7 +1591,7 @@ Panel {
|
||||
spacing: Style.space(10)
|
||||
|
||||
PanelSectionHeader {
|
||||
text: "DNS PROVIDER"
|
||||
text: I18n.tr("DNS PROVIDER")
|
||||
foreground: root.bar.foreground
|
||||
fontFamily: root.bar.fontFamily
|
||||
}
|
||||
@@ -1603,7 +1607,7 @@ Panel {
|
||||
DnsProviderPill {
|
||||
provider: "DHCP"
|
||||
index: 0
|
||||
tooltipText: "Use DNS from DHCP"
|
||||
tooltipText: I18n.tr("Use DNS from DHCP")
|
||||
width: dnsRow.cellWidth
|
||||
onClicked: root.setDns(provider)
|
||||
}
|
||||
@@ -1611,7 +1615,7 @@ Panel {
|
||||
DnsProviderPill {
|
||||
provider: "Cloudflare"
|
||||
index: 1
|
||||
tooltipText: "Set DNS to Cloudflare"
|
||||
tooltipText: I18n.tr("Set DNS to %1", "Cloudflare")
|
||||
width: dnsRow.cellWidth
|
||||
onClicked: root.setDns(provider)
|
||||
}
|
||||
@@ -1619,7 +1623,7 @@ Panel {
|
||||
DnsProviderPill {
|
||||
provider: "Google"
|
||||
index: 2
|
||||
tooltipText: "Set DNS to Google"
|
||||
tooltipText: I18n.tr("Set DNS to %1", "Google")
|
||||
width: dnsRow.cellWidth
|
||||
onClicked: root.setDns(provider)
|
||||
}
|
||||
@@ -1627,7 +1631,7 @@ Panel {
|
||||
DnsProviderPill {
|
||||
provider: "Custom"
|
||||
index: 3
|
||||
tooltipText: "Set custom DNS servers"
|
||||
tooltipText: I18n.tr("Set custom DNS servers")
|
||||
width: dnsRow.cellWidth
|
||||
onClicked: root.setDns(provider)
|
||||
}
|
||||
@@ -1643,7 +1647,7 @@ Panel {
|
||||
|
||||
PanelSectionHeader {
|
||||
visible: root.wifiStationAvailable && root.scanning
|
||||
text: "SCANNING WI-FI…"
|
||||
text: I18n.tr("SCANNING WI-FI…")
|
||||
foreground: root.bar.foreground
|
||||
fontFamily: root.bar.fontFamily
|
||||
}
|
||||
@@ -1746,7 +1750,7 @@ Panel {
|
||||
required property string provider
|
||||
required property int index
|
||||
|
||||
text: provider
|
||||
text: I18n.tr(provider)
|
||||
fontSize: Style.font.bodySmall
|
||||
foreground: root.bar.foreground
|
||||
fontFamily: root.bar.fontFamily
|
||||
@@ -1829,12 +1833,12 @@ Panel {
|
||||
readonly property string statusText: {
|
||||
if (!net) return ""
|
||||
if (isPasswordOpen) return ""
|
||||
if (isBusy && root.actionKind === "connect") return "Connecting…"
|
||||
if (isBusy && root.actionKind === "disconnect") return "Disconnecting…"
|
||||
if (isBusy && root.actionKind === "forget") return "Forgetting…"
|
||||
if (isFailed) return root.failureReason || "Failed"
|
||||
if (isConnected && root.kind === "wifi" && root.hasCaptivePortal) return "Sign-in required"
|
||||
if (isConnected) return "Connected"
|
||||
if (isBusy && root.actionKind === "connect") return I18n.tr("Connecting…")
|
||||
if (isBusy && root.actionKind === "disconnect") return I18n.tr("Disconnecting…")
|
||||
if (isBusy && root.actionKind === "forget") return I18n.tr("Forgetting…")
|
||||
if (isFailed) return root.failureReason || I18n.tr("Failed")
|
||||
if (isConnected && root.kind === "wifi" && root.hasCaptivePortal) return I18n.tr("Sign-in required")
|
||||
if (isConnected) return I18n.tr("Connected")
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -1951,7 +1955,7 @@ Panel {
|
||||
|
||||
PanelToolTip {
|
||||
visible: rightMouse.containsMouse || row.forgetFocused
|
||||
text: "Forget network"
|
||||
text: I18n.tr("Forget network")
|
||||
fontFamily: root.bar.fontFamily
|
||||
}
|
||||
}
|
||||
@@ -1967,7 +1971,7 @@ Panel {
|
||||
|
||||
Text {
|
||||
textFormat: Text.PlainText
|
||||
text: row.net ? (row.net.ssid || "Hidden") : ""
|
||||
text: row.net ? (row.net.ssid || I18n.tr("Hidden")) : ""
|
||||
color: root.bar.foreground
|
||||
font.family: root.bar.fontFamily
|
||||
font.pixelSize: Style.font.body
|
||||
@@ -2027,7 +2031,7 @@ Panel {
|
||||
anchors.right: connectPwBtn.left
|
||||
anchors.top: parent.top
|
||||
anchors.rightMargin: Style.space(6)
|
||||
placeholderText: "Identity (user@domain)"
|
||||
placeholderText: I18n.tr("Identity (user@domain)")
|
||||
font.family: Style.font.family
|
||||
font.pixelSize: Style.font.body
|
||||
foreground: root.bar.foreground
|
||||
@@ -2053,7 +2057,7 @@ Panel {
|
||||
anchors.bottomMargin: Style.spacing.rowGap / 2
|
||||
anchors.rightMargin: Style.space(6)
|
||||
password: true
|
||||
placeholderText: "Passphrase"
|
||||
placeholderText: I18n.tr("Passphrase")
|
||||
font.family: Style.font.family
|
||||
font.pixelSize: Style.font.body
|
||||
foreground: root.bar.foreground
|
||||
@@ -2086,7 +2090,7 @@ Panel {
|
||||
anchors.fill: parent
|
||||
horizontalAlignment: Text.AlignHCenter
|
||||
verticalAlignment: Text.AlignVCenter
|
||||
text: row.isFailed ? "Wrong password" : "Connecting..."
|
||||
text: row.isFailed ? I18n.tr("Wrong password") : I18n.tr("Connecting...")
|
||||
color: row.isFailed ? root.bar.urgent : root.bar.foreground
|
||||
font.family: root.bar.fontFamily
|
||||
font.pixelSize: Style.font.bodySmall
|
||||
@@ -2103,7 +2107,7 @@ Panel {
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
enabled: row.net && pwField.text.length > 0 && (!row.isEnterprise || idField.text.length > 0)
|
||||
iconText: ""
|
||||
tooltipText: "Connect"
|
||||
tooltipText: I18n.tr("Connect")
|
||||
foreground: root.bar.foreground
|
||||
fontFamily: root.bar.fontFamily
|
||||
onClicked: row.submitCredentials()
|
||||
@@ -2114,7 +2118,7 @@ Panel {
|
||||
|
||||
component DetailValue: InfoValue {
|
||||
property bool copyable: false
|
||||
property string tooltipText: "Copy to clipboard"
|
||||
property string tooltipText: I18n.tr("Copy to clipboard")
|
||||
|
||||
Layout.fillWidth: true
|
||||
horizontalAlignment: Text.AlignRight
|
||||
|
||||
@@ -54,7 +54,7 @@ Panel {
|
||||
|
||||
function modeLabel() {
|
||||
var device = UPower.displayDevice
|
||||
return Model.modeLabel(device, root.discharging, upowerStates())
|
||||
return I18n.tr(Model.modeLabel(device, root.discharging, upowerStates()))
|
||||
}
|
||||
|
||||
function profileIcon(name) {
|
||||
@@ -94,26 +94,26 @@ Panel {
|
||||
// Cute agent-flavored phrases shown in the hero status line, rotated on a
|
||||
// timer so the panel feels alive when current is flowing (either direction).
|
||||
readonly property var chargingPhrases: [
|
||||
"Pumping power",
|
||||
"Injecting electrons",
|
||||
"Pouring juice",
|
||||
"Amassing watts",
|
||||
"Hoarding joules",
|
||||
"Sucking volts",
|
||||
"Topping reserves",
|
||||
"Soaking amps",
|
||||
"Inhaling kilowatts"
|
||||
I18n.tr("Pumping power"),
|
||||
I18n.tr("Injecting electrons"),
|
||||
I18n.tr("Pouring juice"),
|
||||
I18n.tr("Amassing watts"),
|
||||
I18n.tr("Hoarding joules"),
|
||||
I18n.tr("Sucking volts"),
|
||||
I18n.tr("Topping reserves"),
|
||||
I18n.tr("Soaking amps"),
|
||||
I18n.tr("Inhaling kilowatts")
|
||||
]
|
||||
readonly property var onBatteryPhrases: [
|
||||
"Slurping power",
|
||||
"Spending joules",
|
||||
"Draining watts",
|
||||
"Burning electrons",
|
||||
"Sipping juice",
|
||||
"Spending coulombs",
|
||||
"Bleeding amps",
|
||||
"Guzzling volts",
|
||||
"Munching reserves"
|
||||
I18n.tr("Slurping power"),
|
||||
I18n.tr("Spending joules"),
|
||||
I18n.tr("Draining watts"),
|
||||
I18n.tr("Burning electrons"),
|
||||
I18n.tr("Sipping juice"),
|
||||
I18n.tr("Spending coulombs"),
|
||||
I18n.tr("Bleeding amps"),
|
||||
I18n.tr("Guzzling volts"),
|
||||
I18n.tr("Munching reserves")
|
||||
]
|
||||
property int phraseIndex: 0
|
||||
|
||||
@@ -127,7 +127,7 @@ Panel {
|
||||
readonly property bool rotatingPhrases: activePhrases.length > 0
|
||||
|
||||
readonly property string heroStatusText: {
|
||||
if (fullyCharged) return "Fully charged"
|
||||
if (fullyCharged) return I18n.tr("Fully charged")
|
||||
if (rotatingPhrases) return activePhrases[phraseIndex % activePhrases.length]
|
||||
return modeLabel()
|
||||
}
|
||||
@@ -346,7 +346,7 @@ Panel {
|
||||
spacing: Style.space(2)
|
||||
|
||||
Text {
|
||||
text: "Battery"
|
||||
text: I18n.tr("Battery")
|
||||
color: root.bar.foreground
|
||||
font.family: root.bar.fontFamily
|
||||
font.pixelSize: Style.font.title
|
||||
@@ -433,20 +433,20 @@ Panel {
|
||||
Column {
|
||||
width: (parent.width - parent.spacing) / 2
|
||||
spacing: Style.spacing.labelGap
|
||||
InfoPair { label: "Battery size"; value: root.batteryInfo.size || "" }
|
||||
InfoPair { label: "Charge cycles"; value: root.batteryInfo.cycles || "—" }
|
||||
InfoPair { label: I18n.tr("Battery size"); value: root.batteryInfo.size || "" }
|
||||
InfoPair { label: I18n.tr("Charge cycles"); value: root.batteryInfo.cycles || "—" }
|
||||
}
|
||||
|
||||
Column {
|
||||
width: (parent.width - parent.spacing) / 2
|
||||
spacing: Style.spacing.labelGap
|
||||
InfoPair {
|
||||
label: root.chargeThresholdActive ? "Charge limit" : (root.discharging ? "Time left" : "Time to full")
|
||||
label: root.chargeThresholdActive ? I18n.tr("Charge limit") : (root.discharging ? I18n.tr("Time left") : I18n.tr("Time to full"))
|
||||
value: root.chargeThresholdActive ? (root.batteryInfo.threshold || "-") : (root.batteryFlowIdle ? "-" : (root.batteryInfo.time || "—"))
|
||||
}
|
||||
InfoPair {
|
||||
label: root.chargeThresholdActive ? "Battery state" : (root.discharging ? "Discharging" : "Charging")
|
||||
value: root.chargeThresholdActive ? "Holding" : (root.batteryFull ? "-" : (root.batteryInfo.rate || ""))
|
||||
label: root.chargeThresholdActive ? I18n.tr("Battery state") : (root.discharging ? I18n.tr("Discharging") : I18n.tr("Charging"))
|
||||
value: root.chargeThresholdActive ? I18n.tr("Holding") : (root.batteryFull ? "-" : (root.batteryInfo.rate || ""))
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -461,7 +461,7 @@ Panel {
|
||||
spacing: Style.space(10)
|
||||
|
||||
PanelSectionHeader {
|
||||
text: "POWER PROFILE"
|
||||
text: I18n.tr("POWER PROFILE")
|
||||
foreground: root.bar.foreground
|
||||
fontFamily: root.bar.fontFamily
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ Item {
|
||||
}
|
||||
|
||||
if (!root.expectedStop && exitCode !== 0) {
|
||||
root.error = root.stderrText || "Speed test failed"
|
||||
root.error = root.stderrText || I18n.tr("Speed test failed")
|
||||
root.phase = ""
|
||||
root.running = false
|
||||
return
|
||||
@@ -177,7 +177,7 @@ Item {
|
||||
onStreamFinished: {
|
||||
var fields = String(text || "").trim().split("\t")
|
||||
if (fields[0] === "wifi") root.connectionName = fields[1] || "Wi-Fi"
|
||||
else if (fields[0] === "ethernet") root.connectionName = "Ethernet"
|
||||
else if (fields[0] === "ethernet") root.connectionName = I18n.tr("Ethernet")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -186,9 +186,9 @@ Item {
|
||||
fontFamily: Style.font.family
|
||||
layerNamespace: "omarchy-network-speedtest"
|
||||
title: root.connectionName
|
||||
leftLabel: "DOWNLOAD"
|
||||
rightLabel: "UPLOAD"
|
||||
runAgainTooltip: "Measure again via fast.com"
|
||||
leftLabel: I18n.tr("DOWNLOAD")
|
||||
rightLabel: I18n.tr("UPLOAD")
|
||||
runAgainTooltip: I18n.tr("Measure again via fast.com")
|
||||
running: root.running
|
||||
leftValue: root.downloadValue
|
||||
rightValue: root.uploadValue
|
||||
|
||||
@@ -24,16 +24,16 @@ Panel {
|
||||
property string mullvadQuery: ""
|
||||
property int phraseIndex: 0
|
||||
readonly property var activePhrases: [
|
||||
"Encrypting connections",
|
||||
"Sending secrets",
|
||||
"Guarding wires",
|
||||
"Braiding packets",
|
||||
"Polishing tunnels",
|
||||
"Hiding routes",
|
||||
"Sealing ports",
|
||||
"Sorting tailnets",
|
||||
"Shuffling keys",
|
||||
"Watching machines"
|
||||
I18n.tr("Encrypting connections"),
|
||||
I18n.tr("Sending secrets"),
|
||||
I18n.tr("Guarding wires"),
|
||||
I18n.tr("Braiding packets"),
|
||||
I18n.tr("Polishing tunnels"),
|
||||
I18n.tr("Hiding routes"),
|
||||
I18n.tr("Sealing ports"),
|
||||
I18n.tr("Sorting tailnets"),
|
||||
I18n.tr("Shuffling keys"),
|
||||
I18n.tr("Watching machines")
|
||||
]
|
||||
readonly property string heroPhraseText: activePhrases[phraseIndex % activePhrases.length]
|
||||
|
||||
@@ -52,7 +52,7 @@ Panel {
|
||||
// "header" stays navigable, but an absent CLI leaves nothing to highlight.
|
||||
readonly property bool headerHasCursor: cursorActive && focusSection === "header" && tailscale.installed
|
||||
readonly property color iconColor: tailscale.active ? foreground : dim
|
||||
readonly property string toggleHint: tailscale.active ? "Turn Tailscale off" : (tailscale.needsLogin ? "Authorize this device" : "Turn Tailscale on")
|
||||
readonly property string toggleHint: tailscale.active ? I18n.tr("Turn Tailscale off") : (tailscale.needsLogin ? I18n.tr("Authorize this device") : I18n.tr("Turn Tailscale on"))
|
||||
readonly property color barIconColor: tailscale.active ? barForeground : Qt.darker(barForeground, 1.55)
|
||||
readonly property color hoverFill: bar ? Style.hoverFillFor(bar.foreground, Color.accent) : "transparent"
|
||||
readonly property color selectedFill: bar ? Style.selectedFillFor(bar.foreground, Color.accent) : "transparent"
|
||||
@@ -76,7 +76,7 @@ Panel {
|
||||
var nodes = []
|
||||
for (var i = 0; i < tailscale.tailnetExitNodes.length; i++) nodes.push(tailscale.tailnetExitNodes[i])
|
||||
for (var j = 0; j < recentMullvadExitNodes.length; j++) nodes.push(recentMullvadExitNodes[j])
|
||||
if (tailscale.mullvadRegions.length > 0) nodes.push({ id: "mullvad:add", AddMullvad: true, DisplayName: "Choose Mullvad region" })
|
||||
if (tailscale.mullvadRegions.length > 0) nodes.push({ id: "mullvad:add", AddMullvad: true, DisplayName: I18n.tr("Choose Mullvad region") })
|
||||
return nodes
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ Panel {
|
||||
}
|
||||
|
||||
function mullvadRegionTitle(peer) {
|
||||
if (!peer) return "Unknown"
|
||||
if (!peer) return I18n.tr("Unknown")
|
||||
var city = String(peer.City || "").trim()
|
||||
var country = String(peer.Country || "").trim()
|
||||
if (city === "" || city === "Any") return country || String(peer.DisplayName || "Unknown")
|
||||
@@ -458,7 +458,7 @@ Panel {
|
||||
id: hero
|
||||
width: parent.width
|
||||
title: tailscale.installed ? (tailscale.selfName || "Tailscale") : "Tailscale"
|
||||
meta: tailscale.active ? root.heroPhraseText : "Tailscale is disconnected"
|
||||
meta: tailscale.active ? root.heroPhraseText : I18n.tr("Tailscale is disconnected")
|
||||
foreground: root.foreground
|
||||
fontFamily: root.fontFamily
|
||||
iconOpacity: tailscale.active ? 1.0 : 0.5
|
||||
@@ -501,7 +501,7 @@ Panel {
|
||||
textFormat: Text.PlainText
|
||||
visible: tailscale.actionStatus !== "" || tailscale.lastError !== ""
|
||||
width: parent.width
|
||||
text: tailscale.actionStatus !== "" ? tailscale.actionStatus : tailscale.lastError
|
||||
text: I18n.tr(tailscale.actionStatus !== "" ? tailscale.actionStatus : tailscale.lastError)
|
||||
color: tailscale.lastError !== "" && tailscale.actionStatus === "" ? root.urgent : root.dim
|
||||
font.family: root.fontFamily
|
||||
font.pixelSize: Style.font.bodySmall
|
||||
@@ -520,7 +520,7 @@ Panel {
|
||||
anchors.right: parent.right
|
||||
anchors.verticalCenter: parent.verticalCenter
|
||||
anchors.margins: Style.space(12)
|
||||
text: "Tailscale CLI is not installed or not on PATH."
|
||||
text: I18n.tr("Tailscale CLI is not installed or not on PATH.")
|
||||
color: root.dim
|
||||
font.family: root.fontFamily
|
||||
font.pixelSize: Style.font.body
|
||||
@@ -539,7 +539,7 @@ Panel {
|
||||
spacing: Style.space(10)
|
||||
|
||||
PanelSectionHeader {
|
||||
text: "CONNECTIONS"
|
||||
text: I18n.tr("CONNECTIONS")
|
||||
foreground: root.foreground
|
||||
fontFamily: root.fontFamily
|
||||
}
|
||||
@@ -572,7 +572,7 @@ Panel {
|
||||
spacing: Style.space(10)
|
||||
|
||||
PanelSectionHeader {
|
||||
text: "EXIT NODES"
|
||||
text: I18n.tr("EXIT NODES")
|
||||
foreground: root.foreground
|
||||
fontFamily: root.fontFamily
|
||||
}
|
||||
@@ -602,7 +602,7 @@ Panel {
|
||||
id: mullvadSearch
|
||||
width: parent.width
|
||||
foreground: root.foreground
|
||||
placeholderText: "Search regions"
|
||||
placeholderText: I18n.tr("Search regions")
|
||||
text: root.mullvadQuery
|
||||
onTextChanged: {
|
||||
root.mullvadQuery = text
|
||||
@@ -638,7 +638,7 @@ Panel {
|
||||
Text {
|
||||
visible: root.filteredMullvadRegions.length === 0
|
||||
width: parent.width
|
||||
text: "No Mullvad regions found."
|
||||
text: I18n.tr("No Mullvad regions found.")
|
||||
color: root.dim
|
||||
font.family: root.fontFamily
|
||||
font.pixelSize: Style.font.bodySmall
|
||||
@@ -676,7 +676,7 @@ Panel {
|
||||
spacing: Style.space(10)
|
||||
|
||||
PanelSectionHeader {
|
||||
text: "MACHINES"
|
||||
text: I18n.tr("MACHINES")
|
||||
foreground: root.foreground
|
||||
fontFamily: root.fontFamily
|
||||
}
|
||||
@@ -684,7 +684,7 @@ Panel {
|
||||
Text {
|
||||
visible: tailscale.installed && tailscale.active && tailscale.peers.length === 0
|
||||
width: parent.width
|
||||
text: "No machines found on this tailnet."
|
||||
text: I18n.tr("No machines found on this tailnet.")
|
||||
color: root.dim
|
||||
font.family: root.fontFamily
|
||||
font.pixelSize: Style.font.body
|
||||
@@ -777,7 +777,7 @@ Panel {
|
||||
|
||||
Text {
|
||||
Layout.fillWidth: true
|
||||
text: "Authorize Tailscale operator"
|
||||
text: I18n.tr("Authorize Tailscale operator")
|
||||
color: root.foreground
|
||||
font.family: root.fontFamily
|
||||
font.pixelSize: Style.font.body
|
||||
@@ -786,7 +786,7 @@ Panel {
|
||||
|
||||
Text {
|
||||
Layout.fillWidth: true
|
||||
text: "Allow this user to operate this Tailscale profile"
|
||||
text: I18n.tr("Allow this user to operate this Tailscale profile")
|
||||
color: root.dim
|
||||
font.family: root.fontFamily
|
||||
font.pixelSize: Style.font.caption
|
||||
@@ -803,7 +803,7 @@ Panel {
|
||||
property int rowIndex: 0
|
||||
readonly property bool selectedAccount: account && account.selected === true
|
||||
readonly property bool switchingAccount: account && tailscale.switchingAccountId === String(account.id || "")
|
||||
readonly property string accountText: account ? tailscale.accountLabel(account) : "Account"
|
||||
readonly property string accountText: account ? tailscale.accountLabel(account) : I18n.tr("Account")
|
||||
|
||||
hasCursor: root.cursorActive && root.focusSection === "accounts" && root.accountIndex === rowIndex
|
||||
current: selectedAccount
|
||||
@@ -867,7 +867,7 @@ Panel {
|
||||
id: peerRow
|
||||
property var peer: null
|
||||
property int rowIndex: 0
|
||||
readonly property string peerName: peer ? String(peer.DisplayName || peer.HostName || "Unknown") : "Unknown"
|
||||
readonly property string peerName: peer ? String(peer.DisplayName || peer.HostName || I18n.tr("Unknown")) : I18n.tr("Unknown")
|
||||
readonly property string peerIp: peer && peer.TailscaleIPs && peer.TailscaleIPs.length > 0 ? String(peer.TailscaleIPs[0]) : ""
|
||||
readonly property string peerIpv6: {
|
||||
if (!peer || !peer.TailscaleIPv6 || peer.TailscaleIPv6.length === 0) return ""
|
||||
@@ -978,7 +978,7 @@ Panel {
|
||||
id: sendButton
|
||||
visible: tailscale.canSendFiles(peerRow.peer)
|
||||
iconText: ""
|
||||
tooltipText: "Send files"
|
||||
tooltipText: I18n.tr("Send files")
|
||||
foreground: root.foreground
|
||||
fontFamily: root.fontFamily
|
||||
Layout.alignment: Qt.AlignVCenter
|
||||
@@ -1118,8 +1118,8 @@ Panel {
|
||||
readonly property bool addMullvad: peer && peer.AddMullvad === true
|
||||
readonly property bool activeExitNode: peer && peer.ExitNode === true
|
||||
readonly property bool settingExitNode: peer && tailscale.settingExitNodeId === String(peer.id || "")
|
||||
readonly property string peerName: peer ? String(peer.DisplayName || peer.HostName || "Unknown") : "Unknown"
|
||||
readonly property string actionTooltip: addMullvad ? "" : (activeExitNode ? "Disconnect" : "Connect")
|
||||
readonly property string peerName: peer ? String(peer.DisplayName || peer.HostName || I18n.tr("Unknown")) : I18n.tr("Unknown")
|
||||
readonly property string actionTooltip: addMullvad ? "" : (activeExitNode ? I18n.tr("Disconnect") : I18n.tr("Connect"))
|
||||
|
||||
hasCursor: root.cursorActive && root.focusSection === "exitNodes" && root.exitNodeIndex === rowIndex
|
||||
current: activeExitNode || settingExitNode || (addMullvad && root.mullvadPickerOpen)
|
||||
@@ -1199,7 +1199,7 @@ Panel {
|
||||
readonly property bool activeExitNode: peer && peer.ExitNode === true
|
||||
readonly property bool settingExitNode: peer && tailscale.settingExitNodeId === String(peer.id || "")
|
||||
readonly property bool selectedRegion: root.mullvadPickerOpen && root.mullvadRegionIndex === rowIndex
|
||||
readonly property string actionTooltip: activeExitNode ? "Disconnect" : "Connect"
|
||||
readonly property string actionTooltip: activeExitNode ? I18n.tr("Disconnect") : I18n.tr("Connect")
|
||||
|
||||
foreground: root.foreground
|
||||
fill: root.hoverFill
|
||||
|
||||
@@ -616,7 +616,7 @@ Panel {
|
||||
id: locationField
|
||||
width: Style.space(190)
|
||||
enabled: !root.savingLocation
|
||||
placeholderText: "Search city"
|
||||
placeholderText: I18n.tr("Search city")
|
||||
foreground: root.bar.foreground
|
||||
font.family: root.bar.fontFamily
|
||||
|
||||
@@ -683,7 +683,7 @@ Panel {
|
||||
Column {
|
||||
spacing: Style.space(5)
|
||||
Text {
|
||||
text: "FEELS"
|
||||
text: I18n.tr("FEELS")
|
||||
color: Qt.darker(root.bar.foreground, 1.5)
|
||||
font.family: root.bar.fontFamily
|
||||
font.pixelSize: Style.font.bodySmall
|
||||
@@ -701,7 +701,7 @@ Panel {
|
||||
Column {
|
||||
spacing: Style.space(5)
|
||||
Text {
|
||||
text: "WIND"
|
||||
text: I18n.tr("WIND")
|
||||
color: Qt.darker(root.bar.foreground, 1.5)
|
||||
font.family: root.bar.fontFamily
|
||||
font.pixelSize: Style.font.bodySmall
|
||||
@@ -719,7 +719,7 @@ Panel {
|
||||
Column {
|
||||
spacing: Style.space(5)
|
||||
Text {
|
||||
text: "HUMID"
|
||||
text: I18n.tr("HUMID")
|
||||
color: Qt.darker(root.bar.foreground, 1.5)
|
||||
font.family: root.bar.fontFamily
|
||||
font.pixelSize: Style.font.bodySmall
|
||||
@@ -792,7 +792,7 @@ Panel {
|
||||
|
||||
Text {
|
||||
visible: !root.current
|
||||
text: "Fetching forecast…"
|
||||
text: I18n.tr("Fetching forecast…")
|
||||
color: Qt.darker(root.bar.foreground, 1.5)
|
||||
font.family: root.bar.fontFamily
|
||||
font.pixelSize: Style.font.bodySmall
|
||||
|
||||
@@ -183,7 +183,7 @@ Item {
|
||||
if (exitCode !== 0 || root.qrSize === 0) {
|
||||
root.qrSize = 0
|
||||
root.qrRows = []
|
||||
if (root.error === "") root.error = "Could not generate the Wi-Fi QR code"
|
||||
if (root.error === "") root.error = I18n.tr("Could not generate the Wi-Fi QR code")
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -206,7 +206,7 @@ Item {
|
||||
if (root.pwExpectedStop) return
|
||||
if (!root.opened) return
|
||||
if (exitCode === 0 && root.password !== "") root.passwordVisible = true
|
||||
else root.passwordError = "Could not read the Wi-Fi password"
|
||||
else root.passwordError = I18n.tr("Could not read the Wi-Fi password")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -305,7 +305,7 @@ Item {
|
||||
|
||||
Text {
|
||||
visible: root.loading
|
||||
text: "Generating QR code…"
|
||||
text: I18n.tr("Generating QR code…")
|
||||
color: root.onScrimDim
|
||||
font.family: root.fontFamily
|
||||
font.pixelSize: Style.font.bodySmall
|
||||
@@ -328,7 +328,7 @@ Item {
|
||||
|
||||
Text {
|
||||
visible: root.showingQr
|
||||
text: "Scan to join this network"
|
||||
text: I18n.tr("Scan to join this network")
|
||||
color: root.onScrimDim
|
||||
font.family: root.fontFamily
|
||||
font.pixelSize: Style.font.bodySmall
|
||||
@@ -341,7 +341,7 @@ Item {
|
||||
visible: root.showingQr && root.secured
|
||||
text: root.passwordError !== "" ? root.passwordError
|
||||
: root.passwordVisible ? root.password
|
||||
: "Show password"
|
||||
: I18n.tr("Show password")
|
||||
color: root.passwordError !== "" ? root.onScrimUrgent : root.onScrim
|
||||
opacity: root.passwordVisible || root.passwordError !== "" ? 1 : 0.6
|
||||
font.family: root.fontFamily
|
||||
|
||||
Reference in new issue
Block a user