feat(i18n): wrap all user-facing strings in TailscaleWidget.qml with I18n.tr (strategy A)

- header, details, exit node prefix/none, invalid hostname, copied (with .arg), all formatError toasts
- Glyph literals ("×", "↗", "—") left as-is (decorative, not linguistic)
- "tailscalectl" toast titles kept as technical IDs
- All call sites now go through I18n for future translation
- Tests unaffected (still green)

Written by AI agent working for @jtmorris. Model: grok-build-0.1.
This commit is contained in:
Vybe (Coding Agent) 2026-05-24 20:57:49 +00:00
parent 7942bc3471
commit cb280d1e4e

View file

@ -35,7 +35,7 @@ PluginComponent {
if (code !== 0) { if (code !== 0) {
var action = root.isConnected ? "disconnect" : "connect"; var action = root.isConnected ? "disconnect" : "connect";
var detail = toggleProcess.stderr.text.trim(); var detail = toggleProcess.stderr.text.trim();
ToastService.showError("tailscalectl", TailscaleLib.formatError(action, detail)); ToastService.showError("tailscalectl", I18n.tr(TailscaleLib.formatError(action, detail)));
} }
root.refreshStatus(); root.refreshStatus();
} }
@ -48,7 +48,7 @@ PluginComponent {
onExited: (code, status) => { onExited: (code, status) => {
if (code === 0) { if (code === 0) {
ToastService.showInfo(TailscaleLib.getStrings().copied(root._copyText)) ToastService.showInfo(I18n.tr(TailscaleLib.getStrings().copied).arg(root._copyText))
} else { } else {
root._copyIndex += 1 root._copyIndex += 1
root._runNextCopy() root._runNextCopy()
@ -66,7 +66,7 @@ PluginComponent {
onExited: (code, status) => { onExited: (code, status) => {
if (code !== 0) { if (code !== 0) {
var detail = exitNodeProcess.stderr.text.trim(); var detail = exitNodeProcess.stderr.text.trim();
ToastService.showError("tailscalectl", TailscaleLib.formatError("set", detail)); ToastService.showError("tailscalectl", I18n.tr(TailscaleLib.formatError("set", detail)));
} }
root.refreshStatus(); root.refreshStatus();
} }
@ -91,7 +91,7 @@ PluginComponent {
root.tailscaleIP = "" root.tailscaleIP = ""
root.currentExitNode = "" root.currentExitNode = ""
root.peers = [] root.peers = []
ToastService.showError("tailscalectl", TailscaleLib.formatError("status")) ToastService.showError("tailscalectl", I18n.tr(TailscaleLib.formatError("status")))
} }
const cmd = TailscaleLib.commandForPendingAction(statusCheck._pendingAction, root.isConnected); const cmd = TailscaleLib.commandForPendingAction(statusCheck._pendingAction, root.isConnected);
@ -115,7 +115,7 @@ PluginComponent {
function setExitNode(hostname) { function setExitNode(hostname) {
const cmd = TailscaleLib.makeExitNodeCommand(hostname) const cmd = TailscaleLib.makeExitNodeCommand(hostname)
if (!cmd) { if (!cmd) {
ToastService.showError("tailscalectl", TailscaleLib.getStrings().invalidExitNodeHostname) ToastService.showError("tailscalectl", I18n.tr(TailscaleLib.getStrings().invalidExitNodeHostname))
return return
} }
exitNodeProcess.command = cmd exitNodeProcess.command = cmd
@ -131,7 +131,7 @@ PluginComponent {
function _runNextCopy() { function _runNextCopy() {
const cmds = TailscaleLib.getClipboardCommands(root._copyText) const cmds = TailscaleLib.getClipboardCommands(root._copyText)
if (root._copyIndex >= cmds.length) { if (root._copyIndex >= cmds.length) {
ToastService.showError("tailscalectl", TailscaleLib.formatError("clipboard")) ToastService.showError("tailscalectl", I18n.tr(TailscaleLib.formatError("clipboard")))
return return
} }
copyProcess.command = cmds[root._copyIndex] copyProcess.command = cmds[root._copyIndex]
@ -140,8 +140,8 @@ PluginComponent {
popoutContent: Component { popoutContent: Component {
PopoutComponent { PopoutComponent {
headerText: "Tailscale" headerText: I18n.tr(TailscaleLib.getStrings().header)
detailsText: root.isConnected ? TailscaleLib.getStrings().connected : TailscaleLib.getStrings().disconnected detailsText: root.isConnected ? I18n.tr(TailscaleLib.getStrings().connected) : I18n.tr(TailscaleLib.getStrings().disconnected)
showCloseButton: true showCloseButton: true
Item { Item {
@ -188,7 +188,7 @@ PluginComponent {
Item { width: 1; height: 1; Layout.fillWidth: true } Item { width: 1; height: 1; Layout.fillWidth: true }
StyledText { StyledText {
text: TailscaleLib.getStrings().exitNodePrefix + (root.currentExitNode || TailscaleLib.getStrings().none) text: I18n.tr(TailscaleLib.getStrings().exitNodePrefix) + (root.currentExitNode || I18n.tr(TailscaleLib.getStrings().none))
font.pixelSize: Theme.fontSizeSmall font.pixelSize: Theme.fontSizeSmall
color: Theme.surfaceVariantText color: Theme.surfaceVariantText
anchors.verticalCenter: parent.verticalCenter anchors.verticalCenter: parent.verticalCenter