From 8a476b326136f5c03790fa168686848884c8cd5a Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Thu, 14 Nov 2019 09:27:05 +0100 Subject: l18n: add localization support Revise the messages to make them localizable. Note: The log messages are not marked for localization. Probably, we want to keep log files in English for easier global troubleshooting. Having a user run `go generate` requires a valid and up-to-date Go environment. Rather than instructing users how to setup the environment correctly, the `go generate` was integrated into build.bat. This reuses the Go building environment downloaded and prepared by build.bat to provide controllable and consistent result. Use `make generate` on Linux. As the zgotext.go output varies for GOARCH=386 and amd64, one had to be chosen to provide stable output. The former is the first one to build in build.bat. Signed-off-by: Simon Rozman --- ui/aboutdialog.go | 12 ++++---- ui/confview.go | 54 +++++++++++++++++------------------ ui/editdialog.go | 34 +++++++++++----------- ui/filesave.go | 7 +++-- ui/iconprovider.go | 11 ++++---- ui/logpage.go | 19 +++++++------ ui/managewindow.go | 7 +++-- ui/raise.go | 5 ++-- ui/tray.go | 41 ++++++++++++++------------- ui/tunnelspage.go | 83 +++++++++++++++++++++++++++++------------------------- ui/ui.go | 7 +++-- ui/updatepage.go | 23 +++++++-------- 12 files changed, 159 insertions(+), 144 deletions(-) (limited to 'ui') diff --git a/ui/aboutdialog.go b/ui/aboutdialog.go index d87727aa..238ba5e2 100644 --- a/ui/aboutdialog.go +++ b/ui/aboutdialog.go @@ -6,7 +6,6 @@ package ui import ( - "fmt" "runtime" "strings" @@ -14,6 +13,7 @@ import ( "github.com/lxn/win" "golang.org/x/sys/windows" "golang.zx2c4.com/wireguard/device" + "golang.zx2c4.com/wireguard/windows/l18n" "golang.zx2c4.com/wireguard/windows/version" ) @@ -47,7 +47,7 @@ func runAboutDialog(owner walk.Form) error { showingAboutDialog = nil }() disposables.Add(showingAboutDialog) - showingAboutDialog.SetTitle("About WireGuard") + showingAboutDialog.SetTitle(l18n.Sprintf("About WireGuard")) showingAboutDialog.SetLayout(vbl) if icon, err := loadLogoIcon(32); err == nil { showingAboutDialog.SetIcon(icon) @@ -79,7 +79,7 @@ func runAboutDialog(owner walk.Form) error { if logo, err := loadLogoIcon(128); err == nil { iv.SetImage(logo) } - iv.Accessibility().SetName("WireGuard logo image") + iv.Accessibility().SetName(l18n.Sprintf("WireGuard logo image")) wgLbl, err := walk.NewTextLabel(showingAboutDialog) if err != nil { @@ -95,7 +95,7 @@ func runAboutDialog(owner walk.Form) error { return err } detailsLbl.SetTextAlignment(walk.AlignHCenterVNear) - detailsLbl.SetText(fmt.Sprintf("App version: %s\nGo backend version: %s\nGo version: %s\nOperating system: %s\nArchitecture: %s", version.Number, device.WireGuardGoVersion, strings.TrimPrefix(runtime.Version(), "go"), version.OsName(), runtime.GOARCH)) + detailsLbl.SetText(l18n.Sprintf("App version: %s\nGo backend version: %s\nGo version: %s\nOperating system: %s\nArchitecture: %s", version.Number, device.WireGuardGoVersion, strings.TrimPrefix(runtime.Version(), "go"), version.OsName(), runtime.GOARCH)) copyrightLbl, err := walk.NewTextLabel(showingAboutDialog) if err != nil { @@ -119,14 +119,14 @@ func runAboutDialog(owner walk.Form) error { return err } closePB.SetAlignment(walk.AlignHCenterVNear) - closePB.SetText("Close") + closePB.SetText(l18n.Sprintf("Close")) closePB.Clicked().Attach(showingAboutDialog.Accept) donatePB, err := walk.NewPushButton(buttonCP) if err != nil { return err } donatePB.SetAlignment(walk.AlignHCenterVNear) - donatePB.SetText("♥ &Donate!") + donatePB.SetText(l18n.Sprintf("♥ &Donate!")) donatePB.Clicked().Attach(func() { if easterEggIndex == -1 { easterEggIndex = 0 diff --git a/ui/confview.go b/ui/confview.go index 1c378aa1..d080db30 100644 --- a/ui/confview.go +++ b/ui/confview.go @@ -6,7 +6,6 @@ package ui import ( - "fmt" "strconv" "strings" "time" @@ -15,6 +14,7 @@ import ( "github.com/lxn/win" "golang.zx2c4.com/wireguard/windows/conf" + "golang.zx2c4.com/wireguard/windows/l18n" "golang.zx2c4.com/wireguard/windows/manager" ) @@ -108,7 +108,7 @@ func newLabelStatusLine(parent walk.Container) (*labelStatusLine, error) { return nil, err } disposables.Add(lsl.label) - lsl.label.SetText("Status:") + lsl.label.SetText(l18n.Sprintf("Status:")) lsl.label.SetTextAlignment(walk.AlignHFarVNear) if lsl.statusComposite, err = walk.NewComposite(parent); err != nil { @@ -180,7 +180,7 @@ func newLabelTextLine(fieldName string, parent walk.Container) (*labelTextLine, return nil, err } disposables.Add(lt.label) - lt.label.SetText(fieldName + ":") + lt.label.SetText(fieldName) lt.label.SetTextAlignment(walk.AlignHFarVNear) lt.label.SetVisible(false) @@ -216,9 +216,9 @@ func (tal *toggleActiveLine) update(state manager.TunnelState) { switch state { case manager.TunnelStarted: - text = "&Deactivate" + text = l18n.Sprintf("&Deactivate") case manager.TunnelStopped: - text = "&Activate" + text = l18n.Sprintf("&Activate") case manager.TunnelStarting, manager.TunnelStopping: text = textForState(state, true) default: @@ -300,11 +300,11 @@ func newInterfaceView(parent walk.Container) (*interfaceView, error) { disposables.Add(iv.status) items := []labelTextLineItem{ - {"Public key", &iv.publicKey}, - {"Listen port", &iv.listenPort}, - {"MTU", &iv.mtu}, - {"Addresses", &iv.addresses}, - {"DNS servers", &iv.dns}, + {l18n.Sprintf("Public key:"), &iv.publicKey}, + {l18n.Sprintf("Listen port:"), &iv.listenPort}, + {l18n.Sprintf("MTU:"), &iv.mtu}, + {l18n.Sprintf("Addresses:"), &iv.addresses}, + {l18n.Sprintf("DNS servers:"), &iv.dns}, } if iv.lines, err = createLabelTextLines(items, parent, &disposables); err != nil { return nil, err @@ -328,13 +328,13 @@ func newPeerView(parent walk.Container) (*peerView, error) { pv := new(peerView) items := []labelTextLineItem{ - {"Public key", &pv.publicKey}, - {"Preshared key", &pv.presharedKey}, - {"Allowed IPs", &pv.allowedIPs}, - {"Endpoint", &pv.endpoint}, - {"Persistent keepalive", &pv.persistentKeepalive}, - {"Latest handshake", &pv.latestHandshake}, - {"Transfer", &pv.transfer}, + {l18n.Sprintf("Public key:"), &pv.publicKey}, + {l18n.Sprintf("Preshared key:"), &pv.presharedKey}, + {l18n.Sprintf("Allowed IPs:"), &pv.allowedIPs}, + {l18n.Sprintf("Endpoint:"), &pv.endpoint}, + {l18n.Sprintf("Persistent keepalive:"), &pv.persistentKeepalive}, + {l18n.Sprintf("Latest handshake:"), &pv.latestHandshake}, + {l18n.Sprintf("Transfer:"), &pv.transfer}, } var err error if pv.lines, err = createLabelTextLines(items, parent, nil); err != nil { @@ -383,7 +383,7 @@ func (iv *interfaceView) apply(c *conf.Interface) { for i, address := range c.Addresses { addrStrings[i] = address.String() } - iv.addresses.show(strings.Join(addrStrings[:], ", ")) + iv.addresses.show(strings.Join(addrStrings[:], l18n.EnumerationSeparator())) } else { iv.addresses.hide() } @@ -393,7 +393,7 @@ func (iv *interfaceView) apply(c *conf.Interface) { for i, address := range c.DNS { addrStrings[i] = address.String() } - iv.dns.show(strings.Join(addrStrings[:], ", ")) + iv.dns.show(strings.Join(addrStrings[:], l18n.EnumerationSeparator())) } else { iv.dns.hide() } @@ -407,7 +407,7 @@ func (pv *peerView) apply(c *conf.Peer) { pv.publicKey.show(c.PublicKey.String()) if !c.PresharedKey.IsZero() { - pv.presharedKey.show("enabled") + pv.presharedKey.show(l18n.Sprintf("enabled")) } else { pv.presharedKey.hide() } @@ -417,7 +417,7 @@ func (pv *peerView) apply(c *conf.Peer) { for i, address := range c.AllowedIPs { addrStrings[i] = address.String() } - pv.allowedIPs.show(strings.Join(addrStrings[:], ", ")) + pv.allowedIPs.show(strings.Join(addrStrings[:], l18n.EnumerationSeparator())) } else { pv.allowedIPs.hide() } @@ -441,7 +441,7 @@ func (pv *peerView) apply(c *conf.Peer) { } if c.RxBytes > 0 || c.TxBytes > 0 { - pv.transfer.show(fmt.Sprintf("%s received, %s sent", c.RxBytes.String(), c.TxBytes.String())) + pv.transfer.show(l18n.Sprintf("%s received, %s sent", c.RxBytes.String(), c.TxBytes.String())) } else { pv.transfer.hide() } @@ -552,11 +552,11 @@ func (cv *ConfView) onToggleActiveClicked() { if err != nil { cv.Synchronize(func() { if oldState == manager.TunnelUnknown { - showErrorCustom(cv.Form(), "Failed to determine tunnel state", err.Error()) + showErrorCustom(cv.Form(), l18n.Sprintf("Failed to determine tunnel state"), err.Error()) } else if oldState == manager.TunnelStopped { - showErrorCustom(cv.Form(), "Failed to activate tunnel", err.Error()) + showErrorCustom(cv.Form(), l18n.Sprintf("Failed to activate tunnel"), err.Error()) } else if oldState == manager.TunnelStarted { - showErrorCustom(cv.Form(), "Failed to deactivate tunnel", err.Error()) + showErrorCustom(cv.Form(), l18n.Sprintf("Failed to deactivate tunnel"), err.Error()) } }) } @@ -612,7 +612,7 @@ func (cv *ConfView) setTunnel(tunnel *manager.Tunnel, config *conf.Config, state return } - title := "Interface: " + config.Name + title := l18n.Sprintf("Interface: %s", config.Name) if cv.name.Title() != title { cv.SetSuspended(true) defer cv.SetSuspended(false) @@ -656,7 +656,7 @@ func (cv *ConfView) setTunnel(tunnel *manager.Tunnel, config *conf.Config, state if err != nil { continue } - group.SetTitle("Peer") + group.SetTitle(l18n.Sprintf("Peer")) pv, err := newPeerView(group) if err != nil { group.Dispose() diff --git a/ui/editdialog.go b/ui/editdialog.go index 4d25dd79..ade6c498 100644 --- a/ui/editdialog.go +++ b/ui/editdialog.go @@ -6,7 +6,6 @@ package ui import ( - "fmt" "strings" "github.com/lxn/walk" @@ -14,6 +13,7 @@ import ( "golang.org/x/sys/windows" "golang.zx2c4.com/wireguard/windows/conf" + "golang.zx2c4.com/wireguard/windows/l18n" "golang.zx2c4.com/wireguard/windows/manager" "golang.zx2c4.com/wireguard/windows/ui/syntax" ) @@ -52,9 +52,9 @@ func newEditDialog(owner walk.Form, tunnel *manager.Tunnel) (*EditDialog, error) var title string if tunnel == nil { - title = "Create new tunnel" + title = l18n.Sprintf("Create new tunnel") } else { - title = "Edit tunnel" + title = l18n.Sprintf("Edit tunnel") } if tunnel == nil { @@ -88,7 +88,7 @@ func newEditDialog(owner walk.Form, tunnel *manager.Tunnel) (*EditDialog, error) } layout.SetRange(nameLabel, walk.Rectangle{0, 0, 1, 1}) nameLabel.SetTextAlignment(walk.AlignHFarVCenter) - nameLabel.SetText("&Name:") + nameLabel.SetText(l18n.Sprintf("&Name:")) if dlg.nameEdit, err = walk.NewLineEdit(dlg); err != nil { return nil, err @@ -102,14 +102,14 @@ func newEditDialog(owner walk.Form, tunnel *manager.Tunnel) (*EditDialog, error) } layout.SetRange(pubkeyLabel, walk.Rectangle{0, 1, 1, 1}) pubkeyLabel.SetTextAlignment(walk.AlignHFarVCenter) - pubkeyLabel.SetText("&Public key:") + pubkeyLabel.SetText(l18n.Sprintf("&Public key:")) if dlg.pubkeyEdit, err = walk.NewLineEdit(dlg); err != nil { return nil, err } layout.SetRange(dlg.pubkeyEdit, walk.Rectangle{1, 1, 1, 1}) dlg.pubkeyEdit.SetReadOnly(true) - dlg.pubkeyEdit.SetText("(unknown)") + dlg.pubkeyEdit.SetText(l18n.Sprintf("(unknown)")) dlg.pubkeyEdit.Accessibility().SetRole(walk.AccRoleStatictext) if dlg.syntaxEdit, err = syntax.NewSyntaxEdit(dlg); err != nil { @@ -128,8 +128,8 @@ func newEditDialog(owner walk.Form, tunnel *manager.Tunnel) (*EditDialog, error) if dlg.blockUntunneledTrafficCB, err = walk.NewCheckBox(buttonsContainer); err != nil { return nil, err } - dlg.blockUntunneledTrafficCB.SetText("&Block untunneled traffic (kill-switch)") - dlg.blockUntunneledTrafficCB.SetToolTipText("When a configuration has exactly one peer, and that peer has an allowed IPs containing at least one of 0.0.0.0/0 or ::/0, then the tunnel service engages a firewall ruleset to block all traffic that is neither to nor from the tunnel interface, with special exceptions for DHCP and NDP.") + dlg.blockUntunneledTrafficCB.SetText(l18n.Sprintf("&Block untunneled traffic (kill-switch)")) + dlg.blockUntunneledTrafficCB.SetToolTipText(l18n.Sprintf("When a configuration has exactly one peer, and that peer has an allowed IPs containing at least one of 0.0.0.0/0 or ::/0, then the tunnel service engages a firewall ruleset to block all traffic that is neither to nor from the tunnel interface, with special exceptions for DHCP and NDP.")) dlg.blockUntunneledTrafficCB.SetVisible(false) dlg.blockUntunneledTrafficCB.CheckedChanged().Attach(dlg.onBlockUntunneledTrafficCBCheckedChanged) @@ -138,14 +138,14 @@ func newEditDialog(owner walk.Form, tunnel *manager.Tunnel) (*EditDialog, error) if dlg.saveButton, err = walk.NewPushButton(buttonsContainer); err != nil { return nil, err } - dlg.saveButton.SetText("&Save") + dlg.saveButton.SetText(l18n.Sprintf("&Save")) dlg.saveButton.Clicked().Attach(dlg.onSaveButtonClicked) cancelButton, err := walk.NewPushButton(buttonsContainer) if err != nil { return nil, err } - cancelButton.SetText("Cancel") + cancelButton.SetText(l18n.Sprintf("Cancel")) cancelButton.Clicked().Attach(dlg.Cancel) dlg.SetCancelButton(cancelButton) @@ -160,7 +160,7 @@ func newEditDialog(owner walk.Form, tunnel *manager.Tunnel) (*EditDialog, error) syntaxEditWnd := dlg.syntaxEdit.Handle() parentWnd := win.GetParent(syntaxEditWnd) labelWnd := win.CreateWindowEx(0, - windows.StringToUTF16Ptr("STATIC"), windows.StringToUTF16Ptr("&Configuration:"), + windows.StringToUTF16Ptr("STATIC"), windows.StringToUTF16Ptr(l18n.Sprintf("&Configuration:")), win.WS_CHILD|win.WS_GROUP|win.SS_LEFT, 0, 0, 0, 0, parentWnd, win.HMENU(^uintptr(0)), win.HINSTANCE(win.GetWindowLongPtr(parentWnd, win.GWLP_HINSTANCE)), nil) prevWnd := win.GetWindow(syntaxEditWnd, win.GW_HWNDPREV) @@ -301,18 +301,18 @@ func (dlg *EditDialog) onSyntaxEditPrivateKeyChanged(privateKey string) { if key != nil { dlg.pubkeyEdit.SetText(key.Public().String()) } else { - dlg.pubkeyEdit.SetText("(unknown)") + dlg.pubkeyEdit.SetText(l18n.Sprintf("(unknown)")) } } func (dlg *EditDialog) onSaveButtonClicked() { newName := dlg.nameEdit.Text() if newName == "" { - showWarningCustom(dlg, "Invalid name", "A name is required.") + showWarningCustom(dlg, l18n.Sprintf("Invalid name"), l18n.Sprintf("A name is required.")) return } if !conf.TunnelNameIsValid(newName) { - showWarningCustom(dlg, "Invalid name", fmt.Sprintf("Tunnel name ‘%s’ is invalid.", newName)) + showWarningCustom(dlg, l18n.Sprintf("Invalid name"), l18n.Sprintf("Tunnel name ‘%s’ is invalid.", newName)) return } newNameLower := strings.ToLower(newName) @@ -320,12 +320,12 @@ func (dlg *EditDialog) onSaveButtonClicked() { if newNameLower != strings.ToLower(dlg.config.Name) { existingTunnelList, err := manager.IPCClientTunnels() if err != nil { - showWarningCustom(dlg, "Unable to list existing tunnels", err.Error()) + showWarningCustom(dlg, l18n.Sprintf("Unable to list existing tunnels"), err.Error()) return } for _, tunnel := range existingTunnelList { if strings.ToLower(tunnel.Name) == newNameLower { - showWarningCustom(dlg, "Tunnel already exists", fmt.Sprintf("Another tunnel already exists with the name ‘%s’.", newName)) + showWarningCustom(dlg, l18n.Sprintf("Tunnel already exists"), l18n.Sprintf("Another tunnel already exists with the name ‘%s’.", newName)) return } } @@ -333,7 +333,7 @@ func (dlg *EditDialog) onSaveButtonClicked() { cfg, err := conf.FromWgQuick(dlg.syntaxEdit.Text(), newName) if err != nil { - showErrorCustom(dlg, "Unable to create new configuration", err.Error()) + showErrorCustom(dlg, l18n.Sprintf("Unable to create new configuration"), err.Error()) return } diff --git a/ui/filesave.go b/ui/filesave.go index 4b5c2947..7ca8a2c2 100644 --- a/ui/filesave.go +++ b/ui/filesave.go @@ -6,10 +6,11 @@ package ui import ( - "fmt" "os" "github.com/lxn/walk" + + "golang.zx2c4.com/wireguard/windows/l18n" ) func writeFileWithOverwriteHandling(owner walk.Form, filePath string, write func(file *os.File) error) bool { @@ -18,7 +19,7 @@ func writeFileWithOverwriteHandling(owner walk.Form, filePath string, write func return false } - showErrorCustom(owner, "Writing file failed", err.Error()) + showErrorCustom(owner, l18n.Sprintf("Writing file failed"), err.Error()) return true } @@ -26,7 +27,7 @@ func writeFileWithOverwriteHandling(owner walk.Form, filePath string, write func file, err := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY|os.O_EXCL, 0600) if err != nil { if os.IsExist(err) { - if walk.DlgCmdNo == walk.MsgBox(owner, "Writing file failed", fmt.Sprintf(`File ‘%s’ already exists. + if walk.DlgCmdNo == walk.MsgBox(owner, l18n.Sprintf("Writing file failed"), l18n.Sprintf(`File ‘%s’ already exists. Do you want to overwrite it?`, filePath), walk.MsgBoxYesNo|walk.MsgBoxDefButton2|walk.MsgBoxIconWarning) { return false diff --git a/ui/iconprovider.go b/ui/iconprovider.go index e5177ac3..8db841c5 100644 --- a/ui/iconprovider.go +++ b/ui/iconprovider.go @@ -8,6 +8,7 @@ package ui import ( "github.com/lxn/walk" + "golang.zx2c4.com/wireguard/windows/l18n" "golang.zx2c4.com/wireguard/windows/manager" ) @@ -87,15 +88,15 @@ func iconForState(state manager.TunnelState, size int) (icon *walk.Icon, err err func textForState(state manager.TunnelState, withEllipsis bool) (text string) { switch state { case manager.TunnelStarted: - text = "Active" + text = l18n.Sprintf("Active") case manager.TunnelStarting: - text = "Activating" + text = l18n.Sprintf("Activating") case manager.TunnelStopped: - text = "Inactive" + text = l18n.Sprintf("Inactive") case manager.TunnelStopping: - text = "Deactivating" + text = l18n.Sprintf("Deactivating") case manager.TunnelUnknown: - text = "Unknown state" + text = l18n.Sprintf("Unknown state") } if withEllipsis { switch state { diff --git a/ui/logpage.go b/ui/logpage.go index b8febcbb..1de5c920 100644 --- a/ui/logpage.go +++ b/ui/logpage.go @@ -12,6 +12,7 @@ import ( "time" "github.com/lxn/walk" + "golang.zx2c4.com/wireguard/windows/l18n" "golang.zx2c4.com/wireguard/windows/ringlogger" ) @@ -41,7 +42,7 @@ func NewLogPage() (*LogPage, error) { lp.model.quit <- true }) - lp.SetTitle("Log") + lp.SetTitle(l18n.Sprintf("Log")) lp.SetLayout(walk.NewVBoxLayout()) if lp.logView, err = walk.NewTableView(lp); err != nil { @@ -57,19 +58,19 @@ func NewLogPage() (*LogPage, error) { } lp.logView.AddDisposable(contextMenu) copyAction := walk.NewAction() - copyAction.SetText("&Copy") + copyAction.SetText(l18n.Sprintf("&Copy")) copyAction.SetShortcut(walk.Shortcut{walk.ModControl, walk.KeyC}) copyAction.Triggered().Attach(lp.onCopy) contextMenu.Actions().Add(copyAction) lp.ShortcutActions().Add(copyAction) selectAllAction := walk.NewAction() - selectAllAction.SetText("Select &all") + selectAllAction.SetText(l18n.Sprintf("Select &all")) selectAllAction.SetShortcut(walk.Shortcut{walk.ModControl, walk.KeyA}) selectAllAction.Triggered().Attach(lp.onSelectAll) contextMenu.Actions().Add(selectAllAction) lp.ShortcutActions().Add(selectAllAction) saveAction := walk.NewAction() - saveAction.SetText("&Save to file…") + saveAction.SetText(l18n.Sprintf("&Save to file…")) saveAction.SetShortcut(walk.Shortcut{walk.ModControl, walk.KeyS}) saveAction.Triggered().Attach(lp.onSave) contextMenu.Actions().Add(saveAction) @@ -83,14 +84,14 @@ func NewLogPage() (*LogPage, error) { stampCol := walk.NewTableViewColumn() stampCol.SetName("Stamp") - stampCol.SetTitle("Time") + stampCol.SetTitle(l18n.Sprintf("Time")) stampCol.SetFormat("2006-01-02 15:04:05.000") stampCol.SetWidth(140) lp.logView.Columns().Add(stampCol) msgCol := walk.NewTableViewColumn() msgCol.SetName("Line") - msgCol.SetTitle("Log message") + msgCol.SetTitle(l18n.Sprintf("Log message")) lp.logView.Columns().Add(msgCol) lp.model = newLogModel(lp) @@ -111,7 +112,7 @@ func NewLogPage() (*LogPage, error) { if err != nil { return nil, err } - saveButton.SetText("&Save") + saveButton.SetText(l18n.Sprintf("&Save")) saveButton.Clicked().Attach(lp.onSave) disposables.Spare() @@ -146,9 +147,9 @@ func (lp *LogPage) onSelectAll() { func (lp *LogPage) onSave() { fd := walk.FileDialog{ - Filter: "Text Files (*.txt)|*.txt|All Files (*.*)|*.*", + Filter: l18n.Sprintf("Text Files (*.txt)|*.txt|All Files (*.*)|*.*"), FilePath: fmt.Sprintf("wireguard-log-%s.txt", time.Now().Format("2006-01-02T150405")), - Title: "Export log to file", + Title: l18n.Sprintf("Export log to file"), } form := lp.Form() diff --git a/ui/managewindow.go b/ui/managewindow.go index 542c91b9..e6855d5d 100644 --- a/ui/managewindow.go +++ b/ui/managewindow.go @@ -13,6 +13,7 @@ import ( "github.com/lxn/win" "golang.org/x/sys/windows" + "golang.zx2c4.com/wireguard/windows/l18n" "golang.zx2c4.com/wireguard/windows/manager" ) @@ -118,7 +119,7 @@ func NewManageTunnelsWindow() (*ManageTunnelsWindow, error) { CbSize: uint32(unsafe.Sizeof(win.MENUITEMINFO{})), FMask: win.MIIM_ID | win.MIIM_STRING | win.MIIM_FTYPE, FType: win.MIIM_STRING, - DwTypeData: windows.StringToUTF16Ptr("&About WireGuard…"), + DwTypeData: windows.StringToUTF16Ptr(l18n.Sprintf("&About WireGuard…")), WID: uint32(aboutWireGuardCmd), }) win.InsertMenuItem(systemMenu, 1, true, &win.MENUITEMINFO{ @@ -169,7 +170,7 @@ func (mtw *ManageTunnelsWindow) onTunnelChange(tunnel *manager.Tunnel, state man if len(errMsg) > 0 && errMsg[len(errMsg)-1] != '.' { errMsg += "." } - showWarningCustom(mtw, "Tunnel Error", errMsg+"\n\nPlease consult the log for more information.") + showWarningCustom(mtw, l18n.Sprintf("Tunnel Error"), l18n.Sprintf("%s\n\nPlease consult the log for more information.", errMsg)) } }) } @@ -178,7 +179,7 @@ func (mtw *ManageTunnelsWindow) UpdateFound() { if mtw.updatePage != nil { return } - mtw.SetTitle(mtw.Title() + " (out of date)") + mtw.SetTitle(l18n.Sprintf("%s (out of date)", mtw.Title())) updatePage, err := NewUpdatePage() if err == nil { mtw.updatePage = updatePage diff --git a/ui/raise.go b/ui/raise.go index 42509994..0eac828a 100644 --- a/ui/raise.go +++ b/ui/raise.go @@ -6,12 +6,13 @@ package ui import ( - "fmt" "os" "runtime" "github.com/lxn/win" "golang.org/x/sys/windows" + + "golang.zx2c4.com/wireguard/windows/l18n" ) func raise(hwnd win.HWND) { @@ -66,7 +67,7 @@ func WaitForRaiseUIThenQuit() { return 0 }, 0, 0, win.WINEVENT_SKIPOWNPROCESS|win.WINEVENT_OUTOFCONTEXT) if err != nil { - showErrorCustom(nil, "WireGuard Detection Error", fmt.Sprintf("Unable to wait for WireGuard window to appear: %v", err)) + showErrorCustom(nil, l18n.Sprintf("WireGuard Detection Error"), l18n.Sprintf("Unable to wait for WireGuard window to appear: %v", err)) } for { var msg win.MSG diff --git a/ui/tray.go b/ui/tray.go index 810c759b..f1fb727e 100644 --- a/ui/tray.go +++ b/ui/tray.go @@ -6,12 +6,12 @@ package ui import ( - "fmt" "sort" "strings" "time" "golang.zx2c4.com/wireguard/windows/conf" + "golang.zx2c4.com/wireguard/windows/l18n" "golang.zx2c4.com/wireguard/windows/manager" "github.com/lxn/walk" @@ -53,7 +53,7 @@ func NewTray(mtw *ManageTunnelsWindow) (*Tray, error) { func (tray *Tray) setup() error { tray.clicked = tray.onManageTunnels - tray.SetToolTip("WireGuard: Deactivated") + tray.SetToolTip(l18n.Sprintf("WireGuard: Deactivated")) tray.SetVisible(true) if icon, err := loadLogoIcon(16); err == nil { tray.SetIcon(icon) @@ -76,15 +76,15 @@ func (tray *Tray) setup() error { separator bool defawlt bool }{ - {label: "Status: Unknown"}, - {label: "Addresses: None", hidden: true}, + {label: l18n.Sprintf("Status: Unknown")}, + {label: l18n.Sprintf("Addresses: None"), hidden: true}, {separator: true}, {separator: true}, - {label: "&Manage tunnels…", handler: tray.onManageTunnels, enabled: true, defawlt: true}, - {label: "&Import tunnel(s) from file…", handler: tray.onImport, enabled: true}, + {label: l18n.Sprintf("&Manage tunnels…"), handler: tray.onManageTunnels, enabled: true, defawlt: true}, + {label: l18n.Sprintf("&Import tunnel(s) from file…"), handler: tray.onImport, enabled: true}, {separator: true}, - {label: "&About WireGuard…", handler: tray.onAbout, enabled: true}, - {label: "E&xit", handler: onQuit, enabled: true}, + {label: l18n.Sprintf("&About WireGuard…"), handler: tray.onAbout, enabled: true}, + {label: l18n.Sprintf("E&xit"), handler: onQuit, enabled: true}, } { var action *walk.Action if item.separator { @@ -160,11 +160,11 @@ func (tray *Tray) addTunnelAction(tunnel *manager.Tunnel) { tray.mtw.tunnelsPage.listView.selectTunnel(tclosure.Name) tray.mtw.tabs.SetCurrentIndex(0) if oldState == manager.TunnelUnknown { - showErrorCustom(tray.mtw, "Failed to determine tunnel state", err.Error()) + showErrorCustom(tray.mtw, l18n.Sprintf("Failed to determine tunnel state"), err.Error()) } else if oldState == manager.TunnelStopped { - showErrorCustom(tray.mtw, "Failed to activate tunnel", err.Error()) + showErrorCustom(tray.mtw, l18n.Sprintf("Failed to activate tunnel"), err.Error()) } else if oldState == manager.TunnelStarted { - showErrorCustom(tray.mtw, "Failed to deactivate tunnel", err.Error()) + showErrorCustom(tray.mtw, l18n.Sprintf("Failed to deactivate tunnel"), err.Error()) } }) } @@ -213,7 +213,7 @@ func (tray *Tray) onTunnelChange(tunnel *manager.Tunnel, state manager.TunnelSta tray.updateGlobalState(globalState) tray.SetTunnelState(tunnel, state, err == nil) if !tray.mtw.Visible() && err != nil { - tray.ShowError("WireGuard Tunnel Error", err.Error()) + tray.ShowError(l18n.Sprintf("WireGuard Tunnel Error"), err.Error()) } }) } @@ -234,8 +234,9 @@ func (tray *Tray) updateGlobalState(globalState manager.TunnelState) { } } - tray.SetToolTip(fmt.Sprintf("WireGuard: %s", textForState(globalState, true))) - statusAction.SetText(fmt.Sprintf("Status: %s", textForState(globalState, false))) + tray.SetToolTip(l18n.Sprintf("WireGuard: %s", textForState(globalState, true))) + stateText := textForState(globalState, false) + statusAction.SetText(l18n.Sprintf("Status: %s", stateText)) switch globalState { case manager.TunnelStarting: @@ -274,13 +275,13 @@ func (tray *Tray) SetTunnelState(tunnel *manager.Tunnel, state manager.TunnelSta var sb strings.Builder for i, addr := range config.Interface.Addresses { if i > 0 { - sb.WriteString(", ") + sb.WriteString(l18n.EnumerationSeparator()) } sb.WriteString(addr.String()) } tray.mtw.Synchronize(func() { - activeCIDRsAction.SetText(fmt.Sprintf("Addresses: %s", sb.String())) + activeCIDRsAction.SetText(l18n.Sprintf("Addresses: %s", sb.String())) }) } }() @@ -288,21 +289,21 @@ func (tray *Tray) SetTunnelState(tunnel *manager.Tunnel, state manager.TunnelSta tunnelAction.SetChecked(true) if !wasChecked && showNotifications { icon, _ := iconWithOverlayForState(state, 128) - tray.ShowCustom("WireGuard Activated", fmt.Sprintf("The %s tunnel has been activated.", tunnel.Name), icon) + tray.ShowCustom(l18n.Sprintf("WireGuard Activated"), l18n.Sprintf("The %s tunnel has been activated.", tunnel.Name), icon) } case manager.TunnelStopped: tunnelAction.SetChecked(false) if wasChecked && showNotifications { icon, _ := loadSystemIcon("imageres", 26, 128) // TODO: this icon isn't very good... - tray.ShowCustom("WireGuard Deactivated", fmt.Sprintf("The %s tunnel has been deactivated.", tunnel.Name), icon) + tray.ShowCustom(l18n.Sprintf("WireGuard Deactivated"), l18n.Sprintf("The %s tunnel has been deactivated.", tunnel.Name), icon) } } } func (tray *Tray) UpdateFound() { action := walk.NewAction() - action.SetText("An Update is Available!") + action.SetText(l18n.Sprintf("An Update is Available!")) menuIcon, _ := loadSystemIcon("imageres", 1, 16) action.SetImage(menuIcon) action.SetDefault(true) @@ -319,7 +320,7 @@ func (tray *Tray) UpdateFound() { showUpdateBalloon := func() { icon, _ := loadSystemIcon("imageres", 1, 128) - tray.ShowCustom("WireGuard Update Available", "An update to WireGuard is now available. You are advised to update as soon as possible.", icon) + tray.ShowCustom(l18n.Sprintf("WireGuard Update Available"), l18n.Sprintf("An update to WireGuard is now available. You are advised to update as soon as possible."), icon) } timeSinceStart := time.Now().Sub(startTime) diff --git a/ui/tunnelspage.go b/ui/tunnelspage.go index aed8d157..d5933143 100644 --- a/ui/tunnelspage.go +++ b/ui/tunnelspage.go @@ -7,6 +7,7 @@ package ui import ( "archive/zip" + "errors" "fmt" "io/ioutil" "os" @@ -17,6 +18,7 @@ import ( "github.com/lxn/walk" "golang.zx2c4.com/wireguard/windows/conf" + "golang.zx2c4.com/wireguard/windows/l18n" "golang.zx2c4.com/wireguard/windows/manager" ) @@ -45,7 +47,7 @@ func NewTunnelsPage() (*TunnelsPage, error) { } disposables.Add(tp) - tp.SetTitle("Tunnels") + tp.SetTitle(l18n.Sprintf("Tunnels")) tp.SetLayout(walk.NewHBoxLayout()) tp.listContainer, _ = walk.NewComposite(tp) @@ -101,7 +103,7 @@ func NewTunnelsPage() (*TunnelsPage, error) { tp.listView.CurrentIndexChanged().Attach(func() { editTunnel.SetEnabled(tp.listView.CurrentIndex() > -1) }) - editTunnel.SetText("&Edit") + editTunnel.SetText(l18n.Sprintf("&Edit")) editTunnel.Clicked().Attach(tp.onEditTunnel) disposables.Spare() @@ -142,7 +144,7 @@ func (tp *TunnelsPage) CreateToolbar() error { } tp.AddDisposable(addMenu) importAction := walk.NewAction() - importAction.SetText("&Import tunnel(s) from file…") + importAction.SetText(l18n.Sprintf("&Import tunnel(s) from file…")) importActionIcon, _ := loadSystemIcon("imageres", 3, 16) importAction.SetImage(importActionIcon) importAction.SetShortcut(walk.Shortcut{walk.ModControl, walk.KeyO}) @@ -150,7 +152,7 @@ func (tp *TunnelsPage) CreateToolbar() error { importAction.Triggered().Attach(tp.onImport) addMenu.Actions().Add(importAction) addAction := walk.NewAction() - addAction.SetText("Add &empty tunnel…") + addAction.SetText(l18n.Sprintf("Add &empty tunnel…")) addActionIcon, _ := loadSystemIcon("imageres", 2, 16) addAction.SetImage(addActionIcon) addAction.SetShortcut(walk.Shortcut{walk.ModControl, walk.KeyN}) @@ -159,7 +161,7 @@ func (tp *TunnelsPage) CreateToolbar() error { addMenuAction := walk.NewMenuAction(addMenu) addMenuActionIcon, _ := loadSystemIcon("shell32", 149, 16) addMenuAction.SetImage(addMenuActionIcon) - addMenuAction.SetText("Add Tunnel") + addMenuAction.SetText(l18n.Sprintf("Add Tunnel")) addMenuAction.SetToolTip(importAction.Text()) addMenuAction.Triggered().Attach(tp.onImport) tp.listToolbar.Actions().Add(addMenuAction) @@ -170,7 +172,7 @@ func (tp *TunnelsPage) CreateToolbar() error { deleteActionIcon, _ := loadSystemIcon("shell32", 131, 16) deleteAction.SetImage(deleteActionIcon) deleteAction.SetShortcut(walk.Shortcut{0, walk.KeyDelete}) - deleteAction.SetToolTip("Remove selected tunnel(s)") + deleteAction.SetToolTip(l18n.Sprintf("Remove selected tunnel(s)")) deleteAction.Triggered().Attach(tp.onDelete) tp.listToolbar.Actions().Add(deleteAction) tp.listToolbar.Actions().Add(walk.NewSeparatorAction()) @@ -178,7 +180,7 @@ func (tp *TunnelsPage) CreateToolbar() error { exportAction := walk.NewAction() exportActionIcon, _ := loadSystemIcon("imageres", 165, 16) // Or "shell32", 45? exportAction.SetImage(exportActionIcon) - exportAction.SetToolTip("Export all tunnels to zip…") + exportAction.SetToolTip(l18n.Sprintf("Export all tunnels to zip")) exportAction.Triggered().Attach(tp.onExportTunnels) tp.listToolbar.Actions().Add(exportAction) @@ -195,42 +197,42 @@ func (tp *TunnelsPage) CreateToolbar() error { } tp.listView.AddDisposable(contextMenu) toggleAction := walk.NewAction() - toggleAction.SetText("&Toggle") + toggleAction.SetText(l18n.Sprintf("&Toggle")) toggleAction.SetDefault(true) toggleAction.Triggered().Attach(tp.onTunnelsViewItemActivated) contextMenu.Actions().Add(toggleAction) contextMenu.Actions().Add(walk.NewSeparatorAction()) importAction2 := walk.NewAction() - importAction2.SetText("&Import tunnel(s) from file…") + importAction2.SetText(l18n.Sprintf("&Import tunnel(s) from file…")) importAction2.SetShortcut(walk.Shortcut{walk.ModControl, walk.KeyO}) importAction2.Triggered().Attach(tp.onImport) contextMenu.Actions().Add(importAction2) tp.ShortcutActions().Add(importAction2) addAction2 := walk.NewAction() - addAction2.SetText("Add &empty tunnel…") + addAction2.SetText(l18n.Sprintf("Add &empty tunnel…")) addAction2.SetShortcut(walk.Shortcut{walk.ModControl, walk.KeyN}) addAction2.Triggered().Attach(tp.onAddTunnel) contextMenu.Actions().Add(addAction2) tp.ShortcutActions().Add(addAction2) exportAction2 := walk.NewAction() - exportAction2.SetText("Export all tunnels to &zip…") + exportAction2.SetText(l18n.Sprintf("Export all tunnels to &zip…")) exportAction2.Triggered().Attach(tp.onExportTunnels) contextMenu.Actions().Add(exportAction2) contextMenu.Actions().Add(walk.NewSeparatorAction()) editAction := walk.NewAction() - editAction.SetText("Edit &selected tunnel…") + editAction.SetText(l18n.Sprintf("Edit &selected tunnel…")) editAction.SetShortcut(walk.Shortcut{walk.ModControl, walk.KeyE}) editAction.Triggered().Attach(tp.onEditTunnel) contextMenu.Actions().Add(editAction) tp.ShortcutActions().Add(editAction) deleteAction2 := walk.NewAction() - deleteAction2.SetText("&Remove selected tunnel(s)") + deleteAction2.SetText(l18n.Sprintf("&Remove selected tunnel(s)")) deleteAction2.SetShortcut(walk.Shortcut{0, walk.KeyDelete}) deleteAction2.Triggered().Attach(tp.onDelete) contextMenu.Actions().Add(deleteAction2) tp.listView.ShortcutActions().Add(deleteAction2) selectAllAction := walk.NewAction() - selectAllAction.SetText("Select &all") + selectAllAction.SetText(l18n.Sprintf("Select &all")) selectAllAction.SetShortcut(walk.Shortcut{walk.ModControl, walk.KeyA}) selectAllAction.Triggered().Attach(tp.onSelectAll) contextMenu.Actions().Add(selectAllAction) @@ -324,7 +326,7 @@ func (tp *TunnelsPage) importFiles(paths []string) { } if lastErr != nil || unparsedConfigs == nil { - syncedMsgBox("Error", fmt.Sprintf("Could not import selected configuration: %v", lastErr), walk.MsgBoxIconWarning) + syncedMsgBox(l18n.Sprintf("Error"), l18n.Sprintf("Could not import selected configuration: %v", lastErr), walk.MsgBoxIconWarning) return } @@ -335,7 +337,7 @@ func (tp *TunnelsPage) importFiles(paths []string) { existingTunnelList, err := manager.IPCClientTunnels() if err != nil { - syncedMsgBox("Error", fmt.Sprintf("Could not enumerate existing tunnels: %v", lastErr), walk.MsgBoxIconWarning) + syncedMsgBox(l18n.Sprintf("Error"), l18n.Sprintf("Could not enumerate existing tunnels: %v", lastErr), walk.MsgBoxIconWarning) return } existingLowerTunnels := make(map[string]bool, len(existingTunnelList)) @@ -347,7 +349,7 @@ func (tp *TunnelsPage) importFiles(paths []string) { tp.listView.SetSuspendTunnelsUpdate(true) for _, unparsedConfig := range unparsedConfigs { if existingLowerTunnels[strings.ToLower(unparsedConfig.Name)] { - lastErr = fmt.Errorf("Another tunnel already exists with the name ‘%s’", unparsedConfig.Name) + lastErr = errors.New(l18n.Sprintf("Another tunnel already exists with the name ‘%s’", unparsedConfig.Name)) continue } config, err := conf.FromWgQuickWithUnknownEncoding(unparsedConfig.Config, unparsedConfig.Name) @@ -367,13 +369,13 @@ func (tp *TunnelsPage) importFiles(paths []string) { m, n := configCount, len(unparsedConfigs) switch { case n == 1 && m != n: - syncedMsgBox("Error", fmt.Sprintf("Unable to import configuration: %v", lastErr), walk.MsgBoxIconWarning) + syncedMsgBox(l18n.Sprintf("Error"), l18n.Sprintf("Unable to import configuration: %v", lastErr), walk.MsgBoxIconWarning) case n == 1 && m == n: // nothing case m == n: - syncedMsgBox("Imported tunnels", fmt.Sprintf("Imported %d tunnels", m), walk.MsgBoxIconInformation) + syncedMsgBox(l18n.Sprintf("Imported tunnels"), l18n.Sprintf("Imported %d tunnels", m), walk.MsgBoxIconInformation) case m != n: - syncedMsgBox("Imported tunnels", fmt.Sprintf("Imported %d of %d tunnels", m, n), walk.MsgBoxIconWarning) + syncedMsgBox(l18n.Sprintf("Imported tunnels"), l18n.Sprintf("Imported %d of %d tunnels", m, n), walk.MsgBoxIconWarning) } }() } @@ -405,7 +407,7 @@ func (tp *TunnelsPage) exportTunnels(filePath string) { func (tp *TunnelsPage) addTunnel(config *conf.Config) { _, err := manager.IPCClientNewTunnel(config) if err != nil { - showErrorCustom(tp.Form(), "Unable to create tunnel", err.Error()) + showErrorCustom(tp.Form(), l18n.Sprintf("Unable to create tunnel"), err.Error()) } } @@ -422,11 +424,11 @@ func (tp *TunnelsPage) onTunnelsViewItemActivated() { if err != nil { tp.Synchronize(func() { if oldState == manager.TunnelUnknown { - showErrorCustom(tp.Form(), "Failed to determine tunnel state", err.Error()) + showErrorCustom(tp.Form(), l18n.Sprintf("Failed to determine tunnel state"), err.Error()) } else if oldState == manager.TunnelStopped { - showErrorCustom(tp.Form(), "Failed to activate tunnel", err.Error()) + showErrorCustom(tp.Form(), l18n.Sprintf("Failed to activate tunnel"), err.Error()) } else if oldState == manager.TunnelStarted { - showErrorCustom(tp.Form(), "Failed to deactivate tunnel", err.Error()) + showErrorCustom(tp.Form(), l18n.Sprintf("Failed to deactivate tunnel"), err.Error()) } }) return @@ -466,16 +468,20 @@ func (tp *TunnelsPage) onDelete() { return } - var topic string + var title, question string if len(indices) > 1 { - topic = fmt.Sprintf("%d tunnels", len(indices)) + tunnelCount := len(indices) + title = l18n.Sprintf("Delete %d tunnels", tunnelCount) + question = l18n.Sprintf("Are you sure you would like to delete %d tunnels?", tunnelCount) } else { - topic = fmt.Sprintf("‘%s’", tp.listView.model.tunnels[indices[0]].Name) + tunnelName := tp.listView.model.tunnels[indices[0]].Name + title = l18n.Sprintf("Delete tunnel ‘%s’", tunnelName) + question = l18n.Sprintf("Are you sure you would like to delete tunnel ‘%s’?", tunnelName) } if walk.DlgCmdNo == walk.MsgBox( tp.Form(), - fmt.Sprintf("Delete %s", topic), - fmt.Sprintf("Are you sure you would like to delete %s? You cannot undo this action.", topic), + title, + l18n.Sprintf("%s You cannot undo this action.", question), walk.MsgBoxYesNo|walk.MsgBoxIconWarning) { return } @@ -515,9 +521,9 @@ func (tp *TunnelsPage) onDelete() { if len(errors) > 0 { tp.listView.Synchronize(func() { if len(errors) == 1 { - showErrorCustom(tp.Form(), "Unable to delete tunnel", fmt.Sprintf("A tunnel was unable to be removed: %s", errors[0].Error())) + showErrorCustom(tp.Form(), l18n.Sprintf("Unable to delete tunnel"), l18n.Sprintf("A tunnel was unable to be removed: %s", errors[0].Error())) } else { - showErrorCustom(tp.Form(), "Unable to delete tunnels", fmt.Sprintf("%d tunnels were unable to be removed.", len(errors))) + showErrorCustom(tp.Form(), l18n.Sprintf("Unable to delete tunnels"), l18n.Sprintf("%d tunnels were unable to be removed.", len(errors))) } }) } @@ -530,8 +536,8 @@ func (tp *TunnelsPage) onSelectAll() { func (tp *TunnelsPage) onImport() { dlg := walk.FileDialog{ - Filter: "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*", - Title: "Import tunnel(s) from file", + Filter: l18n.Sprintf("Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*"), + Title: l18n.Sprintf("Import tunnel(s) from file"), } if ok, _ := dlg.ShowOpenMultiple(tp.Form()); !ok { @@ -543,8 +549,8 @@ func (tp *TunnelsPage) onImport() { func (tp *TunnelsPage) onExportTunnels() { dlg := walk.FileDialog{ - Filter: "Configuration ZIP Files (*.zip)|*.zip", - Title: "Export tunnels to zip", + Filter: l18n.Sprintf("Configuration ZIP Files (*.zip)|*.zip"), + Title: l18n.Sprintf("Export tunnels to zip"), } if ok, _ := dlg.ShowSave(tp.Form()); !ok { @@ -571,7 +577,7 @@ func (tp *TunnelsPage) swapFiller(enabled bool) bool { func (tp *TunnelsPage) onTunnelsChanged() { if tp.swapFiller(tp.listView.model.RowCount() == 0) { - tp.fillerButton.SetText("Import tunnel(s) from file") + tp.fillerButton.SetText(l18n.Sprintf("Import tunnel(s) from file")) tp.fillerHandler = tp.onImport } } @@ -581,8 +587,9 @@ func (tp *TunnelsPage) onSelectedTunnelsChanged() { return } indices := tp.listView.SelectedIndexes() - if tp.swapFiller(len(indices) > 1) { - tp.fillerButton.SetText(fmt.Sprintf("Delete %d tunnels", len(indices))) + tunnelCount := len(indices) + if tp.swapFiller(tunnelCount > 1) { + tp.fillerButton.SetText(l18n.Sprintf("Delete %d tunnels", tunnelCount)) tp.fillerHandler = tp.onDelete } } diff --git a/ui/ui.go b/ui/ui.go index 22354d12..0279a8dd 100644 --- a/ui/ui.go +++ b/ui/ui.go @@ -15,6 +15,7 @@ import ( "github.com/lxn/win" "golang.org/x/sys/windows" + "golang.zx2c4.com/wireguard/windows/l18n" "golang.zx2c4.com/wireguard/windows/manager" "golang.zx2c4.com/wireguard/windows/version" ) @@ -75,7 +76,7 @@ func RunUI() { tray.UpdateFound() } case manager.UpdateStateUpdatesDisabledUnofficialBuild: - mtw.SetTitle(mtw.Title() + " (unsigned build, no updates)") + mtw.SetTitle(l18n.Sprintf("%s (unsigned build, no updates)", mtw.Title())) } }) } @@ -100,7 +101,7 @@ func RunUI() { if shouldQuitManagerWhenExiting { _, err := manager.IPCClientQuit(true) if err != nil { - showErrorCustom(nil, "Error Exiting WireGuard", fmt.Sprintf("Unable to exit service due to: %v. You may want to stop WireGuard from the service manager.", err)) + showErrorCustom(nil, l18n.Sprintf("Error Exiting WireGuard"), l18n.Sprintf("Unable to exit service due to: %v. You may want to stop WireGuard from the service manager.", err)) } } } @@ -115,7 +116,7 @@ func showError(err error, owner walk.Form) bool { return false } - showErrorCustom(owner, "Error", err.Error()) + showErrorCustom(owner, l18n.Sprintf("Error"), err.Error()) return true } diff --git a/ui/updatepage.go b/ui/updatepage.go index 9e73781f..1ed0b74c 100644 --- a/ui/updatepage.go +++ b/ui/updatepage.go @@ -6,10 +6,9 @@ package ui import ( - "fmt" - "github.com/lxn/walk" + "golang.zx2c4.com/wireguard/windows/l18n" "golang.zx2c4.com/wireguard/windows/manager" "golang.zx2c4.com/wireguard/windows/updater" ) @@ -30,7 +29,7 @@ func NewUpdatePage() (*UpdatePage, error) { } disposables.Add(up) - up.SetTitle("An Update is Available!") + up.SetTitle(l18n.Sprintf("An Update is Available!")) tabIcon, _ := loadSystemIcon("imageres", 1, 16) up.SetImage(tabIcon) @@ -41,14 +40,14 @@ func NewUpdatePage() (*UpdatePage, error) { if err != nil { return nil, err } - instructions.SetText("An update to WireGuard is available. It is highly advisable to update without delay.") + instructions.SetText(l18n.Sprintf("An update to WireGuard is available. It is highly advisable to update without delay.")) instructions.SetMinMaxSize(walk.Size{1, 0}, walk.Size{0, 0}) status, err := walk.NewTextLabel(up) if err != nil { return nil, err } - status.SetText("Status: Waiting for user") + status.SetText(l18n.Sprintf("Status: Waiting for user")) status.SetMinMaxSize(walk.Size{1, 0}, walk.Size{0, 0}) bar, err := walk.NewProgressBar(up) @@ -63,7 +62,7 @@ func NewUpdatePage() (*UpdatePage, error) { } updateIcon, _ := loadSystemIcon("shell32", 46, 32) button.SetImage(updateIcon) - button.SetText("Update Now") + button.SetText(l18n.Sprintf("Update Now")) walk.NewVSpacer(up) @@ -75,7 +74,7 @@ func NewUpdatePage() (*UpdatePage, error) { bar.SetVisible(true) bar.SetMarqueeMode(true) up.SetSuspended(false) - status.SetText("Status: Waiting for updater service") + status.SetText(l18n.Sprintf("Status: Waiting for updater service")) } } @@ -97,7 +96,7 @@ func NewUpdatePage() (*UpdatePage, error) { err := manager.IPCClientUpdate() if err != nil { switchToReadyState() - status.SetText(fmt.Sprintf("Error: %v. Please try again.", err)) + status.SetText(l18n.Sprintf("Error: %v. Please try again.", err)) } }) @@ -106,11 +105,13 @@ func NewUpdatePage() (*UpdatePage, error) { switchToUpdatingState() if dp.Error != nil { switchToReadyState() - status.SetText(fmt.Sprintf("Error: %v. Please try again.", dp.Error)) + err := dp.Error + status.SetText(l18n.Sprintf("Error: %v. Please try again.", err)) return } if len(dp.Activity) > 0 { - status.SetText(fmt.Sprintf("Status: %s", dp.Activity)) + stateText := dp.Activity + status.SetText(l18n.Sprintf("Status: %s", stateText)) } if dp.BytesTotal > 0 { bar.SetMarqueeMode(false) @@ -123,7 +124,7 @@ func NewUpdatePage() (*UpdatePage, error) { } if dp.Complete { switchToReadyState() - status.SetText("Status: Complete!") + status.SetText(l18n.Sprintf("Status: Complete!")) return } }) -- cgit v1.2.3-59-g8ed1b