aboutsummaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
-rw-r--r--COPYING2
-rw-r--r--Makefile38
-rw-r--r--README.md4
-rw-r--r--build.bat22
-rw-r--r--conf/admin_windows.go2
-rw-r--r--conf/config.go76
-rw-r--r--conf/dnsresolver_windows.go63
-rw-r--r--conf/dpapi/dpapi_windows.go28
-rw-r--r--conf/dpapi/dpapi_windows_test.go8
-rwxr-xr-xconf/dpapi/test.exebin3622400 -> 0 bytes
-rw-r--r--conf/filewriter_windows.go5
-rw-r--r--conf/migration_windows.go29
-rw-r--r--conf/mksyscall.go8
-rw-r--r--conf/name.go33
-rw-r--r--conf/parser.go266
-rw-r--r--conf/parser_test.go17
-rw-r--r--conf/path_windows.go18
-rw-r--r--conf/store.go18
-rw-r--r--conf/store_test.go10
-rw-r--r--conf/storewatcher.go2
-rw-r--r--conf/storewatcher_windows.go2
-rw-r--r--conf/writer.go82
-rw-r--r--conf/zsyscall_windows.go50
-rw-r--r--docs/adminregistry.md18
-rw-r--r--docs/attacksurface.md15
-rw-r--r--docs/buildrun.md6
-rw-r--r--docs/enterprise.md45
-rw-r--r--docs/netquirk.md4
-rw-r--r--driver/configuration_windows.go183
-rw-r--r--driver/dll_fromfile_windows.go56
-rw-r--r--driver/dll_fromrsrc_windows.go62
-rw-r--r--driver/dll_windows.go91
-rw-r--r--driver/driver_windows.go170
-rw-r--r--driver/memmod/memmod_windows.go698
-rw-r--r--driver/memmod/memmod_windows_32.go16
-rw-r--r--driver/memmod/memmod_windows_386.go8
-rw-r--r--driver/memmod/memmod_windows_64.go36
-rw-r--r--driver/memmod/memmod_windows_amd64.go8
-rw-r--r--driver/memmod/memmod_windows_arm.go8
-rw-r--r--driver/memmod/memmod_windows_arm64.go8
-rw-r--r--driver/memmod/syscall_windows.go392
-rw-r--r--driver/memmod/syscall_windows_32.go96
-rw-r--r--driver/memmod/syscall_windows_64.go95
-rw-r--r--driver/wintunremoval_windows.go50
-rw-r--r--elevate/doas.go8
-rw-r--r--elevate/loader.go2
-rw-r--r--elevate/membership.go2
-rw-r--r--elevate/privileges.go4
-rw-r--r--elevate/shellexecute.go10
-rw-r--r--embeddable-dll-service/.gitignore4
-rw-r--r--embeddable-dll-service/README.md15
-rw-r--r--embeddable-dll-service/build.bat13
-rw-r--r--embeddable-dll-service/csharp/.gitignore3
-rw-r--r--embeddable-dll-service/csharp/DemoUI/MainWindow.Designer.cs2
-rw-r--r--embeddable-dll-service/csharp/DemoUI/MainWindow.cs60
-rw-r--r--embeddable-dll-service/csharp/DemoUI/Program.cs2
-rw-r--r--embeddable-dll-service/csharp/README.md10
-rw-r--r--embeddable-dll-service/csharp/TunnelDll/Driver.cs234
-rw-r--r--embeddable-dll-service/csharp/TunnelDll/Keypair.cs2
-rw-r--r--embeddable-dll-service/csharp/TunnelDll/Ringlogger.cs2
-rw-r--r--embeddable-dll-service/csharp/TunnelDll/Service.cs12
-rw-r--r--embeddable-dll-service/csharp/TunnelDll/Win32.cs54
-rw-r--r--embeddable-dll-service/main.go13
-rw-r--r--go.mod16
-rw-r--r--go.mod.master3
-rw-r--r--go.sum40
-rw-r--r--gotext.go5
-rw-r--r--installer/build.bat16
-rw-r--r--installer/customactions.c94
-rw-r--r--installer/fetcher/Makefile2
-rw-r--r--installer/fetcher/constants.h2
-rw-r--r--installer/fetcher/crypto.c6
-rw-r--r--installer/fetcher/crypto.h4
-rw-r--r--installer/fetcher/fetcher.c33
-rw-r--r--installer/fetcher/filelist.c2
-rw-r--r--installer/fetcher/filelist.h2
-rw-r--r--installer/fetcher/resources.rc4
-rw-r--r--installer/fetcher/systeminfo.c11
-rw-r--r--installer/fetcher/systeminfo.h3
-rw-r--r--installer/fetcher/version.h2
-rw-r--r--installer/wireguard.wxs10
-rw-r--r--l18n/l18n.go10
-rw-r--r--locales/ca/messages.gotext.json1847
-rw-r--r--locales/cs/messages.gotext.json1907
-rw-r--r--locales/de/messages.gotext.json30
-rw-r--r--locales/es-ES/messages.gotext.json1808
-rw-r--r--locales/et/messages.gotext.json1847
-rw-r--r--locales/fa/messages.gotext.json736
-rw-r--r--locales/fi/messages.gotext.json1364
-rw-r--r--locales/id/messages.gotext.json146
-rw-r--r--locales/it/messages.gotext.json142
-rw-r--r--locales/ja/messages.gotext.json132
-rw-r--r--locales/ko/messages.gotext.json1817
-rw-r--r--locales/nl/messages.gotext.json1665
-rw-r--r--locales/pa-IN/messages.gotext.json268
-rw-r--r--locales/pl/messages.gotext.json28
-rw-r--r--locales/pt-BR/messages.gotext.json1847
-rw-r--r--locales/ru/messages.gotext.json158
-rw-r--r--locales/si-LK/messages.gotext.json1831
-rw-r--r--locales/sk/messages.gotext.json960
-rw-r--r--locales/sl/messages.gotext.json16
-rw-r--r--locales/sv-SE/messages.gotext.json1847
-rw-r--r--locales/tr/messages.gotext.json1847
-rw-r--r--locales/uk/messages.gotext.json1536
-rw-r--r--locales/vi/messages.gotext.json168
-rw-r--r--locales/zh-CN/messages.gotext.json8
-rw-r--r--locales/zh-TW/messages.gotext.json126
-rw-r--r--main.go104
-rw-r--r--manager/install.go51
-rw-r--r--manager/interfacecleanup.go56
-rw-r--r--manager/ipc_client.go17
-rw-r--r--manager/ipc_driver.go61
-rw-r--r--manager/ipc_server.go128
-rw-r--r--manager/ipc_uapi.go71
-rw-r--r--manager/legacystore.go129
-rw-r--r--manager/service.go65
-rw-r--r--manager/tunneltracker.go130
-rw-r--r--manager/uiprocess.go103
-rw-r--r--manager/updatestate.go34
-rw-r--r--quickinstall.bat2
-rw-r--r--resources.rc6
-rw-r--r--ringlogger/cli_test.go2
-rw-r--r--ringlogger/dump.go40
-rw-r--r--ringlogger/global.go20
-rw-r--r--ringlogger/ringlogger.go24
-rw-r--r--services/boot.go47
-rw-r--r--services/errors.go25
-rw-r--r--services/names.go26
-rw-r--r--tunnel/addressconfig.go187
-rw-r--r--tunnel/deterministicguid.go16
-rw-r--r--tunnel/firewall/blocker.go6
-rw-r--r--tunnel/firewall/helpers.go2
-rw-r--r--tunnel/firewall/mksyscall.go2
-rw-r--r--tunnel/firewall/rules.go17
-rw-r--r--tunnel/firewall/syscall_windows.go2
-rw-r--r--tunnel/firewall/types_windows.go8
-rw-r--r--tunnel/firewall/types_windows_32.go4
-rw-r--r--tunnel/firewall/types_windows_64.go4
-rw-r--r--tunnel/firewall/types_windows_test.go29
-rw-r--r--tunnel/interfacewatcher.go116
-rw-r--r--tunnel/ipcpermissions.go63
-rw-r--r--tunnel/mtumonitor.go (renamed from tunnel/defaultroutemonitor.go)59
-rw-r--r--tunnel/pitfalls.go177
-rw-r--r--tunnel/scriptrunner.go2
-rw-r--r--tunnel/service.go149
-rw-r--r--tunnel/winipcfg/interface_change_handler.go2
-rw-r--r--tunnel/winipcfg/luid.go93
-rw-r--r--tunnel/winipcfg/mksyscall.go2
-rw-r--r--tunnel/winipcfg/netsh.go14
-rw-r--r--tunnel/winipcfg/route_change_handler.go2
-rw-r--r--tunnel/winipcfg/types.go186
-rw-r--r--tunnel/winipcfg/types_32.go4
-rw-r--r--tunnel/winipcfg/types_64.go4
-rw-r--r--tunnel/winipcfg/types_test.go3
-rw-r--r--tunnel/winipcfg/types_test_32.go4
-rw-r--r--tunnel/winipcfg/types_test_64.go4
-rw-r--r--tunnel/winipcfg/unicast_address_change_handler.go2
-rw-r--r--tunnel/winipcfg/winipcfg.go12
-rw-r--r--tunnel/winipcfg/winipcfg_test.go90
-rw-r--r--tunnel/winipcfg/zwinipcfg_windows.go10
-rw-r--r--tunnel/wintun_test.go202
-rw-r--r--ui/aboutdialog.go13
-rw-r--r--ui/confview.go14
-rw-r--r--ui/editdialog.go61
-rw-r--r--ui/filesave.go4
-rw-r--r--ui/iconprovider.go10
-rw-r--r--ui/listview.go6
-rw-r--r--ui/logpage.go4
-rw-r--r--ui/managewindow.go8
-rw-r--r--ui/raise.go4
-rw-r--r--ui/syntax/highlighter.go22
-rw-r--r--ui/syntax/syntaxedit.go50
-rw-r--r--ui/tray.go8
-rw-r--r--ui/tunnelspage.go11
-rw-r--r--ui/ui.go14
-rw-r--r--ui/updatepage.go10
-rw-r--r--updater/authenticode.go7
-rw-r--r--updater/constants.go2
-rw-r--r--updater/downloader.go2
-rw-r--r--updater/msirunner.go4
-rw-r--r--updater/signify.go10
-rw-r--r--updater/updater_test.go2
-rw-r--r--updater/versions.go2
-rw-r--r--updater/winhttp/mksyscall.go2
-rw-r--r--updater/winhttp/syscall_windows.go12
-rw-r--r--updater/winhttp/winhttp.go19
-rw-r--r--updater/winhttp/winhttp_test.go2
-rw-r--r--version/certificate_test.go2
-rw-r--r--version/official.go11
-rw-r--r--version/os.go2
-rw-r--r--version/protocol.go28
-rw-r--r--version/useragent.go2
-rw-r--r--version/version.go4
-rw-r--r--zgotext.go5458
194 files changed, 31658 insertions, 4416 deletions
diff --git a/COPYING b/COPYING
index eaf986ca..916eef78 100644
--- a/COPYING
+++ b/COPYING
@@ -1,4 +1,4 @@
-Copyright (C) 2018-2021 WireGuard LLC. All Rights Reserved.
+Copyright (C) 2018-2022 WireGuard LLC. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
diff --git a/Makefile b/Makefile
index a947d313..6a64e164 100644
--- a/Makefile
+++ b/Makefile
@@ -1,4 +1,4 @@
-GOFLAGS := -tags load_wintun_from_rsrc -ldflags="-H windowsgui -s -w" -v -trimpath
+GOFLAGS := -tags load_wgnt_from_rsrc -ldflags="-H windowsgui -s -w" -trimpath -buildvcs=false -v
export GOOS := windows
export PATH := $(CURDIR)/.deps/go/bin:$(PATH)
@@ -10,12 +10,12 @@ RCFLAGS := -DWIREGUARD_VERSION_ARRAY=$(subst $(space),$(comma),$(wordlist 1,4,$(
rwildcard=$(foreach d,$(filter-out .deps,$(wildcard $1*)),$(call rwildcard,$d/,$2) $(filter $(subst *,%,$2),$d))
SOURCE_FILES := $(call rwildcard,,*.go) .deps/go/prepared go.mod go.sum
-RESOURCE_FILES := resources.rc version/version.go manifest.xml $(patsubst %.svg,%.ico,$(wildcard ui/icon/*.svg)) .deps/wintun/prepared
+RESOURCE_FILES := resources.rc version/version.go manifest.xml $(patsubst %.svg,%.ico,$(wildcard ui/icon/*.svg)) .deps/wireguard-nt/prepared
DEPLOYMENT_HOST ?= winvm
DEPLOYMENT_PATH ?= Desktop
-all: amd64/wireguard.exe x86/wireguard.exe arm64/wireguard.exe arm/wireguard.exe
+all: amd64/wireguard.exe x86/wireguard.exe arm64/wireguard.exe
define download =
.distfiles/$(1):
@@ -25,35 +25,33 @@ define download =
if ! mv $$@.unverified $$@; then rm -f $$@.unverified; exit 1; fi
endef
-$(eval $(call download,go.tar.zst,https://download.wireguard.com/windows-toolchain/distfiles/go1.16.2-linux_amd64_2021-03-22.tar.zst,a12882673a0e29842a3ba5bfefd1a41dcb4fd0889e1957c98e33b9a3872190a9))
-$(eval $(call download,wintun.zip,https://www.wintun.net/builds/wintun-0.10.2.zip,fcd9f62f1bd5a550fcb9c21fbb5d6a556214753ccbbd1a3ebad4d318ec9dcbef))
+$(eval $(call download,go.tar.gz,https://go.dev/dl/go1.20.14.linux-amd64.tar.gz,ff445e48af27f93f66bd949ae060d97991c83e11289009d311f25426258f9c44))
+$(eval $(call download,wireguard-nt.zip,https://download.wireguard.com/wireguard-nt/wireguard-nt-0.10.1.zip,772c0b1463d8d2212716f43f06f4594d880dea4f735165bd68e388fc41b81605))
-.deps/go/prepared: .distfiles/go.tar.zst
+.deps/go/prepared: .distfiles/go.tar.gz
mkdir -p .deps
rm -rf .deps/go
- bsdtar -C .deps -xf .distfiles/go.tar.zst
+ bsdtar -C .deps -xf .distfiles/go.tar.gz
+ chmod -R +w .deps/go
touch $@
-.deps/wintun/prepared: .distfiles/wintun.zip
+.deps/wireguard-nt/prepared: .distfiles/wireguard-nt.zip
mkdir -p .deps
- rm -rf .deps/wintun
- bsdtar -C .deps -xf .distfiles/wintun.zip
+ rm -rf .deps/wireguard-nt
+ bsdtar -C .deps -xf .distfiles/wireguard-nt.zip
touch $@
%.ico: %.svg
convert -background none $< -define icon:auto-resize="256,192,128,96,64,48,40,32,24,20,16" -compress zip $@
resources_amd64.syso: $(RESOURCE_FILES)
- x86_64-w64-mingw32-windres $(RCFLAGS) -I .deps/wintun/bin/amd64 -i $< -o $@
+ x86_64-w64-mingw32-windres $(RCFLAGS) -I .deps/wireguard-nt/bin/amd64 -i $< -o $@
resources_386.syso: $(RESOURCE_FILES)
- i686-w64-mingw32-windres $(RCFLAGS) -I .deps/wintun/bin/x86 -i $< -o $@
-
-resources_arm.syso: $(RESOURCE_FILES)
- armv7-w64-mingw32-windres $(RCFLAGS) -I .deps/wintun/bin/arm -i $< -o $@
+ i686-w64-mingw32-windres $(RCFLAGS) -I .deps/wireguard-nt/bin/x86 -i $< -o $@
resources_arm64.syso: $(RESOURCE_FILES)
- aarch64-w64-mingw32-windres $(RCFLAGS) -I .deps/wintun/bin/arm64 -i $< -o $@
+ aarch64-w64-mingw32-windres $(RCFLAGS) -I .deps/wireguard-nt/bin/arm64 -i $< -o $@
amd64/wireguard.exe: export GOARCH := amd64
amd64/wireguard.exe: resources_amd64.syso $(SOURCE_FILES)
@@ -63,11 +61,6 @@ x86/wireguard.exe: export GOARCH := 386
x86/wireguard.exe: resources_386.syso $(SOURCE_FILES)
go build $(GOFLAGS) -o $@
-arm/wireguard.exe: export GOARCH := arm
-arm/wireguard.exe: export GOARM := 7
-arm/wireguard.exe: resources_arm.syso $(SOURCE_FILES)
- go build $(GOFLAGS) -o $@
-
arm64/wireguard.exe: export GOARCH := arm64
arm64/wireguard.exe: resources_arm64.syso $(SOURCE_FILES)
go build $(GOFLAGS) -o $@
@@ -78,6 +71,7 @@ remaster: .deps/go/prepared
rm -f go.sum go.mod
cp go.mod.master go.mod
go get -d
+ sed -i $(shell curl -L 'https://go.dev/dl/?mode=json&include=all' | jq -r '(".windows-amd64.zip",".linux-amd64.tar.gz") as $$suffix | .[0].files[] | select(.filename|endswith($$suffix)) | ("-e", "s/go[0-9][^ ]*\\\($$suffix)\\([ ,]\\)[a-f0-9]\\+/\(.filename)\\1\(.sha256)/") | @sh') Makefile build.bat
fmt: export GOARCH := amd64
fmt: .deps/go/prepared
@@ -98,7 +92,7 @@ deploy: amd64/wireguard.exe
scp $< $(DEPLOYMENT_HOST):$(DEPLOYMENT_PATH)
clean:
- rm -rf *.syso ui/icon/*.ico x86/ amd64/ arm/ arm64/ .deps
+ rm -rf *.syso ui/icon/*.ico x86/ amd64/ arm64/ .deps
distclean: clean
rm -rf .distfiles
diff --git a/README.md b/README.md
index 76abf9dd..4ae2f267 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,6 @@
# [WireGuard](https://www.wireguard.com/) for Windows
-This is a fully-featured WireGuard client for Windows that uses [Wintun](https://www.wintun.net/). It is the only official and recommended way of using WireGuard on Windows.
+This is a fully-featured WireGuard client for Windows that uses [WireGuardNT](https://git.zx2c4.com/wireguard-nt/about/). It is the only official and recommended way of using WireGuard on Windows.
## Download &amp; Install
@@ -24,7 +24,7 @@ In addition to this [`README.md`](README.md), the following documents are also a
This repository is MIT-licensed.
```text
-Copyright (C) 2018-2021 WireGuard LLC. All Rights Reserved.
+Copyright (C) 2018-2022 WireGuard LLC. All Rights Reserved.
Permission is hereby granted, free of charge, to any person obtaining a
copy of this software and associated documentation files (the "Software"),
diff --git a/build.bat b/build.bat
index aa810019..47996c68 100644
--- a/build.bat
+++ b/build.bat
@@ -1,6 +1,6 @@
@echo off
rem SPDX-License-Identifier: MIT
-rem Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+rem Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
setlocal enabledelayedexpansion
set BUILDDIR=%~dp0
@@ -13,15 +13,15 @@ if exist .deps\prepared goto :render
rmdir /s /q .deps 2> NUL
mkdir .deps || goto :error
cd .deps || goto :error
- call :download go.zip https://download.wireguard.com/windows-toolchain/distfiles/go1.16.2-windows_amd64_2021-03-22.zip 4f31feaf91be300e3b75be78e6ebf0b99facbdacb6c1367c8c156617b8be0d35 || goto :error
+ call :download go.zip https://go.dev/dl/go1.20.14.windows-amd64.zip 0e0d0190406ead891d94ecf00f961bb5cfa15ddd47499d2649f12eee80aee110 || goto :error
rem Mirror of https://github.com/mstorsjo/llvm-mingw/releases/download/20201020/llvm-mingw-20201020-msvcrt-x86_64.zip
call :download llvm-mingw-msvcrt.zip https://download.wireguard.com/windows-toolchain/distfiles/llvm-mingw-20201020-msvcrt-x86_64.zip 2e46593245090df96d15e360e092f0b62b97e93866e0162dca7f93b16722b844 || goto :error
rem Mirror of https://imagemagick.org/download/binaries/ImageMagick-7.0.8-42-portable-Q16-x64.zip
call :download imagemagick.zip https://download.wireguard.com/windows-toolchain/distfiles/ImageMagick-7.0.8-42-portable-Q16-x64.zip 584e069f56456ce7dde40220948ff9568ac810688c892c5dfb7f6db902aa05aa "convert.exe colors.xml delegates.xml" || goto :error
rem Mirror of https://sourceforge.net/projects/ezwinports/files/make-4.2.1-without-guile-w32-bin.zip
call :download make.zip https://download.wireguard.com/windows-toolchain/distfiles/make-4.2.1-without-guile-w32-bin.zip 30641be9602712be76212b99df7209f4f8f518ba764cf564262bc9d6e4047cc7 "--strip-components 1 bin" || goto :error
- call :download wireguard-tools.zip https://git.zx2c4.com/wireguard-tools/snapshot/wireguard-tools-1.0.20210223.zip c0cee24d469ecd3f0420dd2cc9747faa67f257a39c17063c10cff99ba62a6fa6 "--exclude wg-quick --strip-components 1" || goto :error
- call :download wintun.zip https://www.wintun.net/builds/wintun-0.10.2.zip fcd9f62f1bd5a550fcb9c21fbb5d6a556214753ccbbd1a3ebad4d318ec9dcbef || goto :error
+ call :download wireguard-tools.zip https://git.zx2c4.com/wireguard-tools/snapshot/wireguard-tools-1ee37b8e4833a25efe6f1fc0d5bdcb476148f4ba.zip ed0739bc3e5a7021a59d4cc4fc63e5fb60a0cb8628d30515a747bfbdcf1fdb0a "--exclude wg-quick --strip-components 1" || goto :error
+ call :download wireguard-nt.zip https://download.wireguard.com/wireguard-nt/wireguard-nt-0.10.1.zip 772c0b1463d8d2212716f43f06f4594d880dea4f735165bd68e388fc41b81605 || goto :error
copy /y NUL prepared > NUL || goto :error
cd .. || goto :error
@@ -43,15 +43,14 @@ if exist .deps\prepared goto :render
)
call :build_plat x86 i686 386 || goto :error
call :build_plat amd64 x86_64 amd64 || goto :error
- call :build_plat arm armv7 arm || goto :error
call :build_plat arm64 aarch64 arm64 || goto :error
:sign
if exist .\sign.bat call .\sign.bat
- if "%SigningCertificate%"=="" goto :success
+ if "%SigningProvider%"=="" goto :success
if "%TimestampServer%"=="" goto :success
echo [+] Signing
- signtool sign /sha1 "%SigningCertificate%" /fd sha256 /tr "%TimestampServer%" /td sha256 /d WireGuard x86\wireguard.exe x86\wg.exe amd64\wireguard.exe amd64\wg.exe arm\wireguard.exe arm\wg.exe arm64\wireguard.exe arm64\wg.exe || goto :error
+ signtool sign %SigningProvider% /fd sha256 /tr "%TimestampServer%" /td sha256 /d WireGuard x86\wireguard.exe x86\wg.exe amd64\wireguard.exe amd64\wg.exe arm64\wireguard.exe arm64\wg.exe || goto :error
:success
echo [+] Success. Launch wireguard.exe.
@@ -72,13 +71,14 @@ if exist .deps\prepared goto :render
set GOARCH=%~3
mkdir %1 >NUL 2>&1
echo [+] Assembling resources %1
- %~2-w64-mingw32-windres -I ".deps\wintun\bin\%~1" -DWIREGUARD_VERSION_ARRAY=%WIREGUARD_VERSION_ARRAY% -DWIREGUARD_VERSION_STR=%WIREGUARD_VERSION% -i resources.rc -o "resources_%~3.syso" -O coff -c 65001 || exit /b %errorlevel%
+ %~2-w64-mingw32-windres -I ".deps\wireguard-nt\bin\%~1" -DWIREGUARD_VERSION_ARRAY=%WIREGUARD_VERSION_ARRAY% -DWIREGUARD_VERSION_STR=%WIREGUARD_VERSION% -i resources.rc -o "resources_%~3.syso" -O coff -c 65001 || exit /b %errorlevel%
echo [+] Building program %1
- go build -tags load_wintun_from_rsrc -ldflags="-H windowsgui -s -w" -trimpath -v -o "%~1\wireguard.exe" || exit /b 1
+ go build -tags load_wgnt_from_rsrc -ldflags="-H windowsgui -s -w" -trimpath -buildvcs=false -v -o "%~1\wireguard.exe" || exit /b 1
if not exist "%~1\wg.exe" (
echo [+] Building command line tools %1
- del .deps\src\*.exe .deps\src\*.o .deps\src\wincompat\*.o 2> NUL
- make --no-print-directory -C .deps\src PLATFORM=windows CC=%~2-w64-mingw32-gcc WINDRES=%~2-w64-mingw32-windres V=1 LDFLAGS=-s RUNSTATEDIR= SYSTEMDUNITDIR= -j%NUMBER_OF_PROCESSORS% || exit /b 1
+ del .deps\src\*.exe .deps\src\*.o .deps\src\wincompat\*.o .deps\src\wincompat\*.lib 2> NUL
+ set LDFLAGS=-s
+ make --no-print-directory -C .deps\src PLATFORM=windows CC=%~2-w64-mingw32-gcc WINDRES=%~2-w64-mingw32-windres V=1 RUNSTATEDIR= SYSTEMDUNITDIR= -j%NUMBER_OF_PROCESSORS% || exit /b 1
move /Y .deps\src\wg.exe "%~1\wg.exe" > NUL || exit /b 1
)
goto :eof
diff --git a/conf/admin_windows.go b/conf/admin_windows.go
index a135aa6d..91d4bdc9 100644
--- a/conf/admin_windows.go
+++ b/conf/admin_windows.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
diff --git a/conf/config.go b/conf/config.go
index 0a6c6abf..74ffacf6 100644
--- a/conf/config.go
+++ b/conf/config.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
@@ -9,9 +9,8 @@ import (
"crypto/rand"
"crypto/subtle"
"encoding/base64"
- "encoding/hex"
"fmt"
- "net"
+ "net/netip"
"strings"
"time"
@@ -22,19 +21,16 @@ import (
const KeyLength = 32
-type IPCidr struct {
- IP net.IP
- Cidr uint8
-}
-
type Endpoint struct {
Host string
Port uint16
}
-type Key [KeyLength]byte
-type HandshakeTime time.Duration
-type Bytes uint64
+type (
+ Key [KeyLength]byte
+ HandshakeTime time.Duration
+ Bytes uint64
+)
type Config struct {
Name string
@@ -44,21 +40,22 @@ type Config struct {
type Interface struct {
PrivateKey Key
- Addresses []IPCidr
+ Addresses []netip.Prefix
ListenPort uint16
MTU uint16
- DNS []net.IP
+ DNS []netip.Addr
DNSSearch []string
PreUp string
PostUp string
PreDown string
PostDown string
+ TableOff bool
}
type Peer struct {
PublicKey Key
PresharedKey Key
- AllowedIPs []IPCidr
+ AllowedIPs []netip.Prefix
Endpoint Endpoint
PersistentKeepalive uint16
@@ -67,34 +64,37 @@ type Peer struct {
LastHandshakeTime HandshakeTime
}
-func (r *IPCidr) String() string {
- return fmt.Sprintf("%s/%d", r.IP.String(), r.Cidr)
-}
-
-func (r *IPCidr) Bits() uint8 {
- if r.IP.To4() != nil {
- return 32
+func (conf *Config) IntersectsWith(other *Config) bool {
+ allRoutes := make(map[netip.Prefix]bool, len(conf.Interface.Addresses)*2+len(conf.Peers)*3)
+ for _, a := range conf.Interface.Addresses {
+ allRoutes[netip.PrefixFrom(a.Addr(), a.Addr().BitLen())] = true
+ allRoutes[a.Masked()] = true
}
- return 128
-}
-
-func (r *IPCidr) IPNet() net.IPNet {
- return net.IPNet{
- IP: r.IP,
- Mask: net.CIDRMask(int(r.Cidr), int(r.Bits())),
+ for i := range conf.Peers {
+ for _, a := range conf.Peers[i].AllowedIPs {
+ allRoutes[a.Masked()] = true
+ }
}
-}
-
-func (r *IPCidr) MaskSelf() {
- bits := int(r.Bits())
- mask := net.CIDRMask(int(r.Cidr), bits)
- for i := 0; i < bits/8; i++ {
- r.IP[i] &= mask[i]
+ for _, a := range other.Interface.Addresses {
+ if allRoutes[netip.PrefixFrom(a.Addr(), a.Addr().BitLen())] {
+ return true
+ }
+ if allRoutes[a.Masked()] {
+ return true
+ }
}
+ for i := range other.Peers {
+ for _, a := range other.Peers[i].AllowedIPs {
+ if allRoutes[a.Masked()] {
+ return true
+ }
+ }
+ }
+ return false
}
func (e *Endpoint) String() string {
- if strings.IndexByte(e.Host, ':') > 0 {
+ if strings.IndexByte(e.Host, ':') != -1 {
return fmt.Sprintf("[%s]:%d", e.Host, e.Port)
}
return fmt.Sprintf("%s:%d", e.Host, e.Port)
@@ -108,10 +108,6 @@ func (k *Key) String() string {
return base64.StdEncoding.EncodeToString(k[:])
}
-func (k *Key) HexString() string {
- return hex.EncodeToString(k[:])
-}
-
func (k *Key) IsZero() bool {
var zeros Key
return subtle.ConstantTimeCompare(zeros[:], k[:]) == 1
diff --git a/conf/dnsresolver_windows.go b/conf/dnsresolver_windows.go
index b17be849..a299c475 100644
--- a/conf/dnsresolver_windows.go
+++ b/conf/dnsresolver_windows.go
@@ -1,28 +1,26 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
import (
- "fmt"
"log"
- "net"
- "syscall"
+ "net/netip"
"time"
"unsafe"
+ "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
+
"golang.org/x/sys/windows"
+ "golang.zx2c4.com/wireguard/windows/services"
)
-//sys internetGetConnectedState(flags *uint32, reserved uint32) (connected bool) = wininet.InternetGetConnectedState
-
func resolveHostname(name string) (resolvedIPString string, err error) {
maxTries := 10
- systemJustBooted := windows.DurationSinceBoot() <= time.Minute*4
- if systemJustBooted {
- maxTries *= 4
+ if services.StartedAtBoot() {
+ maxTries *= 3
}
for i := 0; i < maxTries; i++ {
if i > 0 {
@@ -33,12 +31,11 @@ func resolveHostname(name string) (resolvedIPString string, err error) {
return
}
if err == windows.WSATRY_AGAIN {
- log.Printf("Temporary DNS error when resolving %s, sleeping for 4 seconds", name)
+ log.Printf("Temporary DNS error when resolving %s, so sleeping for 4 seconds", name)
continue
}
- var state uint32
- if err == windows.WSAHOST_NOT_FOUND && systemJustBooted && !internetGetConnectedState(&state, 0) {
- log.Printf("Host not found when resolving %s, but no Internet connection available, sleeping for 4 seconds", name)
+ if err == windows.WSAHOST_NOT_FOUND && services.StartedAtBoot() {
+ log.Printf("Host not found when resolving %s at boot time, so sleeping for 4 seconds", name)
continue
}
return
@@ -66,25 +63,35 @@ func resolveHostnameOnce(name string) (resolvedIPString string, err error) {
return
}
defer windows.FreeAddrInfoW(result)
- ipv6 := ""
+ var v6 netip.Addr
for ; result != nil; result = result.Next {
- switch result.Family {
- case windows.AF_INET:
- return (net.IP)((*syscall.RawSockaddrInet4)(unsafe.Pointer(result.Addr)).Addr[:]).String(), nil
- case windows.AF_INET6:
- if len(ipv6) != 0 {
- continue
- }
- a := (*syscall.RawSockaddrInet6)(unsafe.Pointer(result.Addr))
- ipv6 = (net.IP)(a.Addr[:]).String()
- if a.Scope_id != 0 {
- ipv6 += fmt.Sprintf("%%%d", a.Scope_id)
- }
+ if result.Family != windows.AF_INET && result.Family != windows.AF_INET6 {
+ continue
+ }
+ addr := (*winipcfg.RawSockaddrInet)(unsafe.Pointer(result.Addr)).Addr()
+ if addr.Is4() {
+ return addr.String(), nil
+ } else if !v6.IsValid() && addr.Is6() {
+ v6 = addr
}
}
- if len(ipv6) != 0 {
- return ipv6, nil
+ if v6.IsValid() {
+ return v6.String(), nil
}
err = windows.WSAHOST_NOT_FOUND
return
}
+
+func (config *Config) ResolveEndpoints() error {
+ for i := range config.Peers {
+ if config.Peers[i].Endpoint.IsEmpty() {
+ continue
+ }
+ var err error
+ config.Peers[i].Endpoint.Host, err = resolveHostname(config.Peers[i].Endpoint.Host)
+ if err != nil {
+ return err
+ }
+ }
+ return nil
+}
diff --git a/conf/dpapi/dpapi_windows.go b/conf/dpapi/dpapi_windows.go
index b3f28a93..49a32915 100644
--- a/conf/dpapi/dpapi_windows.go
+++ b/conf/dpapi/dpapi_windows.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package dpapi
@@ -28,16 +28,9 @@ func Encrypt(data []byte, name string) ([]byte, error) {
if err != nil {
return nil, fmt.Errorf("unable to encrypt DPAPI protected data: %w", err)
}
-
- outSlice := *(*[]byte)(unsafe.Pointer(&(struct {
- addr *byte
- len int
- cap int
- }{out.Data, int(out.Size), int(out.Size)})))
- ret := make([]byte, len(outSlice))
- copy(ret, outSlice)
+ ret := make([]byte, out.Size)
+ copy(ret, unsafe.Slice(out.Data, out.Size))
windows.LocalFree(windows.Handle(unsafe.Pointer(out.Data)))
-
return ret, nil
}
@@ -48,19 +41,12 @@ func Decrypt(data []byte, name string) ([]byte, error) {
if err != nil {
return nil, err
}
-
err = windows.CryptUnprotectData(bytesToBlob(data), &outName, nil, 0, nil, windows.CRYPTPROTECT_UI_FORBIDDEN, &out)
if err != nil {
return nil, fmt.Errorf("unable to decrypt DPAPI protected data: %w", err)
}
-
- outSlice := *(*[]byte)(unsafe.Pointer(&(struct {
- addr *byte
- len int
- cap int
- }{out.Data, int(out.Size), int(out.Size)})))
- ret := make([]byte, len(outSlice))
- copy(ret, outSlice)
+ ret := make([]byte, out.Size)
+ copy(ret, unsafe.Slice(out.Data, out.Size))
windows.LocalFree(windows.Handle(unsafe.Pointer(out.Data)))
// Note: this ridiculous open-coded strcmp is not constant time.
@@ -75,8 +61,8 @@ func Decrypt(data []byte, name string) ([]byte, error) {
if *a == 0 || *b == 0 {
break
}
- a = (*uint16)(unsafe.Pointer(uintptr(unsafe.Pointer(a)) + 2))
- b = (*uint16)(unsafe.Pointer(uintptr(unsafe.Pointer(b)) + 2))
+ a = (*uint16)(unsafe.Add(unsafe.Pointer(a), 2))
+ b = (*uint16)(unsafe.Add(unsafe.Pointer(b), 2))
}
runtime.KeepAlive(utf16Name)
windows.LocalFree(windows.Handle(unsafe.Pointer(outName)))
diff --git a/conf/dpapi/dpapi_windows_test.go b/conf/dpapi/dpapi_windows_test.go
index 2e12e273..fd7307e6 100644
--- a/conf/dpapi/dpapi_windows_test.go
+++ b/conf/dpapi/dpapi_windows_test.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package dpapi
@@ -53,11 +53,7 @@ func TestRoundTrip(t *testing.T) {
if err != nil {
t.Errorf("Unable to get utf16 chars for name: %s", err)
}
- nameUtf16Bytes := *(*[]byte)(unsafe.Pointer(&struct {
- addr *byte
- len int
- cap int
- }{(*byte)(unsafe.Pointer(&nameUtf16[0])), len(nameUtf16) * 2, cap(nameUtf16) * 2}))
+ nameUtf16Bytes := unsafe.Slice((*byte)(unsafe.Pointer(&nameUtf16[0])), len(nameUtf16)*2)
i := bytes.Index(eCorrupt, nameUtf16Bytes)
if i == -1 {
t.Error("Unable to find ad in blob")
diff --git a/conf/dpapi/test.exe b/conf/dpapi/test.exe
deleted file mode 100755
index 9e5f23a7..00000000
--- a/conf/dpapi/test.exe
+++ /dev/null
Binary files differ
diff --git a/conf/filewriter_windows.go b/conf/filewriter_windows.go
index b0fca73e..c6bb2b45 100644
--- a/conf/filewriter_windows.go
+++ b/conf/filewriter_windows.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
@@ -8,6 +8,7 @@ package conf
import (
"crypto/rand"
"encoding/hex"
+ "path/filepath"
"sync/atomic"
"unsafe"
@@ -40,7 +41,7 @@ func writeLockedDownFile(destination string, overwrite bool, contents []byte) er
if err != nil {
return err
}
- tmpDestination := randomFileName()
+ tmpDestination := filepath.Join(filepath.Dir(destination), randomFileName())
tmpDestination16, err := windows.UTF16PtrFromString(tmpDestination)
if err != nil {
return err
diff --git a/conf/migration_windows.go b/conf/migration_windows.go
index 091efa32..ed288f3c 100644
--- a/conf/migration_windows.go
+++ b/conf/migration_windows.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
@@ -18,12 +18,19 @@ import (
"golang.org/x/sys/windows"
)
-var migrating sync.Mutex
-var lastMigrationTimer *time.Timer
+var (
+ migrating sync.Mutex
+ lastMigrationTimer *time.Timer
+)
+
+type MigrationCallback func(name, oldPath, newPath string)
-func MigrateUnencryptedConfigs() { migrateUnencryptedConfigs(3) }
+func MigrateUnencryptedConfigs(migrated MigrationCallback) { migrateUnencryptedConfigs(3, migrated) }
-func migrateUnencryptedConfigs(sharingBase int) {
+func migrateUnencryptedConfigs(sharingBase int, migrated MigrationCallback) {
+ if migrated == nil {
+ migrated = func(_, _, _ string) {}
+ }
migrating.Lock()
defer migrating.Unlock()
configFileDir, err := tunnelConfigurationsDirectory()
@@ -48,12 +55,13 @@ func migrateUnencryptedConfigs(sharingBase int) {
if err != nil {
continue
}
- if info.Mode().Perm()&0444 == 0 {
+ if info.Mode().Perm()&0o444 == 0 {
continue
}
var bytes []byte
var config *Config
+ var newPath string
// We don't use os.ReadFile, because we actually want RDWR, so that we can take advantage
// of Windows file locking for ensuring the file is finished being written.
f, err := os.OpenFile(path, os.O_RDWR, 0)
@@ -65,7 +73,7 @@ func migrateUnencryptedConfigs(sharingBase int) {
if lastMigrationTimer != nil {
lastMigrationTimer.Stop()
}
- lastMigrationTimer = time.AfterFunc(time.Second/time.Duration(sharingBase*sharingBase), func() { migrateUnencryptedConfigs(sharingBase - 1) })
+ lastMigrationTimer = time.AfterFunc(time.Second/time.Duration(sharingBase*sharingBase), func() { migrateUnencryptedConfigs(sharingBase-1, migrated) })
ignoreSharingViolations = true
continue
}
@@ -87,8 +95,13 @@ func migrateUnencryptedConfigs(sharingBase int) {
}
err = os.Remove(path)
if err != nil {
- log.Printf("Unable to remove old path %#q: %v", path, err)
+ goto error
+ }
+ newPath, err = config.Path()
+ if err != nil {
+ goto error
}
+ migrated(config.Name, path, newPath)
continue
error:
log.Printf("Unable to ingest and encrypt %#q: %v", path, err)
diff --git a/conf/mksyscall.go b/conf/mksyscall.go
deleted file mode 100644
index c7ed0e4f..00000000
--- a/conf/mksyscall.go
+++ /dev/null
@@ -1,8 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
- */
-
-package conf
-
-//go:generate go run golang.org/x/sys/windows/mkwinsyscall -output zsyscall_windows.go dnsresolver_windows.go migration_windows.go storewatcher_windows.go
diff --git a/conf/name.go b/conf/name.go
index a4affb48..0d084070 100644
--- a/conf/name.go
+++ b/conf/name.go
@@ -1,11 +1,12 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
import (
+ "errors"
"regexp"
"strconv"
"strings"
@@ -17,15 +18,13 @@ var reservedNames = []string{
"LPT1", "LPT2", "LPT3", "LPT4", "LPT5", "LPT6", "LPT7", "LPT8", "LPT9",
}
-const serviceNameForbidden = "$"
-const netshellDllForbidden = "\\/:*?\"<>|\t"
-const specialChars = "/\\<>:\"|?*\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x00"
-
-var allowedNameFormat *regexp.Regexp
+const (
+ serviceNameForbidden = "$"
+ netshellDllForbidden = "\\/:*?\"<>|\t"
+ specialChars = "/\\<>:\"|?*\x01\x02\x03\x04\x05\x06\x07\x08\x09\x0a\x0b\x0c\x0d\x0e\x0f\x10\x11\x12\x13\x14\x15\x16\x17\x18\x19\x1a\x1b\x1c\x1d\x1e\x1f\x00"
+)
-func init() {
- allowedNameFormat = regexp.MustCompile("^[a-zA-Z0-9_=+.-]{1,32}$")
-}
+var allowedNameFormat = regexp.MustCompile("^[a-zA-Z0-9_=+.-]{1,32}$")
func isReserved(name string) bool {
if len(name) == 0 {
@@ -35,6 +34,14 @@ func isReserved(name string) bool {
if strings.EqualFold(name, reserved) {
return true
}
+ for i := len(name) - 1; i >= 0; i-- {
+ if name[i] == '.' {
+ if strings.EqualFold(name[:i], reserved) {
+ return true
+ }
+ break
+ }
+ }
}
return false
}
@@ -55,6 +62,7 @@ type naturalSortToken struct {
maybeString string
maybeNumber int
}
+
type naturalSortString struct {
originalString string
tokens []naturalSortToken
@@ -110,3 +118,10 @@ func TunnelNameIsLess(a, b string) bool {
}
return false
}
+
+func ServiceNameOfTunnel(tunnelName string) (string, error) {
+ if !TunnelNameIsValid(tunnelName) {
+ return "", errors.New("Tunnel name is not valid")
+ }
+ return "WireGuardTunnel$" + tunnelName, nil
+}
diff --git a/conf/parser.go b/conf/parser.go
index bd08ee6c..b1da9816 100644
--- a/conf/parser.go
+++ b/conf/parser.go
@@ -1,22 +1,20 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
import (
- "bufio"
"encoding/base64"
- "encoding/hex"
- "io"
- "net"
+ "net/netip"
"strconv"
"strings"
- "time"
+ "golang.org/x/sys/windows"
"golang.org/x/text/encoding/unicode"
+ "golang.zx2c4.com/wireguard/windows/driver"
"golang.zx2c4.com/wireguard/windows/l18n"
)
@@ -29,43 +27,16 @@ func (e *ParseError) Error() string {
return l18n.Sprintf("%s: %q", e.why, e.offender)
}
-func parseIPCidr(s string) (ipcidr *IPCidr, err error) {
- var addrStr, cidrStr string
- var cidr int
-
- i := strings.IndexByte(s, '/')
- if i < 0 {
- addrStr = s
- } else {
- addrStr, cidrStr = s[:i], s[i+1:]
- }
-
- err = &ParseError{l18n.Sprintf("Invalid IP address"), s}
- addr := net.ParseIP(addrStr)
- if addr == nil {
- return
+func parseIPCidr(s string) (netip.Prefix, error) {
+ ipcidr, err := netip.ParsePrefix(s)
+ if err == nil {
+ return ipcidr, nil
}
- maybeV4 := addr.To4()
- if maybeV4 != nil {
- addr = maybeV4
- }
- if len(cidrStr) > 0 {
- err = &ParseError{l18n.Sprintf("Invalid network prefix length"), s}
- cidr, err = strconv.Atoi(cidrStr)
- if err != nil || cidr < 0 || cidr > 128 {
- return
- }
- if cidr > 32 && maybeV4 != nil {
- return
- }
- } else {
- if maybeV4 != nil {
- cidr = 32
- } else {
- cidr = 128
- }
+ addr, err := netip.ParseAddr(s)
+ if err != nil {
+ return netip.Prefix{}, &ParseError{l18n.Sprintf("Invalid IP address: "), s}
}
- return &IPCidr{addr, uint8(cidr)}, nil
+ return netip.PrefixFrom(addr, addr.BitLen()), nil
}
func parseEndpoint(s string) (*Endpoint, error) {
@@ -89,8 +60,8 @@ func parseEndpoint(s string) (*Endpoint, error) {
if i := strings.LastIndexByte(host, '%'); i > 1 {
end = i
}
- maybeV6 := net.ParseIP(host[1:end])
- if maybeV6 == nil || len(maybeV6) != net.IPv6len {
+ maybeV6, err2 := netip.ParseAddr(host[1:end])
+ if err2 != nil || !maybeV6.Is6() {
return nil, err
}
} else {
@@ -98,7 +69,7 @@ func parseEndpoint(s string) (*Endpoint, error) {
}
host = host[1 : len(host)-1]
}
- return &Endpoint{host, uint16(port)}, nil
+ return &Endpoint{host, port}, nil
}
func parseMTU(s string) (uint16, error) {
@@ -137,21 +108,18 @@ func parsePersistentKeepalive(s string) (uint16, error) {
return uint16(m), nil
}
-func parseKeyBase64(s string) (*Key, error) {
- k, err := base64.StdEncoding.DecodeString(s)
- if err != nil {
- return nil, &ParseError{l18n.Sprintf("Invalid key: %v", err), s}
- }
- if len(k) != KeyLength {
- return nil, &ParseError{l18n.Sprintf("Keys must decode to exactly 32 bytes"), s}
+func parseTableOff(s string) (bool, error) {
+ if s == "off" {
+ return true, nil
+ } else if s == "auto" || s == "main" {
+ return false, nil
}
- var key Key
- copy(key[:], k)
- return &key, nil
+ _, err := strconv.ParseUint(s, 10, 32)
+ return false, err
}
-func parseKeyHex(s string) (*Key, error) {
- k, err := hex.DecodeString(s)
+func parseKeyBase64(s string) (*Key, error) {
+ k, err := base64.StdEncoding.DecodeString(s)
if err != nil {
return nil, &ParseError{l18n.Sprintf("Invalid key: %v", err), s}
}
@@ -163,14 +131,6 @@ func parseKeyHex(s string) (*Key, error) {
return &key, nil
}
-func parseBytesOrStamp(s string) (uint64, error) {
- b, err := strconv.ParseUint(s, 10, 64)
- if err != nil {
- return 0, &ParseError{l18n.Sprintf("Number must be a number between 0 and 2^64-1: %v", err), s}
- }
- return b, nil
-}
-
func splitList(s string) ([]string, error) {
var out []string
for _, split := range strings.Split(s, ",") {
@@ -197,7 +157,7 @@ func (c *Config) maybeAddPeer(p *Peer) {
}
}
-func FromWgQuick(s string, name string) (*Config, error) {
+func FromWgQuick(s, name string) (*Config, error) {
if !TunnelNameIsValid(name) {
return nil, &ParseError{l18n.Sprintf("Tunnel name is not valid"), name}
}
@@ -207,10 +167,7 @@ func FromWgQuick(s string, name string) (*Config, error) {
sawPrivateKey := false
var peer *Peer
for _, line := range lines {
- pound := strings.IndexByte(line, '#')
- if pound >= 0 {
- line = line[:pound]
- }
+ line, _, _ = strings.Cut(line, "#")
line = strings.TrimSpace(line)
lineLower := strings.ToLower(line)
if len(line) == 0 {
@@ -269,7 +226,7 @@ func FromWgQuick(s string, name string) (*Config, error) {
if err != nil {
return nil, err
}
- conf.Interface.Addresses = append(conf.Interface.Addresses, *a)
+ conf.Interface.Addresses = append(conf.Interface.Addresses, a)
}
case "dns":
addresses, err := splitList(val)
@@ -277,8 +234,8 @@ func FromWgQuick(s string, name string) (*Config, error) {
return nil, err
}
for _, address := range addresses {
- a := net.ParseIP(address)
- if a == nil {
+ a, err := netip.ParseAddr(address)
+ if err != nil {
conf.Interface.DNSSearch = append(conf.Interface.DNSSearch, address)
} else {
conf.Interface.DNS = append(conf.Interface.DNS, a)
@@ -292,6 +249,12 @@ func FromWgQuick(s string, name string) (*Config, error) {
conf.Interface.PreDown = val
case "postdown":
conf.Interface.PostDown = val
+ case "table":
+ tableOff, err := parseTableOff(val)
+ if err != nil {
+ return nil, err
+ }
+ conf.Interface.TableOff = tableOff
default:
return nil, &ParseError{l18n.Sprintf("Invalid key for [Interface] section"), key}
}
@@ -319,7 +282,7 @@ func FromWgQuick(s string, name string) (*Config, error) {
if err != nil {
return nil, err
}
- peer.AllowedIPs = append(peer.AllowedIPs, *a)
+ peer.AllowedIPs = append(peer.AllowedIPs, a)
}
case "persistentkeepalive":
p, err := parsePersistentKeepalive(val)
@@ -352,7 +315,7 @@ func FromWgQuick(s string, name string) (*Config, error) {
return &conf, nil
}
-func FromWgQuickWithUnknownEncoding(s string, name string) (*Config, error) {
+func FromWgQuickWithUnknownEncoding(s, name string) (*Config, error) {
c, firstErr := FromWgQuick(s, name)
if firstErr == nil {
return c, nil
@@ -369,8 +332,7 @@ func FromWgQuickWithUnknownEncoding(s string, name string) (*Config, error) {
return nil, firstErr
}
-func FromUAPI(reader io.Reader, existingConfig *Config) (*Config, error) {
- parserState := inInterfaceSection
+func FromDriverConfiguration(interfaze *driver.Interface, existingConfig *Config) *Config {
conf := Config{
Name: existingConfig.Name,
Interface: Interface{
@@ -382,125 +344,57 @@ func FromUAPI(reader io.Reader, existingConfig *Config) (*Config, error) {
PostUp: existingConfig.Interface.PostUp,
PreDown: existingConfig.Interface.PreDown,
PostDown: existingConfig.Interface.PostDown,
+ TableOff: existingConfig.Interface.TableOff,
},
}
- var peer *Peer
- lineReader := bufio.NewReader(reader)
- for {
- line, err := lineReader.ReadString('\n')
- if err != nil {
- return nil, err
+ if interfaze.Flags&driver.InterfaceHasPrivateKey != 0 {
+ conf.Interface.PrivateKey = interfaze.PrivateKey
+ }
+ if interfaze.Flags&driver.InterfaceHasListenPort != 0 {
+ conf.Interface.ListenPort = interfaze.ListenPort
+ }
+ var p *driver.Peer
+ for i := uint32(0); i < interfaze.PeerCount; i++ {
+ if p == nil {
+ p = interfaze.FirstPeer()
+ } else {
+ p = p.NextPeer()
}
- line = line[:len(line)-1]
- if len(line) == 0 {
- break
+ peer := Peer{}
+ if p.Flags&driver.PeerHasPublicKey != 0 {
+ peer.PublicKey = p.PublicKey
}
- equals := strings.IndexByte(line, '=')
- if equals < 0 {
- return nil, &ParseError{l18n.Sprintf("Config key is missing an equals separator"), line}
+ if p.Flags&driver.PeerHasPresharedKey != 0 {
+ peer.PresharedKey = p.PresharedKey
}
- key, val := line[:equals], line[equals+1:]
- if len(val) == 0 {
- return nil, &ParseError{l18n.Sprintf("Key must have a value"), line}
+ if p.Flags&driver.PeerHasEndpoint != 0 {
+ peer.Endpoint.Port = p.Endpoint.Port()
+ peer.Endpoint.Host = p.Endpoint.Addr().String()
}
- switch key {
- case "public_key":
- conf.maybeAddPeer(peer)
- peer = &Peer{}
- parserState = inPeerSection
- case "errno":
- if val == "0" {
- continue
- } else {
- return nil, &ParseError{l18n.Sprintf("Error in getting configuration"), val}
- }
+ if p.Flags&driver.PeerHasPersistentKeepalive != 0 {
+ peer.PersistentKeepalive = p.PersistentKeepalive
}
- if parserState == inInterfaceSection {
- switch key {
- case "private_key":
- k, err := parseKeyHex(val)
- if err != nil {
- return nil, err
- }
- conf.Interface.PrivateKey = *k
- case "listen_port":
- p, err := parsePort(val)
- if err != nil {
- return nil, err
- }
- conf.Interface.ListenPort = p
- case "fwmark":
- // Ignored for now.
-
- default:
- return nil, &ParseError{l18n.Sprintf("Invalid key for interface section"), key}
+ peer.TxBytes = Bytes(p.TxBytes)
+ peer.RxBytes = Bytes(p.RxBytes)
+ if p.LastHandshake != 0 {
+ peer.LastHandshakeTime = HandshakeTime((p.LastHandshake - 116444736000000000) * 100)
+ }
+ var a *driver.AllowedIP
+ for j := uint32(0); j < p.AllowedIPsCount; j++ {
+ if a == nil {
+ a = p.FirstAllowedIP()
+ } else {
+ a = a.NextAllowedIP()
}
- } else if parserState == inPeerSection {
- switch key {
- case "public_key":
- k, err := parseKeyHex(val)
- if err != nil {
- return nil, err
- }
- peer.PublicKey = *k
- case "preshared_key":
- k, err := parseKeyHex(val)
- if err != nil {
- return nil, err
- }
- peer.PresharedKey = *k
- case "protocol_version":
- if val != "1" {
- return nil, &ParseError{l18n.Sprintf("Protocol version must be 1"), val}
- }
- case "allowed_ip":
- a, err := parseIPCidr(val)
- if err != nil {
- return nil, err
- }
- peer.AllowedIPs = append(peer.AllowedIPs, *a)
- case "persistent_keepalive_interval":
- p, err := parsePersistentKeepalive(val)
- if err != nil {
- return nil, err
- }
- peer.PersistentKeepalive = p
- case "endpoint":
- e, err := parseEndpoint(val)
- if err != nil {
- return nil, err
- }
- peer.Endpoint = *e
- case "tx_bytes":
- b, err := parseBytesOrStamp(val)
- if err != nil {
- return nil, err
- }
- peer.TxBytes = Bytes(b)
- case "rx_bytes":
- b, err := parseBytesOrStamp(val)
- if err != nil {
- return nil, err
- }
- peer.RxBytes = Bytes(b)
- case "last_handshake_time_sec":
- t, err := parseBytesOrStamp(val)
- if err != nil {
- return nil, err
- }
- peer.LastHandshakeTime += HandshakeTime(time.Duration(t) * time.Second)
- case "last_handshake_time_nsec":
- t, err := parseBytesOrStamp(val)
- if err != nil {
- return nil, err
- }
- peer.LastHandshakeTime += HandshakeTime(time.Duration(t) * time.Nanosecond)
- default:
- return nil, &ParseError{l18n.Sprintf("Invalid key for peer section"), key}
+ var ip netip.Addr
+ if a.AddressFamily == windows.AF_INET {
+ ip = netip.AddrFrom4(*(*[4]byte)(a.Address[:4]))
+ } else if a.AddressFamily == windows.AF_INET6 {
+ ip = netip.AddrFrom16(*(*[16]byte)(a.Address[:16]))
}
+ peer.AllowedIPs = append(peer.AllowedIPs, netip.PrefixFrom(ip, int(a.Cidr)))
}
+ conf.Peers = append(conf.Peers, peer)
}
- conf.maybeAddPeer(peer)
-
- return &conf, nil
+ return &conf
}
diff --git a/conf/parser_test.go b/conf/parser_test.go
index f80d6d18..25d906fd 100644
--- a/conf/parser_test.go
+++ b/conf/parser_test.go
@@ -1,12 +1,12 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
import (
- "net"
+ "net/netip"
"reflect"
"runtime"
"testing"
@@ -45,7 +45,7 @@ func noError(t *testing.T, err error) bool {
return false
}
-func equal(t *testing.T, expected, actual interface{}) bool {
+func equal(t *testing.T, expected, actual any) bool {
if reflect.DeepEqual(expected, actual) {
return true
}
@@ -53,7 +53,8 @@ func equal(t *testing.T, expected, actual interface{}) bool {
t.Errorf("Failed equals at %s:%d\nactual %#v\nexpected %#v", fn, line, actual, expected)
return false
}
-func lenTest(t *testing.T, actualO interface{}, expected int) bool {
+
+func lenTest(t *testing.T, actualO any, expected int) bool {
actual := reflect.ValueOf(actualO).Len()
if reflect.DeepEqual(expected, actual) {
return true
@@ -62,7 +63,8 @@ func lenTest(t *testing.T, actualO interface{}, expected int) bool {
t.Errorf("Wrong length at %s:%d\nactual %#v\nexpected %#v", fn, line, actual, expected)
return false
}
-func contains(t *testing.T, list, element interface{}) bool {
+
+func contains(t *testing.T, list, element any) bool {
listValue := reflect.ValueOf(list)
for i := 0; i < listValue.Len(); i++ {
if reflect.DeepEqual(listValue.Index(i).Interface(), element) {
@@ -77,10 +79,9 @@ func contains(t *testing.T, list, element interface{}) bool {
func TestFromWgQuick(t *testing.T) {
conf, err := FromWgQuick(testInput, "test")
if noError(t, err) {
-
lenTest(t, conf.Interface.Addresses, 2)
- contains(t, conf.Interface.Addresses, IPCidr{net.IPv4(10, 10, 0, 1), uint8(16)})
- contains(t, conf.Interface.Addresses, IPCidr{net.IPv4(10, 192, 122, 1), uint8(24)})
+ contains(t, conf.Interface.Addresses, netip.PrefixFrom(netip.AddrFrom4([4]byte{0, 10, 0, 1}), 16))
+ contains(t, conf.Interface.Addresses, netip.PrefixFrom(netip.AddrFrom4([4]byte{10, 192, 122, 1}), 24))
equal(t, "yAnz5TF+lXXJte14tji3zlMNq+hd2rYUIgJBgB3fBmk=", conf.Interface.PrivateKey.String())
equal(t, uint16(51820), conf.Interface.ListenPort)
diff --git a/conf/path_windows.go b/conf/path_windows.go
index e9ff783a..0ff0a057 100644
--- a/conf/path_windows.go
+++ b/conf/path_windows.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
@@ -15,8 +15,10 @@ import (
"golang.org/x/sys/windows"
)
-var cachedConfigFileDir string
-var cachedRootDir string
+var (
+ cachedConfigFileDir string
+ cachedRootDir string
+)
func tunnelConfigurationsDirectory() (string, error) {
if cachedConfigFileDir != "" {
@@ -27,7 +29,7 @@ func tunnelConfigurationsDirectory() (string, error) {
return "", err
}
c := filepath.Join(root, "Configurations")
- err = os.Mkdir(c, os.ModeDir|0700)
+ err = os.Mkdir(c, os.ModeDir|0o700)
if err != nil && !os.IsExist(err) {
return "", err
}
@@ -126,3 +128,11 @@ func RootDirectory(create bool) (string, error) {
cachedRootDir = data
return cachedRootDir, nil
}
+
+func LogFile(createRoot bool) (string, error) {
+ root, err := RootDirectory(createRoot)
+ if err != nil {
+ return "", err
+ }
+ return filepath.Join(root, "log.bin"), nil
+}
diff --git a/conf/store.go b/conf/store.go
index f6f450c6..02807b77 100644
--- a/conf/store.go
+++ b/conf/store.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
@@ -14,8 +14,10 @@ import (
"golang.zx2c4.com/wireguard/windows/conf/dpapi"
)
-const configFileSuffix = ".conf.dpapi"
-const configFileUnencryptedSuffix = ".conf"
+const (
+ configFileSuffix = ".conf.dpapi"
+ configFileUnencryptedSuffix = ".conf"
+)
func ListConfigNames() ([]string, error) {
configFileDir, err := tunnelConfigurationsDirectory()
@@ -29,8 +31,8 @@ func ListConfigNames() ([]string, error) {
configs := make([]string, len(files))
i := 0
for _, file := range files {
- name := filepath.Base(file.Name())
- if len(name) <= len(configFileSuffix) || !strings.HasSuffix(name, configFileSuffix) {
+ name, err := NameFromPath(file.Name())
+ if err != nil {
continue
}
if !file.Type().IsRegular() {
@@ -40,11 +42,7 @@ func ListConfigNames() ([]string, error) {
if err != nil {
continue
}
- if info.Mode().Perm()&0444 == 0 {
- continue
- }
- name = strings.TrimSuffix(name, configFileSuffix)
- if !TunnelNameIsValid(name) {
+ if info.Mode().Perm()&0o444 == 0 {
continue
}
configs[i] = name
diff --git a/conf/store_test.go b/conf/store_test.go
index 3cec0035..3427a2b1 100644
--- a/conf/store_test.go
+++ b/conf/store_test.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
@@ -17,7 +17,7 @@ func TestStorage(t *testing.T) {
return
}
- err = c.Save()
+ err = c.Save(true)
if err != nil {
t.Errorf("Unable to save config: %s", err.Error())
}
@@ -54,7 +54,11 @@ func TestStorage(t *testing.T) {
}
c.Interface.PrivateKey = *k
- err = c.Save()
+ err = c.Save(false)
+ if err == nil {
+ t.Error("Config disappeared or was unexpectedly overwritten")
+ }
+ err = c.Save(true)
if err != nil {
t.Errorf("Unable to save config a second time: %s", err.Error())
}
diff --git a/conf/storewatcher.go b/conf/storewatcher.go
index 94586c38..70a44add 100644
--- a/conf/storewatcher.go
+++ b/conf/storewatcher.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
diff --git a/conf/storewatcher_windows.go b/conf/storewatcher_windows.go
index a12fb59b..0c4b74e7 100644
--- a/conf/storewatcher_windows.go
+++ b/conf/storewatcher_windows.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
diff --git a/conf/writer.go b/conf/writer.go
index c786ec10..162962b5 100644
--- a/conf/writer.go
+++ b/conf/writer.go
@@ -1,13 +1,19 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package conf
import (
"fmt"
+ "net/netip"
"strings"
+ "unsafe"
+
+ "golang.org/x/sys/windows"
+ "golang.zx2c4.com/wireguard/windows/driver"
+ "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
)
func (conf *Config) ToWgQuick() string {
@@ -53,6 +59,9 @@ func (conf *Config) ToWgQuick() string {
if len(conf.Interface.PostDown) > 0 {
output.WriteString(fmt.Sprintf("PostDown = %s\n", conf.Interface.PostDown))
}
+ if conf.Interface.TableOff {
+ output.WriteString("Table = off\n")
+ }
for _, peer := range conf.Peers {
output.WriteString("\n[Peer]\n")
@@ -82,43 +91,50 @@ func (conf *Config) ToWgQuick() string {
return output.String()
}
-func (conf *Config) ToUAPI() (uapi string, dnsErr error) {
- var output strings.Builder
- output.WriteString(fmt.Sprintf("private_key=%s\n", conf.Interface.PrivateKey.HexString()))
-
- if conf.Interface.ListenPort > 0 {
- output.WriteString(fmt.Sprintf("listen_port=%d\n", conf.Interface.ListenPort))
- }
-
- if len(conf.Peers) > 0 {
- output.WriteString("replace_peers=true\n")
+func (config *Config) ToDriverConfiguration() (*driver.Interface, uint32) {
+ preallocation := unsafe.Sizeof(driver.Interface{}) + uintptr(len(config.Peers))*unsafe.Sizeof(driver.Peer{})
+ for i := range config.Peers {
+ preallocation += uintptr(len(config.Peers[i].AllowedIPs)) * unsafe.Sizeof(driver.AllowedIP{})
}
-
- for _, peer := range conf.Peers {
- output.WriteString(fmt.Sprintf("public_key=%s\n", peer.PublicKey.HexString()))
-
- if !peer.PresharedKey.IsZero() {
- output.WriteString(fmt.Sprintf("preshared_key=%s\n", peer.PresharedKey.HexString()))
+ var c driver.ConfigBuilder
+ c.Preallocate(uint32(preallocation))
+ c.AppendInterface(&driver.Interface{
+ Flags: driver.InterfaceHasPrivateKey | driver.InterfaceHasListenPort,
+ ListenPort: config.Interface.ListenPort,
+ PrivateKey: config.Interface.PrivateKey,
+ PeerCount: uint32(len(config.Peers)),
+ })
+ for i := range config.Peers {
+ flags := driver.PeerHasPublicKey | driver.PeerHasPersistentKeepalive
+ if !config.Peers[i].PresharedKey.IsZero() {
+ flags |= driver.PeerHasPresharedKey
}
-
- if !peer.Endpoint.IsEmpty() {
- var resolvedIP string
- resolvedIP, dnsErr = resolveHostname(peer.Endpoint.Host)
- if dnsErr != nil {
- return
+ var endpoint winipcfg.RawSockaddrInet
+ if !config.Peers[i].Endpoint.IsEmpty() {
+ addr, err := netip.ParseAddr(config.Peers[i].Endpoint.Host)
+ if err == nil {
+ flags |= driver.PeerHasEndpoint
+ endpoint.SetAddrPort(netip.AddrPortFrom(addr, config.Peers[i].Endpoint.Port))
}
- resolvedEndpoint := Endpoint{resolvedIP, peer.Endpoint.Port}
- output.WriteString(fmt.Sprintf("endpoint=%s\n", resolvedEndpoint.String()))
}
-
- output.WriteString(fmt.Sprintf("persistent_keepalive_interval=%d\n", peer.PersistentKeepalive))
-
- if len(peer.AllowedIPs) > 0 {
- output.WriteString("replace_allowed_ips=true\n")
- for _, address := range peer.AllowedIPs {
- output.WriteString(fmt.Sprintf("allowed_ip=%s\n", address.String()))
+ c.AppendPeer(&driver.Peer{
+ Flags: flags,
+ PublicKey: config.Peers[i].PublicKey,
+ PresharedKey: config.Peers[i].PresharedKey,
+ PersistentKeepalive: config.Peers[i].PersistentKeepalive,
+ Endpoint: endpoint,
+ AllowedIPsCount: uint32(len(config.Peers[i].AllowedIPs)),
+ })
+ for j := range config.Peers[i].AllowedIPs {
+ a := &driver.AllowedIP{Cidr: uint8(config.Peers[i].AllowedIPs[j].Bits())}
+ copy(a.Address[:], config.Peers[i].AllowedIPs[j].Addr().AsSlice())
+ if config.Peers[i].AllowedIPs[j].Addr().Is4() {
+ a.AddressFamily = windows.AF_INET
+ } else if config.Peers[i].AllowedIPs[j].Addr().Is6() {
+ a.AddressFamily = windows.AF_INET6
}
+ c.AppendAllowedIP(a)
}
}
- return output.String(), nil
+ return c.Interface()
}
diff --git a/conf/zsyscall_windows.go b/conf/zsyscall_windows.go
deleted file mode 100644
index 783411f6..00000000
--- a/conf/zsyscall_windows.go
+++ /dev/null
@@ -1,50 +0,0 @@
-// Code generated by 'go generate'; DO NOT EDIT.
-
-package conf
-
-import (
- "syscall"
- "unsafe"
-
- "golang.org/x/sys/windows"
-)
-
-var _ unsafe.Pointer
-
-// Do the interface allocations only once for common
-// Errno values.
-const (
- errnoERROR_IO_PENDING = 997
-)
-
-var (
- errERROR_IO_PENDING error = syscall.Errno(errnoERROR_IO_PENDING)
- errERROR_EINVAL error = syscall.EINVAL
-)
-
-// errnoErr returns common boxed Errno values, to prevent
-// allocations at runtime.
-func errnoErr(e syscall.Errno) error {
- switch e {
- case 0:
- return errERROR_EINVAL
- case errnoERROR_IO_PENDING:
- return errERROR_IO_PENDING
- }
- // TODO: add more here, after collecting data on the common
- // error values see on Windows. (perhaps when running
- // all.bat?)
- return e
-}
-
-var (
- modwininet = windows.NewLazySystemDLL("wininet.dll")
-
- procInternetGetConnectedState = modwininet.NewProc("InternetGetConnectedState")
-)
-
-func internetGetConnectedState(flags *uint32, reserved uint32) (connected bool) {
- r0, _, _ := syscall.Syscall(procInternetGetConnectedState.Addr(), 2, uintptr(unsafe.Pointer(flags)), uintptr(reserved), 0)
- connected = r0 != 0
- return
-}
diff --git a/docs/adminregistry.md b/docs/adminregistry.md
index f7d04409..4289fb38 100644
--- a/docs/adminregistry.md
+++ b/docs/adminregistry.md
@@ -13,12 +13,16 @@ users belonging to the Network Configuration Operators builtin group
(S-1-5-32-556), with the following limitations for members of that group:
- Configurations are stripped of all public, private, and pre-shared keys;
- - No version update notifications are delivered;
+ - No version update popup notifications are shown, and updates are not permitted, though a tab still indicates the availability;
- Adding, removing, editing, importing, or exporting configurations is forbidden; and
- Quitting the manager is forbidden.
However, basic functionality such as starting and stopping tunnels remains intact.
+```
+> reg add HKLM\Software\WireGuard /v LimitedOperatorUI /t REG_DWORD /d 1 /f
+```
+
#### `HKLM\Software\WireGuard\DangerousScriptExecution`
When this key is set to `DWORD(1)`, the tunnel service will execute the commands
@@ -30,12 +34,6 @@ utmost trepidation. Rather than use `%i`, WireGuard for Windows instead sets the
environment variable `WIREGUARD_TUNNEL_NAME` to the name of the tunnel when
executing these scripts.
-#### `HKLM\Software\WireGuard\MultipleSimultaneousTunnels`
-
-When this key is set to `DWORD(1)`, the UI may start multiple tunnels at the
-same time; otherwise, an existing tunnel is stopped when a new one is started.
-Note that it is always possible, regardless of this key, to start multiple
-tunnels using `wireguard /installtunnelservice`; this controls only the semantics
-of tunnel start requests coming from the UI. If all goes well, this key will be
-removed and the logic of whether to stop existing tunnels will be based on
-overlapping routes, but for now, this key provides a manual override.
+```
+> reg add HKLM\Software\WireGuard /v DangerousScriptExecution /t REG_DWORD /d 1 /f
+```
diff --git a/docs/attacksurface.md b/docs/attacksurface.md
index 6dca229f..a495ba41 100644
--- a/docs/attacksurface.md
+++ b/docs/attacksurface.md
@@ -4,22 +4,21 @@ _This is an evolving document, describing currently known attack surface, a few
WireGuard for Windows consists of four components: a kernel driver, and three separate interacting userspace parts.
-### Wintun
+### WireGuardNT
-Wintun is a kernel driver. It exposes:
+WireGuardNT is a kernel driver. It exposes:
- A miniport driver to the ndis stack, meaning any process on the system that can access the network stack in a reasonable way can send and receive packets, hitting those related ndis handlers.
+ - A UDP port parsing WireGuard packets.
- There are also various ndis OID calls, accessible to certain users, which hit further code.
- - IOCTLs are added to the NDIS device file, and those IOCTLs are restricted to `SDDL_DEVOBJ_SYS_ALL`. The IOCTL allows userspace to register a pair of rings and event objects, which Wintun then locks the pages of with a double mapping and takes a reference to the event object. It parses the contents of the ring to send and receive layer 3 packets, each of which it minimally parses to determine IP family.
+ - A PNP and Close notifier added to the NDIS device file.
+ - IOCTLs are added to the NDIS device file, and those IOCTLs are restricted to `O:SYD:P(A;;FA;;;SY)(A;;FA;;;BA)S:(ML;;NWNRNX;;;HI)`. The IOCTL allows userspace to get and set configuration, adapter state, and read log messages from a ring buffer.
### Tunnel Service
-The tunnel service is a userspace service running as Local System, responsible for creating UDP sockets, creating Wintun adapters, and speaking the WireGuard protocol between the two. It exposes:
+The tunnel service is a userspace service running as Local System, responsible for creating WireGuardNT adapters and configuring them. It exposes:
- - A listening pipe in `\\.\pipe\ProtectedPrefix\Administrators\WireGuard\%s`, where `%s` is some basename of an already valid filename. Its DACL is set to `O:SYD:(A;;GA;;;SY)`. If the config file used by the tunnel service is not DPAPI-encrypted and it is owned by a SID other than "Local System" then an additional ACE is added giving that file owner SID access to the named pipe. This pipe gives access to private keys and allows for reconfiguration of the interface, as well as rebinding to different ports (below 1024, even). Clients who connect to the pipe run `GetSecurityInfo` to verify that it is owned by "Local System".
- - A global mutex is used for Wintun interface creation, with the same DACL as the pipe, but first CreatePrivateNamespace is called with a "Local System" SID.
- - It handles data from its two UDP sockets, accessible to the public Internet.
- - It handles data from Wintun, accessible to all users who can do anything with the network stack.
+ - A global mutex is used for WireGuardNT interface creation, with the same DACL as the pipe, but first CreatePrivateNamespace is called with a "Local System" SID.
- After some initial setup, it uses `AdjustTokenPrivileges` to remove all privileges, except for `SeLoadDriverPrivilege`, so that it can remove the interface when shutting down. This latter point is rather unfortunate, as `SeLoadDriverPrivilege` can be used for all sorts of interesting escalation. Future work includes forking an additional process or the like so that we can drop this from the main tunnel process.
### Manager Service
diff --git a/docs/buildrun.md b/docs/buildrun.md
index 265c4d68..687d2e61 100644
--- a/docs/buildrun.md
+++ b/docs/buildrun.md
@@ -18,7 +18,7 @@ After you've built the application, run `amd64\wireguard.exe` or `x86\wireguard.
C:\Projects\wireguard-windows> amd64\wireguard.exe
```
-Since WireGuard requires the Wintun driver to be installed, and this generally requires a valid Microsoft signature, you may benefit from first installing a release of WireGuard for Windows from the official [wireguard.com](https://www.wireguard.com/install/) builds, which bundles a Microsoft-signed Wintun, and then subsequently run your own wireguard.exe. Alternatively, you can craft your own installer using the `quickinstall.bat` script.
+Since WireGuard requires a driver to be installed, and this generally requires a valid Microsoft signature, you may benefit from first installing a release of WireGuard for Windows from the official [wireguard.com](https://www.wireguard.com/install/) builds, which bundles a Microsoft-signed driver, and then subsequently run your own wireguard.exe. Alternatively, you can craft your own installer using the `quickinstall.bat` script.
### Optional: Localizing
@@ -60,8 +60,8 @@ C:\Projects\wireguard-windows\installer> build
Add a file called `sign.bat` in the root of this repository with these contents, or similar:
```text
-set SigningCertificate=DF98E075A012ED8C86FBCF14854B8F9555CB3D45
-set TimestampServer=http://timestamp.digicert.com
+set SigningProvider=/sha1 8BC932FDFF15B892E8364C49B383210810E4709D
+set TimestampServer=http://timestamp.entrust.net/rfc3161ts2
```
After, run the above `build` commands as usual, from a shell that has [`signtool.exe`](https://docs.microsoft.com/en-us/windows/desktop/SecCrypto/signtool) in its `PATH`, such as the Visual Studio 2017 command prompt.
diff --git a/docs/enterprise.md b/docs/enterprise.md
index 3f75ad14..8430cc99 100644
--- a/docs/enterprise.md
+++ b/docs/enterprise.md
@@ -8,7 +8,7 @@ While consumer users are generally directed toward [wireguard-installer.exe](htt
### Tunnel Service versus Manager Service and UI
-The "manager service" is responsible for displaying a UI on select users' desktops (in the system tray), and responding to requests from the UI to do things like add, remove, start, or stop tunnels. The "tunnel service" is a separate Windows service for each tunnel. These two services may be used together, or separately, as described below.
+The "manager service" is responsible for displaying a UI on select users' desktops (in the system tray), and responding to requests from the UI to do things like add, remove, start, or stop tunnels. The "tunnel service" is a separate Windows service for each tunnel. These two services may be used together, or separately, as described below. The various commands below will log errors and status to standard error, or, if standard error does not exist, to standard output.
### Tunnel Service
@@ -58,15 +58,24 @@ The manager service monitors `%ProgramFiles%\WireGuard\Data\Configurations\` for
The UI is started in the system tray of all builtin Administrators when the manager service is running. A limited UI may also be started in the system tray of all builtin Network Configuration Operators, if the correct registry key is set. [See `adminregistry.md` for information.](adminregistry.md)
-By default, the manager stops existing tunnels when starting new tunnels, so that only one tunnel service is running at a time. This behavior may be disabled if the correct registry key is set. [See `adminregistry.md` for information.](adminregistry.md)
+### Diagnostic Logs
+The manager and all tunnel services produce diagnostic logs in a shared ringbuffer-based log. This is shown in the UI, and also can be dumped to standard out using the command:
-### Diagnostic Logs
+```text
+> wireguard /dumplog > C:\path\to\diagnostic\log.txt
+```
+
+Alternatively, the log can be tailed continuously, for passing it to logging services:
-The manager and all tunnel services produce diagnostic logs in a shared ringbuffer-based log. This is shown in the UI, and also can be dumped to a file using the command:
+```text
+> wireguard /dumplog /tail | log-ingest
+```
+
+Or it can be monitored in PowerShell by piping to `select`:
```text
-> wireguard /dumplog C:\path\to\diagnostic\log.txt
+PS> wireguard /dumplog /tail | select
```
### Updates
@@ -74,13 +83,31 @@ The manager and all tunnel services produce diagnostic logs in a shared ringbuff
Administrators are notified of updates within the UI and can update from within the UI, but updates can also be invoked at the command line using the command:
```text
-> wireguard /update C:\path\to\update\log.txt
+> wireguard /update
+```
+
+Or, to log the status of that command:
+
+```text
+> wireguard /update 2> C:\path\to\update\log.txt
+```
+
+One could have Task Scheduler run it daily at 3am:
+
+```text
+> schtasks /create /f /ru SYSTEM /sc daily /tn "WireGuard Update" /tr "%PROGRAMFILES%\WireGuard\wireguard.exe /update" /st 03:00
```
-### Wintun Adapters
+### Driver Removal
+
+The tunnel service creates a network adapter at startup and destroys it at shutdown. If there are no more network adapters, the driver may be removed with:
+
+```text
+> wireguard /removedriver
+```
-The tunnel service creates a Wintun adapter at startup and destroys it at shutdown. It may be desirable, however, to remove all Wintun adapters created in WireGuard's pool and uninstall the driver if no other applications are using Wintun. This can be accomplished using the command:
+Or, to log the status of that command:
```text
-> wireguard /removealladapters C:\path\to\removal\log.txt
+> wireguard /removedriver 2> C:\path\to\removal\log.txt
```
diff --git a/docs/netquirk.md b/docs/netquirk.md
index 1fe2ad72..d53c8cdb 100644
--- a/docs/netquirk.md
+++ b/docs/netquirk.md
@@ -4,7 +4,7 @@ As part of setting up a WireGuard tunnel, the tunnel service also sets up variou
### Routing
-The tunnel service takes all the allowed IPs from each peer, deduplicates them, and adds them to the routes for the WireGuard interface. The service then monitors which interface on the system has a default route (a route with a `/0` CIDR) that is not the WireGuard interface itself, and it uses the [`IP_UNICAST_IF` socket option](https://docs.microsoft.com/en-us/windows/win32/winsock/ipproto-ip-socket-options) to bind WireGuard's UDP packets to that default route interface. If no MTU has been specified in the configuration, it also sets the MTU of the WireGuard interface to be 80 less than the MTU of that default route interface. If no default route interface can be found, then those outgoing packets are blackholed. If WireGuard packets would ordinarily be routed over a non-default route interface, the use of `IP_UNICAST_IF` forces the packets to, in fact, go over the default route interface. This is problematic, but at this moment, Microsoft has not provided a viable workaround. If any allowed IPs are a `/0`, then the interface is given a `0` metric and Windows' [automatic metric logic](https://docs.microsoft.com/en-us/troubleshoot/windows-server/networking/automatic-metric-for-ipv4-routes) is disabled.
+The tunnel service takes all the allowed IPs from each peer, deduplicates them, and adds them to the routes for the WireGuard interface. The service then monitors which interface on the system has a default route (a route with a `/0` CIDR) that is not the WireGuard interface itself, and, if no MTU has been specified in the configuration, it sets the MTU of the WireGuard interface to be 80 less than the MTU of that default route interface. WireGuardNT also monitors the routing table and determines the outgoing route that does not loopback to itself, and then sends each packet using `IP_PKTINFO`/`IPV6_PKTINFO`. It keeps track of the incoming interface and source address for received packets, and always replies to the sender in that way.
### Firewall Considerations for `/0` Allowed IPs
@@ -30,4 +30,4 @@ Windows assigns a unique GUID to each new WireGuard adapter. The application tak
### Adapter Lifetime
-WireGuard's Wintun adapter is created dynamically when a tunnel is started and destroyed when a tunnel is stopped. This means that additional filters, address families, or protocols should be bound to the adapter programmatically, possibly through use of dangerous script execution in thet configuration file or by way of automatic NDIS layer binding.
+WireGuard's network adapter is created dynamically when a tunnel is started and destroyed when a tunnel is stopped. This means that additional filters, address families, or protocols should be bound to the adapter programmatically, possibly through use of dangerous script execution in the configuration file or by way of automatic NDIS layer binding.
diff --git a/driver/configuration_windows.go b/driver/configuration_windows.go
new file mode 100644
index 00000000..d838dcf2
--- /dev/null
+++ b/driver/configuration_windows.go
@@ -0,0 +1,183 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package driver
+
+import (
+ "syscall"
+ "unsafe"
+
+ "golang.org/x/sys/windows"
+ "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
+)
+
+type AdapterState uint32
+
+const (
+ AdapterStateDown AdapterState = 0
+ AdapterStateUp AdapterState = 1
+)
+
+type AllowedIP struct {
+ Address [16]byte
+ AddressFamily winipcfg.AddressFamily
+ Cidr uint8
+ _ [4]byte
+}
+
+type PeerFlag uint32
+
+const (
+ PeerHasPublicKey PeerFlag = 1 << 0
+ PeerHasPresharedKey PeerFlag = 1 << 1
+ PeerHasPersistentKeepalive PeerFlag = 1 << 2
+ PeerHasEndpoint PeerFlag = 1 << 3
+ PeerReplaceAllowedIPs PeerFlag = 1 << 5
+ PeerRemove PeerFlag = 1 << 6
+ PeerUpdateOnly PeerFlag = 1 << 7
+)
+
+type Peer struct {
+ Flags PeerFlag
+ _ uint32
+ PublicKey [32]byte
+ PresharedKey [32]byte
+ PersistentKeepalive uint16
+ _ uint16
+ Endpoint winipcfg.RawSockaddrInet
+ TxBytes uint64
+ RxBytes uint64
+ LastHandshake uint64
+ AllowedIPsCount uint32
+ _ [4]byte
+}
+
+type InterfaceFlag uint32
+
+const (
+ InterfaceHasPublicKey InterfaceFlag = 1 << 0
+ InterfaceHasPrivateKey InterfaceFlag = 1 << 1
+ InterfaceHasListenPort InterfaceFlag = 1 << 2
+ InterfaceReplacePeers InterfaceFlag = 1 << 3
+)
+
+type Interface struct {
+ Flags InterfaceFlag
+ ListenPort uint16
+ PrivateKey [32]byte
+ PublicKey [32]byte
+ PeerCount uint32
+ _ [4]byte
+}
+
+var (
+ procWireGuardSetAdapterState = modwireguard.NewProc("WireGuardSetAdapterState")
+ procWireGuardGetAdapterState = modwireguard.NewProc("WireGuardGetAdapterState")
+ procWireGuardSetConfiguration = modwireguard.NewProc("WireGuardSetConfiguration")
+ procWireGuardGetConfiguration = modwireguard.NewProc("WireGuardGetConfiguration")
+)
+
+// SetAdapterState sets the adapter either Up or Down.
+func (wireguard *Adapter) SetAdapterState(adapterState AdapterState) (err error) {
+ r0, _, e1 := syscall.SyscallN(procWireGuardSetAdapterState.Addr(), wireguard.handle, uintptr(adapterState))
+ if r0 == 0 {
+ err = e1
+ }
+ return
+}
+
+// AdapterState returns the current state of the adapter.
+func (wireguard *Adapter) AdapterState() (adapterState AdapterState, err error) {
+ r0, _, e1 := syscall.SyscallN(procWireGuardGetAdapterState.Addr(), wireguard.handle, uintptr(unsafe.Pointer(&adapterState)))
+ if r0 == 0 {
+ err = e1
+ }
+ return
+}
+
+// SetConfiguration sets the adapter configuration.
+func (wireguard *Adapter) SetConfiguration(interfaze *Interface, size uint32) (err error) {
+ r0, _, e1 := syscall.SyscallN(procWireGuardSetConfiguration.Addr(), wireguard.handle, uintptr(unsafe.Pointer(interfaze)), uintptr(size))
+ if r0 == 0 {
+ err = e1
+ }
+ return
+}
+
+// Configuration gets the adapter configuration.
+func (wireguard *Adapter) Configuration() (interfaze *Interface, err error) {
+ size := wireguard.lastGetGuessSize
+ if size == 0 {
+ size = 512
+ }
+ for {
+ buf := make([]byte, size)
+ r0, _, e1 := syscall.SyscallN(procWireGuardGetConfiguration.Addr(), wireguard.handle, uintptr(unsafe.Pointer(&buf[0])), uintptr(unsafe.Pointer(&size)))
+ if r0 != 0 {
+ wireguard.lastGetGuessSize = size
+ return (*Interface)(unsafe.Pointer(&buf[0])), nil
+ }
+ if e1 != windows.ERROR_MORE_DATA {
+ return nil, e1
+ }
+ }
+}
+
+// FirstPeer returns the first peer attached to the interface.
+func (interfaze *Interface) FirstPeer() *Peer {
+ return (*Peer)(unsafe.Add(unsafe.Pointer(interfaze), unsafe.Sizeof(*interfaze)))
+}
+
+// NextPeer returns the subsequent peer of the current one.
+func (peer *Peer) NextPeer() *Peer {
+ return (*Peer)(unsafe.Pointer(uintptr(unsafe.Pointer(peer)) + unsafe.Sizeof(*peer) + uintptr(peer.AllowedIPsCount)*unsafe.Sizeof(AllowedIP{})))
+}
+
+// FirstAllowedIP returns the first allowed IP attached to the peer.
+func (peer *Peer) FirstAllowedIP() *AllowedIP {
+ return (*AllowedIP)(unsafe.Add(unsafe.Pointer(peer), unsafe.Sizeof(*peer)))
+}
+
+// NextAllowedIP returns the subsequent allowed IP of the current one.
+func (allowedIP *AllowedIP) NextAllowedIP() *AllowedIP {
+ return (*AllowedIP)(unsafe.Add(unsafe.Pointer(allowedIP), unsafe.Sizeof(*allowedIP)))
+}
+
+type ConfigBuilder struct {
+ buffer []byte
+}
+
+// Preallocate reserves memory in the config builder to reduce allocations of append operations.
+func (builder *ConfigBuilder) Preallocate(size uint32) {
+ if builder.buffer == nil {
+ builder.buffer = make([]byte, 0, size)
+ }
+}
+
+// AppendInterface appends an interface to the building configuration. This should be called first.
+func (builder *ConfigBuilder) AppendInterface(interfaze *Interface) {
+ newBytes := unsafe.Slice((*byte)(unsafe.Pointer(interfaze)), unsafe.Sizeof(*interfaze))
+ builder.buffer = append(builder.buffer, newBytes...)
+}
+
+// AppendPeer appends a peer to the building configuration. This should be called after an interface has been added.
+func (builder *ConfigBuilder) AppendPeer(peer *Peer) {
+ newBytes := unsafe.Slice((*byte)(unsafe.Pointer(peer)), unsafe.Sizeof(*peer))
+ builder.buffer = append(builder.buffer, newBytes...)
+}
+
+// AppendAllowedIP appends an allowed IP to the building configuration. This should be called after a peer has been added.
+func (builder *ConfigBuilder) AppendAllowedIP(allowedIP *AllowedIP) {
+ newBytes := unsafe.Slice((*byte)(unsafe.Pointer(allowedIP)), unsafe.Sizeof(*allowedIP))
+ builder.buffer = append(builder.buffer, newBytes...)
+}
+
+// Interface assembles the configuration and returns the interface and length to be passed to SetConfiguration.
+func (builder *ConfigBuilder) Interface() (*Interface, uint32) {
+ if builder.buffer == nil {
+ return nil, 0
+ }
+ return (*Interface)(unsafe.Pointer(&builder.buffer[0])), uint32(len(builder.buffer))
+}
diff --git a/driver/dll_fromfile_windows.go b/driver/dll_fromfile_windows.go
new file mode 100644
index 00000000..b815b4c0
--- /dev/null
+++ b/driver/dll_fromfile_windows.go
@@ -0,0 +1,56 @@
+//go:build !load_wgnt_from_rsrc
+
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
+ */
+
+package driver
+
+import (
+ "fmt"
+ "sync"
+ "sync/atomic"
+ "unsafe"
+
+ "golang.org/x/sys/windows"
+)
+
+type lazyDLL struct {
+ Name string
+ Base windows.Handle
+ mu sync.Mutex
+ module windows.Handle
+ onLoad func(d *lazyDLL)
+}
+
+func (d *lazyDLL) Load() error {
+ if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&d.module))) != nil {
+ return nil
+ }
+ d.mu.Lock()
+ defer d.mu.Unlock()
+ if d.module != 0 {
+ return nil
+ }
+
+ const (
+ LOAD_LIBRARY_SEARCH_APPLICATION_DIR = 0x00000200
+ LOAD_LIBRARY_SEARCH_SYSTEM32 = 0x00000800
+ )
+ module, err := windows.LoadLibraryEx(d.Name, 0, LOAD_LIBRARY_SEARCH_APPLICATION_DIR|LOAD_LIBRARY_SEARCH_SYSTEM32)
+ if err != nil {
+ return fmt.Errorf("Unable to load library: %w", err)
+ }
+ d.Base = module
+
+ atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&d.module)), unsafe.Pointer(module))
+ if d.onLoad != nil {
+ d.onLoad(d)
+ }
+ return nil
+}
+
+func (p *lazyProc) nameToAddr() (uintptr, error) {
+ return windows.GetProcAddress(p.dll.module, p.Name)
+}
diff --git a/driver/dll_fromrsrc_windows.go b/driver/dll_fromrsrc_windows.go
new file mode 100644
index 00000000..65b1cfce
--- /dev/null
+++ b/driver/dll_fromrsrc_windows.go
@@ -0,0 +1,62 @@
+//go:build load_wgnt_from_rsrc
+
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019 WireGuard LLC. All Rights Reserved.
+ */
+
+package driver
+
+import (
+ "fmt"
+ "sync"
+ "sync/atomic"
+ "unsafe"
+
+ "golang.org/x/sys/windows"
+ "golang.zx2c4.com/wireguard/windows/driver/memmod"
+)
+
+type lazyDLL struct {
+ Name string
+ Base windows.Handle
+ mu sync.Mutex
+ module *memmod.Module
+ onLoad func(d *lazyDLL)
+}
+
+func (d *lazyDLL) Load() error {
+ if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&d.module))) != nil {
+ return nil
+ }
+ d.mu.Lock()
+ defer d.mu.Unlock()
+ if d.module != nil {
+ return nil
+ }
+
+ const ourModule windows.Handle = 0
+ resInfo, err := windows.FindResource(ourModule, d.Name, windows.RT_RCDATA)
+ if err != nil {
+ return fmt.Errorf("Unable to find \"%v\" RCDATA resource: %w", d.Name, err)
+ }
+ data, err := windows.LoadResourceData(ourModule, resInfo)
+ if err != nil {
+ return fmt.Errorf("Unable to load resource: %w", err)
+ }
+ module, err := memmod.LoadLibrary(data)
+ if err != nil {
+ return fmt.Errorf("Unable to load library: %w", err)
+ }
+ d.Base = windows.Handle(module.BaseAddr())
+
+ atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&d.module)), unsafe.Pointer(module))
+ if d.onLoad != nil {
+ d.onLoad(d)
+ }
+ return nil
+}
+
+func (p *lazyProc) nameToAddr() (uintptr, error) {
+ return p.dll.module.ProcAddressByName(p.Name)
+}
diff --git a/driver/dll_windows.go b/driver/dll_windows.go
new file mode 100644
index 00000000..5dcb849e
--- /dev/null
+++ b/driver/dll_windows.go
@@ -0,0 +1,91 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package driver
+
+import (
+ "fmt"
+ "sync"
+ "sync/atomic"
+ "unsafe"
+
+ "golang.org/x/sys/windows"
+)
+
+func newLazyDLL(name string, onLoad func(d *lazyDLL)) *lazyDLL {
+ return &lazyDLL{Name: name, onLoad: onLoad}
+}
+
+func (d *lazyDLL) NewProc(name string) *lazyProc {
+ return &lazyProc{dll: d, Name: name}
+}
+
+type lazyProc struct {
+ Name string
+ mu sync.Mutex
+ dll *lazyDLL
+ addr uintptr
+}
+
+func (p *lazyProc) Find() error {
+ if atomic.LoadPointer((*unsafe.Pointer)(unsafe.Pointer(&p.addr))) != nil {
+ return nil
+ }
+ p.mu.Lock()
+ defer p.mu.Unlock()
+ if p.addr != 0 {
+ return nil
+ }
+
+ err := p.dll.Load()
+ if err != nil {
+ return fmt.Errorf("Error loading %v DLL: %w", p.dll.Name, err)
+ }
+ addr, err := p.nameToAddr()
+ if err != nil {
+ return fmt.Errorf("Error getting %v address: %w", p.Name, err)
+ }
+
+ atomic.StorePointer((*unsafe.Pointer)(unsafe.Pointer(&p.addr)), unsafe.Pointer(addr))
+ return nil
+}
+
+func (p *lazyProc) Addr() uintptr {
+ err := p.Find()
+ if err != nil {
+ panic(err)
+ }
+ return p.addr
+}
+
+// Version returns the version of the driver DLL.
+func Version() string {
+ if modwireguard.Load() != nil {
+ return "unknown"
+ }
+ resInfo, err := windows.FindResource(modwireguard.Base, windows.ResourceID(1), windows.RT_VERSION)
+ if err != nil {
+ return "unknown"
+ }
+ data, err := windows.LoadResourceData(modwireguard.Base, resInfo)
+ if err != nil {
+ return "unknown"
+ }
+
+ var fixedInfo *windows.VS_FIXEDFILEINFO
+ fixedInfoLen := uint32(unsafe.Sizeof(*fixedInfo))
+ err = windows.VerQueryValue(unsafe.Pointer(&data[0]), `\`, unsafe.Pointer(&fixedInfo), &fixedInfoLen)
+ if err != nil {
+ return "unknown"
+ }
+ version := fmt.Sprintf("%d.%d", (fixedInfo.FileVersionMS>>16)&0xff, (fixedInfo.FileVersionMS>>0)&0xff)
+ if nextNibble := (fixedInfo.FileVersionLS >> 16) & 0xff; nextNibble != 0 {
+ version += fmt.Sprintf(".%d", nextNibble)
+ }
+ if nextNibble := (fixedInfo.FileVersionLS >> 0) & 0xff; nextNibble != 0 {
+ version += fmt.Sprintf(".%d", nextNibble)
+ }
+ return version
+}
diff --git a/driver/driver_windows.go b/driver/driver_windows.go
new file mode 100644
index 00000000..462c3a30
--- /dev/null
+++ b/driver/driver_windows.go
@@ -0,0 +1,170 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package driver
+
+import (
+ "log"
+ "runtime"
+ "syscall"
+ "unsafe"
+
+ "golang.org/x/sys/windows"
+ "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
+)
+
+type loggerLevel int
+
+const (
+ logInfo loggerLevel = iota
+ logWarn
+ logErr
+)
+
+const AdapterNameMax = 128
+
+type Adapter struct {
+ handle uintptr
+ lastGetGuessSize uint32
+}
+
+var (
+ modwireguard = newLazyDLL("wireguard.dll", setupLogger)
+ procWireGuardCreateAdapter = modwireguard.NewProc("WireGuardCreateAdapter")
+ procWireGuardOpenAdapter = modwireguard.NewProc("WireGuardOpenAdapter")
+ procWireGuardCloseAdapter = modwireguard.NewProc("WireGuardCloseAdapter")
+ procWireGuardDeleteDriver = modwireguard.NewProc("WireGuardDeleteDriver")
+ procWireGuardGetAdapterLUID = modwireguard.NewProc("WireGuardGetAdapterLUID")
+ procWireGuardGetRunningDriverVersion = modwireguard.NewProc("WireGuardGetRunningDriverVersion")
+ procWireGuardSetAdapterLogging = modwireguard.NewProc("WireGuardSetAdapterLogging")
+)
+
+type TimestampedWriter interface {
+ WriteWithTimestamp(p []byte, ts int64) (n int, err error)
+}
+
+func logMessage(level loggerLevel, timestamp uint64, msg *uint16) int {
+ if tw, ok := log.Default().Writer().(TimestampedWriter); ok {
+ tw.WriteWithTimestamp([]byte(log.Default().Prefix()+windows.UTF16PtrToString(msg)), (int64(timestamp)-116444736000000000)*100)
+ } else {
+ log.Println(windows.UTF16PtrToString(msg))
+ }
+ return 0
+}
+
+func setupLogger(dll *lazyDLL) {
+ var callback uintptr
+ if runtime.GOARCH == "386" {
+ callback = windows.NewCallback(func(level loggerLevel, timestampLow, timestampHigh uint32, msg *uint16) int {
+ return logMessage(level, uint64(timestampHigh)<<32|uint64(timestampLow), msg)
+ })
+ } else if runtime.GOARCH == "arm" {
+ callback = windows.NewCallback(func(level loggerLevel, _, timestampLow, timestampHigh uint32, msg *uint16) int {
+ return logMessage(level, uint64(timestampHigh)<<32|uint64(timestampLow), msg)
+ })
+ } else if runtime.GOARCH == "amd64" || runtime.GOARCH == "arm64" {
+ callback = windows.NewCallback(logMessage)
+ }
+ syscall.SyscallN(dll.NewProc("WireGuardSetLogger").Addr(), callback)
+}
+
+func closeAdapter(wireguard *Adapter) {
+ syscall.SyscallN(procWireGuardCloseAdapter.Addr(), wireguard.handle)
+}
+
+// CreateAdapter creates a WireGuard adapter. name is the cosmetic name of the adapter.
+// tunnelType represents the type of adapter and should be "WireGuard". requestedGUID is
+// the GUID of the created network adapter, which then influences NLA generation
+// deterministically. If it is set to nil, the GUID is chosen by the system at random,
+// and hence a new NLA entry is created for each new adapter.
+func CreateAdapter(name, tunnelType string, requestedGUID *windows.GUID) (wireguard *Adapter, err error) {
+ var name16 *uint16
+ name16, err = windows.UTF16PtrFromString(name)
+ if err != nil {
+ return
+ }
+ var tunnelType16 *uint16
+ tunnelType16, err = windows.UTF16PtrFromString(tunnelType)
+ if err != nil {
+ return
+ }
+ r0, _, e1 := syscall.SyscallN(procWireGuardCreateAdapter.Addr(), uintptr(unsafe.Pointer(name16)), uintptr(unsafe.Pointer(tunnelType16)), uintptr(unsafe.Pointer(requestedGUID)))
+ if r0 == 0 {
+ err = e1
+ return
+ }
+ wireguard = &Adapter{handle: r0}
+ runtime.SetFinalizer(wireguard, closeAdapter)
+ return
+}
+
+// OpenAdapter opens an existing WireGuard adapter by name.
+func OpenAdapter(name string) (wireguard *Adapter, err error) {
+ var name16 *uint16
+ name16, err = windows.UTF16PtrFromString(name)
+ if err != nil {
+ return
+ }
+ r0, _, e1 := syscall.SyscallN(procWireGuardOpenAdapter.Addr(), uintptr(unsafe.Pointer(name16)))
+ if r0 == 0 {
+ err = e1
+ return
+ }
+ wireguard = &Adapter{handle: r0}
+ runtime.SetFinalizer(wireguard, closeAdapter)
+ return
+}
+
+// Close closes a WireGuard adapter.
+func (wireguard *Adapter) Close() (err error) {
+ runtime.SetFinalizer(wireguard, nil)
+ r1, _, e1 := syscall.SyscallN(procWireGuardCloseAdapter.Addr(), wireguard.handle)
+ if r1 == 0 {
+ err = e1
+ }
+ return
+}
+
+// Uninstall removes the driver from the system if no drivers are currently in use.
+func Uninstall() (err error) {
+ r1, _, e1 := syscall.SyscallN(procWireGuardDeleteDriver.Addr())
+ if r1 == 0 {
+ err = e1
+ }
+ return
+}
+
+type AdapterLogState uint32
+
+const (
+ AdapterLogOff AdapterLogState = 0
+ AdapterLogOn AdapterLogState = 1
+ AdapterLogOnWithPrefix AdapterLogState = 2
+)
+
+// SetLogging enables or disables logging on the WireGuard adapter.
+func (wireguard *Adapter) SetLogging(logState AdapterLogState) (err error) {
+ r1, _, e1 := syscall.SyscallN(procWireGuardSetAdapterLogging.Addr(), wireguard.handle, uintptr(logState))
+ if r1 == 0 {
+ err = e1
+ }
+ return
+}
+
+// RunningVersion returns the version of the loaded driver.
+func RunningVersion() (version uint32, err error) {
+ r0, _, e1 := syscall.SyscallN(procWireGuardGetRunningDriverVersion.Addr())
+ version = uint32(r0)
+ if version == 0 {
+ err = e1
+ }
+ return
+}
+
+// LUID returns the LUID of the adapter.
+func (wireguard *Adapter) LUID() (luid winipcfg.LUID) {
+ syscall.SyscallN(procWireGuardGetAdapterLUID.Addr(), wireguard.handle, uintptr(unsafe.Pointer(&luid)))
+ return
+}
diff --git a/driver/memmod/memmod_windows.go b/driver/memmod/memmod_windows.go
new file mode 100644
index 00000000..7b54282a
--- /dev/null
+++ b/driver/memmod/memmod_windows.go
@@ -0,0 +1,698 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package memmod
+
+import (
+ "errors"
+ "fmt"
+ "strings"
+ "sync"
+ "syscall"
+ "unsafe"
+
+ "golang.org/x/sys/windows"
+)
+
+type addressList struct {
+ next *addressList
+ address uintptr
+}
+
+func (head *addressList) free() {
+ for node := head; node != nil; node = node.next {
+ windows.VirtualFree(node.address, 0, windows.MEM_RELEASE)
+ }
+}
+
+type Module struct {
+ headers *IMAGE_NT_HEADERS
+ codeBase uintptr
+ modules []windows.Handle
+ initialized bool
+ isDLL bool
+ isRelocated bool
+ nameExports map[string]uint16
+ entry uintptr
+ blockedMemory *addressList
+}
+
+func (module *Module) BaseAddr() uintptr {
+ return module.codeBase
+}
+
+func (module *Module) headerDirectory(idx int) *IMAGE_DATA_DIRECTORY {
+ return &module.headers.OptionalHeader.DataDirectory[idx]
+}
+
+func (module *Module) copySections(address, size uintptr, oldHeaders *IMAGE_NT_HEADERS) error {
+ sections := module.headers.Sections()
+ for i := range sections {
+ if sections[i].SizeOfRawData == 0 {
+ // Section doesn't contain data in the dll itself, but may define uninitialized data.
+ sectionSize := oldHeaders.OptionalHeader.SectionAlignment
+ if sectionSize == 0 {
+ continue
+ }
+ dest, err := windows.VirtualAlloc(module.codeBase+uintptr(sections[i].VirtualAddress),
+ uintptr(sectionSize),
+ windows.MEM_COMMIT,
+ windows.PAGE_READWRITE)
+ if err != nil {
+ return fmt.Errorf("Error allocating section: %w", err)
+ }
+
+ // Always use position from file to support alignments smaller than page size (allocation above will align to page size).
+ dest = module.codeBase + uintptr(sections[i].VirtualAddress)
+ // NOTE: On 64bit systems we truncate to 32bit here but expand again later when "PhysicalAddress" is used.
+ sections[i].SetPhysicalAddress((uint32)(dest & 0xffffffff))
+ dst := unsafe.Slice((*byte)(a2p(dest)), sectionSize)
+ for j := range dst {
+ dst[j] = 0
+ }
+ continue
+ }
+
+ if size < uintptr(sections[i].PointerToRawData+sections[i].SizeOfRawData) {
+ return errors.New("Incomplete section")
+ }
+
+ // Commit memory block and copy data from dll.
+ dest, err := windows.VirtualAlloc(module.codeBase+uintptr(sections[i].VirtualAddress),
+ uintptr(sections[i].SizeOfRawData),
+ windows.MEM_COMMIT,
+ windows.PAGE_READWRITE)
+ if err != nil {
+ return fmt.Errorf("Error allocating memory block: %w", err)
+ }
+
+ // Always use position from file to support alignments smaller than page size (allocation above will align to page size).
+ memcpy(
+ module.codeBase+uintptr(sections[i].VirtualAddress),
+ address+uintptr(sections[i].PointerToRawData),
+ uintptr(sections[i].SizeOfRawData))
+ // NOTE: On 64bit systems we truncate to 32bit here but expand again later when "PhysicalAddress" is used.
+ sections[i].SetPhysicalAddress((uint32)(dest & 0xffffffff))
+ }
+
+ return nil
+}
+
+func (module *Module) realSectionSize(section *IMAGE_SECTION_HEADER) uintptr {
+ size := section.SizeOfRawData
+ if size != 0 {
+ return uintptr(size)
+ }
+ if (section.Characteristics & IMAGE_SCN_CNT_INITIALIZED_DATA) != 0 {
+ return uintptr(module.headers.OptionalHeader.SizeOfInitializedData)
+ }
+ if (section.Characteristics & IMAGE_SCN_CNT_UNINITIALIZED_DATA) != 0 {
+ return uintptr(module.headers.OptionalHeader.SizeOfUninitializedData)
+ }
+ return 0
+}
+
+type sectionFinalizeData struct {
+ address uintptr
+ alignedAddress uintptr
+ size uintptr
+ characteristics uint32
+ last bool
+}
+
+func (module *Module) finalizeSection(sectionData *sectionFinalizeData) error {
+ if sectionData.size == 0 {
+ return nil
+ }
+
+ if (sectionData.characteristics & IMAGE_SCN_MEM_DISCARDABLE) != 0 {
+ // Section is not needed any more and can safely be freed.
+ if sectionData.address == sectionData.alignedAddress &&
+ (sectionData.last ||
+ (sectionData.size%uintptr(module.headers.OptionalHeader.SectionAlignment)) == 0) {
+ // Only allowed to decommit whole pages.
+ windows.VirtualFree(sectionData.address, sectionData.size, windows.MEM_DECOMMIT)
+ }
+ return nil
+ }
+
+ // determine protection flags based on characteristics
+ ProtectionFlags := [8]uint32{
+ windows.PAGE_NOACCESS, // not writeable, not readable, not executable
+ windows.PAGE_EXECUTE, // not writeable, not readable, executable
+ windows.PAGE_READONLY, // not writeable, readable, not executable
+ windows.PAGE_EXECUTE_READ, // not writeable, readable, executable
+ windows.PAGE_WRITECOPY, // writeable, not readable, not executable
+ windows.PAGE_EXECUTE_WRITECOPY, // writeable, not readable, executable
+ windows.PAGE_READWRITE, // writeable, readable, not executable
+ windows.PAGE_EXECUTE_READWRITE, // writeable, readable, executable
+ }
+ protect := ProtectionFlags[sectionData.characteristics>>29]
+ if (sectionData.characteristics & IMAGE_SCN_MEM_NOT_CACHED) != 0 {
+ protect |= windows.PAGE_NOCACHE
+ }
+
+ // Change memory access flags.
+ var oldProtect uint32
+ err := windows.VirtualProtect(sectionData.address, sectionData.size, protect, &oldProtect)
+ if err != nil {
+ return fmt.Errorf("Error protecting memory page: %w", err)
+ }
+
+ return nil
+}
+
+func (module *Module) registerExceptionHandlers() {
+ directory := module.headerDirectory(IMAGE_DIRECTORY_ENTRY_EXCEPTION)
+ if directory.Size == 0 || directory.VirtualAddress == 0 {
+ return
+ }
+ runtimeFuncs := (*windows.RUNTIME_FUNCTION)(unsafe.Pointer(module.codeBase + uintptr(directory.VirtualAddress)))
+ windows.RtlAddFunctionTable(runtimeFuncs, uint32(uintptr(directory.Size)/unsafe.Sizeof(*runtimeFuncs)), module.codeBase)
+}
+
+func (module *Module) finalizeSections() error {
+ sections := module.headers.Sections()
+ imageOffset := module.headers.OptionalHeader.imageOffset()
+ sectionData := sectionFinalizeData{}
+ sectionData.address = uintptr(sections[0].PhysicalAddress()) | imageOffset
+ sectionData.alignedAddress = alignDown(sectionData.address, uintptr(module.headers.OptionalHeader.SectionAlignment))
+ sectionData.size = module.realSectionSize(&sections[0])
+ sections[0].SetVirtualSize(uint32(sectionData.size))
+ sectionData.characteristics = sections[0].Characteristics
+
+ // Loop through all sections and change access flags.
+ for i := uint16(1); i < module.headers.FileHeader.NumberOfSections; i++ {
+ sectionAddress := uintptr(sections[i].PhysicalAddress()) | imageOffset
+ alignedAddress := alignDown(sectionAddress, uintptr(module.headers.OptionalHeader.SectionAlignment))
+ sectionSize := module.realSectionSize(&sections[i])
+ sections[i].SetVirtualSize(uint32(sectionSize))
+ // Combine access flags of all sections that share a page.
+ // TODO: We currently share flags of a trailing large section with the page of a first small section. This should be optimized.
+ if sectionData.alignedAddress == alignedAddress || sectionData.address+sectionData.size > alignedAddress {
+ // Section shares page with previous.
+ if (sections[i].Characteristics&IMAGE_SCN_MEM_DISCARDABLE) == 0 || (sectionData.characteristics&IMAGE_SCN_MEM_DISCARDABLE) == 0 {
+ sectionData.characteristics = (sectionData.characteristics | sections[i].Characteristics) &^ IMAGE_SCN_MEM_DISCARDABLE
+ } else {
+ sectionData.characteristics |= sections[i].Characteristics
+ }
+ sectionData.size = sectionAddress + sectionSize - sectionData.address
+ continue
+ }
+
+ err := module.finalizeSection(&sectionData)
+ if err != nil {
+ return fmt.Errorf("Error finalizing section: %w", err)
+ }
+ sectionData.address = sectionAddress
+ sectionData.alignedAddress = alignedAddress
+ sectionData.size = sectionSize
+ sectionData.characteristics = sections[i].Characteristics
+ }
+ sectionData.last = true
+ err := module.finalizeSection(&sectionData)
+ if err != nil {
+ return fmt.Errorf("Error finalizing section: %w", err)
+ }
+ return nil
+}
+
+func (module *Module) executeTLS() {
+ directory := module.headerDirectory(IMAGE_DIRECTORY_ENTRY_TLS)
+ if directory.VirtualAddress == 0 {
+ return
+ }
+
+ tls := (*IMAGE_TLS_DIRECTORY)(a2p(module.codeBase + uintptr(directory.VirtualAddress)))
+ callback := tls.AddressOfCallbacks
+ if callback != 0 {
+ for {
+ f := *(*uintptr)(a2p(callback))
+ if f == 0 {
+ break
+ }
+ syscall.SyscallN(f, module.codeBase, DLL_PROCESS_ATTACH, 0)
+ callback += unsafe.Sizeof(f)
+ }
+ }
+}
+
+func (module *Module) performBaseRelocation(delta uintptr) (relocated bool, err error) {
+ directory := module.headerDirectory(IMAGE_DIRECTORY_ENTRY_BASERELOC)
+ if directory.Size == 0 {
+ return delta == 0, nil
+ }
+
+ relocationHdr := (*IMAGE_BASE_RELOCATION)(a2p(module.codeBase + uintptr(directory.VirtualAddress)))
+ for relocationHdr.VirtualAddress > 0 {
+ dest := module.codeBase + uintptr(relocationHdr.VirtualAddress)
+
+ relInfos := unsafe.Slice(
+ (*uint16)(a2p(uintptr(unsafe.Pointer(relocationHdr))+unsafe.Sizeof(*relocationHdr))),
+ (uintptr(relocationHdr.SizeOfBlock)-unsafe.Sizeof(*relocationHdr))/unsafe.Sizeof(uint16(0)))
+ for _, relInfo := range relInfos {
+ // The upper 4 bits define the type of relocation.
+ relType := relInfo >> 12
+ // The lower 12 bits define the offset.
+ relOffset := uintptr(relInfo & 0xfff)
+
+ switch relType {
+ case IMAGE_REL_BASED_ABSOLUTE:
+ // Skip relocation.
+
+ case IMAGE_REL_BASED_LOW:
+ *(*uint16)(a2p(dest + relOffset)) += uint16(delta & 0xffff)
+ break
+
+ case IMAGE_REL_BASED_HIGH:
+ *(*uint16)(a2p(dest + relOffset)) += uint16(uint32(delta) >> 16)
+ break
+
+ case IMAGE_REL_BASED_HIGHLOW:
+ *(*uint32)(a2p(dest + relOffset)) += uint32(delta)
+
+ case IMAGE_REL_BASED_DIR64:
+ *(*uint64)(a2p(dest + relOffset)) += uint64(delta)
+
+ case IMAGE_REL_BASED_THUMB_MOV32:
+ inst := *(*uint32)(a2p(dest + relOffset))
+ imm16 := ((inst << 1) & 0x0800) + ((inst << 12) & 0xf000) +
+ ((inst >> 20) & 0x0700) + ((inst >> 16) & 0x00ff)
+ if (inst & 0x8000fbf0) != 0x0000f240 {
+ return false, fmt.Errorf("Wrong Thumb2 instruction %08x, expected MOVW", inst)
+ }
+ imm16 += uint32(delta) & 0xffff
+ hiDelta := (uint32(delta&0xffff0000) >> 16) + ((imm16 & 0xffff0000) >> 16)
+ *(*uint32)(a2p(dest + relOffset)) = (inst & 0x8f00fbf0) + ((imm16 >> 1) & 0x0400) +
+ ((imm16 >> 12) & 0x000f) +
+ ((imm16 << 20) & 0x70000000) +
+ ((imm16 << 16) & 0xff0000)
+ if hiDelta != 0 {
+ inst = *(*uint32)(a2p(dest + relOffset + 4))
+ imm16 = ((inst << 1) & 0x0800) + ((inst << 12) & 0xf000) +
+ ((inst >> 20) & 0x0700) + ((inst >> 16) & 0x00ff)
+ if (inst & 0x8000fbf0) != 0x0000f2c0 {
+ return false, fmt.Errorf("Wrong Thumb2 instruction %08x, expected MOVT", inst)
+ }
+ imm16 += hiDelta
+ if imm16 > 0xffff {
+ return false, fmt.Errorf("Resulting immediate value won't fit: %08x", imm16)
+ }
+ *(*uint32)(a2p(dest + relOffset + 4)) = (inst & 0x8f00fbf0) +
+ ((imm16 >> 1) & 0x0400) +
+ ((imm16 >> 12) & 0x000f) +
+ ((imm16 << 20) & 0x70000000) +
+ ((imm16 << 16) & 0xff0000)
+ }
+
+ default:
+ return false, fmt.Errorf("Unsupported relocation: %v", relType)
+ }
+ }
+
+ // Advance to next relocation block.
+ relocationHdr = (*IMAGE_BASE_RELOCATION)(a2p(uintptr(unsafe.Pointer(relocationHdr)) + uintptr(relocationHdr.SizeOfBlock)))
+ }
+ return true, nil
+}
+
+func (module *Module) buildImportTable() error {
+ directory := module.headerDirectory(IMAGE_DIRECTORY_ENTRY_IMPORT)
+ if directory.Size == 0 {
+ return nil
+ }
+
+ module.modules = make([]windows.Handle, 0, 16)
+ importDesc := (*IMAGE_IMPORT_DESCRIPTOR)(a2p(module.codeBase + uintptr(directory.VirtualAddress)))
+ for importDesc.Name != 0 {
+ handle, err := windows.LoadLibraryEx(windows.BytePtrToString((*byte)(a2p(module.codeBase+uintptr(importDesc.Name)))), 0, windows.LOAD_LIBRARY_SEARCH_SYSTEM32)
+ if err != nil {
+ return fmt.Errorf("Error loading module: %w", err)
+ }
+ var thunkRef, funcRef *uintptr
+ if importDesc.OriginalFirstThunk() != 0 {
+ thunkRef = (*uintptr)(a2p(module.codeBase + uintptr(importDesc.OriginalFirstThunk())))
+ funcRef = (*uintptr)(a2p(module.codeBase + uintptr(importDesc.FirstThunk)))
+ } else {
+ // No hint table.
+ thunkRef = (*uintptr)(a2p(module.codeBase + uintptr(importDesc.FirstThunk)))
+ funcRef = (*uintptr)(a2p(module.codeBase + uintptr(importDesc.FirstThunk)))
+ }
+ for *thunkRef != 0 {
+ if IMAGE_SNAP_BY_ORDINAL(*thunkRef) {
+ *funcRef, err = windows.GetProcAddressByOrdinal(handle, IMAGE_ORDINAL(*thunkRef))
+ } else {
+ thunkData := (*IMAGE_IMPORT_BY_NAME)(a2p(module.codeBase + *thunkRef))
+ *funcRef, err = windows.GetProcAddress(handle, windows.BytePtrToString(&thunkData.Name[0]))
+ }
+ if err != nil {
+ windows.FreeLibrary(handle)
+ return fmt.Errorf("Error getting function address: %w", err)
+ }
+ thunkRef = (*uintptr)(a2p(uintptr(unsafe.Pointer(thunkRef)) + unsafe.Sizeof(*thunkRef)))
+ funcRef = (*uintptr)(a2p(uintptr(unsafe.Pointer(funcRef)) + unsafe.Sizeof(*funcRef)))
+ }
+ module.modules = append(module.modules, handle)
+ importDesc = (*IMAGE_IMPORT_DESCRIPTOR)(a2p(uintptr(unsafe.Pointer(importDesc)) + unsafe.Sizeof(*importDesc)))
+ }
+ return nil
+}
+
+func (module *Module) buildNameExports() error {
+ directory := module.headerDirectory(IMAGE_DIRECTORY_ENTRY_EXPORT)
+ if directory.Size == 0 {
+ return errors.New("No export table found")
+ }
+ exports := (*IMAGE_EXPORT_DIRECTORY)(a2p(module.codeBase + uintptr(directory.VirtualAddress)))
+ if exports.NumberOfNames == 0 || exports.NumberOfFunctions == 0 {
+ return errors.New("No functions exported")
+ }
+ if exports.NumberOfNames == 0 {
+ return errors.New("No functions exported by name")
+ }
+ nameRefs := unsafe.Slice((*uint32)(a2p(module.codeBase+uintptr(exports.AddressOfNames))), exports.NumberOfNames)
+ ordinals := unsafe.Slice((*uint16)(a2p(module.codeBase+uintptr(exports.AddressOfNameOrdinals))), exports.NumberOfNames)
+ module.nameExports = make(map[string]uint16)
+ for i := range nameRefs {
+ nameArray := windows.BytePtrToString((*byte)(a2p(module.codeBase + uintptr(nameRefs[i]))))
+ module.nameExports[nameArray] = ordinals[i]
+ }
+ return nil
+}
+
+type addressRange struct {
+ start uintptr
+ end uintptr
+}
+
+var (
+ loadedAddressRanges []addressRange
+ loadedAddressRangesMu sync.RWMutex
+ haveHookedRtlPcToFileHeader sync.Once
+ hookRtlPcToFileHeaderResult error
+)
+
+func hookRtlPcToFileHeader() error {
+ var kernelBase windows.Handle
+ err := windows.GetModuleHandleEx(windows.GET_MODULE_HANDLE_EX_FLAG_UNCHANGED_REFCOUNT, windows.StringToUTF16Ptr("kernelbase.dll"), &kernelBase)
+ if err != nil {
+ return err
+ }
+ imageBase := unsafe.Pointer(kernelBase)
+ dosHeader := (*IMAGE_DOS_HEADER)(imageBase)
+ ntHeaders := (*IMAGE_NT_HEADERS)(unsafe.Add(imageBase, dosHeader.E_lfanew))
+ importsDirectory := ntHeaders.OptionalHeader.DataDirectory[IMAGE_DIRECTORY_ENTRY_IMPORT]
+ importDescriptor := (*IMAGE_IMPORT_DESCRIPTOR)(unsafe.Add(imageBase, importsDirectory.VirtualAddress))
+ for ; importDescriptor.Name != 0; importDescriptor = (*IMAGE_IMPORT_DESCRIPTOR)(unsafe.Add(unsafe.Pointer(importDescriptor), unsafe.Sizeof(*importDescriptor))) {
+ libraryName := windows.BytePtrToString((*byte)(unsafe.Add(imageBase, importDescriptor.Name)))
+ if strings.EqualFold(libraryName, "ntdll.dll") {
+ break
+ }
+ }
+ if importDescriptor.Name == 0 {
+ return errors.New("ntdll.dll not found")
+ }
+ originalThunk := (*uintptr)(unsafe.Add(imageBase, importDescriptor.OriginalFirstThunk()))
+ thunk := (*uintptr)(unsafe.Add(imageBase, importDescriptor.FirstThunk))
+ for ; *originalThunk != 0; originalThunk = (*uintptr)(unsafe.Add(unsafe.Pointer(originalThunk), unsafe.Sizeof(*originalThunk))) {
+ if *originalThunk&IMAGE_ORDINAL_FLAG == 0 {
+ function := (*IMAGE_IMPORT_BY_NAME)(unsafe.Add(imageBase, *originalThunk))
+ name := windows.BytePtrToString(&function.Name[0])
+ if name == "RtlPcToFileHeader" {
+ break
+ }
+ }
+ thunk = (*uintptr)(unsafe.Add(unsafe.Pointer(thunk), unsafe.Sizeof(*thunk)))
+ }
+ if *originalThunk == 0 {
+ return errors.New("RtlPcToFileHeader not found")
+ }
+ var oldProtect uint32
+ err = windows.VirtualProtect(uintptr(unsafe.Pointer(thunk)), unsafe.Sizeof(*thunk), windows.PAGE_READWRITE, &oldProtect)
+ if err != nil {
+ return err
+ }
+ originalRtlPcToFileHeader := *thunk
+ *thunk = windows.NewCallback(func(pcValue uintptr, baseOfImage *uintptr) uintptr {
+ loadedAddressRangesMu.RLock()
+ for i := range loadedAddressRanges {
+ if pcValue >= loadedAddressRanges[i].start && pcValue < loadedAddressRanges[i].end {
+ pcValue = *thunk
+ break
+ }
+ }
+ loadedAddressRangesMu.RUnlock()
+ ret, _, _ := syscall.SyscallN(originalRtlPcToFileHeader, pcValue, uintptr(unsafe.Pointer(baseOfImage)))
+ return ret
+ })
+ err = windows.VirtualProtect(uintptr(unsafe.Pointer(thunk)), unsafe.Sizeof(*thunk), oldProtect, &oldProtect)
+ if err != nil {
+ return err
+ }
+ return nil
+}
+
+// LoadLibrary loads module image to memory.
+func LoadLibrary(data []byte) (module *Module, err error) {
+ addr := uintptr(unsafe.Pointer(&data[0]))
+ size := uintptr(len(data))
+ if size < unsafe.Sizeof(IMAGE_DOS_HEADER{}) {
+ return nil, errors.New("Incomplete IMAGE_DOS_HEADER")
+ }
+ dosHeader := (*IMAGE_DOS_HEADER)(a2p(addr))
+ if dosHeader.E_magic != IMAGE_DOS_SIGNATURE {
+ return nil, fmt.Errorf("Not an MS-DOS binary (provided: %x, expected: %x)", dosHeader.E_magic, IMAGE_DOS_SIGNATURE)
+ }
+ if (size < uintptr(dosHeader.E_lfanew)+unsafe.Sizeof(IMAGE_NT_HEADERS{})) {
+ return nil, errors.New("Incomplete IMAGE_NT_HEADERS")
+ }
+ oldHeader := (*IMAGE_NT_HEADERS)(a2p(addr + uintptr(dosHeader.E_lfanew)))
+ if oldHeader.Signature != IMAGE_NT_SIGNATURE {
+ return nil, fmt.Errorf("Not an NT binary (provided: %x, expected: %x)", oldHeader.Signature, IMAGE_NT_SIGNATURE)
+ }
+ if oldHeader.FileHeader.Machine != imageFileProcess {
+ return nil, fmt.Errorf("Foreign platform (provided: %x, expected: %x)", oldHeader.FileHeader.Machine, imageFileProcess)
+ }
+ if (oldHeader.OptionalHeader.SectionAlignment & 1) != 0 {
+ return nil, errors.New("Unaligned section")
+ }
+ lastSectionEnd := uintptr(0)
+ sections := oldHeader.Sections()
+ optionalSectionSize := oldHeader.OptionalHeader.SectionAlignment
+ for i := range sections {
+ var endOfSection uintptr
+ if sections[i].SizeOfRawData == 0 {
+ // Section without data in the DLL
+ endOfSection = uintptr(sections[i].VirtualAddress) + uintptr(optionalSectionSize)
+ } else {
+ endOfSection = uintptr(sections[i].VirtualAddress) + uintptr(sections[i].SizeOfRawData)
+ }
+ if endOfSection > lastSectionEnd {
+ lastSectionEnd = endOfSection
+ }
+ }
+ alignedImageSize := alignUp(uintptr(oldHeader.OptionalHeader.SizeOfImage), uintptr(oldHeader.OptionalHeader.SectionAlignment))
+ if alignedImageSize != alignUp(lastSectionEnd, uintptr(oldHeader.OptionalHeader.SectionAlignment)) {
+ return nil, errors.New("Section is not page-aligned")
+ }
+
+ module = &Module{isDLL: (oldHeader.FileHeader.Characteristics & IMAGE_FILE_DLL) != 0}
+ defer func() {
+ if err != nil {
+ module.Free()
+ module = nil
+ }
+ }()
+
+ // Reserve memory for image of library.
+ // TODO: Is it correct to commit the complete memory region at once? Calling DllEntry raises an exception if we don't.
+ module.codeBase, err = windows.VirtualAlloc(oldHeader.OptionalHeader.ImageBase,
+ alignedImageSize,
+ windows.MEM_RESERVE|windows.MEM_COMMIT,
+ windows.PAGE_READWRITE)
+ if err != nil {
+ // Try to allocate memory at arbitrary position.
+ module.codeBase, err = windows.VirtualAlloc(0,
+ alignedImageSize,
+ windows.MEM_RESERVE|windows.MEM_COMMIT,
+ windows.PAGE_READWRITE)
+ if err != nil {
+ err = fmt.Errorf("Error allocating code: %w", err)
+ return
+ }
+ }
+ err = module.check4GBBoundaries(alignedImageSize)
+ if err != nil {
+ err = fmt.Errorf("Error reallocating code: %w", err)
+ return
+ }
+
+ if size < uintptr(oldHeader.OptionalHeader.SizeOfHeaders) {
+ err = errors.New("Incomplete headers")
+ return
+ }
+ // Commit memory for headers.
+ headers, err := windows.VirtualAlloc(module.codeBase,
+ uintptr(oldHeader.OptionalHeader.SizeOfHeaders),
+ windows.MEM_COMMIT,
+ windows.PAGE_READWRITE)
+ if err != nil {
+ err = fmt.Errorf("Error allocating headers: %w", err)
+ return
+ }
+ // Copy PE header to code.
+ memcpy(headers, addr, uintptr(oldHeader.OptionalHeader.SizeOfHeaders))
+ module.headers = (*IMAGE_NT_HEADERS)(a2p(headers + uintptr(dosHeader.E_lfanew)))
+
+ // Update position.
+ module.headers.OptionalHeader.ImageBase = module.codeBase
+
+ // Copy sections from DLL file block to new memory location.
+ err = module.copySections(addr, size, oldHeader)
+ if err != nil {
+ err = fmt.Errorf("Error copying sections: %w", err)
+ return
+ }
+
+ // Adjust base address of imported data.
+ locationDelta := module.headers.OptionalHeader.ImageBase - oldHeader.OptionalHeader.ImageBase
+ if locationDelta != 0 {
+ module.isRelocated, err = module.performBaseRelocation(locationDelta)
+ if err != nil {
+ err = fmt.Errorf("Error relocating module: %w", err)
+ return
+ }
+ } else {
+ module.isRelocated = true
+ }
+
+ // Load required dlls and adjust function table of imports.
+ err = module.buildImportTable()
+ if err != nil {
+ err = fmt.Errorf("Error building import table: %w", err)
+ return
+ }
+
+ // Mark memory pages depending on section headers and release sections that are marked as "discardable".
+ err = module.finalizeSections()
+ if err != nil {
+ err = fmt.Errorf("Error finalizing sections: %w", err)
+ return
+ }
+
+ // Register exception tables, if they exist.
+ module.registerExceptionHandlers()
+
+ // Register function PCs.
+ loadedAddressRangesMu.Lock()
+ loadedAddressRanges = append(loadedAddressRanges, addressRange{module.codeBase, module.codeBase + alignedImageSize})
+ loadedAddressRangesMu.Unlock()
+ haveHookedRtlPcToFileHeader.Do(func() {
+ hookRtlPcToFileHeaderResult = hookRtlPcToFileHeader()
+ })
+ err = hookRtlPcToFileHeaderResult
+ if err != nil {
+ return
+ }
+
+ // TLS callbacks are executed BEFORE the main loading.
+ module.executeTLS()
+
+ // Get entry point of loaded module.
+ if module.headers.OptionalHeader.AddressOfEntryPoint != 0 {
+ module.entry = module.codeBase + uintptr(module.headers.OptionalHeader.AddressOfEntryPoint)
+ if module.isDLL {
+ // Notify library about attaching to process.
+ r0, _, _ := syscall.SyscallN(module.entry, module.codeBase, DLL_PROCESS_ATTACH, 0)
+ successful := r0 != 0
+ if !successful {
+ err = windows.ERROR_DLL_INIT_FAILED
+ return
+ }
+ module.initialized = true
+ }
+ }
+
+ module.buildNameExports()
+ return
+}
+
+// Free releases module resources and unloads it.
+func (module *Module) Free() {
+ if module.initialized {
+ // Notify library about detaching from process.
+ syscall.SyscallN(module.entry, module.codeBase, DLL_PROCESS_DETACH, 0)
+ module.initialized = false
+ }
+ if module.modules != nil {
+ // Free previously opened libraries.
+ for _, handle := range module.modules {
+ windows.FreeLibrary(handle)
+ }
+ module.modules = nil
+ }
+ if module.codeBase != 0 {
+ windows.VirtualFree(module.codeBase, 0, windows.MEM_RELEASE)
+ module.codeBase = 0
+ }
+ if module.blockedMemory != nil {
+ module.blockedMemory.free()
+ module.blockedMemory = nil
+ }
+}
+
+// ProcAddressByName returns function address by exported name.
+func (module *Module) ProcAddressByName(name string) (uintptr, error) {
+ directory := module.headerDirectory(IMAGE_DIRECTORY_ENTRY_EXPORT)
+ if directory.Size == 0 {
+ return 0, errors.New("No export table found")
+ }
+ exports := (*IMAGE_EXPORT_DIRECTORY)(a2p(module.codeBase + uintptr(directory.VirtualAddress)))
+ if module.nameExports == nil {
+ return 0, errors.New("No functions exported by name")
+ }
+ if idx, ok := module.nameExports[name]; ok {
+ if uint32(idx) > exports.NumberOfFunctions {
+ return 0, errors.New("Ordinal number too high")
+ }
+ // AddressOfFunctions contains the RVAs to the "real" functions.
+ return module.codeBase + uintptr(*(*uint32)(a2p(module.codeBase + uintptr(exports.AddressOfFunctions) + uintptr(idx)*4))), nil
+ }
+ return 0, errors.New("Function not found by name")
+}
+
+// ProcAddressByOrdinal returns function address by exported ordinal.
+func (module *Module) ProcAddressByOrdinal(ordinal uint16) (uintptr, error) {
+ directory := module.headerDirectory(IMAGE_DIRECTORY_ENTRY_EXPORT)
+ if directory.Size == 0 {
+ return 0, errors.New("No export table found")
+ }
+ exports := (*IMAGE_EXPORT_DIRECTORY)(a2p(module.codeBase + uintptr(directory.VirtualAddress)))
+ if uint32(ordinal) < exports.Base {
+ return 0, errors.New("Ordinal number too low")
+ }
+ idx := ordinal - uint16(exports.Base)
+ if uint32(idx) > exports.NumberOfFunctions {
+ return 0, errors.New("Ordinal number too high")
+ }
+ // AddressOfFunctions contains the RVAs to the "real" functions.
+ return module.codeBase + uintptr(*(*uint32)(a2p(module.codeBase + uintptr(exports.AddressOfFunctions) + uintptr(idx)*4))), nil
+}
+
+func alignDown(value, alignment uintptr) uintptr {
+ return value & ^(alignment - 1)
+}
+
+func alignUp(value, alignment uintptr) uintptr {
+ return (value + alignment - 1) & ^(alignment - 1)
+}
+
+func a2p(addr uintptr) unsafe.Pointer {
+ return unsafe.Pointer(addr)
+}
+
+func memcpy(dst, src, size uintptr) {
+ copy(unsafe.Slice((*byte)(a2p(dst)), size), unsafe.Slice((*byte)(a2p(src)), size))
+}
diff --git a/driver/memmod/memmod_windows_32.go b/driver/memmod/memmod_windows_32.go
new file mode 100644
index 00000000..611fbe53
--- /dev/null
+++ b/driver/memmod/memmod_windows_32.go
@@ -0,0 +1,16 @@
+//go:build (windows && 386) || (windows && arm)
+
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package memmod
+
+func (opthdr *IMAGE_OPTIONAL_HEADER) imageOffset() uintptr {
+ return 0
+}
+
+func (module *Module) check4GBBoundaries(alignedImageSize uintptr) (err error) {
+ return
+}
diff --git a/driver/memmod/memmod_windows_386.go b/driver/memmod/memmod_windows_386.go
new file mode 100644
index 00000000..71d6c93e
--- /dev/null
+++ b/driver/memmod/memmod_windows_386.go
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package memmod
+
+const imageFileProcess = IMAGE_FILE_MACHINE_I386
diff --git a/driver/memmod/memmod_windows_64.go b/driver/memmod/memmod_windows_64.go
new file mode 100644
index 00000000..28ada96e
--- /dev/null
+++ b/driver/memmod/memmod_windows_64.go
@@ -0,0 +1,36 @@
+//go:build (windows && amd64) || (windows && arm64)
+
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package memmod
+
+import (
+ "fmt"
+
+ "golang.org/x/sys/windows"
+)
+
+func (opthdr *IMAGE_OPTIONAL_HEADER) imageOffset() uintptr {
+ return uintptr(opthdr.ImageBase & 0xffffffff00000000)
+}
+
+func (module *Module) check4GBBoundaries(alignedImageSize uintptr) (err error) {
+ for (module.codeBase >> 32) < ((module.codeBase + alignedImageSize) >> 32) {
+ node := &addressList{
+ next: module.blockedMemory,
+ address: module.codeBase,
+ }
+ module.blockedMemory = node
+ module.codeBase, err = windows.VirtualAlloc(0,
+ alignedImageSize,
+ windows.MEM_RESERVE|windows.MEM_COMMIT,
+ windows.PAGE_READWRITE)
+ if err != nil {
+ return fmt.Errorf("Error allocating memory block: %w", err)
+ }
+ }
+ return
+}
diff --git a/driver/memmod/memmod_windows_amd64.go b/driver/memmod/memmod_windows_amd64.go
new file mode 100644
index 00000000..2459b2d2
--- /dev/null
+++ b/driver/memmod/memmod_windows_amd64.go
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package memmod
+
+const imageFileProcess = IMAGE_FILE_MACHINE_AMD64
diff --git a/driver/memmod/memmod_windows_arm.go b/driver/memmod/memmod_windows_arm.go
new file mode 100644
index 00000000..a644cee6
--- /dev/null
+++ b/driver/memmod/memmod_windows_arm.go
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package memmod
+
+const imageFileProcess = IMAGE_FILE_MACHINE_ARMNT
diff --git a/driver/memmod/memmod_windows_arm64.go b/driver/memmod/memmod_windows_arm64.go
new file mode 100644
index 00000000..09e24639
--- /dev/null
+++ b/driver/memmod/memmod_windows_arm64.go
@@ -0,0 +1,8 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package memmod
+
+const imageFileProcess = IMAGE_FILE_MACHINE_ARM64
diff --git a/driver/memmod/syscall_windows.go b/driver/memmod/syscall_windows.go
new file mode 100644
index 00000000..cdc6ef67
--- /dev/null
+++ b/driver/memmod/syscall_windows.go
@@ -0,0 +1,392 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package memmod
+
+import "unsafe"
+
+const (
+ IMAGE_DOS_SIGNATURE = 0x5A4D // MZ
+ IMAGE_OS2_SIGNATURE = 0x454E // NE
+ IMAGE_OS2_SIGNATURE_LE = 0x454C // LE
+ IMAGE_VXD_SIGNATURE = 0x454C // LE
+ IMAGE_NT_SIGNATURE = 0x00004550 // PE00
+)
+
+// DOS .EXE header
+type IMAGE_DOS_HEADER struct {
+ E_magic uint16 // Magic number
+ E_cblp uint16 // Bytes on last page of file
+ E_cp uint16 // Pages in file
+ E_crlc uint16 // Relocations
+ E_cparhdr uint16 // Size of header in paragraphs
+ E_minalloc uint16 // Minimum extra paragraphs needed
+ E_maxalloc uint16 // Maximum extra paragraphs needed
+ E_ss uint16 // Initial (relative) SS value
+ E_sp uint16 // Initial SP value
+ E_csum uint16 // Checksum
+ E_ip uint16 // Initial IP value
+ E_cs uint16 // Initial (relative) CS value
+ E_lfarlc uint16 // File address of relocation table
+ E_ovno uint16 // Overlay number
+ E_res [4]uint16 // Reserved words
+ E_oemid uint16 // OEM identifier (for e_oeminfo)
+ E_oeminfo uint16 // OEM information; e_oemid specific
+ E_res2 [10]uint16 // Reserved words
+ E_lfanew int32 // File address of new exe header
+}
+
+// File header format
+type IMAGE_FILE_HEADER struct {
+ Machine uint16
+ NumberOfSections uint16
+ TimeDateStamp uint32
+ PointerToSymbolTable uint32
+ NumberOfSymbols uint32
+ SizeOfOptionalHeader uint16
+ Characteristics uint16
+}
+
+const (
+ IMAGE_SIZEOF_FILE_HEADER = 20
+
+ IMAGE_FILE_RELOCS_STRIPPED = 0x0001 // Relocation info stripped from file.
+ IMAGE_FILE_EXECUTABLE_IMAGE = 0x0002 // File is executable (i.e. no unresolved external references).
+ IMAGE_FILE_LINE_NUMS_STRIPPED = 0x0004 // Line nunbers stripped from file.
+ IMAGE_FILE_LOCAL_SYMS_STRIPPED = 0x0008 // Local symbols stripped from file.
+ IMAGE_FILE_AGGRESIVE_WS_TRIM = 0x0010 // Aggressively trim working set
+ IMAGE_FILE_LARGE_ADDRESS_AWARE = 0x0020 // App can handle >2gb addresses
+ IMAGE_FILE_BYTES_REVERSED_LO = 0x0080 // Bytes of machine word are reversed.
+ IMAGE_FILE_32BIT_MACHINE = 0x0100 // 32 bit word machine.
+ IMAGE_FILE_DEBUG_STRIPPED = 0x0200 // Debugging info stripped from file in .DBG file
+ IMAGE_FILE_REMOVABLE_RUN_FROM_SWAP = 0x0400 // If Image is on removable media, copy and run from the swap file.
+ IMAGE_FILE_NET_RUN_FROM_SWAP = 0x0800 // If Image is on Net, copy and run from the swap file.
+ IMAGE_FILE_SYSTEM = 0x1000 // System File.
+ IMAGE_FILE_DLL = 0x2000 // File is a DLL.
+ IMAGE_FILE_UP_SYSTEM_ONLY = 0x4000 // File should only be run on a UP machine
+ IMAGE_FILE_BYTES_REVERSED_HI = 0x8000 // Bytes of machine word are reversed.
+
+ IMAGE_FILE_MACHINE_UNKNOWN = 0
+ IMAGE_FILE_MACHINE_TARGET_HOST = 0x0001 // Useful for indicating we want to interact with the host and not a WoW guest.
+ IMAGE_FILE_MACHINE_I386 = 0x014c // Intel 386.
+ IMAGE_FILE_MACHINE_R3000 = 0x0162 // MIPS little-endian, 0x160 big-endian
+ IMAGE_FILE_MACHINE_R4000 = 0x0166 // MIPS little-endian
+ IMAGE_FILE_MACHINE_R10000 = 0x0168 // MIPS little-endian
+ IMAGE_FILE_MACHINE_WCEMIPSV2 = 0x0169 // MIPS little-endian WCE v2
+ IMAGE_FILE_MACHINE_ALPHA = 0x0184 // Alpha_AXP
+ IMAGE_FILE_MACHINE_SH3 = 0x01a2 // SH3 little-endian
+ IMAGE_FILE_MACHINE_SH3DSP = 0x01a3
+ IMAGE_FILE_MACHINE_SH3E = 0x01a4 // SH3E little-endian
+ IMAGE_FILE_MACHINE_SH4 = 0x01a6 // SH4 little-endian
+ IMAGE_FILE_MACHINE_SH5 = 0x01a8 // SH5
+ IMAGE_FILE_MACHINE_ARM = 0x01c0 // ARM Little-Endian
+ IMAGE_FILE_MACHINE_THUMB = 0x01c2 // ARM Thumb/Thumb-2 Little-Endian
+ IMAGE_FILE_MACHINE_ARMNT = 0x01c4 // ARM Thumb-2 Little-Endian
+ IMAGE_FILE_MACHINE_AM33 = 0x01d3
+ IMAGE_FILE_MACHINE_POWERPC = 0x01F0 // IBM PowerPC Little-Endian
+ IMAGE_FILE_MACHINE_POWERPCFP = 0x01f1
+ IMAGE_FILE_MACHINE_IA64 = 0x0200 // Intel 64
+ IMAGE_FILE_MACHINE_MIPS16 = 0x0266 // MIPS
+ IMAGE_FILE_MACHINE_ALPHA64 = 0x0284 // ALPHA64
+ IMAGE_FILE_MACHINE_MIPSFPU = 0x0366 // MIPS
+ IMAGE_FILE_MACHINE_MIPSFPU16 = 0x0466 // MIPS
+ IMAGE_FILE_MACHINE_AXP64 = IMAGE_FILE_MACHINE_ALPHA64
+ IMAGE_FILE_MACHINE_TRICORE = 0x0520 // Infineon
+ IMAGE_FILE_MACHINE_CEF = 0x0CEF
+ IMAGE_FILE_MACHINE_EBC = 0x0EBC // EFI Byte Code
+ IMAGE_FILE_MACHINE_AMD64 = 0x8664 // AMD64 (K8)
+ IMAGE_FILE_MACHINE_M32R = 0x9041 // M32R little-endian
+ IMAGE_FILE_MACHINE_ARM64 = 0xAA64 // ARM64 Little-Endian
+ IMAGE_FILE_MACHINE_CEE = 0xC0EE
+)
+
+// Directory format
+type IMAGE_DATA_DIRECTORY struct {
+ VirtualAddress uint32
+ Size uint32
+}
+
+const IMAGE_NUMBEROF_DIRECTORY_ENTRIES = 16
+
+type IMAGE_NT_HEADERS struct {
+ Signature uint32
+ FileHeader IMAGE_FILE_HEADER
+ OptionalHeader IMAGE_OPTIONAL_HEADER
+}
+
+func (ntheader *IMAGE_NT_HEADERS) Sections() []IMAGE_SECTION_HEADER {
+ return (*[0xffff]IMAGE_SECTION_HEADER)(unsafe.Pointer(
+ (uintptr)(unsafe.Pointer(ntheader)) +
+ unsafe.Offsetof(ntheader.OptionalHeader) +
+ uintptr(ntheader.FileHeader.SizeOfOptionalHeader)))[:ntheader.FileHeader.NumberOfSections]
+}
+
+const (
+ IMAGE_DIRECTORY_ENTRY_EXPORT = 0 // Export Directory
+ IMAGE_DIRECTORY_ENTRY_IMPORT = 1 // Import Directory
+ IMAGE_DIRECTORY_ENTRY_RESOURCE = 2 // Resource Directory
+ IMAGE_DIRECTORY_ENTRY_EXCEPTION = 3 // Exception Directory
+ IMAGE_DIRECTORY_ENTRY_SECURITY = 4 // Security Directory
+ IMAGE_DIRECTORY_ENTRY_BASERELOC = 5 // Base Relocation Table
+ IMAGE_DIRECTORY_ENTRY_DEBUG = 6 // Debug Directory
+ IMAGE_DIRECTORY_ENTRY_COPYRIGHT = 7 // (X86 usage)
+ IMAGE_DIRECTORY_ENTRY_ARCHITECTURE = 7 // Architecture Specific Data
+ IMAGE_DIRECTORY_ENTRY_GLOBALPTR = 8 // RVA of GP
+ IMAGE_DIRECTORY_ENTRY_TLS = 9 // TLS Directory
+ IMAGE_DIRECTORY_ENTRY_LOAD_CONFIG = 10 // Load Configuration Directory
+ IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT = 11 // Bound Import Directory in headers
+ IMAGE_DIRECTORY_ENTRY_IAT = 12 // Import Address Table
+ IMAGE_DIRECTORY_ENTRY_DELAY_IMPORT = 13 // Delay Load Import Descriptors
+ IMAGE_DIRECTORY_ENTRY_COM_DESCRIPTOR = 14 // COM Runtime descriptor
+)
+
+const IMAGE_SIZEOF_SHORT_NAME = 8
+
+// Section header format
+type IMAGE_SECTION_HEADER struct {
+ Name [IMAGE_SIZEOF_SHORT_NAME]byte
+ physicalAddressOrVirtualSize uint32
+ VirtualAddress uint32
+ SizeOfRawData uint32
+ PointerToRawData uint32
+ PointerToRelocations uint32
+ PointerToLinenumbers uint32
+ NumberOfRelocations uint16
+ NumberOfLinenumbers uint16
+ Characteristics uint32
+}
+
+func (ishdr *IMAGE_SECTION_HEADER) PhysicalAddress() uint32 {
+ return ishdr.physicalAddressOrVirtualSize
+}
+
+func (ishdr *IMAGE_SECTION_HEADER) SetPhysicalAddress(addr uint32) {
+ ishdr.physicalAddressOrVirtualSize = addr
+}
+
+func (ishdr *IMAGE_SECTION_HEADER) VirtualSize() uint32 {
+ return ishdr.physicalAddressOrVirtualSize
+}
+
+func (ishdr *IMAGE_SECTION_HEADER) SetVirtualSize(addr uint32) {
+ ishdr.physicalAddressOrVirtualSize = addr
+}
+
+const (
+ // Dll characteristics.
+ IMAGE_DLL_CHARACTERISTICS_HIGH_ENTROPY_VA = 0x0020
+ IMAGE_DLL_CHARACTERISTICS_DYNAMIC_BASE = 0x0040
+ IMAGE_DLL_CHARACTERISTICS_FORCE_INTEGRITY = 0x0080
+ IMAGE_DLL_CHARACTERISTICS_NX_COMPAT = 0x0100
+ IMAGE_DLL_CHARACTERISTICS_NO_ISOLATION = 0x0200
+ IMAGE_DLL_CHARACTERISTICS_NO_SEH = 0x0400
+ IMAGE_DLL_CHARACTERISTICS_NO_BIND = 0x0800
+ IMAGE_DLL_CHARACTERISTICS_APPCONTAINER = 0x1000
+ IMAGE_DLL_CHARACTERISTICS_WDM_DRIVER = 0x2000
+ IMAGE_DLL_CHARACTERISTICS_GUARD_CF = 0x4000
+ IMAGE_DLL_CHARACTERISTICS_TERMINAL_SERVER_AWARE = 0x8000
+)
+
+const (
+ // Section characteristics.
+ IMAGE_SCN_TYPE_REG = 0x00000000 // Reserved.
+ IMAGE_SCN_TYPE_DSECT = 0x00000001 // Reserved.
+ IMAGE_SCN_TYPE_NOLOAD = 0x00000002 // Reserved.
+ IMAGE_SCN_TYPE_GROUP = 0x00000004 // Reserved.
+ IMAGE_SCN_TYPE_NO_PAD = 0x00000008 // Reserved.
+ IMAGE_SCN_TYPE_COPY = 0x00000010 // Reserved.
+
+ IMAGE_SCN_CNT_CODE = 0x00000020 // Section contains code.
+ IMAGE_SCN_CNT_INITIALIZED_DATA = 0x00000040 // Section contains initialized data.
+ IMAGE_SCN_CNT_UNINITIALIZED_DATA = 0x00000080 // Section contains uninitialized data.
+
+ IMAGE_SCN_LNK_OTHER = 0x00000100 // Reserved.
+ IMAGE_SCN_LNK_INFO = 0x00000200 // Section contains comments or some other type of information.
+ IMAGE_SCN_TYPE_OVER = 0x00000400 // Reserved.
+ IMAGE_SCN_LNK_REMOVE = 0x00000800 // Section contents will not become part of image.
+ IMAGE_SCN_LNK_COMDAT = 0x00001000 // Section contents comdat.
+ IMAGE_SCN_MEM_PROTECTED = 0x00004000 // Obsolete.
+ IMAGE_SCN_NO_DEFER_SPEC_EXC = 0x00004000 // Reset speculative exceptions handling bits in the TLB entries for this section.
+ IMAGE_SCN_GPREL = 0x00008000 // Section content can be accessed relative to GP
+ IMAGE_SCN_MEM_FARDATA = 0x00008000
+ IMAGE_SCN_MEM_SYSHEAP = 0x00010000 // Obsolete.
+ IMAGE_SCN_MEM_PURGEABLE = 0x00020000
+ IMAGE_SCN_MEM_16BIT = 0x00020000
+ IMAGE_SCN_MEM_LOCKED = 0x00040000
+ IMAGE_SCN_MEM_PRELOAD = 0x00080000
+
+ IMAGE_SCN_ALIGN_1BYTES = 0x00100000 //
+ IMAGE_SCN_ALIGN_2BYTES = 0x00200000 //
+ IMAGE_SCN_ALIGN_4BYTES = 0x00300000 //
+ IMAGE_SCN_ALIGN_8BYTES = 0x00400000 //
+ IMAGE_SCN_ALIGN_16BYTES = 0x00500000 // Default alignment if no others are specified.
+ IMAGE_SCN_ALIGN_32BYTES = 0x00600000 //
+ IMAGE_SCN_ALIGN_64BYTES = 0x00700000 //
+ IMAGE_SCN_ALIGN_128BYTES = 0x00800000 //
+ IMAGE_SCN_ALIGN_256BYTES = 0x00900000 //
+ IMAGE_SCN_ALIGN_512BYTES = 0x00A00000 //
+ IMAGE_SCN_ALIGN_1024BYTES = 0x00B00000 //
+ IMAGE_SCN_ALIGN_2048BYTES = 0x00C00000 //
+ IMAGE_SCN_ALIGN_4096BYTES = 0x00D00000 //
+ IMAGE_SCN_ALIGN_8192BYTES = 0x00E00000 //
+ IMAGE_SCN_ALIGN_MASK = 0x00F00000
+
+ IMAGE_SCN_LNK_NRELOC_OVFL = 0x01000000 // Section contains extended relocations.
+ IMAGE_SCN_MEM_DISCARDABLE = 0x02000000 // Section can be discarded.
+ IMAGE_SCN_MEM_NOT_CACHED = 0x04000000 // Section is not cachable.
+ IMAGE_SCN_MEM_NOT_PAGED = 0x08000000 // Section is not pageable.
+ IMAGE_SCN_MEM_SHARED = 0x10000000 // Section is shareable.
+ IMAGE_SCN_MEM_EXECUTE = 0x20000000 // Section is executable.
+ IMAGE_SCN_MEM_READ = 0x40000000 // Section is readable.
+ IMAGE_SCN_MEM_WRITE = 0x80000000 // Section is writeable.
+
+ // TLS Characteristic Flags
+ IMAGE_SCN_SCALE_INDEX = 0x00000001 // Tls index is scaled.
+)
+
+// Based relocation format
+type IMAGE_BASE_RELOCATION struct {
+ VirtualAddress uint32
+ SizeOfBlock uint32
+}
+
+const (
+ IMAGE_REL_BASED_ABSOLUTE = 0
+ IMAGE_REL_BASED_HIGH = 1
+ IMAGE_REL_BASED_LOW = 2
+ IMAGE_REL_BASED_HIGHLOW = 3
+ IMAGE_REL_BASED_HIGHADJ = 4
+ IMAGE_REL_BASED_MACHINE_SPECIFIC_5 = 5
+ IMAGE_REL_BASED_RESERVED = 6
+ IMAGE_REL_BASED_MACHINE_SPECIFIC_7 = 7
+ IMAGE_REL_BASED_MACHINE_SPECIFIC_8 = 8
+ IMAGE_REL_BASED_MACHINE_SPECIFIC_9 = 9
+ IMAGE_REL_BASED_DIR64 = 10
+
+ IMAGE_REL_BASED_IA64_IMM64 = 9
+
+ IMAGE_REL_BASED_MIPS_JMPADDR = 5
+ IMAGE_REL_BASED_MIPS_JMPADDR16 = 9
+
+ IMAGE_REL_BASED_ARM_MOV32 = 5
+ IMAGE_REL_BASED_THUMB_MOV32 = 7
+)
+
+// Export Format
+type IMAGE_EXPORT_DIRECTORY struct {
+ Characteristics uint32
+ TimeDateStamp uint32
+ MajorVersion uint16
+ MinorVersion uint16
+ Name uint32
+ Base uint32
+ NumberOfFunctions uint32
+ NumberOfNames uint32
+ AddressOfFunctions uint32 // RVA from base of image
+ AddressOfNames uint32 // RVA from base of image
+ AddressOfNameOrdinals uint32 // RVA from base of image
+}
+
+type IMAGE_IMPORT_BY_NAME struct {
+ Hint uint16
+ Name [1]byte
+}
+
+func IMAGE_ORDINAL(ordinal uintptr) uintptr {
+ return ordinal & 0xffff
+}
+
+func IMAGE_SNAP_BY_ORDINAL(ordinal uintptr) bool {
+ return (ordinal & IMAGE_ORDINAL_FLAG) != 0
+}
+
+// Thread Local Storage
+type IMAGE_TLS_DIRECTORY struct {
+ StartAddressOfRawData uintptr
+ EndAddressOfRawData uintptr
+ AddressOfIndex uintptr // PDWORD
+ AddressOfCallbacks uintptr // PIMAGE_TLS_CALLBACK *;
+ SizeOfZeroFill uint32
+ Characteristics uint32
+}
+
+type IMAGE_IMPORT_DESCRIPTOR struct {
+ characteristicsOrOriginalFirstThunk uint32 // 0 for terminating null import descriptor
+ // RVA to original unbound IAT (PIMAGE_THUNK_DATA)
+ TimeDateStamp uint32 // 0 if not bound,
+ // -1 if bound, and real date\time stamp
+ // in IMAGE_DIRECTORY_ENTRY_BOUND_IMPORT (new BIND)
+ // O.W. date/time stamp of DLL bound to (Old BIND)
+ ForwarderChain uint32 // -1 if no forwarders
+ Name uint32
+ FirstThunk uint32 // RVA to IAT (if bound this IAT has actual addresses)
+}
+
+func (imgimpdesc *IMAGE_IMPORT_DESCRIPTOR) Characteristics() uint32 {
+ return imgimpdesc.characteristicsOrOriginalFirstThunk
+}
+
+func (imgimpdesc *IMAGE_IMPORT_DESCRIPTOR) OriginalFirstThunk() uint32 {
+ return imgimpdesc.characteristicsOrOriginalFirstThunk
+}
+
+type IMAGE_DELAYLOAD_DESCRIPTOR struct {
+ Attributes uint32
+ DllNameRVA uint32
+ ModuleHandleRVA uint32
+ ImportAddressTableRVA uint32
+ ImportNameTableRVA uint32
+ BoundImportAddressTableRVA uint32
+ UnloadInformationTableRVA uint32
+ TimeDateStamp uint32
+}
+
+type IMAGE_LOAD_CONFIG_CODE_INTEGRITY struct {
+ Flags uint16
+ Catalog uint16
+ CatalogOffset uint32
+ Reserved uint32
+}
+
+const (
+ IMAGE_GUARD_CF_INSTRUMENTED = 0x00000100
+ IMAGE_GUARD_CFW_INSTRUMENTED = 0x00000200
+ IMAGE_GUARD_CF_FUNCTION_TABLE_PRESENT = 0x00000400
+ IMAGE_GUARD_SECURITY_COOKIE_UNUSED = 0x00000800
+ IMAGE_GUARD_PROTECT_DELAYLOAD_IAT = 0x00001000
+ IMAGE_GUARD_DELAYLOAD_IAT_IN_ITS_OWN_SECTION = 0x00002000
+ IMAGE_GUARD_CF_EXPORT_SUPPRESSION_INFO_PRESENT = 0x00004000
+ IMAGE_GUARD_CF_ENABLE_EXPORT_SUPPRESSION = 0x00008000
+ IMAGE_GUARD_CF_LONGJUMP_TABLE_PRESENT = 0x00010000
+ IMAGE_GUARD_RF_INSTRUMENTED = 0x00020000
+ IMAGE_GUARD_RF_ENABLE = 0x00040000
+ IMAGE_GUARD_RF_STRICT = 0x00080000
+ IMAGE_GUARD_RETPOLINE_PRESENT = 0x00100000
+ IMAGE_GUARD_EH_CONTINUATION_TABLE_PRESENT = 0x00400000
+ IMAGE_GUARD_XFG_ENABLED = 0x00800000
+ IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_MASK = 0xF0000000
+ IMAGE_GUARD_CF_FUNCTION_TABLE_SIZE_SHIFT = 28
+)
+
+const (
+ DLL_PROCESS_ATTACH = 1
+ DLL_THREAD_ATTACH = 2
+ DLL_THREAD_DETACH = 3
+ DLL_PROCESS_DETACH = 0
+)
+
+type SYSTEM_INFO struct {
+ ProcessorArchitecture uint16
+ Reserved uint16
+ PageSize uint32
+ MinimumApplicationAddress uintptr
+ MaximumApplicationAddress uintptr
+ ActiveProcessorMask uintptr
+ NumberOfProcessors uint32
+ ProcessorType uint32
+ AllocationGranularity uint32
+ ProcessorLevel uint16
+ ProcessorRevision uint16
+}
diff --git a/driver/memmod/syscall_windows_32.go b/driver/memmod/syscall_windows_32.go
new file mode 100644
index 00000000..dde8b360
--- /dev/null
+++ b/driver/memmod/syscall_windows_32.go
@@ -0,0 +1,96 @@
+//go:build (windows && 386) || (windows && arm)
+
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package memmod
+
+// Optional header format
+type IMAGE_OPTIONAL_HEADER struct {
+ Magic uint16
+ MajorLinkerVersion uint8
+ MinorLinkerVersion uint8
+ SizeOfCode uint32
+ SizeOfInitializedData uint32
+ SizeOfUninitializedData uint32
+ AddressOfEntryPoint uint32
+ BaseOfCode uint32
+ BaseOfData uint32
+ ImageBase uintptr
+ SectionAlignment uint32
+ FileAlignment uint32
+ MajorOperatingSystemVersion uint16
+ MinorOperatingSystemVersion uint16
+ MajorImageVersion uint16
+ MinorImageVersion uint16
+ MajorSubsystemVersion uint16
+ MinorSubsystemVersion uint16
+ Win32VersionValue uint32
+ SizeOfImage uint32
+ SizeOfHeaders uint32
+ CheckSum uint32
+ Subsystem uint16
+ DllCharacteristics uint16
+ SizeOfStackReserve uintptr
+ SizeOfStackCommit uintptr
+ SizeOfHeapReserve uintptr
+ SizeOfHeapCommit uintptr
+ LoaderFlags uint32
+ NumberOfRvaAndSizes uint32
+ DataDirectory [IMAGE_NUMBEROF_DIRECTORY_ENTRIES]IMAGE_DATA_DIRECTORY
+}
+
+const IMAGE_ORDINAL_FLAG uintptr = 0x80000000
+
+type IMAGE_LOAD_CONFIG_DIRECTORY struct {
+ Size uint32
+ TimeDateStamp uint32
+ MajorVersion uint16
+ MinorVersion uint16
+ GlobalFlagsClear uint32
+ GlobalFlagsSet uint32
+ CriticalSectionDefaultTimeout uint32
+ DeCommitFreeBlockThreshold uint32
+ DeCommitTotalFreeThreshold uint32
+ LockPrefixTable uint32
+ MaximumAllocationSize uint32
+ VirtualMemoryThreshold uint32
+ ProcessHeapFlags uint32
+ ProcessAffinityMask uint32
+ CSDVersion uint16
+ DependentLoadFlags uint16
+ EditList uint32
+ SecurityCookie uint32
+ SEHandlerTable uint32
+ SEHandlerCount uint32
+ GuardCFCheckFunctionPointer uint32
+ GuardCFDispatchFunctionPointer uint32
+ GuardCFFunctionTable uint32
+ GuardCFFunctionCount uint32
+ GuardFlags uint32
+ CodeIntegrity IMAGE_LOAD_CONFIG_CODE_INTEGRITY
+ GuardAddressTakenIatEntryTable uint32
+ GuardAddressTakenIatEntryCount uint32
+ GuardLongJumpTargetTable uint32
+ GuardLongJumpTargetCount uint32
+ DynamicValueRelocTable uint32
+ CHPEMetadataPointer uint32
+ GuardRFFailureRoutine uint32
+ GuardRFFailureRoutineFunctionPointer uint32
+ DynamicValueRelocTableOffset uint32
+ DynamicValueRelocTableSection uint16
+ Reserved2 uint16
+ GuardRFVerifyStackPointerFunctionPointer uint32
+ HotPatchTableOffset uint32
+ Reserved3 uint32
+ EnclaveConfigurationPointer uint32
+ VolatileMetadataPointer uint32
+ GuardEHContinuationTable uint32
+ GuardEHContinuationCount uint32
+ GuardXFGCheckFunctionPointer uint32
+ GuardXFGDispatchFunctionPointer uint32
+ GuardXFGTableDispatchFunctionPointer uint32
+ CastGuardOsDeterminedFailureMode uint32
+}
diff --git a/driver/memmod/syscall_windows_64.go b/driver/memmod/syscall_windows_64.go
new file mode 100644
index 00000000..f23524fb
--- /dev/null
+++ b/driver/memmod/syscall_windows_64.go
@@ -0,0 +1,95 @@
+//go:build (windows && amd64) || (windows && arm64)
+
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2017-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package memmod
+
+// Optional header format
+type IMAGE_OPTIONAL_HEADER struct {
+ Magic uint16
+ MajorLinkerVersion uint8
+ MinorLinkerVersion uint8
+ SizeOfCode uint32
+ SizeOfInitializedData uint32
+ SizeOfUninitializedData uint32
+ AddressOfEntryPoint uint32
+ BaseOfCode uint32
+ ImageBase uintptr
+ SectionAlignment uint32
+ FileAlignment uint32
+ MajorOperatingSystemVersion uint16
+ MinorOperatingSystemVersion uint16
+ MajorImageVersion uint16
+ MinorImageVersion uint16
+ MajorSubsystemVersion uint16
+ MinorSubsystemVersion uint16
+ Win32VersionValue uint32
+ SizeOfImage uint32
+ SizeOfHeaders uint32
+ CheckSum uint32
+ Subsystem uint16
+ DllCharacteristics uint16
+ SizeOfStackReserve uintptr
+ SizeOfStackCommit uintptr
+ SizeOfHeapReserve uintptr
+ SizeOfHeapCommit uintptr
+ LoaderFlags uint32
+ NumberOfRvaAndSizes uint32
+ DataDirectory [IMAGE_NUMBEROF_DIRECTORY_ENTRIES]IMAGE_DATA_DIRECTORY
+}
+
+const IMAGE_ORDINAL_FLAG uintptr = 0x8000000000000000
+
+type IMAGE_LOAD_CONFIG_DIRECTORY struct {
+ Size uint32
+ TimeDateStamp uint32
+ MajorVersion uint16
+ MinorVersion uint16
+ GlobalFlagsClear uint32
+ GlobalFlagsSet uint32
+ CriticalSectionDefaultTimeout uint32
+ DeCommitFreeBlockThreshold uint64
+ DeCommitTotalFreeThreshold uint64
+ LockPrefixTable uint64
+ MaximumAllocationSize uint64
+ VirtualMemoryThreshold uint64
+ ProcessAffinityMask uint64
+ ProcessHeapFlags uint32
+ CSDVersion uint16
+ DependentLoadFlags uint16
+ EditList uint64
+ SecurityCookie uint64
+ SEHandlerTable uint64
+ SEHandlerCount uint64
+ GuardCFCheckFunctionPointer uint64
+ GuardCFDispatchFunctionPointer uint64
+ GuardCFFunctionTable uint64
+ GuardCFFunctionCount uint64
+ GuardFlags uint32
+ CodeIntegrity IMAGE_LOAD_CONFIG_CODE_INTEGRITY
+ GuardAddressTakenIatEntryTable uint64
+ GuardAddressTakenIatEntryCount uint64
+ GuardLongJumpTargetTable uint64
+ GuardLongJumpTargetCount uint64
+ DynamicValueRelocTable uint64
+ CHPEMetadataPointer uint64
+ GuardRFFailureRoutine uint64
+ GuardRFFailureRoutineFunctionPointer uint64
+ DynamicValueRelocTableOffset uint32
+ DynamicValueRelocTableSection uint16
+ Reserved2 uint16
+ GuardRFVerifyStackPointerFunctionPointer uint64
+ HotPatchTableOffset uint32
+ Reserved3 uint32
+ EnclaveConfigurationPointer uint64
+ VolatileMetadataPointer uint64
+ GuardEHContinuationTable uint64
+ GuardEHContinuationCount uint64
+ GuardXFGCheckFunctionPointer uint64
+ GuardXFGDispatchFunctionPointer uint64
+ GuardXFGTableDispatchFunctionPointer uint64
+ CastGuardOsDeterminedFailureMode uint64
+}
diff --git a/driver/wintunremoval_windows.go b/driver/wintunremoval_windows.go
new file mode 100644
index 00000000..ab51d989
--- /dev/null
+++ b/driver/wintunremoval_windows.go
@@ -0,0 +1,50 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package driver
+
+import (
+ "path/filepath"
+
+ "golang.org/x/sys/windows"
+)
+
+func UninstallLegacyWintun() error {
+ deviceClassNetGUID := &windows.GUID{0x4d36e972, 0xe325, 0x11ce, [8]byte{0xbf, 0xc1, 0x08, 0x00, 0x2b, 0xe1, 0x03, 0x18}}
+ devInfo, err := windows.SetupDiCreateDeviceInfoListEx(deviceClassNetGUID, 0, "")
+ if err != nil {
+ return err
+ }
+ defer devInfo.Close()
+ devInfoData, err := devInfo.CreateDeviceInfo("Wintun", deviceClassNetGUID, "", 0, windows.DICD_GENERATE_ID)
+ if err != nil {
+ return err
+ }
+ err = devInfo.SetDeviceRegistryProperty(devInfoData, windows.SPDRP_HARDWAREID, []byte("W\x00i\x00n\x00t\x00u\x00n\x00\x00\x00\x00\x00"))
+ if err != nil {
+ return err
+ }
+ err = devInfo.BuildDriverInfoList(devInfoData, windows.SPDIT_COMPATDRIVER)
+ if err != nil {
+ return err
+ }
+ defer devInfo.DestroyDriverInfoList(devInfoData, windows.SPDIT_COMPATDRIVER)
+ var lastError error
+ for i := 0; ; i++ {
+ drvInfoData, err := devInfo.EnumDriverInfo(devInfoData, windows.SPDIT_COMPATDRIVER, i)
+ if err != nil {
+ if err == windows.ERROR_NO_MORE_ITEMS {
+ break
+ }
+ continue
+ }
+ drvInfoDetailData, err := devInfo.DriverInfoDetail(devInfoData, drvInfoData)
+ if err != nil {
+ continue
+ }
+ lastError = windows.SetupUninstallOEMInf(filepath.Base(drvInfoDetailData.InfFileName()), 0)
+ }
+ return lastError
+}
diff --git a/elevate/doas.go b/elevate/doas.go
index da692b20..b67ee88c 100644
--- a/elevate/doas.go
+++ b/elevate/doas.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package elevate
@@ -19,11 +19,11 @@ import (
func setAllEnv(env []string) {
windows.Clearenv()
for _, e := range env {
- kv := strings.SplitN(e, "=", 2)
- if len(kv) != 2 {
+ k, v, ok := strings.Cut(e, "=")
+ if !ok {
continue
}
- windows.Setenv(kv[0], kv[1])
+ windows.Setenv(k, v)
}
}
diff --git a/elevate/loader.go b/elevate/loader.go
index d474a007..7d15f8a4 100644
--- a/elevate/loader.go
+++ b/elevate/loader.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package elevate
diff --git a/elevate/membership.go b/elevate/membership.go
index e73b2f9d..383a10ba 100644
--- a/elevate/membership.go
+++ b/elevate/membership.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package elevate
diff --git a/elevate/privileges.go b/elevate/privileges.go
index 5c4cd69f..3d51640f 100644
--- a/elevate/privileges.go
+++ b/elevate/privileges.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package elevate
@@ -44,7 +44,7 @@ func DropAllPrivileges(retainDriverLoading bool) error {
}
tokenPrivileges := (*windows.Tokenprivileges)(unsafe.Pointer(&buffer[0]))
for i := uint32(0); i < tokenPrivileges.PrivilegeCount; i++ {
- item := (*windows.LUIDAndAttributes)(unsafe.Pointer(uintptr(unsafe.Pointer(&tokenPrivileges.Privileges[0])) + unsafe.Sizeof(tokenPrivileges.Privileges[0])*uintptr(i)))
+ item := (*windows.LUIDAndAttributes)(unsafe.Add(unsafe.Pointer(&tokenPrivileges.Privileges[0]), unsafe.Sizeof(tokenPrivileges.Privileges[0])*uintptr(i)))
if retainDriverLoading && item.Luid == luid {
continue
}
diff --git a/elevate/shellexecute.go b/elevate/shellexecute.go
index 2ac5581c..e0be9d98 100644
--- a/elevate/shellexecute.go
+++ b/elevate/shellexecute.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package elevate
@@ -24,7 +24,7 @@ const (
cSEE_MASK_DEFAULT = 0
)
-func ShellExecute(program string, arguments string, directory string, show int32) (err error) {
+func ShellExecute(program, arguments, directory string, show int32) (err error) {
var (
program16 *uint16
arguments16 *uint16
@@ -121,7 +121,7 @@ func ShellExecute(program string, arguments string, directory string, show int32
if err = windows.CoGetObject(
windows.StringToUTF16Ptr("Elevation:Administrator!new:{3E5FC7F9-9A51-4367-9063-A120244FBEC7}"),
&windows.BIND_OPTS3{
- CbStruct: uint32(unsafe.Sizeof(windows.BIND_OPTS3{})),
+ CbStruct: uint32(unsafe.Sizeof(windows.BIND_OPTS3{})),
ClassContext: windows.CLSCTX_LOCAL_SERVER,
},
&windows.GUID{0x6EDD6D74, 0xC007, 0x4E75, [8]byte{0xB7, 0x6A, 0xE5, 0x74, 0x09, 0x95, 0xE2, 0x4C}},
@@ -130,13 +130,13 @@ func ShellExecute(program string, arguments string, directory string, show int32
return
}
- defer syscall.Syscall((*interfacePointer)[releaseOffset], 1, uintptr(unsafe.Pointer(interfacePointer)), 0, 0)
+ defer syscall.SyscallN((*interfacePointer)[releaseOffset], uintptr(unsafe.Pointer(interfacePointer)))
if program16 == nil {
return
}
- if ret, _, _ := syscall.Syscall6((*interfacePointer)[shellExecuteOffset], 6,
+ if ret, _, _ := syscall.SyscallN((*interfacePointer)[shellExecuteOffset],
uintptr(unsafe.Pointer(interfacePointer)),
uintptr(unsafe.Pointer(program16)),
uintptr(unsafe.Pointer(arguments16)),
diff --git a/embeddable-dll-service/.gitignore b/embeddable-dll-service/.gitignore
new file mode 100644
index 00000000..9e3c52ab
--- /dev/null
+++ b/embeddable-dll-service/.gitignore
@@ -0,0 +1,4 @@
+# Build Output
+/x86
+/amd64
+/arm64
diff --git a/embeddable-dll-service/README.md b/embeddable-dll-service/README.md
index c93b4345..a326dc70 100644
--- a/embeddable-dll-service/README.md
+++ b/embeddable-dll-service/README.md
@@ -1,6 +1,6 @@
## Embeddable WireGuard Tunnel Library
-This allows embedding WireGuard as a service inside of another application. Build `tunnel.dll` by running `./build.bat` in this folder. The first time you run it, it will invoke `..\build.bat` simply for downloading dependencies. After, you should have `amd64/tunnel.dll` and `x86/tunnel.dll`.
+This allows embedding WireGuard as a service inside of another application. Build `tunnel.dll` by running `./build.bat` in this folder. The first time you run it, it will invoke `..\build.bat` simply for downloading dependencies. After, you should have `amd64/tunnel.dll`, `x86/tunnel.dll`, and `arm64/tunnel.dll`. In addition, `tunnel.dll` requires `wireguard.dll`, which can be downloaded from [the wireguard-nt download server](https://download.wireguard.com/wireguard-nt/).
The basic setup to use `tunnel.dll` is:
@@ -24,23 +24,18 @@ is absolutely essential; do not forget it.
##### 2. Have your program's main function handle the `/service` switch:
```c
-if (!strcmp(argv[1], "/service") && argc == 3) {
+if (wargc == 3 && !wcscmp(wargv[1], L"/service")) {
HMODULE tunnel_lib = LoadLibrary("tunnel.dll");
if (!tunnel_lib)
abort();
- tunnel_proc_t tunnel_proc = (tunnel_proc_t)GetProcAddress(tunnel_lib, "WireGuardTunnelService");
+ BOOL (_cdecl *tunnel_proc)(_In_ LPCWSTR conf_file);
+ *(FARPROC*)&tunnel_proc = GetProcAddress(tunnel_lib, "WireGuardTunnelService");
if (!tunnel_proc)
abort();
- struct go_string conf_file = {
- .str = argv[2],
- .n = strlen(argv[2])
- };
- return tunnel_proc(conf_file);
+ return tunnel_proc(wargv[2]);
}
```
##### 3. Scoop up logs by implementing a ringlogger format reader.
-##### 4. Talk to the service over its named pipe.
-
There is a sample implementation of bits and pieces of this inside of the `csharp\` directory.
diff --git a/embeddable-dll-service/build.bat b/embeddable-dll-service/build.bat
index 0d2cbdbb..f1001192 100644
--- a/embeddable-dll-service/build.bat
+++ b/embeddable-dll-service/build.bat
@@ -1,6 +1,6 @@
@echo off
rem SPDX-License-Identifier: MIT
-rem Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+rem Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
setlocal
set BUILDDIR=%~dp0
@@ -21,9 +21,14 @@ if exist ..\.deps\prepared goto :build
set CGO_CFLAGS=-O3 -Wall -Wno-unused-function -Wno-switch -std=gnu11 -DWINVER=0x0601
call :build_plat x86 i686 386 || goto :error
call :build_plat amd64 x86_64 amd64 || goto :error
- rem Uncomment when cgo is implemented:
- rem call :build_plat arm armv7 arm || goto :error
- rem call :build_plat arm64 aarch64 arm64 || goto :error
+ call :build_plat arm64 aarch64 arm64 || goto :error
+
+:sign
+ if exist ..\sign.bat call ..\sign.bat
+ if "%SigningProvider%"=="" goto :success
+ if "%TimestampServer%"=="" goto :success
+ echo [+] Signing
+ signtool sign %SigningProvider% /fd sha256 /tr "%TimestampServer%" /td sha256 /d "WireGuard Tunnel" x86\tunnel.dll amd64\tunnel.dll arm64\tunnel.dll || goto :error
:success
echo [+] Success
diff --git a/embeddable-dll-service/csharp/.gitignore b/embeddable-dll-service/csharp/.gitignore
new file mode 100644
index 00000000..28bcb4ab
--- /dev/null
+++ b/embeddable-dll-service/csharp/.gitignore
@@ -0,0 +1,3 @@
+/.vs
+/bin
+/obj
diff --git a/embeddable-dll-service/csharp/DemoUI/MainWindow.Designer.cs b/embeddable-dll-service/csharp/DemoUI/MainWindow.Designer.cs
index 5fae35d3..5aad1b97 100644
--- a/embeddable-dll-service/csharp/DemoUI/MainWindow.Designer.cs
+++ b/embeddable-dll-service/csharp/DemoUI/MainWindow.Designer.cs
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
namespace DemoUI
diff --git a/embeddable-dll-service/csharp/DemoUI/MainWindow.cs b/embeddable-dll-service/csharp/DemoUI/MainWindow.cs
index 7d1e3f6f..1df17181 100644
--- a/embeddable-dll-service/csharp/DemoUI/MainWindow.cs
+++ b/embeddable-dll-service/csharp/DemoUI/MainWindow.cs
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
using System;
@@ -66,49 +66,43 @@ namespace DemoUI
private void tailTransfer()
{
- StreamReader reader = null;
- NamedPipeClientStream stream = null;
+ Tunnel.Driver.Adapter adapter = null;
while (threadsRunning)
{
- try
+ if (adapter == null)
{
- stream = Tunnel.Service.GetPipe(configFile);
- stream.Connect();
- reader = new StreamReader(stream);
- break;
+ while (threadsRunning)
+ {
+ try
+ {
+ adapter = Tunnel.Service.GetAdapter(configFile);
+ break;
+ }
+ catch
+ {
+ try
+ {
+ Thread.Sleep(1000);
+ }
+ catch { }
+ }
+ }
}
- catch { }
- Thread.Sleep(1000);
- }
-
- try
- {
- while (threadsRunning)
+ if (adapter == null)
+ continue;
+ try
{
- stream.Write(Encoding.UTF8.GetBytes("get=1\n\n"));
ulong rx = 0, tx = 0;
- while (threadsRunning)
+ var config = adapter.GetConfiguration();
+ foreach (var peer in config.Peers)
{
- var line = reader.ReadLine();
- if (line == null)
- break;
- line = line.Trim();
- if (line.Length == 0)
- break;
- if (line.StartsWith("rx_bytes="))
- rx += ulong.Parse(line.Substring(9));
- else if (line.StartsWith("tx_bytes="))
- tx += ulong.Parse(line.Substring(9));
+ rx += peer.RxBytes;
+ tx += peer.TxBytes;
}
Invoke(new Action<ulong, ulong>(updateTransferTitle), new object[] { rx, tx });
Thread.Sleep(1000);
}
- }
- catch { }
- finally
- {
- if (stream.IsConnected)
- stream.Close();
+ catch { adapter = null; }
}
}
diff --git a/embeddable-dll-service/csharp/DemoUI/Program.cs b/embeddable-dll-service/csharp/DemoUI/Program.cs
index 8c420973..3649ab93 100644
--- a/embeddable-dll-service/csharp/DemoUI/Program.cs
+++ b/embeddable-dll-service/csharp/DemoUI/Program.cs
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
using System;
diff --git a/embeddable-dll-service/csharp/README.md b/embeddable-dll-service/csharp/README.md
index 071d15f6..24b36563 100644
--- a/embeddable-dll-service/csharp/README.md
+++ b/embeddable-dll-service/csharp/README.md
@@ -4,12 +4,4 @@ This is a simple client for demo.wireguard.com, which brings up WireGuard tunnel
## Building
-The code in this repository can be built in Visual Studio 2019 by opening the .sln and pressing build. However, it requires `tunnel.dll` to be present in the run directory. That can be built by:
-
-```batch
-> git clone https://git.zx2c4.com/wireguard-windows
-> cd wireguard-windows\embeddable-dll-service
-> .\build.bat
-```
-
-In addition, `tunnel.dll` requires `wintun.dll`, which can be downloaded from [wintun.net](https://www.wintun.net).
+The code in this repository can be built in Visual Studio 2019 by opening the .sln and pressing build. However, it requires [`tunnel.dll` and `wireguard.dll`](../README.md).
diff --git a/embeddable-dll-service/csharp/TunnelDll/Driver.cs b/embeddable-dll-service/csharp/TunnelDll/Driver.cs
new file mode 100644
index 00000000..69911ec8
--- /dev/null
+++ b/embeddable-dll-service/csharp/TunnelDll/Driver.cs
@@ -0,0 +1,234 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+using System;
+using System.ComponentModel;
+using System.Net;
+using System.Runtime.InteropServices;
+
+namespace Tunnel
+{
+ public class Driver
+ {
+ [DllImport("wireguard.dll", EntryPoint = "WireGuardOpenAdapter", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
+ private static extern IntPtr openAdapter([MarshalAs(UnmanagedType.LPWStr)] string name);
+ [DllImport("wireguard.dll", EntryPoint = "WireGuardCloseAdapter", CallingConvention = CallingConvention.StdCall)]
+ private static extern void freeAdapter(IntPtr adapter);
+ [DllImport("wireguard.dll", EntryPoint = "WireGuardGetConfiguration", CallingConvention = CallingConvention.StdCall, SetLastError = true)]
+ private static extern bool getConfiguration(IntPtr adapter, byte[] iface, ref UInt32 bytes);
+
+ public class Adapter
+ {
+ private IntPtr _handle;
+ private UInt32 _lastGetGuess;
+ public Adapter(string name)
+ {
+ _lastGetGuess = 1024;
+ _handle = openAdapter(name);
+ if (_handle == IntPtr.Zero)
+ throw new Win32Exception();
+ }
+ ~Adapter()
+ {
+ freeAdapter(_handle);
+ }
+ public unsafe Interface GetConfiguration()
+ {
+ var iface = new Interface();
+ byte[] bytes;
+ for (; ; )
+ {
+ bytes = new byte[_lastGetGuess];
+ if (getConfiguration(_handle, bytes, ref _lastGetGuess))
+ break;
+ if (Marshal.GetLastWin32Error() != 234 /* ERROR_MORE_DATA */)
+ throw new Win32Exception();
+ }
+ fixed (void* start = bytes)
+ {
+ var ioctlIface = (IoctlInterface*)start;
+ if ((ioctlIface->Flags & IoctlInterfaceFlags.HasPublicKey) != 0)
+ iface.PublicKey = new Key(ioctlIface->PublicKey);
+ if ((ioctlIface->Flags & IoctlInterfaceFlags.HasPrivateKey) != 0)
+ iface.PrivateKey = new Key(ioctlIface->PrivateKey);
+ if ((ioctlIface->Flags & IoctlInterfaceFlags.HasListenPort) != 0)
+ iface.ListenPort = ioctlIface->ListenPort;
+ var peers = new Peer[ioctlIface->PeersCount];
+ var ioctlPeer = (IoctlPeer*)((byte*)ioctlIface + sizeof(IoctlInterface));
+ for (UInt32 i = 0; i < peers.Length; ++i)
+ {
+ var peer = new Peer();
+ if ((ioctlPeer->Flags & IoctlPeerFlags.HasPublicKey) != 0)
+ peer.PublicKey = new Key(ioctlPeer->PublicKey);
+ if ((ioctlPeer->Flags & IoctlPeerFlags.HasPresharedKey) != 0)
+ peer.PresharedKey = new Key(ioctlPeer->PresharedKey);
+ if ((ioctlPeer->Flags & IoctlPeerFlags.HasPersistentKeepalive) != 0)
+ peer.PersistentKeepalive = ioctlPeer->PersistentKeepalive;
+ if ((ioctlPeer->Flags & IoctlPeerFlags.HasEndpoint) != 0)
+ {
+ if (ioctlPeer->Endpoint.si_family == Win32.ADDRESS_FAMILY.AF_INET)
+ {
+ var ip = new byte[4];
+ Marshal.Copy((IntPtr)ioctlPeer->Endpoint.Ipv4.sin_addr.bytes, ip, 0, 4);
+ peer.Endpoint = new IPEndPoint(new IPAddress(ip), (ushort)IPAddress.NetworkToHostOrder((short)ioctlPeer->Endpoint.Ipv4.sin_port));
+ }
+ else if (ioctlPeer->Endpoint.si_family == Win32.ADDRESS_FAMILY.AF_INET6)
+ {
+ var ip = new byte[16];
+ Marshal.Copy((IntPtr)ioctlPeer->Endpoint.Ipv6.sin6_addr.bytes, ip, 0, 16);
+ peer.Endpoint = new IPEndPoint(new IPAddress(ip), (ushort)IPAddress.NetworkToHostOrder((short)ioctlPeer->Endpoint.Ipv6.sin6_port));
+ }
+ }
+ peer.TxBytes = ioctlPeer->TxBytes;
+ peer.RxBytes = ioctlPeer->RxBytes;
+ if (ioctlPeer->LastHandshake != 0)
+ peer.LastHandshake = DateTime.FromFileTimeUtc((long)ioctlPeer->LastHandshake);
+ var allowedIPs = new AllowedIP[ioctlPeer->AllowedIPsCount];
+ var ioctlAllowedIP = (IoctlAllowedIP*)((byte*)ioctlPeer + sizeof(IoctlPeer));
+ for (UInt32 j = 0; j < allowedIPs.Length; ++j)
+ {
+ var allowedIP = new AllowedIP();
+ if (ioctlAllowedIP->AddressFamily == Win32.ADDRESS_FAMILY.AF_INET)
+ {
+ var ip = new byte[4];
+ Marshal.Copy((IntPtr)ioctlAllowedIP->V4.bytes, ip, 0, 4);
+ allowedIP.Address = new IPAddress(ip);
+ }
+ else if (ioctlAllowedIP->AddressFamily == Win32.ADDRESS_FAMILY.AF_INET6)
+ {
+ var ip = new byte[16];
+ Marshal.Copy((IntPtr)ioctlAllowedIP->V6.bytes, ip, 0, 16);
+ allowedIP.Address = new IPAddress(ip);
+ }
+ allowedIP.Cidr = ioctlAllowedIP->Cidr;
+ allowedIPs[j] = allowedIP;
+ ioctlAllowedIP = (IoctlAllowedIP*)((byte*)ioctlAllowedIP + sizeof(IoctlAllowedIP));
+ }
+ peer.AllowedIPs = allowedIPs;
+ peers[i] = peer;
+ ioctlPeer = (IoctlPeer*)ioctlAllowedIP;
+ }
+ iface.Peers = peers;
+ }
+ return iface;
+ }
+
+ public class Key
+ {
+ private byte[] _bytes;
+ public byte[] Bytes
+ {
+ get
+ {
+ return _bytes;
+ }
+ set
+ {
+ if (value == null || value.Length != 32)
+ throw new ArgumentException("Keys must be 32 bytes");
+ _bytes = value;
+ }
+ }
+ public Key(byte[] bytes)
+ {
+ Bytes = bytes;
+ }
+ public unsafe Key(byte* bytes)
+ {
+ _bytes = new byte[32];
+ Marshal.Copy((IntPtr)bytes, _bytes, 0, 32);
+ }
+ public override String ToString()
+ {
+ return Convert.ToBase64String(_bytes);
+ }
+ }
+
+ public class Interface
+ {
+ public UInt16 ListenPort { get; set; }
+ public Key PrivateKey { get; set; }
+ public Key PublicKey { get; set; }
+ public Peer[] Peers { get; set; }
+ }
+
+ public class Peer
+ {
+ public Key PublicKey { get; set; }
+ public Key PresharedKey { get; set; }
+ public UInt16 PersistentKeepalive { get; set; }
+ public IPEndPoint Endpoint { get; set; }
+ public UInt64 TxBytes { get; set; }
+ public UInt64 RxBytes { get; set; }
+ public DateTime LastHandshake { get; set; }
+ public AllowedIP[] AllowedIPs { get; set; }
+ }
+
+ public class AllowedIP
+ {
+ public IPAddress Address { get; set; }
+ public byte Cidr { get; set; }
+ }
+
+ private enum IoctlInterfaceFlags : UInt32
+ {
+ HasPublicKey = 1 << 0,
+ HasPrivateKey = 1 << 1,
+ HasListenPort = 1 << 2,
+ ReplacePeers = 1 << 3
+ };
+
+ [StructLayout(LayoutKind.Sequential, Pack = 8, Size = 80)]
+ private unsafe struct IoctlInterface
+ {
+ public IoctlInterfaceFlags Flags;
+ public UInt16 ListenPort;
+ public fixed byte PrivateKey[32];
+ public fixed byte PublicKey[32];
+ public UInt32 PeersCount;
+ };
+
+ private enum IoctlPeerFlags : UInt32
+ {
+ HasPublicKey = 1 << 0,
+ HasPresharedKey = 1 << 1,
+ HasPersistentKeepalive = 1 << 2,
+ HasEndpoint = 1 << 3,
+ ReplaceAllowedIPs = 1 << 5,
+ Remove = 1 << 6,
+ UpdateOnly = 1 << 7
+ };
+
+ [StructLayout(LayoutKind.Sequential, Pack = 8, Size = 136)]
+ private unsafe struct IoctlPeer
+ {
+ public IoctlPeerFlags Flags;
+ public UInt32 Reserved;
+ public fixed byte PublicKey[32];
+ public fixed byte PresharedKey[32];
+ public UInt16 PersistentKeepalive;
+ public Win32.SOCKADDR_INET Endpoint;
+ public UInt64 TxBytes, RxBytes;
+ public UInt64 LastHandshake;
+ public UInt32 AllowedIPsCount;
+ };
+
+ [StructLayout(LayoutKind.Explicit, Pack = 8, Size = 24)]
+ private unsafe struct IoctlAllowedIP
+ {
+ [FieldOffset(0)]
+ [MarshalAs(UnmanagedType.Struct)]
+ public Win32.IN_ADDR V4;
+ [FieldOffset(0)]
+ [MarshalAs(UnmanagedType.Struct)]
+ public Win32.IN6_ADDR V6;
+ [FieldOffset(16)]
+ public Win32.ADDRESS_FAMILY AddressFamily;
+ [FieldOffset(20)]
+ public byte Cidr;
+ }
+ }
+ }
+}
diff --git a/embeddable-dll-service/csharp/TunnelDll/Keypair.cs b/embeddable-dll-service/csharp/TunnelDll/Keypair.cs
index 146d56e0..59847b98 100644
--- a/embeddable-dll-service/csharp/TunnelDll/Keypair.cs
+++ b/embeddable-dll-service/csharp/TunnelDll/Keypair.cs
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
using System;
diff --git a/embeddable-dll-service/csharp/TunnelDll/Ringlogger.cs b/embeddable-dll-service/csharp/TunnelDll/Ringlogger.cs
index 469927c1..9db01fc8 100644
--- a/embeddable-dll-service/csharp/TunnelDll/Ringlogger.cs
+++ b/embeddable-dll-service/csharp/TunnelDll/Ringlogger.cs
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
using System;
diff --git a/embeddable-dll-service/csharp/TunnelDll/Service.cs b/embeddable-dll-service/csharp/TunnelDll/Service.cs
index 7f2c622e..74e1a888 100644
--- a/embeddable-dll-service/csharp/TunnelDll/Service.cs
+++ b/embeddable-dll-service/csharp/TunnelDll/Service.cs
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
using System;
@@ -21,10 +21,9 @@ namespace Tunnel
[DllImport("tunnel.dll", EntryPoint = "WireGuardTunnelService", CallingConvention = CallingConvention.Cdecl)]
public static extern bool Run([MarshalAs(UnmanagedType.LPWStr)] string configFile);
- public static NamedPipeClientStream GetPipe(string configFile)
+ public static Driver.Adapter GetAdapter(string configFile)
{
- var pipepath = "ProtectedPrefix\\Administrators\\WireGuard\\" + Path.GetFileNameWithoutExtension(configFile);
- return new NamedPipeClientStream(pipepath);
+ return new Driver.Adapter(Path.GetFileNameWithoutExtension(configFile));
}
public static void Add(string configFile, bool ephemeral)
@@ -46,7 +45,7 @@ namespace Tunnel
Win32.CloseServiceHandle(service);
Remove(configFile, true);
}
- service = Win32.CreateService(scm, shortName, longName, Win32.ServiceAccessRights.AllAccess, Win32.ServiceType.Win32OwnProcess, Win32.ServiceStartType.Demand, Win32.ServiceError.Normal, pathAndArgs, null, IntPtr.Zero, "Nsi\0TcpIp", null, null);
+ service = Win32.CreateService(scm, shortName, longName, Win32.ServiceAccessRights.AllAccess, Win32.ServiceType.Win32OwnProcess, Win32.ServiceStartType.Demand, Win32.ServiceError.Normal, pathAndArgs, null, IntPtr.Zero, "Nsi\0TcpIp\0", null, null);
if (service == IntPtr.Zero)
throw new Win32Exception(Marshal.GetLastWin32Error());
try
@@ -88,10 +87,7 @@ namespace Tunnel
{
var service = Win32.OpenService(scm, shortName, Win32.ServiceAccessRights.AllAccess);
if (service == IntPtr.Zero)
- {
- Win32.CloseServiceHandle(service);
return;
- }
try
{
var serviceStatus = new Win32.ServiceStatus();
diff --git a/embeddable-dll-service/csharp/TunnelDll/Win32.cs b/embeddable-dll-service/csharp/TunnelDll/Win32.cs
index d8447f7f..8e7f986d 100644
--- a/embeddable-dll-service/csharp/TunnelDll/Win32.cs
+++ b/embeddable-dll-service/csharp/TunnelDll/Win32.cs
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
using System;
@@ -135,6 +135,58 @@ namespace Tunnel
SidInfo = 5
}
+ [StructLayout(LayoutKind.Sequential)]
+ public unsafe struct IN_ADDR
+ {
+ public fixed byte bytes[4];
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public unsafe struct IN6_ADDR
+ {
+ public fixed byte bytes[16];
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct SOCKADDR_IN
+ {
+ public ushort sin_family;
+ public ushort sin_port;
+ public IN_ADDR sin_addr;
+ }
+
+ [StructLayout(LayoutKind.Sequential)]
+ public struct SOCKADDR_IN6
+ {
+ public ushort sin6_family;
+ public ushort sin6_port;
+ public uint sin6_flowinfo;
+ public IN6_ADDR sin6_addr;
+ public uint sin6_scope_id;
+ }
+
+ [StructLayout(LayoutKind.Explicit)]
+ public struct SOCKADDR_INET
+ {
+ [FieldOffset(0)]
+ [MarshalAs(UnmanagedType.Struct)]
+ public SOCKADDR_IN Ipv4;
+
+ [FieldOffset(0)]
+ [MarshalAs(UnmanagedType.Struct)]
+ public SOCKADDR_IN6 Ipv6;
+
+ [FieldOffset(0)]
+ public ADDRESS_FAMILY si_family;
+ }
+
+ public enum ADDRESS_FAMILY : UInt16
+ {
+ AF_UNSPEC = 0,
+ AF_INET = 2,
+ AF_INET6 = 23
+ }
+
[DllImport("advapi32.dll", EntryPoint = "OpenSCManagerW", ExactSpelling = true, CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr OpenSCManager(string machineName, string databaseName, ScmAccessRights dwDesiredAccess);
diff --git a/embeddable-dll-service/main.go b/embeddable-dll-service/main.go
index df63034e..f313ae7f 100644
--- a/embeddable-dll-service/main.go
+++ b/embeddable-dll-service/main.go
@@ -1,23 +1,22 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package main
import (
"C"
+ "crypto/rand"
+ "log"
+ "path/filepath"
+ "unsafe"
"golang.org/x/crypto/curve25519"
"golang.org/x/sys/windows"
"golang.zx2c4.com/wireguard/windows/conf"
"golang.zx2c4.com/wireguard/windows/tunnel"
-
- "crypto/rand"
- "log"
- "path/filepath"
- "unsafe"
)
//export WireGuardTunnelService
@@ -33,7 +32,7 @@ func WireGuardTunnelService(confFile16 *uint16) bool {
}
//export WireGuardGenerateKeypair
-func WireGuardGenerateKeypair(publicKey *byte, privateKey *byte) {
+func WireGuardGenerateKeypair(publicKey, privateKey *byte) {
publicKeyArray := (*[32]byte)(unsafe.Pointer(publicKey))
privateKeyArray := (*[32]byte)(unsafe.Pointer(privateKey))
n, err := rand.Read(privateKeyArray[:])
diff --git a/go.mod b/go.mod
index 8c85ec21..a5cf5235 100644
--- a/go.mod
+++ b/go.mod
@@ -1,15 +1,19 @@
module golang.zx2c4.com/wireguard/windows
-go 1.16
+go 1.20
require (
github.com/lxn/walk v0.0.0-20210112085537-c389da54e794
github.com/lxn/win v0.0.0-20210218163916-a377121e959e
- golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2
- golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4
- golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57
- golang.org/x/text v0.3.6
- golang.zx2c4.com/wireguard v0.0.0-20210409202608-75526d60714c
+ golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd
+ golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86
+ golang.org/x/text v0.3.8-0.20220124021120-d1c84af989ab
+)
+
+require (
+ golang.org/x/mod v0.4.2 // indirect
+ golang.org/x/tools v0.1.7 // indirect
+ golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
)
replace (
diff --git a/go.mod.master b/go.mod.master
index a61c1ed9..e4adb918 100644
--- a/go.mod.master
+++ b/go.mod.master
@@ -1,6 +1,6 @@
module golang.zx2c4.com/wireguard/windows
-go 1.16
+go 1.20
require (
github.com/lxn/walk latest
@@ -9,7 +9,6 @@ require (
golang.org/x/net latest
golang.org/x/sys latest
golang.org/x/text master
- golang.zx2c4.com/wireguard master
)
replace (
diff --git a/go.sum b/go.sum
index 2ae11467..90ea1843 100644
--- a/go.sum
+++ b/go.sum
@@ -1,29 +1,27 @@
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
-golang.org/x/crypto v0.0.0-20210220033148-5ea612d1eb83/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
-golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2 h1:It14KIkyBFYkHkwZ7k45minvA9aorojkyjGk9KJ5B/w=
-golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4=
+golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
+golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd h1:XcWmESyNjXJMLahc3mqVQJcgSTDxFxhETVlfk9uGc38=
+golang.org/x/crypto v0.0.0-20220315160706-3147a52a75dd/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
+golang.org/x/mod v0.4.2 h1:Gz96sIWK3OalVv/I/qNygP42zyoKp3xptRVCWRFEBvo=
+golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
-golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
-golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4 h1:4nGaVu0QrbjT/AK2PRLuQfQuh6DJve+pELhqTdAj3x0=
-golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
+golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
+golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
-golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
+golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201018230417-eeed37f84f13/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210309040221-94ec62e08169/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57 h1:F5Gozwx4I1xtr/sr/8CFbb57iKi3297KFs0QDbGN60A=
-golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
-golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
-golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
+golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86 h1:A9i04dxx7Cribqbs8jf3FQLogkL/CV2YN7hj9KWJCkc=
+golang.org/x/sys v0.0.0-20220315194320-039c03cc5b86/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
-golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
-golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
-golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e h1:FDhOuMEY4JVRztM/gsbk+IKUQ8kj74bxZrgw87eMMVc=
-golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
-golang.zx2c4.com/wireguard v0.0.0-20210409202608-75526d60714c h1:XRNeg3YTKFRna0lwwswhrxNM5nyeS6WIUcmB+NkPB5c=
-golang.zx2c4.com/wireguard v0.0.0-20210409202608-75526d60714c/go.mod h1:a057zjmoc00UN7gVkaJt2sXVK523kMJcogDTEvPIasg=
+golang.org/x/text v0.3.8-0.20220124021120-d1c84af989ab h1:eHo2TTVBaAPw9lDGK2Gb9GyPMXT6g7O63W6sx3ylbzU=
+golang.org/x/text v0.3.8-0.20220124021120-d1c84af989ab/go.mod h1:EFNZuWvGYxIRUEX+K8UmCFwYmZjqcrnq15ZuVldZkZ0=
+golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
+golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ=
+golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
+golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
+golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.zx2c4.com/wireguard/windows v0.0.0-20210121140954-e7fc19d483bd h1:kAUzMAITME2MCtrXBaUa9P4tndiXGWO674k9gn6ZR28=
golang.zx2c4.com/wireguard/windows v0.0.0-20210121140954-e7fc19d483bd/go.mod h1:Y+FYqVFaQO6a+1uigm0N0GiuaZrLEaBxEiJ8tfH9sMQ=
golang.zx2c4.com/wireguard/windows v0.0.0-20210224134948-620c54ef6199 h1:ogXKLng/Myrt2odYTkleySGzQj/GWg9GV1AQ8P9NnU4=
diff --git a/gotext.go b/gotext.go
index 0ed7401c..db39bdd3 100644
--- a/gotext.go
+++ b/gotext.go
@@ -1,9 +1,10 @@
-// +build generate
+//go:build generate
+
//go:generate go run gotext.go
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package main
diff --git a/installer/build.bat b/installer/build.bat
index c9da9c91..ff3aaba2 100644
--- a/installer/build.bat
+++ b/installer/build.bat
@@ -1,6 +1,6 @@
@echo off
rem SPDX-License-Identifier: MIT
-rem Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+rem Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
setlocal
set PATHEXT=.exe
@@ -21,7 +21,7 @@ if exist .deps\prepared goto :build
rmdir /s /q .deps 2> NUL
mkdir .deps || goto :error
cd .deps || goto :error
- call :download wix-binaries.zip https://wixtoolset.org/downloads/v3.14.0.4118/wix314-binaries.zip 34dcbba9952902bfb710161bd45ee2e721ffa878db99f738285a21c9b09c6edb || goto :error
+ call :download wix-binaries.zip https://github.com/wixtoolset/wix3/releases/download/wix3141rtm/wix314-binaries.zip 6ac824e1642d6f7277d0ed7ea09411a508f6116ba6fae0aa5f2c7daa2ff43d31 || goto :error
echo [+] Extracting wix-binaries.zip
mkdir wix\bin || goto :error
tar -xf wix-binaries.zip -C wix\bin || goto :error
@@ -31,6 +31,7 @@ if exist .deps\prepared goto :build
cd .. || goto :error
:build
+ if exist ..\sign.bat call ..\sign.bat
set PATH=%BUILDDIR%..\.deps\llvm-mingw\bin;%PATH%
set WIX=%BUILDDIR%.deps\wix\
set CFLAGS=-O3 -Wall -std=gnu11 -DWINVER=0x0601 -D_WIN32_WINNT=0x0601 -municode -DUNICODE -D_UNICODE -DNDEBUG
@@ -38,13 +39,11 @@ if exist .deps\prepared goto :build
set LDLIBS=-lmsi -lole32 -lshlwapi -lshell32 -luuid -lntdll
call :msi x86 i686 x86 || goto :error
call :msi amd64 x86_64 x64 || goto :error
- call :msi arm armv7 arm || goto :error
call :msi arm64 aarch64 arm64 || goto :error
- if exist ..\sign.bat call ..\sign.bat
- if "%SigningCertificate%"=="" goto :success
+ if "%SigningProvider%"=="" goto :success
if "%TimestampServer%"=="" goto :success
echo [+] Signing
- signtool sign /sha1 "%SigningCertificate%" /fd sha256 /tr "%TimestampServer%" /td sha256 /d "WireGuard Setup" "dist\wireguard-*-%WIREGUARD_VERSION%.msi" || goto :error
+ signtool sign %SigningProvider% /fd sha256 /tr "%TimestampServer%" /td sha256 /d "WireGuard Setup" "dist\wireguard-*-%WIREGUARD_VERSION%.msi" || goto :error
:success
echo [+] Success.
@@ -62,6 +61,11 @@ if exist .deps\prepared goto :build
if not exist "%~1" mkdir "%~1"
echo [+] Compiling %1
%CC% %CFLAGS% %LDFLAGS% -o "%~1\customactions.dll" customactions.c %LDLIBS% || exit /b 1
+ if "%SigningProvider%"=="" goto :skipsign
+ if "%TimestampServer%"=="" goto :skipsign
+ echo [+] Signing %1
+ signtool sign %SigningProvider% /fd sha256 /tr "%TimestampServer%" /td sha256 /d "WireGuard Setup Custom Actions" "%~1\customactions.dll" || exit /b 1
+:skipsign
"%WIX%bin\candle" %WIX_CANDLE_FLAGS% -dWIREGUARD_PLATFORM="%~1" -out "%~1\wireguard.wixobj" -arch %3 wireguard.wxs || exit /b %errorlevel%
echo [+] Linking %1
"%WIX%bin\light" %WIX_LIGHT_FLAGS% -out "dist\wireguard-%~1-%WIREGUARD_VERSION%.msi" "%~1\wireguard.wixobj" || exit /b %errorlevel%
diff --git a/installer/customactions.c b/installer/customactions.c
index 981415e1..d3078a31 100644
--- a/installer/customactions.c
+++ b/installer/customactions.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: MIT
/*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
#include <windows.h>
@@ -96,7 +96,7 @@ __declspec(dllexport) UINT __stdcall CheckWow64(MSIHANDLE installer)
log_errorf(installer, LOG_LEVEL_ERR, ret, TEXT("Failed to get kernel32.dll handle"));
goto out;
}
- IsWow64Process2 = (void *)GetProcAddress(kernel32, "IsWow64Process2");
+ *(FARPROC *)&IsWow64Process2 = GetProcAddress(kernel32, "IsWow64Process2");
if (IsWow64Process2) {
if (!IsWow64Process2(GetCurrentProcess(), &process_machine, &native_machine)) {
ret = GetLastError();
@@ -122,94 +122,6 @@ out:
return ret;
}
-extern NTAPI __declspec(dllimport) void RtlGetNtVersionNumbers(DWORD *MajorVersion, DWORD *MinorVersion, DWORD *BuildNumber);
-
-static int message_box(MSIHANDLE installer, TCHAR *text, UINT type)
-{
- TCHAR progressOnly[2];
- DWORD len;
- MSIHANDLE record;
- int ret;
-
- len = _countof(progressOnly);
- if (MsiGetProperty(installer, TEXT("MsiUIProgressOnly"), progressOnly, &len) == ERROR_SUCCESS && _tcstoul(progressOnly, NULL, 10) == 1)
- return MessageBox(GetForegroundWindow(), text, TEXT("WireGuard"), type);
- record = MsiCreateRecord(2);
- MsiRecordSetString(record, 0, TEXT("[1]"));
- MsiRecordSetString(record, 1, text);
- ret = MsiProcessMessage(installer, INSTALLMESSAGE_USER | type, record);
- MsiCloseHandle(record);
- return ret;
-}
-
-__declspec(dllexport) UINT __stdcall CheckKB2921916(MSIHANDLE installer)
-{
- bool is_com_initialized = SUCCEEDED(CoInitialize(NULL));
- UINT ret = ERROR_SUCCESS;
- DWORD maj, min, build, len;
- TCHAR uiLevel[10];
- TCHAR setupapi_path[MAX_PATH];
- HANDLE setupapi_handle = INVALID_HANDLE_VALUE;
- HANDLE setupapi_filemapping = NULL;
- const char *setupapi_bytes = NULL;
- MEMORY_BASIC_INFORMATION setupapi_meminfo;
- static const char setupapi_marker[] = "Signature Hash";
-
- RtlGetNtVersionNumbers(&maj, &min, &build);
- if (maj != 6 || min != 1)
- goto out;
-
- ret = ERROR_INSTALL_FAILURE;
- if (!GetSystemDirectory(setupapi_path, _countof(setupapi_path)))
- goto out;
- if (!PathAppend(setupapi_path, TEXT("setupapi.dll")))
- goto out;
- setupapi_handle = CreateFile(setupapi_path, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
- if (setupapi_handle == INVALID_HANDLE_VALUE)
- goto out;
- setupapi_filemapping = CreateFileMapping(setupapi_handle, NULL, PAGE_READONLY, 0, 0, NULL);
- if (!setupapi_filemapping)
- goto out;
- setupapi_bytes = MapViewOfFile(setupapi_filemapping, FILE_MAP_READ, 0, 0, 0);
- if (!setupapi_bytes)
- goto out;
- if (VirtualQuery(setupapi_bytes, &setupapi_meminfo, sizeof(setupapi_meminfo)) != sizeof(setupapi_meminfo))
- goto out;
- if (setupapi_meminfo.RegionSize > strlen(setupapi_marker)) {
- for (const char *p = setupapi_bytes + strlen(setupapi_marker) - 1; (p = memchr(p, 'h', setupapi_meminfo.RegionSize - (p - setupapi_bytes))); ++p) {
- if (!memcmp(p - strlen(setupapi_marker) + 1, setupapi_marker, strlen(setupapi_marker))) {
- ret = ERROR_SUCCESS;
- goto out;
- }
- }
- }
-
- len = _countof(uiLevel);
- if (MsiGetProperty(installer, TEXT("UILevel"), uiLevel, &len) != ERROR_SUCCESS || _tcstoul(uiLevel, NULL, 10) < INSTALLUILEVEL_BASIC) {
- log_messagef(installer, LOG_LEVEL_MSIERR, TEXT("Use of WireGuard on Windows 7 requires KB2921916."));
- goto out;
- }
-#ifdef _WIN64
- static const TCHAR url[] = TEXT("https://download.wireguard.com/windows-toolchain/distfiles/Windows6.1-KB2921916-x64.msu");
-#else
- static const TCHAR url[] = TEXT("https://download.wireguard.com/windows-toolchain/distfiles/Windows6.1-KB2921916-x86.msu");
-#endif
- if (message_box(installer, TEXT("Missing Windows Hotfix\n\nUse of WireGuard on Windows 7 requires KB2921916. Would you like to download the hotfix in your web browser?"), MB_ICONWARNING | MB_YESNO) == IDYES)
- ShellExecute(GetForegroundWindow(), NULL, url, NULL, NULL, SW_SHOWNORMAL);
- ret = ERROR_INSTALL_USEREXIT;
-
-out:
- if (setupapi_bytes)
- UnmapViewOfFile(setupapi_bytes);
- if (setupapi_filemapping)
- CloseHandle(setupapi_filemapping);
- if (setupapi_handle != INVALID_HANDLE_VALUE)
- CloseHandle(setupapi_handle);
- if (is_com_initialized)
- CoUninitialize();
- return ret;
-}
-
static UINT insert_service_control(MSIHANDLE installer, MSIHANDLE view, const TCHAR *service_name, bool start)
{
static unsigned int index = 0;
@@ -607,7 +519,7 @@ __declspec(dllexport) UINT __stdcall RemoveAdapters(MSIHANDLE installer)
log_errorf(installer, LOG_LEVEL_WARN, GetLastError(), TEXT("SetHandleInformation failed"));
goto cleanup_pipe_w;
}
- if (!CreateProcess(path, TEXT("wireguard /removealladapters"), NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) {
+ if (!CreateProcess(path, TEXT("wireguard /removedriver"), NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi)) {
log_errorf(installer, LOG_LEVEL_WARN, GetLastError(), TEXT("Failed to create \"%1\" process"), path);
goto cleanup_pipe_w;
}
diff --git a/installer/fetcher/Makefile b/installer/fetcher/Makefile
index 8bc06ff1..a247adfe 100644
--- a/installer/fetcher/Makefile
+++ b/installer/fetcher/Makefile
@@ -1,6 +1,6 @@
# SPDX-License-Identifier: GPL-2.0
#
-# Copyright (C) 2015-2021 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
+# Copyright (C) 2015-2022 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
CFLAGS ?= -Os
DEPLOYMENT_HOST ?= winvm
diff --git a/installer/fetcher/constants.h b/installer/fetcher/constants.h
index 8f2f3403..96d88d0e 100644
--- a/installer/fetcher/constants.h
+++ b/installer/fetcher/constants.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0
*
- * Copyright (C) 2020-2021 Jason A. Donenfeld. All Rights Reserved.
+ * Copyright (C) 2020-2022 Jason A. Donenfeld. All Rights Reserved.
*/
#ifndef _CONSTANTS_H
diff --git a/installer/fetcher/crypto.c b/installer/fetcher/crypto.c
index 880cff30..33154efb 100644
--- a/installer/fetcher/crypto.c
+++ b/installer/fetcher/crypto.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Copyright (C) 2020-2021 Jason A. Donenfeld. All Rights Reserved.
+ * Copyright (C) 2020-2022 Jason A. Donenfeld. All Rights Reserved.
* Copyright (c) 2020, Google Inc.
*/
@@ -2239,7 +2239,7 @@ void blake2b256_update(struct blake2b256_state *state, const uint8_t *in,
state->buflen += inlen;
}
-void blake2b256_final(struct blake2b256_state *state, uint8_t *out)
+void blake2b256_final(struct blake2b256_state *state, uint8_t out[32])
{
state->t[0] += state->buflen;
state->t[1] += (state->t[0] < state->buflen);
@@ -2247,6 +2247,6 @@ void blake2b256_final(struct blake2b256_state *state, uint8_t *out)
memset(state->buf + state->buflen, 0, 128 - state->buflen);
blake2b256_compress(state, state->buf);
- for (int i = 0; i < 8; ++i)
+ for (int i = 0; i < 4; ++i)
store_le64(out + i * sizeof(state->h[i]), state->h[i]);
}
diff --git a/installer/fetcher/crypto.h b/installer/fetcher/crypto.h
index 51691a46..dc234ec7 100644
--- a/installer/fetcher/crypto.h
+++ b/installer/fetcher/crypto.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0
*
- * Copyright (C) 2020-2021 Jason A. Donenfeld. All Rights Reserved.
+ * Copyright (C) 2020-2022 Jason A. Donenfeld. All Rights Reserved.
*/
#ifndef _CRYPTO_H
@@ -21,7 +21,7 @@ struct blake2b256_state {
void blake2b256_init(struct blake2b256_state *state);
void blake2b256_update(struct blake2b256_state *state, const uint8_t *in,
unsigned int inlen);
-void blake2b256_final(struct blake2b256_state *state, uint8_t *out);
+void blake2b256_final(struct blake2b256_state *state, uint8_t out[32]);
bool ed25519_verify(const uint8_t signature[64], const uint8_t public_key[32],
const void *message, size_t message_size);
diff --git a/installer/fetcher/fetcher.c b/installer/fetcher/fetcher.c
index e9d23567..5c688997 100644
--- a/installer/fetcher/fetcher.c
+++ b/installer/fetcher/fetcher.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Copyright (C) 2020-2021 Jason A. Donenfeld. All Rights Reserved.
+ * Copyright (C) 2020-2022 Jason A. Donenfeld. All Rights Reserved.
*/
#include <windows.h>
@@ -23,7 +23,7 @@
#include "constants.h"
static char msi_filename[MAX_PATH];
-static volatile bool msi_filename_is_set;
+static volatile bool msi_filename_is_set, prompts = true;
static volatile size_t g_current, g_total;
static HWND progress;
static HANDLE filehandle = INVALID_HANDLE_VALUE;
@@ -114,6 +114,12 @@ static DWORD __stdcall download_thread(void *param)
if (!session)
goto out;
WinHttpSetOption(session, WINHTTP_OPTION_ENABLE_HTTP_PROTOCOL, &enable_http2, sizeof(enable_http2)); // Don't check return value, in case of old Windows
+ if (is_win8dotzero_or_below()) {
+ DWORD enable_tls12 = WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2;
+ if (!WinHttpSetOption(session, WINHTTP_OPTION_SECURE_PROTOCOLS, &enable_tls12, sizeof(enable_tls12)))
+ goto out;
+ }
+
connection = WinHttpConnect(session, L(server), port, 0);
if (!connection)
goto out;
@@ -181,7 +187,10 @@ static DWORD __stdcall download_thread(void *param)
CloseHandle(filehandle); //TODO: I wish this wasn't required.
filehandle = INVALID_HANDLE_VALUE;
wintrust_fileinfo.pcwszFilePath = L(msi_filename);
- if (WinVerifyTrust(INVALID_HANDLE_VALUE, &(GUID)WINTRUST_ACTION_GENERIC_VERIFY_V2, &wintrust_data))
+ ret = WinVerifyTrustEx(INVALID_HANDLE_VALUE, &(GUID)WINTRUST_ACTION_GENERIC_VERIFY_V2, &wintrust_data);
+ wintrust_data.dwStateAction = WTD_STATEACTION_CLOSE;
+ WinVerifyTrustEx(INVALID_HANDLE_VALUE, &(GUID)WINTRUST_ACTION_GENERIC_VERIFY_V2, &wintrust_data);
+ if (ret)
goto out;
set_status(progress, "launching installer");
@@ -199,7 +208,7 @@ out:
if (security_attributes.lpSecurityDescriptor)
LocalFree(security_attributes.lpSecurityDescriptor);
- if (ret) {
+ if (ret && prompts) {
ShowWindow(progress, SW_SHOWDEFAULT);
if (MessageBoxA(progress, "Something went wrong when downloading the WireGuard installer. Would you like to open your web browser to the MSI download page?", "Download Error", MB_YESNO | MB_ICONWARNING) == IDYES)
ShellExecuteA(progress, NULL, "https://" server msi_path, NULL, NULL, SW_SHOWNORMAL);
@@ -276,6 +285,20 @@ static LRESULT CALLBACK wndproc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lPar
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}
+static void parse_command_line(void)
+{
+ LPWSTR *argv;
+ int argc;
+ argv = CommandLineToArgvW(GetCommandLineW(), &argc);
+ if (!argv)
+ return;
+ for (int i = 1; i < argc; ++i) {
+ if (wcsicmp(argv[i], L"/noprompt") == 0)
+ prompts = false;
+ }
+ LocalFree(argv);
+}
+
int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine, int nCmdShow)
{
MSG msg;
@@ -288,6 +311,8 @@ int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, PSTR pCmdLine,
if (!SetDllDirectoryA("") || !SetDefaultDllDirectories(LOAD_LIBRARY_SEARCH_SYSTEM32))
return 1;
+ parse_command_line();
+
InitCommonControlsEx(&(INITCOMMONCONTROLSEX){ .dwSize = sizeof(INITCOMMONCONTROLSEX), .dwICC = ICC_PROGRESS_CLASS });
progress = CreateWindowExA(0, PROGRESS_CLASS, "WireGuard Installer",
diff --git a/installer/fetcher/filelist.c b/installer/fetcher/filelist.c
index a65c397d..f938e324 100644
--- a/installer/fetcher/filelist.c
+++ b/installer/fetcher/filelist.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Copyright (C) 2020-2021 Jason A. Donenfeld. All Rights Reserved.
+ * Copyright (C) 2020-2022 Jason A. Donenfeld. All Rights Reserved.
*/
#include "constants.h"
diff --git a/installer/fetcher/filelist.h b/installer/fetcher/filelist.h
index 7b3b7263..7da57470 100644
--- a/installer/fetcher/filelist.h
+++ b/installer/fetcher/filelist.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0
*
- * Copyright (C) 2020-2021 Jason A. Donenfeld. All Rights Reserved.
+ * Copyright (C) 2020-2022 Jason A. Donenfeld. All Rights Reserved.
*/
#ifndef _FILELIST_H
diff --git a/installer/fetcher/resources.rc b/installer/fetcher/resources.rc
index 771c6d46..f2bedb66 100644
--- a/installer/fetcher/resources.rc
+++ b/installer/fetcher/resources.rc
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0
*
- * Copyright (C) 2020-2021 Jason A. Donenfeld. All Rights Reserved.
+ * Copyright (C) 2020-2022 Jason A. Donenfeld. All Rights Reserved.
*/
#include <windows.h>
@@ -27,7 +27,7 @@ BEGIN
VALUE "FileDescription", "WireGuard Installer: Fast, Modern, Secure VPN Tunnel"
VALUE "FileVersion", VERSION_STR
VALUE "InternalName", "wireguard-installer"
- VALUE "LegalCopyright", "Copyright © 2015-2021 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved."
+ VALUE "LegalCopyright", "Copyright © 2015-2022 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved."
VALUE "OriginalFilename", "wireguard-installer.exe"
VALUE "ProductName", "WireGuard"
VALUE "ProductVersion", VERSION_STR
diff --git a/installer/fetcher/systeminfo.c b/installer/fetcher/systeminfo.c
index 2281226b..f1f80e7f 100644
--- a/installer/fetcher/systeminfo.c
+++ b/installer/fetcher/systeminfo.c
@@ -1,6 +1,6 @@
// SPDX-License-Identifier: GPL-2.0
/*
- * Copyright (C) 2020-2021 Jason A. Donenfeld. All Rights Reserved.
+ * Copyright (C) 2020-2022 Jason A. Donenfeld. All Rights Reserved.
*/
#include "systeminfo.h"
@@ -25,7 +25,7 @@ const char *architecture(void)
kernel32 = GetModuleHandleA("kernel32.dll");
if (!kernel32)
return NULL;
- IsWow64Process2 = (void *)GetProcAddress(kernel32, "IsWow64Process2");
+ *(FARPROC *)&IsWow64Process2 = GetProcAddress(kernel32, "IsWow64Process2");
if (IsWow64Process2) {
if (!IsWow64Process2(GetCurrentProcess(), &process_machine, &native_machine))
return NULL;
@@ -65,3 +65,10 @@ bool is_win7(void)
RtlGetNtVersionNumbers(&maj, &min, &build);
return maj == 6 && min == 1;
}
+
+bool is_win8dotzero_or_below(void)
+{
+ DWORD maj, min, build;
+ RtlGetNtVersionNumbers(&maj, &min, &build);
+ return maj == 6 && min <= 2;
+}
diff --git a/installer/fetcher/systeminfo.h b/installer/fetcher/systeminfo.h
index 12c3444a..2c06a166 100644
--- a/installer/fetcher/systeminfo.h
+++ b/installer/fetcher/systeminfo.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0
*
- * Copyright (C) 2020-2021 Jason A. Donenfeld. All Rights Reserved.
+ * Copyright (C) 2020-2022 Jason A. Donenfeld. All Rights Reserved.
*/
#ifndef _SYSTEMINFO_H
@@ -11,5 +11,6 @@
const char *architecture(void);
const char *useragent(void);
bool is_win7(void);
+bool is_win8dotzero_or_below(void);
#endif
diff --git a/installer/fetcher/version.h b/installer/fetcher/version.h
index 794a9926..dd6f54d1 100644
--- a/installer/fetcher/version.h
+++ b/installer/fetcher/version.h
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: GPL-2.0
*
- * Copyright (C) 2020-2021 Jason A. Donenfeld. All Rights Reserved.
+ * Copyright (C) 2020-2022 Jason A. Donenfeld. All Rights Reserved.
*/
#ifndef _VERSION_H
diff --git a/installer/wireguard.wxs b/installer/wireguard.wxs
index a0fc1396..ab90d3cd 100644
--- a/installer/wireguard.wxs
+++ b/installer/wireguard.wxs
@@ -2,7 +2,7 @@
<!--
SPDX-License-Identifier: GPL-2.0
- Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
-->
<?if $(var.WIREGUARD_PLATFORM) = "amd64" Or $(var.WIREGUARD_PLATFORM) = "arm64"?>
@@ -102,14 +102,6 @@
</InstallExecuteSequence>
<!--
- Abort early if running without KB2921916 on Windows 7
- -->
- <CustomAction Id="CheckKB2921916" BinaryKey="customactions.dll" DllEntry="CheckKB2921916" />
- <InstallExecuteSequence>
- <Custom Action="CheckKB2921916" After="CheckWow64">NOT REMOVE</Custom>
- </InstallExecuteSequence>
-
- <!--
Evaluate WireGuard services and populate ServiceControl table
-->
<CustomAction Id="EvaluateWireGuardServices" BinaryKey="customactions.dll" DllEntry="EvaluateWireGuardServices" />
diff --git a/l18n/l18n.go b/l18n/l18n.go
index 0eb72714..512fe2a2 100644
--- a/l18n/l18n.go
+++ b/l18n/l18n.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package l18n
@@ -13,8 +13,10 @@ import (
"golang.org/x/text/message"
)
-var printer *message.Printer
-var printerLock sync.Mutex
+var (
+ printer *message.Printer
+ printerLock sync.Mutex
+)
// prn returns the printer for user preferred UI language.
func prn() *message.Printer {
@@ -50,7 +52,7 @@ func lang() (tag language.Tag) {
}
// Sprintf is like fmt.Sprintf, but using language-specific formatting.
-func Sprintf(key message.Reference, a ...interface{}) string {
+func Sprintf(key message.Reference, a ...any) string {
return prn().Sprintf(key, a...)
}
diff --git a/locales/ca/messages.gotext.json b/locales/ca/messages.gotext.json
new file mode 100644
index 00000000..e5a0f488
--- /dev/null
+++ b/locales/ca/messages.gotext.json
@@ -0,0 +1,1847 @@
+{
+ "language": "ca",
+ "messages": [
+ {
+ "id": "Error",
+ "message": "Error",
+ "translation": "Error",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "(no argument): elevate and install manager service",
+ "message": "(no argument): elevate and install manager service",
+ "translation": "(sense argument): eleva i instala el servei d'administrador",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Usage: {Args0} [\n{String}]",
+ "message": "Usage: {Args0} [\n{String}]",
+ "translation": "Ús: {Args0} [\n{String}]",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Args0",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "os.Args[0]"
+ },
+ {
+ "id": "String",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "builder.String()"
+ }
+ ]
+ },
+ {
+ "id": "Command Line Options",
+ "message": "Command Line Options",
+ "translation": "Opcions de línia d'ordres",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to determine whether the process is running under WOW64: {Err}",
+ "message": "Unable to determine whether the process is running under WOW64: {Err}",
+ "translation": "No s'ha pogut determinar si el procés corre sota WOW64: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "You must use the native version of WireGuard on this computer.",
+ "message": "You must use the native version of WireGuard on this computer.",
+ "translation": "Heu de fer servir la versio nativa de WireGuard en aquest ordinador.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to open current process token: {Err}",
+ "message": "Unable to open current process token: {Err}",
+ "translation": "No s'ha pogut obrir el token del procés actual: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard may only be used by users who are a member of the Builtin {AdminGroupName} group.",
+ "message": "WireGuard may only be used by users who are a member of the Builtin {AdminGroupName} group.",
+ "translation": "WireGuard només es pot fer servir per els usuaris que són membres del grup del sistema {AdminGroupName}.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "AdminGroupName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "elevate.AdminGroupName()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard is running, but the UI is only accessible from desktops of the Builtin {AdminGroupName} group.",
+ "message": "WireGuard is running, but the UI is only accessible from desktops of the Builtin {AdminGroupName} group.",
+ "translation": "WireGuard s'està executsnt, pero la interfície gràfica només és accessible als usuaris que són membres del grup del sistema {AdminGroupName}.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "AdminGroupName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "elevate.AdminGroupName()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard system tray icon did not appear after 30 seconds.",
+ "message": "WireGuard system tray icon did not appear after 30 seconds.",
+ "translation": "La icona de WireGuard de la safata del sistema no ha aparegut després de 30 segons.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Now",
+ "message": "Now",
+ "translation": "Ara",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "System clock wound backward!",
+ "message": "System clock wound backward!",
+ "translation": "El rellotge del sistema s'ha atraçat!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Years} year(s)",
+ "message": "{Years} year(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Years",
+ "cases": {
+ "one": {
+ "msg": "{Years} any"
+ },
+ "other": {
+ "msg": "{Years} anys"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Years",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "years"
+ }
+ ]
+ },
+ {
+ "id": "{Days} day(s)",
+ "message": "{Days} day(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Days",
+ "cases": {
+ "one": {
+ "msg": "{Days} dia"
+ },
+ "other": {
+ "msg": "{Days} dies"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Days",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "days"
+ }
+ ]
+ },
+ {
+ "id": "{Hours} hour(s)",
+ "message": "{Hours} hour(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Hours",
+ "cases": {
+ "one": {
+ "msg": "{Hours} hora"
+ },
+ "other": {
+ "msg": "{Hours} hores"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Hours",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "hours"
+ }
+ ]
+ },
+ {
+ "id": "{Minutes} minute(s)",
+ "message": "{Minutes} minute(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Minutes",
+ "cases": {
+ "one": {
+ "msg": "{Minutes} minut"
+ },
+ "other": {
+ "msg": "{Minutes} minuts"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Minutes",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "minutes"
+ }
+ ]
+ },
+ {
+ "id": "{Seconds} second(s)",
+ "message": "{Seconds} second(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Seconds",
+ "cases": {
+ "one": {
+ "msg": "{Seconds} segon"
+ },
+ "other": {
+ "msg": "{Seconds} segons"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Seconds",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "seconds"
+ }
+ ]
+ },
+ {
+ "id": "{Timestamp} ago",
+ "message": "{Timestamp} ago",
+ "translation": "Fa {Timestamp}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Timestamp",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "timestamp"
+ }
+ ]
+ },
+ {
+ "id": "{Bytes} B",
+ "message": "{Bytes} B",
+ "translation": "{Bytes} B",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Bytes",
+ "string": "%[1]d",
+ "type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
+ "underlyingType": "uint64",
+ "argNum": 1,
+ "expr": "b"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024} KiB",
+ "message": "{Float64b__1024} KiB",
+ "translation": "{Float64b__1024} KiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / 1024"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024} MiB",
+ "message": "{Float64b__1024__1024} MiB",
+ "translation": "{Float64b__1024__1024} MiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024} GiB",
+ "message": "{Float64b__1024__1024__1024} GiB",
+ "translation": "{Float64b__1024__1024__1024} GiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024__1024} TiB",
+ "message": "{Float64b__1024__1024__1024__1024} TiB",
+ "translation": "{Float64b__1024__1024__1024__1024} TiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024) / 1024"
+ }
+ ]
+ },
+ {
+ "id": "{Why}: {Offender}",
+ "message": "{Why}: {Offender}",
+ "translation": "{Why}: {Offender}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Why",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "e.why"
+ },
+ {
+ "id": "Offender",
+ "string": "%[2]q",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "e.offender"
+ }
+ ]
+ },
+ {
+ "id": "Invalid IP address",
+ "message": "Invalid IP address",
+ "translation": "Adreça IP invàlida",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid network prefix length",
+ "message": "Invalid network prefix length",
+ "translation": "Tamany del prefix de xarxa invàlid",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Missing port from endpoint",
+ "message": "Missing port from endpoint",
+ "translation": "Falta el port de l'extrem",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid endpoint host",
+ "message": "Invalid endpoint host",
+ "translation": "El format de l'extrem no és valid",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Brackets must contain an IPv6 address",
+ "message": "Brackets must contain an IPv6 address",
+ "translation": "Els claudàtors han de contenir una adreça IPv6",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid MTU",
+ "message": "Invalid MTU",
+ "translation": "MTU invàlida",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid port",
+ "message": "Invalid port",
+ "translation": "Port invàlid",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid persistent keepalive",
+ "message": "Invalid persistent keepalive",
+ "translation": "Temps de missatge de persistència invàlid",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key: {Err}",
+ "message": "Invalid key: {Err}",
+ "translation": "Clau invàlida: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Keys must decode to exactly 32 bytes",
+ "message": "Keys must decode to exactly 32 bytes",
+ "translation": "Les claus han de descodificar a exactament 32 bytes",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Number must be a number between 0 and 2^64-1: {Err}",
+ "message": "Number must be a number between 0 and 2^64-1: {Err}",
+ "translation": "El nombre ha de estar entre 0 i 2^64-1: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Two commas in a row",
+ "message": "Two commas in a row",
+ "translation": "Dos comes seguides",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel name is not valid",
+ "message": "Tunnel name is not valid",
+ "translation": "El nom del túnel no és vàlid",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Line must occur in a section",
+ "message": "Line must occur in a section",
+ "translation": "La línia ha d'aparèixer en una secció",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Config key is missing an equals separator",
+ "message": "Config key is missing an equals separator",
+ "translation": "La clau de configuració no té un separador d'igualtat",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Key must have a value",
+ "message": "Key must have a value",
+ "translation": "La clau ha de tenir un valor",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for [Interface] section",
+ "message": "Invalid key for [Interface] section",
+ "translation": "La clau no és vàlida per la secció [Interface]",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for [Peer] section",
+ "message": "Invalid key for [Peer] section",
+ "translation": "La clau no és vàlida per la secció [Peer]",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "An interface must have a private key",
+ "message": "An interface must have a private key",
+ "translation": "Una interfície ha de tenir una clau privada",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "[none specified]",
+ "message": "[none specified]",
+ "translation": "[no especificat]",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "All peers must have public keys",
+ "message": "All peers must have public keys",
+ "translation": "Tots els parells han de tenir claus públiques",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error in getting configuration",
+ "message": "Error in getting configuration",
+ "translation": "Error obtenint configuració",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for interface section",
+ "message": "Invalid key for interface section",
+ "translation": "La clau no és vàlida per la secció d'interfície",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Protocol version must be 1",
+ "message": "Protocol version must be 1",
+ "translation": "La versió del protocol ha de ser 1",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for peer section",
+ "message": "Invalid key for peer section",
+ "translation": "La clau no és vàlida per la secció de parell",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "[EnumerationSeparator]",
+ "message": "[EnumerationSeparator]",
+ "translation": ", ",
+ "comment": "Text to insert between items when listing - most western languages will translate ‘[EnumerationSeparator]’ into ‘, ’ to produce lists like ‘apple, orange, strawberry’. Eastern languages might translate into ‘、’ to produce lists like ‘リンゴ、オレンジ、イチゴ’."
+ },
+ {
+ "id": "[UnitSeparator]",
+ "message": "[UnitSeparator]",
+ "translation": ", ",
+ "comment": "Text to insert when combining units of a measure - most languages will translate ‘[UnitSeparator]’ into ‘ ’ (space) to produce lists like ‘2 minuti 30 sekund’, or empty string ‘’ to produce ‘2分30秒’."
+ },
+ {
+ "id": "About WireGuard",
+ "message": "About WireGuard",
+ "translation": "Sobre WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard logo image",
+ "message": "WireGuard logo image",
+ "translation": "Logo de WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "message": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "translation": "Versió de l'aplicació: {Number}\nVersió de backend Go: {WireGuardGoVersion}\nVersió de Go: {Version_go}-{GOARCH}\nSistema operatiu: {OsName}\nArquitectura: {NativeArch}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Number",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "version.Number"
+ },
+ {
+ "id": "WireGuardGoVersion",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "device.WireGuardGoVersion"
+ },
+ {
+ "id": "Version_go",
+ "string": "%[3]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 3,
+ "expr": "strings.TrimPrefix(runtime.Version(), \"go\")"
+ },
+ {
+ "id": "GOARCH",
+ "string": "%[4]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 4,
+ "expr": "runtime.GOARCH"
+ },
+ {
+ "id": "OsName",
+ "string": "%[5]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 5,
+ "expr": "version.OsName()"
+ },
+ {
+ "id": "NativeArch",
+ "string": "%[6]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 6,
+ "expr": "version.NativeArch()"
+ }
+ ]
+ },
+ {
+ "id": "Close",
+ "message": "Close",
+ "translation": "Tanca",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "♥ &Donate!",
+ "message": "♥ &Donate!",
+ "translation": "♥ & Dona!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status:",
+ "message": "Status:",
+ "translation": "Estat:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Deactivate",
+ "message": "&Deactivate",
+ "translation": "&Desactiva",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Activate",
+ "message": "&Activate",
+ "translation": "&Activa",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Public key:",
+ "message": "Public key:",
+ "translation": "Clau pública:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Listen port:",
+ "message": "Listen port:",
+ "translation": "Port d'escolta:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "MTU:",
+ "message": "MTU:",
+ "translation": "MTU:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Addresses:",
+ "message": "Addresses:",
+ "translation": "Adreces:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "DNS servers:",
+ "message": "DNS servers:",
+ "translation": "Servidors DNS:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Scripts:",
+ "message": "Scripts:",
+ "translation": "Scripts:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Preshared key:",
+ "message": "Preshared key:",
+ "translation": "Clau precompartida:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Allowed IPs:",
+ "message": "Allowed IPs:",
+ "translation": "IPs permeses:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Endpoint:",
+ "message": "Endpoint:",
+ "translation": "Extrem:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Persistent keepalive:",
+ "message": "Persistent keepalive:",
+ "translation": "Missatge de persistència:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Latest handshake:",
+ "message": "Latest handshake:",
+ "translation": "Últim handshake:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Transfer:",
+ "message": "Transfer:",
+ "translation": "Transferència:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-up",
+ "message": "pre-up",
+ "translation": "preactivació",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-up",
+ "message": "post-up",
+ "translation": "postactivació",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-down",
+ "message": "pre-down",
+ "translation": "predesactivació",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-down",
+ "message": "post-down",
+ "translation": "postdesactivació",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "disabled, per policy",
+ "message": "disabled, per policy",
+ "translation": "deshabilitat, per política",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "enabled",
+ "message": "enabled",
+ "translation": "habilitat",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{String} received, {String_1} sent",
+ "message": "{String} received, {String_1} sent",
+ "translation": "{String} rebut, {String_1} enviat",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "String",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "c.RxBytes.String()"
+ },
+ {
+ "id": "String_1",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "c.TxBytes.String()"
+ }
+ ]
+ },
+ {
+ "id": "Failed to determine tunnel state",
+ "message": "Failed to determine tunnel state",
+ "translation": "Error en determinar l'estat del túnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Failed to activate tunnel",
+ "message": "Failed to activate tunnel",
+ "translation": "Error en activar el túnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Failed to deactivate tunnel",
+ "message": "Failed to deactivate tunnel",
+ "translation": "Error en desactivar el túnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Interface: {Name}",
+ "message": "Interface: {Name}",
+ "translation": "Interfície: {Name}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "config.Name"
+ }
+ ]
+ },
+ {
+ "id": "Peer",
+ "message": "Peer",
+ "translation": "Parell",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Create new tunnel",
+ "message": "Create new tunnel",
+ "translation": "Crear un túnel nou",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Edit tunnel",
+ "message": "Edit tunnel",
+ "translation": "Editar túnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Name:",
+ "message": "&Name:",
+ "translation": "&Nom:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Public key:",
+ "message": "&Public key:",
+ "translation": "&Clau pública:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "(unknown)",
+ "message": "(unknown)",
+ "translation": "(desconegut)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Block untunneled traffic (kill-switch)",
+ "message": "&Block untunneled traffic (kill-switch)",
+ "translation": "&Bloquejar el trànsit que no passa pel túnel (kill-switch)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "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 or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "message": "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 or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "translation": "Quan una configuració té exactament un parell, i aquest parell té adreces IP permeses que continguin almenys 0.0.0.0/0 o ::/0, el servei del túnel activa regles de tallafoc per bloquejar tot el trànsit que no es és ni de la interfície del túnel o cap al servidor DNS equivocat, amb excepció per DHCP i NDP.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Save",
+ "message": "&Save",
+ "translation": "&Desar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Cancel",
+ "message": "Cancel",
+ "translation": "Cancel·lar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Configuration:",
+ "message": "&Configuration:",
+ "translation": "&Configuració:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid name",
+ "message": "Invalid name",
+ "translation": "Nom invàlid",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "A name is required.",
+ "message": "A name is required.",
+ "translation": "És necessari un nom.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel name ‘{NewName}’ is invalid.",
+ "message": "Tunnel name ‘{NewName}’ is invalid.",
+ "translation": "El nom del túnel ‘{NewName}’ és invàlid.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "NewName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "newName"
+ }
+ ]
+ },
+ {
+ "id": "Unable to list existing tunnels",
+ "message": "Unable to list existing tunnels",
+ "translation": "No s'ha pogut llistar els túnels existents",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel already exists",
+ "message": "Tunnel already exists",
+ "translation": "El túnel ja existeix",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Another tunnel already exists with the name ‘{NewName}’.",
+ "message": "Another tunnel already exists with the name ‘{NewName}’.",
+ "translation": "Ja existeix un altre túnel amb el nom ‘{NewName}’.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "NewName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "newName"
+ }
+ ]
+ },
+ {
+ "id": "Unable to create new configuration",
+ "message": "Unable to create new configuration",
+ "translation": "No s'ha pogut crear una nova configuració",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Writing file failed",
+ "message": "Writing file failed",
+ "translation": "Error en escriure el fitxer",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "File ‘{FilePath}’ already exists.\n\nDo you want to overwrite it?",
+ "message": "File ‘{FilePath}’ already exists.\n\nDo you want to overwrite it?",
+ "translation": "El fitxer ‘{FilePath}’ ja existeix.\n\nEl vols sobreescriure?",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "FilePath",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "filePath"
+ }
+ ]
+ },
+ {
+ "id": "Active",
+ "message": "Active",
+ "translation": "Actiu",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Activating",
+ "message": "Activating",
+ "translation": "Activant",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Inactive",
+ "message": "Inactive",
+ "translation": "Inactiu",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Deactivating",
+ "message": "Deactivating",
+ "translation": "Desactivant",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unknown state",
+ "message": "Unknown state",
+ "translation": "Estat desconegut",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Log",
+ "message": "Log",
+ "translation": "Registre",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Copy",
+ "message": "&Copy",
+ "translation": "&Copia",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Select &all",
+ "message": "Select &all",
+ "translation": "Selecciona-ho tot",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Save to file…",
+ "message": "&Save to file…",
+ "translation": "Desa en un arxiu…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Time",
+ "message": "Time",
+ "translation": "Temps",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Log message",
+ "message": "Log message",
+ "translation": "Missatge de registre",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "message": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "translation": "Fitxers de text (*.txt)|*.txt|Tots els fitxers (*.*)|*.*",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export log to file",
+ "message": "Export log to file",
+ "translation": "Exporta registre a fitxer",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&About WireGuard…",
+ "message": "&About WireGuard…",
+ "translation": "&Sobre WireGuard…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel Error",
+ "message": "Tunnel Error",
+ "translation": "Error de túnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "message": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "translation": "{ErrMsg}\n\nSi us plau, consulteu el registre per més informació.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "ErrMsg",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errMsg"
+ }
+ ]
+ },
+ {
+ "id": "{Title} (out of date)",
+ "message": "{Title} (out of date)",
+ "translation": "{Title} (desactualitzat)",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Title",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "mtw.Title()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Detection Error",
+ "message": "WireGuard Detection Error",
+ "translation": "Error en detectar WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to wait for WireGuard window to appear: {Err}",
+ "message": "Unable to wait for WireGuard window to appear: {Err}",
+ "translation": "No ha estat possible esperar que aparegui la finestra de WireGuard: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard: Deactivated",
+ "message": "WireGuard: Deactivated",
+ "translation": "WireGuard: Desactivat",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Unknown",
+ "message": "Status: Unknown",
+ "translation": "Estat: Desconegut",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Addresses: None",
+ "message": "Addresses: None",
+ "translation": "Adreces: Cap",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Manage tunnels…",
+ "message": "&Manage tunnels…",
+ "translation": "&Administrar túnels…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Import tunnel(s) from file…",
+ "message": "&Import tunnel(s) from file…",
+ "translation": "&Importar túnel(s) des d'un fitxer…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "E&xit",
+ "message": "E&xit",
+ "translation": "&Surt",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Tunnels",
+ "message": "&Tunnels",
+ "translation": "&Túnels",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Activated",
+ "message": "WireGuard Activated",
+ "translation": "WireGuard Activat",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "The {Name} tunnel has been activated.",
+ "message": "The {Name} tunnel has been activated.",
+ "translation": "El túnel {Name} ha estat activat.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnel.Name"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Deactivated",
+ "message": "WireGuard Deactivated",
+ "translation": "WireGuard Desactivat",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "The {Name} tunnel has been deactivated.",
+ "message": "The {Name} tunnel has been deactivated.",
+ "translation": "El túnel {Name} ha estat desactivat.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnel.Name"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Tunnel Error",
+ "message": "WireGuard Tunnel Error",
+ "translation": "Error en el túnel de WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard: {TextForStateglobalState_true}",
+ "message": "WireGuard: {TextForStateglobalState_true}",
+ "translation": "WireGuard: {TextForStateglobalState_true}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TextForStateglobalState_true",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "textForState(globalState, true)"
+ }
+ ]
+ },
+ {
+ "id": "Status: {StateText}",
+ "message": "Status: {StateText}",
+ "translation": "Estat: {StateText}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "StateText",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "stateText"
+ }
+ ]
+ },
+ {
+ "id": "Addresses: {EnumerationSeparator}",
+ "message": "Addresses: {EnumerationSeparator}",
+ "translation": "Adreces: {EnumerationSeparator}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "EnumerationSeparator",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "strings.Join(addrs, l18n.EnumerationSeparator())"
+ }
+ ]
+ },
+ {
+ "id": "An Update is Available!",
+ "message": "An Update is Available!",
+ "translation": "Hi ha una actualització disponible!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Update Available",
+ "message": "WireGuard Update Available",
+ "translation": "Actualització de WireGuard disponible",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "An update to WireGuard is now available. You are advised to update as soon as possible.",
+ "message": "An update to WireGuard is now available. You are advised to update as soon as possible.",
+ "translation": "Hi ha una actualització de WireGuard. Es recomana actualitzar el més aviat millor.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnels",
+ "message": "Tunnels",
+ "translation": "Túnels",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Edit",
+ "message": "&Edit",
+ "translation": "&Editar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Add &empty tunnel…",
+ "message": "Add &empty tunnel…",
+ "translation": "Afegir &túnel buit…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Add Tunnel",
+ "message": "Add Tunnel",
+ "translation": "Afegir túnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Remove selected tunnel(s)",
+ "message": "Remove selected tunnel(s)",
+ "translation": "Eliminar túnel(s) seleccionats",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export all tunnels to zip",
+ "message": "Export all tunnels to zip",
+ "translation": "Exportar túnels a zip",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Toggle",
+ "message": "&Toggle",
+ "translation": "&Alterna",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export all tunnels to &zip…",
+ "message": "Export all tunnels to &zip…",
+ "translation": "Exportar tots els túnels a &zip…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Edit &selected tunnel…",
+ "message": "Edit &selected tunnel…",
+ "translation": "Editar túnels &seleccionats…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Remove selected tunnel(s)",
+ "message": "&Remove selected tunnel(s)",
+ "translation": "&Eliminar túnel(s) seleccionats",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "no configuration files were found",
+ "message": "no configuration files were found",
+ "translation": "no s'han trobat fitxers de configuració",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Could not import selected configuration: {LastErr}",
+ "message": "Could not import selected configuration: {LastErr}",
+ "translation": "No s'ha pogut importar la configuració seleccionada: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Could not enumerate existing tunnels: {LastErr}",
+ "message": "Could not enumerate existing tunnels: {LastErr}",
+ "translation": "No s'han pogut enumerar els túnels existents: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Another tunnel already exists with the name ‘{Name}’",
+ "message": "Another tunnel already exists with the name ‘{Name}’",
+ "translation": "Ja existeix un altre túnel amb el nom ‘{Name}’",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "unparsedConfig.Name"
+ }
+ ]
+ },
+ {
+ "id": "Unable to import configuration: {LastErr}",
+ "message": "Unable to import configuration: {LastErr}",
+ "translation": "No s'ha pogut importar la configuració: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Imported tunnels",
+ "message": "Imported tunnels",
+ "translation": "Túnels importats",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Imported {M} tunnels",
+ "message": "Imported {M} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "M",
+ "cases": {
+ "one": {
+ "msg": "{M} túnel importat"
+ },
+ "other": {
+ "msg": "{M} túnels importats"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ }
+ ]
+ },
+ {
+ "id": "Imported {M} of {N} tunnels",
+ "message": "Imported {M} of {N} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "N",
+ "cases": {
+ "one": {
+ "msg": "{M} de {N} túnel importat"
+ },
+ "other": {
+ "msg": "{M} de {N} túnels importats"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ },
+ {
+ "id": "N",
+ "string": "%[2]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 2,
+ "expr": "n"
+ }
+ ]
+ },
+ {
+ "id": "Unable to create tunnel",
+ "message": "Unable to create tunnel",
+ "translation": "No s'ha pogut crear el túnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Delete {TunnelCount} tunnels",
+ "message": "Delete {TunnelCount} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "TunnelCount",
+ "cases": {
+ "one": {
+ "msg": "Eliminar {TunnelCount} túnel"
+ },
+ "other": {
+ "msg": "Eliminar {TunnelCount} túnels"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "TunnelCount",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "tunnelCount"
+ }
+ ]
+ },
+ {
+ "id": "Are you sure you would like to delete {TunnelCount} tunnels?",
+ "message": "Are you sure you would like to delete {TunnelCount} tunnels?",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "TunnelCount",
+ "cases": {
+ "one": {
+ "msg": "Estàs segur que vols eliminar {TunnelCount} túnel?"
+ },
+ "other": {
+ "msg": "Estàs segur que vols eliminar {TunnelCount} túnels?"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "TunnelCount",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "tunnelCount"
+ }
+ ]
+ },
+ {
+ "id": "Delete tunnel ‘{TunnelName}’",
+ "message": "Delete tunnel ‘{TunnelName}’",
+ "translation": "Eliminar túnel ‘{TunnelName}’",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TunnelName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnelName"
+ }
+ ]
+ },
+ {
+ "id": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
+ "message": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
+ "translation": "Estàs segur que vols eliminar el túnel ‘{TunnelName}’?",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TunnelName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnelName"
+ }
+ ]
+ },
+ {
+ "id": "{Question} You cannot undo this action.",
+ "message": "{Question} You cannot undo this action.",
+ "translation": "{Question} Aquesta acció no es pot desfer.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Question",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "question"
+ }
+ ]
+ },
+ {
+ "id": "Unable to delete tunnel",
+ "message": "Unable to delete tunnel",
+ "translation": "No s'ha pogut eliminar el túnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "A tunnel was unable to be removed: {Error}",
+ "message": "A tunnel was unable to be removed: {Error}",
+ "translation": "Un túnel no ha estat capaç de ser eliminat: {Error}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Error",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errors[0].Error()"
+ }
+ ]
+ },
+ {
+ "id": "Unable to delete tunnels",
+ "message": "Unable to delete tunnels",
+ "translation": "No s'ha pogut eliminar els túnels",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Lenerrors} tunnels were unable to be removed.",
+ "message": "{Lenerrors} tunnels were unable to be removed.",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Lenerrors",
+ "cases": {
+ "one": {
+ "msg": "No s'ha pogut eliminar {Lenerrors} túnel."
+ },
+ "other": {
+ "msg": "No s'ha pogut eliminar {Lenerrors} túnels."
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Lenerrors",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "len(errors)"
+ }
+ ]
+ },
+ {
+ "id": "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
+ "message": "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
+ "translation": "Fitxers de configuració (*.zip, *.conf)|*.zip;*.conf|Tots els fitxers (*.*)|*.*",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Import tunnel(s) from file",
+ "message": "Import tunnel(s) from file",
+ "translation": "Importar túnel(s) des d'un fitxer",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Configuration ZIP Files (*.zip)|*.zip",
+ "message": "Configuration ZIP Files (*.zip)|*.zip",
+ "translation": "Fitxers ZIP de configuració (*.zip)|*.zip",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export tunnels to zip",
+ "message": "Export tunnels to zip",
+ "translation": "Exportar túnels a zip",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Title} (unsigned build, no updates)",
+ "message": "{Title} (unsigned build, no updates)",
+ "translation": "{Title} (compilació no signada, sense actualitzacions)",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Title",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "mtw.Title()"
+ }
+ ]
+ },
+ {
+ "id": "Error Exiting WireGuard",
+ "message": "Error Exiting WireGuard",
+ "translation": "Error al sortir de WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
+ "message": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
+ "translation": "No s'ha pogut sortir del servei a causa de l'error: {Err}. Pot intentar aturar WireGuard des de l'administrador de serveis.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "message": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "translation": "Una actualització per WireGuard està disponible. Es recomana actualitzar immediatament.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Waiting for user",
+ "message": "Status: Waiting for user",
+ "translation": "Estat: Esperant a l'usuari",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Update Now",
+ "message": "Update Now",
+ "translation": "Actualitza ara",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Waiting for updater service",
+ "message": "Status: Waiting for updater service",
+ "translation": "Estat: Esperant el servei d'actualitzacions",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error: {Err}. Please try again.",
+ "message": "Error: {Err}. Please try again.",
+ "translation": "Error: {Err}. Si us plau, torneu-ho a provar.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Status: Complete!",
+ "message": "Status: Complete!",
+ "translation": "Estat: Completat!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "http2: Framer {F}: failed to decode just-written frame",
+ "message": "http2: Framer {F}: failed to decode just-written frame",
+ "translation": "http2: Framer {F}: failed to decode just-written frame",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "F",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "f"
+ }
+ ]
+ },
+ {
+ "id": "http2: Framer {F}: wrote {Http2summarizeFramefr}",
+ "message": "http2: Framer {F}: wrote {Http2summarizeFramefr}",
+ "translation": "http2: Framer {F}: wrote {Http2summarizeFramefr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "F",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "f"
+ },
+ {
+ "id": "Http2summarizeFramefr",
+ "string": "%[2]v",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "http2summarizeFrame(fr)"
+ }
+ ]
+ },
+ {
+ "id": "http2: Framer {Fr}: read {Http2summarizeFramef}",
+ "message": "http2: Framer {Fr}: read {Http2summarizeFramef}",
+ "translation": "http2: Framer {Fr}: read {Http2summarizeFramef}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Fr",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "fr"
+ },
+ {
+ "id": "Http2summarizeFramef",
+ "string": "%[2]v",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "http2summarizeFrame(f)"
+ }
+ ]
+ },
+ {
+ "id": "http2: decoded hpack field {HeaderField}",
+ "message": "http2: decoded hpack field {HeaderField}",
+ "translation": "http2: decoded hpack field {HeaderField}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "HeaderField",
+ "string": "%+[1]v",
+ "type": "vendor/golang.org/x/net/http2/hpack.HeaderField",
+ "underlyingType": "struct{Name string; Value string; Sensitive bool}",
+ "argNum": 1,
+ "expr": "hf"
+ }
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/locales/cs/messages.gotext.json b/locales/cs/messages.gotext.json
new file mode 100644
index 00000000..a28d47b9
--- /dev/null
+++ b/locales/cs/messages.gotext.json
@@ -0,0 +1,1907 @@
+{
+ "language": "cs",
+ "messages": [
+ {
+ "id": "Error",
+ "message": "Error",
+ "translation": "Chyba",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "(no argument): elevate and install manager service",
+ "message": "(no argument): elevate and install manager service",
+ "translation": "(žádný argument): Zvýšit oprávnění a instalovat službu správce",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Usage: {Args0} [\n{String}]",
+ "message": "Usage: {Args0} [\n{String}]",
+ "translation": "Použití: {Args0} [\n{String}]",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Args0",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "os.Args[0]"
+ },
+ {
+ "id": "String",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "builder.String()"
+ }
+ ]
+ },
+ {
+ "id": "Command Line Options",
+ "message": "Command Line Options",
+ "translation": "Možnosti příkazového řádku",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to determine whether the process is running under WOW64: {Err}",
+ "message": "Unable to determine whether the process is running under WOW64: {Err}",
+ "translation": "Nelze zjistit, zda proces běží pod WOW64: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "You must use the native version of WireGuard on this computer.",
+ "message": "You must use the native version of WireGuard on this computer.",
+ "translation": "Musíte použít nativní verzi aplikace WireGuard na tomto počítači.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to open current process token: {Err}",
+ "message": "Unable to open current process token: {Err}",
+ "translation": "Nelze otevřít token aktuálního procesu: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard may only be used by users who are a member of the Builtin {AdminGroupName} group.",
+ "message": "WireGuard may only be used by users who are a member of the Builtin {AdminGroupName} group.",
+ "translation": "WireGuard můžou používat pouze uživatelé, kteří jsou členy Builtin skupiny {AdminGroupName}.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "AdminGroupName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "elevate.AdminGroupName()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard is running, but the UI is only accessible from desktops of the Builtin {AdminGroupName} group.",
+ "message": "WireGuard is running, but the UI is only accessible from desktops of the Builtin {AdminGroupName} group.",
+ "translation": "WireGuard je spuštěn, ale uživatelské rozhraní je přístupné pouze uživatelům Builtin skupiny {AdminGroupName}.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "AdminGroupName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "elevate.AdminGroupName()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard system tray icon did not appear after 30 seconds.",
+ "message": "WireGuard system tray icon did not appear after 30 seconds.",
+ "translation": "Ikona WireGuard se ani po 30 sekundách nezobrazila na systémové liště.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Now",
+ "message": "Now",
+ "translation": "Teď",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "System clock wound backward!",
+ "message": "System clock wound backward!",
+ "translation": "Systémové hodiny byly posunuty dozadu!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Years} year(s)",
+ "message": "{Years} year(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Years",
+ "cases": {
+ "one": {
+ "msg": "{Years} rok"
+ },
+ "few": {
+ "msg": "{Years} roky"
+ },
+ "many": {
+ "msg": "{Years} let"
+ },
+ "other": {
+ "msg": "{Years} let"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Years",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "years"
+ }
+ ]
+ },
+ {
+ "id": "{Days} day(s)",
+ "message": "{Days} day(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Days",
+ "cases": {
+ "one": {
+ "msg": "{Days} den"
+ },
+ "few": {
+ "msg": "{Days} dny"
+ },
+ "many": {
+ "msg": "{Days} dnů"
+ },
+ "other": {
+ "msg": "{Days} dny"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Days",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "days"
+ }
+ ]
+ },
+ {
+ "id": "{Hours} hour(s)",
+ "message": "{Hours} hour(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Hours",
+ "cases": {
+ "one": {
+ "msg": "{Hours} hodina"
+ },
+ "few": {
+ "msg": "{Hours} hodiny"
+ },
+ "many": {
+ "msg": "{Hours} hodin"
+ },
+ "other": {
+ "msg": "{Hours} hodin"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Hours",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "hours"
+ }
+ ]
+ },
+ {
+ "id": "{Minutes} minute(s)",
+ "message": "{Minutes} minute(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Minutes",
+ "cases": {
+ "one": {
+ "msg": "{Minutes} minuta"
+ },
+ "few": {
+ "msg": "{Minutes} minuty"
+ },
+ "many": {
+ "msg": "{Minutes} minut"
+ },
+ "other": {
+ "msg": "{Minutes} minut"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Minutes",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "minutes"
+ }
+ ]
+ },
+ {
+ "id": "{Seconds} second(s)",
+ "message": "{Seconds} second(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Seconds",
+ "cases": {
+ "one": {
+ "msg": "{Seconds} sekunda"
+ },
+ "few": {
+ "msg": "{Seconds} sekundy"
+ },
+ "many": {
+ "msg": "{Seconds} sekund"
+ },
+ "other": {
+ "msg": "{Seconds} sekund"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Seconds",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "seconds"
+ }
+ ]
+ },
+ {
+ "id": "{Timestamp} ago",
+ "message": "{Timestamp} ago",
+ "translation": "před {Timestamp}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Timestamp",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "timestamp"
+ }
+ ]
+ },
+ {
+ "id": "{Bytes} B",
+ "message": "{Bytes} B",
+ "translation": "{Bytes} B",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Bytes",
+ "string": "%[1]d",
+ "type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
+ "underlyingType": "uint64",
+ "argNum": 1,
+ "expr": "b"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024} KiB",
+ "message": "{Float64b__1024} KiB",
+ "translation": "{Float64b__1024} KiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / 1024"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024} MiB",
+ "message": "{Float64b__1024__1024} MiB",
+ "translation": "{Float64b__1024__1024} MiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024} GiB",
+ "message": "{Float64b__1024__1024__1024} GiB",
+ "translation": "{Float64b__1024__1024__1024} GiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024__1024} TiB",
+ "message": "{Float64b__1024__1024__1024__1024} TiB",
+ "translation": "{Float64b__1024__1024__1024__1024} TiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024) / 1024"
+ }
+ ]
+ },
+ {
+ "id": "{Why}: {Offender}",
+ "message": "{Why}: {Offender}",
+ "translation": "{Why}: {Offender}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Why",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "e.why"
+ },
+ {
+ "id": "Offender",
+ "string": "%[2]q",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "e.offender"
+ }
+ ]
+ },
+ {
+ "id": "Invalid IP address",
+ "message": "Invalid IP address",
+ "translation": "Neplatná IP adresa",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid network prefix length",
+ "message": "Invalid network prefix length",
+ "translation": "Neplatná délka síťového prefixu",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Missing port from endpoint",
+ "message": "Missing port from endpoint",
+ "translation": "Endpointu chybí port",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid endpoint host",
+ "message": "Invalid endpoint host",
+ "translation": "Neplatný endpoint",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Brackets must contain an IPv6 address",
+ "message": "Brackets must contain an IPv6 address",
+ "translation": "Závorky musí obsahovat IPv6 adresu",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid MTU",
+ "message": "Invalid MTU",
+ "translation": "Neplatné MTU",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid port",
+ "message": "Invalid port",
+ "translation": "Neplatný port",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid persistent keepalive",
+ "message": "Invalid persistent keepalive",
+ "translation": "Neplatný persistentní keepalive",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key: {Err}",
+ "message": "Invalid key: {Err}",
+ "translation": "Neplatný klíč: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Keys must decode to exactly 32 bytes",
+ "message": "Keys must decode to exactly 32 bytes",
+ "translation": "Klíče musí být dekódovány přesně na 32 bajtů",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Number must be a number between 0 and 2^64-1: {Err}",
+ "message": "Number must be a number between 0 and 2^64-1: {Err}",
+ "translation": "Číslo musí mít hodnotu mezi 0 a 2^64-1: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Two commas in a row",
+ "message": "Two commas in a row",
+ "translation": "Dvě čárky za sebou",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel name is not valid",
+ "message": "Tunnel name is not valid",
+ "translation": "Název tunelu je neplatný",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Line must occur in a section",
+ "message": "Line must occur in a section",
+ "translation": "Řádek musí být v některé sekci",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Config key is missing an equals separator",
+ "message": "Config key is missing an equals separator",
+ "translation": "Konfigurační klíč neobsahuje oddělovač (znak 'rovná se')",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Key must have a value",
+ "message": "Key must have a value",
+ "translation": "Klíč musí mít hodnotu",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for [Interface] section",
+ "message": "Invalid key for [Interface] section",
+ "translation": "Neplatný klíč pro sekci [Interface]",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for [Peer] section",
+ "message": "Invalid key for [Peer] section",
+ "translation": "Neplatný klíč pro sekci [Peer]",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "An interface must have a private key",
+ "message": "An interface must have a private key",
+ "translation": "Rozhraní musí obsahovat soukromý klíč",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "[none specified]",
+ "message": "[none specified]",
+ "translation": "[není specifikováno]",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "All peers must have public keys",
+ "message": "All peers must have public keys",
+ "translation": "Všichni peeři musí mít veřejné klíče",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error in getting configuration",
+ "message": "Error in getting configuration",
+ "translation": "Chyba při načítání konfigurace",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for interface section",
+ "message": "Invalid key for interface section",
+ "translation": "Neplatný klíč pro sekci rozhraní",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Protocol version must be 1",
+ "message": "Protocol version must be 1",
+ "translation": "Verze protokolu musí být 1",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for peer section",
+ "message": "Invalid key for peer section",
+ "translation": "Neplatný klíč v sekci peer",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "[EnumerationSeparator]",
+ "message": "[EnumerationSeparator]",
+ "translation": ", ",
+ "comment": "Text to insert between items when listing - most western languages will translate ‘[EnumerationSeparator]’ into ‘, ’ to produce lists like ‘apple, orange, strawberry’. Eastern languages might translate into ‘、’ to produce lists like ‘リンゴ、オレンジ、イチゴ’."
+ },
+ {
+ "id": "[UnitSeparator]",
+ "message": "[UnitSeparator]",
+ "translation": ", ",
+ "comment": "Text to insert when combining units of a measure - most languages will translate ‘[UnitSeparator]’ into ‘ ’ (space) to produce lists like ‘2 minuti 30 sekund’, or empty string ‘’ to produce ‘2分30秒’."
+ },
+ {
+ "id": "About WireGuard",
+ "message": "About WireGuard",
+ "translation": "O aplikaci WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard logo image",
+ "message": "WireGuard logo image",
+ "translation": "Obrázek loga WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "message": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "translation": "Verze aplikace: {Number}\nVerze Go backendu: {WireGuardGoVersion}\nVerze Go: {Version_go}-{GOARCH}\nOperační systém: {OsName}\nArchitektura: {NativeArch}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Number",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "version.Number"
+ },
+ {
+ "id": "WireGuardGoVersion",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "device.WireGuardGoVersion"
+ },
+ {
+ "id": "Version_go",
+ "string": "%[3]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 3,
+ "expr": "strings.TrimPrefix(runtime.Version(), \"go\")"
+ },
+ {
+ "id": "GOARCH",
+ "string": "%[4]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 4,
+ "expr": "runtime.GOARCH"
+ },
+ {
+ "id": "OsName",
+ "string": "%[5]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 5,
+ "expr": "version.OsName()"
+ },
+ {
+ "id": "NativeArch",
+ "string": "%[6]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 6,
+ "expr": "version.NativeArch()"
+ }
+ ]
+ },
+ {
+ "id": "Close",
+ "message": "Close",
+ "translation": "Zavřít",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "♥ &Donate!",
+ "message": "♥ &Donate!",
+ "translation": "♥ &Darovat!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status:",
+ "message": "Status:",
+ "translation": "Stav:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Deactivate",
+ "message": "&Deactivate",
+ "translation": "&Deaktivovat",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Activate",
+ "message": "&Activate",
+ "translation": "&Aktivovat",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Public key:",
+ "message": "Public key:",
+ "translation": "Veřejný klíč:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Listen port:",
+ "message": "Listen port:",
+ "translation": "Port pro naslouchání:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "MTU:",
+ "message": "MTU:",
+ "translation": "MTU:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Addresses:",
+ "message": "Addresses:",
+ "translation": "Adresy:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "DNS servers:",
+ "message": "DNS servers:",
+ "translation": "DNS servery:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Scripts:",
+ "message": "Scripts:",
+ "translation": "Skripty:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Preshared key:",
+ "message": "Preshared key:",
+ "translation": "Předsdílený klíč:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Allowed IPs:",
+ "message": "Allowed IPs:",
+ "translation": "Povolené IP:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Endpoint:",
+ "message": "Endpoint:",
+ "translation": "Endpoint:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Persistent keepalive:",
+ "message": "Persistent keepalive:",
+ "translation": "Persistent keepalive:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Latest handshake:",
+ "message": "Latest handshake:",
+ "translation": "Poslední handshake:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Transfer:",
+ "message": "Transfer:",
+ "translation": "Přenos:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-up",
+ "message": "pre-up",
+ "translation": "před-zapnutím",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-up",
+ "message": "post-up",
+ "translation": "po-zapnutí",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-down",
+ "message": "pre-down",
+ "translation": "před-vypnutím",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-down",
+ "message": "post-down",
+ "translation": "po-vypnutí",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "disabled, per policy",
+ "message": "disabled, per policy",
+ "translation": "vypnuto, podle zásad",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "enabled",
+ "message": "enabled",
+ "translation": "zapnuto",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{String} received, {String_1} sent",
+ "message": "{String} received, {String_1} sent",
+ "translation": "{String} přijato, {String_1} odesláno",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "String",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "c.RxBytes.String()"
+ },
+ {
+ "id": "String_1",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "c.TxBytes.String()"
+ }
+ ]
+ },
+ {
+ "id": "Failed to determine tunnel state",
+ "message": "Failed to determine tunnel state",
+ "translation": "Nepodařilo se zjistit stav tunelu",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Failed to activate tunnel",
+ "message": "Failed to activate tunnel",
+ "translation": "Nepodařilo se aktivovat tunel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Failed to deactivate tunnel",
+ "message": "Failed to deactivate tunnel",
+ "translation": "Nepodařilo se deaktivovat tunel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Interface: {Name}",
+ "message": "Interface: {Name}",
+ "translation": "Rozhraní: {Name}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "config.Name"
+ }
+ ]
+ },
+ {
+ "id": "Peer",
+ "message": "Peer",
+ "translation": "Peer",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Create new tunnel",
+ "message": "Create new tunnel",
+ "translation": "Vytvořit nový tunel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Edit tunnel",
+ "message": "Edit tunnel",
+ "translation": "Upravit tunel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Name:",
+ "message": "&Name:",
+ "translation": "&Název:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Public key:",
+ "message": "&Public key:",
+ "translation": "&Veřejný klíč:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "(unknown)",
+ "message": "(unknown)",
+ "translation": "(neznámý)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Block untunneled traffic (kill-switch)",
+ "message": "&Block untunneled traffic (kill-switch)",
+ "translation": "&Blokovat netunelovaný provoz (kill-switch)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "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 or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "message": "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 or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "translation": "Pokud má konfigurace přesně jednoho peera a tento peer má povolené IP adresy obsahující alespoň jednu z 0.0.0.0/0 nebo ::/0, pak služba tunelu použije sadu pravidel firewallu k blokování veškerého provozu, který nesměřuje z/do rozhraní tunelu nebo na nesprávný server DNS, se zvláštními výjimkami pro DHCP a NDP.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Save",
+ "message": "&Save",
+ "translation": "&Uložit",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Cancel",
+ "message": "Cancel",
+ "translation": "Zrušit",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Configuration:",
+ "message": "&Configuration:",
+ "translation": "&Nastavení:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid name",
+ "message": "Invalid name",
+ "translation": "Neplatný název",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "A name is required.",
+ "message": "A name is required.",
+ "translation": "Název je povinný.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel name ‘{NewName}’ is invalid.",
+ "message": "Tunnel name ‘{NewName}’ is invalid.",
+ "translation": "Název tunelu '{NewName}' je neplatný.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "NewName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "newName"
+ }
+ ]
+ },
+ {
+ "id": "Unable to list existing tunnels",
+ "message": "Unable to list existing tunnels",
+ "translation": "Nepodařilo se zobrazit existující tunely",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel already exists",
+ "message": "Tunnel already exists",
+ "translation": "Tunel již existuje",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Another tunnel already exists with the name ‘{NewName}’.",
+ "message": "Another tunnel already exists with the name ‘{NewName}’.",
+ "translation": "Tunel s názvem '{NewName}' již existuje.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "NewName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "newName"
+ }
+ ]
+ },
+ {
+ "id": "Unable to create new configuration",
+ "message": "Unable to create new configuration",
+ "translation": "Nepodařilo se vytvořit novou konfiguraci",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Writing file failed",
+ "message": "Writing file failed",
+ "translation": "Zápis souboru se nezdařil",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "File ‘{FilePath}’ already exists.\n\nDo you want to overwrite it?",
+ "message": "File ‘{FilePath}’ already exists.\n\nDo you want to overwrite it?",
+ "translation": "Soubor \"{FilePath}\" již existuje.\n\nChcete jej přepsat?",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "FilePath",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "filePath"
+ }
+ ]
+ },
+ {
+ "id": "Active",
+ "message": "Active",
+ "translation": "Aktivní",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Activating",
+ "message": "Activating",
+ "translation": "Aktivuji",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Inactive",
+ "message": "Inactive",
+ "translation": "Neaktivní",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Deactivating",
+ "message": "Deactivating",
+ "translation": "Deaktivuji",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unknown state",
+ "message": "Unknown state",
+ "translation": "Neznámý stav",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Log",
+ "message": "Log",
+ "translation": "Záznamy",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Copy",
+ "message": "&Copy",
+ "translation": "&Kopírovat",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Select &all",
+ "message": "Select &all",
+ "translation": "Vybr&at vše",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Save to file…",
+ "message": "&Save to file…",
+ "translation": "&Uložit do souboru…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Time",
+ "message": "Time",
+ "translation": "Čas",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Log message",
+ "message": "Log message",
+ "translation": "Zpráva logu",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "message": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "translation": "Textové soubory (*.txt)|*.txt|Všechny soubory (*.*)|*.*",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export log to file",
+ "message": "Export log to file",
+ "translation": "Exportovat záznam do souboru",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&About WireGuard…",
+ "message": "&About WireGuard…",
+ "translation": "&O aplikaci WireGuard…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel Error",
+ "message": "Tunnel Error",
+ "translation": "Chyba tunelu",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "message": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "translation": "{ErrMsg}\n\nPro více informací se prosím podívejte do logu.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "ErrMsg",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errMsg"
+ }
+ ]
+ },
+ {
+ "id": "{Title} (out of date)",
+ "message": "{Title} (out of date)",
+ "translation": "{Title} (neaktuální)",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Title",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "mtw.Title()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Detection Error",
+ "message": "WireGuard Detection Error",
+ "translation": "Chyba při detekci WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to wait for WireGuard window to appear: {Err}",
+ "message": "Unable to wait for WireGuard window to appear: {Err}",
+ "translation": "Nelze čekat na zobrazení okna WireGuard: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard: Deactivated",
+ "message": "WireGuard: Deactivated",
+ "translation": "WireGuard: Deaktivován",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Unknown",
+ "message": "Status: Unknown",
+ "translation": "Stav: Neznámý",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Addresses: None",
+ "message": "Addresses: None",
+ "translation": "Adresy: žádné",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Manage tunnels…",
+ "message": "&Manage tunnels…",
+ "translation": "Spravovat tunely…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Import tunnel(s) from file…",
+ "message": "&Import tunnel(s) from file…",
+ "translation": "&Importovat tunel(y) ze souboru…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "E&xit",
+ "message": "E&xit",
+ "translation": "U&končit",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Tunnels",
+ "message": "&Tunnels",
+ "translation": "&Tunely",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Activated",
+ "message": "WireGuard Activated",
+ "translation": "WireGuard aktivován",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "The {Name} tunnel has been activated.",
+ "message": "The {Name} tunnel has been activated.",
+ "translation": "Tunel {Name} byl aktivován.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnel.Name"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Deactivated",
+ "message": "WireGuard Deactivated",
+ "translation": "WireGuard deaktivován",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "The {Name} tunnel has been deactivated.",
+ "message": "The {Name} tunnel has been deactivated.",
+ "translation": "Tunel {Name} byl deaktivován.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnel.Name"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Tunnel Error",
+ "message": "WireGuard Tunnel Error",
+ "translation": "WireGuard Chyba Tunelu",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard: {TextForStateglobalState_true}",
+ "message": "WireGuard: {TextForStateglobalState_true}",
+ "translation": "WireGuard: {TextForStateglobalState_true}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TextForStateglobalState_true",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "textForState(globalState, true)"
+ }
+ ]
+ },
+ {
+ "id": "Status: {StateText}",
+ "message": "Status: {StateText}",
+ "translation": "Stav: {StateText}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "StateText",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "stateText"
+ }
+ ]
+ },
+ {
+ "id": "Addresses: {EnumerationSeparator}",
+ "message": "Addresses: {EnumerationSeparator}",
+ "translation": "Adresy: {EnumerationSeparator}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "EnumerationSeparator",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "strings.Join(addrs, l18n.EnumerationSeparator())"
+ }
+ ]
+ },
+ {
+ "id": "An Update is Available!",
+ "message": "An Update is Available!",
+ "translation": "Aktualizace je k dispozici!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Update Available",
+ "message": "WireGuard Update Available",
+ "translation": "Aktualizace WireGuard je k dispozici",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "An update to WireGuard is now available. You are advised to update as soon as possible.",
+ "message": "An update to WireGuard is now available. You are advised to update as soon as possible.",
+ "translation": "Aktualizace aplikace WireGuard je nyní k dispozici. Doporučujeme ji aktualizovat co nejdříve.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnels",
+ "message": "Tunnels",
+ "translation": "Tunely",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Edit",
+ "message": "&Edit",
+ "translation": "&Upravit",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Add &empty tunnel…",
+ "message": "Add &empty tunnel…",
+ "translation": "Přidat &prázdný tunel…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Add Tunnel",
+ "message": "Add Tunnel",
+ "translation": "Přidat tunel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Remove selected tunnel(s)",
+ "message": "Remove selected tunnel(s)",
+ "translation": "Odstranit vybrané tunely",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export all tunnels to zip",
+ "message": "Export all tunnels to zip",
+ "translation": "Exportovat všechny tunely do zip",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Toggle",
+ "message": "&Toggle",
+ "translation": "&Přepnout",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export all tunnels to &zip…",
+ "message": "Export all tunnels to &zip…",
+ "translation": "Exportovat všechny tunely do &zip…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Edit &selected tunnel…",
+ "message": "Edit &selected tunnel…",
+ "translation": "Upravit &vybraný tunel…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Remove selected tunnel(s)",
+ "message": "&Remove selected tunnel(s)",
+ "translation": "&Odstranit vybrané tunely",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "no configuration files were found",
+ "message": "no configuration files were found",
+ "translation": "nebyly nalezeny žádné konfigurační soubory",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Could not import selected configuration: {LastErr}",
+ "message": "Could not import selected configuration: {LastErr}",
+ "translation": "Nelze importovat vybranou konfiguraci: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Could not enumerate existing tunnels: {LastErr}",
+ "message": "Could not enumerate existing tunnels: {LastErr}",
+ "translation": "Nepodařilo se vyjmenovat existující tunely: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Another tunnel already exists with the name ‘{Name}’",
+ "message": "Another tunnel already exists with the name ‘{Name}’",
+ "translation": "Tunel s názvem '{Name}' již existuje",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "unparsedConfig.Name"
+ }
+ ]
+ },
+ {
+ "id": "Unable to import configuration: {LastErr}",
+ "message": "Unable to import configuration: {LastErr}",
+ "translation": "Nelze importovat konfiguraci: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Imported tunnels",
+ "message": "Imported tunnels",
+ "translation": "Importované tunely",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Imported {M} tunnels",
+ "message": "Imported {M} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "M",
+ "cases": {
+ "one": {
+ "msg": "Importován {M} tunel"
+ },
+ "few": {
+ "msg": "Importovány {M} tunely"
+ },
+ "many": {
+ "msg": "Importováno {M} tunelů"
+ },
+ "other": {
+ "msg": "Importováno {M} tunelů"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ }
+ ]
+ },
+ {
+ "id": "Imported {M} of {N} tunnels",
+ "message": "Imported {M} of {N} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "N",
+ "cases": {
+ "one": {
+ "msg": "Importován {M} z {N} tunel"
+ },
+ "few": {
+ "msg": "Importováno {M} z {N} tunelů"
+ },
+ "many": {
+ "msg": "Importováno {M} z {N} tunelů"
+ },
+ "other": {
+ "msg": "Importováno {M} z {N} tunelů"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ },
+ {
+ "id": "N",
+ "string": "%[2]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 2,
+ "expr": "n"
+ }
+ ]
+ },
+ {
+ "id": "Unable to create tunnel",
+ "message": "Unable to create tunnel",
+ "translation": "Nelze vytvořit tunel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Delete {TunnelCount} tunnels",
+ "message": "Delete {TunnelCount} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "TunnelCount",
+ "cases": {
+ "one": {
+ "msg": "Odstranit {TunnelCount} tunel"
+ },
+ "few": {
+ "msg": "Odstranit {TunnelCount} tunely"
+ },
+ "many": {
+ "msg": "Odstranit {TunnelCount} tunelů"
+ },
+ "other": {
+ "msg": "Odstranit {TunnelCount} tunelů"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "TunnelCount",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "tunnelCount"
+ }
+ ]
+ },
+ {
+ "id": "Are you sure you would like to delete {TunnelCount} tunnels?",
+ "message": "Are you sure you would like to delete {TunnelCount} tunnels?",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "TunnelCount",
+ "cases": {
+ "one": {
+ "msg": "Opravdu chcete odstranit {TunnelCount} tunel?"
+ },
+ "few": {
+ "msg": "Opravdu chcete odstranit {TunnelCount} tunely?"
+ },
+ "many": {
+ "msg": "Opravdu chcete odstranit {TunnelCount} tunelů?"
+ },
+ "other": {
+ "msg": "Opravdu chcete odstranit {TunnelCount} tunelů?"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "TunnelCount",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "tunnelCount"
+ }
+ ]
+ },
+ {
+ "id": "Delete tunnel ‘{TunnelName}’",
+ "message": "Delete tunnel ‘{TunnelName}’",
+ "translation": "Odstranit tunel \"{TunnelName}\"",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TunnelName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnelName"
+ }
+ ]
+ },
+ {
+ "id": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
+ "message": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
+ "translation": "Opravdu chcete odstranit tunel \"{TunnelName}\"?",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TunnelName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnelName"
+ }
+ ]
+ },
+ {
+ "id": "{Question} You cannot undo this action.",
+ "message": "{Question} You cannot undo this action.",
+ "translation": "{Question} Tuto akci nelze vrátit zpět.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Question",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "question"
+ }
+ ]
+ },
+ {
+ "id": "Unable to delete tunnel",
+ "message": "Unable to delete tunnel",
+ "translation": "Nelze odstranit tunel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "A tunnel was unable to be removed: {Error}",
+ "message": "A tunnel was unable to be removed: {Error}",
+ "translation": "Tunel nebylo možné odstranit: {Error}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Error",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errors[0].Error()"
+ }
+ ]
+ },
+ {
+ "id": "Unable to delete tunnels",
+ "message": "Unable to delete tunnels",
+ "translation": "Nelze odstranit tunely",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Lenerrors} tunnels were unable to be removed.",
+ "message": "{Lenerrors} tunnels were unable to be removed.",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Lenerrors",
+ "cases": {
+ "one": {
+ "msg": "{Lenerrors} tunel nebylo možné odstranit."
+ },
+ "few": {
+ "msg": "{Lenerrors} tunely nebylo možné odstranit."
+ },
+ "many": {
+ "msg": "{Lenerrors} tunelů nebylo možné odstranit."
+ },
+ "other": {
+ "msg": "{Lenerrors} tunelů nebylo možné odstranit."
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Lenerrors",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "len(errors)"
+ }
+ ]
+ },
+ {
+ "id": "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
+ "message": "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
+ "translation": "Konfigurace souborů (*.zip, *.conf)|*.zip; *.conf|Všechny soubory (*.*)|*.*",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Import tunnel(s) from file",
+ "message": "Import tunnel(s) from file",
+ "translation": "Importovat tunel(y) ze souboru",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Configuration ZIP Files (*.zip)|*.zip",
+ "message": "Configuration ZIP Files (*.zip)|*.zip",
+ "translation": "Konfigurace souborů ZIP (*.zip)|*.zip",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export tunnels to zip",
+ "message": "Export tunnels to zip",
+ "translation": "Exportovat tunely do zip",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Title} (unsigned build, no updates)",
+ "message": "{Title} (unsigned build, no updates)",
+ "translation": "{Title} (nepodepsaná verze, žádné aktualizace)",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Title",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "mtw.Title()"
+ }
+ ]
+ },
+ {
+ "id": "Error Exiting WireGuard",
+ "message": "Error Exiting WireGuard",
+ "translation": "Chyba při ukončování aplikace WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
+ "message": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
+ "translation": "Nelze ukončit službu z důvodu: {Err}. WireGuard můžete zastavit ve správci služeb.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "message": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "translation": "Aktualizace aplikace WireGuard je nyní k dispozici. Silně doporučujeme ji aktualizovat co nejdříve.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Waiting for user",
+ "message": "Status: Waiting for user",
+ "translation": "Stav: Čekání na uživatele",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Update Now",
+ "message": "Update Now",
+ "translation": "Aktualizovat nyní",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Waiting for updater service",
+ "message": "Status: Waiting for updater service",
+ "translation": "Stav: Čeká se na službu aktualizací",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error: {Err}. Please try again.",
+ "message": "Error: {Err}. Please try again.",
+ "translation": "Chyba: {Err}. Zkuste to znovu.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Status: Complete!",
+ "message": "Status: Complete!",
+ "translation": "Stav: Dokončeno!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "http2: Framer {F}: failed to decode just-written frame",
+ "message": "http2: Framer {F}: failed to decode just-written frame",
+ "translation": "http2: Framer {F}: failed to decode just-written frame",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "F",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "f"
+ }
+ ]
+ },
+ {
+ "id": "http2: Framer {F}: wrote {Http2summarizeFramefr}",
+ "message": "http2: Framer {F}: wrote {Http2summarizeFramefr}",
+ "translation": "http2: Framer {F}: wrote {Http2summarizeFramefr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "F",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "f"
+ },
+ {
+ "id": "Http2summarizeFramefr",
+ "string": "%[2]v",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "http2summarizeFrame(fr)"
+ }
+ ]
+ },
+ {
+ "id": "http2: Framer {Fr}: read {Http2summarizeFramef}",
+ "message": "http2: Framer {Fr}: read {Http2summarizeFramef}",
+ "translation": "http2: Framer {Fr}: read {Http2summarizeFramef}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Fr",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "fr"
+ },
+ {
+ "id": "Http2summarizeFramef",
+ "string": "%[2]v",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "http2summarizeFrame(f)"
+ }
+ ]
+ },
+ {
+ "id": "http2: decoded hpack field {HeaderField}",
+ "message": "http2: decoded hpack field {HeaderField}",
+ "translation": "http2: decoded hpack field {HeaderField}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "HeaderField",
+ "string": "%+[1]v",
+ "type": "vendor/golang.org/x/net/http2/hpack.HeaderField",
+ "underlyingType": "struct{Name string; Value string; Sensitive bool}",
+ "argNum": 1,
+ "expr": "hf"
+ }
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/locales/de/messages.gotext.json b/locales/de/messages.gotext.json
index cae1860e..5d26c8ab 100644
--- a/locales/de/messages.gotext.json
+++ b/locales/de/messages.gotext.json
@@ -744,6 +744,30 @@
"translatorComment": "Copied from source."
},
{
+ "id": "pre-up",
+ "message": "pre-up",
+ "translation": "vor Verbindsaufbau",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-up",
+ "message": "post-up",
+ "translation": "nach Verbindungsaufbau",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-down",
+ "message": "pre-down",
+ "translation": "vor Verbindungsabbau",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-down",
+ "message": "post-down",
+ "translation": "nach Verbindungsabbau",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "disabled, per policy",
"message": "disabled, per policy",
"translation": "deaktiviert, per Richtlinie",
@@ -1144,6 +1168,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "&Tunnels",
+ "message": "&Tunnels",
+ "translation": "&Tunnel",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "WireGuard Activated",
"message": "WireGuard Activated",
"translation": "WireGuard aktiviert",
diff --git a/locales/es-ES/messages.gotext.json b/locales/es-ES/messages.gotext.json
index 273022d4..c8332e6d 100644
--- a/locales/es-ES/messages.gotext.json
+++ b/locales/es-ES/messages.gotext.json
@@ -10,7 +10,7 @@
{
"id": "(no argument): elevate and install manager service",
"message": "(no argument): elevate and install manager service",
- "translation": "(sin argumento): eleva e instala el servicio de administrador",
+ "translation": "(sin argumento): eleve e instale el servicio de administrador",
"translatorComment": "Copied from source."
},
{
@@ -36,6 +36,1812 @@
"expr": "builder.String()"
}
]
+ },
+ {
+ "id": "Command Line Options",
+ "message": "Command Line Options",
+ "translation": "Opciones de línea de comandos",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to determine whether the process is running under WOW64: {Err}",
+ "message": "Unable to determine whether the process is running under WOW64: {Err}",
+ "translation": "No fue posible determinar si el proceso se está ejecutando bajo WOW64: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "You must use the native version of WireGuard on this computer.",
+ "message": "You must use the native version of WireGuard on this computer.",
+ "translation": "Debe usar la versión nativa de WireGuard en este equipo.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to open current process token: {Err}",
+ "message": "Unable to open current process token: {Err}",
+ "translation": "No fue posible abrir el token del proceso actual: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard may only be used by users who are a member of the Builtin {AdminGroupName} group.",
+ "message": "WireGuard may only be used by users who are a member of the Builtin {AdminGroupName} group.",
+ "translation": "WireGuard solo puede ser usado por usuarios que sean miembros del grupo integrado {AdminGroupName}.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "AdminGroupName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "elevate.AdminGroupName()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard is running, but the UI is only accessible from desktops of the Builtin {AdminGroupName} group.",
+ "message": "WireGuard is running, but the UI is only accessible from desktops of the Builtin {AdminGroupName} group.",
+ "translation": "WireGuard se está ejecutando, pero la interfaz de usuario solo es accesible desde escritorios del grupo integrado {AdminGroupName}.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "AdminGroupName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "elevate.AdminGroupName()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard system tray icon did not appear after 30 seconds.",
+ "message": "WireGuard system tray icon did not appear after 30 seconds.",
+ "translation": "El icono WireGuard de la bandeja del sistema no apareció después de 30 segundos.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Now",
+ "message": "Now",
+ "translation": "Ahora",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "System clock wound backward!",
+ "message": "System clock wound backward!",
+ "translation": "¡El reloj del sistema ha retrocedido!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Years} year(s)",
+ "message": "{Years} year(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Years",
+ "cases": {
+ "one": {
+ "msg": "{Years} año"
+ },
+ "other": {
+ "msg": "{Years} años"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Years",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "years"
+ }
+ ]
+ },
+ {
+ "id": "{Days} day(s)",
+ "message": "{Days} day(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Days",
+ "cases": {
+ "one": {
+ "msg": "{Days} día"
+ },
+ "other": {
+ "msg": "{Days} días"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Days",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "days"
+ }
+ ]
+ },
+ {
+ "id": "{Hours} hour(s)",
+ "message": "{Hours} hour(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Hours",
+ "cases": {
+ "one": {
+ "msg": "{Hours} hora"
+ },
+ "other": {
+ "msg": "{Hours} horas"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Hours",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "hours"
+ }
+ ]
+ },
+ {
+ "id": "{Minutes} minute(s)",
+ "message": "{Minutes} minute(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Minutes",
+ "cases": {
+ "one": {
+ "msg": "{Minutes} minuto"
+ },
+ "other": {
+ "msg": "{Minutes} minutos"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Minutes",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "minutes"
+ }
+ ]
+ },
+ {
+ "id": "{Seconds} second(s)",
+ "message": "{Seconds} second(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Seconds",
+ "cases": {
+ "one": {
+ "msg": "{Seconds} segundo"
+ },
+ "other": {
+ "msg": "{Seconds} segundos"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Seconds",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "seconds"
+ }
+ ]
+ },
+ {
+ "id": "{Timestamp} ago",
+ "message": "{Timestamp} ago",
+ "translation": "hace {Timestamp}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Timestamp",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "timestamp"
+ }
+ ]
+ },
+ {
+ "id": "{Bytes} B",
+ "message": "{Bytes} B",
+ "translation": "{Bytes} B",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Bytes",
+ "string": "%[1]d",
+ "type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
+ "underlyingType": "uint64",
+ "argNum": 1,
+ "expr": "b"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024} KiB",
+ "message": "{Float64b__1024} KiB",
+ "translation": "{Float64b__1024} KiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / 1024"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024} MiB",
+ "message": "{Float64b__1024__1024} MiB",
+ "translation": "{Float64b__1024__1024} MiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024} GiB",
+ "message": "{Float64b__1024__1024__1024} GiB",
+ "translation": "{Float64b__1024__1024__1024} GiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024__1024} TiB",
+ "message": "{Float64b__1024__1024__1024__1024} TiB",
+ "translation": "{Float64b__1024__1024__1024__1024} TiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024) / 1024"
+ }
+ ]
+ },
+ {
+ "id": "{Why}: {Offender}",
+ "message": "{Why}: {Offender}",
+ "translation": "{Why}: {Offender}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Why",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "e.why"
+ },
+ {
+ "id": "Offender",
+ "string": "%[2]q",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "e.offender"
+ }
+ ]
+ },
+ {
+ "id": "Invalid IP address",
+ "message": "Invalid IP address",
+ "translation": "La dirección IP no es válida",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid network prefix length",
+ "message": "Invalid network prefix length",
+ "translation": "La longitud del prefijo de red no es válida",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Missing port from endpoint",
+ "message": "Missing port from endpoint",
+ "translation": "Falta el puerto del Endpoint",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid endpoint host",
+ "message": "Invalid endpoint host",
+ "translation": "El host del Endpoint no es válido",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Brackets must contain an IPv6 address",
+ "message": "Brackets must contain an IPv6 address",
+ "translation": "Los corchetes deben contener una dirección IPv6",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid MTU",
+ "message": "Invalid MTU",
+ "translation": "La MTU no es válida",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid port",
+ "message": "Invalid port",
+ "translation": "El puerto no es válido",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid persistent keepalive",
+ "message": "Invalid persistent keepalive",
+ "translation": "El Keepalive persistente no es válido",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key: {Err}",
+ "message": "Invalid key: {Err}",
+ "translation": "La clave no es válida: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Keys must decode to exactly 32 bytes",
+ "message": "Keys must decode to exactly 32 bytes",
+ "translation": "Las claves deben decodificar exactamente a 32 bytes",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Number must be a number between 0 and 2^64-1: {Err}",
+ "message": "Number must be a number between 0 and 2^64-1: {Err}",
+ "translation": "El número debe estar entre 0 y 2^64-1: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Two commas in a row",
+ "message": "Two commas in a row",
+ "translation": "Dos comas consecutivas",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel name is not valid",
+ "message": "Tunnel name is not valid",
+ "translation": "El nombre del túnel no es válido",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Line must occur in a section",
+ "message": "Line must occur in a section",
+ "translation": "La línea debe aparecer en una sección",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Config key is missing an equals separator",
+ "message": "Config key is missing an equals separator",
+ "translation": "La clave de configuración no tiene un separador de igualdad",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Key must have a value",
+ "message": "Key must have a value",
+ "translation": "La clave debe tener un valor",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for [Interface] section",
+ "message": "Invalid key for [Interface] section",
+ "translation": "La clave no es válida para la sección [Interface]",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for [Peer] section",
+ "message": "Invalid key for [Peer] section",
+ "translation": "La clave no es válida para la sección [Peer]",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "An interface must have a private key",
+ "message": "An interface must have a private key",
+ "translation": "Una interfaz debe tener una clave privada",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "[none specified]",
+ "message": "[none specified]",
+ "translation": "[ninguno especificado]",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "All peers must have public keys",
+ "message": "All peers must have public keys",
+ "translation": "Todos los pares deben tener claves públicas",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error in getting configuration",
+ "message": "Error in getting configuration",
+ "translation": "Error al obtener la configuración",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for interface section",
+ "message": "Invalid key for interface section",
+ "translation": "La clave no es válida para sección de interfaz",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Protocol version must be 1",
+ "message": "Protocol version must be 1",
+ "translation": "La versión del protocolo debe ser 1",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for peer section",
+ "message": "Invalid key for peer section",
+ "translation": "La clave no es válida para la sección de par",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "[EnumerationSeparator]",
+ "message": "[EnumerationSeparator]",
+ "translation": ", ",
+ "comment": "Text to insert between items when listing - most western languages will translate ‘[EnumerationSeparator]’ into ‘, ’ to produce lists like ‘apple, orange, strawberry’. Eastern languages might translate into ‘、’ to produce lists like ‘リンゴ、オレンジ、イチゴ’."
+ },
+ {
+ "id": "[UnitSeparator]",
+ "message": "[UnitSeparator]",
+ "translation": ", ",
+ "comment": "Text to insert when combining units of a measure - most languages will translate ‘[UnitSeparator]’ into ‘ ’ (space) to produce lists like ‘2 minuti 30 sekund’, or empty string ‘’ to produce ‘2分30秒’."
+ },
+ {
+ "id": "About WireGuard",
+ "message": "About WireGuard",
+ "translation": "Acerca de WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard logo image",
+ "message": "WireGuard logo image",
+ "translation": "Logotipo de WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "message": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "translation": "Versión de la aplicación: {Number}\nVersión de backend Go: {WireGuardGoVersion}\nVersión de Go: {Version_go}-{GOARCH}\nSistema operativo: {OsName}\nArquitectura: {NativeArch}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Number",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "version.Number"
+ },
+ {
+ "id": "WireGuardGoVersion",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "device.WireGuardGoVersion"
+ },
+ {
+ "id": "Version_go",
+ "string": "%[3]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 3,
+ "expr": "strings.TrimPrefix(runtime.Version(), \"go\")"
+ },
+ {
+ "id": "GOARCH",
+ "string": "%[4]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 4,
+ "expr": "runtime.GOARCH"
+ },
+ {
+ "id": "OsName",
+ "string": "%[5]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 5,
+ "expr": "version.OsName()"
+ },
+ {
+ "id": "NativeArch",
+ "string": "%[6]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 6,
+ "expr": "version.NativeArch()"
+ }
+ ]
+ },
+ {
+ "id": "Close",
+ "message": "Close",
+ "translation": "Cerrar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "♥ &Donate!",
+ "message": "♥ &Donate!",
+ "translation": "♥ &¡Dona!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status:",
+ "message": "Status:",
+ "translation": "Estado:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Deactivate",
+ "message": "&Deactivate",
+ "translation": "&Desactivar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Activate",
+ "message": "&Activate",
+ "translation": "&Activar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Public key:",
+ "message": "Public key:",
+ "translation": "Clave pública:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Listen port:",
+ "message": "Listen port:",
+ "translation": "Puerto de escucha:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "MTU:",
+ "message": "MTU:",
+ "translation": "MTU:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Addresses:",
+ "message": "Addresses:",
+ "translation": "Direcciones:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "DNS servers:",
+ "message": "DNS servers:",
+ "translation": "Servidores DNS:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Scripts:",
+ "message": "Scripts:",
+ "translation": "Secuencias de comandos:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Preshared key:",
+ "message": "Preshared key:",
+ "translation": "Clave compartida:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Allowed IPs:",
+ "message": "Allowed IPs:",
+ "translation": "IPs permitidas:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Endpoint:",
+ "message": "Endpoint:",
+ "translation": "Endpoint:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Persistent keepalive:",
+ "message": "Persistent keepalive:",
+ "translation": "Keepalive persistente:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Latest handshake:",
+ "message": "Latest handshake:",
+ "translation": "Último saludo:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Transfer:",
+ "message": "Transfer:",
+ "translation": "Transferencia:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-up",
+ "message": "pre-up",
+ "translation": "pre-activación",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-up",
+ "message": "post-up",
+ "translation": "post-activación",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-down",
+ "message": "pre-down",
+ "translation": "pre-desactivación",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-down",
+ "message": "post-down",
+ "translation": "post-desactivación",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "disabled, per policy",
+ "message": "disabled, per policy",
+ "translation": "inhabilitado, por política",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "enabled",
+ "message": "enabled",
+ "translation": "habilitado",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{String} received, {String_1} sent",
+ "message": "{String} received, {String_1} sent",
+ "translation": "{String} recibido, {String_1} enviado",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "String",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "c.RxBytes.String()"
+ },
+ {
+ "id": "String_1",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "c.TxBytes.String()"
+ }
+ ]
+ },
+ {
+ "id": "Failed to determine tunnel state",
+ "message": "Failed to determine tunnel state",
+ "translation": "Error al determinar el estado del túnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Failed to activate tunnel",
+ "message": "Failed to activate tunnel",
+ "translation": "Error al activar el túnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Failed to deactivate tunnel",
+ "message": "Failed to deactivate tunnel",
+ "translation": "Error al desactivar el túnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Interface: {Name}",
+ "message": "Interface: {Name}",
+ "translation": "Interfaz: {Name}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "config.Name"
+ }
+ ]
+ },
+ {
+ "id": "Peer",
+ "message": "Peer",
+ "translation": "Par",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Create new tunnel",
+ "message": "Create new tunnel",
+ "translation": "Crear un túnel nuevo",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Edit tunnel",
+ "message": "Edit tunnel",
+ "translation": "Editar túnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Name:",
+ "message": "&Name:",
+ "translation": "&Nombre:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Public key:",
+ "message": "&Public key:",
+ "translation": "Clave pública:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "(unknown)",
+ "message": "(unknown)",
+ "translation": "(desconocido)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Block untunneled traffic (kill-switch)",
+ "message": "&Block untunneled traffic (kill-switch)",
+ "translation": "&Bloquear tráfico sin tunelizar (interruptor de apagado)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "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 or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "message": "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 or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "translation": "Cuando una configuración tiene exactamente un par, y ese par tiene IPs permitidas que contengan al menos 0.0.0.0/0 o ::/0, entonces el servicio del túnel activa reglas de firewall para bloquear todo el tráfico que no es hacia ni desde la interfaz del túnel o hacia al servidor DNS equivocado, con excepciones especiales para DHCP y NDP.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Save",
+ "message": "&Save",
+ "translation": "&Guardar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Cancel",
+ "message": "Cancel",
+ "translation": "Cancelar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Configuration:",
+ "message": "&Configuration:",
+ "translation": "&Configuración:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid name",
+ "message": "Invalid name",
+ "translation": "El nombre no es válido",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "A name is required.",
+ "message": "A name is required.",
+ "translation": "Se requiere un nombre.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel name ‘{NewName}’ is invalid.",
+ "message": "Tunnel name ‘{NewName}’ is invalid.",
+ "translation": "El nombre del túnel ‘{NewName}’ no es válido.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "NewName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "newName"
+ }
+ ]
+ },
+ {
+ "id": "Unable to list existing tunnels",
+ "message": "Unable to list existing tunnels",
+ "translation": "No fue posible listar los túneles existentes",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel already exists",
+ "message": "Tunnel already exists",
+ "translation": "El túnel ya existe",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Another tunnel already exists with the name ‘{NewName}’.",
+ "message": "Another tunnel already exists with the name ‘{NewName}’.",
+ "translation": "Ya existe otro túnel con el nombre ‘{NewName}’.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "NewName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "newName"
+ }
+ ]
+ },
+ {
+ "id": "Unable to create new configuration",
+ "message": "Unable to create new configuration",
+ "translation": "No fue posible crear una nueva configuración",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Writing file failed",
+ "message": "Writing file failed",
+ "translation": "Error al escribir el archivo",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "File ‘{FilePath}’ already exists.\n\nDo you want to overwrite it?",
+ "message": "File ‘{FilePath}’ already exists.\n\nDo you want to overwrite it?",
+ "translation": "El archivo ‘{FilePath}’ ya existe.\n\n¿Desea sobrescribir el archivo?",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "FilePath",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "filePath"
+ }
+ ]
+ },
+ {
+ "id": "Active",
+ "message": "Active",
+ "translation": "Activo",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Activating",
+ "message": "Activating",
+ "translation": "Activando",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Inactive",
+ "message": "Inactive",
+ "translation": "Inactivo",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Deactivating",
+ "message": "Deactivating",
+ "translation": "Desactivando",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unknown state",
+ "message": "Unknown state",
+ "translation": "Estado desconocido",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Log",
+ "message": "Log",
+ "translation": "Registro",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Copy",
+ "message": "&Copy",
+ "translation": "&Copiar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Select &all",
+ "message": "Select &all",
+ "translation": "Seleccionar &todos",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Save to file…",
+ "message": "&Save to file…",
+ "translation": "&Guardar en archivo…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Time",
+ "message": "Time",
+ "translation": "Tiempo",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Log message",
+ "message": "Log message",
+ "translation": "Mensaje del registro",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "message": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "translation": "Archivos de texto (*.txt)|*.txt|Todos los archivos (*.*)|*.*",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export log to file",
+ "message": "Export log to file",
+ "translation": "Exportar registro a archivo",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&About WireGuard…",
+ "message": "&About WireGuard…",
+ "translation": "&Acerca de WireGuard…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel Error",
+ "message": "Tunnel Error",
+ "translation": "Error en el túnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "message": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "translation": "{ErrMsg}\n\nPor favor, consulte el registro para más información.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "ErrMsg",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errMsg"
+ }
+ ]
+ },
+ {
+ "id": "{Title} (out of date)",
+ "message": "{Title} (out of date)",
+ "translation": "{Title} (desactualizado)",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Title",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "mtw.Title()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Detection Error",
+ "message": "WireGuard Detection Error",
+ "translation": "Error al detectar WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to wait for WireGuard window to appear: {Err}",
+ "message": "Unable to wait for WireGuard window to appear: {Err}",
+ "translation": "No fue posible esperar a que aparezca la ventana de WireGuard: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard: Deactivated",
+ "message": "WireGuard: Deactivated",
+ "translation": "WireGuard: Desactivado",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Unknown",
+ "message": "Status: Unknown",
+ "translation": "Estado: Desconocido",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Addresses: None",
+ "message": "Addresses: None",
+ "translation": "Direcciones: Ninguna",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Manage tunnels…",
+ "message": "&Manage tunnels…",
+ "translation": "&Administrar túneles…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Import tunnel(s) from file…",
+ "message": "&Import tunnel(s) from file…",
+ "translation": "&Importar túnel(es) desde archivo…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "E&xit",
+ "message": "E&xit",
+ "translation": "&Salir",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Tunnels",
+ "message": "&Tunnels",
+ "translation": "&Túneles",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Activated",
+ "message": "WireGuard Activated",
+ "translation": "WireGuard Activado",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "The {Name} tunnel has been activated.",
+ "message": "The {Name} tunnel has been activated.",
+ "translation": "El túnel {Name} ha sido activado.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnel.Name"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Deactivated",
+ "message": "WireGuard Deactivated",
+ "translation": "WireGuard Desactivado",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "The {Name} tunnel has been deactivated.",
+ "message": "The {Name} tunnel has been deactivated.",
+ "translation": "El túnel {Name} ha sido desactivado.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnel.Name"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Tunnel Error",
+ "message": "WireGuard Tunnel Error",
+ "translation": "Error en el túnel de WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard: {TextForStateglobalState_true}",
+ "message": "WireGuard: {TextForStateglobalState_true}",
+ "translation": "WireGuard: {TextForStateglobalState_true}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TextForStateglobalState_true",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "textForState(globalState, true)"
+ }
+ ]
+ },
+ {
+ "id": "Status: {StateText}",
+ "message": "Status: {StateText}",
+ "translation": "Estado: {StateText}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "StateText",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "stateText"
+ }
+ ]
+ },
+ {
+ "id": "Addresses: {EnumerationSeparator}",
+ "message": "Addresses: {EnumerationSeparator}",
+ "translation": "Direcciones: {EnumerationSeparator}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "EnumerationSeparator",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "strings.Join(addrs, l18n.EnumerationSeparator())"
+ }
+ ]
+ },
+ {
+ "id": "An Update is Available!",
+ "message": "An Update is Available!",
+ "translation": "¡Hay una actualización disponible!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Update Available",
+ "message": "WireGuard Update Available",
+ "translation": "Actualización de WireGuard disponible",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "An update to WireGuard is now available. You are advised to update as soon as possible.",
+ "message": "An update to WireGuard is now available. You are advised to update as soon as possible.",
+ "translation": "Está disponible una actualización de WireGuard. Se recomienda actualizar lo antes posible.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnels",
+ "message": "Tunnels",
+ "translation": "Túneles",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Edit",
+ "message": "&Edit",
+ "translation": "&Editar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Add &empty tunnel…",
+ "message": "Add &empty tunnel…",
+ "translation": "Agregar &túnel vacío…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Add Tunnel",
+ "message": "Add Tunnel",
+ "translation": "Agregar túnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Remove selected tunnel(s)",
+ "message": "Remove selected tunnel(s)",
+ "translation": "Eliminar túnel(es) seleccionados",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export all tunnels to zip",
+ "message": "Export all tunnels to zip",
+ "translation": "Exportar todos los túneles a ZIP",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Toggle",
+ "message": "&Toggle",
+ "translation": "&Cambiar estado",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export all tunnels to &zip…",
+ "message": "Export all tunnels to &zip…",
+ "translation": "Exportar todos los túneles a &ZIP…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Edit &selected tunnel…",
+ "message": "Edit &selected tunnel…",
+ "translation": "Editar túneles &seleccionados…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Remove selected tunnel(s)",
+ "message": "&Remove selected tunnel(s)",
+ "translation": "&Eliminar túnel(es) seleccionados",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "no configuration files were found",
+ "message": "no configuration files were found",
+ "translation": "no se encontraron archivos de configuración",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Could not import selected configuration: {LastErr}",
+ "message": "Could not import selected configuration: {LastErr}",
+ "translation": "No se puede importar la configuración seleccionada: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Could not enumerate existing tunnels: {LastErr}",
+ "message": "Could not enumerate existing tunnels: {LastErr}",
+ "translation": "No se pueden enumerar los túneles existentes: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Another tunnel already exists with the name ‘{Name}’",
+ "message": "Another tunnel already exists with the name ‘{Name}’",
+ "translation": "Ya existe otro túnel con el nombre '{Name}'",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "unparsedConfig.Name"
+ }
+ ]
+ },
+ {
+ "id": "Unable to import configuration: {LastErr}",
+ "message": "Unable to import configuration: {LastErr}",
+ "translation": "No fue posible importar la configuración: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Imported tunnels",
+ "message": "Imported tunnels",
+ "translation": "Túneles importados",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Imported {M} tunnels",
+ "message": "Imported {M} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "M",
+ "cases": {
+ "one": {
+ "msg": "{M} túnel importado"
+ },
+ "other": {
+ "msg": "{M} túneles importados"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ }
+ ]
+ },
+ {
+ "id": "Imported {M} of {N} tunnels",
+ "message": "Imported {M} of {N} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "N",
+ "cases": {
+ "one": {
+ "msg": "Importado {M} de {N} túnel"
+ },
+ "other": {
+ "msg": "Importados {M} de {N} túneles"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ },
+ {
+ "id": "N",
+ "string": "%[2]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 2,
+ "expr": "n"
+ }
+ ]
+ },
+ {
+ "id": "Unable to create tunnel",
+ "message": "Unable to create tunnel",
+ "translation": "No fue posible crear el túnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Delete {TunnelCount} tunnels",
+ "message": "Delete {TunnelCount} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "TunnelCount",
+ "cases": {
+ "one": {
+ "msg": "Eliminar {TunnelCount} túnel"
+ },
+ "other": {
+ "msg": "Eliminar {TunnelCount} túneles"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "TunnelCount",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "tunnelCount"
+ }
+ ]
+ },
+ {
+ "id": "Are you sure you would like to delete {TunnelCount} tunnels?",
+ "message": "Are you sure you would like to delete {TunnelCount} tunnels?",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "TunnelCount",
+ "cases": {
+ "one": {
+ "msg": "¿Está seguro de que querer eliminar {TunnelCount} túnel?"
+ },
+ "other": {
+ "msg": "¿Está seguro de que querer eliminar {TunnelCount} túneles?"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "TunnelCount",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "tunnelCount"
+ }
+ ]
+ },
+ {
+ "id": "Delete tunnel ‘{TunnelName}’",
+ "message": "Delete tunnel ‘{TunnelName}’",
+ "translation": "Eliminar túnel ‘{TunnelName}’",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TunnelName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnelName"
+ }
+ ]
+ },
+ {
+ "id": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
+ "message": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
+ "translation": "¿Está seguro de que desea eliminar el túnel ‘{TunnelName}’?",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TunnelName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnelName"
+ }
+ ]
+ },
+ {
+ "id": "{Question} You cannot undo this action.",
+ "message": "{Question} You cannot undo this action.",
+ "translation": "{Question} No puede deshacer esta acción.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Question",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "question"
+ }
+ ]
+ },
+ {
+ "id": "Unable to delete tunnel",
+ "message": "Unable to delete tunnel",
+ "translation": "No fue posible eliminar el túnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "A tunnel was unable to be removed: {Error}",
+ "message": "A tunnel was unable to be removed: {Error}",
+ "translation": "Un túnel no pudo ser eliminado: {Error}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Error",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errors[0].Error()"
+ }
+ ]
+ },
+ {
+ "id": "Unable to delete tunnels",
+ "message": "Unable to delete tunnels",
+ "translation": "No fue posible eliminar los túneles",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Lenerrors} tunnels were unable to be removed.",
+ "message": "{Lenerrors} tunnels were unable to be removed.",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Lenerrors",
+ "cases": {
+ "one": {
+ "msg": "No fue posible eliminar {Lenerrors} túnel."
+ },
+ "other": {
+ "msg": "No fue posible eliminar {Lenerrors} túneles."
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Lenerrors",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "len(errors)"
+ }
+ ]
+ },
+ {
+ "id": "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
+ "message": "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
+ "translation": "Archivos de configuración (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Import tunnel(s) from file",
+ "message": "Import tunnel(s) from file",
+ "translation": "Importar túnel(es) desde archivo",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Configuration ZIP Files (*.zip)|*.zip",
+ "message": "Configuration ZIP Files (*.zip)|*.zip",
+ "translation": "Archivos ZIP de configuración (*.zip)|*.zip",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export tunnels to zip",
+ "message": "Export tunnels to zip",
+ "translation": "Exportar túneles a ZIP",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Title} (unsigned build, no updates)",
+ "message": "{Title} (unsigned build, no updates)",
+ "translation": "{Title} (compilación no firmada, sin actualizaciones)",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Title",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "mtw.Title()"
+ }
+ ]
+ },
+ {
+ "id": "Error Exiting WireGuard",
+ "message": "Error Exiting WireGuard",
+ "translation": "Error al salir de WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
+ "message": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
+ "translation": "No fue posible terminar el servicio debido a: {Err}. Puede intentar detener WireGuard desde el administrador de servicios.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "message": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "translation": "Hay una actualización de Wireguard disponible. Es muy recomendable actualizar de inmediato.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Waiting for user",
+ "message": "Status: Waiting for user",
+ "translation": "Estado: Esperando al usuario",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Update Now",
+ "message": "Update Now",
+ "translation": "Actualizar ahora",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Waiting for updater service",
+ "message": "Status: Waiting for updater service",
+ "translation": "Estado: Esperando al servicio de actualización",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error: {Err}. Please try again.",
+ "message": "Error: {Err}. Please try again.",
+ "translation": "Error: {Err}. Por favor, intente de nuevo.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Status: Complete!",
+ "message": "Status: Complete!",
+ "translation": "Estado: ¡Completo!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "http2: Framer {F}: failed to decode just-written frame",
+ "message": "http2: Framer {F}: failed to decode just-written frame",
+ "translation": "http2: Framer {F}: failed to decode just-written frame",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "F",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "f"
+ }
+ ]
+ },
+ {
+ "id": "http2: Framer {F}: wrote {Http2summarizeFramefr}",
+ "message": "http2: Framer {F}: wrote {Http2summarizeFramefr}",
+ "translation": "http2: Framer {F}: wrote {Http2summarizeFramefr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "F",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "f"
+ },
+ {
+ "id": "Http2summarizeFramefr",
+ "string": "%[2]v",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "http2summarizeFrame(fr)"
+ }
+ ]
+ },
+ {
+ "id": "http2: Framer {Fr}: read {Http2summarizeFramef}",
+ "message": "http2: Framer {Fr}: read {Http2summarizeFramef}",
+ "translation": "http2: Framer {Fr}: read {Http2summarizeFramef}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Fr",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "fr"
+ },
+ {
+ "id": "Http2summarizeFramef",
+ "string": "%[2]v",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "http2summarizeFrame(f)"
+ }
+ ]
+ },
+ {
+ "id": "http2: decoded hpack field {HeaderField}",
+ "message": "http2: decoded hpack field {HeaderField}",
+ "translation": "http2: decoded hpack field {HeaderField}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "HeaderField",
+ "string": "%+[1]v",
+ "type": "vendor/golang.org/x/net/http2/hpack.HeaderField",
+ "underlyingType": "struct{Name string; Value string; Sensitive bool}",
+ "argNum": 1,
+ "expr": "hf"
+ }
+ ]
}
]
} \ No newline at end of file
diff --git a/locales/et/messages.gotext.json b/locales/et/messages.gotext.json
new file mode 100644
index 00000000..b06b42b7
--- /dev/null
+++ b/locales/et/messages.gotext.json
@@ -0,0 +1,1847 @@
+{
+ "language": "et",
+ "messages": [
+ {
+ "id": "Error",
+ "message": "Error",
+ "translation": "Viga",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "(no argument): elevate and install manager service",
+ "message": "(no argument): elevate and install manager service",
+ "translation": "(tühi muutuja): paigalda haldusteenus ülemõigustega",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Usage: {Args0} [\n{String}]",
+ "message": "Usage: {Args0} [\n{String}]",
+ "translation": "Kasutus: {Args0} [ \n{String}]",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Args0",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "os.Args[0]"
+ },
+ {
+ "id": "String",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "builder.String()"
+ }
+ ]
+ },
+ {
+ "id": "Command Line Options",
+ "message": "Command Line Options",
+ "translation": "Käsurea valikud",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to determine whether the process is running under WOW64: {Err}",
+ "message": "Unable to determine whether the process is running under WOW64: {Err}",
+ "translation": "Pole võimalik tuvastada, kas protsess töötab WOW64 kontekstis: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "You must use the native version of WireGuard on this computer.",
+ "message": "You must use the native version of WireGuard on this computer.",
+ "translation": "Peate kasutama antud arvutiga sobivat WireGuard'i versiooni.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to open current process token: {Err}",
+ "message": "Unable to open current process token: {Err}",
+ "translation": "Praeguse protsessi tähist ei saa avada: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard may only be used by users who are a member of the Builtin {AdminGroupName} group.",
+ "message": "WireGuard may only be used by users who are a member of the Builtin {AdminGroupName} group.",
+ "translation": "WireGuard'i võivad kasutada ainult kasutajad, kes on sisseehitatud {AdminGroupName} grupi liikmed.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "AdminGroupName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "elevate.AdminGroupName()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard is running, but the UI is only accessible from desktops of the Builtin {AdminGroupName} group.",
+ "message": "WireGuard is running, but the UI is only accessible from desktops of the Builtin {AdminGroupName} group.",
+ "translation": "WireGuard töötab, aga kasutajaliides on ainult ligipääsetav sisseehitatud {AdminGroupName} grupi töölaudadest.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "AdminGroupName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "elevate.AdminGroupName()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard system tray icon did not appear after 30 seconds.",
+ "message": "WireGuard system tray icon did not appear after 30 seconds.",
+ "translation": "WireGuard'i süsteemisalve ikoon ei ilmunud 30 sekundi jooksul.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Now",
+ "message": "Now",
+ "translation": "Nüüd",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "System clock wound backward!",
+ "message": "System clock wound backward!",
+ "translation": "Süsteemi kella on tagasi keritud!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Years} year(s)",
+ "message": "{Years} year(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Years",
+ "cases": {
+ "one": {
+ "msg": "{Years} aasta"
+ },
+ "other": {
+ "msg": "{Years} aastat"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Years",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "years"
+ }
+ ]
+ },
+ {
+ "id": "{Days} day(s)",
+ "message": "{Days} day(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Days",
+ "cases": {
+ "one": {
+ "msg": "{Days} päev"
+ },
+ "other": {
+ "msg": "{Days} päeva"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Days",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "days"
+ }
+ ]
+ },
+ {
+ "id": "{Hours} hour(s)",
+ "message": "{Hours} hour(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Hours",
+ "cases": {
+ "one": {
+ "msg": "{Hours} tund"
+ },
+ "other": {
+ "msg": "{Hours} tundi"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Hours",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "hours"
+ }
+ ]
+ },
+ {
+ "id": "{Minutes} minute(s)",
+ "message": "{Minutes} minute(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Minutes",
+ "cases": {
+ "one": {
+ "msg": "{Minutes} minut"
+ },
+ "other": {
+ "msg": "{Minutes} minutit"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Minutes",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "minutes"
+ }
+ ]
+ },
+ {
+ "id": "{Seconds} second(s)",
+ "message": "{Seconds} second(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Seconds",
+ "cases": {
+ "one": {
+ "msg": "{Seconds} sekund"
+ },
+ "other": {
+ "msg": "{Seconds} sekundit"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Seconds",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "seconds"
+ }
+ ]
+ },
+ {
+ "id": "{Timestamp} ago",
+ "message": "{Timestamp} ago",
+ "translation": "{Timestamp} tagasi",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Timestamp",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "timestamp"
+ }
+ ]
+ },
+ {
+ "id": "{Bytes} B",
+ "message": "{Bytes} B",
+ "translation": "{Bytes} B",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Bytes",
+ "string": "%[1]d",
+ "type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
+ "underlyingType": "uint64",
+ "argNum": 1,
+ "expr": "b"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024} KiB",
+ "message": "{Float64b__1024} KiB",
+ "translation": "{Float64b__1024} KiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / 1024"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024} MiB",
+ "message": "{Float64b__1024__1024} MiB",
+ "translation": "{Float64b__1024__1024} MiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024} GiB",
+ "message": "{Float64b__1024__1024__1024} GiB",
+ "translation": "{Float64b__1024__1024__1024} GiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024__1024} TiB",
+ "message": "{Float64b__1024__1024__1024__1024} TiB",
+ "translation": "{Float64b__1024__1024__1024__1024} TiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024) / 1024"
+ }
+ ]
+ },
+ {
+ "id": "{Why}: {Offender}",
+ "message": "{Why}: {Offender}",
+ "translation": "{Why}: {Offender}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Why",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "e.why"
+ },
+ {
+ "id": "Offender",
+ "string": "%[2]q",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "e.offender"
+ }
+ ]
+ },
+ {
+ "id": "Invalid IP address",
+ "message": "Invalid IP address",
+ "translation": "Sobimatu IP-aadress",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid network prefix length",
+ "message": "Invalid network prefix length",
+ "translation": "Sobimatu alamvõrgu maski pikkus",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Missing port from endpoint",
+ "message": "Missing port from endpoint",
+ "translation": "Lõpp-punktis on port määramata",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid endpoint host",
+ "message": "Invalid endpoint host",
+ "translation": "Sobimatu lõpp-punkti aadress",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Brackets must contain an IPv6 address",
+ "message": "Brackets must contain an IPv6 address",
+ "translation": "Looksulud peavad sisaldama IPv6-aadressi",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid MTU",
+ "message": "Invalid MTU",
+ "translation": "Sobimatu MTU",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid port",
+ "message": "Invalid port",
+ "translation": "Sobimatu port",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid persistent keepalive",
+ "message": "Invalid persistent keepalive",
+ "translation": "Sobimatu kestva ühendushoidiku väärtus",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key: {Err}",
+ "message": "Invalid key: {Err}",
+ "translation": "Sobimatu võti: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Keys must decode to exactly 32 bytes",
+ "message": "Keys must decode to exactly 32 bytes",
+ "translation": "Võtmed peavad dekodeerima täpselt 32 baidi suuruseks",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Number must be a number between 0 and 2^64-1: {Err}",
+ "message": "Number must be a number between 0 and 2^64-1: {Err}",
+ "translation": "Number peab olema väärtus 0 ja 2^64-1 vahel: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Two commas in a row",
+ "message": "Two commas in a row",
+ "translation": "Kaks koma järjest",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel name is not valid",
+ "message": "Tunnel name is not valid",
+ "translation": "Tunneli nimi pole sobilik",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Line must occur in a section",
+ "message": "Line must occur in a section",
+ "translation": "Rida peab olemas olema lõigu sees",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Config key is missing an equals separator",
+ "message": "Config key is missing an equals separator",
+ "translation": "Seadistusvõtmel on võrdusmärk eraldajana puudu",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Key must have a value",
+ "message": "Key must have a value",
+ "translation": "Võti peab omama väärtust",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for [Interface] section",
+ "message": "Invalid key for [Interface] section",
+ "translation": "Sobimatu võti [Interface] lõigus",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for [Peer] section",
+ "message": "Invalid key for [Peer] section",
+ "translation": "Sobimatu võti [Peer] lõigus",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "An interface must have a private key",
+ "message": "An interface must have a private key",
+ "translation": "Liides peab omama privaatvõtit",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "[none specified]",
+ "message": "[none specified]",
+ "translation": "[pole määratud]",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "All peers must have public keys",
+ "message": "All peers must have public keys",
+ "translation": "Kõik partnerid peavad omama avalikke võtmeid",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error in getting configuration",
+ "message": "Error in getting configuration",
+ "translation": "Seadistuste saamisel ilmnes viga",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for interface section",
+ "message": "Invalid key for interface section",
+ "translation": "Sobimatu võti liidese lõigus",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Protocol version must be 1",
+ "message": "Protocol version must be 1",
+ "translation": "Protokolli versioon peab olema 1",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for peer section",
+ "message": "Invalid key for peer section",
+ "translation": "Sobimatu võti partneri lõigus",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "[EnumerationSeparator]",
+ "message": "[EnumerationSeparator]",
+ "translation": ", ",
+ "comment": "Text to insert between items when listing - most western languages will translate ‘[EnumerationSeparator]’ into ‘, ’ to produce lists like ‘apple, orange, strawberry’. Eastern languages might translate into ‘、’ to produce lists like ‘リンゴ、オレンジ、イチゴ’."
+ },
+ {
+ "id": "[UnitSeparator]",
+ "message": "[UnitSeparator]",
+ "translation": ", ",
+ "comment": "Text to insert when combining units of a measure - most languages will translate ‘[UnitSeparator]’ into ‘ ’ (space) to produce lists like ‘2 minuti 30 sekund’, or empty string ‘’ to produce ‘2分30秒’."
+ },
+ {
+ "id": "About WireGuard",
+ "message": "About WireGuard",
+ "translation": "WireGuard'ist",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard logo image",
+ "message": "WireGuard logo image",
+ "translation": "WireGuard logo pilt",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "message": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "translation": "Programmi versioon: {Number}\nGo taustsüsteemi versioon: {WireGuardGoVersion}\nGo versioon: {Version_go}-{GOARCH}\nOperatsioonisüsteem: {OsName}\nArhitektuur: {NativeArch}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Number",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "version.Number"
+ },
+ {
+ "id": "WireGuardGoVersion",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "device.WireGuardGoVersion"
+ },
+ {
+ "id": "Version_go",
+ "string": "%[3]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 3,
+ "expr": "strings.TrimPrefix(runtime.Version(), \"go\")"
+ },
+ {
+ "id": "GOARCH",
+ "string": "%[4]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 4,
+ "expr": "runtime.GOARCH"
+ },
+ {
+ "id": "OsName",
+ "string": "%[5]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 5,
+ "expr": "version.OsName()"
+ },
+ {
+ "id": "NativeArch",
+ "string": "%[6]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 6,
+ "expr": "version.NativeArch()"
+ }
+ ]
+ },
+ {
+ "id": "Close",
+ "message": "Close",
+ "translation": "Sulge",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "♥ &Donate!",
+ "message": "♥ &Donate!",
+ "translation": "♥ &Anneta!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status:",
+ "message": "Status:",
+ "translation": "Staatus:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Deactivate",
+ "message": "&Deactivate",
+ "translation": "&Ühendu lahti",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Activate",
+ "message": "&Activate",
+ "translation": "&Ühenda",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Public key:",
+ "message": "Public key:",
+ "translation": "Avalik võti:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Listen port:",
+ "message": "Listen port:",
+ "translation": "Kuulamisport:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "MTU:",
+ "message": "MTU:",
+ "translation": "MTU:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Addresses:",
+ "message": "Addresses:",
+ "translation": "Aadressid:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "DNS servers:",
+ "message": "DNS servers:",
+ "translation": "DNS-serverid:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Scripts:",
+ "message": "Scripts:",
+ "translation": "Skriptid:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Preshared key:",
+ "message": "Preshared key:",
+ "translation": "Eeljagatud võti:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Allowed IPs:",
+ "message": "Allowed IPs:",
+ "translation": "Lubatud IP-aadressid:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Endpoint:",
+ "message": "Endpoint:",
+ "translation": "Lõpp-punkt:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Persistent keepalive:",
+ "message": "Persistent keepalive:",
+ "translation": "Kestev ühendushoidik:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Latest handshake:",
+ "message": "Latest handshake:",
+ "translation": "Värskeim kätlus:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Transfer:",
+ "message": "Transfer:",
+ "translation": "Ülekanded:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-up",
+ "message": "pre-up",
+ "translation": "enne ühendumist",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-up",
+ "message": "post-up",
+ "translation": "pärast ühendumist",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-down",
+ "message": "pre-down",
+ "translation": "enne lahti ühendumist",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-down",
+ "message": "post-down",
+ "translation": "pärast lahti ühendumist",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "disabled, per policy",
+ "message": "disabled, per policy",
+ "translation": "keelatud, poliitika põhiselt",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "enabled",
+ "message": "enabled",
+ "translation": "lubatud",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{String} received, {String_1} sent",
+ "message": "{String} received, {String_1} sent",
+ "translation": "{String} vastu võetud, {String_1} saadetud",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "String",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "c.RxBytes.String()"
+ },
+ {
+ "id": "String_1",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "c.TxBytes.String()"
+ }
+ ]
+ },
+ {
+ "id": "Failed to determine tunnel state",
+ "message": "Failed to determine tunnel state",
+ "translation": "Tunneli oleku tuvastamine ebaõnnestus",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Failed to activate tunnel",
+ "message": "Failed to activate tunnel",
+ "translation": "Tunneli ühendamine ebaõnnestus",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Failed to deactivate tunnel",
+ "message": "Failed to deactivate tunnel",
+ "translation": "Tunneli lahti ühendamine ebaõnnestus",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Interface: {Name}",
+ "message": "Interface: {Name}",
+ "translation": "Liides: {Name}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "config.Name"
+ }
+ ]
+ },
+ {
+ "id": "Peer",
+ "message": "Peer",
+ "translation": "Partner",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Create new tunnel",
+ "message": "Create new tunnel",
+ "translation": "Loo uus tunnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Edit tunnel",
+ "message": "Edit tunnel",
+ "translation": "Muuda tunnelit",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Name:",
+ "message": "&Name:",
+ "translation": "&Nimi:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Public key:",
+ "message": "&Public key:",
+ "translation": "&Avalik võti:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "(unknown)",
+ "message": "(unknown)",
+ "translation": "(tundmatu)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Block untunneled traffic (kill-switch)",
+ "message": "&Block untunneled traffic (kill-switch)",
+ "translation": "&Keela tunneldamata liiklus (kaitselüliti)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "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 or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "message": "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 or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "translation": "Kui seadistuses on ainult üks partner ning sellel partneril on lubatud IP-aadresside seas määratud vähemalt üks 0.0.0.0/0 või ::/0 aadress, siis tunneliteenus lülitab sisse tulemüürireeglistiku, mis keelab kogu liikluse, mis pole pärit tunneliliidesest ega suundu selle poole või liigub vale DNS-serveri suunas. DHCP ja NDP jaoks on loodud erandid.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Save",
+ "message": "&Save",
+ "translation": "&Salvesta",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Cancel",
+ "message": "Cancel",
+ "translation": "Loobu",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Configuration:",
+ "message": "&Configuration:",
+ "translation": "&Seadistus:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid name",
+ "message": "Invalid name",
+ "translation": "Sobimatu nimi",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "A name is required.",
+ "message": "A name is required.",
+ "translation": "Nimi on kohustuslik.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel name ‘{NewName}’ is invalid.",
+ "message": "Tunnel name ‘{NewName}’ is invalid.",
+ "translation": "Tunneli nimi '{NewName}' on sobimatu.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "NewName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "newName"
+ }
+ ]
+ },
+ {
+ "id": "Unable to list existing tunnels",
+ "message": "Unable to list existing tunnels",
+ "translation": "Olemasolevaid tunneleid ei saa loetleda",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel already exists",
+ "message": "Tunnel already exists",
+ "translation": "Tunnel on juba olemas",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Another tunnel already exists with the name ‘{NewName}’.",
+ "message": "Another tunnel already exists with the name ‘{NewName}’.",
+ "translation": "Tunnel nimega '{NewName}' juba on olemas.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "NewName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "newName"
+ }
+ ]
+ },
+ {
+ "id": "Unable to create new configuration",
+ "message": "Unable to create new configuration",
+ "translation": "Uue seadistuse loomine ebaõnnestus",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Writing file failed",
+ "message": "Writing file failed",
+ "translation": "Faili kirjutamine ebaõnnestus",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "File ‘{FilePath}’ already exists.\n\nDo you want to overwrite it?",
+ "message": "File ‘{FilePath}’ already exists.\n\nDo you want to overwrite it?",
+ "translation": "Fail nimega '{FilePath}' on juba olemas.\n\nKas soovid selle üle kirjutada?",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "FilePath",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "filePath"
+ }
+ ]
+ },
+ {
+ "id": "Active",
+ "message": "Active",
+ "translation": "Ühenduses",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Activating",
+ "message": "Activating",
+ "translation": "Ühendumas",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Inactive",
+ "message": "Inactive",
+ "translation": "Jõudeolekus",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Deactivating",
+ "message": "Deactivating",
+ "translation": "Lahti ühendumas",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unknown state",
+ "message": "Unknown state",
+ "translation": "Tundmatu olek",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Log",
+ "message": "Log",
+ "translation": "Logi",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Copy",
+ "message": "&Copy",
+ "translation": "&Kopeeri",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Select &all",
+ "message": "Select &all",
+ "translation": "Vali &kõik",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Save to file…",
+ "message": "&Save to file…",
+ "translation": "&Salvesta faili…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Time",
+ "message": "Time",
+ "translation": "Aeg",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Log message",
+ "message": "Log message",
+ "translation": "Logisõnum",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "message": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "translation": "Tekstifailid (*.txt)|*.txt|Kõik failid (*.*)|*.*",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export log to file",
+ "message": "Export log to file",
+ "translation": "Ekspordi logid faili",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&About WireGuard…",
+ "message": "&About WireGuard…",
+ "translation": "WireGu&ard'ist…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel Error",
+ "message": "Tunnel Error",
+ "translation": "Tunneli viga",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "message": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "translation": "{ErrMsg}\n\nLisainformatsiooni saamiseks palun vaadake logisid.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "ErrMsg",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errMsg"
+ }
+ ]
+ },
+ {
+ "id": "{Title} (out of date)",
+ "message": "{Title} (out of date)",
+ "translation": "{Title} (uuendamata)",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Title",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "mtw.Title()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Detection Error",
+ "message": "WireGuard Detection Error",
+ "translation": "WireGuard'i tuvastusviga",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to wait for WireGuard window to appear: {Err}",
+ "message": "Unable to wait for WireGuard window to appear: {Err}",
+ "translation": "WireGuard'i akna ilmumise ootamine ebaõnnestus: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard: Deactivated",
+ "message": "WireGuard: Deactivated",
+ "translation": "WireGuard: Lahti ühendatud",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Unknown",
+ "message": "Status: Unknown",
+ "translation": "Staatus: Tundmatu olek",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Addresses: None",
+ "message": "Addresses: None",
+ "translation": "Aadressid: Pole",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Manage tunnels…",
+ "message": "&Manage tunnels…",
+ "translation": "&Halda tunneleid…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Import tunnel(s) from file…",
+ "message": "&Import tunnel(s) from file…",
+ "translation": "&Impordi tunnel(id) failist…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "E&xit",
+ "message": "E&xit",
+ "translation": "Sul&e",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Tunnels",
+ "message": "&Tunnels",
+ "translation": "&Tunnelid",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Activated",
+ "message": "WireGuard Activated",
+ "translation": "WireGuard ühendatud",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "The {Name} tunnel has been activated.",
+ "message": "The {Name} tunnel has been activated.",
+ "translation": "Tunnel '{Name}' on ühendatud.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnel.Name"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Deactivated",
+ "message": "WireGuard Deactivated",
+ "translation": "WireGuard lahti ühendatud",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "The {Name} tunnel has been deactivated.",
+ "message": "The {Name} tunnel has been deactivated.",
+ "translation": "Tunnel '{Name}' on lahti ühendatud.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnel.Name"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Tunnel Error",
+ "message": "WireGuard Tunnel Error",
+ "translation": "WireGuard tunneli viga",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard: {TextForStateglobalState_true}",
+ "message": "WireGuard: {TextForStateglobalState_true}",
+ "translation": "WireGuard: {TextForStateglobalState_true}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TextForStateglobalState_true",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "textForState(globalState, true)"
+ }
+ ]
+ },
+ {
+ "id": "Status: {StateText}",
+ "message": "Status: {StateText}",
+ "translation": "Staatus: {StateText}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "StateText",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "stateText"
+ }
+ ]
+ },
+ {
+ "id": "Addresses: {EnumerationSeparator}",
+ "message": "Addresses: {EnumerationSeparator}",
+ "translation": "Aadressid: {EnumerationSeparator}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "EnumerationSeparator",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "strings.Join(addrs, l18n.EnumerationSeparator())"
+ }
+ ]
+ },
+ {
+ "id": "An Update is Available!",
+ "message": "An Update is Available!",
+ "translation": "Uuendus on saadaval!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Update Available",
+ "message": "WireGuard Update Available",
+ "translation": "WireGuard uuendus saadaval",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "An update to WireGuard is now available. You are advised to update as soon as possible.",
+ "message": "An update to WireGuard is now available. You are advised to update as soon as possible.",
+ "translation": "WireGuard'i uuendus on nüüd saadaval. Soovitame teil esimesel võimalusel uuendada.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnels",
+ "message": "Tunnels",
+ "translation": "Tunnelid",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Edit",
+ "message": "&Edit",
+ "translation": "&Muuda",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Add &empty tunnel…",
+ "message": "Add &empty tunnel…",
+ "translation": "Lisa tühi tunn&el…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Add Tunnel",
+ "message": "Add Tunnel",
+ "translation": "Lisa tunnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Remove selected tunnel(s)",
+ "message": "Remove selected tunnel(s)",
+ "translation": "Eemalda valitud tunnel(id)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export all tunnels to zip",
+ "message": "Export all tunnels to zip",
+ "translation": "Ekspordi kõik tunnelid zip-faili",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Toggle",
+ "message": "&Toggle",
+ "translation": "Lüli&tu ümber",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export all tunnels to &zip…",
+ "message": "Export all tunnels to &zip…",
+ "translation": "Ekspordi kõik tunnelid &zip-faili…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Edit &selected tunnel…",
+ "message": "Edit &selected tunnel…",
+ "translation": "Muuda &valitud tunnelit…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Remove selected tunnel(s)",
+ "message": "&Remove selected tunnel(s)",
+ "translation": "&Eemalda valitud tunnel(id)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "no configuration files were found",
+ "message": "no configuration files were found",
+ "translation": "ühtegi seadistusfaili ei leitud",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Could not import selected configuration: {LastErr}",
+ "message": "Could not import selected configuration: {LastErr}",
+ "translation": "Pole võimeline importima valitud seadistusfaili: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Could not enumerate existing tunnels: {LastErr}",
+ "message": "Could not enumerate existing tunnels: {LastErr}",
+ "translation": "Pole võimeline loetlema olemasolevaid tunneleid: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Another tunnel already exists with the name ‘{Name}’",
+ "message": "Another tunnel already exists with the name ‘{Name}’",
+ "translation": "Tunnel nimega '{Name}' on juba olemas",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "unparsedConfig.Name"
+ }
+ ]
+ },
+ {
+ "id": "Unable to import configuration: {LastErr}",
+ "message": "Unable to import configuration: {LastErr}",
+ "translation": "Seadistuse import ebaõnnestus: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Imported tunnels",
+ "message": "Imported tunnels",
+ "translation": "Imporditud tunnelid",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Imported {M} tunnels",
+ "message": "Imported {M} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "M",
+ "cases": {
+ "one": {
+ "msg": "Imporditud {M} tunnel"
+ },
+ "other": {
+ "msg": "Importitud {M} tunnelit"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ }
+ ]
+ },
+ {
+ "id": "Imported {M} of {N} tunnels",
+ "message": "Imported {M} of {N} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "N",
+ "cases": {
+ "one": {
+ "msg": "Imporditud {M} {N}-st tunnelist"
+ },
+ "other": {
+ "msg": "Imporditud {M} {N}-st tunnelist"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ },
+ {
+ "id": "N",
+ "string": "%[2]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 2,
+ "expr": "n"
+ }
+ ]
+ },
+ {
+ "id": "Unable to create tunnel",
+ "message": "Unable to create tunnel",
+ "translation": "Tunnelit ei saa luua",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Delete {TunnelCount} tunnels",
+ "message": "Delete {TunnelCount} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "TunnelCount",
+ "cases": {
+ "one": {
+ "msg": "Kustuta {TunnelCount} tunnel"
+ },
+ "other": {
+ "msg": "Kustuta {TunnelCount} tunnelit"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "TunnelCount",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "tunnelCount"
+ }
+ ]
+ },
+ {
+ "id": "Are you sure you would like to delete {TunnelCount} tunnels?",
+ "message": "Are you sure you would like to delete {TunnelCount} tunnels?",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "TunnelCount",
+ "cases": {
+ "one": {
+ "msg": "Kas oled kindel, et soovid kustutada {TunnelCount} tunneli?"
+ },
+ "other": {
+ "msg": "Kas oled kindel, et soovid kustutada {TunnelCount} tunnelit?"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "TunnelCount",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "tunnelCount"
+ }
+ ]
+ },
+ {
+ "id": "Delete tunnel ‘{TunnelName}’",
+ "message": "Delete tunnel ‘{TunnelName}’",
+ "translation": "Kustuta tunnel '{TunnelName}'",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TunnelName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnelName"
+ }
+ ]
+ },
+ {
+ "id": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
+ "message": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
+ "translation": "Kas oled kindel, et soovid kustutada tunneli nimega '{TunnelName}'?",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TunnelName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnelName"
+ }
+ ]
+ },
+ {
+ "id": "{Question} You cannot undo this action.",
+ "message": "{Question} You cannot undo this action.",
+ "translation": "{Question} Seda tegevust ei saa tagasi võtta.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Question",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "question"
+ }
+ ]
+ },
+ {
+ "id": "Unable to delete tunnel",
+ "message": "Unable to delete tunnel",
+ "translation": "Tunnelit ei saa kustutada",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "A tunnel was unable to be removed: {Error}",
+ "message": "A tunnel was unable to be removed: {Error}",
+ "translation": "Tunnelit ei saanud kustutada: {Error}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Error",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errors[0].Error()"
+ }
+ ]
+ },
+ {
+ "id": "Unable to delete tunnels",
+ "message": "Unable to delete tunnels",
+ "translation": "Tunneleid ei saa kustutada",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Lenerrors} tunnels were unable to be removed.",
+ "message": "{Lenerrors} tunnels were unable to be removed.",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Lenerrors",
+ "cases": {
+ "one": {
+ "msg": "Ei saanud eemaldada {Lenerrors} tunnelit."
+ },
+ "other": {
+ "msg": "Ei saanud eemaldada {Lenerrors} tunnelit."
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Lenerrors",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "len(errors)"
+ }
+ ]
+ },
+ {
+ "id": "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
+ "message": "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
+ "translation": "Seadistusfailid (*.zip, *.conf)|*.zip;*.conf|Kõik failid (*.*)|*.*",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Import tunnel(s) from file",
+ "message": "Import tunnel(s) from file",
+ "translation": "Impordi tunnel(id) failist",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Configuration ZIP Files (*.zip)|*.zip",
+ "message": "Configuration ZIP Files (*.zip)|*.zip",
+ "translation": "Pakendatud seadistusfailid (*.zip)|*.zip",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export tunnels to zip",
+ "message": "Export tunnels to zip",
+ "translation": "Ekspordi tunnelid zip-faili",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Title} (unsigned build, no updates)",
+ "message": "{Title} (unsigned build, no updates)",
+ "translation": "{Title} (allkirjastamata kompilatsioon, uuendusi pole)",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Title",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "mtw.Title()"
+ }
+ ]
+ },
+ {
+ "id": "Error Exiting WireGuard",
+ "message": "Error Exiting WireGuard",
+ "translation": "Viga WireGuard'i sulgemisel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
+ "message": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
+ "translation": "Teenuse lõpetamine ebaõnnestus järgneva tõttu: {Err}. Võid proovida WireGuard'i lõpetada teenusehaldurist.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "message": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "translation": "WireGuard'ile on uuendus saadaval. Sügavalt soovitame uuendada niipea kui võimalik.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Waiting for user",
+ "message": "Status: Waiting for user",
+ "translation": "Staatus: Ootan kasutaja järel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Update Now",
+ "message": "Update Now",
+ "translation": "Uuenda nüüd",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Waiting for updater service",
+ "message": "Status: Waiting for updater service",
+ "translation": "Staatus: Ootan uuendusteenuse järel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error: {Err}. Please try again.",
+ "message": "Error: {Err}. Please try again.",
+ "translation": "Viga: {Err}. Palun proovige uuesti.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Status: Complete!",
+ "message": "Status: Complete!",
+ "translation": "Staatus: Valmis!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "http2: Framer {F}: failed to decode just-written frame",
+ "message": "http2: Framer {F}: failed to decode just-written frame",
+ "translation": "http2: Kadeerija {F}: värske kaadri dekodeerimine ebaõnnestus",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "F",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "f"
+ }
+ ]
+ },
+ {
+ "id": "http2: Framer {F}: wrote {Http2summarizeFramefr}",
+ "message": "http2: Framer {F}: wrote {Http2summarizeFramefr}",
+ "translation": "http2: Kadeerija {F}: kirjutas {Http2summarizeFramefr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "F",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "f"
+ },
+ {
+ "id": "Http2summarizeFramefr",
+ "string": "%[2]v",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "http2summarizeFrame(fr)"
+ }
+ ]
+ },
+ {
+ "id": "http2: Framer {Fr}: read {Http2summarizeFramef}",
+ "message": "http2: Framer {Fr}: read {Http2summarizeFramef}",
+ "translation": "http2: Kadeerija {Fr}: luges {Http2summarizeFramef}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Fr",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "fr"
+ },
+ {
+ "id": "Http2summarizeFramef",
+ "string": "%[2]v",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "http2summarizeFrame(f)"
+ }
+ ]
+ },
+ {
+ "id": "http2: decoded hpack field {HeaderField}",
+ "message": "http2: decoded hpack field {HeaderField}",
+ "translation": "http2: dekodeeritud hpack väli {HeaderField}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "HeaderField",
+ "string": "%+[1]v",
+ "type": "vendor/golang.org/x/net/http2/hpack.HeaderField",
+ "underlyingType": "struct{Name string; Value string; Sensitive bool}",
+ "argNum": 1,
+ "expr": "hf"
+ }
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/locales/fa/messages.gotext.json b/locales/fa/messages.gotext.json
index f0918cc7..95744520 100644
--- a/locales/fa/messages.gotext.json
+++ b/locales/fa/messages.gotext.json
@@ -8,18 +8,130 @@
"translatorComment": "Copied from source."
},
{
+ "id": "(no argument): elevate and install manager service",
+ "message": "(no argument): elevate and install manager service",
+ "translation": "(بدون ورودیی): سرویس مدیریت را ارتقا و نصب کنید",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Usage: {Args0} [\n{String}]",
+ "message": "Usage: {Args0} [\n{String}]",
+ "translation": "استفاده: {Args0} [\n{String}]",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Args0",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "os.Args[0]"
+ },
+ {
+ "id": "String",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "builder.String()"
+ }
+ ]
+ },
+ {
"id": "Command Line Options",
"message": "Command Line Options",
"translation": "گزینه‌های خط فرمان",
"translatorComment": "Copied from source."
},
{
+ "id": "Unable to determine whether the process is running under WOW64: {Err}",
+ "message": "Unable to determine whether the process is running under WOW64: {Err}",
+ "translation": "ناتوان در ارزیابی اینکه فرآیند تحت WOW64 کار می کند: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "You must use the native version of WireGuard on this computer.",
+ "message": "You must use the native version of WireGuard on this computer.",
+ "translation": "شما باید از نگارش بومی وایرگارد بر روی این رایانه استفاده کنید.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to open current process token: {Err}",
+ "message": "Unable to open current process token: {Err}",
+ "translation": "رمز فرآیند فعلی باز نشد: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard may only be used by users who are a member of the Builtin {AdminGroupName} group.",
+ "message": "WireGuard may only be used by users who are a member of the Builtin {AdminGroupName} group.",
+ "translation": "وایرگارد فقط توسط کاربرانی که عضو گروه {AdminGroupName} هستند ممکن است استفاده شود.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "AdminGroupName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "elevate.AdminGroupName()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard is running, but the UI is only accessible from desktops of the Builtin {AdminGroupName} group.",
+ "message": "WireGuard is running, but the UI is only accessible from desktops of the Builtin {AdminGroupName} group.",
+ "translation": "وایرگارد در حال اجرا است، اما رابط کاربری فقط از دسکتاپ های گروه {AdminGroupName} قابل دسترسی است.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "AdminGroupName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "elevate.AdminGroupName()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard system tray icon did not appear after 30 seconds.",
+ "message": "WireGuard system tray icon did not appear after 30 seconds.",
+ "translation": "ایکون وایرگارد در سینی سیستم ،بعد از 30 ثانیه ظاهر نشد.",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Now",
"message": "Now",
"translation": "هم اکنون",
"translatorComment": "Copied from source."
},
{
+ "id": "System clock wound backward!",
+ "message": "System clock wound backward!",
+ "translation": "زمان سیستم شما عقب است!",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "{Years} year(s)",
"message": "{Years} year(s)",
"translation": {
@@ -192,12 +304,124 @@
]
},
{
+ "id": "{Float64b__1024} KiB",
+ "message": "{Float64b__1024} KiB",
+ "translation": "{Float64b__1024} KiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / 1024"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024} MiB",
+ "message": "{Float64b__1024__1024} MiB",
+ "translation": "{Float64b__1024__1024} MiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024} GiB",
+ "message": "{Float64b__1024__1024__1024} GiB",
+ "translation": "{Float64b__1024__1024__1024} GiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024__1024} TiB",
+ "message": "{Float64b__1024__1024__1024__1024} TiB",
+ "translation": "{Float64b__1024__1024__1024__1024} TiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024) / 1024"
+ }
+ ]
+ },
+ {
+ "id": "{Why}: {Offender}",
+ "message": "{Why}: {Offender}",
+ "translation": "{Why}: {Offender}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Why",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "e.why"
+ },
+ {
+ "id": "Offender",
+ "string": "%[2]q",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "e.offender"
+ }
+ ]
+ },
+ {
"id": "Invalid IP address",
"message": "Invalid IP address",
"translation": "نشانی آی‌پی نامعتبر است",
"translatorComment": "Copied from source."
},
{
+ "id": "Invalid network prefix length",
+ "message": "Invalid network prefix length",
+ "translation": "طول پیشوند شبکه نامعتبر است",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Missing port from endpoint",
+ "message": "Missing port from endpoint",
+ "translation": "پورت از نقطه پایانی وجود ندارد",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid endpoint host",
+ "message": "Invalid endpoint host",
+ "translation": "میزبان نقطه پایانی نامعتبر است",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Brackets must contain an IPv6 address",
+ "message": "Brackets must contain an IPv6 address",
+ "translation": "براکت‌ها باید حاوی آدرس IPv6 باشند",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Invalid MTU",
"message": "Invalid MTU",
"translation": "MTU نامعتبر است",
@@ -210,12 +434,98 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Invalid persistent keepalive",
+ "message": "Invalid persistent keepalive",
+ "translation": "مقدار کنترلر وصل بودن مجاز نیست",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key: {Err}",
+ "message": "Invalid key: {Err}",
+ "translation": "کلید نامعتبر: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Keys must decode to exactly 32 bytes",
+ "message": "Keys must decode to exactly 32 bytes",
+ "translation": "کلیدها باید دقیقا به ۳۲ بایت رمزگشایی شوند",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Number must be a number between 0 and 2^64-1: {Err}",
+ "message": "Number must be a number between 0 and 2^64-1: {Err}",
+ "translation": "عدد باید عددی بین 0 و 2^64-1 باشد: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Two commas in a row",
+ "message": "Two commas in a row",
+ "translation": "دو کاما پشت سر هم",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel name is not valid",
+ "message": "Tunnel name is not valid",
+ "translation": "نام تونل معتبر نیست",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Line must occur in a section",
+ "message": "Line must occur in a section",
+ "translation": "خط باید در یک بخش رخ دهد",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Config key is missing an equals separator",
+ "message": "Config key is missing an equals separator",
+ "translation": "کلید پیکربندی یک جداکننده برابر ندارد",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Key must have a value",
"message": "Key must have a value",
"translation": "کلید باید یک مقدار داشته باشد",
"translatorComment": "Copied from source."
},
{
+ "id": "Invalid key for [Interface] section",
+ "message": "Invalid key for [Interface] section",
+ "translation": "کلید برای رابط بخش [Interface] نامعتبر است",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for [Peer] section",
+ "message": "Invalid key for [Peer] section",
+ "translation": "کلید برای رابط بخش [Peer] نامعتبر است",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "An interface must have a private key",
+ "message": "An interface must have a private key",
+ "translation": "یک رابط باید یک کلید خصوصی داشته باشد",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "[none specified]",
"message": "[none specified]",
"translation": "[مشخص نشده]",
@@ -234,6 +544,24 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Invalid key for interface section",
+ "message": "Invalid key for interface section",
+ "translation": "کلید برای بخش [Interface] نامعتبر است",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Protocol version must be 1",
+ "message": "Protocol version must be 1",
+ "translation": "نسخه پروتکل باید 1 باشد",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for peer section",
+ "message": "Invalid key for peer section",
+ "translation": "کلید برای بخش طرفین نامعتبر است",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "[EnumerationSeparator]",
"message": "[EnumerationSeparator]",
"translation": "، ",
@@ -252,6 +580,68 @@
"translatorComment": "Copied from source."
},
{
+ "id": "WireGuard logo image",
+ "message": "WireGuard logo image",
+ "translation": "تصویر لوگوی WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "message": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "translation": "ورژن برنامه: {Number}\nورژن زبان گو در بطن:{WireGuardGoVersion}\nورژن زبان گو:{Version_go}-{GOARCH}\nسیستم عامل: {OsName}\nمعماری: {NativeArch}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Number",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "version.Number"
+ },
+ {
+ "id": "WireGuardGoVersion",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "device.WireGuardGoVersion"
+ },
+ {
+ "id": "Version_go",
+ "string": "%[3]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 3,
+ "expr": "strings.TrimPrefix(runtime.Version(), \"go\")"
+ },
+ {
+ "id": "GOARCH",
+ "string": "%[4]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 4,
+ "expr": "runtime.GOARCH"
+ },
+ {
+ "id": "OsName",
+ "string": "%[5]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 5,
+ "expr": "version.OsName()"
+ },
+ {
+ "id": "NativeArch",
+ "string": "%[6]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 6,
+ "expr": "version.NativeArch()"
+ }
+ ]
+ },
+ {
"id": "Close",
"message": "Close",
"translation": "بستن",
@@ -312,6 +702,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Scripts:",
+ "message": "Scripts:",
+ "translation": "اسکریپت‌ها:",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Preshared key:",
"message": "Preshared key:",
"translation": "کلید از پیش تقسیم شده:",
@@ -336,18 +732,96 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Latest handshake:",
+ "message": "Latest handshake:",
+ "translation": "آخرین دست دادن:",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Transfer:",
"message": "Transfer:",
"translation": "انتقال:",
"translatorComment": "Copied from source."
},
{
+ "id": "pre-up",
+ "message": "pre-up",
+ "translation": "پیشنیاز",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-up",
+ "message": "post-up",
+ "translation": "پس نیاز برقراری",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-down",
+ "message": "pre-down",
+ "translation": "پیشنیاز قطعی",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-down",
+ "message": "post-down",
+ "translation": "پسنیاز قطعی",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "disabled, per policy",
+ "message": "disabled, per policy",
+ "translation": "غیر فعال، بر اساس خط مشی",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "enabled",
"message": "enabled",
"translation": "فعال شده",
"translatorComment": "Copied from source."
},
{
+ "id": "{String} received, {String_1} sent",
+ "message": "{String} received, {String_1} sent",
+ "translation": "{String} دریافت شد، {String_1} ارسال شد",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "String",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "c.RxBytes.String()"
+ },
+ {
+ "id": "String_1",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "c.TxBytes.String()"
+ }
+ ]
+ },
+ {
+ "id": "Failed to determine tunnel state",
+ "message": "Failed to determine tunnel state",
+ "translation": "وضعیت تونل تعیین نشده است",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Failed to activate tunnel",
+ "message": "Failed to activate tunnel",
+ "translation": "فعال سازی تونل ناموفق بود",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Failed to deactivate tunnel",
+ "message": "Failed to deactivate tunnel",
+ "translation": "غیرفعال سازی تونل ناموفق بود",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Interface: {Name}",
"message": "Interface: {Name}",
"translation": "رابط: {Name}",
@@ -400,6 +874,18 @@
"translatorComment": "Copied from source."
},
{
+ "id": "&Block untunneled traffic (kill-switch)",
+ "message": "&Block untunneled traffic (kill-switch)",
+ "translation": "&مسدود کردن ترافیک تونل نشده (سوئیچ مرگ)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "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 or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "message": "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 or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "translation": "هنگامی که یک پیکربندی فقط یک peer داشته باشد و آن peer دارای IP های مجاز باشد که حداقل یکی از 0.0.0.0/0 یا ::/0 را شامل می شود، سرویس تونل مجموعه ای از قوانین فایروال را درگیر می کند تا تمام ترافیکی که نه به و نه از آن peer و یا به سرور DNS اشتباهی است را را مسدود میکند. ، با استثناء تعریف ویژه برای DHCP و NDP.",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "&Save",
"message": "&Save",
"translation": "&ذخیره",
@@ -430,6 +916,22 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Tunnel name ‘{NewName}’ is invalid.",
+ "message": "Tunnel name ‘{NewName}’ is invalid.",
+ "translation": "تونل با نام '{NewName}' نامعتبر است.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "NewName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "newName"
+ }
+ ]
+ },
+ {
"id": "Unable to list existing tunnels",
"message": "Unable to list existing tunnels",
"translation": "نمی‌توان تونل‌های موجود را فهرست کرد",
@@ -442,6 +944,50 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Another tunnel already exists with the name ‘{NewName}’.",
+ "message": "Another tunnel already exists with the name ‘{NewName}’.",
+ "translation": "تونل دیگری با نام '{NewName}' وجود دارد.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "NewName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "newName"
+ }
+ ]
+ },
+ {
+ "id": "Unable to create new configuration",
+ "message": "Unable to create new configuration",
+ "translation": "ناتوان در ایجاد پیکربندی جدید",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Writing file failed",
+ "message": "Writing file failed",
+ "translation": "نوشتن پرونده انجام نشد",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "File ‘{FilePath}’ already exists.\n\nDo you want to overwrite it?",
+ "message": "File ‘{FilePath}’ already exists.\n\nDo you want to overwrite it?",
+ "translation": "پرونده «{FilePath}» از قبل وجود دارد.\n\nآیا می‌خواهید آن را بازنویسی کنید؟",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "FilePath",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "filePath"
+ }
+ ]
+ },
+ {
"id": "Active",
"message": "Active",
"translation": "فعال",
@@ -484,6 +1030,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Select &all",
+ "message": "Select &all",
+ "translation": "انتخاب همه",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "&Save to file…",
"message": "&Save to file…",
"translation": "&ذخیره در پرونده…",
@@ -502,6 +1054,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "message": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "translation": "پرونده‌های متنی (*.txt)|*.txt|همه پرونده‌ها (*.*)|*.*",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Export log to file",
"message": "Export log to file",
"translation": "برون‌برد گزارش رویداد به پرونده",
@@ -520,6 +1078,66 @@
"translatorComment": "Copied from source."
},
{
+ "id": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "message": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "translation": "{ErrMsg}\n\nلطفا برای اطلاعات بیشتر به گزارش رویداد مراجعه کنید.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "ErrMsg",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errMsg"
+ }
+ ]
+ },
+ {
+ "id": "{Title} (out of date)",
+ "message": "{Title} (out of date)",
+ "translation": "{Title} (قدیمی)",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Title",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "mtw.Title()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Detection Error",
+ "message": "WireGuard Detection Error",
+ "translation": "وقوع اشکال در وایرگارد",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to wait for WireGuard window to appear: {Err}",
+ "message": "Unable to wait for WireGuard window to appear: {Err}",
+ "translation": "نمی‌توان منتظر ماند تا پنجره WireGuard ظاهر شود: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard: Deactivated",
+ "message": "WireGuard: Deactivated",
+ "translation": "WireGuard: غیر فعال شده است",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Status: Unknown",
"message": "Status: Unknown",
"translation": "وضعیت: ناشناخته",
@@ -538,15 +1156,33 @@
"translatorComment": "Copied from source."
},
{
+ "id": "&Import tunnel(s) from file…",
+ "message": "&Import tunnel(s) from file…",
+ "translation": "&وارد کردن تونل(ها) از پرونده…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "E&xit",
+ "message": "E&xit",
+ "translation": "خروج",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Tunnels",
+ "message": "&Tunnels",
+ "translation": "&تونل‌ها",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "WireGuard Activated",
"message": "WireGuard Activated",
- "translation": "WireGuard فعال‌شد",
+ "translation": "WireGuard فعال‌ شد",
"translatorComment": "Copied from source."
},
{
"id": "The {Name} tunnel has been activated.",
"message": "The {Name} tunnel has been activated.",
- "translation": "تونل {Name} فعال‌شده.",
+ "translation": "تونل {Name} فعال‌ شده است.",
"translatorComment": "Copied from source.",
"placeholders": [
{
@@ -566,12 +1202,44 @@
"translatorComment": "Copied from source."
},
{
+ "id": "The {Name} tunnel has been deactivated.",
+ "message": "The {Name} tunnel has been deactivated.",
+ "translation": "تونل {Name} غیرفعال شده است.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnel.Name"
+ }
+ ]
+ },
+ {
"id": "WireGuard Tunnel Error",
"message": "WireGuard Tunnel Error",
"translation": "خطای تونل WireGuard",
"translatorComment": "Copied from source."
},
{
+ "id": "WireGuard: {TextForStateglobalState_true}",
+ "message": "WireGuard: {TextForStateglobalState_true}",
+ "translation": "WireGuard: {TextForStateglobalState_true}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TextForStateglobalState_true",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "textForState(globalState, true)"
+ }
+ ]
+ },
+ {
"id": "Status: {StateText}",
"message": "Status: {StateText}",
"translation": "وضعیت: {StateText}",
@@ -588,6 +1256,22 @@
]
},
{
+ "id": "Addresses: {EnumerationSeparator}",
+ "message": "Addresses: {EnumerationSeparator}",
+ "translation": "نشانی‌ها: {EnumerationSeparator}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "EnumerationSeparator",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "strings.Join(addrs, l18n.EnumerationSeparator())"
+ }
+ ]
+ },
+ {
"id": "An Update is Available!",
"message": "An Update is Available!",
"translation": "یک به‌روزرسانی در دسترس است!",
@@ -600,6 +1284,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "An update to WireGuard is now available. You are advised to update as soon as possible.",
+ "message": "An update to WireGuard is now available. You are advised to update as soon as possible.",
+ "translation": "به‌روزرسانی WireGuard اکنون در دسترس است. به شما توصیه می‌شود در اسرع وقت به‌روزرسانی کنید.",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Tunnels",
"message": "Tunnels",
"translation": "تونل‌ها",
@@ -636,12 +1326,52 @@
"translatorComment": "Copied from source."
},
{
+ "id": "&Toggle",
+ "message": "&Toggle",
+ "translation": "تغییر وضعیت",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Export all tunnels to &zip…",
"message": "Export all tunnels to &zip…",
"translation": "برون‌بری همه تونل‌ها به &زیپ…",
"translatorComment": "Copied from source."
},
{
+ "id": "Edit &selected tunnel…",
+ "message": "Edit &selected tunnel…",
+ "translation": "ویرایش تونل انتخابی…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Remove selected tunnel(s)",
+ "message": "&Remove selected tunnel(s)",
+ "translation": "&حذف تونل(های) انتخاب شده",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "no configuration files were found",
+ "message": "no configuration files were found",
+ "translation": "هیچ فایل پیکربندی یافت نشد",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Could not import selected configuration: {LastErr}",
+ "message": "Could not import selected configuration: {LastErr}",
+ "translation": "تنظیمات انتخاب شده قابل واردکردن نیست: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
"id": "Imported tunnels",
"message": "Imported tunnels",
"translation": "تونل‌های وارد شده",
@@ -812,7 +1542,7 @@
{
"id": "Status: Waiting for updater service",
"message": "Status: Waiting for updater service",
- "translation": "وضعیت: درانتظار برای سرویس به‌روزرسانی",
+ "translation": "وضعیت: درانتظار برای سرویس به‌روزرسان",
"translatorComment": "Copied from source."
},
{
diff --git a/locales/fi/messages.gotext.json b/locales/fi/messages.gotext.json
index cca09e32..e0583a6c 100644
--- a/locales/fi/messages.gotext.json
+++ b/locales/fi/messages.gotext.json
@@ -8,6 +8,118 @@
"translatorComment": "Copied from source."
},
{
+ "id": "(no argument): elevate and install manager service",
+ "message": "(no argument): elevate and install manager service",
+ "translation": "(ei määrityksiä): suorita järjestelmäoikeuksilla ja asenna hallintapalvelu",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Usage: {Args0} [\n{String}]",
+ "message": "Usage: {Args0} [\n{String}]",
+ "translation": "Käyttö: {Args0} [\n{String}]",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Args0",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "os.Args[0]"
+ },
+ {
+ "id": "String",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "builder.String()"
+ }
+ ]
+ },
+ {
+ "id": "Command Line Options",
+ "message": "Command Line Options",
+ "translation": "Komentorivin valinnat",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to determine whether the process is running under WOW64: {Err}",
+ "message": "Unable to determine whether the process is running under WOW64: {Err}",
+ "translation": "Ei pystytä määrittämään mikäli prosessia suoritetaan WOW64-järjestelmän alaisuudessa: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "You must use the native version of WireGuard on this computer.",
+ "message": "You must use the native version of WireGuard on this computer.",
+ "translation": "Tällä tietokoneella voi käyttää vain WireGuardin natiivia versiota.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to open current process token: {Err}",
+ "message": "Unable to open current process token: {Err}",
+ "translation": "Ei voida avata tämänhetkisen prosessin tokenia: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard may only be used by users who are a member of the Builtin {AdminGroupName} group.",
+ "message": "WireGuard may only be used by users who are a member of the Builtin {AdminGroupName} group.",
+ "translation": "Ainoastaan sisäänrakennetun ryhmän {AdminGroupName} jäsenet voivat käyttää WireGuardia.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "AdminGroupName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "elevate.AdminGroupName()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard is running, but the UI is only accessible from desktops of the Builtin {AdminGroupName} group.",
+ "message": "WireGuard is running, but the UI is only accessible from desktops of the Builtin {AdminGroupName} group.",
+ "translation": "WireGuard on käynnissä, mutta käyttöliittymä on vain sisäänrakennetun ryhmän {AdminGroupName} käytettävissä.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "AdminGroupName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "elevate.AdminGroupName()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard system tray icon did not appear after 30 seconds.",
+ "message": "WireGuard system tray icon did not appear after 30 seconds.",
+ "translation": "WireGuardin ilmoitusalueen kuvake ei ilmestynyt 30 sekunnin jälkeen.",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Now",
"message": "Now",
"translation": "Nyt",
@@ -20,18 +132,448 @@
"translatorComment": "Copied from source."
},
{
+ "id": "{Years} year(s)",
+ "message": "{Years} year(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Years",
+ "cases": {
+ "one": {
+ "msg": "{Years} vuosi"
+ },
+ "other": {
+ "msg": "{Years} vuotta"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Years",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "years"
+ }
+ ]
+ },
+ {
+ "id": "{Days} day(s)",
+ "message": "{Days} day(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Days",
+ "cases": {
+ "one": {
+ "msg": "{Days} päivä"
+ },
+ "other": {
+ "msg": "{Days} päivää"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Days",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "days"
+ }
+ ]
+ },
+ {
+ "id": "{Hours} hour(s)",
+ "message": "{Hours} hour(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Hours",
+ "cases": {
+ "one": {
+ "msg": "{Hours} tunti"
+ },
+ "other": {
+ "msg": "{Hours} tuntia"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Hours",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "hours"
+ }
+ ]
+ },
+ {
+ "id": "{Minutes} minute(s)",
+ "message": "{Minutes} minute(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Minutes",
+ "cases": {
+ "one": {
+ "msg": "{Minutes} minuutti"
+ },
+ "other": {
+ "msg": "{Minutes} minuuttia"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Minutes",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "minutes"
+ }
+ ]
+ },
+ {
+ "id": "{Seconds} second(s)",
+ "message": "{Seconds} second(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Seconds",
+ "cases": {
+ "one": {
+ "msg": "{Seconds} sekunti"
+ },
+ "other": {
+ "msg": "{Seconds} sekuntia"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Seconds",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "seconds"
+ }
+ ]
+ },
+ {
+ "id": "{Timestamp} ago",
+ "message": "{Timestamp} ago",
+ "translation": "{Timestamp} sitten",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Timestamp",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "timestamp"
+ }
+ ]
+ },
+ {
+ "id": "{Bytes} B",
+ "message": "{Bytes} B",
+ "translation": "{Bytes} B",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Bytes",
+ "string": "%[1]d",
+ "type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
+ "underlyingType": "uint64",
+ "argNum": 1,
+ "expr": "b"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024} KiB",
+ "message": "{Float64b__1024} KiB",
+ "translation": "{Float64b__1024} KiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / 1024"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024} MiB",
+ "message": "{Float64b__1024__1024} MiB",
+ "translation": "{Float64b__1024__1024} MiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024} GiB",
+ "message": "{Float64b__1024__1024__1024} GiB",
+ "translation": "{Float64b__1024__1024__1024} GiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024__1024} TiB",
+ "message": "{Float64b__1024__1024__1024__1024} TiB",
+ "translation": "{Float64b__1024__1024__1024__1024} TiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024) / 1024"
+ }
+ ]
+ },
+ {
+ "id": "{Why}: {Offender}",
+ "message": "{Why}: {Offender}",
+ "translation": "{Why}: {Offender}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Why",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "e.why"
+ },
+ {
+ "id": "Offender",
+ "string": "%[2]q",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "e.offender"
+ }
+ ]
+ },
+ {
+ "id": "Invalid IP address",
+ "message": "Invalid IP address",
+ "translation": "Virheellinen IP-osoite",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid network prefix length",
+ "message": "Invalid network prefix length",
+ "translation": "Virheellinen verkon etuliitteen pituus",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Missing port from endpoint",
+ "message": "Missing port from endpoint",
+ "translation": "Päätepisteestä puuttuu porttinumero",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid endpoint host",
+ "message": "Invalid endpoint host",
+ "translation": "Virheellinen päätepisteen isäntäosoite",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Brackets must contain an IPv6 address",
+ "message": "Brackets must contain an IPv6 address",
+ "translation": "Sulkujen sisään pitää määritellä IPv6-osoite",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid MTU",
+ "message": "Invalid MTU",
+ "translation": "Virheellinen MTU",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid port",
+ "message": "Invalid port",
+ "translation": "Virheellinen portti",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Invalid persistent keepalive",
"message": "Invalid persistent keepalive",
"translation": "Virheellinen jatkuva keepalive",
"translatorComment": "Copied from source."
},
{
+ "id": "Invalid key: {Err}",
+ "message": "Invalid key: {Err}",
+ "translation": "Virheellinen avain: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Keys must decode to exactly 32 bytes",
+ "message": "Keys must decode to exactly 32 bytes",
+ "translation": "Avainten tulee olla tasan 32 tavua pitkiä",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Number must be a number between 0 and 2^64-1: {Err}",
+ "message": "Number must be a number between 0 and 2^64-1: {Err}",
+ "translation": "Luvun tulee olla väliltä 0 ja 2^64-1: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Two commas in a row",
+ "message": "Two commas in a row",
+ "translation": "Kaksi pilkkua peräkkäin",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel name is not valid",
+ "message": "Tunnel name is not valid",
+ "translation": "Tunnelin nimi ei kelpaa",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Line must occur in a section",
+ "message": "Line must occur in a section",
+ "translation": "Rivin pitää esiintyä osiossa",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Config key is missing an equals separator",
+ "message": "Config key is missing an equals separator",
+ "translation": "Määrittelyavaimesta puuttuu yhtäsuuruuserotin",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Key must have a value",
+ "message": "Key must have a value",
+ "translation": "Avaimella pitää olla arvo",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for [Interface] section",
+ "message": "Invalid key for [Interface] section",
+ "translation": "Virheellinen avain [Interface] -osiossa",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for [Peer] section",
+ "message": "Invalid key for [Peer] section",
+ "translation": "Virheellinen avain [Peer] -osiossa",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "An interface must have a private key",
+ "message": "An interface must have a private key",
+ "translation": "Liitännällä pitää olla yksityinen avain",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "[none specified]",
+ "message": "[none specified]",
+ "translation": "[ei määriteltynä]",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "All peers must have public keys",
+ "message": "All peers must have public keys",
+ "translation": "Kaikilla osapuolilla pitää olla julkinen avain",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error in getting configuration",
+ "message": "Error in getting configuration",
+ "translation": "Virhe luettaessa määritystä",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for interface section",
+ "message": "Invalid key for interface section",
+ "translation": "Virheellinen avain liitäntä-osiossa",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Protocol version must be 1",
+ "message": "Protocol version must be 1",
+ "translation": "Protokollan version pitää olla 1",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for peer section",
+ "message": "Invalid key for peer section",
+ "translation": "Virheellinen avain osapuoli-osiossa",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "[EnumerationSeparator]",
"message": "[EnumerationSeparator]",
"translation": ", ",
"comment": "Text to insert between items when listing - most western languages will translate ‘[EnumerationSeparator]’ into ‘, ’ to produce lists like ‘apple, orange, strawberry’. Eastern languages might translate into ‘、’ to produce lists like ‘リンゴ、オレンジ、イチゴ’."
},
{
+ "id": "[UnitSeparator]",
+ "message": "[UnitSeparator]",
+ "translation": ", ",
+ "comment": "Text to insert when combining units of a measure - most languages will translate ‘[UnitSeparator]’ into ‘ ’ (space) to produce lists like ‘2 minuti 30 sekund’, or empty string ‘’ to produce ‘2分30秒’."
+ },
+ {
"id": "About WireGuard",
"message": "About WireGuard",
"translation": "Tietoa WireGuardista",
@@ -44,6 +586,62 @@
"translatorComment": "Copied from source."
},
{
+ "id": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "message": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "translation": "Sovelluksen versio: {Number}\nGo taustajärjestelmän versio: {WireGuardGoVersion}\nGo versio: {Version_go}-{GOARCH}\nKäyttöjärjestelmä: {OsName}\nArkkitehtuuri: {NativeArch}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Number",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "version.Number"
+ },
+ {
+ "id": "WireGuardGoVersion",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "device.WireGuardGoVersion"
+ },
+ {
+ "id": "Version_go",
+ "string": "%[3]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 3,
+ "expr": "strings.TrimPrefix(runtime.Version(), \"go\")"
+ },
+ {
+ "id": "GOARCH",
+ "string": "%[4]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 4,
+ "expr": "runtime.GOARCH"
+ },
+ {
+ "id": "OsName",
+ "string": "%[5]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 5,
+ "expr": "version.OsName()"
+ },
+ {
+ "id": "NativeArch",
+ "string": "%[6]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 6,
+ "expr": "version.NativeArch()"
+ }
+ ]
+ },
+ {
"id": "Close",
"message": "Close",
"translation": "Sulje",
@@ -62,6 +660,30 @@
"translatorComment": "Copied from source."
},
{
+ "id": "&Deactivate",
+ "message": "&Deactivate",
+ "translation": "&Deaktivoi",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Activate",
+ "message": "&Activate",
+ "translation": "&Aktivoi",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Public key:",
+ "message": "Public key:",
+ "translation": "Julkinen avain:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Listen port:",
+ "message": "Listen port:",
+ "translation": "Kuuntele porttia:",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "MTU:",
"message": "MTU:",
"translation": "MTU:",
@@ -122,6 +744,100 @@
"translatorComment": "Copied from source."
},
{
+ "id": "pre-up",
+ "message": "pre-up",
+ "translation": "pre-up",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-up",
+ "message": "post-up",
+ "translation": "post-up",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-down",
+ "message": "pre-down",
+ "translation": "pre-down",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-down",
+ "message": "post-down",
+ "translation": "post-down",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "disabled, per policy",
+ "message": "disabled, per policy",
+ "translation": "pois käytöstä, käytännön perusteella",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "enabled",
+ "message": "enabled",
+ "translation": "käytössä",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{String} received, {String_1} sent",
+ "message": "{String} received, {String_1} sent",
+ "translation": "{String} vastaanotettu, {String_1} lähetetty",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "String",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "c.RxBytes.String()"
+ },
+ {
+ "id": "String_1",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "c.TxBytes.String()"
+ }
+ ]
+ },
+ {
+ "id": "Failed to determine tunnel state",
+ "message": "Failed to determine tunnel state",
+ "translation": "Tunnelin tilan määritys epäonnistui",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Failed to activate tunnel",
+ "message": "Failed to activate tunnel",
+ "translation": "Tunnelin aktivointi epäonnistui",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Failed to deactivate tunnel",
+ "message": "Failed to deactivate tunnel",
+ "translation": "Tunnelin deaktivointi epäonnistui",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Interface: {Name}",
+ "message": "Interface: {Name}",
+ "translation": "Liitäntä: {Name}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "config.Name"
+ }
+ ]
+ },
+ {
"id": "Peer",
"message": "Peer",
"translation": "Osapuoli",
@@ -164,12 +880,24 @@
"translatorComment": "Copied from source."
},
{
+ "id": "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 or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "message": "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 or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "translation": "Mikäli määriteltynä on tasan yksi toinen osapuoli ja kyseisen osapuolen sallituissa IP-osoitteessa on määritelty 0.0.0.0/0 ja/tai ::/0, tunnelipalvelu kytkee käyttöön palomuurin säännön joka estää kaiken liikenteen joka ei joko tule tai mene tunneliliitännän kautta tai se kohdistuu väärään DNS-palvelimeen. Erikoispoikkeuksena tästä on DHCP ja NDP liikenne.",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "&Save",
"message": "&Save",
"translation": "&Tallenna",
"translatorComment": "Copied from source."
},
{
+ "id": "Cancel",
+ "message": "Cancel",
+ "translation": "Peruuta",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "&Configuration:",
"message": "&Configuration:",
"translation": "&Konfiguraatio:",
@@ -188,12 +916,108 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Tunnel name ‘{NewName}’ is invalid.",
+ "message": "Tunnel name ‘{NewName}’ is invalid.",
+ "translation": "Tunnelin nimi ‘{NewName}’ on virheellinen.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "NewName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "newName"
+ }
+ ]
+ },
+ {
+ "id": "Unable to list existing tunnels",
+ "message": "Unable to list existing tunnels",
+ "translation": "Olemassaolevia tunneleita ei voitu listata",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Tunnel already exists",
"message": "Tunnel already exists",
"translation": "Tunneli on jo olemassa",
"translatorComment": "Copied from source."
},
{
+ "id": "Another tunnel already exists with the name ‘{NewName}’.",
+ "message": "Another tunnel already exists with the name ‘{NewName}’.",
+ "translation": "Nimellä ‘{NewName}’ on jo olemassa tunneli.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "NewName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "newName"
+ }
+ ]
+ },
+ {
+ "id": "Unable to create new configuration",
+ "message": "Unable to create new configuration",
+ "translation": "Uutta määritystä ei voida luoda",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Writing file failed",
+ "message": "Writing file failed",
+ "translation": "Tiedoston kirjoitus epäonnistui",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "File ‘{FilePath}’ already exists.\n\nDo you want to overwrite it?",
+ "message": "File ‘{FilePath}’ already exists.\n\nDo you want to overwrite it?",
+ "translation": "Tiedosto ‘{FilePath}’ on jo olemassa.\n\nHaluatko korvata sen?",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "FilePath",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "filePath"
+ }
+ ]
+ },
+ {
+ "id": "Active",
+ "message": "Active",
+ "translation": "Aktiivinen",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Activating",
+ "message": "Activating",
+ "translation": "Aktivoidaan",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Inactive",
+ "message": "Inactive",
+ "translation": "Epäaktiivinen",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Deactivating",
+ "message": "Deactivating",
+ "translation": "Deaktivoidaan",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unknown state",
+ "message": "Unknown state",
+ "translation": "Tuntematon tila",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Log",
"message": "Log",
"translation": "Loki",
@@ -206,6 +1030,248 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Select &all",
+ "message": "Select &all",
+ "translation": "Valitse k&aikki",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Save to file…",
+ "message": "&Save to file…",
+ "translation": "&Tallenna tiedostoon…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Time",
+ "message": "Time",
+ "translation": "Aika",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Log message",
+ "message": "Log message",
+ "translation": "Lokiviesti",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "message": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "translation": "Tekstitiedostot (*.txt)|*.txt|Kaikki tiedostot (*.*)|*.*",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export log to file",
+ "message": "Export log to file",
+ "translation": "Vie loki tiedostoon",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&About WireGuard…",
+ "message": "&About WireGuard…",
+ "translation": "Tietoja WireGu&ardista…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel Error",
+ "message": "Tunnel Error",
+ "translation": "Tunnelivirhe",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "message": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "translation": "{ErrMsg}\n\nLue lisää lokista saadaksesi lisätietoja.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "ErrMsg",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errMsg"
+ }
+ ]
+ },
+ {
+ "id": "{Title} (out of date)",
+ "message": "{Title} (out of date)",
+ "translation": "{Title} (ei ajantasalla)",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Title",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "mtw.Title()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Detection Error",
+ "message": "WireGuard Detection Error",
+ "translation": "WireGuardin tunnistusvirhe",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to wait for WireGuard window to appear: {Err}",
+ "message": "Unable to wait for WireGuard window to appear: {Err}",
+ "translation": "Ei voida odottaa WireGuardin ikkunan ilmestymistä: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard: Deactivated",
+ "message": "WireGuard: Deactivated",
+ "translation": "WireGuard: deaktivoitu",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Unknown",
+ "message": "Status: Unknown",
+ "translation": "Tila: tuntematon",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Addresses: None",
+ "message": "Addresses: None",
+ "translation": "Osoitteet: ei mitään",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Manage tunnels…",
+ "message": "&Manage tunnels…",
+ "translation": "&Hallitse tunneleita…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Import tunnel(s) from file…",
+ "message": "&Import tunnel(s) from file…",
+ "translation": "Tuo tunnele&ita tiedostosta…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "E&xit",
+ "message": "E&xit",
+ "translation": "Lo&peta",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Tunnels",
+ "message": "&Tunnels",
+ "translation": "&Tunnelit",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Activated",
+ "message": "WireGuard Activated",
+ "translation": "WireGuard aktivoitu",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "The {Name} tunnel has been activated.",
+ "message": "The {Name} tunnel has been activated.",
+ "translation": "Tunneli {Name} on aktivoitu.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnel.Name"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Deactivated",
+ "message": "WireGuard Deactivated",
+ "translation": "WireGuard deaktivoitu",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "The {Name} tunnel has been deactivated.",
+ "message": "The {Name} tunnel has been deactivated.",
+ "translation": "Tunneli {Name} on deaktivoitu.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnel.Name"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Tunnel Error",
+ "message": "WireGuard Tunnel Error",
+ "translation": "WireGuard tunnelivirhe",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard: {TextForStateglobalState_true}",
+ "message": "WireGuard: {TextForStateglobalState_true}",
+ "translation": "WireGuard: {TextForStateglobalState_true}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TextForStateglobalState_true",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "textForState(globalState, true)"
+ }
+ ]
+ },
+ {
+ "id": "Status: {StateText}",
+ "message": "Status: {StateText}",
+ "translation": "Tila: {StateText}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "StateText",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "stateText"
+ }
+ ]
+ },
+ {
+ "id": "Addresses: {EnumerationSeparator}",
+ "message": "Addresses: {EnumerationSeparator}",
+ "translation": "Osoitteet: {EnumerationSeparator}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "EnumerationSeparator",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "strings.Join(addrs, l18n.EnumerationSeparator())"
+ }
+ ]
+ },
+ {
"id": "An Update is Available!",
"message": "An Update is Available!",
"translation": "Päivitys on saatavilla!",
@@ -236,6 +1302,124 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Add &empty tunnel…",
+ "message": "Add &empty tunnel…",
+ "translation": "Lisää tyhjä tunn&eli…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Add Tunnel",
+ "message": "Add Tunnel",
+ "translation": "Lisää tunneli",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Remove selected tunnel(s)",
+ "message": "Remove selected tunnel(s)",
+ "translation": "Poista valitut tunneli(t)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export all tunnels to zip",
+ "message": "Export all tunnels to zip",
+ "translation": "Vie kaikki tunnelit zip-tiedostoon",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Toggle",
+ "message": "&Toggle",
+ "translation": "Vaihda &tila",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export all tunnels to &zip…",
+ "message": "Export all tunnels to &zip…",
+ "translation": "Vie kaikki tunnelit &zip-tiedostoon…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Edit &selected tunnel…",
+ "message": "Edit &selected tunnel…",
+ "translation": "Muokkaa &valittua tunnelia…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Remove selected tunnel(s)",
+ "message": "&Remove selected tunnel(s)",
+ "translation": "&Poista valitut tunnelit",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "no configuration files were found",
+ "message": "no configuration files were found",
+ "translation": "määritystiedostoa ei löytynyt",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Could not import selected configuration: {LastErr}",
+ "message": "Could not import selected configuration: {LastErr}",
+ "translation": "Valittua määritystiedostoa ei voitu tuoda: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Could not enumerate existing tunnels: {LastErr}",
+ "message": "Could not enumerate existing tunnels: {LastErr}",
+ "translation": "Olemassaolevia tunneleita ei voitu luetella: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Another tunnel already exists with the name ‘{Name}’",
+ "message": "Another tunnel already exists with the name ‘{Name}’",
+ "translation": "Nimellä ‘{Name}’ on jo olemassaoleva tunneli",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "unparsedConfig.Name"
+ }
+ ]
+ },
+ {
+ "id": "Unable to import configuration: {LastErr}",
+ "message": "Unable to import configuration: {LastErr}",
+ "translation": "Ei voitu tuoda määritystiedostoa: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
"id": "Imported tunnels",
"message": "Imported tunnels",
"translation": "Tuodut tunnelit",
@@ -270,6 +1454,174 @@
]
},
{
+ "id": "Imported {M} of {N} tunnels",
+ "message": "Imported {M} of {N} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "N",
+ "cases": {
+ "one": {
+ "msg": "Tuotiin {M} / {N} tunnelia"
+ },
+ "other": {
+ "msg": "Tuotiin {M} / {N} tunnelia"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ },
+ {
+ "id": "N",
+ "string": "%[2]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 2,
+ "expr": "n"
+ }
+ ]
+ },
+ {
+ "id": "Unable to create tunnel",
+ "message": "Unable to create tunnel",
+ "translation": "Tunnelia ei voitu luoda",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Delete {TunnelCount} tunnels",
+ "message": "Delete {TunnelCount} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "TunnelCount",
+ "cases": {
+ "one": {
+ "msg": "Poista {TunnelCount} tunneli"
+ },
+ "other": {
+ "msg": "Poista {TunnelCount} tunnelia"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "TunnelCount",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "tunnelCount"
+ }
+ ]
+ },
+ {
+ "id": "Are you sure you would like to delete {TunnelCount} tunnels?",
+ "message": "Are you sure you would like to delete {TunnelCount} tunnels?",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "TunnelCount",
+ "cases": {
+ "one": {
+ "msg": "Oletko varma että haluat poistaa {TunnelCount} tunnelin?"
+ },
+ "other": {
+ "msg": "Oletko varma että haluat poistaa {TunnelCount} tunnelia?"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "TunnelCount",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "tunnelCount"
+ }
+ ]
+ },
+ {
+ "id": "Delete tunnel ‘{TunnelName}’",
+ "message": "Delete tunnel ‘{TunnelName}’",
+ "translation": "Poista tunneli ‘{TunnelName}’",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TunnelName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnelName"
+ }
+ ]
+ },
+ {
+ "id": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
+ "message": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
+ "translation": "Oletko varma että haluat poistaa tunnelin ‘{TunnelName}’?",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TunnelName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnelName"
+ }
+ ]
+ },
+ {
+ "id": "{Question} You cannot undo this action.",
+ "message": "{Question} You cannot undo this action.",
+ "translation": "{Question} Tätä toimintoa ei voi peruuttaa.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Question",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "question"
+ }
+ ]
+ },
+ {
+ "id": "Unable to delete tunnel",
+ "message": "Unable to delete tunnel",
+ "translation": "Tunnelia ei voitu poistaa",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "A tunnel was unable to be removed: {Error}",
+ "message": "A tunnel was unable to be removed: {Error}",
+ "translation": "Tunnelia ei voitu poistaa: {Error}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Error",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errors[0].Error()"
+ }
+ ]
+ },
+ {
"id": "Unable to delete tunnels",
"message": "Unable to delete tunnels",
"translation": "Tunnelia ei voitu poistaa",
@@ -282,6 +1634,18 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Export tunnels to zip",
+ "message": "Export tunnels to zip",
+ "translation": "Vie tunnelit zip-tiedostoon",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error Exiting WireGuard",
+ "message": "Error Exiting WireGuard",
+ "translation": "Virhe WireGuardista poistuttaessa",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Status: Waiting for user",
"message": "Status: Waiting for user",
"translation": "Tila: Odotetaan käyttäjää",
diff --git a/locales/id/messages.gotext.json b/locales/id/messages.gotext.json
index 07fad080..c124906b 100644
--- a/locales/id/messages.gotext.json
+++ b/locales/id/messages.gotext.json
@@ -60,6 +60,12 @@
]
},
{
+ "id": "You must use the native version of WireGuard on this computer.",
+ "message": "You must use the native version of WireGuard on this computer.",
+ "translation": "Anda harus menggunakan WireGuard versi asli pada komputer ini.",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Unable to open current process token: {Err}",
"message": "Unable to open current process token: {Err}",
"translation": "Tidak dapat membuka token proses saat ini: {Err}",
@@ -475,6 +481,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Config key is missing an equals separator",
+ "message": "Config key is missing an equals separator",
+ "translation": "Kunci konfigurasi tidak valid, tidak memiliki pemisah dan sama dengan",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Key must have a value",
"message": "Key must have a value",
"translation": "Kunci harus memiliki value",
@@ -541,12 +553,80 @@
"comment": "Text to insert between items when listing - most western languages will translate ‘[EnumerationSeparator]’ into ‘, ’ to produce lists like ‘apple, orange, strawberry’. Eastern languages might translate into ‘、’ to produce lists like ‘リンゴ、オレンジ、イチゴ’."
},
{
+ "id": "[UnitSeparator]",
+ "message": "[UnitSeparator]",
+ "translation": ", ",
+ "comment": "Text to insert when combining units of a measure - most languages will translate ‘[UnitSeparator]’ into ‘ ’ (space) to produce lists like ‘2 minuti 30 sekund’, or empty string ‘’ to produce ‘2分30秒’."
+ },
+ {
"id": "About WireGuard",
"message": "About WireGuard",
"translation": "Tentang WireGuard",
"translatorComment": "Copied from source."
},
{
+ "id": "WireGuard logo image",
+ "message": "WireGuard logo image",
+ "translation": "Gambar logo WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "message": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "translation": "Versi Aplikasi: {Number}\nVersi back-end Go: {WireGuardGoVersion}\nVersi Go: {Version_go}--{GOARCH}\nSistem Operasi: {OsName}\nArsitektur: {NativeArch}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Number",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "version.Number"
+ },
+ {
+ "id": "WireGuardGoVersion",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "device.WireGuardGoVersion"
+ },
+ {
+ "id": "Version_go",
+ "string": "%[3]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 3,
+ "expr": "strings.TrimPrefix(runtime.Version(), \"go\")"
+ },
+ {
+ "id": "GOARCH",
+ "string": "%[4]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 4,
+ "expr": "runtime.GOARCH"
+ },
+ {
+ "id": "OsName",
+ "string": "%[5]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 5,
+ "expr": "version.OsName()"
+ },
+ {
+ "id": "NativeArch",
+ "string": "%[6]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 6,
+ "expr": "version.NativeArch()"
+ }
+ ]
+ },
+ {
"id": "Close",
"message": "Close",
"translation": "Tutup",
@@ -565,6 +645,72 @@
"translatorComment": "Copied from source."
},
{
+ "id": "&Deactivate",
+ "message": "&Deactivate",
+ "translation": "&Nonaktifkan",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Activate",
+ "message": "&Activate",
+ "translation": "&Aktifkan",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Public key:",
+ "message": "Public key:",
+ "translation": "Kunci publik:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Listen port:",
+ "message": "Listen port:",
+ "translation": "Port Pendengar:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "MTU:",
+ "message": "MTU:",
+ "translation": "MTU:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Addresses:",
+ "message": "Addresses:",
+ "translation": "Alamat:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "DNS servers:",
+ "message": "DNS servers:",
+ "translation": "Server DNS:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Scripts:",
+ "message": "Scripts:",
+ "translation": "Skrip:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Preshared key:",
+ "message": "Preshared key:",
+ "translation": "Preshared key:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Allowed IPs:",
+ "message": "Allowed IPs:",
+ "translation": "IP yang diperbolehkan:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Endpoint:",
+ "message": "Endpoint:",
+ "translation": "Endpoint:",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Active",
"message": "Active",
"translation": "Aktif",
diff --git a/locales/it/messages.gotext.json b/locales/it/messages.gotext.json
index f1626e8b..5bea90c2 100644
--- a/locales/it/messages.gotext.json
+++ b/locales/it/messages.gotext.json
@@ -60,6 +60,12 @@
]
},
{
+ "id": "You must use the native version of WireGuard on this computer.",
+ "message": "You must use the native version of WireGuard on this computer.",
+ "translation": "Devi utilizzare la versione nativa di WireGuard su questo computer.",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Unable to open current process token: {Err}",
"message": "Unable to open current process token: {Err}",
"translation": "Impossibile aprire il token del processo corrente: {Err}",
@@ -490,6 +496,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Config key is missing an equals separator",
+ "message": "Config key is missing an equals separator",
+ "translation": "Manca un separatore di uguaglianza per la chiave di configurazione",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Key must have a value",
"message": "Key must have a value",
"translation": "La chiave deve avere un valore",
@@ -574,6 +586,62 @@
"translatorComment": "Copied from source."
},
{
+ "id": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "message": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "translation": "Versione applicazione: {Number}\nVersione backend Go: {WireGuardGoVersion}\nVersione Go: {Version_go}-{GOARCH}\nSistema operativo: {OsName}\nArchitettura: {NativeArch}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Number",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "version.Number"
+ },
+ {
+ "id": "WireGuardGoVersion",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "device.WireGuardGoVersion"
+ },
+ {
+ "id": "Version_go",
+ "string": "%[3]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 3,
+ "expr": "strings.TrimPrefix(runtime.Version(), \"go\")"
+ },
+ {
+ "id": "GOARCH",
+ "string": "%[4]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 4,
+ "expr": "runtime.GOARCH"
+ },
+ {
+ "id": "OsName",
+ "string": "%[5]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 5,
+ "expr": "version.OsName()"
+ },
+ {
+ "id": "NativeArch",
+ "string": "%[6]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 6,
+ "expr": "version.NativeArch()"
+ }
+ ]
+ },
+ {
"id": "Close",
"message": "Close",
"translation": "Chiudi",
@@ -634,6 +702,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Scripts:",
+ "message": "Scripts:",
+ "translation": "Script:",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Preshared key:",
"message": "Preshared key:",
"translation": "Chiave pre-condivisa:",
@@ -670,6 +744,36 @@
"translatorComment": "Copied from source."
},
{
+ "id": "pre-up",
+ "message": "pre-up",
+ "translation": "pre-up",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-up",
+ "message": "post-up",
+ "translation": "post-up",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-down",
+ "message": "pre-down",
+ "translation": "pre-down",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-down",
+ "message": "post-down",
+ "translation": "post-down",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "disabled, per policy",
+ "message": "disabled, per policy",
+ "translation": "disattivato, per criterio",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "enabled",
"message": "enabled",
"translation": "abilitato",
@@ -776,6 +880,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "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 or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "message": "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 or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "translation": "Quando una configurazione ha esattamente un peer e quel peer ha un IP consentito contenente almeno uno tra 0.0.0.0/0 o ::/0, il servizio tunnel impiega un insieme di regole del firewall per bloccare tutto il traffico nè diretto nè proveniente dall'interfaccia tunnel o verso un server DNS sbagliato, con speciali eccezioni per DHCP e NDP.",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "&Save",
"message": "&Save",
"translation": "&Salva",
@@ -1058,6 +1168,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "&Tunnels",
+ "message": "&Tunnels",
+ "translation": "&Tunnel",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "WireGuard Activated",
"message": "WireGuard Activated",
"translation": "WireGuard attivato",
@@ -1140,6 +1256,22 @@
]
},
{
+ "id": "Addresses: {EnumerationSeparator}",
+ "message": "Addresses: {EnumerationSeparator}",
+ "translation": "Indirizzi: {EnumerationSeparator}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "EnumerationSeparator",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "strings.Join(addrs, l18n.EnumerationSeparator())"
+ }
+ ]
+ },
+ {
"id": "An Update is Available!",
"message": "An Update is Available!",
"translation": "Un aggiornamento è disponibile!",
@@ -1172,7 +1304,7 @@
{
"id": "Add &empty tunnel…",
"message": "Add &empty tunnel…",
- "translation": "Aggiungi tunn&el vuoto",
+ "translation": "Aggiungi tunn&el vuoto...",
"translatorComment": "Copied from source."
},
{
@@ -1202,7 +1334,7 @@
{
"id": "Export all tunnels to &zip…",
"message": "Export all tunnels to &zip…",
- "translation": "Esporta tutti i tunnel in &zip",
+ "translation": "Esporta tutti i tunnel in &zip...",
"translatorComment": "Copied from source."
},
{
@@ -1218,6 +1350,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "no configuration files were found",
+ "message": "no configuration files were found",
+ "translation": "nessun file di configurazione trovato",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Could not import selected configuration: {LastErr}",
"message": "Could not import selected configuration: {LastErr}",
"translation": "Impossibile importare la configurazione selezionata: {LastErr}",
diff --git a/locales/ja/messages.gotext.json b/locales/ja/messages.gotext.json
index 61751200..1666f408 100644
--- a/locales/ja/messages.gotext.json
+++ b/locales/ja/messages.gotext.json
@@ -60,6 +60,12 @@
]
},
{
+ "id": "You must use the native version of WireGuard on this computer.",
+ "message": "You must use the native version of WireGuard on this computer.",
+ "translation": "このコンピュータではネイティブ版の WireGuard を使ってください。",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Unable to open current process token: {Err}",
"message": "Unable to open current process token: {Err}",
"translation": "現在のプロセスのトークンを開けません: {Err}",
@@ -565,6 +571,62 @@
"translatorComment": "Copied from source."
},
{
+ "id": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "message": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "translation": "アプリ バージョン: {Number}\nGo バックエンド バージョン: {WireGuardGoVersion}\nGo バージョン: {Version_go}-{GOARCH}\nOS: {OsName}\nアーキテクチャ: {NativeArch}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Number",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "version.Number"
+ },
+ {
+ "id": "WireGuardGoVersion",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "device.WireGuardGoVersion"
+ },
+ {
+ "id": "Version_go",
+ "string": "%[3]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 3,
+ "expr": "strings.TrimPrefix(runtime.Version(), \"go\")"
+ },
+ {
+ "id": "GOARCH",
+ "string": "%[4]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 4,
+ "expr": "runtime.GOARCH"
+ },
+ {
+ "id": "OsName",
+ "string": "%[5]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 5,
+ "expr": "version.OsName()"
+ },
+ {
+ "id": "NativeArch",
+ "string": "%[6]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 6,
+ "expr": "version.NativeArch()"
+ }
+ ]
+ },
+ {
"id": "Close",
"message": "Close",
"translation": "閉じる",
@@ -625,6 +687,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Scripts:",
+ "message": "Scripts:",
+ "translation": "スクリプト:",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Preshared key:",
"message": "Preshared key:",
"translation": "事前共有鍵:",
@@ -661,6 +729,36 @@
"translatorComment": "Copied from source."
},
{
+ "id": "pre-up",
+ "message": "pre-up",
+ "translation": "pre-up",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-up",
+ "message": "post-up",
+ "translation": "post-up",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-down",
+ "message": "pre-down",
+ "translation": "pre-down",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-down",
+ "message": "post-down",
+ "translation": "post-down",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "disabled, per policy",
+ "message": "disabled, per policy",
+ "translation": "ポリシーにより無効です",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "enabled",
"message": "enabled",
"translation": "有効",
@@ -767,6 +865,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "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 or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "message": "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 or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "translation": "ピアが1つだけ設定されており、かつAllowed IPs に 0.0.0.0/0 や ::/0 が含まれている場合、トンネルサービスはトンネルインターフェイスを通らないトラフィックや間違った DNS サーバーに向かう通信をブロックするファイアウォールルールを追加します。\nDHCP と NDP には特別な例外があります。",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "&Save",
"message": "&Save",
"translation": "保存(&S)",
@@ -1049,6 +1153,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "&Tunnels",
+ "message": "&Tunnels",
+ "translation": "トンネル(&T)",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "WireGuard Activated",
"message": "WireGuard Activated",
"translation": "WireGuard 有効化済み",
@@ -1131,6 +1241,22 @@
]
},
{
+ "id": "Addresses: {EnumerationSeparator}",
+ "message": "Addresses: {EnumerationSeparator}",
+ "translation": "アドレス: {EnumerationSeparator}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "EnumerationSeparator",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "strings.Join(addrs, l18n.EnumerationSeparator())"
+ }
+ ]
+ },
+ {
"id": "An Update is Available!",
"message": "An Update is Available!",
"translation": "更新が利用できます!",
@@ -1209,6 +1335,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "no configuration files were found",
+ "message": "no configuration files were found",
+ "translation": "設定ファイルが見つかりません",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Could not import selected configuration: {LastErr}",
"message": "Could not import selected configuration: {LastErr}",
"translation": "選択したファイルからインポートできませんでした: {LastErr}",
diff --git a/locales/ko/messages.gotext.json b/locales/ko/messages.gotext.json
new file mode 100644
index 00000000..21c9af78
--- /dev/null
+++ b/locales/ko/messages.gotext.json
@@ -0,0 +1,1817 @@
+{
+ "language": "ko",
+ "messages": [
+ {
+ "id": "Error",
+ "message": "Error",
+ "translation": "오류",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "(no argument): elevate and install manager service",
+ "message": "(no argument): elevate and install manager service",
+ "translation": "(인수 없음): 관리자 서비스 상승 및 설치",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Usage: {Args0} [\n{String}]",
+ "message": "Usage: {Args0} [\n{String}]",
+ "translation": "사용: {Args0} [\n{String}]",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Args0",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "os.Args[0]"
+ },
+ {
+ "id": "String",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "builder.String()"
+ }
+ ]
+ },
+ {
+ "id": "Command Line Options",
+ "message": "Command Line Options",
+ "translation": "커맨드 라인 옵션",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to determine whether the process is running under WOW64: {Err}",
+ "message": "Unable to determine whether the process is running under WOW64: {Err}",
+ "translation": "WOW64에서 프로세스가 실행 중인지 확인할 수 없음: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "You must use the native version of WireGuard on this computer.",
+ "message": "You must use the native version of WireGuard on this computer.",
+ "translation": "이 컴퓨터에서는 기본 버전의 WireGuard를 사용해야 합니다.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to open current process token: {Err}",
+ "message": "Unable to open current process token: {Err}",
+ "translation": "현재 프로세스 토큰을 열 수 없음: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard may only be used by users who are a member of the Builtin {AdminGroupName} group.",
+ "message": "WireGuard may only be used by users who are a member of the Builtin {AdminGroupName} group.",
+ "translation": "WireGuard는 Builtin {AdminGroupName} 그룹의 구성원인 사용자만 사용할 수 있습니다.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "AdminGroupName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "elevate.AdminGroupName()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard is running, but the UI is only accessible from desktops of the Builtin {AdminGroupName} group.",
+ "message": "WireGuard is running, but the UI is only accessible from desktops of the Builtin {AdminGroupName} group.",
+ "translation": "WireGuard가 실행 중이나 UI는 Builtin의 데스크톱에서만 액세스할 수 있습니다{AdminGroupName} 그룹.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "AdminGroupName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "elevate.AdminGroupName()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard system tray icon did not appear after 30 seconds.",
+ "message": "WireGuard system tray icon did not appear after 30 seconds.",
+ "translation": "WireGuard 시스템 트레이 아이콘이 30초 후에 나타나지 않았습니다.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Now",
+ "message": "Now",
+ "translation": "지금",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "System clock wound backward!",
+ "message": "System clock wound backward!",
+ "translation": "시스템 시간이 되돌려짐!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Years} year(s)",
+ "message": "{Years} year(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Years",
+ "cases": {
+ "other": {
+ "msg": "{Years} 년"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Years",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "years"
+ }
+ ]
+ },
+ {
+ "id": "{Days} day(s)",
+ "message": "{Days} day(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Days",
+ "cases": {
+ "other": {
+ "msg": "{Days} 일"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Days",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "days"
+ }
+ ]
+ },
+ {
+ "id": "{Hours} hour(s)",
+ "message": "{Hours} hour(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Hours",
+ "cases": {
+ "other": {
+ "msg": "{Hours} 시간"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Hours",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "hours"
+ }
+ ]
+ },
+ {
+ "id": "{Minutes} minute(s)",
+ "message": "{Minutes} minute(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Minutes",
+ "cases": {
+ "other": {
+ "msg": "{Minutes} 분"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Minutes",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "minutes"
+ }
+ ]
+ },
+ {
+ "id": "{Seconds} second(s)",
+ "message": "{Seconds} second(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Seconds",
+ "cases": {
+ "other": {
+ "msg": "{Seconds} 초"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Seconds",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "seconds"
+ }
+ ]
+ },
+ {
+ "id": "{Timestamp} ago",
+ "message": "{Timestamp} ago",
+ "translation": "{Timestamp} 전에",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Timestamp",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "timestamp"
+ }
+ ]
+ },
+ {
+ "id": "{Bytes} B",
+ "message": "{Bytes} B",
+ "translation": "{Bytes} 바이트",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Bytes",
+ "string": "%[1]d",
+ "type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
+ "underlyingType": "uint64",
+ "argNum": 1,
+ "expr": "b"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024} KiB",
+ "message": "{Float64b__1024} KiB",
+ "translation": "{Float64b__1024} KiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / 1024"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024} MiB",
+ "message": "{Float64b__1024__1024} MiB",
+ "translation": "{Float64b__1024__1024} MiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024} GiB",
+ "message": "{Float64b__1024__1024__1024} GiB",
+ "translation": "{Float64b__1024__1024__1024} GiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024__1024} TiB",
+ "message": "{Float64b__1024__1024__1024__1024} TiB",
+ "translation": "{Float64b__1024__1024__1024__1024} TiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024) / 1024"
+ }
+ ]
+ },
+ {
+ "id": "{Why}: {Offender}",
+ "message": "{Why}: {Offender}",
+ "translation": "{Why}: {Offender}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Why",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "e.why"
+ },
+ {
+ "id": "Offender",
+ "string": "%[2]q",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "e.offender"
+ }
+ ]
+ },
+ {
+ "id": "Invalid IP address",
+ "message": "Invalid IP address",
+ "translation": "잘못된 IP 주소",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid network prefix length",
+ "message": "Invalid network prefix length",
+ "translation": "잘못된 네트워크 접두사 길이",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Missing port from endpoint",
+ "message": "Missing port from endpoint",
+ "translation": "엔드포인트에서 포트가 누락됨",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid endpoint host",
+ "message": "Invalid endpoint host",
+ "translation": "잘못된 엔드포인트 호스트",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Brackets must contain an IPv6 address",
+ "message": "Brackets must contain an IPv6 address",
+ "translation": "대괄호에는 IPv6 주소가 포함되어야 합니다",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid MTU",
+ "message": "Invalid MTU",
+ "translation": "잘못된 MTU",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid port",
+ "message": "Invalid port",
+ "translation": "잘못된 포트",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid persistent keepalive",
+ "message": "Invalid persistent keepalive",
+ "translation": "잘못된 영구 연결 유지",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key: {Err}",
+ "message": "Invalid key: {Err}",
+ "translation": "유효하지 않은 키: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Keys must decode to exactly 32 bytes",
+ "message": "Keys must decode to exactly 32 bytes",
+ "translation": "키는 정확히 32바이트로 디코딩이 필요",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Number must be a number between 0 and 2^64-1: {Err}",
+ "message": "Number must be a number between 0 and 2^64-1: {Err}",
+ "translation": "숫자는 다음 사이의 숫자여야 합니다 0 그리고 2^64-1: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Two commas in a row",
+ "message": "Two commas in a row",
+ "translation": "엔드포인트에서 포트가 누락됨",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel name is not valid",
+ "message": "Tunnel name is not valid",
+ "translation": "터널 이름이 유효하지 않음",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Line must occur in a section",
+ "message": "Line must occur in a section",
+ "translation": "행은 섹션에 있어야 함",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Config key is missing an equals separator",
+ "message": "Config key is missing an equals separator",
+ "translation": "구성 키에 등호 구분 기호가 없음",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Key must have a value",
+ "message": "Key must have a value",
+ "translation": "키에는 값이 있어야 합니다",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for [Interface] section",
+ "message": "Invalid key for [Interface] section",
+ "translation": "[Interface] 구간에 대한 잘못된 키",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for [Peer] section",
+ "message": "Invalid key for [Peer] section",
+ "translation": "[Peer] 구간에 대한 잘못된 키",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "An interface must have a private key",
+ "message": "An interface must have a private key",
+ "translation": "인터페이스에는 개인 키가 있어야 함",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "[none specified]",
+ "message": "[none specified]",
+ "translation": "[특정되지 않음]",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "All peers must have public keys",
+ "message": "All peers must have public keys",
+ "translation": "모든 피어에는 공개 키가 있어야 함",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error in getting configuration",
+ "message": "Error in getting configuration",
+ "translation": "구성을 가져오는 중 오류가 발생",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for interface section",
+ "message": "Invalid key for interface section",
+ "translation": "인터페이스 섹션의 키가 잘못됨",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Protocol version must be 1",
+ "message": "Protocol version must be 1",
+ "translation": "프로토콜 버전은 1이어야 합니다.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for peer section",
+ "message": "Invalid key for peer section",
+ "translation": "피어 섹션의 키가 잘못됨",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "[EnumerationSeparator]",
+ "message": "[EnumerationSeparator]",
+ "translation": ", ",
+ "comment": "Text to insert between items when listing - most western languages will translate ‘[EnumerationSeparator]’ into ‘, ’ to produce lists like ‘apple, orange, strawberry’. Eastern languages might translate into ‘、’ to produce lists like ‘リンゴ、オレンジ、イチゴ’."
+ },
+ {
+ "id": "[UnitSeparator]",
+ "message": "[UnitSeparator]",
+ "translation": ", ",
+ "comment": "Text to insert when combining units of a measure - most languages will translate ‘[UnitSeparator]’ into ‘ ’ (space) to produce lists like ‘2 minuti 30 sekund’, or empty string ‘’ to produce ‘2分30秒’."
+ },
+ {
+ "id": "About WireGuard",
+ "message": "About WireGuard",
+ "translation": "WireGuard에 관하여",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard logo image",
+ "message": "WireGuard logo image",
+ "translation": "WireGuard 로고 이미지",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "message": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "translation": "앱 버전: {Number}\nGo 백엔드 버전: {WireGuardGoVersion}\nGo 버전: {Version_go}-{GOARCH}\n운영체제: {OsName}\n아키텍처: {NativeArch}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Number",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "version.Number"
+ },
+ {
+ "id": "WireGuardGoVersion",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "device.WireGuardGoVersion"
+ },
+ {
+ "id": "Version_go",
+ "string": "%[3]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 3,
+ "expr": "strings.TrimPrefix(runtime.Version(), \"go\")"
+ },
+ {
+ "id": "GOARCH",
+ "string": "%[4]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 4,
+ "expr": "runtime.GOARCH"
+ },
+ {
+ "id": "OsName",
+ "string": "%[5]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 5,
+ "expr": "version.OsName()"
+ },
+ {
+ "id": "NativeArch",
+ "string": "%[6]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 6,
+ "expr": "version.NativeArch()"
+ }
+ ]
+ },
+ {
+ "id": "Close",
+ "message": "Close",
+ "translation": "닫기",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "♥ &Donate!",
+ "message": "♥ &Donate!",
+ "translation": "♥ &기부하기!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status:",
+ "message": "Status:",
+ "translation": "상태:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Deactivate",
+ "message": "&Deactivate",
+ "translation": "&비활성화하기",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Activate",
+ "message": "&Activate",
+ "translation": "&활성화하기",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Public key:",
+ "message": "Public key:",
+ "translation": "공개 키:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Listen port:",
+ "message": "Listen port:",
+ "translation": "수신 포트:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "MTU:",
+ "message": "MTU:",
+ "translation": "MTU:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Addresses:",
+ "message": "Addresses:",
+ "translation": "주소:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "DNS servers:",
+ "message": "DNS servers:",
+ "translation": "DNS 서버:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Scripts:",
+ "message": "Scripts:",
+ "translation": "스크립트:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Preshared key:",
+ "message": "Preshared key:",
+ "translation": "사전 공유 키:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Allowed IPs:",
+ "message": "Allowed IPs:",
+ "translation": "허용된 IP:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Endpoint:",
+ "message": "Endpoint:",
+ "translation": "엔드포인트:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Persistent keepalive:",
+ "message": "Persistent keepalive:",
+ "translation": "지속적 연결 유지:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Latest handshake:",
+ "message": "Latest handshake:",
+ "translation": "마지막 정보교환:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Transfer:",
+ "message": "Transfer:",
+ "translation": "전송:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-up",
+ "message": "pre-up",
+ "translation": "사전-준비",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-up",
+ "message": "post-up",
+ "translation": "게시-하기",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-down",
+ "message": "pre-down",
+ "translation": "준비-해제",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-down",
+ "message": "post-down",
+ "translation": "게시-중단",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "disabled, per policy",
+ "message": "disabled, per policy",
+ "translation": "비활성화됨, 정책에 따라",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "enabled",
+ "message": "enabled",
+ "translation": "활성화됨",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{String} received, {String_1} sent",
+ "message": "{String} received, {String_1} sent",
+ "translation": "{String} 받음, {String_1} 보내기",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "String",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "c.RxBytes.String()"
+ },
+ {
+ "id": "String_1",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "c.TxBytes.String()"
+ }
+ ]
+ },
+ {
+ "id": "Failed to determine tunnel state",
+ "message": "Failed to determine tunnel state",
+ "translation": "터널 상태를 확인하지 못함",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Failed to activate tunnel",
+ "message": "Failed to activate tunnel",
+ "translation": "터널을 활성화하지 못함",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Failed to deactivate tunnel",
+ "message": "Failed to deactivate tunnel",
+ "translation": "터널을 비활성화하지 못함",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Interface: {Name}",
+ "message": "Interface: {Name}",
+ "translation": "인터페이스: {Name}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "config.Name"
+ }
+ ]
+ },
+ {
+ "id": "Peer",
+ "message": "Peer",
+ "translation": "피어",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Create new tunnel",
+ "message": "Create new tunnel",
+ "translation": "새로운 터널 만들기",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Edit tunnel",
+ "message": "Edit tunnel",
+ "translation": "터널 편집",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Name:",
+ "message": "&Name:",
+ "translation": "&이름:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Public key:",
+ "message": "&Public key:",
+ "translation": "&공개 키:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "(unknown)",
+ "message": "(unknown)",
+ "translation": "(알수없음)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Block untunneled traffic (kill-switch)",
+ "message": "&Block untunneled traffic (kill-switch)",
+ "translation": "&Block 터널 없는 교통 (킬-스위치)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "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 or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "message": "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 or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "translation": "구성에 단일 피어가 하나 있고, 해당 피어의 허용된 IP에 0.0.0.0/0 또는 ::/0 중 하나 이상이 포함된 경우, 터널 서비스는 터널 인터페이스로의 또는 터널 인터페이스에서의 트래픽이 아닌 모든 트래픽과 잘못된 DNS 서버로의 트래픽을 차단하는 방화벽 규칙 집합을 활성화합니다. DHCP 및 NDP에 대한 특별 예외가 적용됩니다.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Save",
+ "message": "&Save",
+ "translation": "&저장",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Cancel",
+ "message": "Cancel",
+ "translation": "취소",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Configuration:",
+ "message": "&Configuration:",
+ "translation": "&환경설정:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid name",
+ "message": "Invalid name",
+ "translation": "잘못된 이름",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "A name is required.",
+ "message": "A name is required.",
+ "translation": "이름은 필수 항목 입니다.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel name ‘{NewName}’ is invalid.",
+ "message": "Tunnel name ‘{NewName}’ is invalid.",
+ "translation": "터널명 ‘{NewName}’ 무효입니다.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "NewName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "newName"
+ }
+ ]
+ },
+ {
+ "id": "Unable to list existing tunnels",
+ "message": "Unable to list existing tunnels",
+ "translation": "기존 터널을 나열할 수 없음",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel already exists",
+ "message": "Tunnel already exists",
+ "translation": "이름이 이미 있음",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Another tunnel already exists with the name ‘{NewName}’.",
+ "message": "Another tunnel already exists with the name ‘{NewName}’.",
+ "translation": "이름과 함께 또 다른 터널이 이미 존재합니다 ‘{NewName}’.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "NewName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "newName"
+ }
+ ]
+ },
+ {
+ "id": "Unable to create new configuration",
+ "message": "Unable to create new configuration",
+ "translation": "구성을 가져올 수 없음",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Writing file failed",
+ "message": "Writing file failed",
+ "translation": "파일 쓰기 실패",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "File ‘{FilePath}’ already exists.\n\nDo you want to overwrite it?",
+ "message": "File ‘{FilePath}’ already exists.\n\nDo you want to overwrite it?",
+ "translation": "파일 ‘{FilePath}’ 이미 존재합니다.\n\nDo you want to overwrite it?",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "FilePath",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "filePath"
+ }
+ ]
+ },
+ {
+ "id": "Active",
+ "message": "Active",
+ "translation": "활성화",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Activating",
+ "message": "Activating",
+ "translation": "활성화 중",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Inactive",
+ "message": "Inactive",
+ "translation": "비활성",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Deactivating",
+ "message": "Deactivating",
+ "translation": "비활성화 중",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unknown state",
+ "message": "Unknown state",
+ "translation": "알 수 없는 상태",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Log",
+ "message": "Log",
+ "translation": "로그",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Copy",
+ "message": "&Copy",
+ "translation": "&복사",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Select &all",
+ "message": "Select &all",
+ "translation": "전체 &선택",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Save to file…",
+ "message": "&Save to file…",
+ "translation": "&파일에 저장…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Time",
+ "message": "Time",
+ "translation": "시간",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Log message",
+ "message": "Log message",
+ "translation": "로그 메시지",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "message": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "translation": "텍스트 파일 (*.txt)|*.txt|모든 파일 (*.*)|*.*",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export log to file",
+ "message": "Export log to file",
+ "translation": "로그 파일 내보내기",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&About WireGuard…",
+ "message": "&About WireGuard…",
+ "translation": "&WireGuard에 관하여…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel Error",
+ "message": "Tunnel Error",
+ "translation": "터널 오류",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "message": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "translation": "{ErrMsg}\n\n자세한 내용은 로그를 참조하세요.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "ErrMsg",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errMsg"
+ }
+ ]
+ },
+ {
+ "id": "{Title} (out of date)",
+ "message": "{Title} (out of date)",
+ "translation": "{Title} (구식)",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Title",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "mtw.Title()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Detection Error",
+ "message": "WireGuard Detection Error",
+ "translation": "WireGuard 감지 오류",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to wait for WireGuard window to appear: {Err}",
+ "message": "Unable to wait for WireGuard window to appear: {Err}",
+ "translation": "WireGuard 창이 나타날 때까지 기다릴 수 없음: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard: Deactivated",
+ "message": "WireGuard: Deactivated",
+ "translation": "WireGuard: 비활성화됨",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Unknown",
+ "message": "Status: Unknown",
+ "translation": "상태: 알 수 없음",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Addresses: None",
+ "message": "Addresses: None",
+ "translation": "주소: 없음",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Manage tunnels…",
+ "message": "&Manage tunnels…",
+ "translation": "&터널 관리…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Import tunnel(s) from file…",
+ "message": "&Import tunnel(s) from file…",
+ "translation": "&파일에서 터널(s) 불러오기…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "E&xit",
+ "message": "E&xit",
+ "translation": "종료&",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Tunnels",
+ "message": "&Tunnels",
+ "translation": "&터널",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Activated",
+ "message": "WireGuard Activated",
+ "translation": "WireGuard 활성화됨",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "The {Name} tunnel has been activated.",
+ "message": "The {Name} tunnel has been activated.",
+ "translation": "다음 {Name} 터널이 활성화되었습니다.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnel.Name"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Deactivated",
+ "message": "WireGuard Deactivated",
+ "translation": "WireGuard 비활성화됨",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "The {Name} tunnel has been deactivated.",
+ "message": "The {Name} tunnel has been deactivated.",
+ "translation": "다음 {Name} 터널이 비활성화되었습니다.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnel.Name"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Tunnel Error",
+ "message": "WireGuard Tunnel Error",
+ "translation": "WireGuard 터널 오류",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard: {TextForStateglobalState_true}",
+ "message": "WireGuard: {TextForStateglobalState_true}",
+ "translation": "와이어가드: {TextForStateglobalState_true}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TextForStateglobalState_true",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "textForState(globalState, true)"
+ }
+ ]
+ },
+ {
+ "id": "Status: {StateText}",
+ "message": "Status: {StateText}",
+ "translation": "상태: {StateText}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "StateText",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "stateText"
+ }
+ ]
+ },
+ {
+ "id": "Addresses: {EnumerationSeparator}",
+ "message": "Addresses: {EnumerationSeparator}",
+ "translation": "주소: {EnumerationSeparator}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "EnumerationSeparator",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "strings.Join(addrs, l18n.EnumerationSeparator())"
+ }
+ ]
+ },
+ {
+ "id": "An Update is Available!",
+ "message": "An Update is Available!",
+ "translation": "업데이트를 사용할 수 있습니다!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Update Available",
+ "message": "WireGuard Update Available",
+ "translation": "WireGuard 업데이트 가능",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "An update to WireGuard is now available. You are advised to update as soon as possible.",
+ "message": "An update to WireGuard is now available. You are advised to update as soon as possible.",
+ "translation": "이제 WireGuard 업데이트를 사용할 수 있습니다. 최대한 빨리 업데이트하는 것이 좋습니다.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnels",
+ "message": "Tunnels",
+ "translation": "터널",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Edit",
+ "message": "&Edit",
+ "translation": "&편집",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Add &empty tunnel…",
+ "message": "Add &empty tunnel…",
+ "translation": "&빈 터널 추가…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Add Tunnel",
+ "message": "Add Tunnel",
+ "translation": "터널 추가",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Remove selected tunnel(s)",
+ "message": "Remove selected tunnel(s)",
+ "translation": "선택한 터널(s) 제거",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export all tunnels to zip",
+ "message": "Export all tunnels to zip",
+ "translation": "터널들을 Zip 파일에 내보내기",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Toggle",
+ "message": "&Toggle",
+ "translation": "&토글",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export all tunnels to &zip…",
+ "message": "Export all tunnels to &zip…",
+ "translation": "모든 터널을 &zip으로 내보내기…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Edit &selected tunnel…",
+ "message": "Edit &selected tunnel…",
+ "translation": "편집 &선택한 터널…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Remove selected tunnel(s)",
+ "message": "&Remove selected tunnel(s)",
+ "translation": "&선택한 터널(s) 제거",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "no configuration files were found",
+ "message": "no configuration files were found",
+ "translation": "구성 파일을 찾을 수 없음",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Could not import selected configuration: {LastErr}",
+ "message": "Could not import selected configuration: {LastErr}",
+ "translation": "선택한 구성을 가져올 수 없음: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Could not enumerate existing tunnels: {LastErr}",
+ "message": "Could not enumerate existing tunnels: {LastErr}",
+ "translation": "기존 터널을 열거할 수 없음: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Another tunnel already exists with the name ‘{Name}’",
+ "message": "Another tunnel already exists with the name ‘{Name}’",
+ "translation": "이름과 함께 또 다른 터널이 이미 존재합니다 ‘{Name}’",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "unparsedConfig.Name"
+ }
+ ]
+ },
+ {
+ "id": "Unable to import configuration: {LastErr}",
+ "message": "Unable to import configuration: {LastErr}",
+ "translation": "구성을 가져올 수 없음: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Imported tunnels",
+ "message": "Imported tunnels",
+ "translation": "터널을 가져옴",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Imported {M} tunnels",
+ "message": "Imported {M} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "M",
+ "cases": {
+ "other": {
+ "msg": "터널 {M} 가져옴"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ }
+ ]
+ },
+ {
+ "id": "Imported {M} of {N} tunnels",
+ "message": "Imported {M} of {N} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "N",
+ "cases": {
+ "other": {
+ "msg": "터널 {M} 의 {N} 가져옴"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ },
+ {
+ "id": "N",
+ "string": "%[2]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 2,
+ "expr": "n"
+ }
+ ]
+ },
+ {
+ "id": "Unable to create tunnel",
+ "message": "Unable to create tunnel",
+ "translation": "터널을 생성할 수 없음",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Delete {TunnelCount} tunnels",
+ "message": "Delete {TunnelCount} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "TunnelCount",
+ "cases": {
+ "other": {
+ "msg": "터널 {TunnelCount} 삭제"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "TunnelCount",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "tunnelCount"
+ }
+ ]
+ },
+ {
+ "id": "Are you sure you would like to delete {TunnelCount} tunnels?",
+ "message": "Are you sure you would like to delete {TunnelCount} tunnels?",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "TunnelCount",
+ "cases": {
+ "other": {
+ "msg": "삭제하고 싶은 게 확실해 {TunnelCount} 터널?"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "TunnelCount",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "tunnelCount"
+ }
+ ]
+ },
+ {
+ "id": "Delete tunnel ‘{TunnelName}’",
+ "message": "Delete tunnel ‘{TunnelName}’",
+ "translation": "터널 삭제 ‘{TunnelName}’",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TunnelName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnelName"
+ }
+ ]
+ },
+ {
+ "id": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
+ "message": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
+ "translation": "터널을 삭제하고 싶은 것이 확실합니까 ‘{TunnelName}’?",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TunnelName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnelName"
+ }
+ ]
+ },
+ {
+ "id": "{Question} You cannot undo this action.",
+ "message": "{Question} You cannot undo this action.",
+ "translation": "{Question} 이 작업은 실행취소할 수 없습니다.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Question",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "question"
+ }
+ ]
+ },
+ {
+ "id": "Unable to delete tunnel",
+ "message": "Unable to delete tunnel",
+ "translation": "터널을 삭제할 수 없음",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "A tunnel was unable to be removed: {Error}",
+ "message": "A tunnel was unable to be removed: {Error}",
+ "translation": "터널을 제거할 수 없음: {Error}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Error",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errors[0].Error()"
+ }
+ ]
+ },
+ {
+ "id": "Unable to delete tunnels",
+ "message": "Unable to delete tunnels",
+ "translation": "터널을 삭제할 수 없음",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Lenerrors} tunnels were unable to be removed.",
+ "message": "{Lenerrors} tunnels were unable to be removed.",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Lenerrors",
+ "cases": {
+ "other": {
+ "msg": "{Lenerrors} 터널을 제거할 수 없었습니다."
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Lenerrors",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "len(errors)"
+ }
+ ]
+ },
+ {
+ "id": "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
+ "message": "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
+ "translation": "구성 파일 (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Import tunnel(s) from file",
+ "message": "Import tunnel(s) from file",
+ "translation": "파일에서 터널(s) 불러오기",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Configuration ZIP Files (*.zip)|*.zip",
+ "message": "Configuration ZIP Files (*.zip)|*.zip",
+ "translation": "형상 ZIP 파일 (*.zip)|*.zip",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export tunnels to zip",
+ "message": "Export tunnels to zip",
+ "translation": "터널들을 Zip 파일에 내보내기",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Title} (unsigned build, no updates)",
+ "message": "{Title} (unsigned build, no updates)",
+ "translation": "{Title} (서명되지 않은 빌드, 업데이트 없음)",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Title",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "mtw.Title()"
+ }
+ ]
+ },
+ {
+ "id": "Error Exiting WireGuard",
+ "message": "Error Exiting WireGuard",
+ "translation": "WireGuard 오류로 종료중",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
+ "message": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
+ "translation": "다음 원인으로 인해 서비스를 종료할 수 없: {Err}. 서비스 관리자에서 WireGuard를 중지할 수 있습니다.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "message": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "translation": "WireGuard에 대한 업데이트가 가능합니다. 지체 없이 업데이트하는 것이 좋습니다.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Waiting for user",
+ "message": "Status: Waiting for user",
+ "translation": "상태: 사용자를 기다리는 중",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Update Now",
+ "message": "Update Now",
+ "translation": "지금 업데이트",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Waiting for updater service",
+ "message": "Status: Waiting for updater service",
+ "translation": "상태: 업데이터 서비스를 기다리는 중",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error: {Err}. Please try again.",
+ "message": "Error: {Err}. Please try again.",
+ "translation": "오류: {Err}. 다시 시도해 주세요.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Status: Complete!",
+ "message": "Status: Complete!",
+ "translation": "상태: 완료!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "http2: Framer {F}: failed to decode just-written frame",
+ "message": "http2: Framer {F}: failed to decode just-written frame",
+ "translation": "http2: 프레이머 {F}: 방금 작성된 프레임을 디코딩하는 데 실패",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "F",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "f"
+ }
+ ]
+ },
+ {
+ "id": "http2: Framer {F}: wrote {Http2summarizeFramefr}",
+ "message": "http2: Framer {F}: wrote {Http2summarizeFramefr}",
+ "translation": "http2: 프레이머 {F}: {Http2summarizeFramefr} 을(를) 작성함",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "F",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "f"
+ },
+ {
+ "id": "Http2summarizeFramefr",
+ "string": "%[2]v",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "http2summarizeFrame(fr)"
+ }
+ ]
+ },
+ {
+ "id": "http2: Framer {Fr}: read {Http2summarizeFramef}",
+ "message": "http2: Framer {Fr}: read {Http2summarizeFramef}",
+ "translation": "http2: 프레이머 {Fr}: {Http2summarizeFramef} 을(를) 읽음",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Fr",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "fr"
+ },
+ {
+ "id": "Http2summarizeFramef",
+ "string": "%[2]v",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "http2summarizeFrame(f)"
+ }
+ ]
+ },
+ {
+ "id": "http2: decoded hpack field {HeaderField}",
+ "message": "http2: decoded hpack field {HeaderField}",
+ "translation": "http2: 디코딩된 Hpack 필드 {HeaderField}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "HeaderField",
+ "string": "%+[1]v",
+ "type": "vendor/golang.org/x/net/http2/hpack.HeaderField",
+ "underlyingType": "struct{Name string; Value string; Sensitive bool}",
+ "argNum": 1,
+ "expr": "hf"
+ }
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/locales/nl/messages.gotext.json b/locales/nl/messages.gotext.json
new file mode 100644
index 00000000..511d4300
--- /dev/null
+++ b/locales/nl/messages.gotext.json
@@ -0,0 +1,1665 @@
+{
+ "language": "nl",
+ "messages": [
+ {
+ "id": "Error",
+ "message": "Error",
+ "translation": "Foutmelding",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "(no argument): elevate and install manager service",
+ "message": "(no argument): elevate and install manager service",
+ "translation": "(geen argumenten): Verhoog rechten en installeer beheerder-service",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Usage: {Args0} [\n{String}]",
+ "message": "Usage: {Args0} [\n{String}]",
+ "translation": "Gebruikswijze: {Args0} [\n{String}]",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Args0",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "os.Args[0]"
+ },
+ {
+ "id": "String",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "builder.String()"
+ }
+ ]
+ },
+ {
+ "id": "Command Line Options",
+ "message": "Command Line Options",
+ "translation": "Opdracht-prompt Opties",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to determine whether the process is running under WOW64: {Err}",
+ "message": "Unable to determine whether the process is running under WOW64: {Err}",
+ "translation": "Kan niet bepalen of het proces wordt uitgevoerd onder WOW64: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "You must use the native version of WireGuard on this computer.",
+ "message": "You must use the native version of WireGuard on this computer.",
+ "translation": "Je moet de native versie van WireGuard gebruiken op deze computer.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to open current process token: {Err}",
+ "message": "Unable to open current process token: {Err}",
+ "translation": "Kan de huidige proces-token niet openen: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard may only be used by users who are a member of the Builtin {AdminGroupName} group.",
+ "message": "WireGuard may only be used by users who are a member of the Builtin {AdminGroupName} group.",
+ "translation": "WireGuard mag alleen gebruikt worden door gebruikers die deel uitmaken van de ingebouwde {AdminGroupName} groep.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "AdminGroupName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "elevate.AdminGroupName()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard is running, but the UI is only accessible from desktops of the Builtin {AdminGroupName} group.",
+ "message": "WireGuard is running, but the UI is only accessible from desktops of the Builtin {AdminGroupName} group.",
+ "translation": "WireGuard is actief, maar de gebruikersinterface is alleen toegankelijk via de desktops van de Ingebouwde {AdminGroupName} groep.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "AdminGroupName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "elevate.AdminGroupName()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard system tray icon did not appear after 30 seconds.",
+ "message": "WireGuard system tray icon did not appear after 30 seconds.",
+ "translation": "WireGuard systeem tray icoon is niet weergegeven na 30 seconden.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Now",
+ "message": "Now",
+ "translation": "Nu",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "System clock wound backward!",
+ "message": "System clock wound backward!",
+ "translation": "Systeemklok is achteruit gezet!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Years} year(s)",
+ "message": "{Years} year(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Years",
+ "cases": {
+ "one": {
+ "msg": "{Years} jaar"
+ },
+ "other": {
+ "msg": "{Years} jaren"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Years",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "years"
+ }
+ ]
+ },
+ {
+ "id": "{Days} day(s)",
+ "message": "{Days} day(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Days",
+ "cases": {
+ "one": {
+ "msg": "{Days} dag"
+ },
+ "other": {
+ "msg": "{Days} dagen"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Days",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "days"
+ }
+ ]
+ },
+ {
+ "id": "{Hours} hour(s)",
+ "message": "{Hours} hour(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Hours",
+ "cases": {
+ "one": {
+ "msg": "{Hours} uur"
+ },
+ "other": {
+ "msg": "{Hours} uur"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Hours",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "hours"
+ }
+ ]
+ },
+ {
+ "id": "{Minutes} minute(s)",
+ "message": "{Minutes} minute(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Minutes",
+ "cases": {
+ "one": {
+ "msg": "{Minutes} minuut"
+ },
+ "other": {
+ "msg": "{Minutes} Minuten"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Minutes",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "minutes"
+ }
+ ]
+ },
+ {
+ "id": "{Seconds} second(s)",
+ "message": "{Seconds} second(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Seconds",
+ "cases": {
+ "one": {
+ "msg": "{Seconds} Seconde"
+ },
+ "other": {
+ "msg": "{Seconds} Seconden"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Seconds",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "seconds"
+ }
+ ]
+ },
+ {
+ "id": "{Timestamp} ago",
+ "message": "{Timestamp} ago",
+ "translation": "{Timestamp} geleden",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Timestamp",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "timestamp"
+ }
+ ]
+ },
+ {
+ "id": "{Bytes} B",
+ "message": "{Bytes} B",
+ "translation": "{Bytes} B",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Bytes",
+ "string": "%[1]d",
+ "type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
+ "underlyingType": "uint64",
+ "argNum": 1,
+ "expr": "b"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024} KiB",
+ "message": "{Float64b__1024} KiB",
+ "translation": "{Float64b__1024} KiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / 1024"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024} MiB",
+ "message": "{Float64b__1024__1024} MiB",
+ "translation": "{Float64b__1024__1024} MiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024} GiB",
+ "message": "{Float64b__1024__1024__1024} GiB",
+ "translation": "{Float64b__1024__1024__1024} GiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024__1024} TiB",
+ "message": "{Float64b__1024__1024__1024__1024} TiB",
+ "translation": "{Float64b__1024__1024__1024__1024} TiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024) / 1024"
+ }
+ ]
+ },
+ {
+ "id": "{Why}: {Offender}",
+ "message": "{Why}: {Offender}",
+ "translation": "{Why}: {Offender}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Why",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "e.why"
+ },
+ {
+ "id": "Offender",
+ "string": "%[2]q",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "e.offender"
+ }
+ ]
+ },
+ {
+ "id": "Invalid IP address",
+ "message": "Invalid IP address",
+ "translation": "Ongeldig IP-adres",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid network prefix length",
+ "message": "Invalid network prefix length",
+ "translation": "Ongeldige netwerkprefix-lengte",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Missing port from endpoint",
+ "message": "Missing port from endpoint",
+ "translation": "Ontbrekende poort voor endpoint",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid endpoint host",
+ "message": "Invalid endpoint host",
+ "translation": "Ongeldig endpoint host",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Brackets must contain an IPv6 address",
+ "message": "Brackets must contain an IPv6 address",
+ "translation": "Haakjes moeten een IPv6-adres bevatten",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid MTU",
+ "message": "Invalid MTU",
+ "translation": "Ongeldige MTU",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid port",
+ "message": "Invalid port",
+ "translation": "Ongeldige poort",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid persistent keepalive",
+ "message": "Invalid persistent keepalive",
+ "translation": "Ongeldige Persistent Keep-alive",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key: {Err}",
+ "message": "Invalid key: {Err}",
+ "translation": "Ongeldige sleutel: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Keys must decode to exactly 32 bytes",
+ "message": "Keys must decode to exactly 32 bytes",
+ "translation": "Keys moeten gedecodeerd exact 32 bytes zijn",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Number must be a number between 0 and 2^64-1: {Err}",
+ "message": "Number must be a number between 0 and 2^64-1: {Err}",
+ "translation": "Number moet een getal zijn tussen 0 en 2^64-1: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Two commas in a row",
+ "message": "Two commas in a row",
+ "translation": "Twee komma's op een rij",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel name is not valid",
+ "message": "Tunnel name is not valid",
+ "translation": "Tunnelnaam is ongeldig",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Line must occur in a section",
+ "message": "Line must occur in a section",
+ "translation": "Lijn moet in een sectie voorkomen",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Config key is missing an equals separator",
+ "message": "Config key is missing an equals separator",
+ "translation": "Configuratiesleutel mist een gelijkheidsteken als seperator",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Key must have a value",
+ "message": "Key must have a value",
+ "translation": "Sleutel met een waarde hebben",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for [Interface] section",
+ "message": "Invalid key for [Interface] section",
+ "translation": "Ongeldige sleutel voor [Interface]-gedeelte",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for [Peer] section",
+ "message": "Invalid key for [Peer] section",
+ "translation": "Ongeldige sleutel voor [Peer]-gedeelte",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "An interface must have a private key",
+ "message": "An interface must have a private key",
+ "translation": "Een interface moet een privé sleutel hebben",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "[none specified]",
+ "message": "[none specified]",
+ "translation": "[Niets opgegeven]",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "All peers must have public keys",
+ "message": "All peers must have public keys",
+ "translation": "Alle peers moeten publieke sleutels hebben",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error in getting configuration",
+ "message": "Error in getting configuration",
+ "translation": "Fout bij het lezen van de configuratie",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for interface section",
+ "message": "Invalid key for interface section",
+ "translation": "Ongeldige sleutel voor interface-gedeelte",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Protocol version must be 1",
+ "message": "Protocol version must be 1",
+ "translation": "Protocol-versie moet 1 zijn",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for peer section",
+ "message": "Invalid key for peer section",
+ "translation": "Ongeldige sleutel voor peer-gedeelte",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "[EnumerationSeparator]",
+ "message": "[EnumerationSeparator]",
+ "translation": ", ",
+ "comment": "Text to insert between items when listing - most western languages will translate ‘[EnumerationSeparator]’ into ‘, ’ to produce lists like ‘apple, orange, strawberry’. Eastern languages might translate into ‘、’ to produce lists like ‘リンゴ、オレンジ、イチゴ’."
+ },
+ {
+ "id": "[UnitSeparator]",
+ "message": "[UnitSeparator]",
+ "translation": " ",
+ "comment": "Text to insert when combining units of a measure - most languages will translate ‘[UnitSeparator]’ into ‘ ’ (space) to produce lists like ‘2 minuti 30 sekund’, or empty string ‘’ to produce ‘2分30秒’."
+ },
+ {
+ "id": "About WireGuard",
+ "message": "About WireGuard",
+ "translation": "Over WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard logo image",
+ "message": "WireGuard logo image",
+ "translation": "WireGuard logo-afbeelding",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "message": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "translation": "App-versie: {Number}\nGo backend versie: {WireGuardGoVersion}\nGo-versie: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Number",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "version.Number"
+ },
+ {
+ "id": "WireGuardGoVersion",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "device.WireGuardGoVersion"
+ },
+ {
+ "id": "Version_go",
+ "string": "%[3]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 3,
+ "expr": "strings.TrimPrefix(runtime.Version(), \"go\")"
+ },
+ {
+ "id": "GOARCH",
+ "string": "%[4]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 4,
+ "expr": "runtime.GOARCH"
+ },
+ {
+ "id": "OsName",
+ "string": "%[5]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 5,
+ "expr": "version.OsName()"
+ },
+ {
+ "id": "NativeArch",
+ "string": "%[6]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 6,
+ "expr": "version.NativeArch()"
+ }
+ ]
+ },
+ {
+ "id": "Close",
+ "message": "Close",
+ "translation": "Sluiten",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "♥ &Donate!",
+ "message": "♥ &Donate!",
+ "translation": "♥ &Doneer!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status:",
+ "message": "Status:",
+ "translation": "Status:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Deactivate",
+ "message": "&Deactivate",
+ "translation": "&Deactiveer",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Activate",
+ "message": "&Activate",
+ "translation": "&Activeer",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Public key:",
+ "message": "Public key:",
+ "translation": "Publieke sleutel:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Listen port:",
+ "message": "Listen port:",
+ "translation": "Luister op poort:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "MTU:",
+ "message": "MTU:",
+ "translation": "MTU:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Addresses:",
+ "message": "Addresses:",
+ "translation": "Adressen:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "DNS servers:",
+ "message": "DNS servers:",
+ "translation": "DNS-servers:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Scripts:",
+ "message": "Scripts:",
+ "translation": "Scripts:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Preshared key:",
+ "message": "Preshared key:",
+ "translation": "Gedeelde sleutel:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Allowed IPs:",
+ "message": "Allowed IPs:",
+ "translation": "Toegestane IP-adressen:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Endpoint:",
+ "message": "Endpoint:",
+ "translation": "Eindpunt:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Latest handshake:",
+ "message": "Latest handshake:",
+ "translation": "Recentste uitwisseling:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Transfer:",
+ "message": "Transfer:",
+ "translation": "Overdracht:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "disabled, per policy",
+ "message": "disabled, per policy",
+ "translation": "uitgeschakeld, per beleid",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "enabled",
+ "message": "enabled",
+ "translation": "ingeschakeld",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{String} received, {String_1} sent",
+ "message": "{String} received, {String_1} sent",
+ "translation": "{String} ontvangen, {String_1} verzonden",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "String",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "c.RxBytes.String()"
+ },
+ {
+ "id": "String_1",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "c.TxBytes.String()"
+ }
+ ]
+ },
+ {
+ "id": "Failed to determine tunnel state",
+ "message": "Failed to determine tunnel state",
+ "translation": "Kon tunnelstatus niet vaststellen",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Failed to activate tunnel",
+ "message": "Failed to activate tunnel",
+ "translation": "Kon tunnel niet activeren",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Failed to deactivate tunnel",
+ "message": "Failed to deactivate tunnel",
+ "translation": "Kon tunnel niet deactiveren",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Create new tunnel",
+ "message": "Create new tunnel",
+ "translation": "Maak nieuwe tunnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Name:",
+ "message": "&Name:",
+ "translation": "&Naam:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Public key:",
+ "message": "&Public key:",
+ "translation": "&Publieke sleutel:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "(unknown)",
+ "message": "(unknown)",
+ "translation": "(onbekend)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Block untunneled traffic (kill-switch)",
+ "message": "&Block untunneled traffic (kill-switch)",
+ "translation": "&Ongetunneld verkeer blokkeren (kill-switch)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Save",
+ "message": "&Save",
+ "translation": "&Opslaan",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Cancel",
+ "message": "Cancel",
+ "translation": "Annuleren",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Configuration:",
+ "message": "&Configuration:",
+ "translation": "&Instellingen:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid name",
+ "message": "Invalid name",
+ "translation": "Ongeldige naam",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "A name is required.",
+ "message": "A name is required.",
+ "translation": "Een naam is vereist.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel name ‘{NewName}’ is invalid.",
+ "message": "Tunnel name ‘{NewName}’ is invalid.",
+ "translation": "Naam van tunnel '{NewName}' is ongeldig.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "NewName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "newName"
+ }
+ ]
+ },
+ {
+ "id": "Unable to list existing tunnels",
+ "message": "Unable to list existing tunnels",
+ "translation": "Kan bestaande tunnels niet weergeven",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel already exists",
+ "message": "Tunnel already exists",
+ "translation": "Tunnel bestaat reeds",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Another tunnel already exists with the name ‘{NewName}’.",
+ "message": "Another tunnel already exists with the name ‘{NewName}’.",
+ "translation": "Er bestaat al een andere tunnel met de naam '{NewName}'.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "NewName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "newName"
+ }
+ ]
+ },
+ {
+ "id": "Unable to create new configuration",
+ "message": "Unable to create new configuration",
+ "translation": "De nieuwe instellingen konden niet worden aangemaakt",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Writing file failed",
+ "message": "Writing file failed",
+ "translation": "Bestand schrijven mislukt",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "File ‘{FilePath}’ already exists.\n\nDo you want to overwrite it?",
+ "message": "File ‘{FilePath}’ already exists.\n\nDo you want to overwrite it?",
+ "translation": "Bestand '{FilePath}' bestaat al.\n\nWil je dit overschrijven?",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "FilePath",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "filePath"
+ }
+ ]
+ },
+ {
+ "id": "Active",
+ "message": "Active",
+ "translation": "Actief",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Activating",
+ "message": "Activating",
+ "translation": "Activeren",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Inactive",
+ "message": "Inactive",
+ "translation": "Inactief",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Deactivating",
+ "message": "Deactivating",
+ "translation": "Deactiveren",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unknown state",
+ "message": "Unknown state",
+ "translation": "Onbekende status",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Log",
+ "message": "Log",
+ "translation": "Logboek",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Copy",
+ "message": "&Copy",
+ "translation": "&Kopiëer",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Select &all",
+ "message": "Select &all",
+ "translation": "Selecteer &alles",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Save to file…",
+ "message": "&Save to file…",
+ "translation": "&Opslaan naar bestand…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Time",
+ "message": "Time",
+ "translation": "Tijd",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Log message",
+ "message": "Log message",
+ "translation": "Logbericht",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "message": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "translation": "Tekstbestanden (*.txt)|*.txt|Alle bestanden (*. *)|*.*",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export log to file",
+ "message": "Export log to file",
+ "translation": "Exporteer logboek naar bestand",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&About WireGuard…",
+ "message": "&About WireGuard…",
+ "translation": "Over Wiregu&ard…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel Error",
+ "message": "Tunnel Error",
+ "translation": "Tunnel-fout",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "message": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "translation": "{ErrMsg}\n\nRaadpleeg het logboek voor meer informatie.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "ErrMsg",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errMsg"
+ }
+ ]
+ },
+ {
+ "id": "{Title} (out of date)",
+ "message": "{Title} (out of date)",
+ "translation": "{Title} (out-of-date)",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Title",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "mtw.Title()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Detection Error",
+ "message": "WireGuard Detection Error",
+ "translation": "WireGuard Detection Fout",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to wait for WireGuard window to appear: {Err}",
+ "message": "Unable to wait for WireGuard window to appear: {Err}",
+ "translation": "Kan niet wachten op het Wireguard-window: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard: Deactivated",
+ "message": "WireGuard: Deactivated",
+ "translation": "WireGuard: Gedeactiveerd",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Unknown",
+ "message": "Status: Unknown",
+ "translation": "Status: Onbekend",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Addresses: None",
+ "message": "Addresses: None",
+ "translation": "Addressen: Geen",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Manage tunnels…",
+ "message": "&Manage tunnels…",
+ "translation": "&Tunnels beheren…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Import tunnel(s) from file…",
+ "message": "&Import tunnel(s) from file…",
+ "translation": "&Importeer tunnel(s) van bestand…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "E&xit",
+ "message": "E&xit",
+ "translation": "&Afsluiten",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Tunnels",
+ "message": "&Tunnels",
+ "translation": "&Tunnels",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Activated",
+ "message": "WireGuard Activated",
+ "translation": "WireGuard Geactiveerd",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "The {Name} tunnel has been activated.",
+ "message": "The {Name} tunnel has been activated.",
+ "translation": "De {Name} tunnel is geactiveerd.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnel.Name"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Deactivated",
+ "message": "WireGuard Deactivated",
+ "translation": "WireGuard Gedeactiveerd",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "The {Name} tunnel has been deactivated.",
+ "message": "The {Name} tunnel has been deactivated.",
+ "translation": "De {Name} tunnel is gedeactiveerd.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnel.Name"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Tunnel Error",
+ "message": "WireGuard Tunnel Error",
+ "translation": "WireGuard Tunnel Fout",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard: {TextForStateglobalState_true}",
+ "message": "WireGuard: {TextForStateglobalState_true}",
+ "translation": "WireGuard: {TextForStateglobalState_true}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TextForStateglobalState_true",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "textForState(globalState, true)"
+ }
+ ]
+ },
+ {
+ "id": "Status: {StateText}",
+ "message": "Status: {StateText}",
+ "translation": "Status: {StateText}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "StateText",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "stateText"
+ }
+ ]
+ },
+ {
+ "id": "Addresses: {EnumerationSeparator}",
+ "message": "Addresses: {EnumerationSeparator}",
+ "translation": "Addressen: {EnumerationSeparator}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "EnumerationSeparator",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "strings.Join(addrs, l18n.EnumerationSeparator())"
+ }
+ ]
+ },
+ {
+ "id": "An Update is Available!",
+ "message": "An Update is Available!",
+ "translation": "Een Update is Beschikbaar!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Update Available",
+ "message": "WireGuard Update Available",
+ "translation": "WireGuard update beschikbaar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "An update to WireGuard is now available. You are advised to update as soon as possible.",
+ "message": "An update to WireGuard is now available. You are advised to update as soon as possible.",
+ "translation": "Een update voor WireGuard is beschikbaar. Het wordt aangeraden zo snel mogelijk bij te werken.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnels",
+ "message": "Tunnels",
+ "translation": "Tunnels",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Edit",
+ "message": "&Edit",
+ "translation": "B&ewerken",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Add &empty tunnel…",
+ "message": "Add &empty tunnel…",
+ "translation": "Voeg l&ege tunnel toe…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Add Tunnel",
+ "message": "Add Tunnel",
+ "translation": "Tunnel toevoegen",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Remove selected tunnel(s)",
+ "message": "Remove selected tunnel(s)",
+ "translation": "Geselecteerde tunnel(s) verwijderen",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export all tunnels to zip",
+ "message": "Export all tunnels to zip",
+ "translation": "Alle tunnels naar een zip-bestand exporteren",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Toggle",
+ "message": "&Toggle",
+ "translation": "In-/ui&tschakelen",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export all tunnels to &zip…",
+ "message": "Export all tunnels to &zip…",
+ "translation": "Alle tunnels naar een &zip-bestand exporteren…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Edit &selected tunnel…",
+ "message": "Edit &selected tunnel…",
+ "translation": "Ge&selecteerde tunnel bewerken…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Remove selected tunnel(s)",
+ "message": "&Remove selected tunnel(s)",
+ "translation": "Geselecteerde tunnel(s) ve&rwijderen",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "no configuration files were found",
+ "message": "no configuration files were found",
+ "translation": "geen configuratiebestanden gevonden",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Could not import selected configuration: {LastErr}",
+ "message": "Could not import selected configuration: {LastErr}",
+ "translation": "Kan geselecteerde configuratiebestand niet importeren: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Could not enumerate existing tunnels: {LastErr}",
+ "message": "Could not enumerate existing tunnels: {LastErr}",
+ "translation": "Kon bestaande tunnels niet opsommen: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Another tunnel already exists with the name ‘{Name}’",
+ "message": "Another tunnel already exists with the name ‘{Name}’",
+ "translation": "Er bestaat al een andere tunnel met de naam '{Name}'",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "unparsedConfig.Name"
+ }
+ ]
+ },
+ {
+ "id": "Unable to import configuration: {LastErr}",
+ "message": "Unable to import configuration: {LastErr}",
+ "translation": "Kan configuratiebestand niet importeren: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Imported tunnels",
+ "message": "Imported tunnels",
+ "translation": "Geïmporteerde tunnels",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Imported {M} tunnels",
+ "message": "Imported {M} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "M",
+ "cases": {
+ "one": {
+ "msg": "{M} tunnel geïmporteerd"
+ },
+ "other": {
+ "msg": "{M} tunnels geïmporteerd"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ }
+ ]
+ },
+ {
+ "id": "Imported {M} of {N} tunnels",
+ "message": "Imported {M} of {N} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "N",
+ "cases": {
+ "one": {
+ "msg": "{M} van {N} tunnel(s) geïmporteerd"
+ },
+ "other": {
+ "msg": "{M} van de {N} tunnels geïmporteerd"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ },
+ {
+ "id": "N",
+ "string": "%[2]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 2,
+ "expr": "n"
+ }
+ ]
+ },
+ {
+ "id": "Unable to create tunnel",
+ "message": "Unable to create tunnel",
+ "translation": "Kan tunnel niet creëren",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Delete {TunnelCount} tunnels",
+ "message": "Delete {TunnelCount} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "TunnelCount",
+ "cases": {
+ "one": {
+ "msg": "{TunnelCount} tunnel verwijderd"
+ },
+ "other": {
+ "msg": "{TunnelCount} tunnels verwijderd"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "TunnelCount",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "tunnelCount"
+ }
+ ]
+ },
+ {
+ "id": "Are you sure you would like to delete {TunnelCount} tunnels?",
+ "message": "Are you sure you would like to delete {TunnelCount} tunnels?",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "TunnelCount",
+ "cases": {
+ "one": {
+ "msg": "Weet je zeker dat je {TunnelCount} tunnel wilt verwijderen?"
+ },
+ "other": {
+ "msg": "Weet je zeker dat je {TunnelCount} tunnels wilt verwijderen?"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "TunnelCount",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "tunnelCount"
+ }
+ ]
+ },
+ {
+ "id": "Delete tunnel ‘{TunnelName}’",
+ "message": "Delete tunnel ‘{TunnelName}’",
+ "translation": "Verwijder tunnel '{TunnelName}'",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TunnelName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnelName"
+ }
+ ]
+ },
+ {
+ "id": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
+ "message": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
+ "translation": "Weet je zeker dat je de tunnel '{TunnelName}' wil verwijderen?",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TunnelName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnelName"
+ }
+ ]
+ },
+ {
+ "id": "{Question} You cannot undo this action.",
+ "message": "{Question} You cannot undo this action.",
+ "translation": "{Question} Je kan deze actie niet ongedaan maken.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Question",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "question"
+ }
+ ]
+ },
+ {
+ "id": "Unable to delete tunnel",
+ "message": "Unable to delete tunnel",
+ "translation": "Kan tunnel niet verwijderen",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "A tunnel was unable to be removed: {Error}",
+ "message": "A tunnel was unable to be removed: {Error}",
+ "translation": "Eén tunnel kon niet worden verwijderd: {Error}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Error",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errors[0].Error()"
+ }
+ ]
+ },
+ {
+ "id": "Unable to delete tunnels",
+ "message": "Unable to delete tunnels",
+ "translation": "Kan tunnels niet verwijderen",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Lenerrors} tunnels were unable to be removed.",
+ "message": "{Lenerrors} tunnels were unable to be removed.",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Lenerrors",
+ "cases": {
+ "one": {
+ "msg": "{Lenerrors} tunnel kon niet worden verwijderd."
+ },
+ "other": {
+ "msg": "{Lenerrors} tunnels konden niet worden verwijderd."
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Lenerrors",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "len(errors)"
+ }
+ ]
+ },
+ {
+ "id": "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
+ "message": "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
+ "translation": "Configuratiebestanden (*.zip, *.conf)|*.zip;*.conf|Alle bestanden (*.*)|*.*",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Import tunnel(s) from file",
+ "message": "Import tunnel(s) from file",
+ "translation": "Importeer tunnel(s) uit bestand",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Configuration ZIP Files (*.zip)|*.zip",
+ "message": "Configuration ZIP Files (*.zip)|*.zip",
+ "translation": "Configuratiebestanden ZIP (*.zip)|*.zip",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export tunnels to zip",
+ "message": "Export tunnels to zip",
+ "translation": "Alle tunnels naar zip-bestand exporteren",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error Exiting WireGuard",
+ "message": "Error Exiting WireGuard",
+ "translation": "Fout bij afsluiten WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "message": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "translation": "Er is een update voor WireGuard beschikbaar. Het wordt ten sterkste aangeraden deze zo snel mogelijk te installeren.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Waiting for user",
+ "message": "Status: Waiting for user",
+ "translation": "Status: Wachten op gebruiker",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Update Now",
+ "message": "Update Now",
+ "translation": "Nu Bijwerken",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error: {Err}. Please try again.",
+ "message": "Error: {Err}. Please try again.",
+ "translation": "Fout: {Err}. Probeer het opnieuw.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Status: Complete!",
+ "message": "Status: Complete!",
+ "translation": "Status: Voltooid!",
+ "translatorComment": "Copied from source."
+ }
+ ]
+} \ No newline at end of file
diff --git a/locales/pa-IN/messages.gotext.json b/locales/pa-IN/messages.gotext.json
index 1fe5c65d..6f25ac3a 100644
--- a/locales/pa-IN/messages.gotext.json
+++ b/locales/pa-IN/messages.gotext.json
@@ -422,6 +422,62 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Invalid key: {Err}",
+ "message": "Invalid key: {Err}",
+ "translation": "ਗ਼ੈਰ-ਵਾਜਬ ਕੁੰਜੀ: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Keys must decode to exactly 32 bytes",
+ "message": "Keys must decode to exactly 32 bytes",
+ "translation": "ਕੁੰਜੀਆਂ ਠੀਕ 32 ਬਾਈਟ ਲਈ ਡੀਕੋਡ ਹੋਣੀਆਂ ਚਾਹੀਦੀਆਂ ਹਨ",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Number must be a number between 0 and 2^64-1: {Err}",
+ "message": "Number must be a number between 0 and 2^64-1: {Err}",
+ "translation": "ਨੰਬਰ 0 ਅਤੇ 2^64-1 ਦੇ ਵਿਚਾਲੇ ਹੋਣਾ ਚਾਹੀਦਾ ਹੈ: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Two commas in a row",
+ "message": "Two commas in a row",
+ "translation": "ਇੱਕ ਕਤਾਰ ਵਿੱਚ ਦੋ ਕੌਮੇ ਹਨ",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel name is not valid",
+ "message": "Tunnel name is not valid",
+ "translation": "ਟਨਲ ਦਾ ਨਾਂ ਠੀਕ ਨਹੀਂ ਹੈ",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Line must occur in a section",
+ "message": "Line must occur in a section",
+ "translation": "ਭਾਗ ਵਿੱਚ ਲਾਈਨ ਹੋਣੀ ਚਾਹੀਦੀ ਹੈ",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "[EnumerationSeparator]",
"message": "[EnumerationSeparator]",
"translation": ", ",
@@ -562,6 +618,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Preshared key:",
+ "message": "Preshared key:",
+ "translation": "ਪਹਿਲਾਂ-ਸਾਂਝੀ ਕੀਤੀ ਕੁੰਜੀ:",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Allowed IPs:",
"message": "Allowed IPs:",
"translation": "ਮਨਜ਼ੂਰ ਕੀਤੇ IP:",
@@ -574,12 +636,30 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Persistent keepalive:",
+ "message": "Persistent keepalive:",
+ "translation": "ਸਥਿਰ ਲਗਾਤਾਰ ਜਾਰੀ ਰੱਖੋ:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Latest handshake:",
+ "message": "Latest handshake:",
+ "translation": "ਆਖਰੀ ਹੈਂਡ-ਸ਼ੇਕ:",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Transfer:",
"message": "Transfer:",
"translation": "ਟਰਾਂਸਫਰ:",
"translatorComment": "Copied from source."
},
{
+ "id": "disabled, per policy",
+ "message": "disabled, per policy",
+ "translation": "ਅਸਮਰੱਥ ਹੈ, ਹਰ ਪਾਲਸੀ",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "enabled",
"message": "enabled",
"translation": "ਸਮਰੱਥ ਹੈ",
@@ -680,6 +760,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "&Block untunneled traffic (kill-switch)",
+ "message": "&Block untunneled traffic (kill-switch)",
+ "translation": "ਬਿਨਾਂ-ਟਨਲ ਵਾਲੇ ਟਰੈਫਿਕ ਉੱਤੇ ਪਾਬੰਦੀ ਲਾਓ (&B) (kill-switch)",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "&Save",
"message": "&Save",
"translation": "ਸੰਭਾਲੋ(&S)",
@@ -1112,18 +1198,106 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Another tunnel already exists with the name ‘{Name}’",
+ "message": "Another tunnel already exists with the name ‘{Name}’",
+ "translation": "‘{Name}’ ਨਾਂ ਨਾਲ ਹੋਰ ਟਨਲ ਪਹਿਲਾਂ ਹੀ ਮੌਜੂਦ ਹੈ",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "unparsedConfig.Name"
+ }
+ ]
+ },
+ {
+ "id": "Unable to import configuration: {LastErr}",
+ "message": "Unable to import configuration: {LastErr}",
+ "translation": "ਸੰਰਚਨਾ ਇੰਪੋਰਟ ਕਰਨ ਲਈ ਅਸਮਰੱਥ: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
"id": "Imported tunnels",
"message": "Imported tunnels",
"translation": "ਇੰਪੋਰਟ ਕੀਤੀਆਂ ਟਨਲਾਂ",
"translatorComment": "Copied from source."
},
{
+ "id": "Imported {M} tunnels",
+ "message": "Imported {M} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "M",
+ "cases": {
+ "one": {
+ "msg": "{M} ਟਨਲ ਇੰਪੋਰਟ ਕੀਤੀ"
+ },
+ "other": {
+ "msg": "{M} ਟਨਲਾਂ ਇੰਪੋਰਟ ਕੀਤੀਆਂ"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ }
+ ]
+ },
+ {
"id": "Unable to create tunnel",
"message": "Unable to create tunnel",
"translation": "ਟਨਲ ਬਣਾਉਣ ਲਈ ਅਸਮਰੱਥ",
"translatorComment": "Copied from source."
},
{
+ "id": "Delete {TunnelCount} tunnels",
+ "message": "Delete {TunnelCount} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "TunnelCount",
+ "cases": {
+ "one": {
+ "msg": "{TunnelCount} ਟਨਲ ਹਟਾਓ"
+ },
+ "other": {
+ "msg": "{TunnelCount} ਟਨਲਾਂ ਹਟਾਓ"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "TunnelCount",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "tunnelCount"
+ }
+ ]
+ },
+ {
"id": "Are you sure you would like to delete {TunnelCount} tunnels?",
"message": "Are you sure you would like to delete {TunnelCount} tunnels?",
"translation": {
@@ -1184,12 +1358,50 @@
]
},
{
+ "id": "{Question} You cannot undo this action.",
+ "message": "{Question} You cannot undo this action.",
+ "translation": "{Question} ਤੁਸੀਂ ਇਹ ਕਾਰਵਾਈ ਵਾਪਸ ਨਹੀਂ ਲੈ ਸਕਦੇ ਹੋ।",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Question",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "question"
+ }
+ ]
+ },
+ {
"id": "Unable to delete tunnel",
"message": "Unable to delete tunnel",
"translation": "ਟਨਲ ਹਟਾਉਣ ਲਈ ਅਸਮਰੱਥ",
"translatorComment": "Copied from source."
},
{
+ "id": "A tunnel was unable to be removed: {Error}",
+ "message": "A tunnel was unable to be removed: {Error}",
+ "translation": "ਟਨਲ ਹਟਾਉਣ ਲਈ ਅਸਮਰੱਥ ਹੈ: {Error}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Error",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errors[0].Error()"
+ }
+ ]
+ },
+ {
+ "id": "Unable to delete tunnels",
+ "message": "Unable to delete tunnels",
+ "translation": "ਟਨਲਾਂ ਹਟਾਉਣ ਲਈ ਅਸਮਰੱਥ",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
"message": "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
"translation": "ਸੰਰਚਨਾ ਫ਼ਾਇਲਾਂ (*.zip, *.conf)|*.zip;*.conf|ਸਾਰੀਆਂ ਫ਼ਾਇਲਾਂ (*.*)|*.*",
@@ -1208,12 +1420,68 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Error Exiting WireGuard",
+ "message": "Error Exiting WireGuard",
+ "translation": "WireGuard ਤੋਂ ਬਾਹਰ ਜਾਣ ਲਈ ਗ਼ਲਤੀ",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
+ "message": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
+ "translation": "ਸੇਵਾ ਤੋਂ ਬਾਹਰ ਜਾਣ ਲਈ ਅਸਮਰੱਥ, ਕਾਰਨ: {Err}। ਤੁਸੀਂ ਸੇਵਾ ਮੈਨੇਜਰ ਤੋਂ WireGuard ਨੂੰ ਰੋਕਣਾ ਚਾਹੋਗੇ।",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "message": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "translation": "WireGuard ਲਈ ਅੱਪਡੇਟ ਮੌਜੂਦ ਹੈ। ਤੁਹਾਨੂੰ ਬਿਨਾਂ ਦੇਰ ਕੀਤਿਆਂ ਅੱਪਡੇਟ ਕਰਨ ਦੀ ਸਲਾਹ ਦਿੱਤੀ ਜਾਂਦੀ ਹੈ।",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Waiting for user",
+ "message": "Status: Waiting for user",
+ "translation": "ਹਾਲਤ: ਵਰਤੋਂਕਾਰ ਲਈ ਉਡੀਕ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Update Now",
"message": "Update Now",
"translation": "ਹੁਣੇ ਅੱਪਡੇਟ ਕਰੋ",
"translatorComment": "Copied from source."
},
{
+ "id": "Status: Waiting for updater service",
+ "message": "Status: Waiting for updater service",
+ "translation": "ਹਾਲਤ: ਅੱਪਡੇਟਰ ਸੇਵਾ ਦੀ ਉਡੀਕ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error: {Err}. Please try again.",
+ "message": "Error: {Err}. Please try again.",
+ "translation": "ਗ਼ਲਤੀ: {Err}। ਫੇਰ ਕੋਸ਼ਿਸ਼ ਕਰੋ।",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
"id": "Status: Complete!",
"message": "Status: Complete!",
"translation": "ਸਥਿਤੀ: ਪੂਰਾ!",
diff --git a/locales/pl/messages.gotext.json b/locales/pl/messages.gotext.json
index 072fa8e4..fd09ea97 100644
--- a/locales/pl/messages.gotext.json
+++ b/locales/pl/messages.gotext.json
@@ -16,7 +16,7 @@
{
"id": "Usage: {Args0} [\n{String}]",
"message": "Usage: {Args0} [\n{String}]",
- "translation": "Użycie: {Args0} [{String}]",
+ "translation": "Użycie: {Args0} [\n{String}]",
"translatorComment": "Copied from source.",
"placeholders": [
{
@@ -62,7 +62,7 @@
{
"id": "You must use the native version of WireGuard on this computer.",
"message": "You must use the native version of WireGuard on this computer.",
- "translation": "Musisz użyć natywnej wersji WireGuard na tym komputerze.",
+ "translation": "Należy użyć natywnej wersji WireGuard na tym komputerze.",
"translatorComment": "Copied from source."
},
{
@@ -149,7 +149,7 @@
"msg": "{Years} lat"
},
"other": {
- "msg": "{Years} lata"
+ "msg": "{Years} lat"
}
}
}
@@ -217,7 +217,7 @@
"msg": "{Hours} godzin"
},
"other": {
- "msg": "{Hours} godziny"
+ "msg": "{Hours} godzin"
}
}
}
@@ -806,7 +806,7 @@
{
"id": "enabled",
"message": "enabled",
- "translation": "włączyć",
+ "translation": "włączone",
"translatorComment": "Copied from source."
},
{
@@ -1110,7 +1110,7 @@
{
"id": "{ErrMsg}\n\nPlease consult the log for more information.",
"message": "{ErrMsg}\n\nPlease consult the log for more information.",
- "translation": "{ErrMsg}\n\nAby uzyskać więcej informacji, zapoznaj się z logiem.",
+ "translation": "{ErrMsg}\n\nAby uzyskać więcej informacji, zapoznaj się z dziennikiem.",
"translatorComment": "Copied from source.",
"placeholders": [
{
@@ -1188,7 +1188,7 @@
{
"id": "&Import tunnel(s) from file…",
"message": "&Import tunnel(s) from file…",
- "translation": "&Importuj tunel (tunele) z pliku…",
+ "translation": "&Importuj tunel(e) z pliku…",
"translatorComment": "Copied from source."
},
{
@@ -1228,7 +1228,7 @@
{
"id": "WireGuard Deactivated",
"message": "WireGuard Deactivated",
- "translation": "WireGuard Dezaktywowany",
+ "translation": "WireGuard dezaktywowany",
"translatorComment": "Copied from source."
},
{
@@ -1340,13 +1340,13 @@
{
"id": "Add Tunnel",
"message": "Add Tunnel",
- "translation": "Dodaj Tunel",
+ "translation": "Dodaj tunel",
"translatorComment": "Copied from source."
},
{
"id": "Remove selected tunnel(s)",
"message": "Remove selected tunnel(s)",
- "translation": "Usuń wybrany tunel (tunele)",
+ "translation": "Usuń wybrany(-e) tunel(e)",
"translatorComment": "Copied from source."
},
{
@@ -1376,7 +1376,7 @@
{
"id": "&Remove selected tunnel(s)",
"message": "&Remove selected tunnel(s)",
- "translation": "&Usuń wybrany tunel (tunele)",
+ "translation": "&Usuń wybrany(-e) tunel(e)",
"translatorComment": "Copied from source."
},
{
@@ -1498,7 +1498,7 @@
"arg": "N",
"cases": {
"one": {
- "msg": "Zaimportowano {M} z {N} tunel"
+ "msg": "Zaimportowano {M} z {N} tunelu"
},
"few": {
"msg": "Zaimportowano {M} z {N} tunele"
@@ -1724,7 +1724,7 @@
{
"id": "Import tunnel(s) from file",
"message": "Import tunnel(s) from file",
- "translation": "Importuj tunel (tunele) z pliku",
+ "translation": "Importuj tunel(e) z pliku",
"translatorComment": "Copied from source."
},
{
@@ -1764,7 +1764,7 @@
{
"id": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
"message": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
- "translation": "Nie można wyłączyć usługi ze względu na: {Err}. Jeśli chcesz wyłączyć WireGuard możesz to zrobić z poziomu menedżera usług.",
+ "translation": "Nie można wyłączyć usługi ze względu na: {Err}. Jeśli chcesz wyłączyć WireGuard, możesz to zrobić z poziomu menedżera usług.",
"translatorComment": "Copied from source.",
"placeholders": [
{
diff --git a/locales/pt-BR/messages.gotext.json b/locales/pt-BR/messages.gotext.json
new file mode 100644
index 00000000..84313ba7
--- /dev/null
+++ b/locales/pt-BR/messages.gotext.json
@@ -0,0 +1,1847 @@
+{
+ "language": "pt-BR",
+ "messages": [
+ {
+ "id": "Error",
+ "message": "Error",
+ "translation": "Erro",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "(no argument): elevate and install manager service",
+ "message": "(no argument): elevate and install manager service",
+ "translation": "(sem argumento): elevar e instalar o serviço gerenciador",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Usage: {Args0} [\n{String}]",
+ "message": "Usage: {Args0} [\n{String}]",
+ "translation": "Uso: {Args0} [\n{String}]",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Args0",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "os.Args[0]"
+ },
+ {
+ "id": "String",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "builder.String()"
+ }
+ ]
+ },
+ {
+ "id": "Command Line Options",
+ "message": "Command Line Options",
+ "translation": "Opções de linha de comando",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to determine whether the process is running under WOW64: {Err}",
+ "message": "Unable to determine whether the process is running under WOW64: {Err}",
+ "translation": "Não foi possível determinar se o processo está sendo executado em WOW64: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "You must use the native version of WireGuard on this computer.",
+ "message": "You must use the native version of WireGuard on this computer.",
+ "translation": "Você deve usar a versão nativa do WireGuard neste computador.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to open current process token: {Err}",
+ "message": "Unable to open current process token: {Err}",
+ "translation": "Não foi possível abrir o token do processo atual: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard may only be used by users who are a member of the Builtin {AdminGroupName} group.",
+ "message": "WireGuard may only be used by users who are a member of the Builtin {AdminGroupName} group.",
+ "translation": "O WireGuard só pode ser usado por usuários que são membros do grupo incorporado {AdminGroupName}.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "AdminGroupName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "elevate.AdminGroupName()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard is running, but the UI is only accessible from desktops of the Builtin {AdminGroupName} group.",
+ "message": "WireGuard is running, but the UI is only accessible from desktops of the Builtin {AdminGroupName} group.",
+ "translation": "O WireGuard está funcionando, mas a interface do usuário só é acessível em desktops do grupo incorporado {AdminGroupName}.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "AdminGroupName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "elevate.AdminGroupName()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard system tray icon did not appear after 30 seconds.",
+ "message": "WireGuard system tray icon did not appear after 30 seconds.",
+ "translation": "O ícone do sistema da barra do WireGuard não apareceu após 30 segundos.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Now",
+ "message": "Now",
+ "translation": "Agora",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "System clock wound backward!",
+ "message": "System clock wound backward!",
+ "translation": "Relógio do sistema voltou!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Years} year(s)",
+ "message": "{Years} year(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Years",
+ "cases": {
+ "one": {
+ "msg": "{Years} ano"
+ },
+ "other": {
+ "msg": "{Years} anos"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Years",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "years"
+ }
+ ]
+ },
+ {
+ "id": "{Days} day(s)",
+ "message": "{Days} day(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Days",
+ "cases": {
+ "one": {
+ "msg": "{Days} dia"
+ },
+ "other": {
+ "msg": "{Days} dias"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Days",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "days"
+ }
+ ]
+ },
+ {
+ "id": "{Hours} hour(s)",
+ "message": "{Hours} hour(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Hours",
+ "cases": {
+ "one": {
+ "msg": "{Hours} hora"
+ },
+ "other": {
+ "msg": "{Hours} horas"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Hours",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "hours"
+ }
+ ]
+ },
+ {
+ "id": "{Minutes} minute(s)",
+ "message": "{Minutes} minute(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Minutes",
+ "cases": {
+ "one": {
+ "msg": "{Minutes} minuto"
+ },
+ "other": {
+ "msg": "{Minutes} minutes"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Minutes",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "minutes"
+ }
+ ]
+ },
+ {
+ "id": "{Seconds} second(s)",
+ "message": "{Seconds} second(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Seconds",
+ "cases": {
+ "one": {
+ "msg": "{Seconds} segundo"
+ },
+ "other": {
+ "msg": "{Seconds} segundos"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Seconds",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "seconds"
+ }
+ ]
+ },
+ {
+ "id": "{Timestamp} ago",
+ "message": "{Timestamp} ago",
+ "translation": "{Timestamp} atrás",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Timestamp",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "timestamp"
+ }
+ ]
+ },
+ {
+ "id": "{Bytes} B",
+ "message": "{Bytes} B",
+ "translation": "{Bytes} B",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Bytes",
+ "string": "%[1]d",
+ "type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
+ "underlyingType": "uint64",
+ "argNum": 1,
+ "expr": "b"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024} KiB",
+ "message": "{Float64b__1024} KiB",
+ "translation": "{Float64b__1024} KiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / 1024"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024} MiB",
+ "message": "{Float64b__1024__1024} MiB",
+ "translation": "{Float64b__1024__1024} MiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024} GiB",
+ "message": "{Float64b__1024__1024__1024} GiB",
+ "translation": "{Float64b__1024__1024__1024} GiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024__1024} TiB",
+ "message": "{Float64b__1024__1024__1024__1024} TiB",
+ "translation": "{Float64b__1024__1024__1024__1024} TiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024) / 1024"
+ }
+ ]
+ },
+ {
+ "id": "{Why}: {Offender}",
+ "message": "{Why}: {Offender}",
+ "translation": "{Why}: {Offender}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Why",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "e.why"
+ },
+ {
+ "id": "Offender",
+ "string": "%[2]q",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "e.offender"
+ }
+ ]
+ },
+ {
+ "id": "Invalid IP address",
+ "message": "Invalid IP address",
+ "translation": "Endereço IP inválido",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid network prefix length",
+ "message": "Invalid network prefix length",
+ "translation": "Comprimento do prefixo de rede inválido",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Missing port from endpoint",
+ "message": "Missing port from endpoint",
+ "translation": "Porta ausente do endpoint",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid endpoint host",
+ "message": "Invalid endpoint host",
+ "translation": "Servidor de endpoint inválido",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Brackets must contain an IPv6 address",
+ "message": "Brackets must contain an IPv6 address",
+ "translation": "Os colchetes devem conter um endereço IPv6",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid MTU",
+ "message": "Invalid MTU",
+ "translation": "MTU inválido",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid port",
+ "message": "Invalid port",
+ "translation": "Porta inválida",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid persistent keepalive",
+ "message": "Invalid persistent keepalive",
+ "translation": "Keepalive persistente inválido",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key: {Err}",
+ "message": "Invalid key: {Err}",
+ "translation": "Chave inválida: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Keys must decode to exactly 32 bytes",
+ "message": "Keys must decode to exactly 32 bytes",
+ "translation": "Chaves devem decodificar exatamente para 32 bytes",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Number must be a number between 0 and 2^64-1: {Err}",
+ "message": "Number must be a number between 0 and 2^64-1: {Err}",
+ "translation": "O número deve ser um número entre 0 e 2^64-1: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Two commas in a row",
+ "message": "Two commas in a row",
+ "translation": "Duas vírgulas seguidas",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel name is not valid",
+ "message": "Tunnel name is not valid",
+ "translation": "Nome do túnel não é válido",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Line must occur in a section",
+ "message": "Line must occur in a section",
+ "translation": "A linha deve ocorrer em uma seção",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Config key is missing an equals separator",
+ "message": "Config key is missing an equals separator",
+ "translation": "Chave de configuração está faltando um separador igual",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Key must have a value",
+ "message": "Key must have a value",
+ "translation": "Chaves devem ter um valor",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for [Interface] section",
+ "message": "Invalid key for [Interface] section",
+ "translation": "Chave inválida para a seção [Interface]",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for [Peer] section",
+ "message": "Invalid key for [Peer] section",
+ "translation": "Chave inválida para a seção [Peer]",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "An interface must have a private key",
+ "message": "An interface must have a private key",
+ "translation": "Uma interface deve ter uma chave privada",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "[none specified]",
+ "message": "[none specified]",
+ "translation": "[nenhum especificado]",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "All peers must have public keys",
+ "message": "All peers must have public keys",
+ "translation": "Todos os pares devem ter chaves públicas",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error in getting configuration",
+ "message": "Error in getting configuration",
+ "translation": "Erro ao atualizar configuração",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for interface section",
+ "message": "Invalid key for interface section",
+ "translation": "Chave inválida para a seção da interface",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Protocol version must be 1",
+ "message": "Protocol version must be 1",
+ "translation": "A versão do protocolo deve ser 1",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for peer section",
+ "message": "Invalid key for peer section",
+ "translation": "Chave inválida para a seção do par",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "[EnumerationSeparator]",
+ "message": "[EnumerationSeparator]",
+ "translation": ", ",
+ "comment": "Text to insert between items when listing - most western languages will translate ‘[EnumerationSeparator]’ into ‘, ’ to produce lists like ‘apple, orange, strawberry’. Eastern languages might translate into ‘、’ to produce lists like ‘リンゴ、オレンジ、イチゴ’."
+ },
+ {
+ "id": "[UnitSeparator]",
+ "message": "[UnitSeparator]",
+ "translation": ", ",
+ "comment": "Text to insert when combining units of a measure - most languages will translate ‘[UnitSeparator]’ into ‘ ’ (space) to produce lists like ‘2 minuti 30 sekund’, or empty string ‘’ to produce ‘2分30秒’."
+ },
+ {
+ "id": "About WireGuard",
+ "message": "About WireGuard",
+ "translation": "Sobre o WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard logo image",
+ "message": "WireGuard logo image",
+ "translation": "Imagem do logotipo WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "message": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "translation": "Versão do app: {Number}\nVersão do backend: {WireGuardGoVersion}\nVersão Go: {Version_go}-{GOARCH}\nSistema Operacional: {OsName}\nArquitetura: {NativeArch}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Number",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "version.Number"
+ },
+ {
+ "id": "WireGuardGoVersion",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "device.WireGuardGoVersion"
+ },
+ {
+ "id": "Version_go",
+ "string": "%[3]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 3,
+ "expr": "strings.TrimPrefix(runtime.Version(), \"go\")"
+ },
+ {
+ "id": "GOARCH",
+ "string": "%[4]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 4,
+ "expr": "runtime.GOARCH"
+ },
+ {
+ "id": "OsName",
+ "string": "%[5]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 5,
+ "expr": "version.OsName()"
+ },
+ {
+ "id": "NativeArch",
+ "string": "%[6]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 6,
+ "expr": "version.NativeArch()"
+ }
+ ]
+ },
+ {
+ "id": "Close",
+ "message": "Close",
+ "translation": "Fechar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "♥ &Donate!",
+ "message": "♥ &Donate!",
+ "translation": "♥ &Doar!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status:",
+ "message": "Status:",
+ "translation": "Status:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Deactivate",
+ "message": "&Deactivate",
+ "translation": "Desativado",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Activate",
+ "message": "&Activate",
+ "translation": "&Ativar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Public key:",
+ "message": "Public key:",
+ "translation": "Chaves públicas:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Listen port:",
+ "message": "Listen port:",
+ "translation": "Porta de escuta:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "MTU:",
+ "message": "MTU:",
+ "translation": "MTU:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Addresses:",
+ "message": "Addresses:",
+ "translation": "Endereços:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "DNS servers:",
+ "message": "DNS servers:",
+ "translation": "Servidores DNS:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Scripts:",
+ "message": "Scripts:",
+ "translation": "Scripts:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Preshared key:",
+ "message": "Preshared key:",
+ "translation": "Tecla Pressionada:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Allowed IPs:",
+ "message": "Allowed IPs:",
+ "translation": "IPs Permitidos:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Endpoint:",
+ "message": "Endpoint:",
+ "translation": "Ponto Final:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Persistent keepalive:",
+ "message": "Persistent keepalive:",
+ "translation": "Mensagem persistente:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Latest handshake:",
+ "message": "Latest handshake:",
+ "translation": "Shake mais recente:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Transfer:",
+ "message": "Transfer:",
+ "translation": "Transferir:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-up",
+ "message": "pre-up",
+ "translation": "pré-cima",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-up",
+ "message": "post-up",
+ "translation": "postar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-down",
+ "message": "pre-down",
+ "translation": "pré-baixo",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-down",
+ "message": "post-down",
+ "translation": "pós-baixo",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "disabled, per policy",
+ "message": "disabled, per policy",
+ "translation": "desativada, por política",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "enabled",
+ "message": "enabled",
+ "translation": "habilitado",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{String} received, {String_1} sent",
+ "message": "{String} received, {String_1} sent",
+ "translation": "{String} recebido, {String_1} enviado",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "String",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "c.RxBytes.String()"
+ },
+ {
+ "id": "String_1",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "c.TxBytes.String()"
+ }
+ ]
+ },
+ {
+ "id": "Failed to determine tunnel state",
+ "message": "Failed to determine tunnel state",
+ "translation": "Falha ao determinar o estado do túnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Failed to activate tunnel",
+ "message": "Failed to activate tunnel",
+ "translation": "Falha ao ativar o túnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Failed to deactivate tunnel",
+ "message": "Failed to deactivate tunnel",
+ "translation": "Falha ao desativar o tunel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Interface: {Name}",
+ "message": "Interface: {Name}",
+ "translation": "Interface: {Name}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "config.Name"
+ }
+ ]
+ },
+ {
+ "id": "Peer",
+ "message": "Peer",
+ "translation": "Parceiros",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Create new tunnel",
+ "message": "Create new tunnel",
+ "translation": "Criar túnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Edit tunnel",
+ "message": "Edit tunnel",
+ "translation": "Editar túnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Name:",
+ "message": "&Name:",
+ "translation": "&Nome:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Public key:",
+ "message": "&Public key:",
+ "translation": "&Chaves públicas:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "(unknown)",
+ "message": "(unknown)",
+ "translation": "(desconhecido)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Block untunneled traffic (kill-switch)",
+ "message": "&Block untunneled traffic (kill-switch)",
+ "translation": "&Bloquear tráfego sem tunelamento (kill-switch)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "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 or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "message": "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 or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "translation": "Quando uma configuração tem exatamente um par e esse par tem um IPs permitidos contendo pelo menos um dos 0.0.0. /0 ou ::/0, então o serviço de túnel envolve uma regra de firewall para bloquear todo o tráfego que não é de nem de um túnel ou está para o servidor DNS errado, com exceções especiais para DHCP e NDP.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Save",
+ "message": "&Save",
+ "translation": "&Salvar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Cancel",
+ "message": "Cancel",
+ "translation": "Cancelar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Configuration:",
+ "message": "&Configuration:",
+ "translation": "&Configuração:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid name",
+ "message": "Invalid name",
+ "translation": "Nome inválido",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "A name is required.",
+ "message": "A name is required.",
+ "translation": "Um nome é necessário.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel name ‘{NewName}’ is invalid.",
+ "message": "Tunnel name ‘{NewName}’ is invalid.",
+ "translation": "O nome do túnel ‘{NewName}' é inválido.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "NewName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "newName"
+ }
+ ]
+ },
+ {
+ "id": "Unable to list existing tunnels",
+ "message": "Unable to list existing tunnels",
+ "translation": "Não foi possível listar túneis existentes",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel already exists",
+ "message": "Tunnel already exists",
+ "translation": "Arquivo já existe",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Another tunnel already exists with the name ‘{NewName}’.",
+ "message": "Another tunnel already exists with the name ‘{NewName}’.",
+ "translation": "Já existe outro túnel com o nome ‘{NewName}’.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "NewName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "newName"
+ }
+ ]
+ },
+ {
+ "id": "Unable to create new configuration",
+ "message": "Unable to create new configuration",
+ "translation": "Não é possível adicionar a configuração",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Writing file failed",
+ "message": "Writing file failed",
+ "translation": "Falha ao escrever arquivo",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "File ‘{FilePath}’ already exists.\n\nDo you want to overwrite it?",
+ "message": "File ‘{FilePath}’ already exists.\n\nDo you want to overwrite it?",
+ "translation": "O arquivo '{FilePath}' já existe.\n\nVocê deseja sobrescrever isso?",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "FilePath",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "filePath"
+ }
+ ]
+ },
+ {
+ "id": "Active",
+ "message": "Active",
+ "translation": "Ativo",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Activating",
+ "message": "Activating",
+ "translation": "Ativar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Inactive",
+ "message": "Inactive",
+ "translation": "Inativo",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Deactivating",
+ "message": "Deactivating",
+ "translation": "Desativando",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unknown state",
+ "message": "Unknown state",
+ "translation": "Situação desconhecida",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Log",
+ "message": "Log",
+ "translation": "Registro",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Copy",
+ "message": "&Copy",
+ "translation": "&Copiar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Select &all",
+ "message": "Select &all",
+ "translation": "Selecionar &Tudo",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Save to file…",
+ "message": "&Save to file…",
+ "translation": "&Salvar em arquivo…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Time",
+ "message": "Time",
+ "translation": "Tempo",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Log message",
+ "message": "Log message",
+ "translation": "Registro de mensagens",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "message": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "translation": "Arquivos de texto (*.txt)|*.txt|Todos os arquivos (*.*)|*.*",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export log to file",
+ "message": "Export log to file",
+ "translation": "Exportar arquivo de log",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&About WireGuard…",
+ "message": "&About WireGuard…",
+ "translation": "&Sobre o WireGuard…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel Error",
+ "message": "Tunnel Error",
+ "translation": "Erro de túnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "message": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "translation": "{ErrMsg}\n\nPor favor, consulte o log para obter mais informações.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "ErrMsg",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errMsg"
+ }
+ ]
+ },
+ {
+ "id": "{Title} (out of date)",
+ "message": "{Title} (out of date)",
+ "translation": "{Title} (desatualizado)",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Title",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "mtw.Title()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Detection Error",
+ "message": "WireGuard Detection Error",
+ "translation": "Erro de Detecção do WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to wait for WireGuard window to appear: {Err}",
+ "message": "Unable to wait for WireGuard window to appear: {Err}",
+ "translation": "Não foi possível esperar a janela do WireGuard aparecer: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard: Deactivated",
+ "message": "WireGuard: Deactivated",
+ "translation": "WireGuard: Desativado",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Unknown",
+ "message": "Status: Unknown",
+ "translation": "Status desconhecido",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Addresses: None",
+ "message": "Addresses: None",
+ "translation": "Endereços: Nenhum",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Manage tunnels…",
+ "message": "&Manage tunnels…",
+ "translation": "&Gerenciar túneis…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Import tunnel(s) from file…",
+ "message": "&Import tunnel(s) from file…",
+ "translation": "&Importar túnel(s) do arquivo…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "E&xit",
+ "message": "E&xit",
+ "translation": "Sai&r",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Tunnels",
+ "message": "&Tunnels",
+ "translation": "&Túneis",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Activated",
+ "message": "WireGuard Activated",
+ "translation": "WireGuard ativado",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "The {Name} tunnel has been activated.",
+ "message": "The {Name} tunnel has been activated.",
+ "translation": "O túnel {Name} foi ativado.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnel.Name"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Deactivated",
+ "message": "WireGuard Deactivated",
+ "translation": "WireGuard: Desativado",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "The {Name} tunnel has been deactivated.",
+ "message": "The {Name} tunnel has been deactivated.",
+ "translation": "O túnel {Name} foi desativado.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnel.Name"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Tunnel Error",
+ "message": "WireGuard Tunnel Error",
+ "translation": "Erro no Túnel WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard: {TextForStateglobalState_true}",
+ "message": "WireGuard: {TextForStateglobalState_true}",
+ "translation": "WireGuard: {TextForStateglobalState_true}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TextForStateglobalState_true",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "textForState(globalState, true)"
+ }
+ ]
+ },
+ {
+ "id": "Status: {StateText}",
+ "message": "Status: {StateText}",
+ "translation": "Status: {StateText}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "StateText",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "stateText"
+ }
+ ]
+ },
+ {
+ "id": "Addresses: {EnumerationSeparator}",
+ "message": "Addresses: {EnumerationSeparator}",
+ "translation": "Endereços: {EnumerationSeparator}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "EnumerationSeparator",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "strings.Join(addrs, l18n.EnumerationSeparator())"
+ }
+ ]
+ },
+ {
+ "id": "An Update is Available!",
+ "message": "An Update is Available!",
+ "translation": "Uma atualização está disponível!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Update Available",
+ "message": "WireGuard Update Available",
+ "translation": "Atualização do WireGuard disponível",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "An update to WireGuard is now available. You are advised to update as soon as possible.",
+ "message": "An update to WireGuard is now available. You are advised to update as soon as possible.",
+ "translation": "Uma atualização para o WireGuard está agora disponível. Recomenda-se atualizar o mais rápido possível.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnels",
+ "message": "Tunnels",
+ "translation": "Túneis",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Edit",
+ "message": "&Edit",
+ "translation": "&Editar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Add &empty tunnel…",
+ "message": "Add &empty tunnel…",
+ "translation": "Adicionar &túnel vazio…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Add Tunnel",
+ "message": "Add Tunnel",
+ "translation": "Adicionar um túnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Remove selected tunnel(s)",
+ "message": "Remove selected tunnel(s)",
+ "translation": "Remover túneis selecionados",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export all tunnels to zip",
+ "message": "Export all tunnels to zip",
+ "translation": "Exportar todos os túneis para zip",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Toggle",
+ "message": "&Toggle",
+ "translation": "&Alternancia",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export all tunnels to &zip…",
+ "message": "Export all tunnels to &zip…",
+ "translation": "Exportar todos os túneis para &zip…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Edit &selected tunnel…",
+ "message": "Edit &selected tunnel…",
+ "translation": "Editar &túnel selecionado…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Remove selected tunnel(s)",
+ "message": "&Remove selected tunnel(s)",
+ "translation": "&Remover túneis selecionados",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "no configuration files were found",
+ "message": "no configuration files were found",
+ "translation": "nenhum arquivo de configuração foi encontrado",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Could not import selected configuration: {LastErr}",
+ "message": "Could not import selected configuration: {LastErr}",
+ "translation": "Não foi possível importar a configuração selecionada: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Could not enumerate existing tunnels: {LastErr}",
+ "message": "Could not enumerate existing tunnels: {LastErr}",
+ "translation": "Não foi possível enumerar túneis existentes: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Another tunnel already exists with the name ‘{Name}’",
+ "message": "Another tunnel already exists with the name ‘{Name}’",
+ "translation": "Já existe outro túnel com o nome ‘{Name}’",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "unparsedConfig.Name"
+ }
+ ]
+ },
+ {
+ "id": "Unable to import configuration: {LastErr}",
+ "message": "Unable to import configuration: {LastErr}",
+ "translation": "Não foi possível importar a configuração: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Imported tunnels",
+ "message": "Imported tunnels",
+ "translation": "Importados túneis",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Imported {M} tunnels",
+ "message": "Imported {M} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "M",
+ "cases": {
+ "one": {
+ "msg": "Túnel {M} importado"
+ },
+ "other": {
+ "msg": "{M} túneis importados"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ }
+ ]
+ },
+ {
+ "id": "Imported {M} of {N} tunnels",
+ "message": "Imported {M} of {N} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "N",
+ "cases": {
+ "one": {
+ "msg": "Importados {M} dos {N} túneis"
+ },
+ "other": {
+ "msg": "Importados {M} dos {N} túneis"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ },
+ {
+ "id": "N",
+ "string": "%[2]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 2,
+ "expr": "n"
+ }
+ ]
+ },
+ {
+ "id": "Unable to create tunnel",
+ "message": "Unable to create tunnel",
+ "translation": "Não foi possível criar o túnel: %s",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Delete {TunnelCount} tunnels",
+ "message": "Delete {TunnelCount} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "TunnelCount",
+ "cases": {
+ "one": {
+ "msg": "Excluir túnel {TunnelCount}"
+ },
+ "other": {
+ "msg": "Excluir {TunnelCount} túneis"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "TunnelCount",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "tunnelCount"
+ }
+ ]
+ },
+ {
+ "id": "Are you sure you would like to delete {TunnelCount} tunnels?",
+ "message": "Are you sure you would like to delete {TunnelCount} tunnels?",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "TunnelCount",
+ "cases": {
+ "one": {
+ "msg": "Tem certeza que deseja excluir o túnel {TunnelCount}?"
+ },
+ "other": {
+ "msg": "Você tem certeza que deseja excluir os túneis {TunnelCount}?"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "TunnelCount",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "tunnelCount"
+ }
+ ]
+ },
+ {
+ "id": "Delete tunnel ‘{TunnelName}’",
+ "message": "Delete tunnel ‘{TunnelName}’",
+ "translation": "Excluir túnel ‘{TunnelName}'",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TunnelName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnelName"
+ }
+ ]
+ },
+ {
+ "id": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
+ "message": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
+ "translation": "Tem certeza de que deseja excluir o túnel ‘{TunnelName}?",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TunnelName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnelName"
+ }
+ ]
+ },
+ {
+ "id": "{Question} You cannot undo this action.",
+ "message": "{Question} You cannot undo this action.",
+ "translation": "{Question} Você não pode desfazer essa ação.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Question",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "question"
+ }
+ ]
+ },
+ {
+ "id": "Unable to delete tunnel",
+ "message": "Unable to delete tunnel",
+ "translation": "Não foi possível excluir o túnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "A tunnel was unable to be removed: {Error}",
+ "message": "A tunnel was unable to be removed: {Error}",
+ "translation": "Não foi possível remover um túnel: {Error}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Error",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errors[0].Error()"
+ }
+ ]
+ },
+ {
+ "id": "Unable to delete tunnels",
+ "message": "Unable to delete tunnels",
+ "translation": "Não foi possível excluir túneis",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Lenerrors} tunnels were unable to be removed.",
+ "message": "{Lenerrors} tunnels were unable to be removed.",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Lenerrors",
+ "cases": {
+ "one": {
+ "msg": "O túnel {Lenerrors} não pôde ser removido."
+ },
+ "other": {
+ "msg": "{Lenerrors} túneis não puderam ser removidos."
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Lenerrors",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "len(errors)"
+ }
+ ]
+ },
+ {
+ "id": "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
+ "message": "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
+ "translation": "Arquivos de configuração (*.zip, *.conf)|*.zip;*.conf|Todos os arquivos (*.*)|*.*",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Import tunnel(s) from file",
+ "message": "Import tunnel(s) from file",
+ "translation": "Importar túnel(es) do arquivo",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Configuration ZIP Files (*.zip)|*.zip",
+ "message": "Configuration ZIP Files (*.zip)|*.zip",
+ "translation": "Arquivos ZIP de configuração (*.zip)|*.zip",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export tunnels to zip",
+ "message": "Export tunnels to zip",
+ "translation": "Exportar túneis para zip",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Title} (unsigned build, no updates)",
+ "message": "{Title} (unsigned build, no updates)",
+ "translation": "{Title} (versão não assinada, sem atualizações)",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Title",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "mtw.Title()"
+ }
+ ]
+ },
+ {
+ "id": "Error Exiting WireGuard",
+ "message": "Error Exiting WireGuard",
+ "translation": "Erro ao sair do WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
+ "message": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
+ "translation": "Não é possível sair do serviço devido a: {Err}. Você pode querer parar o WireGuard do gerenciador de serviços.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "message": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "translation": "Uma atualização para o WireGuard está disponível. É altamente aconselhável atualizar sem demora.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Waiting for user",
+ "message": "Status: Waiting for user",
+ "translation": "Status: Aguardando o usuário",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Update Now",
+ "message": "Update Now",
+ "translation": "Atualizar agora",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Waiting for updater service",
+ "message": "Status: Waiting for updater service",
+ "translation": "Estado: Aguardando o serviço do atualizador",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error: {Err}. Please try again.",
+ "message": "Error: {Err}. Please try again.",
+ "translation": "Erro: {Err}. Por favor, tente novamente.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Status: Complete!",
+ "message": "Status: Complete!",
+ "translation": "Status da tarefa: Concluída!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "http2: Framer {F}: failed to decode just-written frame",
+ "message": "http2: Framer {F}: failed to decode just-written frame",
+ "translation": "http2: Framer {F}: falha ao decodificar o quadro recém-escrito",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "F",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "f"
+ }
+ ]
+ },
+ {
+ "id": "http2: Framer {F}: wrote {Http2summarizeFramefr}",
+ "message": "http2: Framer {F}: wrote {Http2summarizeFramefr}",
+ "translation": "http2: Framer {F}: escreveu {Http2summarizeFramefr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "F",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "f"
+ },
+ {
+ "id": "Http2summarizeFramefr",
+ "string": "%[2]v",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "http2summarizeFrame(fr)"
+ }
+ ]
+ },
+ {
+ "id": "http2: Framer {Fr}: read {Http2summarizeFramef}",
+ "message": "http2: Framer {Fr}: read {Http2summarizeFramef}",
+ "translation": "http2: Framer {Fr}: read {Http2summarizeFramef}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Fr",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "fr"
+ },
+ {
+ "id": "Http2summarizeFramef",
+ "string": "%[2]v",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "http2summarizeFrame(f)"
+ }
+ ]
+ },
+ {
+ "id": "http2: decoded hpack field {HeaderField}",
+ "message": "http2: decoded hpack field {HeaderField}",
+ "translation": "http2: campo hpack decodificado {HeaderField}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "HeaderField",
+ "string": "%+[1]v",
+ "type": "vendor/golang.org/x/net/http2/hpack.HeaderField",
+ "underlyingType": "struct{Name string; Value string; Sensitive bool}",
+ "argNum": 1,
+ "expr": "hf"
+ }
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/locales/ru/messages.gotext.json b/locales/ru/messages.gotext.json
index 9cc9b0f1..140869d2 100644
--- a/locales/ru/messages.gotext.json
+++ b/locales/ru/messages.gotext.json
@@ -4,7 +4,7 @@
{
"id": "Error",
"message": "Error",
- "translation": "Ошибка",
+ "translation": "Алдаа",
"translatorComment": "Copied from source."
},
{
@@ -16,7 +16,7 @@
{
"id": "Usage: {Args0} [\n{String}]",
"message": "Usage: {Args0} [\n{String}]",
- "translation": "Использование: {Args0} [\n{String}]",
+ "translation": "Хэрэглээ: {Args0} [\n{String}]",
"translatorComment": "Copied from source.",
"placeholders": [
{
@@ -40,13 +40,13 @@
{
"id": "Command Line Options",
"message": "Command Line Options",
- "translation": "Параметры командной строки",
+ "translation": "Коммандын мөрний сонголтууд",
"translatorComment": "Copied from source."
},
{
"id": "Unable to determine whether the process is running under WOW64: {Err}",
"message": "Unable to determine whether the process is running under WOW64: {Err}",
- "translation": "Ошибка определения или процесс работает как WOW64: {Err}",
+ "translation": "Процесс ажиллаж байгаа эсэхийг тодорхойлох боломжгүй байна\n WOW64: {Err}",
"translatorComment": "Copied from source.",
"placeholders": [
{
@@ -62,13 +62,13 @@
{
"id": "You must use the native version of WireGuard on this computer.",
"message": "You must use the native version of WireGuard on this computer.",
- "translation": "Используйте нативную версию WireGuard на этом компьютере.",
+ "translation": "Та энэ компьютер дээр WireGuard-ийн эх хувилбарыг ашиглах ёстой.",
"translatorComment": "Copied from source."
},
{
"id": "Unable to open current process token: {Err}",
"message": "Unable to open current process token: {Err}",
- "translation": "Не удается открыть токен текущего процесса: {Err}",
+ "translation": "Одоогийн процессын токеныг нээх боломжгүй байна: {Err}",
"translatorComment": "Copied from source.",
"placeholders": [
{
@@ -84,7 +84,7 @@
{
"id": "WireGuard may only be used by users who are a member of the Builtin {AdminGroupName} group.",
"message": "WireGuard may only be used by users who are a member of the Builtin {AdminGroupName} group.",
- "translation": "WireGuard может использоваться только пользователями, входящими в группу {AdminGroupName}.",
+ "translation": "WireGuard может использоваться только пользователями, входящими во встроенную группу {AdminGroupName}.",
"translatorComment": "Copied from source.",
"placeholders": [
{
@@ -116,19 +116,19 @@
{
"id": "WireGuard system tray icon did not appear after 30 seconds.",
"message": "WireGuard system tray icon did not appear after 30 seconds.",
- "translation": "Значок в системном трее WireGuard не появился после 30 секунд.",
+ "translation": "WireGuard системийн тавиурын дүрс 30 секундын дараа гарч ирсэнгүй.",
"translatorComment": "Copied from source."
},
{
"id": "Now",
"message": "Now",
- "translation": "Сейчас",
+ "translation": "Одоо",
"translatorComment": "Copied from source."
},
{
"id": "System clock wound backward!",
"message": "System clock wound backward!",
- "translation": "Системные часы переведены назад!",
+ "translation": "Системийн цаг хойшоо эргэж байна!",
"translatorComment": "Copied from source."
},
{
@@ -140,16 +140,16 @@
"arg": "Years",
"cases": {
"one": {
- "msg": "{Years}г"
+ "msg": "{Years} год"
},
"few": {
- "msg": "{Years}г"
+ "msg": "{Years} года"
},
"many": {
- "msg": "{Years}г"
+ "msg": "{Years} лет"
},
"other": {
- "msg": "{Years}г"
+ "msg": "{Years} лет"
}
}
}
@@ -174,16 +174,16 @@
"arg": "Days",
"cases": {
"one": {
- "msg": "{Days}д"
+ "msg": "{Days} день"
},
"few": {
- "msg": "{Days}д"
+ "msg": "{Days} дня"
},
"many": {
- "msg": "{Days}д"
+ "msg": "{Days} дней"
},
"other": {
- "msg": "{Days}д"
+ "msg": "{Days} дней"
}
}
}
@@ -208,16 +208,16 @@
"arg": "Hours",
"cases": {
"one": {
- "msg": "{Hours}ч"
+ "msg": "{Hours} час"
},
"few": {
- "msg": "{Hours}ч"
+ "msg": "{Hours} часа"
},
"many": {
- "msg": "{Hours}ч"
+ "msg": "{Hours} часов"
},
"other": {
- "msg": "{Hours}ч"
+ "msg": "{Hours} часов"
}
}
}
@@ -242,16 +242,16 @@
"arg": "Minutes",
"cases": {
"one": {
- "msg": "{Minutes}мин"
+ "msg": "{Minutes} минута"
},
"few": {
- "msg": "{Minutes}мин"
+ "msg": "{Minutes} минуты"
},
"many": {
- "msg": "{Minutes}мин"
+ "msg": "{Minutes} минут"
},
"other": {
- "msg": "{Minutes}мин"
+ "msg": "{Minutes} минут"
}
}
}
@@ -276,16 +276,16 @@
"arg": "Seconds",
"cases": {
"one": {
- "msg": "{Seconds}сек"
+ "msg": "{Seconds} секунда"
},
"few": {
- "msg": "{Seconds}сек"
+ "msg": "{Seconds} секунды"
},
"many": {
- "msg": "{Seconds}сек"
+ "msg": "{Seconds} секунд"
},
"other": {
- "msg": "{Seconds}сек"
+ "msg": "{Seconds} секунд"
}
}
}
@@ -336,7 +336,7 @@
{
"id": "{Float64b__1024} KiB",
"message": "{Float64b__1024} KiB",
- "translation": "{Float64b__1024} Кб",
+ "translation": "{Float64b__1024} КиБ",
"translatorComment": "Copied from source.",
"placeholders": [
{
@@ -352,7 +352,7 @@
{
"id": "{Float64b__1024__1024} MiB",
"message": "{Float64b__1024__1024} MiB",
- "translation": "{Float64b__1024__1024} Мб",
+ "translation": "{Float64b__1024__1024} МиБ",
"translatorComment": "Copied from source.",
"placeholders": [
{
@@ -368,7 +368,7 @@
{
"id": "{Float64b__1024__1024__1024} GiB",
"message": "{Float64b__1024__1024__1024} GiB",
- "translation": "{Float64b__1024__1024__1024} Гб",
+ "translation": "{Float64b__1024__1024__1024} ГиБ",
"translatorComment": "Copied from source.",
"placeholders": [
{
@@ -384,7 +384,7 @@
{
"id": "{Float64b__1024__1024__1024__1024} TiB",
"message": "{Float64b__1024__1024__1024__1024} TiB",
- "translation": "{Float64b__1024__1024__1024__1024} Тб",
+ "translation": "{Float64b__1024__1024__1024__1024} ТиБ",
"translatorComment": "Copied from source.",
"placeholders": [
{
@@ -436,7 +436,7 @@
{
"id": "Missing port from endpoint",
"message": "Missing port from endpoint",
- "translation": "Отсутствует порт IP-адреса сервера",
+ "translation": "Порт сервера не указан",
"translatorComment": "Copied from source."
},
{
@@ -448,7 +448,7 @@
{
"id": "Brackets must contain an IPv6 address",
"message": "Brackets must contain an IPv6 address",
- "translation": "В скобках должен быть IPv6 адрес",
+ "translation": "В скобках должен быть адрес IPv6",
"translatorComment": "Copied from source."
},
{
@@ -488,7 +488,7 @@
{
"id": "Keys must decode to exactly 32 bytes",
"message": "Keys must decode to exactly 32 bytes",
- "translation": "Ключи должны декодироваться ровно с 32 байтами",
+ "translation": "Ключи должны декодироваться ровно в 32 байта",
"translatorComment": "Copied from source."
},
{
@@ -516,7 +516,7 @@
{
"id": "Tunnel name is not valid",
"message": "Tunnel name is not valid",
- "translation": "Название туннеля недействительно",
+ "translation": "Неправильное имя туннеля",
"translatorComment": "Copied from source."
},
{
@@ -552,13 +552,13 @@
{
"id": "An interface must have a private key",
"message": "An interface must have a private key",
- "translation": "В Интерфейсе должен быть приватный ключ",
+ "translation": "Для интерфейса должен быть задан приватный ключ",
"translatorComment": "Copied from source."
},
{
"id": "[none specified]",
"message": "[none specified]",
- "translation": "[не указано]",
+ "translation": "[не указан]",
"translatorComment": "Copied from source."
},
{
@@ -576,7 +576,7 @@
{
"id": "Invalid key for interface section",
"message": "Invalid key for interface section",
- "translation": "Неверный ключ для секции Интерфейса",
+ "translation": "Неверный ключ для секции интерфейса",
"translatorComment": "Copied from source."
},
{
@@ -888,7 +888,7 @@
{
"id": "&Name:",
"message": "&Name:",
- "translation": "&Название:",
+ "translation": "&Имя:",
"translatorComment": "Copied from source."
},
{
@@ -906,7 +906,7 @@
{
"id": "&Block untunneled traffic (kill-switch)",
"message": "&Block untunneled traffic (kill-switch)",
- "translation": "&Блокировать нетуннелированный трафик",
+ "translation": "&Блокировать трафик, идущий мимо туннеля (kill-switch)",
"translatorComment": "Copied from source."
},
{
@@ -936,19 +936,19 @@
{
"id": "Invalid name",
"message": "Invalid name",
- "translation": "Некорректное название",
+ "translation": "Недопустимое имя",
"translatorComment": "Copied from source."
},
{
"id": "A name is required.",
"message": "A name is required.",
- "translation": "Необходимо название.",
+ "translation": "Требуется имя.",
"translatorComment": "Copied from source."
},
{
"id": "Tunnel name ‘{NewName}’ is invalid.",
"message": "Tunnel name ‘{NewName}’ is invalid.",
- "translation": "Название туннеля ‘{NewName}’ недопустимо.",
+ "translation": "Имя туннеля ‘{NewName}’ недопустимо.",
"translatorComment": "Copied from source.",
"placeholders": [
{
@@ -998,13 +998,13 @@
{
"id": "Writing file failed",
"message": "Writing file failed",
- "translation": "Ошибка записи файла",
+ "translation": "Ошибка при записи в файл",
"translatorComment": "Copied from source."
},
{
"id": "File ‘{FilePath}’ already exists.\n\nDo you want to overwrite it?",
"message": "File ‘{FilePath}’ already exists.\n\nDo you want to overwrite it?",
- "translation": "Файл '{FilePath}' уже существует!\n\nВы хотите перезаписать его?",
+ "translation": "Файл ‘{FilePath}’ уже существует!\n\nВы хотите перезаписать его?",
"translatorComment": "Copied from source.",
"placeholders": [
{
@@ -1056,7 +1056,7 @@
{
"id": "&Copy",
"message": "&Copy",
- "translation": "&Скопировать",
+ "translation": "&Копировать",
"translatorComment": "Copied from source."
},
{
@@ -1164,13 +1164,13 @@
{
"id": "WireGuard: Deactivated",
"message": "WireGuard: Deactivated",
- "translation": "WireGuard: Деактивирован",
+ "translation": "WireGuard: деактивирован",
"translatorComment": "Copied from source."
},
{
"id": "Status: Unknown",
"message": "Status: Unknown",
- "translation": "Статус: Неизвестен",
+ "translation": "Статус: неизвестен",
"translatorComment": "Copied from source."
},
{
@@ -1206,7 +1206,7 @@
{
"id": "WireGuard Activated",
"message": "WireGuard Activated",
- "translation": "WireGuard Включен",
+ "translation": "WireGuard включен",
"translatorComment": "Copied from source."
},
{
@@ -1228,7 +1228,7 @@
{
"id": "WireGuard Deactivated",
"message": "WireGuard Deactivated",
- "translation": "WireGuard Выключен",
+ "translation": "WireGuard выключен",
"translatorComment": "Copied from source."
},
{
@@ -1464,16 +1464,16 @@
"arg": "M",
"cases": {
"one": {
- "msg": "Импортированный {M} туннель"
+ "msg": "Импортирован {M} туннель"
},
"few": {
- "msg": "Импортированы туннели: {M}"
+ "msg": "Импортированы {M} туннеля"
},
"many": {
- "msg": "Импортированы туннели: {M}"
+ "msg": "Импортировано {M} туннелей"
},
"other": {
- "msg": "Импортированы туннели: {M}"
+ "msg": "Импортировано {M} туннелей"
}
}
}
@@ -1498,16 +1498,16 @@
"arg": "N",
"cases": {
"one": {
- "msg": "Импортированы туннели: {M} из {N}"
+ "msg": "Импортирован {M} из {N} туннелей"
},
"few": {
- "msg": "Импортированы туннели: {M} из {N}"
+ "msg": "Импортированы {M} из {N} туннелей"
},
"many": {
- "msg": "Импортированы туннели: {M} из {N}"
+ "msg": "Импортировано {M} из {N} туннелей"
},
"other": {
- "msg": "Импортированы туннели: {M} из {N}"
+ "msg": "Импортировано {M} из {N} туннелей"
}
}
}
@@ -1549,13 +1549,13 @@
"msg": "Удалить {TunnelCount} туннель"
},
"few": {
- "msg": "Удалить туннели: {TunnelCount}"
+ "msg": "Удалить {TunnelCount} туннеля"
},
"many": {
- "msg": "Удалить туннели: {TunnelCount}"
+ "msg": "Удалить {TunnelCount} туннелей"
},
"other": {
- "msg": "Удалить туннели: {TunnelCount}"
+ "msg": "Удалить {TunnelCount} туннелей"
}
}
}
@@ -1583,13 +1583,13 @@
"msg": "Вы уверены, что хотите удалить {TunnelCount} туннель?"
},
"few": {
- "msg": "Вы уверены, что хотите удалить туннели: {TunnelCount}?"
+ "msg": "Вы уверены, что хотите удалить {TunnelCount} туннеля?"
},
"many": {
- "msg": "Вы уверены, что хотите удалить туннели: {TunnelCount}?"
+ "msg": "Вы уверены, что хотите удалить {TunnelCount} туннелей?"
},
"other": {
- "msg": "Вы уверены, что хотите удалить туннели: {TunnelCount}?"
+ "msg": "Вы уверены, что хотите удалить {TunnelCount} туннелей?"
}
}
}
@@ -1624,7 +1624,7 @@
{
"id": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
"message": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
- "translation": "Вы уверены, что хотите удалить '{TunnelName}' туннель?",
+ "translation": "Вы уверены, что хотите удалить ‘{TunnelName}’ туннель?",
"translatorComment": "Copied from source.",
"placeholders": [
{
@@ -1693,13 +1693,13 @@
"msg": "{Lenerrors} туннель не удалось удалить."
},
"few": {
- "msg": "туннелей не удалось удалить: {Lenerrors}"
+ "msg": "{Lenerrors} туннеля не удалось удалить."
},
"many": {
- "msg": "туннелей не удалось удалить: {Lenerrors}"
+ "msg": "{Lenerrors} туннелей не удалось удалить."
},
"other": {
- "msg": "туннелей не удалось удалить: {Lenerrors}"
+ "msg": "{Lenerrors} туннелей не удалось удалить."
}
}
}
@@ -1730,7 +1730,7 @@
{
"id": "Configuration ZIP Files (*.zip)|*.zip",
"message": "Configuration ZIP Files (*.zip)|*.zip",
- "translation": "Конфигурация ZIP файлов (*.zip)|*.zip",
+ "translation": "ZIP-файлы конфигурации (*.zip)|*.zip",
"translatorComment": "Copied from source."
},
{
@@ -1758,13 +1758,13 @@
{
"id": "Error Exiting WireGuard",
"message": "Error Exiting WireGuard",
- "translation": "Ошибка выхода из WireGuard",
+ "translation": "Ошибка при завершении WireGuard",
"translatorComment": "Copied from source."
},
{
"id": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
"message": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
- "translation": "Не удается выйти из сервиса из-за: {Err}. Вы можете остановить WireGuard из менеджера служб.",
+ "translation": "Не удалось завершить службу: {Err}. Вы можете остановить WireGuard вручную из оснастки Службы.",
"translatorComment": "Copied from source.",
"placeholders": [
{
@@ -1786,19 +1786,19 @@
{
"id": "Status: Waiting for user",
"message": "Status: Waiting for user",
- "translation": "Статус: Ожидание пользователя",
+ "translation": "Статус: ожидание пользователя",
"translatorComment": "Copied from source."
},
{
"id": "Update Now",
"message": "Update Now",
- "translation": "Обновить Сейчас",
+ "translation": "Обновить сейчас",
"translatorComment": "Copied from source."
},
{
"id": "Status: Waiting for updater service",
"message": "Status: Waiting for updater service",
- "translation": "Статус: Ожидание обновления",
+ "translation": "Статус: ожидание обновления",
"translatorComment": "Copied from source."
},
{
@@ -1820,13 +1820,13 @@
{
"id": "Status: Complete!",
"message": "Status: Complete!",
- "translation": "Статус: Завершено!",
+ "translation": "Статус: завершено!",
"translatorComment": "Copied from source."
},
{
"id": "http2: Framer {F}: failed to decode just-written frame",
"message": "http2: Framer {F}: failed to decode just-written frame",
- "translation": "http2: Framer {F}: не удалось декодировать только что записанный кадр",
+ "translation": "http2: Framer {F}: не удалось декодировать только что записанный фрейм",
"translatorComment": "Copied from source.",
"placeholders": [
{
diff --git a/locales/si-LK/messages.gotext.json b/locales/si-LK/messages.gotext.json
new file mode 100644
index 00000000..639aafec
--- /dev/null
+++ b/locales/si-LK/messages.gotext.json
@@ -0,0 +1,1831 @@
+{
+ "language": "si-LK",
+ "messages": [
+ {
+ "id": "Error",
+ "message": "Error",
+ "translation": "දෝෂයකි",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "(no argument): elevate and install manager service",
+ "message": "(no argument): elevate and install manager service",
+ "translation": "(තර්කයක් නැත): කළමනාකරු සේවාව ඉහළ නැංවීම සහ ස්ථාපනය කිරීම",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Usage: {Args0} [\n{String}]",
+ "message": "Usage: {Args0} [\n{String}]",
+ "translation": "භාවිතය: {Args0} [\n{String}]",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Args0",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "os.Args[0]"
+ },
+ {
+ "id": "String",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "builder.String()"
+ }
+ ]
+ },
+ {
+ "id": "Command Line Options",
+ "message": "Command Line Options",
+ "translation": "විධාන රේඛා විකල්ප",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to determine whether the process is running under WOW64: {Err}",
+ "message": "Unable to determine whether the process is running under WOW64: {Err}",
+ "translation": "ක්‍රියාවලිය WOW64: {Err}යටතේ ක්‍රියාත්මක වේද යන්න තීරණය කළ නොහැක",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "You must use the native version of WireGuard on this computer.",
+ "message": "You must use the native version of WireGuard on this computer.",
+ "translation": "ඔබ මෙම පරිගණකයේ WireGuard හි දේශීය අනුවාදය භාවිතා කළ යුතුය.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to open current process token: {Err}",
+ "message": "Unable to open current process token: {Err}",
+ "translation": "වත්මන් ක්‍රියාවලි ටෝකනය විවෘත කළ නොහැක: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard may only be used by users who are a member of the Builtin {AdminGroupName} group.",
+ "message": "WireGuard may only be used by users who are a member of the Builtin {AdminGroupName} group.",
+ "translation": "WireGuard භාවිතා කළ හැක්කේ Builtin {AdminGroupName} කණ්ඩායමේ සාමාජිකයෙකු වන පරිශීලකයින් විසින් පමණි.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "AdminGroupName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "elevate.AdminGroupName()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard is running, but the UI is only accessible from desktops of the Builtin {AdminGroupName} group.",
+ "message": "WireGuard is running, but the UI is only accessible from desktops of the Builtin {AdminGroupName} group.",
+ "translation": "WireGuard ක්‍රියාත්මක වේ, නමුත් UI ප්‍රවේශ විය හැක්කේ Builtin {AdminGroupName} කාණ්ඩයේ ඩෙස්ක්ටොප් වලින් පමණි.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "AdminGroupName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "elevate.AdminGroupName()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard system tray icon did not appear after 30 seconds.",
+ "message": "WireGuard system tray icon did not appear after 30 seconds.",
+ "translation": "WireGuard පද්ධති තැටි නිරූපකය තත්පර 30කට පසුව දිස් නොවීය.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Now",
+ "message": "Now",
+ "translation": "දැන්",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "System clock wound backward!",
+ "message": "System clock wound backward!",
+ "translation": "පද්ධති ඔරලෝසුව පසුපසට තුවාල වී ඇත!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Years} year(s)",
+ "message": "{Years} year(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Years",
+ "cases": {
+ "one": {
+ "msg": "අවුරුදු {Years}"
+ },
+ "other": {
+ "msg": "අවුරුදු {Years}"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Years",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "years"
+ }
+ ]
+ },
+ {
+ "id": "{Days} day(s)",
+ "message": "{Days} day(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Days",
+ "cases": {
+ "one": {
+ "msg": "දවස් {Days}"
+ },
+ "other": {
+ "msg": "දවස් {Days}"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Days",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "days"
+ }
+ ]
+ },
+ {
+ "id": "{Hours} hour(s)",
+ "message": "{Hours} hour(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Hours",
+ "cases": {
+ "one": {
+ "msg": "පැය {Hours}"
+ },
+ "other": {
+ "msg": "පැය {Hours}"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Hours",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "hours"
+ }
+ ]
+ },
+ {
+ "id": "{Minutes} minute(s)",
+ "message": "{Minutes} minute(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Minutes",
+ "cases": {
+ "one": {
+ "msg": "විනාඩි {Minutes}"
+ },
+ "other": {
+ "msg": "විනාඩි {Minutes}"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Minutes",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "minutes"
+ }
+ ]
+ },
+ {
+ "id": "{Seconds} second(s)",
+ "message": "{Seconds} second(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Seconds",
+ "cases": {
+ "one": {
+ "msg": "තත්පර {Seconds}"
+ },
+ "other": {
+ "msg": "තත්පර {Seconds}"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Seconds",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "seconds"
+ }
+ ]
+ },
+ {
+ "id": "{Timestamp} ago",
+ "message": "{Timestamp} ago",
+ "translation": "{Timestamp} ට පෙර",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Timestamp",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "timestamp"
+ }
+ ]
+ },
+ {
+ "id": "{Bytes} B",
+ "message": "{Bytes} B",
+ "translation": "බ. {Bytes}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Bytes",
+ "string": "%[1]d",
+ "type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
+ "underlyingType": "uint64",
+ "argNum": 1,
+ "expr": "b"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024} KiB",
+ "message": "{Float64b__1024} KiB",
+ "translation": "කි.බ. {Float64b__1024}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / 1024"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024} MiB",
+ "message": "{Float64b__1024__1024} MiB",
+ "translation": "මෙ.බ. {Float64b__1024__1024}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024} GiB",
+ "message": "{Float64b__1024__1024__1024} GiB",
+ "translation": "ගි.බ. {Float64b__1024__1024__1024}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024__1024} TiB",
+ "message": "{Float64b__1024__1024__1024__1024} TiB",
+ "translation": "ටෙ.බ. {Float64b__1024__1024__1024__1024}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024) / 1024"
+ }
+ ]
+ },
+ {
+ "id": "{Why}: {Offender}",
+ "message": "{Why}: {Offender}",
+ "translation": "{Why}: {Offender}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Why",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "e.why"
+ },
+ {
+ "id": "Offender",
+ "string": "%[2]q",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "e.offender"
+ }
+ ]
+ },
+ {
+ "id": "Invalid IP address",
+ "message": "Invalid IP address",
+ "translation": "අ.ජා.කෙ. වලංගු නොවේ",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid network prefix length",
+ "message": "Invalid network prefix length",
+ "translation": "වලංගු නොවන ජාල උපසර්ග දිග",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Missing port from endpoint",
+ "message": "Missing port from endpoint",
+ "translation": "අන්ත ලක්ෂ්‍යයෙන් වරාය අස්ථානගත වී ඇත",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid endpoint host",
+ "message": "Invalid endpoint host",
+ "translation": "අවලංගු අන්ත ලක්ෂ්‍ය ධාරකයකි",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Brackets must contain an IPv6 address",
+ "message": "Brackets must contain an IPv6 address",
+ "translation": "වරහන් වල IPv6 ලිපිනයක් අඩංගු විය යුතුය",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid MTU",
+ "message": "Invalid MTU",
+ "translation": "වලංගු නොවන MTU",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid port",
+ "message": "Invalid port",
+ "translation": "තොට වලංගු නොවේ",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid persistent keepalive",
+ "message": "Invalid persistent keepalive",
+ "translation": "වලංගු නොවන නොනැසී පැවතීම",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key: {Err}",
+ "message": "Invalid key: {Err}",
+ "translation": "වලංගු නොවන යතුර: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Keys must decode to exactly 32 bytes",
+ "message": "Keys must decode to exactly 32 bytes",
+ "translation": "යතුරු හරියටම බයිට් 32කට විකේතනය කළ යුතුය",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Number must be a number between 0 and 2^64-1: {Err}",
+ "message": "Number must be a number between 0 and 2^64-1: {Err}",
+ "translation": "අංකය 0 සහ 2^64-1: {Err}අතර අංකයක් විය යුතුය",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Two commas in a row",
+ "message": "Two commas in a row",
+ "translation": "පේළියකට අල්පවිරාම දෙකක්",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel name is not valid",
+ "message": "Tunnel name is not valid",
+ "translation": "උමං නම වලංගු නැත",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Line must occur in a section",
+ "message": "Line must occur in a section",
+ "translation": "රේඛාව කොටසක ඇති විය යුතුය",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Config key is missing an equals separator",
+ "message": "Config key is missing an equals separator",
+ "translation": "වින්‍යාස යතුර සමාන බෙදුම්කරුවෙකු අස්ථානගත වී ඇත",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Key must have a value",
+ "message": "Key must have a value",
+ "translation": "යතුරට අගයක් තිබිය යුතුය",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for [Interface] section",
+ "message": "Invalid key for [Interface] section",
+ "translation": "[Interface] කොටස සඳහා වලංගු නොවන යතුර",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for [Peer] section",
+ "message": "Invalid key for [Peer] section",
+ "translation": "[Peer] කොටස සඳහා වලංගු නොවන යතුර",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "An interface must have a private key",
+ "message": "An interface must have a private key",
+ "translation": "අතුරුමුහුතකට පුද්. යතුරක් තිබිය යුතුය",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "[none specified]",
+ "message": "[none specified]",
+ "translation": "[කිසිවක් සඳහන් කර නැත]",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "All peers must have public keys",
+ "message": "All peers must have public keys",
+ "translation": "සියලුම සම වයසේ මිතුරන්ට පොදු යතුරු තිබිය යුතුය",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error in getting configuration",
+ "message": "Error in getting configuration",
+ "translation": "වින්‍යාසය ලබා ගැනීමේ දෝෂයකි",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for interface section",
+ "message": "Invalid key for interface section",
+ "translation": "අතුරු මුහුණත කොටස සඳහා වලංගු නොවන යතුර",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Protocol version must be 1",
+ "message": "Protocol version must be 1",
+ "translation": "කෙටුම්පතෙහි අනු. 1 විය යුතුය",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for peer section",
+ "message": "Invalid key for peer section",
+ "translation": "සම වයසේ කොටස සඳහා වලංගු නොවන යතුරක්",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "[EnumerationSeparator]",
+ "message": "[EnumerationSeparator]",
+ "translation": ", ",
+ "comment": "Text to insert between items when listing - most western languages will translate ‘[EnumerationSeparator]’ into ‘, ’ to produce lists like ‘apple, orange, strawberry’. Eastern languages might translate into ‘、’ to produce lists like ‘リンゴ、オレンジ、イチゴ’."
+ },
+ {
+ "id": "[UnitSeparator]",
+ "message": "[UnitSeparator]",
+ "translation": ", ",
+ "comment": "Text to insert when combining units of a measure - most languages will translate ‘[UnitSeparator]’ into ‘ ’ (space) to produce lists like ‘2 minuti 30 sekund’, or empty string ‘’ to produce ‘2分30秒’."
+ },
+ {
+ "id": "About WireGuard",
+ "message": "About WireGuard",
+ "translation": "වයර්ගාඩ් ගැන",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard logo image",
+ "message": "WireGuard logo image",
+ "translation": "WireGuard ලාංඡන රූපය",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "message": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "translation": "යෙදුම් අනුවාදය: {Number}\nGo backend අනුවාදය: {WireGuardGoVersion}\nGo අනුවාදය: {Version_go}-{GOARCH}\nමෙහෙයුම් පද්ධතිය: {OsName}\nගෘහ නිර්මාණ ශිල්පය: {NativeArch}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Number",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "version.Number"
+ },
+ {
+ "id": "WireGuardGoVersion",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "device.WireGuardGoVersion"
+ },
+ {
+ "id": "Version_go",
+ "string": "%[3]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 3,
+ "expr": "strings.TrimPrefix(runtime.Version(), \"go\")"
+ },
+ {
+ "id": "GOARCH",
+ "string": "%[4]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 4,
+ "expr": "runtime.GOARCH"
+ },
+ {
+ "id": "OsName",
+ "string": "%[5]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 5,
+ "expr": "version.OsName()"
+ },
+ {
+ "id": "NativeArch",
+ "string": "%[6]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 6,
+ "expr": "version.NativeArch()"
+ }
+ ]
+ },
+ {
+ "id": "Close",
+ "message": "Close",
+ "translation": "වසන්න",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "♥ &Donate!",
+ "message": "♥ &Donate!",
+ "translation": "♥ &පරිත්‍යාග!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status:",
+ "message": "Status:",
+ "translation": "තත්‍වය:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Deactivate",
+ "message": "&Deactivate",
+ "translation": "&අක්‍රිය කරන්න",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Activate",
+ "message": "&Activate",
+ "translation": "&සක්රිය කරන්න",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Public key:",
+ "message": "Public key:",
+ "translation": "පොදු යතුර:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Listen port:",
+ "message": "Listen port:",
+ "translation": "සවන්දීමේ තොට:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "MTU:",
+ "message": "MTU:",
+ "translation": "MTU:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Addresses:",
+ "message": "Addresses:",
+ "translation": "ලිපින:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "DNS servers:",
+ "message": "DNS servers:",
+ "translation": "ව.නා.ප. සේවාදායක:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Scripts:",
+ "message": "Scripts:",
+ "translation": "ස්ක්‍රිප්ට්:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Preshared key:",
+ "message": "Preshared key:",
+ "translation": "පෙර බෙදාගත් යතුර:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Allowed IPs:",
+ "message": "Allowed IPs:",
+ "translation": "ඉඩදුන් අ.ජා.කෙ.:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Endpoint:",
+ "message": "Endpoint:",
+ "translation": "අන්ත ලක්ෂ්‍යය:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Persistent keepalive:",
+ "message": "Persistent keepalive:",
+ "translation": "නොනැසී පැවතීම:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Latest handshake:",
+ "message": "Latest handshake:",
+ "translation": "නවතම අතට අත දීම:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Transfer:",
+ "message": "Transfer:",
+ "translation": "මාරු:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-up",
+ "message": "pre-up",
+ "translation": "පූර්ව-අප්",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-up",
+ "message": "post-up",
+ "translation": "පශ්චාත්-අප්",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-down",
+ "message": "pre-down",
+ "translation": "පෙර-පහළට",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-down",
+ "message": "post-down",
+ "translation": "පශ්චාත්-පහළ",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "disabled, per policy",
+ "message": "disabled, per policy",
+ "translation": "ආබාධිත, ප්රතිපත්තිය අනුව",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "enabled",
+ "message": "enabled",
+ "translation": "සබලයි",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{String} received, {String_1} sent",
+ "message": "{String} received, {String_1} sent",
+ "translation": "{String} ලැබුණී, {String_1} යැවිණි",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "String",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "c.RxBytes.String()"
+ },
+ {
+ "id": "String_1",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "c.TxBytes.String()"
+ }
+ ]
+ },
+ {
+ "id": "Failed to determine tunnel state",
+ "message": "Failed to determine tunnel state",
+ "translation": "උමං තත්ත්වය තීරණය කිරීමට අසමත් විය",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Failed to activate tunnel",
+ "message": "Failed to activate tunnel",
+ "translation": "උමග සක්රිය කිරීමට අසමත් විය",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Failed to deactivate tunnel",
+ "message": "Failed to deactivate tunnel",
+ "translation": "උමග අක්‍රිය කිරීමට අසමත් විය",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Interface: {Name}",
+ "message": "Interface: {Name}",
+ "translation": "අතුරුමුහුණත: {Name}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "config.Name"
+ }
+ ]
+ },
+ {
+ "id": "Peer",
+ "message": "Peer",
+ "translation": "සම වයසේ මිතුරන්",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Create new tunnel",
+ "message": "Create new tunnel",
+ "translation": "නව උමගක් සාදන්න",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Edit tunnel",
+ "message": "Edit tunnel",
+ "translation": "උමග සංස්කරණය කරන්න",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Name:",
+ "message": "&Name:",
+ "translation": "&නම:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Public key:",
+ "message": "&Public key:",
+ "translation": "&පොදු යතුර:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "(unknown)",
+ "message": "(unknown)",
+ "translation": "(නොදනී)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Block untunneled traffic (kill-switch)",
+ "message": "&Block untunneled traffic (kill-switch)",
+ "translation": "&උමං මාර්ග රහිත ගමනාගමනය අවහිර කරන්න (මරන්න-ස්විච්)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "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 or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "message": "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 or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "translation": "වින්‍යාසයකට හරියටම එක් මිතුරෙකු සිටින විට සහ එම සම වයසේ මිතුරෙකුට අවම වශයෙන් 0.0.0.0/0 හෝ ::/0 න් එකක් අඩංගු අවසර ලත් IPs තිබේ නම්, එවිට උමං සේවාව ෆයර්වෝල් නීති පද්ධතියක් සමඟ සම්බන්ධ වන අතර එමඟින් එම ස්ථානයට හෝ ඉන් පිටතට නොවන සියලුම ගමනාගමනය අවහිර කරයි. DHCP සහ NDP සඳහා විශේෂ ව්‍යතිරේක සහිතව උමං අතුරුමුහුණත හෝ වැරදි DNS සේවාදායකය වෙත වේ.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Save",
+ "message": "&Save",
+ "translation": "&සුරකින්න",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Cancel",
+ "message": "Cancel",
+ "translation": "අවලංගු",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Configuration:",
+ "message": "&Configuration:",
+ "translation": "&වින්‍යාසය:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid name",
+ "message": "Invalid name",
+ "translation": "වලංගු නොවන නමකි",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "A name is required.",
+ "message": "A name is required.",
+ "translation": "නමක් අවශ්‍යයි.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel name ‘{NewName}’ is invalid.",
+ "message": "Tunnel name ‘{NewName}’ is invalid.",
+ "translation": "උමං නම '{NewName}' වලංගු නැත.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "NewName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "newName"
+ }
+ ]
+ },
+ {
+ "id": "Unable to list existing tunnels",
+ "message": "Unable to list existing tunnels",
+ "translation": "පවතින උමං ලැයිස්තුගත කළ නොහැක",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel already exists",
+ "message": "Tunnel already exists",
+ "translation": "උමග දැනටමත් පවතී",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Another tunnel already exists with the name ‘{NewName}’.",
+ "message": "Another tunnel already exists with the name ‘{NewName}’.",
+ "translation": "තවත් උමගක් දැනටමත් '{NewName}' යන නාමයෙන් පවතී.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "NewName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "newName"
+ }
+ ]
+ },
+ {
+ "id": "Unable to create new configuration",
+ "message": "Unable to create new configuration",
+ "translation": "නව වින්‍යාසය සෑදීමට නොහැකියි",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Writing file failed",
+ "message": "Writing file failed",
+ "translation": "ගොනුව ලිවීමට අසමත්විය",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "File ‘{FilePath}’ already exists.\n\nDo you want to overwrite it?",
+ "message": "File ‘{FilePath}’ already exists.\n\nDo you want to overwrite it?",
+ "translation": "'{FilePath}' ගොනුව දැනටමත් පවතී.\n\nඔබට එය උඩින් ලිවීමට අවශ්‍යද?",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "FilePath",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "filePath"
+ }
+ ]
+ },
+ {
+ "id": "Active",
+ "message": "Active",
+ "translation": "ක්රියාකාරී",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Activating",
+ "message": "Activating",
+ "translation": "සක්‍රිය වෙමින්",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Inactive",
+ "message": "Inactive",
+ "translation": "අක්රියයි",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Deactivating",
+ "message": "Deactivating",
+ "translation": "අක්රිය කිරීම",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unknown state",
+ "message": "Unknown state",
+ "translation": "නොදන්නා තත්‍වයකි",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Log",
+ "message": "Log",
+ "translation": "සටහන",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Copy",
+ "message": "&Copy",
+ "translation": "&පිටපතක්",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Select &all",
+ "message": "Select &all",
+ "translation": "&සියල්ල තෝරන්න",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Save to file…",
+ "message": "&Save to file…",
+ "translation": "&ගොනුවකට සුරකින්න…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Time",
+ "message": "Time",
+ "translation": "වේලාව",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Log message",
+ "message": "Log message",
+ "translation": "ලොග් පණිවිඩය",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "message": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "translation": "පෙළ ගොනු (*.txt)|*.txt|සියලු ගොනු (*.*)|*.*",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export log to file",
+ "message": "Export log to file",
+ "translation": "ලොගය ගොනුවට අපනයනය කරන්න",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&About WireGuard…",
+ "message": "&About WireGuard…",
+ "translation": "&වයර්ගාඩ් ගැන…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel Error",
+ "message": "Tunnel Error",
+ "translation": "උමං දෝෂය",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "message": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "translation": "{ErrMsg}\n\nවැඩි විස්තර සඳහා කරුණාකර ලඝු-සටහන බලන්න.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "ErrMsg",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errMsg"
+ }
+ ]
+ },
+ {
+ "id": "{Title} (out of date)",
+ "message": "{Title} (out of date)",
+ "translation": "{Title} (ඉකුත් වී ඇත)",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Title",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "mtw.Title()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Detection Error",
+ "message": "WireGuard Detection Error",
+ "translation": "WireGuard හඳුනාගැනීමේ දෝෂය",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to wait for WireGuard window to appear: {Err}",
+ "message": "Unable to wait for WireGuard window to appear: {Err}",
+ "translation": "වයර්ගාඩ් කවුළුව පෙනෙන තෙක් බලා සිටීමට බලාපොරොත්තු වේ: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard: Deactivated",
+ "message": "WireGuard: Deactivated",
+ "translation": "WireGuard: අක්‍රිය කර ඇත",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Unknown",
+ "message": "Status: Unknown",
+ "translation": "තත්‍වය: නොදනී",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Addresses: None",
+ "message": "Addresses: None",
+ "translation": "ලිපින: කිසිත් නැත",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Manage tunnels…",
+ "message": "&Manage tunnels…",
+ "translation": "&උමං…කළමනාකරණය කරන්න",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Import tunnel(s) from file…",
+ "message": "&Import tunnel(s) from file…",
+ "translation": "…ගොනුවෙන් උමං(ය) &ආයාත කරන්න",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "E&xit",
+ "message": "E&xit",
+ "translation": "පි&ටවන්න",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Tunnels",
+ "message": "&Tunnels",
+ "translation": "&උමං මාර්ග",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Activated",
+ "message": "WireGuard Activated",
+ "translation": "වයර්ගාඩ් ක්‍රියාත්මකයි",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "The {Name} tunnel has been activated.",
+ "message": "The {Name} tunnel has been activated.",
+ "translation": "{Name} උමග සක්රිය කර ඇත.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnel.Name"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Deactivated",
+ "message": "WireGuard Deactivated",
+ "translation": "WireGuard අක්රිය කර ඇත",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "The {Name} tunnel has been deactivated.",
+ "message": "The {Name} tunnel has been deactivated.",
+ "translation": "{Name} උමං මාර්ගය අක්‍රිය කර ඇත.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnel.Name"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Tunnel Error",
+ "message": "WireGuard Tunnel Error",
+ "translation": "WireGuard උමං දෝෂය",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: {StateText}",
+ "message": "Status: {StateText}",
+ "translation": "තත්‍වය: {StateText}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "StateText",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "stateText"
+ }
+ ]
+ },
+ {
+ "id": "Addresses: {EnumerationSeparator}",
+ "message": "Addresses: {EnumerationSeparator}",
+ "translation": "ලිපින: {EnumerationSeparator}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "EnumerationSeparator",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "strings.Join(addrs, l18n.EnumerationSeparator())"
+ }
+ ]
+ },
+ {
+ "id": "An Update is Available!",
+ "message": "An Update is Available!",
+ "translation": "යාවත්කාලීනයක් තිබේ!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Update Available",
+ "message": "WireGuard Update Available",
+ "translation": "WireGuard යාවත්කාලීනය තිබේ",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "An update to WireGuard is now available. You are advised to update as soon as possible.",
+ "message": "An update to WireGuard is now available. You are advised to update as soon as possible.",
+ "translation": "WireGuard වෙත යාවත්කාලීනයක් දැන් තිබේ. හැකි ඉක්මනින් යාවත්කාලීන කිරීමට ඔබට උපදෙස් දෙනු ලැබේ.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnels",
+ "message": "Tunnels",
+ "translation": "උමං මාර්ග",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Edit",
+ "message": "&Edit",
+ "translation": "&සංස්කරණය",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Add &empty tunnel…",
+ "message": "Add &empty tunnel…",
+ "translation": "හිස් උමං…එකතු කරන්න",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Add Tunnel",
+ "message": "Add Tunnel",
+ "translation": "උමග එකතු කරන්න",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Remove selected tunnel(s)",
+ "message": "Remove selected tunnel(s)",
+ "translation": "තෝරාගත් උමං(ය) ඉවත් කරන්න",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export all tunnels to zip",
+ "message": "Export all tunnels to zip",
+ "translation": "සියලුම උමං zip වෙත අපනයනය කරන්න",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Toggle",
+ "message": "&Toggle",
+ "translation": "&ටොගල් කරන්න",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export all tunnels to &zip…",
+ "message": "Export all tunnels to &zip…",
+ "translation": "සියලුම උමං &zip…වෙත අපනයනය කරන්න",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Edit &selected tunnel…",
+ "message": "Edit &selected tunnel…",
+ "translation": "සංස්කරණය &තෝරාගත් උමග…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Remove selected tunnel(s)",
+ "message": "&Remove selected tunnel(s)",
+ "translation": "&තෝරාගත් උමං(ය) ඉවත් කරන්න",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "no configuration files were found",
+ "message": "no configuration files were found",
+ "translation": "වින්‍යාස ගොනු කිසිවක් හමු නොවිණි",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Could not import selected configuration: {LastErr}",
+ "message": "Could not import selected configuration: {LastErr}",
+ "translation": "තෝරාගත් වින්‍යාසය ආයාත කළ නොහැක: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Could not enumerate existing tunnels: {LastErr}",
+ "message": "Could not enumerate existing tunnels: {LastErr}",
+ "translation": "පවතින උමං මාර්ග ගණනය කළ නොහැක: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Another tunnel already exists with the name ‘{Name}’",
+ "message": "Another tunnel already exists with the name ‘{Name}’",
+ "translation": "තවත් උමගක් දැනටමත් '{Name}' නමින් පවතී",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "unparsedConfig.Name"
+ }
+ ]
+ },
+ {
+ "id": "Unable to import configuration: {LastErr}",
+ "message": "Unable to import configuration: {LastErr}",
+ "translation": "වින්‍යාසය ආයාත කළ නොහැකිය: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Imported tunnels",
+ "message": "Imported tunnels",
+ "translation": "ආනයනික උමං මාර්ග",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Imported {M} tunnels",
+ "message": "Imported {M} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "M",
+ "cases": {
+ "one": {
+ "msg": "උමං {M} ආනයනය කරන ලදී"
+ },
+ "other": {
+ "msg": "උමං {M} ක් ආනයනය කරන ලදී"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ }
+ ]
+ },
+ {
+ "id": "Imported {M} of {N} tunnels",
+ "message": "Imported {M} of {N} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "N",
+ "cases": {
+ "one": {
+ "msg": "උමං {N} කින් {M} ක් ආනයනය කරන ලදී"
+ },
+ "other": {
+ "msg": "උමං {N} කින් {M} ක් ආනයනය කරන ලදී"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ },
+ {
+ "id": "N",
+ "string": "%[2]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 2,
+ "expr": "n"
+ }
+ ]
+ },
+ {
+ "id": "Unable to create tunnel",
+ "message": "Unable to create tunnel",
+ "translation": "උමග නිර්මාණය කළ නොහැක",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Delete {TunnelCount} tunnels",
+ "message": "Delete {TunnelCount} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "TunnelCount",
+ "cases": {
+ "one": {
+ "msg": "{TunnelCount} උමග මකන්න"
+ },
+ "other": {
+ "msg": "උමං {TunnelCount} ක් මකන්න"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "TunnelCount",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "tunnelCount"
+ }
+ ]
+ },
+ {
+ "id": "Are you sure you would like to delete {TunnelCount} tunnels?",
+ "message": "Are you sure you would like to delete {TunnelCount} tunnels?",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "TunnelCount",
+ "cases": {
+ "one": {
+ "msg": "ඔබ {TunnelCount} උමග මැකීමට කැමති බව විශ්වාසද?"
+ },
+ "other": {
+ "msg": "ඔබ උමං මාර්ග {TunnelCount} ක් මැකීමට කැමති බව විශ්වාසද?"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "TunnelCount",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "tunnelCount"
+ }
+ ]
+ },
+ {
+ "id": "Delete tunnel ‘{TunnelName}’",
+ "message": "Delete tunnel ‘{TunnelName}’",
+ "translation": "උමං '{TunnelName}' මකන්න",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TunnelName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnelName"
+ }
+ ]
+ },
+ {
+ "id": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
+ "message": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
+ "translation": "ඔබ '{TunnelName}' උමඟ මැකීමට කැමති බව විශ්වාසද?",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TunnelName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnelName"
+ }
+ ]
+ },
+ {
+ "id": "{Question} You cannot undo this action.",
+ "message": "{Question} You cannot undo this action.",
+ "translation": "{Question} මෙම ක්‍රියාව ආපසු හැරවිය.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Question",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "question"
+ }
+ ]
+ },
+ {
+ "id": "Unable to delete tunnel",
+ "message": "Unable to delete tunnel",
+ "translation": "උමග මැකීමට නොහැකිය",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "A tunnel was unable to be removed: {Error}",
+ "message": "A tunnel was unable to be removed: {Error}",
+ "translation": "උමගක් ඉවත් කිරීමට නොහැකි විය: {Error}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Error",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errors[0].Error()"
+ }
+ ]
+ },
+ {
+ "id": "Unable to delete tunnels",
+ "message": "Unable to delete tunnels",
+ "translation": "උමං මකා දැමිය නොහැක",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Lenerrors} tunnels were unable to be removed.",
+ "message": "{Lenerrors} tunnels were unable to be removed.",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Lenerrors",
+ "cases": {
+ "one": {
+ "msg": "{Lenerrors} උමං ඉවත් කිරීමට නොහැකි විය."
+ },
+ "other": {
+ "msg": "උමං {Lenerrors} ක් ඉවත් කිරීමට නොහැකි විය."
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Lenerrors",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "len(errors)"
+ }
+ ]
+ },
+ {
+ "id": "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
+ "message": "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
+ "translation": "වින්‍යාස ගොනු (*.zip, *.conf)|*.zip;*.conf|සියලු ගොනු (*.*)|*.*",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Import tunnel(s) from file",
+ "message": "Import tunnel(s) from file",
+ "translation": "ගොනුවෙන් උමං(ය) ආයාත කරන්න",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Configuration ZIP Files (*.zip)|*.zip",
+ "message": "Configuration ZIP Files (*.zip)|*.zip",
+ "translation": "වින්‍යාස කිරීම ZIP ගොනු (*.zip)|*.zip",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export tunnels to zip",
+ "message": "Export tunnels to zip",
+ "translation": "zip වෙත උමං අපනයනය කරන්න",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Title} (unsigned build, no updates)",
+ "message": "{Title} (unsigned build, no updates)",
+ "translation": "{Title} (අත්සන් නොකළ ගොඩනැගීම, යාවත්කාලීන නැත)",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Title",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "mtw.Title()"
+ }
+ ]
+ },
+ {
+ "id": "Error Exiting WireGuard",
+ "message": "Error Exiting WireGuard",
+ "translation": "වයර්ගාඩ් පිටවීමේදී දෝෂයකි",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
+ "message": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
+ "translation": "{Err}නිසා සේවයෙන් ඉවත් විය නොහැක. ඔබට සේවා කළමනාකරුගෙන් WireGuard නැවැත්වීමට අවශ්‍ය විය හැකිය.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "message": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "translation": "WireGuard වෙත යාවත්කාලීනයක් තිබේ. ප්රමාදයකින් තොරව යාවත්කාලීන කිරීම ඉතා යෝග්ය වේ.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Waiting for user",
+ "message": "Status: Waiting for user",
+ "translation": "තත්‍වය: පරිශීලක සඳහා රැඳෙමින්",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Update Now",
+ "message": "Update Now",
+ "translation": "යාවත්කාල කරන්න",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Waiting for updater service",
+ "message": "Status: Waiting for updater service",
+ "translation": "තත්‍වය: යාවත්කාල සේවාව සඳහා රැඳෙමින්",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error: {Err}. Please try again.",
+ "message": "Error: {Err}. Please try again.",
+ "translation": "දෝෂය: {Err}. යළි උත්සාහ කරන්න.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Status: Complete!",
+ "message": "Status: Complete!",
+ "translation": "තත්‍වය: සම්පූර්ණයි!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "http2: Framer {F}: failed to decode just-written frame",
+ "message": "http2: Framer {F}: failed to decode just-written frame",
+ "translation": "http2: Framer {F}: ලියන ලද රාමුව විකේතනය කිරීමට අසමත් විය",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "F",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "f"
+ }
+ ]
+ },
+ {
+ "id": "http2: Framer {F}: wrote {Http2summarizeFramefr}",
+ "message": "http2: Framer {F}: wrote {Http2summarizeFramefr}",
+ "translation": "http2: රාමු {F}: ලිව්වේ {Http2summarizeFramefr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "F",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "f"
+ },
+ {
+ "id": "Http2summarizeFramefr",
+ "string": "%[2]v",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "http2summarizeFrame(fr)"
+ }
+ ]
+ },
+ {
+ "id": "http2: Framer {Fr}: read {Http2summarizeFramef}",
+ "message": "http2: Framer {Fr}: read {Http2summarizeFramef}",
+ "translation": "http2: රාමු {Fr}: කියවන්න {Http2summarizeFramef}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Fr",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "fr"
+ },
+ {
+ "id": "Http2summarizeFramef",
+ "string": "%[2]v",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "http2summarizeFrame(f)"
+ }
+ ]
+ },
+ {
+ "id": "http2: decoded hpack field {HeaderField}",
+ "message": "http2: decoded hpack field {HeaderField}",
+ "translation": "http2: විකේතනය කළ hpack ක්ෂේත්‍ර {HeaderField}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "HeaderField",
+ "string": "%+[1]v",
+ "type": "vendor/golang.org/x/net/http2/hpack.HeaderField",
+ "underlyingType": "struct{Name string; Value string; Sensitive bool}",
+ "argNum": 1,
+ "expr": "hf"
+ }
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/locales/sk/messages.gotext.json b/locales/sk/messages.gotext.json
index c8d05aa2..0591c0ae 100644
--- a/locales/sk/messages.gotext.json
+++ b/locales/sk/messages.gotext.json
@@ -60,6 +60,12 @@
]
},
{
+ "id": "You must use the native version of WireGuard on this computer.",
+ "message": "You must use the native version of WireGuard on this computer.",
+ "translation": "V tomto počítači musíte používať pôvodnú verziu programu WireGuard.",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Unable to open current process token: {Err}",
"message": "Unable to open current process token: {Err}",
"translation": "Nepodarilo sa otvoriť token aktuálneho procesu: {Err}",
@@ -126,6 +132,40 @@
"translatorComment": "Copied from source."
},
{
+ "id": "{Years} year(s)",
+ "message": "{Years} year(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Years",
+ "cases": {
+ "one": {
+ "msg": "{Years} rok"
+ },
+ "few": {
+ "msg": "{Years} roky"
+ },
+ "many": {
+ "msg": "{Years} rokov"
+ },
+ "other": {
+ "msg": "{Years} rokov"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Years",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "years"
+ }
+ ]
+ },
+ {
"id": "{Days} day(s)",
"message": "{Days} day(s)",
"translation": {
@@ -576,6 +616,62 @@
"translatorComment": "Copied from source."
},
{
+ "id": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "message": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "translation": "Verzia aplikácie.: {Number}\nVerzia Go backendu: {WireGuardGoVersion}\nVerzia Go: {Version_go}-{GOARCH}\nOperačný systém: {OsName}\nArchitektúra: {NativeArch}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Number",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "version.Number"
+ },
+ {
+ "id": "WireGuardGoVersion",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "device.WireGuardGoVersion"
+ },
+ {
+ "id": "Version_go",
+ "string": "%[3]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 3,
+ "expr": "strings.TrimPrefix(runtime.Version(), \"go\")"
+ },
+ {
+ "id": "GOARCH",
+ "string": "%[4]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 4,
+ "expr": "runtime.GOARCH"
+ },
+ {
+ "id": "OsName",
+ "string": "%[5]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 5,
+ "expr": "version.OsName()"
+ },
+ {
+ "id": "NativeArch",
+ "string": "%[6]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 6,
+ "expr": "version.NativeArch()"
+ }
+ ]
+ },
+ {
"id": "Close",
"message": "Close",
"translation": "Zatvoriť",
@@ -584,7 +680,7 @@
{
"id": "♥ &Donate!",
"message": "♥ &Donate!",
- "translation": "♥ a Darovat!",
+ "translation": "♥ &Darovat!",
"translatorComment": "Copied from source."
},
{
@@ -596,13 +692,13 @@
{
"id": "&Deactivate",
"message": "&Deactivate",
- "translation": "a Deaktivovať",
+ "translation": "&Deaktivovať",
"translatorComment": "Copied from source."
},
{
"id": "&Activate",
"message": "&Activate",
- "translation": "a Aktivovať",
+ "translation": "&Aktivovať",
"translatorComment": "Copied from source."
},
{
@@ -636,6 +732,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Scripts:",
+ "message": "Scripts:",
+ "translation": "Skripty:",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Preshared key:",
"message": "Preshared key:",
"translation": "Vopred zdieľaný kľúč:",
@@ -672,6 +774,36 @@
"translatorComment": "Copied from source."
},
{
+ "id": "pre-up",
+ "message": "pre-up",
+ "translation": "pred-zapnutím",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-up",
+ "message": "post-up",
+ "translation": "po-zapnutí",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-down",
+ "message": "pre-down",
+ "translation": "pred-vypnutím",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-down",
+ "message": "post-down",
+ "translation": "po-vypnutí",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "disabled, per policy",
+ "message": "disabled, per policy",
+ "translation": "zakázané, na základe pravidla",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "enabled",
"message": "enabled",
"translation": "povolené",
@@ -778,6 +910,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "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 or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "message": "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 or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "translation": "Ak konfigurácia obsahuje práve jedného peera a tento má v povolených IP 0.0.0.0/0 alebo ::/0, tak tak tento tunel aktivuje pravidlo firewallu blokujúce komunikáciu, ktorá nepochádza z alebo nesmeruje na rozhranie tohto tunela alebo smeruje na nesprávny DNS server, špeciálnou výnimkou je DHCP a NDP komunikácia.",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "&Save",
"message": "&Save",
"translation": "&Uložiť",
@@ -910,12 +1048,138 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Log",
+ "message": "Log",
+ "translation": "Denník udalostí",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Copy",
+ "message": "&Copy",
+ "translation": "&Kopírovať",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Select &all",
+ "message": "Select &all",
+ "translation": "Vybr&ať všetko",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Save to file…",
+ "message": "&Save to file…",
+ "translation": "Uložiť do &súboru…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Time",
+ "message": "Time",
+ "translation": "Čas",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Log message",
+ "message": "Log message",
+ "translation": "Správa v denníku udalostí",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "message": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "translation": "Textové súbory (*.txt)|*.txt|Všetky súbory (*.*)|*.*",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export log to file",
+ "message": "Export log to file",
+ "translation": "Exportovať denník udalostí do súboru",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "&About WireGuard…",
"message": "&About WireGuard…",
"translation": "&O WireGuard…",
"translatorComment": "Copied from source."
},
{
+ "id": "Tunnel Error",
+ "message": "Tunnel Error",
+ "translation": "Chyba tunela",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "message": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "translation": "{ErrMsg}\n\nViac informácií nájdete v denníku udalostí.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "ErrMsg",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errMsg"
+ }
+ ]
+ },
+ {
+ "id": "{Title} (out of date)",
+ "message": "{Title} (out of date)",
+ "translation": "{Title} (neaktuány)",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Title",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "mtw.Title()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Detection Error",
+ "message": "WireGuard Detection Error",
+ "translation": "Chyba detekcie WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to wait for WireGuard window to appear: {Err}",
+ "message": "Unable to wait for WireGuard window to appear: {Err}",
+ "translation": "Nie je možné čakať na zobrazenie WireGuard okna: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard: Deactivated",
+ "message": "WireGuard: Deactivated",
+ "translation": "WireGuard: deaktivovaný",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Unknown",
+ "message": "Status: Unknown",
+ "translation": "Stav: Nezámy",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Addresses: None",
+ "message": "Addresses: None",
+ "translation": "Adresa: žiadna",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "&Manage tunnels…",
"message": "&Manage tunnels…",
"translation": "&Spravovať tunely…",
@@ -934,6 +1198,62 @@
"translatorComment": "Copied from source."
},
{
+ "id": "&Tunnels",
+ "message": "&Tunnels",
+ "translation": "&Tunely",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Activated",
+ "message": "WireGuard Activated",
+ "translation": "WireGuard je aktivovaný",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "The {Name} tunnel has been activated.",
+ "message": "The {Name} tunnel has been activated.",
+ "translation": "Tunel {Name} bol aktivovaný.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnel.Name"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Deactivated",
+ "message": "WireGuard Deactivated",
+ "translation": "WireGuard je deaktivovaný",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "The {Name} tunnel has been deactivated.",
+ "message": "The {Name} tunnel has been deactivated.",
+ "translation": "Tunel {Name} bol deaktivovaný.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnel.Name"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Tunnel Error",
+ "message": "WireGuard Tunnel Error",
+ "translation": "Chyba WireGuard tunelu",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "WireGuard: {TextForStateglobalState_true}",
"message": "WireGuard: {TextForStateglobalState_true}",
"translation": "WireGuard: {TextForStateglobalState_true}",
@@ -948,6 +1268,640 @@
"expr": "textForState(globalState, true)"
}
]
+ },
+ {
+ "id": "Status: {StateText}",
+ "message": "Status: {StateText}",
+ "translation": "Stav: {StateText}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "StateText",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "stateText"
+ }
+ ]
+ },
+ {
+ "id": "Addresses: {EnumerationSeparator}",
+ "message": "Addresses: {EnumerationSeparator}",
+ "translation": "Adresa: {EnumerationSeparator}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "EnumerationSeparator",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "strings.Join(addrs, l18n.EnumerationSeparator())"
+ }
+ ]
+ },
+ {
+ "id": "An Update is Available!",
+ "message": "An Update is Available!",
+ "translation": "Je dostupná aktualizácia!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Update Available",
+ "message": "WireGuard Update Available",
+ "translation": "Dostupná aktualizácia pre WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "An update to WireGuard is now available. You are advised to update as soon as possible.",
+ "message": "An update to WireGuard is now available. You are advised to update as soon as possible.",
+ "translation": "Je k dispozícii aktualizácia programu WireGuard. Je odporúčané čo najskôr vykonať aktualizáciu.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnels",
+ "message": "Tunnels",
+ "translation": "Tunely",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Edit",
+ "message": "&Edit",
+ "translation": "&Upraviť",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Add &empty tunnel…",
+ "message": "Add &empty tunnel…",
+ "translation": "Pridať &prázdny tunel…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Add Tunnel",
+ "message": "Add Tunnel",
+ "translation": "Pridať tunel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Remove selected tunnel(s)",
+ "message": "Remove selected tunnel(s)",
+ "translation": "Odstrániť označený(é) tunel(y)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export all tunnels to zip",
+ "message": "Export all tunnels to zip",
+ "translation": "Export všetkých tunelov do zip súboru",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Toggle",
+ "message": "&Toggle",
+ "translation": "P&repnúť",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export all tunnels to &zip…",
+ "message": "Export all tunnels to &zip…",
+ "translation": "Export všetkých tunelov do &zip súboru…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Edit &selected tunnel…",
+ "message": "Edit &selected tunnel…",
+ "translation": "Upraviť &označený tunel…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Remove selected tunnel(s)",
+ "message": "&Remove selected tunnel(s)",
+ "translation": "&Odstrániť označené tunely",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "no configuration files were found",
+ "message": "no configuration files were found",
+ "translation": "neboli nájdené žiadne konfiguračné súbory",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Could not import selected configuration: {LastErr}",
+ "message": "Could not import selected configuration: {LastErr}",
+ "translation": "Nepodarilo sa naimportovať vybrané konfigurácie: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Could not enumerate existing tunnels: {LastErr}",
+ "message": "Could not enumerate existing tunnels: {LastErr}",
+ "translation": "Nepodarilo sa načítať existujúce tunely: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Another tunnel already exists with the name ‘{Name}’",
+ "message": "Another tunnel already exists with the name ‘{Name}’",
+ "translation": "Už existuje tunel s názvom '{Name}'",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "unparsedConfig.Name"
+ }
+ ]
+ },
+ {
+ "id": "Unable to import configuration: {LastErr}",
+ "message": "Unable to import configuration: {LastErr}",
+ "translation": "Nepodarilo sa naimportovať konfiguráciu: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Imported tunnels",
+ "message": "Imported tunnels",
+ "translation": "Naimportované tunely",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Imported {M} tunnels",
+ "message": "Imported {M} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "M",
+ "cases": {
+ "one": {
+ "msg": "Importovaný {M} tunel"
+ },
+ "few": {
+ "msg": "Naimportované {M} tunely"
+ },
+ "many": {
+ "msg": "Naimportovaných {M} tunelov"
+ },
+ "other": {
+ "msg": "Naimportovaných {M} tunelov"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ }
+ ]
+ },
+ {
+ "id": "Imported {M} of {N} tunnels",
+ "message": "Imported {M} of {N} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "N",
+ "cases": {
+ "one": {
+ "msg": "Naimportovaný {M} z {N} tunelov"
+ },
+ "few": {
+ "msg": "Naimportované {M} z {N} tunelov"
+ },
+ "many": {
+ "msg": "Naimportovaných {M} z {N} tunelov"
+ },
+ "other": {
+ "msg": "Naimportovaných {M} z {N} tunelov"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ },
+ {
+ "id": "N",
+ "string": "%[2]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 2,
+ "expr": "n"
+ }
+ ]
+ },
+ {
+ "id": "Unable to create tunnel",
+ "message": "Unable to create tunnel",
+ "translation": "Tunel sa nedá vytvoriť",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Delete {TunnelCount} tunnels",
+ "message": "Delete {TunnelCount} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "TunnelCount",
+ "cases": {
+ "one": {
+ "msg": "Odstránený {TunnelCount} tunel"
+ },
+ "few": {
+ "msg": "Odstránene {TunnelCount} tunely"
+ },
+ "many": {
+ "msg": "Odstránených {TunnelCount} tunelov"
+ },
+ "other": {
+ "msg": "Odstránených {TunnelCount} tunelov"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "TunnelCount",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "tunnelCount"
+ }
+ ]
+ },
+ {
+ "id": "Are you sure you would like to delete {TunnelCount} tunnels?",
+ "message": "Are you sure you would like to delete {TunnelCount} tunnels?",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "TunnelCount",
+ "cases": {
+ "one": {
+ "msg": "Ste si istý, že si želáte odstrániť {TunnelCount} tunel?"
+ },
+ "few": {
+ "msg": "Ste si istý, že si želáte odstrániť {TunnelCount} tunely?"
+ },
+ "many": {
+ "msg": "Ste si istý, že si želáte odstrániť {TunnelCount} tunelov?"
+ },
+ "other": {
+ "msg": "Ste si istý, že si želáte odstrániť {TunnelCount} tunelov?"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "TunnelCount",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "tunnelCount"
+ }
+ ]
+ },
+ {
+ "id": "Delete tunnel ‘{TunnelName}’",
+ "message": "Delete tunnel ‘{TunnelName}’",
+ "translation": "Odstránenie tunela ‘{TunnelName}’",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TunnelName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnelName"
+ }
+ ]
+ },
+ {
+ "id": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
+ "message": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
+ "translation": "Ste si istý, že si želáte odstrániť tunel ‘{TunnelName}’?",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TunnelName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnelName"
+ }
+ ]
+ },
+ {
+ "id": "{Question} You cannot undo this action.",
+ "message": "{Question} You cannot undo this action.",
+ "translation": "{Question} Túto akciu nemôže vrátiť späť.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Question",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "question"
+ }
+ ]
+ },
+ {
+ "id": "Unable to delete tunnel",
+ "message": "Unable to delete tunnel",
+ "translation": "Tunel sa nedá odstrániť",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "A tunnel was unable to be removed: {Error}",
+ "message": "A tunnel was unable to be removed: {Error}",
+ "translation": "Nebolo možné odstrániť tunel: {Error}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Error",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errors[0].Error()"
+ }
+ ]
+ },
+ {
+ "id": "Unable to delete tunnels",
+ "message": "Unable to delete tunnels",
+ "translation": "Tunely sa nedajú odstrániť",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Lenerrors} tunnels were unable to be removed.",
+ "message": "{Lenerrors} tunnels were unable to be removed.",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Lenerrors",
+ "cases": {
+ "one": {
+ "msg": "{Lenerrors} tunel nebolo možné odstrániť."
+ },
+ "few": {
+ "msg": "{Lenerrors} tunely nebolo možné odstrániť."
+ },
+ "many": {
+ "msg": "{Lenerrors} tunelov nebolo možné odstrániť."
+ },
+ "other": {
+ "msg": "{Lenerrors} tunelov nebolo možné odstrániť."
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Lenerrors",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "len(errors)"
+ }
+ ]
+ },
+ {
+ "id": "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
+ "message": "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
+ "translation": "Konfirugačné súbory (*.zip, *.conf)|*.zip;*.conf|Všetky súbory (*.*)|*.*",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Import tunnel(s) from file",
+ "message": "Import tunnel(s) from file",
+ "translation": "Importovať tunel(y) zo súboru",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Configuration ZIP Files (*.zip)|*.zip",
+ "message": "Configuration ZIP Files (*.zip)|*.zip",
+ "translation": "Konfiguračné ZIP súbry (*.zip)|*.zip",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export tunnels to zip",
+ "message": "Export tunnels to zip",
+ "translation": "Export tunelov do zip súboru",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Title} (unsigned build, no updates)",
+ "message": "{Title} (unsigned build, no updates)",
+ "translation": "{Title} (nepodpísaná verzia, žiadne aktualizácie)",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Title",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "mtw.Title()"
+ }
+ ]
+ },
+ {
+ "id": "Error Exiting WireGuard",
+ "message": "Error Exiting WireGuard",
+ "translation": "Chyba ukončenia WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
+ "message": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
+ "translation": "Nie je možné ukončiť služby z dôvodu: {Err}. Skúste zastaviť WireGuard v správcovi služieb.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "message": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "translation": "Je k dispozícii nová verzia programu WireGuard. Odporúčame bezodkladne vykonať aktualizáciu.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Waiting for user",
+ "message": "Status: Waiting for user",
+ "translation": "Stav: Čaká sa na užívateľa",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Update Now",
+ "message": "Update Now",
+ "translation": "Aktualizovať teraz",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Waiting for updater service",
+ "message": "Status: Waiting for updater service",
+ "translation": "Stav: Čaká sa na aktualizačnú službu",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error: {Err}. Please try again.",
+ "message": "Error: {Err}. Please try again.",
+ "translation": "Chyba: {Err}. Skúste to znova.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Status: Complete!",
+ "message": "Status: Complete!",
+ "translation": "Stav: Dokončené!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "http2: Framer {F}: failed to decode just-written frame",
+ "message": "http2: Framer {F}: failed to decode just-written frame",
+ "translation": "http2: Framer {F}: failed to decode just-written frame",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "F",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "f"
+ }
+ ]
+ },
+ {
+ "id": "http2: Framer {F}: wrote {Http2summarizeFramefr}",
+ "message": "http2: Framer {F}: wrote {Http2summarizeFramefr}",
+ "translation": "http2: Framer {F}: wrote {Http2summarizeFramefr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "F",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "f"
+ },
+ {
+ "id": "Http2summarizeFramefr",
+ "string": "%[2]v",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "http2summarizeFrame(fr)"
+ }
+ ]
+ },
+ {
+ "id": "http2: Framer {Fr}: read {Http2summarizeFramef}",
+ "message": "http2: Framer {Fr}: read {Http2summarizeFramef}",
+ "translation": "http2: Framer {Fr}: read {Http2summarizeFramef}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Fr",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "fr"
+ },
+ {
+ "id": "Http2summarizeFramef",
+ "string": "%[2]v",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "http2summarizeFrame(f)"
+ }
+ ]
+ },
+ {
+ "id": "http2: decoded hpack field {HeaderField}",
+ "message": "http2: decoded hpack field {HeaderField}",
+ "translation": "http2: decoded hpack field {HeaderField}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "HeaderField",
+ "string": "%+[1]v",
+ "type": "vendor/golang.org/x/net/http2/hpack.HeaderField",
+ "underlyingType": "struct{Name string; Value string; Sensitive bool}",
+ "argNum": 1,
+ "expr": "hf"
+ }
+ ]
}
]
} \ No newline at end of file
diff --git a/locales/sl/messages.gotext.json b/locales/sl/messages.gotext.json
index c3418f02..d1cf6f90 100644
--- a/locales/sl/messages.gotext.json
+++ b/locales/sl/messages.gotext.json
@@ -692,7 +692,7 @@
{
"id": "&Deactivate",
"message": "&Deactivate",
- "translation": "&Deaktiviraj",
+ "translation": "&Dezaktiviraj",
"translatorComment": "Copied from source."
},
{
@@ -788,13 +788,13 @@
{
"id": "pre-down",
"message": "pre-down",
- "translation": "pred-deaktivacijo",
+ "translation": "pred-dezaktivacijo",
"translatorComment": "Copied from source."
},
{
"id": "post-down",
"message": "post-down",
- "translation": "po-deaktivaciji",
+ "translation": "po-dezaktivaciji",
"translatorComment": "Copied from source."
},
{
@@ -848,7 +848,7 @@
{
"id": "Failed to deactivate tunnel",
"message": "Failed to deactivate tunnel",
- "translation": "Napaka pri deaktiviranju tunela",
+ "translation": "Napaka pri dezaktiviranju tunela",
"translatorComment": "Copied from source."
},
{
@@ -1038,7 +1038,7 @@
{
"id": "Deactivating",
"message": "Deactivating",
- "translation": "Se deaktivira",
+ "translation": "Se dezaktivira",
"translatorComment": "Copied from source."
},
{
@@ -1164,7 +1164,7 @@
{
"id": "WireGuard: Deactivated",
"message": "WireGuard: Deactivated",
- "translation": "WireGuard: Deaktiviran",
+ "translation": "WireGuard: Dezaktiviran",
"translatorComment": "Copied from source."
},
{
@@ -1228,13 +1228,13 @@
{
"id": "WireGuard Deactivated",
"message": "WireGuard Deactivated",
- "translation": "WireGuard deaktiviran",
+ "translation": "WireGuard dezaktiviran",
"translatorComment": "Copied from source."
},
{
"id": "The {Name} tunnel has been deactivated.",
"message": "The {Name} tunnel has been deactivated.",
- "translation": "Tunel {Name} je bil deaktiviran.",
+ "translation": "Tunel {Name} je bil dezaktiviran.",
"translatorComment": "Copied from source.",
"placeholders": [
{
diff --git a/locales/sv-SE/messages.gotext.json b/locales/sv-SE/messages.gotext.json
new file mode 100644
index 00000000..5d2685dc
--- /dev/null
+++ b/locales/sv-SE/messages.gotext.json
@@ -0,0 +1,1847 @@
+{
+ "language": "sv-SE",
+ "messages": [
+ {
+ "id": "Error",
+ "message": "Error",
+ "translation": "Fel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "(no argument): elevate and install manager service",
+ "message": "(no argument): elevate and install manager service",
+ "translation": "(inget argument): höj och installera hanterartjänsten",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Usage: {Args0} [\n{String}]",
+ "message": "Usage: {Args0} [\n{String}]",
+ "translation": "Användning: {Args0} [\n{String}]",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Args0",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "os.Args[0]"
+ },
+ {
+ "id": "String",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "builder.String()"
+ }
+ ]
+ },
+ {
+ "id": "Command Line Options",
+ "message": "Command Line Options",
+ "translation": "Kommandoradsalternativ",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to determine whether the process is running under WOW64: {Err}",
+ "message": "Unable to determine whether the process is running under WOW64: {Err}",
+ "translation": "Det går inte att avgöra om processen körs under WOW64: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "You must use the native version of WireGuard on this computer.",
+ "message": "You must use the native version of WireGuard on this computer.",
+ "translation": "Du måste använda den inbyggda versionen av WireGuard på denna dator.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to open current process token: {Err}",
+ "message": "Unable to open current process token: {Err}",
+ "translation": "Det går inte att öppna nuvarande process-token: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard may only be used by users who are a member of the Builtin {AdminGroupName} group.",
+ "message": "WireGuard may only be used by users who are a member of the Builtin {AdminGroupName} group.",
+ "translation": "WireGuard får endast användas av användare som är medlemmar i gruppen Builtin {AdminGroupName}.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "AdminGroupName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "elevate.AdminGroupName()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard is running, but the UI is only accessible from desktops of the Builtin {AdminGroupName} group.",
+ "message": "WireGuard is running, but the UI is only accessible from desktops of the Builtin {AdminGroupName} group.",
+ "translation": "WireGuard körs, men gränssnittet är endast tillgängligt från skrivbordet i gruppen Builtin {AdminGroupName}.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "AdminGroupName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "elevate.AdminGroupName()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard system tray icon did not appear after 30 seconds.",
+ "message": "WireGuard system tray icon did not appear after 30 seconds.",
+ "translation": "WireGuard systemfältet visades inte efter 30 sekunder.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Now",
+ "message": "Now",
+ "translation": "Nu",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "System clock wound backward!",
+ "message": "System clock wound backward!",
+ "translation": "Systemets klocka har ställts tillbaka!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Years} year(s)",
+ "message": "{Years} year(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Years",
+ "cases": {
+ "one": {
+ "msg": "{Years} år"
+ },
+ "other": {
+ "msg": "{Years} år"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Years",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "years"
+ }
+ ]
+ },
+ {
+ "id": "{Days} day(s)",
+ "message": "{Days} day(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Days",
+ "cases": {
+ "one": {
+ "msg": "{Days} dag"
+ },
+ "other": {
+ "msg": "{Days} dagar"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Days",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "days"
+ }
+ ]
+ },
+ {
+ "id": "{Hours} hour(s)",
+ "message": "{Hours} hour(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Hours",
+ "cases": {
+ "one": {
+ "msg": "{Hours} timme"
+ },
+ "other": {
+ "msg": "{Hours} timmar"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Hours",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "hours"
+ }
+ ]
+ },
+ {
+ "id": "{Minutes} minute(s)",
+ "message": "{Minutes} minute(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Minutes",
+ "cases": {
+ "one": {
+ "msg": "{Minutes} minut"
+ },
+ "other": {
+ "msg": "{Minutes} minuter"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Minutes",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "minutes"
+ }
+ ]
+ },
+ {
+ "id": "{Seconds} second(s)",
+ "message": "{Seconds} second(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Seconds",
+ "cases": {
+ "one": {
+ "msg": "{Seconds} sekund"
+ },
+ "other": {
+ "msg": "{Seconds} sekunder"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Seconds",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "seconds"
+ }
+ ]
+ },
+ {
+ "id": "{Timestamp} ago",
+ "message": "{Timestamp} ago",
+ "translation": "{Timestamp} sedan",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Timestamp",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "timestamp"
+ }
+ ]
+ },
+ {
+ "id": "{Bytes} B",
+ "message": "{Bytes} B",
+ "translation": "{Bytes} B",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Bytes",
+ "string": "%[1]d",
+ "type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
+ "underlyingType": "uint64",
+ "argNum": 1,
+ "expr": "b"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024} KiB",
+ "message": "{Float64b__1024} KiB",
+ "translation": "{Float64b__1024} KiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / 1024"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024} MiB",
+ "message": "{Float64b__1024__1024} MiB",
+ "translation": "{Float64b__1024__1024} MiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024} GiB",
+ "message": "{Float64b__1024__1024__1024} GiB",
+ "translation": "{Float64b__1024__1024__1024} GiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024__1024} TiB",
+ "message": "{Float64b__1024__1024__1024__1024} TiB",
+ "translation": "{Float64b__1024__1024__1024__1024} TiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024) / 1024"
+ }
+ ]
+ },
+ {
+ "id": "{Why}: {Offender}",
+ "message": "{Why}: {Offender}",
+ "translation": "{Why}: {Offender}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Why",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "e.why"
+ },
+ {
+ "id": "Offender",
+ "string": "%[2]q",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "e.offender"
+ }
+ ]
+ },
+ {
+ "id": "Invalid IP address",
+ "message": "Invalid IP address",
+ "translation": "Ogiltig IP-adress",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid network prefix length",
+ "message": "Invalid network prefix length",
+ "translation": "Ogiltigt nätverksprefixlängd",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Missing port from endpoint",
+ "message": "Missing port from endpoint",
+ "translation": "Saknad port från slutpunkt",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid endpoint host",
+ "message": "Invalid endpoint host",
+ "translation": "Ogiltig slutpunktsvärd",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Brackets must contain an IPv6 address",
+ "message": "Brackets must contain an IPv6 address",
+ "translation": "Parenteser måste innehålla en IPv6-adress",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid MTU",
+ "message": "Invalid MTU",
+ "translation": "Ogiltig MTU",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid port",
+ "message": "Invalid port",
+ "translation": "Ogiltig port",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid persistent keepalive",
+ "message": "Invalid persistent keepalive",
+ "translation": "Ogiltig beständig keepalive",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key: {Err}",
+ "message": "Invalid key: {Err}",
+ "translation": "Ogiltig nyckel: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Keys must decode to exactly 32 bytes",
+ "message": "Keys must decode to exactly 32 bytes",
+ "translation": "Nycklar måste avkoda till exakt 32 byte",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Number must be a number between 0 and 2^64-1: {Err}",
+ "message": "Number must be a number between 0 and 2^64-1: {Err}",
+ "translation": "Numret måste vara ett tal mellan 0 och 2^64-1: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Two commas in a row",
+ "message": "Two commas in a row",
+ "translation": "Två kommatecken i rad",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel name is not valid",
+ "message": "Tunnel name is not valid",
+ "translation": "Tunnelnamn är ogiltig",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Line must occur in a section",
+ "message": "Line must occur in a section",
+ "translation": "Linje måste förekomma i ett avsnitt",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Config key is missing an equals separator",
+ "message": "Config key is missing an equals separator",
+ "translation": "Konfigurationsnyckel saknar en likvärdig separator",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Key must have a value",
+ "message": "Key must have a value",
+ "translation": "Nyckel måste ha ett värde",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for [Interface] section",
+ "message": "Invalid key for [Interface] section",
+ "translation": "Ogiltig nyckel för sektionen [Interface]",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for [Peer] section",
+ "message": "Invalid key for [Peer] section",
+ "translation": "Ogiltig nyckel för sektionen [Peer]",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "An interface must have a private key",
+ "message": "An interface must have a private key",
+ "translation": "Ett gränssnitt måste innehålla en privat nyckel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "[none specified]",
+ "message": "[none specified]",
+ "translation": "[ingen angiven]",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "All peers must have public keys",
+ "message": "All peers must have public keys",
+ "translation": "Alla peers måste ha offentliga nycklar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error in getting configuration",
+ "message": "Error in getting configuration",
+ "translation": "Fel vid hämtning av konfiguration",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for interface section",
+ "message": "Invalid key for interface section",
+ "translation": "Ogiltig nyckel för gränssnittsavsnitt",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Protocol version must be 1",
+ "message": "Protocol version must be 1",
+ "translation": "Protokollversion måste vara 1",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for peer section",
+ "message": "Invalid key for peer section",
+ "translation": "Ogiltig nyckel för peer-avsnitt",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "[EnumerationSeparator]",
+ "message": "[EnumerationSeparator]",
+ "translation": ", ",
+ "comment": "Text to insert between items when listing - most western languages will translate ‘[EnumerationSeparator]’ into ‘, ’ to produce lists like ‘apple, orange, strawberry’. Eastern languages might translate into ‘、’ to produce lists like ‘リンゴ、オレンジ、イチゴ’."
+ },
+ {
+ "id": "[UnitSeparator]",
+ "message": "[UnitSeparator]",
+ "translation": ", ",
+ "comment": "Text to insert when combining units of a measure - most languages will translate ‘[UnitSeparator]’ into ‘ ’ (space) to produce lists like ‘2 minuti 30 sekund’, or empty string ‘’ to produce ‘2分30秒’."
+ },
+ {
+ "id": "About WireGuard",
+ "message": "About WireGuard",
+ "translation": "Om WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard logo image",
+ "message": "WireGuard logo image",
+ "translation": "WireGuard-logotyp bild",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "message": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "translation": "Appversion: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperativsystem: {OsName}\nArkitektur: {NativeArch}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Number",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "version.Number"
+ },
+ {
+ "id": "WireGuardGoVersion",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "device.WireGuardGoVersion"
+ },
+ {
+ "id": "Version_go",
+ "string": "%[3]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 3,
+ "expr": "strings.TrimPrefix(runtime.Version(), \"go\")"
+ },
+ {
+ "id": "GOARCH",
+ "string": "%[4]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 4,
+ "expr": "runtime.GOARCH"
+ },
+ {
+ "id": "OsName",
+ "string": "%[5]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 5,
+ "expr": "version.OsName()"
+ },
+ {
+ "id": "NativeArch",
+ "string": "%[6]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 6,
+ "expr": "version.NativeArch()"
+ }
+ ]
+ },
+ {
+ "id": "Close",
+ "message": "Close",
+ "translation": "Stäng",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "♥ &Donate!",
+ "message": "♥ &Donate!",
+ "translation": "♥ &Donera!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status:",
+ "message": "Status:",
+ "translation": "Status:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Deactivate",
+ "message": "&Deactivate",
+ "translation": "&Avaktivera",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Activate",
+ "message": "&Activate",
+ "translation": "&Aktivera",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Public key:",
+ "message": "Public key:",
+ "translation": "Publik nyckel:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Listen port:",
+ "message": "Listen port:",
+ "translation": "Lyssningsport:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "MTU:",
+ "message": "MTU:",
+ "translation": "MTU:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Addresses:",
+ "message": "Addresses:",
+ "translation": "Adresser:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "DNS servers:",
+ "message": "DNS servers:",
+ "translation": "DNS-servrar:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Scripts:",
+ "message": "Scripts:",
+ "translation": "Skript:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Preshared key:",
+ "message": "Preshared key:",
+ "translation": "Fördelad nyckel:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Allowed IPs:",
+ "message": "Allowed IPs:",
+ "translation": "Tillåtna IP: s:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Endpoint:",
+ "message": "Endpoint:",
+ "translation": "Slutpunkt:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Persistent keepalive:",
+ "message": "Persistent keepalive:",
+ "translation": "Beständig keepalive:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Latest handshake:",
+ "message": "Latest handshake:",
+ "translation": "Senaste handskakning:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Transfer:",
+ "message": "Transfer:",
+ "translation": "Överföring:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-up",
+ "message": "pre-up",
+ "translation": "före uppstart",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-up",
+ "message": "post-up",
+ "translation": "efter uppstart",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-down",
+ "message": "pre-down",
+ "translation": "innan nertagning",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-down",
+ "message": "post-down",
+ "translation": "efter nedtagning",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "disabled, per policy",
+ "message": "disabled, per policy",
+ "translation": "inaktiverad, per policy",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "enabled",
+ "message": "enabled",
+ "translation": "aktiverad",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{String} received, {String_1} sent",
+ "message": "{String} received, {String_1} sent",
+ "translation": "{String} mottagen, {String_1} skickad",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "String",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "c.RxBytes.String()"
+ },
+ {
+ "id": "String_1",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "c.TxBytes.String()"
+ }
+ ]
+ },
+ {
+ "id": "Failed to determine tunnel state",
+ "message": "Failed to determine tunnel state",
+ "translation": "Det gick inte att bestämma tunnelns tillstånd",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Failed to activate tunnel",
+ "message": "Failed to activate tunnel",
+ "translation": "Kunde inte aktivera tunneln",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Failed to deactivate tunnel",
+ "message": "Failed to deactivate tunnel",
+ "translation": "Kunde inte avaktivera tunnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Interface: {Name}",
+ "message": "Interface: {Name}",
+ "translation": "Gränssnitt: {Name}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "config.Name"
+ }
+ ]
+ },
+ {
+ "id": "Peer",
+ "message": "Peer",
+ "translation": "Peer",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Create new tunnel",
+ "message": "Create new tunnel",
+ "translation": "Skapa ny tunnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Edit tunnel",
+ "message": "Edit tunnel",
+ "translation": "Redigera tunnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Name:",
+ "message": "&Name:",
+ "translation": "&Namn:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Public key:",
+ "message": "&Public key:",
+ "translation": "&Publik nyckel:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "(unknown)",
+ "message": "(unknown)",
+ "translation": "(okänd)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Block untunneled traffic (kill-switch)",
+ "message": "&Block untunneled traffic (kill-switch)",
+ "translation": "&Blockera otunnlad trafik (kill-switch)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "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 or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "message": "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 or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "translation": "När en konfiguration har exakt en peer och denna peer har en tillåten IP-adress som innehåller åtminstone 0.0.0.0/0 eller ::/0, kommer tunneltjänsten aktivera en brandväggsregel som förhindrar all trafik som varken är till eller från tunnelns gränssnitt eller är till fel DNS-server, med särskilda undantag för DHCP och NDP.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Save",
+ "message": "&Save",
+ "translation": "&Spara",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Cancel",
+ "message": "Cancel",
+ "translation": "Avbryt",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Configuration:",
+ "message": "&Configuration:",
+ "translation": "&Konfiguration:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid name",
+ "message": "Invalid name",
+ "translation": "Ogiltigt namn",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "A name is required.",
+ "message": "A name is required.",
+ "translation": "Ett namn krävs.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel name ‘{NewName}’ is invalid.",
+ "message": "Tunnel name ‘{NewName}’ is invalid.",
+ "translation": "Tunnelnamnet ‘{NewName}’ är ogiltigt.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "NewName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "newName"
+ }
+ ]
+ },
+ {
+ "id": "Unable to list existing tunnels",
+ "message": "Unable to list existing tunnels",
+ "translation": "Kan inte lista befintliga tunnlar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel already exists",
+ "message": "Tunnel already exists",
+ "translation": "Tunnel finns redan",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Another tunnel already exists with the name ‘{NewName}’.",
+ "message": "Another tunnel already exists with the name ‘{NewName}’.",
+ "translation": "En annan tunnel finns redan med namnet ‘{NewName}’.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "NewName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "newName"
+ }
+ ]
+ },
+ {
+ "id": "Unable to create new configuration",
+ "message": "Unable to create new configuration",
+ "translation": "Kan inte skapa ny inställning",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Writing file failed",
+ "message": "Writing file failed",
+ "translation": "Misslyckades att skriva till fil",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "File ‘{FilePath}’ already exists.\n\nDo you want to overwrite it?",
+ "message": "File ‘{FilePath}’ already exists.\n\nDo you want to overwrite it?",
+ "translation": "Filen ‘{FilePath}’ finns redan.\n\nVill du skriva över den?",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "FilePath",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "filePath"
+ }
+ ]
+ },
+ {
+ "id": "Active",
+ "message": "Active",
+ "translation": "Aktiv",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Activating",
+ "message": "Activating",
+ "translation": "Aktiverar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Inactive",
+ "message": "Inactive",
+ "translation": "Passiv",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Deactivating",
+ "message": "Deactivating",
+ "translation": "Passiviserar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unknown state",
+ "message": "Unknown state",
+ "translation": "Okänt tillstånd",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Log",
+ "message": "Log",
+ "translation": "Logg",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Copy",
+ "message": "&Copy",
+ "translation": "&Kopiera",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Select &all",
+ "message": "Select &all",
+ "translation": "Markera &allt",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Save to file…",
+ "message": "&Save to file…",
+ "translation": "&Spara till fil…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Time",
+ "message": "Time",
+ "translation": "Tid",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Log message",
+ "message": "Log message",
+ "translation": "Loggmeddelande",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "message": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "translation": "Textfiler (*.txt)|*.txt|Alla filer (*.*)|*.*",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export log to file",
+ "message": "Export log to file",
+ "translation": "Exportera logg till fil",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&About WireGuard…",
+ "message": "&About WireGuard…",
+ "translation": "&Om WireGuard…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel Error",
+ "message": "Tunnel Error",
+ "translation": "Tunnelfel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "message": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "translation": "{ErrMsg}\n\nVänligen inspektera loggen för mer information.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "ErrMsg",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errMsg"
+ }
+ ]
+ },
+ {
+ "id": "{Title} (out of date)",
+ "message": "{Title} (out of date)",
+ "translation": "{Title} (föråldrad)",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Title",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "mtw.Title()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Detection Error",
+ "message": "WireGuard Detection Error",
+ "translation": "WireGuard Vaktfel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to wait for WireGuard window to appear: {Err}",
+ "message": "Unable to wait for WireGuard window to appear: {Err}",
+ "translation": "Lyckas inte vänta på att WireGuard fönstret ska visas: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard: Deactivated",
+ "message": "WireGuard: Deactivated",
+ "translation": "WireGuard: inaktiverad",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Unknown",
+ "message": "Status: Unknown",
+ "translation": "Status: Okänd",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Addresses: None",
+ "message": "Addresses: None",
+ "translation": "Adresser: Ingen",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Manage tunnels…",
+ "message": "&Manage tunnels…",
+ "translation": "&Hantera tunnlar…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Import tunnel(s) from file…",
+ "message": "&Import tunnel(s) from file…",
+ "translation": "&Importera tunnlar från fil…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "E&xit",
+ "message": "E&xit",
+ "translation": "A&vsluta",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Tunnels",
+ "message": "&Tunnels",
+ "translation": "&Tunnlar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Activated",
+ "message": "WireGuard Activated",
+ "translation": "WireGuard aktiverad",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "The {Name} tunnel has been activated.",
+ "message": "The {Name} tunnel has been activated.",
+ "translation": "{Name} tunneln har aktiverats.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnel.Name"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Deactivated",
+ "message": "WireGuard Deactivated",
+ "translation": "WireGuard inaktiverad",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "The {Name} tunnel has been deactivated.",
+ "message": "The {Name} tunnel has been deactivated.",
+ "translation": "{Name} tunneln har inaktiverats.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnel.Name"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Tunnel Error",
+ "message": "WireGuard Tunnel Error",
+ "translation": "WireGuard Tunnelfel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard: {TextForStateglobalState_true}",
+ "message": "WireGuard: {TextForStateglobalState_true}",
+ "translation": "WireGuard: {TextForStateglobalState_true}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TextForStateglobalState_true",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "textForState(globalState, true)"
+ }
+ ]
+ },
+ {
+ "id": "Status: {StateText}",
+ "message": "Status: {StateText}",
+ "translation": "Status: {StateText}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "StateText",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "stateText"
+ }
+ ]
+ },
+ {
+ "id": "Addresses: {EnumerationSeparator}",
+ "message": "Addresses: {EnumerationSeparator}",
+ "translation": "Adresser: {EnumerationSeparator}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "EnumerationSeparator",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "strings.Join(addrs, l18n.EnumerationSeparator())"
+ }
+ ]
+ },
+ {
+ "id": "An Update is Available!",
+ "message": "An Update is Available!",
+ "translation": "En uppdatering är tillgänglig!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Update Available",
+ "message": "WireGuard Update Available",
+ "translation": "WireGuard uppdatering tillgänglig",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "An update to WireGuard is now available. You are advised to update as soon as possible.",
+ "message": "An update to WireGuard is now available. You are advised to update as soon as possible.",
+ "translation": "En uppdatering till WireGuard är nu tillgänglig. Du rekommenderas att uppdatera så snart som möjligt.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnels",
+ "message": "Tunnels",
+ "translation": "Tunnlar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Edit",
+ "message": "&Edit",
+ "translation": "&Redigera",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Add &empty tunnel…",
+ "message": "Add &empty tunnel…",
+ "translation": "Lägg till &tom tunnel…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Add Tunnel",
+ "message": "Add Tunnel",
+ "translation": "Skapa tunnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Remove selected tunnel(s)",
+ "message": "Remove selected tunnel(s)",
+ "translation": "Ta bort valda tunnlar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export all tunnels to zip",
+ "message": "Export all tunnels to zip",
+ "translation": "Exportera alla tunnlar till zip",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Toggle",
+ "message": "&Toggle",
+ "translation": "&Växla",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export all tunnels to &zip…",
+ "message": "Export all tunnels to &zip…",
+ "translation": "Exportera alla tunnlar till &zip…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Edit &selected tunnel…",
+ "message": "Edit &selected tunnel…",
+ "translation": "Redigera &vald tunnel…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Remove selected tunnel(s)",
+ "message": "&Remove selected tunnel(s)",
+ "translation": "&Ta bort valda tunnlar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "no configuration files were found",
+ "message": "no configuration files were found",
+ "translation": "inga konfigurationsfiler hittades",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Could not import selected configuration: {LastErr}",
+ "message": "Could not import selected configuration: {LastErr}",
+ "translation": "Kunde inte importera vald konfiguration: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Could not enumerate existing tunnels: {LastErr}",
+ "message": "Could not enumerate existing tunnels: {LastErr}",
+ "translation": "Det gick inte att numrera existerande tunnlar: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Another tunnel already exists with the name ‘{Name}’",
+ "message": "Another tunnel already exists with the name ‘{Name}’",
+ "translation": "Det finns redan en annan tunnel med namnet ‘{Name}’",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "unparsedConfig.Name"
+ }
+ ]
+ },
+ {
+ "id": "Unable to import configuration: {LastErr}",
+ "message": "Unable to import configuration: {LastErr}",
+ "translation": "Kan inte importera konfiguration: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Imported tunnels",
+ "message": "Imported tunnels",
+ "translation": "Importerade tunnlar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Imported {M} tunnels",
+ "message": "Imported {M} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "M",
+ "cases": {
+ "one": {
+ "msg": "Importerade {M} tunnel"
+ },
+ "other": {
+ "msg": "Importerade {M} tunnlar"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ }
+ ]
+ },
+ {
+ "id": "Imported {M} of {N} tunnels",
+ "message": "Imported {M} of {N} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "N",
+ "cases": {
+ "one": {
+ "msg": "Importerade {M} av {N} tunnlar"
+ },
+ "other": {
+ "msg": "Importerade {M} av {N} tunnlar"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ },
+ {
+ "id": "N",
+ "string": "%[2]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 2,
+ "expr": "n"
+ }
+ ]
+ },
+ {
+ "id": "Unable to create tunnel",
+ "message": "Unable to create tunnel",
+ "translation": "Kan inte skapa tunnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Delete {TunnelCount} tunnels",
+ "message": "Delete {TunnelCount} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "TunnelCount",
+ "cases": {
+ "one": {
+ "msg": "Ta bort {TunnelCount} tunnel"
+ },
+ "other": {
+ "msg": "Ta bort {TunnelCount} tunnlar"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "TunnelCount",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "tunnelCount"
+ }
+ ]
+ },
+ {
+ "id": "Are you sure you would like to delete {TunnelCount} tunnels?",
+ "message": "Are you sure you would like to delete {TunnelCount} tunnels?",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "TunnelCount",
+ "cases": {
+ "one": {
+ "msg": "Är du säker på att du vill ta bort {TunnelCount} tunnel?"
+ },
+ "other": {
+ "msg": "Är du säker på att du vill radera {TunnelCount} tunnlar?"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "TunnelCount",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "tunnelCount"
+ }
+ ]
+ },
+ {
+ "id": "Delete tunnel ‘{TunnelName}’",
+ "message": "Delete tunnel ‘{TunnelName}’",
+ "translation": "Ta bort tunnel ‘{TunnelName}’",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TunnelName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnelName"
+ }
+ ]
+ },
+ {
+ "id": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
+ "message": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
+ "translation": "Är du säker på att du vill ta bort tunneln ‘{TunnelName}’?",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TunnelName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnelName"
+ }
+ ]
+ },
+ {
+ "id": "{Question} You cannot undo this action.",
+ "message": "{Question} You cannot undo this action.",
+ "translation": "{Question} Du kan inte ångra denna åtgärd.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Question",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "question"
+ }
+ ]
+ },
+ {
+ "id": "Unable to delete tunnel",
+ "message": "Unable to delete tunnel",
+ "translation": "Kan inte ta bort tunnel",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "A tunnel was unable to be removed: {Error}",
+ "message": "A tunnel was unable to be removed: {Error}",
+ "translation": "En tunnel kunde inte tas bort: {Error}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Error",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errors[0].Error()"
+ }
+ ]
+ },
+ {
+ "id": "Unable to delete tunnels",
+ "message": "Unable to delete tunnels",
+ "translation": "Kan inte ta bort tunnlar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Lenerrors} tunnels were unable to be removed.",
+ "message": "{Lenerrors} tunnels were unable to be removed.",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Lenerrors",
+ "cases": {
+ "one": {
+ "msg": "{Lenerrors} tunneln kunde inte tas bort."
+ },
+ "other": {
+ "msg": "{Lenerrors} tunnlar kunde inte tas bort."
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Lenerrors",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "len(errors)"
+ }
+ ]
+ },
+ {
+ "id": "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
+ "message": "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
+ "translation": "Inställningsfiler (*.zip, *.conf)|*.zip;*.conf|Alla filer (*.*)|*.*",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Import tunnel(s) from file",
+ "message": "Import tunnel(s) from file",
+ "translation": "Importera tunnlar från fil",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Configuration ZIP Files (*.zip)|*.zip",
+ "message": "Configuration ZIP Files (*.zip)|*.zip",
+ "translation": "Inställningsfiler ZIP (*.zip)|*.zip",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export tunnels to zip",
+ "message": "Export tunnels to zip",
+ "translation": "Exportera tunnlar till zip",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Title} (unsigned build, no updates)",
+ "message": "{Title} (unsigned build, no updates)",
+ "translation": "{Title} (osignerat bygge, inga uppdateringar)",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Title",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "mtw.Title()"
+ }
+ ]
+ },
+ {
+ "id": "Error Exiting WireGuard",
+ "message": "Error Exiting WireGuard",
+ "translation": "Fel när WireGuard avslutades",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
+ "message": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
+ "translation": "Det går inte att avsluta tjänsten på grund av {Err}. Du kanske vill stoppa WireGuard från servicehanteraren.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "message": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "translation": "En uppdatering av WireGuard finns tillgänglig. Uppdatering bör utföras snarast möjligt.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Waiting for user",
+ "message": "Status: Waiting for user",
+ "translation": "Status: Väntar på användaren",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Update Now",
+ "message": "Update Now",
+ "translation": "Uppdatera nu",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Waiting for updater service",
+ "message": "Status: Waiting for updater service",
+ "translation": "Status: Väntar på uppdateringstjänst",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error: {Err}. Please try again.",
+ "message": "Error: {Err}. Please try again.",
+ "translation": "Fel: {Err}. Vänligen försök igen.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Status: Complete!",
+ "message": "Status: Complete!",
+ "translation": "Status: Färdig!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "http2: Framer {F}: failed to decode just-written frame",
+ "message": "http2: Framer {F}: failed to decode just-written frame",
+ "translation": "http2: Framer {F}: misslyckades att avkoda \"just-written frame\"",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "F",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "f"
+ }
+ ]
+ },
+ {
+ "id": "http2: Framer {F}: wrote {Http2summarizeFramefr}",
+ "message": "http2: Framer {F}: wrote {Http2summarizeFramefr}",
+ "translation": "http2: Framer {F}: skrev {Http2summarizeFramefr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "F",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "f"
+ },
+ {
+ "id": "Http2summarizeFramefr",
+ "string": "%[2]v",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "http2summarizeFrame(fr)"
+ }
+ ]
+ },
+ {
+ "id": "http2: Framer {Fr}: read {Http2summarizeFramef}",
+ "message": "http2: Framer {Fr}: read {Http2summarizeFramef}",
+ "translation": "http2: Framer {Fr}: läs {Http2summarizeFramef}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Fr",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "fr"
+ },
+ {
+ "id": "Http2summarizeFramef",
+ "string": "%[2]v",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "http2summarizeFrame(f)"
+ }
+ ]
+ },
+ {
+ "id": "http2: decoded hpack field {HeaderField}",
+ "message": "http2: decoded hpack field {HeaderField}",
+ "translation": "http2: avkodat hpack fält {HeaderField}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "HeaderField",
+ "string": "%+[1]v",
+ "type": "vendor/golang.org/x/net/http2/hpack.HeaderField",
+ "underlyingType": "struct{Name string; Value string; Sensitive bool}",
+ "argNum": 1,
+ "expr": "hf"
+ }
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/locales/tr/messages.gotext.json b/locales/tr/messages.gotext.json
new file mode 100644
index 00000000..9aa7291e
--- /dev/null
+++ b/locales/tr/messages.gotext.json
@@ -0,0 +1,1847 @@
+{
+ "language": "tr",
+ "messages": [
+ {
+ "id": "Error",
+ "message": "Error",
+ "translation": "Hata",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "(no argument): elevate and install manager service",
+ "message": "(no argument): elevate and install manager service",
+ "translation": "(parametre belirtilmediyse): gerekli izinleri al ve yönetim hizmetini yükle",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Usage: {Args0} [\n{String}]",
+ "message": "Usage: {Args0} [\n{String}]",
+ "translation": "Kullanım: {Args0} [\n{String}]",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Args0",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "os.Args[0]"
+ },
+ {
+ "id": "String",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "builder.String()"
+ }
+ ]
+ },
+ {
+ "id": "Command Line Options",
+ "message": "Command Line Options",
+ "translation": "Komut Satırı Seçenekleri",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to determine whether the process is running under WOW64: {Err}",
+ "message": "Unable to determine whether the process is running under WOW64: {Err}",
+ "translation": "İşlemin WOW64 altında çalıştığından emin olunamadı: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "You must use the native version of WireGuard on this computer.",
+ "message": "You must use the native version of WireGuard on this computer.",
+ "translation": "Bu bilgisayarda WireGuard'ın yerel sürümünü kullanmalısınız.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to open current process token: {Err}",
+ "message": "Unable to open current process token: {Err}",
+ "translation": "Geçerli işlem jetonu açılamadı: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard may only be used by users who are a member of the Builtin {AdminGroupName} group.",
+ "message": "WireGuard may only be used by users who are a member of the Builtin {AdminGroupName} group.",
+ "translation": "WireGuard'ı sadece yerleşik {AdminGroupName} grubunun üyeleri kullanabilir.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "AdminGroupName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "elevate.AdminGroupName()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard is running, but the UI is only accessible from desktops of the Builtin {AdminGroupName} group.",
+ "message": "WireGuard is running, but the UI is only accessible from desktops of the Builtin {AdminGroupName} group.",
+ "translation": "WireGuard çalışıyor fakat kullanıcı arayüzüne sadece yerleşik {AdminGroupName} grubunun bilgisayarlarından erişilebilir.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "AdminGroupName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "elevate.AdminGroupName()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard system tray icon did not appear after 30 seconds.",
+ "message": "WireGuard system tray icon did not appear after 30 seconds.",
+ "translation": "WireGuard sistem tepsisi simgesi 30 saniye sonunda belirmedi.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Now",
+ "message": "Now",
+ "translation": "Şimdi",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "System clock wound backward!",
+ "message": "System clock wound backward!",
+ "translation": "Sistem saati geri alınmış!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Years} year(s)",
+ "message": "{Years} year(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Years",
+ "cases": {
+ "one": {
+ "msg": "{Years} yıl"
+ },
+ "other": {
+ "msg": "{Years} yıl"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Years",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "years"
+ }
+ ]
+ },
+ {
+ "id": "{Days} day(s)",
+ "message": "{Days} day(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Days",
+ "cases": {
+ "one": {
+ "msg": "{Days} gün"
+ },
+ "other": {
+ "msg": "{Days} gün"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Days",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "days"
+ }
+ ]
+ },
+ {
+ "id": "{Hours} hour(s)",
+ "message": "{Hours} hour(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Hours",
+ "cases": {
+ "one": {
+ "msg": "{Hours} saat"
+ },
+ "other": {
+ "msg": "{Hours} saat"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Hours",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "hours"
+ }
+ ]
+ },
+ {
+ "id": "{Minutes} minute(s)",
+ "message": "{Minutes} minute(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Minutes",
+ "cases": {
+ "one": {
+ "msg": "{Minutes} dakika"
+ },
+ "other": {
+ "msg": "{Minutes} dakika"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Minutes",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "minutes"
+ }
+ ]
+ },
+ {
+ "id": "{Seconds} second(s)",
+ "message": "{Seconds} second(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Seconds",
+ "cases": {
+ "one": {
+ "msg": "{Seconds} saniye"
+ },
+ "other": {
+ "msg": "{Seconds} saniye"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Seconds",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "seconds"
+ }
+ ]
+ },
+ {
+ "id": "{Timestamp} ago",
+ "message": "{Timestamp} ago",
+ "translation": "{Timestamp} önce",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Timestamp",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "timestamp"
+ }
+ ]
+ },
+ {
+ "id": "{Bytes} B",
+ "message": "{Bytes} B",
+ "translation": "{Bytes} B",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Bytes",
+ "string": "%[1]d",
+ "type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
+ "underlyingType": "uint64",
+ "argNum": 1,
+ "expr": "b"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024} KiB",
+ "message": "{Float64b__1024} KiB",
+ "translation": "{Float64b__1024} KiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / 1024"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024} MiB",
+ "message": "{Float64b__1024__1024} MiB",
+ "translation": "{Float64b__1024__1024} MiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024} GiB",
+ "message": "{Float64b__1024__1024__1024} GiB",
+ "translation": "{Float64b__1024__1024__1024} GiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024__1024} TiB",
+ "message": "{Float64b__1024__1024__1024__1024} TiB",
+ "translation": "{Float64b__1024__1024__1024__1024} TiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024) / 1024"
+ }
+ ]
+ },
+ {
+ "id": "{Why}: {Offender}",
+ "message": "{Why}: {Offender}",
+ "translation": "{Why}: {Offender}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Why",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "e.why"
+ },
+ {
+ "id": "Offender",
+ "string": "%[2]q",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "e.offender"
+ }
+ ]
+ },
+ {
+ "id": "Invalid IP address",
+ "message": "Invalid IP address",
+ "translation": "Geçersiz IP adresi",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid network prefix length",
+ "message": "Invalid network prefix length",
+ "translation": "Geçersiz ağ öneki uzunluğu",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Missing port from endpoint",
+ "message": "Missing port from endpoint",
+ "translation": "Uç nokta portu eksik",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid endpoint host",
+ "message": "Invalid endpoint host",
+ "translation": "Geçersiz uç nokta",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Brackets must contain an IPv6 address",
+ "message": "Brackets must contain an IPv6 address",
+ "translation": "Köşeli parantezler IPv6 adresi içermelidir",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid MTU",
+ "message": "Invalid MTU",
+ "translation": "Geçersiz MTU",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid port",
+ "message": "Invalid port",
+ "translation": "Geçersiz port",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid persistent keepalive",
+ "message": "Invalid persistent keepalive",
+ "translation": "Geçersiz sürekli keepalive",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key: {Err}",
+ "message": "Invalid key: {Err}",
+ "translation": "Geçersiz anahtar: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Keys must decode to exactly 32 bytes",
+ "message": "Keys must decode to exactly 32 bytes",
+ "translation": "Anahtarlar çözüldüğünde tam 32 bayt olmalıdır",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Number must be a number between 0 and 2^64-1: {Err}",
+ "message": "Number must be a number between 0 and 2^64-1: {Err}",
+ "translation": "Sayı 0 ile 2^64-1 arasında olmalıdır: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Two commas in a row",
+ "message": "Two commas in a row",
+ "translation": "Yan yana iki virgül",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel name is not valid",
+ "message": "Tunnel name is not valid",
+ "translation": "Tünel adı geçerli değil",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Line must occur in a section",
+ "message": "Line must occur in a section",
+ "translation": "Satır bir bölüm içinde olmalıdır",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Config key is missing an equals separator",
+ "message": "Config key is missing an equals separator",
+ "translation": "Yapılandırma anahtarında eşittir ayracı eksik",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Key must have a value",
+ "message": "Key must have a value",
+ "translation": "Anahtar bir değere sahip olmalı",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for [Interface] section",
+ "message": "Invalid key for [Interface] section",
+ "translation": "[Interface] bölümü için geçersiz anahtar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for [Peer] section",
+ "message": "Invalid key for [Peer] section",
+ "translation": "[Peer] bölümü için geçersiz anahtar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "An interface must have a private key",
+ "message": "An interface must have a private key",
+ "translation": "Arabirimde gizli anahtar bulunmalıdır",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "[none specified]",
+ "message": "[none specified]",
+ "translation": "[belirtilmedi]",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "All peers must have public keys",
+ "message": "All peers must have public keys",
+ "translation": "Tüm eşlerin ortak anahtarları olmalıdır",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error in getting configuration",
+ "message": "Error in getting configuration",
+ "translation": "Yapılandırma alınırken hata oluştu",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for interface section",
+ "message": "Invalid key for interface section",
+ "translation": "Arabirim bölümünde geçersiz anahtar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Protocol version must be 1",
+ "message": "Protocol version must be 1",
+ "translation": "Protokol sürümü 1 olmalıdır",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid key for peer section",
+ "message": "Invalid key for peer section",
+ "translation": "Eş bölümünde geçersiz anahtar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "[EnumerationSeparator]",
+ "message": "[EnumerationSeparator]",
+ "translation": ", ",
+ "comment": "Text to insert between items when listing - most western languages will translate ‘[EnumerationSeparator]’ into ‘, ’ to produce lists like ‘apple, orange, strawberry’. Eastern languages might translate into ‘、’ to produce lists like ‘リンゴ、オレンジ、イチゴ’."
+ },
+ {
+ "id": "[UnitSeparator]",
+ "message": "[UnitSeparator]",
+ "translation": ", ",
+ "comment": "Text to insert when combining units of a measure - most languages will translate ‘[UnitSeparator]’ into ‘ ’ (space) to produce lists like ‘2 minuti 30 sekund’, or empty string ‘’ to produce ‘2分30秒’."
+ },
+ {
+ "id": "About WireGuard",
+ "message": "About WireGuard",
+ "translation": "WireGuard Hakkında",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard logo image",
+ "message": "WireGuard logo image",
+ "translation": "WireGuard logosu",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "message": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "translation": "Uygulama sürümü: {Number}\nGo arka uç sürümü: {WireGuardGoVersion}\nGo sürümü: {Version_go}-{GOARCH}\nİşletim sistemi: {OsName}\nMimari: {NativeArch}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Number",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "version.Number"
+ },
+ {
+ "id": "WireGuardGoVersion",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "device.WireGuardGoVersion"
+ },
+ {
+ "id": "Version_go",
+ "string": "%[3]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 3,
+ "expr": "strings.TrimPrefix(runtime.Version(), \"go\")"
+ },
+ {
+ "id": "GOARCH",
+ "string": "%[4]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 4,
+ "expr": "runtime.GOARCH"
+ },
+ {
+ "id": "OsName",
+ "string": "%[5]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 5,
+ "expr": "version.OsName()"
+ },
+ {
+ "id": "NativeArch",
+ "string": "%[6]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 6,
+ "expr": "version.NativeArch()"
+ }
+ ]
+ },
+ {
+ "id": "Close",
+ "message": "Close",
+ "translation": "Kapat",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "♥ &Donate!",
+ "message": "♥ &Donate!",
+ "translation": "♥ &Bağış yap!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status:",
+ "message": "Status:",
+ "translation": "Durum:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Deactivate",
+ "message": "&Deactivate",
+ "translation": "&Devre dışı bırak",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Activate",
+ "message": "&Activate",
+ "translation": "&Etkinleştir",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Public key:",
+ "message": "Public key:",
+ "translation": "Ortak anahtar:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Listen port:",
+ "message": "Listen port:",
+ "translation": "Dinlenen port:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "MTU:",
+ "message": "MTU:",
+ "translation": "MTU:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Addresses:",
+ "message": "Addresses:",
+ "translation": "Adresler:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "DNS servers:",
+ "message": "DNS servers:",
+ "translation": "DNS sunucuları:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Scripts:",
+ "message": "Scripts:",
+ "translation": "Betikler:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Preshared key:",
+ "message": "Preshared key:",
+ "translation": "Önceden paylaşılan anahtar:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Allowed IPs:",
+ "message": "Allowed IPs:",
+ "translation": "İzin verilen IP’ler:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Endpoint:",
+ "message": "Endpoint:",
+ "translation": "Uç nokta:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Persistent keepalive:",
+ "message": "Persistent keepalive:",
+ "translation": "Sürekli keepalive:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Latest handshake:",
+ "message": "Latest handshake:",
+ "translation": "En son el sıkışma:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Transfer:",
+ "message": "Transfer:",
+ "translation": "Aktarım:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-up",
+ "message": "pre-up",
+ "translation": "bağlantı öncesi",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-up",
+ "message": "post-up",
+ "translation": "bağlantı sonrası",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-down",
+ "message": "pre-down",
+ "translation": "bağlantı kesme öncesi",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-down",
+ "message": "post-down",
+ "translation": "bağlantı kesme sonrası",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "disabled, per policy",
+ "message": "disabled, per policy",
+ "translation": "ilke gereği devre dışı",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "enabled",
+ "message": "enabled",
+ "translation": "etkin",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{String} received, {String_1} sent",
+ "message": "{String} received, {String_1} sent",
+ "translation": "{String} alındı, {String_1} gönderildi",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "String",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "c.RxBytes.String()"
+ },
+ {
+ "id": "String_1",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "c.TxBytes.String()"
+ }
+ ]
+ },
+ {
+ "id": "Failed to determine tunnel state",
+ "message": "Failed to determine tunnel state",
+ "translation": "Tünel durumu belirlenemedi",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Failed to activate tunnel",
+ "message": "Failed to activate tunnel",
+ "translation": "Tünel etkinleştirilemedi",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Failed to deactivate tunnel",
+ "message": "Failed to deactivate tunnel",
+ "translation": "Tünel devre dışı bırakılamadı",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Interface: {Name}",
+ "message": "Interface: {Name}",
+ "translation": "Arabirim: {Name}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "config.Name"
+ }
+ ]
+ },
+ {
+ "id": "Peer",
+ "message": "Peer",
+ "translation": "Eş",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Create new tunnel",
+ "message": "Create new tunnel",
+ "translation": "Yeni tünel oluştur",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Edit tunnel",
+ "message": "Edit tunnel",
+ "translation": "Tüneli düzenle",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Name:",
+ "message": "&Name:",
+ "translation": "&İsim:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Public key:",
+ "message": "&Public key:",
+ "translation": "&Ortak anahtar:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "(unknown)",
+ "message": "(unknown)",
+ "translation": "(bilinmiyor)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Block untunneled traffic (kill-switch)",
+ "message": "&Block untunneled traffic (kill-switch)",
+ "translation": "&Tünelden geçmeyen trafiği engelle (kill switch)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "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 or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "message": "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 or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "translation": "Yapılandırmada tek bir eş varsa ve bu eşin izinli IP listesinde 0.0.0.0/0 veya ::/0 bulunuyorsa tünel hizmeti, DHCP ve NDP'ye ait istisnalar dışında tünel arabirimine gitmeyen veya bu arabirimden gelmeyen veya yanlış DNS sunucusuna giden tüm trafiği engellemek için güvenlik duvarına bir kural kümesi ekler.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Save",
+ "message": "&Save",
+ "translation": "&Kaydet",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Cancel",
+ "message": "Cancel",
+ "translation": "İptal",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Configuration:",
+ "message": "&Configuration:",
+ "translation": "&Yapılandırma:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid name",
+ "message": "Invalid name",
+ "translation": "Geçersiz isim",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "A name is required.",
+ "message": "A name is required.",
+ "translation": "Bir isim girmelisiniz.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel name ‘{NewName}’ is invalid.",
+ "message": "Tunnel name ‘{NewName}’ is invalid.",
+ "translation": "‘{NewName}’ geçersiz bir tünel ismi.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "NewName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "newName"
+ }
+ ]
+ },
+ {
+ "id": "Unable to list existing tunnels",
+ "message": "Unable to list existing tunnels",
+ "translation": "Mevcut tüneller listelenemedi",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel already exists",
+ "message": "Tunnel already exists",
+ "translation": "Tünel zaten mevcut",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Another tunnel already exists with the name ‘{NewName}’.",
+ "message": "Another tunnel already exists with the name ‘{NewName}’.",
+ "translation": "‘{NewName}’ adında başka bir tünel mevcut.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "NewName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "newName"
+ }
+ ]
+ },
+ {
+ "id": "Unable to create new configuration",
+ "message": "Unable to create new configuration",
+ "translation": "Yeni yapılandırma oluşturulamadı",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Writing file failed",
+ "message": "Writing file failed",
+ "translation": "Dosya yazılamadı",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "File ‘{FilePath}’ already exists.\n\nDo you want to overwrite it?",
+ "message": "File ‘{FilePath}’ already exists.\n\nDo you want to overwrite it?",
+ "translation": "`{FilePath}` dosyası zaten mevcut.\n\nÜzerine yazmak ister misiniz?",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "FilePath",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "filePath"
+ }
+ ]
+ },
+ {
+ "id": "Active",
+ "message": "Active",
+ "translation": "Etkin",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Activating",
+ "message": "Activating",
+ "translation": "Etkinleştiriliyor",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Inactive",
+ "message": "Inactive",
+ "translation": "Devre dışı",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Deactivating",
+ "message": "Deactivating",
+ "translation": "Devre dışı bırakılıyor",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unknown state",
+ "message": "Unknown state",
+ "translation": "Durum bilinmiyor",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Log",
+ "message": "Log",
+ "translation": "Günlük",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Copy",
+ "message": "&Copy",
+ "translation": "&Kopyala",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Select &all",
+ "message": "Select &all",
+ "translation": "&Tümünü seç",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Save to file…",
+ "message": "&Save to file…",
+ "translation": "&Dosyaya kaydet…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Time",
+ "message": "Time",
+ "translation": "Saat",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Log message",
+ "message": "Log message",
+ "translation": "Günlük mesajı",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "message": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "translation": "Metin dosyaları (*.txt)|*.txt|Tüm dosyalar (*.*)|*.*",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export log to file",
+ "message": "Export log to file",
+ "translation": "Günlüğü dosyaya aktar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&About WireGuard…",
+ "message": "&About WireGuard…",
+ "translation": "&WireGuard hakkında…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel Error",
+ "message": "Tunnel Error",
+ "translation": "Tünel Hatası",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "message": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "translation": "{ErrMsg}\n\nDaha fazla bilgi için lütfen günlüğe göz atın.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "ErrMsg",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errMsg"
+ }
+ ]
+ },
+ {
+ "id": "{Title} (out of date)",
+ "message": "{Title} (out of date)",
+ "translation": "{Title} (eski sürüm)",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Title",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "mtw.Title()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Detection Error",
+ "message": "WireGuard Detection Error",
+ "translation": "WireGuard Tespit Hatası",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to wait for WireGuard window to appear: {Err}",
+ "message": "Unable to wait for WireGuard window to appear: {Err}",
+ "translation": "WireGuard penceresinin belirmesi beklenemedi: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard: Deactivated",
+ "message": "WireGuard: Deactivated",
+ "translation": "WireGuard: Devre dışı",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Unknown",
+ "message": "Status: Unknown",
+ "translation": "Durum: Bilinmiyor",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Addresses: None",
+ "message": "Addresses: None",
+ "translation": "Adresler: Yok",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Manage tunnels…",
+ "message": "&Manage tunnels…",
+ "translation": "&Tünelleri yönet…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Import tunnel(s) from file…",
+ "message": "&Import tunnel(s) from file…",
+ "translation": "Tünelleri dosyadan &içe aktar…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "E&xit",
+ "message": "E&xit",
+ "translation": "Çı&kış",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Tunnels",
+ "message": "&Tunnels",
+ "translation": "&Tüneller",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Activated",
+ "message": "WireGuard Activated",
+ "translation": "WireGuard Etkin",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "The {Name} tunnel has been activated.",
+ "message": "The {Name} tunnel has been activated.",
+ "translation": "{Name} tüneli etkinleştirildi.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnel.Name"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Deactivated",
+ "message": "WireGuard Deactivated",
+ "translation": "WireGuard Devre Dışı Bırakıldı",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "The {Name} tunnel has been deactivated.",
+ "message": "The {Name} tunnel has been deactivated.",
+ "translation": "{Name} tüneli devre dışı bırakıldı.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnel.Name"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Tunnel Error",
+ "message": "WireGuard Tunnel Error",
+ "translation": "WireGuard Tünel Hatası",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard: {TextForStateglobalState_true}",
+ "message": "WireGuard: {TextForStateglobalState_true}",
+ "translation": "WireGuard: {TextForStateglobalState_true}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TextForStateglobalState_true",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "textForState(globalState, true)"
+ }
+ ]
+ },
+ {
+ "id": "Status: {StateText}",
+ "message": "Status: {StateText}",
+ "translation": "Durum: {StateText}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "StateText",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "stateText"
+ }
+ ]
+ },
+ {
+ "id": "Addresses: {EnumerationSeparator}",
+ "message": "Addresses: {EnumerationSeparator}",
+ "translation": "Adresler: {EnumerationSeparator}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "EnumerationSeparator",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "strings.Join(addrs, l18n.EnumerationSeparator())"
+ }
+ ]
+ },
+ {
+ "id": "An Update is Available!",
+ "message": "An Update is Available!",
+ "translation": "Güncelleme Mevcut!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Update Available",
+ "message": "WireGuard Update Available",
+ "translation": "WireGuard Güncellemesi Mevcut",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "An update to WireGuard is now available. You are advised to update as soon as possible.",
+ "message": "An update to WireGuard is now available. You are advised to update as soon as possible.",
+ "translation": "Yeni bir WireGuard güncellemesi yayımlandı. İlk fırsatta güncelleme yapmanız tavsiye edilir.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnels",
+ "message": "Tunnels",
+ "translation": "Tüneller",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Edit",
+ "message": "&Edit",
+ "translation": "&Düzenle",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Add &empty tunnel…",
+ "message": "Add &empty tunnel…",
+ "translation": "Boş tünel &ekle…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Add Tunnel",
+ "message": "Add Tunnel",
+ "translation": "Tünel ekle",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Remove selected tunnel(s)",
+ "message": "Remove selected tunnel(s)",
+ "translation": "Seçilen tünelleri kaldır",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export all tunnels to zip",
+ "message": "Export all tunnels to zip",
+ "translation": "Tüm tünelleri zip olarak dışa aktar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Toggle",
+ "message": "&Toggle",
+ "translation": "&Aç/kapat",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export all tunnels to &zip…",
+ "message": "Export all tunnels to &zip…",
+ "translation": "Tüm tünelleri &zip olarak dışa aktar…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Edit &selected tunnel…",
+ "message": "Edit &selected tunnel…",
+ "translation": "&Seçilen tüneli düzenle…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Remove selected tunnel(s)",
+ "message": "&Remove selected tunnel(s)",
+ "translation": "S&eçilen tünelleri kaldır",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "no configuration files were found",
+ "message": "no configuration files were found",
+ "translation": "yapılandırma dosyası bulunamadı",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Could not import selected configuration: {LastErr}",
+ "message": "Could not import selected configuration: {LastErr}",
+ "translation": "Seçilen yapılandırma içe aktarılamadı: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Could not enumerate existing tunnels: {LastErr}",
+ "message": "Could not enumerate existing tunnels: {LastErr}",
+ "translation": "Mevcut tüneller sıralanamadı: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Another tunnel already exists with the name ‘{Name}’",
+ "message": "Another tunnel already exists with the name ‘{Name}’",
+ "translation": "‘{Name}’ adında başka bir tünel mevcut",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "unparsedConfig.Name"
+ }
+ ]
+ },
+ {
+ "id": "Unable to import configuration: {LastErr}",
+ "message": "Unable to import configuration: {LastErr}",
+ "translation": "Yapılandırma içe aktarılamadı: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Imported tunnels",
+ "message": "Imported tunnels",
+ "translation": "Tüneller içe aktarıldı",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Imported {M} tunnels",
+ "message": "Imported {M} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "M",
+ "cases": {
+ "one": {
+ "msg": "{M} tünel içe aktarıldı"
+ },
+ "other": {
+ "msg": "{M} tünel içe aktarıldı"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ }
+ ]
+ },
+ {
+ "id": "Imported {M} of {N} tunnels",
+ "message": "Imported {M} of {N} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "N",
+ "cases": {
+ "one": {
+ "msg": "{N}/{M} tünel içe aktarıldı"
+ },
+ "other": {
+ "msg": "{N}/{M} tünel içe aktarıldı"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ },
+ {
+ "id": "N",
+ "string": "%[2]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 2,
+ "expr": "n"
+ }
+ ]
+ },
+ {
+ "id": "Unable to create tunnel",
+ "message": "Unable to create tunnel",
+ "translation": "Tünel oluşturulamadı",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Delete {TunnelCount} tunnels",
+ "message": "Delete {TunnelCount} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "TunnelCount",
+ "cases": {
+ "one": {
+ "msg": "{TunnelCount} tüneli sil"
+ },
+ "other": {
+ "msg": "{TunnelCount} tüneli sil"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "TunnelCount",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "tunnelCount"
+ }
+ ]
+ },
+ {
+ "id": "Are you sure you would like to delete {TunnelCount} tunnels?",
+ "message": "Are you sure you would like to delete {TunnelCount} tunnels?",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "TunnelCount",
+ "cases": {
+ "one": {
+ "msg": "{TunnelCount} tüneli silmek istediğinizden emin misiniz?"
+ },
+ "other": {
+ "msg": "{TunnelCount} tüneli silmek istediğinizden emin misiniz?"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "TunnelCount",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "tunnelCount"
+ }
+ ]
+ },
+ {
+ "id": "Delete tunnel ‘{TunnelName}’",
+ "message": "Delete tunnel ‘{TunnelName}’",
+ "translation": "‘{TunnelName}’ tünelini sil",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TunnelName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnelName"
+ }
+ ]
+ },
+ {
+ "id": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
+ "message": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
+ "translation": "‘{TunnelName}’ tünelini silmek istediğinizden emin misiniz?",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TunnelName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnelName"
+ }
+ ]
+ },
+ {
+ "id": "{Question} You cannot undo this action.",
+ "message": "{Question} You cannot undo this action.",
+ "translation": "{Question} Bu işlemi geri alamazsınız.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Question",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "question"
+ }
+ ]
+ },
+ {
+ "id": "Unable to delete tunnel",
+ "message": "Unable to delete tunnel",
+ "translation": "Tünel silinemedi",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "A tunnel was unable to be removed: {Error}",
+ "message": "A tunnel was unable to be removed: {Error}",
+ "translation": "Bir tünel kaldırılamadı: {Error}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Error",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errors[0].Error()"
+ }
+ ]
+ },
+ {
+ "id": "Unable to delete tunnels",
+ "message": "Unable to delete tunnels",
+ "translation": "Tüneller silinemedi",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Lenerrors} tunnels were unable to be removed.",
+ "message": "{Lenerrors} tunnels were unable to be removed.",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Lenerrors",
+ "cases": {
+ "one": {
+ "msg": "{Lenerrors} tünel kaldırılamadı."
+ },
+ "other": {
+ "msg": "{Lenerrors} tünel kaldırılamadı."
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Lenerrors",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "len(errors)"
+ }
+ ]
+ },
+ {
+ "id": "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
+ "message": "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
+ "translation": "Yapılandırma dosyaları (*.zip, *.conf)|*.zip;*.conf|Tüm dosyalar (*.*)|*.*",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Import tunnel(s) from file",
+ "message": "Import tunnel(s) from file",
+ "translation": "Tünelleri dosyadan içe aktar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Configuration ZIP Files (*.zip)|*.zip",
+ "message": "Configuration ZIP Files (*.zip)|*.zip",
+ "translation": "Yapılandırma ZIP dosyaları (*.zip)|*.zip",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export tunnels to zip",
+ "message": "Export tunnels to zip",
+ "translation": "Tünelleri zip olarak dışa aktar",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Title} (unsigned build, no updates)",
+ "message": "{Title} (unsigned build, no updates)",
+ "translation": "{Title} (imzasız derleme, güncelleme yok)",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Title",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "mtw.Title()"
+ }
+ ]
+ },
+ {
+ "id": "Error Exiting WireGuard",
+ "message": "Error Exiting WireGuard",
+ "translation": "WireGuard Çıkış Hatası",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
+ "message": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
+ "translation": "Şu nedenden dolayı hizmetten çıkılamadı: {Err}. WireGuard'ı hizmet yöneticisinden durdurabilirsiniz.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "message": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "translation": "Yeni bir WireGuard güncellemesi yayımlandı. Vakit kaybetmeden güncelleme yapmanız tavsiye edilir.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Waiting for user",
+ "message": "Status: Waiting for user",
+ "translation": "Durum: Kullanıcı bekleniyor",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Update Now",
+ "message": "Update Now",
+ "translation": "Şimdi güncelle",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Waiting for updater service",
+ "message": "Status: Waiting for updater service",
+ "translation": "Durum: Güncelleştirme hizmeti bekleniyor",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error: {Err}. Please try again.",
+ "message": "Error: {Err}. Please try again.",
+ "translation": "Hata: {Err}. Lütfen yeniden deneyin.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Status: Complete!",
+ "message": "Status: Complete!",
+ "translation": "Durum: Tamamlandı!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "http2: Framer {F}: failed to decode just-written frame",
+ "message": "http2: Framer {F}: failed to decode just-written frame",
+ "translation": "http2: Framer {F}: az önce yazılmış çerçeve çözülemedi",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "F",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "f"
+ }
+ ]
+ },
+ {
+ "id": "http2: Framer {F}: wrote {Http2summarizeFramefr}",
+ "message": "http2: Framer {F}: wrote {Http2summarizeFramefr}",
+ "translation": "http2: Framer {F}: {Http2summarizeFramefr} yazıldı",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "F",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "f"
+ },
+ {
+ "id": "Http2summarizeFramefr",
+ "string": "%[2]v",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "http2summarizeFrame(fr)"
+ }
+ ]
+ },
+ {
+ "id": "http2: Framer {Fr}: read {Http2summarizeFramef}",
+ "message": "http2: Framer {Fr}: read {Http2summarizeFramef}",
+ "translation": "http2: Framer {Fr}: {Http2summarizeFramef} okundu",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Fr",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "fr"
+ },
+ {
+ "id": "Http2summarizeFramef",
+ "string": "%[2]v",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "http2summarizeFrame(f)"
+ }
+ ]
+ },
+ {
+ "id": "http2: decoded hpack field {HeaderField}",
+ "message": "http2: decoded hpack field {HeaderField}",
+ "translation": "https2: {HeaderField} hpack alanı çözüldü",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "HeaderField",
+ "string": "%+[1]v",
+ "type": "vendor/golang.org/x/net/http2/hpack.HeaderField",
+ "underlyingType": "struct{Name string; Value string; Sensitive bool}",
+ "argNum": 1,
+ "expr": "hf"
+ }
+ ]
+ }
+ ]
+} \ No newline at end of file
diff --git a/locales/uk/messages.gotext.json b/locales/uk/messages.gotext.json
index ca6635da..c5d41082 100644
--- a/locales/uk/messages.gotext.json
+++ b/locales/uk/messages.gotext.json
@@ -8,6 +8,36 @@
"translatorComment": "Copied from source."
},
{
+ "id": "(no argument): elevate and install manager service",
+ "message": "(no argument): elevate and install manager service",
+ "translation": "(немає аргумента): отримати права аднімістратора і встановити службу",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Usage: {Args0} [\n{String}]",
+ "message": "Usage: {Args0} [\n{String}]",
+ "translation": "Використання: {Args0} [\n{String}]",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Args0",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "os.Args[0]"
+ },
+ {
+ "id": "String",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "builder.String()"
+ }
+ ]
+ },
+ {
"id": "Command Line Options",
"message": "Command Line Options",
"translation": "Параметри командного рядка",
@@ -30,6 +60,12 @@
]
},
{
+ "id": "You must use the native version of WireGuard on this computer.",
+ "message": "You must use the native version of WireGuard on this computer.",
+ "translation": "Ви повинні використовувати нативну версію WireGuard на цьому комп'ютері.",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Unable to open current process token: {Err}",
"message": "Unable to open current process token: {Err}",
"translation": "Не вдалося відкрити токен поточного процесу: {Err}",
@@ -96,6 +132,176 @@
"translatorComment": "Copied from source."
},
{
+ "id": "{Years} year(s)",
+ "message": "{Years} year(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Years",
+ "cases": {
+ "one": {
+ "msg": "{Years} рік"
+ },
+ "few": {
+ "msg": "{Years} роки"
+ },
+ "many": {
+ "msg": "{Years} років"
+ },
+ "other": {
+ "msg": "{Years} років"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Years",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "years"
+ }
+ ]
+ },
+ {
+ "id": "{Days} day(s)",
+ "message": "{Days} day(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Days",
+ "cases": {
+ "one": {
+ "msg": "{Days} день"
+ },
+ "few": {
+ "msg": "{Days} дні"
+ },
+ "many": {
+ "msg": "{Days} днів"
+ },
+ "other": {
+ "msg": "{Days} днів"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Days",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "days"
+ }
+ ]
+ },
+ {
+ "id": "{Hours} hour(s)",
+ "message": "{Hours} hour(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Hours",
+ "cases": {
+ "one": {
+ "msg": "{Hours} година"
+ },
+ "few": {
+ "msg": "{Hours} години"
+ },
+ "many": {
+ "msg": "{Hours} години"
+ },
+ "other": {
+ "msg": "{Hours} годин"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Hours",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "hours"
+ }
+ ]
+ },
+ {
+ "id": "{Minutes} minute(s)",
+ "message": "{Minutes} minute(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Minutes",
+ "cases": {
+ "one": {
+ "msg": "{Minutes} хвилина"
+ },
+ "few": {
+ "msg": "{Minutes} хвилини"
+ },
+ "many": {
+ "msg": "{Minutes} хвилин"
+ },
+ "other": {
+ "msg": "{Minutes} хвилин"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Minutes",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "minutes"
+ }
+ ]
+ },
+ {
+ "id": "{Seconds} second(s)",
+ "message": "{Seconds} second(s)",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Seconds",
+ "cases": {
+ "one": {
+ "msg": "{Seconds} секунда"
+ },
+ "few": {
+ "msg": "{Seconds} секунди"
+ },
+ "many": {
+ "msg": "{Seconds} секунд"
+ },
+ "other": {
+ "msg": "{Seconds} секунд"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Seconds",
+ "string": "%[1]d",
+ "type": "int64",
+ "underlyingType": "int64",
+ "argNum": 1,
+ "expr": "seconds"
+ }
+ ]
+ },
+ {
"id": "{Timestamp} ago",
"message": "{Timestamp} ago",
"translation": "{Timestamp} тому",
@@ -178,7 +384,7 @@
{
"id": "{Float64b__1024__1024__1024__1024} TiB",
"message": "{Float64b__1024__1024__1024__1024} TiB",
- "translation": "{Float64b__1024__1024__1024__1024} ТБ",
+ "translation": "{Float64b__1024__1024__1024__1024} TiB",
"translatorComment": "Copied from source.",
"placeholders": [
{
@@ -192,6 +398,30 @@
]
},
{
+ "id": "{Why}: {Offender}",
+ "message": "{Why}: {Offender}",
+ "translation": "{Why}: {Offender}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Why",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "e.why"
+ },
+ {
+ "id": "Offender",
+ "string": "%[2]q",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "e.offender"
+ }
+ ]
+ },
+ {
"id": "Invalid IP address",
"message": "Invalid IP address",
"translation": "Недійсна IP-адреса",
@@ -234,6 +464,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Invalid persistent keepalive",
+ "message": "Invalid persistent keepalive",
+ "translation": "Некоректне значення keepalive",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Invalid key: {Err}",
"message": "Invalid key: {Err}",
"translation": "Недійсний ключ: {Err}",
@@ -250,12 +486,40 @@
]
},
{
+ "id": "Keys must decode to exactly 32 bytes",
+ "message": "Keys must decode to exactly 32 bytes",
+ "translation": "Ключ повинен декодуватись до 32 байт",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Number must be a number between 0 and 2^64-1: {Err}",
+ "message": "Number must be a number between 0 and 2^64-1: {Err}",
+ "translation": "Номер повинен бути числом від 0 до 2^64-1: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
"id": "Two commas in a row",
"message": "Two commas in a row",
"translation": "Дві коми поспіль",
"translatorComment": "Copied from source."
},
{
+ "id": "Tunnel name is not valid",
+ "message": "Tunnel name is not valid",
+ "translation": "Назва тунелю некоректна",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Line must occur in a section",
"message": "Line must occur in a section",
"translation": "Рядок повинен бути вказаним у розділі",
@@ -322,6 +586,24 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Invalid key for peer section",
+ "message": "Invalid key for peer section",
+ "translation": "Хибний ключ для [Peer] розділу",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "[EnumerationSeparator]",
+ "message": "[EnumerationSeparator]",
+ "translation": ", ",
+ "comment": "Text to insert between items when listing - most western languages will translate ‘[EnumerationSeparator]’ into ‘, ’ to produce lists like ‘apple, orange, strawberry’. Eastern languages might translate into ‘、’ to produce lists like ‘リンゴ、オレンジ、イチゴ’."
+ },
+ {
+ "id": "[UnitSeparator]",
+ "message": "[UnitSeparator]",
+ "translation": ", ",
+ "comment": "Text to insert when combining units of a measure - most languages will translate ‘[UnitSeparator]’ into ‘ ’ (space) to produce lists like ‘2 minuti 30 sekund’, or empty string ‘’ to produce ‘2分30秒’."
+ },
+ {
"id": "About WireGuard",
"message": "About WireGuard",
"translation": "Про WireGuard",
@@ -334,6 +616,62 @@
"translatorComment": "Copied from source."
},
{
+ "id": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "message": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "translation": "Версія додатку: {Number}\nВерсія Go бекенду: {WireGuardGoVersion}\nВерсія Go: {Version_go}-{GOARCH}\nОпераційна система: {OsName}\nАрхітектура {NativeArch}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Number",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "version.Number"
+ },
+ {
+ "id": "WireGuardGoVersion",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "device.WireGuardGoVersion"
+ },
+ {
+ "id": "Version_go",
+ "string": "%[3]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 3,
+ "expr": "strings.TrimPrefix(runtime.Version(), \"go\")"
+ },
+ {
+ "id": "GOARCH",
+ "string": "%[4]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 4,
+ "expr": "runtime.GOARCH"
+ },
+ {
+ "id": "OsName",
+ "string": "%[5]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 5,
+ "expr": "version.OsName()"
+ },
+ {
+ "id": "NativeArch",
+ "string": "%[6]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 6,
+ "expr": "version.NativeArch()"
+ }
+ ]
+ },
+ {
"id": "Close",
"message": "Close",
"translation": "Закрити",
@@ -368,6 +706,1202 @@
"message": "Public key:",
"translation": "Відкритий ключ:",
"translatorComment": "Copied from source."
+ },
+ {
+ "id": "Listen port:",
+ "message": "Listen port:",
+ "translation": "Порт:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "MTU:",
+ "message": "MTU:",
+ "translation": "MTU:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Addresses:",
+ "message": "Addresses:",
+ "translation": "Адреси:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "DNS servers:",
+ "message": "DNS servers:",
+ "translation": "DNS-сервери:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Scripts:",
+ "message": "Scripts:",
+ "translation": "Скрипти:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Preshared key:",
+ "message": "Preshared key:",
+ "translation": "Preshared ключ:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Allowed IPs:",
+ "message": "Allowed IPs:",
+ "translation": "Дозволені IP адреси:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Endpoint:",
+ "message": "Endpoint:",
+ "translation": "Endpoint:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Persistent keepalive:",
+ "message": "Persistent keepalive:",
+ "translation": "Persistent keepalive:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Latest handshake:",
+ "message": "Latest handshake:",
+ "translation": "Останнє рукостискання:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Transfer:",
+ "message": "Transfer:",
+ "translation": "Передано:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-up",
+ "message": "pre-up",
+ "translation": "перед-запуском",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-up",
+ "message": "post-up",
+ "translation": "після-запуску",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-down",
+ "message": "pre-down",
+ "translation": "перед-зупинкою",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-down",
+ "message": "post-down",
+ "translation": "після-зупинки",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "disabled, per policy",
+ "message": "disabled, per policy",
+ "translation": "вимкнено, відповідно до політики",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "enabled",
+ "message": "enabled",
+ "translation": "увімкнено",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{String} received, {String_1} sent",
+ "message": "{String} received, {String_1} sent",
+ "translation": "{String} отримано, {String_1} відправлено",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "String",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "c.RxBytes.String()"
+ },
+ {
+ "id": "String_1",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "c.TxBytes.String()"
+ }
+ ]
+ },
+ {
+ "id": "Failed to determine tunnel state",
+ "message": "Failed to determine tunnel state",
+ "translation": "Не вдалося визначити стан тунелю",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Failed to activate tunnel",
+ "message": "Failed to activate tunnel",
+ "translation": "Не вдалося активувати тунель",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Failed to deactivate tunnel",
+ "message": "Failed to deactivate tunnel",
+ "translation": "Не вдалося деактивувати тунель",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Interface: {Name}",
+ "message": "Interface: {Name}",
+ "translation": "Інтерфейс: {Name}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "config.Name"
+ }
+ ]
+ },
+ {
+ "id": "Peer",
+ "message": "Peer",
+ "translation": "Пір",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Create new tunnel",
+ "message": "Create new tunnel",
+ "translation": "Створити новий тунель",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Edit tunnel",
+ "message": "Edit tunnel",
+ "translation": "Редагувати тунель",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Name:",
+ "message": "&Name:",
+ "translation": "&Назва:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Public key:",
+ "message": "&Public key:",
+ "translation": "&Публічний ключ:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "(unknown)",
+ "message": "(unknown)",
+ "translation": "(невідомий)",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Block untunneled traffic (kill-switch)",
+ "message": "&Block untunneled traffic (kill-switch)",
+ "translation": "&Блокувати трафік поза тунелем",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "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 or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "message": "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 or is to the wrong DNS server, with special exceptions for DHCP and NDP.",
+ "translation": "У випадку якщо в конфігурації вказаний лише один пір, та його дозволені ІР-адреси містять 0.0.0.0/0 або ::/0, сервіс тунелю вводить у дію правила фаєрволу що блокують увесь трафік поза тунелем або до невідповідних DNS серверів, з виключеннями для DHCP та NDP.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Save",
+ "message": "&Save",
+ "translation": "&Зберегти",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Cancel",
+ "message": "Cancel",
+ "translation": "Скасувати",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Configuration:",
+ "message": "&Configuration:",
+ "translation": "&Налаштування:",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Invalid name",
+ "message": "Invalid name",
+ "translation": "Хибне ім'я",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "A name is required.",
+ "message": "A name is required.",
+ "translation": "Необхідно ввести ім'я.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel name ‘{NewName}’ is invalid.",
+ "message": "Tunnel name ‘{NewName}’ is invalid.",
+ "translation": "Ім'я тунелю '{NewName}' некоректне.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "NewName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "newName"
+ }
+ ]
+ },
+ {
+ "id": "Unable to list existing tunnels",
+ "message": "Unable to list existing tunnels",
+ "translation": "Не вдалося відобразити існуючі тунелі",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel already exists",
+ "message": "Tunnel already exists",
+ "translation": "Тунель вже існує",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Another tunnel already exists with the name ‘{NewName}’.",
+ "message": "Another tunnel already exists with the name ‘{NewName}’.",
+ "translation": "Тунель з ім'ям ‘{NewName}’ вже існує.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "NewName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "newName"
+ }
+ ]
+ },
+ {
+ "id": "Unable to create new configuration",
+ "message": "Unable to create new configuration",
+ "translation": "Неможливо створити нову конфігурацію",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Writing file failed",
+ "message": "Writing file failed",
+ "translation": "Помилка запису файлу",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "File ‘{FilePath}’ already exists.\n\nDo you want to overwrite it?",
+ "message": "File ‘{FilePath}’ already exists.\n\nDo you want to overwrite it?",
+ "translation": "Файл \"{FilePath}\" вже існує.\n\nВи хочете перезаписати його?",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "FilePath",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "filePath"
+ }
+ ]
+ },
+ {
+ "id": "Active",
+ "message": "Active",
+ "translation": "Активний",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Activating",
+ "message": "Activating",
+ "translation": "Активується",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Inactive",
+ "message": "Inactive",
+ "translation": "Неактивний",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Deactivating",
+ "message": "Deactivating",
+ "translation": "Вимикається",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unknown state",
+ "message": "Unknown state",
+ "translation": "Невідомий стан",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Log",
+ "message": "Log",
+ "translation": "Лог",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Copy",
+ "message": "&Copy",
+ "translation": "&Скопіювати",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Select &all",
+ "message": "Select &all",
+ "translation": "Обрати &все",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Save to file…",
+ "message": "&Save to file…",
+ "translation": "&Зберегти у файл…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Time",
+ "message": "Time",
+ "translation": "Час",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Log message",
+ "message": "Log message",
+ "translation": "Повідомлення з логу",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "message": "Text Files (*.txt)|*.txt|All Files (*.*)|*.*",
+ "translation": "Текстові файли (*.txt)|*.txt|Усі файли (*.*)|*.*",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export log to file",
+ "message": "Export log to file",
+ "translation": "Експортувати лог у файл",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&About WireGuard…",
+ "message": "&About WireGuard…",
+ "translation": "&Про WireGuard…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnel Error",
+ "message": "Tunnel Error",
+ "translation": "Помилка тунелю",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "message": "{ErrMsg}\n\nPlease consult the log for more information.",
+ "translation": "{ErrMsg}\n\nБудь ласка, зверніться до логу для отримання додаткової інформації.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "ErrMsg",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errMsg"
+ }
+ ]
+ },
+ {
+ "id": "{Title} (out of date)",
+ "message": "{Title} (out of date)",
+ "translation": "{Title} (застарілий)",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Title",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "mtw.Title()"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Detection Error",
+ "message": "WireGuard Detection Error",
+ "translation": "Помилка виявлення WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to wait for WireGuard window to appear: {Err}",
+ "message": "Unable to wait for WireGuard window to appear: {Err}",
+ "translation": "Не вдалося дочекатися появи вікна WireGuard: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard: Deactivated",
+ "message": "WireGuard: Deactivated",
+ "translation": "WireGuard: Вимкнений",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Unknown",
+ "message": "Status: Unknown",
+ "translation": "Статус: Невідомий",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Addresses: None",
+ "message": "Addresses: None",
+ "translation": "Адреси: немає",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Manage tunnels…",
+ "message": "&Manage tunnels…",
+ "translation": "&Керування тунелями…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Import tunnel(s) from file…",
+ "message": "&Import tunnel(s) from file…",
+ "translation": "&Імпортувати тунель з файлу…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "E&xit",
+ "message": "E&xit",
+ "translation": "Ви&йти",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Tunnels",
+ "message": "&Tunnels",
+ "translation": "&Тунелі",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Activated",
+ "message": "WireGuard Activated",
+ "translation": "WireGuard активовано",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "The {Name} tunnel has been activated.",
+ "message": "The {Name} tunnel has been activated.",
+ "translation": "Тунель {Name} активовано.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnel.Name"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Deactivated",
+ "message": "WireGuard Deactivated",
+ "translation": "WireGuard деактивовано",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "The {Name} tunnel has been deactivated.",
+ "message": "The {Name} tunnel has been deactivated.",
+ "translation": "Тунель {Name} було деактивовано.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnel.Name"
+ }
+ ]
+ },
+ {
+ "id": "WireGuard Tunnel Error",
+ "message": "WireGuard Tunnel Error",
+ "translation": "Помилка тунелю WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard: {TextForStateglobalState_true}",
+ "message": "WireGuard: {TextForStateglobalState_true}",
+ "translation": "WireGuard: {TextForStateglobalState_true}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TextForStateglobalState_true",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "textForState(globalState, true)"
+ }
+ ]
+ },
+ {
+ "id": "Status: {StateText}",
+ "message": "Status: {StateText}",
+ "translation": "Статус: {StateText}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "StateText",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "stateText"
+ }
+ ]
+ },
+ {
+ "id": "Addresses: {EnumerationSeparator}",
+ "message": "Addresses: {EnumerationSeparator}",
+ "translation": "Адреси: {EnumerationSeparator}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "EnumerationSeparator",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "strings.Join(addrs, l18n.EnumerationSeparator())"
+ }
+ ]
+ },
+ {
+ "id": "An Update is Available!",
+ "message": "An Update is Available!",
+ "translation": "Доступно оновлення!",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "WireGuard Update Available",
+ "message": "WireGuard Update Available",
+ "translation": "Доступне оновлення WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "An update to WireGuard is now available. You are advised to update as soon as possible.",
+ "message": "An update to WireGuard is now available. You are advised to update as soon as possible.",
+ "translation": "Оновлення до WireGuard доступне. Рекомендуємо оновити якомога швидше.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Tunnels",
+ "message": "Tunnels",
+ "translation": "Тунелі",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Edit",
+ "message": "&Edit",
+ "translation": "&Редагувати",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Add &empty tunnel…",
+ "message": "Add &empty tunnel…",
+ "translation": "Додати &пустий тунель…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Add Tunnel",
+ "message": "Add Tunnel",
+ "translation": "Додати тунель",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Remove selected tunnel(s)",
+ "message": "Remove selected tunnel(s)",
+ "translation": "Видалити обрані тунелі",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export all tunnels to zip",
+ "message": "Export all tunnels to zip",
+ "translation": "Експортувати всі тунелі в zip",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Toggle",
+ "message": "&Toggle",
+ "translation": "&Перемкнути",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export all tunnels to &zip…",
+ "message": "Export all tunnels to &zip…",
+ "translation": "Експортувати всі тунелі в &zip…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Edit &selected tunnel…",
+ "message": "Edit &selected tunnel…",
+ "translation": "Редагувати &вибраний тунель…",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Remove selected tunnel(s)",
+ "message": "&Remove selected tunnel(s)",
+ "translation": "&Видалити обрані тунелі",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "no configuration files were found",
+ "message": "no configuration files were found",
+ "translation": "не знайдено файлів конфігурації",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Could not import selected configuration: {LastErr}",
+ "message": "Could not import selected configuration: {LastErr}",
+ "translation": "Не вдалося імпортувати вибрану конфігурацію: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Could not enumerate existing tunnels: {LastErr}",
+ "message": "Could not enumerate existing tunnels: {LastErr}",
+ "translation": "Не вдалося перерахувати існуючі тунелі: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Another tunnel already exists with the name ‘{Name}’",
+ "message": "Another tunnel already exists with the name ‘{Name}’",
+ "translation": "Тунель з ім'ям ‘{Name}’ вже існує",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Name",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "unparsedConfig.Name"
+ }
+ ]
+ },
+ {
+ "id": "Unable to import configuration: {LastErr}",
+ "message": "Unable to import configuration: {LastErr}",
+ "translation": "Не вдалося імпортувати конфігурацію: {LastErr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "LastErr",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "lastErr"
+ }
+ ]
+ },
+ {
+ "id": "Imported tunnels",
+ "message": "Imported tunnels",
+ "translation": "Імпортовано тунелі",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Imported {M} tunnels",
+ "message": "Imported {M} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "M",
+ "cases": {
+ "one": {
+ "msg": "Імпортовано {M} тунель"
+ },
+ "few": {
+ "msg": "Імпортовано {M} тунелі"
+ },
+ "many": {
+ "msg": "Імпортовано {M} тунелів"
+ },
+ "other": {
+ "msg": "Імпортовано {M} тунелів"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ }
+ ]
+ },
+ {
+ "id": "Imported {M} of {N} tunnels",
+ "message": "Imported {M} of {N} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "N",
+ "cases": {
+ "one": {
+ "msg": "Імпортовано {M} з {N} тунелів"
+ },
+ "few": {
+ "msg": "Імпортовано {M} з {N} тунелів"
+ },
+ "many": {
+ "msg": "Імпортовано {M} з {N} тунелів"
+ },
+ "other": {
+ "msg": "Імпортовано {M} з {N} тунелів"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "M",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "m"
+ },
+ {
+ "id": "N",
+ "string": "%[2]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 2,
+ "expr": "n"
+ }
+ ]
+ },
+ {
+ "id": "Unable to create tunnel",
+ "message": "Unable to create tunnel",
+ "translation": "Не вдалося створити тунель",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Delete {TunnelCount} tunnels",
+ "message": "Delete {TunnelCount} tunnels",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "TunnelCount",
+ "cases": {
+ "one": {
+ "msg": "Видалити {TunnelCount} тунель"
+ },
+ "few": {
+ "msg": "Видалити {TunnelCount} тунелі"
+ },
+ "many": {
+ "msg": "Видалити {TunnelCount} тунелів"
+ },
+ "other": {
+ "msg": "Видалити {TunnelCount} тунелів"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "TunnelCount",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "tunnelCount"
+ }
+ ]
+ },
+ {
+ "id": "Are you sure you would like to delete {TunnelCount} tunnels?",
+ "message": "Are you sure you would like to delete {TunnelCount} tunnels?",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "TunnelCount",
+ "cases": {
+ "one": {
+ "msg": "Ви впевнені, що хочете видалити {TunnelCount} тунель?"
+ },
+ "few": {
+ "msg": "Ви впевнені, що хочете видалити {TunnelCount} тунелі?"
+ },
+ "many": {
+ "msg": "Ви впевнені, що хочете видалити {TunnelCount} тунелів?"
+ },
+ "other": {
+ "msg": "Ви впевнені, що хочете видалити {TunnelCount} тунелі?"
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "TunnelCount",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "tunnelCount"
+ }
+ ]
+ },
+ {
+ "id": "Delete tunnel ‘{TunnelName}’",
+ "message": "Delete tunnel ‘{TunnelName}’",
+ "translation": "Видалити тунель '{TunnelName}'",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TunnelName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnelName"
+ }
+ ]
+ },
+ {
+ "id": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
+ "message": "Are you sure you would like to delete tunnel ‘{TunnelName}’?",
+ "translation": "Ви впевнені, що бажаєте видалити тунель '{TunnelName}'?",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "TunnelName",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "tunnelName"
+ }
+ ]
+ },
+ {
+ "id": "{Question} You cannot undo this action.",
+ "message": "{Question} You cannot undo this action.",
+ "translation": "{Question} Цю дію не можна буде скасувати.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Question",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "question"
+ }
+ ]
+ },
+ {
+ "id": "Unable to delete tunnel",
+ "message": "Unable to delete tunnel",
+ "translation": "Неможливо видалити тунель",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "A tunnel was unable to be removed: {Error}",
+ "message": "A tunnel was unable to be removed: {Error}",
+ "translation": "Тунель не вдалося видалити: {Error}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Error",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "errors[0].Error()"
+ }
+ ]
+ },
+ {
+ "id": "Unable to delete tunnels",
+ "message": "Unable to delete tunnels",
+ "translation": "Неможливо видалити тунелі",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Lenerrors} tunnels were unable to be removed.",
+ "message": "{Lenerrors} tunnels were unable to be removed.",
+ "translation": {
+ "select": {
+ "feature": "plural",
+ "arg": "Lenerrors",
+ "cases": {
+ "one": {
+ "msg": "{Lenerrors} тунель не вдалося видалити."
+ },
+ "few": {
+ "msg": "{Lenerrors} тунелі не вдалося видалити."
+ },
+ "many": {
+ "msg": "{Lenerrors} тунелів не вдалося видалити."
+ },
+ "other": {
+ "msg": "{Lenerrors} тунелів не вдалося видалити."
+ }
+ }
+ }
+ },
+ "placeholders": [
+ {
+ "id": "Lenerrors",
+ "string": "%[1]d",
+ "type": "int",
+ "underlyingType": "int",
+ "argNum": 1,
+ "expr": "len(errors)"
+ }
+ ]
+ },
+ {
+ "id": "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
+ "message": "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*",
+ "translation": "Файли конфігурації (*.zip, *.conf)|*.zip;*.conf|Всі файли (*.*)|*.*",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Import tunnel(s) from file",
+ "message": "Import tunnel(s) from file",
+ "translation": "Імпортувати тунелі з файлу",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Configuration ZIP Files (*.zip)|*.zip",
+ "message": "Configuration ZIP Files (*.zip)|*.zip",
+ "translation": "ZIP-файли конфігурації (*.zip) | *.zip",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Export tunnels to zip",
+ "message": "Export tunnels to zip",
+ "translation": "Експортувати тунелі в zip",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "{Title} (unsigned build, no updates)",
+ "message": "{Title} (unsigned build, no updates)",
+ "translation": "{Title} (непідписані збірки, немає оновлень)",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Title",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "mtw.Title()"
+ }
+ ]
+ },
+ {
+ "id": "Error Exiting WireGuard",
+ "message": "Error Exiting WireGuard",
+ "translation": "Помилка при виході з WireGuard",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
+ "message": "Unable to exit service due to: {Err}. You may want to stop WireGuard from the service manager.",
+ "translation": "Не вдалося зупинити службу через: {Err}. Ви можете зупинити її вручну через менеджер сервісів.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "message": "An update to WireGuard is available. It is highly advisable to update without delay.",
+ "translation": "Доступне оновлення WireGuard, доцільне оновлення без затримок.",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Waiting for user",
+ "message": "Status: Waiting for user",
+ "translation": "Статус: Очікування користувача",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Update Now",
+ "message": "Update Now",
+ "translation": "Оновити зараз",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Status: Waiting for updater service",
+ "message": "Status: Waiting for updater service",
+ "translation": "Статус: Очікування на службу оновлення",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error: {Err}. Please try again.",
+ "message": "Error: {Err}. Please try again.",
+ "translation": "Помилка: {Err}. Будь ласка, спробуйте ще раз.",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
+ "id": "Status: Complete!",
+ "message": "Status: Complete!",
+ "translation": "Стан: Завершено",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "http2: Framer {F}: failed to decode just-written frame",
+ "message": "http2: Framer {F}: failed to decode just-written frame",
+ "translation": "http2: Framer {F}: failed to decode just-written frame",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "F",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "f"
+ }
+ ]
+ },
+ {
+ "id": "http2: Framer {F}: wrote {Http2summarizeFramefr}",
+ "message": "http2: Framer {F}: wrote {Http2summarizeFramefr}",
+ "translation": "http2: Framer {F}: wrote {Http2summarizeFramefr}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "F",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "f"
+ },
+ {
+ "id": "Http2summarizeFramefr",
+ "string": "%[2]v",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "http2summarizeFrame(fr)"
+ }
+ ]
+ },
+ {
+ "id": "http2: Framer {Fr}: read {Http2summarizeFramef}",
+ "message": "http2: Framer {Fr}: read {Http2summarizeFramef}",
+ "translation": "http2: Framer {Fr}: read {Http2summarizeFramef}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Fr",
+ "string": "%[1]p",
+ "type": "*net/http.http2Framer",
+ "underlyingType": "*net/http.http2Framer",
+ "argNum": 1,
+ "expr": "fr"
+ },
+ {
+ "id": "Http2summarizeFramef",
+ "string": "%[2]v",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "http2summarizeFrame(f)"
+ }
+ ]
+ },
+ {
+ "id": "http2: decoded hpack field {HeaderField}",
+ "message": "http2: decoded hpack field {HeaderField}",
+ "translation": "http2: decoded hpack field {HeaderField}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "HeaderField",
+ "string": "%+[1]v",
+ "type": "vendor/golang.org/x/net/http2/hpack.HeaderField",
+ "underlyingType": "struct{Name string; Value string; Sensitive bool}",
+ "argNum": 1,
+ "expr": "hf"
+ }
+ ]
}
]
} \ No newline at end of file
diff --git a/locales/vi/messages.gotext.json b/locales/vi/messages.gotext.json
index 94d44344..7e8f92ae 100644
--- a/locales/vi/messages.gotext.json
+++ b/locales/vi/messages.gotext.json
@@ -8,6 +8,36 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Usage: {Args0} [\n{String}]",
+ "message": "Usage: {Args0} [\n{String}]",
+ "translation": "Sử dụng: {Args0} [\n{String}]",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Args0",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "os.Args[0]"
+ },
+ {
+ "id": "String",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "builder.String()"
+ }
+ ]
+ },
+ {
+ "id": "Command Line Options",
+ "message": "Command Line Options",
+ "translation": "Tùy chọn dòng lệnh",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Now",
"message": "Now",
"translation": "Vừa xong",
@@ -155,24 +185,150 @@
]
},
{
+ "id": "{Bytes} B",
+ "message": "{Bytes} B",
+ "translation": "{Bytes} B",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Bytes",
+ "string": "%[1]d",
+ "type": "golang.zx2c4.com/wireguard/windows/conf.Bytes",
+ "underlyingType": "uint64",
+ "argNum": 1,
+ "expr": "b"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024} KiB",
+ "message": "{Float64b__1024} KiB",
+ "translation": "{Float64b__1024} KiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / 1024"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024} MiB",
+ "message": "{Float64b__1024__1024} MiB",
+ "translation": "{Float64b__1024__1024} MiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024} GiB",
+ "message": "{Float64b__1024__1024__1024} GiB",
+ "translation": "{Float64b__1024__1024__1024} GiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024)"
+ }
+ ]
+ },
+ {
+ "id": "{Float64b__1024__1024__1024__1024} TiB",
+ "message": "{Float64b__1024__1024__1024__1024} TiB",
+ "translation": "{Float64b__1024__1024__1024__1024} TiB",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Float64b__1024__1024__1024__1024",
+ "string": "%.2[1]f",
+ "type": "float64",
+ "underlyingType": "float64",
+ "argNum": 1,
+ "expr": "float64(b) / (1024 * 1024 * 1024) / 1024"
+ }
+ ]
+ },
+ {
"id": "Invalid IP address",
"message": "Invalid IP address",
"translation": "Địa chỉ IP không hợp lệ",
"translatorComment": "Copied from source."
},
{
+ "id": "Invalid MTU",
+ "message": "Invalid MTU",
+ "translation": "Khoá không hợp lệ",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Invalid port",
"message": "Invalid port",
"translation": "Cổng (port) không hợp lệ",
"translatorComment": "Copied from source."
},
{
+ "id": "Invalid key: {Err}",
+ "message": "Invalid key: {Err}",
+ "translation": "Khoá không hợp lệ: {Err}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Err",
+ "string": "%[1]v",
+ "type": "error",
+ "underlyingType": "interface{Error() string}",
+ "argNum": 1,
+ "expr": "err"
+ }
+ ]
+ },
+ {
"id": "Tunnel name is not valid",
"message": "Tunnel name is not valid",
"translation": "Tên VPN không hợp lệ",
"translatorComment": "Copied from source."
},
{
+ "id": "[none specified]",
+ "message": "[none specified]",
+ "translation": "Ko có Chỉ định",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "Error in getting configuration",
+ "message": "Error in getting configuration",
+ "translation": "Lỗi khi lưu cấu hình",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "[EnumerationSeparator]",
+ "message": "[EnumerationSeparator]",
+ "translation": ",",
+ "comment": "Text to insert between items when listing - most western languages will translate ‘[EnumerationSeparator]’ into ‘, ’ to produce lists like ‘apple, orange, strawberry’. Eastern languages might translate into ‘、’ to produce lists like ‘リンゴ、オレンジ、イチゴ’."
+ },
+ {
+ "id": "[UnitSeparator]",
+ "message": "[UnitSeparator]",
+ "translation": ",",
+ "comment": "Text to insert when combining units of a measure - most languages will translate ‘[UnitSeparator]’ into ‘ ’ (space) to produce lists like ‘2 minuti 30 sekund’, or empty string ‘’ to produce ‘2分30秒’."
+ },
+ {
"id": "About WireGuard",
"message": "About WireGuard",
"translation": "Thông tin về WireGuard",
@@ -197,6 +353,18 @@
"translatorComment": "Copied from source."
},
{
+ "id": "&Deactivate",
+ "message": "&Deactivate",
+ "translation": "Đã hủy kích hoạt",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "&Activate",
+ "message": "&Activate",
+ "translation": "Kích hoạt",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Endpoint:",
"message": "Endpoint:",
"translation": "Đầu cuối:",
diff --git a/locales/zh-CN/messages.gotext.json b/locales/zh-CN/messages.gotext.json
index 140a073c..ea56a3f1 100644
--- a/locales/zh-CN/messages.gotext.json
+++ b/locales/zh-CN/messages.gotext.json
@@ -465,7 +465,7 @@
{
"id": "Two commas in a row",
"message": "Two commas in a row",
- "translation": "一行中有两个逗号",
+ "translation": "存在多余的逗号",
"translatorComment": "Copied from source."
},
{
@@ -495,13 +495,13 @@
{
"id": "Invalid key for [Interface] section",
"message": "Invalid key for [Interface] section",
- "translation": "[Interface] 段落的键无效",
+ "translation": "[Interface] 段落中的该键无效",
"translatorComment": "Copied from source."
},
{
"id": "Invalid key for [Peer] section",
"message": "Invalid key for [Peer] section",
- "translation": "[Peer] 段落的键无效",
+ "translation": "[Peer] 段落中的该键无效",
"translatorComment": "Copied from source."
},
{
@@ -519,7 +519,7 @@
{
"id": "All peers must have public keys",
"message": "All peers must have public keys",
- "translation": "所有节点必须拥有公钥。",
+ "translation": "每个节点都必须指定公钥",
"translatorComment": "Copied from source."
},
{
diff --git a/locales/zh-TW/messages.gotext.json b/locales/zh-TW/messages.gotext.json
index f6283b2e..d9249856 100644
--- a/locales/zh-TW/messages.gotext.json
+++ b/locales/zh-TW/messages.gotext.json
@@ -60,6 +60,12 @@
]
},
{
+ "id": "You must use the native version of WireGuard on this computer.",
+ "message": "You must use the native version of WireGuard on this computer.",
+ "translation": "您必須在此電腦上執行原生版本的 WireGuard。",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Unable to open current process token: {Err}",
"message": "Unable to open current process token: {Err}",
"translation": "無法開啓目前處理程序的權杖: {Err}",
@@ -565,6 +571,62 @@
"translatorComment": "Copied from source."
},
{
+ "id": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "message": "App version: {Number}\nGo backend version: {WireGuardGoVersion}\nGo version: {Version_go}-{GOARCH}\nOperating system: {OsName}\nArchitecture: {NativeArch}",
+ "translation": "應用程式版本: {Number}\n後端程式(Go 實作)版本: {WireGuardGoVersion}\nGo 版本: {Version_go}-{GOARCH}\n作業系統: {OsName}\n架構: {NativeArch}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "Number",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "version.Number"
+ },
+ {
+ "id": "WireGuardGoVersion",
+ "string": "%[2]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 2,
+ "expr": "device.WireGuardGoVersion"
+ },
+ {
+ "id": "Version_go",
+ "string": "%[3]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 3,
+ "expr": "strings.TrimPrefix(runtime.Version(), \"go\")"
+ },
+ {
+ "id": "GOARCH",
+ "string": "%[4]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 4,
+ "expr": "runtime.GOARCH"
+ },
+ {
+ "id": "OsName",
+ "string": "%[5]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 5,
+ "expr": "version.OsName()"
+ },
+ {
+ "id": "NativeArch",
+ "string": "%[6]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 6,
+ "expr": "version.NativeArch()"
+ }
+ ]
+ },
+ {
"id": "Close",
"message": "Close",
"translation": "關閉",
@@ -625,6 +687,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "Scripts:",
+ "message": "Scripts:",
+ "translation": "指令碼:",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Preshared key:",
"message": "Preshared key:",
"translation": "預交換金鑰",
@@ -661,6 +729,36 @@
"translatorComment": "Copied from source."
},
{
+ "id": "pre-up",
+ "message": "pre-up",
+ "translation": "連接前",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-up",
+ "message": "post-up",
+ "translation": "連接後",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "pre-down",
+ "message": "pre-down",
+ "translation": "斷線前",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "post-down",
+ "message": "post-down",
+ "translation": "斷線後",
+ "translatorComment": "Copied from source."
+ },
+ {
+ "id": "disabled, per policy",
+ "message": "disabled, per policy",
+ "translation": "已關閉, 隨著策略",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "enabled",
"message": "enabled",
"translation": "已啓用",
@@ -1049,6 +1147,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "&Tunnels",
+ "message": "&Tunnels",
+ "translation": "隧道(&T)",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "WireGuard Activated",
"message": "WireGuard Activated",
"translation": "WireGuard 已連線",
@@ -1131,6 +1235,22 @@
]
},
{
+ "id": "Addresses: {EnumerationSeparator}",
+ "message": "Addresses: {EnumerationSeparator}",
+ "translation": "位址: {EnumerationSeparator}",
+ "translatorComment": "Copied from source.",
+ "placeholders": [
+ {
+ "id": "EnumerationSeparator",
+ "string": "%[1]s",
+ "type": "string",
+ "underlyingType": "string",
+ "argNum": 1,
+ "expr": "strings.Join(addrs, l18n.EnumerationSeparator())"
+ }
+ ]
+ },
+ {
"id": "An Update is Available!",
"message": "An Update is Available!",
"translation": "更新",
@@ -1209,6 +1329,12 @@
"translatorComment": "Copied from source."
},
{
+ "id": "no configuration files were found",
+ "message": "no configuration files were found",
+ "translation": "找不到設定檔",
+ "translatorComment": "Copied from source."
+ },
+ {
"id": "Could not import selected configuration: {LastErr}",
"message": "Could not import selected configuration: {LastErr}",
"translation": "無法匯入設定: {LastErr}",
diff --git a/main.go b/main.go
index 5862d4e3..62a0b559 100644
--- a/main.go
+++ b/main.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package main
@@ -9,6 +9,7 @@ import (
"debug/pe"
"errors"
"fmt"
+ "io"
"log"
"os"
"strconv"
@@ -16,8 +17,9 @@ import (
"time"
"golang.org/x/sys/windows"
- "golang.zx2c4.com/wireguard/tun"
+ "golang.zx2c4.com/wireguard/windows/conf"
+ "golang.zx2c4.com/wireguard/windows/driver"
"golang.zx2c4.com/wireguard/windows/elevate"
"golang.zx2c4.com/wireguard/windows/l18n"
"golang.zx2c4.com/wireguard/windows/manager"
@@ -27,21 +29,41 @@ import (
"golang.zx2c4.com/wireguard/windows/updater"
)
-func fatal(v ...interface{}) {
- windows.MessageBox(0, windows.StringToUTF16Ptr(fmt.Sprint(v...)), windows.StringToUTF16Ptr(l18n.Sprintf("Error")), windows.MB_ICONERROR)
- os.Exit(1)
+func setLogFile() {
+ logHandle, err := windows.GetStdHandle(windows.STD_ERROR_HANDLE)
+ if logHandle == 0 || err != nil {
+ logHandle, err = windows.GetStdHandle(windows.STD_OUTPUT_HANDLE)
+ }
+ if logHandle == 0 || err != nil {
+ log.SetOutput(io.Discard)
+ } else {
+ log.SetOutput(os.NewFile(uintptr(logHandle), "stderr"))
+ }
}
-func fatalf(format string, v ...interface{}) {
+func fatal(v ...any) {
+ if log.Writer() == io.Discard {
+ windows.MessageBox(0, windows.StringToUTF16Ptr(fmt.Sprint(v...)), windows.StringToUTF16Ptr(l18n.Sprintf("Error")), windows.MB_ICONERROR)
+ os.Exit(1)
+ } else {
+ log.Fatal(append([]any{l18n.Sprintf("Error: ")}, v...))
+ }
+}
+
+func fatalf(format string, v ...any) {
fatal(l18n.Sprintf(format, v...))
}
-func info(title string, format string, v ...interface{}) {
- windows.MessageBox(0, windows.StringToUTF16Ptr(l18n.Sprintf(format, v...)), windows.StringToUTF16Ptr(title), windows.MB_ICONINFORMATION)
+func info(title, format string, v ...any) {
+ if log.Writer() == io.Discard {
+ windows.MessageBox(0, windows.StringToUTF16Ptr(l18n.Sprintf(format, v...)), windows.StringToUTF16Ptr(title), windows.MB_ICONINFORMATION)
+ } else {
+ log.Printf(title+":\n"+format, v...)
+ }
}
func usage() {
- var flags = [...]string{
+ flags := [...]string{
l18n.Sprintf("(no argument): elevate and install manager service"),
"/installmanagerservice",
"/installtunnelservice CONFIG_PATH",
@@ -50,9 +72,9 @@ func usage() {
"/managerservice",
"/tunnelservice CONFIG_PATH",
"/ui CMD_READ_HANDLE CMD_WRITE_HANDLE CMD_EVENT_HANDLE LOG_MAPPING_HANDLE",
- "/dumplog OUTPUT_PATH",
- "/update [LOG_FILE]",
- "/removealladapters [LOG_FILE]",
+ "/dumplog [/tail]",
+ "/update",
+ "/removedriver",
}
builder := strings.Builder{}
for _, flag := range flags {
@@ -133,6 +155,7 @@ func main() {
panic("failed to restrict dll search path")
}
+ setLogFile()
checkForWow64()
if len(os.Args) <= 1 {
@@ -246,35 +269,31 @@ func main() {
ui.RunUI()
return
case "/dumplog":
- if len(os.Args) != 3 {
+ if len(os.Args) != 2 && len(os.Args) != 3 {
usage()
}
- file, err := os.Create(os.Args[2])
+ outputHandle, err := windows.GetStdHandle(windows.STD_OUTPUT_HANDLE)
if err != nil {
fatal(err)
}
+ if outputHandle == 0 {
+ fatal("Stdout must be set")
+ }
+ file := os.NewFile(uintptr(outputHandle), "stdout")
defer file.Close()
- err = ringlogger.DumpTo(file, true)
+ logPath, err := conf.LogFile(false)
+ if err != nil {
+ fatal(err)
+ }
+ err = ringlogger.DumpTo(logPath, file, len(os.Args) == 3 && os.Args[2] == "/tail")
if err != nil {
fatal(err)
}
return
case "/update":
- if len(os.Args) != 2 && len(os.Args) != 3 {
+ if len(os.Args) != 2 {
usage()
}
- var f *os.File
- var err error
- if len(os.Args) == 2 {
- f = os.Stdout
- } else {
- f, err = os.Create(os.Args[2])
- if err != nil {
- fatal(err)
- }
- defer f.Close()
- }
- l := log.New(f, "", log.LstdFlags)
for progress := range updater.DownloadVerifyAndExecute(0) {
if len(progress.Activity) > 0 {
if progress.BytesTotal > 0 || progress.BytesDownloaded > 0 {
@@ -282,40 +301,27 @@ func main() {
if progress.BytesTotal > 0 {
percent = float64(progress.BytesDownloaded) / float64(progress.BytesTotal) * 100.0
}
- l.Printf("%s: %d/%d (%.2f%%)\n", progress.Activity, progress.BytesDownloaded, progress.BytesTotal, percent)
+ log.Printf("%s: %d/%d (%.2f%%)\n", progress.Activity, progress.BytesDownloaded, progress.BytesTotal, percent)
} else {
- l.Println(progress.Activity)
+ log.Println(progress.Activity)
}
}
if progress.Error != nil {
- l.Printf("Error: %v\n", progress.Error)
+ log.Printf("Error: %v\n", progress.Error)
}
if progress.Complete || progress.Error != nil {
return
}
}
return
- case "/removealladapters":
- if len(os.Args) != 2 && len(os.Args) != 3 {
+ case "/removedriver":
+ if len(os.Args) != 2 {
usage()
}
- var f *os.File
- var err error
- if len(os.Args) == 2 {
- f = os.Stdout
- } else {
- f, err = os.Create(os.Args[2])
- if err != nil {
- fatal(err)
- }
- defer f.Close()
- }
- log.SetOutput(f)
- rebootRequired, err := tun.WintunPool.DeleteDriver()
+ _ = driver.UninstallLegacyWintun() // Best effort
+ err := driver.Uninstall()
if err != nil {
- log.Printf("Error: %v\n", err)
- } else if rebootRequired {
- log.Println("A reboot may be required")
+ fatal(err)
}
return
}
diff --git a/manager/install.go b/manager/install.go
index bd7d23c7..44a744cf 100644
--- a/manager/install.go
+++ b/manager/install.go
@@ -1,13 +1,15 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package manager
import (
"errors"
+ "log"
"os"
+ "strings"
"time"
"golang.org/x/sys/windows"
@@ -15,7 +17,6 @@ import (
"golang.org/x/sys/windows/svc/mgr"
"golang.zx2c4.com/wireguard/windows/conf"
- "golang.zx2c4.com/wireguard/windows/services"
)
var cachedServiceManager *mgr.Mgr
@@ -128,7 +129,7 @@ func InstallTunnel(configPath string) error {
return err
}
- serviceName, err := services.ServiceNameOfTunnel(name)
+ serviceName, err := conf.ServiceNameOfTunnel(name)
if err != nil {
return err
}
@@ -181,7 +182,7 @@ func UninstallTunnel(name string) error {
if err != nil {
return err
}
- serviceName, err := services.ServiceNameOfTunnel(name)
+ serviceName, err := conf.ServiceNameOfTunnel(name)
if err != nil {
return err
}
@@ -197,3 +198,45 @@ func UninstallTunnel(name string) error {
}
return err2
}
+
+func changeTunnelServiceConfigFilePath(name, oldPath, newPath string) {
+ var err error
+ defer func() {
+ if err != nil {
+ log.Printf("Unable to change tunnel service command line argument from %#q to %#q: %v", oldPath, newPath, err)
+ }
+ }()
+ m, err := serviceManager()
+ if err != nil {
+ return
+ }
+ serviceName, err := conf.ServiceNameOfTunnel(name)
+ if err != nil {
+ return
+ }
+ service, err := m.OpenService(serviceName)
+ if err == windows.ERROR_SERVICE_DOES_NOT_EXIST {
+ err = nil
+ return
+ } else if err != nil {
+ return
+ }
+ defer service.Close()
+ config, err := service.Config()
+ if err != nil {
+ return
+ }
+ exePath, err := os.Executable()
+ if err != nil {
+ return
+ }
+ args, err := windows.DecomposeCommandLine(config.BinaryPathName)
+ if err != nil || len(args) != 3 ||
+ !strings.EqualFold(args[0], exePath) || args[1] != "/tunnelservice" || !strings.EqualFold(args[2], oldPath) {
+ err = nil
+ return
+ }
+ args[2] = newPath
+ config.BinaryPathName = windows.ComposeCommandLine(args)
+ err = service.UpdateConfig(config)
+}
diff --git a/manager/interfacecleanup.go b/manager/interfacecleanup.go
deleted file mode 100644
index c270f4ab..00000000
--- a/manager/interfacecleanup.go
+++ /dev/null
@@ -1,56 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
- */
-
-package manager
-
-import (
- "log"
-
- "golang.org/x/sys/windows"
- "golang.org/x/sys/windows/svc"
- "golang.org/x/sys/windows/svc/mgr"
- "golang.zx2c4.com/wireguard/tun/wintun"
-
- "golang.zx2c4.com/wireguard/tun"
- "golang.zx2c4.com/wireguard/windows/services"
-)
-
-func cleanupStaleWintunInterfaces() {
- m, err := mgr.Connect()
- if err != nil {
- return
- }
- defer m.Disconnect()
-
- tun.WintunPool.DeleteMatchingAdapters(func(wintun *wintun.Adapter) bool {
- interfaceName, err := wintun.Name()
- if err != nil {
- log.Printf("Removing Wintun interface because determining interface name failed: %v", err)
- return true
- }
- serviceName, err := services.ServiceNameOfTunnel(interfaceName)
- if err != nil {
- log.Printf("Removing Wintun interface ‘%s’ because determining tunnel service name failed: %v", interfaceName, err)
- return true
- }
- service, err := m.OpenService(serviceName)
- if err == windows.ERROR_SERVICE_DOES_NOT_EXIST {
- log.Printf("Removing Wintun interface ‘%s’ because no service for it exists", interfaceName)
- return true
- } else if err != nil {
- return false
- }
- defer service.Close()
- status, err := service.Query()
- if err != nil {
- return false
- }
- if status.State == svc.Stopped {
- log.Printf("Removing Wintun interface ‘%s’ because its service is stopped", interfaceName)
- return true
- }
- return false
- }, false)
-}
diff --git a/manager/ipc_client.go b/manager/ipc_client.go
index 2f78a47e..8c9c4c04 100644
--- a/manager/ipc_client.go
+++ b/manager/ipc_client.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package manager
@@ -64,7 +64,7 @@ var (
)
type TunnelChangeCallback struct {
- cb func(tunnel *Tunnel, state TunnelState, globalState TunnelState, err error)
+ cb func(tunnel *Tunnel, state, globalState TunnelState, err error)
}
var tunnelChangeCallbacks = make(map[*TunnelChangeCallback]bool)
@@ -93,7 +93,7 @@ type UpdateProgressCallback struct {
var updateProgressCallbacks = make(map[*UpdateProgressCallback]bool)
-func InitializeIPCClient(reader *os.File, writer *os.File, events *os.File) {
+func InitializeIPCClient(reader, writer, events *os.File) {
rpcDecoder = gob.NewDecoder(reader)
rpcEncoder = gob.NewEncoder(writer)
go func() {
@@ -431,43 +431,52 @@ func IPCClientUpdate() error {
return rpcEncoder.Encode(UpdateMethodType)
}
-func IPCClientRegisterTunnelChange(cb func(tunnel *Tunnel, state TunnelState, globalState TunnelState, err error)) *TunnelChangeCallback {
+func IPCClientRegisterTunnelChange(cb func(tunnel *Tunnel, state, globalState TunnelState, err error)) *TunnelChangeCallback {
s := &TunnelChangeCallback{cb}
tunnelChangeCallbacks[s] = true
return s
}
+
func (cb *TunnelChangeCallback) Unregister() {
delete(tunnelChangeCallbacks, cb)
}
+
func IPCClientRegisterTunnelsChange(cb func()) *TunnelsChangeCallback {
s := &TunnelsChangeCallback{cb}
tunnelsChangeCallbacks[s] = true
return s
}
+
func (cb *TunnelsChangeCallback) Unregister() {
delete(tunnelsChangeCallbacks, cb)
}
+
func IPCClientRegisterManagerStopping(cb func()) *ManagerStoppingCallback {
s := &ManagerStoppingCallback{cb}
managerStoppingCallbacks[s] = true
return s
}
+
func (cb *ManagerStoppingCallback) Unregister() {
delete(managerStoppingCallbacks, cb)
}
+
func IPCClientRegisterUpdateFound(cb func(updateState UpdateState)) *UpdateFoundCallback {
s := &UpdateFoundCallback{cb}
updateFoundCallbacks[s] = true
return s
}
+
func (cb *UpdateFoundCallback) Unregister() {
delete(updateFoundCallbacks, cb)
}
+
func IPCClientRegisterUpdateProgress(cb func(dp updater.DownloadProgress)) *UpdateProgressCallback {
s := &UpdateProgressCallback{cb}
updateProgressCallbacks[s] = true
return s
}
+
func (cb *UpdateProgressCallback) Unregister() {
delete(updateProgressCallbacks, cb)
}
diff --git a/manager/ipc_driver.go b/manager/ipc_driver.go
new file mode 100644
index 00000000..6cb43c38
--- /dev/null
+++ b/manager/ipc_driver.go
@@ -0,0 +1,61 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package manager
+
+import (
+ "sync"
+
+ "golang.zx2c4.com/wireguard/windows/driver"
+)
+
+type lockedDriverAdapter struct {
+ *driver.Adapter
+ sync.Mutex
+}
+
+var (
+ driverAdapters = make(map[string]*lockedDriverAdapter)
+ driverAdaptersLock sync.RWMutex
+)
+
+func findDriverAdapter(tunnelName string) (*lockedDriverAdapter, error) {
+ driverAdaptersLock.RLock()
+ driverAdapter, ok := driverAdapters[tunnelName]
+ if ok {
+ driverAdapter.Lock()
+ driverAdaptersLock.RUnlock()
+ return driverAdapter, nil
+ }
+ driverAdaptersLock.RUnlock()
+ driverAdaptersLock.Lock()
+ defer driverAdaptersLock.Unlock()
+ driverAdapter, ok = driverAdapters[tunnelName]
+ if ok {
+ driverAdapter.Lock()
+ return driverAdapter, nil
+ }
+ driverAdapter = &lockedDriverAdapter{}
+ var err error
+ driverAdapter.Adapter, err = driver.OpenAdapter(tunnelName)
+ if err != nil {
+ return nil, err
+ }
+ driverAdapters[tunnelName] = driverAdapter
+ driverAdapter.Lock()
+ return driverAdapter, nil
+}
+
+func releaseDriverAdapter(tunnelName string) {
+ driverAdaptersLock.Lock()
+ defer driverAdaptersLock.Unlock()
+ driverAdapter, ok := driverAdapters[tunnelName]
+ if !ok {
+ return
+ }
+ driverAdapter.Lock()
+ delete(driverAdapters, tunnelName)
+ driverAdapter.Unlock()
+}
diff --git a/manager/ipc_server.go b/manager/ipc_server.go
index 8ba050f9..e21ffaf0 100644
--- a/manager/ipc_server.go
+++ b/manager/ipc_server.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package manager
@@ -20,14 +20,15 @@ import (
"golang.org/x/sys/windows/svc"
"golang.zx2c4.com/wireguard/windows/conf"
- "golang.zx2c4.com/wireguard/windows/services"
"golang.zx2c4.com/wireguard/windows/updater"
)
-var managerServices = make(map[*ManagerService]bool)
-var managerServicesLock sync.RWMutex
-var haveQuit uint32
-var quitManagersChan = make(chan struct{}, 1)
+var (
+ managerServices = make(map[*ManagerService]bool)
+ managerServicesLock sync.RWMutex
+ haveQuit uint32
+ quitManagersChan = make(chan struct{}, 1)
+)
type ManagerService struct {
events *os.File
@@ -51,33 +52,18 @@ func (s *ManagerService) RuntimeConfig(tunnelName string) (*conf.Config, error)
if err != nil {
return nil, err
}
- pipe, err := connectTunnelServicePipe(tunnelName)
- if err != nil {
- return nil, err
- }
- pipe.SetDeadline(time.Now().Add(time.Second * 2))
- _, err = pipe.Write([]byte("get=1\n\n"))
- if err == windows.ERROR_NO_DATA {
- log.Println("IPC pipe closed unexpectedly, so reopening")
- pipe.Unlock()
- disconnectTunnelServicePipe(tunnelName)
- pipe, err = connectTunnelServicePipe(tunnelName)
- if err != nil {
- return nil, err
- }
- pipe.SetDeadline(time.Now().Add(time.Second * 2))
- _, err = pipe.Write([]byte("get=1\n\n"))
- }
+ driverAdapter, err := findDriverAdapter(tunnelName)
if err != nil {
- pipe.Unlock()
- disconnectTunnelServicePipe(tunnelName)
return nil, err
}
- conf, err := conf.FromUAPI(pipe, storedConfig)
- pipe.Unlock()
+ runtimeConfig, err := driverAdapter.Configuration()
if err != nil {
+ driverAdapter.Unlock()
+ releaseDriverAdapter(tunnelName)
return nil, err
}
+ conf := conf.FromDriverConfiguration(runtimeConfig, storedConfig)
+ driverAdapter.Unlock()
if s.elevatedToken == 0 {
conf.Redact()
}
@@ -85,44 +71,47 @@ func (s *ManagerService) RuntimeConfig(tunnelName string) (*conf.Config, error)
}
func (s *ManagerService) Start(tunnelName string) error {
- // TODO: Rather than being lazy and gating this behind a knob (yuck!), we should instead keep track of the routes
- // of each tunnel, and only deactivate in the case of a tunnel with identical routes being added.
- if !conf.AdminBool("MultipleSimultaneousTunnels") {
- trackedTunnelsLock.Lock()
- tt := make([]string, 0, len(trackedTunnels))
- var inTransition string
- for t, state := range trackedTunnels {
- tt = append(tt, t)
- if len(t) > 0 && (state == TunnelStarting || state == TunnelUnknown) {
- inTransition = t
- break
- }
- }
- trackedTunnelsLock.Unlock()
- if len(inTransition) != 0 {
- return fmt.Errorf("Please allow the tunnel ‘%s’ to finish activating", inTransition)
- }
- go func() {
- for _, t := range tt {
- s.Stop(t)
- }
- for _, t := range tt {
- state, err := s.State(t)
- if err == nil && (state == TunnelStarted || state == TunnelStarting) {
- log.Printf("[%s] Trying again to stop zombie tunnel", t)
- s.Stop(t)
- time.Sleep(time.Millisecond * 100)
- }
- }
- }()
- }
- time.AfterFunc(time.Second*10, cleanupStaleWintunInterfaces)
-
- // After that process is started -- it's somewhat asynchronous -- we install the new one.
c, err := conf.LoadFromName(tunnelName)
if err != nil {
return err
}
+
+ // Figure out which tunnels have intersecting addresses/routes and stop those.
+ trackedTunnelsLock.Lock()
+ tt := make([]string, 0, len(trackedTunnels))
+ var inTransition string
+ for t, state := range trackedTunnels {
+ c2, err := conf.LoadFromName(t)
+ if err != nil || !c.IntersectsWith(c2) {
+ // If we can't get the config, assume it doesn't intersect.
+ continue
+ }
+ tt = append(tt, t)
+ if len(t) > 0 && (state == TunnelStarting || state == TunnelUnknown) {
+ inTransition = t
+ break
+ }
+ }
+ trackedTunnelsLock.Unlock()
+ if len(inTransition) != 0 {
+ return fmt.Errorf("Please allow the tunnel ‘%s’ to finish activating", inTransition)
+ }
+
+ // Stop those intersecting tunnels asynchronously.
+ go func() {
+ for _, t := range tt {
+ s.Stop(t)
+ }
+ for _, t := range tt {
+ state, err := s.State(t)
+ if err == nil && (state == TunnelStarted || state == TunnelStarting) {
+ log.Printf("[%s] Trying again to stop zombie tunnel", t)
+ s.Stop(t)
+ time.Sleep(time.Millisecond * 100)
+ }
+ }
+ }()
+ // After the stop process has begun, but before it's finished, we install the new one.
path, err := c.Path()
if err != nil {
return err
@@ -131,8 +120,6 @@ func (s *ManagerService) Start(tunnelName string) error {
}
func (s *ManagerService) Stop(tunnelName string) error {
- time.AfterFunc(time.Second*10, cleanupStaleWintunInterfaces)
-
err := UninstallTunnel(tunnelName)
if err == windows.ERROR_SERVICE_DOES_NOT_EXIST {
_, notExistsError := conf.LoadFromName(tunnelName)
@@ -144,7 +131,7 @@ func (s *ManagerService) Stop(tunnelName string) error {
}
func (s *ManagerService) WaitForStop(tunnelName string) error {
- serviceName, err := services.ServiceNameOfTunnel(tunnelName)
+ serviceName, err := conf.ServiceNameOfTunnel(tunnelName)
if err != nil {
return err
}
@@ -175,7 +162,7 @@ func (s *ManagerService) Delete(tunnelName string) error {
}
func (s *ManagerService) State(tunnelName string) (TunnelState, error) {
- serviceName, err := services.ServiceNameOfTunnel(tunnelName)
+ serviceName, err := conf.ServiceNameOfTunnel(tunnelName)
if err != nil {
return 0, err
}
@@ -230,7 +217,7 @@ func (s *ManagerService) Tunnels() ([]Tunnel, error) {
}
tunnels := make([]Tunnel, len(names))
for i := 0; i < len(tunnels); i++ {
- (tunnels)[i].Name = names[i]
+ tunnels[i].Name = names[i]
}
return tunnels, nil
// TODO: account for running ones that aren't in the configuration store somehow
@@ -267,9 +254,6 @@ func (s *ManagerService) Quit(stopTunnelsOnQuit bool) (alreadyQuit bool, err err
}
func (s *ManagerService) UpdateState() UpdateState {
- if s.elevatedToken == 0 {
- return UpdateStateUnknown
- }
return updateState
}
@@ -457,7 +441,7 @@ func (s *ManagerService) ServeConn(reader io.Reader, writer io.Writer) {
}
}
-func IPCServerListen(reader *os.File, writer *os.File, events *os.File, elevatedToken windows.Token) {
+func IPCServerListen(reader, writer, events *os.File, elevatedToken windows.Token) {
service := &ManagerService{
events: events,
elevatedToken: elevatedToken,
@@ -477,7 +461,7 @@ func IPCServerListen(reader *os.File, writer *os.File, events *os.File, elevated
}()
}
-func notifyAll(notificationType NotificationType, adminOnly bool, ifaces ...interface{}) {
+func notifyAll(notificationType NotificationType, adminOnly bool, ifaces ...any) {
if len(managerServices) == 0 {
return
}
@@ -528,7 +512,7 @@ func IPCServerNotifyTunnelsChange() {
}
func IPCServerNotifyUpdateFound(state UpdateState) {
- notifyAll(UpdateFoundNotificationType, true, state)
+ notifyAll(UpdateFoundNotificationType, false, state)
}
func IPCServerNotifyUpdateProgress(dp updater.DownloadProgress) {
diff --git a/manager/ipc_uapi.go b/manager/ipc_uapi.go
deleted file mode 100644
index 85477125..00000000
--- a/manager/ipc_uapi.go
+++ /dev/null
@@ -1,71 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
- */
-
-package manager
-
-import (
- "net"
- "sync"
-
- "golang.org/x/sys/windows"
- "golang.zx2c4.com/wireguard/ipc/winpipe"
-
- "golang.zx2c4.com/wireguard/windows/services"
-)
-
-type connectedTunnel struct {
- net.Conn
- sync.Mutex
-}
-
-var connectedTunnelServicePipes = make(map[string]*connectedTunnel)
-var connectedTunnelServicePipesLock sync.RWMutex
-
-func connectTunnelServicePipe(tunnelName string) (*connectedTunnel, error) {
- connectedTunnelServicePipesLock.RLock()
- pipe, ok := connectedTunnelServicePipes[tunnelName]
- if ok {
- pipe.Lock()
- connectedTunnelServicePipesLock.RUnlock()
- return pipe, nil
- }
- connectedTunnelServicePipesLock.RUnlock()
- connectedTunnelServicePipesLock.Lock()
- defer connectedTunnelServicePipesLock.Unlock()
- pipe, ok = connectedTunnelServicePipes[tunnelName]
- if ok {
- pipe.Lock()
- return pipe, nil
- }
- pipePath, err := services.PipePathOfTunnel(tunnelName)
- if err != nil {
- return nil, err
- }
- localSystem, err := windows.CreateWellKnownSid(windows.WinLocalSystemSid)
- if err != nil {
- return nil, err
- }
- pipe = &connectedTunnel{}
- pipe.Conn, err = winpipe.Dial(pipePath, nil, &winpipe.DialConfig{ExpectedOwner: localSystem})
- if err != nil {
- return nil, err
- }
- connectedTunnelServicePipes[tunnelName] = pipe
- pipe.Lock()
- return pipe, nil
-}
-
-func disconnectTunnelServicePipe(tunnelName string) {
- connectedTunnelServicePipesLock.Lock()
- defer connectedTunnelServicePipesLock.Unlock()
- pipe, ok := connectedTunnelServicePipes[tunnelName]
- if !ok {
- return
- }
- pipe.Lock()
- pipe.Close()
- delete(connectedTunnelServicePipes, tunnelName)
- pipe.Unlock()
-}
diff --git a/manager/legacystore.go b/manager/legacystore.go
deleted file mode 100644
index 4125cb86..00000000
--- a/manager/legacystore.go
+++ /dev/null
@@ -1,129 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
- */
-
-package manager
-
-import (
- "fmt"
- "log"
- "os"
- "path/filepath"
- "regexp"
- "strings"
-
- "golang.org/x/sys/windows"
- "golang.org/x/sys/windows/registry"
- "golang.org/x/sys/windows/svc/mgr"
-
- "golang.zx2c4.com/wireguard/windows/conf"
-)
-
-func moveConfigsFromLegacyStore() {
- oldRoot, err := windows.KnownFolderPath(windows.FOLDERID_LocalAppData, windows.KF_FLAG_DEFAULT)
- if err != nil {
- return
- }
- oldC := filepath.Join(oldRoot, "WireGuard", "Configurations")
- files, err := os.ReadDir(oldC)
- if err != nil {
- return
- }
- pendingDeletion := make(map[string]bool)
- if key, err := registry.OpenKey(registry.LOCAL_MACHINE, `SYSTEM\CurrentControlSet\Control\Session Manager`, registry.READ); err == nil {
- if ntPaths, _, err := key.GetStringsValue("PendingFileRenameOperations"); err == nil {
- for _, ntPath := range ntPaths {
- pendingDeletion[strings.ToLower(strings.TrimPrefix(ntPath, `\??\`))] = true
- }
- }
- key.Close()
- }
- migratedConfigs := make(map[string]string)
- for i := range files {
- if files[i].IsDir() {
- continue
- }
- fileName := files[i].Name()
- oldPath := filepath.Join(oldC, fileName)
- if pendingDeletion[strings.ToLower(oldPath)] {
- continue
- }
- config, err := conf.LoadFromPath(oldPath)
- if err != nil {
- continue
- }
- newPath, err := config.Path()
- if err != nil {
- continue
- }
- err = config.Save(false)
- if err != nil {
- continue
- }
- oldPath16, err := windows.UTF16PtrFromString(oldPath)
- if err == nil {
- windows.MoveFileEx(oldPath16, nil, windows.MOVEFILE_DELAY_UNTIL_REBOOT)
- }
- migratedConfigs[strings.ToLower(oldPath)] = newPath
- log.Printf("Migrated configuration from ‘%s’ to ‘%s’", oldPath, newPath)
- }
- oldC16, err := windows.UTF16PtrFromString(oldC)
- if err == nil {
- windows.MoveFileEx(oldC16, nil, windows.MOVEFILE_DELAY_UNTIL_REBOOT)
- }
- oldLog16, err := windows.UTF16PtrFromString(filepath.Join(oldRoot, "WireGuard", "log.bin"))
- if err == nil {
- windows.MoveFileEx(oldLog16, nil, windows.MOVEFILE_DELAY_UNTIL_REBOOT)
- }
- oldRoot16, err := windows.UTF16PtrFromString(filepath.Join(oldRoot, "WireGuard"))
- if err == nil {
- windows.MoveFileEx(oldRoot16, nil, windows.MOVEFILE_DELAY_UNTIL_REBOOT)
- }
- if len(migratedConfigs) == 0 {
- return
- }
- m, err := mgr.Connect()
- if err != nil {
- return
- }
- defer m.Disconnect()
- services, err := m.ListServices()
- if err != nil {
- return
- }
- matcher, err := regexp.Compile(" /tunnelservice \"?([^\"]+)\"?$")
- if err != nil {
- return
- }
- for _, svcName := range services {
- if !strings.HasPrefix(svcName, "WireGuardTunnel$") {
- continue
- }
- svc, err := m.OpenService(svcName)
- if err != nil {
- continue
- }
- config, err := svc.Config()
- if err != nil {
- continue
- }
- matches := matcher.FindStringSubmatchIndex(config.BinaryPathName)
- if len(matches) != 4 {
- svc.Close()
- continue
- }
- newName, found := migratedConfigs[strings.ToLower(config.BinaryPathName[matches[2]:])]
- if !found {
- svc.Close()
- continue
- }
- config.BinaryPathName = config.BinaryPathName[:matches[0]] + fmt.Sprintf(" /tunnelservice \"%s\"", newName)
- err = svc.UpdateConfig(config)
- svc.Close()
- if err != nil {
- continue
- }
- log.Printf("Migrated service command line arguments for ‘%s’", svcName)
- }
-}
diff --git a/manager/service.go b/manager/service.go
index 99187eab..47e20d45 100644
--- a/manager/service.go
+++ b/manager/service.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package manager
@@ -12,18 +12,17 @@ import (
"runtime"
"strconv"
"sync"
- "syscall"
"time"
"unsafe"
"golang.org/x/sys/windows"
"golang.org/x/sys/windows/svc"
+ "golang.zx2c4.com/wireguard/windows/driver"
"golang.zx2c4.com/wireguard/windows/conf"
"golang.zx2c4.com/wireguard/windows/elevate"
"golang.zx2c4.com/wireguard/windows/ringlogger"
"golang.zx2c4.com/wireguard/windows/services"
- "golang.zx2c4.com/wireguard/windows/version"
)
type managerService struct{}
@@ -43,38 +42,36 @@ func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest
changes <- svc.Status{State: svc.StopPending}
}()
- err = ringlogger.InitGlobalLogger("MGR")
+ var logFile string
+ logFile, err = conf.LogFile(true)
if err != nil {
serviceError = services.ErrorRingloggerOpen
return
}
-
- log.Println("Starting", version.UserAgent())
-
- path, err := os.Executable()
+ err = ringlogger.InitGlobalLogger(logFile, "MGR")
if err != nil {
- serviceError = services.ErrorDetermineExecutablePath
+ serviceError = services.ErrorRingloggerOpen
return
}
- devNull, err := os.OpenFile(os.DevNull, os.O_RDWR, 0)
+ services.PrintStarting()
+
+ path, err := os.Executable()
if err != nil {
- serviceError = services.ErrorOpenNULFile
+ serviceError = services.ErrorDetermineExecutablePath
return
}
- moveConfigsFromLegacyStore()
-
- err = trackExistingTunnels()
+ err = watchNewTunnelServices()
if err != nil {
serviceError = services.ErrorTrackTunnels
return
}
- conf.RegisterStoreChangeCallback(conf.MigrateUnencryptedConfigs)
+ conf.RegisterStoreChangeCallback(func() { conf.MigrateUnencryptedConfigs(changeTunnelServiceConfigFilePath) })
conf.RegisterStoreChangeCallback(IPCServerNotifyTunnelsChange)
- procs := make(map[uint32]*os.Process)
+ procs := make(map[uint32]*uiProcess)
aliveSessions := make(map[uint32]bool)
procsLock := sync.Mutex{}
stoppingManager := false
@@ -196,29 +193,22 @@ func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest
}
log.Printf("Starting UI process for user ‘%s@%s’ for session %d", username, domain, session)
- attr := &os.ProcAttr{
- Sys: &syscall.SysProcAttr{
- Token: syscall.Token(runToken),
- AdditionalInheritedHandles: []syscall.Handle{
- syscall.Handle(theirReader.Fd()),
- syscall.Handle(theirWriter.Fd()),
- syscall.Handle(theirEvents.Fd()),
- syscall.Handle(theirLogMapping)},
- },
- Files: []*os.File{devNull, devNull, devNull},
- Dir: userProfileDirectory,
- }
procsLock.Lock()
- var proc *os.Process
+ var proc *uiProcess
if alive := aliveSessions[session]; alive {
- proc, err = os.StartProcess(path, []string{
+ proc, err = launchUIProcess(path, []string{
path,
"/ui",
strconv.FormatUint(uint64(theirReader.Fd()), 10),
strconv.FormatUint(uint64(theirWriter.Fd()), 10),
strconv.FormatUint(uint64(theirEvents.Fd()), 10),
strconv.FormatUint(uint64(theirLogMapping), 10),
- }, attr)
+ }, userProfileDirectory, []windows.Handle{
+ windows.Handle(theirReader.Fd()),
+ windows.Handle(theirWriter.Fd()),
+ windows.Handle(theirEvents.Fd()),
+ theirLogMapping,
+ }, runToken)
} else {
err = errors.New("Session has logged out")
}
@@ -240,9 +230,7 @@ func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest
procsLock.Unlock()
sessionIsDead := false
- processStatus, err := proc.Wait()
- if err == nil {
- exitCode := processStatus.Sys().(syscall.WaitStatus).ExitCode
+ if exitCode, err := proc.Wait(); err == nil {
log.Printf("Exited UI process for user '%s@%s' for session %d with status %x", username, domain, session, exitCode)
const STATUS_DLL_INIT_FAILED_LOGOFF = 0xC000026B
sessionIsDead = exitCode == STATUS_DLL_INIT_FAILED_LOGOFF
@@ -271,8 +259,8 @@ func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest
}()
}
- time.AfterFunc(time.Second*10, cleanupStaleWintunInterfaces)
go checkForUpdates()
+ go driver.UninstallLegacyWintun() // We uninstall opportunistically here, so that we don't have to carry around the uninstaller code forever.
var sessionsPointer *windows.WTS_SESSION_INFO
var count uint32
@@ -281,12 +269,7 @@ func (service *managerService) Execute(args []string, r <-chan svc.ChangeRequest
serviceError = services.ErrorEnumerateSessions
return
}
- sessions := *(*[]windows.WTS_SESSION_INFO)(unsafe.Pointer(&struct {
- addr *windows.WTS_SESSION_INFO
- len int
- cap int
- }{sessionsPointer, int(count), int(count)}))
- for _, session := range sessions {
+ for _, session := range unsafe.Slice(sessionsPointer, count) {
if session.State != windows.WTSActive && session.State != windows.WTSDisconnected {
continue
}
diff --git a/manager/tunneltracker.go b/manager/tunneltracker.go
index b32450a3..9003d445 100644
--- a/manager/tunneltracker.go
+++ b/manager/tunneltracker.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package manager
@@ -24,31 +24,10 @@ import (
"golang.zx2c4.com/wireguard/windows/services"
)
-func trackExistingTunnels() error {
- m, err := serviceManager()
- if err != nil {
- return err
- }
- names, err := conf.ListConfigNames()
- if err != nil {
- return err
- }
- for _, name := range names {
- serviceName, err := services.ServiceNameOfTunnel(name)
- if err != nil {
- continue
- }
- service, err := m.OpenService(serviceName)
- if err != nil {
- continue
- }
- go trackTunnelService(name, service)
- }
- return nil
-}
-
-var trackedTunnels = make(map[string]TunnelState)
-var trackedTunnelsLock = sync.Mutex{}
+var (
+ trackedTunnels = make(map[string]TunnelState)
+ trackedTunnelsLock = sync.Mutex{}
+)
func trackedTunnelsGlobalState() (state TunnelState) {
state = TunnelStopped
@@ -196,16 +175,17 @@ func trackService(service *mgr.Service, callback func(status uint32) bool) error
}
func trackTunnelService(tunnelName string, service *mgr.Service) {
- defer func() {
- service.Close()
- log.Printf("[%s] Tunnel service tracker finished", tunnelName)
- }()
-
trackedTunnelsLock.Lock()
if _, found := trackedTunnels[tunnelName]; found {
trackedTunnelsLock.Unlock()
+ service.Close()
return
}
+
+ defer func() {
+ service.Close()
+ log.Printf("[%s] Tunnel service tracker finished", tunnelName)
+ }()
trackedTunnels[tunnelName] = TunnelUnknown
trackedTunnelsLock.Unlock()
defer func() {
@@ -214,6 +194,15 @@ func trackTunnelService(tunnelName string, service *mgr.Service) {
trackedTunnelsLock.Unlock()
}()
+ for i := 0; i < 20; i++ {
+ if i > 0 {
+ time.Sleep(time.Second / 5)
+ }
+ if status, err := service.Query(); err != nil || status.State != svc.Stopped {
+ break
+ }
+ }
+
checkForDisabled := func() (shouldReturn bool) {
config, err := service.Config()
if err == windows.ERROR_SERVICE_MARKED_FOR_DELETE || (err != nil && config.StartType == windows.SERVICE_DISABLED) {
@@ -273,5 +262,82 @@ func trackTunnelService(tunnelName string, service *mgr.Service) {
IPCServerNotifyTunnelChange(tunnelName, TunnelStopped, fmt.Errorf("Unable to continue monitoring service, so stopping: %w", err))
service.Control(svc.Stop)
}
- disconnectTunnelServicePipe(tunnelName)
+}
+
+func trackExistingTunnels() error {
+ m, err := serviceManager()
+ if err != nil {
+ return err
+ }
+ names, err := conf.ListConfigNames()
+ if err != nil {
+ return err
+ }
+ for _, name := range names {
+ trackedTunnelsLock.Lock()
+ if _, found := trackedTunnels[name]; found {
+ trackedTunnelsLock.Unlock()
+ continue
+ }
+ trackedTunnelsLock.Unlock()
+ serviceName, err := conf.ServiceNameOfTunnel(name)
+ if err != nil {
+ continue
+ }
+ service, err := m.OpenService(serviceName)
+ if err != nil {
+ continue
+ }
+ go trackTunnelService(name, service)
+ }
+ return nil
+}
+
+var servicesSubscriptionWatcherCallbackPtr = windows.NewCallback(func(notification uint32, context uintptr) uintptr {
+ trackExistingTunnels()
+ return 0
+})
+
+func watchNewTunnelServices() error {
+ m, err := serviceManager()
+ if err != nil {
+ return err
+ }
+ var subscription uintptr
+ err = windows.SubscribeServiceChangeNotifications(m.Handle, windows.SC_EVENT_DATABASE_CHANGE, servicesSubscriptionWatcherCallbackPtr, 0, &subscription)
+ if err == nil {
+ // We probably could do:
+ // defer windows.UnsubscribeServiceChangeNotifications(subscription)
+ // and then terminate after some point, but instead we just let this go forever; it's process-lived.
+ return trackExistingTunnels()
+ }
+ if !errors.Is(err, windows.ERROR_PROC_NOT_FOUND) {
+ return err
+ }
+
+ // TODO: Below this line is Windows 7 compatibility code, which hopefully we can delete at some point.
+ go func() {
+ runtime.LockOSThread()
+ notifier := &windows.SERVICE_NOTIFY{
+ Version: windows.SERVICE_NOTIFY_STATUS_CHANGE,
+ NotifyCallback: serviceTrackerCallbackPtr,
+ }
+ for {
+ err := windows.NotifyServiceStatusChange(m.Handle, windows.SERVICE_NOTIFY_CREATED, notifier)
+ if err == nil {
+ windows.SleepEx(windows.INFINITE, true)
+ if notifier.ServiceNames != nil {
+ windows.LocalFree(windows.Handle(unsafe.Pointer(notifier.ServiceNames)))
+ notifier.ServiceNames = nil
+ }
+ trackExistingTunnels()
+ } else if err == windows.ERROR_SERVICE_NOTIFY_CLIENT_LAGGING {
+ continue
+ } else {
+ time.Sleep(time.Second * 3)
+ trackExistingTunnels()
+ }
+ }
+ }()
+ return trackExistingTunnels()
}
diff --git a/manager/uiprocess.go b/manager/uiprocess.go
new file mode 100644
index 00000000..b33b1ad3
--- /dev/null
+++ b/manager/uiprocess.go
@@ -0,0 +1,103 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package manager
+
+import (
+ "errors"
+ "runtime"
+ "sync/atomic"
+ "syscall"
+ "unsafe"
+
+ "golang.org/x/sys/windows"
+)
+
+type uiProcess struct {
+ handle uintptr
+}
+
+func launchUIProcess(executable string, args []string, workingDirectory string, handles []windows.Handle, token windows.Token) (*uiProcess, error) {
+ executable16, err := windows.UTF16PtrFromString(executable)
+ if err != nil {
+ return nil, err
+ }
+ args16, err := windows.UTF16PtrFromString(windows.ComposeCommandLine(args))
+ if err != nil {
+ return nil, err
+ }
+ workingDirectory16, err := windows.UTF16PtrFromString(workingDirectory)
+ if err != nil {
+ return nil, err
+ }
+ var environmentBlock *uint16
+ err = windows.CreateEnvironmentBlock(&environmentBlock, token, false)
+ if err != nil {
+ return nil, err
+ }
+ defer windows.DestroyEnvironmentBlock(environmentBlock)
+ attributeList, err := windows.NewProcThreadAttributeList(1)
+ if err != nil {
+ return nil, err
+ }
+ defer attributeList.Delete()
+ si := &windows.StartupInfoEx{
+ StartupInfo: windows.StartupInfo{Cb: uint32(unsafe.Sizeof(windows.StartupInfoEx{}))},
+ ProcThreadAttributeList: attributeList.List(),
+ }
+ if len(handles) == 0 {
+ handles = []windows.Handle{0}
+ }
+ attributeList.Update(windows.PROC_THREAD_ATTRIBUTE_HANDLE_LIST, unsafe.Pointer(&handles[0]), uintptr(len(handles))*unsafe.Sizeof(handles[0]))
+ pi := new(windows.ProcessInformation)
+ err = windows.CreateProcessAsUser(token, executable16, args16, nil, nil, true, windows.CREATE_DEFAULT_ERROR_MODE|windows.CREATE_UNICODE_ENVIRONMENT|windows.EXTENDED_STARTUPINFO_PRESENT, environmentBlock, workingDirectory16, &si.StartupInfo, pi)
+ if err != nil {
+ return nil, err
+ }
+ windows.CloseHandle(pi.Thread)
+ uiProc := &uiProcess{handle: uintptr(pi.Process)}
+ runtime.SetFinalizer(uiProc, (*uiProcess).release)
+ return uiProc, nil
+}
+
+func (p *uiProcess) release() error {
+ handle := windows.Handle(atomic.SwapUintptr(&p.handle, uintptr(windows.InvalidHandle)))
+ if handle == windows.InvalidHandle {
+ return nil
+ }
+ err := windows.CloseHandle(handle)
+ if err != nil {
+ return err
+ }
+ runtime.SetFinalizer(p, nil)
+ return nil
+}
+
+func (p *uiProcess) Wait() (uint32, error) {
+ handle := windows.Handle(atomic.LoadUintptr(&p.handle))
+ s, err := windows.WaitForSingleObject(handle, syscall.INFINITE)
+ switch s {
+ case windows.WAIT_OBJECT_0:
+ case windows.WAIT_FAILED:
+ return 0, err
+ default:
+ return 0, errors.New("unexpected result from WaitForSingleObject")
+ }
+ var exitCode uint32
+ err = windows.GetExitCodeProcess(handle, &exitCode)
+ if err != nil {
+ return 0, err
+ }
+ p.release()
+ return exitCode, nil
+}
+
+func (p *uiProcess) Kill() error {
+ handle := windows.Handle(atomic.LoadUintptr(&p.handle))
+ if handle == windows.InvalidHandle {
+ return nil
+ }
+ return windows.TerminateProcess(handle, 1)
+}
diff --git a/manager/updatestate.go b/manager/updatestate.go
index 069e9b8a..d5a19c8d 100644
--- a/manager/updatestate.go
+++ b/manager/updatestate.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package manager
@@ -8,11 +8,16 @@ package manager
import (
"log"
"time"
+ _ "unsafe"
+ "golang.zx2c4.com/wireguard/windows/services"
"golang.zx2c4.com/wireguard/windows/updater"
"golang.zx2c4.com/wireguard/windows/version"
)
+//go:linkname fastrandn runtime.fastrandn
+func fastrandn(n uint32) uint32
+
type UpdateState uint32
const (
@@ -23,6 +28,10 @@ const (
var updateState = UpdateStateUnknown
+func jitterSleep(min, max time.Duration) {
+ time.Sleep(min + time.Millisecond*time.Duration(fastrandn(uint32((max-min+1)/time.Millisecond))))
+}
+
func checkForUpdates() {
if !version.IsRunningOfficialVersion() {
log.Println("Build is not official, so updates are disabled")
@@ -30,26 +39,27 @@ func checkForUpdates() {
IPCServerNotifyUpdateFound(updateState)
return
}
-
- first := true
+ if services.StartedAtBoot() {
+ jitterSleep(time.Minute*2, time.Minute*5)
+ }
+ noError, didNotify := true, false
for {
update, err := updater.CheckForUpdate()
- if err == nil && update != nil {
+ if err == nil && update != nil && !didNotify {
log.Println("An update is available")
updateState = UpdateStateFoundUpdate
IPCServerNotifyUpdateFound(updateState)
- return
- }
- if err != nil {
+ didNotify = true
+ } else if err != nil && !didNotify {
log.Printf("Update checker: %v", err)
- if first {
- time.Sleep(time.Minute * 4)
- first = false
+ if noError {
+ jitterSleep(time.Minute*4, time.Minute*6)
+ noError = false
} else {
- time.Sleep(time.Minute * 25)
+ jitterSleep(time.Minute*25, time.Minute*30)
}
} else {
- time.Sleep(time.Hour)
+ jitterSleep(time.Hour-time.Minute*3, time.Hour+time.Minute*3)
}
}
}
diff --git a/quickinstall.bat b/quickinstall.bat
index 95157bbd..47d66a30 100644
--- a/quickinstall.bat
+++ b/quickinstall.bat
@@ -1,6 +1,6 @@
@echo off
rem SPDX-License-Identifier: MIT
-rem Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+rem Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
setlocal
cd /d %~dp0 || exit /b 1
diff --git a/resources.rc b/resources.rc
index 464492c0..0601d938 100644
--- a/resources.rc
+++ b/resources.rc
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
#include <windows.h>
@@ -14,7 +14,7 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
CREATEPROCESS_MANIFEST_RESOURCE_ID RT_MANIFEST manifest.xml
7 ICON ui/icon/wireguard.ico
8 ICON ui/icon/dot.ico
-wintun.dll RCDATA wintun.dll
+wireguard.dll RCDATA wireguard.dll
#define VERSIONINFO_TEMPLATE(block_id, lang_id, codepage_id, file_desc, comments) \
VS_VERSION_INFO VERSIONINFO \
@@ -32,7 +32,7 @@ BEGIN \
VALUE "FileDescription", file_desc \
VALUE "FileVersion", EXPAND(WIREGUARD_VERSION_STR) \
VALUE "InternalName", "wireguard-windows" \
- VALUE "LegalCopyright", "Copyright © 2015-2021 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved." \
+ VALUE "LegalCopyright", "Copyright © 2015-2022 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved." \
VALUE "OriginalFilename", "wireguard.exe" \
VALUE "ProductName", "WireGuard" \
VALUE "ProductVersion", EXPAND(WIREGUARD_VERSION_STR) \
diff --git a/ringlogger/cli_test.go b/ringlogger/cli_test.go
index 960fe547..12541c81 100644
--- a/ringlogger/cli_test.go
+++ b/ringlogger/cli_test.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package ringlogger
diff --git a/ringlogger/dump.go b/ringlogger/dump.go
index 8b5651e3..3c089751 100644
--- a/ringlogger/dump.go
+++ b/ringlogger/dump.go
@@ -1,27 +1,22 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package ringlogger
import (
+ "errors"
+ "fmt"
"io"
"os"
- "path/filepath"
+ "time"
"golang.org/x/sys/windows"
-
- "golang.zx2c4.com/wireguard/windows/conf"
)
-func DumpTo(out io.Writer, notSystem bool) error {
- root, err := conf.RootDirectory(!notSystem)
- if err != nil {
- return err
- }
- path := filepath.Join(root, "log.bin")
- file, err := os.Open(path)
+func DumpTo(inPath string, out io.Writer, continuous bool) error {
+ file, err := os.Open(inPath)
if err != nil {
return err
}
@@ -36,9 +31,26 @@ func DumpTo(out io.Writer, notSystem bool) error {
return err
}
defer rl.Close()
- _, err = rl.WriteTo(out)
- if err != nil {
- return err
+ if !continuous {
+ _, err = rl.WriteTo(out)
+ if err != nil {
+ return err
+ }
+ } else {
+ cursor := CursorAll
+ for {
+ var items []FollowLine
+ items, cursor = rl.FollowFromCursor(cursor)
+ for _, item := range items {
+ _, err = fmt.Fprintf(out, "%s: %s\n", item.Stamp.Format("2006-01-02 15:04:05.000000"), item.Line)
+ if errors.Is(err, io.EOF) {
+ return nil
+ } else if err != nil {
+ return err
+ }
+ }
+ time.Sleep(time.Millisecond * 100)
+ }
}
return nil
}
diff --git a/ringlogger/global.go b/ringlogger/global.go
index 4213e2f1..5c522a70 100644
--- a/ringlogger/global.go
+++ b/ringlogger/global.go
@@ -1,29 +1,23 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package ringlogger
import (
"log"
- "path/filepath"
"unsafe"
-
- "golang.zx2c4.com/wireguard/windows/conf"
)
var Global *Ringlogger
-func InitGlobalLogger(tag string) error {
+func InitGlobalLogger(file, tag string) error {
if Global != nil {
return nil
}
- root, err := conf.RootDirectory(true)
- if err != nil {
- return err
- }
- Global, err = NewRinglogger(filepath.Join(root, "log.bin"), tag)
+ var err error
+ Global, err = NewRinglogger(file, tag)
if err != nil {
return err
}
@@ -36,8 +30,10 @@ func InitGlobalLogger(tag string) error {
//go:linkname overrideWrite runtime.overrideWrite
var overrideWrite func(fd uintptr, p unsafe.Pointer, n int32) int32
-var globalBuffer [maxLogLineLength - 1 - maxTagLength - 3]byte
-var globalBufferLocation int
+var (
+ globalBuffer [maxLogLineLength - 1 - maxTagLength - 3]byte
+ globalBufferLocation int
+)
//go:nosplit
func globalWrite(fd uintptr, p unsafe.Pointer, n int32) int32 {
diff --git a/ringlogger/ringlogger.go b/ringlogger/ringlogger.go
index 2d7c0c8f..e932f88c 100644
--- a/ringlogger/ringlogger.go
+++ b/ringlogger/ringlogger.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package ringlogger
@@ -45,11 +45,11 @@ type Ringlogger struct {
readOnly bool
}
-func NewRinglogger(filename string, tag string) (*Ringlogger, error) {
+func NewRinglogger(filename, tag string) (*Ringlogger, error) {
if len(tag) > maxTagLength {
return nil, windows.ERROR_LABEL_TOO_LONG
}
- file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0600)
+ file, err := os.OpenFile(filename, os.O_RDWR|os.O_CREATE, 0o600)
if err != nil {
return nil, err
}
@@ -63,13 +63,14 @@ func NewRinglogger(filename string, tag string) (*Ringlogger, error) {
}
rl, err := newRingloggerFromMappingHandle(mapping, tag, windows.FILE_MAP_WRITE)
if err != nil {
+ windows.CloseHandle(mapping)
return nil, err
}
rl.file = file
return rl, nil
}
-func NewRingloggerFromInheritedMappingHandle(handleStr string, tag string) (*Ringlogger, error) {
+func NewRingloggerFromInheritedMappingHandle(handleStr, tag string) (*Ringlogger, error) {
handle, err := strconv.ParseUint(handleStr, 10, 64)
if err != nil {
return nil, err
@@ -82,10 +83,6 @@ func newRingloggerFromMappingHandle(mappingHandle windows.Handle, tag string, ac
if err != nil {
return nil, err
}
- if err != nil {
- windows.CloseHandle(mappingHandle)
- return nil, err
- }
log := (*logMem)(unsafe.Pointer(view))
if log.magic != magic {
bytes := (*[unsafe.Sizeof(logMem{})]byte)(unsafe.Pointer(log))
@@ -107,6 +104,12 @@ func newRingloggerFromMappingHandle(mappingHandle windows.Handle, tag string, ac
}
func (rl *Ringlogger) Write(p []byte) (n int, err error) {
+ // Race: This isn't synchronized with the fetch_add below, so items might be slightly out of order.
+ ts := time.Now().UnixNano()
+ return rl.WriteWithTimestamp(p, ts)
+}
+
+func (rl *Ringlogger) WriteWithTimestamp(p []byte, ts int64) (n int, err error) {
if rl.readOnly {
return 0, io.ErrShortWrite
}
@@ -116,9 +119,6 @@ func (rl *Ringlogger) Write(p []byte) (n int, err error) {
return ret, nil
}
- // Race: This isn't synchronized with the fetch_add below, so items might be slightly out of order.
- ts := time.Now().UnixNano()
-
if rl.log == nil {
return 0, io.EOF
}
@@ -136,7 +136,7 @@ func (rl *Ringlogger) Write(p []byte) (n int, err error) {
textLen := 3 + len(p) + len(rl.tag)
if textLen > maxLogLineLength-1 {
p = p[:maxLogLineLength-1-3-len(rl.tag)]
- textLen = maxLogLineLength-1
+ textLen = maxLogLineLength - 1
}
line.line[textLen] = 0
line.line[0] = 0 // Null out the beginning and only let it extend after the other writes have completed
diff --git a/services/boot.go b/services/boot.go
new file mode 100644
index 00000000..ae7aadda
--- /dev/null
+++ b/services/boot.go
@@ -0,0 +1,47 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package services
+
+import (
+ "errors"
+ "log"
+ "sync"
+ "time"
+
+ "golang.org/x/sys/windows"
+ "golang.org/x/sys/windows/svc"
+ "golang.zx2c4.com/wireguard/windows/version"
+)
+
+var (
+ startedAtBoot bool
+ startedAtBootOnce sync.Once
+)
+
+func StartedAtBoot() bool {
+ startedAtBootOnce.Do(func() {
+ if isService, err := svc.IsWindowsService(); err == nil && !isService {
+ return
+ }
+ if reason, err := svc.DynamicStartReason(); err == nil {
+ startedAtBoot = (reason&svc.StartReasonAuto) != 0 || (reason&svc.StartReasonDelayedAuto) != 0
+ } else if errors.Is(err, windows.ERROR_PROC_NOT_FOUND) {
+ // TODO: Below this line is Windows 7 compatibility code, which hopefully we can delete at some point.
+ startedAtBoot = windows.DurationSinceBoot() < time.Minute*10
+ } else {
+ log.Printf("Unable to determine service start reason: %v", err)
+ }
+ })
+ return startedAtBoot
+}
+
+func PrintStarting() {
+ boot := ""
+ if StartedAtBoot() {
+ boot = " at boot"
+ }
+ log.Printf("Starting%s %s", boot, version.UserAgent())
+}
diff --git a/services/errors.go b/services/errors.go
index e17cad88..c0588494 100644
--- a/services/errors.go
+++ b/services/errors.go
@@ -1,13 +1,12 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package services
import (
"fmt"
- "syscall"
"golang.org/x/sys/windows"
)
@@ -18,15 +17,15 @@ const (
ErrorSuccess Error = iota
ErrorRingloggerOpen
ErrorLoadConfiguration
- ErrorCreateWintun
- ErrorUAPIListen
+ ErrorCreateNetworkAdapter
ErrorDNSLookup
ErrorFirewall
ErrorDeviceSetConfig
+ ErrorDeviceBringUp
ErrorBindSocketsToDefaultRoutes
+ ErrorMonitorMTUChanges
ErrorSetNetConfig
ErrorDetermineExecutablePath
- ErrorOpenNULFile
ErrorTrackTunnels
ErrorEnumerateSessions
ErrorDropPrivileges
@@ -44,22 +43,22 @@ func (e Error) Error() string {
return "Unable to determine path of running executable"
case ErrorLoadConfiguration:
return "Unable to load configuration from path"
- case ErrorCreateWintun:
- return "Unable to create Wintun interface"
- case ErrorUAPIListen:
- return "Unable to listen on named pipe"
+ case ErrorCreateNetworkAdapter:
+ return "Unable to create network adapter"
case ErrorDNSLookup:
return "Unable to resolve one or more DNS hostname endpoints"
case ErrorFirewall:
return "Unable to enable firewall rules"
case ErrorDeviceSetConfig:
return "Unable to set device configuration"
+ case ErrorDeviceBringUp:
+ return "Unable to bring up adapter"
case ErrorBindSocketsToDefaultRoutes:
return "Unable to bind sockets to default route"
+ case ErrorMonitorMTUChanges:
+ return "Unable to monitor default route MTU for changes"
case ErrorSetNetConfig:
- return "Unable to set interface addresses, routes, dns, and/or interface settings"
- case ErrorOpenNULFile:
- return "Unable to open NUL file"
+ return "Unable to configure adapter network settings"
case ErrorTrackTunnels:
return "Unable to track existing tunnels"
case ErrorEnumerateSessions:
@@ -76,7 +75,7 @@ func (e Error) Error() string {
}
func DetermineErrorCode(err error, serviceError Error) (bool, uint32) {
- if syserr, ok := err.(syscall.Errno); ok {
+ if syserr, ok := err.(windows.Errno); ok {
return false, uint32(syserr)
} else if serviceError != ErrorSuccess {
return true, uint32(serviceError)
diff --git a/services/names.go b/services/names.go
deleted file mode 100644
index 2b9c1d64..00000000
--- a/services/names.go
+++ /dev/null
@@ -1,26 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
- */
-
-package services
-
-import (
- "errors"
-
- "golang.zx2c4.com/wireguard/windows/conf"
-)
-
-func ServiceNameOfTunnel(tunnelName string) (string, error) {
- if !conf.TunnelNameIsValid(tunnelName) {
- return "", errors.New("Tunnel name is not valid")
- }
- return "WireGuardTunnel$" + tunnelName, nil
-}
-
-func PipePathOfTunnel(tunnelName string) (string, error) {
- if !conf.TunnelNameIsValid(tunnelName) {
- return "", errors.New("Tunnel name is not valid")
- }
- return `\\.\pipe\ProtectedPrefix\Administrators\WireGuard\` + tunnelName, nil
-}
diff --git a/tunnel/addressconfig.go b/tunnel/addressconfig.go
index 44bfd8ae..a3ce6295 100644
--- a/tunnel/addressconfig.go
+++ b/tunnel/addressconfig.go
@@ -1,42 +1,30 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package tunnel
import (
- "bytes"
+ "fmt"
"log"
- "net"
- "sort"
+ "net/netip"
+ "time"
"golang.org/x/sys/windows"
- "golang.zx2c4.com/wireguard/tun"
-
"golang.zx2c4.com/wireguard/windows/conf"
+ "golang.zx2c4.com/wireguard/windows/services"
"golang.zx2c4.com/wireguard/windows/tunnel/firewall"
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
)
-func cleanupAddressesOnDisconnectedInterfaces(family winipcfg.AddressFamily, addresses []net.IPNet) {
+func cleanupAddressesOnDisconnectedInterfaces(family winipcfg.AddressFamily, addresses []netip.Prefix) {
if len(addresses) == 0 {
return
}
- includedInAddresses := func(a net.IPNet) bool {
- // TODO: this makes the whole algorithm O(n^2). But we can't stick net.IPNet in a Go hashmap. Bummer!
- for _, addr := range addresses {
- ip := addr.IP
- if ip4 := ip.To4(); ip4 != nil {
- ip = ip4
- }
- mA, _ := addr.Mask.Size()
- mB, _ := a.Mask.Size()
- if bytes.Equal(ip, a.IP) && mA == mB {
- return true
- }
- }
- return false
+ addrHash := make(map[netip.Addr]bool, len(addresses))
+ for i := range addresses {
+ addrHash[addresses[i].Addr()] = true
}
interfaces, err := winipcfg.GetAdaptersAddresses(family, winipcfg.GAAFlagDefault)
if err != nil {
@@ -47,147 +35,124 @@ func cleanupAddressesOnDisconnectedInterfaces(family winipcfg.AddressFamily, add
continue
}
for address := iface.FirstUnicastAddress; address != nil; address = address.Next {
- ip := address.Address.IP()
- ipnet := net.IPNet{IP: ip, Mask: net.CIDRMask(int(address.OnLinkPrefixLength), 8*len(ip))}
- if includedInAddresses(ipnet) {
- log.Printf("Cleaning up stale address %s from interface ‘%s’", ipnet.String(), iface.FriendlyName())
- iface.LUID.DeleteIPAddress(ipnet)
+ if ip, _ := netip.AddrFromSlice(address.Address.IP()); addrHash[ip] {
+ prefix := netip.PrefixFrom(ip, int(address.OnLinkPrefixLength))
+ log.Printf("Cleaning up stale address %s from interface ‘%s’", prefix.String(), iface.FriendlyName())
+ iface.LUID.DeleteIPAddress(prefix)
}
}
}
}
-func configureInterface(family winipcfg.AddressFamily, conf *conf.Config, tun *tun.NativeTun) error {
- luid := winipcfg.LUID(tun.LUID())
+func configureInterface(family winipcfg.AddressFamily, conf *conf.Config, luid winipcfg.LUID) error {
+ retryOnFailure := services.StartedAtBoot()
+ tryTimes := 0
+startOver:
+ var err error
+ if tryTimes > 0 {
+ log.Printf("Retrying interface configuration after failure because system just booted (T+%v): %v", windows.DurationSinceBoot(), err)
+ time.Sleep(time.Second)
+ retryOnFailure = retryOnFailure && tryTimes < 15
+ }
+ tryTimes++
estimatedRouteCount := 0
for _, peer := range conf.Peers {
estimatedRouteCount += len(peer.AllowedIPs)
}
- routes := make([]winipcfg.RouteData, 0, estimatedRouteCount)
- addresses := make([]net.IPNet, len(conf.Interface.Addresses))
- var haveV4Address, haveV6Address bool
- for i, addr := range conf.Interface.Addresses {
- addresses[i] = addr.IPNet()
- if addr.Bits() == 32 {
- haveV4Address = true
- } else if addr.Bits() == 128 {
- haveV6Address = true
- }
- }
+ routes := make(map[winipcfg.RouteData]bool, estimatedRouteCount)
foundDefault4 := false
foundDefault6 := false
for _, peer := range conf.Peers {
for _, allowedip := range peer.AllowedIPs {
- allowedip.MaskSelf()
- if (allowedip.Bits() == 32 && !haveV4Address) || (allowedip.Bits() == 128 && !haveV6Address) {
- continue
- }
route := winipcfg.RouteData{
- Destination: allowedip.IPNet(),
+ Destination: allowedip.Masked(),
Metric: 0,
}
- if allowedip.Bits() == 32 {
- if allowedip.Cidr == 0 {
+ if allowedip.Addr().Is4() {
+ if allowedip.Bits() == 0 {
foundDefault4 = true
}
- route.NextHop = net.IPv4zero
- } else if allowedip.Bits() == 128 {
- if allowedip.Cidr == 0 {
+ route.NextHop = netip.IPv4Unspecified()
+ } else if allowedip.Addr().Is6() {
+ if allowedip.Bits() == 0 {
foundDefault6 = true
}
- route.NextHop = net.IPv6zero
+ route.NextHop = netip.IPv6Unspecified()
}
- routes = append(routes, route)
+ routes[route] = true
}
}
- err := luid.SetIPAddressesForFamily(family, addresses)
- if err == windows.ERROR_OBJECT_ALREADY_EXISTS {
- cleanupAddressesOnDisconnectedInterfaces(family, addresses)
- err = luid.SetIPAddressesForFamily(family, addresses)
- }
- if err != nil {
- return err
+ deduplicatedRoutes := make([]*winipcfg.RouteData, 0, len(routes))
+ for route := range routes {
+ r := route
+ deduplicatedRoutes = append(deduplicatedRoutes, &r)
}
- deduplicatedRoutes := make([]*winipcfg.RouteData, 0, len(routes))
- sort.Slice(routes, func(i, j int) bool {
- if routes[i].Metric != routes[j].Metric {
- return routes[i].Metric < routes[j].Metric
- }
- if c := bytes.Compare(routes[i].NextHop, routes[j].NextHop); c != 0 {
- return c < 0
+ if !conf.Interface.TableOff {
+ err = luid.SetRoutesForFamily(family, deduplicatedRoutes)
+ if err == windows.ERROR_NOT_FOUND && retryOnFailure {
+ goto startOver
+ } else if err != nil {
+ return fmt.Errorf("unable to set routes: %w", err)
}
- if c := bytes.Compare(routes[i].Destination.IP, routes[j].Destination.IP); c != 0 {
- return c < 0
- }
- if c := bytes.Compare(routes[i].Destination.Mask, routes[j].Destination.Mask); c != 0 {
- return c < 0
- }
- return false
- })
- for i := 0; i < len(routes); i++ {
- if i > 0 && routes[i].Metric == routes[i-1].Metric &&
- bytes.Equal(routes[i].NextHop, routes[i-1].NextHop) &&
- bytes.Equal(routes[i].Destination.IP, routes[i-1].Destination.IP) &&
- bytes.Equal(routes[i].Destination.Mask, routes[i-1].Destination.Mask) {
- continue
- }
- deduplicatedRoutes = append(deduplicatedRoutes, &routes[i])
}
- err = luid.SetRoutesForFamily(family, deduplicatedRoutes)
- if err != nil {
- return err
+ err = luid.SetIPAddressesForFamily(family, conf.Interface.Addresses)
+ if err == windows.ERROR_OBJECT_ALREADY_EXISTS {
+ cleanupAddressesOnDisconnectedInterfaces(family, conf.Interface.Addresses)
+ err = luid.SetIPAddressesForFamily(family, conf.Interface.Addresses)
+ }
+ if err == windows.ERROR_NOT_FOUND && retryOnFailure {
+ goto startOver
+ } else if err != nil {
+ return fmt.Errorf("unable to set ips: %w", err)
}
- ipif, err := luid.IPInterface(family)
+ var ipif *winipcfg.MibIPInterfaceRow
+ ipif, err = luid.IPInterface(family)
if err != nil {
return err
}
+ ipif.RouterDiscoveryBehavior = winipcfg.RouterDiscoveryDisabled
+ ipif.DadTransmits = 0
+ ipif.ManagedAddressConfigurationSupported = false
+ ipif.OtherStatefulConfigurationSupported = false
if conf.Interface.MTU > 0 {
ipif.NLMTU = uint32(conf.Interface.MTU)
- tun.ForceMTU(int(ipif.NLMTU))
}
- if family == windows.AF_INET {
- if foundDefault4 {
- ipif.UseAutomaticMetric = false
- ipif.Metric = 0
- }
- } else if family == windows.AF_INET6 {
- if foundDefault6 {
- ipif.UseAutomaticMetric = false
- ipif.Metric = 0
- }
- ipif.DadTransmits = 0
- ipif.RouterDiscoveryBehavior = winipcfg.RouterDiscoveryDisabled
+ if (family == windows.AF_INET && foundDefault4) || (family == windows.AF_INET6 && foundDefault6) {
+ ipif.UseAutomaticMetric = false
+ ipif.Metric = 0
}
err = ipif.Set()
- if err != nil {
- return err
+ if err == windows.ERROR_NOT_FOUND && retryOnFailure {
+ goto startOver
+ } else if err != nil {
+ return fmt.Errorf("unable to set metric and MTU: %w", err)
}
- return luid.SetDNS(family, conf.Interface.DNS, conf.Interface.DNSSearch)
+ err = luid.SetDNS(family, conf.Interface.DNS, conf.Interface.DNSSearch)
+ if err == windows.ERROR_NOT_FOUND && retryOnFailure {
+ goto startOver
+ } else if err != nil {
+ return fmt.Errorf("unable to set DNS: %w", err)
+ }
+ return nil
}
-func enableFirewall(conf *conf.Config, tun *tun.NativeTun) error {
+func enableFirewall(conf *conf.Config, luid winipcfg.LUID) error {
doNotRestrict := true
- if len(conf.Peers) == 1 {
- nextallowedip:
+ if len(conf.Peers) == 1 && !conf.Interface.TableOff {
for _, allowedip := range conf.Peers[0].AllowedIPs {
- if allowedip.Cidr == 0 {
- for _, b := range allowedip.IP {
- if b != 0 {
- continue nextallowedip
- }
- }
+ if allowedip.Bits() == 0 && allowedip == allowedip.Masked() {
doNotRestrict = false
break
}
}
}
log.Println("Enabling firewall rules")
- return firewall.EnableFirewall(tun.LUID(), doNotRestrict, conf.Interface.DNS)
+ return firewall.EnableFirewall(uint64(luid), doNotRestrict, conf.Interface.DNS)
}
diff --git a/tunnel/deterministicguid.go b/tunnel/deterministicguid.go
index 455deaeb..405d33a3 100644
--- a/tunnel/deterministicguid.go
+++ b/tunnel/deterministicguid.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package tunnel
@@ -18,8 +18,10 @@ import (
"golang.zx2c4.com/wireguard/windows/conf"
)
-const deterministicGUIDLabel = "Deterministic WireGuard Windows GUID v1 jason@zx2c4.com"
-const fixedGUIDLabel = "Fixed WireGuard Windows GUID v1 jason@zx2c4.com"
+const (
+ deterministicGUIDLabel = "Deterministic WireGuard Windows GUID v1 jason@zx2c4.com"
+ fixedGUIDLabel = "Fixed WireGuard Windows GUID v1 jason@zx2c4.com"
+)
// Escape hatch for external consumers, not us.
var UseFixedGUIDInsteadOfDeterministic = false
@@ -80,13 +82,13 @@ func deterministicGUID(c *conf.Config) *windows.GUID {
b2Number(len(peer.AllowedIPs))
sortedAllowedIPs := peer.AllowedIPs
sort.Slice(sortedAllowedIPs, func(i, j int) bool {
- if bi, bj := sortedAllowedIPs[i].Bits(), sortedAllowedIPs[j].Bits(); bi != bj {
+ if bi, bj := sortedAllowedIPs[i].Addr().BitLen(), sortedAllowedIPs[j].Addr().BitLen(); bi != bj {
return bi < bj
}
- if sortedAllowedIPs[i].Cidr != sortedAllowedIPs[j].Cidr {
- return sortedAllowedIPs[i].Cidr < sortedAllowedIPs[j].Cidr
+ if sortedAllowedIPs[i].Bits() != sortedAllowedIPs[j].Bits() {
+ return sortedAllowedIPs[i].Bits() < sortedAllowedIPs[j].Bits()
}
- return bytes.Compare(sortedAllowedIPs[i].IP[:], sortedAllowedIPs[j].IP[:]) < 0
+ return sortedAllowedIPs[i].Addr().Compare(sortedAllowedIPs[j].Addr()) < 0
})
for _, allowedip := range sortedAllowedIPs {
b2String(allowedip.String())
diff --git a/tunnel/firewall/blocker.go b/tunnel/firewall/blocker.go
index 2cb2c7f2..8a4967ba 100644
--- a/tunnel/firewall/blocker.go
+++ b/tunnel/firewall/blocker.go
@@ -1,13 +1,13 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package firewall
import (
"errors"
- "net"
+ "net/netip"
"unsafe"
"golang.org/x/sys/windows"
@@ -101,7 +101,7 @@ func registerBaseObjects(session uintptr) (*baseObjects, error) {
return bo, nil
}
-func EnableFirewall(luid uint64, doNotRestrict bool, restrictToDNSServers []net.IP) error {
+func EnableFirewall(luid uint64, doNotRestrict bool, restrictToDNSServers []netip.Addr) error {
if wfpSession != 0 {
return errors.New("The firewall has already been enabled")
}
diff --git a/tunnel/firewall/helpers.go b/tunnel/firewall/helpers.go
index e3e4eac6..46e43aa5 100644
--- a/tunnel/firewall/helpers.go
+++ b/tunnel/firewall/helpers.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package firewall
diff --git a/tunnel/firewall/mksyscall.go b/tunnel/firewall/mksyscall.go
index d5ff98aa..fc108007 100644
--- a/tunnel/firewall/mksyscall.go
+++ b/tunnel/firewall/mksyscall.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package firewall
diff --git a/tunnel/firewall/rules.go b/tunnel/firewall/rules.go
index c4488a31..41632f98 100644
--- a/tunnel/firewall/rules.go
+++ b/tunnel/firewall/rules.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package firewall
@@ -8,7 +8,7 @@ package firewall
import (
"encoding/binary"
"errors"
- "net"
+ "net/netip"
"runtime"
"unsafe"
@@ -582,7 +582,6 @@ func permitDHCPIPv6(session uintptr, baseObjects *baseObjects, weight uint8) err
}
func permitNdp(session uintptr, baseObjects *baseObjects, weight uint8) error {
-
/* TODO: actually handle the hop limit somehow! The rules should vaguely be:
* - icmpv6 133: must be outgoing, dst must be FF02::2/128, hop limit must be 255
* - icmpv6 134: must be incoming, src must be FE80::/10, hop limit must be 255
@@ -985,7 +984,7 @@ func blockAll(session uintptr, baseObjects *baseObjects, weight uint8) error {
}
// Block all DNS traffic except towards specified DNS servers.
-func blockDNS(except []net.IP, session uintptr, baseObjects *baseObjects, weightAllow uint8, weightDeny uint8) error {
+func blockDNS(except []netip.Addr, session uintptr, baseObjects *baseObjects, weightAllow, weightDeny uint8) error {
if weightDeny >= weightAllow {
return errors.New("The allow weight must be greater than the deny weight")
}
@@ -1106,8 +1105,7 @@ func blockDNS(except []net.IP, session uintptr, baseObjects *baseObjects, weight
allowConditionsV4 := make([]wtFwpmFilterCondition0, 0, len(denyConditions)+len(except))
allowConditionsV4 = append(allowConditionsV4, denyConditions...)
for _, ip := range except {
- ip4 := ip.To4()
- if ip4 == nil {
+ if !ip.Is4() {
continue
}
allowConditionsV4 = append(allowConditionsV4, wtFwpmFilterCondition0{
@@ -1115,7 +1113,7 @@ func blockDNS(except []net.IP, session uintptr, baseObjects *baseObjects, weight
matchType: cFWP_MATCH_EQUAL,
conditionValue: wtFwpConditionValue0{
_type: cFWP_UINT32,
- value: uintptr(binary.BigEndian.Uint32(ip4)),
+ value: uintptr(binary.BigEndian.Uint32(ip.AsSlice())),
},
})
}
@@ -1124,11 +1122,10 @@ func blockDNS(except []net.IP, session uintptr, baseObjects *baseObjects, weight
allowConditionsV6 := make([]wtFwpmFilterCondition0, 0, len(denyConditions)+len(except))
allowConditionsV6 = append(allowConditionsV6, denyConditions...)
for _, ip := range except {
- if ip.To4() != nil {
+ if !ip.Is6() {
continue
}
- var address wtFwpByteArray16
- copy(address.byteArray16[:], ip)
+ address := wtFwpByteArray16{byteArray16: ip.As16()}
allowConditionsV6 = append(allowConditionsV6, wtFwpmFilterCondition0{
fieldKey: cFWPM_CONDITION_IP_REMOTE_ADDRESS,
matchType: cFWP_MATCH_EQUAL,
diff --git a/tunnel/firewall/syscall_windows.go b/tunnel/firewall/syscall_windows.go
index 661527d9..4d8eea42 100644
--- a/tunnel/firewall/syscall_windows.go
+++ b/tunnel/firewall/syscall_windows.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package firewall
diff --git a/tunnel/firewall/types_windows.go b/tunnel/firewall/types_windows.go
index 075daae4..54e2aad7 100644
--- a/tunnel/firewall/types_windows.go
+++ b/tunnel/firewall/types_windows.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package firewall
@@ -148,8 +148,10 @@ var cFWPM_CONDITION_IP_LOCAL_ADDRESS = windows.GUID{
Data4: [8]byte{0xbf, 0xe3, 0xff, 0xd8, 0xf5, 0xa0, 0x89, 0x57},
}
-var cFWPM_CONDITION_ICMP_TYPE = cFWPM_CONDITION_IP_LOCAL_PORT
-var cFWPM_CONDITION_ICMP_CODE = cFWPM_CONDITION_IP_REMOTE_PORT
+var (
+ cFWPM_CONDITION_ICMP_TYPE = cFWPM_CONDITION_IP_LOCAL_PORT
+ cFWPM_CONDITION_ICMP_CODE = cFWPM_CONDITION_IP_REMOTE_PORT
+)
// 7bc43cbf-37ba-45f1-b74a-82ff518eeb10
var cFWPM_CONDITION_L2_FLAGS = windows.GUID{
diff --git a/tunnel/firewall/types_windows_32.go b/tunnel/firewall/types_windows_32.go
index 83aced6e..29ae553a 100644
--- a/tunnel/firewall/types_windows_32.go
+++ b/tunnel/firewall/types_windows_32.go
@@ -1,8 +1,8 @@
-// +build 386 arm
+//go:build 386 || arm
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package firewall
diff --git a/tunnel/firewall/types_windows_64.go b/tunnel/firewall/types_windows_64.go
index 6e60aa5b..a476a745 100644
--- a/tunnel/firewall/types_windows_64.go
+++ b/tunnel/firewall/types_windows_64.go
@@ -1,8 +1,8 @@
-// +build amd64 arm64
+//go:build amd64 || arm64
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package firewall
diff --git a/tunnel/firewall/types_windows_test.go b/tunnel/firewall/types_windows_test.go
index 683e52ea..afa1988f 100644
--- a/tunnel/firewall/types_windows_test.go
+++ b/tunnel/firewall/types_windows_test.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package firewall
@@ -11,7 +11,6 @@ import (
)
func TestWtFwpByteBlobSize(t *testing.T) {
-
const actualWtFwpByteBlobSize = unsafe.Sizeof(wtFwpByteBlob{})
if actualWtFwpByteBlobSize != wtFwpByteBlob_Size {
@@ -21,7 +20,6 @@ func TestWtFwpByteBlobSize(t *testing.T) {
}
func TestWtFwpByteBlobOffsets(t *testing.T) {
-
s := wtFwpByteBlob{}
sp := uintptr(unsafe.Pointer(&s))
@@ -34,7 +32,6 @@ func TestWtFwpByteBlobOffsets(t *testing.T) {
}
func TestWtFwpmAction0Size(t *testing.T) {
-
const actualWtFwpmAction0Size = unsafe.Sizeof(wtFwpmAction0{})
if actualWtFwpmAction0Size != wtFwpmAction0_Size {
@@ -44,7 +41,6 @@ func TestWtFwpmAction0Size(t *testing.T) {
}
func TestWtFwpmAction0Offsets(t *testing.T) {
-
s := wtFwpmAction0{}
sp := uintptr(unsafe.Pointer(&s))
@@ -58,7 +54,6 @@ func TestWtFwpmAction0Offsets(t *testing.T) {
}
func TestWtFwpBitmapArray64Size(t *testing.T) {
-
const actualWtFwpBitmapArray64Size = unsafe.Sizeof(wtFwpBitmapArray64{})
if actualWtFwpBitmapArray64Size != wtFwpBitmapArray64_Size {
@@ -68,7 +63,6 @@ func TestWtFwpBitmapArray64Size(t *testing.T) {
}
func TestWtFwpByteArray6Size(t *testing.T) {
-
const actualWtFwpByteArray6Size = unsafe.Sizeof(wtFwpByteArray6{})
if actualWtFwpByteArray6Size != wtFwpByteArray6_Size {
@@ -78,7 +72,6 @@ func TestWtFwpByteArray6Size(t *testing.T) {
}
func TestWtFwpByteArray16Size(t *testing.T) {
-
const actualWtFwpByteArray16Size = unsafe.Sizeof(wtFwpByteArray16{})
if actualWtFwpByteArray16Size != wtFwpByteArray16_Size {
@@ -88,7 +81,6 @@ func TestWtFwpByteArray16Size(t *testing.T) {
}
func TestWtFwpConditionValue0Size(t *testing.T) {
-
const actualWtFwpConditionValue0Size = unsafe.Sizeof(wtFwpConditionValue0{})
if actualWtFwpConditionValue0Size != wtFwpConditionValue0_Size {
@@ -98,7 +90,6 @@ func TestWtFwpConditionValue0Size(t *testing.T) {
}
func TestWtFwpConditionValue0Offsets(t *testing.T) {
-
s := wtFwpConditionValue0{}
sp := uintptr(unsafe.Pointer(&s))
@@ -111,7 +102,6 @@ func TestWtFwpConditionValue0Offsets(t *testing.T) {
}
func TestWtFwpV4AddrAndMaskSize(t *testing.T) {
-
const actualWtFwpV4AddrAndMaskSize = unsafe.Sizeof(wtFwpV4AddrAndMask{})
if actualWtFwpV4AddrAndMaskSize != wtFwpV4AddrAndMask_Size {
@@ -121,7 +111,6 @@ func TestWtFwpV4AddrAndMaskSize(t *testing.T) {
}
func TestWtFwpV4AddrAndMaskOffsets(t *testing.T) {
-
s := wtFwpV4AddrAndMask{}
sp := uintptr(unsafe.Pointer(&s))
@@ -135,7 +124,6 @@ func TestWtFwpV4AddrAndMaskOffsets(t *testing.T) {
}
func TestWtFwpV6AddrAndMaskSize(t *testing.T) {
-
const actualWtFwpV6AddrAndMaskSize = unsafe.Sizeof(wtFwpV6AddrAndMask{})
if actualWtFwpV6AddrAndMaskSize != wtFwpV6AddrAndMask_Size {
@@ -145,7 +133,6 @@ func TestWtFwpV6AddrAndMaskSize(t *testing.T) {
}
func TestWtFwpV6AddrAndMaskOffsets(t *testing.T) {
-
s := wtFwpV6AddrAndMask{}
sp := uintptr(unsafe.Pointer(&s))
@@ -159,7 +146,6 @@ func TestWtFwpV6AddrAndMaskOffsets(t *testing.T) {
}
func TestWtFwpValue0Size(t *testing.T) {
-
const actualWtFwpValue0Size = unsafe.Sizeof(wtFwpValue0{})
if actualWtFwpValue0Size != wtFwpValue0_Size {
@@ -168,7 +154,6 @@ func TestWtFwpValue0Size(t *testing.T) {
}
func TestWtFwpValue0Offsets(t *testing.T) {
-
s := wtFwpValue0{}
sp := uintptr(unsafe.Pointer(&s))
@@ -181,7 +166,6 @@ func TestWtFwpValue0Offsets(t *testing.T) {
}
func TestWtFwpmDisplayData0Size(t *testing.T) {
-
const actualWtFwpmDisplayData0Size = unsafe.Sizeof(wtFwpmDisplayData0{})
if actualWtFwpmDisplayData0Size != wtFwpmDisplayData0_Size {
@@ -191,7 +175,6 @@ func TestWtFwpmDisplayData0Size(t *testing.T) {
}
func TestWtFwpmDisplayData0Offsets(t *testing.T) {
-
s := wtFwpmDisplayData0{}
sp := uintptr(unsafe.Pointer(&s))
@@ -205,7 +188,6 @@ func TestWtFwpmDisplayData0Offsets(t *testing.T) {
}
func TestWtFwpmFilterCondition0Size(t *testing.T) {
-
const actualWtFwpmFilterCondition0Size = unsafe.Sizeof(wtFwpmFilterCondition0{})
if actualWtFwpmFilterCondition0Size != wtFwpmFilterCondition0_Size {
@@ -215,7 +197,6 @@ func TestWtFwpmFilterCondition0Size(t *testing.T) {
}
func TestWtFwpmFilterCondition0Offsets(t *testing.T) {
-
s := wtFwpmFilterCondition0{}
sp := uintptr(unsafe.Pointer(&s))
@@ -237,7 +218,6 @@ func TestWtFwpmFilterCondition0Offsets(t *testing.T) {
}
func TestWtFwpmFilter0Size(t *testing.T) {
-
const actualWtFwpmFilter0Size = unsafe.Sizeof(wtFwpmFilter0{})
if actualWtFwpmFilter0Size != wtFwpmFilter0_Size {
@@ -247,7 +227,6 @@ func TestWtFwpmFilter0Size(t *testing.T) {
}
func TestWtFwpmFilter0Offsets(t *testing.T) {
-
s := wtFwpmFilter0{}
sp := uintptr(unsafe.Pointer(&s))
@@ -364,7 +343,6 @@ func TestWtFwpmFilter0Offsets(t *testing.T) {
}
func TestWtFwpProvider0Size(t *testing.T) {
-
const actualWtFwpProvider0Size = unsafe.Sizeof(wtFwpProvider0{})
if actualWtFwpProvider0Size != wtFwpProvider0_Size {
@@ -374,7 +352,6 @@ func TestWtFwpProvider0Size(t *testing.T) {
}
func TestWtFwpProvider0Offsets(t *testing.T) {
-
s := wtFwpProvider0{}
sp := uintptr(unsafe.Pointer(&s))
@@ -412,7 +389,6 @@ func TestWtFwpProvider0Offsets(t *testing.T) {
}
func TestWtFwpmSession0Size(t *testing.T) {
-
const actualWtFwpmSession0Size = unsafe.Sizeof(wtFwpmSession0{})
if actualWtFwpmSession0Size != wtFwpmSession0_Size {
@@ -422,7 +398,6 @@ func TestWtFwpmSession0Size(t *testing.T) {
}
func TestWtFwpmSession0Offsets(t *testing.T) {
-
s := wtFwpmSession0{}
sp := uintptr(unsafe.Pointer(&s))
@@ -482,7 +457,6 @@ func TestWtFwpmSession0Offsets(t *testing.T) {
}
func TestWtFwpmSublayer0Size(t *testing.T) {
-
const actualWtFwpmSublayer0Size = unsafe.Sizeof(wtFwpmSublayer0{})
if actualWtFwpmSublayer0Size != wtFwpmSublayer0_Size {
@@ -492,7 +466,6 @@ func TestWtFwpmSublayer0Size(t *testing.T) {
}
func TestWtFwpmSublayer0Offsets(t *testing.T) {
-
s := wtFwpmSublayer0{}
sp := uintptr(unsafe.Pointer(&s))
diff --git a/tunnel/interfacewatcher.go b/tunnel/interfacewatcher.go
index e12e5929..a831d06e 100644
--- a/tunnel/interfacewatcher.go
+++ b/tunnel/interfacewatcher.go
@@ -1,20 +1,20 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package tunnel
import (
+ "errors"
+ "fmt"
"log"
"sync"
+ "time"
"golang.org/x/sys/windows"
-
- "golang.zx2c4.com/wireguard/conn"
- "golang.zx2c4.com/wireguard/tun"
-
"golang.zx2c4.com/wireguard/windows/conf"
+ "golang.zx2c4.com/wireguard/windows/driver"
"golang.zx2c4.com/wireguard/windows/services"
"golang.zx2c4.com/wireguard/windows/tunnel/firewall"
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
@@ -24,63 +24,30 @@ type interfaceWatcherError struct {
serviceError services.Error
err error
}
+
type interfaceWatcherEvent struct {
luid winipcfg.LUID
family winipcfg.AddressFamily
}
+
type interfaceWatcher struct {
- errors chan interfaceWatcherError
+ errors chan interfaceWatcherError
+ started chan winipcfg.AddressFamily
- binder conn.BindSocketToInterface
- conf *conf.Config
- tun *tun.NativeTun
+ conf *conf.Config
+ adapter *driver.Adapter
+ luid winipcfg.LUID
setupMutex sync.Mutex
interfaceChangeCallback winipcfg.ChangeCallback
changeCallbacks4 []winipcfg.ChangeCallback
changeCallbacks6 []winipcfg.ChangeCallback
storedEvents []interfaceWatcherEvent
-}
-
-func hasDefaultRoute(family winipcfg.AddressFamily, peers []conf.Peer) bool {
- var (
- foundV401 bool
- foundV41281 bool
- foundV600001 bool
- foundV680001 bool
- foundV400 bool
- foundV600 bool
- v40 = [4]byte{}
- v60 = [16]byte{}
- v48 = [4]byte{0x80}
- v68 = [16]byte{0x80}
- )
- for _, peer := range peers {
- for _, allowedip := range peer.AllowedIPs {
- if allowedip.Cidr == 1 && len(allowedip.IP) == 16 && allowedip.IP.Equal(v60[:]) {
- foundV600001 = true
- } else if allowedip.Cidr == 1 && len(allowedip.IP) == 16 && allowedip.IP.Equal(v68[:]) {
- foundV680001 = true
- } else if allowedip.Cidr == 1 && len(allowedip.IP) == 4 && allowedip.IP.Equal(v40[:]) {
- foundV401 = true
- } else if allowedip.Cidr == 1 && len(allowedip.IP) == 4 && allowedip.IP.Equal(v48[:]) {
- foundV41281 = true
- } else if allowedip.Cidr == 0 && len(allowedip.IP) == 16 && allowedip.IP.Equal(v60[:]) {
- foundV600 = true
- } else if allowedip.Cidr == 0 && len(allowedip.IP) == 4 && allowedip.IP.Equal(v40[:]) {
- foundV400 = true
- }
- }
- }
- if family == windows.AF_INET {
- return foundV400 || (foundV401 && foundV41281)
- } else if family == windows.AF_INET6 {
- return foundV600 || (foundV600001 && foundV680001)
- }
- return false
+ watchdog *time.Timer
}
func (iw *interfaceWatcher) setup(family winipcfg.AddressFamily) {
+ iw.watchdog.Stop()
var changeCallbacks *[]winipcfg.ChangeCallback
var ipversion string
if family == windows.AF_INET {
@@ -100,25 +67,35 @@ func (iw *interfaceWatcher) setup(family winipcfg.AddressFamily) {
}
var err error
- log.Printf("Monitoring default %s routes", ipversion)
- *changeCallbacks, err = monitorDefaultRoutes(family, iw.binder, iw.conf.Interface.MTU == 0, hasDefaultRoute(family, iw.conf.Peers), iw.tun)
- if err != nil {
- iw.errors <- interfaceWatcherError{services.ErrorBindSocketsToDefaultRoutes, err}
- return
+ if iw.conf.Interface.MTU == 0 {
+ log.Printf("Monitoring MTU of default %s routes", ipversion)
+ *changeCallbacks, err = monitorMTU(family, iw.luid)
+ if err != nil {
+ iw.errors <- interfaceWatcherError{services.ErrorMonitorMTUChanges, err}
+ return
+ }
}
log.Printf("Setting device %s addresses", ipversion)
- err = configureInterface(family, iw.conf, iw.tun)
+ err = configureInterface(family, iw.conf, iw.luid)
if err != nil {
iw.errors <- interfaceWatcherError{services.ErrorSetNetConfig, err}
return
}
+ evaluateDynamicPitfalls(family, iw.conf, iw.luid)
+
+ iw.started <- family
}
func watchInterface() (*interfaceWatcher, error) {
iw := &interfaceWatcher{
- errors: make(chan interfaceWatcherError, 2),
+ errors: make(chan interfaceWatcherError, 2),
+ started: make(chan winipcfg.AddressFamily, 4),
}
+ iw.watchdog = time.AfterFunc(time.Duration(1<<63-1), func() {
+ iw.errors <- interfaceWatcherError{services.ErrorCreateNetworkAdapter, errors.New("TCP/IP interface for adapter did not appear after one minute")}
+ })
+ iw.watchdog.Stop()
var err error
iw.interfaceChangeCallback, err = winipcfg.RegisterInterfaceChangeCallback(func(notificationType winipcfg.MibNotificationType, iface *winipcfg.MibIPInterfaceRow) {
iw.setupMutex.Lock()
@@ -127,28 +104,41 @@ func watchInterface() (*interfaceWatcher, error) {
if notificationType != winipcfg.MibAddInstance {
return
}
- if iw.tun == nil {
+ if iw.luid == 0 {
iw.storedEvents = append(iw.storedEvents, interfaceWatcherEvent{iface.InterfaceLUID, iface.Family})
return
}
- if iface.InterfaceLUID != winipcfg.LUID(iw.tun.LUID()) {
+ if iface.InterfaceLUID != iw.luid {
return
}
iw.setup(iface.Family)
+
+ if state, err := iw.adapter.AdapterState(); err == nil && state == driver.AdapterStateDown {
+ log.Println("Reinitializing adapter configuration")
+ err = iw.adapter.SetConfiguration(iw.conf.ToDriverConfiguration())
+ if err != nil {
+ log.Println(fmt.Errorf("%v: %w", services.ErrorDeviceSetConfig, err))
+ }
+ err = iw.adapter.SetAdapterState(driver.AdapterStateUp)
+ if err != nil {
+ log.Println(fmt.Errorf("%v: %w", services.ErrorDeviceBringUp, err))
+ }
+ }
})
if err != nil {
- return nil, err
+ return nil, fmt.Errorf("unable to register interface change callback: %w", err)
}
return iw, nil
}
-func (iw *interfaceWatcher) Configure(binder conn.BindSocketToInterface, conf *conf.Config, tun *tun.NativeTun) {
+func (iw *interfaceWatcher) Configure(adapter *driver.Adapter, conf *conf.Config, luid winipcfg.LUID) {
iw.setupMutex.Lock()
defer iw.setupMutex.Unlock()
+ iw.watchdog.Reset(time.Minute)
- iw.binder, iw.conf, iw.tun = binder, conf, tun
+ iw.adapter, iw.conf, iw.luid = adapter, conf, luid
for _, event := range iw.storedEvents {
- if event.luid == winipcfg.LUID(iw.tun.LUID()) {
+ if event.luid == luid {
iw.setup(event.family)
}
}
@@ -157,10 +147,11 @@ func (iw *interfaceWatcher) Configure(binder conn.BindSocketToInterface, conf *c
func (iw *interfaceWatcher) Destroy() {
iw.setupMutex.Lock()
+ iw.watchdog.Stop()
changeCallbacks4 := iw.changeCallbacks4
changeCallbacks6 := iw.changeCallbacks6
interfaceChangeCallback := iw.interfaceChangeCallback
- tun := iw.tun
+ luid := iw.luid
iw.setupMutex.Unlock()
if interfaceChangeCallback != nil {
@@ -186,10 +177,9 @@ func (iw *interfaceWatcher) Destroy() {
changeCallbacks6 = changeCallbacks6[1:]
}
firewall.DisableFirewall()
- if tun != nil && iw.tun == tun {
+ if luid != 0 && iw.luid == luid {
// It seems that the Windows networking stack doesn't like it when we destroy interfaces that have active
// routes, so to be certain, just remove everything before destroying.
- luid := winipcfg.LUID(tun.LUID())
luid.FlushRoutes(windows.AF_INET)
luid.FlushIPAddresses(windows.AF_INET)
luid.FlushDNS(windows.AF_INET)
diff --git a/tunnel/ipcpermissions.go b/tunnel/ipcpermissions.go
deleted file mode 100644
index 3a676e4b..00000000
--- a/tunnel/ipcpermissions.go
+++ /dev/null
@@ -1,63 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
- */
-
-package tunnel
-
-import (
- "golang.org/x/sys/windows"
-
- "golang.zx2c4.com/wireguard/ipc"
-
- "golang.zx2c4.com/wireguard/windows/conf"
-)
-
-func CopyConfigOwnerToIPCSecurityDescriptor(filename string) error {
- if conf.PathIsEncrypted(filename) {
- return nil
- }
-
- fileSd, err := windows.GetNamedSecurityInfo(filename, windows.SE_FILE_OBJECT, windows.OWNER_SECURITY_INFORMATION)
- if err != nil {
- return err
- }
- fileOwner, _, err := fileSd.Owner()
- if err != nil {
- return err
- }
- if fileOwner.IsWellKnown(windows.WinLocalSystemSid) {
- return nil
- }
- additionalEntries := []windows.EXPLICIT_ACCESS{{
- AccessPermissions: windows.GENERIC_ALL,
- AccessMode: windows.GRANT_ACCESS,
- Trustee: windows.TRUSTEE{
- TrusteeForm: windows.TRUSTEE_IS_SID,
- TrusteeType: windows.TRUSTEE_IS_USER,
- TrusteeValue: windows.TrusteeValueFromSID(fileOwner),
- },
- }}
-
- sd, err := ipc.UAPISecurityDescriptor.ToAbsolute()
- if err != nil {
- return err
- }
- dacl, defaulted, _ := sd.DACL()
-
- newDacl, err := windows.ACLFromEntries(additionalEntries, dacl)
- if err != nil {
- return err
- }
- err = sd.SetDACL(newDacl, true, defaulted)
- if err != nil {
- return err
- }
- sd, err = sd.ToSelfRelative()
- if err != nil {
- return err
- }
- ipc.UAPISecurityDescriptor = sd
-
- return nil
-}
diff --git a/tunnel/defaultroutemonitor.go b/tunnel/mtumonitor.go
index aa0db675..c07823a2 100644
--- a/tunnel/defaultroutemonitor.go
+++ b/tunnel/mtumonitor.go
@@ -1,30 +1,23 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package tunnel
import (
- "log"
- "sync"
- "time"
-
"golang.org/x/sys/windows"
-
- "golang.zx2c4.com/wireguard/conn"
- "golang.zx2c4.com/wireguard/tun"
"golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
)
-func bindSocketRoute(family winipcfg.AddressFamily, binder conn.BindSocketToInterface, ourLUID winipcfg.LUID, lastLUID *winipcfg.LUID, lastIndex *uint32, blackholeWhenLoop bool) error {
+func findDefaultLUID(family winipcfg.AddressFamily, ourLUID winipcfg.LUID, lastLUID *winipcfg.LUID, lastIndex *uint32) error {
r, err := winipcfg.GetIPForwardTable2(family)
if err != nil {
return err
}
lowestMetric := ^uint32(0)
- index := uint32(0) // Zero is "unspecified", which for IP_UNICAST_IF resets the value, which is what we want.
- luid := winipcfg.LUID(0) // Hopefully luid zero is unspecified, but hard to find docs saying so.
+ index := uint32(0)
+ luid := winipcfg.LUID(0)
for i := range r {
if r[i].DestinationPrefix.PrefixLength != 0 || r[i].InterfaceLUID == ourLUID {
continue
@@ -50,36 +43,24 @@ func bindSocketRoute(family winipcfg.AddressFamily, binder conn.BindSocketToInte
}
*lastLUID = luid
*lastIndex = index
- blackhole := blackholeWhenLoop && index == 0
- if family == windows.AF_INET {
- log.Printf("Binding v4 socket to interface %d (blackhole=%v)", index, blackhole)
- return binder.BindSocketToInterface4(index, blackhole)
- } else if family == windows.AF_INET6 {
- log.Printf("Binding v6 socket to interface %d (blackhole=%v)", index, blackhole)
- return binder.BindSocketToInterface6(index, blackhole)
- }
return nil
}
-func monitorDefaultRoutes(family winipcfg.AddressFamily, binder conn.BindSocketToInterface, autoMTU bool, blackholeWhenLoop bool, tun *tun.NativeTun) ([]winipcfg.ChangeCallback, error) {
+func monitorMTU(family winipcfg.AddressFamily, ourLUID winipcfg.LUID) ([]winipcfg.ChangeCallback, error) {
var minMTU uint32
if family == windows.AF_INET {
minMTU = 576
} else if family == windows.AF_INET6 {
minMTU = 1280
}
- ourLUID := winipcfg.LUID(tun.LUID())
lastLUID := winipcfg.LUID(0)
lastIndex := ^uint32(0)
lastMTU := uint32(0)
doIt := func() error {
- err := bindSocketRoute(family, binder, ourLUID, &lastLUID, &lastIndex, blackholeWhenLoop)
+ err := findDefaultLUID(family, ourLUID, &lastLUID, &lastIndex)
if err != nil {
return err
}
- if !autoMTU {
- return nil
- }
mtu := uint32(0)
if lastLUID != 0 {
iface, err := lastLUID.Interface()
@@ -103,7 +84,6 @@ func monitorDefaultRoutes(family winipcfg.AddressFamily, binder conn.BindSocketT
if err != nil {
return err
}
- tun.ForceMTU(int(iface.NLMTU)) // TODO: having one MTU for both v4 and v6 kind of breaks the windows model, so right now this just gets the second one which is... bad.
lastMTU = mtu
}
return nil
@@ -112,32 +92,9 @@ func monitorDefaultRoutes(family winipcfg.AddressFamily, binder conn.BindSocketT
if err != nil {
return nil, err
}
-
- firstBurst := time.Time{}
- burstMutex := sync.Mutex{}
- burstTimer := time.AfterFunc(time.Hour*200, func() {
- burstMutex.Lock()
- firstBurst = time.Time{}
- doIt()
- burstMutex.Unlock()
- })
- burstTimer.Stop()
- bump := func() {
- burstMutex.Lock()
- burstTimer.Reset(time.Millisecond * 150)
- if firstBurst.IsZero() {
- firstBurst = time.Now()
- } else if time.Since(firstBurst) > time.Second*2 {
- firstBurst = time.Time{}
- burstTimer.Stop()
- doIt()
- }
- burstMutex.Unlock()
- }
-
cbr, err := winipcfg.RegisterRouteChangeCallback(func(notificationType winipcfg.MibNotificationType, route *winipcfg.MibIPforwardRow2) {
if route != nil && route.DestinationPrefix.PrefixLength == 0 {
- bump()
+ doIt()
}
})
if err != nil {
@@ -145,7 +102,7 @@ func monitorDefaultRoutes(family winipcfg.AddressFamily, binder conn.BindSocketT
}
cbi, err := winipcfg.RegisterInterfaceChangeCallback(func(notificationType winipcfg.MibNotificationType, iface *winipcfg.MibIPInterfaceRow) {
if notificationType == winipcfg.MibParameterNotification {
- bump()
+ doIt()
}
})
if err != nil {
diff --git a/tunnel/pitfalls.go b/tunnel/pitfalls.go
new file mode 100644
index 00000000..fdef6eb2
--- /dev/null
+++ b/tunnel/pitfalls.go
@@ -0,0 +1,177 @@
+/* SPDX-License-Identifier: MIT
+ *
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
+ */
+
+package tunnel
+
+import (
+ "log"
+ "net/netip"
+ "strings"
+ "unsafe"
+
+ "golang.org/x/sys/windows"
+ "golang.org/x/sys/windows/svc/mgr"
+ "golang.zx2c4.com/wireguard/windows/conf"
+ "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
+)
+
+func evaluateStaticPitfalls() {
+ go func() {
+ pitfallDnsCacheDisabled()
+ pitfallVirtioNetworkDriver()
+ }()
+}
+
+func evaluateDynamicPitfalls(family winipcfg.AddressFamily, conf *conf.Config, luid winipcfg.LUID) {
+ go func() {
+ pitfallWeakHostSend(family, conf, luid)
+ }()
+}
+
+func pitfallDnsCacheDisabled() {
+ scm, err := mgr.Connect()
+ if err != nil {
+ return
+ }
+ defer scm.Disconnect()
+ svc := mgr.Service{Name: "dnscache"}
+ svc.Handle, err = windows.OpenService(scm.Handle, windows.StringToUTF16Ptr(svc.Name), windows.SERVICE_QUERY_CONFIG)
+ if err != nil {
+ return
+ }
+ defer svc.Close()
+ cfg, err := svc.Config()
+ if err != nil {
+ return
+ }
+ if cfg.StartType != mgr.StartDisabled {
+ return
+ }
+
+ log.Printf("Warning: the %q (dnscache) service is disabled; please re-enable it", cfg.DisplayName)
+}
+
+func pitfallVirtioNetworkDriver() {
+ var modules []windows.RTL_PROCESS_MODULE_INFORMATION
+ for bufferSize := uint32(128 * 1024); ; {
+ moduleBuffer := make([]byte, bufferSize)
+ err := windows.NtQuerySystemInformation(windows.SystemModuleInformation, unsafe.Pointer(&moduleBuffer[0]), bufferSize, &bufferSize)
+ switch err {
+ case windows.STATUS_INFO_LENGTH_MISMATCH:
+ continue
+ case nil:
+ break
+ default:
+ return
+ }
+ mods := (*windows.RTL_PROCESS_MODULES)(unsafe.Pointer(&moduleBuffer[0]))
+ modules = unsafe.Slice(&mods.Modules[0], mods.NumberOfModules)
+ break
+ }
+ for i := range modules {
+ if !strings.EqualFold(windows.ByteSliceToString(modules[i].FullPathName[modules[i].OffsetToFileName:]), "netkvm.sys") {
+ continue
+ }
+ driverPath := `\\?\GLOBALROOT` + windows.ByteSliceToString(modules[i].FullPathName[:])
+ var zero windows.Handle
+ infoSize, err := windows.GetFileVersionInfoSize(driverPath, &zero)
+ if err != nil {
+ return
+ }
+ versionInfo := make([]byte, infoSize)
+ err = windows.GetFileVersionInfo(driverPath, 0, infoSize, unsafe.Pointer(&versionInfo[0]))
+ if err != nil {
+ return
+ }
+ var fixedInfo *windows.VS_FIXEDFILEINFO
+ fixedInfoLen := uint32(unsafe.Sizeof(*fixedInfo))
+ err = windows.VerQueryValue(unsafe.Pointer(&versionInfo[0]), `\`, unsafe.Pointer(&fixedInfo), &fixedInfoLen)
+ if err != nil {
+ return
+ }
+ const minimumPlausibleVersion = 40 << 48
+ const minimumGoodVersion = (100 << 48) | (85 << 32) | (104 << 16) | (20800 << 0)
+ version := (uint64(fixedInfo.FileVersionMS) << 32) | uint64(fixedInfo.FileVersionLS)
+ if version >= minimumGoodVersion || version < minimumPlausibleVersion {
+ return
+ }
+ log.Println("Warning: the VirtIO network driver (NetKVM) is out of date and may cause known problems; please update to v100.85.104.20800 or later")
+ return
+ }
+}
+
+func pitfallWeakHostSend(family winipcfg.AddressFamily, conf *conf.Config, ourLUID winipcfg.LUID) {
+ routingTable, err := winipcfg.GetIPForwardTable2(family)
+ if err != nil {
+ return
+ }
+ type endpointRoute struct {
+ addr netip.Addr
+ name string
+ lowestMetric uint32
+ highestCIDR uint8
+ weakHostSend bool
+ finalIsOurs bool
+ }
+ endpoints := make([]endpointRoute, 0, len(conf.Peers))
+ for _, peer := range conf.Peers {
+ addr, err := netip.ParseAddr(peer.Endpoint.Host)
+ if err != nil || (addr.Is4() && family != windows.AF_INET) || (addr.Is6() && family != windows.AF_INET6) {
+ continue
+ }
+ endpoints = append(endpoints, endpointRoute{addr: addr, lowestMetric: ^uint32(0)})
+ }
+ for i := range routingTable {
+ var (
+ ifrow *winipcfg.MibIfRow2
+ ifacerow *winipcfg.MibIPInterfaceRow
+ metric uint32
+ )
+ for j := range endpoints {
+ r, e := &routingTable[i], &endpoints[j]
+ if r.DestinationPrefix.PrefixLength < e.highestCIDR {
+ continue
+ }
+ if !r.DestinationPrefix.Prefix().Contains(e.addr) {
+ continue
+ }
+ if ifrow == nil {
+ ifrow, err = r.InterfaceLUID.Interface()
+ if err != nil {
+ continue
+ }
+ }
+ if ifrow.OperStatus != winipcfg.IfOperStatusUp {
+ continue
+ }
+ if ifacerow == nil {
+ ifacerow, err = r.InterfaceLUID.IPInterface(family)
+ if err != nil {
+ continue
+ }
+ metric = r.Metric + ifacerow.Metric
+ }
+ if r.DestinationPrefix.PrefixLength == e.highestCIDR && metric > e.lowestMetric {
+ continue
+ }
+ e.lowestMetric = metric
+ e.highestCIDR = r.DestinationPrefix.PrefixLength
+ e.finalIsOurs = r.InterfaceLUID == ourLUID
+ if !e.finalIsOurs {
+ e.name = ifrow.Alias()
+ e.weakHostSend = ifacerow.ForwardingEnabled || ifacerow.WeakHostSend
+ }
+ }
+ }
+ problematicInterfaces := make(map[string]bool, len(endpoints))
+ for _, e := range endpoints {
+ if e.weakHostSend && e.finalIsOurs {
+ problematicInterfaces[e.name] = true
+ }
+ }
+ for iface := range problematicInterfaces {
+ log.Printf("Warning: the %q interface has Forwarding/WeakHostSend enabled, which will cause routing loops", iface)
+ }
+}
diff --git a/tunnel/scriptrunner.go b/tunnel/scriptrunner.go
index 450d8e21..eb97d98d 100644
--- a/tunnel/scriptrunner.go
+++ b/tunnel/scriptrunner.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package tunnel
diff --git a/tunnel/service.go b/tunnel/service.go
index 63cd243f..a56ed1f3 100644
--- a/tunnel/service.go
+++ b/tunnel/service.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package tunnel
@@ -9,7 +9,6 @@ import (
"bytes"
"fmt"
"log"
- "net"
"os"
"runtime"
"time"
@@ -17,16 +16,12 @@ import (
"golang.org/x/sys/windows"
"golang.org/x/sys/windows/svc"
"golang.org/x/sys/windows/svc/mgr"
- "golang.zx2c4.com/wireguard/conn"
- "golang.zx2c4.com/wireguard/device"
- "golang.zx2c4.com/wireguard/ipc"
- "golang.zx2c4.com/wireguard/tun"
-
"golang.zx2c4.com/wireguard/windows/conf"
+ "golang.zx2c4.com/wireguard/windows/driver"
"golang.zx2c4.com/wireguard/windows/elevate"
"golang.zx2c4.com/wireguard/windows/ringlogger"
"golang.zx2c4.com/wireguard/windows/services"
- "golang.zx2c4.com/wireguard/windows/version"
+ "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
)
type tunnelService struct {
@@ -34,12 +29,12 @@ type tunnelService struct {
}
func (service *tunnelService) Execute(args []string, r <-chan svc.ChangeRequest, changes chan<- svc.Status) (svcSpecificEC bool, exitCode uint32) {
- changes <- svc.Status{State: svc.StartPending}
+ serviceState := svc.StartPending
+ changes <- svc.Status{State: serviceState}
- var dev *device.Device
- var uapi net.Listener
var watcher *interfaceWatcher
- var nativeTun *tun.NativeTun
+ var adapter *driver.Adapter
+ var luid winipcfg.LUID
var config *conf.Config
var err error
serviceError := services.ErrorSuccess
@@ -50,7 +45,8 @@ func (service *tunnelService) Execute(args []string, r <-chan svc.ChangeRequest,
if logErr != nil {
log.Println(logErr)
}
- changes <- svc.Status{State: svc.StopPending}
+ serviceState = svc.StopPending
+ changes <- svc.Status{State: serviceState}
stopIt := make(chan bool, 1)
go func() {
@@ -84,60 +80,63 @@ func (service *tunnelService) Execute(args []string, r <-chan svc.ChangeRequest,
}
}()
- if logErr == nil && dev != nil && config != nil {
+ if logErr == nil && adapter != nil && config != nil {
logErr = runScriptCommand(config.Interface.PreDown, config.Name)
}
if watcher != nil {
watcher.Destroy()
}
- if uapi != nil {
- uapi.Close()
- }
- if dev != nil {
- dev.Close()
+ if adapter != nil {
+ adapter.Close()
}
- if logErr == nil && dev != nil && config != nil {
+ if logErr == nil && adapter != nil && config != nil {
_ = runScriptCommand(config.Interface.PostDown, config.Name)
}
stopIt <- true
log.Println("Shutting down")
}()
- err = ringlogger.InitGlobalLogger("TUN")
+ var logFile string
+ logFile, err = conf.LogFile(true)
if err != nil {
serviceError = services.ErrorRingloggerOpen
return
}
-
- config, err = conf.LoadFromPath(service.Path)
+ err = ringlogger.InitGlobalLogger(logFile, "TUN")
if err != nil {
- serviceError = services.ErrorLoadConfiguration
+ serviceError = services.ErrorRingloggerOpen
return
}
- config.DeduplicateNetworkEntries()
- err = CopyConfigOwnerToIPCSecurityDescriptor(service.Path)
+
+ config, err = conf.LoadFromPath(service.Path)
if err != nil {
serviceError = services.ErrorLoadConfiguration
return
}
+ config.DeduplicateNetworkEntries()
log.SetPrefix(fmt.Sprintf("[%s] ", config.Name))
- log.Println("Starting", version.UserAgent())
+ services.PrintStarting()
- if m, err := mgr.Connect(); err == nil {
- if lockStatus, err := m.LockStatus(); err == nil && lockStatus.IsLocked {
- /* If we don't do this, then the Wintun installation will block forever, because
- * installing a Wintun device starts a service too. Apparently at boot time, Windows
- * 8.1 locks the SCM for each service start, creating a deadlock if we don't announce
- * that we're running before starting additional services.
- */
- log.Printf("SCM locked for %v by %s, marking service as started", lockStatus.Age, lockStatus.Owner)
- changes <- svc.Status{State: svc.Running}
+ if services.StartedAtBoot() {
+ if m, err := mgr.Connect(); err == nil {
+ if lockStatus, err := m.LockStatus(); err == nil && lockStatus.IsLocked {
+ /* If we don't do this, then the driver installation will block forever, because
+ * installing a network adapter starts the driver service too. Apparently at boot time,
+ * Windows 8.1 locks the SCM for each service start, creating a deadlock if we don't
+ * announce that we're running before starting additional services.
+ */
+ log.Printf("SCM locked for %v by %s, marking service as started", lockStatus.Age, lockStatus.Owner)
+ serviceState = svc.Running
+ changes <- svc.Status{State: serviceState}
+ }
+ m.Disconnect()
}
- m.Disconnect()
}
+ evaluateStaticPitfalls()
+
log.Println("Watching network interfaces")
watcher, err = watchInterface()
if err != nil {
@@ -146,34 +145,40 @@ func (service *tunnelService) Execute(args []string, r <-chan svc.ChangeRequest,
}
log.Println("Resolving DNS names")
- uapiConf, err := config.ToUAPI()
+ err = config.ResolveEndpoints()
if err != nil {
serviceError = services.ErrorDNSLookup
return
}
- log.Println("Creating Wintun interface")
- var wintun tun.Device
- for i := 0; i < 5; i++ {
+ log.Println("Creating network adapter")
+ for i := 0; i < 15; i++ {
if i > 0 {
time.Sleep(time.Second)
- log.Printf("Retrying Wintun creation after failure because system just booted (T+%v): %v", windows.DurationSinceBoot(), err)
+ log.Printf("Retrying adapter creation after failure because system just booted (T+%v): %v", windows.DurationSinceBoot(), err)
}
- wintun, err = tun.CreateTUNWithRequestedGUID(config.Name, deterministicGUID(config), 0)
- if err == nil || windows.DurationSinceBoot() > time.Minute*4 {
+ adapter, err = driver.CreateAdapter(config.Name, "WireGuard", deterministicGUID(config))
+ if err == nil || !services.StartedAtBoot() {
break
}
}
if err != nil {
- serviceError = services.ErrorCreateWintun
+ err = fmt.Errorf("Error creating adapter: %w", err)
+ serviceError = services.ErrorCreateNetworkAdapter
return
}
- nativeTun = wintun.(*tun.NativeTun)
- wintunVersion, err := nativeTun.RunningVersion()
+ luid = adapter.LUID()
+ driverVersion, err := driver.RunningVersion()
if err != nil {
- log.Printf("Warning: unable to determine Wintun version: %v", err)
+ log.Printf("Warning: unable to determine driver version: %v", err)
} else {
- log.Printf("Using Wintun/%d.%d", (wintunVersion>>16)&0xffff, wintunVersion&0xffff)
+ log.Printf("Using WireGuardNT/%d.%d", (driverVersion>>16)&0xffff, driverVersion&0xffff)
+ }
+ err = adapter.SetLogging(driver.AdapterLogOn)
+ if err != nil {
+ err = fmt.Errorf("Error enabling adapter logging: %w", err)
+ serviceError = services.ErrorCreateNetworkAdapter
+ return
}
err = runScriptCommand(config.Interface.PreUp, config.Name)
@@ -182,7 +187,7 @@ func (service *tunnelService) Execute(args []string, r <-chan svc.ChangeRequest,
return
}
- err = enableFirewall(config, nativeTun)
+ err = enableFirewall(config, luid)
if err != nil {
serviceError = services.ErrorFirewall
return
@@ -195,37 +200,18 @@ func (service *tunnelService) Execute(args []string, r <-chan svc.ChangeRequest,
return
}
- log.Println("Creating interface instance")
- bind := conn.NewDefaultBind()
- dev = device.NewDevice(wintun, bind, &device.Logger{log.Printf, log.Printf})
-
log.Println("Setting interface configuration")
- uapi, err = ipc.UAPIListen(config.Name)
+ err = adapter.SetConfiguration(config.ToDriverConfiguration())
if err != nil {
- serviceError = services.ErrorUAPIListen
+ serviceError = services.ErrorDeviceSetConfig
return
}
- err = dev.IpcSet(uapiConf)
+ err = adapter.SetAdapterState(driver.AdapterStateUp)
if err != nil {
- serviceError = services.ErrorDeviceSetConfig
+ serviceError = services.ErrorDeviceBringUp
return
}
-
- log.Println("Bringing peers up")
- dev.Up()
-
- watcher.Configure(bind.(conn.BindSocketToInterface), config, nativeTun)
-
- log.Println("Listening for UAPI requests")
- go func() {
- for {
- conn, err := uapi.Accept()
- if err != nil {
- continue
- }
- go dev.IpcHandle(conn)
- }
- }()
+ watcher.Configure(adapter, config, luid)
err = runScriptCommand(config.Interface.PostUp, config.Name)
if err != nil {
@@ -233,9 +219,9 @@ func (service *tunnelService) Execute(args []string, r <-chan svc.ChangeRequest,
return
}
- changes <- svc.Status{State: svc.Running, Accepts: svc.AcceptStop | svc.AcceptShutdown}
- log.Println("Startup complete")
+ changes <- svc.Status{State: serviceState, Accepts: svc.AcceptStop | svc.AcceptShutdown}
+ var started bool
for {
select {
case c := <-r:
@@ -247,8 +233,13 @@ func (service *tunnelService) Execute(args []string, r <-chan svc.ChangeRequest,
default:
log.Printf("Unexpected service control request #%d\n", c)
}
- case <-dev.Wait():
- return
+ case <-watcher.started:
+ if !started {
+ serviceState = svc.Running
+ changes <- svc.Status{State: serviceState, Accepts: svc.AcceptStop | svc.AcceptShutdown}
+ log.Println("Startup complete")
+ started = true
+ }
case e := <-watcher.errors:
serviceError, err = e.serviceError, e.err
return
@@ -261,7 +252,7 @@ func Run(confPath string) error {
if err != nil {
return err
}
- serviceName, err := services.ServiceNameOfTunnel(name)
+ serviceName, err := conf.ServiceNameOfTunnel(name)
if err != nil {
return err
}
diff --git a/tunnel/winipcfg/interface_change_handler.go b/tunnel/winipcfg/interface_change_handler.go
index 4d229e78..af29801a 100644
--- a/tunnel/winipcfg/interface_change_handler.go
+++ b/tunnel/winipcfg/interface_change_handler.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
diff --git a/tunnel/winipcfg/luid.go b/tunnel/winipcfg/luid.go
index 02ba65b4..0c898b89 100644
--- a/tunnel/winipcfg/luid.go
+++ b/tunnel/winipcfg/luid.go
@@ -1,13 +1,13 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
import (
"errors"
- "net"
+ "net/netip"
"strings"
"golang.org/x/sys/windows"
@@ -76,10 +76,10 @@ func LUIDFromIndex(index uint32) (LUID, error) {
// IPAddress method returns MibUnicastIPAddressRow struct that matches to provided 'ip' argument. Corresponds to GetUnicastIpAddressEntry
// (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getunicastipaddressentry)
-func (luid LUID) IPAddress(ip net.IP) (*MibUnicastIPAddressRow, error) {
+func (luid LUID) IPAddress(addr netip.Addr) (*MibUnicastIPAddressRow, error) {
row := &MibUnicastIPAddressRow{InterfaceLUID: luid}
- err := row.Address.SetIP(ip, 0)
+ err := row.Address.SetAddr(addr)
if err != nil {
return nil, err
}
@@ -94,22 +94,24 @@ func (luid LUID) IPAddress(ip net.IP) (*MibUnicastIPAddressRow, error) {
// AddIPAddress method adds new unicast IP address to the interface. Corresponds to CreateUnicastIpAddressEntry function
// (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-createunicastipaddressentry).
-func (luid LUID) AddIPAddress(address net.IPNet) error {
+func (luid LUID) AddIPAddress(address netip.Prefix) error {
row := &MibUnicastIPAddressRow{}
row.Init()
row.InterfaceLUID = luid
- err := row.Address.SetIP(address.IP, 0)
+ row.DadState = DadStatePreferred
+ row.ValidLifetime = 0xffffffff
+ row.PreferredLifetime = 0xffffffff
+ err := row.Address.SetAddr(address.Addr())
if err != nil {
return err
}
- ones, _ := address.Mask.Size()
- row.OnLinkPrefixLength = uint8(ones)
+ row.OnLinkPrefixLength = uint8(address.Bits())
return row.Create()
}
// AddIPAddresses method adds multiple new unicast IP addresses to the interface. Corresponds to CreateUnicastIpAddressEntry function
// (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-createunicastipaddressentry).
-func (luid LUID) AddIPAddresses(addresses []net.IPNet) error {
+func (luid LUID) AddIPAddresses(addresses []netip.Prefix) error {
for i := range addresses {
err := luid.AddIPAddress(addresses[i])
if err != nil {
@@ -120,7 +122,7 @@ func (luid LUID) AddIPAddresses(addresses []net.IPNet) error {
}
// SetIPAddresses method sets new unicast IP addresses to the interface.
-func (luid LUID) SetIPAddresses(addresses []net.IPNet) error {
+func (luid LUID) SetIPAddresses(addresses []netip.Prefix) error {
err := luid.FlushIPAddresses(windows.AF_UNSPEC)
if err != nil {
return err
@@ -129,16 +131,15 @@ func (luid LUID) SetIPAddresses(addresses []net.IPNet) error {
}
// SetIPAddressesForFamily method sets new unicast IP addresses for a specific family to the interface.
-func (luid LUID) SetIPAddressesForFamily(family AddressFamily, addresses []net.IPNet) error {
+func (luid LUID) SetIPAddressesForFamily(family AddressFamily, addresses []netip.Prefix) error {
err := luid.FlushIPAddresses(family)
if err != nil {
return err
}
for i := range addresses {
- asV4 := addresses[i].IP.To4()
- if asV4 == nil && family == windows.AF_INET {
+ if !addresses[i].Addr().Is4() && family == windows.AF_INET {
continue
- } else if asV4 != nil && family == windows.AF_INET6 {
+ } else if !addresses[i].Addr().Is6() && family == windows.AF_INET6 {
continue
}
err := luid.AddIPAddress(addresses[i])
@@ -151,17 +152,16 @@ func (luid LUID) SetIPAddressesForFamily(family AddressFamily, addresses []net.I
// DeleteIPAddress method deletes interface's unicast IP address. Corresponds to DeleteUnicastIpAddressEntry function
// (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-deleteunicastipaddressentry).
-func (luid LUID) DeleteIPAddress(address net.IPNet) error {
+func (luid LUID) DeleteIPAddress(address netip.Prefix) error {
row := &MibUnicastIPAddressRow{}
row.Init()
row.InterfaceLUID = luid
- err := row.Address.SetIP(address.IP, 0)
+ err := row.Address.SetAddr(address.Addr())
if err != nil {
return err
}
// Note: OnLinkPrefixLength member is ignored by DeleteUnicastIpAddressEntry().
- ones, _ := address.Mask.Size()
- row.OnLinkPrefixLength = uint8(ones)
+ row.OnLinkPrefixLength = uint8(address.Bits())
return row.Delete()
}
@@ -185,15 +185,17 @@ func (luid LUID) FlushIPAddresses(family AddressFamily) error {
// Route method returns route determined with the input arguments. Corresponds to GetIpForwardEntry2 function
// (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-getipforwardentry2).
// NOTE: If the corresponding route isn't found, the method will return error.
-func (luid LUID) Route(destination net.IPNet, nextHop net.IP) (*MibIPforwardRow2, error) {
+func (luid LUID) Route(destination netip.Prefix, nextHop netip.Addr) (*MibIPforwardRow2, error) {
row := &MibIPforwardRow2{}
row.Init()
row.InterfaceLUID = luid
- err := row.DestinationPrefix.SetIPNet(destination)
+ row.ValidLifetime = 0xffffffff
+ row.PreferredLifetime = 0xffffffff
+ err := row.DestinationPrefix.SetPrefix(destination)
if err != nil {
return nil, err
}
- err = row.NextHop.SetIP(nextHop, 0)
+ err = row.NextHop.SetAddr(nextHop)
if err != nil {
return nil, err
}
@@ -207,15 +209,15 @@ func (luid LUID) Route(destination net.IPNet, nextHop net.IP) (*MibIPforwardRow2
// AddRoute method adds a route to the interface. Corresponds to CreateIpForwardEntry2 function, with added splitDefault feature.
// (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-createipforwardentry2)
-func (luid LUID) AddRoute(destination net.IPNet, nextHop net.IP, metric uint32) error {
+func (luid LUID) AddRoute(destination netip.Prefix, nextHop netip.Addr, metric uint32) error {
row := &MibIPforwardRow2{}
row.Init()
row.InterfaceLUID = luid
- err := row.DestinationPrefix.SetIPNet(destination)
+ err := row.DestinationPrefix.SetPrefix(destination)
if err != nil {
return err
}
- err = row.NextHop.SetIP(nextHop, 0)
+ err = row.NextHop.SetAddr(nextHop)
if err != nil {
return err
}
@@ -250,10 +252,9 @@ func (luid LUID) SetRoutesForFamily(family AddressFamily, routesData []*RouteDat
return err
}
for _, rd := range routesData {
- asV4 := rd.Destination.IP.To4()
- if asV4 == nil && family == windows.AF_INET {
+ if !rd.Destination.Addr().Is4() && family == windows.AF_INET {
continue
- } else if asV4 != nil && family == windows.AF_INET6 {
+ } else if !rd.Destination.Addr().Is6() && family == windows.AF_INET6 {
continue
}
err := luid.AddRoute(rd.Destination, rd.NextHop, rd.Metric)
@@ -266,15 +267,15 @@ func (luid LUID) SetRoutesForFamily(family AddressFamily, routesData []*RouteDat
// DeleteRoute method deletes a route that matches the criteria. Corresponds to DeleteIpForwardEntry2 function
// (https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/nf-netioapi-deleteipforwardentry2).
-func (luid LUID) DeleteRoute(destination net.IPNet, nextHop net.IP) error {
+func (luid LUID) DeleteRoute(destination netip.Prefix, nextHop netip.Addr) error {
row := &MibIPforwardRow2{}
row.Init()
row.InterfaceLUID = luid
- err := row.DestinationPrefix.SetIPNet(destination)
+ err := row.DestinationPrefix.SetPrefix(destination)
if err != nil {
return err
}
- err = row.NextHop.SetIP(nextHop, 0)
+ err = row.NextHop.SetAddr(nextHop)
if err != nil {
return err
}
@@ -307,17 +308,19 @@ func (luid LUID) FlushRoutes(family AddressFamily) error {
}
// DNS method returns all DNS server addresses associated with the adapter.
-func (luid LUID) DNS() ([]net.IP, error) {
+func (luid LUID) DNS() ([]netip.Addr, error) {
addresses, err := GetAdaptersAddresses(windows.AF_UNSPEC, GAAFlagDefault)
if err != nil {
return nil, err
}
- r := make([]net.IP, 0, len(addresses))
+ r := make([]netip.Addr, 0, len(addresses))
for _, addr := range addresses {
if addr.LUID == luid {
for dns := addr.FirstDNSServerAddress; dns != nil; dns = dns.Next {
if ip := dns.Address.IP(); ip != nil {
- r = append(r, ip)
+ if a, ok := netip.AddrFromSlice(ip); ok {
+ r = append(r, a)
+ }
} else {
return nil, windows.ERROR_INVALID_PARAMETER
}
@@ -328,17 +331,15 @@ func (luid LUID) DNS() ([]net.IP, error) {
}
// SetDNS method clears previous and associates new DNS servers and search domains with the adapter for a specific family.
-func (luid LUID) SetDNS(family AddressFamily, servers []net.IP, domains []string) error {
+func (luid LUID) SetDNS(family AddressFamily, servers []netip.Addr, domains []string) error {
if family != windows.AF_INET && family != windows.AF_INET6 {
return windows.ERROR_PROTOCOL_UNREACHABLE
}
var filteredServers []string
for _, server := range servers {
- if v4 := server.To4(); v4 != nil && family == windows.AF_INET {
- filteredServers = append(filteredServers, v4.String())
- } else if v6 := server.To16(); v4 == nil && v6 != nil && family == windows.AF_INET6 {
- filteredServers = append(filteredServers, v6.String())
+ if (server.Is4() && family == windows.AF_INET) || (server.Is6() && family == windows.AF_INET6) {
+ filteredServers = append(filteredServers, server.String())
}
}
servers16, err := windows.UTF16PtrFromString(strings.Join(filteredServers, ","))
@@ -353,17 +354,17 @@ func (luid LUID) SetDNS(family AddressFamily, servers []net.IP, domains []string
if err != nil {
return err
}
- var maybeV6 uint64
+ dnsInterfaceSettings := &DnsInterfaceSettings{
+ Version: DnsInterfaceSettingsVersion1,
+ Flags: DnsInterfaceSettingsFlagNameserver | DnsInterfaceSettingsFlagSearchList,
+ NameServer: servers16,
+ SearchList: domains16,
+ }
if family == windows.AF_INET6 {
- maybeV6 = disFlagsIPv6
+ dnsInterfaceSettings.Flags |= DnsInterfaceSettingsFlagIPv6
}
// For >= Windows 10 1809
- err = setInterfaceDnsSettings(*guid, &dnsInterfaceSettings{
- Version: disVersion1,
- Flags: disFlagsNameServer | disFlagsSearchList | maybeV6,
- NameServer: servers16,
- SearchList: domains16,
- })
+ err = SetInterfaceDnsSettings(*guid, dnsInterfaceSettings)
if err == nil || !errors.Is(err, windows.ERROR_PROC_NOT_FOUND) {
return err
}
diff --git a/tunnel/winipcfg/mksyscall.go b/tunnel/winipcfg/mksyscall.go
index e9e06676..d62d38df 100644
--- a/tunnel/winipcfg/mksyscall.go
+++ b/tunnel/winipcfg/mksyscall.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
diff --git a/tunnel/winipcfg/netsh.go b/tunnel/winipcfg/netsh.go
index 1f3d12d0..4f8e5b13 100644
--- a/tunnel/winipcfg/netsh.go
+++ b/tunnel/winipcfg/netsh.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
@@ -10,7 +10,7 @@ import (
"errors"
"fmt"
"io"
- "net"
+ "net/netip"
"os/exec"
"path/filepath"
"strings"
@@ -57,7 +57,7 @@ const (
netshCmdTemplateAdd6 = "interface ipv6 add dnsservers name=%d address=%s validate=no"
)
-func (luid LUID) fallbackSetDNSForFamily(family AddressFamily, dnses []net.IP) error {
+func (luid LUID) fallbackSetDNSForFamily(family AddressFamily, dnses []netip.Addr) error {
var templateFlush string
if family == windows.AF_INET {
templateFlush = netshCmdTemplateFlush4
@@ -72,10 +72,10 @@ func (luid LUID) fallbackSetDNSForFamily(family AddressFamily, dnses []net.IP) e
}
cmds = append(cmds, fmt.Sprintf(templateFlush, ipif.InterfaceIndex))
for i := 0; i < len(dnses); i++ {
- if v4 := dnses[i].To4(); v4 != nil && family == windows.AF_INET {
- cmds = append(cmds, fmt.Sprintf(netshCmdTemplateAdd4, ipif.InterfaceIndex, v4.String()))
- } else if v6 := dnses[i].To16(); v4 == nil && v6 != nil && family == windows.AF_INET6 {
- cmds = append(cmds, fmt.Sprintf(netshCmdTemplateAdd6, ipif.InterfaceIndex, v6.String()))
+ if dnses[i].Is4() && family == windows.AF_INET {
+ cmds = append(cmds, fmt.Sprintf(netshCmdTemplateAdd4, ipif.InterfaceIndex, dnses[i].String()))
+ } else if dnses[i].Is6() && family == windows.AF_INET6 {
+ cmds = append(cmds, fmt.Sprintf(netshCmdTemplateAdd6, ipif.InterfaceIndex, dnses[i].String()))
}
}
return runNetsh(cmds)
diff --git a/tunnel/winipcfg/route_change_handler.go b/tunnel/winipcfg/route_change_handler.go
index 75dcf82c..4b78331e 100644
--- a/tunnel/winipcfg/route_change_handler.go
+++ b/tunnel/winipcfg/route_change_handler.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
diff --git a/tunnel/winipcfg/types.go b/tunnel/winipcfg/types.go
index 02f7f788..8e8f4a59 100644
--- a/tunnel/winipcfg/types.go
+++ b/tunnel/winipcfg/types.go
@@ -1,12 +1,15 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
import (
- "net"
+ "encoding/binary"
+ "fmt"
+ "net/netip"
+ "strconv"
"unsafe"
"golang.org/x/sys/windows"
@@ -582,11 +585,15 @@ const (
// RouteData structure describes a route to add
type RouteData struct {
- Destination net.IPNet
- NextHop net.IP
+ Destination netip.Prefix
+ NextHop netip.Addr
Metric uint32
}
+func (routeData *RouteData) String() string {
+ return fmt.Sprintf("%+v", *routeData)
+}
+
// IPAdapterDNSSuffix structure stores a DNS suffix in a linked list of DNS suffixes for a particular adapter.
// https://docs.microsoft.com/en-us/windows/desktop/api/iptypes/ns-iptypes-_ip_adapter_dns_suffix
type IPAdapterDNSSuffix struct {
@@ -679,8 +686,7 @@ func (row *MibIPInterfaceRow) Set() error {
// get method returns all table rows as a Go slice.
func (tab *mibIPInterfaceTable) get() (s []MibIPInterfaceRow) {
- unsafeSlice(unsafe.Pointer(&s), unsafe.Pointer(&tab.table[0]), int(tab.numEntries))
- return
+ return unsafe.Slice(&tab.table[0], tab.numEntries)
}
// free method frees the buffer allocated by the functions that return tables of network interfaces, addresses, and routes.
@@ -717,8 +723,7 @@ func (row *MibIfRow2) get() (ret error) {
// get method returns all table rows as a Go slice.
func (tab *mibIfTable2) get() (s []MibIfRow2) {
- unsafeSlice(unsafe.Pointer(&s), unsafe.Pointer(&tab.table[0]), int(tab.numEntries))
- return
+ return unsafe.Slice(&tab.table[0], tab.numEntries)
}
// free method frees the buffer allocated by the functions that return tables of network interfaces, addresses, and routes.
@@ -734,45 +739,82 @@ type RawSockaddrInet struct {
data [26]byte
}
-// SetIP method sets family, address, and port to the given IPv4 or IPv6 address and port.
+func ntohs(i uint16) uint16 {
+ return binary.BigEndian.Uint16((*[2]byte)(unsafe.Pointer(&i))[:])
+}
+
+func htons(i uint16) uint16 {
+ b := make([]byte, 2)
+ binary.BigEndian.PutUint16(b, i)
+ return *(*uint16)(unsafe.Pointer(&b[0]))
+}
+
+// SetAddrPort method sets family, address, and port to the given IPv4 or IPv6 address and port.
// All other members of the structure are set to zero.
-func (addr *RawSockaddrInet) SetIP(ip net.IP, port uint16) error {
- if v4 := ip.To4(); v4 != nil {
+func (addr *RawSockaddrInet) SetAddrPort(addrPort netip.AddrPort) error {
+ if addrPort.Addr().Is4() {
addr4 := (*windows.RawSockaddrInet4)(unsafe.Pointer(addr))
addr4.Family = windows.AF_INET
- copy(addr4.Addr[:], v4)
- addr4.Port = port
+ addr4.Addr = addrPort.Addr().As4()
+ addr4.Port = htons(addrPort.Port())
for i := 0; i < 8; i++ {
addr4.Zero[i] = 0
}
return nil
- }
-
- if v6 := ip.To16(); v6 != nil {
+ } else if addrPort.Addr().Is6() {
addr6 := (*windows.RawSockaddrInet6)(unsafe.Pointer(addr))
addr6.Family = windows.AF_INET6
- addr6.Port = port
+ addr6.Addr = addrPort.Addr().As16()
+ addr6.Port = htons(addrPort.Port())
addr6.Flowinfo = 0
- copy(addr6.Addr[:], v6)
- addr6.Scope_id = 0
+ scopeId := uint32(0)
+ if z := addrPort.Addr().Zone(); z != "" {
+ if s, err := strconv.ParseUint(z, 10, 32); err == nil {
+ scopeId = uint32(s)
+ }
+ }
+ addr6.Scope_id = scopeId
return nil
}
-
return windows.ERROR_INVALID_PARAMETER
}
-// IP method returns IPv4 or IPv6 address.
-// If the address is neither IPv4 not IPv6 nil is returned.
-func (addr *RawSockaddrInet) IP() net.IP {
+// SetAddr method sets family and address to the given IPv4 or IPv6 address.
+// All other members of the structure are set to zero.
+func (addr *RawSockaddrInet) SetAddr(netAddr netip.Addr) error {
+ return addr.SetAddrPort(netip.AddrPortFrom(netAddr, 0))
+}
+
+// AddrPort returns the IP address and port.
+func (addr *RawSockaddrInet) AddrPort() netip.AddrPort {
+ return netip.AddrPortFrom(addr.Addr(), addr.Port())
+}
+
+// Addr returns IPv4 or IPv6 address, or an invalid address if the address is neither.
+func (addr *RawSockaddrInet) Addr() netip.Addr {
switch addr.Family {
case windows.AF_INET:
- return (*windows.RawSockaddrInet4)(unsafe.Pointer(addr)).Addr[:]
-
+ return netip.AddrFrom4((*windows.RawSockaddrInet4)(unsafe.Pointer(addr)).Addr)
case windows.AF_INET6:
- return (*windows.RawSockaddrInet6)(unsafe.Pointer(addr)).Addr[:]
+ raw := (*windows.RawSockaddrInet6)(unsafe.Pointer(addr))
+ a := netip.AddrFrom16(raw.Addr)
+ if raw.Scope_id != 0 {
+ a = a.WithZone(strconv.FormatUint(uint64(raw.Scope_id), 10))
+ }
+ return a
}
+ return netip.Addr{}
+}
- return nil
+// Port returns the port if the address if IPv4 or IPv6, or 0 if neither.
+func (addr *RawSockaddrInet) Port() uint16 {
+ switch addr.Family {
+ case windows.AF_INET:
+ return ntohs((*windows.RawSockaddrInet4)(unsafe.Pointer(addr)).Port)
+ case windows.AF_INET6:
+ return ntohs((*windows.RawSockaddrInet6)(unsafe.Pointer(addr)).Port)
+ }
+ return 0
}
// Init method initializes a MibUnicastIPAddressRow structure with default values for a unicast IP address entry on the local computer.
@@ -807,8 +849,7 @@ func (row *MibUnicastIPAddressRow) Delete() error {
// get method returns all table rows as a Go slice.
func (tab *mibUnicastIPAddressTable) get() (s []MibUnicastIPAddressRow) {
- unsafeSlice(unsafe.Pointer(&s), unsafe.Pointer(&tab.table[0]), int(tab.numEntries))
- return
+ return unsafe.Slice(&tab.table[0], tab.numEntries)
}
// free method frees the buffer allocated by the functions that return tables of network interfaces, addresses, and routes.
@@ -837,8 +878,7 @@ func (row *MibAnycastIPAddressRow) Delete() error {
// get method returns all table rows as a Go slice.
func (tab *mibAnycastIPAddressTable) get() (s []MibAnycastIPAddressRow) {
- unsafeSlice(unsafe.Pointer(&s), unsafe.Pointer(&tab.table[0]), int(tab.numEntries))
- return
+ return unsafe.Slice(&tab.table[0], tab.numEntries)
}
// free method frees the buffer allocated by the functions that return tables of network interfaces, addresses, and routes.
@@ -850,32 +890,30 @@ func (tab *mibAnycastIPAddressTable) free() {
// IPAddressPrefix structure stores an IP address prefix.
// https://docs.microsoft.com/en-us/windows/desktop/api/netioapi/ns-netioapi-_ip_address_prefix
type IPAddressPrefix struct {
- Prefix RawSockaddrInet
+ RawPrefix RawSockaddrInet
PrefixLength uint8
_ [2]byte
}
-// SetIPNet method sets IP address prefix using net.IPNet.
-func (prefix *IPAddressPrefix) SetIPNet(net net.IPNet) error {
- err := prefix.Prefix.SetIP(net.IP, 0)
+// SetPrefix method sets IP address prefix using netip.Prefix.
+func (prefix *IPAddressPrefix) SetPrefix(netPrefix netip.Prefix) error {
+ err := prefix.RawPrefix.SetAddr(netPrefix.Addr())
if err != nil {
return err
}
- ones, _ := net.Mask.Size()
- prefix.PrefixLength = uint8(ones)
+ prefix.PrefixLength = uint8(netPrefix.Bits())
return nil
}
-// IPNet method returns IP address prefix as net.IPNet.
-// If the address is neither IPv4 not IPv6 an empty net.IPNet is returned. The resulting net.IPNet should be checked appropriately.
-func (prefix *IPAddressPrefix) IPNet() net.IPNet {
- switch prefix.Prefix.Family {
+// Prefix returns IP address prefix as netip.Prefix.
+func (prefix *IPAddressPrefix) Prefix() netip.Prefix {
+ switch prefix.RawPrefix.Family {
case windows.AF_INET:
- return net.IPNet{IP: (*windows.RawSockaddrInet4)(unsafe.Pointer(&prefix.Prefix)).Addr[:], Mask: net.CIDRMask(int(prefix.PrefixLength), 8*net.IPv4len)}
+ return netip.PrefixFrom(netip.AddrFrom4((*windows.RawSockaddrInet4)(unsafe.Pointer(&prefix.RawPrefix)).Addr), int(prefix.PrefixLength))
case windows.AF_INET6:
- return net.IPNet{IP: (*windows.RawSockaddrInet6)(unsafe.Pointer(&prefix.Prefix)).Addr[:], Mask: net.CIDRMask(int(prefix.PrefixLength), 8*net.IPv6len)}
+ return netip.PrefixFrom(netip.AddrFrom16((*windows.RawSockaddrInet6)(unsafe.Pointer(&prefix.RawPrefix)).Addr), int(prefix.PrefixLength))
}
- return net.IPNet{}
+ return netip.Prefix{}
}
// MibIPforwardRow2 structure stores information about an IP route entry.
@@ -930,8 +968,7 @@ func (row *MibIPforwardRow2) Delete() error {
// get method returns all table rows as a Go slice.
func (tab *mibIPforwardTable2) get() (s []MibIPforwardRow2) {
- unsafeSlice(unsafe.Pointer(&s), unsafe.Pointer(&tab.table[0]), int(tab.numEntries))
- return
+ return unsafe.Slice(&tab.table[0], tab.numEntries)
}
// free method frees the buffer allocated by the functions that return tables of network interfaces, addresses, and routes.
@@ -941,11 +978,11 @@ func (tab *mibIPforwardTable2) free() {
}
//
-// Undocumented DNS API
+// DNS API
//
-// dnsInterfaceSettings is mean to be used with setInterfaceDnsSettings
-type dnsInterfaceSettings struct {
+// DnsInterfaceSettings is meant to be used with SetInterfaceDnsSettings
+type DnsInterfaceSettings struct {
Version uint32
_ [4]byte
Flags uint64
@@ -960,37 +997,22 @@ type dnsInterfaceSettings struct {
}
const (
- disVersion1 = 1
- disVersion2 = 2
-
- disFlagsIPv6 = 0x1
- disFlagsNameServer = 0x2
- disFlagsSearchList = 0x4
- disFlagsRegistrationEnabled = 0x8
- disFlagsRegisterAdapterName = 0x10
- disFlagsDomain = 0x20
- disFlagsHostname = 0x40 // ??
- disFlagsEnableLLMNR = 0x80
- disFlagsQueryAdapterName = 0x100
- disFlagsProfileNameServer = 0x200
- disFlagsVersion2 = 0x400 // ?? - v2 only
- disFlagsMoreFlags = 0x800 // ?? - v2 only
+ DnsInterfaceSettingsVersion1 = 1 // for DnsInterfaceSettings
+ DnsInterfaceSettingsVersion2 = 2 // for DnsInterfaceSettingsEx
+ DnsInterfaceSettingsVersion3 = 3 // for DnsInterfaceSettings3
+
+ DnsInterfaceSettingsFlagIPv6 = 0x0001
+ DnsInterfaceSettingsFlagNameserver = 0x0002
+ DnsInterfaceSettingsFlagSearchList = 0x0004
+ DnsInterfaceSettingsFlagRegistrationEnabled = 0x0008
+ DnsInterfaceSettingsFlagRegisterAdapterName = 0x0010
+ DnsInterfaceSettingsFlagDomain = 0x0020
+ DnsInterfaceSettingsFlagHostname = 0x0040
+ DnsInterfaceSettingsFlagEnableLLMNR = 0x0080
+ DnsInterfaceSettingsFlagQueryAdapterName = 0x0100
+ DnsInterfaceSettingsFlagProfileNameserver = 0x0200
+ DnsInterfaceSettingsFlagDisableUnconstrainedQueries = 0x0400 // v2 only
+ DnsInterfaceSettingsFlagSupplementalSearchList = 0x0800 // v2 only
+ DnsInterfaceSettingsFlagDOH = 0x1000 // v3 only
+ DnsInterfaceSettingsFlagDOHProfile = 0x2000 // v3 only
)
-
-// unsafeSlice updates the slice slicePtr to be a slice
-// referencing the provided data with its length & capacity set to
-// lenCap.
-//
-// TODO: when Go 1.16 or Go 1.17 is the minimum supported version,
-// update callers to use unsafe.Slice instead of this.
-func unsafeSlice(slicePtr, data unsafe.Pointer, lenCap int) {
- type sliceHeader struct {
- Data unsafe.Pointer
- Len int
- Cap int
- }
- h := (*sliceHeader)(slicePtr)
- h.Data = data
- h.Len = lenCap
- h.Cap = lenCap
-}
diff --git a/tunnel/winipcfg/types_32.go b/tunnel/winipcfg/types_32.go
index 51a8d31c..1a8d4443 100644
--- a/tunnel/winipcfg/types_32.go
+++ b/tunnel/winipcfg/types_32.go
@@ -1,8 +1,8 @@
-// +build 386 arm
+//go:build 386 || arm
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
diff --git a/tunnel/winipcfg/types_64.go b/tunnel/winipcfg/types_64.go
index 6623ce54..3a1fe07f 100644
--- a/tunnel/winipcfg/types_64.go
+++ b/tunnel/winipcfg/types_64.go
@@ -1,8 +1,8 @@
-// +build amd64 arm64
+//go:build amd64 || arm64
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
diff --git a/tunnel/winipcfg/types_test.go b/tunnel/winipcfg/types_test.go
index 26268dbe..b72d73f5 100644
--- a/tunnel/winipcfg/types_test.go
+++ b/tunnel/winipcfg/types_test.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
@@ -957,7 +957,6 @@ func TestIPAddressPrefix(t *testing.T) {
offset := uintptr(unsafe.Pointer(&s.PrefixLength)) - sp
if offset != ipAddressPrefixPrefixLengthOffset {
t.Errorf("IPAddressPrefix.PrefixLength offset is %d although %d is expected", offset, ipAddressPrefixPrefixLengthOffset)
-
}
}
diff --git a/tunnel/winipcfg/types_test_32.go b/tunnel/winipcfg/types_test_32.go
index fa3f91d5..9e62bfef 100644
--- a/tunnel/winipcfg/types_test_32.go
+++ b/tunnel/winipcfg/types_test_32.go
@@ -1,8 +1,8 @@
-// +build 386 arm
+//go:build 386 || arm
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
diff --git a/tunnel/winipcfg/types_test_64.go b/tunnel/winipcfg/types_test_64.go
index d20cdb30..8a181575 100644
--- a/tunnel/winipcfg/types_test_64.go
+++ b/tunnel/winipcfg/types_test_64.go
@@ -1,8 +1,8 @@
-// +build amd64 arm64
+//go:build amd64 || arm64
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
diff --git a/tunnel/winipcfg/unicast_address_change_handler.go b/tunnel/winipcfg/unicast_address_change_handler.go
index 517ff037..cf4fcb3a 100644
--- a/tunnel/winipcfg/unicast_address_change_handler.go
+++ b/tunnel/winipcfg/unicast_address_change_handler.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
diff --git a/tunnel/winipcfg/winipcfg.go b/tunnel/winipcfg/winipcfg.go
index dd09d3a0..e24157b9 100644
--- a/tunnel/winipcfg/winipcfg.go
+++ b/tunnel/winipcfg/winipcfg.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package winipcfg
@@ -170,18 +170,18 @@ func GetIPForwardTable2(family AddressFamily) ([]MibIPforwardRow2, error) {
//sys cancelMibChangeNotify2(notificationHandle windows.Handle) (ret error) = iphlpapi.CancelMibChangeNotify2
//
-// Undocumented DNS API
+// DNS-related functions
//
-//sys setInterfaceDnsSettingsByPtr(guid *windows.GUID, settings *dnsInterfaceSettings) (ret error) = iphlpapi.SetInterfaceDnsSettings?
-//sys setInterfaceDnsSettingsByQwords(guid1 uintptr, guid2 uintptr, settings *dnsInterfaceSettings) (ret error) = iphlpapi.SetInterfaceDnsSettings?
-//sys setInterfaceDnsSettingsByDwords(guid1 uintptr, guid2 uintptr, guid3 uintptr, guid4 uintptr, settings *dnsInterfaceSettings) (ret error) = iphlpapi.SetInterfaceDnsSettings?
+//sys setInterfaceDnsSettingsByPtr(guid *windows.GUID, settings *DnsInterfaceSettings) (ret error) = iphlpapi.SetInterfaceDnsSettings?
+//sys setInterfaceDnsSettingsByQwords(guid1 uintptr, guid2 uintptr, settings *DnsInterfaceSettings) (ret error) = iphlpapi.SetInterfaceDnsSettings?
+//sys setInterfaceDnsSettingsByDwords(guid1 uintptr, guid2 uintptr, guid3 uintptr, guid4 uintptr, settings *DnsInterfaceSettings) (ret error) = iphlpapi.SetInterfaceDnsSettings?
// The GUID is passed by value, not by reference, which means different
// things on different calling conventions. On amd64, this means it's
// passed by reference anyway, while on arm, arm64, and 386, it's split
// into words.
-func setInterfaceDnsSettings(guid windows.GUID, settings *dnsInterfaceSettings) error {
+func SetInterfaceDnsSettings(guid windows.GUID, settings *DnsInterfaceSettings) error {
words := (*[4]uintptr)(unsafe.Pointer(&guid))
switch runtime.GOARCH {
case "amd64":
diff --git a/tunnel/winipcfg/winipcfg_test.go b/tunnel/winipcfg/winipcfg_test.go
index 7689a0c1..b49daf33 100644
--- a/tunnel/winipcfg/winipcfg_test.go
+++ b/tunnel/winipcfg/winipcfg_test.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
/*
@@ -8,8 +8,8 @@
Some tests in this file require:
- A dedicated network adapter
- Any network adapter will do. It may be virtual (Wintun etc.). The adapter name
- must contain string "winipcfg_test".
+ Any network adapter will do. It may be virtual (WireGuardNT, Wintun,
+ etc.). The adapter name must contain string "winipcfg_test".
Tests will add, remove, flush DNS servers, change adapter IP address, manipulate
routes etc.
The adapter will not be returned to previous state, so use an expendable one.
@@ -22,8 +22,7 @@ Some tests in this file require:
package winipcfg
import (
- "bytes"
- "net"
+ "net/netip"
"strings"
"syscall"
"testing"
@@ -38,22 +37,13 @@ const (
// TODO: Add IPv6 tests.
var (
- unexistentIPAddresToAdd = net.IPNet{
- IP: net.IP{172, 16, 1, 114},
- Mask: net.IPMask{255, 255, 255, 0},
- }
- unexistentRouteIPv4ToAdd = RouteData{
- Destination: net.IPNet{
- IP: net.IP{172, 16, 200, 0},
- Mask: net.IPMask{255, 255, 255, 0},
- },
- NextHop: net.IP{172, 16, 1, 2},
- Metric: 0,
- }
- dnsesToSet = []net.IP{
- net.IPv4(8, 8, 8, 8),
- net.IPv4(8, 8, 4, 4),
+ nonexistantIPv4ToAdd = netip.MustParsePrefix("172.16.1.114/24")
+ nonexistentRouteIPv4ToAdd = RouteData{
+ Destination: netip.MustParsePrefix("172.16.200.0/24"),
+ NextHop: netip.MustParseAddr("172.16.1.2"),
+ Metric: 0,
}
+ dnsesToSet = []netip.Addr{netip.MustParseAddr("8.8.8.8"), netip.MustParseAddr("8.8.4.4")}
)
func runningElevated() bool {
@@ -74,7 +64,7 @@ func getTestInterface() (*IPAdapterAddresses, error) {
marker := strings.ToLower(testInterfaceMarker)
for _, ifc := range ifcs {
- if strings.Index(strings.ToLower(ifc.FriendlyName()), marker) != -1 {
+ if strings.Contains(strings.ToLower(ifc.FriendlyName()), marker) {
return ifc, nil
}
}
@@ -380,9 +370,9 @@ func TestAddDeleteIPAddress(t *testing.T) {
return
}
- addr, err := ifc.LUID.IPAddress(unexistentIPAddresToAdd.IP)
+ addr, err := ifc.LUID.IPAddress(nonexistantIPv4ToAdd.Addr())
if err == nil {
- t.Errorf("Unicast address %s already exists. Please set unexistentIPAddresToAdd appropriately.", unexistentIPAddresToAdd.IP.String())
+ t.Errorf("Unicast address %s already exists. Please set nonexistantIPv4ToAdd appropriately.", nonexistantIPv4ToAdd.Addr().String())
return
} else if err != windows.ERROR_NOT_FOUND {
t.Errorf("LUID.IPAddress() returned an error: %w", err)
@@ -410,7 +400,7 @@ func TestAddDeleteIPAddress(t *testing.T) {
for addr := ifc.FirstUnicastAddress; addr != nil; addr = addr.Next {
count--
}
- err = ifc.LUID.AddIPAddresses([]net.IPNet{unexistentIPAddresToAdd})
+ err = ifc.LUID.AddIPAddresses([]netip.Prefix{nonexistantIPv4ToAdd})
if err != nil {
t.Errorf("LUID.AddIPAddresses() returned an error: %w", err)
}
@@ -424,26 +414,26 @@ func TestAddDeleteIPAddress(t *testing.T) {
if count != 1 {
t.Errorf("After adding there are %d new interface(s).", count)
}
- addr, err = ifc.LUID.IPAddress(unexistentIPAddresToAdd.IP)
+ addr, err = ifc.LUID.IPAddress(nonexistantIPv4ToAdd.Addr())
if err != nil {
t.Errorf("LUID.IPAddress() returned an error: %w", err)
} else if addr == nil {
- t.Errorf("Unicast address %s still doesn't exist, although it's added successfully.", unexistentIPAddresToAdd.IP.String())
+ t.Errorf("Unicast address %s still doesn't exist, although it's added successfully.", nonexistantIPv4ToAdd.Addr().String())
}
if !created {
t.Errorf("Notification handler has not been called on add.")
}
- err = ifc.LUID.DeleteIPAddress(unexistentIPAddresToAdd)
+ err = ifc.LUID.DeleteIPAddress(nonexistantIPv4ToAdd)
if err != nil {
t.Errorf("LUID.DeleteIPAddress() returned an error: %w", err)
}
time.Sleep(500 * time.Millisecond)
- addr, err = ifc.LUID.IPAddress(unexistentIPAddresToAdd.IP)
+ addr, err = ifc.LUID.IPAddress(nonexistantIPv4ToAdd.Addr())
if err == nil {
- t.Errorf("Unicast address %s still exists, although it's deleted successfully.", unexistentIPAddresToAdd.IP.String())
+ t.Errorf("Unicast address %s still exists, although it's deleted successfully.", nonexistantIPv4ToAdd.Addr().String())
} else if err != windows.ERROR_NOT_FOUND {
t.Errorf("LUID.IPAddress() returned an error: %w", err)
}
@@ -460,14 +450,13 @@ func TestGetRoutes(t *testing.T) {
}
func TestAddDeleteRoute(t *testing.T) {
- findRoute := func(luid LUID, dest net.IPNet) ([]MibIPforwardRow2, error) {
+ findRoute := func(luid LUID, dest netip.Prefix) ([]MibIPforwardRow2, error) {
var family AddressFamily
- switch {
- case dest.IP.To4() != nil:
+ if dest.Addr().Is4() {
family = windows.AF_INET
- case dest.IP.To16() != nil:
+ } else if dest.Addr().Is6() {
family = windows.AF_INET6
- default:
+ } else {
return nil, windows.ERROR_INVALID_PARAMETER
}
r, err := GetIPForwardTable2(family)
@@ -475,9 +464,8 @@ func TestAddDeleteRoute(t *testing.T) {
return nil, err
}
matches := make([]MibIPforwardRow2, 0, len(r))
- ones, _ := dest.Mask.Size()
for _, route := range r {
- if route.InterfaceLUID == luid && route.DestinationPrefix.PrefixLength == uint8(ones) && route.DestinationPrefix.Prefix.Family == family && route.DestinationPrefix.Prefix.IP().Equal(dest.IP) {
+ if route.InterfaceLUID == luid && route.DestinationPrefix.PrefixLength == uint8(dest.Bits()) && route.DestinationPrefix.RawPrefix.Family == family && route.DestinationPrefix.RawPrefix.Addr() == dest.Addr() {
matches = append(matches, route)
}
}
@@ -494,20 +482,20 @@ func TestAddDeleteRoute(t *testing.T) {
return
}
- _, err = ifc.LUID.Route(unexistentRouteIPv4ToAdd.Destination, unexistentRouteIPv4ToAdd.NextHop)
+ _, err = ifc.LUID.Route(nonexistentRouteIPv4ToAdd.Destination, nonexistentRouteIPv4ToAdd.NextHop)
if err == nil {
- t.Error("LUID.Route() returned a route although it isn't added yet. Have you forgot to set unexistentRouteIPv4ToAdd appropriately?")
+ t.Error("LUID.Route() returned a route although it isn't added yet. Have you forgot to set nonexistentRouteIPv4ToAdd appropriately?")
return
} else if err != windows.ERROR_NOT_FOUND {
t.Errorf("LUID.Route() returned an error: %w", err)
return
}
- routes, err := findRoute(ifc.LUID, unexistentRouteIPv4ToAdd.Destination)
+ routes, err := findRoute(ifc.LUID, nonexistentRouteIPv4ToAdd.Destination)
if err != nil {
t.Errorf("findRoute() returned an error: %w", err)
} else if len(routes) != 0 {
- t.Errorf("findRoute() returned %d items although the route isn't added yet. Have you forgot to set unexistentRouteIPv4ToAdd appropriately?", len(routes))
+ t.Errorf("findRoute() returned %d items although the route isn't added yet. Have you forgot to set nonexistentRouteIPv4ToAdd appropriately?", len(routes))
}
var created, deleted bool
@@ -524,42 +512,42 @@ func TestAddDeleteRoute(t *testing.T) {
} else {
defer cb.Unregister()
}
- err = ifc.LUID.AddRoute(unexistentRouteIPv4ToAdd.Destination, unexistentRouteIPv4ToAdd.NextHop, unexistentRouteIPv4ToAdd.Metric)
+ err = ifc.LUID.AddRoute(nonexistentRouteIPv4ToAdd.Destination, nonexistentRouteIPv4ToAdd.NextHop, nonexistentRouteIPv4ToAdd.Metric)
if err != nil {
t.Errorf("LUID.AddRoute() returned an error: %w", err)
}
time.Sleep(500 * time.Millisecond)
- route, err := ifc.LUID.Route(unexistentRouteIPv4ToAdd.Destination, unexistentRouteIPv4ToAdd.NextHop)
+ route, err := ifc.LUID.Route(nonexistentRouteIPv4ToAdd.Destination, nonexistentRouteIPv4ToAdd.NextHop)
if err == windows.ERROR_NOT_FOUND {
t.Error("LUID.Route() returned nil although the route is added successfully.")
} else if err != nil {
t.Errorf("LUID.Route() returned an error: %w", err)
- } else if !route.DestinationPrefix.Prefix.IP().Equal(unexistentRouteIPv4ToAdd.Destination.IP) || !route.NextHop.IP().Equal(unexistentRouteIPv4ToAdd.NextHop) {
+ } else if route.DestinationPrefix.RawPrefix.Addr() != nonexistentRouteIPv4ToAdd.Destination.Addr() || route.NextHop.Addr() != nonexistentRouteIPv4ToAdd.NextHop {
t.Error("LUID.Route() returned a wrong route!")
}
if !created {
t.Errorf("Route handler has not been called on add.")
}
- routes, err = findRoute(ifc.LUID, unexistentRouteIPv4ToAdd.Destination)
+ routes, err = findRoute(ifc.LUID, nonexistentRouteIPv4ToAdd.Destination)
if err != nil {
t.Errorf("findRoute() returned an error: %w", err)
} else if len(routes) != 1 {
t.Errorf("findRoute() returned %d items although %d is expected.", len(routes), 1)
- } else if !routes[0].DestinationPrefix.Prefix.IP().Equal(unexistentRouteIPv4ToAdd.Destination.IP) {
- t.Errorf("findRoute() returned a wrong route. Dest: %s; expected: %s.", routes[0].DestinationPrefix.Prefix.IP().String(), unexistentRouteIPv4ToAdd.Destination.IP.String())
+ } else if routes[0].DestinationPrefix.RawPrefix.Addr() != nonexistentRouteIPv4ToAdd.Destination.Addr() {
+ t.Errorf("findRoute() returned a wrong route. Dest: %s; expected: %s.", routes[0].DestinationPrefix.RawPrefix.Addr().String(), nonexistentRouteIPv4ToAdd.Destination.Addr().String())
}
- err = ifc.LUID.DeleteRoute(unexistentRouteIPv4ToAdd.Destination, unexistentRouteIPv4ToAdd.NextHop)
+ err = ifc.LUID.DeleteRoute(nonexistentRouteIPv4ToAdd.Destination, nonexistentRouteIPv4ToAdd.NextHop)
if err != nil {
t.Errorf("LUID.DeleteRoute() returned an error: %w", err)
}
time.Sleep(500 * time.Millisecond)
- _, err = ifc.LUID.Route(unexistentRouteIPv4ToAdd.Destination, unexistentRouteIPv4ToAdd.NextHop)
+ _, err = ifc.LUID.Route(nonexistentRouteIPv4ToAdd.Destination, nonexistentRouteIPv4ToAdd.NextHop)
if err == nil {
t.Error("LUID.Route() returned a route although it is removed successfully.")
} else if err != windows.ERROR_NOT_FOUND {
@@ -569,7 +557,7 @@ func TestAddDeleteRoute(t *testing.T) {
t.Errorf("Route handler has not been called on delete.")
}
- routes, err = findRoute(ifc.LUID, unexistentRouteIPv4ToAdd.Destination)
+ routes, err = findRoute(ifc.LUID, nonexistentRouteIPv4ToAdd.Destination)
if err != nil {
t.Errorf("findRoute() returned an error: %w", err)
} else if len(routes) != 0 {
@@ -606,7 +594,7 @@ func TestFlushDNS(t *testing.T) {
t.Errorf("LUID.DNS() returned an error: %w", err)
}
for _, a := range dns {
- if len(a) != 16 || a.To4() != nil || !((a[15] == 1 || a[15] == 2 || a[15] == 3) && bytes.HasPrefix(a, []byte{0xfe, 0xc0, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00})) {
+ if a.Is4() {
n++
}
}
@@ -651,7 +639,7 @@ func TestSetDNS(t *testing.T) {
t.Errorf("dnsesToSet contains %d items, while DNSServerAddresses contains %d.", len(dnsesToSet), len(newDNSes))
} else {
for i := range dnsesToSet {
- if !dnsesToSet[i].Equal(newDNSes[i]) {
+ if dnsesToSet[i] != newDNSes[i] {
t.Errorf("dnsesToSet[%d] = %s while DNSServerAddresses[%d] = %s.", i, dnsesToSet[i].String(), i, newDNSes[i].String())
}
}
diff --git a/tunnel/winipcfg/zwinipcfg_windows.go b/tunnel/winipcfg/zwinipcfg_windows.go
index ac89fec1..3a0d8680 100644
--- a/tunnel/winipcfg/zwinipcfg_windows.go
+++ b/tunnel/winipcfg/zwinipcfg_windows.go
@@ -289,7 +289,7 @@ func notifyUnicastIPAddressChange(family AddressFamily, callback uintptr, caller
return
}
-func setInterfaceDnsSettingsByDwords(guid1 uintptr, guid2 uintptr, guid3 uintptr, guid4 uintptr, settings *dnsInterfaceSettings) (ret error) {
+func setInterfaceDnsSettingsByDwords(guid1 uintptr, guid2 uintptr, guid3 uintptr, guid4 uintptr, settings *DnsInterfaceSettings) (ret error) {
ret = procSetInterfaceDnsSettings.Find()
if ret != nil {
return
@@ -301,24 +301,24 @@ func setInterfaceDnsSettingsByDwords(guid1 uintptr, guid2 uintptr, guid3 uintptr
return
}
-func setInterfaceDnsSettingsByPtr(guid *windows.GUID, settings *dnsInterfaceSettings) (ret error) {
+func setInterfaceDnsSettingsByQwords(guid1 uintptr, guid2 uintptr, settings *DnsInterfaceSettings) (ret error) {
ret = procSetInterfaceDnsSettings.Find()
if ret != nil {
return
}
- r0, _, _ := syscall.Syscall(procSetInterfaceDnsSettings.Addr(), 2, uintptr(unsafe.Pointer(guid)), uintptr(unsafe.Pointer(settings)), 0)
+ r0, _, _ := syscall.Syscall(procSetInterfaceDnsSettings.Addr(), 3, uintptr(guid1), uintptr(guid2), uintptr(unsafe.Pointer(settings)))
if r0 != 0 {
ret = syscall.Errno(r0)
}
return
}
-func setInterfaceDnsSettingsByQwords(guid1 uintptr, guid2 uintptr, settings *dnsInterfaceSettings) (ret error) {
+func setInterfaceDnsSettingsByPtr(guid *windows.GUID, settings *DnsInterfaceSettings) (ret error) {
ret = procSetInterfaceDnsSettings.Find()
if ret != nil {
return
}
- r0, _, _ := syscall.Syscall(procSetInterfaceDnsSettings.Addr(), 3, uintptr(guid1), uintptr(guid2), uintptr(unsafe.Pointer(settings)))
+ r0, _, _ := syscall.Syscall(procSetInterfaceDnsSettings.Addr(), 2, uintptr(unsafe.Pointer(guid)), uintptr(unsafe.Pointer(settings)), 0)
if r0 != 0 {
ret = syscall.Errno(r0)
}
diff --git a/tunnel/wintun_test.go b/tunnel/wintun_test.go
deleted file mode 100644
index 4e56ff65..00000000
--- a/tunnel/wintun_test.go
+++ /dev/null
@@ -1,202 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
- */
-
-package tunnel_test
-
-import (
- "bytes"
- "crypto/rand"
- "encoding/binary"
- "fmt"
- "net"
- "sync"
- "testing"
- "time"
-
- "golang.org/x/sys/windows"
-
- "golang.zx2c4.com/wireguard/tun"
-
- "golang.zx2c4.com/wireguard/windows/elevate"
- "golang.zx2c4.com/wireguard/windows/tunnel/winipcfg"
-)
-
-func TestWintunOrdering(t *testing.T) {
- var tunDevice tun.Device
- err := elevate.DoAsSystem(func() error {
- var err error
- tunDevice, err = tun.CreateTUNWithRequestedGUID("tunordertest", &windows.GUID{12, 12, 12, [8]byte{12, 12, 12, 12, 12, 12, 12, 12}}, 1500)
- return err
- })
- if err != nil {
- t.Fatal(err)
- }
- defer tunDevice.Close()
- nativeTunDevice := tunDevice.(*tun.NativeTun)
- luid := winipcfg.LUID(nativeTunDevice.LUID())
- ip, ipnet, _ := net.ParseCIDR("10.82.31.4/24")
- err = luid.SetIPAddresses([]net.IPNet{{ip, ipnet.Mask}})
- if err != nil {
- t.Fatal(err)
- }
- err = luid.SetRoutes([]*winipcfg.RouteData{{*ipnet, ipnet.IP, 0}})
- if err != nil {
- t.Fatal(err)
- }
- var token [32]byte
- _, err = rand.Read(token[:])
- if err != nil {
- t.Fatal(err)
- }
- var sockWrite net.Conn
- for i := 0; i < 1000; i++ {
- sockWrite, err = net.Dial("udp", "10.82.31.5:9999")
- if err == nil {
- defer sockWrite.Close()
- break
- }
- time.Sleep(time.Millisecond * 100)
- }
- if err != nil {
- t.Fatal(err)
- }
- var sockRead *net.UDPConn
- for i := 0; i < 1000; i++ {
- var listenAddress *net.UDPAddr
- listenAddress, err = net.ResolveUDPAddr("udp", "10.82.31.4:9999")
- if err != nil {
- continue
- }
- sockRead, err = net.ListenUDP("udp", listenAddress)
- if err == nil {
- defer sockRead.Close()
- break
- }
- time.Sleep(time.Millisecond * 100)
- }
- if err != nil {
- t.Fatal(err)
- }
- var wait sync.WaitGroup
- wait.Add(4)
- doneSockWrite := false
- doneTunWrite := false
- fatalErrors := make(chan error, 2)
- errors := make(chan error, 2)
- go func() {
- defer wait.Done()
- buffer := append(token[:], 0, 0, 0, 0, 0, 0, 0, 0)
- for sendingIndex := uint64(0); !doneSockWrite; sendingIndex++ {
- binary.LittleEndian.PutUint64(buffer[32:], sendingIndex)
- _, err := sockWrite.Write(buffer[:])
- if err != nil {
- fatalErrors <- err
- }
- }
- }()
- go func() {
- defer wait.Done()
- packet := [20 + 8 + 32 + 8]byte{
- 0x45, 0, 0, 20 + 8 + 32 + 8,
- 0, 0, 0, 0,
- 0x80, 0x11, 0, 0,
- 10, 82, 31, 5,
- 10, 82, 31, 4,
- 8888 >> 8, 8888 & 0xff, 9999 >> 8, 9999 & 0xff, 0, 8 + 32 + 8, 0, 0,
- }
- copy(packet[28:], token[:])
- for sendingIndex := uint64(0); !doneTunWrite; sendingIndex++ {
- binary.BigEndian.PutUint16(packet[4:], uint16(sendingIndex))
- var checksum uint32
- for i := 0; i < 20; i += 2 {
- if i != 10 {
- checksum += uint32(binary.BigEndian.Uint16(packet[i:]))
- }
- }
- binary.BigEndian.PutUint16(packet[10:], ^(uint16(checksum>>16) + uint16(checksum&0xffff)))
- binary.LittleEndian.PutUint64(packet[20+8+32:], sendingIndex)
- n, err := tunDevice.Write(packet[:], 0)
- if err != nil {
- fatalErrors <- err
- }
- if n == 0 {
- time.Sleep(time.Millisecond * 300)
- }
- }
- }()
- const packetsPerTest = 1 << 21
- go func() {
- defer func() {
- doneSockWrite = true
- wait.Done()
- }()
- var expectedIndex uint64
- for i := uint64(0); i < packetsPerTest; {
- var buffer [(1 << 16) - 1]byte
- bytesRead, err := tunDevice.Read(buffer[:], 0)
- if err != nil {
- fatalErrors <- err
- }
- if bytesRead < 0 || bytesRead > len(buffer) {
- continue
- }
- packet := buffer[:bytesRead]
- tokenPos := bytes.Index(packet, token[:])
- if tokenPos == -1 || tokenPos+32+8 > len(packet) {
- continue
- }
- foundIndex := binary.LittleEndian.Uint64(packet[tokenPos+32:])
- if foundIndex < expectedIndex {
- errors <- fmt.Errorf("Sock write, tun read: expected packet %d, received packet %d", expectedIndex, foundIndex)
- }
- expectedIndex = foundIndex + 1
- i++
- }
- }()
- go func() {
- defer func() {
- doneTunWrite = true
- wait.Done()
- }()
- var expectedIndex uint64
- for i := uint64(0); i < packetsPerTest; {
- var buffer [(1 << 16) - 1]byte
- bytesRead, err := sockRead.Read(buffer[:])
- if err != nil {
- fatalErrors <- err
- }
- if bytesRead < 0 || bytesRead > len(buffer) {
- continue
- }
- packet := buffer[:bytesRead]
- if len(packet) != 32+8 || !bytes.HasPrefix(packet, token[:]) {
- continue
- }
- foundIndex := binary.LittleEndian.Uint64(packet[32:])
- if foundIndex < expectedIndex {
- errors <- fmt.Errorf("Tun write, sock read: expected packet %d, received packet %d", expectedIndex, foundIndex)
- }
- expectedIndex = foundIndex + 1
- i++
- }
- }()
- done := make(chan bool, 2)
- doneFunc := func() {
- wait.Wait()
- done <- true
- }
- defer doneFunc()
- go doneFunc()
- for {
- select {
- case err := <-fatalErrors:
- t.Fatal(err)
- case err := <-errors:
- t.Error(err)
- case <-done:
- return
- }
- }
-}
diff --git a/ui/aboutdialog.go b/ui/aboutdialog.go
index f9be1f90..0f939b15 100644
--- a/ui/aboutdialog.go
+++ b/ui/aboutdialog.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package ui
@@ -12,13 +12,16 @@ import (
"github.com/lxn/walk"
"github.com/lxn/win"
"golang.org/x/sys/windows"
+ "golang.zx2c4.com/wireguard/windows/driver"
"golang.zx2c4.com/wireguard/windows/l18n"
"golang.zx2c4.com/wireguard/windows/version"
)
-var easterEggIndex = -1
-var showingAboutDialog *walk.Dialog
+var (
+ easterEggIndex = -1
+ showingAboutDialog *walk.Dialog
+)
func onAbout(owner walk.Form) {
showError(runAboutDialog(owner), owner)
@@ -95,7 +98,7 @@ func runAboutDialog(owner walk.Form) error {
return err
}
detailsLbl.SetTextAlignment(walk.AlignHCenterVNear)
- detailsLbl.SetText(l18n.Sprintf("App version: %s\nGo backend version: %s\nGo version: %s-%s\nOperating system: %s\nArchitecture: %s", version.Number, version.ProtoImplementation(), strings.TrimPrefix(runtime.Version(), "go"), runtime.GOARCH, version.OsName(), version.Arch()))
+ detailsLbl.SetText(l18n.Sprintf("App version: %s\nDriver version: %s\nGo version: %s\nOperating system: %s\nArchitecture: %s", version.Number, driver.Version(), strings.TrimPrefix(runtime.Version(), "go"), version.OsName(), version.Arch()))
copyrightLbl, err := walk.NewTextLabel(showingAboutDialog)
if err != nil {
@@ -104,7 +107,7 @@ func runAboutDialog(owner walk.Form) error {
copyrightFont, _ := walk.NewFont("Segoe UI", 7, 0)
copyrightLbl.SetFont(copyrightFont)
copyrightLbl.SetTextAlignment(walk.AlignHCenterVNear)
- copyrightLbl.SetText("Copyright © 2015-2021 Jason A. Donenfeld. All Rights Reserved.")
+ copyrightLbl.SetText("Copyright © 2015-2022 Jason A. Donenfeld. All Rights Reserved.")
buttonCP, err := walk.NewComposite(showingAboutDialog)
if err != nil {
diff --git a/ui/confview.go b/ui/confview.go
index f3ddbc9d..78e4df91 100644
--- a/ui/confview.go
+++ b/ui/confview.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package ui
@@ -51,6 +51,7 @@ type interfaceView struct {
addresses *labelTextLine
dns *labelTextLine
scripts *labelTextLine
+ table *labelTextLine
toggleActive *toggleActiveLine
lines []widgetsLine
}
@@ -307,6 +308,7 @@ func newInterfaceView(parent walk.Container) (*interfaceView, error) {
{l18n.Sprintf("Addresses:"), &iv.addresses},
{l18n.Sprintf("DNS servers:"), &iv.dns},
{l18n.Sprintf("Scripts:"), &iv.scripts},
+ {l18n.Sprintf("Table:"), &iv.table},
}
if iv.lines, err = createLabelTextLines(items, parent, &disposables); err != nil {
return nil, err
@@ -427,6 +429,12 @@ func (iv *interfaceView) apply(c *conf.Interface) {
} else {
iv.scripts.hide()
}
+
+ if c.TableOff {
+ iv.table.show(l18n.Sprintf("off"))
+ } else {
+ iv.table.hide()
+ }
}
func (pv *peerView) widgetsLines() []widgetsLine {
@@ -597,7 +605,7 @@ func (cv *ConfView) onToggleActiveClicked() {
}()
}
-func (cv *ConfView) onTunnelChanged(tunnel *manager.Tunnel, state manager.TunnelState, globalState manager.TunnelState, err error) {
+func (cv *ConfView) onTunnelChanged(tunnel *manager.Tunnel, state, globalState manager.TunnelState, err error) {
cv.Synchronize(func() {
cv.interfaze.toggleActive.updateGlobal(globalState)
if cv.tunnel != nil && cv.tunnel.Name == tunnel.Name {
@@ -620,7 +628,7 @@ func (cv *ConfView) onTunnelChanged(tunnel *manager.Tunnel, state manager.Tunnel
}
func (cv *ConfView) SetTunnel(tunnel *manager.Tunnel) {
- cv.tunnel = tunnel //XXX: This races with the read in the updateTicker, but it's pointer-sized!
+ cv.tunnel = tunnel // XXX: This races with the read in the updateTicker, but it's pointer-sized!
var config conf.Config
var state manager.TunnelState
diff --git a/ui/editdialog.go b/ui/editdialog.go
index 71b71150..45b25fd0 100644
--- a/ui/editdialog.go
+++ b/ui/editdialog.go
@@ -1,11 +1,12 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package ui
import (
+ "net/netip"
"strings"
"github.com/lxn/walk"
@@ -129,7 +130,7 @@ func newEditDialog(owner walk.Form, tunnel *manager.Tunnel) (*EditDialog, error)
return nil, err
}
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 or is to the wrong DNS server, with special exceptions for DHCP and NDP."))
+ 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, and the interface does not have table off, then the tunnel service engages a firewall ruleset to block all traffic that is neither to nor from the tunnel interface or is to the wrong DNS server, with special exceptions for DHCP and NDP."))
dlg.blockUntunneledTrafficCB.SetVisible(false)
dlg.blockUntunneledTrafficCB.CheckedChanged().Attach(dlg.onBlockUntunneledTrafficCBCheckedChanged)
@@ -185,15 +186,17 @@ func (dlg *EditDialog) onBlockUntunneledTrafficCBCheckedChanged() {
return
}
var (
- v40 = [4]byte{}
- v60 = [16]byte{}
- v48 = [4]byte{0x80}
- v68 = [16]byte{0x80}
+ v400 = netip.PrefixFrom(netip.IPv4Unspecified(), 0)
+ v600000 = netip.PrefixFrom(netip.IPv6Unspecified(), 0)
+ v401 = netip.PrefixFrom(netip.AddrFrom4([4]byte{}), 1)
+ v600001 = netip.PrefixFrom(netip.AddrFrom16([16]byte{}), 1)
+ v41281 = netip.PrefixFrom(netip.AddrFrom4([4]byte{0x80}), 1)
+ v680001 = netip.PrefixFrom(netip.AddrFrom16([16]byte{0x80}), 1)
)
block := dlg.blockUntunneledTrafficCB.Checked()
cfg, err := conf.FromWgQuick(dlg.syntaxEdit.Text(), "temporary")
- var newAllowedIPs []conf.IPCidr
+ var newAllowedIPs []netip.Prefix
if err != nil {
goto err
@@ -202,7 +205,7 @@ func (dlg *EditDialog) onBlockUntunneledTrafficCBCheckedChanged() {
goto err
}
- newAllowedIPs = make([]conf.IPCidr, 0, len(cfg.Peers[0].AllowedIPs))
+ newAllowedIPs = make([]netip.Prefix, 0, len(cfg.Peers[0].AllowedIPs))
if block {
var (
foundV401 bool
@@ -211,13 +214,13 @@ func (dlg *EditDialog) onBlockUntunneledTrafficCBCheckedChanged() {
foundV680001 bool
)
for _, allowedip := range cfg.Peers[0].AllowedIPs {
- if allowedip.Cidr == 1 && len(allowedip.IP) == 16 && allowedip.IP.Equal(v60[:]) {
+ if allowedip == v600001 {
foundV600001 = true
- } else if allowedip.Cidr == 1 && len(allowedip.IP) == 16 && allowedip.IP.Equal(v68[:]) {
+ } else if allowedip == v680001 {
foundV680001 = true
- } else if allowedip.Cidr == 1 && len(allowedip.IP) == 4 && allowedip.IP.Equal(v40[:]) {
+ } else if allowedip == v401 {
foundV401 = true
- } else if allowedip.Cidr == 1 && len(allowedip.IP) == 4 && allowedip.IP.Equal(v48[:]) {
+ } else if allowedip == v41281 {
foundV41281 = true
} else {
newAllowedIPs = append(newAllowedIPs, allowedip)
@@ -227,44 +230,44 @@ func (dlg *EditDialog) onBlockUntunneledTrafficCBCheckedChanged() {
goto err
}
if foundV401 && foundV41281 {
- newAllowedIPs = append(newAllowedIPs, conf.IPCidr{v40[:], 0})
+ newAllowedIPs = append(newAllowedIPs, v400)
} else if foundV401 {
- newAllowedIPs = append(newAllowedIPs, conf.IPCidr{v40[:], 1})
+ newAllowedIPs = append(newAllowedIPs, v401)
} else if foundV41281 {
- newAllowedIPs = append(newAllowedIPs, conf.IPCidr{v48[:], 1})
+ newAllowedIPs = append(newAllowedIPs, v41281)
}
if foundV600001 && foundV680001 {
- newAllowedIPs = append(newAllowedIPs, conf.IPCidr{v60[:], 0})
+ newAllowedIPs = append(newAllowedIPs, v600000)
} else if foundV600001 {
- newAllowedIPs = append(newAllowedIPs, conf.IPCidr{v60[:], 1})
+ newAllowedIPs = append(newAllowedIPs, v600001)
} else if foundV680001 {
- newAllowedIPs = append(newAllowedIPs, conf.IPCidr{v68[:], 1})
+ newAllowedIPs = append(newAllowedIPs, v680001)
}
cfg.Peers[0].AllowedIPs = newAllowedIPs
} else {
var (
- foundV400 bool
- foundV600 bool
+ foundV400 bool
+ foundV600000 bool
)
for _, allowedip := range cfg.Peers[0].AllowedIPs {
- if allowedip.Cidr == 0 && len(allowedip.IP) == 16 && allowedip.IP.Equal(v60[:]) {
- foundV600 = true
- } else if allowedip.Cidr == 0 && len(allowedip.IP) == 4 && allowedip.IP.Equal(v40[:]) {
+ if allowedip == v600000 {
+ foundV600000 = true
+ } else if allowedip == v400 {
foundV400 = true
} else {
newAllowedIPs = append(newAllowedIPs, allowedip)
}
}
- if !(foundV400 || foundV600) {
+ if !(foundV400 || foundV600000) {
goto err
}
if foundV400 {
- newAllowedIPs = append(newAllowedIPs, conf.IPCidr{v40[:], 1})
- newAllowedIPs = append(newAllowedIPs, conf.IPCidr{v48[:], 1})
+ newAllowedIPs = append(newAllowedIPs, v401)
+ newAllowedIPs = append(newAllowedIPs, v41281)
}
- if foundV600 {
- newAllowedIPs = append(newAllowedIPs, conf.IPCidr{v60[:], 1})
- newAllowedIPs = append(newAllowedIPs, conf.IPCidr{v68[:], 1})
+ if foundV600000 {
+ newAllowedIPs = append(newAllowedIPs, v600001)
+ newAllowedIPs = append(newAllowedIPs, v680001)
}
cfg.Peers[0].AllowedIPs = newAllowedIPs
}
diff --git a/ui/filesave.go b/ui/filesave.go
index 8cedec27..3a54f015 100644
--- a/ui/filesave.go
+++ b/ui/filesave.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package ui
@@ -24,7 +24,7 @@ func writeFileWithOverwriteHandling(owner walk.Form, filePath string, write func
return true
}
- file, err := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY|os.O_EXCL, 0600)
+ file, err := os.OpenFile(filePath, os.O_CREATE|os.O_WRONLY|os.O_EXCL, 0o600)
if err != nil {
if os.IsExist(err) {
if walk.DlgCmdNo == walk.MsgBox(owner, l18n.Sprintf("Writing file failed"), l18n.Sprintf(`File ‘%s’ already exists.
diff --git a/ui/iconprovider.go b/ui/iconprovider.go
index e3f810e3..154a1628 100644
--- a/ui/iconprovider.go
+++ b/ui/iconprovider.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package ui
@@ -121,6 +121,14 @@ func loadSystemIcon(dll string, index int32, size int) (icon *walk.Icon, err err
return
}
+func loadShieldIcon(size int) (icon *walk.Icon, err error) {
+ icon, err = loadSystemIcon("imageres", -1028, size)
+ if err != nil {
+ icon, err = loadSystemIcon("imageres", 1, size)
+ }
+ return
+}
+
var cachedLogoIconsForWidth = make(map[int]*walk.Icon)
func loadLogoIcon(size int) (icon *walk.Icon, err error) {
diff --git a/ui/listview.go b/ui/listview.go
index 13608b4e..609feb40 100644
--- a/ui/listview.go
+++ b/ui/listview.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package ui
@@ -32,7 +32,7 @@ func (t *ListModel) RowCount() int {
return len(t.tunnels)
}
-func (t *ListModel) Value(row, col int) interface{} {
+func (t *ListModel) Value(row, col int) any {
if col != 0 || row < 0 || row >= len(t.tunnels) {
return ""
}
@@ -181,7 +181,7 @@ func (tv *ListView) StyleCell(style *walk.CellStyle) {
}
}
-func (tv *ListView) onTunnelChange(tunnel *manager.Tunnel, state manager.TunnelState, globalState manager.TunnelState, err error) {
+func (tv *ListView) onTunnelChange(tunnel *manager.Tunnel, state, globalState manager.TunnelState, err error) {
tv.Synchronize(func() {
idx := -1
for i := range tv.model.tunnels {
diff --git a/ui/logpage.go b/ui/logpage.go
index 17c3c8f0..5b7681b3 100644
--- a/ui/logpage.go
+++ b/ui/logpage.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package ui
@@ -216,6 +216,6 @@ func newLogModel(lp *LogPage) *logModel {
return mdl
}
-func (mdl *logModel) Items() interface{} {
+func (mdl *logModel) Items() any {
return mdl.items
}
diff --git a/ui/managewindow.go b/ui/managewindow.go
index 74f205a9..30a1cedc 100644
--- a/ui/managewindow.go
+++ b/ui/managewindow.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package ui
@@ -161,7 +161,7 @@ func (mtw *ManageTunnelsWindow) updateProgressIndicator(globalState manager.Tunn
}
}
-func (mtw *ManageTunnelsWindow) onTunnelChange(tunnel *manager.Tunnel, state manager.TunnelState, globalState manager.TunnelState, err error) {
+func (mtw *ManageTunnelsWindow) onTunnelChange(tunnel *manager.Tunnel, state, globalState manager.TunnelState, err error) {
mtw.Synchronize(func() {
mtw.updateProgressIndicator(globalState)
@@ -179,7 +179,9 @@ func (mtw *ManageTunnelsWindow) UpdateFound() {
if mtw.updatePage != nil {
return
}
- mtw.SetTitle(l18n.Sprintf("%s (out of date)", mtw.Title()))
+ if IsAdmin {
+ 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 2d748a5c..3cea8a88 100644
--- a/ui/raise.go
+++ b/ui/raise.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package ui
@@ -55,7 +55,7 @@ func WaitForRaiseUIThenQuit() {
var handle win.HWINEVENTHOOK
runtime.LockOSThread()
defer runtime.UnlockOSThread()
- handle, err := win.SetWinEventHook(win.EVENT_OBJECT_CREATE, win.EVENT_OBJECT_CREATE, 0, func(hWinEventHook win.HWINEVENTHOOK, event uint32, hwnd win.HWND, idObject int32, idChild int32, idEventThread uint32, dwmsEventTime uint32) uintptr {
+ handle, err := win.SetWinEventHook(win.EVENT_OBJECT_CREATE, win.EVENT_OBJECT_CREATE, 0, func(hWinEventHook win.HWINEVENTHOOK, event uint32, hwnd win.HWND, idObject, idChild int32, idEventThread, dwmsEventTime uint32) uintptr {
class := make([]uint16, len(manageWindowWindowClass)+2) /* Plus 2, one for the null terminator, and one to see if this is only a prefix */
n, err := win.GetClassName(hwnd, &class[0], len(class))
if err != nil || n != len(manageWindowWindowClass) || windows.UTF16ToString(class) != manageWindowWindowClass {
diff --git a/ui/syntax/highlighter.go b/ui/syntax/highlighter.go
index d49cab32..099a23b0 100644
--- a/ui/syntax/highlighter.go
+++ b/ui/syntax/highlighter.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*
* This is a direct translation of the original C, and for that reason, it's pretty unusual Go code:
* https://git.zx2c4.com/wireguard-tools/tree/contrib/highlighter/highlighter.c
@@ -26,6 +26,7 @@ const (
highlightKeepalive
highlightComment
highlightDelimiter
+ highlightTable
highlightCmd
highlightError
)
@@ -61,7 +62,7 @@ type stringSpan struct {
}
func (s stringSpan) at(i int) *byte {
- return (*byte)(unsafe.Pointer(uintptr(unsafe.Pointer(s.s)) + uintptr(i)))
+ return (*byte)(unsafe.Add(unsafe.Pointer(s.s), uintptr(i)))
}
func (s stringSpan) isSame(c string) bool {
@@ -221,7 +222,7 @@ func (s stringSpan) isValidIPv6() bool {
return true
}
-func (s stringSpan) isValidUint(supportHex bool, min uint64, max uint64) bool {
+func (s stringSpan) isValidUint(supportHex bool, min, max uint64) bool {
// Bound this around 32 bits, so that we don't have to write overflow logic.
if s.len > 10 || s.len == 0 {
return false
@@ -256,6 +257,10 @@ func (s stringSpan) isValidMTU() bool {
return s.isValidUint(false, 576, 65535)
}
+func (s stringSpan) isValidTable() bool {
+ return s.isSame("off") || s.isSame("auto") || s.isSame("main") || s.isValidUint(false, 0, (1<<32)-1)
+}
+
func (s stringSpan) isValidPersistentKeepAlive() bool {
if s.isSame("off") {
return true
@@ -360,6 +365,7 @@ const (
fieldAddress
fieldDNS
fieldMTU
+ fieldTable
fieldPreUp
fieldPostUp
fieldPreDown
@@ -395,6 +401,8 @@ func (s stringSpan) field() field {
return fieldDNS
case s.isCaselessSame("MTU"):
return fieldMTU
+ case s.isCaselessSame("Table"):
+ return fieldTable
case s.isCaselessSame("PublicKey"):
return fieldPublicKey
case s.isCaselessSame("PresharedKey"):
@@ -436,7 +444,7 @@ func (hsa *highlightSpanArray) append(o *byte, s stringSpan, t highlight) {
*hsa = append(*hsa, highlightSpan{t, int((uintptr(unsafe.Pointer(s.s))) - (uintptr(unsafe.Pointer(o)))), s.len})
}
-func (hsa *highlightSpanArray) highlightMultivalueValue(parent stringSpan, s stringSpan, section field) {
+func (hsa *highlightSpanArray) highlightMultivalueValue(parent, s stringSpan, section field) {
switch section {
case fieldDNS:
if s.isValidIPv4() || s.isValidIPv6() {
@@ -469,7 +477,7 @@ func (hsa *highlightSpanArray) highlightMultivalueValue(parent stringSpan, s str
}
}
-func (hsa *highlightSpanArray) highlightMultivalue(parent stringSpan, s stringSpan, section field) {
+func (hsa *highlightSpanArray) highlightMultivalue(parent, s stringSpan, section field) {
currentSpan := stringSpan{s.s, 0}
lenAtLastSpace := 0
for i := 0; i < s.len; i++ {
@@ -498,7 +506,7 @@ func (hsa *highlightSpanArray) highlightMultivalue(parent stringSpan, s stringSp
}
}
-func (hsa *highlightSpanArray) highlightValue(parent stringSpan, s stringSpan, section field) {
+func (hsa *highlightSpanArray) highlightValue(parent, s stringSpan, section field) {
switch section {
case fieldPrivateKey:
hsa.append(parent.s, s, validateHighlight(s.isValidKey(), highlightPrivateKey))
@@ -508,6 +516,8 @@ func (hsa *highlightSpanArray) highlightValue(parent stringSpan, s stringSpan, s
hsa.append(parent.s, s, validateHighlight(s.isValidKey(), highlightPresharedKey))
case fieldMTU:
hsa.append(parent.s, s, validateHighlight(s.isValidMTU(), highlightMTU))
+ case fieldTable:
+ hsa.append(parent.s, s, validateHighlight(s.isValidTable(), highlightTable))
case fieldPreUp, fieldPostUp, fieldPreDown, fieldPostDown:
hsa.append(parent.s, s, validateHighlight(s.isValidPrePostUpDown(), highlightCmd))
case fieldListenPort:
diff --git a/ui/syntax/syntaxedit.go b/ui/syntax/syntaxedit.go
index 26cd533f..a3c94d86 100644
--- a/ui/syntax/syntaxedit.go
+++ b/ui/syntax/syntaxedit.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package syntax
@@ -90,26 +90,29 @@ type spanStyle struct {
}
var stylemap = map[highlight]spanStyle{
- highlightSection: spanStyle{color: win.RGB(0x32, 0x6D, 0x74), effects: win.CFE_BOLD},
- highlightField: spanStyle{color: win.RGB(0x9B, 0x23, 0x93), effects: win.CFE_BOLD},
- highlightPrivateKey: spanStyle{color: win.RGB(0x64, 0x38, 0x20)},
- highlightPublicKey: spanStyle{color: win.RGB(0x64, 0x38, 0x20)},
- highlightPresharedKey: spanStyle{color: win.RGB(0x64, 0x38, 0x20)},
- highlightIP: spanStyle{color: win.RGB(0x0E, 0x0E, 0xFF)},
- highlightCidr: spanStyle{color: win.RGB(0x81, 0x5F, 0x03)},
- highlightHost: spanStyle{color: win.RGB(0x0E, 0x0E, 0xFF)},
- highlightPort: spanStyle{color: win.RGB(0x81, 0x5F, 0x03)},
- highlightMTU: spanStyle{color: win.RGB(0x1C, 0x00, 0xCF)},
- highlightKeepalive: spanStyle{color: win.RGB(0x1C, 0x00, 0xCF)},
- highlightComment: spanStyle{color: win.RGB(0x53, 0x65, 0x79), effects: win.CFE_ITALIC},
- highlightDelimiter: spanStyle{color: win.RGB(0x00, 0x00, 0x00)},
- highlightCmd: spanStyle{color: win.RGB(0x63, 0x75, 0x89)},
- highlightError: spanStyle{color: win.RGB(0xC4, 0x1A, 0x16), effects: win.CFE_UNDERLINE},
+ highlightSection: {color: win.RGB(0x32, 0x6D, 0x74), effects: win.CFE_BOLD},
+ highlightField: {color: win.RGB(0x9B, 0x23, 0x93), effects: win.CFE_BOLD},
+ highlightPrivateKey: {color: win.RGB(0x64, 0x38, 0x20)},
+ highlightPublicKey: {color: win.RGB(0x64, 0x38, 0x20)},
+ highlightPresharedKey: {color: win.RGB(0x64, 0x38, 0x20)},
+ highlightIP: {color: win.RGB(0x0E, 0x0E, 0xFF)},
+ highlightCidr: {color: win.RGB(0x81, 0x5F, 0x03)},
+ highlightHost: {color: win.RGB(0x0E, 0x0E, 0xFF)},
+ highlightPort: {color: win.RGB(0x81, 0x5F, 0x03)},
+ highlightMTU: {color: win.RGB(0x1C, 0x00, 0xCF)},
+ highlightTable: {color: win.RGB(0x1C, 0x00, 0xCF)},
+ highlightKeepalive: {color: win.RGB(0x1C, 0x00, 0xCF)},
+ highlightComment: {color: win.RGB(0x53, 0x65, 0x79), effects: win.CFE_ITALIC},
+ highlightDelimiter: {color: win.RGB(0x00, 0x00, 0x00)},
+ highlightCmd: {color: win.RGB(0x63, 0x75, 0x89)},
+ highlightError: {color: win.RGB(0xC4, 0x1A, 0x16), effects: win.CFE_UNDERLINE},
}
func (se *SyntaxEdit) evaluateUntunneledBlocking(cfg string, spans []highlightSpan) {
state := InevaluableBlockingUntunneledTraffic
var onAllowedIPs,
+ onTable,
+ tableOff,
seenPeer,
seen00v6,
seen00v4,
@@ -132,10 +135,13 @@ func (se *SyntaxEdit) evaluateUntunneledBlocking(cfg string, spans []highlightSp
} else {
goto done
}
- break
case highlightField:
onAllowedIPs = strings.EqualFold(cfg[span.s:span.s+span.len], "AllowedIPs")
- break
+ onTable = strings.EqualFold(cfg[span.s:span.s+span.len], "Table")
+ case highlightTable:
+ if onTable {
+ tableOff = cfg[span.s:span.s+span.len] == "off"
+ }
case highlightIP:
if !onAllowedIPs || !seenPeer {
break
@@ -166,9 +172,11 @@ func (se *SyntaxEdit) evaluateUntunneledBlocking(cfg string, spans []highlightSp
seen80001v6 = true
}
}
- break
}
}
+ if tableOff {
+ return
+ }
if seen00v4 || seen00v6 {
state = BlockingUntunneledTraffic
@@ -469,10 +477,10 @@ func NewSyntaxEdit(parent walk.Container) (*SyntaxEdit, error) {
se.GraphicsEffects().Add(walk.InteractionEffect)
se.GraphicsEffects().Add(walk.FocusEffect)
se.MustRegisterProperty("Text", walk.NewProperty(
- func() interface{} {
+ func() any {
return se.Text()
},
- func(v interface{}) error {
+ func(v any) error {
if s, ok := v.(string); ok {
return se.SetText(s)
}
diff --git a/ui/tray.go b/ui/tray.go
index 34e4b003..7771c966 100644
--- a/ui/tray.go
+++ b/ui/tray.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package ui
@@ -252,7 +252,7 @@ func (tray *Tray) rebalanceTunnelsMenu() {
}
}
-func (tray *Tray) onTunnelChange(tunnel *manager.Tunnel, state manager.TunnelState, globalState manager.TunnelState, err error) {
+func (tray *Tray) onTunnelChange(tunnel *manager.Tunnel, state, globalState manager.TunnelState, err error) {
tray.mtw.Synchronize(func() {
tray.updateGlobalState(globalState)
if err == nil {
@@ -343,7 +343,7 @@ func (tray *Tray) setTunnelState(tunnel *manager.Tunnel, state manager.TunnelSta
func (tray *Tray) UpdateFound() {
action := walk.NewAction()
action.SetText(l18n.Sprintf("An Update is Available!"))
- menuIcon, _ := loadSystemIcon("imageres", 1, 16)
+ menuIcon, _ := loadShieldIcon(16)
action.SetImage(menuIcon)
action.SetDefault(true)
showUpdateTab := func() {
@@ -358,7 +358,7 @@ func (tray *Tray) UpdateFound() {
tray.ContextMenu().Actions().Insert(tray.ContextMenu().Actions().Len()-2, action)
showUpdateBalloon := func() {
- icon, _ := loadSystemIcon("imageres", 1, 128)
+ icon, _ := loadShieldIcon(128)
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)
}
diff --git a/ui/tunnelspage.go b/ui/tunnelspage.go
index 10bf2f8e..d104f598 100644
--- a/ui/tunnelspage.go
+++ b/ui/tunnelspage.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package ui
@@ -91,8 +91,9 @@ func NewTunnelsPage() (*TunnelsPage, error) {
if err != nil {
return nil, err
}
- controlsContainer.SetLayout(walk.NewHBoxLayout())
- controlsContainer.Layout().SetMargins(walk.Margins{})
+ hlayout = walk.NewHBoxLayout()
+ hlayout.SetMargins(walk.Margins{})
+ controlsContainer.SetLayout(hlayout)
walk.NewHSpacer(controlsContainer)
@@ -279,7 +280,7 @@ func (tp *TunnelsPage) updateConfView() {
func (tp *TunnelsPage) importFiles(paths []string) {
go func() {
- syncedMsgBox := func(title string, message string, flags walk.MsgBoxStyle) {
+ syncedMsgBox := func(title, message string, flags walk.MsgBoxStyle) {
tp.Synchronize(func() {
walk.MsgBox(tp.Form(), title, message, flags)
})
@@ -421,7 +422,6 @@ func (tp *TunnelsPage) addTunnel(config *conf.Config) {
if err != nil {
showErrorCustom(tp.Form(), l18n.Sprintf("Unable to create tunnel"), err.Error())
}
-
}
// Handlers
@@ -518,7 +518,6 @@ func (tp *TunnelsPage) onDelete() {
tunnelsToDelete := make([]manager.Tunnel, len(indices))
for i, j := range indices {
tunnelsToDelete[i] = tp.listView.model.tunnels[j]
-
}
go func() {
tp.listView.SetSuspendTunnelsUpdate(true)
diff --git a/ui/ui.go b/ui/ui.go
index 55b846fc..569fc8ae 100644
--- a/ui/ui.go
+++ b/ui/ui.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package ui
@@ -20,10 +20,12 @@ import (
"golang.zx2c4.com/wireguard/windows/version"
)
-var noTrayAvailable = false
-var shouldQuitManagerWhenExiting = false
-var startTime = time.Now()
-var IsAdmin = false // A global, because this really is global for the process
+var (
+ noTrayAvailable = false
+ shouldQuitManagerWhenExiting = false
+ startTime = time.Now()
+ IsAdmin = false // A global, because this really is global for the process
+)
func RunUI() {
runtime.LockOSThread()
@@ -73,7 +75,7 @@ func RunUI() {
switch updateState {
case manager.UpdateStateFoundUpdate:
mtw.UpdateFound()
- if tray != nil {
+ if tray != nil && IsAdmin {
tray.UpdateFound()
}
case manager.UpdateStateUpdatesDisabledUnofficialBuild:
diff --git a/ui/updatepage.go b/ui/updatepage.go
index 88992ced..ff2bbe5f 100644
--- a/ui/updatepage.go
+++ b/ui/updatepage.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package ui
@@ -31,7 +31,7 @@ func NewUpdatePage() (*UpdatePage, error) {
up.SetTitle(l18n.Sprintf("An Update is Available!"))
- tabIcon, _ := loadSystemIcon("imageres", 1, 16)
+ tabIcon, _ := loadShieldIcon(16)
up.SetImage(tabIcon)
up.SetLayout(walk.NewVBoxLayout())
@@ -64,6 +64,12 @@ func NewUpdatePage() (*UpdatePage, error) {
button.SetImage(updateIcon)
button.SetText(l18n.Sprintf("Update Now"))
+ if !IsAdmin {
+ button.SetText(l18n.Sprintf("Please ask the system administrator to update."))
+ button.SetEnabled(false)
+ status.SetText(l18n.Sprintf("Status: Waiting for administrator"))
+ }
+
walk.NewVSpacer(up)
switchToUpdatingState := func() {
diff --git a/updater/authenticode.go b/updater/authenticode.go
index d6d80df5..1e0a25c0 100644
--- a/updater/authenticode.go
+++ b/updater/authenticode.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package updater
@@ -27,5 +27,8 @@ func verifyAuthenticode(path string) bool {
FilePath: path16,
}),
}
- return windows.WinVerifyTrustEx(windows.InvalidHWND, &windows.WINTRUST_ACTION_GENERIC_VERIFY_V2, data) == nil
+ verified := windows.WinVerifyTrustEx(windows.InvalidHWND, &windows.WINTRUST_ACTION_GENERIC_VERIFY_V2, data) == nil
+ data.StateAction = windows.WTD_STATEACTION_CLOSE
+ windows.WinVerifyTrustEx(windows.InvalidHWND, &windows.WINTRUST_ACTION_GENERIC_VERIFY_V2, data)
+ return verified
}
diff --git a/updater/constants.go b/updater/constants.go
index 04b972fe..cf0ced92 100644
--- a/updater/constants.go
+++ b/updater/constants.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package updater
diff --git a/updater/downloader.go b/updater/downloader.go
index b8b2763d..bf28db54 100644
--- a/updater/downloader.go
+++ b/updater/downloader.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package updater
diff --git a/updater/msirunner.go b/updater/msirunner.go
index 13495f46..ec6b1bd3 100644
--- a/updater/msirunner.go
+++ b/updater/msirunner.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package updater
@@ -38,7 +38,7 @@ func (t *tempFile) Delete() error {
if err != nil {
return err
}
- return windows.DeleteFile(name16) //TODO: how does this deal with reparse points?
+ return windows.DeleteFile(name16) // TODO: how does this deal with reparse points?
}
disposition := byte(1)
err := windows.SetFileInformationByHandle(t.originalHandle, windows.FileDispositionInfo, &disposition, 1)
diff --git a/updater/signify.go b/updater/signify.go
index eef9198a..de50fcba 100644
--- a/updater/signify.go
+++ b/updater/signify.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package updater
@@ -53,17 +53,17 @@ func readFileList(input []byte) (fileList, error) {
if len(line) == 0 && index == len(fileLines)-1 {
break
}
- components := strings.SplitN(line, " ", 2)
- if len(components) != 2 {
+ first, second, ok := strings.Cut(line, " ")
+ if !ok {
return nil, errors.New("File hash line has too few components")
}
- maybeHash, err := hex.DecodeString(components[0])
+ maybeHash, err := hex.DecodeString(first)
if err != nil || len(maybeHash) != blake2b.Size256 {
return nil, errors.New("File hash is invalid base64 or incorrect number of bytes")
}
var hash [blake2b.Size256]byte
copy(hash[:], maybeHash)
- fileHashes[components[1]] = hash
+ fileHashes[second] = hash
}
if len(fileHashes) == 0 {
return nil, errors.New("No file hashes found in signed input")
diff --git a/updater/updater_test.go b/updater/updater_test.go
index a90b13cb..809262bd 100644
--- a/updater/updater_test.go
+++ b/updater/updater_test.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package updater
diff --git a/updater/versions.go b/updater/versions.go
index 5b42a748..dfc4c665 100644
--- a/updater/versions.go
+++ b/updater/versions.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package updater
diff --git a/updater/winhttp/mksyscall.go b/updater/winhttp/mksyscall.go
index 1daedb08..54c06e85 100644
--- a/updater/winhttp/mksyscall.go
+++ b/updater/winhttp/mksyscall.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package winhttp
diff --git a/updater/winhttp/syscall_windows.go b/updater/winhttp/syscall_windows.go
index 77e733e6..4f967bfa 100644
--- a/updater/winhttp/syscall_windows.go
+++ b/updater/winhttp/syscall_windows.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package winhttp
@@ -256,6 +256,16 @@ const (
_INTERNET_SCHEME_FTP = 3
_INTERNET_SCHEME_SOCKS = 4
+ _WINHTTP_FLAG_SECURE_PROTOCOL_SSL2 = 0x00000008
+ _WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 = 0x00000020
+ _WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 = 0x00000080
+ _WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 = 0x00000200
+ _WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2 = 0x00000800
+ _WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_3 = 0x00002000
+ _WINHTTP_FLAG_SECURE_PROTOCOL_ALL = _WINHTTP_FLAG_SECURE_PROTOCOL_SSL2 | _WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 | _WINHTTP_FLAG_SECURE_PROTOCOL_TLS1
+
+ _WINHTTP_PROTOCOL_FLAG_HTTP2 = 0x1
+
_WINHTTP_ERROR_BASE = 12000
_ERROR_WINHTTP_OUT_OF_HANDLES = Error(12000 + 1)
_ERROR_WINHTTP_TIMEOUT = Error(12000 + 2)
diff --git a/updater/winhttp/winhttp.go b/updater/winhttp/winhttp.go
index ac390a4f..cb19f194 100644
--- a/updater/winhttp/winhttp.go
+++ b/updater/winhttp/winhttp.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package winhttp
@@ -21,11 +21,13 @@ import (
type Session struct {
handle _HINTERNET
}
+
type Connection struct {
handle _HINTERNET
session *Session
https bool
}
+
type Response struct {
handle _HINTERNET
connection *Connection
@@ -48,6 +50,11 @@ func isWin7() bool {
return maj < 6 || (maj == 6 && min <= 1)
}
+func isWin8DotZeroOrBelow() bool {
+ maj, min, _ := windows.RtlGetNtVersionNumbers()
+ return maj < 6 || (maj == 6 && min <= 2)
+}
+
func NewSession(userAgent string) (session *Session, err error) {
session = new(Session)
defer convertError(&err)
@@ -69,9 +76,17 @@ func NewSession(userAgent string) (session *Session, err error) {
if err != nil {
return
}
- var enableHttp2 uint32 = 1
+ var enableHttp2 uint32 = _WINHTTP_PROTOCOL_FLAG_HTTP2
_ = winHttpSetOption(session.handle, _WINHTTP_OPTION_ENABLE_HTTP_PROTOCOL, unsafe.Pointer(&enableHttp2), uint32(unsafe.Sizeof(enableHttp2))) // Don't check return value, in case of old Windows
+ if isWin8DotZeroOrBelow() {
+ var enableTLS12 uint32 = _WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2
+ err = winHttpSetOption(session.handle, _WINHTTP_OPTION_SECURE_PROTOCOLS, unsafe.Pointer(&enableTLS12), uint32(unsafe.Sizeof(enableTLS12)))
+ if err != nil {
+ return
+ }
+ }
+
runtime.SetFinalizer(session, func(session *Session) {
session.Close()
})
diff --git a/updater/winhttp/winhttp_test.go b/updater/winhttp/winhttp_test.go
index 41fbeb6b..36017a48 100644
--- a/updater/winhttp/winhttp_test.go
+++ b/updater/winhttp/winhttp_test.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package winhttp
diff --git a/version/certificate_test.go b/version/certificate_test.go
index 677e6fdc..724c524f 100644
--- a/version/certificate_test.go
+++ b/version/certificate_test.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package version
diff --git a/version/official.go b/version/official.go
index 5998124c..2951c893 100644
--- a/version/official.go
+++ b/version/official.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package version
@@ -19,7 +19,7 @@ const (
policyExtensionOid = "2.5.29.32"
)
-// These are easily by-passable checks, which do not serve serve security purposes.
+// These are easily by-passable checks, which do not serve security purposes.
// DO NOT PLACE SECURITY-SENSITIVE FUNCTIONS IN THIS FILE
func IsRunningOfficialVersion() bool {
@@ -101,7 +101,7 @@ func extractCertificateNames(path string) ([]string, error) {
return names, nil
}
-func extractCertificatePolicies(path string, oid string) ([]string, error) {
+func extractCertificatePolicies(path, oid string) ([]string, error) {
path16, err := windows.UTF16PtrFromString(path)
if err != nil {
return nil, err
@@ -129,8 +129,7 @@ func extractCertificatePolicies(path string, oid string) ([]string, error) {
if cert == nil {
break
}
- ci := (*windows.CertInfo)(unsafe.Pointer(cert.CertInfo))
- ext := windows.CertFindExtension(oid8, ci.CountExtensions, ci.Extensions)
+ ext := windows.CertFindExtension(oid8, cert.CertInfo.CountExtensions, cert.CertInfo.Extensions)
if ext == nil {
continue
}
@@ -146,7 +145,7 @@ func extractCertificatePolicies(path string, oid string) ([]string, error) {
return nil, err
}
for i := uintptr(0); i < uintptr(certPoliciesInfo.Count); i++ {
- cp := (*windows.CertPolicyInfo)(unsafe.Pointer(uintptr(unsafe.Pointer(certPoliciesInfo.PolicyInfos)) + i*unsafe.Sizeof(*certPoliciesInfo.PolicyInfos)))
+ cp := (*windows.CertPolicyInfo)(unsafe.Add(unsafe.Pointer(certPoliciesInfo.PolicyInfos), i*unsafe.Sizeof(*certPoliciesInfo.PolicyInfos)))
policies = append(policies, windows.BytePtrToString(cp.Identifier))
}
}
diff --git a/version/os.go b/version/os.go
index fd6ae475..ff9188bb 100644
--- a/version/os.go
+++ b/version/os.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package version
diff --git a/version/protocol.go b/version/protocol.go
deleted file mode 100644
index 72a35e95..00000000
--- a/version/protocol.go
+++ /dev/null
@@ -1,28 +0,0 @@
-/* SPDX-License-Identifier: MIT
- *
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
- */
-
-package version
-
-import (
- "runtime/debug"
- "strings"
-)
-
-func ProtoImplementation() string {
- info, ok := debug.ReadBuildInfo()
- if !ok {
- return "unknown"
- }
- for _, dep := range info.Deps {
- if dep.Path == "golang.zx2c4.com/wireguard" {
- parts := strings.Split(dep.Version, "-")
- if len(parts) == 3 && len(parts[2]) == 12 {
- return parts[2][:7]
- }
- return dep.Version
- }
- }
- return "unknown"
-}
diff --git a/version/useragent.go b/version/useragent.go
index 698e185b..3b5240c6 100644
--- a/version/useragent.go
+++ b/version/useragent.go
@@ -1,6 +1,6 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package version
diff --git a/version/version.go b/version/version.go
index b2405e59..a7f908e8 100644
--- a/version/version.go
+++ b/version/version.go
@@ -1,10 +1,10 @@
/* SPDX-License-Identifier: MIT
*
- * Copyright (C) 2019-2021 WireGuard LLC. All Rights Reserved.
+ * Copyright (C) 2019-2022 WireGuard LLC. All Rights Reserved.
*/
package version
const (
- Number = "0.3.9"
+ Number = "0.5.3"
)
diff --git a/zgotext.go b/zgotext.go
index b4baa53c..376c6c8d 100644
--- a/zgotext.go
+++ b/zgotext.go
@@ -27,21 +27,30 @@ func (d *dictionary) Lookup(key string) (data string, ok bool) {
func init() {
dict := map[string]catalog.Dictionary{
+ "ca": &dictionary{index: caIndex, data: caData},
+ "cs": &dictionary{index: csIndex, data: csData},
"de": &dictionary{index: deIndex, data: deData},
"en": &dictionary{index: enIndex, data: enData},
"es_ES": &dictionary{index: es_ESIndex, data: es_ESData},
+ "et": &dictionary{index: etIndex, data: etData},
"fa": &dictionary{index: faIndex, data: faData},
"fi": &dictionary{index: fiIndex, data: fiData},
"fr": &dictionary{index: frIndex, data: frData},
"id": &dictionary{index: idIndex, data: idData},
"it": &dictionary{index: itIndex, data: itData},
"ja": &dictionary{index: jaIndex, data: jaData},
+ "ko": &dictionary{index: koIndex, data: koData},
+ "nl": &dictionary{index: nlIndex, data: nlData},
"pa_IN": &dictionary{index: pa_INIndex, data: pa_INData},
"pl": &dictionary{index: plIndex, data: plData},
+ "pt_BR": &dictionary{index: pt_BRIndex, data: pt_BRData},
"ro": &dictionary{index: roIndex, data: roData},
"ru": &dictionary{index: ruIndex, data: ruData},
+ "si_LK": &dictionary{index: si_LKIndex, data: si_LKData},
"sk": &dictionary{index: skIndex, data: skData},
"sl": &dictionary{index: slIndex, data: slData},
+ "sv_SE": &dictionary{index: sv_SEIndex, data: sv_SEData},
+ "tr": &dictionary{index: trIndex, data: trData},
"uk": &dictionary{index: ukIndex, data: ukData},
"vi": &dictionary{index: viIndex, data: viData},
"zh_CN": &dictionary{index: zh_CNIndex, data: zh_CNData},
@@ -64,181 +73,461 @@ var messageKeyToIndex = map[string]int{
"%d hour(s)": 14,
"%d minute(s)": 15,
"%d second(s)": 16,
- "%d tunnels were unable to be removed.": 161,
+ "%d tunnels were unable to be removed.": 157,
"%d year(s)": 12,
"%d\u00a0B": 18,
- "%s\n\nPlease consult the log for more information.": 113,
- "%s (out of date)": 114,
- "%s (unsigned build, no updates)": 166,
- "%s You cannot undo this action.": 157,
+ "%s\n\nPlease consult the log for more information.": 108,
+ "%s (out of date)": 109,
+ "%s (unsigned build, no updates)": 162,
+ "%s You cannot undo this action.": 153,
"%s ago": 17,
- "%s received, %s sent": 73,
+ "%s received, %s sent": 69,
"%s: %q": 23,
- "&About WireGuard…": 111,
- "&Activate": 58,
- "&Block untunneled traffic (kill-switch)": 84,
- "&Configuration:": 88,
- "&Copy": 104,
- "&Deactivate": 57,
- "&Edit": 135,
- "&Import tunnel(s) from file…": 121,
- "&Manage tunnels…": 120,
- "&Name:": 81,
- "&Public key:": 82,
- "&Remove selected tunnel(s)": 143,
- "&Save": 86,
- "&Save to file…": 106,
- "&Toggle": 140,
- "&Tunnels": 179,
+ "&About WireGuard…": 106,
+ "&Activate": 50,
+ "&Block untunneled traffic (kill-switch)": 80,
+ "&Configuration:": 83,
+ "&Copy": 99,
+ "&Deactivate": 49,
+ "&Edit": 131,
+ "&Import tunnel(s) from file…": 116,
+ "&Manage tunnels…": 115,
+ "&Name:": 77,
+ "&Public key:": 78,
+ "&Remove selected tunnel(s)": 139,
+ "&Save": 81,
+ "&Save to file…": 101,
+ "&Toggle": 136,
+ "&Tunnels": 118,
"(no argument): elevate and install manager service": 1,
- "(unknown)": 83,
- "A name is required.": 90,
- "A tunnel was unable to be removed: %s": 159,
- "About WireGuard": 51,
- "Activating": 99,
- "Active": 98,
- "Add &empty tunnel…": 136,
- "Add Tunnel": 137,
- "Addresses:": 62,
- "Addresses: %s": 130,
- "Addresses: None": 119,
- "All peers must have public keys": 44,
- "Allowed IPs:": 66,
- "An Update is Available!": 131,
- "An interface must have a private key": 42,
- "An update to WireGuard is available. It is highly advisable to update without delay.": 169,
- "An update to WireGuard is now available. You are advised to update as soon as possible.": 133,
- "Another tunnel already exists with the name ‘%s’": 147,
- "Another tunnel already exists with the name ‘%s’.": 94,
- "App version: %s\nGo backend version: %s\nGo version: %s-%s\nOperating system: %s\nArchitecture: %s": 53,
- "Are you sure you would like to delete %d tunnels?": 154,
- "Are you sure you would like to delete tunnel ‘%s’?": 156,
- "Brackets must contain an IPv6 address": 28,
- "Cancel": 87,
- "Close": 54,
- "Command Line Options": 3,
- "Config key is missing an equals separator": 38,
- "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*": 162,
- "Configuration ZIP Files (*.zip)|*.zip": 164,
- "Could not enumerate existing tunnels: %v": 146,
- "Could not import selected configuration: %v": 145,
- "Create new tunnel": 79,
- "DNS servers:": 63,
- "Deactivating": 101,
- "Delete %d tunnels": 153,
- "Delete tunnel ‘%s’": 155,
- "E&xit": 122,
- "Edit &selected tunnel…": 142,
- "Edit tunnel": 80,
- "Endpoint:": 67,
- "Error": 0,
- "Error Exiting WireGuard": 167,
- "Error in getting configuration": 45,
- "Error: %v. Please try again.": 173,
- "Export all tunnels to &zip…": 141,
- "Export all tunnels to zip": 139,
- "Export log to file": 110,
- "Export tunnels to zip": 165,
- "Failed to activate tunnel": 75,
- "Failed to deactivate tunnel": 76,
- "Failed to determine tunnel state": 74,
- "File ‘%s’ already exists.\n\nDo you want to overwrite it?": 97,
- "Import tunnel(s) from file": 163,
- "Imported %d of %d tunnels": 151,
- "Imported %d tunnels": 150,
- "Imported tunnels": 149,
- "Inactive": 100,
- "Interface: %s": 77,
- "Invalid IP address": 24,
- "Invalid MTU": 29,
- "Invalid endpoint host": 27,
- "Invalid key for [Interface] section": 40,
- "Invalid key for [Peer] section": 41,
- "Invalid key for interface section": 46,
- "Invalid key for peer section": 48,
- "Invalid key: %v": 32,
- "Invalid name": 89,
- "Invalid network prefix length": 25,
- "Invalid persistent keepalive": 31,
- "Invalid port": 30,
- "Key must have a value": 39,
- "Keys must decode to exactly 32 bytes": 33,
- "Latest handshake:": 69,
- "Line must occur in a section": 37,
- "Listen port:": 60,
- "Log": 103,
- "Log message": 108,
- "MTU:": 61,
- "Missing port from endpoint": 26,
- "Now": 10,
- "Number must be a number between 0 and 2^64-1: %v": 34,
- "Peer": 78,
- "Persistent keepalive:": 68,
- "Preshared key:": 65,
- "Protocol version must be 1": 47,
- "Public key:": 59,
- "Remove selected tunnel(s)": 138,
- "Scripts:": 64,
- "Select &all": 105,
- "Status:": 56,
- "Status: %s": 129,
- "Status: Complete!": 174,
- "Status: Unknown": 118,
- "Status: Waiting for updater service": 172,
- "Status: Waiting for user": 170,
- "System clock wound backward!": 11,
- "Text Files (*.txt)|*.txt|All Files (*.*)|*.*": 109,
- "The %s tunnel has been activated.": 124,
- "The %s tunnel has been deactivated.": 126,
- "Time": 107,
- "Transfer:": 70,
- "Tunnel Error": 112,
- "Tunnel already exists": 93,
- "Tunnel name is not valid": 36,
- "Tunnel name ‘%s’ is invalid.": 91,
- "Tunnels": 134,
- "Two commas in a row": 35,
- "Unable to create new configuration": 95,
- "Unable to create tunnel": 152,
- "Unable to delete tunnel": 158,
- "Unable to delete tunnels": 160,
+ "(unknown)": 79,
+ "A name is required.": 85,
+ "A tunnel was unable to be removed: %s": 155,
+ "About WireGuard": 44,
+ "Activating": 94,
+ "Active": 93,
+ "Add &empty tunnel…": 132,
+ "Add Tunnel": 133,
+ "Addresses:": 54,
+ "Addresses: %s": 126,
+ "Addresses: None": 114,
+ "All peers must have public keys": 41,
+ "Allowed IPs:": 58,
+ "An Update is Available!": 127,
+ "An interface must have a private key": 39,
+ "An update to WireGuard is available. It is highly advisable to update without delay.": 165,
+ "An update to WireGuard is now available. You are advised to update as soon as possible.": 129,
+ "Another tunnel already exists with the name ‘%s’": 143,
+ "Another tunnel already exists with the name ‘%s’.": 89,
+ "App version: %s\nDriver version: %s\nGo version: %s\nOperating system: %s\nArchitecture: %s": 173,
+ "Are you sure you would like to delete %d tunnels?": 150,
+ "Are you sure you would like to delete tunnel ‘%s’?": 152,
+ "Brackets must contain an IPv6 address": 26,
+ "Cancel": 82,
+ "Close": 46,
+ "Command Line Options": 3,
+ "Config key is missing an equals separator": 35,
+ "Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*": 158,
+ "Configuration ZIP Files (*.zip)|*.zip": 160,
+ "Could not enumerate existing tunnels: %v": 142,
+ "Could not import selected configuration: %v": 141,
+ "Create new tunnel": 75,
+ "DNS servers:": 55,
+ "Deactivating": 96,
+ "Delete %d tunnels": 149,
+ "Delete tunnel ‘%s’": 151,
+ "E&xit": 117,
+ "Edit &selected tunnel…": 138,
+ "Edit tunnel": 76,
+ "Endpoint:": 59,
+ "Error": 0,
+ "Error Exiting WireGuard": 163,
+ "Error: ": 171,
+ "Error: %v. Please try again.": 169,
+ "Export all tunnels to &zip…": 137,
+ "Export all tunnels to zip": 135,
+ "Export log to file": 105,
+ "Export tunnels to zip": 161,
+ "Failed to activate tunnel": 71,
+ "Failed to deactivate tunnel": 72,
+ "Failed to determine tunnel state": 70,
+ "File ‘%s’ already exists.\n\nDo you want to overwrite it?": 92,
+ "Import tunnel(s) from file": 159,
+ "Imported %d of %d tunnels": 147,
+ "Imported %d tunnels": 146,
+ "Imported tunnels": 145,
+ "Inactive": 95,
+ "Interface: %s": 73,
+ "Invalid IP address: ": 172,
+ "Invalid MTU": 27,
+ "Invalid endpoint host": 25,
+ "Invalid key for [Interface] section": 37,
+ "Invalid key for [Peer] section": 38,
+ "Invalid key: %v": 30,
+ "Invalid name": 84,
+ "Invalid persistent keepalive": 29,
+ "Invalid port": 28,
+ "Key must have a value": 36,
+ "Keys must decode to exactly 32 bytes": 31,
+ "Latest handshake:": 61,
+ "Line must occur in a section": 34,
+ "Listen port:": 52,
+ "Log": 98,
+ "Log message": 103,
+ "MTU:": 53,
+ "Missing port from endpoint": 24,
+ "Now": 10,
+ "Peer": 74,
+ "Persistent keepalive:": 60,
+ "Please ask the system administrator to update.": 177,
+ "Preshared key:": 57,
+ "Public key:": 51,
+ "Remove selected tunnel(s)": 134,
+ "Scripts:": 56,
+ "Select &all": 100,
+ "Status:": 48,
+ "Status: %s": 125,
+ "Status: Complete!": 170,
+ "Status: Unknown": 113,
+ "Status: Waiting for administrator": 178,
+ "Status: Waiting for updater service": 168,
+ "Status: Waiting for user": 166,
+ "System clock wound backward!": 11,
+ "Table:": 174,
+ "Text Files (*.txt)|*.txt|All Files (*.*)|*.*": 104,
+ "The %s tunnel has been activated.": 120,
+ "The %s tunnel has been deactivated.": 122,
+ "Time": 102,
+ "Transfer:": 62,
+ "Tunnel Error": 107,
+ "Tunnel already exists": 88,
+ "Tunnel name is not valid": 33,
+ "Tunnel name ‘%s’ is invalid.": 86,
+ "Tunnels": 130,
+ "Two commas in a row": 32,
+ "Unable to create new configuration": 90,
+ "Unable to create tunnel": 148,
+ "Unable to delete tunnel": 154,
+ "Unable to delete tunnels": 156,
"Unable to determine whether the process is running under WOW64: %v": 4,
- "Unable to exit service due to: %v. You may want to stop WireGuard from the service manager.": 168,
- "Unable to import configuration: %v": 148,
- "Unable to list existing tunnels": 92,
+ "Unable to exit service due to: %v. You may want to stop WireGuard from the service manager.": 164,
+ "Unable to import configuration: %v": 144,
+ "Unable to list existing tunnels": 87,
"Unable to open current process token: %v": 6,
- "Unable to wait for WireGuard window to appear: %v": 116,
- "Unknown state": 102,
- "Update Now": 171,
+ "Unable to wait for WireGuard window to appear: %v": 111,
+ "Unknown state": 97,
+ "Update Now": 167,
"Usage: %s [\n%s]": 2,
- "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 or is to the wrong DNS server, with special exceptions for DHCP and NDP.": 85,
- "WireGuard Activated": 123,
- "WireGuard Deactivated": 125,
- "WireGuard Detection Error": 115,
- "WireGuard Tunnel Error": 127,
- "WireGuard Update Available": 132,
+ "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, and the interface does not have table off, then the tunnel service engages a firewall ruleset to block all traffic that is neither to nor from the tunnel interface or is to the wrong DNS server, with special exceptions for DHCP and NDP.": 176,
+ "WireGuard Activated": 119,
+ "WireGuard Deactivated": 121,
+ "WireGuard Detection Error": 110,
+ "WireGuard Tunnel Error": 123,
+ "WireGuard Update Available": 128,
"WireGuard is running, but the UI is only accessible from desktops of the Builtin %s group.": 8,
- "WireGuard logo image": 52,
+ "WireGuard logo image": 45,
"WireGuard may only be used by users who are a member of the Builtin %s group.": 7,
"WireGuard system tray icon did not appear after 30 seconds.": 9,
- "WireGuard: %s": 128,
- "WireGuard: Deactivated": 117,
- "Writing file failed": 96,
+ "WireGuard: %s": 124,
+ "WireGuard: Deactivated": 112,
+ "Writing file failed": 91,
"You must use the native version of WireGuard on this computer.": 5,
- "[EnumerationSeparator]": 49,
- "[UnitSeparator]": 50,
- "[none specified]": 43,
- "disabled, per policy": 71,
- "enabled": 72,
- "no configuration files were found": 144,
- "post-down": 178,
- "post-up": 176,
- "pre-down": 177,
- "pre-up": 175,
- "♥ &Donate!": 55,
+ "[EnumerationSeparator]": 42,
+ "[UnitSeparator]": 43,
+ "[none specified]": 40,
+ "disabled, per policy": 67,
+ "enabled": 68,
+ "no configuration files were found": 140,
+ "off": 175,
+ "post-down": 66,
+ "post-up": 64,
+ "pre-down": 65,
+ "pre-up": 63,
+ "♥ &Donate!": 47,
}
-var deIndex = []uint32{ // 181 elements
+var caIndex = []uint32{ // 180 elements
+ // Entry 0 - 1F
+ 0x00000000, 0x00000006, 0x00000042, 0x00000056,
+ 0x00000071, 0x000000b0, 0x000000f5, 0x0000012c,
+ 0x0000018c, 0x00000215, 0x0000026a, 0x0000026e,
+ 0x00000295, 0x000002b3, 0x000002d1, 0x000002f1,
+ 0x00000313, 0x00000335, 0x0000033e, 0x00000347,
+ 0x00000354, 0x00000361, 0x0000036e, 0x0000037b,
+ 0x00000388, 0x000003a2, 0x000003c5, 0x000003f6,
+ 0x00000404, 0x00000412, 0x0000043e, 0x00000454,
+ // Entry 20 - 3F
+ 0x00000488, 0x0000049b, 0x000004bb, 0x000004e4,
+ 0x0000051c, 0x00000539, 0x0000056b, 0x00000598,
+ 0x000005c5, 0x000005d6, 0x00000605, 0x00000608,
+ 0x0000060b, 0x0000061b, 0x0000062d, 0x00000633,
+ 0x0000063f, 0x00000646, 0x00000651, 0x00000659,
+ 0x00000668, 0x00000678, 0x0000067d, 0x00000686,
+ 0x00000695, 0x0000069e, 0x000006b2, 0x000006c0,
+ 0x000006c8, 0x000006e3, 0x000006f5, 0x00000705,
+ // Entry 40 - 5F
+ 0x00000713, 0x00000722, 0x00000733, 0x00000745,
+ 0x00000761, 0x0000076b, 0x00000785, 0x000007ac,
+ 0x000007c7, 0x000007e5, 0x000007f8, 0x000007ff,
+ 0x00000813, 0x00000821, 0x00000827, 0x00000837,
+ 0x00000844, 0x00000881, 0x00000888, 0x00000894,
+ 0x000008a4, 0x000008b1, 0x000008c7, 0x000008f3,
+ 0x0000091f, 0x00000935, 0x00000969, 0x00000994,
+ 0x000009b0, 0x000009eb, 0x000009f1, 0x000009fa,
+ // Entry 60 - 7F
+ 0x00000a02, 0x00000a0e, 0x00000a1f, 0x00000a28,
+ 0x00000a2f, 0x00000a41, 0x00000a55, 0x00000a5b,
+ 0x00000a70, 0x00000aa9, 0x00000ac3, 0x00000ad7,
+ 0x00000ae7, 0x00000b26, 0x00000b3d, 0x00000b59,
+ 0x00000ba3, 0x00000bb9, 0x00000bcb, 0x00000bd8,
+ 0x00000bf0, 0x00000c17, 0x00000c1d, 0x00000c26,
+ 0x00000c38, 0x00000c5a, 0x00000c6f, 0x00000c94,
+ 0x00000cb4, 0x00000cc5, 0x00000cd2, 0x00000ce1,
+ // Entry 80 - 9F
+ 0x00000d06, 0x00000d2d, 0x00000d82, 0x00000d8a,
+ 0x00000d92, 0x00000da9, 0x00000db7, 0x00000dd7,
+ 0x00000dee, 0x00000df7, 0x00000e1b, 0x00000e3b,
+ 0x00000e5c, 0x00000e85, 0x00000ec1, 0x00000ef6,
+ 0x00000f29, 0x00000f58, 0x00000f6a, 0x00000fa1,
+ 0x00000fe9, 0x00001007, 0x0000103d, 0x000010a1,
+ 0x000010bd, 0x000010f3, 0x0000111a, 0x0000113b,
+ 0x0000116f, 0x00001192, 0x000011e6, 0x00001237,
+ // Entry A0 - BF
+ 0x0000125a, 0x00001285, 0x0000129c, 0x000012d2,
+ 0x000012ef, 0x0000136b, 0x000013c5, 0x000013e0,
+ 0x000013ef, 0x0000141b, 0x00001449, 0x0000145b,
+ 0x0000145b, 0x0000145b, 0x0000145b, 0x0000145b,
+ 0x0000145b, 0x0000145b, 0x0000145b, 0x0000145b,
+} // Size: 744 bytes
+
+const caData string = "" + // Size: 5211 bytes
+ "\x02Error\x02(sense argument): eleva i instala el servei d'administrador" +
+ "\x02Ús: %[1]s [\x0a%[2]s]\x02Opcions de línia d'ordres\x02No s'ha pogut " +
+ "determinar si el procés corre sota WOW64: %[1]v\x02Heu de fer servir la " +
+ "versio nativa de WireGuard en aquest ordinador.\x02No s'ha pogut obrir e" +
+ "l token del procés actual: %[1]v\x02WireGuard només es pot fer servir pe" +
+ "r els usuaris que són membres del grup del sistema %[1]s.\x02WireGuard s" +
+ "'està executsnt, pero la interfície gràfica només és accessible als usua" +
+ "ris que són membres del grup del sistema %[1]s.\x02La icona de WireGuard" +
+ " de la safata del sistema no ha aparegut després de 30 segons.\x02Ara" +
+ "\x02El rellotge del sistema s'ha atraçat!\x14\x01\x81\x01\x00\x02\x0a" +
+ "\x02%[1]d any\x00\x0b\x02%[1]d anys\x14\x01\x81\x01\x00\x02\x0a\x02%[1]d" +
+ " dia\x00\x0b\x02%[1]d dies\x14\x01\x81\x01\x00\x02\x0b\x02%[1]d hora\x00" +
+ "\x0c\x02%[1]d hores\x14\x01\x81\x01\x00\x02\x0c\x02%[1]d minut\x00\x0d" +
+ "\x02%[1]d minuts\x14\x01\x81\x01\x00\x02\x0c\x02%[1]d segon\x00\x0d\x02%" +
+ "[1]d segons\x02Fa %[1]s\x02%[1]d\u00a0B\x02%.2[1]f\u00a0KiB\x02%.2[1]f" +
+ "\u00a0MiB\x02%.2[1]f\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02Fal" +
+ "ta el port de l'extrem\x02El format de l'extrem no és valid\x02Els claud" +
+ "àtors han de contenir una adreça IPv6\x02MTU invàlida\x02Port invàlid" +
+ "\x02Temps de missatge de persistència invàlid\x02Clau invàlida: %[1]v" +
+ "\x02Les claus han de descodificar a exactament 32 bytes\x02Dos comes seg" +
+ "uides\x02El nom del túnel no és vàlid\x02La línia ha d'aparèixer en una " +
+ "secció\x02La clau de configuració no té un separador d'igualtat\x02La cl" +
+ "au ha de tenir un valor\x02La clau no és vàlida per la secció [Interface" +
+ "]\x02La clau no és vàlida per la secció [Peer]\x02Una interfície ha de t" +
+ "enir una clau privada\x02[no especificat]\x02Tots els parells han de ten" +
+ "ir claus públiques\x02, \x02, \x02Sobre WireGuard\x02Logo de WireGuard" +
+ "\x02Tanca\x02♥ & Dona!\x02Estat:\x02&Desactiva\x02&Activa\x02Clau públic" +
+ "a:\x02Port d'escolta:\x02MTU:\x02Adreces:\x02Servidors DNS:\x02Scripts:" +
+ "\x02Clau precompartida:\x02IPs permeses:\x02Extrem:\x02Missatge de persi" +
+ "stència:\x02Últim handshake:\x02Transferència:\x02preactivació\x02postac" +
+ "tivació\x02predesactivació\x02postdesactivació\x02deshabilitat, per polí" +
+ "tica\x02habilitat\x02%[1]s rebut, %[2]s enviat\x02Error en determinar l'" +
+ "estat del túnel\x02Error en activar el túnel\x02Error en desactivar el t" +
+ "únel\x02Interfície: %[1]s\x02Parell\x02Crear un túnel nou\x02Editar tún" +
+ "el\x02&Nom:\x02&Clau pública:\x02(desconegut)\x02&Bloquejar el trànsit q" +
+ "ue no passa pel túnel (kill-switch)\x02&Desar\x02Cancel·lar\x02&Configur" +
+ "ació:\x02Nom invàlid\x02És necessari un nom.\x02El nom del túnel ‘%[1]s’" +
+ " és invàlid.\x02No s'ha pogut llistar els túnels existents\x02El túnel j" +
+ "a existeix\x02Ja existeix un altre túnel amb el nom ‘%[1]s’.\x02No s'ha " +
+ "pogut crear una nova configuració\x02Error en escriure el fitxer\x02El f" +
+ "itxer ‘%[1]s’ ja existeix.\x0a\x0aEl vols sobreescriure?\x02Actiu\x02Act" +
+ "ivant\x02Inactiu\x02Desactivant\x02Estat desconegut\x02Registre\x02&Copi" +
+ "a\x02Selecciona-ho tot\x02Desa en un arxiu…\x02Temps\x02Missatge de regi" +
+ "stre\x02Fitxers de text (*.txt)|*.txt|Tots els fitxers (*.*)|*.*\x02Expo" +
+ "rta registre a fitxer\x02&Sobre WireGuard…\x02Error de túnel\x02%[1]s" +
+ "\x0a\x0aSi us plau, consulteu el registre per més informació.\x02%[1]s (" +
+ "desactualitzat)\x02Error en detectar WireGuard\x02No ha estat possible e" +
+ "sperar que aparegui la finestra de WireGuard: %[1]v\x02WireGuard: Desact" +
+ "ivat\x02Estat: Desconegut\x02Adreces: Cap\x02&Administrar túnels…\x02&Im" +
+ "portar túnel(s) des d'un fitxer…\x02&Surt\x02&Túnels\x02WireGuard Activa" +
+ "t\x02El túnel %[1]s ha estat activat.\x02WireGuard Desactivat\x02El túne" +
+ "l %[1]s ha estat desactivat.\x02Error en el túnel de WireGuard\x02WireGu" +
+ "ard: %[1]s\x02Estat: %[1]s\x02Adreces: %[1]s\x02Hi ha una actualització " +
+ "disponible!\x02Actualització de WireGuard disponible\x02Hi ha una actual" +
+ "ització de WireGuard. Es recomana actualitzar el més aviat millor.\x02Tú" +
+ "nels\x02&Editar\x02Afegir &túnel buit…\x02Afegir túnel\x02Eliminar túnel" +
+ "(s) seleccionats\x02Exportar túnels a zip\x02&Alterna\x02Exportar tots e" +
+ "ls túnels a &zip…\x02Editar túnels &seleccionats…\x02&Eliminar túnel(s) " +
+ "seleccionats\x02no s'han trobat fitxers de configuració\x02No s'ha pogut" +
+ " importar la configuració seleccionada: %[1]v\x02No s'han pogut enumerar" +
+ " els túnels existents: %[1]v\x02Ja existeix un altre túnel amb el nom ‘%" +
+ "[1]s’\x02No s'ha pogut importar la configuració: %[1]v\x02Túnels importa" +
+ "ts\x14\x01\x81\x01\x00\x02\x16\x02%[1]d túnel importat\x00\x18\x02%[1]d " +
+ "túnels importats\x14\x02\x80\x01\x02\x1f\x02%[1]d de %[2]d túnel importa" +
+ "t\x00!\x02%[1]d de %[2]d túnels importats\x02No s'ha pogut crear el túne" +
+ "l\x14\x01\x81\x01\x00\x02\x16\x02Eliminar %[1]d túnel\x00\x17\x02Elimina" +
+ "r %[1]d túnels\x14\x01\x81\x01\x00\x02-\x02Estàs segur que vols eliminar" +
+ " %[1]d túnel?\x00.\x02Estàs segur que vols eliminar %[1]d túnels?\x02Eli" +
+ "minar túnel ‘%[1]s’\x02Estàs segur que vols eliminar el túnel ‘%[1]s’?" +
+ "\x02%[1]s Aquesta acció no es pot desfer.\x02No s'ha pogut eliminar el t" +
+ "únel\x02Un túnel no ha estat capaç de ser eliminat: %[1]s\x02No s'ha po" +
+ "gut eliminar els túnels\x14\x01\x81\x01\x00\x02%\x02No s'ha pogut elimin" +
+ "ar %[1]d túnel.\x00&\x02No s'ha pogut eliminar %[1]d túnels.\x02Fitxers " +
+ "de configuració (*.zip, *.conf)|*.zip;*.conf|Tots els fitxers (*.*)|*.*" +
+ "\x02Importar túnel(s) des d'un fitxer\x02Fitxers ZIP de configuració (*." +
+ "zip)|*.zip\x02Exportar túnels a zip\x02%[1]s (compilació no signada, sen" +
+ "se actualitzacions)\x02Error al sortir de WireGuard\x02No s'ha pogut sor" +
+ "tir del servei a causa de l'error: %[1]v. Pot intentar aturar WireGuard " +
+ "des de l'administrador de serveis.\x02Una actualització per WireGuard es" +
+ "tà disponible. Es recomana actualitzar immediatament.\x02Estat: Esperant" +
+ " a l'usuari\x02Actualitza ara\x02Estat: Esperant el servei d'actualitzac" +
+ "ions\x02Error: %[1]v. Si us plau, torneu-ho a provar.\x02Estat: Completa" +
+ "t!"
+
+var csIndex = []uint32{ // 180 elements
+ // Entry 0 - 1F
+ 0x00000000, 0x00000006, 0x0000004f, 0x00000069,
+ 0x0000008a, 0x000000bd, 0x00000106, 0x00000138,
+ 0x00000193, 0x00000201, 0x0000024d, 0x00000252,
+ 0x0000027b, 0x000002b1, 0x000002e7, 0x00000326,
+ 0x00000365, 0x000003a8, 0x000003b4, 0x000003bd,
+ 0x000003ca, 0x000003d7, 0x000003e4, 0x000003f1,
+ 0x000003fe, 0x00000414, 0x00000427, 0x0000044c,
+ 0x0000045a, 0x00000469, 0x0000048b, 0x000004a3,
+ // Entry 20 - 3F
+ 0x000004d9, 0x000004ef, 0x0000050a, 0x0000052f,
+ 0x0000056f, 0x00000589, 0x000005b0, 0x000005d2,
+ 0x000005fd, 0x00000614, 0x00000641, 0x00000644,
+ 0x00000647, 0x0000065c, 0x00000674, 0x0000067d,
+ 0x0000068b, 0x00000691, 0x0000069e, 0x000006a9,
+ 0x000006bb, 0x000006d3, 0x000006d8, 0x000006e0,
+ 0x000006ed, 0x000006f6, 0x0000070d, 0x0000071b,
+ 0x00000725, 0x0000073b, 0x00000750, 0x00000759,
+ // Entry 40 - 5F
+ 0x00000769, 0x00000775, 0x00000785, 0x00000791,
+ 0x000007a7, 0x000007af, 0x000007cf, 0x000007f2,
+ 0x00000811, 0x00000832, 0x00000843, 0x00000848,
+ 0x0000085e, 0x0000086c, 0x00000875, 0x00000888,
+ 0x00000894, 0x000008c1, 0x000008ca, 0x000008d2,
+ 0x000008df, 0x000008f0, 0x00000904, 0x00000928,
+ 0x00000954, 0x00000968, 0x0000098f, 0x000009ba,
+ 0x000009d6, 0x00000a0a, 0x00000a13, 0x00000a1c,
+ // Entry 60 - 7F
+ 0x00000a27, 0x00000a32, 0x00000a41, 0x00000a4a,
+ 0x00000a56, 0x00000a63, 0x00000a7a, 0x00000a7f,
+ 0x00000a8c, 0x00000ac6, 0x00000ae4, 0x00000afd,
+ 0x00000b0a, 0x00000b45, 0x00000b5a, 0x00000b77,
+ 0x00000ba8, 0x00000bc0, 0x00000bd0, 0x00000be1,
+ 0x00000bf5, 0x00000c18, 0x00000c22, 0x00000c2a,
+ 0x00000c3f, 0x00000c5b, 0x00000c72, 0x00000c90,
+ 0x00000ca7, 0x00000cb8, 0x00000cc4, 0x00000cd2,
+ // Entry 80 - 9F
+ 0x00000cee, 0x00000d13, 0x00000d75, 0x00000d7c,
+ 0x00000d85, 0x00000da1, 0x00000daf, 0x00000dc9,
+ 0x00000deb, 0x00000df6, 0x00000e1c, 0x00000e37,
+ 0x00000e52, 0x00000e82, 0x00000eaf, 0x00000ee4,
+ 0x00000f0a, 0x00000f2e, 0x00000f42, 0x00000fb7,
+ 0x0000104c, 0x00001062, 0x000010cc, 0x00001176,
+ 0x0000118e, 0x000011b6, 0x000011db, 0x000011f1,
+ 0x00001217, 0x0000122e, 0x000012d8, 0x00001326,
+ // Entry A0 - BF
+ 0x00001345, 0x0000136c, 0x00001385, 0x000013b6,
+ 0x000013e2, 0x0000143c, 0x000014a5, 0x000014c3,
+ 0x000014d6, 0x000014fe, 0x0000151d, 0x0000152f,
+ 0x0000152f, 0x0000152f, 0x0000152f, 0x0000152f,
+ 0x0000152f, 0x0000152f, 0x0000152f, 0x0000152f,
+} // Size: 744 bytes
+
+const csData string = "" + // Size: 5423 bytes
+ "\x02Chyba\x02(žádný argument): Zvýšit oprávnění a instalovat službu sprá" +
+ "vce\x02Použití: %[1]s [\x0a%[2]s]\x02Možnosti příkazového řádku\x02Nelze" +
+ " zjistit, zda proces běží pod WOW64: %[1]v\x02Musíte použít nativní verz" +
+ "i aplikace WireGuard na tomto počítači.\x02Nelze otevřít token aktuálníh" +
+ "o procesu: %[1]v\x02WireGuard můžou používat pouze uživatelé, kteří jsou" +
+ " členy Builtin skupiny %[1]s.\x02WireGuard je spuštěn, ale uživatelské r" +
+ "ozhraní je přístupné pouze uživatelům Builtin skupiny %[1]s.\x02Ikona Wi" +
+ "reGuard se ani po 30 sekundách nezobrazila na systémové liště.\x02Teď" +
+ "\x02Systémové hodiny byly posunuty dozadu!\x14\x01\x81\x01\x00\x04\x0b" +
+ "\x02%[1]d roky\x05\x0a\x02%[1]d let\x02\x0a\x02%[1]d rok\x00\x0a\x02%[1]" +
+ "d let\x14\x01\x81\x01\x00\x04\x0a\x02%[1]d dny\x05\x0b\x02%[1]d dnů\x02" +
+ "\x0a\x02%[1]d den\x00\x0a\x02%[1]d dny\x14\x01\x81\x01\x00\x04\x0d\x02%[" +
+ "1]d hodiny\x05\x0c\x02%[1]d hodin\x02\x0d\x02%[1]d hodina\x00\x0c\x02%[1" +
+ "]d hodin\x14\x01\x81\x01\x00\x04\x0d\x02%[1]d minuty\x05\x0c\x02%[1]d mi" +
+ "nut\x02\x0d\x02%[1]d minuta\x00\x0c\x02%[1]d minut\x14\x01\x81\x01\x00" +
+ "\x04\x0e\x02%[1]d sekundy\x05\x0d\x02%[1]d sekund\x02\x0e\x02%[1]d sekun" +
+ "da\x00\x0d\x02%[1]d sekund\x02před %[1]s\x02%[1]d\u00a0B\x02%.2[1]f" +
+ "\u00a0KiB\x02%.2[1]f\u00a0MiB\x02%.2[1]f\u00a0GiB\x02%.2[1]f\u00a0TiB" +
+ "\x02%[1]s: %[2]q\x02Endpointu chybí port\x02Neplatný endpoint\x02Závorky" +
+ " musí obsahovat IPv6 adresu\x02Neplatné MTU\x02Neplatný port\x02Neplatný" +
+ " persistentní keepalive\x02Neplatný klíč: %[1]v\x02Klíče musí být dekódo" +
+ "vány přesně na 32 bajtů\x02Dvě čárky za sebou\x02Název tunelu je neplatn" +
+ "ý\x02Řádek musí být v některé sekci\x02Konfigurační klíč neobsahuje odd" +
+ "ělovač (znak 'rovná se')\x02Klíč musí mít hodnotu\x02Neplatný klíč pro " +
+ "sekci [Interface]\x02Neplatný klíč pro sekci [Peer]\x02Rozhraní musí obs" +
+ "ahovat soukromý klíč\x02[není specifikováno]\x02Všichni peeři musí mít v" +
+ "eřejné klíče\x02, \x02, \x02O aplikaci WireGuard\x02Obrázek loga WireGua" +
+ "rd\x02Zavřít\x02♥ &Darovat!\x02Stav:\x02&Deaktivovat\x02&Aktivovat\x02Ve" +
+ "řejný klíč:\x02Port pro naslouchání:\x02MTU:\x02Adresy:\x02DNS servery:" +
+ "\x02Skripty:\x02Předsdílený klíč:\x02Povolené IP:\x02Endpoint:\x02Persis" +
+ "tent keepalive:\x02Poslední handshake:\x02Přenos:\x02před-zapnutím\x02po" +
+ "-zapnutí\x02před-vypnutím\x02po-vypnutí\x02vypnuto, podle zásad\x02zapnu" +
+ "to\x02%[1]s přijato, %[2]s odesláno\x02Nepodařilo se zjistit stav tunelu" +
+ "\x02Nepodařilo se aktivovat tunel\x02Nepodařilo se deaktivovat tunel\x02" +
+ "Rozhraní: %[1]s\x02Peer\x02Vytvořit nový tunel\x02Upravit tunel\x02&Náze" +
+ "v:\x02&Veřejný klíč:\x02(neznámý)\x02&Blokovat netunelovaný provoz (kill" +
+ "-switch)\x02&Uložit\x02Zrušit\x02&Nastavení:\x02Neplatný název\x02Název " +
+ "je povinný.\x02Název tunelu '%[1]s' je neplatný.\x02Nepodařilo se zobraz" +
+ "it existující tunely\x02Tunel již existuje\x02Tunel s názvem '%[1]s' již" +
+ " existuje.\x02Nepodařilo se vytvořit novou konfiguraci\x02Zápis souboru " +
+ "se nezdařil\x02Soubor \x22%[1]s\x22 již existuje.\x0a\x0aChcete jej přep" +
+ "sat?\x02Aktivní\x02Aktivuji\x02Neaktivní\x02Deaktivuji\x02Neznámý stav" +
+ "\x02Záznamy\x02&Kopírovat\x02Vybr&at vše\x02&Uložit do souboru…\x02Čas" +
+ "\x02Zpráva logu\x02Textové soubory (*.txt)|*.txt|Všechny soubory (*.*)|*" +
+ ".*\x02Exportovat záznam do souboru\x02&O aplikaci WireGuard…\x02Chyba tu" +
+ "nelu\x02%[1]s\x0a\x0aPro více informací se prosím podívejte do logu.\x02" +
+ "%[1]s (neaktuální)\x02Chyba při detekci WireGuard\x02Nelze čekat na zobr" +
+ "azení okna WireGuard: %[1]v\x02WireGuard: Deaktivován\x02Stav: Neznámý" +
+ "\x02Adresy: žádné\x02Spravovat tunely…\x02&Importovat tunel(y) ze soubor" +
+ "u…\x02U&končit\x02&Tunely\x02WireGuard aktivován\x02Tunel %[1]s byl akti" +
+ "vován.\x02WireGuard deaktivován\x02Tunel %[1]s byl deaktivován.\x02WireG" +
+ "uard Chyba Tunelu\x02WireGuard: %[1]s\x02Stav: %[1]s\x02Adresy: %[1]s" +
+ "\x02Aktualizace je k dispozici!\x02Aktualizace WireGuard je k dispozici" +
+ "\x02Aktualizace aplikace WireGuard je nyní k dispozici. Doporučujeme ji " +
+ "aktualizovat co nejdříve.\x02Tunely\x02&Upravit\x02Přidat &prázdný tunel" +
+ "…\x02Přidat tunel\x02Odstranit vybrané tunely\x02Exportovat všechny tu" +
+ "nely do zip\x02&Přepnout\x02Exportovat všechny tunely do &zip…\x02Upravi" +
+ "t &vybraný tunel…\x02&Odstranit vybrané tunely\x02nebyly nalezeny žádné " +
+ "konfigurační soubory\x02Nelze importovat vybranou konfiguraci: %[1]v\x02" +
+ "Nepodařilo se vyjmenovat existující tunely: %[1]v\x02Tunel s názvem '%[1" +
+ "]s' již existuje\x02Nelze importovat konfiguraci: %[1]v\x02Importované t" +
+ "unely\x14\x01\x81\x01\x00\x04\x1a\x02Importovány %[1]d tunely\x05\x1b" +
+ "\x02Importováno %[1]d tunelů\x02\x18\x02Importován %[1]d tunel\x00\x1b" +
+ "\x02Importováno %[1]d tunelů\x14\x02\x80\x01\x04#\x02Importováno %[1]d z" +
+ " %[2]d tunelů\x05#\x02Importováno %[1]d z %[2]d tunelů\x02 \x02Importová" +
+ "n %[1]d z %[2]d tunel\x00#\x02Importováno %[1]d z %[2]d tunelů\x02Nelze " +
+ "vytvořit tunel\x14\x01\x81\x01\x00\x04\x17\x02Odstranit %[1]d tunely\x05" +
+ "\x18\x02Odstranit %[1]d tunelů\x02\x16\x02Odstranit %[1]d tunel\x00\x18" +
+ "\x02Odstranit %[1]d tunelů\x14\x01\x81\x01\x00\x04'\x02Opravdu chcete od" +
+ "stranit %[1]d tunely?\x05(\x02Opravdu chcete odstranit %[1]d tunelů?\x02" +
+ "&\x02Opravdu chcete odstranit %[1]d tunel?\x00(\x02Opravdu chcete odstra" +
+ "nit %[1]d tunelů?\x02Odstranit tunel \x22%[1]s\x22\x02Opravdu chcete ods" +
+ "tranit tunel \x22%[1]s\x22?\x02%[1]s Tuto akci nelze vrátit zpět.\x02Nel" +
+ "ze odstranit tunel\x02Tunel nebylo možné odstranit: %[1]s\x02Nelze odstr" +
+ "anit tunely\x14\x01\x81\x01\x00\x04'\x02%[1]d tunely nebylo možné odstra" +
+ "nit.\x05(\x02%[1]d tunelů nebylo možné odstranit.\x02&\x02%[1]d tunel ne" +
+ "bylo možné odstranit.\x00(\x02%[1]d tunelů nebylo možné odstranit.\x02Ko" +
+ "nfigurace souborů (*.zip, *.conf)|*.zip; *.conf|Všechny soubory (*.*)|*." +
+ "*\x02Importovat tunel(y) ze souboru\x02Konfigurace souborů ZIP (*.zip)|*" +
+ ".zip\x02Exportovat tunely do zip\x02%[1]s (nepodepsaná verze, žádné aktu" +
+ "alizace)\x02Chyba při ukončování aplikace WireGuard\x02Nelze ukončit slu" +
+ "žbu z důvodu: %[1]v. WireGuard můžete zastavit ve správci služeb.\x02Ak" +
+ "tualizace aplikace WireGuard je nyní k dispozici. Silně doporučujeme ji " +
+ "aktualizovat co nejdříve.\x02Stav: Čekání na uživatele\x02Aktualizovat n" +
+ "yní\x02Stav: Čeká se na službu aktualizací\x02Chyba: %[1]v. Zkuste to zn" +
+ "ovu.\x02Stav: Dokončeno!"
+
+var deIndex = []uint32{ // 180 elements
// Entry 0 - 1F
0x00000000, 0x00000007, 0x00000059, 0x00000074,
0x0000008b, 0x000000e1, 0x00000137, 0x0000016b,
@@ -246,54 +535,53 @@ var deIndex = []uint32{ // 181 elements
0x000002b6, 0x000002d6, 0x000002f4, 0x00000318,
0x0000033c, 0x00000362, 0x0000036c, 0x00000375,
0x00000382, 0x0000038f, 0x0000039c, 0x000003a9,
- 0x000003b6, 0x000003cc, 0x000003f4, 0x00000412,
- 0x0000042c, 0x00000460, 0x0000046f, 0x00000480,
+ 0x000003b6, 0x000003d4, 0x000003ee, 0x00000422,
+ 0x00000431, 0x00000442, 0x00000462, 0x00000480,
// Entry 20 - 3F
- 0x000004a0, 0x000004be, 0x000004f5, 0x00000521,
- 0x0000053d, 0x0000055a, 0x0000058b, 0x000005c6,
- 0x000005e4, 0x00000612, 0x0000063a, 0x00000674,
- 0x00000689, 0x000006c7, 0x000006ed, 0x0000071a,
- 0x0000073b, 0x00000763, 0x00000766, 0x00000769,
- 0x00000779, 0x00000788, 0x000007f6, 0x00000801,
- 0x0000080f, 0x00000817, 0x00000825, 0x00000831,
- 0x0000084b, 0x00000859, 0x0000085e, 0x00000868,
+ 0x000004b7, 0x000004d3, 0x000004f0, 0x00000521,
+ 0x0000055c, 0x0000057a, 0x000005a8, 0x000005d0,
+ 0x0000060a, 0x0000061f, 0x0000065d, 0x00000660,
+ 0x00000663, 0x00000673, 0x00000682, 0x0000068d,
+ 0x0000069b, 0x000006a3, 0x000006b1, 0x000006bd,
+ 0x000006d7, 0x000006e5, 0x000006ea, 0x000006f4,
+ 0x00000700, 0x00000709, 0x0000071f, 0x0000072d,
+ 0x00000737, 0x0000074c, 0x00000766, 0x00000773,
// Entry 40 - 5F
- 0x00000874, 0x0000087d, 0x00000893, 0x000008a1,
- 0x000008ab, 0x000008c0, 0x000008da, 0x000008e7,
- 0x00000903, 0x0000090d, 0x0000092d, 0x00000958,
- 0x0000097d, 0x000009a4, 0x000009b9, 0x000009c4,
- 0x000009e1, 0x000009f3, 0x000009fa, 0x00000a15,
- 0x00000a21, 0x00000a55, 0x00000bbd, 0x00000bc8,
- 0x00000bd2, 0x00000be2, 0x00000bf3, 0x00000c0b,
- 0x00000c2f, 0x00000c62, 0x00000c7b, 0x00000cb3,
+ 0x00000786, 0x0000079d, 0x000007b2, 0x000007c8,
+ 0x000007e4, 0x000007ee, 0x0000080e, 0x00000839,
+ 0x0000085e, 0x00000885, 0x0000089a, 0x000008a5,
+ 0x000008c2, 0x000008d4, 0x000008db, 0x000008f6,
+ 0x00000902, 0x00000936, 0x00000941, 0x0000094b,
+ 0x0000095b, 0x0000096c, 0x00000984, 0x000009a8,
+ 0x000009db, 0x000009f4, 0x00000a2c, 0x00000a5a,
+ 0x00000a7a, 0x00000abf, 0x00000ac5, 0x00000acf,
// Entry 60 - 7F
- 0x00000ce1, 0x00000d01, 0x00000d46, 0x00000d4c,
- 0x00000d56, 0x00000d5e, 0x00000d6a, 0x00000d7e,
- 0x00000d88, 0x00000d92, 0x00000da3, 0x00000dba,
- 0x00000dbf, 0x00000dd0, 0x00000e01, 0x00000e1f,
- 0x00000e33, 0x00000e41, 0x00000e82, 0x00000e93,
- 0x00000eae, 0x00000ef6, 0x00000f0d, 0x00000f1f,
- 0x00000f2f, 0x00000f44, 0x00000f65, 0x00000f6e,
- 0x00000f82, 0x00000fa4, 0x00000fba, 0x00000fde,
+ 0x00000ad7, 0x00000ae3, 0x00000af7, 0x00000b01,
+ 0x00000b0b, 0x00000b1c, 0x00000b33, 0x00000b38,
+ 0x00000b49, 0x00000b7a, 0x00000b98, 0x00000bac,
+ 0x00000bba, 0x00000bfb, 0x00000c0c, 0x00000c27,
+ 0x00000c6f, 0x00000c86, 0x00000c98, 0x00000ca8,
+ 0x00000cbd, 0x00000cde, 0x00000ce7, 0x00000cef,
+ 0x00000d03, 0x00000d25, 0x00000d3b, 0x00000d5f,
+ 0x00000d77, 0x00000d88, 0x00000d96, 0x00000da6,
// Entry 80 - 9F
- 0x00000ff6, 0x00001007, 0x00001015, 0x00001025,
- 0x00001049, 0x0000106d, 0x000010e0, 0x000010e7,
- 0x000010f3, 0x00001117, 0x0000112a, 0x00001148,
- 0x00001172, 0x0000117e, 0x000011a3, 0x000011c7,
- 0x000011e8, 0x0000120d, 0x0000124e, 0x00001280,
- 0x000012ba, 0x000012ee, 0x00001300, 0x00001339,
- 0x00001385, 0x000013a5, 0x000013da, 0x0000144a,
- 0x00001466, 0x0000149d, 0x000014da, 0x000014f9,
+ 0x00000dca, 0x00000dee, 0x00000e61, 0x00000e68,
+ 0x00000e74, 0x00000e98, 0x00000eab, 0x00000ec9,
+ 0x00000ef3, 0x00000eff, 0x00000f24, 0x00000f48,
+ 0x00000f69, 0x00000f8e, 0x00000fcf, 0x00001001,
+ 0x0000103b, 0x0000106f, 0x00001081, 0x000010ba,
+ 0x00001106, 0x00001126, 0x0000115b, 0x000011cb,
+ 0x000011e7, 0x0000121e, 0x0000125b, 0x0000127a,
+ 0x000012aa, 0x000012d0, 0x00001331, 0x0000137b,
// Entry A0 - BF
- 0x00001529, 0x0000154f, 0x000015b0, 0x000015fa,
- 0x00001616, 0x0000163f, 0x0000165e, 0x00001689,
- 0x000016ab, 0x00001717, 0x00001785, 0x0000179f,
- 0x000017b3, 0x000017dc, 0x0000180a, 0x0000181a,
- 0x0000181a, 0x0000181a, 0x0000181a, 0x0000181a,
- 0x0000181a,
-} // Size: 748 bytes
+ 0x00001397, 0x000013c0, 0x000013df, 0x0000140a,
+ 0x0000142c, 0x00001498, 0x00001506, 0x00001520,
+ 0x00001534, 0x0000155d, 0x0000158b, 0x0000159b,
+ 0x0000159b, 0x0000159b, 0x0000159b, 0x0000159b,
+ 0x0000159b, 0x0000159b, 0x0000159b, 0x0000159b,
+} // Size: 744 bytes
-const deData string = "" + // Size: 6170 bytes
+const deData string = "" + // Size: 5531 bytes
"\x02Fehler\x02(kein Argument): Als Administrator ausführen und den Manag" +
"er-Dienst installieren\x02Verwendung: %[1]s [\x0a%[2]s]\x02Kommandozeile" +
"noptionen\x02Es kann nicht festgestellt werden, ob der Prozess unter WOW" +
@@ -310,89 +598,80 @@ const deData string = "" + // Size: 6170 bytes
"\x81\x01\x00\x02\x0d\x02%[1]d Minute\x00\x0e\x02%[1]d Minuten\x14\x01" +
"\x81\x01\x00\x02\x0e\x02%[1]d Sekunde\x00\x0f\x02%[1]d Sekunden\x02vor %" +
"[1]s\x02%[1]d\u00a0B\x02%.2[1]f\u00a0KiB\x02%.2[1]f\u00a0MiB\x02%.2[1]f" +
- "\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02Ungültige IP-Adresse" +
- "\x02Ungültige Länge des Netzwerkpräfixes\x02Fehlender Port des Endpunkte" +
- "s\x02Ungültiger Endpunkt-Host\x02Eckige Klammern müssen eine IPv6 Adress" +
- "e enthalten\x02Ungültige MTU\x02Ungültiger Port\x02Ungültiges Erhaltungs" +
- "intervall\x02Ungültiger Schlüssel: %[1]v\x02Schlüssel müssen auf exakt 3" +
- "2 Bytes dekodiert werden\x02Zahl muss zwischen 0 und 2^64-1 sein: %[1]v" +
- "\x02Zwei Kommata in einer Zeile\x02Der Tunnelname ist ungültig\x02Die Ze" +
- "ile muss innerhalb eines Abschnitts stehen\x02Konfigurationsschlüssel fe" +
- "hlt ein Gleichheitstrennzeichen\x02Eintrag muss einen Wert haben\x02Ungü" +
- "ltiger Eintrage im [Interface] Abschnitt\x02Ungültiger Eintrag im [Peer]" +
- " Abschnitt\x02Eine Schnittstelle muss einen privaten Schlssel enthalten" +
- "\x02[nicht spezifiziert]\x02Alle Teilnehmer (peers) müssen öffentliche S" +
- "chlüssel haben\x02Fehler beim Abrufen der Konfiguration\x02Ungültiger Ei" +
- "ntrag im Abschnitt [interface]\x02Die Protokollversion muss 1 sein\x02Un" +
- "gültiger Eintrag im Abschnitt [peer]\x02, \x02, \x02Über WireGuard\x02Wi" +
- "reGuard Logo\x02App Version: %[1]s\x0aGo backend Version: %[2]s\x0aGo Ve" +
- "rsion: %[3]s-%[4]s\x0aBetriebssystem: %[5]s\x0aArchitektur: %[6]s\x02Sch" +
- "ließen\x02♥ &Spenden!\x02Status:\x02&Deaktivieren\x02&Aktivieren\x02Öffe" +
- "ntlicher Schlüssel:\x02Eingangsport:\x02MTU:\x02Adressen:\x02DNS-Server:" +
- "\x02Skripte:\x02Geteilter Schlüssel:\x02Erlaubte IPs:\x02Endpunkt:\x02Er" +
- "haltungsintervall:\x02Letzter Schlüsseltausch:\x02Übertragen:\x02deaktiv" +
- "iert, per Richtlinie\x02aktiviert\x02%[1]s empfangen, %[2]s gesendet\x02" +
- "Tunnelstatus konnte nicht ermittelt werden\x02Tunnel aktivieren ist fehl" +
- "geschlagen\x02Tunnel deaktivieren ist fehlgeschlagen\x02Schnittstelle: %" +
- "[1]s\x02Teilnehmer\x02Einen neuen Tunnel erstellen\x02Tunnel bearbeiten" +
- "\x02&Name:\x02&Öffentlicher Schlüssel:\x02(unbekannt)\x02&Blockiere Verk" +
- "ehr außerhalb des Tunnels (Not-Aus)\x02Wenn eine Konfiguration genau ein" +
- "en Teilnehmer enthält und dieser einen der Einträge 0.0.0.0/0 oder ::/0 " +
- "in den erlaubten IPs enthält, dann erstellt der Tunneldienst ein Firewal" +
- "l-Regelsatz, der allen Verkehr (insbesondere zum falschen DNS-Server) bl" +
- "ockiert, der weder aus dem Tunnel stammt noch in den Tunnel geht, mit Au" +
- "snahmen für DHCP- und NDP-Verkehr.\x02&Speichern\x02Abbrechen\x02&Konfig" +
- "uration:\x02Ungültiger Name\x02Ein Name ist notwendig.\x02Der Name „%[1]" +
- "s“ ist ungültig.\x02Vorhandene Tunnel können nicht aufgelistet werden" +
- "\x02Tunnel existiert bereits\x02Ein Tunnel mit dem Namen „%[1]s“ existie" +
- "rt bereits.\x02Neue Konfiguration kann nicht erstellt werden\x02Schreibe" +
- "n der Datei schlug fehl\x02Die Datei „%[1]s“ existiert bereits.\x0a\x0aM" +
- "öchten Sie sie ersetzen?\x02Aktiv\x02Aktiviere\x02Inaktiv\x02Deaktivier" +
- "e\x02Unbekannter Zustand\x02Protokoll\x02&Kopieren\x02&Alles markieren" +
- "\x02&In Datei Speichern…\x02Zeit\x02Protokolleintrag\x02Textdateien (*.t" +
- "xt)|*.txt|Alle Dateien (*.*)|*.*\x02Exportiere Protokoll in Datei\x02&Üb" +
- "er WireGuard…\x02Tunnel Fehler\x02%[1]s\x0a\x0aBitte lesen Sie das Proto" +
- "koll für weitere Informationen.\x02%[1]s (veraltet)\x02WireGuard Erkennu" +
- "ngsfehler\x02Warten auf das Erscheinen des WireGuard Fensters nicht mögl" +
- "ich: %[1]v \x02WireGuard: Deaktiviert\x02Status: Unbekannt\x02Adressen: " +
- "Keine\x02Tunnel &verwalten…\x02Tunnel aus Datei &importieren…\x02&Beende" +
- "n\x02WireGuard aktiviert\x02Der Tunnel %[1]s wurde aktiviert.\x02WireGua" +
- "rd deaktiviert\x02Der Tunnel %[1]s wurde deaktiviert.\x02WireGuard Tunne" +
- "l Fehler\x02WireGuard: %[1]s\x02Status: %[1]s\x02Adressen: %[1]s\x02Eine" +
- " Aktualisierung ist verfügbar!\x02WireGuard Aktualisierung verfügbar\x02" +
- "Eine Aktualisierung für WireGuard ist jetzt verfügbar. Es wird empfohlen" +
- " diese schnellstmöglich durchzuführen.\x02Tunnel\x02&Bearbeiten\x02Einen" +
- " &leeren Tunnel hinzufügen…\x02Tunnel hinzufügen\x02Markierte(n) Tunnel " +
- "entfernen\x02Alle Tunnel in eine Zip-Datei exportieren\x02&Umschalten" +
- "\x02Exportiere alle Tunnel in &Zip-Datei\x02Ausgewählten Tunnel &bearbei" +
- "ten…\x02Ausgewählte(n) Tunnel &löschen\x02keine Konfigurationsdateien ge" +
- "funden\x02Ausgewählte Konfiguration konnte nicht importiert werden: %[1]" +
- "v\x02Konnte existierende Tunnel nicht auflisten: %[1]v\x02Es existiert b" +
- "ereits ein Tunnel mit dem Namen „%[1]s“\x02Importieren der Konfiguration" +
- " nicht möglich: %[1]v\x02Tunnel importiert\x14\x01\x81\x01\x00\x02\x18" +
- "\x02%[1]d Tunnel importiert\x00\x18\x02%[1]d Tunnel importiert\x14\x02" +
- "\x80\x01\x02\x22\x02%[1]d von %[2]d Tunnel importiert\x00\x22\x02%[1]d v" +
- "on %[2]d Tunnel importiert\x02Tunnel erstellen nicht möglich\x14\x01\x81" +
- "\x01\x00\x02\x16\x02%[1]d Tunnel löschen\x00\x16\x02%[1]d Tunnel löschen" +
- "\x14\x01\x81\x01\x00\x024\x02Möchten Sie diesen %[1]d Tunnel wirklich lö" +
- "schen?\x003\x02Möchten Sie diese %[1]d Tunnel wirklich löschen?\x02Tunne" +
- "l „%[1]s“ löschen\x02Möchten Sie den Tunnel „%[1]s“ wirklich löschen?" +
- "\x02%[1]s Dieser Schritt kann nicht rückgängig gemacht werden.\x02Tunnel" +
- " löschen nicht möglich\x02Ein Tunnel konnte nicht gelöscht werden: %[1]s" +
- "\x02Tunnel konnten nicht gelöscht werden\x14\x01\x81\x01\x00\x02+\x02%[1" +
- "]d Tunnel konnte nicht entfernt werden.\x00-\x02%[1]d Tunnel konnten nic" +
- "ht gelöscht werden.\x02Konfigurationsdateien (*.zip, *.conf)|*.zip;*.con" +
- "f|Alle Dateien (*.*)|*.*\x02Importiere Tunnel aus Datei\x02Konfiguration" +
- "s-ZIP-Dateien (*.zip)|*.zip\x02Exportiere Tunnel in Zip-Datei\x02%[1]s (" +
- "unsigniert, keine Aktualisierungen)\x02Fehler beim Beenden von WireGuard" +
- "\x02Der Dienst konnte nicht gestoppt werden: %[1]v. Versuchen Sie WireGu" +
- "ard in der Dienstverwaltung zu beenden.\x02Eine Aktualisierung für WireG" +
- "uard ist verfügbar. Es ist höchst empfehlenswert diese sofort durchzufüh" +
- "ren.\x02Status: Auf Nutzer warten\x02Jetzt aktualisieren\x02Status: Auf " +
- "Aktualisierungsdienst warten\x02Fehler: %[1]v. Bitte versuchen Sie es er" +
- "neut.\x02Status: Fertig!"
+ "\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02Fehlender Port des Endp" +
+ "unktes\x02Ungültiger Endpunkt-Host\x02Eckige Klammern müssen eine IPv6 A" +
+ "dresse enthalten\x02Ungültige MTU\x02Ungültiger Port\x02Ungültiges Erhal" +
+ "tungsintervall\x02Ungültiger Schlüssel: %[1]v\x02Schlüssel müssen auf ex" +
+ "akt 32 Bytes dekodiert werden\x02Zwei Kommata in einer Zeile\x02Der Tunn" +
+ "elname ist ungültig\x02Die Zeile muss innerhalb eines Abschnitts stehen" +
+ "\x02Konfigurationsschlüssel fehlt ein Gleichheitstrennzeichen\x02Eintrag" +
+ " muss einen Wert haben\x02Ungültiger Eintrage im [Interface] Abschnitt" +
+ "\x02Ungültiger Eintrag im [Peer] Abschnitt\x02Eine Schnittstelle muss ei" +
+ "nen privaten Schlssel enthalten\x02[nicht spezifiziert]\x02Alle Teilnehm" +
+ "er (peers) müssen öffentliche Schlüssel haben\x02, \x02, \x02Über WireGu" +
+ "ard\x02WireGuard Logo\x02Schließen\x02♥ &Spenden!\x02Status:\x02&Deaktiv" +
+ "ieren\x02&Aktivieren\x02Öffentlicher Schlüssel:\x02Eingangsport:\x02MTU:" +
+ "\x02Adressen:\x02DNS-Server:\x02Skripte:\x02Geteilter Schlüssel:\x02Erla" +
+ "ubte IPs:\x02Endpunkt:\x02Erhaltungsintervall:\x02Letzter Schlüsseltausc" +
+ "h:\x02Übertragen:\x02vor Verbindsaufbau\x02nach Verbindungsaufbau\x02vor" +
+ " Verbindungsabbau\x02nach Verbindungsabbau\x02deaktiviert, per Richtlini" +
+ "e\x02aktiviert\x02%[1]s empfangen, %[2]s gesendet\x02Tunnelstatus konnte" +
+ " nicht ermittelt werden\x02Tunnel aktivieren ist fehlgeschlagen\x02Tunne" +
+ "l deaktivieren ist fehlgeschlagen\x02Schnittstelle: %[1]s\x02Teilnehmer" +
+ "\x02Einen neuen Tunnel erstellen\x02Tunnel bearbeiten\x02&Name:\x02&Öffe" +
+ "ntlicher Schlüssel:\x02(unbekannt)\x02&Blockiere Verkehr außerhalb des T" +
+ "unnels (Not-Aus)\x02&Speichern\x02Abbrechen\x02&Konfiguration:\x02Ungült" +
+ "iger Name\x02Ein Name ist notwendig.\x02Der Name „%[1]s“ ist ungültig." +
+ "\x02Vorhandene Tunnel können nicht aufgelistet werden\x02Tunnel existier" +
+ "t bereits\x02Ein Tunnel mit dem Namen „%[1]s“ existiert bereits.\x02Neue" +
+ " Konfiguration kann nicht erstellt werden\x02Schreiben der Datei schlug " +
+ "fehl\x02Die Datei „%[1]s“ existiert bereits.\x0a\x0aMöchten Sie sie erse" +
+ "tzen?\x02Aktiv\x02Aktiviere\x02Inaktiv\x02Deaktiviere\x02Unbekannter Zus" +
+ "tand\x02Protokoll\x02&Kopieren\x02&Alles markieren\x02&In Datei Speicher" +
+ "n…\x02Zeit\x02Protokolleintrag\x02Textdateien (*.txt)|*.txt|Alle Dateien" +
+ " (*.*)|*.*\x02Exportiere Protokoll in Datei\x02&Über WireGuard…\x02Tunne" +
+ "l Fehler\x02%[1]s\x0a\x0aBitte lesen Sie das Protokoll für weitere Infor" +
+ "mationen.\x02%[1]s (veraltet)\x02WireGuard Erkennungsfehler\x02Warten au" +
+ "f das Erscheinen des WireGuard Fensters nicht möglich: %[1]v \x02WireGua" +
+ "rd: Deaktiviert\x02Status: Unbekannt\x02Adressen: Keine\x02Tunnel &verwa" +
+ "lten…\x02Tunnel aus Datei &importieren…\x02&Beenden\x02&Tunnel\x02WireGu" +
+ "ard aktiviert\x02Der Tunnel %[1]s wurde aktiviert.\x02WireGuard deaktivi" +
+ "ert\x02Der Tunnel %[1]s wurde deaktiviert.\x02WireGuard Tunnel Fehler" +
+ "\x02WireGuard: %[1]s\x02Status: %[1]s\x02Adressen: %[1]s\x02Eine Aktuali" +
+ "sierung ist verfügbar!\x02WireGuard Aktualisierung verfügbar\x02Eine Akt" +
+ "ualisierung für WireGuard ist jetzt verfügbar. Es wird empfohlen diese s" +
+ "chnellstmöglich durchzuführen.\x02Tunnel\x02&Bearbeiten\x02Einen &leeren" +
+ " Tunnel hinzufügen…\x02Tunnel hinzufügen\x02Markierte(n) Tunnel entferne" +
+ "n\x02Alle Tunnel in eine Zip-Datei exportieren\x02&Umschalten\x02Exporti" +
+ "ere alle Tunnel in &Zip-Datei\x02Ausgewählten Tunnel &bearbeiten…\x02Aus" +
+ "gewählte(n) Tunnel &löschen\x02keine Konfigurationsdateien gefunden\x02A" +
+ "usgewählte Konfiguration konnte nicht importiert werden: %[1]v\x02Konnte" +
+ " existierende Tunnel nicht auflisten: %[1]v\x02Es existiert bereits ein " +
+ "Tunnel mit dem Namen „%[1]s“\x02Importieren der Konfiguration nicht mögl" +
+ "ich: %[1]v\x02Tunnel importiert\x14\x01\x81\x01\x00\x02\x18\x02%[1]d Tun" +
+ "nel importiert\x00\x18\x02%[1]d Tunnel importiert\x14\x02\x80\x01\x02" +
+ "\x22\x02%[1]d von %[2]d Tunnel importiert\x00\x22\x02%[1]d von %[2]d Tun" +
+ "nel importiert\x02Tunnel erstellen nicht möglich\x14\x01\x81\x01\x00\x02" +
+ "\x16\x02%[1]d Tunnel löschen\x00\x16\x02%[1]d Tunnel löschen\x14\x01\x81" +
+ "\x01\x00\x024\x02Möchten Sie diesen %[1]d Tunnel wirklich löschen?\x003" +
+ "\x02Möchten Sie diese %[1]d Tunnel wirklich löschen?\x02Tunnel „%[1]s“ l" +
+ "öschen\x02Möchten Sie den Tunnel „%[1]s“ wirklich löschen?\x02%[1]s Die" +
+ "ser Schritt kann nicht rückgängig gemacht werden.\x02Tunnel löschen nich" +
+ "t möglich\x02Ein Tunnel konnte nicht gelöscht werden: %[1]s\x02Tunnel ko" +
+ "nnten nicht gelöscht werden\x14\x01\x81\x01\x00\x02+\x02%[1]d Tunnel kon" +
+ "nte nicht entfernt werden.\x00-\x02%[1]d Tunnel konnten nicht gelöscht w" +
+ "erden.\x02Konfigurationsdateien (*.zip, *.conf)|*.zip;*.conf|Alle Dateie" +
+ "n (*.*)|*.*\x02Importiere Tunnel aus Datei\x02Konfigurations-ZIP-Dateien" +
+ " (*.zip)|*.zip\x02Exportiere Tunnel in Zip-Datei\x02%[1]s (unsigniert, k" +
+ "eine Aktualisierungen)\x02Fehler beim Beenden von WireGuard\x02Der Diens" +
+ "t konnte nicht gestoppt werden: %[1]v. Versuchen Sie WireGuard in der Di" +
+ "enstverwaltung zu beenden.\x02Eine Aktualisierung für WireGuard ist verf" +
+ "ügbar. Es ist höchst empfehlenswert diese sofort durchzuführen.\x02Stat" +
+ "us: Auf Nutzer warten\x02Jetzt aktualisieren\x02Status: Auf Aktualisieru" +
+ "ngsdienst warten\x02Fehler: %[1]v. Bitte versuchen Sie es erneut.\x02Sta" +
+ "tus: Fertig!"
-var enIndex = []uint32{ // 181 elements
+var enIndex = []uint32{ // 180 elements
// Entry 0 - 1F
0x00000000, 0x00000006, 0x00000039, 0x0000004f,
0x00000064, 0x000000aa, 0x000000e9, 0x00000115,
@@ -400,54 +679,53 @@ var enIndex = []uint32{ // 181 elements
0x00000221, 0x00000241, 0x0000025f, 0x0000027f,
0x000002a3, 0x000002c7, 0x000002d1, 0x000002da,
0x000002e7, 0x000002f4, 0x00000301, 0x0000030e,
- 0x0000031b, 0x0000032e, 0x0000034c, 0x00000367,
- 0x0000037d, 0x000003a3, 0x000003af, 0x000003bc,
+ 0x0000031b, 0x00000336, 0x0000034c, 0x00000372,
+ 0x0000037e, 0x0000038b, 0x000003a8, 0x000003bb,
// Entry 20 - 3F
- 0x000003d9, 0x000003ec, 0x00000411, 0x00000445,
- 0x00000459, 0x00000472, 0x0000048f, 0x000004b9,
- 0x000004cf, 0x000004f3, 0x00000512, 0x00000537,
- 0x00000548, 0x00000568, 0x00000587, 0x000005a9,
- 0x000005c4, 0x000005e1, 0x000005e4, 0x000005e7,
- 0x000005f7, 0x0000060c, 0x0000067d, 0x00000683,
- 0x00000690, 0x00000698, 0x000006a4, 0x000006ae,
- 0x000006ba, 0x000006c7, 0x000006cc, 0x000006d7,
+ 0x000003e0, 0x000003f4, 0x0000040d, 0x0000042a,
+ 0x00000454, 0x0000046a, 0x0000048e, 0x000004ad,
+ 0x000004d2, 0x000004e3, 0x00000503, 0x00000506,
+ 0x00000509, 0x00000519, 0x0000052e, 0x00000534,
+ 0x00000541, 0x00000549, 0x00000555, 0x0000055f,
+ 0x0000056b, 0x00000578, 0x0000057d, 0x00000588,
+ 0x00000595, 0x0000059e, 0x000005ad, 0x000005ba,
+ 0x000005c4, 0x000005da, 0x000005ec, 0x000005f6,
// Entry 40 - 5F
- 0x000006e4, 0x000006ed, 0x000006fc, 0x00000709,
- 0x00000713, 0x00000729, 0x0000073b, 0x00000745,
- 0x0000075a, 0x00000762, 0x0000077d, 0x0000079e,
- 0x000007b8, 0x000007d4, 0x000007e5, 0x000007ea,
- 0x000007fc, 0x00000808, 0x0000080f, 0x0000081c,
- 0x00000826, 0x0000084e, 0x0000098a, 0x00000990,
- 0x00000997, 0x000009a7, 0x000009b4, 0x000009c8,
- 0x000009ec, 0x00000a0c, 0x00000a22, 0x00000a5b,
+ 0x000005fd, 0x00000605, 0x0000060e, 0x00000618,
+ 0x0000062d, 0x00000635, 0x00000650, 0x00000671,
+ 0x0000068b, 0x000006a7, 0x000006b8, 0x000006bd,
+ 0x000006cf, 0x000006db, 0x000006e2, 0x000006ef,
+ 0x000006f9, 0x00000721, 0x00000727, 0x0000072e,
+ 0x0000073e, 0x0000074b, 0x0000075f, 0x00000783,
+ 0x000007a3, 0x000007b9, 0x000007f2, 0x00000815,
+ 0x00000829, 0x00000868, 0x0000086f, 0x0000087a,
// Entry 60 - 7F
- 0x00000a7e, 0x00000a92, 0x00000ad1, 0x00000ad8,
- 0x00000ae3, 0x00000aec, 0x00000af9, 0x00000b07,
- 0x00000b0b, 0x00000b11, 0x00000b1d, 0x00000b2e,
- 0x00000b33, 0x00000b3f, 0x00000b6c, 0x00000b7f,
- 0x00000b93, 0x00000ba0, 0x00000bd4, 0x00000be8,
- 0x00000c02, 0x00000c37, 0x00000c4e, 0x00000c5e,
- 0x00000c6e, 0x00000c81, 0x00000ca0, 0x00000ca6,
- 0x00000cba, 0x00000cdf, 0x00000cf5, 0x00000d1c,
+ 0x00000883, 0x00000890, 0x0000089e, 0x000008a2,
+ 0x000008a8, 0x000008b4, 0x000008c5, 0x000008ca,
+ 0x000008d6, 0x00000903, 0x00000916, 0x0000092a,
+ 0x00000937, 0x0000096b, 0x0000097f, 0x00000999,
+ 0x000009ce, 0x000009e5, 0x000009f5, 0x00000a05,
+ 0x00000a18, 0x00000a37, 0x00000a3d, 0x00000a46,
+ 0x00000a5a, 0x00000a7f, 0x00000a95, 0x00000abc,
+ 0x00000ad3, 0x00000ae4, 0x00000af2, 0x00000b03,
// Entry 80 - 9F
- 0x00000d33, 0x00000d44, 0x00000d52, 0x00000d63,
- 0x00000d7b, 0x00000d96, 0x00000dee, 0x00000df6,
- 0x00000dfc, 0x00000e11, 0x00000e1c, 0x00000e36,
- 0x00000e50, 0x00000e58, 0x00000e76, 0x00000e8f,
- 0x00000eaa, 0x00000ecc, 0x00000efb, 0x00000f27,
- 0x00000f5f, 0x00000f85, 0x00000f96, 0x00000fcc,
- 0x00001013, 0x0000102b, 0x0000105d, 0x000010cf,
- 0x000010e9, 0x00001123, 0x00001146, 0x0000115e,
+ 0x00000b1b, 0x00000b36, 0x00000b8e, 0x00000b96,
+ 0x00000b9c, 0x00000bb1, 0x00000bbc, 0x00000bd6,
+ 0x00000bf0, 0x00000bf8, 0x00000c16, 0x00000c2f,
+ 0x00000c4a, 0x00000c6c, 0x00000c9b, 0x00000cc7,
+ 0x00000cff, 0x00000d25, 0x00000d36, 0x00000d6c,
+ 0x00000db3, 0x00000dcb, 0x00000dfd, 0x00000e6f,
+ 0x00000e89, 0x00000ec3, 0x00000ee6, 0x00000efe,
+ 0x00000f27, 0x00000f40, 0x00000f99, 0x00000fde,
// Entry A0 - BF
- 0x00001187, 0x000011a0, 0x000011f9, 0x0000123e,
- 0x00001259, 0x0000127f, 0x00001295, 0x000012b8,
- 0x000012d0, 0x0000132f, 0x00001384, 0x0000139d,
- 0x000013a8, 0x000013cc, 0x000013ec, 0x000013fe,
- 0x00001405, 0x0000140d, 0x00001416, 0x00001420,
- 0x00001429,
-} // Size: 748 bytes
+ 0x00000ff9, 0x0000101f, 0x00001035, 0x00001058,
+ 0x00001070, 0x000010cf, 0x00001124, 0x0000113d,
+ 0x00001148, 0x0000116c, 0x0000118c, 0x0000119e,
+ 0x000011aa, 0x000011c3, 0x0000122a, 0x00001231,
+ 0x00001235, 0x0000139c, 0x000013cb, 0x000013ed,
+} // Size: 744 bytes
-const enData string = "" + // Size: 5161 bytes
+const enData string = "" + // Size: 5101 bytes
"\x02Error\x02(no argument): elevate and install manager service\x02Usage" +
": %[1]s [\x0a%[2]s]\x02Command Line Options\x02Unable to determine wheth" +
"er the process is running under WOW64: %[1]v\x02You must use the native " +
@@ -462,302 +740,605 @@ const enData string = "" + // Size: 5161 bytes
"\x01\x00\x02\x0d\x02%[1]d minute\x00\x0e\x02%[1]d minutes\x14\x01\x81" +
"\x01\x00\x02\x0d\x02%[1]d second\x00\x0e\x02%[1]d seconds\x02%[1]s ago" +
"\x02%[1]d\u00a0B\x02%.2[1]f\u00a0KiB\x02%.2[1]f\u00a0MiB\x02%.2[1]f" +
- "\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02Invalid IP address\x02I" +
- "nvalid network prefix length\x02Missing port from endpoint\x02Invalid en" +
- "dpoint host\x02Brackets must contain an IPv6 address\x02Invalid MTU\x02I" +
- "nvalid port\x02Invalid persistent keepalive\x02Invalid key: %[1]v\x02Key" +
- "s must decode to exactly 32 bytes\x02Number must be a number between 0 a" +
- "nd 2^64-1: %[1]v\x02Two commas in a row\x02Tunnel name is not valid\x02L" +
- "ine must occur in a section\x02Config key is missing an equals separator" +
- "\x02Key must have a value\x02Invalid key for [Interface] section\x02Inva" +
- "lid key for [Peer] section\x02An interface must have a private key\x02[n" +
- "one specified]\x02All peers must have public keys\x02Error in getting co" +
- "nfiguration\x02Invalid key for interface section\x02Protocol version mus" +
- "t be 1\x02Invalid key for peer section\x02, \x02, \x02About WireGuard" +
- "\x02WireGuard logo image\x02App version: %[1]s\x0aGo backend version: %[" +
- "2]s\x0aGo version: %[3]s-%[4]s\x0aOperating system: %[5]s\x0aArchitectur" +
- "e: %[6]s\x02Close\x02♥ &Donate!\x02Status:\x02&Deactivate\x02&Activate" +
- "\x02Public key:\x02Listen port:\x02MTU:\x02Addresses:\x02DNS servers:" +
- "\x02Scripts:\x02Preshared key:\x02Allowed IPs:\x02Endpoint:\x02Persisten" +
- "t keepalive:\x02Latest handshake:\x02Transfer:\x02disabled, per policy" +
- "\x02enabled\x02%[1]s received, %[2]s sent\x02Failed to determine tunnel " +
- "state\x02Failed to activate tunnel\x02Failed to deactivate tunnel\x02Int" +
- "erface: %[1]s\x02Peer\x02Create new tunnel\x02Edit tunnel\x02&Name:\x02&" +
- "Public key:\x02(unknown)\x02&Block untunneled traffic (kill-switch)\x02W" +
- "hen a configuration has exactly one peer, and that peer has an allowed I" +
- "Ps 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 or is to the wrong DNS server, with special ex" +
- "ceptions for DHCP and NDP.\x02&Save\x02Cancel\x02&Configuration:\x02Inva" +
- "lid name\x02A name is required.\x02Tunnel name ‘%[1]s’ is invalid.\x02Un" +
- "able to list existing tunnels\x02Tunnel already exists\x02Another tunnel" +
- " already exists with the name ‘%[1]s’.\x02Unable to create new configura" +
- "tion\x02Writing file failed\x02File ‘%[1]s’ already exists.\x0a\x0aDo yo" +
- "u want to overwrite it?\x02Active\x02Activating\x02Inactive\x02Deactivat" +
- "ing\x02Unknown state\x02Log\x02&Copy\x02Select &all\x02&Save to file…" +
+ "\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02Missing port from endpo" +
+ "int\x02Invalid endpoint host\x02Brackets must contain an IPv6 address" +
+ "\x02Invalid MTU\x02Invalid port\x02Invalid persistent keepalive\x02Inval" +
+ "id key: %[1]v\x02Keys must decode to exactly 32 bytes\x02Two commas in a" +
+ " row\x02Tunnel name is not valid\x02Line must occur in a section\x02Conf" +
+ "ig key is missing an equals separator\x02Key must have a value\x02Invali" +
+ "d key for [Interface] section\x02Invalid key for [Peer] section\x02An in" +
+ "terface must have a private key\x02[none specified]\x02All peers must ha" +
+ "ve public keys\x02, \x02, \x02About WireGuard\x02WireGuard logo image" +
+ "\x02Close\x02♥ &Donate!\x02Status:\x02&Deactivate\x02&Activate\x02Public" +
+ " key:\x02Listen port:\x02MTU:\x02Addresses:\x02DNS servers:\x02Scripts:" +
+ "\x02Preshared key:\x02Allowed IPs:\x02Endpoint:\x02Persistent keepalive:" +
+ "\x02Latest handshake:\x02Transfer:\x02pre-up\x02post-up\x02pre-down\x02p" +
+ "ost-down\x02disabled, per policy\x02enabled\x02%[1]s received, %[2]s sen" +
+ "t\x02Failed to determine tunnel state\x02Failed to activate tunnel\x02Fa" +
+ "iled to deactivate tunnel\x02Interface: %[1]s\x02Peer\x02Create new tunn" +
+ "el\x02Edit tunnel\x02&Name:\x02&Public key:\x02(unknown)\x02&Block untun" +
+ "neled traffic (kill-switch)\x02&Save\x02Cancel\x02&Configuration:\x02Inv" +
+ "alid name\x02A name is required.\x02Tunnel name ‘%[1]s’ is invalid.\x02U" +
+ "nable to list existing tunnels\x02Tunnel already exists\x02Another tunne" +
+ "l already exists with the name ‘%[1]s’.\x02Unable to create new configur" +
+ "ation\x02Writing file failed\x02File ‘%[1]s’ already exists.\x0a\x0aDo y" +
+ "ou want to overwrite it?\x02Active\x02Activating\x02Inactive\x02Deactiva" +
+ "ting\x02Unknown state\x02Log\x02&Copy\x02Select &all\x02&Save to file…" +
"\x02Time\x02Log message\x02Text Files (*.txt)|*.txt|All Files (*.*)|*.*" +
"\x02Export log to file\x02&About WireGuard…\x02Tunnel Error\x02%[1]s\x0a" +
"\x0aPlease consult the log for more information.\x02%[1]s (out of date)" +
"\x02WireGuard Detection Error\x02Unable to wait for WireGuard window to " +
"appear: %[1]v\x02WireGuard: Deactivated\x02Status: Unknown\x02Addresses:" +
- " None\x02&Manage tunnels…\x02&Import tunnel(s) from file…\x02E&xit\x02Wi" +
- "reGuard Activated\x02The %[1]s tunnel has been activated.\x02WireGuard D" +
- "eactivated\x02The %[1]s tunnel has been deactivated.\x02WireGuard Tunnel" +
- " Error\x02WireGuard: %[1]s\x02Status: %[1]s\x02Addresses: %[1]s\x02An Up" +
- "date is Available!\x02WireGuard Update Available\x02An update to WireGua" +
- "rd is now available. You are advised to update as soon as possible.\x02T" +
- "unnels\x02&Edit\x02Add &empty tunnel…\x02Add Tunnel\x02Remove selected t" +
- "unnel(s)\x02Export all tunnels to zip\x02&Toggle\x02Export all tunnels t" +
- "o &zip…\x02Edit &selected tunnel…\x02&Remove selected tunnel(s)\x02no co" +
- "nfiguration files were found\x02Could not import selected configuration:" +
- " %[1]v\x02Could not enumerate existing tunnels: %[1]v\x02Another tunnel " +
- "already exists with the name ‘%[1]s’\x02Unable to import configuration: " +
- "%[1]v\x02Imported tunnels\x14\x01\x81\x01\x00\x02\x16\x02Imported %[1]d " +
- "tunnel\x00\x17\x02Imported %[1]d tunnels\x14\x02\x80\x01\x02\x1f\x02Impo" +
- "rted %[1]d of %[2]d tunnel\x00 \x02Imported %[1]d of %[2]d tunnels\x02Un" +
- "able to create tunnel\x14\x01\x81\x01\x00\x02\x14\x02Delete %[1]d tunnel" +
- "\x00\x15\x02Delete %[1]d tunnels\x14\x01\x81\x01\x00\x024\x02Are you sur" +
- "e you would like to delete %[1]d tunnel?\x005\x02Are you sure you would " +
- "like to delete %[1]d tunnels?\x02Delete tunnel ‘%[1]s’\x02Are you sure y" +
- "ou would like to delete tunnel ‘%[1]s’?\x02%[1]s You cannot undo this ac" +
- "tion.\x02Unable to delete tunnel\x02A tunnel was unable to be removed: %" +
- "[1]s\x02Unable to delete tunnels\x14\x01\x81\x01\x00\x02'\x02%[1]d tunne" +
- "l was unable to be removed.\x00)\x02%[1]d tunnels were unable to be remo" +
- "ved.\x02Configuration Files (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)" +
- "|*.*\x02Import tunnel(s) from file\x02Configuration ZIP Files (*.zip)|*." +
- "zip\x02Export tunnels to zip\x02%[1]s (unsigned build, no updates)\x02Er" +
- "ror Exiting WireGuard\x02Unable to exit service due to: %[1]v. You may w" +
- "ant to stop WireGuard from the service manager.\x02An update to WireGuar" +
- "d is available. It is highly advisable to update without delay.\x02Statu" +
- "s: Waiting for user\x02Update Now\x02Status: Waiting for updater service" +
- "\x02Error: %[1]v. Please try again.\x02Status: Complete!\x02pre-up\x02po" +
- "st-up\x02pre-down\x02post-down\x02&Tunnels"
+ " None\x02&Manage tunnels…\x02&Import tunnel(s) from file…\x02E&xit\x02&T" +
+ "unnels\x02WireGuard Activated\x02The %[1]s tunnel has been activated." +
+ "\x02WireGuard Deactivated\x02The %[1]s tunnel has been deactivated.\x02W" +
+ "ireGuard Tunnel Error\x02WireGuard: %[1]s\x02Status: %[1]s\x02Addresses:" +
+ " %[1]s\x02An Update is Available!\x02WireGuard Update Available\x02An up" +
+ "date to WireGuard is now available. You are advised to update as soon as" +
+ " possible.\x02Tunnels\x02&Edit\x02Add &empty tunnel…\x02Add Tunnel\x02Re" +
+ "move selected tunnel(s)\x02Export all tunnels to zip\x02&Toggle\x02Expor" +
+ "t all tunnels to &zip…\x02Edit &selected tunnel…\x02&Remove selected tun" +
+ "nel(s)\x02no configuration files were found\x02Could not import selected" +
+ " configuration: %[1]v\x02Could not enumerate existing tunnels: %[1]v\x02" +
+ "Another tunnel already exists with the name ‘%[1]s’\x02Unable to import " +
+ "configuration: %[1]v\x02Imported tunnels\x14\x01\x81\x01\x00\x02\x16\x02" +
+ "Imported %[1]d tunnel\x00\x17\x02Imported %[1]d tunnels\x14\x02\x80\x01" +
+ "\x02\x1f\x02Imported %[1]d of %[2]d tunnel\x00 \x02Imported %[1]d of %[2" +
+ "]d tunnels\x02Unable to create tunnel\x14\x01\x81\x01\x00\x02\x14\x02Del" +
+ "ete %[1]d tunnel\x00\x15\x02Delete %[1]d tunnels\x14\x01\x81\x01\x00\x02" +
+ "4\x02Are you sure you would like to delete %[1]d tunnel?\x005\x02Are you" +
+ " sure you would like to delete %[1]d tunnels?\x02Delete tunnel ‘%[1]s’" +
+ "\x02Are you sure you would like to delete tunnel ‘%[1]s’?\x02%[1]s You c" +
+ "annot undo this action.\x02Unable to delete tunnel\x02A tunnel was unabl" +
+ "e to be removed: %[1]s\x02Unable to delete tunnels\x14\x01\x81\x01\x00" +
+ "\x02'\x02%[1]d tunnel was unable to be removed.\x00)\x02%[1]d tunnels we" +
+ "re unable to be removed.\x02Configuration Files (*.zip, *.conf)|*.zip;*." +
+ "conf|All Files (*.*)|*.*\x02Import tunnel(s) from file\x02Configuration " +
+ "ZIP Files (*.zip)|*.zip\x02Export tunnels to zip\x02%[1]s (unsigned buil" +
+ "d, no updates)\x02Error Exiting WireGuard\x02Unable to exit service due " +
+ "to: %[1]v. You may want to stop WireGuard from the service manager.\x02A" +
+ "n update to WireGuard is available. It is highly advisable to update wit" +
+ "hout delay.\x02Status: Waiting for user\x02Update Now\x02Status: Waiting" +
+ " for updater service\x02Error: %[1]v. Please try again.\x02Status: Compl" +
+ "ete!\x04\x00\x01 \x07\x02Error:\x04\x00\x01 \x14\x02Invalid IP address:" +
+ "\x02App version: %[1]s\x0aDriver version: %[2]s\x0aGo version: %[3]s\x0a" +
+ "Operating system: %[4]s\x0aArchitecture: %[5]s\x02Table:\x02off\x02When " +
+ "a configuration has exactly one peer, and that peer has an allowed IPs c" +
+ "ontaining at least one of 0.0.0.0/0 or ::/0, and the interface does not " +
+ "have table off, then the tunnel service engages a firewall ruleset to bl" +
+ "ock all traffic that is neither to nor from the tunnel interface or is t" +
+ "o the wrong DNS server, with special exceptions for DHCP and NDP.\x02Ple" +
+ "ase ask the system administrator to update.\x02Status: Waiting for admin" +
+ "istrator"
-var es_ESIndex = []uint32{ // 181 elements
+var es_ESIndex = []uint32{ // 180 elements
// Entry 0 - 1F
0x00000000, 0x00000006, 0x00000044, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
+ 0x00000077, 0x000000c5, 0x000000ff, 0x00000137,
+ 0x00000190, 0x0000020a, 0x0000025d, 0x00000263,
+ 0x0000028a, 0x000002aa, 0x000002ca, 0x000002ea,
+ 0x0000030e, 0x00000334, 0x0000033f, 0x00000347,
+ 0x00000353, 0x0000035f, 0x0000036b, 0x00000377,
+ 0x00000384, 0x000003a1, 0x000003c4, 0x000003f5,
+ 0x0000040a, 0x00000422, 0x00000449, 0x00000467,
// Entry 20 - 3F
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
+ 0x0000049b, 0x000004b2, 0x000004d5, 0x000004fd,
+ 0x0000053a, 0x00000557, 0x0000058b, 0x000005ba,
+ 0x000005e4, 0x000005fb, 0x00000628, 0x0000062b,
+ 0x0000062e, 0x00000642, 0x00000658, 0x0000065f,
+ 0x0000066c, 0x00000674, 0x00000680, 0x00000689,
+ 0x00000699, 0x000006ac, 0x000006b1, 0x000006be,
+ 0x000006ce, 0x000006e6, 0x000006f8, 0x00000708,
+ 0x00000712, 0x00000729, 0x00000739, 0x00000748,
// Entry 40 - 5F
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
+ 0x00000758, 0x00000769, 0x0000077c, 0x00000790,
+ 0x000007ac, 0x000007b7, 0x000007d5, 0x000007fe,
+ 0x00000819, 0x00000837, 0x00000847, 0x0000084b,
+ 0x00000861, 0x0000086f, 0x00000878, 0x00000888,
+ 0x00000896, 0x000008d0, 0x000008d9, 0x000008e2,
+ 0x000008f3, 0x0000090b, 0x00000922, 0x00000952,
+ 0x00000980, 0x00000994, 0x000009c5, 0x000009f3,
+ 0x00000a10, 0x00000a54, 0x00000a5b, 0x00000a65,
// Entry 60 - 7F
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
+ 0x00000a6e, 0x00000a7b, 0x00000a8e, 0x00000a97,
+ 0x00000a9f, 0x00000ab2, 0x00000ac9, 0x00000ad0,
+ 0x00000ae5, 0x00000b22, 0x00000b3e, 0x00000b56,
+ 0x00000b69, 0x00000ba8, 0x00000bbf, 0x00000bdb,
+ 0x00000c20, 0x00000c37, 0x00000c4b, 0x00000c60,
+ 0x00000c79, 0x00000c9f, 0x00000ca6, 0x00000cb0,
+ 0x00000cc3, 0x00000ce5, 0x00000cfb, 0x00000d20,
+ 0x00000d40, 0x00000d51, 0x00000d5f, 0x00000d72,
// Entry 80 - 9F
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
+ 0x00000d97, 0x00000dbe, 0x00000e1b, 0x00000e24,
+ 0x00000e2c, 0x00000e46, 0x00000e55, 0x00000e77,
+ 0x00000e99, 0x00000ea9, 0x00000ecf, 0x00000ef1,
+ 0x00000f14, 0x00000f41, 0x00000f7c, 0x00000fb1,
+ 0x00000fdd, 0x0000100e, 0x00001022, 0x0000105c,
+ 0x000010a7, 0x000010c6, 0x000010fd, 0x00001170,
+ 0x0000118c, 0x000011c8, 0x000011ee, 0x00001210,
+ 0x00001237, 0x0000125c, 0x000012b3, 0x000012ff,
// Entry A0 - BF
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058, 0x00000058, 0x00000058, 0x00000058,
- 0x00000058,
-} // Size: 748 bytes
+ 0x00001321, 0x0000134e, 0x00001366, 0x0000139b,
+ 0x000013b7, 0x00001432, 0x0000148f, 0x000014ac,
+ 0x000014bd, 0x000014ed, 0x00001518, 0x0000152c,
+ 0x0000152c, 0x0000152c, 0x0000152c, 0x0000152c,
+ 0x0000152c, 0x0000152c, 0x0000152c, 0x0000152c,
+} // Size: 744 bytes
-const es_ESData string = "" + // Size: 88 bytes
- "\x02Error\x02(sin argumento): eleva e instala el servicio de administrad" +
- "or\x02Uso: %[1]s [\x0a%[2]s]"
+const es_ESData string = "" + // Size: 5420 bytes
+ "\x02Error\x02(sin argumento): eleve e instale el servicio de administrad" +
+ "or\x02Uso: %[1]s [\x0a%[2]s]\x02Opciones de línea de comandos\x02No fue " +
+ "posible determinar si el proceso se está ejecutando bajo WOW64: %[1]v" +
+ "\x02Debe usar la versión nativa de WireGuard en este equipo.\x02No fue p" +
+ "osible abrir el token del proceso actual: %[1]v\x02WireGuard solo puede " +
+ "ser usado por usuarios que sean miembros del grupo integrado %[1]s.\x02W" +
+ "ireGuard se está ejecutando, pero la interfaz de usuario solo es accesib" +
+ "le desde escritorios del grupo integrado %[1]s.\x02El icono WireGuard de" +
+ " la bandeja del sistema no apareció después de 30 segundos.\x02Ahora\x02" +
+ "¡El reloj del sistema ha retrocedido!\x14\x01\x81\x01\x00\x02\x0b\x02%[" +
+ "1]d año\x00\x0c\x02%[1]d años\x14\x01\x81\x01\x00\x02\x0b\x02%[1]d día" +
+ "\x00\x0c\x02%[1]d días\x14\x01\x81\x01\x00\x02\x0b\x02%[1]d hora\x00\x0c" +
+ "\x02%[1]d horas\x14\x01\x81\x01\x00\x02\x0d\x02%[1]d minuto\x00\x0e\x02%" +
+ "[1]d minutos\x14\x01\x81\x01\x00\x02\x0e\x02%[1]d segundo\x00\x0f\x02%[1" +
+ "]d segundos\x02hace %[1]s\x02%[1]d B\x02%.2[1]f KiB\x02%.2[1]f MiB\x02%." +
+ "2[1]f GiB\x02%.2[1]f TiB\x02%[1]s: %[2]q\x02Falta el puerto del Endpoint" +
+ "\x02El host del Endpoint no es válido\x02Los corchetes deben contener un" +
+ "a dirección IPv6\x02La MTU no es válida\x02El puerto no es válido\x02El " +
+ "Keepalive persistente no es válido\x02La clave no es válida: %[1]v\x02La" +
+ "s claves deben decodificar exactamente a 32 bytes\x02Dos comas consecuti" +
+ "vas\x02El nombre del túnel no es válido\x02La línea debe aparecer en una" +
+ " sección\x02La clave de configuración no tiene un separador de igualdad" +
+ "\x02La clave debe tener un valor\x02La clave no es válida para la secció" +
+ "n [Interface]\x02La clave no es válida para la sección [Peer]\x02Una int" +
+ "erfaz debe tener una clave privada\x02[ninguno especificado]\x02Todos lo" +
+ "s pares deben tener claves públicas\x02, \x02, \x02Acerca de WireGuard" +
+ "\x02Logotipo de WireGuard\x02Cerrar\x02♥ &¡Dona!\x02Estado:\x02&Desactiv" +
+ "ar\x02&Activar\x02Clave pública:\x02Puerto de escucha:\x02MTU:\x02Direcc" +
+ "iones:\x02Servidores DNS:\x02Secuencias de comandos:\x02Clave compartida" +
+ ":\x02IPs permitidas:\x02Endpoint:\x02Keepalive persistente:\x02Último sa" +
+ "ludo:\x02Transferencia:\x02pre-activación\x02post-activación\x02pre-desa" +
+ "ctivación\x02post-desactivación\x02inhabilitado, por política\x02habilit" +
+ "ado\x02%[1]s recibido, %[2]s enviado\x02Error al determinar el estado de" +
+ "l túnel\x02Error al activar el túnel\x02Error al desactivar el túnel\x02" +
+ "Interfaz: %[1]s\x02Par\x02Crear un túnel nuevo\x02Editar túnel\x02&Nombr" +
+ "e:\x02Clave pública:\x02(desconocido)\x02&Bloquear tráfico sin tunelizar" +
+ " (interruptor de apagado)\x02&Guardar\x02Cancelar\x02&Configuración:\x02" +
+ "El nombre no es válido\x02Se requiere un nombre.\x02El nombre del túnel " +
+ "‘%[1]s’ no es válido.\x02No fue posible listar los túneles existentes" +
+ "\x02El túnel ya existe\x02Ya existe otro túnel con el nombre ‘%[1]s’." +
+ "\x02No fue posible crear una nueva configuración\x02Error al escribir el" +
+ " archivo\x02El archivo ‘%[1]s’ ya existe.\x0a\x0a¿Desea sobrescribir el " +
+ "archivo?\x02Activo\x02Activando\x02Inactivo\x02Desactivando\x02Estado de" +
+ "sconocido\x02Registro\x02&Copiar\x02Seleccionar &todos\x02&Guardar en ar" +
+ "chivo…\x02Tiempo\x02Mensaje del registro\x02Archivos de texto (*.txt)|*." +
+ "txt|Todos los archivos (*.*)|*.*\x02Exportar registro a archivo\x02&Acer" +
+ "ca de WireGuard…\x02Error en el túnel\x02%[1]s\x0a\x0aPor favor, consult" +
+ "e el registro para más información.\x02%[1]s (desactualizado)\x02Error a" +
+ "l detectar WireGuard\x02No fue posible esperar a que aparezca la ventana" +
+ " de WireGuard: %[1]v\x02WireGuard: Desactivado\x02Estado: Desconocido" +
+ "\x02Direcciones: Ninguna\x02&Administrar túneles…\x02&Importar túnel(es)" +
+ " desde archivo…\x02&Salir\x02&Túneles\x02WireGuard Activado\x02El túnel " +
+ "%[1]s ha sido activado.\x02WireGuard Desactivado\x02El túnel %[1]s ha si" +
+ "do desactivado.\x02Error en el túnel de WireGuard\x02WireGuard: %[1]s" +
+ "\x02Estado: %[1]s\x02Direcciones: %[1]s\x02¡Hay una actualización dispon" +
+ "ible!\x02Actualización de WireGuard disponible\x02Está disponible una ac" +
+ "tualización de WireGuard. Se recomienda actualizar lo antes posible.\x02" +
+ "Túneles\x02&Editar\x02Agregar &túnel vacío…\x02Agregar túnel\x02Eliminar" +
+ " túnel(es) seleccionados\x02Exportar todos los túneles a ZIP\x02&Cambiar" +
+ " estado\x02Exportar todos los túneles a &ZIP…\x02Editar túneles &selecci" +
+ "onados…\x02&Eliminar túnel(es) seleccionados\x02no se encontraron archiv" +
+ "os de configuración\x02No se puede importar la configuración seleccionad" +
+ "a: %[1]v\x02No se pueden enumerar los túneles existentes: %[1]v\x02Ya ex" +
+ "iste otro túnel con el nombre '%[1]s'\x02No fue posible importar la conf" +
+ "iguración: %[1]v\x02Túneles importados\x14\x01\x81\x01\x00\x02\x17\x02%[" +
+ "1]d túnel importado\x00\x1a\x02%[1]d túneles importados\x14\x02\x80\x01" +
+ "\x02 \x02Importado %[1]d de %[2]d túnel\x00#\x02Importados %[1]d de %[2]" +
+ "d túneles\x02No fue posible crear el túnel\x14\x01\x81\x01\x00\x02\x16" +
+ "\x02Eliminar %[1]d túnel\x00\x18\x02Eliminar %[1]d túneles\x14\x01\x81" +
+ "\x01\x00\x024\x02¿Está seguro de que querer eliminar %[1]d túnel?\x006" +
+ "\x02¿Está seguro de que querer eliminar %[1]d túneles?\x02Eliminar túnel" +
+ " ‘%[1]s’\x02¿Está seguro de que desea eliminar el túnel ‘%[1]s’?\x02%[1]" +
+ "s No puede deshacer esta acción.\x02No fue posible eliminar el túnel\x02" +
+ "Un túnel no pudo ser eliminado: %[1]s\x02No fue posible eliminar los tún" +
+ "eles\x14\x01\x81\x01\x00\x02&\x02No fue posible eliminar %[1]d túnel." +
+ "\x00(\x02No fue posible eliminar %[1]d túneles.\x02Archivos de configura" +
+ "ción (*.zip, *.conf)|*.zip;*.conf|All Files (*.*)|*.*\x02Importar túnel(" +
+ "es) desde archivo\x02Archivos ZIP de configuración (*.zip)|*.zip\x02Expo" +
+ "rtar túneles a ZIP\x02%[1]s (compilación no firmada, sin actualizaciones" +
+ ")\x02Error al salir de WireGuard\x02No fue posible terminar el servicio " +
+ "debido a: %[1]v. Puede intentar detener WireGuard desde el administrador" +
+ " de servicios.\x02Hay una actualización de Wireguard disponible. Es muy " +
+ "recomendable actualizar de inmediato.\x02Estado: Esperando al usuario" +
+ "\x02Actualizar ahora\x02Estado: Esperando al servicio de actualización" +
+ "\x02Error: %[1]v. Por favor, intente de nuevo.\x02Estado: ¡Completo!"
-var faIndex = []uint32{ // 181 elements
+var etIndex = []uint32{ // 180 elements
// Entry 0 - 1F
- 0x00000000, 0x00000007, 0x00000007, 0x00000007,
- 0x0000002b, 0x0000002b, 0x0000002b, 0x0000002b,
- 0x0000002b, 0x0000002b, 0x0000002b, 0x0000003b,
- 0x0000003b, 0x0000005e, 0x00000081, 0x000000a8,
- 0x000000d3, 0x000000fe, 0x0000010b, 0x0000011b,
- 0x0000011b, 0x0000011b, 0x0000011b, 0x0000011b,
- 0x0000011b, 0x00000148, 0x00000148, 0x00000148,
- 0x00000148, 0x00000148, 0x00000162, 0x0000017a,
+ 0x00000000, 0x00000005, 0x0000003c, 0x00000055,
+ 0x00000066, 0x000000ae, 0x000000eb, 0x0000011a,
+ 0x00000173, 0x000001dd, 0x0000021d, 0x00000224,
+ 0x00000247, 0x00000269, 0x0000028b, 0x000002ab,
+ 0x000002ce, 0x000002f3, 0x00000300, 0x00000309,
+ 0x00000316, 0x00000323, 0x00000330, 0x0000033d,
+ 0x0000034a, 0x0000036c, 0x0000038a, 0x000003b3,
+ 0x000003c0, 0x000003ce, 0x000003f8, 0x0000040e,
// Entry 20 - 3F
- 0x0000017a, 0x0000017a, 0x0000017a, 0x0000017a,
- 0x0000017a, 0x0000017a, 0x0000017a, 0x0000017a,
- 0x000001b0, 0x000001b0, 0x000001b0, 0x000001b0,
- 0x000001c4, 0x00000214, 0x0000023e, 0x0000023e,
- 0x0000023e, 0x0000023e, 0x00000242, 0x00000246,
- 0x0000025d, 0x0000025d, 0x0000025d, 0x00000266,
- 0x0000027d, 0x00000289, 0x000002a4, 0x000002b9,
- 0x000002ce, 0x000002e1, 0x000002e6, 0x000002f9,
+ 0x00000445, 0x00000458, 0x00000472, 0x00000495,
+ 0x000004c7, 0x000004e3, 0x00000506, 0x00000524,
+ 0x00000544, 0x00000556, 0x00000585, 0x00000588,
+ 0x0000058b, 0x00000599, 0x000005ad, 0x000005b3,
+ 0x000005c0, 0x000005c9, 0x000005d8, 0x000005e1,
+ 0x000005ef, 0x000005fd, 0x00000602, 0x0000060d,
+ 0x0000061b, 0x00000625, 0x00000637, 0x0000064d,
+ 0x0000065a, 0x00000671, 0x00000684, 0x00000690,
// Entry 40 - 5F
- 0x0000030d, 0x0000030d, 0x00000335, 0x00000348,
- 0x0000035d, 0x00000388, 0x00000388, 0x00000396,
- 0x00000396, 0x000003a6, 0x000003a6, 0x000003a6,
- 0x000003a6, 0x000003a6, 0x000003b6, 0x000003bf,
- 0x000003dc, 0x000003f2, 0x000003fb, 0x00000411,
- 0x00000424, 0x00000424, 0x00000424, 0x00000430,
- 0x00000437, 0x0000044a, 0x00000460, 0x00000481,
- 0x00000481, 0x000004c7, 0x000004f4, 0x000004f4,
+ 0x000006a1, 0x000006b5, 0x000006cc, 0x000006e6,
+ 0x00000704, 0x0000070c, 0x00000730, 0x00000757,
+ 0x00000778, 0x0000079f, 0x000007ad, 0x000007b5,
+ 0x000007c4, 0x000007d3, 0x000007da, 0x000007e9,
+ 0x000007f4, 0x00000820, 0x0000082a, 0x00000830,
+ 0x0000083c, 0x0000084a, 0x0000085f, 0x00000881,
+ 0x000008a9, 0x000008bf, 0x000008e5, 0x00000909,
+ 0x00000928, 0x0000096e, 0x00000979, 0x00000984,
// Entry 60 - 7F
- 0x000004f4, 0x000004f4, 0x000004f4, 0x000004fd,
- 0x0000051d, 0x0000052c, 0x00000552, 0x0000056e,
- 0x00000584, 0x00000592, 0x00000592, 0x000005b3,
- 0x000005bc, 0x000005dd, 0x000005dd, 0x00000619,
- 0x00000634, 0x00000648, 0x00000648, 0x00000648,
- 0x00000648, 0x00000648, 0x00000648, 0x00000665,
- 0x0000067f, 0x000006a0, 0x000006a0, 0x000006a0,
- 0x000006ba, 0x000006dc, 0x000006fa, 0x000006fa,
+ 0x00000991, 0x000009a2, 0x000009b0, 0x000009b5,
+ 0x000009be, 0x000009ca, 0x000009dd, 0x000009e1,
+ 0x000009ec, 0x00000a1e, 0x00000a33, 0x00000a45,
+ 0x00000a52, 0x00000a8d, 0x00000aa0, 0x00000ab9,
+ 0x00000af0, 0x00000b0c, 0x00000b23, 0x00000b33,
+ 0x00000b47, 0x00000b66, 0x00000b6c, 0x00000b76,
+ 0x00000b8b, 0x00000ba9, 0x00000bc4, 0x00000be8,
+ 0x00000bff, 0x00000c10, 0x00000c1f, 0x00000c30,
// Entry 80 - 9F
- 0x00000716, 0x00000716, 0x00000728, 0x00000728,
- 0x0000075d, 0x00000796, 0x00000796, 0x000007a6,
- 0x000007b4, 0x000007e2, 0x000007f8, 0x0000081d,
- 0x00000852, 0x00000852, 0x0000088b, 0x0000088b,
- 0x0000088b, 0x0000088b, 0x0000088b, 0x0000088b,
- 0x0000088b, 0x0000088b, 0x000008ad, 0x000008f0,
- 0x00000948, 0x00000975, 0x000009aa, 0x000009aa,
- 0x000009c6, 0x000009c6, 0x000009c6, 0x000009f8,
+ 0x00000c45, 0x00000c60, 0x00000cb6, 0x00000cbf,
+ 0x00000cc6, 0x00000cdc, 0x00000ce8, 0x00000d03,
+ 0x00000d25, 0x00000d35, 0x00000d5b, 0x00000d76,
+ 0x00000d92, 0x00000db3, 0x00000deb, 0x00000e23,
+ 0x00000e48, 0x00000e6e, 0x00000e82, 0x00000ebd,
+ 0x00000f0d, 0x00000f22, 0x00000f57, 0x00000fc9,
+ 0x00000fe0, 0x0000101d, 0x00001047, 0x00001061,
+ 0x00001085, 0x000010a0, 0x000010f1, 0x00001135,
// Entry A0 - BF
- 0x000009f8, 0x00000a2d, 0x00000a2d, 0x00000a2d,
- 0x00000a60, 0x00000a9c, 0x00000aca, 0x00000aca,
- 0x00000b00, 0x00000b00, 0x00000b00, 0x00000b31,
- 0x00000b5a, 0x00000ba3, 0x00000bdb, 0x00000bf6,
- 0x00000bf6, 0x00000bf6, 0x00000bf6, 0x00000bf6,
- 0x00000bf6,
-} // Size: 748 bytes
+ 0x00001150, 0x00001179, 0x00001195, 0x000011ca,
+ 0x000011e6, 0x00001257, 0x000012ad, 0x000012cc,
+ 0x000012da, 0x000012ff, 0x00001323, 0x00001334,
+ 0x00001334, 0x00001334, 0x00001334, 0x00001334,
+ 0x00001334, 0x00001334, 0x00001334, 0x00001334,
+} // Size: 744 bytes
-const faData string = "" + // Size: 3062 bytes
- "\x02خطا\x02گزینه\u200cهای خط فرمان\x02هم اکنون\x14\x01\x81\x01\x00\x02" +
- "\x0d\x02%[1]d سال\x00\x0d\x02%[1]d سال\x14\x01\x81\x01\x00\x02\x0d\x02%[" +
- "1]d روز\x00\x0d\x02%[1]d روز\x14\x01\x81\x01\x00\x02\x0f\x02%[1]d ساعت" +
- "\x00\x0f\x02%[1]d ساعت\x14\x01\x81\x01\x00\x02\x11\x02%[1]d دقیقه\x00" +
- "\x11\x02%[1]d دقیقه\x14\x01\x81\x01\x00\x02\x11\x02%[1]d ثانیه\x00\x11" +
- "\x02%[1]d ثانیه\x02%[1]s پیش\x02%[1]d\u00a0بایت\x02نشانی آی\u200cپی نامع" +
- "تبر است\x02MTU نامعتبر است\x02پورت نامعتبر\x02کلید باید یک مقدار داشته " +
- "باشد\x02[مشخص نشده]\x02همه همتاها باید کلید\u200cهای عمومی داشته باشند" +
- "\x02خطا در دریافت پیکربندی\x02، \x02، \x02درباره WireGuard\x02بستن\x02♥&" +
- "کمک\u200cمالی!\x02وضعیت:\x02&غیرفعال\u200cسازی\x02&فعال\u200cسازی\x02کل" +
- "ید عمومی:\x02پورت شنود:\x02MTU:\x02نشانی\u200cها:\x02سرورهای DNS:\x02کل" +
- "ید از پیش تقسیم شده:\x02IPهای مجاز:\x02نقطه پایان:\x02زنده نگه\u200cداش" +
- "تن پیوسته:\x02انتقال:\x02فعال شده\x02رابط: %[1]s\x02همتا\x02ایجاد تونل " +
- "جدید\x02ویرایش تونل\x02&نام:\x02&کلید عمومی:\x02(ناشناخته)\x02&ذخیره" +
- "\x02لغو\x02&پیکربندی:\x02نام نامعتبر\x02یک نام الزامی است.\x02نمی\u200cت" +
- "وان تونل\u200cهای موجود را فهرست کرد\x02تونل هم\u200cاکنون موجود است" +
- "\x02فعال\x02در حال فعال\u200cسازی\x02غیرفعال\x02در حال غیرفعال\u200cسازی" +
- "\x02وضعیت ناشناخته\x02گزارش وقایع\x02&روگرفت\x02&ذخیره در پرونده…\x02زما" +
- "ن\x02پیام گزارش رویداد\x02برون\u200cبرد گزارش رویداد به پرونده\x02&دربا" +
- "ره WireGuard…\x02خطالی تونل\x02وضعیت: ناشناخته\x02نشانی\u200cها: هیچ" +
- "\x02&مدیریت تونل\u200cها…\x02WireGuard فعال\u200cشد\x02تونل %[1]s فعال" +
- "\u200cشده.\x02WireGuard غیرفعال شد\x02خطای تونل WireGuard\x02وضعیت: %[1]" +
- "s\x02یک به\u200cروزرسانی در دسترس است!\x02به\u200cروزرسانی WireGuard در " +
- "دسترس است\x02تونل\u200cها\x02&ویرایش\x02افزودن &خالی\u200cکردن تونل…" +
- "\x02افزودن تونل\x02حذف تونل(ها) انتخابی\x02برون\u200cبری همه تونل\u200cه" +
- "ا به زیپ\x02برون\u200cبری همه تونل\u200cها به &زیپ…\x02تونل\u200cهای وا" +
- "رد شده\x14\x01\x81\x01\x00\x02\x1d\x02%[1]d تونل وارد شد\x00\x1d\x02%[1" +
- "]d تونل وارد شد\x14\x02\x80\x01\x02(\x02%[1]d از %[2]d تونل وارد شد\x00(" +
- "\x02%[1]d از %[2]d تونل وارد شد\x02نمی\u200cتوان تونل ایجاد کرد\x14\x01" +
- "\x81\x01\x00\x02\x16\x02حذف %[1]d تونل\x00\x16\x02حذف %[1]d تونل\x02حذف " +
- "تونل ‘%[1]s’\x02حذف تونل\u200c امکان\u200cپذیر نیست\x02نمی\u200cتوان تو" +
- "نل\u200cها را حذف کرد\x02وارد کردن تونل(ها) از پرونده\x02پرونده\u200cها" +
- "ی پیکربندی زیپ (*.zip)|*.zip\x02برون\u200cبری تونل\u200cها به زیپ\x02خط" +
- "ا در هنگام خارج شدن از WireGuard\x02وضعیت: درانتظار برای کاربر\x02اکنون" +
- " به\u200cروز رسانی کن\x02وضعیت: درانتظار برای سرویس به\u200cروزرسانی\x02" +
- "خطا: %[1]v. لطفا دوباره تلاش کنید.\x02وضعیت: کامل شد!"
+const etData string = "" + // Size: 4916 bytes
+ "\x02Viga\x02(tühi muutuja): paigalda haldusteenus ülemõigustega\x02Kasut" +
+ "us: %[1]s [ \x0a%[2]s]\x02Käsurea valikud\x02Pole võimalik tuvastada, ka" +
+ "s protsess töötab WOW64 kontekstis: %[1]v\x02Peate kasutama antud arvuti" +
+ "ga sobivat WireGuard'i versiooni.\x02Praeguse protsessi tähist ei saa av" +
+ "ada: %[1]v\x02WireGuard'i võivad kasutada ainult kasutajad, kes on sisse" +
+ "ehitatud %[1]s grupi liikmed.\x02WireGuard töötab, aga kasutajaliides on" +
+ " ainult ligipääsetav sisseehitatud %[1]s grupi töölaudadest.\x02WireGuar" +
+ "d'i süsteemisalve ikoon ei ilmunud 30 sekundi jooksul.\x02Nüüd\x02Süstee" +
+ "mi kella on tagasi keritud!\x14\x01\x81\x01\x00\x02\x0c\x02%[1]d aasta" +
+ "\x00\x0d\x02%[1]d aastat\x14\x01\x81\x01\x00\x02\x0c\x02%[1]d päev\x00" +
+ "\x0d\x02%[1]d päeva\x14\x01\x81\x01\x00\x02\x0b\x02%[1]d tund\x00\x0c" +
+ "\x02%[1]d tundi\x14\x01\x81\x01\x00\x02\x0c\x02%[1]d minut\x00\x0e\x02%[" +
+ "1]d minutit\x14\x01\x81\x01\x00\x02\x0d\x02%[1]d sekund\x00\x0f\x02%[1]d" +
+ " sekundit\x02%[1]s tagasi\x02%[1]d\u00a0B\x02%.2[1]f\u00a0KiB\x02%.2[1]f" +
+ "\u00a0MiB\x02%.2[1]f\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02Lõp" +
+ "p-punktis on port määramata\x02Sobimatu lõpp-punkti aadress\x02Looksulud" +
+ " peavad sisaldama IPv6-aadressi\x02Sobimatu MTU\x02Sobimatu port\x02Sobi" +
+ "matu kestva ühendushoidiku väärtus\x02Sobimatu võti: %[1]v\x02Võtmed pea" +
+ "vad dekodeerima täpselt 32 baidi suuruseks\x02Kaks koma järjest\x02Tunne" +
+ "li nimi pole sobilik\x02Rida peab olemas olema lõigu sees\x02Seadistusvõ" +
+ "tmel on võrdusmärk eraldajana puudu\x02Võti peab omama väärtust\x02Sobim" +
+ "atu võti [Interface] lõigus\x02Sobimatu võti [Peer] lõigus\x02Liides pea" +
+ "b omama privaatvõtit\x02[pole määratud]\x02Kõik partnerid peavad omama a" +
+ "valikke võtmeid\x02, \x02, \x02WireGuard'ist\x02WireGuard logo pilt\x02S" +
+ "ulge\x02♥ &Anneta!\x02Staatus:\x02&Ühendu lahti\x02&Ühenda\x02Avalik võt" +
+ "i:\x02Kuulamisport:\x02MTU:\x02Aadressid:\x02DNS-serverid:\x02Skriptid:" +
+ "\x02Eeljagatud võti:\x02Lubatud IP-aadressid:\x02Lõpp-punkt:\x02Kestev ü" +
+ "hendushoidik:\x02Värskeim kätlus:\x02Ülekanded:\x02enne ühendumist\x02pä" +
+ "rast ühendumist\x02enne lahti ühendumist\x02pärast lahti ühendumist\x02k" +
+ "eelatud, poliitika põhiselt\x02lubatud\x02%[1]s vastu võetud, %[2]s saad" +
+ "etud\x02Tunneli oleku tuvastamine ebaõnnestus\x02Tunneli ühendamine ebaõ" +
+ "nnestus\x02Tunneli lahti ühendamine ebaõnnestus\x02Liides: %[1]s\x02Part" +
+ "ner\x02Loo uus tunnel\x02Muuda tunnelit\x02&Nimi:\x02&Avalik võti:\x02(t" +
+ "undmatu)\x02&Keela tunneldamata liiklus (kaitselüliti)\x02&Salvesta\x02L" +
+ "oobu\x02&Seadistus:\x02Sobimatu nimi\x02Nimi on kohustuslik.\x02Tunneli " +
+ "nimi '%[1]s' on sobimatu.\x02Olemasolevaid tunneleid ei saa loetleda\x02" +
+ "Tunnel on juba olemas\x02Tunnel nimega '%[1]s' juba on olemas.\x02Uue se" +
+ "adistuse loomine ebaõnnestus\x02Faili kirjutamine ebaõnnestus\x02Fail ni" +
+ "mega '%[1]s' on juba olemas.\x0a\x0aKas soovid selle üle kirjutada?\x02Ü" +
+ "henduses\x02Ühendumas\x02Jõudeolekus\x02Lahti ühendumas\x02Tundmatu olek" +
+ "\x02Logi\x02&Kopeeri\x02Vali &kõik\x02&Salvesta faili…\x02Aeg\x02Logisõn" +
+ "um\x02Tekstifailid (*.txt)|*.txt|Kõik failid (*.*)|*.*\x02Ekspordi logid" +
+ " faili\x02WireGu&ard'ist…\x02Tunneli viga\x02%[1]s\x0a\x0aLisainformatsi" +
+ "ooni saamiseks palun vaadake logisid.\x02%[1]s (uuendamata)\x02WireGuard" +
+ "'i tuvastusviga\x02WireGuard'i akna ilmumise ootamine ebaõnnestus: %[1]v" +
+ "\x02WireGuard: Lahti ühendatud\x02Staatus: Tundmatu olek\x02Aadressid: P" +
+ "ole\x02&Halda tunneleid…\x02&Impordi tunnel(id) failist…\x02Sul&e\x02&Tu" +
+ "nnelid\x02WireGuard ühendatud\x02Tunnel '%[1]s' on ühendatud.\x02WireGua" +
+ "rd lahti ühendatud\x02Tunnel '%[1]s' on lahti ühendatud.\x02WireGuard tu" +
+ "nneli viga\x02WireGuard: %[1]s\x02Staatus: %[1]s\x02Aadressid: %[1]s\x02" +
+ "Uuendus on saadaval!\x02WireGuard uuendus saadaval\x02WireGuard'i uuendu" +
+ "s on nüüd saadaval. Soovitame teil esimesel võimalusel uuendada.\x02Tunn" +
+ "elid\x02&Muuda\x02Lisa tühi tunn&el…\x02Lisa tunnel\x02Eemalda valitud t" +
+ "unnel(id)\x02Ekspordi kõik tunnelid zip-faili\x02Lüli&tu ümber\x02Ekspor" +
+ "di kõik tunnelid &zip-faili…\x02Muuda &valitud tunnelit…\x02&Eemalda val" +
+ "itud tunnel(id)\x02ühtegi seadistusfaili ei leitud\x02Pole võimeline imp" +
+ "ortima valitud seadistusfaili: %[1]v\x02Pole võimeline loetlema olemasol" +
+ "evaid tunneleid: %[1]v\x02Tunnel nimega '%[1]s' on juba olemas\x02Seadis" +
+ "tuse import ebaõnnestus: %[1]v\x02Imporditud tunnelid\x14\x01\x81\x01" +
+ "\x00\x02\x18\x02Imporditud %[1]d tunnel\x00\x1a\x02Importitud %[1]d tunn" +
+ "elit\x14\x02\x80\x01\x02$\x02Imporditud %[1]d %[2]d-st tunnelist\x00$" +
+ "\x02Imporditud %[1]d %[2]d-st tunnelist\x02Tunnelit ei saa luua\x14\x01" +
+ "\x81\x01\x00\x02\x15\x02Kustuta %[1]d tunnel\x00\x17\x02Kustuta %[1]d tu" +
+ "nnelit\x14\x01\x81\x01\x00\x024\x02Kas oled kindel, et soovid kustutada " +
+ "%[1]d tunneli?\x005\x02Kas oled kindel, et soovid kustutada %[1]d tunnel" +
+ "it?\x02Kustuta tunnel '%[1]s'\x02Kas oled kindel, et soovid kustutada tu" +
+ "nneli nimega '%[1]s'?\x02%[1]s Seda tegevust ei saa tagasi võtta.\x02Tun" +
+ "nelit ei saa kustutada\x02Tunnelit ei saanud kustutada: %[1]s\x02Tunnele" +
+ "id ei saa kustutada\x14\x01\x81\x01\x00\x02$\x02Ei saanud eemaldada %[1]" +
+ "d tunnelit.\x00$\x02Ei saanud eemaldada %[1]d tunnelit.\x02Seadistusfail" +
+ "id (*.zip, *.conf)|*.zip;*.conf|Kõik failid (*.*)|*.*\x02Impordi tunnel(" +
+ "id) failist\x02Pakendatud seadistusfailid (*.zip)|*.zip\x02Ekspordi tunn" +
+ "elid zip-faili\x02%[1]s (allkirjastamata kompilatsioon, uuendusi pole)" +
+ "\x02Viga WireGuard'i sulgemisel\x02Teenuse lõpetamine ebaõnnestus järgne" +
+ "va tõttu: %[1]v. Võid proovida WireGuard'i lõpetada teenusehaldurist." +
+ "\x02WireGuard'ile on uuendus saadaval. Sügavalt soovitame uuendada niipe" +
+ "a kui võimalik.\x02Staatus: Ootan kasutaja järel\x02Uuenda nüüd\x02Staat" +
+ "us: Ootan uuendusteenuse järel\x02Viga: %[1]v. Palun proovige uuesti." +
+ "\x02Staatus: Valmis!"
-var fiIndex = []uint32{ // 181 elements
+var faIndex = []uint32{ // 180 elements
// Entry 0 - 1F
- 0x00000000, 0x00000006, 0x00000006, 0x00000006,
- 0x00000006, 0x00000006, 0x00000006, 0x00000006,
- 0x00000006, 0x00000006, 0x00000006, 0x0000000a,
- 0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a,
- 0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a,
- 0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a,
- 0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a,
- 0x0000002a, 0x0000002a, 0x0000002a, 0x0000002a,
+ 0x00000000, 0x00000007, 0x0000005b, 0x0000007a,
+ 0x0000009e, 0x000000fe, 0x00000171, 0x000001a3,
+ 0x00000222, 0x000002bb, 0x0000031d, 0x0000032d,
+ 0x00000357, 0x0000037a, 0x0000039d, 0x000003c4,
+ 0x000003ef, 0x0000041a, 0x00000427, 0x00000437,
+ 0x00000444, 0x00000451, 0x0000045e, 0x0000046b,
+ 0x00000478, 0x000004b0, 0x000004e9, 0x00000526,
+ 0x00000540, 0x00000558, 0x00000592, 0x000005b1,
// Entry 20 - 3F
- 0x00000049, 0x00000049, 0x00000049, 0x00000049,
- 0x00000049, 0x00000049, 0x00000049, 0x00000049,
- 0x00000049, 0x00000049, 0x00000049, 0x00000049,
- 0x00000049, 0x00000049, 0x00000049, 0x00000049,
- 0x00000049, 0x00000049, 0x0000004c, 0x0000004c,
- 0x00000061, 0x00000076, 0x00000076, 0x0000007c,
- 0x0000008b, 0x00000091, 0x00000091, 0x00000091,
- 0x00000091, 0x00000091, 0x00000096, 0x000000a1,
+ 0x000005ff, 0x0000061e, 0x00000642, 0x0000066d,
+ 0x000006b3, 0x000006e9, 0x0000072d, 0x0000076c,
+ 0x000007b0, 0x000007c4, 0x00000814, 0x00000818,
+ 0x0000081c, 0x00000833, 0x00000853, 0x0000085c,
+ 0x00000873, 0x0000087f, 0x0000089a, 0x000008af,
+ 0x000008c4, 0x000008d7, 0x000008dc, 0x000008ef,
+ 0x00000903, 0x0000091a, 0x00000942, 0x00000955,
+ 0x0000096a, 0x00000995, 0x000009b1, 0x000009bf,
// Entry 40 - 5F
- 0x000000b1, 0x000000c0, 0x000000ce, 0x000000e5,
- 0x000000f3, 0x00000106, 0x0000011a, 0x00000123,
- 0x00000123, 0x00000123, 0x00000123, 0x00000123,
- 0x00000123, 0x00000123, 0x00000123, 0x0000012c,
- 0x0000013d, 0x0000014e, 0x00000155, 0x00000166,
- 0x00000173, 0x000001a3, 0x000001a3, 0x000001ad,
- 0x000001ad, 0x000001bd, 0x000001cf, 0x000001e3,
- 0x000001e3, 0x000001e3, 0x000001fa, 0x000001fa,
+ 0x000009ce, 0x000009eb, 0x00000a03, 0x00000a19,
+ 0x00000a45, 0x00000a55, 0x00000a85, 0x00000ab4,
+ 0x00000ae3, 0x00000b18, 0x00000b28, 0x00000b31,
+ 0x00000b4e, 0x00000b64, 0x00000b6d, 0x00000b83,
+ 0x00000b96, 0x00000bde, 0x00000bea, 0x00000bf1,
+ 0x00000c04, 0x00000c1a, 0x00000c3b, 0x00000c6f,
+ 0x00000cb5, 0x00000ce2, 0x00000d1d, 0x00000d54,
+ 0x00000d7e, 0x00000df6, 0x00000dff, 0x00000e1f,
// Entry 60 - 7F
- 0x000001fa, 0x000001fa, 0x000001fa, 0x000001fa,
- 0x000001fa, 0x000001fa, 0x000001fa, 0x000001fa,
- 0x000001ff, 0x00000207, 0x00000207, 0x00000207,
- 0x00000207, 0x00000207, 0x00000207, 0x00000207,
- 0x00000207, 0x00000207, 0x00000207, 0x00000207,
- 0x00000207, 0x00000207, 0x00000207, 0x00000207,
- 0x00000207, 0x00000207, 0x00000207, 0x00000207,
- 0x00000207, 0x00000207, 0x00000207, 0x00000207,
+ 0x00000e2e, 0x00000e54, 0x00000e70, 0x00000e86,
+ 0x00000e94, 0x00000ea8, 0x00000ec9, 0x00000ed2,
+ 0x00000ef3, 0x00000f45, 0x00000f81, 0x00000f9c,
+ 0x00000fb0, 0x00001017, 0x0000102a, 0x00001054,
+ 0x000010ab, 0x000010d4, 0x000010f1, 0x0000110b,
+ 0x0000112c, 0x00001163, 0x0000116c, 0x0000117d,
+ 0x00001198, 0x000011c2, 0x000011e0, 0x0000120d,
+ 0x00001229, 0x0000123a, 0x0000124c, 0x00001265,
// Entry 80 - 9F
- 0x00000207, 0x00000207, 0x00000207, 0x00000207,
- 0x00000220, 0x0000023f, 0x0000029f, 0x000002a7,
- 0x000002b0, 0x000002b0, 0x000002b0, 0x000002b0,
- 0x000002b0, 0x000002b0, 0x000002b0, 0x000002b0,
- 0x000002b0, 0x000002b0, 0x000002b0, 0x000002b0,
- 0x000002b0, 0x000002b0, 0x000002c0, 0x000002f2,
- 0x000002f2, 0x000002f2, 0x000002f2, 0x000002f2,
- 0x000002f2, 0x000002f2, 0x000002f2, 0x000002f2,
+ 0x0000129a, 0x000012d3, 0x00001374, 0x00001384,
+ 0x00001392, 0x000013c0, 0x000013d6, 0x000013fb,
+ 0x00001430, 0x00001446, 0x0000147f, 0x000014a7,
+ 0x000014d4, 0x00001505, 0x00001552, 0x00001552,
+ 0x00001552, 0x00001552, 0x00001574, 0x000015b7,
+ 0x0000160f, 0x0000163c, 0x00001671, 0x00001671,
+ 0x0000168d, 0x0000168d, 0x0000168d, 0x000016bf,
+ 0x000016bf, 0x000016f4, 0x000016f4, 0x000016f4,
// Entry A0 - BF
- 0x000002f2, 0x0000030c, 0x0000030c, 0x0000030c,
- 0x00000327, 0x00000327, 0x00000327, 0x00000327,
- 0x00000327, 0x00000327, 0x00000327, 0x00000345,
- 0x00000353, 0x00000353, 0x00000353, 0x00000361,
- 0x00000361, 0x00000361, 0x00000361, 0x00000361,
- 0x00000361,
-} // Size: 748 bytes
+ 0x00001727, 0x00001763, 0x00001791, 0x00001791,
+ 0x000017c7, 0x000017c7, 0x000017c7, 0x000017f8,
+ 0x00001821, 0x00001868, 0x000018a0, 0x000018bb,
+ 0x000018bb, 0x000018bb, 0x000018bb, 0x000018bb,
+ 0x000018bb, 0x000018bb, 0x000018bb, 0x000018bb,
+} // Size: 744 bytes
-const fiData string = "" + // Size: 865 bytes
- "\x02Virhe\x02Nyt\x02Järjestelmän kello jättää!\x02Virheellinen jatkuva k" +
- "eepalive\x02, \x02Tietoa WireGuardista\x02WireGuard logon kuva\x02Sulje" +
- "\x02♥ &Lahjoita!\x02Tila:\x02MTU:\x02Osoitteet:\x02DNS palvelimet:\x02Ko" +
- "mentosarjat:\x02Jaettu avain:\x02Sallitut IP-osoitteet:\x02Päätepiste:" +
- "\x02Jatkuva keepalive:\x02Viimeisin kättely:\x02Siirrot:\x02Osapuoli\x02" +
- "Luo uusi tunneli\x02Muokkaa tunnelia\x02&Nimi:\x02&Julkinen avain:\x02(t" +
- "untematon)\x02&Estä tunneloimaton liikenne (pääkatkaisija)\x02&Tallenna" +
- "\x02&Konfiguraatio:\x02Virheellinen nimi\x02Nimi on pakollinen.\x02Tunne" +
- "li on jo olemassa\x02Loki\x02&Kopioi\x02Päivitys on saatavilla!\x02WireG" +
- "uard päivitys saatavilla\x02WireGuardin päivitys on nyt saatavilla. Sinu" +
- "a kehotetaan päivittämään mahdollisimman pian.\x02Tunneli\x02&Muokkaa" +
- "\x02Tuodut tunnelit\x14\x01\x81\x01\x00\x02\x14\x02Tuotu %[1]d tunneli" +
- "\x00\x15\x02Tuotu %[1]d tunnelia\x02Tunnelia ei voitu poistaa\x02Tuo tun" +
- "neli(t) tiedostosta\x02Tila: Odotetaan käyttäjää\x02Päivitä nyt\x02Tila:" +
- " Valmis!"
+const faData string = "" + // Size: 6331 bytes
+ "\x02خطا\x02(بدون ورودیی): سرویس مدیریت را ارتقا و نصب کنید\x02استفاده: %" +
+ "[1]s [\x0a%[2]s]\x02گزینه\u200cهای خط فرمان\x02ناتوان در ارزیابی اینکه ف" +
+ "رآیند تحت WOW64 کار می کند: %[1]v\x02شما باید از نگارش بومی وایرگارد بر" +
+ " روی این رایانه استفاده کنید.\x02رمز فرآیند فعلی باز نشد: %[1]v\x02وایرگ" +
+ "ارد فقط توسط کاربرانی که عضو گروه %[1]s هستند ممکن است استفاده شود.\x02" +
+ "وایرگارد در حال اجرا است، اما رابط کاربری فقط از دسکتاپ های گروه %[1]s " +
+ "قابل دسترسی است.\x02ایکون وایرگارد در سینی سیستم ،بعد از 30 ثانیه ظاهر " +
+ "نشد.\x02هم اکنون\x02زمان سیستم شما عقب است!\x14\x01\x81\x01\x00\x02\x0d" +
+ "\x02%[1]d سال\x00\x0d\x02%[1]d سال\x14\x01\x81\x01\x00\x02\x0d\x02%[1]d " +
+ "روز\x00\x0d\x02%[1]d روز\x14\x01\x81\x01\x00\x02\x0f\x02%[1]d ساعت\x00" +
+ "\x0f\x02%[1]d ساعت\x14\x01\x81\x01\x00\x02\x11\x02%[1]d دقیقه\x00\x11" +
+ "\x02%[1]d دقیقه\x14\x01\x81\x01\x00\x02\x11\x02%[1]d ثانیه\x00\x11\x02%[" +
+ "1]d ثانیه\x02%[1]s پیش\x02%[1]d\u00a0بایت\x02%.2[1]f\u00a0KiB\x02%.2[1]f" +
+ "\u00a0MiB\x02%.2[1]f\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02پور" +
+ "ت از نقطه پایانی وجود ندارد\x02میزبان نقطه پایانی نامعتبر است\x02براکت" +
+ "\u200cها باید حاوی آدرس IPv6 باشند\x02MTU نامعتبر است\x02پورت نامعتبر" +
+ "\x02مقدار کنترلر وصل بودن مجاز نیست\x02کلید نامعتبر: %[1]v\x02کلیدها بای" +
+ "د دقیقا به ۳۲ بایت رمزگشایی شوند\x02دو کاما پشت سر هم\x02نام تونل معتبر" +
+ " نیست\x02خط باید در یک بخش رخ دهد\x02کلید پیکربندی یک جداکننده برابر ندا" +
+ "رد\x02کلید باید یک مقدار داشته باشد\x02کلید برای رابط بخش [Interface] ن" +
+ "امعتبر است\x02کلید برای رابط بخش [Peer] نامعتبر است\x02یک رابط باید یک " +
+ "کلید خصوصی داشته باشد\x02[مشخص نشده]\x02همه همتاها باید کلید\u200cهای ع" +
+ "مومی داشته باشند\x02، \x02، \x02درباره WireGuard\x02تصویر لوگوی WireGua" +
+ "rd\x02بستن\x02♥&کمک\u200cمالی!\x02وضعیت:\x02&غیرفعال\u200cسازی\x02&فعال" +
+ "\u200cسازی\x02کلید عمومی:\x02پورت شنود:\x02MTU:\x02نشانی\u200cها:\x02سرو" +
+ "رهای DNS:\x02اسکریپت\u200cها:\x02کلید از پیش تقسیم شده:\x02IPهای مجاز:" +
+ "\x02نقطه پایان:\x02زنده نگه\u200cداشتن پیوسته:\x02آخرین دست دادن:\x02انت" +
+ "قال:\x02پیشنیاز\x02پس نیاز برقراری\x02پیشنیاز قطعی\x02پسنیاز قطعی\x02غی" +
+ "ر فعال، بر اساس خط مشی\x02فعال شده\x02%[1]s دریافت شد، %[2]s ارسال شد" +
+ "\x02وضعیت تونل تعیین نشده است\x02فعال سازی تونل ناموفق بود\x02غیرفعال سا" +
+ "زی تونل ناموفق بود\x02رابط: %[1]s\x02همتا\x02ایجاد تونل جدید\x02ویرایش " +
+ "تونل\x02&نام:\x02&کلید عمومی:\x02(ناشناخته)\x02&مسدود کردن ترافیک تونل " +
+ "نشده (سوئیچ مرگ)\x02&ذخیره\x02لغو\x02&پیکربندی:\x02نام نامعتبر\x02یک نا" +
+ "م الزامی است.\x02تونل با نام '%[1]s' نامعتبر است.\x02نمی\u200cتوان تونل" +
+ "\u200cهای موجود را فهرست کرد\x02تونل هم\u200cاکنون موجود است\x02تونل دیگ" +
+ "ری با نام '%[1]s' وجود دارد.\x02ناتوان در ایجاد پیکربندی جدید\x02نوشتن " +
+ "پرونده انجام نشد\x02پرونده «%[1]s» از قبل وجود دارد.\x0a\x0aآیا می" +
+ "\u200cخواهید آن را بازنویسی کنید؟\x02فعال\x02در حال فعال\u200cسازی\x02غی" +
+ "رفعال\x02در حال غیرفعال\u200cسازی\x02وضعیت ناشناخته\x02گزارش وقایع\x02&" +
+ "روگرفت\x02انتخاب همه\x02&ذخیره در پرونده…\x02زمان\x02پیام گزارش رویداد" +
+ "\x02پرونده\u200cهای متنی (*.txt)|*.txt|همه پرونده\u200cها (*.*)|*.*\x02ب" +
+ "رون\u200cبرد گزارش رویداد به پرونده\x02&درباره WireGuard…\x02خطالی تونل" +
+ "\x02%[1]s\x0a\x0aلطفا برای اطلاعات بیشتر به گزارش رویداد مراجعه کنید." +
+ "\x02%[1]s (قدیمی)\x02وقوع اشکال در وایرگارد\x02نمی\u200cتوان منتظر ماند " +
+ "تا پنجره WireGuard ظاهر شود: %[1]v\x02WireGuard: غیر فعال شده است\x02وض" +
+ "عیت: ناشناخته\x02نشانی\u200cها: هیچ\x02&مدیریت تونل\u200cها…\x02&وارد ک" +
+ "ردن تونل(ها) از پرونده…\x02خروج\x02&تونل\u200cها\x02WireGuard فعال" +
+ "\u200c شد\x02تونل %[1]s فعال\u200c شده است.\x02WireGuard غیرفعال شد\x02ت" +
+ "ونل %[1]s غیرفعال شده است.\x02خطای تونل WireGuard\x02WireGuard: %[1]s" +
+ "\x02وضعیت: %[1]s\x02نشانی\u200cها: %[1]s\x02یک به\u200cروزرسانی در دسترس" +
+ " است!\x02به\u200cروزرسانی WireGuard در دسترس است\x02به\u200cروزرسانی Wir" +
+ "eGuard اکنون در دسترس است. به شما توصیه می\u200cشود در اسرع وقت به\u200c" +
+ "روزرسانی کنید.\x02تونل\u200cها\x02&ویرایش\x02افزودن &خالی\u200cکردن تون" +
+ "ل…\x02افزودن تونل\x02حذف تونل(ها) انتخابی\x02برون\u200cبری همه تونل" +
+ "\u200cها به زیپ\x02تغییر وضعیت\x02برون\u200cبری همه تونل\u200cها به &زیپ" +
+ "…\x02ویرایش تونل انتخابی…\x02&حذف تونل(های) انتخاب شده\x02هیچ فایل پیک" +
+ "ربندی یافت نشد\x02تنظیمات انتخاب شده قابل واردکردن نیست: %[1]v\x02تونل" +
+ "\u200cهای وارد شده\x14\x01\x81\x01\x00\x02\x1d\x02%[1]d تونل وارد شد\x00" +
+ "\x1d\x02%[1]d تونل وارد شد\x14\x02\x80\x01\x02(\x02%[1]d از %[2]d تونل و" +
+ "ارد شد\x00(\x02%[1]d از %[2]d تونل وارد شد\x02نمی\u200cتوان تونل ایجاد " +
+ "کرد\x14\x01\x81\x01\x00\x02\x16\x02حذف %[1]d تونل\x00\x16\x02حذف %[1]d " +
+ "تونل\x02حذف تونل ‘%[1]s’\x02حذف تونل\u200c امکان\u200cپذیر نیست\x02نمی" +
+ "\u200cتوان تونل\u200cها را حذف کرد\x02وارد کردن تونل(ها) از پرونده\x02پر" +
+ "ونده\u200cهای پیکربندی زیپ (*.zip)|*.zip\x02برون\u200cبری تونل\u200cها " +
+ "به زیپ\x02خطا در هنگام خارج شدن از WireGuard\x02وضعیت: درانتظار برای کا" +
+ "ربر\x02اکنون به\u200cروز رسانی کن\x02وضعیت: درانتظار برای سرویس به" +
+ "\u200cروزرسان\x02خطا: %[1]v. لطفا دوباره تلاش کنید.\x02وضعیت: کامل شد!"
-var frIndex = []uint32{ // 181 elements
+var fiIndex = []uint32{ // 180 elements
+ // Entry 0 - 1F
+ 0x00000000, 0x00000006, 0x00000056, 0x0000006f,
+ 0x00000085, 0x000000ea, 0x00000133, 0x0000016b,
+ 0x000001bf, 0x0000022c, 0x00000272, 0x00000276,
+ 0x00000296, 0x000002b8, 0x000002df, 0x00000301,
+ 0x00000329, 0x0000034f, 0x0000035c, 0x00000364,
+ 0x00000371, 0x0000037e, 0x0000038b, 0x00000398,
+ 0x000003a5, 0x000003cc, 0x000003f7, 0x0000042b,
+ 0x0000043c, 0x00000450, 0x0000046f, 0x00000489,
+ // Entry 20 - 3F
+ 0x000004b4, 0x000004ce, 0x000004e6, 0x00000506,
+ 0x00000537, 0x00000553, 0x0000057b, 0x0000059e,
+ 0x000005cb, 0x000005e0, 0x00000611, 0x00000614,
+ 0x00000617, 0x0000062c, 0x00000641, 0x00000647,
+ 0x00000656, 0x0000065c, 0x00000667, 0x00000670,
+ 0x00000680, 0x00000692, 0x00000697, 0x000006a2,
+ 0x000006b2, 0x000006c1, 0x000006cf, 0x000006e6,
+ 0x000006f4, 0x00000707, 0x0000071b, 0x00000724,
+ // Entry 40 - 5F
+ 0x0000072b, 0x00000733, 0x0000073c, 0x00000746,
+ 0x00000771, 0x0000077d, 0x000007a3, 0x000007ca,
+ 0x000007eb, 0x0000080e, 0x00000820, 0x00000829,
+ 0x0000083a, 0x0000084b, 0x00000852, 0x00000863,
+ 0x00000870, 0x000008a0, 0x000008aa, 0x000008b2,
+ 0x000008c2, 0x000008d4, 0x000008e8, 0x00000913,
+ 0x0000093e, 0x00000955, 0x00000982, 0x000009a5,
+ 0x000009c6, 0x00000a02, 0x00000a0d, 0x00000a19,
+ // Entry 60 - 7F
+ 0x00000a28, 0x00000a36, 0x00000a46, 0x00000a4b,
+ 0x00000a53, 0x00000a63, 0x00000a7b, 0x00000a80,
+ 0x00000a8b, 0x00000ac4, 0x00000ad8, 0x00000af2,
+ 0x00000aff, 0x00000b33, 0x00000b4a, 0x00000b65,
+ 0x00000b9f, 0x00000bb6, 0x00000bc7, 0x00000bde,
+ 0x00000bf6, 0x00000c15, 0x00000c1d, 0x00000c27,
+ 0x00000c3b, 0x00000c57, 0x00000c6d, 0x00000c8b,
+ 0x00000ca2, 0x00000cb3, 0x00000cbf, 0x00000cd0,
+ // Entry 80 - 9F
+ 0x00000ce9, 0x00000d08, 0x00000d68, 0x00000d70,
+ 0x00000d79, 0x00000d94, 0x00000da4, 0x00000dbe,
+ 0x00000de1, 0x00000dee, 0x00000e15, 0x00000e33,
+ 0x00000e4c, 0x00000e6d, 0x00000ea0, 0x00000ed3,
+ 0x00000f04, 0x00000f2e, 0x00000f3e, 0x00000f70,
+ 0x00000fb6, 0x00000fce, 0x00001002, 0x0000106f,
+ 0x0000108a, 0x000010c2, 0x000010eb, 0x00001105,
+ 0x00001126, 0x00001140, 0x00001140, 0x00001140,
+ // Entry A0 - BF
+ 0x0000115b, 0x0000115b, 0x00001177, 0x00001177,
+ 0x00001199, 0x00001199, 0x00001199, 0x000011b7,
+ 0x000011c5, 0x000011c5, 0x000011c5, 0x000011d3,
+ 0x000011d3, 0x000011d3, 0x000011d3, 0x000011d3,
+ 0x000011d3, 0x000011d3, 0x000011d3, 0x000011d3,
+} // Size: 744 bytes
+
+const fiData string = "" + // Size: 4563 bytes
+ "\x02Virhe\x02(ei määrityksiä): suorita järjestelmäoikeuksilla ja asenna " +
+ "hallintapalvelu\x02Käyttö: %[1]s [\x0a%[2]s]\x02Komentorivin valinnat" +
+ "\x02Ei pystytä määrittämään mikäli prosessia suoritetaan WOW64-järjestel" +
+ "män alaisuudessa: %[1]v\x02Tällä tietokoneella voi käyttää vain WireGuar" +
+ "din natiivia versiota.\x02Ei voida avata tämänhetkisen prosessin tokenia" +
+ ": %[1]v\x02Ainoastaan sisäänrakennetun ryhmän %[1]s jäsenet voivat käytt" +
+ "ää WireGuardia.\x02WireGuard on käynnissä, mutta käyttöliittymä on vain" +
+ " sisäänrakennetun ryhmän %[1]s käytettävissä.\x02WireGuardin ilmoitusalu" +
+ "een kuvake ei ilmestynyt 30 sekunnin jälkeen.\x02Nyt\x02Järjestelmän kel" +
+ "lo jättää!\x14\x01\x81\x01\x00\x02\x0c\x02%[1]d vuosi\x00\x0d\x02%[1]d v" +
+ "uotta\x14\x01\x81\x01\x00\x02\x0e\x02%[1]d päivä\x00\x10\x02%[1]d päivää" +
+ "\x14\x01\x81\x01\x00\x02\x0c\x02%[1]d tunti\x00\x0d\x02%[1]d tuntia\x14" +
+ "\x01\x81\x01\x00\x02\x0f\x02%[1]d minuutti\x00\x10\x02%[1]d minuuttia" +
+ "\x14\x01\x81\x01\x00\x02\x0e\x02%[1]d sekunti\x00\x0f\x02%[1]d sekuntia" +
+ "\x02%[1]s sitten\x02%[1]d B\x02%.2[1]f\u00a0KiB\x02%.2[1]f\u00a0MiB\x02%" +
+ ".2[1]f\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02Päätepisteestä pu" +
+ "uttuu porttinumero\x02Virheellinen päätepisteen isäntäosoite\x02Sulkujen" +
+ " sisään pitää määritellä IPv6-osoite\x02Virheellinen MTU\x02Virheellinen" +
+ " portti\x02Virheellinen jatkuva keepalive\x02Virheellinen avain: %[1]v" +
+ "\x02Avainten tulee olla tasan 32 tavua pitkiä\x02Kaksi pilkkua peräkkäin" +
+ "\x02Tunnelin nimi ei kelpaa\x02Rivin pitää esiintyä osiossa\x02Määrittel" +
+ "yavaimesta puuttuu yhtäsuuruuserotin\x02Avaimella pitää olla arvo\x02Vir" +
+ "heellinen avain [Interface] -osiossa\x02Virheellinen avain [Peer] -osios" +
+ "sa\x02Liitännällä pitää olla yksityinen avain\x02[ei määriteltynä]\x02Ka" +
+ "ikilla osapuolilla pitää olla julkinen avain\x02, \x02, \x02Tietoa WireG" +
+ "uardista\x02WireGuard logon kuva\x02Sulje\x02♥ &Lahjoita!\x02Tila:\x02&D" +
+ "eaktivoi\x02&Aktivoi\x02Julkinen avain:\x02Kuuntele porttia:\x02MTU:\x02" +
+ "Osoitteet:\x02DNS palvelimet:\x02Komentosarjat:\x02Jaettu avain:\x02Sall" +
+ "itut IP-osoitteet:\x02Päätepiste:\x02Jatkuva keepalive:\x02Viimeisin kät" +
+ "tely:\x02Siirrot:\x02pre-up\x02post-up\x02pre-down\x02post-down\x02pois " +
+ "käytöstä, käytännön perusteella\x02käytössä\x02%[1]s vastaanotettu, %[2]" +
+ "s lähetetty\x02Tunnelin tilan määritys epäonnistui\x02Tunnelin aktivoint" +
+ "i epäonnistui\x02Tunnelin deaktivointi epäonnistui\x02Liitäntä: %[1]s" +
+ "\x02Osapuoli\x02Luo uusi tunneli\x02Muokkaa tunnelia\x02&Nimi:\x02&Julki" +
+ "nen avain:\x02(tuntematon)\x02&Estä tunneloimaton liikenne (pääkatkaisij" +
+ "a)\x02&Tallenna\x02Peruuta\x02&Konfiguraatio:\x02Virheellinen nimi\x02Ni" +
+ "mi on pakollinen.\x02Tunnelin nimi ‘%[1]s’ on virheellinen.\x02Olemassao" +
+ "levia tunneleita ei voitu listata\x02Tunneli on jo olemassa\x02Nimellä ‘" +
+ "%[1]s’ on jo olemassa tunneli.\x02Uutta määritystä ei voida luoda\x02Tie" +
+ "doston kirjoitus epäonnistui\x02Tiedosto ‘%[1]s’ on jo olemassa.\x0a\x0a" +
+ "Haluatko korvata sen?\x02Aktiivinen\x02Aktivoidaan\x02Epäaktiivinen\x02D" +
+ "eaktivoidaan\x02Tuntematon tila\x02Loki\x02&Kopioi\x02Valitse k&aikki" +
+ "\x02&Tallenna tiedostoon…\x02Aika\x02Lokiviesti\x02Tekstitiedostot (*.tx" +
+ "t)|*.txt|Kaikki tiedostot (*.*)|*.*\x02Vie loki tiedostoon\x02Tietoja Wi" +
+ "reGu&ardista…\x02Tunnelivirhe\x02%[1]s\x0a\x0aLue lisää lokista saadakse" +
+ "si lisätietoja.\x02%[1]s (ei ajantasalla)\x02WireGuardin tunnistusvirhe" +
+ "\x02Ei voida odottaa WireGuardin ikkunan ilmestymistä: %[1]v\x02WireGuar" +
+ "d: deaktivoitu\x02Tila: tuntematon\x02Osoitteet: ei mitään\x02&Hallitse " +
+ "tunneleita…\x02Tuo tunnele&ita tiedostosta…\x02Lo&peta\x02&Tunnelit\x02W" +
+ "ireGuard aktivoitu\x02Tunneli %[1]s on aktivoitu.\x02WireGuard deaktivoi" +
+ "tu\x02Tunneli %[1]s on deaktivoitu.\x02WireGuard tunnelivirhe\x02WireGua" +
+ "rd: %[1]s\x02Tila: %[1]s\x02Osoitteet: %[1]s\x02Päivitys on saatavilla!" +
+ "\x02WireGuard päivitys saatavilla\x02WireGuardin päivitys on nyt saatavi" +
+ "lla. Sinua kehotetaan päivittämään mahdollisimman pian.\x02Tunneli\x02&M" +
+ "uokkaa\x02Lisää tyhjä tunn&eli…\x02Lisää tunneli\x02Poista valitut tunne" +
+ "li(t)\x02Vie kaikki tunnelit zip-tiedostoon\x02Vaihda &tila\x02Vie kaikk" +
+ "i tunnelit &zip-tiedostoon…\x02Muokkaa &valittua tunnelia…\x02&Poista va" +
+ "litut tunnelit\x02määritystiedostoa ei löytynyt\x02Valittua määritystied" +
+ "ostoa ei voitu tuoda: %[1]v\x02Olemassaolevia tunneleita ei voitu luetel" +
+ "la: %[1]v\x02Nimellä ‘%[1]s’ on jo olemassaoleva tunneli\x02Ei voitu tuo" +
+ "da määritystiedostoa: %[1]v\x02Tuodut tunnelit\x14\x01\x81\x01\x00\x02" +
+ "\x14\x02Tuotu %[1]d tunneli\x00\x15\x02Tuotu %[1]d tunnelia\x14\x02\x80" +
+ "\x01\x02\x1f\x02Tuotiin %[1]d / %[2]d tunnelia\x00\x1f\x02Tuotiin %[1]d " +
+ "/ %[2]d tunnelia\x02Tunnelia ei voitu luoda\x14\x01\x81\x01\x00\x02\x15" +
+ "\x02Poista %[1]d tunneli\x00\x16\x02Poista %[1]d tunnelia\x14\x01\x81" +
+ "\x01\x00\x022\x02Oletko varma että haluat poistaa %[1]d tunnelin?\x002" +
+ "\x02Oletko varma että haluat poistaa %[1]d tunnelia?\x02Poista tunneli ‘" +
+ "%[1]s’\x02Oletko varma että haluat poistaa tunnelin ‘%[1]s’?\x02%[1]s Tä" +
+ "tä toimintoa ei voi peruuttaa.\x02Tunnelia ei voitu poistaa\x02Tunnelia " +
+ "ei voitu poistaa: %[1]s\x02Tunnelia ei voitu poistaa\x02Tuo tunneli(t) t" +
+ "iedostosta\x02Vie tunnelit zip-tiedostoon\x02Virhe WireGuardista poistut" +
+ "taessa\x02Tila: Odotetaan käyttäjää\x02Päivitä nyt\x02Tila: Valmis!"
+
+var frIndex = []uint32{ // 180 elements
// Entry 0 - 1F
0x00000000, 0x00000007, 0x00000046, 0x00000063,
0x00000083, 0x000000cb, 0x00000112, 0x0000014b,
@@ -765,54 +1346,53 @@ var frIndex = []uint32{ // 181 elements
0x000002b0, 0x000002cc, 0x000002ec, 0x0000030e,
0x00000332, 0x00000358, 0x00000365, 0x0000036e,
0x0000037b, 0x00000388, 0x00000395, 0x000003a2,
- 0x000003b0, 0x000003c6, 0x000003ee, 0x00000414,
- 0x0000043d, 0x00000475, 0x00000484, 0x00000494,
+ 0x000003b0, 0x000003d6, 0x000003ff, 0x00000437,
+ 0x00000446, 0x00000456, 0x0000046b, 0x00000483,
// Entry 20 - 3F
- 0x000004a9, 0x000004c1, 0x000004ee, 0x00000526,
- 0x00000542, 0x0000055b, 0x00000587, 0x000005c2,
- 0x000005dd, 0x00000609, 0x00000630, 0x00000658,
- 0x00000670, 0x000006a4, 0x000006cb, 0x000006f7,
- 0x00000719, 0x00000745, 0x00000748, 0x0000074a,
- 0x00000761, 0x0000077c, 0x00000806, 0x0000080d,
- 0x00000821, 0x00000829, 0x00000836, 0x0000083f,
- 0x0000084f, 0x00000860, 0x00000866, 0x00000871,
+ 0x000004b0, 0x000004cc, 0x000004e5, 0x00000511,
+ 0x0000054c, 0x00000567, 0x00000593, 0x000005ba,
+ 0x000005e2, 0x000005fa, 0x0000062e, 0x00000631,
+ 0x00000633, 0x0000064a, 0x00000665, 0x0000066c,
+ 0x00000680, 0x00000688, 0x00000695, 0x0000069e,
+ 0x000006ae, 0x000006bf, 0x000006c5, 0x000006d0,
+ 0x000006df, 0x000006e9, 0x000006ff, 0x00000719,
+ 0x00000730, 0x0000075e, 0x00000785, 0x00000791,
// Entry 40 - 5F
- 0x00000880, 0x0000088a, 0x000008a0, 0x000008ba,
- 0x000008d1, 0x000008ff, 0x00000926, 0x00000932,
- 0x00000950, 0x0000095b, 0x0000097c, 0x000009a8,
- 0x000009c7, 0x000009eb, 0x000009fd, 0x00000a07,
- 0x00000a20, 0x00000a33, 0x00000a3a, 0x00000a4b,
- 0x00000a58, 0x00000a8b, 0x00000c05, 0x00000c12,
- 0x00000c1a, 0x00000c2b, 0x00000c3a, 0x00000c52,
- 0x00000c7c, 0x00000cb1, 0x00000cc7, 0x00000cfb,
+ 0x000007a1, 0x000007b1, 0x000007c5, 0x000007d9,
+ 0x000007f7, 0x00000802, 0x00000823, 0x0000084f,
+ 0x0000086e, 0x00000892, 0x000008a4, 0x000008ae,
+ 0x000008c7, 0x000008da, 0x000008e1, 0x000008f2,
+ 0x000008ff, 0x00000932, 0x0000093f, 0x00000947,
+ 0x00000958, 0x00000967, 0x0000097f, 0x000009a9,
+ 0x000009de, 0x000009f4, 0x00000a28, 0x00000a58,
+ 0x00000a76, 0x00000ab5, 0x00000abe, 0x00000ad2,
// Entry 60 - 7F
- 0x00000d2b, 0x00000d49, 0x00000d88, 0x00000d91,
- 0x00000da5, 0x00000dae, 0x00000dc6, 0x00000dd4,
- 0x00000ddc, 0x00000de4, 0x00000df8, 0x00000e18,
- 0x00000e1e, 0x00000e31, 0x00000e6a, 0x00000e8e,
- 0x00000ea6, 0x00000eb7, 0x00000f01, 0x00000f13,
- 0x00000f35, 0x00000f77, 0x00000f8e, 0x00000f9e,
- 0x00000fb0, 0x00000fc8, 0x00000ffa, 0x00001003,
- 0x00001015, 0x00001033, 0x00001049, 0x0000106b,
+ 0x00000adb, 0x00000af3, 0x00000b01, 0x00000b09,
+ 0x00000b11, 0x00000b25, 0x00000b45, 0x00000b4b,
+ 0x00000b5e, 0x00000b97, 0x00000bbb, 0x00000bd3,
+ 0x00000be4, 0x00000c2e, 0x00000c40, 0x00000c62,
+ 0x00000ca4, 0x00000cbb, 0x00000ccb, 0x00000cdd,
+ 0x00000cf5, 0x00000d27, 0x00000d30, 0x00000d3a,
+ 0x00000d4c, 0x00000d6a, 0x00000d80, 0x00000da2,
+ 0x00000dbd, 0x00000dcf, 0x00000ddd, 0x00000dee,
// Entry 80 - 9F
- 0x00001086, 0x00001098, 0x000010a6, 0x000010b7,
- 0x000010d0, 0x000010f6, 0x0000116b, 0x00001173,
- 0x0000117d, 0x00001198, 0x000011aa, 0x000011d5,
- 0x000011f8, 0x00001202, 0x00001229, 0x0000124e,
- 0x0000127a, 0x000012a1, 0x000012df, 0x00001316,
- 0x00001342, 0x00001371, 0x00001383, 0x000013ba,
- 0x00001403, 0x00001422, 0x0000145a, 0x000014be,
- 0x000014de, 0x00001514, 0x00001543, 0x00001565,
+ 0x00000e07, 0x00000e2d, 0x00000ea2, 0x00000eaa,
+ 0x00000eb4, 0x00000ecf, 0x00000ee1, 0x00000f0c,
+ 0x00000f2f, 0x00000f39, 0x00000f60, 0x00000f85,
+ 0x00000fb1, 0x00000fd8, 0x00001016, 0x0000104d,
+ 0x00001079, 0x000010a8, 0x000010ba, 0x000010f1,
+ 0x0000113a, 0x00001159, 0x00001191, 0x000011f5,
+ 0x00001215, 0x0000124b, 0x0000127a, 0x0000129c,
+ 0x000012d1, 0x000012f5, 0x00001361, 0x000013b4,
// Entry A0 - BF
- 0x0000159a, 0x000015be, 0x0000162a, 0x0000167d,
- 0x000016ab, 0x000016d7, 0x000016f5, 0x00001726,
- 0x00001744, 0x000017bf, 0x00001838, 0x0000185d,
- 0x00001877, 0x000018a6, 0x000018cb, 0x000018dc,
- 0x000018ec, 0x000018fc, 0x00001910, 0x00001924,
- 0x0000192e,
-} // Size: 748 bytes
+ 0x000013e2, 0x0000140e, 0x0000142c, 0x0000145d,
+ 0x0000147b, 0x000014f6, 0x0000156f, 0x00001594,
+ 0x000015ae, 0x000015dd, 0x00001602, 0x00001613,
+ 0x00001613, 0x00001613, 0x00001613, 0x00001613,
+ 0x00001613, 0x00001613, 0x00001613, 0x00001613,
+} // Size: 744 bytes
-const frData string = "" + // Size: 6446 bytes
+const frData string = "" + // Size: 5651 bytes
"\x02Erreur\x02(sans argument) : élever et installer service du gestionna" +
"ire\x02Utilisation : %[1]s [\x0a%[2]s]\x02Options de la ligne de command" +
"e\x02Impossible de détecter si le processus s’exécute sous WOW64 : %[1]v" +
@@ -829,433 +1409,657 @@ const frData string = "" + // Size: 6446 bytes
"\x02%[1]d minute\x00\x0e\x02%[1]d minutes\x14\x01\x81\x01\x00\x02\x0e" +
"\x02%[1]d seconde\x00\x0f\x02%[1]d secondes\x02Il y a %[1]s\x02%[1]d" +
"\u00a0o\x02%.2[1]f\u00a0Kio\x02%.2[1]f\u00a0Mio\x02%.2[1]f\u00a0Gio\x02%" +
- ".2[1]f\u00a0Tio\x02%[1]s : %[2]q\x02Adresse IP non valide\x02Longueur du" +
- " préfixe réseau non valide\x02Port manquant au point de terminaison\x02H" +
- "ôte du point de terminaison non valide\x02L’adresse IPv6 doit être cont" +
- "enue entre des crochets\x02MTU non valide\x02Port non valide\x02Keepaliv" +
- "e non valide\x02Clé non valide : %[1]v\x02Clés doivent être décodées sur" +
- " 32 octets\x02Le numéro doit être compris entre 0 et 2^64-1 : %[1]v\x02D" +
- "eux virgules consécutives\x02Nom du tunnel non valide\x02Une ligne doit " +
- "apparaître dans une section\x02Il manque le séparateur égal à la clé de " +
- "configuration\x02Clé doit avoir une valeur\x02Clé non valide pour la sec" +
- "tion [Interface]\x02Clé non valide pour la section [Peer]\x02L'interface" +
- " doit avoir une clé privée\x02[aucune spécification]\x02Toutes les pairs" +
- " doivent contenir une clé publique\x02Erreur d'obtention de la configura" +
- "tion\x02Clé non valide pour la section d'interface\x02Version du protoco" +
- "le doit être 1\x02Clé non valide pour la section d'homologue\x02, \x02 " +
- "\x02À propos du WireGuard\x02Image du logo du WireGuard\x02Version de l'" +
- "application : %[1]s\x0aVersion backend Go : %[2]s\x0aVersion Go : %[3]s-" +
- "%[4]s\x0aSystème d'exploitation : %[5]s\x0aArchitecture : %[6]s\x02Ferme" +
- "r\x02♥ &Faites un don!\x02État :\x02&Désactiver\x02&Activer\x02Clé publi" +
- "que :\x02Port d'écoute :\x02MTU :\x02Adresses :\x02Serveurs DNS :\x02Scr" +
- "ipts :\x02Clé pré-partagée :\x02Adresses IP autorisées :\x02Point de ter" +
- "minaison :\x02Conservation de connexion active permanente :\x02Dernier é" +
- "tablissement d'une liaison :\x02Transfert :\x02désactivé, par préférence" +
- "\x02activé(e)\x02%[1]s reçu(e), %[2]s envoyé(e)\x02Impossible de détermi" +
- "ner l'état du tunnel\x02Impossible d'activer le tunnel\x02Impossible de " +
- "désactiver le tunnel\x02Interface : %[1]s\x02Homologue\x02Créer un nouve" +
- "au tunnel\x02Modifier le tunnel\x02&Nom :\x02&Clé publique :\x02(inconnu" +
- "(e))\x02&Bloquer tous le trafic hors tunnel (interrupteur)\x02Si la conf" +
- "iguration a exactement un homologue et si cet homologue a une adresse IP" +
- " autorisée contenant au moins un de 0.0.0.0/0\u00a0ou\u00a0::/0, le serv" +
- "ice de tunnel utilise un ensemble de règles du pare-feu afin de bloquer " +
- "tout le trafic qui n'est ni vers ni depuis l'interface de tunnel ou qui " +
- "est vers le mauvais serveur DNS, avec des exceptions spéciales pour les " +
- "DHCP et NDP.\x02&Enregistrer\x02Annuler\x02&Configuration :\x02Nom non v" +
- "alide\x02Le nom est obligatoire.\x02Nom de tunnel « %[1]s » est non vali" +
- "de.\x02Impossible de créer une liste des tunnels existants\x02Tunnel exi" +
- "ste déjà.\x02Nom « %[1]s » est déjà utilisé pour un tunnel.\x02Impossibl" +
- "e de créer une configuration nouvelle\x02Échec d'écriture du fichier\x02" +
- "Fichier « %[1]s » existe déjà.\x0a\x0aVoulez-vous le remplacer ?\x02Acti" +
- "vée\x02Activation en cours\x02Éteinte\x02Désactivation en cours\x02État " +
- "inconnu\x02Journal\x02&Copier\x02Sélectionner &tout\x02&Enregistrer dans" +
- " le fichier…\x02Temps\x02Message du journal\x02Fichiers texte (*.txt)|*." +
- "txt|Tous les fichiers (*.*)|*.*\x02Exporter le journal vers le fichier" +
- "\x02&À propos WireGuard…\x02Erreur du tunnel\x02%[1]s\x0a\x0aConsultez l" +
- "e journal pour plus d’informations, s'il vous plaît.\x02%[1]s (obsolète)" +
- "\x02Erreur de détection du WireGuard\x02Impossible d’attendre l'affichag" +
- "e du fenêtre WireGuard : %[1]v\x02WireGuard: Désactivé\x02État : Inconnu" +
- "\x02Adresses : Aucune\x02&Gestion des tunnels…\x02&Importer le(s) tunnel" +
- "(s) à partir du fichier…\x02Q&uitter\x02WireGuard activé\x02Tunnel %[1]s" +
- " a été activé.\x02WireGuard désactivé\x02Tunnel %[1]s a été désactivé." +
- "\x02Erreur du tunnel WireGuard\x02WireGuard : %[1]s\x02État : %[1]s\x02A" +
- "dresses : %[1]s\x02Mise à jour disponible!\x02WireGuard mise à jour est " +
- "disponible\x02Une mise à jour du WireGuard est disponible. Il est consei" +
- "llé de mettre votre WireGuard à jour dès que possible.\x02Tunnels\x02&Mo" +
- "difier\x02Ajouter un &tunnel vide…\x02Ajouter le tunnel\x02Supprimer le(" +
- "s) tunnel(s) sélectionné(s)\x02Exporter tous les tunnels vers zip\x02&Ba" +
- "sculer\x02Exporter tous les tunnels vers &zip…\x02Modifier &le tunnel sé" +
- "lectionné…\x02&Supprimer le(s) tunnel(s) sélectionné(s)\x02aucun fichier" +
- " de configuration trouvé\x02Impossible d'importer la configuration sélec" +
- "tionnée : %[1]v\x02Impossible d'énumérer les tunnels existantes : %[1]v" +
- "\x02Un tunnel nommé « %[1]s » existe déjà.\x02Impossible d'importer la c" +
- "onfiguration : %[1]v\x02Tunnels importés\x14\x01\x81\x01\x00\x02\x16\x02" +
- "%[1]d tunnel importé\x00\x18\x02%[1]d tunnels importés\x14\x02\x80\x01" +
- "\x02 \x02%[1]d de %[2]d tunnels importé\x00!\x02%[1]d de %[2]d tunnels i" +
- "mportés\x02Impossible de créer le tunnel\x14\x01\x81\x01\x00\x02\x17\x02" +
- "Supprimer %[1]d tunnel\x00\x18\x02Supprimer %[1]d tunnels\x14\x01\x81" +
- "\x01\x00\x02-\x02Voulez-vous vraiment supprimer %[1]d tunnel?\x00.\x02Vo" +
- "ulez-vous vraiment supprimer %[1]d tunnels?\x02Supprimer le tunnel ‘%[1]" +
- "s’\x02Voulez-vous vraiment supprimer le tunnel « %[1]s »?\x02%[1]s Vous " +
- "ne pouvez pas annuler cette action.\x02Impossible de supprimer le tunnel" +
- "\x02Il a été impossible de supprimer un tunnel : %[1]s\x02Impossible de " +
- "supprimer les tunnels\x14\x01\x81\x01\x00\x021\x02Il a été impossible de" +
- " supprimer %[1]d tunnel.\x002\x02Il a été impossible de supprimer %[1]d " +
- "tunnels.\x02Fichiers de configuration (*.zip, *.conf)|*.zip;*.conf|Tous " +
- "les fichiers (*.*)|*.*\x02Importer le(s) tunnel(s) à partir du fichier" +
- "\x02Fichiers de configuration ZIP (*.zip)|*.zip\x02Exporter les tunnels " +
- "vers zip\x02%[1]s (version non signée, aucune mise à jour)\x02Erreur de " +
- "sortie du WireGuard\x02Impossible de quitter le service en raison de : %" +
- "[1]v. Essayez d'arrêter WireGuard à partir du gestionnair des services." +
- "\x02Une mise à jour du WireGuard est disponible. Il est fortement consei" +
- "llé de metter votre WireGuard à jour sans délai.\x02État: En attente de " +
- "l’utilisateur\x02Mettre à jour maintenant\x02État: En attente du program" +
- "me de mise à jour\x02Erreur : %[1]v. Veuillez réessayer.\x02État: Termin" +
- "é!\x02pré-activation\x02post-activation\x02pré-désactivation\x02post-dé" +
- "sactivation\x02& Tunnels"
+ ".2[1]f\u00a0Tio\x02%[1]s : %[2]q\x02Port manquant au point de terminaiso" +
+ "n\x02Hôte du point de terminaison non valide\x02L’adresse IPv6 doit être" +
+ " contenue entre des crochets\x02MTU non valide\x02Port non valide\x02Kee" +
+ "palive non valide\x02Clé non valide : %[1]v\x02Clés doivent être décodée" +
+ "s sur 32 octets\x02Deux virgules consécutives\x02Nom du tunnel non valid" +
+ "e\x02Une ligne doit apparaître dans une section\x02Il manque le séparate" +
+ "ur égal à la clé de configuration\x02Clé doit avoir une valeur\x02Clé no" +
+ "n valide pour la section [Interface]\x02Clé non valide pour la section [" +
+ "Peer]\x02L'interface doit avoir une clé privée\x02[aucune spécification]" +
+ "\x02Toutes les pairs doivent contenir une clé publique\x02, \x02 \x02À p" +
+ "ropos du WireGuard\x02Image du logo du WireGuard\x02Fermer\x02♥ &Faites " +
+ "un don!\x02État :\x02&Désactiver\x02&Activer\x02Clé publique :\x02Port d" +
+ "'écoute :\x02MTU :\x02Adresses :\x02Serveurs DNS :\x02Scripts :\x02Clé p" +
+ "ré-partagée :\x02Adresses IP autorisées :\x02Point de terminaison :\x02C" +
+ "onservation de connexion active permanente :\x02Dernier établissement d'" +
+ "une liaison :\x02Transfert :\x02pré-activation\x02post-activation\x02pré" +
+ "-désactivation\x02post-désactivation\x02désactivé, par préférence\x02act" +
+ "ivé(e)\x02%[1]s reçu(e), %[2]s envoyé(e)\x02Impossible de déterminer l'é" +
+ "tat du tunnel\x02Impossible d'activer le tunnel\x02Impossible de désacti" +
+ "ver le tunnel\x02Interface : %[1]s\x02Homologue\x02Créer un nouveau tunn" +
+ "el\x02Modifier le tunnel\x02&Nom :\x02&Clé publique :\x02(inconnu(e))" +
+ "\x02&Bloquer tous le trafic hors tunnel (interrupteur)\x02&Enregistrer" +
+ "\x02Annuler\x02&Configuration :\x02Nom non valide\x02Le nom est obligato" +
+ "ire.\x02Nom de tunnel « %[1]s » est non valide.\x02Impossible de créer u" +
+ "ne liste des tunnels existants\x02Tunnel existe déjà.\x02Nom « %[1]s » e" +
+ "st déjà utilisé pour un tunnel.\x02Impossible de créer une configuration" +
+ " nouvelle\x02Échec d'écriture du fichier\x02Fichier « %[1]s » existe déj" +
+ "à.\x0a\x0aVoulez-vous le remplacer ?\x02Activée\x02Activation en cours" +
+ "\x02Éteinte\x02Désactivation en cours\x02État inconnu\x02Journal\x02&Cop" +
+ "ier\x02Sélectionner &tout\x02&Enregistrer dans le fichier…\x02Temps\x02M" +
+ "essage du journal\x02Fichiers texte (*.txt)|*.txt|Tous les fichiers (*.*" +
+ ")|*.*\x02Exporter le journal vers le fichier\x02&À propos WireGuard…\x02" +
+ "Erreur du tunnel\x02%[1]s\x0a\x0aConsultez le journal pour plus d’inform" +
+ "ations, s'il vous plaît.\x02%[1]s (obsolète)\x02Erreur de détection du W" +
+ "ireGuard\x02Impossible d’attendre l'affichage du fenêtre WireGuard : %[1" +
+ "]v\x02WireGuard: Désactivé\x02État : Inconnu\x02Adresses : Aucune\x02&Ge" +
+ "stion des tunnels…\x02&Importer le(s) tunnel(s) à partir du fichier…\x02" +
+ "Q&uitter\x02& Tunnels\x02WireGuard activé\x02Tunnel %[1]s a été activé." +
+ "\x02WireGuard désactivé\x02Tunnel %[1]s a été désactivé.\x02Erreur du tu" +
+ "nnel WireGuard\x02WireGuard : %[1]s\x02État : %[1]s\x02Adresses : %[1]s" +
+ "\x02Mise à jour disponible!\x02WireGuard mise à jour est disponible\x02U" +
+ "ne mise à jour du WireGuard est disponible. Il est conseillé de mettre v" +
+ "otre WireGuard à jour dès que possible.\x02Tunnels\x02&Modifier\x02Ajout" +
+ "er un &tunnel vide…\x02Ajouter le tunnel\x02Supprimer le(s) tunnel(s) sé" +
+ "lectionné(s)\x02Exporter tous les tunnels vers zip\x02&Basculer\x02Expor" +
+ "ter tous les tunnels vers &zip…\x02Modifier &le tunnel sélectionné…\x02&" +
+ "Supprimer le(s) tunnel(s) sélectionné(s)\x02aucun fichier de configurati" +
+ "on trouvé\x02Impossible d'importer la configuration sélectionnée : %[1]v" +
+ "\x02Impossible d'énumérer les tunnels existantes : %[1]v\x02Un tunnel no" +
+ "mmé « %[1]s » existe déjà.\x02Impossible d'importer la configuration : %" +
+ "[1]v\x02Tunnels importés\x14\x01\x81\x01\x00\x02\x16\x02%[1]d tunnel imp" +
+ "orté\x00\x18\x02%[1]d tunnels importés\x14\x02\x80\x01\x02 \x02%[1]d de " +
+ "%[2]d tunnels importé\x00!\x02%[1]d de %[2]d tunnels importés\x02Impossi" +
+ "ble de créer le tunnel\x14\x01\x81\x01\x00\x02\x17\x02Supprimer %[1]d tu" +
+ "nnel\x00\x18\x02Supprimer %[1]d tunnels\x14\x01\x81\x01\x00\x02-\x02Voul" +
+ "ez-vous vraiment supprimer %[1]d tunnel?\x00.\x02Voulez-vous vraiment su" +
+ "pprimer %[1]d tunnels?\x02Supprimer le tunnel ‘%[1]s’\x02Voulez-vous vra" +
+ "iment supprimer le tunnel « %[1]s »?\x02%[1]s Vous ne pouvez pas annuler" +
+ " cette action.\x02Impossible de supprimer le tunnel\x02Il a été impossib" +
+ "le de supprimer un tunnel : %[1]s\x02Impossible de supprimer les tunnels" +
+ "\x14\x01\x81\x01\x00\x021\x02Il a été impossible de supprimer %[1]d tunn" +
+ "el.\x002\x02Il a été impossible de supprimer %[1]d tunnels.\x02Fichiers " +
+ "de configuration (*.zip, *.conf)|*.zip;*.conf|Tous les fichiers (*.*)|*." +
+ "*\x02Importer le(s) tunnel(s) à partir du fichier\x02Fichiers de configu" +
+ "ration ZIP (*.zip)|*.zip\x02Exporter les tunnels vers zip\x02%[1]s (vers" +
+ "ion non signée, aucune mise à jour)\x02Erreur de sortie du WireGuard\x02" +
+ "Impossible de quitter le service en raison de : %[1]v. Essayez d'arrêter" +
+ " WireGuard à partir du gestionnair des services.\x02Une mise à jour du W" +
+ "ireGuard est disponible. Il est fortement conseillé de metter votre Wire" +
+ "Guard à jour sans délai.\x02État: En attente de l’utilisateur\x02Mettre " +
+ "à jour maintenant\x02État: En attente du programme de mise à jour\x02Er" +
+ "reur : %[1]v. Veuillez réessayer.\x02État: Terminé!"
-var idIndex = []uint32{ // 181 elements
+var idIndex = []uint32{ // 180 elements
// Entry 0 - 1F
0x00000000, 0x0000000a, 0x00000047, 0x00000062,
- 0x00000074, 0x000000bf, 0x000000bf, 0x000000f0,
- 0x00000148, 0x000001a1, 0x000001d6, 0x000001df,
- 0x000001f2, 0x00000211, 0x00000223, 0x00000234,
- 0x00000247, 0x0000025a, 0x0000026a, 0x00000272,
- 0x0000027e, 0x0000028a, 0x00000296, 0x000002a2,
- 0x000002af, 0x000002c5, 0x000002e0, 0x00000300,
- 0x0000031a, 0x00000340, 0x00000350, 0x00000361,
+ 0x00000074, 0x000000bf, 0x000000fe, 0x0000012f,
+ 0x00000187, 0x000001e0, 0x00000215, 0x0000021e,
+ 0x00000231, 0x00000250, 0x00000262, 0x00000273,
+ 0x00000286, 0x00000299, 0x000002a9, 0x000002b1,
+ 0x000002bd, 0x000002c9, 0x000002d5, 0x000002e1,
+ 0x000002ee, 0x0000030e, 0x00000328, 0x0000034e,
+ 0x0000035e, 0x0000036f, 0x00000390, 0x000003a6,
// Entry 20 - 3F
- 0x00000382, 0x00000398, 0x000003c0, 0x000003f2,
- 0x0000040c, 0x00000424, 0x00000441, 0x00000441,
- 0x0000045c, 0x00000486, 0x000004ab, 0x000004d0,
- 0x000004e1, 0x00000509, 0x0000052d, 0x00000557,
- 0x0000056e, 0x00000593, 0x00000596, 0x00000596,
- 0x000005a8, 0x000005a8, 0x000005a8, 0x000005ae,
- 0x000005bb, 0x000005c3, 0x000005c3, 0x000005c3,
- 0x000005c3, 0x000005c3, 0x000005c3, 0x000005c3,
+ 0x000003ce, 0x000003e8, 0x00000400, 0x0000041d,
+ 0x00000463, 0x0000047e, 0x000004a8, 0x000004cd,
+ 0x000004f2, 0x00000503, 0x0000052b, 0x0000052e,
+ 0x00000531, 0x00000543, 0x00000559, 0x0000055f,
+ 0x0000056c, 0x00000574, 0x00000581, 0x0000058b,
+ 0x00000599, 0x000005a9, 0x000005ae, 0x000005b6,
+ 0x000005c2, 0x000005c9, 0x000005d8, 0x000005ef,
+ 0x000005f9, 0x000005f9, 0x000005f9, 0x000005f9,
// Entry 40 - 5F
- 0x000005c3, 0x000005c3, 0x000005c3, 0x000005c3,
- 0x000005c3, 0x000005c3, 0x000005c3, 0x000005c3,
- 0x000005c3, 0x000005c3, 0x000005c3, 0x000005c3,
- 0x000005c3, 0x000005c3, 0x000005c3, 0x000005c3,
- 0x000005c3, 0x000005c3, 0x000005c3, 0x000005c3,
- 0x000005c3, 0x000005c3, 0x000005c3, 0x000005c3,
- 0x000005c3, 0x000005c3, 0x000005c3, 0x000005c3,
- 0x000005c3, 0x000005c3, 0x000005c3, 0x000005c3,
+ 0x000005f9, 0x000005f9, 0x000005f9, 0x000005f9,
+ 0x000005f9, 0x000005f9, 0x000005f9, 0x000005f9,
+ 0x000005f9, 0x000005f9, 0x000005f9, 0x000005f9,
+ 0x000005f9, 0x000005f9, 0x000005f9, 0x000005f9,
+ 0x000005f9, 0x000005f9, 0x000005f9, 0x000005f9,
+ 0x000005f9, 0x000005f9, 0x000005f9, 0x000005f9,
+ 0x000005f9, 0x000005f9, 0x000005f9, 0x000005f9,
+ 0x000005f9, 0x000005f9, 0x000005ff, 0x0000060c,
// Entry 60 - 7F
- 0x000005c3, 0x000005c3, 0x000005c3, 0x000005c9,
- 0x000005d6, 0x000005df, 0x000005ed, 0x00000604,
- 0x0000060c, 0x00000612, 0x0000061e, 0x0000063b,
- 0x00000641, 0x0000064b, 0x0000067b, 0x00000693,
- 0x000006a9, 0x000006b5, 0x000006eb, 0x000006fe,
- 0x00000715, 0x0000074a, 0x00000763, 0x0000077b,
- 0x0000078a, 0x0000079d, 0x000007b8, 0x000007c0,
- 0x000007c0, 0x000007c0, 0x000007c0, 0x000007c0,
+ 0x00000615, 0x00000623, 0x0000063a, 0x00000642,
+ 0x00000648, 0x00000654, 0x00000671, 0x00000677,
+ 0x00000681, 0x000006b1, 0x000006c9, 0x000006df,
+ 0x000006eb, 0x00000721, 0x00000734, 0x0000074b,
+ 0x00000780, 0x00000799, 0x000007b1, 0x000007c0,
+ 0x000007d3, 0x000007ee, 0x000007f6, 0x000007f6,
+ 0x000007f6, 0x000007f6, 0x000007f6, 0x000007f6,
+ 0x0000080c, 0x0000081d, 0x0000082b, 0x0000082b,
// Entry 80 - 9F
- 0x000007d6, 0x000007e7, 0x000007f5, 0x000007f5,
- 0x000007f5, 0x000007f5, 0x000007f5, 0x000007f5,
- 0x000007f5, 0x000007f5, 0x000007f5, 0x000007f5,
- 0x000007f5, 0x000007f5, 0x00000814, 0x0000082d,
- 0x00000844, 0x00000844, 0x0000087a, 0x0000087a,
- 0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
- 0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
- 0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
+ 0x0000082b, 0x0000082b, 0x0000082b, 0x0000082b,
+ 0x0000082b, 0x0000082b, 0x0000082b, 0x0000082b,
+ 0x0000082b, 0x0000082b, 0x0000084a, 0x00000863,
+ 0x0000087a, 0x0000087a, 0x000008b0, 0x000008b0,
+ 0x000008b0, 0x000008b0, 0x000008b0, 0x000008b0,
+ 0x000008b0, 0x000008b0, 0x000008b0, 0x000008b0,
+ 0x000008b0, 0x000008b0, 0x000008b0, 0x000008b0,
+ 0x000008b0, 0x000008b0, 0x000008b0, 0x000008b0,
// Entry A0 - BF
- 0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
- 0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
- 0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
- 0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
- 0x0000087a, 0x0000087a, 0x0000087a, 0x0000087a,
- 0x0000087a,
-} // Size: 748 bytes
+ 0x000008b0, 0x000008b0, 0x000008b0, 0x000008b0,
+ 0x000008b0, 0x000008b0, 0x000008b0, 0x000008b0,
+ 0x000008b0, 0x000008b0, 0x000008b0, 0x000008b0,
+ 0x000008b0, 0x000008b0, 0x000008b0, 0x000008b0,
+ 0x000008b0, 0x000008b0, 0x000008b0, 0x000008b0,
+} // Size: 744 bytes
-const idData string = "" + // Size: 2170 bytes
+const idData string = "" + // Size: 2224 bytes
"\x02Kesalahan\x02(tidak ada argumen): naikkan akses dan instal servis ma" +
"najer\x02Penggunaan: %[1]s [\x0a%[2]s]\x02Opsi Command Line\x02Tidak dap" +
- "at menentukan apakah proses sedang berjalan di bawah WOW64: %[1]v\x02Tid" +
- "ak dapat membuka token proses saat ini: %[1]v\x02WireGuard hanya dapat d" +
- "igunakan oleh pengguna yang merupakan anggota grup Bawaan %[1]s.\x02Wire" +
- "Guard sedang berjalan, tetapi UI hanya dapat diakses dari desktop grup B" +
- "awaan %[1]s.\x02Ikon sistem WireGuard tidak muncul setelah 30 detik.\x02" +
- "Sekarang\x02Jam sistem mundur!\x14\x01\x81\x01\x00\x00\x18\x02%[1]d tahu" +
- "n\x0a%[1]d tahun\x14\x01\x81\x01\x00\x00\x0b\x02%[1]d Hari\x14\x01\x81" +
- "\x01\x00\x00\x0a\x02%[1]d jam\x14\x01\x81\x01\x00\x00\x0c\x02%[1]d menit" +
- "\x14\x01\x81\x01\x00\x00\x0c\x02%[1]d detik\x02%[1]s yang lalu\x02%[1]d " +
- "B\x02%.2[1]f KiB\x02%.2[1]f MiB\x02%.2[1]f GiB\x02%.2[1]f TiB\x02%[1]s: " +
- "%[2]q\x02Alamat IP tidak valid\x02Network prefix tidak valid\x02Port bel" +
- "um terisi dari endpoint\x02Host endpoint tidak valid\x02Dalam Kurung har" +
- "us berisi alamat IPv6\x02MTU tidak valid\x02Port tidak valid\x02Persiste" +
- "nt keepalive tidak valid\x02Kunci tidak sah:%[1]v\x02Kunci harus diterje" +
- "mahkan tepat 32 byte\x02Nomor harus diantara 0 sampai dengan 2^64-1:%[1]" +
- "v\x02Dua koma dalam satu baris\x02Nama Tunnel tidak valid\x02Garis harus" +
- " muncul perbagian\x02Kunci harus memiliki value\x02Kunci tidak valid pad" +
- "a bagian [Interface]\x02Kunci tidak valid pada bagian [Peer]\x02Interfac" +
- "e harus memiliki Private Key\x02Tidak Ditetapkan\x02Semua peers harus me" +
- "miliki kunci publik\x02Eror ketika mendapatkan konfigurasi\x02Kunci tida" +
- "k valid pada bagian [Interface]\x02Versi protokol harus 1\x02Kunci tidak" +
- " valid pada bagian [Peer]\x02, \x02Tentang WireGuard\x02Tutup\x02♥ &Dona" +
- "si!\x02Status:\x02Aktif\x02Mengaktifkan\x02Nonaktif\x02Menonaktifkan\x02" +
- "Status tidak diketahui\x02Catatan\x02Salin\x02Pilih semua\x02Menyimpan k" +
- "e dalam berkas…\x02Waktu\x02Pesan log\x02Berkas Txt (*.Txt)|*.Txt|Semua " +
- "berkas (*.*)|*.*\x02Ekspor log kedalam file\x02&Tentang WireGuard…\x02Tu" +
- "nnel eror\x02%[1]s\x0a\x0aSilakan baca log untuk informasi lebih lanjut." +
- "\x02%[1]s (kadaluarsa)\x02Deteksi eror WireGuard\x02Tidak dapat menunggu" +
- " jendela WireGuard muncul: %[1]v\x02WireGuard: Dinonaktifkan\x02Status: " +
- "Tidak diketahui\x02Alamat: Kosong\x02&Manajer Tunnel…\x02&Impor tunnel d" +
- "ari file…\x02&Keluar\x02Wireguard Tunnel Eror\x02WireGuard: %[1]s\x02Sta" +
- "tus: %[1]s\x02Ekspor semua tunnel ke &zip…\x02Ubah tunnel &terpilih…\x02" +
- "&Hapus tunnel terpilih\x02Tidak dapat mengimpor konfigurasi yang dipilih" +
- ": %[1]v"
+ "at menentukan apakah proses sedang berjalan di bawah WOW64: %[1]v\x02And" +
+ "a harus menggunakan WireGuard versi asli pada komputer ini.\x02Tidak dap" +
+ "at membuka token proses saat ini: %[1]v\x02WireGuard hanya dapat digunak" +
+ "an oleh pengguna yang merupakan anggota grup Bawaan %[1]s.\x02WireGuard " +
+ "sedang berjalan, tetapi UI hanya dapat diakses dari desktop grup Bawaan " +
+ "%[1]s.\x02Ikon sistem WireGuard tidak muncul setelah 30 detik.\x02Sekara" +
+ "ng\x02Jam sistem mundur!\x14\x01\x81\x01\x00\x00\x18\x02%[1]d tahun\x0a%" +
+ "[1]d tahun\x14\x01\x81\x01\x00\x00\x0b\x02%[1]d Hari\x14\x01\x81\x01\x00" +
+ "\x00\x0a\x02%[1]d jam\x14\x01\x81\x01\x00\x00\x0c\x02%[1]d menit\x14\x01" +
+ "\x81\x01\x00\x00\x0c\x02%[1]d detik\x02%[1]s yang lalu\x02%[1]d B\x02%.2" +
+ "[1]f KiB\x02%.2[1]f MiB\x02%.2[1]f GiB\x02%.2[1]f TiB\x02%[1]s: %[2]q" +
+ "\x02Port belum terisi dari endpoint\x02Host endpoint tidak valid\x02Dala" +
+ "m Kurung harus berisi alamat IPv6\x02MTU tidak valid\x02Port tidak valid" +
+ "\x02Persistent keepalive tidak valid\x02Kunci tidak sah:%[1]v\x02Kunci h" +
+ "arus diterjemahkan tepat 32 byte\x02Dua koma dalam satu baris\x02Nama Tu" +
+ "nnel tidak valid\x02Garis harus muncul perbagian\x02Kunci konfigurasi ti" +
+ "dak valid, tidak memiliki pemisah dan sama dengan\x02Kunci harus memilik" +
+ "i value\x02Kunci tidak valid pada bagian [Interface]\x02Kunci tidak vali" +
+ "d pada bagian [Peer]\x02Interface harus memiliki Private Key\x02Tidak Di" +
+ "tetapkan\x02Semua peers harus memiliki kunci publik\x02, \x02, \x02Tenta" +
+ "ng WireGuard\x02Gambar logo WireGuard\x02Tutup\x02♥ &Donasi!\x02Status:" +
+ "\x02&Nonaktifkan\x02&Aktifkan\x02Kunci publik:\x02Port Pendengar:\x02MTU" +
+ ":\x02Alamat:\x02Server DNS:\x02Skrip:\x02Preshared key:\x02IP yang diper" +
+ "bolehkan:\x02Endpoint:\x02Aktif\x02Mengaktifkan\x02Nonaktif\x02Menonakti" +
+ "fkan\x02Status tidak diketahui\x02Catatan\x02Salin\x02Pilih semua\x02Men" +
+ "yimpan ke dalam berkas…\x02Waktu\x02Pesan log\x02Berkas Txt (*.Txt)|*.Tx" +
+ "t|Semua berkas (*.*)|*.*\x02Ekspor log kedalam file\x02&Tentang WireGuar" +
+ "d…\x02Tunnel eror\x02%[1]s\x0a\x0aSilakan baca log untuk informasi lebih" +
+ " lanjut.\x02%[1]s (kadaluarsa)\x02Deteksi eror WireGuard\x02Tidak dapat " +
+ "menunggu jendela WireGuard muncul: %[1]v\x02WireGuard: Dinonaktifkan\x02" +
+ "Status: Tidak diketahui\x02Alamat: Kosong\x02&Manajer Tunnel…\x02&Impor " +
+ "tunnel dari file…\x02&Keluar\x02Wireguard Tunnel Eror\x02WireGuard: %[1]" +
+ "s\x02Status: %[1]s\x02Ekspor semua tunnel ke &zip…\x02Ubah tunnel &terpi" +
+ "lih…\x02&Hapus tunnel terpilih\x02Tidak dapat mengimpor konfigurasi yang" +
+ " dipilih: %[1]v"
-var itIndex = []uint32{ // 181 elements
+var itIndex = []uint32{ // 180 elements
// Entry 0 - 1F
0x00000000, 0x00000007, 0x00000044, 0x0000005d,
- 0x00000075, 0x000000bd, 0x000000bd, 0x000000f6,
- 0x0000014d, 0x000001be, 0x00000212, 0x00000216,
- 0x0000023d, 0x0000025c, 0x0000027f, 0x0000029c,
- 0x000002bf, 0x000002e4, 0x000002ed, 0x000002f6,
- 0x00000303, 0x00000310, 0x0000031d, 0x0000032a,
- 0x00000337, 0x0000034f, 0x00000379, 0x00000396,
- 0x000003b4, 0x000003e4, 0x000003f3, 0x00000404,
+ 0x00000075, 0x000000bd, 0x00000101, 0x0000013a,
+ 0x00000191, 0x00000202, 0x00000256, 0x0000025a,
+ 0x00000281, 0x000002a0, 0x000002c3, 0x000002e0,
+ 0x00000303, 0x00000328, 0x00000331, 0x0000033a,
+ 0x00000347, 0x00000354, 0x00000361, 0x0000036e,
+ 0x0000037b, 0x00000398, 0x000003b6, 0x000003e6,
+ 0x000003f5, 0x00000406, 0x00000426, 0x0000043f,
// Entry 20 - 3F
- 0x00000424, 0x0000043d, 0x0000046f, 0x000004ae,
- 0x000004c6, 0x000004e7, 0x00000514, 0x00000514,
- 0x00000533, 0x00000560, 0x00000588, 0x000005b5,
- 0x000005c7, 0x000005f5, 0x00000625, 0x00000657,
- 0x00000680, 0x000006a6, 0x000006a9, 0x000006ab,
- 0x000006c5, 0x000006e4, 0x000006e4, 0x000006eb,
- 0x00000703, 0x0000070a, 0x00000715, 0x0000071d,
- 0x0000072e, 0x00000740, 0x00000745, 0x00000750,
+ 0x00000471, 0x00000489, 0x000004aa, 0x000004d7,
+ 0x0000051a, 0x00000539, 0x00000566, 0x0000058e,
+ 0x000005bb, 0x000005cd, 0x000005fb, 0x000005fe,
+ 0x00000600, 0x0000061a, 0x00000639, 0x00000640,
+ 0x00000658, 0x0000065f, 0x0000066a, 0x00000672,
+ 0x00000683, 0x00000695, 0x0000069a, 0x000006a5,
+ 0x000006b1, 0x000006b9, 0x000006cf, 0x000006de,
+ 0x000006e8, 0x000006fe, 0x00000713, 0x00000722,
// Entry 40 - 5F
- 0x0000075c, 0x0000075c, 0x00000772, 0x00000781,
- 0x0000078b, 0x000007a1, 0x000007b6, 0x000007c5,
- 0x000007c5, 0x000007cf, 0x000007ed, 0x00000820,
- 0x00000844, 0x0000086b, 0x0000087e, 0x00000883,
- 0x0000088f, 0x0000089f, 0x000008a6, 0x000008b8,
- 0x000008c6, 0x000008f6, 0x000008f6, 0x000008fd,
- 0x00000905, 0x00000916, 0x00000926, 0x0000093c,
- 0x0000096a, 0x00000992, 0x000009a8, 0x000009dd,
+ 0x00000729, 0x00000731, 0x0000073a, 0x00000744,
+ 0x0000075e, 0x00000768, 0x00000786, 0x000007b9,
+ 0x000007dd, 0x00000804, 0x00000817, 0x0000081c,
+ 0x00000828, 0x00000838, 0x0000083f, 0x00000851,
+ 0x0000085f, 0x0000088f, 0x00000896, 0x0000089e,
+ 0x000008af, 0x000008bf, 0x000008d5, 0x00000903,
+ 0x0000092b, 0x00000941, 0x00000976, 0x000009a1,
+ 0x000009c1, 0x000009f8, 0x000009ff, 0x00000a0b,
// Entry 60 - 7F
- 0x00000a08, 0x00000a28, 0x00000a5f, 0x00000a66,
- 0x00000a72, 0x00000a7b, 0x00000a8a, 0x00000a9c,
- 0x00000aa0, 0x00000aa7, 0x00000ab8, 0x00000aca,
- 0x00000ad0, 0x00000ae1, 0x00000b14, 0x00000b28,
- 0x00000b46, 0x00000b58, 0x00000b8b, 0x00000b9c,
- 0x00000bbf, 0x00000c04, 0x00000c1b, 0x00000c2e,
- 0x00000c41, 0x00000c57, 0x00000c72, 0x00000c78,
- 0x00000c8b, 0x00000cae, 0x00000cc4, 0x00000cea,
+ 0x00000a14, 0x00000a23, 0x00000a35, 0x00000a39,
+ 0x00000a40, 0x00000a51, 0x00000a63, 0x00000a69,
+ 0x00000a7a, 0x00000aad, 0x00000ac1, 0x00000adf,
+ 0x00000af1, 0x00000b24, 0x00000b35, 0x00000b58,
+ 0x00000b9d, 0x00000bb4, 0x00000bc7, 0x00000bda,
+ 0x00000bf0, 0x00000c0b, 0x00000c11, 0x00000c19,
+ 0x00000c2c, 0x00000c4f, 0x00000c65, 0x00000c8b,
+ 0x00000ca6, 0x00000cb7, 0x00000cc4, 0x00000cd5,
// Entry 80 - 9F
- 0x00000d05, 0x00000d16, 0x00000d23, 0x00000d23,
- 0x00000d44, 0x00000d6b, 0x00000dca, 0x00000dd1,
- 0x00000ddb, 0x00000df2, 0x00000e02, 0x00000e1d,
- 0x00000e3b, 0x00000e44, 0x00000e63, 0x00000e86,
- 0x00000ea4, 0x00000ea4, 0x00000edf, 0x00000f0f,
- 0x00000f43, 0x00000f72, 0x00000f83, 0x00000fba,
- 0x00001002, 0x0000101f, 0x00001052, 0x000010b3,
- 0x000010ce, 0x00001103, 0x00001133, 0x00001153,
+ 0x00000cf6, 0x00000d1d, 0x00000d7c, 0x00000d83,
+ 0x00000d8d, 0x00000da7, 0x00000db7, 0x00000dd2,
+ 0x00000df0, 0x00000df9, 0x00000e1b, 0x00000e3e,
+ 0x00000e5c, 0x00000e82, 0x00000ebd, 0x00000eed,
+ 0x00000f21, 0x00000f50, 0x00000f61, 0x00000f98,
+ 0x00000fe0, 0x00000ffd, 0x00001030, 0x00001091,
+ 0x000010ac, 0x000010e1, 0x00001111, 0x00001131,
+ 0x00001163, 0x00001182, 0x000011e9, 0x00001234,
// Entry A0 - BF
- 0x00001185, 0x000011a4, 0x0000120b, 0x00001256,
- 0x0000126d, 0x00001296, 0x000012ac, 0x000012df,
- 0x00001307, 0x00001379, 0x000013de, 0x000013fb,
- 0x00001408, 0x00001437, 0x00001454, 0x00001465,
- 0x00001465, 0x00001465, 0x00001465, 0x00001465,
- 0x00001465,
-} // Size: 748 bytes
+ 0x0000124b, 0x00001274, 0x0000128a, 0x000012bd,
+ 0x000012e5, 0x00001357, 0x000013bc, 0x000013d9,
+ 0x000013e6, 0x00001415, 0x00001432, 0x00001443,
+ 0x00001443, 0x00001443, 0x00001443, 0x00001443,
+ 0x00001443, 0x00001443, 0x00001443, 0x00001443,
+} // Size: 744 bytes
-const itData string = "" + // Size: 5221 bytes
+const itData string = "" + // Size: 5187 bytes
"\x02Errore\x02(nessun argomento): eleva e installa il servizio di gestio" +
"ne\x02Utilizzo: %[1]s [\x0a%[2]s]\x02Opzioni riga di comando\x02Impossib" +
- "ile determinare se il processo è in esecuzione in WOW64: %[1]v\x02Imposs" +
- "ibile aprire il token del processo corrente: %[1]v\x02WireGuard può esse" +
- "re utilizzato solo dagli utenti membri del gruppo %[1]s di sistema.\x02W" +
- "ireGuard è in esecuzione, ma l'interfaccia utente è accessibile solo dai" +
- " desktop del gruppo %[1]s di sistema.\x02L'icona della barra delle appli" +
- "cazioni di WireGuard non è apparsa dopo 30 secondi.\x02Ora\x02L'orologio" +
- " di sistema va all'indietro!\x14\x01\x81\x01\x00\x02\x0b\x02%[1]d anno" +
+ "ile determinare se il processo è in esecuzione in WOW64: %[1]v\x02Devi u" +
+ "tilizzare la versione nativa di WireGuard su questo computer.\x02Impossi" +
+ "bile aprire il token del processo corrente: %[1]v\x02WireGuard può esser" +
+ "e utilizzato solo dagli utenti membri del gruppo %[1]s di sistema.\x02Wi" +
+ "reGuard è in esecuzione, ma l'interfaccia utente è accessibile solo dai " +
+ "desktop del gruppo %[1]s di sistema.\x02L'icona della barra delle applic" +
+ "azioni di WireGuard non è apparsa dopo 30 secondi.\x02Ora\x02L'orologio " +
+ "di sistema va all'indietro!\x14\x01\x81\x01\x00\x02\x0b\x02%[1]d anno" +
"\x00\x0b\x02%[1]d anni\x14\x01\x81\x01\x00\x02\x0d\x02%[1]d giorno\x00" +
"\x0d\x02%[1]d giorni\x14\x01\x81\x01\x00\x02\x0a\x02%[1]d ora\x00\x0a" +
"\x02%[1]d ore\x14\x01\x81\x01\x00\x02\x0d\x02%[1]d minuto\x00\x0d\x02%[1" +
"]d minuti\x14\x01\x81\x01\x00\x02\x0e\x02%[1]d secondo\x00\x0e\x02%[1]d " +
"secondi\x02%[1]s fa\x02%[1]d\u00a0B\x02%.2[1]f\u00a0KiB\x02%.2[1]f\u00a0" +
- "MiB\x02%.2[1]f\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02Indirizzo" +
- " IP non valido\x02Lunghezza del prefisso di rete non valida\x02Manca la " +
+ "MiB\x02%.2[1]f\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02Manca la " +
"porta dall'endpoint\x02Host dell'endpoint non valido\x02Le parentesi dev" +
"ono contenere un indirizzo IPv6\x02MTU non valido\x02Porta non valida" +
"\x02Keepalive permanente non valido\x02Chiave non valida: %[1]v\x02Le ch" +
- "iavi devono decodificare esattamente 32 byte\x02Il numero deve essere un" +
- " numero compreso tra 0 e 2^64-1: %[1]v\x02Due virgole in una riga\x02Il " +
- "nome del tunnel non è valido\x02Una riga deve essere presente in una sez" +
- "ione\x02La chiave deve avere un valore\x02Chiave non valida per la sezio" +
- "ne [Interface]\x02Chiave non valida per la sezione [Peer]\x02Un'interfac" +
- "cia deve avere una chiave privata\x02[non specificato]\x02Tutti i peer d" +
- "evono avere una chiave pubblica\x02Errore durante il recupero della conf" +
- "igurazione\x02Chiave non valida per la sezione dell'interfaccia\x02La ve" +
- "rsione del protocollo deve essere 1\x02Chiave non valida per la sezione " +
- "peer\x02, \x02 \x02Informazioni su WireGuard\x02Immagine del logo di Wir" +
- "eGuard\x02Chiudi\x02♥ Fai una &donazione!\x02Stato:\x02&Disattiva\x02&At" +
- "tiva\x02Chiave pubblica:\x02Porta in ascolto:\x02MTU:\x02Indirizzi:\x02S" +
- "erver DNS:\x02Chiave pre-condivisa:\x02IP consentiti:\x02Endpoint:\x02Ke" +
- "epalive permanente:\x02Ultima negoziazione:\x02Trasferimento:\x02abilita" +
- "to\x02%[1]s ricevuti, %[2]s inviati\x02Determinazione dello stato del tu" +
- "nnel non riuscita\x02Attivazione del tunnel non riuscita\x02Disattivazio" +
- "ne del tunnel non riuscita\x02Interfaccia: %[1]s\x02Peer\x02Crea tunnel" +
- "\x02Modifica tunnel\x02&Nome:\x02Chiave &pubblica:\x02(sconosciuto)\x02&" +
- "Blocca traffico fuori dal tunnel (kill-switch)\x02&Salva\x02Annulla\x02&" +
- "Configurazione:\x02Nome non valido\x02Un nome è richiesto.\x02Il nome de" +
- "l tunnel ‘%[1]s’ non è valido.\x02Impossibile elencare i tunnel esistent" +
- "i\x02Il tunnel esiste già\x02Un altro tunnel con il nome ‘%[1]s’ esiste " +
- "già.\x02Impossibile creare la nuova configurazione\x02Scrittura del file" +
- " non riuscita\x02Il file ‘%[1]s’ esiste già.\x0a\x0aVuoi sovrascriverlo?" +
- "\x02Attivo\x02Attivazione\x02Inattivo\x02Disattivazione\x02Stato sconosc" +
- "iuto\x02Log\x02&Copia\x02Selezion&a tutto\x02&Salva su file…\x02Tempo" +
- "\x02Messaggio di log\x02File di testo (*.txt)|*.txt|Tutti i file (*.*)|*" +
- ".*\x02Esporta log su file\x02Inform&azioni su WireGuard…\x02Errore del t" +
- "unnel\x02%[1]s\x0a\x0aConsulta il log per ulteriori Informazioni.\x02%[1" +
- "]s (obsoleto)\x02Errore di rilevamento di WireGuard\x02Impossibile atten" +
- "dere la comparsa della finestra di WireGuard: %[1]v\x02WireGuard: disatt" +
- "ivato\x02Stato: sconosciuto\x02Indirizzi: nessuno\x02&Gestisci i tunnel…" +
- "\x02&Importa tunnel da file…\x02E&sci\x02WireGuard attivato\x02Il tunnel" +
- " %[1]s è stato attivato.\x02WireGuard disattivato\x02Il tunnel %[1]s è s" +
- "tato disattivato.\x02Errore tunnel di WireGuard\x02WireGuard: %[1]s\x02S" +
- "tato: %[1]s\x02Un aggiornamento è disponibile!\x02Aggiornamento di WireG" +
- "uard disponibile\x02Un aggiornamento di WireGuard è disponibile. Ti cons" +
- "igliamo di aggiornare il prima possibile.\x02Tunnel\x02&Modifica\x02Aggi" +
- "ungi tunn&el vuoto\x02Aggiungi tunnel\x02Rimuovi tunnel selezionati\x02E" +
- "sporta tutti i tunnel in zip\x02Commu&ta\x02Esporta tutti i tunnel in &z" +
- "ip\x02Modifica il tunnel &selezionato…\x02&Rimuovi i tunnel selezionati" +
- "\x02Impossibile importare la configurazione selezionata: %[1]v\x02Imposs" +
- "ibile enumerare i tunnel esistenti: %[1]v\x02Un altro tunnel esiste già " +
- "con il nome ‘%[1]s‘\x02Impossibile importare la configurazione: %[1]v" +
- "\x02Tunnel importati\x14\x01\x81\x01\x00\x02\x17\x02%[1]d tunnel importa" +
- "to\x00\x17\x02%[1]d tunnel importati\x14\x02\x80\x01\x02 \x02%[1]d de %[" +
- "2]d tunnel importato\x00 \x02%[1]d di %[2]d tunnel importati\x02Impossib" +
- "ile creare il tunnel\x14\x01\x81\x01\x00\x02\x15\x02Elimina %[1]d tunnel" +
- "\x00\x15\x02Elimina %[1]d tunnel\x14\x01\x81\x01\x00\x02,\x02Sei sicuro " +
- "di voler eliminare %[1]d tunnel?\x00,\x02Sei sicuro di voler eliminare %" +
- "[1]d tunnel?\x02Elimina tunnel ‘%[1]s‘\x02Sei sicuro di voler eliminare " +
- "il tunnel ‘%[1]s‘?\x02%[1]s Non è possibile annullare questa azione.\x02" +
- "Impossibile eliminare il tunnel\x02Non è stato possibile rimuovere un tu" +
- "nnel: %[1]s\x02Impossibile eliminare i tunnel\x14\x01\x81\x01\x00\x02/" +
- "\x02Non è stato possibile eliminare %[1]d tunnel.\x00/\x02Non è stato po" +
- "ssibile eliminare %[1]d tunnel.\x02File di configurazione (*.zip, *.conf" +
- ")|*.zip;*.conf|Tutti i file (*.*)|*.*\x02Importa tunnel da file\x02File " +
- "di configurazione ZIP (*.zip)|*.zip\x02Esporta tunnel in zip\x02%[1]s (v" +
- "ersione non firmata, nessun aggiornamento)\x02Errore durante la chiusura" +
- " di WireGuard\x02Impossibile uscire dal servizio a causa di: %[1]v. Potr" +
- "esti voler interrompere WireGuard dal gestore dei servizi.\x02Un aggiorn" +
- "amento di WireGuard è disponibile. Ti consigliamo vivamente di aggiornar" +
- "e immediatamente.\x02Stato: in attesa dell'utente\x02Aggiorna ora\x02Sta" +
- "to: in attesa del servizio di aggiornamento\x02Errore: %[1]v. Prova anco" +
- "ra.\x02Stato: Completo!"
+ "iavi devono decodificare esattamente 32 byte\x02Due virgole in una riga" +
+ "\x02Il nome del tunnel non è valido\x02Una riga deve essere presente in " +
+ "una sezione\x02Manca un separatore di uguaglianza per la chiave di confi" +
+ "gurazione\x02La chiave deve avere un valore\x02Chiave non valida per la " +
+ "sezione [Interface]\x02Chiave non valida per la sezione [Peer]\x02Un'int" +
+ "erfaccia deve avere una chiave privata\x02[non specificato]\x02Tutti i p" +
+ "eer devono avere una chiave pubblica\x02, \x02 \x02Informazioni su WireG" +
+ "uard\x02Immagine del logo di WireGuard\x02Chiudi\x02♥ Fai una &donazione" +
+ "!\x02Stato:\x02&Disattiva\x02&Attiva\x02Chiave pubblica:\x02Porta in asc" +
+ "olto:\x02MTU:\x02Indirizzi:\x02Server DNS:\x02Script:\x02Chiave pre-cond" +
+ "ivisa:\x02IP consentiti:\x02Endpoint:\x02Keepalive permanente:\x02Ultima" +
+ " negoziazione:\x02Trasferimento:\x02pre-up\x02post-up\x02pre-down\x02pos" +
+ "t-down\x02disattivato, per criterio\x02abilitato\x02%[1]s ricevuti, %[2]" +
+ "s inviati\x02Determinazione dello stato del tunnel non riuscita\x02Attiv" +
+ "azione del tunnel non riuscita\x02Disattivazione del tunnel non riuscita" +
+ "\x02Interfaccia: %[1]s\x02Peer\x02Crea tunnel\x02Modifica tunnel\x02&Nom" +
+ "e:\x02Chiave &pubblica:\x02(sconosciuto)\x02&Blocca traffico fuori dal t" +
+ "unnel (kill-switch)\x02&Salva\x02Annulla\x02&Configurazione:\x02Nome non" +
+ " valido\x02Un nome è richiesto.\x02Il nome del tunnel ‘%[1]s’ non è vali" +
+ "do.\x02Impossibile elencare i tunnel esistenti\x02Il tunnel esiste già" +
+ "\x02Un altro tunnel con il nome ‘%[1]s’ esiste già.\x02Impossibile crear" +
+ "e la nuova configurazione\x02Scrittura del file non riuscita\x02Il file " +
+ "‘%[1]s’ esiste già.\x0a\x0aVuoi sovrascriverlo?\x02Attivo\x02Attivazio" +
+ "ne\x02Inattivo\x02Disattivazione\x02Stato sconosciuto\x02Log\x02&Copia" +
+ "\x02Selezion&a tutto\x02&Salva su file…\x02Tempo\x02Messaggio di log\x02" +
+ "File di testo (*.txt)|*.txt|Tutti i file (*.*)|*.*\x02Esporta log su fil" +
+ "e\x02Inform&azioni su WireGuard…\x02Errore del tunnel\x02%[1]s\x0a\x0aCo" +
+ "nsulta il log per ulteriori Informazioni.\x02%[1]s (obsoleto)\x02Errore " +
+ "di rilevamento di WireGuard\x02Impossibile attendere la comparsa della f" +
+ "inestra di WireGuard: %[1]v\x02WireGuard: disattivato\x02Stato: sconosci" +
+ "uto\x02Indirizzi: nessuno\x02&Gestisci i tunnel…\x02&Importa tunnel da f" +
+ "ile…\x02E&sci\x02&Tunnel\x02WireGuard attivato\x02Il tunnel %[1]s è stat" +
+ "o attivato.\x02WireGuard disattivato\x02Il tunnel %[1]s è stato disattiv" +
+ "ato.\x02Errore tunnel di WireGuard\x02WireGuard: %[1]s\x02Stato: %[1]s" +
+ "\x02Indirizzi: %[1]s\x02Un aggiornamento è disponibile!\x02Aggiornamento" +
+ " di WireGuard disponibile\x02Un aggiornamento di WireGuard è disponibile" +
+ ". Ti consigliamo di aggiornare il prima possibile.\x02Tunnel\x02&Modific" +
+ "a\x02Aggiungi tunn&el vuoto...\x02Aggiungi tunnel\x02Rimuovi tunnel sele" +
+ "zionati\x02Esporta tutti i tunnel in zip\x02Commu&ta\x02Esporta tutti i " +
+ "tunnel in &zip...\x02Modifica il tunnel &selezionato…\x02&Rimuovi i tunn" +
+ "el selezionati\x02nessun file di configurazione trovato\x02Impossibile i" +
+ "mportare la configurazione selezionata: %[1]v\x02Impossibile enumerare i" +
+ " tunnel esistenti: %[1]v\x02Un altro tunnel esiste già con il nome ‘%[1]" +
+ "s‘\x02Impossibile importare la configurazione: %[1]v\x02Tunnel importati" +
+ "\x14\x01\x81\x01\x00\x02\x17\x02%[1]d tunnel importato\x00\x17\x02%[1]d " +
+ "tunnel importati\x14\x02\x80\x01\x02 \x02%[1]d de %[2]d tunnel importato" +
+ "\x00 \x02%[1]d di %[2]d tunnel importati\x02Impossibile creare il tunnel" +
+ "\x14\x01\x81\x01\x00\x02\x15\x02Elimina %[1]d tunnel\x00\x15\x02Elimina " +
+ "%[1]d tunnel\x14\x01\x81\x01\x00\x02,\x02Sei sicuro di voler eliminare %" +
+ "[1]d tunnel?\x00,\x02Sei sicuro di voler eliminare %[1]d tunnel?\x02Elim" +
+ "ina tunnel ‘%[1]s‘\x02Sei sicuro di voler eliminare il tunnel ‘%[1]s‘?" +
+ "\x02%[1]s Non è possibile annullare questa azione.\x02Impossibile elimin" +
+ "are il tunnel\x02Non è stato possibile rimuovere un tunnel: %[1]s\x02Imp" +
+ "ossibile eliminare i tunnel\x14\x01\x81\x01\x00\x02/\x02Non è stato poss" +
+ "ibile eliminare %[1]d tunnel.\x00/\x02Non è stato possibile eliminare %[" +
+ "1]d tunnel.\x02File di configurazione (*.zip, *.conf)|*.zip;*.conf|Tutti" +
+ " i file (*.*)|*.*\x02Importa tunnel da file\x02File di configurazione ZI" +
+ "P (*.zip)|*.zip\x02Esporta tunnel in zip\x02%[1]s (versione non firmata," +
+ " nessun aggiornamento)\x02Errore durante la chiusura di WireGuard\x02Imp" +
+ "ossibile uscire dal servizio a causa di: %[1]v. Potresti voler interromp" +
+ "ere WireGuard dal gestore dei servizi.\x02Un aggiornamento di WireGuard " +
+ "è disponibile. Ti consigliamo vivamente di aggiornare immediatamente." +
+ "\x02Stato: in attesa dell'utente\x02Aggiorna ora\x02Stato: in attesa del" +
+ " servizio di aggiornamento\x02Errore: %[1]v. Prova ancora.\x02Stato: Com" +
+ "pleto!"
-var jaIndex = []uint32{ // 181 elements
+var jaIndex = []uint32{ // 180 elements
// Entry 0 - 1F
0x00000000, 0x0000000a, 0x0000005b, 0x00000075,
- 0x0000009a, 0x000000e6, 0x000000e6, 0x00000124,
- 0x0000017b, 0x000001fe, 0x00000253, 0x00000257,
- 0x0000027f, 0x00000290, 0x000002a1, 0x000002b5,
- 0x000002c6, 0x000002d7, 0x000002e1, 0x000002e9,
- 0x000002f6, 0x00000303, 0x00000310, 0x0000031d,
- 0x0000032a, 0x00000344, 0x00000378, 0x000003a6,
- 0x000003ce, 0x000003ff, 0x0000040d, 0x00000426,
+ 0x0000009a, 0x000000e6, 0x00000140, 0x0000017e,
+ 0x000001d5, 0x00000258, 0x000002ad, 0x000002b1,
+ 0x000002d9, 0x000002ea, 0x000002fb, 0x0000030f,
+ 0x00000320, 0x00000331, 0x0000033b, 0x00000343,
+ 0x00000350, 0x0000035d, 0x0000036a, 0x00000377,
+ 0x00000384, 0x000003b2, 0x000003da, 0x0000040b,
+ 0x00000419, 0x00000432, 0x0000045d, 0x00000471,
// Entry 20 - 3F
- 0x00000451, 0x00000465, 0x00000497, 0x000004ea,
- 0x0000050e, 0x0000052d, 0x00000558, 0x0000058f,
- 0x000005c0, 0x000005f5, 0x00000625, 0x0000065c,
- 0x0000066b, 0x0000069c, 0x000006d0, 0x00000703,
- 0x00000746, 0x00000774, 0x00000777, 0x00000779,
- 0x00000790, 0x000007a7, 0x000007a7, 0x000007b1,
- 0x000007cd, 0x000007d5, 0x000007e3, 0x000007f1,
- 0x000007fc, 0x00000813, 0x00000818, 0x00000826,
+ 0x000004a3, 0x000004c7, 0x000004e6, 0x00000511,
+ 0x00000548, 0x00000579, 0x000005ae, 0x000005de,
+ 0x00000615, 0x00000624, 0x00000655, 0x00000658,
+ 0x0000065a, 0x00000671, 0x00000688, 0x00000692,
+ 0x000006ae, 0x000006b6, 0x000006c4, 0x000006d2,
+ 0x000006dd, 0x000006f4, 0x000006f9, 0x00000707,
+ 0x00000716, 0x00000727, 0x00000738, 0x00000745,
+ 0x0000075c, 0x0000077c, 0x0000079c, 0x000007a4,
// Entry 40 - 5F
- 0x00000835, 0x00000835, 0x00000846, 0x00000853,
- 0x0000086a, 0x0000088a, 0x000008aa, 0x000008b2,
- 0x000008b2, 0x000008b9, 0x000008e1, 0x00000912,
- 0x00000940, 0x0000096e, 0x0000098e, 0x00000995,
- 0x000009b1, 0x000009c7, 0x000009d3, 0x000009e2,
- 0x000009eb, 0x00000a44, 0x00000a44, 0x00000a4f,
- 0x00000a5f, 0x00000a6b, 0x00000a7b, 0x00000a94,
- 0x00000ac3, 0x00000af1, 0x00000b19, 0x00000b68,
+ 0x000007ab, 0x000007b3, 0x000007bc, 0x000007c6,
+ 0x000007e8, 0x000007ef, 0x00000817, 0x00000848,
+ 0x00000876, 0x000008a4, 0x000008c4, 0x000008cb,
+ 0x000008e7, 0x000008fd, 0x00000909, 0x00000918,
+ 0x00000921, 0x0000097a, 0x00000985, 0x00000995,
+ 0x000009a1, 0x000009b1, 0x000009ca, 0x000009f9,
+ 0x00000a27, 0x00000a4f, 0x00000a9e, 0x00000acf,
+ 0x00000af4, 0x00000b46, 0x00000b4d, 0x00000b5a,
// Entry 60 - 7F
- 0x00000b99, 0x00000bbe, 0x00000c10, 0x00000c17,
- 0x00000c24, 0x00000c2b, 0x00000c38, 0x00000c48,
- 0x00000c4f, 0x00000c5d, 0x00000c71, 0x00000c8e,
- 0x00000c95, 0x00000cac, 0x00000cf6, 0x00000d21,
- 0x00000d3e, 0x00000d54, 0x00000d89, 0x00000d9e,
- 0x00000db8, 0x00000dfa, 0x00000e15, 0x00000e24,
- 0x00000e39, 0x00000e56, 0x00000e8e, 0x00000e99,
- 0x00000eb3, 0x00000ee5, 0x00000eff, 0x00000f31,
+ 0x00000b61, 0x00000b6e, 0x00000b7e, 0x00000b85,
+ 0x00000b93, 0x00000ba7, 0x00000bc4, 0x00000bcb,
+ 0x00000be2, 0x00000c2c, 0x00000c57, 0x00000c74,
+ 0x00000c8a, 0x00000cbf, 0x00000cd4, 0x00000cee,
+ 0x00000d30, 0x00000d4b, 0x00000d5a, 0x00000d6f,
+ 0x00000d8c, 0x00000dc4, 0x00000dcf, 0x00000de0,
+ 0x00000dfa, 0x00000e2c, 0x00000e46, 0x00000e78,
+ 0x00000e98, 0x00000ea9, 0x00000eb7, 0x00000ecb,
// Entry 80 - 9F
- 0x00000f51, 0x00000f62, 0x00000f70, 0x00000f70,
- 0x00000f8f, 0x00000fb8, 0x00001020, 0x0000102d,
- 0x00001038, 0x0000105b, 0x00001071, 0x00001093,
- 0x000010c7, 0x000010d8, 0x00001113, 0x0000113c,
- 0x00001162, 0x00001162, 0x000011af, 0x000011ed,
- 0x00001239, 0x00001271, 0x00001296, 0x000012ce,
- 0x00001312, 0x00001337, 0x0000135a, 0x00001396,
- 0x000013b9, 0x000013f4, 0x00001425, 0x0000144a,
+ 0x00000eea, 0x00000f13, 0x00000f7b, 0x00000f88,
+ 0x00000f93, 0x00000fb6, 0x00000fcc, 0x00000fee,
+ 0x00001022, 0x00001033, 0x0000106e, 0x00001097,
+ 0x000010bd, 0x000010e8, 0x00001135, 0x00001173,
+ 0x000011bf, 0x000011f7, 0x0000121c, 0x00001254,
+ 0x00001298, 0x000012bd, 0x000012e0, 0x0000131c,
+ 0x0000133f, 0x0000137a, 0x000013ab, 0x000013d0,
+ 0x00001405, 0x0000142a, 0x00001465, 0x000014b8,
// Entry A0 - BF
- 0x0000147f, 0x000014a4, 0x000014df, 0x00001532,
- 0x00001563, 0x0000158d, 0x000015b5, 0x000015eb,
- 0x00001605, 0x00001689, 0x000016ee, 0x00001718,
- 0x00001728, 0x0000175b, 0x00001790, 0x000017a2,
- 0x000017a2, 0x000017a2, 0x000017a2, 0x000017a2,
- 0x000017a2,
-} // Size: 748 bytes
+ 0x000014e9, 0x00001513, 0x0000153b, 0x00001571,
+ 0x0000158b, 0x0000160f, 0x00001674, 0x0000169e,
+ 0x000016ae, 0x000016e1, 0x00001716, 0x00001728,
+ 0x00001728, 0x00001728, 0x00001728, 0x00001728,
+ 0x00001728, 0x00001728, 0x00001728, 0x00001728,
+} // Size: 744 bytes
-const jaData string = "" + // Size: 6050 bytes
+const jaData string = "" + // Size: 5928 bytes
"\x02エラー\x02(引数なし): 管理者権限でmanagerサービスをインストールする\x02使い方: %[1]s [\x0a%[2]s]" +
- "\x02コマンドラインオプション\x02プロセスがWOW64下で動作しているか確認できません: %[1]v\x02現在のプロセスのトークンを開け" +
- "ません: %[1]v\x02WireGuard は組み込みの %[1]s グループのメンバーだけが使えます。\x02WireGuard は実" +
- "行中ですが、UI画面は組み込みの %[1]s グループのデスクトップからしか開けません。\x02WireGuard システムトレイアイコンは" +
- "30秒後に非表示になります。\x02今\x02システム時刻が巻き戻った!\x14\x01\x81\x01\x00\x00\x0a\x02%[1]" +
- "d 年\x14\x01\x81\x01\x00\x00\x0a\x02%[1]d 日\x14\x01\x81\x01\x00\x00\x0d" +
- "\x02%[1]d 時間\x14\x01\x81\x01\x00\x00\x0a\x02%[1]d 分\x14\x01\x81\x01\x00" +
- "\x00\x0a\x02%[1]d 秒\x02%[1]s 前\x02%[1]d B\x02%.2[1]f\u00a0KiB\x02%.2[1]f" +
- "\u00a0MiB\x02%.2[1]f\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02無効な" +
- " IP アドレス\x02無効なネットワークプレフィックス長\x02エンドポイントのポート指定なし\x02無効なエンドポイントホスト\x02カッコ" +
- "内は IPv6 アドレスが入ります\x02無効な MTU\x02無効なポート番号\x02無効な持続的キープアライブ値\x02不正な鍵: %[" +
- "1]v\x02鍵は 32 バイトでなければなりません\x02数値は0から2の64乗-1の範囲内の値でなければなりません: %[1]v\x021行" +
- "にカンマが2つあります\x02トンネル名が不正です\x02行がセクション内にありません\x02設定項目にイコール(=)セパレータがない" +
- "\x02キー項目に対応する値がありません\x02無効な [Interface] セクションのキー項目\x02無効な [Peer] セクションのキ" +
- "ー項目\x02インターフェースには秘密鍵が必須です\x02[指定なし]\x02すべてのピアには公開鍵が必須です\x02設定の読込中にエラーが" +
- "発生しました\x02無効な Interface セクションのキー項目\x02プロトコルバージョンは 1 でなければなりません\x02無効な " +
- "Peer セクションのキー項目\x02, \x02 \x02WireGuard について\x02WireGuard ロゴ画像\x02閉じる" +
- "\x02♥ 寄付のお願い!(&D)\x02状態:\x02無効化(&D)\x02有効化(&A)\x02公開鍵:\x02待受ポート番号:\x02MT" +
- "U:\x02アドレス:\x02DNS サーバ:\x02事前共有鍵:\x02Allowed IPs:\x02エンドポイント:\x02持続的キープア" +
- "ライブ:\x02直近のハンドシェイク:\x02転送:\x02有効\x02%[1]s 受信済み、%[2]s 送信済み\x02トンネルの状態取得" +
- "に失敗しました\x02トンネルの有効化に失敗しました\x02トンネルの無効化に失敗しました\x02インターフェース: %[1]s\x02ピア" +
- "\x02トンネルの新規作成\x02トンネルの編集\x02名前(&N):\x02公開鍵(&P):\x02(不明)\x02トンネルを通らないトラフィ" +
- "ックのブロック(キルスイッチ)(&B)\x02保存(&S)\x02キャンセル\x02設定(&C):\x02無効な名前\x02名前は必須です。" +
- "\x02トンネル名 ‘%[1]s’ は不正です。\x02既存のトンネルを表示できません\x02トンネルはすでに存在します\x02‘%[1]s’ " +
- "という名前の別のトンネルがすでに存在します。\x02新しい設定を作成できませんでした\x02ファイルの書き込みに失敗\x02ファイル ‘%[" +
- "1]s’ はすでに存在します。\x0a\x0a上書きしますか?\x02有効\x02有効化中\x02無効\x02無効化中\x02不明な状態\x02" +
- "ログ\x02コピー(&C)\x02すべて選択(&A)\x02ファイルに保存…(&S)\x02時刻\x02ログ メッセージ\x02テキストファ" +
- "イル (*.txt)|*.txt|すべてのファイル (*.*)|*.*\x02ログをファイルにエクスポート\x02WireGuardについて" +
- "…(&A)\x02トンネルエラー\x02%[1]s\x0a\x0a詳細はログを参照してください。\x02%[1]s (更新あり)\x02Wi" +
- "reGuard 検出エラー\x02WireGuard ウィンドウが表示できませんでした: %[1]v\x02WireGuard: 無効化済み" +
- "\x02状態: 不明\x02アドレス: なし\x02トンネルの管理…(&M)\x02トンネルをファイルからインポート…(&I)\x02終了(&X" +
- ")\x02WireGuard 有効化済み\x02トンネル %[1]s は有効になりました。\x02WireGuard 無効化済み\x02トンネル" +
- " %[1]s は無効になりました。\x02WireGuard トンネルエラー\x02WireGuard: %[1]s\x02状態: %[1]s" +
- "\x02更新が利用できます!\x02WireGuard の更新が利用可能です\x02WireGuard の更新が利用可能になりました。できるだけ" +
- "早く更新してください。\x02トンネル\x02編集(&E)\x02空のトンネルを追加…(&E)\x02トンネルの追加\x02選択したトンネル" +
- "の削除\x02すべてのトンネルをzipにエクスポート\x02切り替え(&T)\x02すべてのトンネルをzipにエクスポート…(&Z)\x02" +
- "選択したトンネルの編集…(&S)\x02選択したトンネルの削除(&R)\x02選択したファイルからインポートできませんでした: %[1]v" +
- "\x02既存のトンネルを表示できませんでした: %[1]v\x02‘%[1]s’ という名前の別のトンネルがすでに存在します\x02設定をインポ" +
- "ートできませんでした: %[1]v\x02トンネルのインポート結果\x14\x01\x81\x01\x00\x001\x02%[1]d トン" +
- "ネルをインポートしました\x14\x02\x80\x01\x00>\x02%[2]d 中の %[1]d トンネルをインポートしました\x02" +
- "トンネルを作成できません\x14\x01\x81\x01\x00\x00\x1c\x02%[1]d トンネルを削除\x14\x01\x81" +
- "\x01\x00\x005\x02本当に %[1]d トンネルを削除しますか?\x02トンネル ‘%[1]s’ を削除\x02本当にトンネル ‘" +
- "%[1]s’ を削除しますか?\x02%[1]s この操作はもとに戻せません。\x02トンネルを削除できません\x02トンネルを削除できませんで" +
- "した: %[1]s\x02トンネルを削除できません\x14\x01\x81\x01\x00\x004\x02%[1]d トンネルを削除できま" +
- "せんでした\x02設定ファイル (*.zip, *.conf)|*.zip;*.conf|すべてのファイル (*.*)|*.*\x02ファイ" +
- "ルからトンネルをインポート\x02ZIP形式設定ファイル (*.zip)|*.zip\x02トンネルをZIPにエクスポート\x02%[1]s" +
- " (未署名のビルド、更新の提供なし)\x02WireGuard 終了エラー\x02%[1]v のためサービスを終了できませんでした。サービスマネ" +
- "ージャから WireGuard を停止できます。\x02WireGuard の更新が利用可能です。速やかに更新することを強く推奨します。" +
- "\x02状態: ユーザーからの応答待ち\x02今すぐ更新\x02状態: アップデータサービスを待機中\x02エラー: %[1]v。再度実行してく" +
- "ださい。\x02状態: 完了!"
+ "\x02コマンドラインオプション\x02プロセスがWOW64下で動作しているか確認できません: %[1]v\x02このコンピュータではネイティブ" +
+ "版の WireGuard を使ってください。\x02現在のプロセスのトークンを開けません: %[1]v\x02WireGuard は組み込み" +
+ "の %[1]s グループのメンバーだけが使えます。\x02WireGuard は実行中ですが、UI画面は組み込みの %[1]s グループのデ" +
+ "スクトップからしか開けません。\x02WireGuard システムトレイアイコンは30秒後に非表示になります。\x02今\x02システム時刻" +
+ "が巻き戻った!\x14\x01\x81\x01\x00\x00\x0a\x02%[1]d 年\x14\x01\x81\x01\x00\x00" +
+ "\x0a\x02%[1]d 日\x14\x01\x81\x01\x00\x00\x0d\x02%[1]d 時間\x14\x01\x81\x01" +
+ "\x00\x00\x0a\x02%[1]d 分\x14\x01\x81\x01\x00\x00\x0a\x02%[1]d 秒\x02%[1]s " +
+ "前\x02%[1]d B\x02%.2[1]f\u00a0KiB\x02%.2[1]f\u00a0MiB\x02%.2[1]f\u00a0G" +
+ "iB\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02エンドポイントのポート指定なし\x02無効なエンドポイントホ" +
+ "スト\x02カッコ内は IPv6 アドレスが入ります\x02無効な MTU\x02無効なポート番号\x02無効な持続的キープアライブ値" +
+ "\x02不正な鍵: %[1]v\x02鍵は 32 バイトでなければなりません\x021行にカンマが2つあります\x02トンネル名が不正です" +
+ "\x02行がセクション内にありません\x02設定項目にイコール(=)セパレータがない\x02キー項目に対応する値がありません\x02無効な [I" +
+ "nterface] セクションのキー項目\x02無効な [Peer] セクションのキー項目\x02インターフェースには秘密鍵が必須です\x02[" +
+ "指定なし]\x02すべてのピアには公開鍵が必須です\x02, \x02 \x02WireGuard について\x02WireGuard ロゴ" +
+ "画像\x02閉じる\x02♥ 寄付のお願い!(&D)\x02状態:\x02無効化(&D)\x02有効化(&A)\x02公開鍵:\x02待受ポ" +
+ "ート番号:\x02MTU:\x02アドレス:\x02DNS サーバ:\x02スクリプト:\x02事前共有鍵:\x02Allowed IPs:" +
+ "\x02エンドポイント:\x02持続的キープアライブ:\x02直近のハンドシェイク:\x02転送:\x02pre-up\x02post-up" +
+ "\x02pre-down\x02post-down\x02ポリシーにより無効です\x02有効\x02%[1]s 受信済み、%[2]s 送信済み" +
+ "\x02トンネルの状態取得に失敗しました\x02トンネルの有効化に失敗しました\x02トンネルの無効化に失敗しました\x02インターフェース: " +
+ "%[1]s\x02ピア\x02トンネルの新規作成\x02トンネルの編集\x02名前(&N):\x02公開鍵(&P):\x02(不明)\x02トン" +
+ "ネルを通らないトラフィックのブロック(キルスイッチ)(&B)\x02保存(&S)\x02キャンセル\x02設定(&C):\x02無効な名前" +
+ "\x02名前は必須です。\x02トンネル名 ‘%[1]s’ は不正です。\x02既存のトンネルを表示できません\x02トンネルはすでに存在します" +
+ "\x02‘%[1]s’ という名前の別のトンネルがすでに存在します。\x02新しい設定を作成できませんでした\x02ファイルの書き込みに失敗" +
+ "\x02ファイル ‘%[1]s’ はすでに存在します。\x0a\x0a上書きしますか?\x02有効\x02有効化中\x02無効\x02無効化中" +
+ "\x02不明な状態\x02ログ\x02コピー(&C)\x02すべて選択(&A)\x02ファイルに保存…(&S)\x02時刻\x02ログ メッセー" +
+ "ジ\x02テキストファイル (*.txt)|*.txt|すべてのファイル (*.*)|*.*\x02ログをファイルにエクスポート\x02Wi" +
+ "reGuardについて…(&A)\x02トンネルエラー\x02%[1]s\x0a\x0a詳細はログを参照してください。\x02%[1]s (更新" +
+ "あり)\x02WireGuard 検出エラー\x02WireGuard ウィンドウが表示できませんでした: %[1]v\x02WireGua" +
+ "rd: 無効化済み\x02状態: 不明\x02アドレス: なし\x02トンネルの管理…(&M)\x02トンネルをファイルからインポート…(&I)" +
+ "\x02終了(&X)\x02トンネル(&T)\x02WireGuard 有効化済み\x02トンネル %[1]s は有効になりました。\x02Wi" +
+ "reGuard 無効化済み\x02トンネル %[1]s は無効になりました。\x02WireGuard トンネルエラー\x02WireGuard" +
+ ": %[1]s\x02状態: %[1]s\x02アドレス: %[1]s\x02更新が利用できます!\x02WireGuard の更新が利用可能で" +
+ "す\x02WireGuard の更新が利用可能になりました。できるだけ早く更新してください。\x02トンネル\x02編集(&E)\x02空の" +
+ "トンネルを追加…(&E)\x02トンネルの追加\x02選択したトンネルの削除\x02すべてのトンネルをzipにエクスポート\x02切り替え(" +
+ "&T)\x02すべてのトンネルをzipにエクスポート…(&Z)\x02選択したトンネルの編集…(&S)\x02選択したトンネルの削除(&R)" +
+ "\x02設定ファイルが見つかりません\x02選択したファイルからインポートできませんでした: %[1]v\x02既存のトンネルを表示できませんで" +
+ "した: %[1]v\x02‘%[1]s’ という名前の別のトンネルがすでに存在します\x02設定をインポートできませんでした: %[1]v" +
+ "\x02トンネルのインポート結果\x14\x01\x81\x01\x00\x001\x02%[1]d トンネルをインポートしました\x14" +
+ "\x02\x80\x01\x00>\x02%[2]d 中の %[1]d トンネルをインポートしました\x02トンネルを作成できません\x14" +
+ "\x01\x81\x01\x00\x00\x1c\x02%[1]d トンネルを削除\x14\x01\x81\x01\x00\x005\x02本当" +
+ "に %[1]d トンネルを削除しますか?\x02トンネル ‘%[1]s’ を削除\x02本当にトンネル ‘%[1]s’ を削除しますか?" +
+ "\x02%[1]s この操作はもとに戻せません。\x02トンネルを削除できません\x02トンネルを削除できませんでした: %[1]s\x02トン" +
+ "ネルを削除できません\x14\x01\x81\x01\x00\x004\x02%[1]d トンネルを削除できませんでした\x02設定ファイル" +
+ " (*.zip, *.conf)|*.zip;*.conf|すべてのファイル (*.*)|*.*\x02ファイルからトンネルをインポート\x02" +
+ "ZIP形式設定ファイル (*.zip)|*.zip\x02トンネルをZIPにエクスポート\x02%[1]s (未署名のビルド、更新の提供なし)" +
+ "\x02WireGuard 終了エラー\x02%[1]v のためサービスを終了できませんでした。サービスマネージャから WireGuard を停" +
+ "止できます。\x02WireGuard の更新が利用可能です。速やかに更新することを強く推奨します。\x02状態: ユーザーからの応答待ち" +
+ "\x02今すぐ更新\x02状態: アップデータサービスを待機中\x02エラー: %[1]v。再度実行してください。\x02状態: 完了!"
-var pa_INIndex = []uint32{ // 181 elements
+var koIndex = []uint32{ // 180 elements
+ // Entry 0 - 1F
+ 0x00000000, 0x00000007, 0x0000003e, 0x00000055,
+ 0x0000006d, 0x000000b6, 0x00000103, 0x00000137,
+ 0x00000192, 0x00000202, 0x00000258, 0x0000025f,
+ 0x00000281, 0x00000292, 0x000002a3, 0x000002b7,
+ 0x000002c8, 0x000002d9, 0x000002e6, 0x000002f7,
+ 0x00000304, 0x00000311, 0x0000031e, 0x0000032b,
+ 0x00000338, 0x00000362, 0x00000386, 0x000003bf,
+ 0x000003cd, 0x000003de, 0x000003fd, 0x0000041c,
+ // Entry 20 - 3F
+ 0x00000450, 0x0000047a, 0x0000049f, 0x000004be,
+ 0x000004eb, 0x00000510, 0x0000053b, 0x00000561,
+ 0x00000593, 0x000005a9, 0x000005d9, 0x000005dc,
+ 0x000005df, 0x000005f6, 0x00000611, 0x00000618,
+ 0x0000062b, 0x00000633, 0x00000647, 0x00000658,
+ 0x00000664, 0x00000673, 0x00000678, 0x00000680,
+ 0x0000068c, 0x0000069a, 0x000006ad, 0x000006bb,
+ 0x000006cc, 0x000006e5, 0x000006fd, 0x00000705,
+ // Entry 40 - 5F
+ 0x00000713, 0x00000721, 0x0000072f, 0x0000073d,
+ 0x0000075f, 0x0000076c, 0x0000078a, 0x000007af,
+ 0x000007d0, 0x000007f4, 0x0000080b, 0x00000812,
+ 0x0000082d, 0x0000083b, 0x00000844, 0x00000851,
+ 0x00000860, 0x0000088c, 0x00000894, 0x0000089b,
+ 0x000008aa, 0x000008bb, 0x000008de, 0x00000905,
+ 0x0000092b, 0x00000943, 0x0000098d, 0x000009ac,
+ 0x000009c1, 0x00000a0a, 0x00000a14, 0x00000a22,
+ // Entry 60 - 7F
+ 0x00000a2c, 0x00000a3d, 0x00000a53, 0x00000a5a,
+ 0x00000a62, 0x00000a71, 0x00000a86, 0x00000a8d,
+ 0x00000a9e, 0x00000ad5, 0x00000af0, 0x00000b0b,
+ 0x00000b19, 0x00000b4f, 0x00000b5e, 0x00000b76,
+ 0x00000bb7, 0x00000bd2, 0x00000be9, 0x00000bf8,
+ 0x00000c0a, 0x00000c32, 0x00000c3a, 0x00000c42,
+ 0x00000c59, 0x00000c8a, 0x00000ca4, 0x00000cd8,
+ 0x00000cf0, 0x00000d07, 0x00000d15, 0x00000d23,
+ // Entry 80 - 9F
+ 0x00000d4f, 0x00000d6d, 0x00000de3, 0x00000dea,
+ 0x00000df2, 0x00000e08, 0x00000e16, 0x00000e31,
+ 0x00000e59, 0x00000e61, 0x00000e8d, 0x00000ea9,
+ 0x00000ec5, 0x00000ee8, 0x00000f18, 0x00000f45,
+ 0x00000f8e, 0x00000fb4, 0x00000fc8, 0x00000fe6,
+ 0x0000100d, 0x0000102c, 0x00001047, 0x0000107e,
+ 0x00001098, 0x000010da, 0x00001110, 0x0000112f,
+ 0x00001155, 0x00001174, 0x000011aa, 0x000011e9,
+ // Entry A0 - BF
+ 0x0000120d, 0x0000122d, 0x00001255, 0x0000128d,
+ 0x000012ab, 0x00001330, 0x0000139b, 0x000013c1,
+ 0x000013d5, 0x00001408, 0x00001433, 0x00001443,
+ 0x00001443, 0x00001443, 0x00001443, 0x00001443,
+ 0x00001443, 0x00001443, 0x00001443, 0x00001443,
+} // Size: 744 bytes
+
+const koData string = "" + // Size: 5187 bytes
+ "\x02오류\x02(인수 없음): 관리자 서비스 상승 및 설치\x02사용: %[1]s [\x0a%[2]s]\x02커맨드 라인 옵션" +
+ "\x02WOW64에서 프로세스가 실행 중인지 확인할 수 없음: %[1]v\x02이 컴퓨터에서는 기본 버전의 WireGuard를 사" +
+ "용해야 합니다.\x02현재 프로세스 토큰을 열 수 없음: %[1]v\x02WireGuard는 Builtin %[1]s 그룹의 " +
+ "구성원인 사용자만 사용할 수 있습니다.\x02WireGuard가 실행 중이나 UI는 Builtin의 데스크톱에서만 액세스할 수" +
+ " 있습니다%[1]s 그룹.\x02WireGuard 시스템 트레이 아이콘이 30초 후에 나타나지 않았습니다.\x02지금\x02시스템" +
+ " 시간이 되돌려짐!\x14\x01\x81\x01\x00\x00\x0a\x02%[1]d 년\x14\x01\x81\x01\x00" +
+ "\x00\x0a\x02%[1]d 일\x14\x01\x81\x01\x00\x00\x0d\x02%[1]d 시간\x14\x01\x81" +
+ "\x01\x00\x00\x0a\x02%[1]d 분\x14\x01\x81\x01\x00\x00\x0a\x02%[1]d 초\x02%[" +
+ "1]s 전에\x02%[1]d\u00a0바이트\x02%.2[1]f\u00a0KiB\x02%.2[1]f\u00a0MiB\x02%.2[" +
+ "1]f\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02엔드포인트에서 포트가 누락됨\x02잘" +
+ "못된 엔드포인트 호스트\x02대괄호에는 IPv6 주소가 포함되어야 합니다\x02잘못된 MTU\x02잘못된 포트\x02잘못된 영" +
+ "구 연결 유지\x02유효하지 않은 키: %[1]v\x02키는 정확히 32바이트로 디코딩이 필요\x02엔드포인트에서 포트가 누락" +
+ "됨\x02터널 이름이 유효하지 않음\x02행은 섹션에 있어야 함\x02구성 키에 등호 구분 기호가 없음\x02키에는 값이 있어" +
+ "야 합니다\x02[Interface] 구간에 대한 잘못된 키\x02[Peer] 구간에 대한 잘못된 키\x02인터페이스에는 개인" +
+ " 키가 있어야 함\x02[특정되지 않음]\x02모든 피어에는 공개 키가 있어야 함\x02, \x02, \x02WireGuard에 " +
+ "관하여\x02WireGuard 로고 이미지\x02닫기\x02♥ &기부하기!\x02상태:\x02&비활성화하기\x02&활성화하기" +
+ "\x02공개 키:\x02수신 포트:\x02MTU:\x02주소:\x02DNS 서버:\x02스크립트:\x02사전 공유 키:\x02허용" +
+ "된 IP:\x02엔드포인트:\x02지속적 연결 유지:\x02마지막 정보교환:\x02전송:\x02사전-준비\x02게시-하기" +
+ "\x02준비-해제\x02게시-중단\x02비활성화됨, 정책에 따라\x02활성화됨\x02%[1]s 받음, %[2]s 보내기\x02터널" +
+ " 상태를 확인하지 못함\x02터널을 활성화하지 못함\x02터널을 비활성화하지 못함\x02인터페이스: %[1]s\x02피어\x02새" +
+ "로운 터널 만들기\x02터널 편집\x02&이름:\x02&공개 키:\x02(알수없음)\x02&Block 터널 없는 교통 (킬-스" +
+ "위치)\x02&저장\x02취소\x02&환경설정:\x02잘못된 이름\x02이름은 필수 항목 입니다.\x02터널명 ‘%[1]s’ " +
+ "무효입니다.\x02기존 터널을 나열할 수 없음\x02이름이 이미 있음\x02이름과 함께 또 다른 터널이 이미 존재합니다 ‘%[" +
+ "1]s’.\x02구성을 가져올 수 없음\x02파일 쓰기 실패\x02파일 ‘%[1]s’ 이미 존재합니다.\x0a\x0aDo you " +
+ "want to overwrite it?\x02활성화\x02활성화 중\x02비활성\x02비활성화 중\x02알 수 없는 상태\x02로" +
+ "그\x02&복사\x02전체 &선택\x02&파일에 저장…\x02시간\x02로그 메시지\x02텍스트 파일 (*.txt)|*.txt" +
+ "|모든 파일 (*.*)|*.*\x02로그 파일 내보내기\x02&WireGuard에 관하여…\x02터널 오류\x02%[1]s\x0a" +
+ "\x0a자세한 내용은 로그를 참조하세요.\x02%[1]s (구식)\x02WireGuard 감지 오류\x02WireGuard 창이 " +
+ "나타날 때까지 기다릴 수 없음: %[1]v\x02WireGuard: 비활성화됨\x02상태: 알 수 없음\x02주소: 없음" +
+ "\x02&터널 관리…\x02&파일에서 터널(s) 불러오기…\x02종료&\x02&터널\x02WireGuard 활성화됨\x02다음 %" +
+ "[1]s 터널이 활성화되었습니다.\x02WireGuard 비활성화됨\x02다음 %[1]s 터널이 비활성화되었습니다.\x02Wire" +
+ "Guard 터널 오류\x02와이어가드: %[1]s\x02상태: %[1]s\x02주소: %[1]s\x02업데이트를 사용할 수 있습니" +
+ "다!\x02WireGuard 업데이트 가능\x02이제 WireGuard 업데이트를 사용할 수 있습니다. 최대한 빨리 업데이트하" +
+ "는 것이 좋습니다.\x02터널\x02&편집\x02&빈 터널 추가…\x02터널 추가\x02선택한 터널(s) 제거\x02터널들을 " +
+ "Zip 파일에 내보내기\x02&토글\x02모든 터널을 &zip으로 내보내기…\x02편집 &선택한 터널…\x02&선택한 터널(s) " +
+ "제거\x02구성 파일을 찾을 수 없음\x02선택한 구성을 가져올 수 없음: %[1]v\x02기존 터널을 열거할 수 없음: %[" +
+ "1]v\x02이름과 함께 또 다른 터널이 이미 존재합니다 ‘%[1]s’\x02구성을 가져올 수 없음: %[1]v\x02터널을 가져" +
+ "옴\x14\x01\x81\x01\x00\x00\x17\x02터널 %[1]d 가져옴\x14\x02\x80\x01\x00!\x02" +
+ "터널 %[1]d 의 %[2]d 가져옴\x02터널을 생성할 수 없음\x14\x01\x81\x01\x00\x00\x14\x02터널" +
+ " %[1]d 삭제\x14\x01\x81\x01\x00\x000\x02삭제하고 싶은 게 확실해 %[1]d 터널?\x02터널 삭제 ‘" +
+ "%[1]s’\x02터널을 삭제하고 싶은 것이 확실합니까 ‘%[1]s’?\x02%[1]s 이 작업은 실행취소할 수 없습니다.\x02" +
+ "터널을 삭제할 수 없음\x02터널을 제거할 수 없음: %[1]s\x02터널을 삭제할 수 없음\x14\x01\x81\x01" +
+ "\x00\x00/\x02%[1]d 터널을 제거할 수 없었습니다.\x02구성 파일 (*.zip, *.conf)|*.zip;*.con" +
+ "f|All Files (*.*)|*.*\x02파일에서 터널(s) 불러오기\x02형상 ZIP 파일 (*.zip)|*.zip\x02터" +
+ "널들을 Zip 파일에 내보내기\x02%[1]s (서명되지 않은 빌드, 업데이트 없음)\x02WireGuard 오류로 종료중" +
+ "\x02다음 원인으로 인해 서비스를 종료할 수 없: %[1]v. 서비스 관리자에서 WireGuard를 중지할 수 있습니다.\x02" +
+ "WireGuard에 대한 업데이트가 가능합니다. 지체 없이 업데이트하는 것이 좋습니다.\x02상태: 사용자를 기다리는 중\x02지" +
+ "금 업데이트\x02상태: 업데이터 서비스를 기다리는 중\x02오류: %[1]v. 다시 시도해 주세요.\x02상태: 완료!"
+
+var nlIndex = []uint32{ // 180 elements
+ // Entry 0 - 1F
+ 0x00000000, 0x0000000c, 0x0000004f, 0x0000006d,
+ 0x00000084, 0x000000c7, 0x0000010a, 0x00000139,
+ 0x0000019f, 0x00000216, 0x00000257, 0x0000025a,
+ 0x0000027a, 0x0000029a, 0x000002b9, 0x000002d6,
+ 0x000002fa, 0x00000320, 0x0000032e, 0x00000337,
+ 0x00000344, 0x00000351, 0x0000035e, 0x0000036b,
+ 0x00000378, 0x00000398, 0x000003af, 0x000003d6,
+ 0x000003e4, 0x000003f4, 0x00000414, 0x0000042d,
+ // Entry 20 - 3F
+ 0x00000459, 0x00000471, 0x00000488, 0x000004aa,
+ 0x000004e6, 0x00000504, 0x00000530, 0x00000557,
+ 0x00000584, 0x00000596, 0x000005c1, 0x000005c4,
+ 0x000005c6, 0x000005d5, 0x000005ef, 0x000005f7,
+ 0x00000604, 0x0000060c, 0x00000618, 0x00000622,
+ 0x00000634, 0x00000646, 0x0000064b, 0x00000655,
+ 0x00000662, 0x0000066b, 0x0000067d, 0x00000695,
+ 0x0000069f, 0x0000069f, 0x000006b7, 0x000006c3,
+ // Entry 40 - 5F
+ 0x000006c3, 0x000006c3, 0x000006c3, 0x000006c3,
+ 0x000006dd, 0x000006ea, 0x0000070b, 0x0000072d,
+ 0x00000747, 0x00000763, 0x00000763, 0x00000763,
+ 0x00000776, 0x00000776, 0x0000077d, 0x00000790,
+ 0x0000079b, 0x000007c8, 0x000007d1, 0x000007db,
+ 0x000007ea, 0x000007f9, 0x0000080e, 0x00000833,
+ 0x00000858, 0x0000086d, 0x000008a2, 0x000008d7,
+ 0x000008f1, 0x00000928, 0x0000092f, 0x00000939,
+ // Entry 60 - 7F
+ 0x00000942, 0x0000094e, 0x0000095f, 0x00000967,
+ 0x00000971, 0x00000982, 0x0000099b, 0x000009a0,
+ 0x000009ab, 0x000009e2, 0x00000a01, 0x00000a14,
+ 0x00000a20, 0x00000a53, 0x00000a67, 0x00000a80,
+ 0x00000ab0, 0x00000ac9, 0x00000ada, 0x00000aea,
+ 0x00000afe, 0x00000b22, 0x00000b2d, 0x00000b36,
+ 0x00000b4c, 0x00000b6c, 0x00000b84, 0x00000ba6,
+ 0x00000bbc, 0x00000bcd, 0x00000bdb, 0x00000bec,
+ // Entry 80 - 9F
+ 0x00000c07, 0x00000c24, 0x00000c83, 0x00000c8b,
+ 0x00000c95, 0x00000cae, 0x00000cbf, 0x00000ce3,
+ 0x00000d10, 0x00000d22, 0x00000d53, 0x00000d75,
+ 0x00000d9a, 0x00000dbe, 0x00000dfb, 0x00000e26,
+ 0x00000e5a, 0x00000e89, 0x00000ea0, 0x00000ee0,
+ 0x00000f39, 0x00000f52, 0x00000f8c, 0x00000ffe,
+ 0x00001017, 0x0000104f, 0x0000107c, 0x00001098,
+ 0x000010c6, 0x000010e3, 0x00001142, 0x0000118e,
+ // Entry A0 - BF
+ 0x000011ae, 0x000011d6, 0x000011ff, 0x000011ff,
+ 0x0000121c, 0x0000121c, 0x00001291, 0x000012ae,
+ 0x000012bb, 0x000012bb, 0x000012dd, 0x000012ef,
+ 0x000012ef, 0x000012ef, 0x000012ef, 0x000012ef,
+ 0x000012ef, 0x000012ef, 0x000012ef, 0x000012ef,
+} // Size: 744 bytes
+
+const nlData string = "" + // Size: 4847 bytes
+ "\x02Foutmelding\x02(geen argumenten): Verhoog rechten en installeer behe" +
+ "erder-service\x02Gebruikswijze: %[1]s [\x0a%[2]s]\x02Opdracht-prompt Opt" +
+ "ies\x02Kan niet bepalen of het proces wordt uitgevoerd onder WOW64: %[1]" +
+ "v\x02Je moet de native versie van WireGuard gebruiken op deze computer." +
+ "\x02Kan de huidige proces-token niet openen: %[1]v\x02WireGuard mag alle" +
+ "en gebruikt worden door gebruikers die deel uitmaken van de ingebouwde %" +
+ "[1]s groep.\x02WireGuard is actief, maar de gebruikersinterface is allee" +
+ "n toegankelijk via de desktops van de Ingebouwde %[1]s groep.\x02WireGua" +
+ "rd systeem tray icoon is niet weergegeven na 30 seconden.\x02Nu\x02Syste" +
+ "emklok is achteruit gezet!\x14\x01\x81\x01\x00\x02\x0b\x02%[1]d jaar\x00" +
+ "\x0c\x02%[1]d jaren\x14\x01\x81\x01\x00\x02\x0a\x02%[1]d dag\x00\x0c\x02" +
+ "%[1]d dagen\x14\x01\x81\x01\x00\x02\x0a\x02%[1]d uur\x00\x0a\x02%[1]d uu" +
+ "r\x14\x01\x81\x01\x00\x02\x0d\x02%[1]d minuut\x00\x0e\x02%[1]d Minuten" +
+ "\x14\x01\x81\x01\x00\x02\x0e\x02%[1]d Seconde\x00\x0f\x02%[1]d Seconden" +
+ "\x02%[1]s geleden\x02%[1]d\u00a0B\x02%.2[1]f\u00a0KiB\x02%.2[1]f\u00a0Mi" +
+ "B\x02%.2[1]f\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02Ontbrekende" +
+ " poort voor endpoint\x02Ongeldig endpoint host\x02Haakjes moeten een IPv" +
+ "6-adres bevatten\x02Ongeldige MTU\x02Ongeldige poort\x02Ongeldige Persis" +
+ "tent Keep-alive\x02Ongeldige sleutel: %[1]v\x02Keys moeten gedecodeerd e" +
+ "xact 32 bytes zijn\x02Twee komma's op een rij\x02Tunnelnaam is ongeldig" +
+ "\x02Lijn moet in een sectie voorkomen\x02Configuratiesleutel mist een ge" +
+ "lijkheidsteken als seperator\x02Sleutel met een waarde hebben\x02Ongeldi" +
+ "ge sleutel voor [Interface]-gedeelte\x02Ongeldige sleutel voor [Peer]-ge" +
+ "deelte\x02Een interface moet een privé sleutel hebben\x02[Niets opgegeve" +
+ "n]\x02Alle peers moeten publieke sleutels hebben\x02, \x02 \x02Over Wire" +
+ "Guard\x02WireGuard logo-afbeelding\x02Sluiten\x02♥ &Doneer!\x02Status:" +
+ "\x02&Deactiveer\x02&Activeer\x02Publieke sleutel:\x02Luister op poort:" +
+ "\x02MTU:\x02Adressen:\x02DNS-servers:\x02Scripts:\x02Gedeelde sleutel:" +
+ "\x02Toegestane IP-adressen:\x02Eindpunt:\x02Recentste uitwisseling:\x02O" +
+ "verdracht:\x02uitgeschakeld, per beleid\x02ingeschakeld\x02%[1]s ontvang" +
+ "en, %[2]s verzonden\x02Kon tunnelstatus niet vaststellen\x02Kon tunnel n" +
+ "iet activeren\x02Kon tunnel niet deactiveren\x02Maak nieuwe tunnel\x02&N" +
+ "aam:\x02&Publieke sleutel:\x02(onbekend)\x02&Ongetunneld verkeer blokker" +
+ "en (kill-switch)\x02&Opslaan\x02Annuleren\x02&Instellingen:\x02Ongeldige" +
+ " naam\x02Een naam is vereist.\x02Naam van tunnel '%[1]s' is ongeldig." +
+ "\x02Kan bestaande tunnels niet weergeven\x02Tunnel bestaat reeds\x02Er b" +
+ "estaat al een andere tunnel met de naam '%[1]s'.\x02De nieuwe instelling" +
+ "en konden niet worden aangemaakt\x02Bestand schrijven mislukt\x02Bestand" +
+ " '%[1]s' bestaat al.\x0a\x0aWil je dit overschrijven?\x02Actief\x02Activ" +
+ "eren\x02Inactief\x02Deactiveren\x02Onbekende status\x02Logboek\x02&Kopië" +
+ "er\x02Selecteer &alles\x02&Opslaan naar bestand…\x02Tijd\x02Logbericht" +
+ "\x02Tekstbestanden (*.txt)|*.txt|Alle bestanden (*. *)|*.*\x02Exporteer " +
+ "logboek naar bestand\x02Over Wiregu&ard…\x02Tunnel-fout\x02%[1]s\x0a\x0a" +
+ "Raadpleeg het logboek voor meer informatie.\x02%[1]s (out-of-date)\x02Wi" +
+ "reGuard Detection Fout\x02Kan niet wachten op het Wireguard-window: %[1]" +
+ "v\x02WireGuard: Gedeactiveerd\x02Status: Onbekend\x02Addressen: Geen\x02" +
+ "&Tunnels beheren…\x02&Importeer tunnel(s) van bestand…\x02&Afsluiten\x02" +
+ "&Tunnels\x02WireGuard Geactiveerd\x02De %[1]s tunnel is geactiveerd.\x02" +
+ "WireGuard Gedeactiveerd\x02De %[1]s tunnel is gedeactiveerd.\x02WireGuar" +
+ "d Tunnel Fout\x02WireGuard: %[1]s\x02Status: %[1]s\x02Addressen: %[1]s" +
+ "\x02Een Update is Beschikbaar!\x02WireGuard update beschikbaar\x02Een up" +
+ "date voor WireGuard is beschikbaar. Het wordt aangeraden zo snel mogelij" +
+ "k bij te werken.\x02Tunnels\x02B&ewerken\x02Voeg l&ege tunnel toe…\x02Tu" +
+ "nnel toevoegen\x02Geselecteerde tunnel(s) verwijderen\x02Alle tunnels na" +
+ "ar een zip-bestand exporteren\x02In-/ui&tschakelen\x02Alle tunnels naar " +
+ "een &zip-bestand exporteren…\x02Ge&selecteerde tunnel bewerken…\x02Gesel" +
+ "ecteerde tunnel(s) ve&rwijderen\x02geen configuratiebestanden gevonden" +
+ "\x02Kan geselecteerde configuratiebestand niet importeren: %[1]v\x02Kon " +
+ "bestaande tunnels niet opsommen: %[1]v\x02Er bestaat al een andere tunne" +
+ "l met de naam '%[1]s'\x02Kan configuratiebestand niet importeren: %[1]v" +
+ "\x02Geïmporteerde tunnels\x14\x01\x81\x01\x00\x02\x1b\x02%[1]d tunnel ge" +
+ "ïmporteerd\x00\x1c\x02%[1]d tunnels geïmporteerd\x14\x02\x80\x01\x02(" +
+ "\x02%[1]d van %[2]d tunnel(s) geïmporteerd\x00)\x02%[1]d van de %[2]d tu" +
+ "nnels geïmporteerd\x02Kan tunnel niet creëren\x14\x01\x81\x01\x00\x02" +
+ "\x18\x02%[1]d tunnel verwijderd\x00\x19\x02%[1]d tunnels verwijderd\x14" +
+ "\x01\x81\x01\x00\x024\x02Weet je zeker dat je %[1]d tunnel wilt verwijde" +
+ "ren?\x005\x02Weet je zeker dat je %[1]d tunnels wilt verwijderen?\x02Ver" +
+ "wijder tunnel '%[1]s'\x02Weet je zeker dat je de tunnel '%[1]s' wil verw" +
+ "ijderen?\x02%[1]s Je kan deze actie niet ongedaan maken.\x02Kan tunnel n" +
+ "iet verwijderen\x02Eén tunnel kon niet worden verwijderd: %[1]s\x02Kan t" +
+ "unnels niet verwijderen\x14\x01\x81\x01\x00\x02)\x02%[1]d tunnel kon nie" +
+ "t worden verwijderd.\x00-\x02%[1]d tunnels konden niet worden verwijderd" +
+ ".\x02Configuratiebestanden (*.zip, *.conf)|*.zip;*.conf|Alle bestanden (" +
+ "*.*)|*.*\x02Importeer tunnel(s) uit bestand\x02Configuratiebestanden ZIP" +
+ " (*.zip)|*.zip\x02Alle tunnels naar zip-bestand exporteren\x02Fout bij a" +
+ "fsluiten WireGuard\x02Er is een update voor WireGuard beschikbaar. Het w" +
+ "ordt ten sterkste aangeraden deze zo snel mogelijk te installeren.\x02St" +
+ "atus: Wachten op gebruiker\x02Nu Bijwerken\x02Fout: %[1]v. Probeer het o" +
+ "pnieuw.\x02Status: Voltooid!"
+
+var pa_INIndex = []uint32{ // 180 elements
// Entry 0 - 1F
0x00000000, 0x00000010, 0x00000010, 0x00000030,
0x0000005d, 0x000000ea, 0x0000017f, 0x000001e6,
@@ -1263,54 +2067,53 @@ var pa_INIndex = []uint32{ // 181 elements
0x00000479, 0x000004a2, 0x000004cb, 0x000004fa,
0x00000529, 0x0000055e, 0x00000577, 0x00000580,
0x0000058d, 0x0000059a, 0x000005a7, 0x000005b4,
- 0x000005c1, 0x000005ea, 0x0000062a, 0x00000671,
- 0x00000671, 0x00000671, 0x0000068f, 0x000006b6,
+ 0x000005c1, 0x00000608, 0x00000608, 0x00000608,
+ 0x00000626, 0x0000064d, 0x0000067c, 0x000006ad,
// Entry 20 - 3F
- 0x000006e5, 0x000006e5, 0x000006e5, 0x000006e5,
- 0x000006e5, 0x000006e5, 0x000006e5, 0x000006e5,
- 0x000006e5, 0x000006e5, 0x000006e5, 0x000006e5,
- 0x000006e5, 0x000006e5, 0x000006e5, 0x000006e5,
- 0x000006e5, 0x000006e5, 0x000006e8, 0x000006eb,
- 0x00000711, 0x00000711, 0x000007d7, 0x000007eb,
- 0x00000808, 0x00000819, 0x0000083e, 0x0000085c,
- 0x0000087d, 0x000008a5, 0x000008aa, 0x000008c1,
+ 0x00000727, 0x00000766, 0x0000079f, 0x000007ea,
+ 0x000007ea, 0x000007ea, 0x000007ea, 0x000007ea,
+ 0x000007ea, 0x000007ea, 0x000007ea, 0x000007ed,
+ 0x000007f0, 0x00000816, 0x00000816, 0x0000082a,
+ 0x00000847, 0x00000858, 0x0000087d, 0x0000089b,
+ 0x000008bc, 0x000008e4, 0x000008e9, 0x00000900,
+ 0x00000912, 0x0000092f, 0x00000970, 0x00000991,
+ 0x000009af, 0x000009ea, 0x00000a0f, 0x00000a26,
// Entry 40 - 5F
- 0x000008d3, 0x000008f0, 0x000008f0, 0x00000911,
- 0x0000092f, 0x0000092f, 0x0000092f, 0x00000946,
- 0x00000946, 0x0000095d, 0x00000984, 0x000009cf,
- 0x00000a11, 0x00000a5a, 0x00000a77, 0x00000a84,
- 0x00000aa8, 0x00000ac9, 0x00000ad8, 0x00000afd,
- 0x00000b15, 0x00000b15, 0x00000b15, 0x00000b2c,
- 0x00000b40, 0x00000b58, 0x00000b6f, 0x00000b96,
- 0x00000b96, 0x00000b96, 0x00000bd1, 0x00000c2f,
+ 0x00000a26, 0x00000a26, 0x00000a26, 0x00000a26,
+ 0x00000a58, 0x00000a6f, 0x00000a96, 0x00000ae1,
+ 0x00000b23, 0x00000b6c, 0x00000b89, 0x00000b96,
+ 0x00000bba, 0x00000bdb, 0x00000bea, 0x00000c0f,
+ 0x00000c27, 0x00000c9e, 0x00000cb5, 0x00000cc9,
+ 0x00000ce1, 0x00000cf8, 0x00000d1f, 0x00000d1f,
+ 0x00000d1f, 0x00000d5a, 0x00000db8, 0x00000e09,
+ 0x00000e47, 0x00000ef1, 0x00000f01, 0x00000f39,
// Entry 60 - 7F
- 0x00000c80, 0x00000cbe, 0x00000d68, 0x00000d78,
- 0x00000db0, 0x00000dc7, 0x00000e06, 0x00000e2c,
- 0x00000e39, 0x00000e54, 0x00000e72, 0x00000ea9,
- 0x00000eb6, 0x00000ed3, 0x00000f37, 0x00000f78,
- 0x00000fa5, 0x00000fbc, 0x00000ff0, 0x00001004,
- 0x00001028, 0x00001028, 0x00001066, 0x0000108d,
- 0x000010be, 0x000010f9, 0x00001144, 0x00001155,
- 0x0000118b, 0x000011c9, 0x00001206, 0x0000124b,
+ 0x00000f50, 0x00000f8f, 0x00000fb5, 0x00000fc2,
+ 0x00000fdd, 0x00000ffb, 0x00001032, 0x0000103f,
+ 0x0000105c, 0x000010c0, 0x00001101, 0x0000112e,
+ 0x00001145, 0x00001179, 0x0000118d, 0x000011b1,
+ 0x000011b1, 0x000011ef, 0x00001216, 0x00001247,
+ 0x00001282, 0x000012cd, 0x000012de, 0x000012ec,
+ 0x00001322, 0x00001360, 0x0000139d, 0x000013e2,
+ 0x00001412, 0x00001432, 0x00001449, 0x00001469,
// Entry 80 - 9F
- 0x0000127b, 0x0000129b, 0x000012b2, 0x000012d2,
- 0x000012fd, 0x00001340, 0x00001436, 0x00001446,
- 0x00001457, 0x00001482, 0x00001499, 0x000014d3,
- 0x00001534, 0x00001545, 0x000015a9, 0x000015d4,
- 0x00001612, 0x00001665, 0x00001665, 0x00001665,
- 0x00001665, 0x00001665, 0x0000169b, 0x0000169b,
- 0x0000169b, 0x000016cf, 0x000016cf, 0x000017a2,
- 0x000017cf, 0x00001837, 0x00001837, 0x0000186b,
+ 0x00001494, 0x000014d7, 0x000015cd, 0x000015dd,
+ 0x000015ee, 0x00001619, 0x00001630, 0x0000166a,
+ 0x000016cb, 0x000016dc, 0x00001740, 0x0000176b,
+ 0x000017a9, 0x000017fc, 0x000017fc, 0x000017fc,
+ 0x00001861, 0x000018b2, 0x000018e8, 0x0000195d,
+ 0x0000195d, 0x00001991, 0x000019da, 0x00001aad,
+ 0x00001ada, 0x00001b42, 0x00001baa, 0x00001bde,
+ 0x00001c20, 0x00001c5a, 0x00001c5a, 0x00001cd3,
// Entry A0 - BF
- 0x0000186b, 0x0000186b, 0x0000186b, 0x000018e4,
- 0x00001928, 0x00001969, 0x00001969, 0x00001969,
- 0x00001969, 0x00001969, 0x00001969, 0x00001969,
- 0x00001993, 0x00001993, 0x00001993, 0x000019b2,
- 0x000019b2, 0x000019b2, 0x000019b2, 0x000019b2,
- 0x000019c0,
-} // Size: 748 bytes
+ 0x00001d17, 0x00001d58, 0x00001d58, 0x00001d58,
+ 0x00001d9a, 0x00001e6e, 0x00001f4a, 0x00001faa,
+ 0x00001fd4, 0x0000203e, 0x0000207f, 0x0000209e,
+ 0x0000209e, 0x0000209e, 0x0000209e, 0x0000209e,
+ 0x0000209e, 0x0000209e, 0x0000209e, 0x0000209e,
+} // Size: 744 bytes
-const pa_INData string = "" + // Size: 6592 bytes
+const pa_INData string = "" + // Size: 8350 bytes
"\x02ਗ਼ਲਤੀ\x02ਵਰਤੋਂ: %[1]s [\x0a%[2]s]\x02ਕਮਾਂਡ ਲਾਈਨ ਚੋਣਾਂ\x02ਪਤਾ ਲਗਾਉਣ ਲ" +
"ਈ ਅਸਮਰੱਥ ਹੈ ਕਿ ਪਰੋਸੈਸ WOW64 ਅਧੀਨ ਚੱਲ ਰਿਹਾ ਹੈ: %[1]v\x02ਤੁਹਾਨੂੰ ਇਸ ਕੰਪਿ" +
"ਊਟਰ ਉੱਤੇ WireGuard ਦਾ ਮੂਲ ਵਰਜ਼ਨ ਵਰਤਣਾ ਚਾਹੀਦਾ ਹੈ।\x02ਮੌਜੂਦਾ ਪਰੋਸੈਸ ਟੋਕਨ " +
@@ -1324,204 +2127,342 @@ const pa_INData string = "" + // Size: 6592 bytes
"\x00\x13\x02%[1]d ਘੰਟੇ\x14\x01\x81\x01\x00\x02\x13\x02%[1]d ਮਿੰਟ\x00\x13" +
"\x02%[1]d ਮਿੰਟ\x14\x01\x81\x01\x00\x02\x16\x02%[1]d ਸਕਿੰਟ\x00\x16\x02%[1" +
"]d ਸਕਿੰਟ\x02%[1]s ਪਹਿਲਾਂ\x02%[1]d\u00a0B\x02%.2[1]f\u00a0KiB\x02%.2[1]f" +
- "\u00a0MiB\x02%.2[1]f\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02ਅਵੈ" +
- "ਧ IP ਸਿਰਨਾਵਾਂ\x02ਗਲਤ ਨੈੱਟਵਰਕ ਅਗੇਤਰ ਲੰਬਾਈ\x02ਐਂਡਪੁਆਇੰਟ ਤੋਂ ਪੋਰਟ ਗੁੰਮ ਹੈ" +
- "\x02ਗ਼ੈਰ-ਵਾਜਬ MTU\x02ਗ਼ੈਰ-ਵਾਜਬ ਪੋਰਟ\x02ਗ਼ੈਰ-ਵਾਜਬ persistent keepalive" +
- "\x02, \x02, \x02ਵਾਇਰਗਾਰਡ ਬਾਰੇ\x02ਐਪ ਦਾ ਵਰਜ਼ਨ: %[1]s\x0aਗੋ ਬੈਕਐਂਡ ਦਾ ਵਰਜ਼ਨ:" +
- " %[2]s\x0aਗੋ ਦਾ ਵਰਜ਼ਨ: %[3]s-%[4]s\x0aਓਪਰੇਟਿੰਗ ਸਿਸਟਮ: %[5]s\x0aਢਾਂਚਾ: %[6" +
- "]s\x02ਬੰਦ ਕਰੋ\x02♥ ਦਾਨ ਦਿਓ(&D)!\x02ਸਥਿਤੀ:\x02ਨਾ-ਸਰਗਰਮ ਕਰੋ(&D)\x02ਸਰਗਰਮ ਕ" +
- "ਰੋ(&A)\x02ਪਬਲਿਕ ਕੁੰਜੀ:\x02ਸੁਣਨ ਵਾਲੀ ਪੋਰਟ:\x02MTU:\x02ਸਿਰਨਾਵੇ:\x02DNS ਸ" +
- "ਰਵਰ:\x02ਸਕ੍ਰਿਪਟਾਂ:\x02ਮਨਜ਼ੂਰ ਕੀਤੇ IP:\x02ਐਂਡ-ਪੁਆਇੰਟ:\x02ਟਰਾਂਸਫਰ:\x02ਸਮਰ" +
- "ੱਥ ਹੈ\x02%[1]s ਮਿਲੇ, %[2]s ਭੇਜੇ\x02ਟਨਲ ਸਥਿਤੀ ਪਤਾ ਲਗਾਉਣ ਲਈ ਅਸਫ਼ਲ\x02ਟਨਲ" +
- " ਸਰਗਰਮ ਕਰਨ ਲਈ ਅਸਫ਼ਲ ਹੈ\x02ਟਨਲ ਨਾ-ਸਰਗਰਮ ਕਰਨ ਲਈ ਅਸਫ਼ਲ ਹੈ\x02ਇੰਟਰਫੇਸ: %[1]s" +
- "\x02ਪੀਅਰ\x02ਨਵੀਂ ਟਨਲ ਬਣਾਓ\x02ਟਨਲ ਨੂੰ ਸੋਧੋ\x02ਨਾਂ(&N):\x02ਪਬਲਿਕ ਕੁੰਜੀ(&P)" +
- ":\x02(ਅਣਪਛਾਤਾ)\x02ਸੰਭਾਲੋ(&S)\x02ਰੱਦ ਕਰੋ\x02ਸੰਰਚਨਾ(&C):\x02ਅਯੋਗ ਨਾਂ\x02ਨਾ" +
- "ਂ ਚਾਹੀਦਾ ਹੈ।\x02ਟਨਲ ਪਹਿਲਾਂ ਹੀ ਮੌਜੂਦ ਹੈ\x02ਨਾਂ ‘%[1]s’ ਨਾਲ ਟਨਲ ਪਹਿਲਾਂ ਹ" +
- "ੀ ਮੌਜੂਦ ਹੈ।\x02ਨਵੀਂ ਸੰਰਚਨਾ ਬਣਾਉਣ ਲਈ ਅਸਮਰੱਥ ਹੈ\x02ਫ਼ਾਇਲ ਬਣਾਉਣ ਲਈ ਅਸਫ਼ਲ " +
- "ਹੈ\x02‘%[1]s’ ਫ਼ਾਇਲ ਪਹਿਲਾਂ ਹੀ ਮੌਜੂਦ ਹੈ।\x0a\x0aਕੀ ਤੁਸੀਂ ਇਸ ਉੱਤੇ ਲਿਖਣਾ " +
- "ਚਾਹੁੰਦੇ ਹੋ?\x02ਸਰਗਰਮ\x02ਸਰਗਰਮ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ\x02ਨਾ-ਸਰਗਰਮ\x02ਨਾ-ਸਰਗਰਮ " +
- "ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ\x02ਅਣਪਛਾਤੀ ਸਥਿਤੀ\x02ਲਾਗੂ\x02ਕਾਪੀ ਕਰੋ(&C)\x02ਸਾਰੇ ਚੁਣੋ(" +
- "&a)\x02ਫ਼ਾਇਲ ਵਿੱਚ ਸੰਭਾਲੋ(&S)…\x02ਸਮਾਂ\x02ਲਾਗ ਸੁਨੇਹਾ\x02ਲਿਖਤ ਫ਼ਾਇਲਾਂ (*.t" +
- "xt)|*.txt|ਸਾਰੀਆਂ ਫ਼ਾਇਲਾਂ (*.*)|*.*\x02ਲਾਗ ਫ਼ਾਇਲ ਵਿੱਚ ਬਰਾਮਦ ਕਰੋ\x02ਵਾਇਰਗਾ" +
- "ਰਡ ਬਾਰੇ(&A)…\x02ਟਨਲ ਗਲਤੀ\x02%[1]s\x0a\x0aPlease consult the log for mo" +
- "re information.\x02%[1]s (out of date)\x02WireGuard ਖੋਜ ਗ਼ਲਤੀ\x02ਵਾਇਰਗਾਰ" +
- "ਡ: ਨਾ-ਸਰਗਰਮ ਕੀਤਾ\x02ਸਥਿਤੀ: ਅਣਪਛਾਤੀ\x02ਸਿਰਨਾਵੇਂ: ਕੋਈ ਨਹੀਂ\x02ਟਨਲਾਂ ਦਾ ਇ" +
- "ੰਤਜ਼ਾਮ ਕਰੋ(&M)…\x02ਫ਼ਾਇਲ ਤੋਂ ਟਨਲਾਂ ਦਰਾਮਦ ਕਰੋ(&I)…\x02ਬਾਹਰ(&x)\x02ਵਾਇਰਗਾ" +
- "ਰਡ ਸਰਗਰਮ ਕੀਤਾ\x02%[1]s ਟਨਲ ਸਰਗਰਮ ਕੀਤੀ ਗਈ ਹੈ।\x02ਵਾਇਰਗਾਰਡ ਨਾ-ਸਰਗਰਮ ਕੀਤਾ" +
- "\x02%[1]s ਟਨਲ ਨਾ-ਸਰਗਰਮ ਕੀਤੀ ਗਈ ਹੈ।\x02ਵਾਇਰਗਾਰਡ ਟਨਲ ਗਲਤੀ\x02ਵਾਇਰਗਾਰਡ: %[1" +
- "]s\x02ਸਥਿਤੀ: %[1]s\x02ਸਿਰਨਾਵੇਂ: %[1]s\x02ਅੱਪਡੇਟ ਮੌਜੂਦ ਹੈ!\x02ਵਾਇਰਗਾਰਡ ਅੱ" +
- "ਪਡੇਟ ਮੌਜੂਦ ਹੈ\x02ਵਾਇਰਗਾਰਡ ਲਈ ਅੱਪਡੇਟ ਹੁਣ ਮੌਜੂਦ ਹੈ। ਜਿੰਨਾ ਛੇਤੀ ਹੋ ਸਕੇ ਤੁ" +
- "ਹਾਨੂੰ ਅੱਪਡੇਟ ਕਰਨ ਦੀ ਸਲਾਹ ਦਿੱਤੀ ਜਾਂਦੀ ਹੈ।\x02ਟਨਲਾਂ\x02ਸੋਧੋ(&E)\x02…ਖਾਲੀ" +
- " ਟਨਲ ਜੋੜੋ(&e)\x02ਟਨਲ ਜੋੜੋ\x02ਚੁਣੀਆਂ ਟਨਲਾਂ ਨੂੰ ਹਟਾਓ\x02ਸਾਰੀਆਂ ਟਨਲਾਂ ਨੂੰ ਜ਼" +
- "ਿੱਪ ਵਜੋਂ ਬਰਾਮਦ ਕਰੋ\x02ਪਲਟੋ(&T)\x02ਸਾਰੀਆਂ ਟਨਲਾਂ ਨੂੰ ਜ਼ਿੱਪ ਵਜੋਂ ਬਰਾਮਦ ਕਰੋ" +
- "…\x02ਚੁਣੀ ਟਨਲ ਸੋਧੋ(&s)…\x02ਚੁਣੀਆਂ ਟਨਲਾਂ ਨੂੰ ਹਟਾਓ(&R)\x02ਕੋਈ ਸੰਰਚਨਾ ਫ਼ਾ" +
- "ਇਲਾਂ ਨਹੀਂ ਲੱਭੀਆਂ\x02ਇੰਪੋਰਟ ਕੀਤੀਆਂ ਟਨਲਾਂ\x02ਟਨਲ ਬਣਾਉਣ ਲਈ ਅਸਮਰੱਥ\x14\x01" +
- "\x81\x01\x00\x02b\x02ਕੀ ਤੁਸੀਂ %[1]d ਟਨਲ ਨੂੰ ਹਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?\x00h\x02ਕ" +
- "ੀ ਤੁਸੀਂ %[1]d ਟਨਲਾਂ ਨੂੰ ਹਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?\x02‘%[1]s’ ਟਨਲ ਨੂੰ ਹਟਾਓ\x02" +
- "ਕੀ ਤੁਸੀਂ ‘%[1]s‘ ਟਨਲ ਨੂੰ ਹਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?\x02ਟਨਲ ਹਟਾਉਣ ਲਈ ਅਸਮਰੱਥ\x02" +
- "ਸੰਰਚਨਾ ਫ਼ਾਇਲਾਂ (*.zip, *.conf)|*.zip;*.conf|ਸਾਰੀਆਂ ਫ਼ਾਇਲਾਂ (*.*)|*.*" +
- "\x02ਫ਼ਾਇਲ ਤੋਂ ਟਨਲਾਂ ਦਰਾਮਦ ਕਰੋ\x02ਸੰਰਚਨਾ ਜ਼ਿੱਪ ਫਾਇਲਾਂ (*.zip)|*.zip\x02ਹੁਣ" +
- "ੇ ਅੱਪਡੇਟ ਕਰੋ\x02ਸਥਿਤੀ: ਪੂਰਾ!\x02ਟਨਲ(&T)"
+ "\u00a0MiB\x02%.2[1]f\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02ਐਂਡ" +
+ "ਪੁਆਇੰਟ ਤੋਂ ਪੋਰਟ ਗੁੰਮ ਹੈ\x02ਗ਼ੈਰ-ਵਾਜਬ MTU\x02ਗ਼ੈਰ-ਵਾਜਬ ਪੋਰਟ\x02ਗ਼ੈਰ-ਵਾਜ" +
+ "ਬ persistent keepalive\x02ਗ਼ੈਰ-ਵਾਜਬ ਕੁੰਜੀ: %[1]v\x02ਕੁੰਜੀਆਂ ਠੀਕ 32 ਬਾਈ" +
+ "ਟ ਲਈ ਡੀਕੋਡ ਹੋਣੀਆਂ ਚਾਹੀਦੀਆਂ ਹਨ\x02ਇੱਕ ਕਤਾਰ ਵਿੱਚ ਦੋ ਕੌਮੇ ਹਨ\x02ਟਨਲ ਦਾ ਨਾ" +
+ "ਂ ਠੀਕ ਨਹੀਂ ਹੈ\x02ਭਾਗ ਵਿੱਚ ਲਾਈਨ ਹੋਣੀ ਚਾਹੀਦੀ ਹੈ\x02, \x02, \x02ਵਾਇਰਗਾਰਡ " +
+ "ਬਾਰੇ\x02ਬੰਦ ਕਰੋ\x02♥ ਦਾਨ ਦਿਓ(&D)!\x02ਸਥਿਤੀ:\x02ਨਾ-ਸਰਗਰਮ ਕਰੋ(&D)\x02ਸਰਗ" +
+ "ਰਮ ਕਰੋ(&A)\x02ਪਬਲਿਕ ਕੁੰਜੀ:\x02ਸੁਣਨ ਵਾਲੀ ਪੋਰਟ:\x02MTU:\x02ਸਿਰਨਾਵੇ:\x02D" +
+ "NS ਸਰਵਰ:\x02ਸਕ੍ਰਿਪਟਾਂ:\x02ਪਹਿਲਾਂ-ਸਾਂਝੀ ਕੀਤੀ ਕੁੰਜੀ:\x02ਮਨਜ਼ੂਰ ਕੀਤੇ IP:\x02" +
+ "ਐਂਡ-ਪੁਆਇੰਟ:\x02ਸਥਿਰ ਲਗਾਤਾਰ ਜਾਰੀ ਰੱਖੋ:\x02ਆਖਰੀ ਹੈਂਡ-ਸ਼ੇਕ:\x02ਟਰਾਂਸਫਰ:" +
+ "\x02ਅਸਮਰੱਥ ਹੈ, ਹਰ ਪਾਲਸੀ\x02ਸਮਰੱਥ ਹੈ\x02%[1]s ਮਿਲੇ, %[2]s ਭੇਜੇ\x02ਟਨਲ ਸਥਿ" +
+ "ਤੀ ਪਤਾ ਲਗਾਉਣ ਲਈ ਅਸਫ਼ਲ\x02ਟਨਲ ਸਰਗਰਮ ਕਰਨ ਲਈ ਅਸਫ਼ਲ ਹੈ\x02ਟਨਲ ਨਾ-ਸਰਗਰਮ ਕਰਨ" +
+ " ਲਈ ਅਸਫ਼ਲ ਹੈ\x02ਇੰਟਰਫੇਸ: %[1]s\x02ਪੀਅਰ\x02ਨਵੀਂ ਟਨਲ ਬਣਾਓ\x02ਟਨਲ ਨੂੰ ਸੋਧੋ" +
+ "\x02ਨਾਂ(&N):\x02ਪਬਲਿਕ ਕੁੰਜੀ(&P):\x02(ਅਣਪਛਾਤਾ)\x02ਬਿਨਾਂ-ਟਨਲ ਵਾਲੇ ਟਰੈਫਿਕ ਉ" +
+ "ੱਤੇ ਪਾਬੰਦੀ ਲਾਓ (&B) (kill-switch)\x02ਸੰਭਾਲੋ(&S)\x02ਰੱਦ ਕਰੋ\x02ਸੰਰਚਨਾ(&" +
+ "C):\x02ਅਯੋਗ ਨਾਂ\x02ਨਾਂ ਚਾਹੀਦਾ ਹੈ।\x02ਟਨਲ ਪਹਿਲਾਂ ਹੀ ਮੌਜੂਦ ਹੈ\x02ਨਾਂ ‘%[1]" +
+ "s’ ਨਾਲ ਟਨਲ ਪਹਿਲਾਂ ਹੀ ਮੌਜੂਦ ਹੈ।\x02ਨਵੀਂ ਸੰਰਚਨਾ ਬਣਾਉਣ ਲਈ ਅਸਮਰੱਥ ਹੈ\x02ਫ਼ਾਇ" +
+ "ਲ ਬਣਾਉਣ ਲਈ ਅਸਫ਼ਲ ਹੈ\x02‘%[1]s’ ਫ਼ਾਇਲ ਪਹਿਲਾਂ ਹੀ ਮੌਜੂਦ ਹੈ।\x0a\x0aਕੀ ਤੁਸ" +
+ "ੀਂ ਇਸ ਉੱਤੇ ਲਿਖਣਾ ਚਾਹੁੰਦੇ ਹੋ?\x02ਸਰਗਰਮ\x02ਸਰਗਰਮ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ\x02ਨਾ-ਸ" +
+ "ਰਗਰਮ\x02ਨਾ-ਸਰਗਰਮ ਕੀਤਾ ਜਾ ਰਿਹਾ ਹੈ\x02ਅਣਪਛਾਤੀ ਸਥਿਤੀ\x02ਲਾਗੂ\x02ਕਾਪੀ ਕਰੋ(" +
+ "&C)\x02ਸਾਰੇ ਚੁਣੋ(&a)\x02ਫ਼ਾਇਲ ਵਿੱਚ ਸੰਭਾਲੋ(&S)…\x02ਸਮਾਂ\x02ਲਾਗ ਸੁਨੇਹਾ\x02" +
+ "ਲਿਖਤ ਫ਼ਾਇਲਾਂ (*.txt)|*.txt|ਸਾਰੀਆਂ ਫ਼ਾਇਲਾਂ (*.*)|*.*\x02ਲਾਗ ਫ਼ਾਇਲ ਵਿੱਚ " +
+ "ਬਰਾਮਦ ਕਰੋ\x02ਵਾਇਰਗਾਰਡ ਬਾਰੇ(&A)…\x02ਟਨਲ ਗਲਤੀ\x02%[1]s\x0a\x0aPlease con" +
+ "sult the log for more information.\x02%[1]s (out of date)\x02WireGuard ਖ" +
+ "ੋਜ ਗ਼ਲਤੀ\x02ਵਾਇਰਗਾਰਡ: ਨਾ-ਸਰਗਰਮ ਕੀਤਾ\x02ਸਥਿਤੀ: ਅਣਪਛਾਤੀ\x02ਸਿਰਨਾਵੇਂ: ਕੋਈ" +
+ " ਨਹੀਂ\x02ਟਨਲਾਂ ਦਾ ਇੰਤਜ਼ਾਮ ਕਰੋ(&M)…\x02ਫ਼ਾਇਲ ਤੋਂ ਟਨਲਾਂ ਦਰਾਮਦ ਕਰੋ(&I)…\x02ਬ" +
+ "ਾਹਰ(&x)\x02ਟਨਲ(&T)\x02ਵਾਇਰਗਾਰਡ ਸਰਗਰਮ ਕੀਤਾ\x02%[1]s ਟਨਲ ਸਰਗਰਮ ਕੀਤੀ ਗਈ ਹ" +
+ "ੈ।\x02ਵਾਇਰਗਾਰਡ ਨਾ-ਸਰਗਰਮ ਕੀਤਾ\x02%[1]s ਟਨਲ ਨਾ-ਸਰਗਰਮ ਕੀਤੀ ਗਈ ਹੈ।\x02ਵਾਇਰ" +
+ "ਗਾਰਡ ਟਨਲ ਗਲਤੀ\x02ਵਾਇਰਗਾਰਡ: %[1]s\x02ਸਥਿਤੀ: %[1]s\x02ਸਿਰਨਾਵੇਂ: %[1]s" +
+ "\x02ਅੱਪਡੇਟ ਮੌਜੂਦ ਹੈ!\x02ਵਾਇਰਗਾਰਡ ਅੱਪਡੇਟ ਮੌਜੂਦ ਹੈ\x02ਵਾਇਰਗਾਰਡ ਲਈ ਅੱਪਡੇਟ ਹ" +
+ "ੁਣ ਮੌਜੂਦ ਹੈ। ਜਿੰਨਾ ਛੇਤੀ ਹੋ ਸਕੇ ਤੁਹਾਨੂੰ ਅੱਪਡੇਟ ਕਰਨ ਦੀ ਸਲਾਹ ਦਿੱਤੀ ਜਾਂਦੀ " +
+ "ਹੈ।\x02ਟਨਲਾਂ\x02ਸੋਧੋ(&E)\x02…ਖਾਲੀ ਟਨਲ ਜੋੜੋ(&e)\x02ਟਨਲ ਜੋੜੋ\x02ਚੁਣੀਆਂ ਟ" +
+ "ਨਲਾਂ ਨੂੰ ਹਟਾਓ\x02ਸਾਰੀਆਂ ਟਨਲਾਂ ਨੂੰ ਜ਼ਿੱਪ ਵਜੋਂ ਬਰਾਮਦ ਕਰੋ\x02ਪਲਟੋ(&T)\x02ਸ" +
+ "ਾਰੀਆਂ ਟਨਲਾਂ ਨੂੰ ਜ਼ਿੱਪ ਵਜੋਂ ਬਰਾਮਦ ਕਰੋ…\x02ਚੁਣੀ ਟਨਲ ਸੋਧੋ(&s)…\x02ਚੁਣੀਆਂ ਟ" +
+ "ਨਲਾਂ ਨੂੰ ਹਟਾਓ(&R)\x02ਕੋਈ ਸੰਰਚਨਾ ਫ਼ਾਇਲਾਂ ਨਹੀਂ ਲੱਭੀਆਂ\x02‘%[1]s’ ਨਾਂ ਨਾਲ" +
+ " ਹੋਰ ਟਨਲ ਪਹਿਲਾਂ ਹੀ ਮੌਜੂਦ ਹੈ\x02ਸੰਰਚਨਾ ਇੰਪੋਰਟ ਕਰਨ ਲਈ ਅਸਮਰੱਥ: %[1]v\x02ਇੰਪ" +
+ "ੋਰਟ ਕੀਤੀਆਂ ਟਨਲਾਂ\x14\x01\x81\x01\x00\x020\x02%[1]d ਟਨਲ ਇੰਪੋਰਟ ਕੀਤੀ\x00" +
+ "<\x02%[1]d ਟਨਲਾਂ ਇੰਪੋਰਟ ਕੀਤੀਆਂ\x02ਟਨਲ ਬਣਾਉਣ ਲਈ ਅਸਮਰੱਥ\x14\x01\x81\x01" +
+ "\x00\x02\x1d\x02%[1]d ਟਨਲ ਹਟਾਓ\x00#\x02%[1]d ਟਨਲਾਂ ਹਟਾਓ\x14\x01\x81\x01" +
+ "\x00\x02b\x02ਕੀ ਤੁਸੀਂ %[1]d ਟਨਲ ਨੂੰ ਹਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?\x00h\x02ਕੀ ਤੁਸੀਂ " +
+ "%[1]d ਟਨਲਾਂ ਨੂੰ ਹਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?\x02‘%[1]s’ ਟਨਲ ਨੂੰ ਹਟਾਓ\x02ਕੀ ਤੁਸੀਂ ‘" +
+ "%[1]s‘ ਟਨਲ ਨੂੰ ਹਟਾਉਣਾ ਚਾਹੁੰਦੇ ਹੋ?\x02%[1]s ਤੁਸੀਂ ਇਹ ਕਾਰਵਾਈ ਵਾਪਸ ਨਹੀਂ ਲੈ " +
+ "ਸਕਦੇ ਹੋ।\x02ਟਨਲ ਹਟਾਉਣ ਲਈ ਅਸਮਰੱਥ\x02ਟਨਲ ਹਟਾਉਣ ਲਈ ਅਸਮਰੱਥ ਹੈ: %[1]s\x02ਟਨ" +
+ "ਲਾਂ ਹਟਾਉਣ ਲਈ ਅਸਮਰੱਥ\x02ਸੰਰਚਨਾ ਫ਼ਾਇਲਾਂ (*.zip, *.conf)|*.zip;*.conf|ਸਾਰ" +
+ "ੀਆਂ ਫ਼ਾਇਲਾਂ (*.*)|*.*\x02ਫ਼ਾਇਲ ਤੋਂ ਟਨਲਾਂ ਦਰਾਮਦ ਕਰੋ\x02ਸੰਰਚਨਾ ਜ਼ਿੱਪ ਫਾਇਲ" +
+ "ਾਂ (*.zip)|*.zip\x02WireGuard ਤੋਂ ਬਾਹਰ ਜਾਣ ਲਈ ਗ਼ਲਤੀ\x02ਸੇਵਾ ਤੋਂ ਬਾਹਰ ਜ" +
+ "ਾਣ ਲਈ ਅਸਮਰੱਥ, ਕਾਰਨ: %[1]v। ਤੁਸੀਂ ਸੇਵਾ ਮੈਨੇਜਰ ਤੋਂ WireGuard ਨੂੰ ਰੋਕਣਾ ਚ" +
+ "ਾਹੋਗੇ।\x02WireGuard ਲਈ ਅੱਪਡੇਟ ਮੌਜੂਦ ਹੈ। ਤੁਹਾਨੂੰ ਬਿਨਾਂ ਦੇਰ ਕੀਤਿਆਂ ਅੱਪਡੇ" +
+ "ਟ ਕਰਨ ਦੀ ਸਲਾਹ ਦਿੱਤੀ ਜਾਂਦੀ ਹੈ।\x02ਹਾਲਤ: ਵਰਤੋਂਕਾਰ ਲਈ ਉਡੀਕ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ" +
+ "\x02ਹੁਣੇ ਅੱਪਡੇਟ ਕਰੋ\x02ਹਾਲਤ: ਅੱਪਡੇਟਰ ਸੇਵਾ ਦੀ ਉਡੀਕ ਕੀਤੀ ਜਾ ਰਹੀ ਹੈ\x02ਗ਼ਲਤ" +
+ "ੀ: %[1]v। ਫੇਰ ਕੋਸ਼ਿਸ਼ ਕਰੋ।\x02ਸਥਿਤੀ: ਪੂਰਾ!"
-var plIndex = []uint32{ // 181 elements
+var plIndex = []uint32{ // 180 elements
// Entry 0 - 1F
- 0x00000000, 0x00000007, 0x0000004f, 0x00000066,
- 0x0000007d, 0x000000cb, 0x00000106, 0x0000013d,
- 0x000001a6, 0x00000226, 0x00000271, 0x00000277,
- 0x0000029a, 0x000002d1, 0x00000309, 0x0000034d,
+ 0x00000000, 0x00000007, 0x0000004f, 0x00000067,
+ 0x0000007e, 0x000000cc, 0x00000108, 0x0000013f,
+ 0x000001a8, 0x00000228, 0x00000273, 0x00000279,
+ 0x0000029c, 0x000002d2, 0x0000030a, 0x0000034d,
0x0000038c, 0x000003cf, 0x000003da, 0x000003e3,
0x000003f0, 0x000003fd, 0x0000040a, 0x00000417,
- 0x00000424, 0x0000043c, 0x00000465, 0x00000487,
- 0x000004b2, 0x000004d6, 0x000004e9, 0x000004fd,
+ 0x00000424, 0x00000446, 0x00000471, 0x00000495,
+ 0x000004a8, 0x000004bc, 0x000004ec, 0x00000508,
// Entry 20 - 3F
- 0x0000052d, 0x00000549, 0x00000584, 0x000005be,
- 0x000005d5, 0x000005f6, 0x00000617, 0x00000653,
- 0x0000066e, 0x0000069a, 0x000006c1, 0x000006e5,
- 0x000006f6, 0x00000727, 0x0000074e, 0x00000778,
- 0x00000796, 0x000007bb, 0x000007be, 0x000007c1,
- 0x000007d8, 0x000007e7, 0x00000870, 0x00000878,
- 0x00000886, 0x0000088e, 0x0000089a, 0x000008a3,
- 0x000008b4, 0x000008c4, 0x000008c9, 0x000008d1,
+ 0x00000543, 0x0000055a, 0x0000057b, 0x0000059c,
+ 0x000005d8, 0x000005f3, 0x0000061f, 0x00000646,
+ 0x0000066a, 0x0000067b, 0x000006ac, 0x000006af,
+ 0x000006b2, 0x000006c9, 0x000006d8, 0x000006e0,
+ 0x000006ee, 0x000006f6, 0x00000702, 0x0000070b,
+ 0x0000071c, 0x0000072c, 0x00000731, 0x00000739,
+ 0x00000746, 0x0000074f, 0x00000754, 0x00000769,
+ 0x0000077f, 0x00000798, 0x000007bc, 0x000007c6,
// Entry 40 - 5F
- 0x000008de, 0x000008e7, 0x000008ec, 0x00000901,
- 0x00000917, 0x00000930, 0x00000954, 0x0000095e,
- 0x0000097f, 0x0000098a, 0x000009a9, 0x000009d1,
- 0x000009f3, 0x00000a13, 0x00000a24, 0x00000a29,
- 0x00000a3c, 0x00000a49, 0x00000a51, 0x00000a63,
- 0x00000a6e, 0x00000aa4, 0x00000bf7, 0x00000bff,
- 0x00000c06, 0x00000c15, 0x00000c2a, 0x00000c3f,
- 0x00000c6a, 0x00000c96, 0x00000caa, 0x00000ce3,
+ 0x000007d9, 0x000007e8, 0x000007fc, 0x0000080c,
+ 0x0000082d, 0x00000838, 0x00000857, 0x0000087f,
+ 0x000008a1, 0x000008c1, 0x000008d2, 0x000008d7,
+ 0x000008ea, 0x000008f7, 0x000008ff, 0x00000911,
+ 0x0000091c, 0x00000952, 0x0000095a, 0x00000961,
+ 0x00000970, 0x00000985, 0x0000099a, 0x000009c5,
+ 0x000009f1, 0x00000a05, 0x00000a3e, 0x00000a66,
+ 0x00000a85, 0x00000abe, 0x00000ac6, 0x00000ad2,
// Entry 60 - 7F
- 0x00000d0b, 0x00000d2a, 0x00000d63, 0x00000d6b,
- 0x00000d77, 0x00000d82, 0x00000d91, 0x00000d9f,
- 0x00000da8, 0x00000db0, 0x00000dc2, 0x00000dd6,
- 0x00000ddb, 0x00000df1, 0x00000e28, 0x00000e44,
- 0x00000e5f, 0x00000e6d, 0x00000ead, 0x00000ec1,
- 0x00000edb, 0x00000f19, 0x00000f32, 0x00000f43,
- 0x00000f50, 0x00000f68, 0x00000f8c, 0x00000f96,
- 0x00000fa8, 0x00000fc8, 0x00000fe0, 0x00001003,
+ 0x00000add, 0x00000aec, 0x00000afa, 0x00000b03,
+ 0x00000b0b, 0x00000b1d, 0x00000b31, 0x00000b36,
+ 0x00000b4c, 0x00000b83, 0x00000b9f, 0x00000bba,
+ 0x00000bc8, 0x00000c0d, 0x00000c21, 0x00000c3b,
+ 0x00000c79, 0x00000c92, 0x00000ca3, 0x00000cb0,
+ 0x00000cc8, 0x00000ce6, 0x00000cf0, 0x00000cf8,
+ 0x00000d0a, 0x00000d2a, 0x00000d42, 0x00000d65,
+ 0x00000d7d, 0x00000d8e, 0x00000d9c, 0x00000daa,
// Entry 80 - 9F
- 0x0000101b, 0x0000102c, 0x0000103a, 0x00001048,
- 0x00001065, 0x0000108b, 0x000010e2, 0x000010e9,
- 0x000010f1, 0x00001107, 0x00001113, 0x00001130,
- 0x0000115b, 0x00001167, 0x00001196, 0x000011af,
- 0x000011cd, 0x000011eb, 0x00001221, 0x00001251,
- 0x00001289, 0x000012b6, 0x000012cb, 0x00001343,
- 0x000013da, 0x000013f6, 0x0000144e, 0x00001506,
- 0x0000151e, 0x0000154e, 0x00001573, 0x0000158e,
+ 0x00000dc7, 0x00000ded, 0x00000e44, 0x00000e4b,
+ 0x00000e53, 0x00000e69, 0x00000e75, 0x00000e90,
+ 0x00000ebb, 0x00000ec7, 0x00000ef6, 0x00000f0f,
+ 0x00000f2b, 0x00000f49, 0x00000f7f, 0x00000faf,
+ 0x00000fe7, 0x00001014, 0x00001029, 0x000010a1,
+ 0x00001139, 0x00001155, 0x000011ad, 0x00001265,
+ 0x0000127d, 0x000012ad, 0x000012d2, 0x000012ed,
+ 0x00001317, 0x00001332, 0x000013dd, 0x00001427,
// Entry A0 - BF
- 0x000015b8, 0x000015d3, 0x0000167e, 0x000016c8,
- 0x000016e8, 0x0000170d, 0x0000172e, 0x0000175d,
- 0x00001780, 0x0000180a, 0x0000185c, 0x0000187b,
- 0x0000188c, 0x000018b4, 0x000018d6, 0x000018ea,
- 0x000018fd, 0x0000190c, 0x00001920, 0x00001930,
- 0x00001938,
-} // Size: 748 bytes
+ 0x00001441, 0x00001466, 0x00001487, 0x000014b6,
+ 0x000014d9, 0x00001564, 0x000015b6, 0x000015d5,
+ 0x000015e6, 0x0000160e, 0x00001630, 0x00001644,
+ 0x00001644, 0x00001644, 0x00001644, 0x00001644,
+ 0x00001644, 0x00001644, 0x00001644, 0x00001644,
+} // Size: 744 bytes
-const plData string = "" + // Size: 6456 bytes
+const plData string = "" + // Size: 5700 bytes
"\x02Błąd\x02(brak argumentu): Podnieś uprawnienia i zainstaluj usługę me" +
- "nedżera\x02Użycie: %[1]s [%[2]s]\x02Opcje wiersza poleceń\x02Nie można o" +
- "kreślić, czy proces jest uruchomiony w środowisku WOW64: %[1]v\x02Musisz" +
- " użyć natywnej wersji WireGuard na tym komputerze.\x02Nie można otworzyć" +
- " bieżącego tokenu procesu: %[1]v\x02WireGuard może być używany tylko prz" +
- "ez użytkowników, którzy są członkami wbudowanej grupy %[1]s.\x02WireGuar" +
- "d jest uruchomiony, ale interfejs jest dostępny tylko z poziomu użytkown" +
- "ików należących do wbudowanej grupy %[1]s.\x02Ikona WireGuard nie pojawi" +
- "ła się po 30 sekundach w zasobniku systemowym.\x02Teraz\x02Zegar system" +
- "owy został cofnięty!\x14\x01\x81\x01\x00\x04\x0b\x02%[1]d lata\x05\x0a" +
- "\x02%[1]d lat\x02\x0a\x02%[1]d rok\x00\x0b\x02%[1]d lata\x14\x01\x81\x01" +
- "\x00\x04\x0a\x02%[1]d dni\x05\x0a\x02%[1]d dni\x02\x0d\x02%[1]d dzień" +
- "\x00\x0a\x02%[1]d dni\x14\x01\x81\x01\x00\x04\x0e\x02%[1]d godziny\x05" +
- "\x0d\x02%[1]d godzin\x02\x0e\x02%[1]d godzina\x00\x0e\x02%[1]d godziny" +
+ "nedżera\x02Użycie: %[1]s [\x0a%[2]s]\x02Opcje wiersza poleceń\x02Nie moż" +
+ "na określić, czy proces jest uruchomiony w środowisku WOW64: %[1]v\x02Na" +
+ "leży użyć natywnej wersji WireGuard na tym komputerze.\x02Nie można otwo" +
+ "rzyć bieżącego tokenu procesu: %[1]v\x02WireGuard może być używany tylko" +
+ " przez użytkowników, którzy są członkami wbudowanej grupy %[1]s.\x02Wire" +
+ "Guard jest uruchomiony, ale interfejs jest dostępny tylko z poziomu użyt" +
+ "kowników należących do wbudowanej grupy %[1]s.\x02Ikona WireGuard nie po" +
+ "jawiła się po 30 sekundach w zasobniku systemowym.\x02Teraz\x02Zegar sys" +
+ "temowy został cofnięty!\x14\x01\x81\x01\x00\x04\x0b\x02%[1]d lata\x05" +
+ "\x0a\x02%[1]d lat\x02\x0a\x02%[1]d rok\x00\x0a\x02%[1]d lat\x14\x01\x81" +
+ "\x01\x00\x04\x0a\x02%[1]d dni\x05\x0a\x02%[1]d dni\x02\x0d\x02%[1]d dzie" +
+ "ń\x00\x0a\x02%[1]d dni\x14\x01\x81\x01\x00\x04\x0e\x02%[1]d godziny\x05" +
+ "\x0d\x02%[1]d godzin\x02\x0e\x02%[1]d godzina\x00\x0d\x02%[1]d godzin" +
"\x14\x01\x81\x01\x00\x04\x0d\x02%[1]d minuty\x05\x0c\x02%[1]d minut\x02" +
"\x0d\x02%[1]d minuta\x00\x0c\x02%[1]d minut\x14\x01\x81\x01\x00\x04\x0e" +
"\x02%[1]d sekundy\x05\x0d\x02%[1]d sekund\x02\x0e\x02%[1]d sekunda\x00" +
"\x0d\x02%[1]d sekund\x02%[1]s temu\x02%[1]d\u00a0B\x02%.2[1]f\u00a0KiB" +
"\x02%.2[1]f\u00a0MiB\x02%.2[1]f\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %" +
- "[2]q\x02Nieprawidłowy adres IP\x02Nieprawidłowa długość prefiksu sieci" +
- "\x02Brak portu urządzenia końcowego\x02Nieprawidłowy host (urządzenie ko" +
- "ńcowe)\x02Nawiasy muszą zawierać adres IPv6\x02Nieprawidłowe MTU\x02Nie" +
- "prawidłowy port\x02Nieprawidłowy parametr utrzymania połączenia\x02Niepr" +
- "awidłowy klucz: %[1]v\x02Klucze muszą zostać zdekodowane do dokładnie 32" +
- " bajtów\x02Liczba musi zawierać się w przedziale 0 - 2^64-1: %[1]v\x02Dw" +
- "a przecinki z rzędu\x02Nazwa tunelu jest nieprawidłowa\x02Linia musi wys" +
- "tępować w sekcji\x02Klucz konfiguracyjny nie zawiera separatora równorzę" +
- "dnego\x02Klucz musi mieć wartość\x02Nieprawidłowy klucz dla sekcji [Inte" +
- "rface]\x02Nieprawidłowy klucz dla sekcji [Peer]\x02Interfejs musi mieć k" +
- "lucz prywatny\x02[nie określono]\x02Wszyscy uczestnicy muszą mieć klucze" +
- " publiczne\x02Błąd podczas pobierania konfiguracji\x02Nieprawidłowy kluc" +
- "z dla sekcji interface\x02Wersja protokołu musi być 1\x02Nieprawidłowy k" +
- "lucz dla sekcji peer\x02, \x02, \x02Informacje o WireGuard\x02Logo WireG" +
- "uard\x02Wersja aplikacji: %[1]s\x0aWersja implementacji w jęz. Go: %[2]s" +
- "\x0aWersja jęz. Go: %[3]s-%[4]s\x0aSystem operacyjny: %[5]s\x0aArchitekt" +
- "ura: %[6]s\x02Zamknij\x02♥ &Wpłać!\x02Status:\x02&Dezaktywuj\x02&Aktywuj" +
- "\x02Klucz publiczny:\x02Port nasłuchu:\x02MTU:\x02Adresy:\x02Serwery DNS" +
- ":\x02Skrypty:\x02PSK:\x02Dozwolone adresy IP:\x02Urządzenie końcowe:\x02" +
- "Utrzymanie połączenia:\x02Ostatni uścisk dłoni (handshake):\x02Transfer:" +
- "\x02wyłączone, według zasad grupy\x02włączyć\x02%[1]s odebrano, %[2]s wy" +
- "słano\x02Nie udało się określić stanu tunelu\x02Nie udało się aktywować " +
- "tunelu\x02Nie można dezaktywować tunelu\x02Interfejs: %[1]s\x02Peer\x02U" +
- "twórz nowy tunel\x02Edytuj tunel\x02&Nazwa:\x02&Klucz publiczny:\x02(nie" +
- "znany)\x02Zablokuj niezabezpieczony ruch (wyłącznik awaryjny)\x02Jeżeli " +
- "konfiguracja ma dokładnie jednego peer'a i ma w liście dozwolonych IP pr" +
- "zynajmniej jeden adres 0.0.0.0/0 lub ::/0, wtedy usługa tunelowania dołą" +
- "cza do zapory sieciowej zestaw zasad, żeby zablokować ruch, który nie je" +
- "st z interfejsu sieciowego lub jest skierowany do złego serwera DNS, z w" +
- "yjątkiem dla serwera DHCP i NDP.\x02&Zapisz\x02Anuluj\x02&Konfiguracja:" +
- "\x02Nieprawidłowa nazwa\x02Nazwa jest wymagana.\x02Nazwa tunelu ‘%[1]s’ " +
- "jest niepoprawna.\x02Nie można wylistować istniejących tuneli\x02Tunel j" +
- "uż istnieje\x02Inny tunel już istnieje z tą samą nazwą ‘%[1]s’.\x02Nie m" +
- "ożna utworzyć nowej konfiguracji\x02Zapis pliku się nie powiódł\x02Plik " +
- "‘%[1]s’ już istnieje. Czy chcesz go nadpisać?\x02Aktywny\x02Aktywowani" +
- "e\x02Nieaktywny\x02Dezaktywowanie\x02Stan nieznany\x02Dziennik\x02&Kopiu" +
- "j\x02Wybierz &wszystko\x02&Zapisz do pliku…\x02Czas\x02Wiadomości dzienn" +
- "ika\x02Pliki tekstowe (*.txt)|*.txt|Wszystkie pliki (*.*)|*.*\x02Eksport" +
- "uj dziennik do pliku\x02&Informacje o WireGuard…\x02Błąd tunelu\x02%[1]s" +
- "\x0a\x0aAby uzyskać więcej informacji, zapoznaj się z logiem.\x02%[1]s (" +
- "nieaktualny)\x02Błąd detekcji WireGuard\x02Nie można poczekać na pojawie" +
- "nie się okna WireGuard: %[1]v\x02WireGuard: Dezaktywowany\x02Status: Nie" +
- "znany\x02Adresy: Brak\x02&Zarządzaj tunelami…\x02&Importuj tunel (tunele" +
- ") z pliku…\x02W&yjście\x02WireGuard Aktywny\x02Tunel %[1]s został aktywo" +
- "wany.\x02WireGuard Dezaktywowany\x02Tunel %[1]s został dezaktywowany." +
- "\x02Błąd tunelu WireGuard\x02WireGuard: %[1]s\x02Status: %[1]s\x02Adresy" +
- ": %[1]s\x02Dostępna nowa aktualizacja!\x02Aktualizacja WireGuard jest do" +
- "stępna\x02Aktualizacja WireGuard jest już dostępna. Zaleca się jak najsz" +
- "ybszą aktualizację.\x02Tunele\x02&Edytuj\x02Dodaj &pusty tunel…\x02Dodaj" +
- " Tunel\x02Usuń wybrany tunel (tunele)\x02Eksportuj wszystkie tunele do a" +
- "rchiwum ZIP\x02&Przełącz\x02Eksportuj wszystkie tunele do archiwum &zip…" +
- "\x02Edytuj &wybrany tunel…\x02&Usuń wybrany tunel (tunele)\x02brak plikó" +
- "w konfiguracyjnych\x02Nie można zaimportować wybranej konfiguracji: %[1]" +
- "v\x02Nie można wskazać istniejących tuneli: %[1]v\x02Inny tunel już istn" +
- "ieje z tą samą nazwą ‘%[1]s’\x02Nie można zaimportować konfiguracji: %[1" +
- "]v\x02Zaimportowane tunele\x14\x01\x81\x01\x00\x04\x1b\x02Zaimportowano " +
- "%[1]d tunele\x05\x1b\x02Zaimportowano %[1]d tuneli\x02\x1a\x02Zaimportow" +
- "ano %[1]d tunel\x00\x1b\x02Zaimportowano %[1]d tuneli\x14\x02\x80\x01" +
- "\x04#\x02Zaimportowano %[1]d z %[2]d tunele\x05#\x02Zaimportowano %[1]d " +
- "z %[2]d tuneli\x02\x22\x02Zaimportowano %[1]d z %[2]d tunel\x00#\x02Zaim" +
- "portowano %[1]d z %[2]d tuneli\x02Nie można utworzyć tunelu\x14\x01\x81" +
- "\x01\x00\x04\x13\x02Usuń %[1]d tunele\x05\x13\x02Usuń %[1]d tuneli\x02" +
- "\x12\x02Usuń %[1]d tunel\x00\x13\x02Usuń %[1]d tuneli\x14\x01\x81\x01" +
- "\x00\x04+\x02Czy na pewno chcesz usunąć %[1]d tunele?\x05+\x02Czy na pew" +
- "no chcesz usunąć %[1]d tuneli?\x02*\x02Czy na pewno chcesz usunąć %[1]d " +
- "tunel?\x00+\x02Czy na pewno chcesz usunąć %[1]d tuneli?\x02Usuń tunel ‘%" +
- "[1]s’\x02Czy na pewno chcesz usunąć tunel ‘%[1]s’?\x02%[1]s Tej akcji ni" +
- "e można cofnąć.\x02Nie można usunąć tunelu\x02Tunel nie mógł zostać usun" +
- "ięty: %[1]s\x02Nie można usunąć tuneli\x14\x01\x81\x01\x00\x04'\x02%[1]d" +
- " tunele nie mogą być usunięte.\x05'\x02%[1]d tunele nie mogą być usunięt" +
- "e.\x02)\x02%[1]d tunel nie może zostać usunięty.\x00'\x02%[1]d tunele ni" +
- "e mogą być usunięte.\x02Pliki konfiguracji (*.zip, *.conf)|*.zip;*.conf|" +
- "Wszystkie pliki (*.*)|*.*\x02Importuj tunel (tunele) z pliku\x02Pliki ZI" +
- "P konfiguracji (*.zip)|*.zip\x02Eksportuj tunele do archiwum ZIP\x02%[1]" +
- "s (wersja niepodpisana, brak aktualizacji)\x02Błąd podczas zamykania Wir" +
- "eGuard\x02Nie można wyłączyć usługi ze względu na: %[1]v. Jeśli chcesz w" +
- "yłączyć WireGuard możesz to zrobić z poziomu menedżera usług.\x02Aktuali" +
- "zacja WireGuard jest dostępna. Zaleca się natychmiastową aktualizację." +
- "\x02Status: Czekam na użytkownika\x02Uaktualnij teraz\x02Status: Czekam " +
- "na usługę aktualizacji\x02Błąd: %[1]v. Spróbuj ponownie.\x02Status: Ukoń" +
- "czone!\x02przed włączeniem\x02po włączeniu\x02przed wyłączeniem\x02po wy" +
- "łączeniu\x02&Tunele"
+ "[2]q\x02Brak portu urządzenia końcowego\x02Nieprawidłowy host (urządzeni" +
+ "e końcowe)\x02Nawiasy muszą zawierać adres IPv6\x02Nieprawidłowe MTU\x02" +
+ "Nieprawidłowy port\x02Nieprawidłowy parametr utrzymania połączenia\x02Ni" +
+ "eprawidłowy klucz: %[1]v\x02Klucze muszą zostać zdekodowane do dokładnie" +
+ " 32 bajtów\x02Dwa przecinki z rzędu\x02Nazwa tunelu jest nieprawidłowa" +
+ "\x02Linia musi występować w sekcji\x02Klucz konfiguracyjny nie zawiera s" +
+ "eparatora równorzędnego\x02Klucz musi mieć wartość\x02Nieprawidłowy kluc" +
+ "z dla sekcji [Interface]\x02Nieprawidłowy klucz dla sekcji [Peer]\x02Int" +
+ "erfejs musi mieć klucz prywatny\x02[nie określono]\x02Wszyscy uczestnicy" +
+ " muszą mieć klucze publiczne\x02, \x02, \x02Informacje o WireGuard\x02Lo" +
+ "go WireGuard\x02Zamknij\x02♥ &Wpłać!\x02Status:\x02&Dezaktywuj\x02&Aktyw" +
+ "uj\x02Klucz publiczny:\x02Port nasłuchu:\x02MTU:\x02Adresy:\x02Serwery D" +
+ "NS:\x02Skrypty:\x02PSK:\x02Dozwolone adresy IP:\x02Urządzenie końcowe:" +
+ "\x02Utrzymanie połączenia:\x02Ostatni uścisk dłoni (handshake):\x02Trans" +
+ "fer:\x02przed włączeniem\x02po włączeniu\x02przed wyłączeniem\x02po wyłą" +
+ "czeniu\x02wyłączone, według zasad grupy\x02włączone\x02%[1]s odebrano, %" +
+ "[2]s wysłano\x02Nie udało się określić stanu tunelu\x02Nie udało się akt" +
+ "ywować tunelu\x02Nie można dezaktywować tunelu\x02Interfejs: %[1]s\x02Pe" +
+ "er\x02Utwórz nowy tunel\x02Edytuj tunel\x02&Nazwa:\x02&Klucz publiczny:" +
+ "\x02(nieznany)\x02Zablokuj niezabezpieczony ruch (wyłącznik awaryjny)" +
+ "\x02&Zapisz\x02Anuluj\x02&Konfiguracja:\x02Nieprawidłowa nazwa\x02Nazwa " +
+ "jest wymagana.\x02Nazwa tunelu ‘%[1]s’ jest niepoprawna.\x02Nie można wy" +
+ "listować istniejących tuneli\x02Tunel już istnieje\x02Inny tunel już ist" +
+ "nieje z tą samą nazwą ‘%[1]s’.\x02Nie można utworzyć nowej konfiguracji" +
+ "\x02Zapis pliku się nie powiódł\x02Plik ‘%[1]s’ już istnieje. Czy chcesz" +
+ " go nadpisać?\x02Aktywny\x02Aktywowanie\x02Nieaktywny\x02Dezaktywowanie" +
+ "\x02Stan nieznany\x02Dziennik\x02&Kopiuj\x02Wybierz &wszystko\x02&Zapisz" +
+ " do pliku…\x02Czas\x02Wiadomości dziennika\x02Pliki tekstowe (*.txt)|*.t" +
+ "xt|Wszystkie pliki (*.*)|*.*\x02Eksportuj dziennik do pliku\x02&Informac" +
+ "je o WireGuard…\x02Błąd tunelu\x02%[1]s\x0a\x0aAby uzyskać więcej inform" +
+ "acji, zapoznaj się z dziennikiem.\x02%[1]s (nieaktualny)\x02Błąd detekcj" +
+ "i WireGuard\x02Nie można poczekać na pojawienie się okna WireGuard: %[1]" +
+ "v\x02WireGuard: Dezaktywowany\x02Status: Nieznany\x02Adresy: Brak\x02&Za" +
+ "rządzaj tunelami…\x02&Importuj tunel(e) z pliku…\x02W&yjście\x02&Tunele" +
+ "\x02WireGuard Aktywny\x02Tunel %[1]s został aktywowany.\x02WireGuard dez" +
+ "aktywowany\x02Tunel %[1]s został dezaktywowany.\x02Błąd tunelu WireGuard" +
+ "\x02WireGuard: %[1]s\x02Status: %[1]s\x02Adresy: %[1]s\x02Dostępna nowa " +
+ "aktualizacja!\x02Aktualizacja WireGuard jest dostępna\x02Aktualizacja Wi" +
+ "reGuard jest już dostępna. Zaleca się jak najszybszą aktualizację.\x02Tu" +
+ "nele\x02&Edytuj\x02Dodaj &pusty tunel…\x02Dodaj tunel\x02Usuń wybrany(-e" +
+ ") tunel(e)\x02Eksportuj wszystkie tunele do archiwum ZIP\x02&Przełącz" +
+ "\x02Eksportuj wszystkie tunele do archiwum &zip…\x02Edytuj &wybrany tune" +
+ "l…\x02&Usuń wybrany(-e) tunel(e)\x02brak plików konfiguracyjnych\x02Nie " +
+ "można zaimportować wybranej konfiguracji: %[1]v\x02Nie można wskazać ist" +
+ "niejących tuneli: %[1]v\x02Inny tunel już istnieje z tą samą nazwą ‘%[1]" +
+ "s’\x02Nie można zaimportować konfiguracji: %[1]v\x02Zaimportowane tunele" +
+ "\x14\x01\x81\x01\x00\x04\x1b\x02Zaimportowano %[1]d tunele\x05\x1b\x02Za" +
+ "importowano %[1]d tuneli\x02\x1a\x02Zaimportowano %[1]d tunel\x00\x1b" +
+ "\x02Zaimportowano %[1]d tuneli\x14\x02\x80\x01\x04#\x02Zaimportowano %[1" +
+ "]d z %[2]d tunele\x05#\x02Zaimportowano %[1]d z %[2]d tuneli\x02#\x02Zai" +
+ "mportowano %[1]d z %[2]d tunelu\x00#\x02Zaimportowano %[1]d z %[2]d tune" +
+ "li\x02Nie można utworzyć tunelu\x14\x01\x81\x01\x00\x04\x13\x02Usuń %[1]" +
+ "d tunele\x05\x13\x02Usuń %[1]d tuneli\x02\x12\x02Usuń %[1]d tunel\x00" +
+ "\x13\x02Usuń %[1]d tuneli\x14\x01\x81\x01\x00\x04+\x02Czy na pewno chces" +
+ "z usunąć %[1]d tunele?\x05+\x02Czy na pewno chcesz usunąć %[1]d tuneli?" +
+ "\x02*\x02Czy na pewno chcesz usunąć %[1]d tunel?\x00+\x02Czy na pewno ch" +
+ "cesz usunąć %[1]d tuneli?\x02Usuń tunel ‘%[1]s’\x02Czy na pewno chcesz u" +
+ "sunąć tunel ‘%[1]s’?\x02%[1]s Tej akcji nie można cofnąć.\x02Nie można u" +
+ "sunąć tunelu\x02Tunel nie mógł zostać usunięty: %[1]s\x02Nie można usuną" +
+ "ć tuneli\x14\x01\x81\x01\x00\x04'\x02%[1]d tunele nie mogą być usunięte" +
+ ".\x05'\x02%[1]d tunele nie mogą być usunięte.\x02)\x02%[1]d tunel nie mo" +
+ "że zostać usunięty.\x00'\x02%[1]d tunele nie mogą być usunięte.\x02Plik" +
+ "i konfiguracji (*.zip, *.conf)|*.zip;*.conf|Wszystkie pliki (*.*)|*.*" +
+ "\x02Importuj tunel(e) z pliku\x02Pliki ZIP konfiguracji (*.zip)|*.zip" +
+ "\x02Eksportuj tunele do archiwum ZIP\x02%[1]s (wersja niepodpisana, brak" +
+ " aktualizacji)\x02Błąd podczas zamykania WireGuard\x02Nie można wyłączyć" +
+ " usługi ze względu na: %[1]v. Jeśli chcesz wyłączyć WireGuard, możesz to" +
+ " zrobić z poziomu menedżera usług.\x02Aktualizacja WireGuard jest dostęp" +
+ "na. Zaleca się natychmiastową aktualizację.\x02Status: Czekam na użytkow" +
+ "nika\x02Uaktualnij teraz\x02Status: Czekam na usługę aktualizacji\x02Błą" +
+ "d: %[1]v. Spróbuj ponownie.\x02Status: Ukończone!"
-var roIndex = []uint32{ // 181 elements
+var pt_BRIndex = []uint32{ // 180 elements
+ // Entry 0 - 1F
+ 0x00000000, 0x00000005, 0x0000003f, 0x00000053,
+ 0x00000070, 0x000000c2, 0x00000102, 0x0000013c,
+ 0x00000196, 0x0000020b, 0x00000256, 0x0000025c,
+ 0x00000278, 0x00000296, 0x000002b4, 0x000002d4,
+ 0x000002f8, 0x0000031e, 0x0000032b, 0x00000333,
+ 0x0000033f, 0x0000034b, 0x00000357, 0x00000363,
+ 0x00000370, 0x0000038a, 0x000003a9, 0x000003d5,
+ 0x000003e3, 0x000003f3, 0x00000413, 0x0000042a,
+ // Entry 20 - 3F
+ 0x0000045c, 0x00000474, 0x00000493, 0x000004b7,
+ 0x000004f1, 0x0000050b, 0x00000536, 0x0000055c,
+ 0x00000585, 0x0000059b, 0x000005c5, 0x000005c8,
+ 0x000005cb, 0x000005dd, 0x000005fa, 0x00000601,
+ 0x0000060c, 0x00000614, 0x0000061f, 0x00000627,
+ 0x00000639, 0x0000064a, 0x0000064f, 0x0000065b,
+ 0x0000066b, 0x00000674, 0x00000687, 0x00000697,
+ 0x000006a4, 0x000006ba, 0x000006ce, 0x000006da,
+ // Entry 40 - 5F
+ 0x000006e4, 0x000006eb, 0x000006f6, 0x00000701,
+ 0x0000071b, 0x00000726, 0x00000744, 0x0000076b,
+ 0x00000784, 0x0000079f, 0x000007b0, 0x000007ba,
+ 0x000007c7, 0x000007d5, 0x000007dc, 0x000007ef,
+ 0x000007fe, 0x0000082f, 0x00000837, 0x00000840,
+ 0x00000851, 0x00000860, 0x00000878, 0x000008a1,
+ 0x000008ce, 0x000008e1, 0x00000911, 0x0000093e,
+ 0x00000958, 0x00000997, 0x0000099d, 0x000009a4,
+ // Entry 60 - 7F
+ 0x000009ac, 0x000009b8, 0x000009d0, 0x000009d9,
+ 0x000009e1, 0x000009f2, 0x00000a08, 0x00000a0e,
+ 0x00000a24, 0x00000a60, 0x00000a78, 0x00000a8e,
+ 0x00000a9d, 0x00000add, 0x00000af3, 0x00000b13,
+ 0x00000b54, 0x00000b6a, 0x00000b7e, 0x00000b91,
+ 0x00000ba7, 0x00000bc9, 0x00000bcf, 0x00000bd8,
+ 0x00000bea, 0x00000c06, 0x00000c1c, 0x00000c3b,
+ 0x00000c54, 0x00000c65, 0x00000c73, 0x00000c85,
+ // Entry 80 - 9F
+ 0x00000caa, 0x00000cd1, 0x00000d3e, 0x00000d46,
+ 0x00000d4e, 0x00000d69, 0x00000d7d, 0x00000d9a,
+ 0x00000dbd, 0x00000dca, 0x00000df1, 0x00000e0f,
+ 0x00000e2d, 0x00000e5d, 0x00000e9d, 0x00000ed3,
+ 0x00000f02, 0x00000f36, 0x00000f49, 0x00000f82,
+ 0x00000fd0, 0x00000ff6, 0x0000102a, 0x00001099,
+ 0x000010b2, 0x000010e7, 0x00001113, 0x00001137,
+ 0x00001163, 0x00001186, 0x000011e1, 0x00001235,
+ // Entry A0 - BF
+ 0x00001254, 0x00001281, 0x0000129b, 0x000012cd,
+ 0x000012e7, 0x0000135c, 0x000013c3, 0x000013e1,
+ 0x000013f1, 0x0000141e, 0x00001447, 0x00001465,
+ 0x00001465, 0x00001465, 0x00001465, 0x00001465,
+ 0x00001465, 0x00001465, 0x00001465, 0x00001465,
+} // Size: 744 bytes
+
+const pt_BRData string = "" + // Size: 5221 bytes
+ "\x02Erro\x02(sem argumento): elevar e instalar o serviço gerenciador\x02" +
+ "Uso: %[1]s [\x0a%[2]s]\x02Opções de linha de comando\x02Não foi possível" +
+ " determinar se o processo está sendo executado em WOW64: %[1]v\x02Você d" +
+ "eve usar a versão nativa do WireGuard neste computador.\x02Não foi possí" +
+ "vel abrir o token do processo atual: %[1]v\x02O WireGuard só pode ser us" +
+ "ado por usuários que são membros do grupo incorporado %[1]s.\x02O WireGu" +
+ "ard está funcionando, mas a interface do usuário só é acessível em deskt" +
+ "ops do grupo incorporado %[1]s.\x02O ícone do sistema da barra do WireGu" +
+ "ard não apareceu após 30 segundos.\x02Agora\x02Relógio do sistema voltou" +
+ "!\x14\x01\x81\x01\x00\x02\x0a\x02%[1]d ano\x00\x0b\x02%[1]d anos\x14\x01" +
+ "\x81\x01\x00\x02\x0a\x02%[1]d dia\x00\x0b\x02%[1]d dias\x14\x01\x81\x01" +
+ "\x00\x02\x0b\x02%[1]d hora\x00\x0c\x02%[1]d horas\x14\x01\x81\x01\x00" +
+ "\x02\x0d\x02%[1]d minuto\x00\x0e\x02%[1]d minutes\x14\x01\x81\x01\x00" +
+ "\x02\x0e\x02%[1]d segundo\x00\x0f\x02%[1]d segundos\x02%[1]s atrás\x02%[" +
+ "1]d B\x02%.2[1]f KiB\x02%.2[1]f MiB\x02%.2[1]f GiB\x02%.2[1]f TiB\x02%[1" +
+ "]s: %[2]q\x02Porta ausente do endpoint\x02Servidor de endpoint inválido" +
+ "\x02Os colchetes devem conter um endereço IPv6\x02MTU inválido\x02Porta " +
+ "inválida\x02Keepalive persistente inválido\x02Chave inválida: %[1]v\x02C" +
+ "haves devem decodificar exatamente para 32 bytes\x02Duas vírgulas seguid" +
+ "as\x02Nome do túnel não é válido\x02A linha deve ocorrer em uma seção" +
+ "\x02Chave de configuração está faltando um separador igual\x02Chaves dev" +
+ "em ter um valor\x02Chave inválida para a seção [Interface]\x02Chave invá" +
+ "lida para a seção [Peer]\x02Uma interface deve ter uma chave privada\x02" +
+ "[nenhum especificado]\x02Todos os pares devem ter chaves públicas\x02, " +
+ "\x02, \x02Sobre o WireGuard\x02Imagem do logotipo WireGuard\x02Fechar" +
+ "\x02♥ &Doar!\x02Status:\x02Desativado\x02&Ativar\x02Chaves públicas:\x02" +
+ "Porta de escuta:\x02MTU:\x02Endereços:\x02Servidores DNS:\x02Scripts:" +
+ "\x02Tecla Pressionada:\x02IPs Permitidos:\x02Ponto Final:\x02Mensagem pe" +
+ "rsistente:\x02Shake mais recente:\x02Transferir:\x02pré-cima\x02postar" +
+ "\x02pré-baixo\x02pós-baixo\x02desativada, por política\x02habilitado\x02" +
+ "%[1]s recebido, %[2]s enviado\x02Falha ao determinar o estado do túnel" +
+ "\x02Falha ao ativar o túnel\x02Falha ao desativar o tunel\x02Interface: " +
+ "%[1]s\x02Parceiros\x02Criar túnel\x02Editar túnel\x02&Nome:\x02&Chaves p" +
+ "úblicas:\x02(desconhecido)\x02&Bloquear tráfego sem tunelamento (kill-s" +
+ "witch)\x02&Salvar\x02Cancelar\x02&Configuração:\x02Nome inválido\x02Um n" +
+ "ome é necessário.\x02O nome do túnel ‘%[1]s' é inválido.\x02Não foi poss" +
+ "ível listar túneis existentes\x02Arquivo já existe\x02Já existe outro t" +
+ "únel com o nome ‘%[1]s’.\x02Não é possível adicionar a configuração\x02" +
+ "Falha ao escrever arquivo\x02O arquivo '%[1]s' já existe.\x0a\x0aVocê de" +
+ "seja sobrescrever isso?\x02Ativo\x02Ativar\x02Inativo\x02Desativando\x02" +
+ "Situação desconhecida\x02Registro\x02&Copiar\x02Selecionar &Tudo\x02&Sal" +
+ "var em arquivo…\x02Tempo\x02Registro de mensagens\x02Arquivos de texto (" +
+ "*.txt)|*.txt|Todos os arquivos (*.*)|*.*\x02Exportar arquivo de log\x02&" +
+ "Sobre o WireGuard…\x02Erro de túnel\x02%[1]s\x0a\x0aPor favor, consulte " +
+ "o log para obter mais informações.\x02%[1]s (desatualizado)\x02Erro de D" +
+ "etecção do WireGuard\x02Não foi possível esperar a janela do WireGuard a" +
+ "parecer: %[1]v\x02WireGuard: Desativado\x02Status desconhecido\x02Endere" +
+ "ços: Nenhum\x02&Gerenciar túneis…\x02&Importar túnel(s) do arquivo…\x02" +
+ "Sai&r\x02&Túneis\x02WireGuard ativado\x02O túnel %[1]s foi ativado.\x02W" +
+ "ireGuard: Desativado\x02O túnel %[1]s foi desativado.\x02Erro no Túnel W" +
+ "ireGuard\x02WireGuard: %[1]s\x02Status: %[1]s\x02Endereços: %[1]s\x02Uma" +
+ " atualização está disponível!\x02Atualização do WireGuard disponível\x02" +
+ "Uma atualização para o WireGuard está agora disponível. Recomenda-se atu" +
+ "alizar o mais rápido possível.\x02Túneis\x02&Editar\x02Adicionar &túnel " +
+ "vazio…\x02Adicionar um túnel\x02Remover túneis selecionados\x02Exportar " +
+ "todos os túneis para zip\x02&Alternancia\x02Exportar todos os túneis par" +
+ "a &zip…\x02Editar &túnel selecionado…\x02&Remover túneis selecionados" +
+ "\x02nenhum arquivo de configuração foi encontrado\x02Não foi possível im" +
+ "portar a configuração selecionada: %[1]v\x02Não foi possível enumerar tú" +
+ "neis existentes: %[1]v\x02Já existe outro túnel com o nome ‘%[1]s’\x02Nã" +
+ "o foi possível importar a configuração: %[1]v\x02Importados túneis\x14" +
+ "\x01\x81\x01\x00\x02\x17\x02Túnel %[1]d importado\x00\x19\x02%[1]d túnei" +
+ "s importados\x14\x02\x80\x01\x02#\x02Importados %[1]d dos %[2]d túneis" +
+ "\x00#\x02Importados %[1]d dos %[2]d túneis\x02Não foi possível criar o t" +
+ "únel: %s\x14\x01\x81\x01\x00\x02\x15\x02Excluir túnel %[1]d\x00\x16\x02" +
+ "Excluir %[1]d túneis\x14\x01\x81\x01\x00\x02/\x02Tem certeza que deseja " +
+ "excluir o túnel %[1]d?\x007\x02Você tem certeza que deseja excluir os tú" +
+ "neis %[1]d?\x02Excluir túnel ‘%[1]s'\x02Tem certeza de que deseja exclui" +
+ "r o túnel ‘%[1]s?\x02%[1]s Você não pode desfazer essa ação.\x02Não foi " +
+ "possível excluir o túnel\x02Não foi possível remover um túnel: %[1]s\x02" +
+ "Não foi possível excluir túneis\x14\x01\x81\x01\x00\x02(\x02O túnel %[1]" +
+ "d não pôde ser removido.\x00*\x02%[1]d túneis não puderam ser removidos." +
+ "\x02Arquivos de configuração (*.zip, *.conf)|*.zip;*.conf|Todos os arqui" +
+ "vos (*.*)|*.*\x02Importar túnel(es) do arquivo\x02Arquivos ZIP de config" +
+ "uração (*.zip)|*.zip\x02Exportar túneis para zip\x02%[1]s (versão não as" +
+ "sinada, sem atualizações)\x02Erro ao sair do WireGuard\x02Não é possível" +
+ " sair do serviço devido a: %[1]v. Você pode querer parar o WireGuard do " +
+ "gerenciador de serviços.\x02Uma atualização para o WireGuard está dispon" +
+ "ível. É altamente aconselhável atualizar sem demora.\x02Status: Aguarda" +
+ "ndo o usuário\x02Atualizar agora\x02Estado: Aguardando o serviço do atua" +
+ "lizador\x02Erro: %[1]v. Por favor, tente novamente.\x02Status da tarefa:" +
+ " Concluída!"
+
+var roIndex = []uint32{ // 180 elements
// Entry 0 - 1F
0x00000000, 0x00000007, 0x0000005d, 0x00000077,
0x00000092, 0x000000d1, 0x0000011a, 0x0000014e,
@@ -1529,54 +2470,53 @@ var roIndex = []uint32{ // 181 elements
0x000002a4, 0x000002cf, 0x000002fc, 0x00000329,
0x0000035d, 0x00000396, 0x000003a1, 0x000003aa,
0x000003b7, 0x000003c4, 0x000003d1, 0x000003de,
- 0x000003eb, 0x00000400, 0x0000042d, 0x00000452,
- 0x00000475, 0x000004a6, 0x000004b4, 0x000004c1,
+ 0x000003eb, 0x00000410, 0x00000433, 0x00000464,
+ 0x00000472, 0x0000047f, 0x000004a2, 0x000004b9,
// Entry 20 - 3F
- 0x000004e4, 0x000004fb, 0x00000540, 0x0000057c,
- 0x0000059e, 0x000005bd, 0x000005e8, 0x0000062f,
- 0x00000655, 0x00000683, 0x000006ac, 0x000006dd,
- 0x000006f4, 0x00000723, 0x00000747, 0x00000775,
- 0x0000079d, 0x000007c8, 0x000007cb, 0x000007ce,
- 0x000007df, 0x000007f8, 0x0000087c, 0x00000887,
- 0x00000896, 0x0000089d, 0x000008aa, 0x000008b4,
- 0x000008c4, 0x000008d7, 0x000008dc, 0x000008e4,
+ 0x000004fe, 0x00000520, 0x0000053f, 0x0000056a,
+ 0x000005b1, 0x000005d7, 0x00000605, 0x0000062e,
+ 0x0000065f, 0x00000676, 0x000006a5, 0x000006a8,
+ 0x000006ab, 0x000006bc, 0x000006d5, 0x000006e0,
+ 0x000006ef, 0x000006f6, 0x00000703, 0x0000070d,
+ 0x0000071d, 0x00000730, 0x00000735, 0x0000073d,
+ 0x0000074a, 0x00000755, 0x0000076c, 0x0000077c,
+ 0x00000789, 0x000007a5, 0x000007c2, 0x000007cf,
// Entry 40 - 5F
- 0x000008f1, 0x000008fc, 0x00000913, 0x00000923,
- 0x00000930, 0x0000094c, 0x00000969, 0x00000976,
- 0x00000994, 0x0000099e, 0x000009b9, 0x000009e5,
- 0x00000a03, 0x00000a24, 0x00000a37, 0x00000a3f,
- 0x00000a50, 0x00000a5e, 0x00000a65, 0x00000a76,
- 0x00000a85, 0x00000ad2, 0x00000c6e, 0x00000c77,
- 0x00000c7f, 0x00000c8f, 0x00000c9c, 0x00000cb2,
- 0x00000cdd, 0x00000d04, 0x00000d19, 0x00000d4a,
+ 0x000007db, 0x000007e8, 0x000007f3, 0x000007ff,
+ 0x0000081d, 0x00000827, 0x00000842, 0x0000086e,
+ 0x0000088c, 0x000008ad, 0x000008c0, 0x000008c8,
+ 0x000008d9, 0x000008e7, 0x000008ee, 0x000008ff,
+ 0x0000090e, 0x0000095b, 0x00000964, 0x0000096c,
+ 0x0000097c, 0x00000989, 0x0000099f, 0x000009ca,
+ 0x000009f1, 0x00000a06, 0x00000a37, 0x00000a5c,
+ 0x00000a7a, 0x00000ac0, 0x00000ac6, 0x00000ad4,
// Entry 60 - 7F
- 0x00000d6f, 0x00000d8d, 0x00000dd3, 0x00000dd9,
- 0x00000de7, 0x00000def, 0x00000e00, 0x00000e13,
- 0x00000e1a, 0x00000e23, 0x00000e36, 0x00000e4e,
- 0x00000e53, 0x00000e63, 0x00000e9a, 0x00000eb7,
- 0x00000ecc, 0x00000edc, 0x00000f14, 0x00000f29,
- 0x00000f47, 0x00000f85, 0x00000f9b, 0x00000faf,
- 0x00000fbf, 0x00000fd7, 0x00000ffc, 0x00001005,
- 0x00001017, 0x00001035, 0x0000104a, 0x0000106b,
+ 0x00000adc, 0x00000aed, 0x00000b00, 0x00000b07,
+ 0x00000b10, 0x00000b23, 0x00000b3b, 0x00000b40,
+ 0x00000b50, 0x00000b87, 0x00000ba4, 0x00000bb9,
+ 0x00000bc9, 0x00000c01, 0x00000c16, 0x00000c34,
+ 0x00000c72, 0x00000c88, 0x00000c9c, 0x00000cac,
+ 0x00000cc4, 0x00000ce9, 0x00000cf2, 0x00000cfc,
+ 0x00000d0e, 0x00000d2c, 0x00000d41, 0x00000d62,
+ 0x00000d7c, 0x00000d8d, 0x00000d9a, 0x00000da8,
// Entry 80 - 9F
- 0x00001085, 0x00001096, 0x000010a3, 0x000010b1,
- 0x000010d2, 0x000010fc, 0x00001172, 0x0000117b,
- 0x00001184, 0x0000119c, 0x000011ac, 0x000011cd,
- 0x000011ef, 0x000011f9, 0x0000121f, 0x0000123a,
- 0x0000125c, 0x00001287, 0x000012c0, 0x000012f5,
- 0x00001325, 0x00001351, 0x00001364, 0x000013b7,
- 0x00001427, 0x00001441, 0x00001497, 0x00001541,
- 0x0000155d, 0x00001597, 0x000015c5, 0x000015e0,
+ 0x00000dc9, 0x00000df3, 0x00000e69, 0x00000e72,
+ 0x00000e7b, 0x00000e93, 0x00000ea3, 0x00000ec4,
+ 0x00000ee6, 0x00000ef0, 0x00000f16, 0x00000f31,
+ 0x00000f53, 0x00000f7e, 0x00000fb7, 0x00000fec,
+ 0x0000101c, 0x00001048, 0x0000105b, 0x000010ae,
+ 0x0000111e, 0x00001138, 0x0000118e, 0x00001238,
+ 0x00001254, 0x0000128e, 0x000012bc, 0x000012d7,
+ 0x000012fe, 0x0000131b, 0x0000139f, 0x000013ef,
// Entry A0 - BF
- 0x00001607, 0x00001624, 0x000016a8, 0x000016f8,
- 0x00001719, 0x00001743, 0x0000175e, 0x0000178f,
- 0x000017b0, 0x00001811, 0x0000186e, 0x00001890,
- 0x000018a3, 0x000018d1, 0x000018f4, 0x00001908,
- 0x00001914, 0x00001921, 0x0000192c, 0x00001938,
- 0x00001942,
-} // Size: 748 bytes
+ 0x00001410, 0x0000143a, 0x00001455, 0x00001486,
+ 0x000014a7, 0x00001508, 0x00001565, 0x00001587,
+ 0x0000159a, 0x000015c8, 0x000015eb, 0x000015ff,
+ 0x000015ff, 0x000015ff, 0x000015ff, 0x000015ff,
+ 0x000015ff, 0x000015ff, 0x000015ff, 0x000015ff,
+} // Size: 744 bytes
-const roData string = "" + // Size: 6466 bytes
+const roData string = "" + // Size: 5631 bytes
"\x02Eroare\x02(fără argument): obținere drept administrativ și instalare" +
" serviciu de gestionare\x02Utilizare: %[1]s [\x0a%[2]s]\x02Opțiuni linie" +
" de comandă\x02Nu se poate determina dacă procesul rulează sub WOW64: %[" +
@@ -1594,348 +2534,505 @@ const roData string = "" + // Size: 6466 bytes
"\x02\x0c\x02%[1]d minut\x00\x10\x02%[1]d de minute\x14\x01\x81\x01\x00" +
"\x04\x0e\x02%[1]d secunde\x02\x0f\x02%[1]d secundă\x00\x11\x02%[1]d de s" +
"ecunde\x02acum %[1]s\x02%[1]d\u00a0B\x02%.2[1]f\u00a0KiB\x02%.2[1]f" +
- "\u00a0MiB\x02%.2[1]f\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02Adr" +
- "esă IP invalidă\x02Lungimea prefixului de rețea este invalidă\x02Lipseșt" +
- "e portul de la punctul final\x02Gazdă invalidă a punctului final\x02Para" +
- "ntezele trebuie să conțină o adresă IPv6\x02MTU invalidă\x02Port invalid" +
- "\x02Mesaj keepalive persistent invalid\x02Cheie invalidă: %[1]v\x02Rezul" +
- "tatul decodificat de chei trebuie să aibă exact 32 de octeți\x02Numărul " +
- "trebuie să fie cuprins între 0 și 2^64-1: %[1]v\x02Două virgule una după" +
- " cealaltă\x02Numele tunelului nu este valid\x02Linia trebuie să apară în" +
- "tr-o secțiune\x02Cheii de configurare îi lipsește un separator de forma " +
- "semnului egal\x02Cheia trebuie să conțină o valoare\x02Cheie invalidă pe" +
- "ntru secțiunea [Interface]\x02Cheie invalidă pentru secțiunea [Peer]\x02" +
- "O interfață trebuie să aibă o cheie privată\x02[niciuna specificată]\x02" +
- "Toate perechile trebuie să aibă chei publice\x02Eroare la obținerea conf" +
- "igurației\x02Cheie invalidă pentru secțiunea interfeței\x02Versiunea de " +
- "protocol trebuie să fie 1\x02Cheie invalidă pentru secțiunea perechii" +
- "\x02, \x02, \x02Despre WireGuard\x02Imagine siglă WireGuard\x02Versiunea" +
- " aplicației: %[1]s\x0aVersiunea bibliotecii Go: %[2]s\x0aVersiunea Go: %" +
- "[3]s-%[4]s\x0aSistem de operare: %[5]s\x0aArhitectură: %[6]s\x02Închider" +
- "e\x02♥ &Donează!\x02Stare:\x02&Dezactivare\x02&Activare\x02Cheie publică" +
- ":\x02Port de ascultare:\x02MTU:\x02Adrese:\x02Servere DNS:\x02Scripturi:" +
- "\x02Cheie predistribuită:\x02IP-uri permise:\x02Punct final:\x02Mesaj ke" +
- "epalive persistent:\x02Ultimul acord de interogare:\x02Transferare:\x02d" +
- "ezactivat, conform politicii\x02activată\x02%[1]s primit, %[2]s trimis" +
- "\x02Nu a putut fi determinată starea tunelului\x02Tunelul nu a putut fi " +
- "activat\x02Tunelul nu a putut fi dezactivat\x02Interfață: %[1]s\x02Perec" +
- "he\x02Creare tunel nou\x02Editare tunel\x02&Nume:\x02Cheie &publică:\x02" +
- "(necunoscută)\x02&Blochează traficul care nu trece prin tunel (întrerupă" +
- "tor de activitate)\x02Când o configurație conține exact o pereche, iar a" +
- "cea pereche are IP-uri permise care conțin cel puțin o variantă dintre 0" +
- ".0.0.0/0 sau ::/0, atunci serviciul tunelului activează un set de reguli" +
- " al paravanului de protecție pentru a bloca întregul trafic care nu prov" +
- "ine de la interfața tunelului sau care este direcționat către serverul D" +
- "NS greșit, existând excepții speciale pentru DHCP și NDP.\x02&Salvare" +
- "\x02Anulare\x02&Configurație:\x02Nume invalid\x02Este necesar un nume." +
- "\x02Numele tunelului „%[1]s” este invalid.\x02Tunelurile existente nu po" +
- "t fi listate\x02Tunelul există deja\x02Există deja un alt tunel cu numel" +
- "e „%[1]s”.\x02Nu se poate crea configurația nouă\x02Scrierea fișierului " +
- "a eșuat\x02Fișierul „%[1]s” există deja.\x0a\x0aDorești suprascrierea ac" +
- "estuia?\x02Activ\x02Se activează\x02Inactiv\x02Se dezactivează\x02Stare " +
- "necunoscută\x02Jurnal\x02&Copiere\x02Selectare &totală\x02&Salvare în fi" +
- "șier…\x02Timp\x02Mesaj de jurnal\x02Fișiere text (*.txt)|*.txt|Toate fi" +
- "șierele (*.*)|*.*\x02Exportare jurnal în fișier\x02&Despre WireGuard…" +
- "\x02Eroare de tunel\x02%[1]s\x0a\x0aConsultă jurnalul pentru mai multe i" +
- "nformații.\x02%[1]s (neactualizat)\x02Eroare de detectare WireGuard\x02N" +
- "u se poate aștepta ca fereastra WireGuard să apară: %[1]v\x02WireGuard: " +
- "dezactivat\x02Stare: necunoscută\x02Adrese: niciuna\x02&Gestionare tunel" +
- "uri…\x02&Importare tunel(uri) din fișier…\x02Ie&șire\x02WireGuard activa" +
- "t\x02Tunelul %[1]s a fost activat.\x02WireGuard dezactivat\x02Tunelul %[" +
- "1]s a fost dezactivat.\x02Eroare de tunel WireGuard\x02WireGuard: %[1]s" +
- "\x02Stare: %[1]s\x02Adrese: %[1]s\x02Este disponibilă o actualizare!\x02" +
- "Actualizare disponibilă pentru WireGuard\x02O actualizare pentru WireGua" +
- "rd este acum disponibilă. Se recomandă efectuarea actualizării cât mai r" +
- "apid posibil.\x02Tuneluri\x02&Editare\x02Adăugare tunel &gol…\x02Adăugar" +
- "e tunel\x02Eliminare tunel(uri) selectat(e)\x02Exportă toate tunelurile " +
- "în zip\x02&Comutare\x02Exportă toate tunelurile în &zip…\x02Editare tun" +
- "el &selectat…\x02&Eliminare tunel(uri) selectat(e)\x02nu au fost găsite " +
- "fișiere de configurare\x02Configurația selectată nu a putut fi importată" +
- ": %[1]v\x02Tunelurile existente nu au putut fi enumerate: %[1]v\x02Exist" +
- "ă deja un alt tunel cu numele „%[1]s”\x02Configurația nu poate fi impor" +
- "tată: %[1]v\x02Tuneluri importate\x14\x01\x81\x01\x00\x04\x18\x02Importa" +
- "t %[1]d tuneluri\x02\x15\x02Importat %[1]d tunel\x00\x1b\x02Importat %[1" +
- "]d de tuneluri\x14\x02\x80\x01\x04\x22\x02Importat %[1]d din %[2]d tunel" +
- "uri\x02\x1f\x02Importat %[1]d din %[2]d tunel\x00%\x02Importat %[1]d din" +
- " %[2]d de tuneluri\x02Tunelul nu poate fi creat\x14\x01\x81\x01\x00\x04" +
- "\x19\x02Ștergere %[1]d tuneluri\x02\x16\x02Ștergere %[1]d tunel\x00\x1c" +
- "\x02Ștergere %[1]d de tuneluri\x14\x01\x81\x01\x00\x045\x02Ești sigur că" +
- " dorești să ștergi %[1]d tuneluri?\x022\x02Ești sigur că dorești să șter" +
- "gi %[1]d tunel?\x008\x02Ești sigur că dorești să ștergi %[1]d de tunelur" +
- "i?\x02Ștergere tunel „%[1]s”\x02Ești sigur că dorești să ștergi tunelul " +
- "„%[1]s”?\x02%[1]s Această acțiune nu poate fi anulată.\x02Tunelul nu p" +
- "oate fi șters\x02Un tunel nu a putut fi eliminat: %[1]s\x02Nu se pot ște" +
- "rge tunelurile\x14\x01\x81\x01\x00\x04)\x02%[1]d tuneluri nu au putut fi" +
- " eliminate.\x02$\x02%[1]d tunel nu a putut fi eliminat.\x00,\x02%[1]d de" +
- " tuneluri nu au putut fi eliminate.\x02Fișiere de configurare (*.zip, *." +
- "conf)|*.zip;*.conf|Toate fișierele (*.*)|*.*\x02Importare tunel(uri) din" +
- " fișier\x02Fișiere ZIP de configurare (*.zip)|*.zip\x02Exportare tunelur" +
- "i în zip\x02%[1]s (versiune nesemnată, fără actualizări)\x02Eroare la ie" +
- "șirea din WireGuard\x02Nu se poate ieși din serviciu din cauza: %[1]v. " +
- "Poți opri WireGuard din managerul de servicii.\x02Este disponibilă o act" +
- "ualizare pentru WireGuard. Se recomandă ferm actualizarea imediată.\x02S" +
- "tare: se așteaptă utilizatorul\x02Actualizează acum\x02Stare: se așteapt" +
- "ă serviciul de actualizare\x02Eroare: %[1]v. Încearcă din nou.\x02Stare" +
- ": finalizată!\x02pre-pornire\x02post-pornire\x02pre-oprire\x02post-oprir" +
- "e\x02&Tuneluri"
+ "\u00a0MiB\x02%.2[1]f\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02Lip" +
+ "sește portul de la punctul final\x02Gazdă invalidă a punctului final\x02" +
+ "Parantezele trebuie să conțină o adresă IPv6\x02MTU invalidă\x02Port inv" +
+ "alid\x02Mesaj keepalive persistent invalid\x02Cheie invalidă: %[1]v\x02R" +
+ "ezultatul decodificat de chei trebuie să aibă exact 32 de octeți\x02Două" +
+ " virgule una după cealaltă\x02Numele tunelului nu este valid\x02Linia tr" +
+ "ebuie să apară într-o secțiune\x02Cheii de configurare îi lipsește un se" +
+ "parator de forma semnului egal\x02Cheia trebuie să conțină o valoare\x02" +
+ "Cheie invalidă pentru secțiunea [Interface]\x02Cheie invalidă pentru sec" +
+ "țiunea [Peer]\x02O interfață trebuie să aibă o cheie privată\x02[niciun" +
+ "a specificată]\x02Toate perechile trebuie să aibă chei publice\x02, \x02" +
+ ", \x02Despre WireGuard\x02Imagine siglă WireGuard\x02Închidere\x02♥ &Don" +
+ "ează!\x02Stare:\x02&Dezactivare\x02&Activare\x02Cheie publică:\x02Port d" +
+ "e ascultare:\x02MTU:\x02Adrese:\x02Servere DNS:\x02Scripturi:\x02Cheie p" +
+ "redistribuită:\x02IP-uri permise:\x02Punct final:\x02Mesaj keepalive per" +
+ "sistent:\x02Ultimul acord de interogare:\x02Transferare:\x02pre-pornire" +
+ "\x02post-pornire\x02pre-oprire\x02post-oprire\x02dezactivat, conform pol" +
+ "iticii\x02activată\x02%[1]s primit, %[2]s trimis\x02Nu a putut fi determ" +
+ "inată starea tunelului\x02Tunelul nu a putut fi activat\x02Tunelul nu a " +
+ "putut fi dezactivat\x02Interfață: %[1]s\x02Pereche\x02Creare tunel nou" +
+ "\x02Editare tunel\x02&Nume:\x02Cheie &publică:\x02(necunoscută)\x02&Bloc" +
+ "hează traficul care nu trece prin tunel (întrerupător de activitate)\x02" +
+ "&Salvare\x02Anulare\x02&Configurație:\x02Nume invalid\x02Este necesar un" +
+ " nume.\x02Numele tunelului „%[1]s” este invalid.\x02Tunelurile existente" +
+ " nu pot fi listate\x02Tunelul există deja\x02Există deja un alt tunel cu" +
+ " numele „%[1]s”.\x02Nu se poate crea configurația nouă\x02Scrierea fișie" +
+ "rului a eșuat\x02Fișierul „%[1]s” există deja.\x0a\x0aDorești suprascrie" +
+ "rea acestuia?\x02Activ\x02Se activează\x02Inactiv\x02Se dezactivează\x02" +
+ "Stare necunoscută\x02Jurnal\x02&Copiere\x02Selectare &totală\x02&Salvare" +
+ " în fișier…\x02Timp\x02Mesaj de jurnal\x02Fișiere text (*.txt)|*.txt|Toa" +
+ "te fișierele (*.*)|*.*\x02Exportare jurnal în fișier\x02&Despre WireGuar" +
+ "d…\x02Eroare de tunel\x02%[1]s\x0a\x0aConsultă jurnalul pentru mai multe" +
+ " informații.\x02%[1]s (neactualizat)\x02Eroare de detectare WireGuard" +
+ "\x02Nu se poate aștepta ca fereastra WireGuard să apară: %[1]v\x02WireGu" +
+ "ard: dezactivat\x02Stare: necunoscută\x02Adrese: niciuna\x02&Gestionare " +
+ "tuneluri…\x02&Importare tunel(uri) din fișier…\x02Ie&șire\x02&Tuneluri" +
+ "\x02WireGuard activat\x02Tunelul %[1]s a fost activat.\x02WireGuard deza" +
+ "ctivat\x02Tunelul %[1]s a fost dezactivat.\x02Eroare de tunel WireGuard" +
+ "\x02WireGuard: %[1]s\x02Stare: %[1]s\x02Adrese: %[1]s\x02Este disponibil" +
+ "ă o actualizare!\x02Actualizare disponibilă pentru WireGuard\x02O actua" +
+ "lizare pentru WireGuard este acum disponibilă. Se recomandă efectuarea a" +
+ "ctualizării cât mai rapid posibil.\x02Tuneluri\x02&Editare\x02Adăugare t" +
+ "unel &gol…\x02Adăugare tunel\x02Eliminare tunel(uri) selectat(e)\x02Expo" +
+ "rtă toate tunelurile în zip\x02&Comutare\x02Exportă toate tunelurile în " +
+ "&zip…\x02Editare tunel &selectat…\x02&Eliminare tunel(uri) selectat(e)" +
+ "\x02nu au fost găsite fișiere de configurare\x02Configurația selectată n" +
+ "u a putut fi importată: %[1]v\x02Tunelurile existente nu au putut fi enu" +
+ "merate: %[1]v\x02Există deja un alt tunel cu numele „%[1]s”\x02Configura" +
+ "ția nu poate fi importată: %[1]v\x02Tuneluri importate\x14\x01\x81\x01" +
+ "\x00\x04\x18\x02Importat %[1]d tuneluri\x02\x15\x02Importat %[1]d tunel" +
+ "\x00\x1b\x02Importat %[1]d de tuneluri\x14\x02\x80\x01\x04\x22\x02Import" +
+ "at %[1]d din %[2]d tuneluri\x02\x1f\x02Importat %[1]d din %[2]d tunel" +
+ "\x00%\x02Importat %[1]d din %[2]d de tuneluri\x02Tunelul nu poate fi cre" +
+ "at\x14\x01\x81\x01\x00\x04\x19\x02Ștergere %[1]d tuneluri\x02\x16\x02Ște" +
+ "rgere %[1]d tunel\x00\x1c\x02Ștergere %[1]d de tuneluri\x14\x01\x81\x01" +
+ "\x00\x045\x02Ești sigur că dorești să ștergi %[1]d tuneluri?\x022\x02Eșt" +
+ "i sigur că dorești să ștergi %[1]d tunel?\x008\x02Ești sigur că dorești " +
+ "să ștergi %[1]d de tuneluri?\x02Ștergere tunel „%[1]s”\x02Ești sigur că " +
+ "dorești să ștergi tunelul „%[1]s”?\x02%[1]s Această acțiune nu poate fi " +
+ "anulată.\x02Tunelul nu poate fi șters\x02Un tunel nu a putut fi eliminat" +
+ ": %[1]s\x02Nu se pot șterge tunelurile\x14\x01\x81\x01\x00\x04)\x02%[1]d" +
+ " tuneluri nu au putut fi eliminate.\x02$\x02%[1]d tunel nu a putut fi el" +
+ "iminat.\x00,\x02%[1]d de tuneluri nu au putut fi eliminate.\x02Fișiere d" +
+ "e configurare (*.zip, *.conf)|*.zip;*.conf|Toate fișierele (*.*)|*.*\x02" +
+ "Importare tunel(uri) din fișier\x02Fișiere ZIP de configurare (*.zip)|*." +
+ "zip\x02Exportare tuneluri în zip\x02%[1]s (versiune nesemnată, fără actu" +
+ "alizări)\x02Eroare la ieșirea din WireGuard\x02Nu se poate ieși din serv" +
+ "iciu din cauza: %[1]v. Poți opri WireGuard din managerul de servicii." +
+ "\x02Este disponibilă o actualizare pentru WireGuard. Se recomandă ferm a" +
+ "ctualizarea imediată.\x02Stare: se așteaptă utilizatorul\x02Actualizează" +
+ " acum\x02Stare: se așteaptă serviciul de actualizare\x02Eroare: %[1]v. Î" +
+ "ncearcă din nou.\x02Stare: finalizată!"
-var ruIndex = []uint32{ // 181 elements
+var ruIndex = []uint32{ // 180 elements
// Entry 0 - 1F
- 0x00000000, 0x0000000d, 0x000000a9, 0x000000d4,
- 0x00000107, 0x00000166, 0x000001c9, 0x00000220,
- 0x000002a7, 0x0000034b, 0x000003b3, 0x000003c0,
- 0x000003fd, 0x0000042a, 0x00000457, 0x00000484,
- 0x000004c1, 0x000004fe, 0x0000050f, 0x00000518,
- 0x00000525, 0x00000532, 0x0000053f, 0x0000054c,
- 0x00000559, 0x00000580, 0x000005be, 0x000005fd,
- 0x0000062b, 0x00000663, 0x00000680, 0x000006a2,
+ 0x00000000, 0x0000000b, 0x000000a7, 0x000000c8,
+ 0x000000fd, 0x0000017a, 0x000001e8, 0x00000249,
+ 0x000002e7, 0x0000038b, 0x000003fc, 0x00000405,
+ 0x00000443, 0x00000486, 0x000004cd, 0x00000518,
+ 0x0000056d, 0x000005ca, 0x000005db, 0x000005e4,
+ 0x000005f3, 0x00000602, 0x00000611, 0x00000620,
+ 0x0000062d, 0x00000657, 0x00000685, 0x000006bd,
+ 0x000006da, 0x000006fc, 0x00000752, 0x0000077b,
// Entry 20 - 3F
- 0x000006f8, 0x00000721, 0x00000776, 0x000007b5,
- 0x000007d8, 0x00000817, 0x0000084a, 0x0000089f,
- 0x000008d1, 0x0000090b, 0x00000940, 0x0000098a,
- 0x000009a0, 0x000009e6, 0x00000a26, 0x00000a69,
- 0x00000aa1, 0x00000ae8, 0x00000aeb, 0x00000aee,
- 0x00000afb, 0x00000b14, 0x00000bcd, 0x00000bdc,
- 0x00000bfb, 0x00000c09, 0x00000c1d, 0x00000c33,
- 0x00000c50, 0x00000c5a, 0x00000c5f, 0x00000c70,
+ 0x000007cc, 0x000007ef, 0x0000081e, 0x00000851,
+ 0x000008a6, 0x000008d8, 0x00000912, 0x00000947,
+ 0x000009a0, 0x000009b4, 0x000009fa, 0x000009fd,
+ 0x00000a00, 0x00000a0d, 0x00000a26, 0x00000a35,
+ 0x00000a54, 0x00000a62, 0x00000a76, 0x00000a8c,
+ 0x00000aa9, 0x00000ab3, 0x00000ab8, 0x00000ac9,
+ 0x00000add, 0x00000aed, 0x00000b02, 0x00000b2a,
+ 0x00000b48, 0x00000b79, 0x00000ba4, 0x00000bb6,
// Entry 40 - 5F
- 0x00000c84, 0x00000c94, 0x00000ca9, 0x00000cd1,
- 0x00000cef, 0x00000d20, 0x00000d4b, 0x00000d5d,
- 0x00000d87, 0x00000d98, 0x00000dcb, 0x00000e16,
- 0x00000e4e, 0x00000e84, 0x00000e9e, 0x00000ea5,
- 0x00000ec3, 0x00000eed, 0x00000f00, 0x00000f1e,
- 0x00000f35, 0x00000f7d, 0x00001186, 0x0000119a,
- 0x000011a7, 0x000011c2, 0x000011ec, 0x00001213,
- 0x00001257, 0x0000128f, 0x000012ba, 0x00001302,
+ 0x00000bda, 0x00000bfc, 0x00000c1e, 0x00000c3e,
+ 0x00000c68, 0x00000c79, 0x00000cac, 0x00000cf7,
+ 0x00000d2f, 0x00000d65, 0x00000d7f, 0x00000d86,
+ 0x00000da4, 0x00000dce, 0x00000dd7, 0x00000df5,
+ 0x00000e0c, 0x00000e65, 0x00000e79, 0x00000e86,
+ 0x00000ea1, 0x00000ec1, 0x00000edc, 0x00000f16,
+ 0x00000f4e, 0x00000f79, 0x00000fc1, 0x00001008,
+ 0x00001035, 0x0000109b, 0x000010ae, 0x000010c5,
// Entry 60 - 7F
- 0x00001349, 0x0000136e, 0x000013d0, 0x000013e3,
- 0x000013fa, 0x0000140b, 0x00001420, 0x0000144a,
- 0x00001457, 0x0000146f, 0x00001486, 0x000014a9,
- 0x000014b4, 0x000014d6, 0x0000151e, 0x00001548,
- 0x00001559, 0x00001575, 0x000015f0, 0x00001607,
- 0x00001635, 0x00001689, 0x000016af, 0x000016d2,
- 0x000016e7, 0x00001713, 0x00001745, 0x00001751,
- 0x0000176a, 0x00001793, 0x000017ae, 0x000017d5,
+ 0x000010d6, 0x000010eb, 0x00001115, 0x00001122,
+ 0x00001138, 0x0000114f, 0x00001172, 0x0000117d,
+ 0x0000119f, 0x000011e7, 0x00001211, 0x00001222,
+ 0x0000123e, 0x000012b9, 0x000012d0, 0x000012fe,
+ 0x00001352, 0x00001378, 0x0000139b, 0x000013b0,
+ 0x000013dc, 0x0000140e, 0x0000141a, 0x0000142a,
+ 0x00001443, 0x0000146c, 0x00001487, 0x000014ae,
+ 0x000014d4, 0x000014e5, 0x000014f9, 0x0000150d,
// Entry 80 - 9F
- 0x000017fb, 0x0000180c, 0x00001820, 0x00001834,
- 0x0000185b, 0x0000188b, 0x00001916, 0x00001925,
- 0x00001941, 0x00001972, 0x00001992, 0x000019c3,
- 0x000019fe, 0x00001a16, 0x00001a55, 0x00001a96,
- 0x00001ac8, 0x00001b09, 0x00001b59, 0x00001bb3,
- 0x00001bfa, 0x00001c4a, 0x00001c78, 0x00001d4c,
- 0x00001e48, 0x00001e7a, 0x00001f1a, 0x00002062,
- 0x0000208c, 0x000020dc, 0x00002127, 0x00002159,
+ 0x00001534, 0x00001564, 0x000015ef, 0x000015fe,
+ 0x0000161a, 0x0000164b, 0x0000166b, 0x0000169c,
+ 0x000016d7, 0x000016ef, 0x0000172e, 0x0000176f,
+ 0x000017a1, 0x000017e2, 0x00001832, 0x0000188c,
+ 0x000018d3, 0x00001923, 0x00001951, 0x00001a20,
+ 0x00001b1e, 0x00001b50, 0x00001bf1, 0x00001d3a,
+ 0x00001d64, 0x00001db8, 0x00001e03, 0x00001e35,
+ 0x00001e6f, 0x00001ea1, 0x00001f96, 0x00001ff3,
// Entry A0 - BF
- 0x00002193, 0x000021c5, 0x000022bc, 0x00002319,
- 0x00002347, 0x0000237f, 0x000023b1, 0x000023fe,
- 0x00002427, 0x000024c1, 0x00002549, 0x00002581,
- 0x0000259f, 0x000025d3, 0x0000260c, 0x0000262e,
- 0x00002652, 0x00002674, 0x00002696, 0x000026b6,
- 0x000026c6,
-} // Size: 748 bytes
+ 0x00002021, 0x00002057, 0x00002089, 0x000020d6,
+ 0x00002109, 0x000021a9, 0x00002231, 0x00002269,
+ 0x00002287, 0x000022bb, 0x000022f4, 0x00002316,
+ 0x00002316, 0x00002316, 0x00002316, 0x00002316,
+ 0x00002316, 0x00002316, 0x00002316, 0x00002316,
+} // Size: 744 bytes
-const ruData string = "" + // Size: 9926 bytes
- "\x02Ошибка\x02(нет аргумента): получить права администратора и установит" +
- "ь административную службу\x02Использование: %[1]s [\x0a%[2]s]\x02Параме" +
- "тры командной строки\x02Ошибка определения или процесс работает как WOW" +
- "64: %[1]v\x02Используйте нативную версию WireGuard на этом компьютере." +
- "\x02Не удается открыть токен текущего процесса: %[1]v\x02WireGuard может" +
- " использоваться только пользователями, входящими в группу %[1]s.\x02Wire" +
- "Guard запущен, но пользовательский интерфейс доступен только с рабочих с" +
- "толов группы %[1]s.\x02Значок в системном трее WireGuard не появился по" +
- "сле 30 секунд.\x02Сейчас\x02Системные часы переведены назад!\x14\x01" +
- "\x81\x01\x00\x04\x08\x02%[1]dг\x05\x08\x02%[1]dг\x02\x08\x02%[1]dг\x00" +
- "\x08\x02%[1]dг\x14\x01\x81\x01\x00\x04\x08\x02%[1]dд\x05\x08\x02%[1]dд" +
- "\x02\x08\x02%[1]dд\x00\x08\x02%[1]dд\x14\x01\x81\x01\x00\x04\x08\x02%[1]" +
- "dч\x05\x08\x02%[1]dч\x02\x08\x02%[1]dч\x00\x08\x02%[1]dч\x14\x01\x81\x01" +
- "\x00\x04\x0c\x02%[1]dмин\x05\x0c\x02%[1]dмин\x02\x0c\x02%[1]dмин\x00\x0c" +
- "\x02%[1]dмин\x14\x01\x81\x01\x00\x04\x0c\x02%[1]dсек\x05\x0c\x02%[1]dсек" +
- "\x02\x0c\x02%[1]dсек\x00\x0c\x02%[1]dсек\x02%[1]s назад\x02%[1]d Б\x02%." +
- "2[1]f Кб\x02%.2[1]f Мб\x02%.2[1]f Гб\x02%.2[1]f Тб\x02%[1]s: %[2]q\x02Не" +
- "допустимый IP-адрес\x02Недопустимая длина префикса сети\x02Отсутствует " +
- "порт IP-адреса сервера\x02Неверный IP-адрес сервера\x02В скобках должен" +
- " быть IPv6 адрес\x02Недопустимый MTU\x02Недопустимый порт\x02Недопустимо" +
- "е значение поддержания соединения\x02Недопустимый ключ: %[1]v\x02Ключи " +
- "должны декодироваться ровно с 32 байтами\x02Число должно быть между 0 и" +
- " 2^64-1: %[1]v\x02Две запятые подряд\x02Название туннеля недействительно" +
- "\x02Строка должна быть в секции\x02В ключе конфигурации отсутствует разд" +
- "елитель\x02Ключ должен иметь значение\x02Неверный ключ для секции [Inte" +
- "rface]\x02Неверный ключ для секции [Peer]\x02В Интерфейсе должен быть пр" +
- "иватный ключ\x02[не указано]\x02Все пиры должны иметь публичные ключи" +
- "\x02Ошибка при получении конфигурации\x02Неверный ключ для секции Интерф" +
- "ейса\x02Версия протокола должна быть 1\x02Недействительный ключ для сек" +
- "ции пира\x02, \x02, \x02О WireGuard\x02Логотип WireGuard\x02Версия прил" +
- "ожения: %[1]s\x0aВерсия Go-бэкенда: %[2]s\x0aВерсия Go: %[3]s-%[4]s\x0a" +
- "Операционная система: %[5]s\x0aАрхитектура: %[6]s\x02Закрыть\x02♥ &Поже" +
- "ртвовать!\x02Статус:\x02&Отключить\x02&Подключить\x02Публичный ключ:" +
- "\x02Порт:\x02MTU:\x02IP-адреса:\x02DNS-серверы:\x02Скрипты:\x02Общий клю" +
- "ч:\x02Разрешенные IP-адреса:\x02IP-адрес сервера:\x02Поддерживание соед" +
- "инения:\x02Последнее рукопожатие:\x02Передача:\x02отключено, по политик" +
- "е\x02включено\x02Получено %[1]s, отправлено %[2]s\x02Не удалось определ" +
- "ить состояние туннеля\x02Не удалось подключить туннель\x02Не удалось от" +
- "ключить туннель\x02Интерфейс: %[1]s\x02Пир\x02Создать туннель\x02Редакт" +
- "ировать туннель\x02&Название:\x02&Публичный ключ:\x02(неизвестно)\x02&Б" +
- "локировать нетуннелированный трафик\x02Если конфигурация имеет ровно од" +
- "ин пир, а этот пир имеет разрешенные IP, содержащие хотя бы один из 0.0" +
- ".0.0/0 или ::/0, то туннельный сервис использует набор правил брандмауэр" +
- "а для блокирования всего трафика, который не проходит через туннель или" +
- " к неверным DNS-серверам, за исключением DHCP и NDP.\x02&Сохранить\x02От" +
- "мена\x02&Конфигурация:\x02Некорректное название\x02Необходимо название." +
- "\x02Название туннеля ‘%[1]s’ недопустимо.\x02Не удалось отобразить тунне" +
- "ли\x02Туннель уже существует\x02Туннель с именем ’%[1]s’ уже существует" +
- ".\x02Не удалось создать новую конфигурацию\x02Ошибка записи файла\x02Фай" +
- "л '%[1]s' уже существует!\x0a\x0aВы хотите перезаписать его?\x02Подключ" +
- "ен\x02Подключение\x02Отключен\x02Отключение\x02Неизвестное состояние" +
- "\x02Журнал\x02&Скопировать\x02Выбрать &все\x02&Сохранить в файл…\x02Врем" +
- "я\x02Сообщение журнала\x02Текстовые файлы (*.txt)|*.txt|Все файлы (*.*)" +
- "|*.*\x02Экспорт журнала в файл\x02&О WireGuard…\x02Ошибка туннеля\x02%[1" +
- "]s\x0a\x0aОбратитесь к журналу для получения дополнительной информации." +
+const ruData string = "" + // Size: 8982 bytes
+ "\x02Алдаа\x02(нет аргумента): получить права администратора и установить" +
+ " административную службу\x02Хэрэглээ: %[1]s [\x0a%[2]s]\x02Коммандын мөр" +
+ "ний сонголтууд\x02Процесс ажиллаж байгаа эсэхийг тодорхойлох боломжгүй " +
+ "байна\x0a WOW64: %[1]v\x02Та энэ компьютер дээр WireGuard-ийн эх хувилб" +
+ "арыг ашиглах ёстой.\x02Одоогийн процессын токеныг нээх боломжгүй байна:" +
+ " %[1]v\x02WireGuard может использоваться только пользователями, входящим" +
+ "и во встроенную группу %[1]s.\x02WireGuard запущен, но пользовательский" +
+ " интерфейс доступен только с рабочих столов группы %[1]s.\x02WireGuard с" +
+ "истемийн тавиурын дүрс 30 секундын дараа гарч ирсэнгүй.\x02Одоо\x02Сист" +
+ "емийн цаг хойшоо эргэж байна!\x14\x01\x81\x01\x00\x04\x0f\x02%[1]d года" +
+ "\x05\x0d\x02%[1]d лет\x02\x0d\x02%[1]d год\x00\x0d\x02%[1]d лет\x14\x01" +
+ "\x81\x01\x00\x04\x0d\x02%[1]d дня\x05\x0f\x02%[1]d дней\x02\x0f\x02%[1]d" +
+ " день\x00\x0f\x02%[1]d дней\x14\x01\x81\x01\x00\x04\x0f\x02%[1]d часа" +
+ "\x05\x11\x02%[1]d часов\x02\x0d\x02%[1]d час\x00\x11\x02%[1]d часов\x14" +
+ "\x01\x81\x01\x00\x04\x13\x02%[1]d минуты\x05\x11\x02%[1]d минут\x02\x13" +
+ "\x02%[1]d минута\x00\x11\x02%[1]d минут\x14\x01\x81\x01\x00\x04\x15\x02%" +
+ "[1]d секунды\x05\x13\x02%[1]d секунд\x02\x15\x02%[1]d секунда\x00\x13" +
+ "\x02%[1]d секунд\x02%[1]s назад\x02%[1]d Б\x02%.2[1]f КиБ\x02%.2[1]f МиБ" +
+ "\x02%.2[1]f ГиБ\x02%.2[1]f ТиБ\x02%[1]s: %[2]q\x02Порт сервера не указан" +
+ "\x02Неверный IP-адрес сервера\x02В скобках должен быть адрес IPv6\x02Нед" +
+ "опустимый MTU\x02Недопустимый порт\x02Недопустимое значение поддержания" +
+ " соединения\x02Недопустимый ключ: %[1]v\x02Ключи должны декодироваться р" +
+ "овно в 32 байта\x02Две запятые подряд\x02Неправильное имя туннеля\x02Ст" +
+ "рока должна быть в секции\x02В ключе конфигурации отсутствует разделите" +
+ "ль\x02Ключ должен иметь значение\x02Неверный ключ для секции [Interface" +
+ "]\x02Неверный ключ для секции [Peer]\x02Для интерфейса должен быть задан" +
+ " приватный ключ\x02[не указан]\x02Все пиры должны иметь публичные ключи" +
+ "\x02, \x02, \x02О WireGuard\x02Логотип WireGuard\x02Закрыть\x02♥ &Пожерт" +
+ "вовать!\x02Статус:\x02&Отключить\x02&Подключить\x02Публичный ключ:\x02П" +
+ "орт:\x02MTU:\x02IP-адреса:\x02DNS-серверы:\x02Скрипты:\x02Общий ключ:" +
+ "\x02Разрешенные IP-адреса:\x02IP-адрес сервера:\x02Поддерживание соедине" +
+ "ния:\x02Последнее рукопожатие:\x02Передача:\x02перед подключением\x02по" +
+ "сле подключения\x02перед отключением\x02после отключения\x02отключено, " +
+ "по политике\x02включено\x02Получено %[1]s, отправлено %[2]s\x02Не удало" +
+ "сь определить состояние туннеля\x02Не удалось подключить туннель\x02Не " +
+ "удалось отключить туннель\x02Интерфейс: %[1]s\x02Пир\x02Создать туннель" +
+ "\x02Редактировать туннель\x02&Имя:\x02&Публичный ключ:\x02(неизвестно)" +
+ "\x02&Блокировать трафик, идущий мимо туннеля (kill-switch)\x02&Сохранить" +
+ "\x02Отмена\x02&Конфигурация:\x02Недопустимое имя\x02Требуется имя.\x02Им" +
+ "я туннеля ‘%[1]s’ недопустимо.\x02Не удалось отобразить туннели\x02Тунн" +
+ "ель уже существует\x02Туннель с именем ’%[1]s’ уже существует.\x02Не уд" +
+ "алось создать новую конфигурацию\x02Ошибка при записи в файл\x02Файл ‘%" +
+ "[1]s’ уже существует!\x0a\x0aВы хотите перезаписать его?\x02Подключен" +
+ "\x02Подключение\x02Отключен\x02Отключение\x02Неизвестное состояние\x02Жу" +
+ "рнал\x02&Копировать\x02Выбрать &все\x02&Сохранить в файл…\x02Время\x02С" +
+ "ообщение журнала\x02Текстовые файлы (*.txt)|*.txt|Все файлы (*.*)|*.*" +
+ "\x02Экспорт журнала в файл\x02&О WireGuard…\x02Ошибка туннеля\x02%[1]s" +
+ "\x0a\x0aОбратитесь к журналу для получения дополнительной информации." +
"\x02%[1]s (устарел)\x02Ошибка обнаружения WireGuard\x02Не удалось дождат" +
- "ься появления окна WireGuard: %[1]v\x02WireGuard: Деактивирован\x02Стат" +
- "ус: Неизвестен\x02Адреса: нет\x02&Управление туннелями…\x02&Импорт тунн" +
- "елей из файла…\x02Вы&ход\x02WireGuard Включен\x02Туннель %[1]s подключе" +
- "н.\x02WireGuard Выключен\x02Туннель %[1]s отключен.\x02Ошибка туннеля W" +
- "ireGuard\x02WireGuard: %[1]s\x02Статус: %[1]s\x02Адреса: %[1]s\x02Доступ" +
- "но обновление!\x02Доступно обновление WireGuard\x02Доступно обновление " +
- "для WireGuard. Рекомендуется обновить его как можно скорее.\x02Туннели" +
- "\x02&Редактировать\x02Добавить &пустой туннель…\x02Добавить туннель\x02У" +
- "далить выбранные туннели\x02Экспорт всех туннелей в zip-архив\x02&Перек" +
- "лючить\x02Экспорт всех туннелей в &zip-архив…\x02Редактировать &выбранн" +
- "ый туннель…\x02&Удалить выбранные туннели\x02файлы конфигурации не были" +
- " найдены\x02Невозможно импортировать конфигурацию: %[1]v\x02Не удалось п" +
- "еречислить существующие туннели: %[1]v\x02Туннель с именем ’%[1]s’ уже " +
- "существует\x02Невозможно импортировать конфигурацию: %[1]v\x02Импортиро" +
- "ванные туннели\x14\x01\x81\x01\x00\x041\x02Импортированы туннели: %[1]d" +
- "\x051\x02Импортированы туннели: %[1]d\x024\x02Импортированный %[1]d тунн" +
- "ель\x001\x02Импортированы туннели: %[1]d\x14\x02\x80\x01\x04<\x02Импорт" +
- "ированы туннели: %[1]d из %[2]d\x05<\x02Импортированы туннели: %[1]d из" +
- " %[2]d\x02<\x02Импортированы туннели: %[1]d из %[2]d\x00<\x02Импортирова" +
- "ны туннели: %[1]d из %[2]d\x02Не удалось создать туннель\x14\x01\x81" +
- "\x01\x00\x04%\x02Удалить туннели: %[1]d\x05%\x02Удалить туннели: %[1]d" +
- "\x02$\x02Удалить %[1]d туннель\x00%\x02Удалить туннели: %[1]d\x14\x01" +
- "\x81\x01\x00\x04O\x02Вы уверены, что хотите удалить туннели: %[1]d?\x05O" +
- "\x02Вы уверены, что хотите удалить туннели: %[1]d?\x02N\x02Вы уверены, ч" +
- "то хотите удалить %[1]d туннель?\x00O\x02Вы уверены, что хотите удалить" +
- " туннели: %[1]d?\x02Удалить туннель ‘%[1]s’\x02Вы уверены, что хотите уд" +
- "алить '%[1]s' туннель?\x02%[1]s Данное действие невозможно отменить." +
- "\x02Не удалось удалить туннель\x02Невозможно удалить туннель: %[1]s\x02Н" +
- "е удалось удалить туннели\x14\x01\x81\x01\x00\x04;\x02туннелей не удало" +
- "сь удалить: %[1]d\x05;\x02туннелей не удалось удалить: %[1]d\x029\x02%[" +
- "1]d туннель не удалось удалить.\x00;\x02туннелей не удалось удалить: %[1" +
- "]d\x02Файлы конфигурации (*.zip, *.conf)|*.zip;*.conf|Все файлы (*.*)|*." +
- "*\x02Импорт туннелей из файла\x02Конфигурация ZIP файлов (*.zip)|*.zip" +
+ "ься появления окна WireGuard: %[1]v\x02WireGuard: деактивирован\x02Стат" +
+ "ус: неизвестен\x02Адреса: нет\x02&Управление туннелями…\x02&Импорт тунн" +
+ "елей из файла…\x02Вы&ход\x02&Туннели\x02WireGuard включен\x02Туннель %[" +
+ "1]s подключен.\x02WireGuard выключен\x02Туннель %[1]s отключен.\x02Ошибк" +
+ "а туннеля WireGuard\x02WireGuard: %[1]s\x02Статус: %[1]s\x02Адреса: %[1" +
+ "]s\x02Доступно обновление!\x02Доступно обновление WireGuard\x02Доступно " +
+ "обновление для WireGuard. Рекомендуется обновить его как можно скорее." +
+ "\x02Туннели\x02&Редактировать\x02Добавить &пустой туннель…\x02Добавить т" +
+ "уннель\x02Удалить выбранные туннели\x02Экспорт всех туннелей в zip-архи" +
+ "в\x02&Переключить\x02Экспорт всех туннелей в &zip-архив…\x02Редактирова" +
+ "ть &выбранный туннель…\x02&Удалить выбранные туннели\x02файлы конфигура" +
+ "ции не были найдены\x02Невозможно импортировать конфигурацию: %[1]v\x02" +
+ "Не удалось перечислить существующие туннели: %[1]v\x02Туннель с именем " +
+ "’%[1]s’ уже существует\x02Невозможно импортировать конфигурацию: %[1]v" +
+ "\x02Импортированные туннели\x14\x01\x81\x01\x00\x040\x02Импортированы %[" +
+ "1]d туннеля\x052\x02Импортировано %[1]d туннелей\x02.\x02Импортирован %[" +
+ "1]d туннель\x002\x02Импортировано %[1]d туннелей\x14\x02\x80\x01\x04=" +
+ "\x02Импортированы %[1]d из %[2]d туннелей\x05=\x02Импортировано %[1]d из" +
+ " %[2]d туннелей\x02;\x02Импортирован %[1]d из %[2]d туннелей\x00=\x02Имп" +
+ "ортировано %[1]d из %[2]d туннелей\x02Не удалось создать туннель\x14" +
+ "\x01\x81\x01\x00\x04$\x02Удалить %[1]d туннеля\x05&\x02Удалить %[1]d тун" +
+ "нелей\x02$\x02Удалить %[1]d туннель\x00&\x02Удалить %[1]d туннелей\x14" +
+ "\x01\x81\x01\x00\x04N\x02Вы уверены, что хотите удалить %[1]d туннеля?" +
+ "\x05P\x02Вы уверены, что хотите удалить %[1]d туннелей?\x02N\x02Вы увере" +
+ "ны, что хотите удалить %[1]d туннель?\x00P\x02Вы уверены, что хотите уд" +
+ "алить %[1]d туннелей?\x02Удалить туннель ‘%[1]s’\x02Вы уверены, что хот" +
+ "ите удалить ‘%[1]s’ туннель?\x02%[1]s Данное действие невозможно отмени" +
+ "ть.\x02Не удалось удалить туннель\x02Невозможно удалить туннель: %[1]s" +
+ "\x02Не удалось удалить туннели\x14\x01\x81\x01\x00\x049\x02%[1]d туннеля" +
+ " не удалось удалить.\x05;\x02%[1]d туннелей не удалось удалить.\x029\x02" +
+ "%[1]d туннель не удалось удалить.\x00;\x02%[1]d туннелей не удалось удал" +
+ "ить.\x02Файлы конфигурации (*.zip, *.conf)|*.zip;*.conf|Все файлы (*.*)" +
+ "|*.*\x02Импорт туннелей из файла\x02ZIP-файлы конфигурации (*.zip)|*.zip" +
"\x02Экспорт туннелей в zip-архив\x02%[1]s (неподписанная сборка, нет обн" +
- "овлений)\x02Ошибка выхода из WireGuard\x02Не удается выйти из сервиса и" +
- "з-за: %[1]v. Вы можете остановить WireGuard из менеджера служб.\x02Дост" +
- "упно обновление WireGuard. Настоятельно рекомендуем обновить приложение" +
- ".\x02Статус: Ожидание пользователя\x02Обновить Сейчас\x02Статус: Ожидани" +
- "е обновления\x02Ошибка: %[1]v. Попробуйте еще раз.\x02Статус: Завершено" +
- "!\x02перед подключением\x02после подключения\x02перед отключением\x02пос" +
- "ле отключения\x02&Туннели"
+ "овлений)\x02Ошибка при завершении WireGuard\x02Не удалось завершить слу" +
+ "жбу: %[1]v. Вы можете остановить WireGuard вручную из оснастки Службы." +
+ "\x02Доступно обновление WireGuard. Настоятельно рекомендуем обновить при" +
+ "ложение.\x02Статус: ожидание пользователя\x02Обновить сейчас\x02Статус:" +
+ " ожидание обновления\x02Ошибка: %[1]v. Попробуйте еще раз.\x02Статус: за" +
+ "вершено!"
+
+var si_LKIndex = []uint32{ // 180 elements
+ // Entry 0 - 1F
+ 0x00000000, 0x00000013, 0x000000a9, 0x000000cc,
+ 0x000000fc, 0x00000197, 0x00000223, 0x00000293,
+ 0x0000035d, 0x00000438, 0x000004bc, 0x000004c9,
+ 0x00000524, 0x00000565, 0x00000594, 0x000005bd,
+ 0x000005f8, 0x0000062d, 0x00000641, 0x0000064d,
+ 0x00000661, 0x00000675, 0x00000689, 0x0000069d,
+ 0x000006aa, 0x0000070d, 0x00000759, 0x000007b8,
+ 0x000007d9, 0x00000800, 0x00000843, 0x00000874,
+ // Entry 20 - 3F
+ 0x000008dd, 0x0000091f, 0x0000094a, 0x0000098e,
+ 0x00000a10, 0x00000a50, 0x00000aa0, 0x00000aeb,
+ 0x00000b51, 0x00000b8a, 0x00000c07, 0x00000c0a,
+ 0x00000c0d, 0x00000c30, 0x00000c57, 0x00000c67,
+ 0x00000c89, 0x00000c9d, 0x00000cc4, 0x00000ce8,
+ 0x00000d03, 0x00000d27, 0x00000d2c, 0x00000d3d,
+ 0x00000d67, 0x00000d8a, 0x00000db8, 0x00000ddf,
+ 0x00000e06, 0x00000e2d, 0x00000e56, 0x00000e64,
+ // Entry 40 - 5F
+ 0x00000e7e, 0x00000e9e, 0x00000eb5, 0x00000ed5,
+ 0x00000f18, 0x00000f28, 0x00000f5b, 0x00000fb8,
+ 0x00001002, 0x0000104f, 0x00001078, 0x000010a2,
+ 0x000010cc, 0x000010ff, 0x00001108, 0x00001124,
+ 0x00001136, 0x000011bc, 0x000011d6, 0x000011e9,
+ 0x00001207, 0x00001231, 0x00001258, 0x0000128c,
+ 0x000012dc, 0x00001309, 0x0000136f, 0x000013be,
+ 0x000013fa, 0x00001482, 0x000014a1, 0x000014ca,
+ // Entry 60 - 7F
+ 0x000014e3, 0x00001506, 0x00001535, 0x00001542,
+ 0x00001559, 0x00001580, 0x000015b3, 0x000015c3,
+ 0x000015e6, 0x00001632, 0x00001675, 0x0000169c,
+ 0x000016b3, 0x00001725, 0x0000174b, 0x00001784,
+ 0x0000181a, 0x00001849, 0x0000186d, 0x0000189b,
+ 0x000018d4, 0x0000191d, 0x00001934, 0x0000194f,
+ 0x00001990, 0x000019c2, 0x000019ed, 0x00001a35,
+ 0x00001a56, 0x00001a56, 0x00001a70, 0x00001a87,
+ // Entry 80 - 9F
+ 0x00001abd, 0x00001af6, 0x00001bdd, 0x00001bf7,
+ 0x00001c11, 0x00001c47, 0x00001c6e, 0x00001cb0,
+ 0x00001cfe, 0x00001d1f, 0x00001d70, 0x00001dad,
+ 0x00001df0, 0x00001e49, 0x00001ea6, 0x00001efb,
+ 0x00001f53, 0x00001fa0, 0x00001fcd, 0x00002045,
+ 0x000020e9, 0x00002123, 0x00002173, 0x00002249,
+ 0x0000226b, 0x000022c8, 0x00002312, 0x00002345,
+ 0x00002399, 0x000023cd, 0x00002479, 0x000024e3,
+ // Entry A0 - BF
+ 0x00002528, 0x00002570, 0x000025ab, 0x00002616,
+ 0x0000265e, 0x00002741, 0x0000280b, 0x0000285b,
+ 0x00002884, 0x000028e7, 0x0000292a, 0x0000295e,
+ 0x0000295e, 0x0000295e, 0x0000295e, 0x0000295e,
+ 0x0000295e, 0x0000295e, 0x0000295e, 0x0000295e,
+} // Size: 744 bytes
+
+const si_LKData string = "" + // Size: 10590 bytes
+ "\x02දෝෂයකි\x02(තර්කයක් නැත): කළමනාකරු සේවාව ඉහළ නැංවීම සහ ස්ථාපනය කිරීම" +
+ "\x02භාවිතය: %[1]s [\x0a%[2]s]\x02විධාන රේඛා විකල්ප\x02ක්\u200dරියාවලිය W" +
+ "OW64: %[1]vයටතේ ක්\u200dරියාත්මක වේද යන්න තීරණය කළ නොහැක\x02ඔබ මෙම පරිගණ" +
+ "කයේ WireGuard හි දේශීය අනුවාදය භාවිතා කළ යුතුය.\x02වත්මන් ක්\u200dරියා" +
+ "වලි ටෝකනය විවෘත කළ නොහැක: %[1]v\x02WireGuard භාවිතා කළ හැක්කේ Builtin " +
+ "%[1]s කණ්ඩායමේ සාමාජිකයෙකු වන පරිශීලකයින් විසින් පමණි.\x02WireGuard ක්" +
+ "\u200dරියාත්මක වේ, නමුත් UI ප්\u200dරවේශ විය හැක්කේ Builtin %[1]s කාණ්ඩය" +
+ "ේ ඩෙස්ක්ටොප් වලින් පමණි.\x02WireGuard පද්ධති තැටි නිරූපකය තත්පර 30කට ප" +
+ "සුව දිස් නොවීය.\x02දැන්\x02පද්ධති ඔරලෝසුව පසුපසට තුවාල වී ඇත!\x14\x01" +
+ "\x81\x01\x00\x02\x1c\x02අවුරුදු %[1]d\x00\x1c\x02අවුරුදු %[1]d\x14\x01" +
+ "\x81\x01\x00\x02\x13\x02දවස් %[1]d\x00\x13\x02දවස් %[1]d\x14\x01\x81\x01" +
+ "\x00\x02\x10\x02පැය %[1]d\x00\x10\x02පැය %[1]d\x14\x01\x81\x01\x00\x02" +
+ "\x19\x02විනාඩි %[1]d\x00\x19\x02විනාඩි %[1]d\x14\x01\x81\x01\x00\x02\x16" +
+ "\x02තත්පර %[1]d\x00\x16\x02තත්පර %[1]d\x02%[1]s ට පෙර\x02බ.\u00a0%[1]d" +
+ "\x02කි.බ. %.2[1]f\x02මෙ.බ. %.2[1]f\x02ගි.බ. %.2[1]f\x02ටෙ.බ. %.2[1]f\x02" +
+ "%[1]s: %[2]q\x02අන්ත ලක්ෂ්\u200dයයෙන් වරාය අස්ථානගත වී ඇත\x02අවලංගු අන්ත" +
+ " ලක්ෂ්\u200dය ධාරකයකි\x02වරහන් වල IPv6 ලිපිනයක් අඩංගු විය යුතුය\x02වලංගු" +
+ " නොවන MTU\x02තොට වලංගු නොවේ\x02වලංගු නොවන නොනැසී පැවතීම\x02වලංගු නොවන යත" +
+ "ුර: %[1]v\x02යතුරු හරියටම බයිට් 32කට විකේතනය කළ යුතුය\x02පේළියකට අල්පව" +
+ "ිරාම දෙකක්\x02උමං නම වලංගු නැත\x02රේඛාව කොටසක ඇති විය යුතුය\x02වින්" +
+ "\u200dයාස යතුර සමාන බෙදුම්කරුවෙකු අස්ථානගත වී ඇත\x02යතුරට අගයක් තිබිය යු" +
+ "තුය\x02[Interface] කොටස සඳහා වලංගු නොවන යතුර\x02[Peer] කොටස සඳහා වලංගු" +
+ " නොවන යතුර\x02අතුරුමුහුතකට පුද්. යතුරක් තිබිය යුතුය\x02[කිසිවක් සඳහන් කර" +
+ " නැත]\x02සියලුම සම වයසේ මිතුරන්ට පොදු යතුරු තිබිය යුතුය\x02, \x02, \x02ව" +
+ "යර්ගාඩ් ගැන\x02WireGuard ලාංඡන රූපය\x02වසන්න\x02♥ &පරිත්\u200dයාග!\x02" +
+ "තත්\u200dවය:\x02&අක්\u200dරිය කරන්න\x02&සක්රිය කරන්න\x02පොදු යතුර:\x02" +
+ "සවන්දීමේ තොට:\x02MTU:\x02ලිපින:\x02ව.නා.ප. සේවාදායක:\x02ස්ක්\u200dරිප්" +
+ "ට්:\x02පෙර බෙදාගත් යතුර:\x02ඉඩදුන් අ.ජා.කෙ.:\x02අන්ත ලක්ෂ්\u200dයය:" +
+ "\x02නොනැසී පැවතීම:\x02නවතම අතට අත දීම:\x02මාරු:\x02පූර්ව-අප්\x02පශ්චාත්-" +
+ "අප්\x02පෙර-පහළට\x02පශ්චාත්-පහළ\x02ආබාධිත, ප්රතිපත්තිය අනුව\x02සබලයි" +
+ "\x02%[1]s ලැබුණී, %[2]s යැවිණි\x02උමං තත්ත්වය තීරණය කිරීමට අසමත් විය\x02" +
+ "උමග සක්රිය කිරීමට අසමත් විය\x02උමග අක්\u200dරිය කිරීමට අසමත් විය\x02අත" +
+ "ුරුමුහුණත: %[1]s\x02සම වයසේ මිතුරන්\x02නව උමගක් සාදන්න\x02උමග සංස්කරණය" +
+ " කරන්න\x02&නම:\x02&පොදු යතුර:\x02(නොදනී)\x02&උමං මාර්ග රහිත ගමනාගමනය අවහ" +
+ "ිර කරන්න (මරන්න-ස්විච්)\x02&සුරකින්න\x02අවලංගු\x02&වින්\u200dයාසය:\x02" +
+ "වලංගු නොවන නමකි\x02නමක් අවශ්\u200dයයි.\x02උමං නම '%[1]s' වලංගු නැත." +
+ "\x02පවතින උමං ලැයිස්තුගත කළ නොහැක\x02උමග දැනටමත් පවතී\x02තවත් උමගක් දැනට" +
+ "මත් '%[1]s' යන නාමයෙන් පවතී.\x02නව වින්\u200dයාසය සෑදීමට නොහැකියි\x02ග" +
+ "ොනුව ලිවීමට අසමත්විය\x02'%[1]s' ගොනුව දැනටමත් පවතී.\x0a\x0aඔබට එය උඩින" +
+ "් ලිවීමට අවශ්\u200dයද?\x02ක්රියාකාරී\x02සක්\u200dරිය වෙමින්\x02අක්රියය" +
+ "ි\x02අක්රිය කිරීම\x02නොදන්නා තත්\u200dවයකි\x02සටහන\x02&පිටපතක්\x02&සිය" +
+ "ල්ල තෝරන්න\x02&ගොනුවකට සුරකින්න…\x02වේලාව\x02ලොග් පණිවිඩය\x02පෙළ ගොනු " +
+ "(*.txt)|*.txt|සියලු ගොනු (*.*)|*.*\x02ලොගය ගොනුවට අපනයනය කරන්න\x02&වයර්ග" +
+ "ාඩ් ගැන…\x02උමං දෝෂය\x02%[1]s\x0a\x0aවැඩි විස්තර සඳහා කරුණාකර ලඝු-සටහන" +
+ " බලන්න.\x02%[1]s (ඉකුත් වී ඇත)\x02WireGuard හඳුනාගැනීමේ දෝෂය\x02වයර්ගාඩ්" +
+ " කවුළුව පෙනෙන තෙක් බලා සිටීමට බලාපොරොත්තු වේ: %[1]v\x02WireGuard: අක්" +
+ "\u200dරිය කර ඇත\x02තත්\u200dවය: නොදනී\x02ලිපින: කිසිත් නැත\x02&උමං…කළමනා" +
+ "කරණය කරන්න\x02…ගොනුවෙන් උමං(ය) &ආයාත කරන්න\x02පි&ටවන්න\x02&උමං මාර්ග" +
+ "\x02වයර්ගාඩ් ක්\u200dරියාත්මකයි\x02%[1]s උමග සක්රිය කර ඇත.\x02WireGuard " +
+ "අක්රිය කර ඇත\x02%[1]s උමං මාර්ගය අක්\u200dරිය කර ඇත.\x02WireGuard උමං " +
+ "දෝෂය\x02තත්\u200dවය: %[1]s\x02ලිපින: %[1]s\x02යාවත්කාලීනයක් තිබේ!\x02W" +
+ "ireGuard යාවත්කාලීනය තිබේ\x02WireGuard වෙත යාවත්කාලීනයක් දැන් තිබේ. හැකි" +
+ " ඉක්මනින් යාවත්කාලීන කිරීමට ඔබට උපදෙස් දෙනු ලැබේ.\x02උමං මාර්ග\x02&සංස්ක" +
+ "රණය\x02හිස් උමං…එකතු කරන්න\x02උමග එකතු කරන්න\x02තෝරාගත් උමං(ය) ඉවත් කර" +
+ "න්න\x02සියලුම උමං zip වෙත අපනයනය කරන්න\x02&ටොගල් කරන්න\x02සියලුම උමං &" +
+ "zip…වෙත අපනයනය කරන්න\x02සංස්කරණය &තෝරාගත් උමග…\x02&තෝරාගත් උමං(ය) ඉවත් ක" +
+ "රන්න\x02වින්\u200dයාස ගොනු කිසිවක් හමු නොවිණි\x02තෝරාගත් වින්\u200dයාස" +
+ "ය ආයාත කළ නොහැක: %[1]v\x02පවතින උමං මාර්ග ගණනය කළ නොහැක: %[1]v\x02තවත්" +
+ " උමගක් දැනටමත් '%[1]s' නමින් පවතී\x02වින්\u200dයාසය ආයාත කළ නොහැකිය: %[1" +
+ "]v\x02ආනයනික උමං මාර්ග\x14\x01\x81\x01\x00\x024\x02උමං %[1]d ආනයනය කරන ල" +
+ "දී\x00;\x02උමං %[1]d ක් ආනයනය කරන ලදී\x14\x02\x80\x01\x02N\x02උමං %[2]" +
+ "d කින් %[1]d ක් ආනයනය කරන ලදී\x00N\x02උමං %[2]d කින් %[1]d ක් ආනයනය කරන " +
+ "ලදී\x02උමග නිර්මාණය කළ නොහැක\x14\x01\x81\x01\x00\x02 \x02%[1]d උමග මකන" +
+ "්න\x00'\x02උමං %[1]d ක් මකන්න\x14\x01\x81\x01\x00\x02[\x02ඔබ %[1]d උමග" +
+ " මැකීමට කැමති බව විශ්වාසද?\x00r\x02ඔබ උමං මාර්ග %[1]d ක් මැකීමට කැමති බව" +
+ " විශ්වාසද?\x02උමං '%[1]s' මකන්න\x02ඔබ '%[1]s' උමඟ මැකීමට කැමති බව විශ්වා" +
+ "සද?\x02%[1]s මෙම ක්\u200dරියාව ආපසු හැරවිය.\x02උමග මැකීමට නොහැකිය\x02උ" +
+ "මගක් ඉවත් කිරීමට නොහැකි විය: %[1]s\x02උමං මකා දැමිය නොහැක\x14\x01\x81" +
+ "\x01\x00\x02N\x02%[1]d උමං ඉවත් කිරීමට නොහැකි විය.\x00U\x02උමං %[1]d ක් " +
+ "ඉවත් කිරීමට නොහැකි විය.\x02වින්\u200dයාස ගොනු (*.zip, *.conf)|*.zip;*." +
+ "conf|සියලු ගොනු (*.*)|*.*\x02ගොනුවෙන් උමං(ය) ආයාත කරන්න\x02වින්\u200dයාස" +
+ " කිරීම ZIP ගොනු (*.zip)|*.zip\x02zip වෙත උමං අපනයනය කරන්න\x02%[1]s (අත්ස" +
+ "න් නොකළ ගොඩනැගීම, යාවත්කාලීන නැත)\x02වයර්ගාඩ් පිටවීමේදී දෝෂයකි\x02%[1]" +
+ "vනිසා සේවයෙන් ඉවත් විය නොහැක. ඔබට සේවා කළමනාකරුගෙන් WireGuard නැවැත්වීමට" +
+ " අවශ්\u200dය විය හැකිය.\x02WireGuard වෙත යාවත්කාලීනයක් තිබේ. ප්රමාදයකින්" +
+ " තොරව යාවත්කාලීන කිරීම ඉතා යෝග්ය වේ.\x02තත්\u200dවය: පරිශීලක සඳහා රැඳෙමි" +
+ "න්\x02යාවත්කාල කරන්න\x02තත්\u200dවය: යාවත්කාල සේවාව සඳහා රැඳෙමින්\x02ද" +
+ "ෝෂය: %[1]v. යළි උත්සාහ කරන්න.\x02තත්\u200dවය: සම්පූර්ණයි!"
-var skIndex = []uint32{ // 181 elements
+var skIndex = []uint32{ // 180 elements
// Entry 0 - 1F
0x00000000, 0x00000006, 0x0000005e, 0x00000078,
- 0x00000097, 0x000000d1, 0x000000d1, 0x00000109,
- 0x0000014b, 0x000001b5, 0x000001ff, 0x00000205,
- 0x0000022d, 0x0000022d, 0x00000265, 0x000002a6,
- 0x000002e9, 0x0000032e, 0x00000339, 0x00000342,
- 0x0000034f, 0x0000035c, 0x00000369, 0x00000376,
- 0x00000383, 0x00000397, 0x000003bd, 0x000003e2,
- 0x00000406, 0x0000042f, 0x0000043d, 0x0000044c,
+ 0x00000097, 0x000000d1, 0x0000011e, 0x00000156,
+ 0x00000198, 0x00000202, 0x0000024c, 0x00000252,
+ 0x0000027a, 0x000002b4, 0x000002ec, 0x0000032d,
+ 0x00000370, 0x000003b5, 0x000003c0, 0x000003c9,
+ 0x000003d6, 0x000003e3, 0x000003f0, 0x000003fd,
+ 0x0000040a, 0x0000042f, 0x00000453, 0x0000047c,
+ 0x0000048a, 0x00000499, 0x000004bb, 0x000004d4,
// Entry 20 - 3F
- 0x0000046e, 0x00000487, 0x000004bc, 0x000004ef,
- 0x00000505, 0x00000522, 0x00000541, 0x00000583,
- 0x000005a4, 0x000005c9, 0x000005e9, 0x0000061c,
- 0x00000630, 0x00000665, 0x00000689, 0x000006ac,
- 0x000006ca, 0x000006e8, 0x000006eb, 0x000006ed,
- 0x000006f9, 0x00000711, 0x00000711, 0x0000071b,
- 0x0000072a, 0x00000730, 0x0000073f, 0x0000074c,
- 0x0000075e, 0x0000076e, 0x00000773, 0x0000077b,
+ 0x00000509, 0x0000051f, 0x0000053c, 0x0000055b,
+ 0x0000059d, 0x000005be, 0x000005e3, 0x00000603,
+ 0x00000636, 0x0000064a, 0x0000067f, 0x00000682,
+ 0x00000684, 0x00000690, 0x000006a8, 0x000006b2,
+ 0x000006c0, 0x000006c6, 0x000006d4, 0x000006e0,
+ 0x000006f2, 0x00000702, 0x00000707, 0x0000070f,
+ 0x0000071c, 0x00000725, 0x00000740, 0x00000755,
+ 0x00000763, 0x0000077c, 0x0000079c, 0x000007a4,
// Entry 40 - 5F
- 0x00000788, 0x00000788, 0x000007a3, 0x000007b8,
- 0x000007c6, 0x000007df, 0x000007ff, 0x00000807,
- 0x00000807, 0x00000811, 0x00000835, 0x00000857,
- 0x00000876, 0x00000897, 0x000008a8, 0x000008ad,
- 0x000008c3, 0x000008d2, 0x000008db, 0x000008ee,
- 0x000008f9, 0x00000927, 0x00000927, 0x00000931,
- 0x0000093a, 0x0000094a, 0x0000095b, 0x0000096f,
- 0x00000997, 0x000009cd, 0x000009e0, 0x00000a0a,
+ 0x000007b3, 0x000007bf, 0x000007ce, 0x000007da,
+ 0x000007fb, 0x00000805, 0x00000829, 0x0000084b,
+ 0x0000086a, 0x0000088b, 0x0000089c, 0x000008a1,
+ 0x000008b7, 0x000008c6, 0x000008cf, 0x000008e2,
+ 0x000008ed, 0x0000091b, 0x00000925, 0x0000092e,
+ 0x0000093e, 0x0000094f, 0x00000963, 0x0000098b,
+ 0x000009c1, 0x000009d4, 0x000009fe, 0x00000a2b,
+ 0x00000a4e, 0x00000a8b, 0x00000a94, 0x00000aa0,
// Entry 60 - 7F
- 0x00000a37, 0x00000a5a, 0x00000a97, 0x00000aa0,
- 0x00000aac, 0x00000ab7, 0x00000ac5, 0x00000ad3,
- 0x00000ad3, 0x00000ad3, 0x00000ad3, 0x00000ad3,
- 0x00000ad3, 0x00000ad3, 0x00000ad3, 0x00000ad3,
- 0x00000ae3, 0x00000ae3, 0x00000ae3, 0x00000ae3,
- 0x00000ae3, 0x00000ae3, 0x00000ae3, 0x00000ae3,
- 0x00000ae3, 0x00000af9, 0x00000b1d, 0x00000b28,
- 0x00000b28, 0x00000b28, 0x00000b28, 0x00000b28,
+ 0x00000aab, 0x00000ab9, 0x00000ac7, 0x00000ad9,
+ 0x00000ae6, 0x00000af7, 0x00000b0f, 0x00000b14,
+ 0x00000b31, 0x00000b6a, 0x00000b93, 0x00000ba3,
+ 0x00000bb0, 0x00000be8, 0x00000bfb, 0x00000c14,
+ 0x00000c4f, 0x00000c68, 0x00000c76, 0x00000c86,
+ 0x00000c9c, 0x00000cc0, 0x00000ccb, 0x00000cd3,
+ 0x00000cec, 0x00000d09, 0x00000d24, 0x00000d43,
+ 0x00000d5a, 0x00000d6b, 0x00000d77, 0x00000d85,
// Entry 80 - 9F
- 0x00000b28, 0x00000b39, 0x00000b39, 0x00000b39,
- 0x00000b39, 0x00000b39, 0x00000b39, 0x00000b39,
- 0x00000b39, 0x00000b39, 0x00000b39, 0x00000b39,
- 0x00000b39, 0x00000b39, 0x00000b39, 0x00000b39,
- 0x00000b39, 0x00000b39, 0x00000b39, 0x00000b39,
- 0x00000b39, 0x00000b39, 0x00000b39, 0x00000b39,
- 0x00000b39, 0x00000b39, 0x00000b39, 0x00000b39,
- 0x00000b39, 0x00000b39, 0x00000b39, 0x00000b39,
+ 0x00000da1, 0x00000dc7, 0x00000e30, 0x00000e37,
+ 0x00000e41, 0x00000e5c, 0x00000e6a, 0x00000e8e,
+ 0x00000eb7, 0x00000ec2, 0x00000eef, 0x00000f0d,
+ 0x00000f2c, 0x00000f5c, 0x00000f96, 0x00000fc9,
+ 0x00000fee, 0x0000101f, 0x00001035, 0x000010b5,
+ 0x00001159, 0x00001172, 0x000011eb, 0x000012d9,
+ 0x000012f9, 0x00001336, 0x00001362, 0x0000137d,
+ 0x000013a5, 0x000013c3, 0x00001475, 0x000014c3,
// Entry A0 - BF
- 0x00000b39, 0x00000b39, 0x00000b39, 0x00000b39,
- 0x00000b39, 0x00000b39, 0x00000b39, 0x00000b39,
- 0x00000b39, 0x00000b39, 0x00000b39, 0x00000b39,
- 0x00000b39, 0x00000b39, 0x00000b39, 0x00000b39,
- 0x00000b39, 0x00000b39, 0x00000b39, 0x00000b39,
- 0x00000b39,
-} // Size: 748 bytes
+ 0x000014e3, 0x0000150b, 0x00001529, 0x0000155d,
+ 0x00001578, 0x000015de, 0x00001641, 0x00001661,
+ 0x00001675, 0x0000169f, 0x000016bf, 0x000016d2,
+ 0x000016d2, 0x000016d2, 0x000016d2, 0x000016d2,
+ 0x000016d2, 0x000016d2, 0x000016d2, 0x000016d2,
+} // Size: 744 bytes
-const skData string = "" + // Size: 2873 bytes
+const skData string = "" + // Size: 5842 bytes
"\x02Chyba\x02(bez argumentu): získať administrátorské práva a nainštalov" +
"ať službu manažéra\x02Použitie: %[1]s [\x0a%[2]s]\x02Možnosti príkazovéh" +
- "o riadku\x02Nepodarilo sa zistiť, či proces beží pod WOW64: %[1]v\x02Nep" +
- "odarilo sa otvoriť token aktuálneho procesu: %[1]v\x02WireGuard môžu pou" +
- "žívať iba členovia Builtin skupiny %[1]s.\x02WireGuard je spustený, ale" +
- " používateľské rozhranie je prístupné iba členom Builtin skupiny %[1]s." +
+ "o riadku\x02Nepodarilo sa zistiť, či proces beží pod WOW64: %[1]v\x02V t" +
+ "omto počítači musíte používať pôvodnú verziu programu WireGuard.\x02Nepo" +
+ "darilo sa otvoriť token aktuálneho procesu: %[1]v\x02WireGuard môžu použ" +
+ "ívať iba členovia Builtin skupiny %[1]s.\x02WireGuard je spustený, ale " +
+ "používateľské rozhranie je prístupné iba členom Builtin skupiny %[1]s." +
"\x02WireGuard ikona sa ani po 30 sekundách neobjavila na systémovej lišt" +
"e.\x02Teraz\x02Systémové hodiny sa vrátili v čase!\x14\x01\x81\x01\x00" +
- "\x04\x0a\x02%[1]d dni\x05\x0b\x02%[1]d dní\x02\x0b\x02%[1]d deň\x00\x0b" +
- "\x02%[1]d dní\x14\x01\x81\x01\x00\x04\x0d\x02%[1]d hodiny\x05\x0d\x02%[1" +
- "]d hodín\x02\x0d\x02%[1]d hodina\x00\x0d\x02%[1]d hodín\x14\x01\x81\x01" +
- "\x00\x04\x0e\x02%[1]d minúty\x05\x0d\x02%[1]d minút\x02\x0e\x02%[1]d min" +
- "úta\x00\x0d\x02%[1]d minút\x14\x01\x81\x01\x00\x04\x0e\x02%[1]d sekundy" +
- "\x05\x0e\x02%[1]d sekúnd\x02\x0e\x02%[1]d sekunda\x00\x0e\x02%[1]d sekún" +
- "d\x02Pred %[1]s\x02%[1]d\u00a0B\x02%.2[1]f\u00a0KiB\x02%.2[1]f\u00a0MiB" +
- "\x02%.2[1]f\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02Neplatná adr" +
- "esa IP\x02Neplatná dĺžka sieťového prefixu\x02Koncovému bodu chýba číslo" +
- " portu\x02Neplatný hostiteľ koncového bodu\x02Medzi zátvorkami musí byť " +
- "IPv6 adresa\x02Neplatné MTU\x02Neplatný port\x02Neplatný perzistentný ke" +
- "epalive\x02Neplatný kľúč: %[1]v\x02Dekódované kľúče musia mať veľkosť 32" +
- " bajtov\x02Číslo musí mať hodnotu medzi 0 a 2^64-1: %[1]v\x02Dve čiarky " +
- "v poradí\x02Názov tunela nie je platný\x02Sekcia musí obsahovať čiaru" +
- "\x02Konfiguračný kľúč neobsahuje separátor (znamienko rovnosti)\x02Kľúč " +
- "musí obsahovať hodnotu\x02Neplatný kľúč sekcie [Interface]\x02Neplatný k" +
- "ľúč sekcie [Peer]\x02Rozhranie musí mať priradený súkromný kľúč\x02[neš" +
- "pecifikované]\x02Všetci peeri musia mať priradený verejný kľúč\x02Chyba " +
- "pri získavaní konfigurácie\x02Neplatný kľúč sekcie rozhrania\x02Verzia p" +
- "rotokolu musí byť 1\x02Neplatný kľúč peer sekcie\x02, \x02 \x02O WireGua" +
- "rd\x02Obrázok WireGuard loga\x02Zatvoriť\x02♥ a Darovat!\x02Stav:\x02a D" +
- "eaktivovať\x02a Aktivovať\x02Verejný kľúč:\x02Otvorený port:\x02MTU:\x02" +
- "Adresy:\x02Servery DNS:\x02Vopred zdieľaný kľúč:\x02Povolené IP adresy:" +
- "\x02Koncový bod:\x02Perzistentný keepalive:\x02Posledné spojenie (handsh" +
- "ake):\x02Prenos:\x02povolené\x02%[1]s prijatých, %[2]s odoslaných\x02Nep" +
- "odarilo sa zistiť stav tunela\x02Nepodarilo sa aktivovať tunel\x02Nepoda" +
- "rilo sa deaktivovať tunel\x02Rozhranie: %[1]s\x02Peer\x02Vytvoriť nový t" +
- "unel\x02Upraviť tunel\x02&Názov:\x02&Verejný kľúč:\x02(neznámy)\x02&Blok" +
- "ovať netunelovaný prenos (kill-switch)\x02&Uložiť\x02Zrušiť\x02&Konfigur" +
- "ácia:\x02Neplatný názov\x02Názov je povinný.\x02Názov tunela ‘%[1]s’ je" +
- " neplatný.\x02Nepodarilo sa pripraviť zoznam existujúcich tunelov\x02Tun" +
- "el už existuje\x02Tunel s názvom ‘%[1]s’ už existuje.\x02Nie je možné vy" +
- "tvoriť novú konfiguráciu\x02Nepodarilo sa zapísať do súboru\x02Súbor ‘%[" +
- "1]s’ už existuje.\x0a\x0aŽeláte si ho prepísať?\x02Aktívny\x02Aktivuje s" +
- "a\x02Neaktívny\x02Deaktivuje sa\x02Neznámy stav\x02&O WireGuard…\x02&Spr" +
- "avovať tunely…\x02&Importovať tunel(y) zo súboru…\x02U&končiť\x02WireGua" +
- "rd: %[1]s"
+ "\x04\x0b\x02%[1]d roky\x05\x0c\x02%[1]d rokov\x02\x0a\x02%[1]d rok\x00" +
+ "\x0c\x02%[1]d rokov\x14\x01\x81\x01\x00\x04\x0a\x02%[1]d dni\x05\x0b\x02" +
+ "%[1]d dní\x02\x0b\x02%[1]d deň\x00\x0b\x02%[1]d dní\x14\x01\x81\x01\x00" +
+ "\x04\x0d\x02%[1]d hodiny\x05\x0d\x02%[1]d hodín\x02\x0d\x02%[1]d hodina" +
+ "\x00\x0d\x02%[1]d hodín\x14\x01\x81\x01\x00\x04\x0e\x02%[1]d minúty\x05" +
+ "\x0d\x02%[1]d minút\x02\x0e\x02%[1]d minúta\x00\x0d\x02%[1]d minút\x14" +
+ "\x01\x81\x01\x00\x04\x0e\x02%[1]d sekundy\x05\x0e\x02%[1]d sekúnd\x02" +
+ "\x0e\x02%[1]d sekunda\x00\x0e\x02%[1]d sekúnd\x02Pred %[1]s\x02%[1]d" +
+ "\u00a0B\x02%.2[1]f\u00a0KiB\x02%.2[1]f\u00a0MiB\x02%.2[1]f\u00a0GiB\x02%" +
+ ".2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02Koncovému bodu chýba číslo portu\x02N" +
+ "eplatný hostiteľ koncového bodu\x02Medzi zátvorkami musí byť IPv6 adresa" +
+ "\x02Neplatné MTU\x02Neplatný port\x02Neplatný perzistentný keepalive\x02" +
+ "Neplatný kľúč: %[1]v\x02Dekódované kľúče musia mať veľkosť 32 bajtov\x02" +
+ "Dve čiarky v poradí\x02Názov tunela nie je platný\x02Sekcia musí obsahov" +
+ "ať čiaru\x02Konfiguračný kľúč neobsahuje separátor (znamienko rovnosti)" +
+ "\x02Kľúč musí obsahovať hodnotu\x02Neplatný kľúč sekcie [Interface]\x02N" +
+ "eplatný kľúč sekcie [Peer]\x02Rozhranie musí mať priradený súkromný kľúč" +
+ "\x02[nešpecifikované]\x02Všetci peeri musia mať priradený verejný kľúč" +
+ "\x02, \x02 \x02O WireGuard\x02Obrázok WireGuard loga\x02Zatvoriť\x02♥ &D" +
+ "arovat!\x02Stav:\x02&Deaktivovať\x02&Aktivovať\x02Verejný kľúč:\x02Otvor" +
+ "ený port:\x02MTU:\x02Adresy:\x02Servery DNS:\x02Skripty:\x02Vopred zdieľ" +
+ "aný kľúč:\x02Povolené IP adresy:\x02Koncový bod:\x02Perzistentný keepali" +
+ "ve:\x02Posledné spojenie (handshake):\x02Prenos:\x02pred-zapnutím\x02po-" +
+ "zapnutí\x02pred-vypnutím\x02po-vypnutí\x02zakázané, na základe pravidla" +
+ "\x02povolené\x02%[1]s prijatých, %[2]s odoslaných\x02Nepodarilo sa zisti" +
+ "ť stav tunela\x02Nepodarilo sa aktivovať tunel\x02Nepodarilo sa deaktiv" +
+ "ovať tunel\x02Rozhranie: %[1]s\x02Peer\x02Vytvoriť nový tunel\x02Upraviť" +
+ " tunel\x02&Názov:\x02&Verejný kľúč:\x02(neznámy)\x02&Blokovať netunelova" +
+ "ný prenos (kill-switch)\x02&Uložiť\x02Zrušiť\x02&Konfigurácia:\x02Neplat" +
+ "ný názov\x02Názov je povinný.\x02Názov tunela ‘%[1]s’ je neplatný.\x02Ne" +
+ "podarilo sa pripraviť zoznam existujúcich tunelov\x02Tunel už existuje" +
+ "\x02Tunel s názvom ‘%[1]s’ už existuje.\x02Nie je možné vytvoriť novú ko" +
+ "nfiguráciu\x02Nepodarilo sa zapísať do súboru\x02Súbor ‘%[1]s’ už existu" +
+ "je.\x0a\x0aŽeláte si ho prepísať?\x02Aktívny\x02Aktivuje sa\x02Neaktívny" +
+ "\x02Deaktivuje sa\x02Neznámy stav\x02Denník udalostí\x02&Kopírovať\x02Vy" +
+ "br&ať všetko\x02Uložiť do &súboru…\x02Čas\x02Správa v denníku udalostí" +
+ "\x02Textové súbory (*.txt)|*.txt|Všetky súbory (*.*)|*.*\x02Exportovať d" +
+ "enník udalostí do súboru\x02&O WireGuard…\x02Chyba tunela\x02%[1]s\x0a" +
+ "\x0aViac informácií nájdete v denníku udalostí.\x02%[1]s (neaktuány)\x02" +
+ "Chyba detekcie WireGuard\x02Nie je možné čakať na zobrazenie WireGuard o" +
+ "kna: %[1]v\x02WireGuard: deaktivovaný\x02Stav: Nezámy\x02Adresa: žiadna" +
+ "\x02&Spravovať tunely…\x02&Importovať tunel(y) zo súboru…\x02U&končiť" +
+ "\x02&Tunely\x02WireGuard je aktivovaný\x02Tunel %[1]s bol aktivovaný." +
+ "\x02WireGuard je deaktivovaný\x02Tunel %[1]s bol deaktivovaný.\x02Chyba " +
+ "WireGuard tunelu\x02WireGuard: %[1]s\x02Stav: %[1]s\x02Adresa: %[1]s\x02" +
+ "Je dostupná aktualizácia!\x02Dostupná aktualizácia pre WireGuard\x02Je k" +
+ " dispozícii aktualizácia programu WireGuard. Je odporúčané čo najskôr vy" +
+ "konať aktualizáciu.\x02Tunely\x02&Upraviť\x02Pridať &prázdny tunel…\x02P" +
+ "ridať tunel\x02Odstrániť označený(é) tunel(y)\x02Export všetkých tunelov" +
+ " do zip súboru\x02P&repnúť\x02Export všetkých tunelov do &zip súboru…" +
+ "\x02Upraviť &označený tunel…\x02&Odstrániť označené tunely\x02neboli náj" +
+ "dené žiadne konfiguračné súbory\x02Nepodarilo sa naimportovať vybrané ko" +
+ "nfigurácie: %[1]v\x02Nepodarilo sa načítať existujúce tunely: %[1]v\x02U" +
+ "ž existuje tunel s názvom '%[1]s'\x02Nepodarilo sa naimportovať konfigu" +
+ "ráciu: %[1]v\x02Naimportované tunely\x14\x01\x81\x01\x00\x04\x1c\x02Naim" +
+ "portované %[1]d tunely\x05\x1f\x02Naimportovaných %[1]d tunelov\x02\x19" +
+ "\x02Importovaný %[1]d tunel\x00\x1f\x02Naimportovaných %[1]d tunelov\x14" +
+ "\x02\x80\x01\x04%\x02Naimportované %[1]d z %[2]d tunelov\x05'\x02Naimpor" +
+ "tovaných %[1]d z %[2]d tunelov\x02%\x02Naimportovaný %[1]d z %[2]d tunel" +
+ "ov\x00'\x02Naimportovaných %[1]d z %[2]d tunelov\x02Tunel sa nedá vytvor" +
+ "iť\x14\x01\x81\x01\x00\x04\x19\x02Odstránene %[1]d tunely\x05\x1d\x02Ods" +
+ "tránených %[1]d tunelov\x02\x19\x02Odstránený %[1]d tunel\x00\x1d\x02Ods" +
+ "tránených %[1]d tunelov\x14\x01\x81\x01\x00\x048\x02Ste si istý, že si ž" +
+ "eláte odstrániť %[1]d tunely?\x059\x02Ste si istý, že si želáte odstráni" +
+ "ť %[1]d tunelov?\x027\x02Ste si istý, že si želáte odstrániť %[1]d tune" +
+ "l?\x009\x02Ste si istý, že si želáte odstrániť %[1]d tunelov?\x02Odstrán" +
+ "enie tunela ‘%[1]s’\x02Ste si istý, že si želáte odstrániť tunel ‘%[1]s’" +
+ "?\x02%[1]s Túto akciu nemôže vrátiť späť.\x02Tunel sa nedá odstrániť\x02" +
+ "Nebolo možné odstrániť tunel: %[1]s\x02Tunely sa nedajú odstrániť\x14" +
+ "\x01\x81\x01\x00\x04)\x02%[1]d tunely nebolo možné odstrániť.\x05*\x02%[" +
+ "1]d tunelov nebolo možné odstrániť.\x02(\x02%[1]d tunel nebolo možné ods" +
+ "trániť.\x00*\x02%[1]d tunelov nebolo možné odstrániť.\x02Konfirugačné sú" +
+ "bory (*.zip, *.conf)|*.zip;*.conf|Všetky súbory (*.*)|*.*\x02Importovať " +
+ "tunel(y) zo súboru\x02Konfiguračné ZIP súbry (*.zip)|*.zip\x02Export tun" +
+ "elov do zip súboru\x02%[1]s (nepodpísaná verzia, žiadne aktualizácie)" +
+ "\x02Chyba ukončenia WireGuard\x02Nie je možné ukončiť služby z dôvodu: %" +
+ "[1]v. Skúste zastaviť WireGuard v správcovi služieb.\x02Je k dispozícii " +
+ "nová verzia programu WireGuard. Odporúčame bezodkladne vykonať aktualizá" +
+ "ciu.\x02Stav: Čaká sa na užívateľa\x02Aktualizovať teraz\x02Stav: Čaká s" +
+ "a na aktualizačnú službu\x02Chyba: %[1]v. Skúste to znova.\x02Stav: Doko" +
+ "nčené!"
-var slIndex = []uint32{ // 181 elements
+var slIndex = []uint32{ // 180 elements
// Entry 0 - 1F
0x00000000, 0x00000007, 0x00000058, 0x00000070,
0x00000089, 0x000000c1, 0x00000111, 0x00000148,
@@ -1943,54 +3040,53 @@ var slIndex = []uint32{ // 181 elements
0x00000268, 0x000002a0, 0x000002d7, 0x0000030b,
0x0000034b, 0x0000038f, 0x0000039b, 0x000003a4,
0x000003b1, 0x000003be, 0x000003cb, 0x000003d8,
- 0x000003e5, 0x000003f8, 0x0000041c, 0x0000043e,
- 0x00000467, 0x0000048d, 0x0000049a, 0x000004a9,
+ 0x000003e5, 0x00000407, 0x00000430, 0x00000456,
+ 0x00000463, 0x00000472, 0x00000496, 0x000004ad,
// Entry 20 - 3F
- 0x000004cd, 0x000004e4, 0x00000515, 0x00000549,
- 0x0000055e, 0x00000575, 0x00000590, 0x000005bf,
- 0x000005da, 0x000005ff, 0x0000061f, 0x00000641,
- 0x0000064f, 0x00000676, 0x00000696, 0x000006b8,
- 0x000006d6, 0x000006f8, 0x000006fb, 0x000006fd,
- 0x0000070a, 0x00000728, 0x000007a3, 0x000007a9,
- 0x000007b7, 0x000007bf, 0x000007cc, 0x000007d7,
- 0x000007e5, 0x000007f8, 0x000007fd, 0x00000806,
+ 0x000004de, 0x000004f3, 0x0000050a, 0x00000525,
+ 0x00000554, 0x0000056f, 0x00000594, 0x000005b4,
+ 0x000005d6, 0x000005e4, 0x0000060b, 0x0000060e,
+ 0x00000610, 0x0000061d, 0x0000063b, 0x00000641,
+ 0x0000064f, 0x00000657, 0x00000665, 0x00000670,
+ 0x0000067e, 0x00000691, 0x00000696, 0x0000069f,
+ 0x000006af, 0x000006b8, 0x000006ce, 0x000006df,
+ 0x000006ef, 0x0000070b, 0x0000071d, 0x00000725,
// Entry 40 - 5F
- 0x00000816, 0x0000081f, 0x00000835, 0x00000846,
- 0x00000856, 0x00000872, 0x00000884, 0x0000088c,
- 0x000008aa, 0x000008b5, 0x000008d2, 0x000008f6,
- 0x00000914, 0x00000934, 0x00000943, 0x0000094b,
- 0x0000095d, 0x00000969, 0x0000096f, 0x0000097e,
- 0x00000988, 0x000009b2, 0x00000af2, 0x00000afa,
- 0x00000b04, 0x00000b14, 0x00000b21, 0x00000b31,
- 0x00000b53, 0x00000b83, 0x00000b95, 0x00000bc0,
+ 0x00000735, 0x00000743, 0x00000756, 0x00000767,
+ 0x00000785, 0x00000790, 0x000007ad, 0x000007d1,
+ 0x000007ef, 0x00000810, 0x0000081f, 0x00000827,
+ 0x00000839, 0x00000845, 0x0000084b, 0x0000085a,
+ 0x00000864, 0x0000088e, 0x00000896, 0x000008a0,
+ 0x000008b0, 0x000008bd, 0x000008cd, 0x000008ef,
+ 0x0000091f, 0x00000931, 0x0000095c, 0x00000983,
+ 0x000009a1, 0x000009dc, 0x000009e4, 0x000009f0,
// Entry 60 - 7F
- 0x00000be7, 0x00000c05, 0x00000c40, 0x00000c48,
- 0x00000c54, 0x00000c5e, 0x00000c6c, 0x00000c7b,
- 0x00000c83, 0x00000c8c, 0x00000c98, 0x00000cb0,
- 0x00000cb5, 0x00000ccb, 0x00000d03, 0x00000d1d,
- 0x00000d30, 0x00000d3e, 0x00000d6d, 0x00000d83,
- 0x00000da0, 0x00000ddb, 0x00000df2, 0x00000e01,
- 0x00000e0f, 0x00000e26, 0x00000e45, 0x00000e4c,
- 0x00000e60, 0x00000e7e, 0x00000e94, 0x00000eb4,
+ 0x000009fa, 0x00000a09, 0x00000a18, 0x00000a20,
+ 0x00000a29, 0x00000a35, 0x00000a4d, 0x00000a52,
+ 0x00000a68, 0x00000aa0, 0x00000aba, 0x00000acd,
+ 0x00000adb, 0x00000b0a, 0x00000b20, 0x00000b3d,
+ 0x00000b78, 0x00000b90, 0x00000b9f, 0x00000bad,
+ 0x00000bc4, 0x00000be3, 0x00000bea, 0x00000bf2,
+ 0x00000c06, 0x00000c24, 0x00000c3b, 0x00000c5c,
+ 0x00000c74, 0x00000c85, 0x00000c93, 0x00000ca2,
// Entry 80 - 9F
- 0x00000ecc, 0x00000edd, 0x00000eeb, 0x00000efa,
- 0x00000f13, 0x00000f36, 0x00000f7b, 0x00000f82,
- 0x00000f89, 0x00000fa2, 0x00000fae, 0x00000fc6,
- 0x00000fde, 0x00000fe8, 0x00001006, 0x0000101f,
- 0x00001038, 0x0000105d, 0x0000108b, 0x000010be,
- 0x000010e3, 0x00001109, 0x00001119, 0x0000117d,
- 0x00001208, 0x00001229, 0x0000128e, 0x0000137b,
- 0x00001396, 0x000013d1, 0x000013fc, 0x00001416,
+ 0x00000cbb, 0x00000cde, 0x00000d23, 0x00000d2a,
+ 0x00000d31, 0x00000d4a, 0x00000d56, 0x00000d6e,
+ 0x00000d86, 0x00000d90, 0x00000dae, 0x00000dc7,
+ 0x00000de0, 0x00000e05, 0x00000e33, 0x00000e66,
+ 0x00000e8b, 0x00000eb1, 0x00000ec1, 0x00000f25,
+ 0x00000fb0, 0x00000fd1, 0x00001036, 0x00001123,
+ 0x0000113e, 0x00001179, 0x000011a4, 0x000011be,
+ 0x000011e6, 0x00001201, 0x000012b5, 0x00001302,
// Entry A0 - BF
- 0x0000143e, 0x00001459, 0x0000150d, 0x0000155a,
- 0x00001573, 0x0000159e, 0x000015bb, 0x000015ec,
- 0x0000160c, 0x00001679, 0x000016cc, 0x000016e8,
- 0x000016f6, 0x0000171d, 0x0000173f, 0x00001751,
- 0x00001761, 0x0000176f, 0x00001781, 0x00001791,
- 0x00001799,
-} // Size: 748 bytes
+ 0x0000131b, 0x00001346, 0x00001363, 0x00001394,
+ 0x000013b4, 0x00001421, 0x00001474, 0x00001490,
+ 0x0000149e, 0x000014c5, 0x000014e7, 0x000014f9,
+ 0x000014f9, 0x000014f9, 0x000014f9, 0x000014f9,
+ 0x000014f9, 0x000014f9, 0x000014f9, 0x000014f9,
+} // Size: 744 bytes
-const slData string = "" + // Size: 6041 bytes
+const slData string = "" + // Size: 5369 bytes
"\x02Napaka\x02(brez argumenta): povzdigni na skrbniške pravice in namest" +
"i skrbniško storitev\x02Uporaba: %[1]s [\x0a%[2]s]\x02Možnosti ukazne vr" +
"stice\x02Napaka pri določanju ali proces teče kot WOW64: %[1]v\x02Na tem" +
@@ -2009,232 +3105,557 @@ const slData string = "" + // Size: 6041 bytes
"inut\x14\x01\x81\x01\x00\x04\x0e\x02%[1]d sekunde\x02\x0e\x02%[1]d sekun" +
"do\x03\x0e\x02%[1]d sekundi\x00\x0d\x02%[1]d sekund\x02%[1]s nazaj\x02%[" +
"1]d\u00a0B\x02%.2[1]f\u00a0KiB\x02%.2[1]f\u00a0MiB\x02%.2[1]f\u00a0GiB" +
- "\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02Napačen naslov IP\x02Napačna dol" +
- "žina predpone omrežja\x02Pri končni točki manjkajo vrata\x02Pri končni " +
- "točki je gostitelj napačen\x02Oklepaji morajo vsebovati naslov IPv6\x02N" +
- "apačen MTU\x02Napačna vrata\x02Napačno trajno ohranjanje povezave\x02Nap" +
- "ačen ključ: %[1]v\x02Dekodirani ključi morajo biti natanko 32 bajtov\x02" +
- "Številka mora biti število med 0 in 2^64-1: %[1]v\x02Dve zaporedni veji" +
- "ci\x02Ime tunela ni veljavno\x02Vrstica mora biti v odseku\x02Ključu v k" +
- "onfiguraciji manjka ločilo enačaj\x02Ključ mora imeti vrednost\x02Napače" +
- "n ključ za odsek [Interface]\x02Napačen ključ za odsek [Peer]\x02Vmesnik" +
- " mora imeti zasebni ključ\x02[ni navedeno]\x02Vsi vrstniki morajo imeti " +
- "javni ključ\x02Napaka pri branju konfiguracije\x02Napačen ključ za odsek" +
- " vmesnika\x02Verzija protokola mora biti 1\x02Napačen ključ za odsek vrs" +
- "tnika\x02, \x02 \x02O WireGuardu\x02Slika WireGuardovega logotipa\x02Ver" +
- "zija aplikacije: %[1]s\x0aVerzija wireguard-go: %[2]s\x0aVerzija Go: %[3" +
- "]s-%[4]s\x0aOperacijski sistem: %[5]s\x0aArhitektura: %[6]s\x02Zapri\x02" +
- "♥ &Doniraj!\x02Status:\x02&Deaktiviraj\x02&Aktiviraj\x02Javni ključ:" +
- "\x02Vrata poslušanja:\x02MTU:\x02Naslovi:\x02Strežniki DNS:\x02Skripta:" +
- "\x02Ključ v skupni rabi:\x02Dovoljeni IP-ji:\x02Končna točka:\x02Trajno " +
- "ohranjanje povezave:\x02Zadnje rokovanje:\x02Prenos:\x02onemogočeno, zar" +
- "adi politike\x02omogočeno\x02%[1]s prejeto, %[2]s poslano\x02Napaka pri " +
- "določanju stanja tunela\x02Napaka pri aktiviranju tunela\x02Napaka pri d" +
- "eaktiviranju tunela\x02Vmesnik: %[1]s\x02Vrstnik\x02Ustvari nov tunel" +
- "\x02Uredi tunel\x02&Ime:\x02&Javni ključ:\x02(neznano)\x02&Blokiraj prom" +
- "et izven tunela (varovalka)\x02Kadar ima konfiguracija natanko enega vrs" +
- "tnika in njegov spisek dovoljenih IP-jev vsebuje vsaj enega izmed 0.0.0." +
- "0/0 ali ::/0, bo storitev tunela vzpostavila pravila požarnega zidu, ki " +
- "bodo blokirala ves promet, ki ni niti za niti iz vmesnika tunela oz. za " +
- "napačen strežnik DNS, s posebnimi izjemami za DHCP and NDP.\x02&Shrani" +
- "\x02Prekliči\x02&Konfiguracija:\x02Napačno ime\x02Ime je obvezno.\x02Ime" +
- " tunela »%[1]s« ni veljavno.\x02Napaka pri pripravi seznama obstoječih t" +
- "unelov\x02Tunel že obstaja\x02Drug tunel z imenom »%[1]s« že obstaja." +
- "\x02Napaka pri izdelavi nove konfiguracije\x02Napaka pri pisanju v datot" +
- "eko\x02Datoteka »%[1]s« že obstaja.\x0a\x0aAli jo želite prepisati?\x02A" +
- "ktivno\x02Se aktivira\x02Neaktivno\x02Se deaktivira\x02Neznano stanje" +
- "\x02Dnevnik\x02&Kopiraj\x02&Izberi vse\x02&Shrani v datoteko\u00a0…\x02Č" +
- "as\x02Sporočilo v dnevniku\x02Tekstovne datoteke (*.txt)|*.txt|Vse datot" +
- "eke (*.*)|*.*\x02Izvozi dnevnik v datoteko\x02O WireGu&ardu\u00a0…\x02Na" +
- "paka tunela\x02%[1]s\x0a\x0aDodatne informacije najdete v dnevniku.\x02%" +
- "[1]s (neposodobljen)\x02Napaka zaznavanja WireGuarda\x02Čakanje, da se p" +
- "ojavi WireGuardovo okno, ni možno: %[1]v\x02WireGuard: Deaktiviran\x02St" +
- "atus: Neznan\x02Naslovi: Brez\x02&Upravljaj tunele\u00a0…\x02&Uvozi tune" +
- "l(e) iz datoteke…\x02I&zhod\x02WireGuard aktiviran\x02Tunel %[1]s je bil" +
- " aktiviran.\x02WireGuard deaktiviran\x02Tunel %[1]s je bil deaktiviran." +
- "\x02Napaka tunela WireGuard\x02WireGuard: %[1]s\x02Status: %[1]s\x02Nasl" +
- "ovi: %[1]s\x02Na voljo je posodobitev!\x02Posodobitev WireGuarda je na v" +
- "oljo\x02Posodobitev WireGuarda je na voljo. Svetujemo posodobitev čim pr" +
- "ej.\x02Tuneli\x02&Uredi\x02Dodaj &prazen tunel\u00a0…\x02Dodaj tunel\x02" +
- "Odstrani izbrane tunele\x02Izvozi vse tunele v zip\x02&Preklopi\x02Izvoz" +
- "i vse tunele v &zip\u00a0…\x02Uredi &izbran tunel\u00a0…\x02Odst&rani iz" +
- "brane tunele\x02ni najdenih konfiguracijskih datotek\x02Napaka pri uvozu" +
- " izbrane konfiguracije: %[1]v\x02Napaka pri preštevanju obstoječih tunel" +
- "ov: %[1]v\x02Tunel z imenom »%[1]s« že obstaja\x02Napaka pri uvozu konfi" +
- "guracije: %[1]v\x02Uvoženi tuneli\x14\x01\x81\x01\x00\x04\x16\x02Uvoženi" +
- " %[1]d tuneli\x02\x14\x02Uvožen %[1]d tunel\x03\x16\x02Uvožena %[1]d tun" +
- "ela\x00\x17\x02Uvoženo %[1]d tunelov\x14\x02\x80\x01\x04 \x02Uvoženi %[1" +
- "]d od %[2]d tunelov\x02\x1f\x02Uvožen %[1]d od %[2]d tunelov\x03 \x02Uvo" +
- "žena %[1]d od %[2]d tunelov\x00 \x02Uvoženo %[1]d od %[2]d tunelov\x02T" +
- "unela ni bilo mogoče ustvariti\x14\x01\x81\x01\x00\x04\x16\x02Izbriši %[" +
- "1]d tunele\x02\x15\x02Izbriši %[1]d tunel\x03\x16\x02Izbriši %[1]d tunel" +
- "a\x00\x17\x02Izbriši %[1]d tunelov\x14\x01\x81\x01\x00\x048\x02Ali ste p" +
- "repričani, da želite izbrisati %[1]d tunele?\x027\x02Ali ste prepričani," +
- " da želite izbrisati %[1]d tunel?\x038\x02Ali ste prepričani, da želite " +
- "izbrisati %[1]d tunela?\x009\x02Ali ste prepričani, da želite izbrisati " +
- "%[1]d tunelov?\x02Izbriši tunel ‘%[1]s’\x02Ali ste prepričani, da želite" +
- " izbrisati tunel »%[1]s«?\x02%[1]s Tega dejanja ne morete razveljaviti." +
- "\x02Napaka pri izbrisu tunela\x02Napaka pri odstranjevanju tunela: %[1]s" +
- "\x02Napaka pri izbrisu tunelov\x14\x01\x81\x01\x00\x04*\x02%[1]d tunelov" +
- " ni bilo mogoče odstraniti.\x02)\x02%[1]d tunela ni bilo mogoče odstrani" +
- "ti.\x03*\x02%[1]d tunelov ni bilo mogoče odstraniti.\x00*\x02%[1]d tunel" +
- "ov ni bilo mogoče odstraniti.\x02Konfiguracijske datoteke (*.zip, *.conf" +
- ")|*.zip;*.conf|Vse datoteke (*.*)|*.*\x02Uvozi tunele iz datoteke\x02Kon" +
- "figuracijske datoteke ZIP (*.zip)|*.zip\x02Izvozi tunele v datoteko zip" +
- "\x02%[1]s (nepodpisane različice, brez posodobitev)\x02Napaka pri izhodu" +
- " iz WireGuarda\x02Storitve ni bilo mogoče zaustaviti, ker: %[1]v. Poskus" +
- "ite zaustaviti WireGuard z uporabo programa Storitve.\x02Posodobitev Wir" +
- "eGuarda je na voljo. Zelo priporočamo posodobitev brez odlašanja.\x02Sta" +
- "tus: Čaka na uporabnika\x02Posodobi zdaj\x02Status: Čaka na servis za po" +
- "sodobitev\x02Napaka: %[1]v. Poskusite ponovno.\x02Status: Končano!\x02pr" +
- "ed-aktivacijo\x02po-aktivaciji\x02pred-deaktivacijo\x02po-deaktivaciji" +
- "\x02&Tuneli"
+ "\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02Pri končni točki manjkajo vrata" +
+ "\x02Pri končni točki je gostitelj napačen\x02Oklepaji morajo vsebovati n" +
+ "aslov IPv6\x02Napačen MTU\x02Napačna vrata\x02Napačno trajno ohranjanje " +
+ "povezave\x02Napačen ključ: %[1]v\x02Dekodirani ključi morajo biti natank" +
+ "o 32 bajtov\x02Dve zaporedni vejici\x02Ime tunela ni veljavno\x02Vrstica" +
+ " mora biti v odseku\x02Ključu v konfiguraciji manjka ločilo enačaj\x02Kl" +
+ "juč mora imeti vrednost\x02Napačen ključ za odsek [Interface]\x02Napačen" +
+ " ključ za odsek [Peer]\x02Vmesnik mora imeti zasebni ključ\x02[ni navede" +
+ "no]\x02Vsi vrstniki morajo imeti javni ključ\x02, \x02 \x02O WireGuardu" +
+ "\x02Slika WireGuardovega logotipa\x02Zapri\x02♥ &Doniraj!\x02Status:\x02" +
+ "&Dezaktiviraj\x02&Aktiviraj\x02Javni ključ:\x02Vrata poslušanja:\x02MTU:" +
+ "\x02Naslovi:\x02Strežniki DNS:\x02Skripta:\x02Ključ v skupni rabi:\x02Do" +
+ "voljeni IP-ji:\x02Končna točka:\x02Trajno ohranjanje povezave:\x02Zadnje" +
+ " rokovanje:\x02Prenos:\x02pred-aktivacijo\x02po-aktivaciji\x02pred-dezak" +
+ "tivacijo\x02po-dezaktivaciji\x02onemogočeno, zaradi politike\x02omogočen" +
+ "o\x02%[1]s prejeto, %[2]s poslano\x02Napaka pri določanju stanja tunela" +
+ "\x02Napaka pri aktiviranju tunela\x02Napaka pri dezaktiviranju tunela" +
+ "\x02Vmesnik: %[1]s\x02Vrstnik\x02Ustvari nov tunel\x02Uredi tunel\x02&Im" +
+ "e:\x02&Javni ključ:\x02(neznano)\x02&Blokiraj promet izven tunela (varov" +
+ "alka)\x02&Shrani\x02Prekliči\x02&Konfiguracija:\x02Napačno ime\x02Ime je" +
+ " obvezno.\x02Ime tunela »%[1]s« ni veljavno.\x02Napaka pri pripravi sezn" +
+ "ama obstoječih tunelov\x02Tunel že obstaja\x02Drug tunel z imenom »%[1]s" +
+ "« že obstaja.\x02Napaka pri izdelavi nove konfiguracije\x02Napaka pri p" +
+ "isanju v datoteko\x02Datoteka »%[1]s« že obstaja.\x0a\x0aAli jo želite p" +
+ "repisati?\x02Aktivno\x02Se aktivira\x02Neaktivno\x02Se dezaktivira\x02Ne" +
+ "znano stanje\x02Dnevnik\x02&Kopiraj\x02&Izberi vse\x02&Shrani v datoteko" +
+ "\u00a0…\x02Čas\x02Sporočilo v dnevniku\x02Tekstovne datoteke (*.txt)|*.t" +
+ "xt|Vse datoteke (*.*)|*.*\x02Izvozi dnevnik v datoteko\x02O WireGu&ardu" +
+ "\u00a0…\x02Napaka tunela\x02%[1]s\x0a\x0aDodatne informacije najdete v d" +
+ "nevniku.\x02%[1]s (neposodobljen)\x02Napaka zaznavanja WireGuarda\x02Čak" +
+ "anje, da se pojavi WireGuardovo okno, ni možno: %[1]v\x02WireGuard: Deza" +
+ "ktiviran\x02Status: Neznan\x02Naslovi: Brez\x02&Upravljaj tunele\u00a0…" +
+ "\x02&Uvozi tunel(e) iz datoteke…\x02I&zhod\x02&Tuneli\x02WireGuard aktiv" +
+ "iran\x02Tunel %[1]s je bil aktiviran.\x02WireGuard dezaktiviran\x02Tunel" +
+ " %[1]s je bil dezaktiviran.\x02Napaka tunela WireGuard\x02WireGuard: %[1" +
+ "]s\x02Status: %[1]s\x02Naslovi: %[1]s\x02Na voljo je posodobitev!\x02Pos" +
+ "odobitev WireGuarda je na voljo\x02Posodobitev WireGuarda je na voljo. S" +
+ "vetujemo posodobitev čim prej.\x02Tuneli\x02&Uredi\x02Dodaj &prazen tune" +
+ "l\u00a0…\x02Dodaj tunel\x02Odstrani izbrane tunele\x02Izvozi vse tunele " +
+ "v zip\x02&Preklopi\x02Izvozi vse tunele v &zip\u00a0…\x02Uredi &izbran t" +
+ "unel\u00a0…\x02Odst&rani izbrane tunele\x02ni najdenih konfiguracijskih " +
+ "datotek\x02Napaka pri uvozu izbrane konfiguracije: %[1]v\x02Napaka pri p" +
+ "reštevanju obstoječih tunelov: %[1]v\x02Tunel z imenom »%[1]s« že obstaj" +
+ "a\x02Napaka pri uvozu konfiguracije: %[1]v\x02Uvoženi tuneli\x14\x01\x81" +
+ "\x01\x00\x04\x16\x02Uvoženi %[1]d tuneli\x02\x14\x02Uvožen %[1]d tunel" +
+ "\x03\x16\x02Uvožena %[1]d tunela\x00\x17\x02Uvoženo %[1]d tunelov\x14" +
+ "\x02\x80\x01\x04 \x02Uvoženi %[1]d od %[2]d tunelov\x02\x1f\x02Uvožen %[" +
+ "1]d od %[2]d tunelov\x03 \x02Uvožena %[1]d od %[2]d tunelov\x00 \x02Uvož" +
+ "eno %[1]d od %[2]d tunelov\x02Tunela ni bilo mogoče ustvariti\x14\x01" +
+ "\x81\x01\x00\x04\x16\x02Izbriši %[1]d tunele\x02\x15\x02Izbriši %[1]d tu" +
+ "nel\x03\x16\x02Izbriši %[1]d tunela\x00\x17\x02Izbriši %[1]d tunelov\x14" +
+ "\x01\x81\x01\x00\x048\x02Ali ste prepričani, da želite izbrisati %[1]d t" +
+ "unele?\x027\x02Ali ste prepričani, da želite izbrisati %[1]d tunel?\x038" +
+ "\x02Ali ste prepričani, da želite izbrisati %[1]d tunela?\x009\x02Ali st" +
+ "e prepričani, da želite izbrisati %[1]d tunelov?\x02Izbriši tunel ‘%[1]s" +
+ "’\x02Ali ste prepričani, da želite izbrisati tunel »%[1]s«?\x02%[1]s T" +
+ "ega dejanja ne morete razveljaviti.\x02Napaka pri izbrisu tunela\x02Napa" +
+ "ka pri odstranjevanju tunela: %[1]s\x02Napaka pri izbrisu tunelov\x14" +
+ "\x01\x81\x01\x00\x04*\x02%[1]d tunelov ni bilo mogoče odstraniti.\x02)" +
+ "\x02%[1]d tunela ni bilo mogoče odstraniti.\x03*\x02%[1]d tunelov ni bil" +
+ "o mogoče odstraniti.\x00*\x02%[1]d tunelov ni bilo mogoče odstraniti." +
+ "\x02Konfiguracijske datoteke (*.zip, *.conf)|*.zip;*.conf|Vse datoteke (" +
+ "*.*)|*.*\x02Uvozi tunele iz datoteke\x02Konfiguracijske datoteke ZIP (*." +
+ "zip)|*.zip\x02Izvozi tunele v datoteko zip\x02%[1]s (nepodpisane različi" +
+ "ce, brez posodobitev)\x02Napaka pri izhodu iz WireGuarda\x02Storitve ni " +
+ "bilo mogoče zaustaviti, ker: %[1]v. Poskusite zaustaviti WireGuard z upo" +
+ "rabo programa Storitve.\x02Posodobitev WireGuarda je na voljo. Zelo prip" +
+ "oročamo posodobitev brez odlašanja.\x02Status: Čaka na uporabnika\x02Pos" +
+ "odobi zdaj\x02Status: Čaka na servis za posodobitev\x02Napaka: %[1]v. Po" +
+ "skusite ponovno.\x02Status: Končano!"
+
+var sv_SEIndex = []uint32{ // 180 elements
+ // Entry 0 - 1F
+ 0x00000000, 0x00000004, 0x0000003c, 0x00000058,
+ 0x0000006f, 0x000000af, 0x000000f7, 0x0000012f,
+ 0x00000188, 0x000001ef, 0x00000227, 0x0000022a,
+ 0x00000252, 0x0000026f, 0x0000028e, 0x000002b0,
+ 0x000002d3, 0x000002f8, 0x00000304, 0x0000030d,
+ 0x0000031a, 0x00000327, 0x00000334, 0x00000341,
+ 0x0000034e, 0x0000036a, 0x00000382, 0x000003ae,
+ 0x000003ba, 0x000003c7, 0x000003e4, 0x000003fa,
+ // Entry 20 - 3F
+ 0x00000423, 0x0000043a, 0x00000451, 0x00000477,
+ 0x000004ab, 0x000004c7, 0x000004f1, 0x00000516,
+ 0x00000549, 0x00000559, 0x00000581, 0x00000584,
+ 0x00000587, 0x00000594, 0x000005ab, 0x000005b2,
+ 0x000005bf, 0x000005c7, 0x000005d3, 0x000005dd,
+ 0x000005ec, 0x000005fb, 0x00000600, 0x0000060a,
+ 0x00000617, 0x0000061f, 0x00000631, 0x00000642,
+ 0x0000064d, 0x00000663, 0x00000679, 0x00000687,
+ // Entry 40 - 5F
+ 0x00000696, 0x000006a5, 0x000006b6, 0x000006c7,
+ 0x000006df, 0x000006e9, 0x00000707, 0x00000737,
+ 0x00000753, 0x00000770, 0x00000783, 0x00000788,
+ 0x00000798, 0x000007a8, 0x000007af, 0x000007bf,
+ 0x000007c8, 0x000007f0, 0x000007f7, 0x000007fe,
+ 0x0000080e, 0x0000081c, 0x0000082d, 0x00000854,
+ 0x00000876, 0x00000889, 0x000008bd, 0x000008dc,
+ 0x000008fd, 0x00000937, 0x0000093d, 0x00000947,
+ // Entry 60 - 7F
+ 0x0000094e, 0x0000095b, 0x0000096d, 0x00000972,
+ 0x0000097b, 0x00000989, 0x0000099c, 0x000009a0,
+ 0x000009af, 0x000009dc, 0x000009f4, 0x00000a05,
+ 0x00000a0f, 0x00000a48, 0x00000a5c, 0x00000a6e,
+ 0x00000aae, 0x00000ac5, 0x00000ad4, 0x00000ae4,
+ 0x00000af8, 0x00000b18, 0x00000b21, 0x00000b2a,
+ 0x00000b3e, 0x00000b5c, 0x00000b72, 0x00000b92,
+ 0x00000ba6, 0x00000bb7, 0x00000bc5, 0x00000bd5,
+ // Entry 80 - 9F
+ 0x00000bf6, 0x00000c19, 0x00000c83, 0x00000c8b,
+ 0x00000c95, 0x00000caf, 0x00000cbc, 0x00000cd2,
+ 0x00000cf2, 0x00000cfa, 0x00000d1e, 0x00000d37,
+ 0x00000d4e, 0x00000d70, 0x00000d9f, 0x00000dd4,
+ 0x00000e0b, 0x00000e33, 0x00000e47, 0x00000e83,
+ 0x00000ed1, 0x00000ee7, 0x00000f1b, 0x00000f8c,
+ 0x00000fa7, 0x00000fe2, 0x0000100b, 0x00001023,
+ 0x00001048, 0x00001061, 0x000010b0, 0x000010f5,
+ // Entry A0 - BF
+ 0x00001111, 0x00001136, 0x00001151, 0x0000117d,
+ 0x0000119b, 0x0000120c, 0x00001268, 0x00001288,
+ 0x00001295, 0x000012bd, 0x000012e2, 0x000012f3,
+ 0x000012f3, 0x000012f3, 0x000012f3, 0x000012f3,
+ 0x000012f3, 0x000012f3, 0x000012f3, 0x000012f3,
+} // Size: 744 bytes
+
+const sv_SEData string = "" + // Size: 4851 bytes
+ "\x02Fel\x02(inget argument): höj och installera hanterartjänsten\x02Anvä" +
+ "ndning: %[1]s [\x0a%[2]s]\x02Kommandoradsalternativ\x02Det går inte att " +
+ "avgöra om processen körs under WOW64: %[1]v\x02Du måste använda den inby" +
+ "ggda versionen av WireGuard på denna dator.\x02Det går inte att öppna nu" +
+ "varande process-token: %[1]v\x02WireGuard får endast användas av använda" +
+ "re som är medlemmar i gruppen Builtin %[1]s.\x02WireGuard körs, men grän" +
+ "ssnittet är endast tillgängligt från skrivbordet i gruppen Builtin %[1]s" +
+ ".\x02WireGuard systemfältet visades inte efter 30 sekunder.\x02Nu\x02Sys" +
+ "temets klocka har ställts tillbaka!\x14\x01\x81\x01\x00\x02\x0a\x02%[1]d" +
+ " år\x00\x0a\x02%[1]d år\x14\x01\x81\x01\x00\x02\x0a\x02%[1]d dag\x00\x0c" +
+ "\x02%[1]d dagar\x14\x01\x81\x01\x00\x02\x0c\x02%[1]d timme\x00\x0d\x02%[" +
+ "1]d timmar\x14\x01\x81\x01\x00\x02\x0c\x02%[1]d minut\x00\x0e\x02%[1]d m" +
+ "inuter\x14\x01\x81\x01\x00\x02\x0d\x02%[1]d sekund\x00\x0f\x02%[1]d seku" +
+ "nder\x02%[1]s sedan\x02%[1]d\u00a0B\x02%.2[1]f\u00a0KiB\x02%.2[1]f\u00a0" +
+ "MiB\x02%.2[1]f\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02Saknad po" +
+ "rt från slutpunkt\x02Ogiltig slutpunktsvärd\x02Parenteser måste innehåll" +
+ "a en IPv6-adress\x02Ogiltig MTU\x02Ogiltig port\x02Ogiltig beständig kee" +
+ "palive\x02Ogiltig nyckel: %[1]v\x02Nycklar måste avkoda till exakt 32 by" +
+ "te\x02Två kommatecken i rad\x02Tunnelnamn är ogiltig\x02Linje måste före" +
+ "komma i ett avsnitt\x02Konfigurationsnyckel saknar en likvärdig separato" +
+ "r\x02Nyckel måste ha ett värde\x02Ogiltig nyckel för sektionen [Interfac" +
+ "e]\x02Ogiltig nyckel för sektionen [Peer]\x02Ett gränssnitt måste innehå" +
+ "lla en privat nyckel\x02[ingen angiven]\x02Alla peers måste ha offentlig" +
+ "a nycklar\x02, \x02, \x02Om WireGuard\x02WireGuard-logotyp bild\x02Stäng" +
+ "\x02♥ &Donera!\x02Status:\x02&Avaktivera\x02&Aktivera\x02Publik nyckel:" +
+ "\x02Lyssningsport:\x02MTU:\x02Adresser:\x02DNS-servrar:\x02Skript:\x02Fö" +
+ "rdelad nyckel:\x02Tillåtna IP: s:\x02Slutpunkt:\x02Beständig keepalive:" +
+ "\x02Senaste handskakning:\x02Överföring:\x02före uppstart\x02efter uppst" +
+ "art\x02innan nertagning\x02efter nedtagning\x02inaktiverad, per policy" +
+ "\x02aktiverad\x02%[1]s mottagen, %[2]s skickad\x02Det gick inte att best" +
+ "ämma tunnelns tillstånd\x02Kunde inte aktivera tunneln\x02Kunde inte av" +
+ "aktivera tunnel\x02Gränssnitt: %[1]s\x02Peer\x02Skapa ny tunnel\x02Redig" +
+ "era tunnel\x02&Namn:\x02&Publik nyckel:\x02(okänd)\x02&Blockera otunnlad" +
+ " trafik (kill-switch)\x02&Spara\x02Avbryt\x02&Konfiguration:\x02Ogiltigt" +
+ " namn\x02Ett namn krävs.\x02Tunnelnamnet ‘%[1]s’ är ogiltigt.\x02Kan int" +
+ "e lista befintliga tunnlar\x02Tunnel finns redan\x02En annan tunnel finn" +
+ "s redan med namnet ‘%[1]s’.\x02Kan inte skapa ny inställning\x02Misslyck" +
+ "ades att skriva till fil\x02Filen ‘%[1]s’ finns redan.\x0a\x0aVill du sk" +
+ "riva över den?\x02Aktiv\x02Aktiverar\x02Passiv\x02Passiviserar\x02Okänt " +
+ "tillstånd\x02Logg\x02&Kopiera\x02Markera &allt\x02&Spara till fil…\x02Ti" +
+ "d\x02Loggmeddelande\x02Textfiler (*.txt)|*.txt|Alla filer (*.*)|*.*\x02E" +
+ "xportera logg till fil\x02&Om WireGuard…\x02Tunnelfel\x02%[1]s\x0a\x0aVä" +
+ "nligen inspektera loggen för mer information.\x02%[1]s (föråldrad)\x02Wi" +
+ "reGuard Vaktfel\x02Lyckas inte vänta på att WireGuard fönstret ska visas" +
+ ": %[1]v\x02WireGuard: inaktiverad\x02Status: Okänd\x02Adresser: Ingen" +
+ "\x02&Hantera tunnlar…\x02&Importera tunnlar från fil…\x02A&vsluta\x02&Tu" +
+ "nnlar\x02WireGuard aktiverad\x02%[1]s tunneln har aktiverats.\x02WireGua" +
+ "rd inaktiverad\x02%[1]s tunneln har inaktiverats.\x02WireGuard Tunnelfel" +
+ "\x02WireGuard: %[1]s\x02Status: %[1]s\x02Adresser: %[1]s\x02En uppdateri" +
+ "ng är tillgänglig!\x02WireGuard uppdatering tillgänglig\x02En uppdaterin" +
+ "g till WireGuard är nu tillgänglig. Du rekommenderas att uppdatera så sn" +
+ "art som möjligt.\x02Tunnlar\x02&Redigera\x02Lägg till &tom tunnel…\x02Sk" +
+ "apa tunnel\x02Ta bort valda tunnlar\x02Exportera alla tunnlar till zip" +
+ "\x02&Växla\x02Exportera alla tunnlar till &zip…\x02Redigera &vald tunnel" +
+ "…\x02&Ta bort valda tunnlar\x02inga konfigurationsfiler hittades\x02Ku" +
+ "nde inte importera vald konfiguration: %[1]v\x02Det gick inte att numrer" +
+ "a existerande tunnlar: %[1]v\x02Det finns redan en annan tunnel med namn" +
+ "et ‘%[1]s’\x02Kan inte importera konfiguration: %[1]v\x02Importerade tun" +
+ "nlar\x14\x01\x81\x01\x00\x02\x19\x02Importerade %[1]d tunnel\x00\x1a\x02" +
+ "Importerade %[1]d tunnlar\x14\x02\x80\x01\x02#\x02Importerade %[1]d av %" +
+ "[2]d tunnlar\x00#\x02Importerade %[1]d av %[2]d tunnlar\x02Kan inte skap" +
+ "a tunnel\x14\x01\x81\x01\x00\x02\x15\x02Ta bort %[1]d tunnel\x00\x16\x02" +
+ "Ta bort %[1]d tunnlar\x14\x01\x81\x01\x00\x024\x02Är du säker på att du " +
+ "vill ta bort %[1]d tunnel?\x004\x02Är du säker på att du vill radera %[1" +
+ "]d tunnlar?\x02Ta bort tunnel ‘%[1]s’\x02Är du säker på att du vill ta b" +
+ "ort tunneln ‘%[1]s’?\x02%[1]s Du kan inte ångra denna åtgärd.\x02Kan int" +
+ "e ta bort tunnel\x02En tunnel kunde inte tas bort: %[1]s\x02Kan inte ta " +
+ "bort tunnlar\x14\x01\x81\x01\x00\x02#\x02%[1]d tunneln kunde inte tas bo" +
+ "rt.\x00#\x02%[1]d tunnlar kunde inte tas bort.\x02Inställningsfiler (*.z" +
+ "ip, *.conf)|*.zip;*.conf|Alla filer (*.*)|*.*\x02Importera tunnlar från " +
+ "fil\x02Inställningsfiler ZIP (*.zip)|*.zip\x02Exportera tunnlar till zip" +
+ "\x02%[1]s (osignerat bygge, inga uppdateringar)\x02Fel när WireGuard avs" +
+ "lutades\x02Det går inte att avsluta tjänsten på grund av %[1]v. Du kansk" +
+ "e vill stoppa WireGuard från servicehanteraren.\x02En uppdatering av Wir" +
+ "eGuard finns tillgänglig. Uppdatering bör utföras snarast möjligt.\x02St" +
+ "atus: Väntar på användaren\x02Uppdatera nu\x02Status: Väntar på uppdater" +
+ "ingstjänst\x02Fel: %[1]v. Vänligen försök igen.\x02Status: Färdig!"
-var ukIndex = []uint32{ // 181 elements
+var trIndex = []uint32{ // 180 elements
// Entry 0 - 1F
- 0x00000000, 0x0000000f, 0x0000000f, 0x0000000f,
- 0x00000042, 0x0000009c, 0x0000009c, 0x000000f5,
- 0x00000191, 0x00000213, 0x0000026a, 0x00000275,
- 0x000002c8, 0x000002c8, 0x000002c8, 0x000002c8,
- 0x000002c8, 0x000002c8, 0x000002d7, 0x000002e0,
- 0x000002ed, 0x000002fa, 0x00000307, 0x00000314,
- 0x00000314, 0x00000335, 0x00000371, 0x000003ac,
- 0x000003e4, 0x0000041f, 0x00000436, 0x00000452,
+ 0x00000000, 0x00000005, 0x00000053, 0x0000006d,
+ 0x00000089, 0x000000cd, 0x00000112, 0x0000013d,
+ 0x00000181, 0x000001fa, 0x00000238, 0x0000023f,
+ 0x0000025d, 0x0000027c, 0x0000029b, 0x000002ba,
+ 0x000002dd, 0x00000300, 0x0000030c, 0x00000315,
+ 0x00000322, 0x0000032f, 0x0000033c, 0x00000349,
+ 0x00000356, 0x0000036c, 0x00000380, 0x000003ae,
+ 0x000003bc, 0x000003cb, 0x000003e8, 0x00000401,
// Entry 20 - 3F
- 0x00000452, 0x00000475, 0x00000475, 0x00000475,
- 0x00000494, 0x00000494, 0x000004da, 0x00000535,
- 0x00000567, 0x0000059f, 0x000005d2, 0x00000619,
- 0x0000063e, 0x0000068a, 0x000006cc, 0x00000713,
- 0x0000074d, 0x0000074d, 0x0000074d, 0x0000074d,
- 0x0000075e, 0x0000078e, 0x0000078e, 0x0000079d,
- 0x000007bc, 0x000007ca, 0x000007e4, 0x000007fa,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
+ 0x00000437, 0x0000044c, 0x00000468, 0x0000048f,
+ 0x000004c2, 0x000004e4, 0x00000512, 0x0000053b,
+ 0x00000563, 0x00000572, 0x0000059f, 0x000005a2,
+ 0x000005a5, 0x000005b9, 0x000005ca, 0x000005d0,
+ 0x000005e3, 0x000005ea, 0x00000600, 0x0000060e,
+ 0x0000061d, 0x0000062c, 0x00000631, 0x0000063b,
+ 0x0000064c, 0x00000656, 0x00000675, 0x0000068d,
+ 0x00000698, 0x000006ac, 0x000006c2, 0x000006cc,
// Entry 40 - 5F
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
+ 0x000006df, 0x000006f3, 0x0000070c, 0x00000726,
+ 0x00000741, 0x00000747, 0x00000769, 0x00000785,
+ 0x000007a0, 0x000007c5, 0x000007d5, 0x000007d9,
+ 0x000007ee, 0x000007ff, 0x00000807, 0x00000817,
+ 0x00000824, 0x00000858, 0x00000860, 0x00000867,
+ 0x00000878, 0x00000887, 0x0000089e, 0x000008c5,
+ 0x000008e4, 0x000008f8, 0x00000926, 0x0000094b,
+ 0x0000095e, 0x0000099d, 0x000009a3, 0x000009b6,
// Entry 60 - 7F
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
+ 0x000009c4, 0x000009e1, 0x000009f2, 0x000009fb,
+ 0x00000a04, 0x00000a14, 0x00000a27, 0x00000a2c,
+ 0x00000a3d, 0x00000a74, 0x00000a8e, 0x00000aa6,
+ 0x00000ab5, 0x00000af2, 0x00000b07, 0x00000b20,
+ 0x00000b54, 0x00000b6d, 0x00000b7f, 0x00000b8d,
+ 0x00000ba3, 0x00000bc6, 0x00000bd1, 0x00000bdc,
+ 0x00000bec, 0x00000c0c, 0x00000c31, 0x00000c5b,
+ 0x00000c74, 0x00000c85, 0x00000c92, 0x00000ca2,
// Entry 80 - 9F
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
+ 0x00000cb6, 0x00000cd5, 0x00000d39, 0x00000d43,
+ 0x00000d4d, 0x00000d62, 0x00000d6e, 0x00000d8a,
+ 0x00000db2, 0x00000dbd, 0x00000de9, 0x00000e07,
+ 0x00000e24, 0x00000e48, 0x00000e7b, 0x00000ea2,
+ 0x00000ecf, 0x00000ef9, 0x00000f14, 0x00000f59,
+ 0x00000fa9, 0x00000fc1, 0x00000fee, 0x0000105d,
+ 0x00001077, 0x000010b2, 0x000010d7, 0x000010e9,
+ 0x0000110c, 0x00001121, 0x00001168, 0x000011b7,
// Entry A0 - BF
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817, 0x00000817, 0x00000817, 0x00000817,
- 0x00000817,
-} // Size: 748 bytes
+ 0x000011d6, 0x00001202, 0x00001225, 0x0000124f,
+ 0x0000126b, 0x000012d8, 0x0000133f, 0x0000135d,
+ 0x0000136e, 0x00001399, 0x000013bf, 0x000013d3,
+ 0x000013d3, 0x000013d3, 0x000013d3, 0x000013d3,
+ 0x000013d3, 0x000013d3, 0x000013d3, 0x000013d3,
+} // Size: 744 bytes
-const ukData string = "" + // Size: 2071 bytes
- "\x02Помилка\x02Параметри командного рядка\x02Неможливо визначити, чи пра" +
- "цює процес під WOW64: %[1]v\x02Не вдалося відкрити токен поточного проц" +
- "есу: %[1]v\x02WireGuard може бути використаний тільки користувачами, як" +
- "і є членами вбудованих %[1]s груп.\x02WireGuard запущено, але UI доступ" +
- "ний лише з комп\x22ютерів вбудованої %[1]s групи.\x02Значок системи Wir" +
- "eGuard не з'явився через 30 секунд.\x02Зараз\x02Системний годинник налаш" +
- "тований некоректно!\x02%[1]s тому\x02%[1]d Б\x02%.2[1]f КБ\x02%.2[1]f М" +
- "Б\x02%.2[1]f ГБ\x02%.2[1]f ТБ\x02Недійсна IP-адреса\x02Невірна довжина " +
- "префіксу мережі\x02Відсутній порт з кінцевої точки\x02Недійсний хост кі" +
- "нцевої точки\x02Дужки повинні містити адресу IPv6\x02Недійсний MTU\x02Н" +
- "едійсний порт\x02Недійсний ключ: %[1]v\x02Дві коми поспіль\x02Рядок пов" +
- "инен бути вказаним у розділі\x02Ключ конфігурації відсутній роздільник " +
- "рівності\x02Ключ повинен мати значення\x02Хибний ключ для [Interface] р" +
- "озділу\x02Хибний ключ для [Peer] розділу\x02Інтерфейс повинен мати особ" +
- "истий ключ\x02[жодного не вказано]\x02Всі учасники повинні мати відкрит" +
- "і ключі\x02Помилка при отриманні конфігурації\x02Недійсний ключ для роз" +
- "ділу інтерфейсу\x02Версія протоколу повинна бути 1\x02Про WireGuard\x02" +
- "Зображення логотипу WireGuard\x02Закрити\x02♥ &Пожертвувати!\x02Статус:" +
- "\x02&Деактивувати\x02&Активувати\x02Відкритий ключ:"
+const trData string = "" + // Size: 5075 bytes
+ "\x02Hata\x02(parametre belirtilmediyse): gerekli izinleri al ve yönetim " +
+ "hizmetini yükle\x02Kullanım: %[1]s [\x0a%[2]s]\x02Komut Satırı Seçenekle" +
+ "ri\x02İşlemin WOW64 altında çalıştığından emin olunamadı: %[1]v\x02Bu bi" +
+ "lgisayarda WireGuard'ın yerel sürümünü kullanmalısınız.\x02Geçerli işlem" +
+ " jetonu açılamadı: %[1]v\x02WireGuard'ı sadece yerleşik %[1]s grubunun ü" +
+ "yeleri kullanabilir.\x02WireGuard çalışıyor fakat kullanıcı arayüzüne sa" +
+ "dece yerleşik %[1]s grubunun bilgisayarlarından erişilebilir.\x02WireGua" +
+ "rd sistem tepsisi simgesi 30 saniye sonunda belirmedi.\x02Şimdi\x02Siste" +
+ "m saati geri alınmış!\x14\x01\x81\x01\x00\x02\x0b\x02%[1]d yıl\x00\x0b" +
+ "\x02%[1]d yıl\x14\x01\x81\x01\x00\x02\x0b\x02%[1]d gün\x00\x0b\x02%[1]d " +
+ "gün\x14\x01\x81\x01\x00\x02\x0b\x02%[1]d saat\x00\x0b\x02%[1]d saat\x14" +
+ "\x01\x81\x01\x00\x02\x0d\x02%[1]d dakika\x00\x0d\x02%[1]d dakika\x14\x01" +
+ "\x81\x01\x00\x02\x0d\x02%[1]d saniye\x00\x0d\x02%[1]d saniye\x02%[1]s ön" +
+ "ce\x02%[1]d\u00a0B\x02%.2[1]f\u00a0KiB\x02%.2[1]f\u00a0MiB\x02%.2[1]f" +
+ "\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02Uç nokta portu eksik" +
+ "\x02Geçersiz uç nokta\x02Köşeli parantezler IPv6 adresi içermelidir\x02G" +
+ "eçersiz MTU\x02Geçersiz port\x02Geçersiz sürekli keepalive\x02Geçersiz a" +
+ "nahtar: %[1]v\x02Anahtarlar çözüldüğünde tam 32 bayt olmalıdır\x02Yan ya" +
+ "na iki virgül\x02Tünel adı geçerli değil\x02Satır bir bölüm içinde olmal" +
+ "ıdır\x02Yapılandırma anahtarında eşittir ayracı eksik\x02Anahtar bir de" +
+ "ğere sahip olmalı\x02[Interface] bölümü için geçersiz anahtar\x02[Peer]" +
+ " bölümü için geçersiz anahtar\x02Arabirimde gizli anahtar bulunmalıdır" +
+ "\x02[belirtilmedi]\x02Tüm eşlerin ortak anahtarları olmalıdır\x02, \x02," +
+ " \x02WireGuard Hakkında\x02WireGuard logosu\x02Kapat\x02♥ &Bağış yap!" +
+ "\x02Durum:\x02&Devre dışı bırak\x02&Etkinleştir\x02Ortak anahtar:\x02Din" +
+ "lenen port:\x02MTU:\x02Adresler:\x02DNS sunucuları:\x02Betikler:\x02Önce" +
+ "den paylaşılan anahtar:\x02İzin verilen IP’ler:\x02Uç nokta:\x02Sürekli " +
+ "keepalive:\x02En son el sıkışma:\x02Aktarım:\x02bağlantı öncesi\x02bağla" +
+ "ntı sonrası\x02bağlantı kesme öncesi\x02bağlantı kesme sonrası\x02ilke g" +
+ "ereği devre dışı\x02etkin\x02%[1]s alındı, %[2]s gönderildi\x02Tünel dur" +
+ "umu belirlenemedi\x02Tünel etkinleştirilemedi\x02Tünel devre dışı bırakı" +
+ "lamadı\x02Arabirim: %[1]s\x02Eş\x02Yeni tünel oluştur\x02Tüneli düzenle" +
+ "\x02&İsim:\x02&Ortak anahtar:\x02(bilinmiyor)\x02&Tünelden geçmeyen traf" +
+ "iği engelle (kill switch)\x02&Kaydet\x02İptal\x02&Yapılandırma:\x02Geçer" +
+ "siz isim\x02Bir isim girmelisiniz.\x02‘%[1]s’ geçersiz bir tünel ismi." +
+ "\x02Mevcut tüneller listelenemedi\x02Tünel zaten mevcut\x02‘%[1]s’ adınd" +
+ "a başka bir tünel mevcut.\x02Yeni yapılandırma oluşturulamadı\x02Dosya y" +
+ "azılamadı\x02`%[1]s` dosyası zaten mevcut.\x0a\x0aÜzerine yazmak ister m" +
+ "isiniz?\x02Etkin\x02Etkinleştiriliyor\x02Devre dışı\x02Devre dışı bırakı" +
+ "lıyor\x02Durum bilinmiyor\x02Günlük\x02&Kopyala\x02&Tümünü seç\x02&Dosya" +
+ "ya kaydet…\x02Saat\x02Günlük mesajı\x02Metin dosyaları (*.txt)|*.txt|Tüm" +
+ " dosyalar (*.*)|*.*\x02Günlüğü dosyaya aktar\x02&WireGuard hakkında…\x02" +
+ "Tünel Hatası\x02%[1]s\x0a\x0aDaha fazla bilgi için lütfen günlüğe göz at" +
+ "ın.\x02%[1]s (eski sürüm)\x02WireGuard Tespit Hatası\x02WireGuard pence" +
+ "resinin belirmesi beklenemedi: %[1]v\x02WireGuard: Devre dışı\x02Durum: " +
+ "Bilinmiyor\x02Adresler: Yok\x02&Tünelleri yönet…\x02Tünelleri dosyadan &" +
+ "içe aktar…\x02Çı&kış\x02&Tüneller\x02WireGuard Etkin\x02%[1]s tüneli etk" +
+ "inleştirildi.\x02WireGuard Devre Dışı Bırakıldı\x02%[1]s tüneli devre dı" +
+ "şı bırakıldı.\x02WireGuard Tünel Hatası\x02WireGuard: %[1]s\x02Durum: %" +
+ "[1]s\x02Adresler: %[1]s\x02Güncelleme Mevcut!\x02WireGuard Güncellemesi " +
+ "Mevcut\x02Yeni bir WireGuard güncellemesi yayımlandı. İlk fırsatta günce" +
+ "lleme yapmanız tavsiye edilir.\x02Tüneller\x02&Düzenle\x02Boş tünel &ekl" +
+ "e…\x02Tünel ekle\x02Seçilen tünelleri kaldır\x02Tüm tünelleri zip olarak" +
+ " dışa aktar\x02&Aç/kapat\x02Tüm tünelleri &zip olarak dışa aktar…\x02&Se" +
+ "çilen tüneli düzenle…\x02S&eçilen tünelleri kaldır\x02yapılandırma dosy" +
+ "ası bulunamadı\x02Seçilen yapılandırma içe aktarılamadı: %[1]v\x02Mevcut" +
+ " tüneller sıralanamadı: %[1]v\x02‘%[1]s’ adında başka bir tünel mevcut" +
+ "\x02Yapılandırma içe aktarılamadı: %[1]v\x02Tüneller içe aktarıldı\x14" +
+ "\x01\x81\x01\x00\x02\x1e\x02%[1]d tünel içe aktarıldı\x00\x1e\x02%[1]d t" +
+ "ünel içe aktarıldı\x14\x02\x80\x01\x02$\x02%[2]d/%[1]d tünel içe aktarı" +
+ "ldı\x00$\x02%[2]d/%[1]d tünel içe aktarıldı\x02Tünel oluşturulamadı\x14" +
+ "\x01\x81\x01\x00\x02\x12\x02%[1]d tüneli sil\x00\x12\x02%[1]d tüneli sil" +
+ "\x14\x01\x81\x01\x00\x023\x02%[1]d tüneli silmek istediğinizden emin mis" +
+ "iniz?\x003\x02%[1]d tüneli silmek istediğinizden emin misiniz?\x02‘%[1]s" +
+ "’ tünelini sil\x02‘%[1]s’ tünelini silmek istediğinizden emin misiniz?" +
+ "\x02%[1]s Bu işlemi geri alamazsınız.\x02Tünel silinemedi\x02Bir tünel k" +
+ "aldırılamadı: %[1]s\x02Tüneller silinemedi\x14\x01\x81\x01\x00\x02\x1f" +
+ "\x02%[1]d tünel kaldırılamadı.\x00\x1f\x02%[1]d tünel kaldırılamadı.\x02" +
+ "Yapılandırma dosyaları (*.zip, *.conf)|*.zip;*.conf|Tüm dosyalar (*.*)|*" +
+ ".*\x02Tünelleri dosyadan içe aktar\x02Yapılandırma ZIP dosyaları (*.zip)" +
+ "|*.zip\x02Tünelleri zip olarak dışa aktar\x02%[1]s (imzasız derleme, gün" +
+ "celleme yok)\x02WireGuard Çıkış Hatası\x02Şu nedenden dolayı hizmetten ç" +
+ "ıkılamadı: %[1]v. WireGuard'ı hizmet yöneticisinden durdurabilirsiniz." +
+ "\x02Yeni bir WireGuard güncellemesi yayımlandı. Vakit kaybetmeden güncel" +
+ "leme yapmanız tavsiye edilir.\x02Durum: Kullanıcı bekleniyor\x02Şimdi gü" +
+ "ncelle\x02Durum: Güncelleştirme hizmeti bekleniyor\x02Hata: %[1]v. Lütfe" +
+ "n yeniden deneyin.\x02Durum: Tamamlandı!"
-var viIndex = []uint32{ // 181 elements
+var ukIndex = []uint32{ // 180 elements
// Entry 0 - 1F
- 0x00000000, 0x00000006, 0x00000006, 0x00000006,
- 0x00000006, 0x00000006, 0x00000006, 0x00000006,
- 0x00000006, 0x00000006, 0x00000006, 0x00000011,
- 0x00000011, 0x00000023, 0x00000036, 0x00000049,
- 0x0000005c, 0x0000006f, 0x0000007e, 0x0000007e,
- 0x0000007e, 0x0000007e, 0x0000007e, 0x0000007e,
- 0x0000007e, 0x000000a0, 0x000000a0, 0x000000a0,
- 0x000000a0, 0x000000a0, 0x000000a0, 0x000000c0,
+ 0x00000000, 0x0000000f, 0x0000008e, 0x000000b7,
+ 0x000000ea, 0x00000144, 0x000001c2, 0x0000021b,
+ 0x000002b7, 0x00000339, 0x00000390, 0x0000039b,
+ 0x000003ee, 0x00000439, 0x00000480, 0x000004d7,
+ 0x00000534, 0x00000591, 0x000005a0, 0x000005a9,
+ 0x000005b6, 0x000005c3, 0x000005d0, 0x000005dc,
+ 0x000005e9, 0x00000624, 0x0000065c, 0x00000697,
+ 0x000006ae, 0x000006ca, 0x000006fa, 0x0000071d,
// Entry 20 - 3F
- 0x000000c0, 0x000000c0, 0x000000c0, 0x000000c0,
- 0x000000c0, 0x000000db, 0x000000db, 0x000000db,
- 0x000000db, 0x000000db, 0x000000db, 0x000000db,
- 0x000000db, 0x000000db, 0x000000db, 0x000000db,
- 0x000000db, 0x000000db, 0x000000db, 0x000000db,
- 0x000000f5, 0x00000104, 0x00000104, 0x0000010b,
- 0x0000010b, 0x0000011a, 0x0000011a, 0x0000011a,
- 0x0000011a, 0x0000011a, 0x0000011a, 0x0000011a,
+ 0x0000075f, 0x0000077e, 0x000007ab, 0x000007f1,
+ 0x0000084c, 0x0000087e, 0x000008b6, 0x000008e9,
+ 0x00000930, 0x00000955, 0x000009a1, 0x000009a4,
+ 0x000009a7, 0x000009b8, 0x000009e8, 0x000009f7,
+ 0x00000a16, 0x00000a24, 0x00000a3e, 0x00000a54,
+ 0x00000a71, 0x00000a7b, 0x00000a80, 0x00000a8e,
+ 0x00000aa2, 0x00000ab2, 0x00000ac6, 0x00000aea,
+ 0x00000af4, 0x00000b0a, 0x00000b35, 0x00000b47,
// Entry 40 - 5F
- 0x0000011a, 0x0000011a, 0x0000011a, 0x0000011a,
- 0x00000129, 0x00000129, 0x00000129, 0x00000129,
- 0x00000129, 0x0000013b, 0x00000155, 0x00000181,
- 0x0000019f, 0x000001c0, 0x000001c0, 0x000001d3,
- 0x000001dd, 0x000001ef, 0x000001ef, 0x000001ef,
- 0x000001ef, 0x000001ef, 0x000001ef, 0x000001ef,
- 0x000001f5, 0x000001f5, 0x0000020c, 0x00000224,
- 0x0000024a, 0x0000026b, 0x00000280, 0x000002ad,
+ 0x00000b63, 0x00000b7d, 0x00000b99, 0x00000bb3,
+ 0x00000bf0, 0x00000c03, 0x00000c38, 0x00000c75,
+ 0x00000cab, 0x00000ce5, 0x00000cff, 0x00000d06,
+ 0x00000d2f, 0x00000d51, 0x00000d5e, 0x00000d7c,
+ 0x00000d91, 0x00000dca, 0x00000ddc, 0x00000def,
+ 0x00000e0a, 0x00000e1d, 0x00000e46, 0x00000e79,
+ 0x00000ec0, 0x00000edf, 0x00000f18, 0x00000f5e,
+ 0x00000f85, 0x00000fdf, 0x00000ff0, 0x00001007,
// Entry 60 - 7F
- 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
- 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
- 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
- 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
- 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
- 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
- 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
- 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
+ 0x0000101c, 0x00001033, 0x0000104f, 0x00001056,
+ 0x0000106c, 0x00001081, 0x000010a2, 0x000010a9,
+ 0x000010ce, 0x00001114, 0x00001140, 0x00001155,
+ 0x00001171, 0x000011f5, 0x00001212, 0x0000123e,
+ 0x0000128e, 0x000012ac, 0x000012cd, 0x000012e6,
+ 0x0000130e, 0x00001344, 0x00001350, 0x0000135e,
+ 0x0000137d, 0x000013a6, 0x000013c9, 0x000013ff,
+ 0x00001425, 0x00001436, 0x0000144a, 0x0000145e,
// Entry 80 - 9F
- 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
- 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
- 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
- 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
- 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
- 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
- 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
- 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
+ 0x00001483, 0x000014b1, 0x0000152a, 0x00001537,
+ 0x0000154d, 0x00001578, 0x00001592, 0x000015bd,
+ 0x000015f1, 0x00001607, 0x0000163f, 0x00001676,
+ 0x000016a2, 0x000016de, 0x00001738, 0x00001788,
+ 0x000017c0, 0x0000180b, 0x0000182f, 0x000018e8,
+ 0x000019c8, 0x000019fa, 0x00001a9b, 0x00001be2,
+ 0x00001c08, 0x00001c5a, 0x00001c99, 0x00001cca,
+ 0x00001d03, 0x00001d34, 0x00001e29, 0x00001e86,
// Entry A0 - BF
- 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
- 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
- 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
- 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
- 0x000002ad, 0x000002ad, 0x000002ad, 0x000002ad,
- 0x000002ad,
-} // Size: 748 bytes
+ 0x00001eb8, 0x00001ef0, 0x00001f1d, 0x00001f66,
+ 0x00001f96, 0x0000203e, 0x000020aa, 0x000020e4,
+ 0x000020fe, 0x00002146, 0x00002192, 0x000021af,
+ 0x000021af, 0x000021af, 0x000021af, 0x000021af,
+ 0x000021af, 0x000021af, 0x000021af, 0x000021af,
+} // Size: 744 bytes
-const viData string = "" + // Size: 685 bytes
- "\x02Lỗi\x02Vừa xong\x14\x01\x81\x01\x00\x00\x0b\x02%[1]d năm\x14\x01\x81" +
- "\x01\x00\x00\x0c\x02%[1]d ngày\x14\x01\x81\x01\x00\x00\x0c\x02%[1]d giờ" +
- "\x14\x01\x81\x01\x00\x00\x0c\x02%[1]d phút\x14\x01\x81\x01\x00\x00\x0c" +
- "\x02%[1]d giây\x02%[1]s trước\x02Địa chỉ IP không hợp lệ\x02Cổng (port) " +
- "không hợp lệ\x02Tên VPN không hợp lệ\x02Thông tin về WireGuard\x02Logo W" +
- "ireGuard\x02Đóng\x02Trạng thái:\x02Đầu cuối:\x02đã kích hoạt\x02Nhận %[1" +
- "]s, gứi %[2]s\x02Không thể xác định tình trạng VPN\x02Không thể kích hoạ" +
- "t VPN\x02Không thể vô hiệu hóa VPN\x02Mạng ngang hàng\x02Tạo VPN\x02Chỉn" +
- "h sửa VPN\x02Huỷ\x02Tên không hợp lệ\x02Yêu cầu nhập tên.\x02Tên VPN ‘%[" +
- "1]s' không hợp lệ.\x02Không thể liệt kê các VPN\x02VPN đã tồn tại\x02Đã " +
- "tồn tại VPN với tên ‘%[1]s’."
+const ukData string = "" + // Size: 8623 bytes
+ "\x02Помилка\x02(немає аргумента): отримати права аднімістратора і встано" +
+ "вити службу\x02Використання: %[1]s [\x0a%[2]s]\x02Параметри командного " +
+ "рядка\x02Неможливо визначити, чи працює процес під WOW64: %[1]v\x02Ви п" +
+ "овинні використовувати нативну версію WireGuard на цьому комп'ютері." +
+ "\x02Не вдалося відкрити токен поточного процесу: %[1]v\x02WireGuard може" +
+ " бути використаний тільки користувачами, які є членами вбудованих %[1]s " +
+ "груп.\x02WireGuard запущено, але UI доступний лише з комп\x22ютерів вбу" +
+ "дованої %[1]s групи.\x02Значок системи WireGuard не з'явився через 30 с" +
+ "екунд.\x02Зараз\x02Системний годинник налаштований некоректно!\x14\x01" +
+ "\x81\x01\x00\x04\x0f\x02%[1]d роки\x05\x11\x02%[1]d років\x02\x0d\x02%[1" +
+ "]d рік\x00\x11\x02%[1]d років\x14\x01\x81\x01\x00\x04\x0d\x02%[1]d дні" +
+ "\x05\x0f\x02%[1]d днів\x02\x0f\x02%[1]d день\x00\x0f\x02%[1]d днів\x14" +
+ "\x01\x81\x01\x00\x04\x13\x02%[1]d години\x05\x13\x02%[1]d години\x02\x13" +
+ "\x02%[1]d година\x00\x11\x02%[1]d годин\x14\x01\x81\x01\x00\x04\x15\x02%" +
+ "[1]d хвилини\x05\x13\x02%[1]d хвилин\x02\x15\x02%[1]d хвилина\x00\x13" +
+ "\x02%[1]d хвилин\x14\x01\x81\x01\x00\x04\x15\x02%[1]d секунди\x05\x13" +
+ "\x02%[1]d секунд\x02\x15\x02%[1]d секунда\x00\x13\x02%[1]d секунд\x02%[1" +
+ "]s тому\x02%[1]d Б\x02%.2[1]f КБ\x02%.2[1]f МБ\x02%.2[1]f ГБ\x02%.2[1]f " +
+ "TiB\x02%[1]s: %[2]q\x02Відсутній порт з кінцевої точки\x02Недійсний хост" +
+ " кінцевої точки\x02Дужки повинні містити адресу IPv6\x02Недійсний MTU" +
+ "\x02Недійсний порт\x02Некоректне значення keepalive\x02Недійсний ключ: %" +
+ "[1]v\x02Ключ повинен декодуватись до 32 байт\x02Дві коми поспіль\x02Назв" +
+ "а тунелю некоректна\x02Рядок повинен бути вказаним у розділі\x02Ключ ко" +
+ "нфігурації відсутній роздільник рівності\x02Ключ повинен мати значення" +
+ "\x02Хибний ключ для [Interface] розділу\x02Хибний ключ для [Peer] розділ" +
+ "у\x02Інтерфейс повинен мати особистий ключ\x02[жодного не вказано]\x02В" +
+ "сі учасники повинні мати відкриті ключі\x02, \x02, \x02Про WireGuard" +
+ "\x02Зображення логотипу WireGuard\x02Закрити\x02♥ &Пожертвувати!\x02Стат" +
+ "ус:\x02&Деактивувати\x02&Активувати\x02Відкритий ключ:\x02Порт:\x02MTU:" +
+ "\x02Адреси:\x02DNS-сервери:\x02Скрипти:\x02Preshared ключ:\x02Дозволені " +
+ "IP адреси:\x02Endpoint:\x02Persistent keepalive:\x02Останнє рукостисканн" +
+ "я:\x02Передано:\x02перед-запуском\x02після-запуску\x02перед-зупинкою" +
+ "\x02після-зупинки\x02вимкнено, відповідно до політики\x02увімкнено\x02%[" +
+ "1]s отримано, %[2]s відправлено\x02Не вдалося визначити стан тунелю\x02Н" +
+ "е вдалося активувати тунель\x02Не вдалося деактивувати тунель\x02Інтерф" +
+ "ейс: %[1]s\x02Пір\x02Створити новий тунель\x02Редагувати тунель\x02&Наз" +
+ "ва:\x02&Публічний ключ:\x02(невідомий)\x02&Блокувати трафік поза тунеле" +
+ "м\x02&Зберегти\x02Скасувати\x02&Налаштування:\x02Хибне ім'я\x02Необхідн" +
+ "о ввести ім'я.\x02Ім'я тунелю '%[1]s' некоректне.\x02Не вдалося відобра" +
+ "зити існуючі тунелі\x02Тунель вже існує\x02Тунель з ім'ям ‘%[1]s’ вже і" +
+ "снує.\x02Неможливо створити нову конфігурацію\x02Помилка запису файлу" +
+ "\x02Файл \x22%[1]s\x22 вже існує.\x0a\x0aВи хочете перезаписати його?" +
+ "\x02Активний\x02Активується\x02Неактивний\x02Вимикається\x02Невідомий ст" +
+ "ан\x02Лог\x02&Скопіювати\x02Обрати &все\x02&Зберегти у файл…\x02Час\x02" +
+ "Повідомлення з логу\x02Текстові файли (*.txt)|*.txt|Усі файли (*.*)|*.*" +
+ "\x02Експортувати лог у файл\x02&Про WireGuard…\x02Помилка тунелю\x02%[1]" +
+ "s\x0a\x0aБудь ласка, зверніться до логу для отримання додаткової інформа" +
+ "ції.\x02%[1]s (застарілий)\x02Помилка виявлення WireGuard\x02Не вдалося" +
+ " дочекатися появи вікна WireGuard: %[1]v\x02WireGuard: Вимкнений\x02Стат" +
+ "ус: Невідомий\x02Адреси: немає\x02&Керування тунелями…\x02&Імпортувати " +
+ "тунель з файлу…\x02Ви&йти\x02&Тунелі\x02WireGuard активовано\x02Тунель " +
+ "%[1]s активовано.\x02WireGuard деактивовано\x02Тунель %[1]s було деактив" +
+ "овано.\x02Помилка тунелю WireGuard\x02WireGuard: %[1]s\x02Статус: %[1]s" +
+ "\x02Адреси: %[1]s\x02Доступно оновлення!\x02Доступне оновлення WireGuard" +
+ "\x02Оновлення до WireGuard доступне. Рекомендуємо оновити якомога швидше" +
+ ".\x02Тунелі\x02&Редагувати\x02Додати &пустий тунель…\x02Додати тунель" +
+ "\x02Видалити обрані тунелі\x02Експортувати всі тунелі в zip\x02&Перемкну" +
+ "ти\x02Експортувати всі тунелі в &zip…\x02Редагувати &вибраний тунель…" +
+ "\x02&Видалити обрані тунелі\x02не знайдено файлів конфігурації\x02Не вда" +
+ "лося імпортувати вибрану конфігурацію: %[1]v\x02Не вдалося перерахувати" +
+ " існуючі тунелі: %[1]v\x02Тунель з ім'ям ‘%[1]s’ вже існує\x02Не вдалося" +
+ " імпортувати конфігурацію: %[1]v\x02Імпортовано тунелі\x14\x01\x81\x01" +
+ "\x00\x04*\x02Імпортовано %[1]d тунелі\x05,\x02Імпортовано %[1]d тунелів" +
+ "\x02*\x02Імпортовано %[1]d тунель\x00,\x02Імпортовано %[1]d тунелів\x14" +
+ "\x02\x80\x01\x045\x02Імпортовано %[1]d з %[2]d тунелів\x055\x02Імпортова" +
+ "но %[1]d з %[2]d тунелів\x025\x02Імпортовано %[1]d з %[2]d тунелів\x005" +
+ "\x02Імпортовано %[1]d з %[2]d тунелів\x02Не вдалося створити тунель\x14" +
+ "\x01\x81\x01\x00\x04$\x02Видалити %[1]d тунелі\x05&\x02Видалити %[1]d ту" +
+ "нелів\x02$\x02Видалити %[1]d тунель\x00&\x02Видалити %[1]d тунелів\x14" +
+ "\x01\x81\x01\x00\x04N\x02Ви впевнені, що хочете видалити %[1]d тунелі?" +
+ "\x05P\x02Ви впевнені, що хочете видалити %[1]d тунелів?\x02N\x02Ви впевн" +
+ "ені, що хочете видалити %[1]d тунель?\x00N\x02Ви впевнені, що хочете ви" +
+ "далити %[1]d тунелі?\x02Видалити тунель '%[1]s'\x02Ви впевнені, що бажа" +
+ "єте видалити тунель '%[1]s'?\x02%[1]s Цю дію не можна буде скасувати." +
+ "\x02Неможливо видалити тунель\x02Тунель не вдалося видалити: %[1]s\x02Не" +
+ "можливо видалити тунелі\x14\x01\x81\x01\x00\x049\x02%[1]d тунелі не вда" +
+ "лося видалити.\x05;\x02%[1]d тунелів не вдалося видалити.\x029\x02%[1]d" +
+ " тунель не вдалося видалити.\x00;\x02%[1]d тунелів не вдалося видалити." +
+ "\x02Файли конфігурації (*.zip, *.conf)|*.zip;*.conf|Всі файли (*.*)|*.*" +
+ "\x02Імпортувати тунелі з файлу\x02ZIP-файли конфігурації (*.zip) | *.zip" +
+ "\x02Експортувати тунелі в zip\x02%[1]s (непідписані збірки, немає оновле" +
+ "нь)\x02Помилка при виході з WireGuard\x02Не вдалося зупинити службу чер" +
+ "ез: %[1]v. Ви можете зупинити її вручну через менеджер сервісів.\x02Дос" +
+ "тупне оновлення WireGuard, доцільне оновлення без затримок.\x02Статус: " +
+ "Очікування користувача\x02Оновити зараз\x02Статус: Очікування на службу" +
+ " оновлення\x02Помилка: %[1]v. Будь ласка, спробуйте ще раз.\x02Стан: Зав" +
+ "ершено"
-var zh_CNIndex = []uint32{ // 181 elements
+var viIndex = []uint32{ // 180 elements
+ // Entry 0 - 1F
+ 0x00000000, 0x00000006, 0x00000006, 0x00000022,
+ 0x0000003b, 0x0000003b, 0x0000003b, 0x0000003b,
+ 0x0000003b, 0x0000003b, 0x0000003b, 0x00000046,
+ 0x00000046, 0x00000058, 0x0000006b, 0x0000007e,
+ 0x00000091, 0x000000a4, 0x000000b3, 0x000000bb,
+ 0x000000c7, 0x000000d3, 0x000000df, 0x000000eb,
+ 0x000000eb, 0x000000eb, 0x000000eb, 0x000000eb,
+ 0x00000103, 0x00000123, 0x00000123, 0x00000142,
+ // Entry 20 - 3F
+ 0x00000142, 0x00000142, 0x0000015d, 0x0000015d,
+ 0x0000015d, 0x0000015d, 0x0000015d, 0x0000015d,
+ 0x0000015d, 0x00000172, 0x00000172, 0x00000174,
+ 0x00000176, 0x00000190, 0x0000019f, 0x000001a6,
+ 0x000001a6, 0x000001b5, 0x000001cd, 0x000001da,
+ 0x000001da, 0x000001da, 0x000001da, 0x000001da,
+ 0x000001da, 0x000001da, 0x000001da, 0x000001da,
+ 0x000001e9, 0x000001e9, 0x000001e9, 0x000001e9,
+ // Entry 40 - 5F
+ 0x000001e9, 0x000001e9, 0x000001e9, 0x000001e9,
+ 0x000001e9, 0x000001fb, 0x00000215, 0x00000241,
+ 0x0000025f, 0x00000280, 0x00000280, 0x00000293,
+ 0x0000029d, 0x000002af, 0x000002af, 0x000002af,
+ 0x000002af, 0x000002af, 0x000002af, 0x000002b5,
+ 0x000002b5, 0x000002cc, 0x000002e4, 0x0000030a,
+ 0x0000032b, 0x00000340, 0x0000036d, 0x0000036d,
+ 0x0000036d, 0x0000036d, 0x0000036d, 0x0000036d,
+ // Entry 60 - 7F
+ 0x0000036d, 0x0000036d, 0x0000036d, 0x0000036d,
+ 0x0000036d, 0x0000036d, 0x0000036d, 0x0000036d,
+ 0x0000036d, 0x0000036d, 0x0000036d, 0x0000036d,
+ 0x0000036d, 0x0000036d, 0x0000036d, 0x0000036d,
+ 0x0000036d, 0x0000036d, 0x0000036d, 0x0000036d,
+ 0x0000036d, 0x0000036d, 0x0000036d, 0x0000036d,
+ 0x0000036d, 0x0000036d, 0x0000036d, 0x0000036d,
+ 0x0000036d, 0x0000036d, 0x0000036d, 0x0000036d,
+ // Entry 80 - 9F
+ 0x0000036d, 0x0000036d, 0x0000036d, 0x0000036d,
+ 0x0000036d, 0x0000036d, 0x0000036d, 0x0000036d,
+ 0x0000036d, 0x0000036d, 0x0000036d, 0x0000036d,
+ 0x0000036d, 0x0000036d, 0x0000036d, 0x0000036d,
+ 0x0000036d, 0x0000036d, 0x0000036d, 0x0000036d,
+ 0x0000036d, 0x0000036d, 0x0000036d, 0x0000036d,
+ 0x0000036d, 0x0000036d, 0x0000036d, 0x0000036d,
+ 0x0000036d, 0x0000036d, 0x0000036d, 0x0000036d,
+ // Entry A0 - BF
+ 0x0000036d, 0x0000036d, 0x0000036d, 0x0000036d,
+ 0x0000036d, 0x0000036d, 0x0000036d, 0x0000036d,
+ 0x0000036d, 0x0000036d, 0x0000036d, 0x0000036d,
+ 0x0000036d, 0x0000036d, 0x0000036d, 0x0000036d,
+ 0x0000036d, 0x0000036d, 0x0000036d, 0x0000036d,
+} // Size: 744 bytes
+
+const viData string = "" + // Size: 877 bytes
+ "\x02Lỗi\x02Sử dụng: %[1]s [\x0a%[2]s]\x02Tùy chọn dòng lệnh\x02Vừa xong" +
+ "\x14\x01\x81\x01\x00\x00\x0b\x02%[1]d năm\x14\x01\x81\x01\x00\x00\x0c" +
+ "\x02%[1]d ngày\x14\x01\x81\x01\x00\x00\x0c\x02%[1]d giờ\x14\x01\x81\x01" +
+ "\x00\x00\x0c\x02%[1]d phút\x14\x01\x81\x01\x00\x00\x0c\x02%[1]d giây\x02" +
+ "%[1]s trước\x02%[1]d B\x02%.2[1]f KiB\x02%.2[1]f MiB\x02%.2[1]f GiB\x02%" +
+ ".2[1]f TiB\x02Khoá không hợp lệ\x02Cổng (port) không hợp lệ\x02Khoá khôn" +
+ "g hợp lệ: %[1]v\x02Tên VPN không hợp lệ\x02Ko có Chỉ định\x02,\x02,\x02T" +
+ "hông tin về WireGuard\x02Logo WireGuard\x02Đóng\x02Trạng thái:\x02Đã hủy" +
+ " kích hoạt\x02Kích hoạt\x02Đầu cuối:\x02đã kích hoạt\x02Nhận %[1]s, gứi " +
+ "%[2]s\x02Không thể xác định tình trạng VPN\x02Không thể kích hoạt VPN" +
+ "\x02Không thể vô hiệu hóa VPN\x02Mạng ngang hàng\x02Tạo VPN\x02Chỉnh sửa" +
+ " VPN\x02Huỷ\x02Tên không hợp lệ\x02Yêu cầu nhập tên.\x02Tên VPN ‘%[1]s' " +
+ "không hợp lệ.\x02Không thể liệt kê các VPN\x02VPN đã tồn tại\x02Đã tồn t" +
+ "ại VPN với tên ‘%[1]s’."
+
+var zh_CNIndex = []uint32{ // 180 elements
// Entry 0 - 1F
0x00000000, 0x00000007, 0x00000030, 0x00000047,
0x00000057, 0x0000008b, 0x000000c9, 0x000000ef,
@@ -2242,54 +3663,53 @@ var zh_CNIndex = []uint32{ // 181 elements
0x000001e5, 0x000001f6, 0x00000207, 0x0000021b,
0x0000022f, 0x00000240, 0x0000024a, 0x00000252,
0x0000025f, 0x0000026c, 0x00000279, 0x00000286,
- 0x00000293, 0x000002a2, 0x000002bb, 0x000002dd,
- 0x00000304, 0x0000032c, 0x00000337, 0x00000344,
+ 0x00000293, 0x000002b5, 0x000002dc, 0x00000304,
+ 0x0000030f, 0x0000031c, 0x00000335, 0x0000034d,
// Entry 20 - 3F
- 0x0000035d, 0x00000375, 0x0000039f, 0x000003cd,
- 0x000003e6, 0x000003f9, 0x00000415, 0x0000043a,
- 0x0000044d, 0x0000046c, 0x00000486, 0x000004a2,
- 0x000004ae, 0x000004d0, 0x000004e6, 0x000004ff,
- 0x00000517, 0x00000530, 0x00000534, 0x00000536,
- 0x00000547, 0x0000055d, 0x000005c7, 0x000005ce,
- 0x000005df, 0x000005e7, 0x000005f3, 0x000005ff,
- 0x00000607, 0x00000615, 0x0000061a, 0x00000622,
+ 0x00000377, 0x0000038d, 0x000003a0, 0x000003bc,
+ 0x000003e1, 0x000003f4, 0x00000419, 0x00000439,
+ 0x00000455, 0x00000461, 0x00000483, 0x00000487,
+ 0x00000489, 0x0000049a, 0x000004b0, 0x000004b7,
+ 0x000004c8, 0x000004d0, 0x000004dc, 0x000004e8,
+ 0x000004f0, 0x000004fe, 0x00000503, 0x0000050b,
+ 0x0000051a, 0x00000522, 0x00000533, 0x00000541,
+ 0x00000549, 0x0000055d, 0x00000571, 0x00000579,
// Entry 40 - 5F
- 0x00000631, 0x00000639, 0x0000064a, 0x00000658,
- 0x00000660, 0x00000674, 0x00000688, 0x00000690,
- 0x000006af, 0x000006b9, 0x000006d4, 0x000006ed,
- 0x00000700, 0x00000719, 0x00000727, 0x0000072e,
- 0x0000073e, 0x0000074b, 0x00000758, 0x00000765,
- 0x0000076e, 0x0000079d, 0x00000873, 0x0000087f,
- 0x00000886, 0x00000893, 0x000008a0, 0x000008b6,
- 0x000008d4, 0x000008ed, 0x000008fd, 0x0000091e,
+ 0x00000583, 0x0000058d, 0x00000597, 0x000005a1,
+ 0x000005c0, 0x000005ca, 0x000005e5, 0x000005fe,
+ 0x00000611, 0x0000062a, 0x00000638, 0x0000063f,
+ 0x0000064f, 0x0000065c, 0x00000669, 0x00000676,
+ 0x0000067f, 0x000006ae, 0x000006ba, 0x000006c1,
+ 0x000006ce, 0x000006db, 0x000006f1, 0x0000070f,
+ 0x00000728, 0x00000738, 0x00000759, 0x00000772,
+ 0x00000785, 0x000007c0, 0x000007ca, 0x000007d7,
// Entry 60 - 7F
- 0x00000937, 0x0000094a, 0x00000985, 0x0000098f,
- 0x0000099c, 0x000009a6, 0x000009b3, 0x000009ba,
- 0x000009c1, 0x000009cd, 0x000009d9, 0x000009e8,
- 0x000009ef, 0x000009fc, 0x00000a2e, 0x00000a3b,
- 0x00000a54, 0x00000a61, 0x00000a87, 0x00000a99,
- 0x00000ab0, 0x00000adb, 0x00000af0, 0x00000aff,
- 0x00000b0b, 0x00000b20, 0x00000b3e, 0x00000b4a,
- 0x00000b5e, 0x00000b7c, 0x00000b90, 0x00000bb4,
+ 0x000007e1, 0x000007ee, 0x000007f5, 0x000007fc,
+ 0x00000808, 0x00000814, 0x00000823, 0x0000082a,
+ 0x00000837, 0x00000869, 0x00000876, 0x0000088f,
+ 0x0000089c, 0x000008c2, 0x000008d4, 0x000008eb,
+ 0x00000916, 0x0000092b, 0x0000093a, 0x00000946,
+ 0x0000095b, 0x00000979, 0x00000985, 0x00000991,
+ 0x000009a5, 0x000009c3, 0x000009d7, 0x000009fb,
+ 0x00000a12, 0x00000a23, 0x00000a31, 0x00000a3f,
// Entry 80 - 9F
- 0x00000bcb, 0x00000bdc, 0x00000bea, 0x00000bf8,
- 0x00000c08, 0x00000c19, 0x00000c5b, 0x00000c62,
- 0x00000c6e, 0x00000c86, 0x00000c93, 0x00000ca6,
- 0x00000cc9, 0x00000ce1, 0x00000d0c, 0x00000d27,
- 0x00000d3f, 0x00000d55, 0x00000d6f, 0x00000d8f,
- 0x00000dbc, 0x00000dd6, 0x00000de3, 0x00000e04,
- 0x00000e3a, 0x00000e4d, 0x00000e6b, 0x00000e9e,
- 0x00000eb6, 0x00000ee0, 0x00000efe, 0x00000f11,
+ 0x00000a4f, 0x00000a60, 0x00000aa2, 0x00000aa9,
+ 0x00000ab5, 0x00000acd, 0x00000ada, 0x00000aed,
+ 0x00000b10, 0x00000b28, 0x00000b53, 0x00000b6e,
+ 0x00000b86, 0x00000b9c, 0x00000bb6, 0x00000bd6,
+ 0x00000c03, 0x00000c1d, 0x00000c2a, 0x00000c4b,
+ 0x00000c81, 0x00000c94, 0x00000cb2, 0x00000ce5,
+ 0x00000cfd, 0x00000d27, 0x00000d45, 0x00000d58,
+ 0x00000d72, 0x00000d85, 0x00000dac, 0x00000ded,
// Entry A0 - BF
- 0x00000f2b, 0x00000f3e, 0x00000f65, 0x00000fa6,
- 0x00000fbc, 0x00000fd7, 0x00000ffa, 0x00001027,
- 0x00001042, 0x000010a3, 0x000010db, 0x000010f0,
- 0x000010fd, 0x00001118, 0x00001135, 0x00001147,
- 0x00001151, 0x0000115b, 0x00001165, 0x0000116f,
- 0x0000117b,
-} // Size: 748 bytes
+ 0x00000e03, 0x00000e1e, 0x00000e41, 0x00000e6e,
+ 0x00000e89, 0x00000eea, 0x00000f22, 0x00000f37,
+ 0x00000f44, 0x00000f5f, 0x00000f7c, 0x00000f8e,
+ 0x00000f8e, 0x00000f8e, 0x00000f8e, 0x00000f8e,
+ 0x00000f8e, 0x00000f8e, 0x00000f8e, 0x00000f8e,
+} // Size: 744 bytes
-const zh_CNData string = "" + // Size: 4475 bytes
+const zh_CNData string = "" + // Size: 3982 bytes
"\x02错误\x02(无参数): 提升并安装管理服务\x02用法: %[1]s [\x0a%[2]s]\x02命令行选项\x02无法确定该进程是" +
"否在WOW64下运行: %[1]v\x02您必须在此计算机上使用原生版本的 WireGuard。\x02无法打开当前进程令牌: %[1]v" +
"\x02WireGuard 可能只能被内建的 %[1]s 小组中的成员使用。\x02WireGuard 正在运行,但用户界面只能从内建的 %[1" +
@@ -2298,140 +3718,134 @@ const zh_CNData string = "" + // Size: 4475 bytes
"\x01\x81\x01\x00\x00\x0d\x02%[1]d 小时\x14\x01\x81\x01\x00\x00\x0d\x02%[1]" +
"d 分钟\x14\x01\x81\x01\x00\x00\x0a\x02%[1]d 秒\x02%[1]s 前\x02%[1]d B\x02%.2" +
"[1]f\u00a0KiB\x02%.2[1]f\u00a0MiB\x02%.2[1]f\u00a0GiB\x02%.2[1]f\u00a0Ti" +
- "B\x02%[1]s: %[2]q\x02IP地址无效\x02网络前缀长度无效\x02对端 (endpoint) 中缺少端口\x02对端主机名 " +
- "(endpoint host) 无效\x02方括号中应包含一个 IPv6 地址\x02MTU 无效\x02端口无效\x02连接保活间隔无效" +
- "\x02无效的密钥:%[1]v\x02解码后的密钥长度必须为32字节\x02数值必须介于 0 至 2^64-1 之间: %[1]v\x02一行中" +
- "有两个逗号\x02隧道名称无效\x02行必须出现在段落中\x02配置项必须要有一个等于号\x02必须有一个值\x02[Interface] " +
- "段落的键无效\x02[Peer] 段落的键无效\x02接口必须有一个私钥\x02[未指定]\x02所有节点必须拥有公钥。\x02获取配置时出" +
- "错\x02接口段落的键无效\x02协议版本必须为 1\x02节点段落的键无效\x02、\x02 \x02关于 WireGuard\x02Wi" +
- "reGuard logo 图片\x02应用版本: %[1]s\x0aGo 后端版本: %[2]s\x0aGo 语言版本: %[3]s-%[4]s" +
- "\x0a操作系统: %[5]s\x0a架构: %[6]s\x02关闭\x02♥ 捐助! (&D)\x02状态:\x02断开 (&D)\x02连接" +
- " (&A)\x02公钥:\x02监听端口:\x02MTU:\x02地址:\x02DNS 服务器:\x02脚本:\x02预共享密钥:\x02允许的" +
- " IP:\x02对端:\x02连接保活间隔:\x02上次握手时间:\x02流量:\x02已禁用(依管理策略)\x02已启用\x02接收 %[1]" +
- "s, 发送 %[2]s\x02无法确认隧道状态\x02无法连接隧道\x02无法断开隧道连接\x02接口: %[1]s\x02节点\x02创建新隧" +
- "道\x02编辑隧道\x02名称 (&N):\x02公钥 (&P):\x02(未知)\x02拦截未经隧道的流量 (kill-switch) (" +
- "&B)\x02只有一个节点,且该节点允许的 IP 中包含 0.0.0.0/0 或 ::/0 时,使用防火墙规则拦截所有未通过隧道,或是发往错误的" +
- " DNS 服务器的流量。DHCP 和 NDP 流量不受影响。\x02保存 (&S)\x02取消\x02配置 (&C):\x02名称无效\x02必" +
- "须输入名称。\x02隧道名「%[1]s」无效。\x02无法列出现有隧道\x02隧道已存在\x02隧道名「%[1]s」已存在。\x02无法创建" +
- "新的配置\x02写入文件失败\x02文件「%[1]s」已存在。\x0a\x0a您确定要覆盖它吗?\x02已连接\x02正在连接\x02已断开" +
- "\x02正在断开\x02未知\x02日志\x02复制 (&C)\x02全选 (&A)\x02导出… (&S)\x02时间\x02日志消息\x02" +
- "文本文件 (*.txt)|*.txt|所有文件 (*.*)|*.*\x02导出日志\x02关于 WireGuard… (&A)\x02隧道错" +
- "误\x02%[1]s\x0a\x0a更多信息请查看日志。\x02%[1]s (已过时)\x02WireGuard 检测错误\x02无法等待 " +
- "WireGuard 窗口出现: %[1]v\x02WireGuard: 已断开\x02状态: 未知\x02地址: 无\x02管理隧道… (&M)" +
- "\x02从文件导入隧道… (&I)\x02退出 (&E)\x02WireGuard 已连接\x02隧道「%[1]s」已连接。\x02WireGu" +
- "ard 已断开\x02隧道「%[1]s」已断开连接。\x02WireGuard 隧道错误\x02WireGuard: %[1]s\x02状态: " +
- "%[1]s\x02地址: %[1]s\x02发现更新!\x02WireGuard 更新\x02新的 WireGuard 版本发布了。强烈建议您现" +
- "在安装。\x02隧道\x02编辑 (&E)\x02新建空隧道… (&E)\x02新建隧道\x02删除所选隧道\x02导出所有隧道 (ZIP " +
- "压缩包)\x02切换连接状态 (&T)\x02导出所有隧道 (ZIP 压缩包)… (&Z)\x02编辑所选隧道… (&E)\x02删除所选隧" +
- "道 (&R)\x02未找到配置文件\x02无法导入配置: %[1]v\x02无法列出现有隧道: %[1]v\x02另一个同名的隧道「%[1]" +
- "s」已存在\x02无法导入配置: %[1]v\x02导入隧道\x14\x01\x81\x01\x00\x00\x1a\x02导入了 %[1]d " +
- "个隧道\x14\x02\x80\x01\x000\x02导入了 %[2]d 个隧道中的 %[1]d 个隧道\x02无法创建隧道\x14" +
- "\x01\x81\x01\x00\x00\x17\x02删除 %[1]d 个隧道\x14\x01\x81\x01\x00\x00,\x02您确定" +
- "要删除这 %[1]d 个隧道吗?\x02删除隧道「%[1]s」\x02您确定要删除隧道「%[1]s」吗?\x02%[1]s此操作无法撤销。" +
- "\x02无法删除隧道\x02无法删除隧道: %[1]s\x02无法删除隧道\x14\x01\x81\x01\x00\x00 \x02无法删除 %" +
- "[1]d 个隧道。\x02配置文件 (*.zip, *.conf)|*.zip;*.conf|所有文件 (*.*)|*.*\x02从文件导入隧道" +
- "\x02配置文件 (*.zip)|*.zip\x02导出配置文件 (ZIP 压缩包)\x02%[1]s (未签名版本,禁用自动更新)\x02退出" +
- " WireGuard 时出错\x02无法停止服务: %[1]v。您可能需要在服务管理器中手动停止 WireGuard 服务。\x02发现新版 W" +
- "ireGuard。强烈建议您现在安装。\x02状态: 等待用户\x02立即更新\x02状态: 等待更新服务\x02错误: %[1]v。请重试。" +
- "\x02状态: 完成!\x02连接前\x02连接后\x02断开前\x02断开后\x02隧道 (&T)"
+ "B\x02%[1]s: %[2]q\x02对端 (endpoint) 中缺少端口\x02对端主机名 (endpoint host) 无效\x02" +
+ "方括号中应包含一个 IPv6 地址\x02MTU 无效\x02端口无效\x02连接保活间隔无效\x02无效的密钥:%[1]v\x02解码后的" +
+ "密钥长度必须为32字节\x02存在多余的逗号\x02隧道名称无效\x02行必须出现在段落中\x02配置项必须要有一个等于号\x02必须有一个" +
+ "值\x02[Interface] 段落中的该键无效\x02[Peer] 段落中的该键无效\x02接口必须有一个私钥\x02[未指定]\x02" +
+ "每个节点都必须指定公钥\x02、\x02 \x02关于 WireGuard\x02WireGuard logo 图片\x02关闭\x02♥ " +
+ "捐助! (&D)\x02状态:\x02断开 (&D)\x02连接 (&A)\x02公钥:\x02监听端口:\x02MTU:\x02地址:" +
+ "\x02DNS 服务器:\x02脚本:\x02预共享密钥:\x02允许的 IP:\x02对端:\x02连接保活间隔:\x02上次握手时间:" +
+ "\x02流量:\x02连接前\x02连接后\x02断开前\x02断开后\x02已禁用(依管理策略)\x02已启用\x02接收 %[1]s, 发送" +
+ " %[2]s\x02无法确认隧道状态\x02无法连接隧道\x02无法断开隧道连接\x02接口: %[1]s\x02节点\x02创建新隧道\x02" +
+ "编辑隧道\x02名称 (&N):\x02公钥 (&P):\x02(未知)\x02拦截未经隧道的流量 (kill-switch) (&B)" +
+ "\x02保存 (&S)\x02取消\x02配置 (&C):\x02名称无效\x02必须输入名称。\x02隧道名「%[1]s」无效。\x02无法列" +
+ "出现有隧道\x02隧道已存在\x02隧道名「%[1]s」已存在。\x02无法创建新的配置\x02写入文件失败\x02文件「%[1]s」已存在" +
+ "。\x0a\x0a您确定要覆盖它吗?\x02已连接\x02正在连接\x02已断开\x02正在断开\x02未知\x02日志\x02复制 (&C" +
+ ")\x02全选 (&A)\x02导出… (&S)\x02时间\x02日志消息\x02文本文件 (*.txt)|*.txt|所有文件 (*.*)|" +
+ "*.*\x02导出日志\x02关于 WireGuard… (&A)\x02隧道错误\x02%[1]s\x0a\x0a更多信息请查看日志。\x02" +
+ "%[1]s (已过时)\x02WireGuard 检测错误\x02无法等待 WireGuard 窗口出现: %[1]v\x02WireGuard" +
+ ": 已断开\x02状态: 未知\x02地址: 无\x02管理隧道… (&M)\x02从文件导入隧道… (&I)\x02退出 (&E)\x02隧道" +
+ " (&T)\x02WireGuard 已连接\x02隧道「%[1]s」已连接。\x02WireGuard 已断开\x02隧道「%[1]s」已断开" +
+ "连接。\x02WireGuard 隧道错误\x02WireGuard: %[1]s\x02状态: %[1]s\x02地址: %[1]s" +
+ "\x02发现更新!\x02WireGuard 更新\x02新的 WireGuard 版本发布了。强烈建议您现在安装。\x02隧道\x02编辑 (" +
+ "&E)\x02新建空隧道… (&E)\x02新建隧道\x02删除所选隧道\x02导出所有隧道 (ZIP 压缩包)\x02切换连接状态 (&T)" +
+ "\x02导出所有隧道 (ZIP 压缩包)… (&Z)\x02编辑所选隧道… (&E)\x02删除所选隧道 (&R)\x02未找到配置文件\x02" +
+ "无法导入配置: %[1]v\x02无法列出现有隧道: %[1]v\x02另一个同名的隧道「%[1]s」已存在\x02无法导入配置: %[1]" +
+ "v\x02导入隧道\x14\x01\x81\x01\x00\x00\x1a\x02导入了 %[1]d 个隧道\x14\x02\x80\x01" +
+ "\x000\x02导入了 %[2]d 个隧道中的 %[1]d 个隧道\x02无法创建隧道\x14\x01\x81\x01\x00\x00\x17" +
+ "\x02删除 %[1]d 个隧道\x14\x01\x81\x01\x00\x00,\x02您确定要删除这 %[1]d 个隧道吗?\x02删除隧道" +
+ "「%[1]s」\x02您确定要删除隧道「%[1]s」吗?\x02%[1]s此操作无法撤销。\x02无法删除隧道\x02无法删除隧道: %[1" +
+ "]s\x02无法删除隧道\x14\x01\x81\x01\x00\x00 \x02无法删除 %[1]d 个隧道。\x02配置文件 (*.zip," +
+ " *.conf)|*.zip;*.conf|所有文件 (*.*)|*.*\x02从文件导入隧道\x02配置文件 (*.zip)|*.zip" +
+ "\x02导出配置文件 (ZIP 压缩包)\x02%[1]s (未签名版本,禁用自动更新)\x02退出 WireGuard 时出错\x02无法停止" +
+ "服务: %[1]v。您可能需要在服务管理器中手动停止 WireGuard 服务。\x02发现新版 WireGuard。强烈建议您现在安装。" +
+ "\x02状态: 等待用户\x02立即更新\x02状态: 等待更新服务\x02错误: %[1]v。请重试。\x02状态: 完成!"
-var zh_TWIndex = []uint32{ // 181 elements
+var zh_TWIndex = []uint32{ // 180 elements
// Entry 0 - 1F
0x00000000, 0x00000007, 0x00000037, 0x00000056,
- 0x00000066, 0x000000a4, 0x000000a4, 0x000000d5,
- 0x00000118, 0x0000017d, 0x000001b9, 0x000001c6,
- 0x000001df, 0x000001f0, 0x00000201, 0x00000215,
- 0x00000229, 0x0000023a, 0x00000244, 0x0000024d,
- 0x0000025a, 0x00000267, 0x00000274, 0x00000281,
- 0x00000290, 0x000002a4, 0x000002c6, 0x000002e5,
- 0x000002ff, 0x00000327, 0x00000335, 0x00000345,
+ 0x00000066, 0x000000a4, 0x000000df, 0x00000110,
+ 0x00000153, 0x000001b8, 0x000001f4, 0x00000201,
+ 0x0000021a, 0x0000022b, 0x0000023c, 0x00000250,
+ 0x00000264, 0x00000275, 0x0000027f, 0x00000288,
+ 0x00000295, 0x000002a2, 0x000002af, 0x000002bc,
+ 0x000002cb, 0x000002ea, 0x00000304, 0x0000032c,
+ 0x0000033a, 0x0000034a, 0x00000370, 0x00000389,
// Entry 20 - 3F
- 0x0000036b, 0x00000384, 0x000003a3, 0x000003cc,
- 0x000003e5, 0x000003f8, 0x00000414, 0x0000043c,
- 0x00000452, 0x00000471, 0x0000048b, 0x000004b1,
- 0x000004bd, 0x000004df, 0x000004fb, 0x00000518,
- 0x00000530, 0x00000548, 0x0000054c, 0x0000054e,
- 0x0000055f, 0x00000575, 0x00000575, 0x0000057c,
- 0x0000058f, 0x00000596, 0x000005a8, 0x000005b4,
- 0x000005bb, 0x000005c5, 0x000005c9, 0x000005d0,
+ 0x000003a8, 0x000003c1, 0x000003d4, 0x000003f0,
+ 0x00000418, 0x0000042e, 0x0000044d, 0x00000467,
+ 0x0000048d, 0x00000499, 0x000004bb, 0x000004bf,
+ 0x000004c1, 0x000004d2, 0x000004e8, 0x000004ef,
+ 0x00000502, 0x00000509, 0x0000051b, 0x00000527,
+ 0x0000052e, 0x00000538, 0x0000053c, 0x00000543,
+ 0x00000551, 0x0000055e, 0x0000056e, 0x0000057e,
+ 0x00000588, 0x00000599, 0x000005ac, 0x000005b3,
// Entry 40 - 5F
- 0x000005de, 0x000005de, 0x000005ee, 0x000005fe,
- 0x00000608, 0x00000619, 0x0000062c, 0x00000633,
- 0x00000633, 0x0000063d, 0x0000065f, 0x00000678,
- 0x0000068b, 0x000006a4, 0x000006b3, 0x000006ba,
- 0x000006ca, 0x000006dd, 0x000006e9, 0x000006f5,
- 0x000006fe, 0x00000733, 0x00000733, 0x0000073f,
- 0x00000746, 0x00000752, 0x00000762, 0x00000778,
- 0x0000079c, 0x000007b5, 0x000007c5, 0x000007e6,
+ 0x000005bd, 0x000005c7, 0x000005d1, 0x000005db,
+ 0x000005f3, 0x000005fd, 0x0000061f, 0x00000638,
+ 0x0000064b, 0x00000664, 0x00000673, 0x0000067a,
+ 0x0000068a, 0x0000069d, 0x000006a9, 0x000006b5,
+ 0x000006be, 0x000006f3, 0x000006ff, 0x00000706,
+ 0x00000712, 0x00000722, 0x00000738, 0x0000075c,
+ 0x00000775, 0x00000785, 0x000007a6, 0x000007c5,
+ 0x000007d8, 0x0000080b, 0x00000815, 0x00000825,
// Entry 60 - 7F
- 0x00000805, 0x00000818, 0x0000084b, 0x00000855,
- 0x00000865, 0x00000875, 0x00000885, 0x0000088c,
- 0x00000893, 0x0000089f, 0x000008ab, 0x000008ba,
- 0x000008c1, 0x000008ce, 0x000008fd, 0x0000090d,
- 0x00000923, 0x00000930, 0x0000095f, 0x00000974,
- 0x0000098c, 0x000009b9, 0x000009cf, 0x000009df,
- 0x000009ec, 0x000009fe, 0x00000a16, 0x00000a22,
- 0x00000a36, 0x00000a51, 0x00000a6b, 0x00000a8f,
+ 0x00000835, 0x00000845, 0x0000084c, 0x00000853,
+ 0x0000085f, 0x0000086b, 0x0000087a, 0x00000881,
+ 0x0000088e, 0x000008bd, 0x000008cd, 0x000008e3,
+ 0x000008f0, 0x0000091f, 0x00000934, 0x0000094c,
+ 0x00000979, 0x0000098f, 0x0000099f, 0x000009ac,
+ 0x000009be, 0x000009d6, 0x000009e2, 0x000009ed,
+ 0x00000a01, 0x00000a1c, 0x00000a36, 0x00000a5a,
+ 0x00000a71, 0x00000a83, 0x00000a92, 0x00000aa0,
// Entry 80 - 9F
- 0x00000aa6, 0x00000ab8, 0x00000ac7, 0x00000ac7,
- 0x00000ace, 0x00000adf, 0x00000b38, 0x00000b3f,
- 0x00000b4b, 0x00000b63, 0x00000b70, 0x00000b83,
- 0x00000ba6, 0x00000bbe, 0x00000be3, 0x00000bfb,
- 0x00000c16, 0x00000c16, 0x00000c32, 0x00000c4e,
- 0x00000c78, 0x00000c94, 0x00000ca4, 0x00000cc5,
- 0x00000cf8, 0x00000d0b, 0x00000d29, 0x00000d59,
- 0x00000d6e, 0x00000d98, 0x00000dbe, 0x00000dd1,
+ 0x00000aa7, 0x00000ab8, 0x00000b11, 0x00000b18,
+ 0x00000b24, 0x00000b3c, 0x00000b49, 0x00000b5c,
+ 0x00000b7f, 0x00000b97, 0x00000bbc, 0x00000bd4,
+ 0x00000bef, 0x00000c02, 0x00000c1e, 0x00000c3a,
+ 0x00000c64, 0x00000c80, 0x00000c90, 0x00000cb1,
+ 0x00000ce4, 0x00000cf7, 0x00000d15, 0x00000d45,
+ 0x00000d5a, 0x00000d84, 0x00000daa, 0x00000dbd,
+ 0x00000dd9, 0x00000dec, 0x00000e10, 0x00000e54,
// Entry A0 - BF
- 0x00000ded, 0x00000e00, 0x00000e24, 0x00000e68,
- 0x00000e84, 0x00000ea2, 0x00000ebb, 0x00000ef1,
- 0x00000f09, 0x00000f6a, 0x00000fbf, 0x00000fd8,
- 0x00000fe5, 0x00001001, 0x00001026, 0x0000103c,
- 0x0000103c, 0x0000103c, 0x0000103c, 0x0000103c,
- 0x0000103c,
-} // Size: 748 bytes
+ 0x00000e70, 0x00000e8e, 0x00000ea7, 0x00000edd,
+ 0x00000ef5, 0x00000f56, 0x00000fab, 0x00000fc4,
+ 0x00000fd1, 0x00000fed, 0x00001012, 0x00001028,
+ 0x00001028, 0x00001028, 0x00001028, 0x00001028,
+ 0x00001028, 0x00001028, 0x00001028, 0x00001028,
+} // Size: 744 bytes
-const zh_TWData string = "" + // Size: 4156 bytes
+const zh_TWData string = "" + // Size: 4136 bytes
"\x02錯誤\x02(無參數):提升權限並安裝管理服務\x02使用方法: %[1]s [\x0a%[2]s]\x02命令列選項\x02無法確定該" +
- "處理程序是否在 WOW64 下執行: %[1]v\x02無法開啓目前處理程序的權杖: %[1]v\x02WireGuard 可能只能被內建的" +
- "「%[1]s」群組成員使用。\x02WireGuard 正在執行,但 UI 只能從內建的內建的「%[1]s」群組成員的桌面存取。\x02Wi" +
- "reGuard 的工作列圖示在 30 秒後並沒有顯示。\x02就是現在\x02系統時鐘倒退了!\x14\x01\x81\x01\x00\x00" +
- "\x0a\x02%[1]d 年\x14\x01\x81\x01\x00\x00\x0a\x02%[1]d 天\x14\x01\x81\x01" +
- "\x00\x00\x0d\x02%[1]d 小時\x14\x01\x81\x01\x00\x00\x0d\x02%[1]d 分鐘\x14\x01" +
- "\x81\x01\x00\x00\x0a\x02%[1]d 秒\x02%[1]s 前\x02%[1]d\u00a0B\x02%.2[1]f" +
- "\u00a0KiB\x02%.2[1]f\u00a0MiB\x02%.2[1]f\u00a0GiB\x02%.2[1]f\u00a0TiB" +
- "\x02%[1]s: %[2]q\x02無效的 IP 位址\x02無效的網路位址首碼長度\x02Endpoint 中沒有指定埠號\x02無效的 " +
- "Endpoint 位址\x02括號中必須包含一個 IPv6 位址\x02無效的 MTU\x02無效的埠號\x02無效的 Persistent K" +
- "eepalive 設定\x02無效的金鑰: %[1]v\x02金鑰必須剛好長 32 bytes\x02數值必須介於 0 到 2^64-1: %[" +
- "1]v\x02一行中有兩個逗號\x02隧道名稱無效\x02行必須出現在段落中\x02設定的項目必須要有一個等號\x02必須要有一個值\x02[I" +
- "nterface] 中有無效選項\x02[Peer] 中有無效選項\x02Interface 中必須要有一把私鑰\x02[未指定]\x02每個 " +
- "Peer 都必須要有公鑰\x02讀取設定時發生錯誤\x02Interface 中的金鑰無效\x02協定版本必須為 1\x02Peer 中的金鑰無" +
- "效\x02、\x02 \x02關於 WireGuard\x02WireGuard logo 圖片\x02關閉\x02♥ 捐贈! (&D)" +
- "\x02狀態\x02中斷連線 (&D)\x02連線 (&A)\x02公鑰\x02監聽埠\x02MTU\x02位址\x02DNS 伺服器\x02預" +
- "交換金鑰\x02允許的位址\x02連接點\x02Keepalive 間隔\x02最後交握時間\x02流量\x02已啓用\x02已收到 %[1" +
- "]s;已傳送 %[2]s\x02無法確認隧道狀態\x02無法連接隧道\x02無法斷開隧道連線\x02[隧道] %[1]s\x02節點\x02建立" +
- "新隧道\x02編輯隧道設定\x02名稱 (&N)\x02公鑰 (&P)\x02(未知)\x02阻斷未經過隧道的流量(kill-switch)" +
- " (&B)\x02儲存 (&S)\x02取消\x02設定 (&C)\x02無效的名稱\x02必須填寫名稱。\x02無效的隧道名稱「%[1]s」。" +
- "\x02無法列出現有隧道\x02隧道已存在\x02已有同名隧道「%[1]s」。\x02無法建立新的隧道設定\x02檔案寫入失敗\x02檔案已存在" +
- ": %[1]s\x0a\x0a您確定要覆蓋嗎?\x02已連線\x02正在連線…\x02已中斷連線\x02正在中斷…\x02未知\x02日誌" +
- "\x02複製 (&C)\x02全選 (&A)\x02匯出… (&S)\x02時間\x02日誌訊息\x02純文字 (*.txt)|*.txt|所有" +
- "檔案 (*.*)|*.*\x02匯出日誌…\x02關於 WireGuard (&A)\x02隧道錯誤\x02%[1]s\x0a\x0a如需更" +
- "多資訊,請查看日誌。\x02%[1]s(已過時)\x02偵測 WireGuard 錯誤\x02無法等待 WireGuard 視窗開啓: %[" +
- "1]v\x02WireGuard - 未連線\x02[狀態] 未知\x02[位址] 無\x02管理隧道 (&M)\x02從檔案匯入… (&I)" +
- "\x02離開 (&X)\x02WireGuard 已連線\x02已連線至隧道 - %[1]s\x02WireGuard 已中斷連線\x02已中斷" +
- "與隧道的連線 - %[1]s\x02WireGuard 隧道錯誤\x02WireGuard - %[1]s\x02[狀態] %[1]s" +
- "\x02更新\x02WireGuard 更新\x02更新的 WireGuard 已經為您準備好了。\x0a強烈建議您立即更新 WireGuard" +
- "。\x02隧道\x02編輯 (&E)\x02新增隧道精靈 (&E)\x02新增隧道\x02刪除選取隧道\x02匯出所有隧道(ZIP 格式)" +
- "\x02切換連線狀態 (&T)\x02匯出所有隧道至 &ZIP 壓縮檔\x02編輯選取隧道 (&S)\x02刪除已選取隧道 (&R)\x02無法" +
- "匯入設定: %[1]v\x02無法列出隧道: %[1]v\x02已有另一個同名的隧道「%[1]s」\x02無法匯入設定: %[1]v\x02" +
- "已匯入隧道\x14\x01\x81\x01\x00\x00\x1a\x02已匯入 %[1]d 個隧道\x14\x02\x80\x01\x00" +
- "-\x02已匯入 %[1]d 個隧道(共 %[2]d 個)\x02無法建立隧道\x14\x01\x81\x01\x00\x00\x17\x02刪" +
- "除 %[1]d 個隧道\x14\x01\x81\x01\x00\x00)\x02您確定要刪除 %[1]d 個隧道嗎?\x02刪除隧道 - %" +
- "[1]s\x02您確定要刪除隧道「%[1]s」嗎?\x02%[1]s\x0a\x0a您將無法復原此操作。\x02無法刪除隧道\x02無法刪除隧道" +
- ": %[1]s\x02無法刪除隧道\x14\x01\x81\x01\x00\x00\x1d\x02無法刪除 %[1]d 個隧道\x02隧道設" +
- "定檔 (*.zip, *.conf)|*.zip;*.conf|所有檔案 (*.*)|*.*\x02從檔案中匯入隧道…\x02隧道設定檔 (" +
- "*.zip)|*.zip\x02匯出隧道設定至…\x02%[1]s(未簽署發行版本,無法自動更新)\x02離開 WireGuard 失敗\x02" +
- "無法結束服務: %[1]v。\x0a您可能需要手動從服務管理中結束 WireGuard 服務。\x02更新的 WireGuard 已經為您準" +
- "備好了。\x0a強烈建議您立即進行更新。\x02狀態:等待使用者\x02立即更新\x02狀態:等待更新服務\x02錯誤: %[1]v。請稍後" +
- "再試。\x02狀態:已完成!"
+ "處理程序是否在 WOW64 下執行: %[1]v\x02您必須在此電腦上執行原生版本的 WireGuard。\x02無法開啓目前處理程序的權" +
+ "杖: %[1]v\x02WireGuard 可能只能被內建的「%[1]s」群組成員使用。\x02WireGuard 正在執行,但 UI 只能" +
+ "從內建的內建的「%[1]s」群組成員的桌面存取。\x02WireGuard 的工作列圖示在 30 秒後並沒有顯示。\x02就是現在\x02系" +
+ "統時鐘倒退了!\x14\x01\x81\x01\x00\x00\x0a\x02%[1]d 年\x14\x01\x81\x01\x00\x00" +
+ "\x0a\x02%[1]d 天\x14\x01\x81\x01\x00\x00\x0d\x02%[1]d 小時\x14\x01\x81\x01" +
+ "\x00\x00\x0d\x02%[1]d 分鐘\x14\x01\x81\x01\x00\x00\x0a\x02%[1]d 秒\x02%[1]s" +
+ " 前\x02%[1]d\u00a0B\x02%.2[1]f\u00a0KiB\x02%.2[1]f\u00a0MiB\x02%.2[1]f" +
+ "\u00a0GiB\x02%.2[1]f\u00a0TiB\x02%[1]s: %[2]q\x02Endpoint 中沒有指定埠號\x02無效的" +
+ " Endpoint 位址\x02括號中必須包含一個 IPv6 位址\x02無效的 MTU\x02無效的埠號\x02無效的 Persistent " +
+ "Keepalive 設定\x02無效的金鑰: %[1]v\x02金鑰必須剛好長 32 bytes\x02一行中有兩個逗號\x02隧道名稱無效" +
+ "\x02行必須出現在段落中\x02設定的項目必須要有一個等號\x02必須要有一個值\x02[Interface] 中有無效選項\x02[Peer" +
+ "] 中有無效選項\x02Interface 中必須要有一把私鑰\x02[未指定]\x02每個 Peer 都必須要有公鑰\x02、\x02 " +
+ "\x02關於 WireGuard\x02WireGuard logo 圖片\x02關閉\x02♥ 捐贈! (&D)\x02狀態\x02中斷連線 " +
+ "(&D)\x02連線 (&A)\x02公鑰\x02監聽埠\x02MTU\x02位址\x02DNS 伺服器\x02指令碼:\x02預交換金鑰" +
+ "\x02允許的位址\x02連接點\x02Keepalive 間隔\x02最後交握時間\x02流量\x02連接前\x02連接後\x02斷線前" +
+ "\x02斷線後\x02已關閉, 隨著策略\x02已啓用\x02已收到 %[1]s;已傳送 %[2]s\x02無法確認隧道狀態\x02無法連接隧道" +
+ "\x02無法斷開隧道連線\x02[隧道] %[1]s\x02節點\x02建立新隧道\x02編輯隧道設定\x02名稱 (&N)\x02公鑰 (&P" +
+ ")\x02(未知)\x02阻斷未經過隧道的流量(kill-switch) (&B)\x02儲存 (&S)\x02取消\x02設定 (&C)" +
+ "\x02無效的名稱\x02必須填寫名稱。\x02無效的隧道名稱「%[1]s」。\x02無法列出現有隧道\x02隧道已存在\x02已有同名隧道「%" +
+ "[1]s」。\x02無法建立新的隧道設定\x02檔案寫入失敗\x02檔案已存在: %[1]s\x0a\x0a您確定要覆蓋嗎?\x02已連線" +
+ "\x02正在連線…\x02已中斷連線\x02正在中斷…\x02未知\x02日誌\x02複製 (&C)\x02全選 (&A)\x02匯出… (&S" +
+ ")\x02時間\x02日誌訊息\x02純文字 (*.txt)|*.txt|所有檔案 (*.*)|*.*\x02匯出日誌…\x02關於 WireG" +
+ "uard (&A)\x02隧道錯誤\x02%[1]s\x0a\x0a如需更多資訊,請查看日誌。\x02%[1]s(已過時)\x02偵測 Wire" +
+ "Guard 錯誤\x02無法等待 WireGuard 視窗開啓: %[1]v\x02WireGuard - 未連線\x02[狀態] 未知\x02" +
+ "[位址] 無\x02管理隧道 (&M)\x02從檔案匯入… (&I)\x02離開 (&X)\x02隧道(&T)\x02WireGuard 已連線" +
+ "\x02已連線至隧道 - %[1]s\x02WireGuard 已中斷連線\x02已中斷與隧道的連線 - %[1]s\x02WireGuard " +
+ "隧道錯誤\x02WireGuard - %[1]s\x02[狀態] %[1]s\x02位址: %[1]s\x02更新\x02WireGuar" +
+ "d 更新\x02更新的 WireGuard 已經為您準備好了。\x0a強烈建議您立即更新 WireGuard。\x02隧道\x02編輯 (&E)" +
+ "\x02新增隧道精靈 (&E)\x02新增隧道\x02刪除選取隧道\x02匯出所有隧道(ZIP 格式)\x02切換連線狀態 (&T)\x02匯出" +
+ "所有隧道至 &ZIP 壓縮檔\x02編輯選取隧道 (&S)\x02刪除已選取隧道 (&R)\x02找不到設定檔\x02無法匯入設定: %[1" +
+ "]v\x02無法列出隧道: %[1]v\x02已有另一個同名的隧道「%[1]s」\x02無法匯入設定: %[1]v\x02已匯入隧道\x14" +
+ "\x01\x81\x01\x00\x00\x1a\x02已匯入 %[1]d 個隧道\x14\x02\x80\x01\x00-\x02已匯入 %[" +
+ "1]d 個隧道(共 %[2]d 個)\x02無法建立隧道\x14\x01\x81\x01\x00\x00\x17\x02刪除 %[1]d 個隧道" +
+ "\x14\x01\x81\x01\x00\x00)\x02您確定要刪除 %[1]d 個隧道嗎?\x02刪除隧道 - %[1]s\x02您確定要刪" +
+ "除隧道「%[1]s」嗎?\x02%[1]s\x0a\x0a您將無法復原此操作。\x02無法刪除隧道\x02無法刪除隧道: %[1]s\x02" +
+ "無法刪除隧道\x14\x01\x81\x01\x00\x00\x1d\x02無法刪除 %[1]d 個隧道\x02隧道設定檔 (*.zip, " +
+ "*.conf)|*.zip;*.conf|所有檔案 (*.*)|*.*\x02從檔案中匯入隧道…\x02隧道設定檔 (*.zip)|*.zip" +
+ "\x02匯出隧道設定至…\x02%[1]s(未簽署發行版本,無法自動更新)\x02離開 WireGuard 失敗\x02無法結束服務: %[1]" +
+ "v。\x0a您可能需要手動從服務管理中結束 WireGuard 服務。\x02更新的 WireGuard 已經為您準備好了。\x0a強烈建議您立" +
+ "即進行更新。\x02狀態:等待使用者\x02立即更新\x02狀態:等待更新服務\x02錯誤: %[1]v。請稍後再試。\x02狀態:已完成!"
- // Total table size 99186 bytes (96KiB); checksum: FBC08C97
+ // Total table size 175581 bytes (171KiB); checksum: F4F0E6D8