aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/ui
diff options
context:
space:
mode:
authorSimon Rozman <simon@rozman.si>2019-11-14 09:27:05 +0100
committerJason A. Donenfeld <Jason@zx2c4.com>2020-03-15 14:49:27 -0600
commit8a476b326136f5c03790fa168686848884c8cd5a (patch)
tree3fac4f2940c3012734a4147ef627e2b52a27a859 /ui
parentmanager: chdir into unelevated profile before execing (diff)
downloadwireguard-windows-8a476b326136f5c03790fa168686848884c8cd5a.tar.xz
wireguard-windows-8a476b326136f5c03790fa168686848884c8cd5a.zip
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 <simon@rozman.si>
Diffstat (limited to '')
-rw-r--r--ui/aboutdialog.go12
-rw-r--r--ui/confview.go54
-rw-r--r--ui/editdialog.go34
-rw-r--r--ui/filesave.go7
-rw-r--r--ui/iconprovider.go11
-rw-r--r--ui/logpage.go19
-rw-r--r--ui/managewindow.go7
-rw-r--r--ui/raise.go5
-rw-r--r--ui/tray.go41
-rw-r--r--ui/tunnelspage.go83
-rw-r--r--ui/ui.go7
-rw-r--r--ui/updatepage.go23
12 files changed, 159 insertions, 144 deletions
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
}
})