Translate finished messages by template and the world clock, Dropbox and scoped titles at display

This commit is contained in:
ZacharyZhang-NY committed 2026-10-06 22:07:19 -04:00
1 parent 2b2302a279
commit f63ecb6697
13 files changed
+139 -28

No files matched your search

+4
View File
@@ -13,4 +13,8 @@ QtObject {
function trMatch(text, templates) {
return Tr.trMatch(text, templates)
}
function trMessage(text) {
return Tr.trMessage(text)
}
}
+78 -1
View File
@@ -97,6 +97,15 @@ var table = {
"Limits paused": "额度已暂停",
"Sign-in expired": "登录已过期",
"Waiting for auth": "等待认证",
"Anthropic's usage endpoint is rate limiting checks right now (retry after %1s). Local Claude Code stats are still shown.": "Anthropic 用量接口正在限制查询频率(%1 秒后重试)。仍显示本地 Claude Code 统计。",
"Anthropic's usage endpoint returned status %1. Local Claude Code stats are still shown.": "Anthropic 用量接口返回状态 %1。仍显示本地 Claude Code 统计。",
"Claude Code's access token has lapsed — showing the last known limits. Start Claude Code to refresh it; signing in again is not needed.": "Claude Code 的访问令牌已过期,显示上次的额度。启动 Claude Code 即可刷新,不需要重新登录。",
"Claude Code's access token has lapsed. Start Claude Code to refresh it; signing in again is not needed.": "Claude Code 的访问令牌已过期。启动 Claude Code 即可刷新,不需要重新登录。",
"Claude Code's saved sign-in expired — showing the last known limits. Start Claude Code, or run `claude auth login`, to refresh it.": "Claude Code 保存的登录已过期,显示上次的额度。启动 Claude Code 或运行 `claude auth login` 刷新。",
"Claude Code's saved sign-in expired. Start Claude Code, or run `claude auth login`, to refresh it.": "Claude Code 保存的登录已过期。启动 Claude Code 或运行 `claude auth login` 刷新。",
"Couldn't reach Anthropic's usage endpoint. Retrying shortly. Local Claude Code stats are still shown.": "无法连接 Anthropic 用量接口,稍后重试。仍显示本地 Claude Code 统计。",
"Anthropic's usage endpoint returned no limits. Local Claude Code stats are still shown.": "Anthropic 用量接口没有返回额度。仍显示本地 Claude Code 统计。",
"Anthropic's usage endpoint is rate limiting checks right now. Local Claude Code stats are still shown.": "Anthropic 用量接口正在限制查询频率。仍显示本地 Claude Code 统计。",
// Network panel
"Wiring bits": "接线中",
"Handling packets": "处理数据包",
@@ -317,6 +326,21 @@ var table = {
"Start the authentication flow": "开始认证",
"Install Dropbox from the service menu": "从服务菜单安装 Dropbox",
"Untitled": "未命名",
"%1 of %2": "%1 / %2",
"Just now": "刚刚",
"Unknown time": "时间未知",
"%1mo ago": "%1个月前",
"%1m ago": "%1分钟前",
"%1h ago": "%1小时前",
"%1d ago": "%1天前",
"%1y ago": "%1年前",
"Starting Dropbox login…": "正在开始 Dropbox 登录…",
"Opened Dropbox login": "已打开 Dropbox 登录",
"Failed to read Dropbox status": "无法读取 Dropbox 状态",
"Could not read Dropbox status": "无法读取 Dropbox 状态",
"Dropbox login failed": "Dropbox 登录失败",
"Dropbox command failed": "Dropbox 命令失败",
"Failed to parse Dropbox status": "无法解析 Dropbox 状态",
// Weather panel
"Search city": "搜索城市",
"FEELS": "体感",
@@ -451,6 +475,23 @@ var table = {
"Voxtype Dictation Ready": "Voxtype 语音输入就绪",
"Web app removed": "网页应用已移除",
"Windows VM": "Windows 虚拟机",
"Battery is down to %1%": "电量降到 %1%",
"Could not send to %1": "无法发送给 %1",
"Couldn't add the %1 account": "无法添加 %1 账户",
"Mirroring enabled (%1)": "已开启镜像(%1)",
"New %1 sessions now use %2": "新的 %1 会话现在使用 %2",
"No plugin to %1": "没有插件可以%1",
"No saved width found for %1 on workspace %2": "工作区 %2 没有为 %1 保存的宽度",
"Saved width for %1 on workspace %2": "已为工作区 %2 的 %1 保存宽度",
"Screen recording directory does not exist: %1": "录屏目录不存在:%1",
"Sent to %1": "已发送给 %1",
"Timezone is now set to %1": "时区已设为 %1",
"Transcoded to %1 %2": "已转码为 %1 %2",
"Workspace layout set to %1": "工作区布局已设为 %1",
"%1 is now the default browser": "%1 现在是默认浏览器",
"%1 is now the default editor": "%1 现在是默认编辑器",
"%1 is now the default terminal": "%1 现在是默认终端",
"%1 installed": "%1 已安装",
// Clock
"Right-click to toggle format": "右键切换格式",
"Back to today": "回到今天",
@@ -483,7 +524,43 @@ var table = {
"Jump to a city": "跳到一个城市",
"Add a city": "添加城市",
"Loading zones…": "正在加载时区…",
"Tomorrow": "明天",
"Yesterday": "昨天",
" in %1": "(%1)",
"Loading cities…": "正在加载城市…",
// Media
"Pause": "暂停",
"Play": "播放"
"Play": "播放",
"Next": "下一首",
"Previous": "上一首"
}
// Parameterized messages that arrive finished; trMessage matches them, so each needs a table entry above.
var templates = [
"Battery is down to %1%",
"Could not send to %1",
"Couldn't add the %1 account",
"Mirroring enabled (%1)",
"New %1 sessions now use %2",
"No plugin to %1",
"No saved width found for %1 on workspace %2",
"Saved width for %1 on workspace %2",
"Screen recording directory does not exist: %1",
"Sent to %1",
"Timezone is now set to %1",
"Transcoded to %1 %2",
"Workspace layout set to %1",
"%1 is now the default browser",
"%1 is now the default editor",
"%1 is now the default terminal",
"%1 installed",
"Anthropic's usage endpoint is rate limiting checks right now (retry after %1s). Local Claude Code stats are still shown.",
"Anthropic's usage endpoint returned status %1. Local Claude Code stats are still shown.",
"Installing the %1 CLI…",
"Sign in to %1 again in the browser window that opens.",
"Sign in to %1 in the browser window that opens.",
"Signed in to %1 again.",
"Signed in to %1.",
"The %1 sign-in didn't finish.",
"Added %1."
]
+5
View File
@@ -22,3 +22,8 @@ function trMatch(text, templates) {
}
return tr(text)
}
// Finished messages from other programs (notifications, collectors) that carry a name or number.
function trMessage(text) {
return trMatch(text, Zh.templates)
}
+13 -13
View File
@@ -455,11 +455,11 @@ Panel {
return text
}
// omarchy-agent-account-add reports progress in English around the agent's name.
readonly property var addMessageTemplates: [
"Installing the %1 CLI…", "Sign in to %1 again in the browser window that opens.", "Sign in to %1 in the browser window that opens.",
"Signed in to %1 again.", "Signed in to %1.", "The %1 sign-in didn't finish.", "Added %1."
]
// A model-scoped title ("Opus Monthly") keeps the model and translates the window.
function windowLabel(title) {
var match = String(title || "").match(/^(.*\S)\s+(Monthly|Weekly|Session|Limit)$/)
return match ? match[1] + " " + I18n.tr(match[2]) : I18n.tr(String(title || ""))
}
function planLabel(p) {
var tier = String(p && p.tierLabel || "")
@@ -1173,7 +1173,7 @@ Panel {
Text {
width: parent.width
textFormat: Text.PlainText
text: I18n.trMatch(root.addStatus, root.addMessageTemplates)
text: I18n.trMessage(root.addStatus)
color: root.foreground
font.family: root.fontFamily
font.pixelSize: Style.font.bodySmall
@@ -1243,7 +1243,7 @@ Panel {
visible: root.addStage === "done" || root.addStage === "error"
width: parent.width
textFormat: Text.PlainText
text: I18n.trMatch(root.addResult, root.addMessageTemplates)
text: I18n.trMessage(root.addResult)
color: root.addStage === "error" ? root.urgent : root.foreground
font.family: root.fontFamily
font.pixelSize: Style.font.bodySmall
@@ -1350,7 +1350,7 @@ Panel {
width: parent.width
textFormat: Text.PlainText
// Shown for the status, so a record with no help to offer says the status rather than nothing.
text: section.provider ? I18n.tr(String(section.provider.authHelpText || section.provider.usageStatusText || "")) : ""
text: section.provider ? I18n.trMessage(String(section.provider.authHelpText || section.provider.usageStatusText || "")) : ""
color: root.urgent
font.family: root.fontFamily
font.pixelSize: Style.font.caption
@@ -1879,7 +1879,7 @@ Panel {
PanelToolTip {
visible: unavailableHover.hovered && unavailable.visible
text: unavailable.record ? I18n.tr(String(unavailable.record.authHelpText || "Usage has not been updated yet.")) : ""
text: unavailable.record ? I18n.trMessage(String(unavailable.record.authHelpText || "Usage has not been updated yet.")) : ""
}
}
@@ -1904,7 +1904,7 @@ Panel {
text: {
var lines = []
if (compact.window) {
lines.push(I18n.tr("%1: %2% used", I18n.tr(compact.window.title), Math.round(compact.window.percent * 100))
lines.push(I18n.tr("%1: %2% used", root.windowLabel(compact.window.title), Math.round(compact.window.percent * 100))
+ (compact.resetMs > 0 ? " · " + I18n.tr("resets in %1", root.formatDuration(compact.resetMs)) : ""))
}
if (compact.stale)
@@ -1912,8 +1912,8 @@ Panel {
? I18n.tr("Last updated %1 ago", root.formatDuration(root.nowMs - compact.fetchedAt))
: compact.fetchedAt > 0 ? I18n.tr("Last updated less than a minute ago") : I18n.tr("Last updated time unavailable"))
for (var i = 0; i < compact.scoped.length; i++)
lines.push(I18n.tr("%1: %2% of its %3 allowance", I18n.tr(compact.scoped[i].title), Math.round(compact.scoped[i].percent * 100),
I18n.tr(String(compact.window ? compact.window.title : "")).toLowerCase()))
lines.push(I18n.tr("%1: %2% of its %3 allowance", root.windowLabel(compact.scoped[i].title), Math.round(compact.scoped[i].percent * 100),
root.windowLabel(compact.window ? compact.window.title : "").toLowerCase()))
return lines.join("\n")
}
}
@@ -1923,7 +1923,7 @@ Panel {
textFormat: Text.PlainText
width: parent.width * 0.3
anchors.verticalCenter: parent.verticalCenter
text: compact.window ? I18n.tr(compact.window.title) : ""
text: compact.window ? root.windowLabel(compact.window.title) : ""
color: root.foreground
font.family: root.fontFamily
font.pixelSize: Style.font.bodySmall
@@ -44,7 +44,7 @@ BorderSurface {
readonly property bool singleLineToast: sanitizedBody.length === 0
readonly property bool collapseRedundantIcon: singleLineToast && !hasGlyph && summaryStartsWithGlyph
readonly property string sanitizedBody: sanitizeBody(body)
readonly property string styledBody: NotificationLogic.styledBody(I18n.tr(body), app, appIcon)
readonly property string styledBody: NotificationLogic.styledBody(I18n.trMessage(body), app, appIcon)
readonly property color dimColor: Qt.darker(Color.notifications.text, 1.4)
readonly property color bodyColor: Qt.darker(Color.notifications.text, 1.15)
@@ -168,7 +168,7 @@ BorderSurface {
textFormat: Text.PlainText
Layout.fillWidth: true
visible: root.summary.length > 0
text: I18n.tr(root.summary)
text: I18n.trMessage(root.summary)
font.family: "Liberation Sans"
color: Color.notifications.text
font.pixelSize: Style.font.title
+2 -2
View File
@@ -90,7 +90,7 @@ Item {
font.family: Style.font.family
font.bold: true
font.pixelSize: Style.font.title
text: I18n.tr(root.message)
text: I18n.trMessage(root.message)
}
TextMetrics {
@@ -190,7 +190,7 @@ Item {
// a hole in the padding; the slack lands in the gap after the bar.
horizontalAlignment: root.hasProgress ? Text.AlignRight : Text.AlignLeft
anchors.verticalCenter: parent.verticalCenter
text: I18n.tr(root.message)
text: I18n.trMessage(root.message)
font: messageMetrics.font
color: Color.popups.text
elide: Text.ElideRight
+10 -3
View File
@@ -37,6 +37,13 @@ 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
// Model.fileMeta reads "5m ago · Folder"; the age is translated, the folder name kept.
function fileMetaText(file) {
var parts = Model.fileMeta(file).split(" · ")
parts[0] = I18n.trMatch(parts[0], ["Just now", "Unknown time", "%1mo ago", "%1m ago", "%1h ago", "%1d ago", "%1y ago"])
return parts.join(" · ")
}
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 —
@@ -284,7 +291,7 @@ Panel {
textFormat: Text.PlainText
visible: dropbox.actionStatus !== "" || dropbox.lastError !== ""
width: parent.width
text: dropbox.actionStatus !== "" ? dropbox.actionStatus : dropbox.lastError
text: I18n.trMessage(dropbox.actionStatus !== "" ? dropbox.actionStatus : dropbox.lastError)
color: dropbox.lastError !== "" && dropbox.actionStatus === "" ? root.urgent : root.dim
font.family: root.fontFamily
font.pixelSize: Style.font.bodySmall
@@ -304,7 +311,7 @@ Panel {
Column {
width: parent.width
spacing: Style.spacing.labelGap
InfoPair { label: I18n.tr("Stored"); value: Model.usageText(dropbox.usedBytes, dropbox.quotaBytes, dropbox.quotaKnown) }
InfoPair { label: I18n.tr("Stored"); value: I18n.trMatch(Model.usageText(dropbox.usedBytes, dropbox.quotaBytes, dropbox.quotaKnown), ["%1 of %2"]) }
}
}
@@ -508,7 +515,7 @@ Panel {
Text {
textFormat: Text.PlainText
Layout.fillWidth: true
text: Model.fileMeta(fileRow.file)
text: root.fileMetaText(fileRow.file)
color: root.dim
font.family: root.fontFamily
font.pixelSize: Style.font.caption
+12 -2
View File
@@ -11,6 +11,16 @@ import "Greetings.js" as Greet
Rectangle {
id: row
// Model.formatDate reads "Tue Oct 6"; a Chinese session reads 10月6日 周二.
function dateText(date) {
var match = String(date).match(/^(\w{3}) (\w{3}) (\d+)$/)
if (!I18n.chinese || !match) return date
var month = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"].indexOf(match[2]) + 1
var weekday = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"].indexOf(match[1])
if (month < 1 || weekday < 0) return date
return month + "月" + match[3] + "日 " + ["周日", "周一", "周二", "周三", "周四", "周五", "周六"][weekday]
}
required property var modelData
required property int index
// The owning Panel: the row reads its clock, facts and drag state.
@@ -222,7 +232,7 @@ Rectangle {
Behavior on opacity { NumberAnimation { duration: Style.duration(110) } }
Caption {
text: row.ready ? row.rowData.date : "\u2026"
text: row.ready ? row.dateText(row.rowData.date) : "\u2026"
color: row.ready && row.rowData.dayLabel !== "" ? row.dim : row.fainter
}
@@ -233,7 +243,7 @@ Rectangle {
}
Caption {
text: row.ready ? row.rowData.dayLabel : ""
text: row.ready ? I18n.tr(row.rowData.dayLabel) : ""
visible: text !== ""
}
}
+1 -1
View File
@@ -585,7 +585,7 @@ Item {
inlineResults: false
loading: root.jumpOptions.length === 0
buttonText: I18n.tr("Jump to a city")
loadingText: "Loading cities\u2026"
loadingText: I18n.tr("Loading cities…")
offsetLabel: function(zoneId) { return Model.utcOffsetLabel(root.offsets[zoneId]) }
foreground: root.foreground
dim: root.dim
+1 -1
View File
@@ -335,7 +335,7 @@ Panel {
// No full stop: a period hanging off the arc reads as a speck.
readonly property string hereLine: I18n.tr("It's %1 here", localTime)
+ (homeCity !== "" ? " in " + homeCity : "")
+ (homeCity !== "" ? I18n.tr(" in %1", homeCity) : "")
+ (scrubLabel !== "" ? " " + scrubLabel : "")
// A capital's line box has empty space above it; the row's top pad drops by it.