Compare commits

...

143 Commits

Author SHA1 Message Date
copilot-swe-agent[bot] 53867985d1 Initial plan 2026-02-12 17:48:29 +00:00
Bernd Storath b3cc1ce839 reduce container size
from around 700mb to 400mb
2026-02-11 15:36:29 +01:00
Bernd Storath 71aaec93ef add unit tests
this adds the groundwork to start unit testing some modules
2026-02-11 15:23:04 +01:00
HackingAll 7a219b73d4 Adding galician (#2473)
* Adding galego -> gl.json

* Update i18n.config.ts

* Update nuxt.config.ts
2026-02-10 11:18:02 +01:00
Bare7a c456c5e7dd Add Bulgarian translation (#2466) 2026-02-09 08:00:38 +01:00
Bernd Storath a5880cc0b8 update packages 2026-02-09 08:00:07 +01:00
Bernd Storath 5fca628ebd change date in copyright footer 2026-02-06 15:32:39 +01:00
Bernd Storath 7ab297c366 Bump version to 15.2.2 2026-02-06 14:55:20 +01:00
Bernd Storath c5de8f0f44 cli: reset 2fa on admin reset (#2461)
reset 2fa on cli reset
2026-02-06 12:28:13 +01:00
Bernd Storath c0641889cf replace watchtower (#2456)
update to maintained fork
2026-02-04 08:24:48 +01:00
Bernd Storath 9141562f91 update tagging convention for latest tag 2026-02-04 08:17:58 +01:00
thebigpotatoe d21af70df1 fix: correct help text for prometheus metrics (#2453) 2026-02-03 11:27:03 +01:00
Bernd Storath 56ee86cc1c update packages 2026-02-02 08:27:05 +01:00
Runar Ingebrigtsen f017b4968c Add Norwegian bokmål translation (#2447)
* add Norwegian bokmål translation

Signed-off-by: Runar Ingebrigtsen <runar@rin.no>

* add nb config, available in UI

Signed-off-by: Runar Ingebrigtsen <runar@rin.no>

---------

Signed-off-by: Runar Ingebrigtsen <runar@rin.no>
2026-02-02 08:18:31 +01:00
Alexander Chepurnoy 6004457666 feat: update client and server interface parameters (#2440) 2026-01-28 09:34:11 +01:00
Bernd Storath 1a5a0180ea Fix LangSelector and ClientCard z-index (#2434)
fix client card
2026-01-27 08:24:53 +01:00
Ayush Chothe c732f149e6 feat: Add wireguard-go package in Dockerfile (#2419)
* feat: Add `wireguard-go` package in `Dockerfile`

* feat: add amneziawg-go
Co-authored-by: cany748 <cany748@gmail.com>
2026-01-27 08:08:24 +01:00
Bernd Storath 4819480eb0 update packages 2026-01-26 09:02:25 +01:00
Alexander Chepurnoy fc7ab0dc21 feat(docs): edit amnezia.md (#2430)
* feat(docs): edit amnezia.md

* Update docs/content/advanced/config/amnezia.md

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

* Update docs/content/advanced/config/amnezia.md

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2026-01-26 08:43:09 +01:00
Bernd Storath eb6b96c0f1 lang: Add dutch language (#2413)
add dutch language

Co-authored-by: Stephan Paternotte <Stephan-P@users.noreply.github.com>
2026-01-21 09:39:18 +01:00
Bernd Storath f62fad9c40 update packages 2026-01-20 08:51:19 +01:00
Maksim M. e9a472c8f7 fix(i18n/ru): use "мусор" for AmneziaWG junk packets (#2402)
The RU translation changed "junk" from "мусорный" to "шумовой".
Amnezia authors consistently describe these packets/bytes as "мусор" in their docs and Habr posts. Align wording with upstream terminology to avoid confusion for RU users.
2026-01-15 08:14:38 +01:00
Bernd Storath 552e2b8cbf update screenshot 2026-01-14 09:53:04 +01:00
Bernd Storath a0b4192cbd Bump version to 15.2.1 2026-01-14 08:51:01 +01:00
Bernd Storath 32a055093a exclude i18n from setup middleware 2026-01-13 13:15:46 +01:00
Bernd Storath 51558c7027 refactor: session handling (#2398)
* refactor session handling

* simplify
2026-01-13 10:11:13 +01:00
binnichtaktiv b85286f0ab Lang(de): Improve and add missing translations (#2393)
* add missing german translations

* fix typos and improve existing translations

* fix punctuation

* fix last overlooked typos
2026-01-13 08:21:08 +01:00
Bernd Storath 48f3fbd715 always generate awg h1-h5 2026-01-13 08:07:13 +01:00
Bernd Storath 458f66818a fix search magnifying icon 2026-01-12 12:04:50 +01:00
Bernd Storath 7964dc7993 Bump version to 15.2.0 2026-01-12 08:28:23 +01:00
RaffaelHold 0ac5d7d461 feat(docs): Extend docs for routed setup with nftables (#2380)
* Extend docs for routed setup with nftables

When using nftables in a routed setup different up and down hooks need to be used. 
To limit interaction with docker managed chains a custom WG_EASY chain is added as a jump target.
Since nft only supports deletion via handles awk is needed to get the handle of the jump rule for deletion

* Remove link to podman-nft

* Fix formatting according to prettier rules

* Add additional whitespace
2026-01-12 08:21:18 +01:00
Bernd Storath 826914a4f3 update packages 2026-01-12 08:19:01 +01:00
Bernd Storath 261da431e7 Fix: reset onetimelink expiration instead of failing (#2370)
* update expiresAt instead of failing

* add changelog
2025-12-29 19:12:53 +01:00
Bernd Storath 94b33abf5e Remove armv7 support (#2369)
remove armv7 support
2025-12-29 18:54:47 +01:00
Bernd Storath 8325056ccc update lockfile 2025-12-29 18:47:48 +01:00
Bernd Storath 81a1b2c907 update packages 2025-12-29 18:36:51 +01:00
dependabot[bot] fc8f89fb83 build(deps): bump actions/download-artifact from 6 to 7 (#2343)
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 6 to 7.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v6...v7)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '7'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-18 07:58:23 +01:00
dependabot[bot] d846c7745f build(deps): bump actions/upload-artifact from 5 to 6 (#2344)
Bumps [actions/upload-artifact](https://github.com/actions/upload-artifact) from 5 to 6.
- [Release notes](https://github.com/actions/upload-artifact/releases)
- [Commits](https://github.com/actions/upload-artifact/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/upload-artifact
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-12-18 07:58:12 +01:00
Bernd Storath 61c6fd6c02 update packages 2025-12-15 08:03:25 +01:00
David DIVERRES abe5708058 Update fr.json (#2326)
Update fr.json - Add missing translations and improve existing ones

- Add missing keys: client.delete, client.search, client.config, client.viewConfig
- Add complete copy section (4 keys)
- Add complete awg section (27 keys for AmneziaWG parameters)
- Fix terminology: "double facteur" → "deux facteurs" (standard French)
- Fix zod.generic.validBoolean translation
- Fix zod.generic.stringMin capitalization and wording
- Translate zod.client.id to French
- Improve admin.general route descriptions
2025-12-08 08:51:38 +01:00
Bernd Storath 626339bddb update packages 2025-12-08 08:30:53 +01:00
Danya 381ae23c07 Update ru (#2324)
* Update ru.json

Full revision of the Russian localization for the AWG configuration block, including terminology corrections, improved consistency, and clarified parameter descriptions.

* Update ru.json

* fix formatting

---------

Co-authored-by: Bernd Storath <999999bst@gmail.com>
2025-12-05 15:59:12 +01:00
Nikolas 52382d1d7a Update uk.json (#2323) 2025-12-05 07:35:15 +01:00
Mike 68e5216d4b Update ru.json (#2319)
* Update ru.json

* format

---------

Co-authored-by: Bernd Storath <999999bst@gmail.com>
2025-12-02 12:26:04 +01:00
Bernd Storath ceff95b336 Bump version to 15.2.0-beta.3 2025-12-01 10:12:01 +01:00
Alexander Chepurnoy 782d1c215f feat(docs): edit amnezia page (#2292)
* feat(docs): edit amnezia page

* Fix AmneziaWG documentation link

* Update AmneziaWG client compatibility information
2025-12-01 08:23:01 +01:00
Bernd Storath e8e26cfe10 update packages 2025-12-01 07:54:59 +01:00
Bernd Storath 400d4d992e Fix light mode admin menu active text color (#2307)
* fix color

* remove duplicates
2025-11-25 08:26:18 +01:00
Bernd Storath b08df55321 fix build 2025-11-24 08:03:37 +01:00
Bernd Storath b26a8110e0 update packages 2025-11-24 08:01:11 +01:00
杨黄林 692f550596 Improve zh-CN translate (#2298)
Fix zh-CN translate

Co-authored-by: yanghuanglin <yanghuanglin@qq.com>
2025-11-24 07:57:17 +01:00
Chiahong badae8b8e4 fix(i18n): Add missing translation for delete action (#2295) 2025-11-21 17:55:11 +01:00
Nikolas 7f89bde99e Update uk.json (#2293) 2025-11-21 08:02:47 +01:00
Bernd Storath 326717444b Bump version to 15.2.0-beta.2 2025-11-18 15:05:42 +01:00
Bernd Storath 4e4bfc75e3 feat: add config btn and modal to view and copy config (#2289)
* add view config btn and modal

* show loading state

* add note about keyboard
2025-11-18 11:36:46 +01:00
Bernd Storath 5c97a8ba73 try all qr ecc levels (#2288)
try ecc levels
2025-11-18 09:25:57 +01:00
Bernd Storath cba7a160ea intellicode deprecated 2025-11-17 08:04:10 +01:00
Nikolas 4a75e1379d Update uk.json (#2286)
* Update uk.json

* fix formatting

---------

Co-authored-by: Bernd Storath <999999bst@gmail.com>
2025-11-17 07:54:50 +01:00
Chiahong 10a140d188 feat(i18n): Add Traditional Chinese (Taiwan, zh-TW) support (#2285) 2025-11-17 07:53:03 +01:00
Bernd Storath edc3c5af57 Bump version to 15.2.0-beta.1 2025-11-12 08:35:19 +01:00
Bernd Storath 26708305d6 add script to calculate i18n progress 2025-11-12 08:23:44 +01:00
Alexander Chepurnoy 6a282e6ab9 AmneziaWG 2.0 (#2226)
* feat!: awg

* feat: add description to fields, add I5

* fix: awg i18n

* fix: types

* minor fixes

* Remove TODO comment from types.ts

Removed TODO comment for more validation.

---------

Co-authored-by: Bernd Storath <999999bst@gmail.com>
2025-11-12 07:46:16 +01:00
Badri Isiani a8ba7f7247 Fixed a bug causing .conf.txt download on Android affecting Firefox based Android browsers. (#2269)
* Fixed a bug causing .conf.txt download on Android
... affecting Firefox based Android browsers.

* change content-type

---------

Co-authored-by: Badri Isiani <badri@loonartech.net>
Co-authored-by: Bernd Storath <999999bst@gmail.com>
2025-11-11 08:02:03 +01:00
Bernd Storath 502fe718d5 update packages 2025-11-10 10:10:24 +01:00
Bernd Storath 5c7aac9fd2 update packages 2025-11-03 08:49:11 +01:00
YuWorm 2f96d9934b add filename cleaning at OneTimeLink download (#2253)
* add filename cleaning at OneTimeLink download

* add cleanConfigFilename function in utils/WireGuard
2025-10-31 09:28:46 +01:00
Bernd Storath daff15463d switch to node v22
https://github.com/wg-easy/wg-easy/discussions/2254
2025-10-31 09:24:45 +01:00
Bernd Storath 5f68d261c0 update packages 2025-10-27 08:41:09 +01:00
Bernd Storath 013ea6dba9 add exemptions stale action 2025-10-22 10:08:50 +02:00
Bernd Storath ab9d75757f fix types 2025-10-21 12:10:53 +02:00
Daniel Vos 9be20109af Add routed (no NAT) example setup (#2181)
* Add routed.md example

* remove bad example

* Add note about 2001:db8::/32

* Add note about OPNSense/PFSense outbound NAT rule.

* add SYS_MODULE capability

* remove whitelines

* fix formatting

* typo LUA -> ULA

* minor fix

---------

Co-authored-by: Bernd Storath <999999bst@gmail.com>
2025-10-21 12:06:55 +02:00
Bernd Storath 9430b76258 update packages 2025-10-21 11:43:39 +02:00
Bernd Storath 99f1a004d5 Fix: Allow lower MTU (#2228)
allow lower mtu
2025-10-21 11:38:39 +02:00
YuWorm 2b42b639ea Add search / filter box (#2170)
* feat: Add search client based on #1978

* moved the filtering to the DB level using zod and tidied up some imports.

* minor fix

* minor fix

* fix typo

---------

Co-authored-by: Bernd Storath <999999bst@gmail.com>
2025-10-20 08:04:21 +02:00
Bernd Storath 76d5944726 Fix: Client Address Cidr (#2217)
fix client cidr
2025-10-14 11:31:41 +02:00
Bernd Storath 81bd19cfb6 update packages 2025-10-13 08:17:17 +02:00
Edgar R.N 0365ca7fb6 docs: Add AdGuard Home tutorial (#2175)
* docs: Add AdGuard Home tutorial

Signed-off-by: Edgar R.N <ernvk23@gmail.com>

* docs: Update AdGuard Home tutorial to use multi-network architecure

Signed-off-by: Edgar R.N <ernvk23@gmail.com>

* docs: Refine AdGuard Home tutorial based on feedback

Signed-off-by: Edgar R.N <ernvk23@gmail.com>

* docs: Temporary fix multi-network iptables

Signed-off-by: Edgar R.N <ernvk23@gmail.com>

* docs: AdGuard Home tutorial compatible with wg-easy v15

Signed-off-by: Edgar R.N <ernvk23@gmail.com>

---------

Signed-off-by: Edgar R.N <ernvk23@gmail.com>
2025-10-08 15:37:48 +02:00
Bernd Storath 529d65b3fb Fix: don't expect dump to contain client
Fixes: #2200
Fixes Bug introduced in: #2058
2025-10-08 13:43:07 +02:00
Bernd Storath cbbf5d3d25 Feat: Return client id of newly created client (#2190)
return client id of newly created client
2025-09-29 08:20:00 +02:00
Bernd Storath 7b2d234ea5 add link to codeberg registry 2025-09-25 15:13:33 +02:00
lenny76 a282ca35f1 feat(i18n): Add Italian language support (#2185)
* feat(i18n): Add Italian language support

This commit introduces Italian (it) language support to the application.
The `it` locale has been added to the `messages` object in `i18n.config.ts`, enabling the application to load and display content in Italian.

* little fix for italian translation

* Update nuxt.config.ts for italian language

---------

Co-authored-by: LucaS <l.scrigna@eoscaffe.it>
2025-09-25 14:42:04 +02:00
Danya 0792862c0d Fix minor issues in Russian translations (#2177)
fix-russian-ui

Update Russian translation
2025-09-22 14:31:01 +02:00
Németh Bálint 6c0d8e91fa Add INIT_ALLOWED_IPS for unattended setup (#2164)
* Add INIT_ALLOWED_IPS env var

Implement INIT_ALLOWED_IPS env var like the INIT_DNS to preset the global Allowed IPs field.

* Docs: Add INIT_ALLOWED_IPS var to unattended setup table

* Make UserConfigService.update param partial

Update UserConfigService.update() to accept any subset of the updatable fields.
Remove the unnecessary userConfig object from  DBService.initialSetup()

* formatting fix

* format on linux

On windows prettier get confused by global conf... common windows things
2025-09-16 12:16:31 +02:00
Bernd Storath 8892c43a7d Feat: Publish package on Codeberg (#2160)
* test codeberg build

* copy container to codeberg
2025-09-13 20:03:38 +02:00
Bernd Storath 7cfe04286a update packages 2025-09-13 18:35:55 +02:00
Bernd Storath 000513f212 fix build
TODO: investigate the root cause
2025-09-08 23:25:34 +02:00
dependabot[bot] 6ca3da1b80 build(deps): bump actions/checkout from 4 to 5 (#2120)
Bumps [actions/checkout](https://github.com/actions/checkout) from 4 to 5.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-09-08 22:53:49 +02:00
Bernd Storath fe394ecbe4 update actions 2025-09-08 22:17:00 +02:00
Bernd Storath ec6f0423ca fix typo 2025-09-08 22:10:16 +02:00
Bernd Storath e12208af75 update packages 2025-09-08 22:08:40 +02:00
TaeHyeon Jo 2d9c75fd81 fix(i18n-ko): unify 2FA terminology; add notConnected/endpoint/endpointDesc; keep PreUp (#2140)
fix(i18n-ko): unify 2FA terminology, add notConnected/endpoint/endpointDesc, keep PreUp
2025-08-30 13:42:57 +02:00
Bahri Rizaldi 0c54b1c3da Add Bahasa Indonesia Translations (#2142)
Add Bahasa Indonesia
2025-08-30 13:33:57 +02:00
xGhostxDev be7943dc9b Add polish language (#2126)
* Update i18n.config.ts

* Update nuxt.config.ts

* Add files via upload
2025-08-26 09:40:16 +02:00
Bernd Storath 303c2f1e39 Docs: Add amneziawg (#2108)
add amneziawg docs
2025-08-16 16:02:17 +02:00
WebX Beyond 0b32ab899c Add Bangla (বাংলা) translation and language support to wg-easy (#2112)
Bangla translation added
2025-08-16 16:01:57 +02:00
Alexander Chepurnoy ef463d3d85 feat: add amneziawg support (#2102)
* feat: detect wireguard executable

* feat: add amneziawg-tools to container

* feat: enhance AWG detection and configuration handling

* refactor: change env name

* refactor: change env values
2025-08-14 09:10:18 +02:00
dependabot[bot] c10daa2fd4 build(deps): bump actions/download-artifact from 4 to 5 (#2096)
Bumps [actions/download-artifact](https://github.com/actions/download-artifact) from 4 to 5.
- [Release notes](https://github.com/actions/download-artifact/releases)
- [Commits](https://github.com/actions/download-artifact/compare/v4...v5)

---
updated-dependencies:
- dependency-name: actions/download-artifact
  dependency-version: '5'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-08-12 09:19:57 +02:00
Kayhan cb8aa45cde Added Turkish language (#2099) 2025-08-12 08:14:05 +02:00
Bernd Storath 54e0a1e886 update packages 2025-08-12 08:13:10 +02:00
Ezmana 71a452080e French language update (#2090) 2025-08-10 20:57:17 +02:00
Ciro Mota 5be7fb3038 feat: Add Português Brasil translation (#2077) 2025-08-08 19:30:22 +02:00
Aleksandr Fedotov 59f0c8b0d2 Update ru.json (#2078) 2025-08-06 07:52:38 +02:00
Bernd Storath e1ed93674d update packages, fix es, remove nuxtr 2025-08-05 08:43:30 +02:00
Néstor 6b65a8099b Create es.json (spanish language) (#2070)
Create es.json

Added a preview of spanish translation.
2025-08-05 08:28:12 +02:00
Nikolas c1dd494d0f Update uk.json (#2065) 2025-07-30 10:10:07 +02:00
Bernd Storath bf9e8a6e21 fix lint 2025-07-25 12:39:13 +02:00
Bernd Storath 371d7617ff fix styling 2025-07-25 12:37:46 +02:00
Bernd Storath 0b435d9ed8 update packages 2025-07-25 12:32:25 +02:00
Bernd Storath 07f89d15a9 Feat: show client endpoint (#2058)
* show client endpoint

* improve

* fix status code
2025-07-25 12:00:42 +02:00
Bernd Storath b5318086d2 Fix: Remove dns if empty (#2057)
remove dns if empty
2025-07-25 11:26:16 +02:00
Bernd Storath b7f9b7c830 Feat: Allow empty dns (#2052)
* allow empty dns

* remove log
2025-07-24 10:58:40 +02:00
mnaray 2e4f386f49 Improve incomplete setup docs in README (#2031)
* Update setup docs in README

* remove redundant information
2025-07-15 10:02:45 +02:00
Astesana 9ead985798 Fixes network creation in docker-run.md (#2018)
* Fixes network creation in docker-run.md

* Update docker-run.md as suggested by @kaaax0815
2025-07-14 09:58:34 +02:00
Bernd Storath 6326ee31c4 migrate to zod v4 2025-07-14 08:19:23 +02:00
Bernd Storath 984dc95550 update packages 2025-07-14 07:51:35 +02:00
Maksim M. cd0a9b8e33 Add Russian translation (#2014)
* feat(i18n): add Russian translation

* Corrected the AI translation

Подправил AI перевод

* fix: format ru.json
2025-07-10 09:53:03 +02:00
Bernd Storath 90b9ba15ec feat: make api more secure (#2015)
make api more secure
2025-07-09 15:42:29 +02:00
Bernd Storath 0abc419db7 fix lint errors 2025-07-07 11:19:45 +02:00
Daeho Ro b185d7a63d add Korean translation (#2003)
Added translation using Weblate (Korean)




Translate-URL: https://mini-i18n.daeho.ro/projects/wg-easy/main/ko/
Translation: wg-easy/main

Co-authored-by: OpenAI <noreply-mt-openai@weblate.org>
2025-07-07 10:59:54 +02:00
Bernd Storath 4bb880c4b7 update packages 2025-07-07 10:06:23 +02:00
SebastiaanTheCoder b0ba9e43f9 Updated traefik documentation (#2005) 2025-07-07 09:53:36 +02:00
杨黄林 ddb01fb968 Improve Chinese translation and fix 4-character Chinese suggestion button (#1997)
* Improve Chinese Simplified translate

* Use whitespace-nowrap class to fix Suggest button

* fix formatting

---------

Co-authored-by: Bernd Storath <999999bst@gmail.com>
2025-07-02 20:15:19 +02:00
Bernd Storath 22812e0632 Fix: Admin menu text (#1999)
make admin menu reactive
2025-07-02 09:42:09 +02:00
Bernd Storath 4d84e1d9d3 fix changelog 2025-07-01 08:51:35 +02:00
Bernd Storath 9368b857e8 Bump version to 15.1.0 2025-07-01 08:50:21 +02:00
Bernd Storath 0f663df7f6 Add option to disable ipv6 (#1951)
* add option to disable ipv6

* don't add ipv6 address

* update docs
2025-07-01 07:57:14 +02:00
Kirill Dvoretskov 68fde7d165 Updated container launch commands (#1989)
* Updated container launch commands

* one more occurrence

---------

Co-authored-by: Bernd Storath <999999bst@gmail.com>
2025-06-30 08:01:26 +02:00
杨黄林 501a784264 Add Chinese Simplified (#1990)
* Add Chinese Simplified

* fix formatting

---------

Co-authored-by: Bernd Storath <999999bst@gmail.com>
2025-06-30 07:55:00 +02:00
Bernd Storath 629c184195 update packages 2025-06-30 07:54:45 +02:00
Rayyamhk 76b8818a33 feat: Add Traditional Chinese (zh-HK) i18n Support (#1988)
* feat:add translation for zh-hk

* fix formatting issues
2025-06-27 08:25:02 +02:00
Pascal Dietrich 6c52301a64 Add german translations (#1889) 2025-06-26 16:05:44 +02:00
Bernd Storath be26db63ca add docs on how to add/update translation 2025-06-26 15:27:27 +02:00
Bernd Storath 962bfa213f update screenshot 2025-06-26 14:56:15 +02:00
Bernd Storath ee00e5c914 update packages 2025-06-23 09:53:30 +02:00
Bernd Storath 6343213538 v14 migration env vars
make note that the env vars from v14 won't be migrated
2025-06-11 11:14:13 +02:00
Bernd Storath 187bdc0836 update packages 2025-06-11 07:42:21 +02:00
wh!le f2520f0481 docs for caddy example (#1939) 2025-06-09 16:04:59 +02:00
Ezmana 5e9a73645b Add French language (#1924)
* French translation file creation

* Add French language
2025-06-09 15:55:12 +02:00
Bernd Storath 783fa3286c update packages
removed override as every package updated
2025-06-02 08:23:26 +02:00
Nikolas 77b4f9db65 Added Ukrainian language (#1906)
* Add files via upload

Ukrainian language

* Update ua.json

* Update i18n.config.ts

* Update i18n.config.ts

* Rename ua.json to uk.json

* Update i18n.config.ts

* Update nuxt.config.ts

* Update uk.json
2025-06-01 16:40:31 +02:00
Bernd Storath 0f6f07161b update docker compose 2025-05-28 13:50:13 +02:00
Bernd Storath d75a836de9 update changelog 2025-05-28 12:33:44 +02:00
Bernd Storath f79b0fd025 Bump version to 15.0.0 2025-05-28 12:22:42 +02:00
114 changed files with 13106 additions and 4511 deletions
+4 -4
View File
@@ -27,17 +27,17 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v6
- name: Initialize CodeQL
uses: github/codeql-action/init@v3
uses: github/codeql-action/init@v4
with:
languages: ${{ matrix.language }}
- name: Autobuild
uses: github/codeql-action/autobuild@v3
uses: github/codeql-action/autobuild@v4
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v3
uses: github/codeql-action/analyze@v4
with:
category: "/language:${{matrix.language}}"
+15 -7
View File
@@ -18,10 +18,10 @@ jobs:
os: ubuntu-latest
- platform: linux/arm64
os: ubuntu-24.04-arm
- platform: linux/arm/v7
os: ubuntu-24.04-arm
# - platform: linux/arm/v7
# os: ubuntu-24.04-arm
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Prepare
run: |
@@ -69,7 +69,7 @@ jobs:
touch "${{ runner.temp }}/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: digests-${{ env.PLATFORM_PAIR }}
path: ${{ runner.temp }}/digests/*
@@ -85,7 +85,7 @@ jobs:
needs: docker-build
steps:
- name: Download digests
uses: actions/download-artifact@v4
uses: actions/download-artifact@v7
with:
path: ${{ runner.temp }}/digests
pattern: digests-*
@@ -98,6 +98,13 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to Codeberg
uses: docker/login-action@v3
with:
registry: codeberg.org
username: ${{ secrets.CODEBERG_USER }}
password: ${{ secrets.CODEBERG_PASS }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
@@ -107,6 +114,7 @@ jobs:
with:
images: |
ghcr.io/wg-easy/wg-easy
codeberg.org/wg-easy/wg-easy
flavor: |
latest=false
tags: |
@@ -130,10 +138,10 @@ jobs:
contents: write
needs: docker-merge
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Setup Python
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: 3.11.9
cache: "pip"
+15 -7
View File
@@ -25,10 +25,10 @@ jobs:
os: ubuntu-latest
- platform: linux/arm64
os: ubuntu-24.04-arm
- platform: linux/arm/v7
os: ubuntu-24.04-arm
# - platform: linux/arm/v7
# os: ubuntu-24.04-arm
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
ref: master
@@ -78,7 +78,7 @@ jobs:
touch "${{ runner.temp }}/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: digests-${{ env.PLATFORM_PAIR }}
path: ${{ runner.temp }}/digests/*
@@ -94,7 +94,7 @@ jobs:
needs: docker-build
steps:
- name: Download digests
uses: actions/download-artifact@v4
uses: actions/download-artifact@v7
with:
path: ${{ runner.temp }}/digests
pattern: digests-*
@@ -107,6 +107,13 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to Codeberg
uses: docker/login-action@v3
with:
registry: codeberg.org
username: ${{ secrets.CODEBERG_USER }}
password: ${{ secrets.CODEBERG_PASS }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
@@ -116,6 +123,7 @@ jobs:
with:
images: |
ghcr.io/wg-easy/wg-easy
codeberg.org/wg-easy/wg-easy
flavor: |
latest=false
tags: |
@@ -139,12 +147,12 @@ jobs:
contents: write
needs: docker-merge
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
with:
ref: master
- name: Setup Python
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: 3.11.9
cache: "pip"
+3 -3
View File
@@ -21,10 +21,10 @@ jobs:
os: ubuntu-latest
- platform: linux/arm64
os: ubuntu-24.04-arm
- platform: linux/arm/v7
os: ubuntu-24.04-arm
# - platform: linux/arm/v7
# os: ubuntu-24.04-arm
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Prepare
run: |
+15 -7
View File
@@ -26,10 +26,10 @@ jobs:
os: ubuntu-latest
- platform: linux/arm64
os: ubuntu-24.04-arm
- platform: linux/arm/v7
os: ubuntu-24.04-arm
# - platform: linux/arm/v7
# os: ubuntu-24.04-arm
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Prepare
run: |
@@ -77,7 +77,7 @@ jobs:
touch "${{ runner.temp }}/digests/${digest#sha256:}"
- name: Upload digest
uses: actions/upload-artifact@v4
uses: actions/upload-artifact@v6
with:
name: digests-${{ env.PLATFORM_PAIR }}
path: ${{ runner.temp }}/digests/*
@@ -95,7 +95,7 @@ jobs:
needs: docker-build
steps:
- name: Download digests
uses: actions/download-artifact@v4
uses: actions/download-artifact@v7
with:
path: ${{ runner.temp }}/digests
pattern: digests-*
@@ -108,6 +108,13 @@ jobs:
username: ${{ github.actor }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Login to Codeberg
uses: docker/login-action@v3
with:
registry: codeberg.org
username: ${{ secrets.CODEBERG_USER }}
password: ${{ secrets.CODEBERG_PASS }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
@@ -117,6 +124,7 @@ jobs:
with:
images: |
ghcr.io/wg-easy/wg-easy
codeberg.org/wg-easy/wg-easy
flavor: |
latest=false
tags: |
@@ -144,10 +152,10 @@ jobs:
contents: write
needs: docker-merge
steps:
- uses: actions/checkout@v4
- uses: actions/checkout@v6
- name: Setup Python
uses: actions/setup-python@v5
uses: actions/setup-python@v6
with:
python-version: 3.11.9
cache: "pip"
+6 -6
View File
@@ -14,7 +14,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v6
- uses: pnpm/action-setup@v4
name: Install pnpm
@@ -22,9 +22,9 @@ jobs:
run_install: false
- name: Setup Node
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version: "lts/*"
node-version: "lts/jod"
check-latest: true
cache: "pnpm"
@@ -47,7 +47,7 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@v4
uses: actions/checkout@v6
- uses: pnpm/action-setup@v4
name: Install pnpm
@@ -55,9 +55,9 @@ jobs:
run_install: false
- name: Setup Node
uses: actions/setup-node@v4
uses: actions/setup-node@v6
with:
node-version: "lts/*"
node-version: "lts/jod"
check-latest: true
cache: "pnpm"
+10 -1
View File
@@ -15,13 +15,16 @@ jobs:
runs-on: ubuntu-latest
if: github.repository_owner == 'wg-easy'
permissions:
actions: write
issues: write
pull-requests: write
steps:
- uses: actions/stale@v9
- uses: actions/stale@v10
with:
# Stale after 30 days of inactivity
days-before-issue-stale: 30
# Close after 14 days of being stale
days-before-issue-close: 14
stale-issue-label: "stale"
stale-issue-message: "This issue is stale because it has been open for 30 days with no activity."
@@ -32,3 +35,9 @@ jobs:
close-pr-message: "This PR was closed because it has been inactive for 14 days since being marked as stale."
repo-token: ${{ secrets.GITHUB_TOKEN }}
operations-per-run: 100
# Ignore Feature requests (https://github.com/actions/stale/issues/1293)
only-issue-types: "Bug"
# Ignore confirmed bugs
exempt-issue-labels: "status: confirmed"
# Ignore PRs with milestones
exempt-all-pr-milestones: true
-2
View File
@@ -3,8 +3,6 @@
"aaron-bond.better-comments",
"dbaeumer.vscode-eslint",
"antfu.goto-alias",
"visualstudioexptteam.vscodeintellicode",
"Nuxtr.nuxtr-vscode",
"esbenp.prettier-vscode",
"yoavbls.pretty-ts-errors",
"bradlc.vscode-tailwindcss",
-3
View File
@@ -3,9 +3,6 @@
"editor.useTabStops": false,
"editor.defaultFormatter": "esbenp.prettier-vscode",
"editor.formatOnSave": true,
"nuxtr.vueFiles.style.addStyleTag": false,
"nuxtr.piniaFiles.defaultTemplate": "setup",
"nuxtr.monorepoMode.DirectoryName": "src",
"editor.codeActionsOnSave": {
"source.fixAll.eslint": "always"
},
+85 -2
View File
@@ -7,14 +7,97 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## [Unreleased]
## [15.2.2] - 2026-02-06
### Added
- Added Userspace WireGuard support (https://github.com/wg-easy/wg-easy/pull/2419)
### Fixed
- LangSelector overlapping with Buttons (https://github.com/wg-easy/wg-easy/pull/2434)
- AmnzeziaWG config parameters (https://github.com/wg-easy/wg-easy/pull/2440)
- OpenMetrics help string format (https://github.com/wg-easy/wg-easy/pull/2453)
- Reset 2fa when resetting admin password (https://github.com/wg-easy/wg-easy/pull/2461)
### Docs
- Replace Watchtower with maintained fork (https://github.com/wg-easy/wg-easy/pull/2456)
## [15.2.1] - 2026-01-14
### Fixed
- Icon in Searchbar (https://github.com/wg-easy/wg-easy/commit/458f66818a400f181e2c6326ede077c8793d71f2)
- Interface save not working (https://github.com/wg-easy/wg-easy/commit/48f3fbd715a889e2425702a8a46332f2752aef91)
- Error Messages in Setup (https://github.com/wg-easy/wg-easy/commit/32a055093a76342c40858d8dcf563b0700a8bd48)
## [15.2.0] - 2026-01-12
### Added
- AmneziaWG integration (https://github.com/wg-easy/wg-easy/pull/2102, https://github.com/wg-easy/wg-easy/pull/2226)
- Search / filter box (https://github.com/wg-easy/wg-easy/pull/2170)
- `INIT_ALLOWED_IPS` env var (https://github.com/wg-easy/wg-easy/pull/2164)
- Show client endpoint (https://github.com/wg-easy/wg-easy/pull/2058)
- Add option to view and copy config (https://github.com/wg-easy/wg-easy/pull/2289)
### Fixed
- Fix download as conf.txt (https://github.com/wg-easy/wg-easy/pull/2269)
- Clean filename for OTL download (https://github.com/wg-easy/wg-easy/pull/2253)
- Text color in admin menu in light mode (https://github.com/wg-easy/wg-easy/pull/2307)
### Changed
- Allow lower MTU (https://github.com/wg-easy/wg-easy/pull/2228)
- Use /32 and /128 for client Cidr (https://github.com/wg-easy/wg-easy/pull/2217)
- Return client id on create (https://github.com/wg-easy/wg-easy/pull/2190)
- Publish on Codeberg (https://github.com/wg-easy/wg-easy/pull/2160)
- Allow empty DNS (https://github.com/wg-easy/wg-easy/pull/2052, https://github.com/wg-easy/wg-easy/pull/2057)
- Don't include keys in API responses (https://github.com/wg-easy/wg-easy/pull/2015)
- Try all QR ecc levels (https://github.com/wg-easy/wg-easy/pull/2288)
- Update OneTimeLink expiry on reuse (https://github.com/wg-easy/wg-easy/pull/2370)
- Removed ARMv7 support (https://github.com/wg-easy/wg-easy/pull/2369)
### Docs
- Add AdGuard Home (https://github.com/wg-easy/wg-easy/pull/2175)
- Add Routed (No NAT) docs (https://github.com/wg-easy/wg-easy/pull/2181, https://github.com/wg-easy/wg-easy/pull/2380)
- Add AmneziaWG docs (https://github.com/wg-easy/wg-easy/pull/2108, https://github.com/wg-easy/wg-easy/pull/2292)
## [15.1.0] - 2025-07-01
### Added
- Added Ukrainian language (#1906)
- Add French language (#1924)
- docs for caddy example (#1939)
- add docs on how to add/update translation (be26db6)
- Add german translations (#1889)
- feat: Add Traditional Chinese (zh-HK) i18n Support (#1988)
- Add Chinese Simplified (#1990)
- Add option to disable ipv6 (#1951)
### Fixed
- Updated container launch commands (#1989)
- update screenshot (962bfa2)
### Changed
- Updated dependencies
## [15.0.0] - 2025-05-28
We're super excited to announce v15!
This update is an entire rewrite to make it even easier to set up your own VPN.
## Breaking Changes
### Breaking Changes
As the whole setup has changed, we recommend to start from scratch. And import your existing configs.
## Major Changes
### Major Changes
- Almost all Environment variables removed
- New and Improved UI
+24 -3
View File
@@ -1,4 +1,4 @@
FROM docker.io/library/node:lts-alpine AS build
FROM docker.io/library/node:jod-alpine AS build
WORKDIR /app
# update corepack
@@ -14,9 +14,18 @@ RUN pnpm install
COPY src ./
RUN pnpm build
# Build amneziawg-tools
RUN apk add linux-headers build-base go git && \
git clone https://github.com/amnezia-vpn/amneziawg-tools.git && \
git clone https://github.com/amnezia-vpn/amneziawg-go && \
cd amneziawg-go && \
make && \
cd ../amneziawg-tools/src && \
make
# Copy build result to a new image.
# This saves a lot of disk space.
FROM docker.io/library/node:lts-alpine
FROM docker.io/library/node:jod-alpine
WORKDIR /app
HEALTHCHECK --interval=1m --timeout=5s --retries=3 CMD /usr/bin/timeout 5s /bin/sh -c "/usr/bin/wg show | /bin/grep -q interface || exit 1"
@@ -27,11 +36,18 @@ COPY --from=build /app/.output /app
COPY --from=build /app/server/database/migrations /app/server/database/migrations
# libsql (https://github.com/nitrojs/nitro/issues/3328)
RUN cd /app/server && \
npm install --no-save libsql && \
npm install --no-save --omit=dev libsql && \
npm cache clean --force
# cli
COPY --from=build /app/cli/cli.sh /usr/local/bin/cli
RUN chmod +x /usr/local/bin/cli
# Copy amneziawg-go
COPY --from=build /app/amneziawg-go/amneziawg-go /usr/bin/amneziawg-go
RUN chmod +x /usr/bin/amneziawg-go
# Copy amneziawg-tools
COPY --from=build /app/amneziawg-tools/src/wg /usr/bin/awg
COPY --from=build /app/amneziawg-tools/src/wg-quick/linux.bash /usr/bin/awg-quick
RUN chmod +x /usr/bin/awg /usr/bin/awg-quick
# Install Linux packages
RUN apk add --no-cache \
@@ -42,8 +58,12 @@ RUN apk add --no-cache \
nftables \
kmod \
iptables-legacy \
wireguard-go \
wireguard-tools
RUN mkdir -p /etc/amnezia
RUN ln -s /etc/wireguard /etc/amnezia/amneziawg
# Use iptables-legacy
RUN update-alternatives --install /usr/sbin/iptables iptables /usr/sbin/iptables-legacy 10 --slave /usr/sbin/iptables-restore iptables-restore /usr/sbin/iptables-legacy-restore --slave /usr/sbin/iptables-save iptables-save /usr/sbin/iptables-legacy-save
RUN update-alternatives --install /usr/sbin/ip6tables ip6tables /usr/sbin/ip6tables-legacy 10 --slave /usr/sbin/ip6tables-restore ip6tables-restore /usr/sbin/ip6tables-legacy-restore --slave /usr/sbin/ip6tables-save ip6tables-save /usr/sbin/ip6tables-legacy-save
@@ -54,6 +74,7 @@ ENV PORT=51821
ENV HOST=0.0.0.0
ENV INSECURE=false
ENV INIT_ENABLED=false
ENV DISABLE_IPV6=false
LABEL org.opencontainers.image.source=https://github.com/wg-easy/wg-easy
+3 -1
View File
@@ -1,4 +1,4 @@
FROM docker.io/library/node:lts-alpine
FROM docker.io/library/node:jod-alpine
WORKDIR /app
# update corepack
@@ -16,6 +16,7 @@ RUN apk add --no-cache \
ip6tables \
kmod \
iptables-legacy \
wireguard-go \
wireguard-tools
# Use iptables-legacy
@@ -28,6 +29,7 @@ ENV PORT=51821
ENV HOST=0.0.0.0
ENV INSECURE=true
ENV INIT_ENABLED=false
ENV DISABLE_IPV6=false
# Install Dependencies
COPY src/package.json src/pnpm-lock.yaml ./
+4 -15
View File
@@ -7,18 +7,12 @@
[![GitHub Release](https://img.shields.io/github/v/release/wg-easy/wg-easy)](https://github.com/wg-easy/wg-easy/releases/latest)
[![Image Pulls](https://img.shields.io/badge/image_pulls-12M+-blue)](https://github.com/wg-easy/wg-easy/pkgs/container/wg-easy)
<!-- TODO: remove after release -->
> [!WARNING]
> You are viewing the README of the pre-release of v15.
> If you want to setup wg-easy right now. Read the README in the production branch here: [README](https://github.com/wg-easy/wg-easy/tree/production) or here for the last nightly: [README](https://github.com/wg-easy/wg-easy/tree/c6dce0f6fb2e28e7e40ddac1498bd67e9bb17cba)
You have found the easiest way to install & manage WireGuard on any Linux host!
<!-- TOOD: update screenshot -->
<p align="center">
<img src="./assets/screenshot.png" width="802" />
<img src="./assets/screenshot.png" width="802" alt="wg-easy Screenshot" />
</p>
## Features
@@ -43,11 +37,6 @@ You have found the easiest way to install & manage WireGuard on any Linux host!
> [!NOTE]
> To better manage documentation for this project, it has its own site here: [https://wg-easy.github.io/wg-easy/latest](https://wg-easy.github.io/wg-easy/latest)
<!-- TODO: remove after release -->
> [!WARNING]
> As the Docs are still in Pre-release, you can access them here [https://wg-easy.github.io/wg-easy/Pre-release](https://wg-easy.github.io/wg-easy/Pre-release)
- [Getting Started](https://wg-easy.github.io/wg-easy/latest/getting-started/)
- [Basic Installation](https://wg-easy.github.io/wg-easy/latest/examples/tutorials/basic-installation/)
- [Caddy](https://wg-easy.github.io/wg-easy/latest/examples/tutorials/caddy/)
@@ -79,11 +68,11 @@ And log in again.
The easiest way to run WireGuard Easy is with Docker Compose.
Just download [`docker-compose.yml`](docker-compose.yml) and execute `sudo docker compose up -d`.
Just follow [these steps](https://wg-easy.github.io/wg-easy/latest/examples/tutorials/basic-installation/) in the detailed documentation.
Now setup a reverse proxy to be able to access the Web UI securely from the internet.
You can also install WireGuard Easy with the [docker run command](https://wg-easy.github.io/wg-easy/latest/examples/tutorials/docker-run/) or via [podman](https://wg-easy.github.io/wg-easy/latest/examples/tutorials/podman-nft/).
If you want to access the Web UI over HTTP, change the env var `INSECURE` to `true`. This is not recommended. Only use this for testing
Now [setup a reverse proxy](https://wg-easy.github.io/wg-easy/latest/examples/tutorials/basic-installation/#setup-reverse-proxy) to be able to access the Web UI securely from the internet. This step is optional, just make sure to follow the guide [here](https://wg-easy.github.io/wg-easy/latest/examples/tutorials/reverse-proxyless/) if you decide not to do it.
## Donate
Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

After

Width:  |  Height:  |  Size: 167 KiB

-44
View File
@@ -1,44 +0,0 @@
volumes:
etc_wireguard:
services:
wg-easy:
#environment:
# Optional:
# - PORT=51821
# - HOST=0.0.0.0
# - INSECURE=false
image: ghcr.io/wg-easy/wg-easy:15
container_name: wg-easy
networks:
wg:
ipv4_address: 10.42.42.42
ipv6_address: fdcc:ad94:bacf:61a3::2a
volumes:
- etc_wireguard:/etc/wireguard
- /lib/modules:/lib/modules:ro
ports:
- "51820:51820/udp"
- "51821:51821/tcp"
restart: unless-stopped
cap_add:
- NET_ADMIN
- SYS_MODULE
# - NET_RAW # ⚠️ Uncomment if using Podman Compose
sysctls:
- net.ipv4.ip_forward=1
- net.ipv4.conf.all.src_valid_mark=1
- net.ipv6.conf.all.disable_ipv6=0
- net.ipv6.conf.all.forwarding=1
- net.ipv6.conf.default.forwarding=1
networks:
wg:
driver: bridge
enable_ipv6: true
ipam:
driver: default
config:
- subnet: 10.42.42.0/24
- subnet: fdcc:ad94:bacf:61a3::/64
+24 -25
View File
@@ -3,35 +3,21 @@ volumes:
services:
wg-easy:
environment:
# Change Language:
# (Supports: en, ua, ru, tr, no, pl, fr, de, ca, es, ko, vi, nl, is, pt, chs, cht, it, th, hi)
- LANG=de
# ⚠️ Required:
# Change this to your host's public address
- WG_HOST=raspberrypi.local
#environment:
# Optional:
# - PORT=51821
# - HOST=0.0.0.0
# - INSECURE=false
# Optional:
# - PASSWORD_HASH=$$2y$$10$$hBCoykrB95WSzuV4fafBzOHWKu9sbyVa34GJr8VV5R/pIelfEMYyG # (needs double $$, hash of 'foobar123'; see "How_to_generate_an_bcrypt_hash.md" for generate the hash)
# - PORT=51821
# - WG_PORT=51820
# - WG_CONFIG_PORT=92820
# - WG_DEFAULT_ADDRESS=10.8.0.x
# - WG_DEFAULT_DNS=1.1.1.1
# - WG_MTU=1420
# - WG_ALLOWED_IPS=192.168.15.0/24, 10.0.1.0/24
# - WG_PERSISTENT_KEEPALIVE=25
# - WG_PRE_UP=echo "Pre Up" > /etc/wireguard/pre-up.txt
# - WG_POST_UP=echo "Post Up" > /etc/wireguard/post-up.txt
# - WG_PRE_DOWN=echo "Pre Down" > /etc/wireguard/pre-down.txt
# - WG_POST_DOWN=echo "Post Down" > /etc/wireguard/post-down.txt
# - UI_TRAFFIC_STATS=true
# - UI_CHART_TYPE=0 # (0 Charts disabled, 1 # Line chart, 2 # Area chart, 3 # Bar chart)
image: ghcr.io/wg-easy/wg-easy:14
image: ghcr.io/wg-easy/wg-easy:15
container_name: wg-easy
networks:
wg:
ipv4_address: 10.42.42.42
ipv6_address: fdcc:ad94:bacf:61a3::2a
volumes:
- etc_wireguard:/etc/wireguard
- /lib/modules:/lib/modules:ro
ports:
- "51820:51820/udp"
- "51821:51821/tcp"
@@ -43,3 +29,16 @@ services:
sysctls:
- net.ipv4.ip_forward=1
- net.ipv4.conf.all.src_valid_mark=1
- net.ipv6.conf.all.disable_ipv6=0
- net.ipv6.conf.all.forwarding=1
- net.ipv6.conf.default.forwarding=1
networks:
wg:
driver: bridge
enable_ipv6: true
ipam:
driver: default
config:
- subnet: 10.42.42.0/24
- subnet: fdcc:ad94:bacf:61a3::/64
+79
View File
@@ -0,0 +1,79 @@
---
title: AmneziaWG
---
## Introduction
**AmneziaWG** is a modified version of the WireGuard protocol with enhanced traffic obfuscation capabilities. AmneziaWG's primary goal is to counter deep packet inspection (DPI) systems and bypass VPN blocking.
AmneziaWG adds multi-level transport-layer obfuscation by:
- Modifying packet headers
- Randomizing handshake message sizes
- Disguising traffic to resemble popular UDP protocols
These measures make it harder for third parties to analyze or identify your traffic, enhancing both privacy and security.
## Activating AmneziaWG
You must install the [AmneziaWG kernel module](https://github.com/amnezia-vpn/amneziawg-linux-kernel-module) on the host system.
Experimental support for AmneziaWG can be enabled by setting the `EXPERIMENTAL_AWG` environment variable to `true`. Starting from wg-easy version 16, this setting will be enabled by default. This feature is still under development and may change in future releases.
When enabled, wg-easy will automatically detect whether the AmneziaWG kernel module is available. If it is not, the system will fall back to the standard WireGuard module.
To override this automatic detection, set the `OVERRIDE_AUTO_AWG` environment variable. By default, this variable is unset.
Possible values:
- `awg` — Force use of AmneziaWG
- `wg` — Force use of standard WireGuard
## AmneziaWG Parameters
Parameter descriptions can be found in the [AmneziaWG documentation](https://docs.amnezia.org/documentation/amnezia-wg) and on the [kernel module page](https://github.com/amnezia-vpn/amneziawg-linux-kernel-module).
All parameters except I1-I5 will be set at first startup. For information on how to set I1-I5 parameters, refer to the [AmneziaWG documentation](https://docs.amnezia.org/documentation/instructions/new-amneziawg-selfhosted/#how-to-extract-a-protocol-signature-for-amneziawg-15-manually).
If a parameter is not set, it will not be added to the configuration. If all AmneziaWG-specific parameters are absent, AmneziaWG will be fully compatible with standard WireGuard.
### Parameter Compatibility Table
| Parameter | Can differ between server and client | Configurable on server | Configurable on client |
| --------- | ------------------------------------ | ---------------------- | ----------------------- |
| Jc | ✅ Yes | ✅ | ✅ |
| Jmin | ✅ Yes | ✅ | ✅ |
| Jmax | ✅ Yes | ✅ | ✅ |
| S1-S4 | ❌ No, must match | ✅ | ❌ (copied from server) |
| H1-H4 | ❌ No, must match | ✅ | ❌ (copied from server) |
| I1-I5 | ✅ Yes | ✅ | ✅ |
## Client Applications
To be able to connect to wg-easy if AmneziaWG is enabled, you must have an AmneziaWG-compatible client. Where an AmneziaWG app is available for your platform, it is recommended to use it rather than Amnezia VPN.
Android:
- [AmneziaWG](https://play.google.com/store/apps/details?id=org.amnezia.awg) - AmneziaWG Official Client
- [WG Tunnel](https://play.google.com/store/apps/details?id=com.zaneschepke.wireguardautotunnel) - Third Party Client
- [Amnezia VPN](https://play.google.com/store/apps/details?id=org.amnezia.vpn) - Amnezia VPN Official Client
iOS and macOS:
- [AmneziaWG](https://apps.apple.com/us/app/amneziawg/id6478942365) - AmneziaWG Official Client
- [Amnezia VPN](https://apps.apple.com/us/app/amneziavpn/id1600529900) - Amnezia VPN Official Client
Windows:
- [AmneziaWG](https://github.com/amnezia-vpn/amneziawg-windows-client/releases) - AmneziaWG Official Client (Requires building from source code)
- [Amnezia VPN](https://amnezia.org/downloads) - Amnezia VPN Official Client
Linux:
- [Amnezia VPN](https://amnezia.org/downloads) - Amnezia VPN Official Client
- [amneziawg-tools](https://github.com/amnezia-vpn/amneziawg-tools) - AmneziaWG Tools
OpenWRT:
- [AmneziaWG OpenWRT](https://github.com/Slava-Shchipunov/awg-openwrt) - AmneziaWG OpenWRT Packages
- [AmneziaWG OpenWRT](https://github.com/lolo6oT/awg-openwrt) - AmneziaWG OpenWRT Packages
@@ -0,0 +1,9 @@
---
title: Experimental Configuration
---
There are several experimental features that can be enabled by setting the appropriate environment variables. These features are not guaranteed to be stable and may change in future releases.
| Env | Default | Example | Description | Notes | More Info |
| ---------------- | ------- | ------- | -------------------------------------- | --------------------------------------- | ------------------------ |
| EXPERIMENTAL_AWG | false | true | Enables experimental AmneziaWG support | Planned to be enabled by default in v16 | [See here](./amnezia.md) |
@@ -4,8 +4,19 @@ title: Optional Configuration
You can set these environment variables to configure the container. They are not required, but can be useful in some cases.
| Env | Default | Example | Description |
| ---------- | --------- | ----------- | ------------------------------ |
| `PORT` | `51821` | `6789` | TCP port for Web UI. |
| `HOST` | `0.0.0.0` | `localhost` | IP address web UI binds to. |
| `INSECURE` | `false` | `true` | If access over http is allowed |
| Env | Default | Example | Description |
| -------------- | --------- | ----------- | ---------------------------------- |
| `PORT` | `51821` | `6789` | TCP port for Web UI. |
| `HOST` | `0.0.0.0` | `localhost` | IP address web UI binds to. |
| `INSECURE` | `false` | `true` | If access over http is allowed |
| `DISABLE_IPV6` | `false` | `true` | If IPv6 support should be disabled |
/// note | IPv6 Caveats
Disabling IPv6 will disable the creation of the default IPv6 firewall rules and won't add a IPv6 address to the interface and clients.
You will however still see a IPv6 address in the Web UI, but it won't be used.
This option can be removed in the future, as more devices support IPv6.
///
@@ -6,18 +6,19 @@ If you want to run the setup without any user interaction, e.g. with a tool like
These will only be used during the first start of the container. After that, the setup will be disabled.
| Env | Example | Description | Group |
| ---------------- | ----------------- | --------------------------------------------------------- | ----- |
| `INIT_ENABLED` | `true` | Enables the below env vars | 0 |
| `INIT_USERNAME` | `admin` | Sets admin username | 1 |
| `INIT_PASSWORD` | `Se!ureP%ssw` | Sets admin password | 1 |
| `INIT_HOST` | `vpn.example.com` | Host clients will connect to | 1 |
| `INIT_PORT` | `51820` | Port clients will connect to and wireguard will listen on | 1 |
| `INIT_DNS` | `1.1.1.1,8.8.8.8` | Sets global dns setting | 2 |
| `INIT_IPV4_CIDR` | `10.8.0.0/24` | Sets IPv4 cidr | 3 |
| `INIT_IPV6_CIDR` | `2001:0DB8::/32` | Sets IPv6 cidr | 3 |
| Env | Example | Description | Group |
| ------------------ | ---------------------------- | --------------------------------------------------------- | ----- |
| `INIT_ENABLED` | `true` | Enables the below env vars | 0 |
| `INIT_USERNAME` | `admin` | Sets admin username | 1 |
| `INIT_PASSWORD` | `Se!ureP%ssw` | Sets admin password | 1 |
| `INIT_HOST` | `vpn.example.com` | Host clients will connect to | 1 |
| `INIT_PORT` | `51820` | Port clients will connect to and wireguard will listen on | 1 |
| `INIT_DNS` | `1.1.1.1,8.8.8.8` | Sets global dns setting | 2 |
| `INIT_IPV4_CIDR` | `10.8.0.0/24` | Sets IPv4 cidr | 3 |
| `INIT_IPV6_CIDR` | `2001:0DB8::/32` | Sets IPv6 cidr | 3 |
| `INIT_ALLOWED_IPS` | `10.8.0.0/24,2001:0DB8::/32` | Sets global Allowed IPs | 4 |
/// warning | Variables have to be used together
/// warning | Variables have to be used together
If variables are in the same group, you have to set all of them. For example, if you set `INIT_IPV4_CIDR`, you also have to set `INIT_IPV6_CIDR`.
+13 -7
View File
@@ -6,22 +6,24 @@ This guide will help you migrate from `v14` to version `v15` of `wg-easy`.
## Changes
- This is a complete rewrite of the `wg-easy` project. Therefore the configuration files and the way you interact with the project have changed.
- If you use armv6, you unfortunately won't be able to migrate to `v15`.
- If you are connecting to the web ui via HTTP, you need to set the `INSECURE` environment variable to `true` in the new container.
- This is a complete rewrite of the `wg-easy` project, therefore the configuration files and the way you interact with the project have changed.
- If you use armv6 or armv7, you unfortunately won't be able to migrate to `v15`.
- If you are connecting to the Web UI via HTTP, you need to set the `INSECURE` environment variable to `true` in the new container.
## Migration
### Backup
Before you start the migration, make sure to backup your existing configuration files.
Before you start the migration, make sure to back up your existing configuration files.
Go into the Web Ui and click the Backup button, this should download a `wg0.json` file.
Go into the Web UI and click the Backup button, this should download a `wg0.json` file.
Or download the `wg0.json` file from your container volume to your pc.
You will need this file for the migration
You will also need to back up the old environment variables you set for the container, as they will not be automatically migrated.
### Remove old container
1. Stop the running container
@@ -32,10 +34,10 @@ If you are using `docker run`
docker stop wg-easy
```
If you are using `docker-compose`
If you are using `docker compose`
```shell
docker-compose down
docker compose down
```
### Start new container
@@ -47,6 +49,10 @@ In the setup wizard, select that you already have a configuration file and uploa
[docs-getting-started]: ../../getting-started.md
[docs-examples]: ../../examples/tutorials/basic-installation.md
### Environment Variables
v15 does not use the same environment variables as v14, most of them have been moved to the Admin Panel in the Web UI.
### Done
You have now successfully migrated to `v15` of `wg-easy`.
+27
View File
@@ -0,0 +1,27 @@
---
title: Translation
---
This project supports multiple languages. If you would like to contribute a translation, please follow these steps:
## Add new Translation
Create a new file in `src/i18n/locales`. Name it `<locale_code>.json` (e.g. `fr.json` for French).
Import and add the newly created file in `src/i18n/i18n.config.ts`.
Add your language in the `src/nuxt.config.ts` file. You have to specify code, language and name.
`code` is the name of the translation file without the extension (e.g. `fr` for `fr.json`).
`language` is the BCP 47 language tag with region (e.g. `fr-FR` for French). See [www.lingoes.net](http://www.lingoes.net/en/translator/langcode.htm) for a list of language codes.
`name` is the display name of the language (e.g. `Français` for French).
## Update existing Translation
If you need to update an existing translation, simply edit the corresponding `<locale_code>.json` file in `src/i18n/locales`.
## Contribute changes
See [Pull Requests](./issues-and-pull-requests.md#pull-requests) on how to contribute your translation.
+171 -3
View File
@@ -2,8 +2,176 @@
title: AdGuard Home
---
It seems like the Docs on how to setup AdGuard Home are not available yet.
This tutorial is a follow-up to the official [Traefik tutorial](./traefik.md). It will guide you through integrating AdGuard Home with your existing `wg-easy` and Traefik setup to provide network-wide DNS ad-blocking.
Feel free to create a PR and add them here.
## Prerequisites
<!-- TODO -->
- A working [wg-easy](./basic-installation.md) and [Traefik](./traefik.md) setup from the previous guides.
/// warning | Important: Following this guide will reset your WireGuard configuration.
The process involves re-creating the `wg-easy` container and its data, which means **all existing WireGuard clients and settings will be deleted.**
You will need to create your clients again after completing this guide.
///
## Add `adguard` configuration
1. Create a directory for the configuration files:
```shell
sudo mkdir -p /etc/docker/containers/adguard
```
2. Create volumes for persistent data:
```shell
sudo mkdir -p /etc/docker/volumes/adguard/adguard_work
sudo mkdir -p /etc/docker/volumes/adguard/adguard_conf
sudo chmod -R 700 /etc/docker/volumes/adguard
```
3. Create the `docker-compose.yml` file.
File: `/etc/docker/containers/adguard/docker-compose.yml`
```yaml
services:
adguard:
image: adguard/adguardhome:v0.107.64
container_name: adguard
restart: unless-stopped
volumes:
- /etc/docker/volumes/adguard/adguard_work:/opt/adguardhome/work
- /etc/docker/volumes/adguard/adguard_conf:/opt/adguardhome/conf
networks:
wg:
interface_name: eth0
ipv4_address: 10.42.42.43
ipv6_address: fdcc:ad94:bacf:61a3::2b
traefik:
interface_name: eth1
labels:
- 'traefik.enable=true'
- 'traefik.http.routers.adguard.rule=Host(`adguard.$example.com$`)'
- 'traefik.http.routers.adguard.entrypoints=websecure'
- 'traefik.http.routers.adguard.service=adguard'
- 'traefik.http.services.adguard.loadbalancer.server.port=3000'
- 'traefik.docker.network=traefik'
networks:
wg:
external: true
traefik:
external: true
```
## Update `wg-easy` configuration
Modify the corresponding sections of your existing `wg-easy` compose file to match the updated version below.
File: `/etc/docker/containers/wg-easy/docker-compose.yml`
```yaml
services:
wg-easy:
ports:
- "51820:51820/udp"
...
networks:
wg:
interface_name: eth0
...
traefik:
interface_name: eth1
...
...
environment:
# Unattended Setup
- INIT_ENABLED=true
# Replace $username$ with your username
- INIT_USERNAME=$username$
# Replace $password$ with your unhashed password
- INIT_PASSWORD=$password$
# Replace $example.com$ with your domain
- INIT_HOST=wg-easy.$example.com$
- INIT_PORT=51820
- INIT_DNS=10.42.42.43,fdcc:ad94:bacf:61a3::2b
- INIT_IPV4_CIDR=10.8.0.0/24
- INIT_IPV6_CIDR=fd42:42:42::/64
...
networks:
wg:
# Prevents Docker Compose from prefixing the network name.
name: wg
...
...
```
## Setup Wireguard
1. Restart `wg-easy`:
```shell
cd /etc/docker/containers/wg-easy
sudo docker compose down -v
sudo docker compose up -d
```
2. Edit Wireguard's Hooks.
In the Admin Panel of your WireGuard server, go to the Hooks tab and replace it with:
**_PostUp_**
```shell
iptables -A INPUT -p udp -m udp --dport {{port}} -j ACCEPT; ip6tables -A INPUT -p udp -m udp --dport {{port}} -j ACCEPT; iptables -t nat -A PREROUTING -i wg0 -p udp --dport 53 -j DNAT --to-destination 10.42.42.43; iptables -t nat -A PREROUTING -i wg0 -p tcp --dport 53 -j DNAT --to-destination 10.42.42.43; ip6tables -t nat -A PREROUTING -i wg0 -p udp --dport 53 -j DNAT --to-destination fdcc:ad94:bacf:61a3::2b; ip6tables -t nat -A PREROUTING -i wg0 -p tcp --dport 53 -j DNAT --to-destination fdcc:ad94:bacf:61a3::2b; iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -A FORWARD -o wg0 -j ACCEPT; iptables -t nat -A POSTROUTING -s {{ipv4Cidr}} -o {{device}} -j MASQUERADE; ip6tables -t nat -A POSTROUTING -s {{ipv6Cidr}} -o {{device}} -j MASQUERADE;
```
**_PostDown_**
```shell
iptables -D INPUT -p udp -m udp --dport {{port}} -j ACCEPT || true; ip6tables -D INPUT -p udp -m udp --dport {{port}} -j ACCEPT || true; iptables -t nat -D PREROUTING -i wg0 -p udp --dport 53 -j DNAT --to-destination 10.42.42.43 || true; iptables -t nat -D PREROUTING -i wg0 -p tcp --dport 53 -j DNAT --to-destination 10.42.42.43 || true; ip6tables -t nat -D PREROUTING -i wg0 -p udp --dport 53 -j DNAT --to-destination fdcc:ad94:bacf:61a3::2b || true; ip6tables -t nat -D PREROUTING -i wg0 -p tcp --dport 53 -j DNAT --to-destination fdcc:ad94:bacf:61a3::2b || true; iptables -D FORWARD -i wg0 -j ACCEPT || true; iptables -D FORWARD -o wg0 -j ACCEPT || true; ip6tables -D FORWARD -i wg0 -j ACCEPT || true; ip6tables -D FORWARD -o wg0 -j ACCEPT || true; iptables -t nat -D POSTROUTING -s {{ipv4Cidr}} -o {{device}} -j MASQUERADE || true; ip6tables -t nat -D POSTROUTING -s {{ipv6Cidr}} -o {{device}} -j MASQUERADE || true;
```
3. Restart `wg-easy` to apply changes:
```shell
sudo docker restart wg-easy
```
## Setup Adguard Home
1. Start `adguard` service:
```shell
cd /etc/docker/containers/adguard
sudo docker compose up -d
```
2. Navigate to `https://adguard.$example.com$` to begin the AdGuard Home setup.
/// warning | Important: Configure AdGuard Home Admin Web Interface Port
During the initial AdGuard Home setup on the `Step 2/5` page, you **must** set the **Admin Web Interface Port** to **3000**. Do not use the default port 80, as it will not work with the Traefik configuration.
After completing the setup, the AdGuard UI might appear unresponsive. This is expected. **Simply reload the page**, and the panel will display correctly.
///
> If you accidentally left it default (80), you will need to manually edit the `docker-compose.yml` file for AdGuard Home (`/etc/docker/containers/adguard/docker-compose.yml`) and change the line `traefik.http.services.adguard.loadbalancer.server.port=3000` to `traefik.http.services.adguard.loadbalancer.server.port=80`. After making this change, restart AdGuard Home by navigating to `/etc/docker/containers/adguard` and running `sudo docker compose up -d`.
## Final System Checks
### Firewall
Ensure the ports `80/tcp`, `443/tcp`, `443/udp`, and `51820/udp` are open.
### Optional: Optimizing UDP Buffer Sizes
AdGuard Home, as a DNS server, handles a large volume of UDP packets. To ensure optimal performance, it is recommended to increase the system's UDP buffer sizes. You can apply these settings using your system's `sysctl` configuration (e.g., by creating a file in `/etc/sysctl.d/`).
```shell
net.core.rmem_max = 7500000
net.core.wmem_max = 7500000
```
After adding these settings, remember to apply them (e.g., by running `sudo sysctl --system` or rebooting)
@@ -20,7 +20,7 @@ File: `/etc/docker/containers/watchtower/docker-compose.yml`
```yaml
services:
watchtower:
image: containrrr/watchtower:latest
image: nickfedor/watchtower:latest
volumes:
- /var/run/docker.sock:/var/run/docker.sock
env_file:
@@ -8,7 +8,7 @@ title: Basic Installation
1. You need to have a host that you can manage
2. You need to have a domain name or a public IP address
3. You need a supported architecture (x86_64, arm64, armv7)
3. You need a supported architecture (x86_64, arm64)
4. You need curl installed on your host
## Install Docker
@@ -33,7 +33,7 @@ Follow the Docs here: <https://docs.docker.com/engine/install/> and install Dock
```shell
cd /etc/docker/containers/wg-easy
sudo docker-compose up -d
sudo docker compose up -d
```
## Setup Firewall
@@ -56,8 +56,8 @@ To update `wg-easy` to the latest version, run:
```shell
cd /etc/docker/containers/wg-easy
sudo docker-compose pull
sudo docker-compose up -d
sudo docker compose pull
sudo docker compose up -d
```
## Auto Update
+96 -3
View File
@@ -2,8 +2,101 @@
title: Caddy
---
It seems like the Docs on how to setup Caddy are not available yet.
/// note | Opinionated
Feel free to create a PR and add them here.
This guide is opinionated. If you use other conventions or folder layouts, feel free to change the commands and paths.
///
<!-- TODO -->
We're using [Caddy](https://caddyserver.com/) here as reverse proxy to serve `wg-easy` on [https://wg-easy.example.com](https://wg-easy.example.com) via TLS.
## Create a docker composition for `caddy`
```txt
.
├── compose.yml
└── Caddyfile
1 directory, 2 files
```
```yaml
# compose.yml
services:
caddy:
container_name: caddy
image: caddy:2.10.0-alpine
# publish everything you deem necessary
ports:
- '80:80/tcp'
- '443:443/tcp'
- '443:443/udp'
networks:
- caddy
restart: unless-stopped
volumes:
- './Caddyfile:/etc/caddy/Caddyfile:ro'
- config:/config
- data:/data
networks:
caddy:
name: caddy
volumes:
config:
data:
```
```txt
# Caddyfile
{
# setup your email address
email mail@example.com
}
wg-easy.example.com {
# since the container will share the network with wg-easy
# we can use the proper container name
reverse_proxy wg-easy:80
tls internal
}
```
...and start it with:
```shell
sudo docker compose up -d
```
## Adapt the docker composition of `wg-easy`
```yaml
services:
wg-easy:
# sync container name and port according to Caddyfile
container_name: wg-easy
environment:
- PORT=80
# no need to publish the HTTP server anymore
ports:
- "51820:51820/udp"
# add to caddy network
networks:
caddy:
...
networks:
caddy:
external: true
...
```
...and restart it with:
```shell
sudo docker compose up -d
```
You can now access `wg-easy` at [https://wg-easy.example.com](https://wg-easy.example.com) and start the setup.
@@ -7,9 +7,9 @@ To setup the IPv6 Network, simply run once:
```shell
docker network create \
-d bridge --ipv6 \
-d default \
--subnet 10.42.42.0/24 \
--subnet fdcc:ad94:bacf:61a3::/64 wg \
--subnet fdcc:ad94:bacf:61a3::/64 \
wg
```
<!-- ref: major version -->
+111
View File
@@ -0,0 +1,111 @@
---
title: Routed setup (No NAT)
---
This guide shows how to run **wg-easy** with a routed setup, so packets are forwarded instead of NATed.
In a routed design, each WireGuard client keeps its own IPv4/IPv6 address. That means you can identify clients by their real addresses instead of seeing everything as the WireGuard servers IP.
## Requirements
1. You know how to add static routes on your router to the WireGuard server.
## Docker setup
To make use of our own IPv4/IPv6 addresses, run the container with the `network_mode: host` option.
```yaml
services:
wg-easy:
image: ghcr.io/wg-easy/wg-easy:15
container_name: wg-easy
network_mode: 'host'
volumes:
- ./config:/etc/wireguard
- /lib/modules:/lib/modules:ro
cap_add:
- NET_ADMIN
- SYS_MODULE
devices:
- /dev/net/tun:/dev/net/tun
restart: unless-stopped
```
Because were on the host network, remove any `ports:` and container `sysctls:` you might have had before.
## Kernel parameters (on the host)
With host networking, system sysctls must be set on the **host**. On your host, create `/etc/sysctl.d/90-wireguard.conf`:
```txt
net.ipv4.ip_forward=1
net.ipv4.conf.all.src_valid_mark=1
net.ipv6.conf.all.disable_ipv6=0
net.ipv6.conf.all.forwarding=1
net.ipv6.conf.default.forwarding=1
```
Apply and verify:
```shell
sysctl -p /etc/sysctl.d/90-wireguard.conf
sysctl -n net.ipv4.ip_forward # should print 1
```
## Add static routes on your router
Pick an IPv4 and IPv6 subnet for your clients and add static routes on your router, pointing to the WireGuard server's LAN addresses.
### Example
/// note | 2001:db8::/32
The _documentation prefix_ `2001:db8::/32` (RFC 3849) used in this example is not meant for production use, replace it with your own ISP-assigned IPv6 prefix (GUA) or local prefix (ULA)
///
I want my WireGuard clients in `192.168.0.0/24` and `2001:db8:abc:0::/64`.
- Routed IPv4 subnet: `192.168.0.0/24`
- Routed IPv6 prefix: `2001:db8:abc:0::/64`
- WireGuard server IPs: `192.168.10.118` and `2001:db8:abc:10:216:3eff:fedb:949e`
On your router:
- Route `192.168.0.0/24` → next hop `192.168.10.118`
- Route `2001:db8:abc:0::/64` → next hop `2001:db8:abc:10:216:3eff:fedb:949e`
Don't forget to create the necessary firewall rules to allow these subnets to travel across your LAN. Some routers or servers may require specific Outbound NAT rules for the chosen IPv4 and IPv6 subnets to allow traffic to traverse your LAN.
## `wg-easy` configuration
In the Web UI → Admin → Interface, click Change CIDR and set the IPv4/IPv6 routed subnets you chose above. Save.
Then go to Admin → Hooks and add:
PostUp
```shell
iptables -A INPUT -p udp -m udp --dport {{port}} -j ACCEPT; iptables -A FORWARD -i wg0 -j ACCEPT; iptables -A FORWARD -o wg0 -j ACCEPT; ip6tables -A INPUT -p udp -m udp --dport {{port}} -j ACCEPT; ip6tables -A FORWARD -i wg0 -j ACCEPT; ip6tables -A FORWARD -o wg0 -j ACCEPT
```
PostDown
```shell
iptables -D INPUT -p udp -m udp --dport {{port}} -j ACCEPT; iptables -D FORWARD -i wg0 -j ACCEPT; iptables -D FORWARD -o wg0 -j ACCEPT; ip6tables -D INPUT -p udp -m udp --dport {{port}} -j ACCEPT; ip6tables -D FORWARD -i wg0 -j ACCEPT; ip6tables -D FORWARD -o wg0 -j ACCEPT
```
/// warning | Important: When using nftables use the following hooks instead.
PostUp
```shell
nft add chain ip filter WG_EASY; nft add rule ip filter DOCKER-USER jump WG_EASY; nft add rule ip filter WG_EASY iifname {{device}} accept; nft add rule ip filter WG_EASY oifname {{device}} accept; nft add chain ip6 filter WG_EASY; nft add rule ip6 filter DOCKER-USER jump WG_EASY; nft add rule ip6 filter WG_EASY iifname {{device}} accept; nft add rule ip6 filter WG_EASY oifname {{device}} accept;
```
PostDown
```shell
nft delete rule ip filter DOCKER-USER handle $(nft -a list chain ip filter DOCKER-USER | awk '/jump WG_EASY/ {print $NF}'); nft flush chain ip filter WG_EASY; nft delete chain ip filter WG_EASY; nft delete rule ip6 filter DOCKER-USER handle $(nft -a list chain ip6 filter DOCKER-USER | awk '/jump WG_EASY/ {print $NF}'); nft flush chain ip6 filter WG_EASY; nft delete chain ip6 filter WG_EASY
```
///
+4 -3
View File
@@ -141,10 +141,10 @@ sudo docker network create traefik
## Start traefik
```shell
sudo docker-compose up -d
sudo docker compose up -d
```
You can no access the Traefik dashboard at `https://traefik.$example.com$` with the credentials you set in `traefik_dynamic.yml`.
You can now access the Traefik dashboard at `https://traefik.$example.com$` with the credentials you set in `traefik_dynamic.yml`.
## Add Labels to `wg-easy`
@@ -166,6 +166,7 @@ services:
- "traefik.http.routers.wg-easy.entrypoints=websecure"
- "traefik.http.routers.wg-easy.service=wg-easy"
- "traefik.http.services.wg-easy.loadbalancer.server.port=51821"
- "traefik.docker.network=traefik"
...
networks:
@@ -178,7 +179,7 @@ networks:
```shell
cd /etc/docker/containers/wg-easy
sudo docker-compose up -d
sudo docker compose up -d
```
You can now access `wg-easy` at `https://wg-easy.$example.com$` and start the setup.
+6 -4
View File
@@ -12,7 +12,7 @@ Before you can get started with deploying your own VPN, there are some requireme
1. You need to have a host that you can manage
2. You need to have a domain name or a public IP address
3. You need a supported architecture (x86_64, arm64, armv7)
3. You need a supported architecture (x86_64, arm64)
### Host Setup
@@ -38,24 +38,26 @@ If you're using podman, make sure to read the related [documentation][docs-podma
To understand which tags you should use, read this section carefully. [Our CI][github-ci] will automatically build, test and push new images to the following container registry:
1. GitHub Container Registry ([`ghcr.io/wg-easy/wg-easy`][ghcr-image])
2. Codeberg Container Registry ([`codeberg.org/wg-easy/wg-easy`][codeberg-image]) (IPv6 support)
All workflows are using the tagging convention listed below. It is subsequently applied to all images.
| tag | Type | Example | Description |
| ------------- | ------------------------------- | ------------------------------------------------------------- | ----------------------------------------------------------------------------- |
| `15` | latest minor for that major tag | `ghcr.io/wg-easy/wg-easy:15` | latest features for specific major versions, no breaking changes, recommended |
| `latest` | latest tag | `ghcr.io/wg-easy/wg-easy:latest` or `ghcr.io/wg-easy/wg-easy` | points to latest release, can include breaking changes |
| `15.0` | latest patch for that minor tag | `ghcr.io/wg-easy/wg-easy:15.0` | latest patches for specific minor version |
| `15.0.0` | specific tag | `ghcr.io/wg-easy/wg-easy:15.0.0` | specific release, no updates |
| `edge` | push to `master` | `ghcr.io/wg-easy/wg-easy:edge` | mostly unstable, gets frequent package and code updates |
| `development` | pull requests | `ghcr.io/wg-easy/wg-easy:development` | used for development, testing code from PRs |
| `latest` | latest tag | `ghcr.io/wg-easy/wg-easy:latest` or `ghcr.io/wg-easy/wg-easy` | points to the v14 release, should be avoided |
<!-- ref: major version -->
<!-- ref: major version (check links too) -->
When publishing a tag we follow the [Semantic Versioning][semver] specification. The `latest` tag is always pointing to the latest stable release. If you want to avoid breaking changes, use the major version tag (e.g. `15`).
When publishing a tag we follow the [Semantic Versioning][semver] specification. Pin to the latest major version to avoid breaking changes (e.g. `15`), avoid using the `latest` tag.
[github-ci]: https://github.com/wg-easy/wg-easy/actions
[ghcr-image]: https://github.com/wg-easy/wg-easy/pkgs/container/wg-easy
[codeberg-image]: https://codeberg.org/wg-easy/-/packages/container/wg-easy/15
[semver]: https://semver.org/
### Follow tutorials
+1 -1
View File
@@ -8,7 +8,7 @@ hide:
/// info | This Documentation is Versioned
**Make sure** to select the correct version of this documentation! It should match the version of the image you are using. The default version corresponds to the `:latest` image tag - [the most recent stable release][docs-tagging].
**Make sure** to select the correct version of this documentation! It should match the version of the image you are using. The default version corresponds to [the most recent stable release][docs-tagging].
///
This documentation provides you not only with the basic setup and configuration of `wg-easy` but also with advanced configuration, elaborate usage scenarios, detailed examples, hints and more.
+3 -2
View File
@@ -7,10 +7,11 @@
"build": "docker build -t wg-easy .",
"docs:preview": "docker run --rm -it -p 8080:8080 -v ./docs:/docs squidfunk/mkdocs-material serve -a 0.0.0.0:8080",
"scripts:version": "bash scripts/version.sh",
"scripts:i18n": "bash scripts/i18n.sh",
"format:check:docs": "prettier --check docs"
},
"devDependencies": {
"prettier": "^3.5.3"
"prettier": "^3.8.1"
},
"packageManager": "pnpm@10.11.0"
"packageManager": "pnpm@10.29.2"
}
+5 -5
View File
@@ -9,16 +9,16 @@ importers:
.:
devDependencies:
prettier:
specifier: ^3.5.3
version: 3.5.3
specifier: ^3.8.1
version: 3.8.1
packages:
prettier@3.5.3:
resolution: {integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==}
prettier@3.8.1:
resolution: {integrity: sha512-UOnG6LftzbdaHZcKoPFtOcCKztrQ57WkHDeRD9t/PTQtmT0NHSeWWepj6pS0z/N7+08BHFDQVUrfmfMRcZwbMg==}
engines: {node: '>=14'}
hasBin: true
snapshots:
prettier@3.5.3: {}
prettier@3.8.1: {}
+19
View File
@@ -0,0 +1,19 @@
#!/bin/bash
folder="src/i18n/locales"
base_file="$folder/en.json"
# Get all leaf keys from the English base file
base_keys=$(jq -r 'paths(scalars) | map(tostring) | join(".")' "$base_file")
total=$(echo "$base_keys" | wc -l)
# Loop through all JSON files in the folder
for file in "$folder"/*.json; do
name=$(basename "$file" .json)
translated_keys=$(jq -r 'paths(scalars) | map(tostring) | join(".")' "$file")
done=$(comm -12 <(echo "$base_keys" | sort) <(echo "$translated_keys" | sort) | wc -l)
percent=$((100 * done / total))
check="[ ]"
[ "$percent" -eq 100 ] && check="[x]"
printf "%s %s (%d%%)\n" "- $check" "$name" "$percent"
done
+1
View File
@@ -30,6 +30,7 @@ echo "Updated package.json to version $new_version"
echo "----"
echo "If you changed the major version, remember to update the docker-compose.yml file and docs (search for: ref: major version)"
echo "Make sure to stage any changes before proceeding (e.g. Changelog updates)."
echo "----"
echo "If you did everything press 'y' to commit the changes and create a new tag"
+2
View File
@@ -23,4 +23,6 @@ logs
.env.*
!.env.example
coverage/
wg-easy.db
+1
View File
@@ -0,0 +1 @@
setups.@nuxt/test-utils="3.23.0"
+3 -3
View File
@@ -11,10 +11,10 @@
</template>
<script setup lang="ts">
import type { VueApexChartsComponent } from 'vue3-apexcharts';
import type { VueApexChartsComponentProps } from 'vue3-apexcharts';
defineProps<{
options: VueApexChartsComponent['options'];
series: VueApexChartsComponent['series'];
options: VueApexChartsComponentProps['options'];
series: VueApexChartsComponentProps['series'];
}>();
</script>
+29
View File
@@ -0,0 +1,29 @@
<template>
<div class="overflow-x-auto rounded border-2 border-red-800 py-2">
<pre
class="mx-2 inline-block"
@click="selectCode"
><code ref="codeBlock">{{ code }}</code></pre>
</div>
</template>
<script setup lang="ts">
defineProps<{
code: string;
}>();
const codeBlock = useTemplateRef('codeBlock');
function selectCode() {
// TODO: keyboard support?
if (codeBlock.value) {
const range = document.createRange();
range.selectNodeContents(codeBlock.value);
const sel = window.getSelection();
if (sel) {
sel.removeAllRanges();
sel.addRange(range);
}
}
}
</script>
+1 -1
View File
@@ -1,7 +1,7 @@
<template>
<ClientCardCharts :client="client" />
<div
class="relative z-10 flex flex-col justify-between gap-3 px-3 py-3 sm:flex-row md:py-5"
class="relative flex flex-col justify-between gap-3 px-3 py-3 sm:flex-row md:py-5"
>
<div class="flex w-full items-center gap-3 md:gap-4">
<ClientCardAvatar :client="client" />
@@ -0,0 +1,74 @@
<template>
<BaseDialog :trigger-class="triggerClass">
<template #trigger>
<slot />
</template>
<template #title>
{{ $t('client.config') }}
</template>
<template #description>
<div v-if="status === 'success'">
<BaseCodeBlock :code="config ?? ''" />
</div>
<div v-else>
<span>{{ $t('general.loading') }}</span>
</div>
</template>
<template #actions>
<DialogClose as-child>
<BaseSecondaryButton>{{ $t('dialog.cancel') }}</BaseSecondaryButton>
</DialogClose>
<DialogClose as-child>
<BasePrimaryButton @click="copyCode">
{{ $t('copy.copy') }}
</BasePrimaryButton>
</DialogClose>
</template>
</BaseDialog>
</template>
<script setup lang="ts">
const props = defineProps<{ triggerClass?: string; clientId: number }>();
const toast = useToast();
const { copied, copy, isSupported } = useClipboard({
// fallback does not work
legacy: false,
});
const { data: config, status } = useFetch(
`/api/client/${props.clientId}/configuration`,
{
responseType: 'text',
server: false,
}
);
async function copyCode() {
if (status.value !== 'success') {
return;
}
if (!isSupported.value) {
toast.showToast({
type: 'error',
message: $t('copy.notSupported'),
});
return;
}
await copy(config.value ?? '');
if (copied.value) {
toast.showToast({
type: 'success',
message: $t('copy.copied'),
});
} else {
toast.showToast({
type: 'error',
message: $t('copy.failed'),
});
}
}
</script>
+1 -1
View File
@@ -9,7 +9,7 @@
</div>
</template>
<template #actions>
<DialogClose>
<DialogClose as-child>
<BaseSecondaryButton>{{ $t('dialog.cancel') }}</BaseSecondaryButton>
</DialogClose>
</template>
+38
View File
@@ -0,0 +1,38 @@
<template>
<div class="relative w-60 md:mr-2">
<div class="relative flex h-full items-center">
<IconsMagnifyingGlass
class="absolute left-2.5 h-4 w-4 text-gray-400 dark:text-neutral-500"
/>
<input
v-model="searchQuery"
type="text"
:placeholder="$t('client.search')"
class="w-full rounded bg-white px-8 py-2 text-sm text-gray-900 shadow-sm ring-1 ring-gray-300 transition-all placeholder:text-gray-400 focus:border-transparent focus:outline-none focus:ring-2 focus:ring-red-600 dark:bg-neutral-800 dark:text-white dark:ring-neutral-700 dark:placeholder:text-neutral-500 dark:focus:ring-red-700"
@input="updateSearch"
/>
<button
v-if="searchQuery"
class="absolute right-2 flex h-5 w-5 items-center justify-center rounded-full bg-gray-200 text-gray-600 hover:bg-gray-300 hover:text-gray-800 dark:bg-neutral-700 dark:text-neutral-300 dark:hover:bg-neutral-600 dark:hover:text-neutral-100"
aria-label="Clear search"
@click="clearSearch"
>
<IconsClose class="h-3 w-3" />
</button>
</div>
</div>
</template>
<script setup lang="ts">
const clientsStore = useClientsStore();
const searchQuery = ref('');
const updateSearch = useDebounceFn(() => {
clientsStore.setSearchQuery(searchQuery.value);
}, 300);
function clearSearch() {
searchQuery.value = '';
clientsStore.setSearchQuery('');
}
</script>
+3 -1
View File
@@ -21,7 +21,9 @@
<BasePrimaryButton as="span">
<div class="flex items-center gap-3">
<IconsSparkles class="w-4" />
<span>{{ $t('admin.config.suggest') }}</span>
<span class="whitespace-nowrap">
{{ $t('admin.config.suggest') }}
</span>
</div>
</BasePrimaryButton>
</AdminSuggestDialog>
+20
View File
@@ -0,0 +1,20 @@
<template>
<div class="flex items-center">
<FormLabel :for="id">
{{ label }}
</FormLabel>
<BaseTooltip v-if="description" :text="description">
<IconsInfo class="size-4" />
</BaseTooltip>
</div>
<span :id="id" class="flex flex-col justify-center">{{ data }}</span>
</template>
<script lang="ts" setup>
defineProps<{
id: string;
label: string;
description?: string;
data?: string;
}>();
</script>
@@ -0,0 +1,28 @@
<template>
<div class="flex items-center">
<FormLabel :for="id">
{{ label }}
</FormLabel>
<BaseTooltip v-if="description" :text="description">
<IconsInfo class="size-4" />
</BaseTooltip>
</div>
<BaseInput :id="id" v-model.number="data" :name="id" type="number" />
</template>
<script lang="ts" setup>
defineProps<{ id: string; label: string; description?: string }>();
const data = defineModel<number | null>({
set(value) {
const temp = value ?? null;
if (temp === 0) {
return null;
}
if ((temp as string | null) === '') {
return null;
}
return temp;
},
});
</script>
@@ -0,0 +1,7 @@
<template>
<MagnifyingGlassIcon />
</template>
<script lang="ts" setup>
import MagnifyingGlassIcon from '@heroicons/vue/24/outline/esm/MagnifyingGlassIcon';
</script>
+1 -1
View File
@@ -1,5 +1,5 @@
<template>
<div class="flex flex-shrink-0 space-x-1 md:block">
<div class="flex flex-shrink-0 items-center space-x-2">
<slot />
</div>
</template>
+1 -1
View File
@@ -7,7 +7,7 @@
href="https://github.com/wg-easy/wg-easy"
>WireGuard Easy</a
>
({{ globalStore.information?.currentRelease }}) © 2021-2025 by
({{ globalStore.information?.currentRelease }}) © 2021-2026 by
<a
class="hover:underline"
target="_blank"
+6 -4
View File
@@ -4,25 +4,27 @@ export default defineNuxtRouteMiddleware(async (to) => {
return;
}
const event = useRequestEvent();
const authStore = useAuthStore();
const userData = await authStore.getSession();
authStore.userData = await authStore.getSession(event);
// skip login if already logged in
if (to.path === '/login') {
if (userData?.username) {
if (authStore.userData?.username) {
return navigateTo('/', { redirectCode: 302 });
}
return;
}
// Require auth for every page other than Login
if (!userData?.username) {
if (!authStore.userData?.username) {
return navigateTo('/login', { redirectCode: 302 });
}
// Check for admin access
if (to.path.startsWith('/admin')) {
if (!hasPermissions(userData, 'admin', 'any')) {
if (!hasPermissions(authStore.userData, 'admin', 'any')) {
return abortNavigation('Not allowed to access Admin Panel');
}
}
+7 -8
View File
@@ -13,11 +13,12 @@
v-for="(item, index) in menuItems"
:key="index"
:to="`/admin/${item.id}`"
active-class="bg-red-800 rounded"
class="group rounded"
active-class="bg-red-800 active"
>
<BaseSecondaryButton
as="span"
class="w-full cursor-pointer rounded p-2 font-medium transition-colors duration-200 hover:bg-red-800 dark:text-neutral-200"
class="w-full font-medium group-[.active]:text-white"
>
{{ item.name }}
</BaseSecondaryButton>
@@ -37,25 +38,23 @@
</template>
<script setup lang="ts">
const authStore = useAuthStore();
authStore.update();
const { t } = useI18n();
const route = useRoute();
const menuItems = [
const menuItems = computed(() => [
{ id: 'general', name: t('pages.admin.general') },
{ id: 'config', name: t('pages.admin.config') },
{ id: 'interface', name: t('pages.admin.interface') },
{ id: 'hooks', name: t('pages.admin.hooks') },
];
]);
const defaultItem = { id: '', name: t('pages.admin.panel') };
const activeMenuItem = computed(() => {
return (
menuItems.find((item) => route.path === `/admin/${item.id}`) ?? defaultItem
menuItems.value.find((item) => route.path === `/admin/${item.id}`) ??
defaultItem
);
});
</script>
+57
View File
@@ -47,6 +47,61 @@
:description="$t('admin.config.persistentKeepaliveDesc')"
/>
</FormGroup>
<FormGroup v-if="globalStore.information?.isAwg">
<FormHeading>{{ $t('awg.obfuscationParameters') }}</FormHeading>
<FormNullNumberField
id="jC"
v-model="data.defaultJC"
:label="$t('awg.jCLabel')"
:description="$t('awg.jCDescription')"
/>
<FormNullNumberField
id="jMin"
v-model="data.defaultJMin"
:label="$t('awg.jMinLabel')"
:description="$t('awg.jMinDescription')"
/>
<FormNullNumberField
id="jMax"
v-model="data.defaultJMax"
:label="$t('awg.jMaxLabel')"
:description="$t('awg.jMaxDescription')"
/>
<div class="col-span-full text-sm">* {{ $t('awg.mtuNote') }}</div>
<FormNullTextField
id="i1"
v-model="data.defaultI1"
:label="$t('awg.i1Label')"
:description="$t('awg.i1Description')"
/>
<FormNullTextField
id="i2"
v-model="data.defaultI2"
:label="$t('awg.i2Label')"
:description="$t('awg.i2Description')"
/>
<FormNullTextField
id="i3"
v-model="data.defaultI3"
:label="$t('awg.i3Label')"
:description="$t('awg.i3Description')"
/>
<FormNullTextField
id="i4"
v-model="data.defaultI4"
:label="$t('awg.i4Label')"
:description="$t('awg.i4Description')"
/>
<FormNullTextField
id="i5"
v-model="data.defaultI5"
:label="$t('awg.i5Label')"
:description="$t('awg.i5Description')"
/>
</FormGroup>
<FormGroup>
<FormHeading>{{ $t('form.actions') }}</FormHeading>
<FormPrimaryActionField type="submit" :label="$t('form.save')" />
@@ -57,6 +112,8 @@
</template>
<script lang="ts" setup>
const globalStore = useGlobalStore();
const { data: _data, refresh } = await useFetch(`/api/admin/userconfig`, {
method: 'get',
});
+105
View File
@@ -21,6 +21,109 @@
:description="$t('admin.interface.deviceDesc')"
/>
</FormGroup>
<FormGroup v-if="globalStore.information?.isAwg">
<FormHeading>{{ $t('awg.obfuscationParameters') }}</FormHeading>
<FormNullNumberField
id="jC"
v-model="data.jC"
:label="$t('awg.jCLabel')"
:description="$t('awg.jCDescription')"
/>
<FormNullNumberField
id="jMin"
v-model="data.jMin"
:label="$t('awg.jMinLabel')"
:description="$t('awg.jMinDescription')"
/>
<FormNullNumberField
id="jMax"
v-model="data.jMax"
:label="$t('awg.jMaxLabel')"
:description="$t('awg.jMaxDescription')"
/>
<FormNullNumberField
id="s1"
v-model="data.s1"
:label="$t('awg.s1Label')"
:description="$t('awg.s1Description')"
/>
<FormNullNumberField
id="s2"
v-model="data.s2"
:label="$t('awg.s2Label')"
:description="$t('awg.s2Description')"
/>
<div class="col-span-full text-sm">* {{ $t('awg.mtuNote') }}</div>
<FormNullNumberField
id="s3"
v-model="data.s3"
:label="$t('awg.s3Label')"
:description="$t('awg.s3Description')"
/>
<FormNullNumberField
id="s4"
v-model="data.s4"
:label="$t('awg.s4Label')"
:description="$t('awg.s4Description')"
/>
<FormNullTextField
id="i1"
v-model="data.i1"
:label="$t('awg.i1Label')"
:description="$t('awg.i1Description')"
/>
<FormNullTextField
id="i2"
v-model="data.i2"
:label="$t('awg.i2Label')"
:description="$t('awg.i2Description')"
/>
<FormNullTextField
id="i3"
v-model="data.i3"
:label="$t('awg.i3Label')"
:description="$t('awg.i3Description')"
/>
<FormNullTextField
id="i4"
v-model="data.i4"
:label="$t('awg.i4Label')"
:description="$t('awg.i4Description')"
/>
<FormNullTextField
id="i5"
v-model="data.i5"
:label="$t('awg.i5Label')"
:description="$t('awg.i5Description')"
/>
<FormNullNumberField
id="h1"
v-model="data.h1"
:label="$t('awg.h1Label')"
:description="$t('awg.h1Description')"
/>
<FormNullNumberField
id="h2"
v-model="data.h2"
:label="$t('awg.h2Label')"
:description="$t('awg.h2Description')"
/>
<FormNullNumberField
id="h3"
v-model="data.h3"
:label="$t('awg.h3Label')"
:description="$t('awg.h3Description')"
/>
<FormNullNumberField
id="h4"
v-model="data.h4"
:label="$t('awg.h4Label')"
:description="$t('awg.h4Description')"
/>
</FormGroup>
<FormGroup>
<FormHeading>{{ $t('form.actions') }}</FormHeading>
<FormPrimaryActionField type="submit" :label="$t('form.save')" />
@@ -53,6 +156,8 @@
</template>
<script setup lang="ts">
const globalStore = useGlobalStore();
const { t } = useI18n();
const { data: _data, refresh } = await useFetch(`/api/admin/interface`, {
+75 -3
View File
@@ -39,6 +39,12 @@
v-model="data.ipv6Address"
label="IPv6"
/>
<FormInfoField
id="endpoint"
:data="data.endpoint ?? $t('client.notConnected')"
:label="$t('client.endpoint')"
:description="$t('client.endpointDesc')"
/>
</FormGroup>
<FormGroup>
<FormHeading :description="$t('client.allowedIpsDesc')">
@@ -76,6 +82,61 @@
:label="$t('general.persistentKeepalive')"
/>
</FormGroup>
<FormGroup v-if="globalStore.information?.isAwg">
<FormHeading>{{ $t('awg.obfuscationParameters') }}</FormHeading>
<FormNullNumberField
id="jC"
v-model="data.jC"
:label="$t('awg.jCLabel')"
:description="$t('awg.jCDescription')"
/>
<FormNullNumberField
id="Jmin"
v-model="data.jMin"
:label="$t('awg.jMinLabel')"
:description="$t('awg.jMinDescription')"
/>
<FormNullNumberField
id="Jmax"
v-model="data.jMax"
:label="$t('awg.jMaxLabel')"
:description="$t('awg.jMaxDescription')"
/>
<div class="col-span-full text-sm">* {{ $t('awg.mtuNote') }}</div>
<FormNullTextField
id="i1"
v-model="data.i1"
:label="$t('awg.i1Label')"
:description="$t('awg.i1Description')"
/>
<FormNullTextField
id="i2"
v-model="data.i2"
:label="$t('awg.i2Label')"
:description="$t('awg.i2Description')"
/>
<FormNullTextField
id="i3"
v-model="data.i3"
:label="$t('awg.i3Label')"
:description="$t('awg.i3Description')"
/>
<FormNullTextField
id="i4"
v-model="data.i4"
:label="$t('awg.i4Label')"
:description="$t('awg.i4Description')"
/>
<FormNullTextField
id="i5"
v-model="data.i5"
:label="$t('awg.i5Label')"
:description="$t('awg.i5Description')"
/>
</FormGroup>
<FormGroup>
<FormHeading :description="$t('client.hooksDescription')">
{{ $t('client.hooks') }}
@@ -118,13 +179,25 @@
@delete="deleteClient"
>
<FormSecondaryActionField
label="Delete"
:label="$t('client.delete')"
class="w-full"
type="button"
tabindex="-1"
as="span"
/>
</ClientsDeleteDialog>
<ClientsConfigDialog
trigger-class="col-span-2"
:client-id="data.id"
>
<FormSecondaryActionField
:label="$t('client.viewConfig')"
class="w-full"
type="button"
tabindex="-1"
as="span"
/>
</ClientsConfigDialog>
</FormGroup>
</FormElement>
</PanelBody>
@@ -133,8 +206,7 @@
</template>
<script lang="ts" setup>
const authStore = useAuthStore();
authStore.update();
const globalStore = useGlobalStore();
const route = useRoute();
const id = route.params.id as string;
+1 -3
View File
@@ -4,6 +4,7 @@
<PanelHead>
<PanelHeadTitle :text="$t('pages.clients')" />
<PanelHeadBoat>
<ClientsSearch />
<ClientsSort />
<ClientsNew />
</PanelHeadBoat>
@@ -28,9 +29,6 @@
</template>
<script setup lang="ts">
const authStore = useAuthStore();
authStore.update();
const globalStore = useGlobalStore();
const clientsStore = useClientsStore();
-3
View File
@@ -67,9 +67,6 @@
</template>
<script setup lang="ts">
const authStore = useAuthStore();
authStore.update();
const toast = useToast();
const { t } = useI18n();
-1
View File
@@ -120,7 +120,6 @@
import { encodeQR } from 'qr';
const authStore = useAuthStore();
authStore.update();
const name = ref(authStore.userData?.name);
const email = ref(authStore.userData?.email);
+3 -1
View File
@@ -1,5 +1,7 @@
import VueApexCharts from 'vue3-apexcharts';
export default defineNuxtPlugin((nuxtApp) => {
nuxtApp.vueApp.use(VueApexCharts);
// https://github.com/apexcharts/vue3-apexcharts/issues/141
// eslint-disable-next-line @typescript-eslint/no-explicit-any
nuxtApp.vueApp.use(VueApexCharts as any);
});
+14 -7
View File
@@ -1,18 +1,25 @@
export const useAuthStore = defineStore('Auth', () => {
const { data: userData, refresh: update } = useFetch('/api/session', {
method: 'get',
});
import type { H3Event } from 'h3';
import type { SharedPublicUser } from '~~/shared/utils/permissions';
async function getSession() {
export const useAuthStore = defineStore('Auth', () => {
const userData = useState<SharedPublicUser | null>('user-data', () => null);
async function getSession(event?: H3Event) {
const fetch = event?.$fetch || $fetch;
try {
const { data } = await useFetch('/api/session', {
const data = await fetch('/api/session', {
method: 'get',
});
return data.value;
return data;
} catch {
return null;
}
}
async function update() {
const data = await getSession();
userData.value = data;
}
return { userData, update, getSession };
});
+18 -5
View File
@@ -31,8 +31,13 @@ export const useClientsStore = defineStore('Clients', () => {
const clients = ref<null | LocalClient[]>(null);
const clientsPersist = ref<Record<string, ClientPersist>>({});
const searchParams = ref({
filter: undefined as string | undefined,
});
const { data: _clients, refresh: _refresh } = useFetch('/api/client', {
method: 'get',
params: searchParams,
});
// TODO: rewrite
@@ -61,10 +66,11 @@ export const useClientsStore = defineStore('Clients', () => {
const clientPersist = clientsPersist.value[client.id]!;
// Debug
// client.transferRx = this.clientsPersist[client.id].transferRxPrevious + Math.random() * 1000;
// client.transferTx = this.clientsPersist[client.id].transferTxPrevious + Math.random() * 1000;
// client.latestHandshakeAt = new Date();
// this.requiresPassword = true;
/* client.transferRx =
clientPersist.transferRxPrevious + Math.random() * 1000;
client.transferTx =
clientPersist.transferTxPrevious + Math.random() * 1000;
client.latestHandshakeAt = new Date().toISOString(); */
clientPersist.transferRxCurrent =
(client.transferRx ?? 0) - clientPersist.transferRxPrevious;
@@ -120,6 +126,7 @@ export const useClientsStore = defineStore('Clients', () => {
};
});
// TODO: move sort to backend
if (transformedClients !== undefined) {
transformedClients = sortByProperty(
transformedClients,
@@ -130,5 +137,11 @@ export const useClientsStore = defineStore('Clients', () => {
clients.value = transformedClients ?? null;
}
return { clients, clientsPersist, refresh, _clients };
function setSearchQuery(filter: string) {
clients.value = null;
searchParams.value.filter = filter || undefined;
}
return { clients, clientsPersist, refresh, _clients, setSearchQuery };
});
+3 -1
View File
@@ -18,7 +18,7 @@ const db = drizzle({ client, schema });
const dbAdminReset = defineCommand({
meta: {
name: 'db:admin:reset',
description: 'Reset the admin user',
description: 'Reset the admin user password and TOTP settings',
},
args: {
password: {
@@ -61,6 +61,8 @@ const dbAdminReset = defineCommand({
.update(schema.user)
.set({
password: hash,
totpVerified: false,
totpKey: null,
})
.where(eq(schema.user.id, 1));
+38
View File
@@ -1,9 +1,47 @@
import en from './locales/en.json';
import pl from './locales/pl.json';
import uk from './locales/uk.json';
import fr from './locales/fr.json';
import de from './locales/de.json';
import it from './locales/it.json';
import ru from './locales/ru.json';
import zhhk from './locales/zh-HK.json';
import zhcn from './locales/zh-CN.json';
import zhtw from './locales/zh-TW.json';
import ko from './locales/ko.json';
import es from './locales/es.json';
import ptbr from './locales/pt-BR.json';
import tr from './locales/tr.json';
import bn from './locales/bn.json';
import id from './locales/id.json';
import nl from './locales/nl.json';
import nb from './locales/nb.json';
import bg from './locales/bg.json';
import gl from './locales/gl.json';
export default defineI18nConfig(() => ({
legacy: false,
fallbackLocale: 'en',
messages: {
en,
pl,
uk,
fr,
de,
it,
ru,
'zh-HK': zhhk,
'zh-CN': zhcn,
'zh-TW': zhtw,
ko,
es,
'pt-BR': ptbr,
tr,
bn,
id,
nl,
nb,
bg,
gl,
},
}));
+286
View File
@@ -0,0 +1,286 @@
{
"pages": {
"me": "Профил",
"clients": "Клиенти",
"admin": {
"panel": "Админ Панел",
"general": "Общи",
"config": "Конфигурация",
"interface": "Интерфейс",
"hooks": "Hooks"
}
},
"user": {
"email": "Имейл"
},
"me": {
"currentPassword": "Текуща парола",
"enable2fa": "Активирай двуфакторна автентикация",
"enable2faDesc": "Сканирай QR кода с твоето приложение за автентикатор или въведи ключа ръчно.",
"2faKey": "TOTP ключ",
"2faCodeDesc": "Въведи кода от твоето приложение за автентикатор.",
"disable2fa": "Деактивирай двуфакторна автентикация",
"disable2faDesc": "Въведи паролата си, за да деактивираш двуфакторната автентикация."
},
"general": {
"name": "Име",
"username": "Потребителско име",
"password": "Парола",
"newPassword": "Нова парола",
"updatePassword": "Обнови парола",
"mtu": "MTU",
"allowedIps": "Разрешени IP-та",
"dns": "DNS",
"persistentKeepalive": "Постоянно поддържане на връзката",
"logout": "Изход",
"continue": "Продължи",
"host": "Хост",
"port": "Порт",
"yes": "Да",
"no": "Не",
"confirmPassword": "Потвърди парола",
"loading": "Зареждане...",
"2fa": "Двуфакторна автентикация",
"2faCode": "TOTP код"
},
"setup": {
"welcome": "Добре дошъл в първоначалната настройка на wg-easy",
"welcomeDesc": "Откри най-лесния начин да инсталираш и управляваш WireGuard на всеки Linux сървър",
"existingSetup": "Имаш ли вече съществуваща инсталация?",
"createAdminDesc": "Моля, първо въведи администраторско потребителско име и силна сигурна парола. Тези данни ще се използват за вход в административния панел.",
"setupConfigDesc": "Моля, въведи хост и порт. Тази информация ще се използва при генериране на клиентски конфигурации за WireGuard.",
"setupMigrationDesc": "Ако желаеш да мигрираш данните от предишна версия на wg-easy, качи резервното копие.",
"upload": "Качи",
"migration": "Възстанови от резервно копие:",
"createAccount": "Създай акаунт",
"successful": "Настройката е успешна",
"hostDesc": "Публично име/адрес, към който клиентите ще се свързват",
"portDesc": "Публичен UDP порт, на който клиентите ще се свързват и на който WireGuard слуша"
},
"update": {
"updateAvailable": "Налична е актуализация!",
"update": "Актуализирай"
},
"theme": {
"dark": "Тъмна тема",
"light": "Светла тема",
"system": "Системна тема"
},
"layout": {
"toggleCharts": "Покажи/скрий графики",
"donate": "Дарение"
},
"login": {
"signIn": "Вход",
"rememberMe": "Запомни ме",
"rememberMeDesc": "Остани влязъл след затваряне на браузъра",
"insecure": "Не можеш да влезеш през несигурна връзка. Използвай HTTPS.",
"2faRequired": "Изисква се двуфакторна автентикация",
"2faWrong": "Грешен код за двуфакторна автентикация"
},
"client": {
"empty": "Все още няма клиенти.",
"newShort": "Нов",
"sort": "Сортирай",
"create": "Създай клиент",
"created": "Клиентът е създаден",
"new": "Нов клиент",
"name": "Име",
"expireDate": "Дата на изтичане",
"expireDateDesc": "Дата, след която клиентът ще бъде деактивиран. Празно = постоянен",
"delete": "Изтрий",
"deleteClient": "Изтрий клиент",
"deleteDialog1": "Сигурен ли си, че искаш да изтриеш",
"deleteDialog2": "Това действие е необратимо.",
"enabled": "Активен",
"address": "Адрес",
"serverAllowedIps": "Разрешени IP-та от сървъра",
"otlDesc": "Генерирай кратък еднократен линк",
"permanent": "Постоянно",
"createdOn": "Създаден на ",
"lastSeen": "Последно видян на ",
"totalDownload": "Общо изтеглени: ",
"totalUpload": "Общо качени: ",
"newClient": "Нов клиент",
"disableClient": "Деактивирай клиент",
"enableClient": "Активирай клиент",
"noPrivKey": "Този клиент няма известен частен ключ. Не може да се създаде конфигурация.",
"showQR": "Покажи QR код",
"downloadConfig": "Изтегли конфигурация",
"allowedIpsDesc": "Кои IP-та ще се насочват през VPN (замества глобалната настройка)",
"serverAllowedIpsDesc": "Кои IP-та сървърът ще насочва към клиента",
"mtuDesc": "Задава максималния размер на пакета (MTU) за VPN тунела",
"persistentKeepaliveDesc": "Интервал (в секунди) за изпращане на keep-alive пакети. 0 = изключено",
"hooks": "Hooks",
"hooksDescription": "Hooks работят само с wg-quick",
"hooksLeaveEmpty": "Само за wg-quick. В противен случай остави празно",
"dnsDesc": "DNS сървър, който клиентите ще използват (замества глобалната настройка)",
"notConnected": "Клиентът не е свързан",
"endpoint": "Крайна точка",
"endpointDesc": "IP адресът на клиента, от който е установена WireGuard връзката",
"search": "Търси клиенти...",
"config": "Конфигурация",
"viewConfig": "Прегледай конфигурацията"
},
"dialog": {
"change": "Промени",
"cancel": "Отказ",
"create": "Създай"
},
"toast": {
"success": "Успех",
"saved": "Запазено",
"error": "Грешка"
},
"form": {
"actions": "Действия",
"save": "Запази",
"revert": "Отмени промените",
"sectionGeneral": "Общи",
"sectionAdvanced": "Разширени",
"noItems": "Няма елементи",
"nullNoItems": "Няма елементи. Използва се глобалната конфигурация",
"add": "Добави"
},
"admin": {
"general": {
"sessionTimeout": "Време на сесията",
"sessionTimeoutDesc": "Продължителност на сесията при „Запомни ме“ (в секунди)",
"metrics": "Метрики",
"metricsPassword": "Парола",
"metricsPasswordDesc": "Bearer парола за достъп до metrics ендпойнт (парола или argon2 хеш)",
"json": "JSON",
"jsonDesc": "Път за метрики в JSON формат",
"prometheus": "Prometheus",
"prometheusDesc": "Път за Prometheus метрики"
},
"config": {
"connection": "Връзка",
"hostDesc": "Публично име/адрес за клиентите (инвалидира конфигурациите)",
"portDesc": "Публичен UDP порт за клиентите (инвалидира конфигурациите; вероятно искаш да смениш и порта на интерфейса)",
"allowedIpsDesc": "Разрешени IP-та за клиентите (глобална настройка)",
"dnsDesc": "DNS сървър за клиентите (глобална настройка)",
"mtuDesc": "MTU, който ще ползват клиентите (само за нови клиенти)",
"persistentKeepaliveDesc": "Интервал в секунди за keep-alive към сървъра. 0 = изключено (само за нови клиенти)",
"suggest": "Предложи",
"suggestDesc": "Избери IP адрес или хост за полето Host"
},
"interface": {
"cidrSuccess": "CIDR променен",
"device": "Устройство",
"deviceDesc": "Мрежово устройство, през което да се препраща WireGuard трафикът",
"mtuDesc": "MTU, който ще ползва WireGuard",
"portDesc": "UDP порт, на който слуша WireGuard (вероятно искаш да смениш и порта в Config)",
"changeCidr": "Смени CIDR",
"restart": "Рестартирай интерфейс",
"restartDesc": "Рестартиране на WireGuard интерфейса",
"restartWarn": "Сигурен ли си, че искаш да рестартираш интерфейса? Всички клиенти ще бъдат изключени.",
"restartSuccess": "Интерфейсът е рестартиран"
},
"introText": "Добре дошъл в административния панел.\n\nТук можеш да управляваш общите настройки, конфигурацията, настройките на интерфейса и hooks.\n\nЗапочни, като избереш някоя от секциите в страничното меню."
},
"zod": {
"generic": {
"required": "{0} е задължително",
"validNumber": "{0} трябва да е валидно число",
"validString": "{0} трябва да е валиден текст",
"validBoolean": "{0} трябва да е валидна булева стойност",
"validArray": "{0} трябва да е валиден масив",
"stringMin": "{0} трябва да съдържа поне {1} символа",
"numberMin": "{0} трябва да е поне {1}"
},
"client": {
"id": "ID на клиента",
"name": "Име",
"expiresAt": "Изтича на",
"address4": "IPv4 адрес",
"address6": "IPv6 адрес",
"serverAllowedIps": "Разрешени IP-та от сървъра"
},
"user": {
"username": "Потребителско име",
"password": "Парола",
"remember": "Запомни",
"name": "Име",
"email": "Имейл",
"emailInvalid": "Имейлът трябва да е валиден",
"passwordMatch": "Паролите трябва да съвпадат",
"totpEnable": "Активиране на TOTP",
"totpEnableTrue": "TOTP Enable трябва да е true",
"totpCode": "TOTP код"
},
"userConfig": {
"host": "Хост"
},
"general": {
"sessionTimeout": "Време на сесията",
"metricsEnabled": "Метрики",
"metricsPassword": "Парола за метрики"
},
"interface": {
"cidr": "CIDR",
"device": "Устройство",
"cidrValid": "CIDR трябва да е валиден"
},
"otl": "Еднократен линк",
"stringMalformed": "Невалиден формат на низа",
"body": "Тялото трябва да е валиден обект",
"hook": "Hook",
"enabled": "Активиран",
"mtu": "MTU",
"port": "Порт",
"persistentKeepalive": "Постоянно поддържане на връзката",
"address": "IP адрес",
"dns": "DNS",
"allowedIps": "Разрешени IP-та",
"file": "Файл"
},
"hooks": {
"preUp": "PreUp",
"postUp": "PostUp",
"preDown": "PreDown",
"postDown": "PostDown"
},
"copy": {
"notSupported": "Копиране не се поддържа",
"copied": "Копирано!",
"failed": "Копирането неуспешно",
"copy": "Копирай"
},
"awg": {
"jCLabel": "Брой junk пакети (Jc)",
"jCDescription": "Брой junk пакети за изпращане (1–128, препоръчително: 4–12)",
"jMinLabel": "Минимален размер на junk пакети (Jmin)",
"jMinDescription": "Минимален размер на junk пакетите (0–1279*, препоръчително: 8, трябва да е < Jmax)",
"jMaxLabel": "Максимален размер на junk пакети (Jmax)",
"jMaxDescription": "Максимален размер на junk пакетите (1–1280*, препоръчително: 80, трябва да е > Jmin)",
"s1Label": "Размер на junk в init пакета (S1)",
"s1Description": "Размер на junk в init пакета (01132 [1280*148=1132], препоръчително: 15150, S1+56 ≠ S2)",
"s2Label": "Размер на junk в отговорния пакет (S2)",
"s2Description": "Размер на junk в response пакета (01188 [1280*92=1188], препоръчително: 15–150)",
"s3Label": "Размер на junk в cookie reply пакета (S3)",
"s3Description": "Размер на junk в cookie reply пакета",
"s4Label": "Размер на junk в транспортния пакет (S4)",
"s4Description": "Размер на junk в транспортния пакет",
"i1Label": "Специален junk пакет 1 (I1)",
"i1Description": "Пакет за имитация на протокол в hex формат: <b 0x...>",
"i2Label": "Специален junk пакет 2 (I2)",
"i2Description": "Пакет за имитация на протокол в hex формат: <b 0x...>",
"i3Label": "Специален junk пакет 3 (I3)",
"i3Description": "Пакет за имитация на протокол в hex формат: <b 0x...>",
"i4Label": "Специален junk пакет 4 (I4)",
"i4Description": "Пакет за имитация на протокол в hex формат: <b 0x...>",
"i5Label": "Специален junk пакет 5 (I5)",
"i5Description": "Пакет за имитация на протокол в hex формат: <b 0x...>",
"h1Label": "Init magic header (H1)",
"h1Description": "Стойност на хедера в init пакета (5–2147483647, уникална спрямо H2–H4)",
"h2Label": "Response magic header (H2)",
"h2Description": "Стойност на хедера в response пакета (52147483647, уникална спрямо H1, H3, H4)",
"h3Label": "Cookie reply magic header (H3)",
"h3Description": "Стойност на хедера в cookie reply пакета (52147483647, уникална спрямо H1, H2, H4)",
"h4Label": "Transport magic header (H4)",
"h4Description": "Стойност на хедера в транспортния пакет (5–2147483647, уникална спрямо H1–H3)",
"mtuNote": "Стойностите зависят от MTU",
"obfuscationParameters": "Параметри за обфускация на AmneziaWG"
}
}
+240
View File
@@ -0,0 +1,240 @@
{
"pages": {
"me": "অ্যাকাউন্ট",
"clients": "ক্লায়েন্টস",
"admin": {
"panel": "অ্যাডমিন প্যানেল",
"general": "সাধারণ",
"config": "কনফিগ",
"interface": "ইন্টারফেস",
"hooks": "হুকস"
}
},
"user": {
"email": "ই-মেইল"
},
"me": {
"currentPassword": "বর্তমান পাসওয়ার্ড",
"enable2fa": "দুই স্তরের যাচাইকরণ চালু করুন",
"enable2faDesc": "আপনার অথেন্টিকেটর অ্যাপ দিয়ে QR কোড স্ক্যান করুন অথবা কীটি ম্যানুয়ালি প্রবেশ করুন।",
"2faKey": "TOTP কী",
"2faCodeDesc": "আপনার অথেন্টিকেটর অ্যাপ থেকে কোডটি প্রবেশ করুন।",
"disable2fa": "দুই স্তরের যাচাইকরণ বন্ধ করুন",
"disable2faDesc": "দুই স্তরের যাচাইকরণ বন্ধ করতে আপনার পাসওয়ার্ড দিন।"
},
"general": {
"name": "নাম",
"username": "ইউজারনেম",
"password": "পাসওয়ার্ড",
"newPassword": "নতুন পাসওয়ার্ড",
"updatePassword": "পাসওয়ার্ড আপডেট করুন",
"mtu": "MTU",
"allowedIps": "অনুমোদিত IPs",
"dns": "DNS",
"persistentKeepalive": "স্থায়ী কিপ-এলাইভ",
"logout": "লগআউট",
"continue": "চালিয়ে যান",
"host": "হোস্ট",
"port": "পোর্ট",
"yes": "হ্যাঁ",
"no": "না",
"confirmPassword": "পাসওয়ার্ড নিশ্চিত করুন",
"loading": "লোড হচ্ছে...",
"2fa": "দুই স্তরের যাচাইকরণ",
"2faCode": "TOTP কোড"
},
"setup": {
"welcome": "wg-easy এর প্রথম সেটআপে স্বাগতম",
"welcomeDesc": "আপনি WireGuard ইনস্টল ও পরিচালনার সবচেয়ে সহজ উপায় পেয়েছেন",
"existingSetup": "আপনার কি পূর্ববর্তী সেটআপ আছে?",
"createAdminDesc": "প্রথমে একটি অ্যাডমিন ইউজারনেম এবং শক্তিশালী পাসওয়ার্ড দিন। এই তথ্য অ্যাডমিন প্যানেলে লগইন করতে ব্যবহৃত হবে।",
"setupConfigDesc": "হোস্ট এবং পোর্ট তথ্য দিন। এটি ক্লায়েন্ট কনফিগারেশনের জন্য ব্যবহৃত হবে যখন WireGuard তাদের ডিভাইসে সেটআপ করা হবে।",
"setupMigrationDesc": "আপনার পূর্ববর্তী wg-easy থেকে নতুন সেটআপে ডেটা স্থানান্তর করতে চাইলে ব্যাকআপ ফাইল দিন।",
"upload": "আপলোড",
"migration": "ব্যাকআপ পুনরুদ্ধার করুন:",
"createAccount": "অ্যাকাউন্ট তৈরি করুন",
"successful": "সেটআপ সফল হয়েছে",
"hostDesc": "পাবলিক হোস্টনেম ক্লায়েন্টরা সংযোগ করবে",
"portDesc": "পাবলিক UDP পোর্ট ক্লায়েন্টরা সংযোগ করবে এবং WireGuard শুনবে"
},
"update": {
"updateAvailable": "একটি আপডেট উপলব্ধ!",
"update": "আপডেট"
},
"theme": {
"dark": "ডার্ক থিম",
"light": "লাইট থিম",
"system": "সিস্টেম থিম"
},
"layout": {
"toggleCharts": "চার্ট দেখান/লুকান",
"donate": "ডোনেট"
},
"login": {
"signIn": "সাইন ইন",
"rememberMe": "মনে রাখুন",
"rememberMeDesc": "ব্রাউজার বন্ধ করার পরেও লগইন থাকুন",
"insecure": "অনিরাপদ সংযোগে লগইন করা যাবে না। HTTPS ব্যবহার করুন।",
"2faRequired": "দুই স্তরের যাচাইকরণ প্রয়োজন",
"2faWrong": "দুই স্তরের যাচাইকরণ ভুল"
},
"client": {
"empty": "এখনো কোনো ক্লায়েন্ট নেই।",
"newShort": "নতুন",
"sort": "সাজান",
"create": "ক্লায়েন্ট তৈরি করুন",
"created": "ক্লায়েন্ট তৈরি হয়েছে",
"new": "নতুন ক্লায়েন্ট",
"name": "নাম",
"expireDate": "মেয়াদ শেষের তারিখ",
"expireDateDesc": "যেদিন ক্লায়েন্ট নিষ্ক্রিয় হবে। স্থায়ী করতে ফাঁকা রাখুন",
"deleteClient": "ক্লায়েন্ট মুছে ফেলুন",
"deleteDialog1": "আপনি কি নিশ্চিতভাবে মুছে ফেলতে চান",
"deleteDialog2": "এই কাজটি পূর্বাবস্থায় ফেরানো যাবে না।",
"enabled": "সক্রিয়",
"address": "ঠিকানা",
"serverAllowedIps": "সার্ভার অনুমোদিত IPs",
"otlDesc": "সংক্ষিপ্ত একবারের লিঙ্ক তৈরি করুন",
"permanent": "স্থায়ী",
"createdOn": "তৈরি হয়েছে",
"lastSeen": "শেষ দেখা হয়েছে",
"totalDownload": "মোট ডাউনলোড: ",
"totalUpload": "মোট আপলোড: ",
"newClient": "নতুন ক্লায়েন্ট",
"disableClient": "ক্লায়েন্ট নিষ্ক্রিয় করুন",
"enableClient": "ক্লায়েন্ট সক্রিয় করুন",
"noPrivKey": "এই ক্লায়েন্টের কোনো ব্যক্তিগত কী নেই। কনফিগারেশন তৈরি করা যাবে না।",
"showQR": "QR কোড দেখান",
"downloadConfig": "কনফিগারেশন ডাউনলোড করুন",
"allowedIpsDesc": "কোন IPs VPN এর মাধ্যমে রাউট হবে (গ্লোবাল কনফিগ ওভাররাইড করবে)",
"serverAllowedIpsDesc": "কোন IPs সার্ভার ক্লায়েন্টে রাউট করবে",
"mtuDesc": "VPN টানেলের জন্য সর্বাধিক প্যাকেট সাইজ নির্ধারণ করে",
"persistentKeepaliveDesc": "কিপ-এলাইভ প্যাকেটের জন্য ইন্টারভাল (সেকেন্ডে)। 0 হলে বন্ধ",
"hooks": "হুকস",
"hooksDescription": "হুকস শুধুমাত্র wg-quick এর সাথে কাজ করে",
"hooksLeaveEmpty": "শুধুমাত্র wg-quick এর জন্য। অন্যথায় ফাঁকা রাখুন",
"dnsDesc": "DNS সার্ভার ক্লায়েন্টরা ব্যবহার করবে (গ্লোবাল কনফিগ ওভাররাইড করবে)",
"notConnected": "ক্লায়েন্ট সংযুক্ত নয়",
"endpoint": "এন্ডপয়েন্ট",
"endpointDesc": "ক্লায়েন্টের IP যেখান থেকে WireGuard সংযোগ স্থাপন করা হয়েছে"
},
"dialog": {
"change": "পরিবর্তন করুন",
"cancel": "বাতিল করুন",
"create": "তৈরি করুন"
},
"toast": {
"success": "সফলতা",
"saved": "সংরক্ষিত",
"error": "ত্রুটি"
},
"form": {
"actions": "কর্মসমূহ",
"save": "সংরক্ষণ করুন",
"revert": "পূর্বাবস্থায় ফেরান",
"sectionGeneral": "সাধারণ",
"sectionAdvanced": "উন্নত",
"noItems": "কোনো আইটেম নেই",
"nullNoItems": "কোনো আইটেম নেই। গ্লোবাল কনফিগ ব্যবহার হচ্ছে",
"add": "যোগ করুন"
},
"admin": {
"general": {
"sessionTimeout": "সেশন টাইমআউট",
"sessionTimeoutDesc": "মনে রাখুনের জন্য সেশন সময়কাল (সেকেন্ডে)",
"metrics": "মেট্রিক্স",
"metricsPassword": "পাসওয়ার্ড",
"metricsPasswordDesc": "মেট্রিক্স এন্ডপয়েন্টের জন্য বেয়ারার পাসওয়ার্ড (পাসওয়ার্ড বা argon2 হ্যাশ)",
"json": "JSON",
"jsonDesc": "JSON ফরম্যাটে মেট্রিক্সের রুট",
"prometheus": "Prometheus",
"prometheusDesc": "Prometheus মেট্রিক্সের রুট"
},
"config": {
"connection": "সংযোগ",
"hostDesc": "পাবলিক হোস্টনেম ক্লায়েন্টরা সংযোগ করবে (কনফিগ বাতিল হবে)",
"portDesc": "পাবলিক UDP পোর্ট ক্লায়েন্টরা সংযোগ করবে (কনফিগ বাতিল হবে, আপনি সম্ভবত ইন্টারফেস পোর্টও পরিবর্তন করতে চাইবেন)",
"allowedIpsDesc": "অনুমোদিত IPs ক্লায়েন্টরা ব্যবহার করবে (গ্লোবাল কনফিগ)",
"dnsDesc": "DNS সার্ভার ক্লায়েন্টরা ব্যবহার করবে (গ্লোবাল কনফিগ)",
"mtuDesc": "MTU ক্লায়েন্টরা ব্যবহার করবে (শুধুমাত্র নতুন ক্লায়েন্টের জন্য)",
"persistentKeepaliveDesc": "সার্ভারে কিপ-এলাইভ পাঠানোর ইন্টারভাল (সেকেন্ডে)। 0 = বন্ধ (শুধুমাত্র নতুন ক্লায়েন্টের জন্য)",
"suggest": "পরামর্শ",
"suggestDesc": "হোস্ট ফিল্ডের জন্য একটি IP-ঠিকানা বা হোস্টনেম নির্বাচন করুন"
},
"interface": {
"cidrSuccess": "CIDR পরিবর্তন হয়েছে",
"device": "ডিভাইস",
"deviceDesc": "ইথারনেট ডিভাইস যার মাধ্যমে wireguard ট্রাফিক ফরওয়ার্ড হবে",
"mtuDesc": "WireGuard ব্যবহার করবে এমন MTU",
"portDesc": "UDP পোর্ট WireGuard শুনবে (আপনি সম্ভবত কনফিগ পোর্টও পরিবর্তন করতে চাইবেন)",
"changeCidr": "CIDR পরিবর্তন করুন",
"restart": "ইন্টারফেস রিস্টার্ট করুন",
"restartDesc": "WireGuard ইন্টারফেস রিস্টার্ট করুন",
"restartWarn": "আপনি কি নিশ্চিতভাবে ইন্টারফেস রিস্টার্ট করতে চান? এতে সব ক্লায়েন্ট সংযোগ বিচ্ছিন্ন হবে।",
"restartSuccess": "ইন্টারফেস রিস্টার্ট হয়েছে"
},
"introText": "অ্যাডমিন প্যানেলে স্বাগতম।\n\nএখানে আপনি সাধারণ সেটিংস, কনফিগারেশন, ইন্টারফেস সেটিংস এবং হুকস পরিচালনা করতে পারবেন।\n\nসাইডবার থেকে একটি বিভাগ নির্বাচন করে শুরু করুন।"
},
"zod": {
"generic": {
"required": "{0} আবশ্যক",
"validNumber": "{0} একটি বৈধ সংখ্যা হতে হবে",
"validString": "{0} একটি বৈধ স্ট্রিং হতে হবে",
"validBoolean": "{0} একটি বৈধ বুলিয়ান হতে হবে",
"validArray": "{0} একটি বৈধ অ্যারে হতে হবে",
"stringMin": "{0} কমপক্ষে {1} অক্ষর হতে হবে",
"numberMin": "{0} কমপক্ষে {1} হতে হবে"
},
"client": {
"id": "ক্লায়েন্ট আইডি",
"name": "নাম",
"expiresAt": "মেয়াদ শেষ",
"address4": "IPv4 ঠিকানা",
"address6": "IPv6 ঠিকানা",
"serverAllowedIps": "সার্ভার অনুমোদিত IPs"
},
"user": {
"username": "ইউজারনেম",
"password": "পাসওয়ার্ড",
"remember": "মনে রাখুন",
"name": "নাম",
"email": "ই-মেইল",
"emailInvalid": "ই-মেইল একটি বৈধ ই-মেইল হতে হবে",
"passwordMatch": "পাসওয়ার্ড মিলতে হবে",
"totpEnable": "TOTP চালু",
"totpEnableTrue": "TOTP চালু সত্য হতে হবে",
"totpCode": "TOTP কোড"
},
"userConfig": {
"host": "হোস্ট"
},
"general": {
"sessionTimeout": "সেশন টাইমআউট",
"metricsEnabled": "মেট্রিক্স",
"metricsPassword": "মেট্রিক্স পাসওয়ার্ড"
},
"interface": {
"cidr": "CIDR",
"device": "ডিভাইস",
"cidrValid": "CIDR বৈধ হতে হবে"
},
"otl": "একবারের লিঙ্ক",
"stringMalformed": "স্ট্রিং বিকৃত",
"body": "বডি একটি বৈধ অবজেক্ট হতে হবে",
"hook": "হুক",
"enabled": "সক্রিয়",
"mtu": "MTU",
"port": "পোর্ট",
"persistentKeepalive": "স্থায়ী কিপ-এলাইভ",
"address": "IP ঠিকানা",
"dns": "DNS",
"allowedIps": "অনুমোদিত IPs",
"file": "ফাইল"
},
"hooks": {
"preUp": "PreUp",
"postUp": "PostUp",
"preDown": "PreDown",
"postDown": "PostDown"
}
}
+286
View File
@@ -0,0 +1,286 @@
{
"pages": {
"me": "Konto",
"clients": "Clients",
"admin": {
"panel": "Admin-Konsole",
"general": "Allgemein",
"config": "Konfiguration",
"interface": "Oberfläche",
"hooks": "Hooks"
}
},
"user": {
"email": "E-Mail"
},
"me": {
"currentPassword": "Aktuelles Passwort",
"enable2fa": "Zwei-Faktor-Authentifizierung aktivieren",
"enable2faDesc": "Scannen Sie den QR-Code mit Ihrer Authentifizierungs-App oder geben Sie den Schlüssel manuell ein.",
"2faKey": "TOTP-Schlüssel",
"2faCodeDesc": "Geben Sie den Code aus Ihrer Authentifizierungs-App ein.",
"disable2fa": "Zwei-Faktor-Authentifizierung deaktivieren",
"disable2faDesc": "Geben Sie Ihr Passwort ein, um die Zwei-Faktor-Authentifizierung zu deaktivieren."
},
"general": {
"name": "Name",
"username": "Benutzername",
"password": "Passwort",
"newPassword": "Neues Passwort",
"updatePassword": "Passwort aktualisieren",
"mtu": "MTU",
"allowedIps": "Erlaubte IP-Adressen",
"dns": "DNS",
"persistentKeepalive": "Dauerhaftes Keepalive",
"logout": "Abmelden",
"continue": "Weiter",
"host": "Host",
"port": "Port",
"yes": "Ja",
"no": "Nein",
"confirmPassword": "Passwort bestätigen",
"loading": "Laden...",
"2fa": "Zwei-Faktor-Authentifizierung",
"2faCode": "TOTP-Code"
},
"setup": {
"welcome": "Willkommen zur Ersteinrichtung von wg-easy",
"welcomeDesc": "Sie haben den einfachsten Weg gefunden, WireGuard auf jedem Linux-Server zu installieren und zu verwalten.",
"existingSetup": "Haben Sie eine bestehende Einrichtung?",
"createAdminDesc": "Bitte geben Sie zuerst einen Admin-Benutzernamen sowie ein starkes, sicheres Passwort ein. Diese Anmeldedaten benötigen Sie, um sich in der Admin-Konsole anzumelden.",
"setupConfigDesc": "Bitte geben Sie die Host- und Portinformationen ein. Diese werden für die Client-Konfiguration verwendet, wenn Sie WireGuard auf Ihren Geräten einrichten.",
"setupMigrationDesc": "Bitte halten Sie die Sicherungsdatei bereit, wenn Sie Ihre Daten von Ihrer vorherigen wg-easy Version auf ihre neue Einrichtung migrieren möchten.",
"upload": "Hochladen",
"migration": "Backup wiederherstellen:",
"createAccount": "Konto erstellen",
"successful": "Einrichtung erfolgreich",
"hostDesc": "Öffentlicher Hostname mit dem sich die Clients verbinden",
"portDesc": "Öffentlicher UDP-Port an dem sich die Clients verbinden und auf dem WireGuard läuft"
},
"update": {
"updateAvailable": "Ein neues Update ist verfügbar!",
"update": "Aktualisieren"
},
"theme": {
"dark": "Dunkles Thema",
"light": "Helles Thema",
"system": "System Thema"
},
"layout": {
"toggleCharts": "Statistiken ein-/ausblenden",
"donate": "Spenden"
},
"login": {
"signIn": "Anmelden",
"rememberMe": "Angemeldet bleiben",
"rememberMeDesc": "Bleiben Sie auch nach dem Schließen des Browsers angemeldet",
"insecure": "Sie können sich nicht über eine unsichere Verbindung anmelden. Bitte benutzen Sie HTTPS.",
"2faRequired": "Zwei-Faktor-Authentifizierung wird benötigt",
"2faWrong": "Zwei-Faktor-Authentifizierung ist fehlgeschlagen"
},
"client": {
"empty": "Es gibt noch keine Clients.",
"newShort": "Neu",
"sort": "Sortieren",
"create": "Client erstellen",
"created": "Client wurde erstellt",
"new": "Neuer Client",
"name": "Name",
"expireDate": "Ablaufdatum",
"expireDateDesc": "Datum, an dem der Client deaktiviert wird. Leer lassen für dauerhaft aktiv.",
"deleteClient": "Client löschen",
"deleteDialog1": "Sind Sie sicher, dass Sie diesen Client löschen möchten",
"deleteDialog2": "Diese Aktion kann nicht rückgängig gemacht werden.",
"enabled": "Aktiviert",
"address": "Adresse",
"serverAllowedIps": "Serverseitig erlaubte IP-Adressen",
"otlDesc": "Einen kurzen Einmal-Link erzeugen",
"permanent": "Dauerhaft",
"createdOn": "Angelegt am ",
"lastSeen": "Zuletzt verbunden am ",
"totalDownload": "Gesamt-Download: ",
"totalUpload": "Gesamt-Upload: ",
"newClient": "Neuer Client",
"disableClient": "Client deaktivieren",
"enableClient": "Client aktivieren",
"noPrivKey": "Dieser Client hat keinen bekannten privaten Schlüssel, weshalb keine Konfiguration angelegt werden kann.",
"showQR": "QR-Code anzeigen",
"downloadConfig": "Konfiguration herunterladen",
"allowedIpsDesc": "Welche IP-Adressen durch das VPN geleitet werden (überschreibt die globale Konfiguration)",
"serverAllowedIpsDesc": "Welche IP-Adressen der Server zum Client leiten wird",
"mtuDesc": "Setzt die maximale Übertragungsgröße (Paketgröße) für den VPN-Tunnel",
"persistentKeepaliveDesc": "Legt das Intervall (in Sekunden) für Keepalive-Pakete fest. 0 deaktiviert es",
"hooks": "Hooks",
"hooksDescription": "Hooks funktionieren nur mit wg-quick",
"hooksLeaveEmpty": "Nur für wg-quick. Andernfalls leer lassen",
"dnsDesc": "DNS-Server, den die Clients benutzen (überschreibt die globale Konfiguration)",
"delete": "Löschen",
"notConnected": "Client nicht verbunden",
"endpoint": "Endpunkt",
"endpointDesc": "IP-Adresse des Clients, von dem aus die WireGuard-Verbindung hergestellt wird",
"search": "Suche Clients...",
"config": "Konfiguration",
"viewConfig": "Konfiguration anzeigen"
},
"dialog": {
"change": "Ändern",
"cancel": "Abbrechen",
"create": "Erstellen"
},
"toast": {
"success": "Erfolg",
"saved": "Gespeichert",
"error": "Fehler"
},
"form": {
"actions": "Aktionen",
"save": "Speichern",
"revert": "Rückgängig machen",
"sectionGeneral": "Allgemein",
"sectionAdvanced": "Erweitert",
"noItems": "Keine Einträge",
"nullNoItems": "Keine Einträge. Die globale Konfiguration wird benutzt",
"add": "Hinzufügen"
},
"admin": {
"general": {
"sessionTimeout": "Sitzungszeitüberschreitung",
"sessionTimeoutDesc": "Sitzungsdauer für \"Angemeldet bleiben\" (Sekunden)",
"metrics": "Statistiken",
"metricsPassword": "Passwort",
"metricsPasswordDesc": "Bearer-Passwort für den Statistik-Endpunkt (Passwort oder Argon2-Hash)",
"json": "JSON",
"jsonDesc": "Pfad zu den Statistiken als JSON",
"prometheus": "Prometheus",
"prometheusDesc": "Pfad zu den Prometheus-Statistiken"
},
"config": {
"connection": "Verbindung",
"hostDesc": "Öffentlicher Hostname mit dem sich die Clients verbinden (überschreibt die Konfiguration)",
"portDesc": "Öffentlicher UDP-Port an dem sich die Clients verbinden (überschreibt die Konfiguration, vermutlich wollen Sie auch den Interface-Port ändern)",
"allowedIpsDesc": "Erlaubte IP-Adressen, die die Clients nutzen werden (Globale Konfiguration)",
"dnsDesc": "DNS-Server, den die Clients nutzen werden (Globale Konfiguration)",
"mtuDesc": "MTU, den die Clients benutzen werden (nur für neue Clients)",
"persistentKeepaliveDesc": "Intervall in Sekunden, in dem Keepalive-Pakete an den Server gesendet werden. 0 = deaktiviert (nur für neue Clients)",
"suggest": "Vorschlagen",
"suggestDesc": "Wählen Sie eine IP-Adresse oder einen Hostnamen für das Host-Feld aus"
},
"interface": {
"cidrSuccess": "CIDR wurde geändert",
"device": "Gerät",
"deviceDesc": "Ethernet-Gerät, durch das der WireGuard-Datenverkehr geleitet werden soll",
"mtuDesc": "MTU, den WireGuard benutzen wird",
"portDesc": "UDP-Port, auf dem WireGuard lauschen wird (Sie wollen wahrscheinlich auch den Interface-Port ändern)",
"changeCidr": "CIDR ändern",
"restart": "Interface neu starten",
"restartDesc": "Das WireGuard-Interface neu starten",
"restartWarn": "Sind Sie sicher, dass Sie das Interface neu starten möchten? Dies wird die Verbindungen aller Clients trennen.",
"restartSuccess": "Interface neu gestartet"
},
"introText": "Willkommen in der Admin-Konsole.\n\nHier können Sie die allgemeinen Einstellungen, die Konfiguration, die Schnittstelleneinstellungen und die Hooks verwalten.\n\nBeginnen Sie, indem Sie einen der Bereiche in der Seitenleiste auswählen."
},
"zod": {
"generic": {
"required": "{0} ist erforderlich",
"validNumber": "{0} muss eine Zahl sein",
"validString": "{0} muss eine Zeichenkette sein",
"validBoolean": "{0} muss ein Wahrheitswert sein",
"validArray": "{0} muss eine Liste sein",
"stringMin": "{0} muss mindestens {1} Zeichen lang sein",
"numberMin": "{0} muss mindestens {1} sein"
},
"client": {
"id": "Client-ID",
"name": "Name",
"expiresAt": "Läuft ab am",
"address4": "IPv4-Adresse",
"address6": "IPv6-Adresse",
"serverAllowedIps": "Serverseitig erlaubte IP-Adressen"
},
"user": {
"username": "Benutzername",
"password": "Passwort",
"remember": "Merken",
"name": "Name",
"email": "E-Mail",
"emailInvalid": "Die E-Mail-Adresse muss gültig sein",
"passwordMatch": "Die Passwörter müssen übereinstimmen",
"totpEnable": "TOTP aktivieren",
"totpEnableTrue": "\"TOTP aktivieren\" muss ausgewählt sein",
"totpCode": "TOTP-Code"
},
"userConfig": {
"host": "Host"
},
"general": {
"sessionTimeout": "Sitzungszeitüberschreitung",
"metricsEnabled": "Statistiken",
"metricsPassword": "Passwort für Statistiken"
},
"interface": {
"cidr": "CIDR",
"device": "Gerät",
"cidrValid": "CIDR muss gültig sein"
},
"otl": "Einmal-Link",
"stringMalformed": "Zeichenkette ist fehlerhaft",
"body": "Body muss ein gültiges Objekt sein",
"hook": "Hook",
"enabled": "Aktiviert",
"mtu": "MTU",
"port": "Port",
"persistentKeepalive": "Dauerhaftes Keepalive",
"address": "IP-Adresse",
"dns": "DNS",
"allowedIps": "Erlaubte IP-Adressen",
"file": "Datei"
},
"hooks": {
"preUp": "PreUp",
"postUp": "PostUp",
"preDown": "PreDown",
"postDown": "PostDown"
},
"copy": {
"notSupported": "Kopieren ist nicht unterstützt",
"copied": "Kopiert!",
"failed": "Kopieren fehlgeschlagen",
"copy": "Kopieren"
},
"awg": {
"jCLabel": "Anzahl der Junk-Pakete (Jc)",
"jCDescription": "Anzahl der zu sendenden Junk-Pakete (1-128, empfohlen: 4-12)",
"jMinLabel": "Minimale Junk-Paketgröße (Jmin)",
"jMinDescription": "Mindestgröße von Junk-Paketen (0-1279*, empfohlen: 8, muss < Jmax sein)",
"jMaxLabel": "Maximale Junk-Paketgröße (Jmax)",
"jMaxDescription": "Maximalgröße von Junk-Paketen (1-1280*, empfohlen: 80, muss > Jmin sein)",
"s1Label": "Junk-Paketgröße des Init-Pakets (S1)",
"s1Description": "Junk-Paketgröße des Init-Pakets (0-1132[1280* - 148 = 1132], empfohlen: 15-150, S1+56 ≠ S2)",
"s2Label": "Junk-Paketgröße des Antwort-Pakets (S2)",
"s2Description": "Junk-Paketgröße des Antwort-Pakets (0-1188[1280* - 92 = 1188], empfohlen: 15-150)",
"s3Label": "Junk-Paketgröße des Cookie-Antwort-Pakets (S3)",
"s3Description": "Junk-Paketgröße des Cookie-Antwort-Pakets",
"s4Label": "Junk-Paketgröße des Transport-Pakets (S4)",
"s4Description": "Junk-Paketgröße des Transport-Pakets",
"i1Label": "Spezial-Junk-Paket 1 (I1)",
"i1Description": "Protokoll-Nachahmungspaket im Hex-Format: <b 0x...>",
"i2Label": "Spezial-Junk-Paket 2 (I2)",
"i2Description": "Protokoll-Nachahmungspaket im Hex-Format: <b 0x...>",
"i3Label": "Spezial-Junk-Paket 3 (I3)",
"i3Description": "Protokoll-Nachahmungspaket im Hex-Format: <b 0x...>",
"i4Label": "Spezial-Junk-Paket 4 (I4)",
"i4Description": "Protokoll-Nachahmungspaket im Hex-Format: <b 0x...>",
"i5Label": "Spezial-Junk-Paket 5 (I5)",
"i5Description": "Protokoll-Nachahmungspaket im Hex-Format: <b 0x...>",
"h1Label": "Init-Magic-Header (H1)",
"h1Description": "Wert des Init-Paket-Headers (5-2147483647, muss eindeutig zu H2-H4 sein)",
"h2Label": "Antwort-Magic-Header (H2)",
"h2Description": "Wert des Antwort-Paket-Headers (5-2147483647, muss eindeutig zu H1, H3, H4 sein)",
"h3Label": "Cookie-Antwort-Magic-Header (H3)",
"h3Description": "Wert des Cookie-Antwort-Paket-Headers (5-2147483647, muss eindeutig zu H1, H2, H4 sein)",
"h4Label": "Transport-Magic-Header (H4)",
"h4Description": "Wert des Transport-Paket-Headers (5-2147483647, muss eindeutig zu H1-H3 sein)",
"mtuNote": "Werte hängen von der MTU ab",
"obfuscationParameters": "AmneziaWG Verschleierungsparameter"
}
}
+50 -1
View File
@@ -88,6 +88,7 @@
"name": "Name",
"expireDate": "Expire Date",
"expireDateDesc": "Date the client will be disabled. Blank for permanent",
"delete": "Delete",
"deleteClient": "Delete Client",
"deleteDialog1": "Are you sure you want to delete",
"deleteDialog2": "This action cannot be undone.",
@@ -113,7 +114,13 @@
"hooks": "Hooks",
"hooksDescription": "Hooks only work with wg-quick",
"hooksLeaveEmpty": "Only for wg-quick. Otherwise, leave it empty",
"dnsDesc": "DNS server clients will use (overrides global config)"
"dnsDesc": "DNS server clients will use (overrides global config)",
"notConnected": "Client not connected",
"endpoint": "Endpoint",
"endpointDesc": "IP of the client from which the WireGuard connection is established",
"search": "Search clients...",
"config": "Configuration",
"viewConfig": "View Configuration"
},
"dialog": {
"change": "Change",
@@ -233,5 +240,47 @@
"postUp": "PostUp",
"preDown": "PreDown",
"postDown": "PostDown"
},
"copy": {
"notSupported": "Copy is not supported",
"copied": "Copied!",
"failed": "Copy failed",
"copy": "Copy"
},
"awg": {
"jCLabel": "Junk packet count (Jc)",
"jCDescription": "Number of junk packets to send (1-128, recommended: 4-12)",
"jMinLabel": "Junk packet min size (Jmin)",
"jMinDescription": "Minimum size of junk packets (0-1279*, recommended: 8, must be < Jmax)",
"jMaxLabel": "Junk packet max size (Jmax)",
"jMaxDescription": "Maximum size of junk packets (1-1280*, recommended: 80, must be > Jmin)",
"s1Label": "Init packet junk size (S1)",
"s1Description": "Init packet junk size (0-1132[1280* - 148 = 1132], recommended: 15-150, S1+56 ≠ S2)",
"s2Label": "Response packet junk size (S2)",
"s2Description": "Response packet junk size (0-1188[1280* - 92 = 1188], recommended: 15-150)",
"s3Label": "Cookie reply packet junk size (S3)",
"s3Description": "Cookie reply packet junk size",
"s4Label": "Transport packet junk size (S4)",
"s4Description": "Transport packet junk size",
"i1Label": "Special junk packet 1 (I1)",
"i1Description": "Protocol mimic packet in hex format: <b 0x...>",
"i2Label": "Special junk packet 2 (I2)",
"i2Description": "Protocol mimic packet in hex format: <b 0x...>",
"i3Label": "Special junk packet 3 (I3)",
"i3Description": "Protocol mimic packet in hex format: <b 0x...>",
"i4Label": "Special junk packet 4 (I4)",
"i4Description": "Protocol mimic packet in hex format: <b 0x...>",
"i5Label": "Special junk packet 5 (I5)",
"i5Description": "Protocol mimic packet in hex format: <b 0x...>",
"h1Label": "Init magic header (H1)",
"h1Description": "Init packet header value (5-2147483647, must be unique from H2-H4)",
"h2Label": "Response magic header (H2)",
"h2Description": "Response packet header value (5-2147483647, must be unique from H1, H3, H4)",
"h3Label": "Cookie reply magic header (H3)",
"h3Description": "Cookie reply packet header value (5-2147483647, must be unique from H1, H2, H4)",
"h4Label": "Transport magic header (H4)",
"h4Description": "Transport packet header value (5-2147483647, must be unique from H1-H3)",
"mtuNote": "Values depend on the MTU",
"obfuscationParameters": "AmneziaWG Obfuscation Parameters"
}
}
+240
View File
@@ -0,0 +1,240 @@
{
"pages": {
"me": "Cuenta",
"clients": "Clientes",
"admin": {
"panel": "Panel de Admin.",
"general": "General",
"config": "Configuración",
"interface": "Interfaz",
"hooks": "Hooks"
}
},
"user": {
"email": "Correo electrónico"
},
"me": {
"currentPassword": "Contraseña actual",
"enable2fa": "Habilitar autenticación en dos pasos",
"enable2faDesc": "Escanea el código QR con tu aplicación de autenticación o introduce la clave manualmente.",
"2faKey": "Clave TOTP",
"2faCodeDesc": "Introduce el código de tu aplicación de autenticación.",
"disable2fa": "Desactivar autenticación en dos pasos",
"disable2faDesc": "Introduce tu contraseña para desactivar la autenticación en dos pasos."
},
"general": {
"name": "Nombre",
"username": "Usuario",
"password": "Contraseña",
"newPassword": "Nueva contraseña",
"updatePassword": "Actualizar contraseña",
"mtu": "MTU",
"allowedIps": "IPs permitidas",
"dns": "DNS",
"persistentKeepalive": "Keepalive persistente",
"logout": "Cerrar sesión",
"continue": "Continuar",
"host": "Host",
"port": "Puerto",
"yes": "Sí",
"no": "No",
"confirmPassword": "Confirmar contraseña",
"loading": "Cargando...",
"2fa": "Autenticación en dos pasos",
"2faCode": "Código TOTP"
},
"setup": {
"welcome": "Bienvenido a tu primera configuración de wg-easy",
"welcomeDesc": "Has encontrado la forma más fácil de instalar y gestionar WireGuard en cualquier host Linux",
"existingSetup": "¿Tienes una configuración existente?",
"createAdminDesc": "Por favor, introduce un nombre de usuario y una contraseña segura. Esta información se usará para iniciar sesión en el panel de administración.",
"setupConfigDesc": "Introduce la información del host y puerto. Se utilizará para la configuración del cliente al instalar WireGuard en sus dispositivos.",
"setupMigrationDesc": "Proporciona el archivo de copia de seguridad si deseas migrar tus datos desde una versión anterior de wg-easy a esta nueva configuración.",
"upload": "Subir",
"migration": "Restaurar copia de seguridad:",
"createAccount": "Crear cuenta",
"successful": "Configuración completada",
"hostDesc": "Nombre de host público al que se conectarán los clientes",
"portDesc": "Puerto UDP público al que se conectarán los clientes y que escuchará WireGuard"
},
"update": {
"updateAvailable": "¡Hay una actualización disponible!",
"update": "Actualizar"
},
"theme": {
"dark": "Tema oscuro",
"light": "Tema claro",
"system": "Tema del sistema"
},
"layout": {
"toggleCharts": "Mostrar/ocultar gráficos",
"donate": "Donar"
},
"login": {
"signIn": "Iniciar sesión",
"rememberMe": "Recordarme",
"rememberMeDesc": "Mantener sesión iniciada tras cerrar el navegador",
"insecure": "No puedes iniciar sesión con una conexión no segura. Usa HTTPS.",
"2faRequired": "Se requiere autenticación en dos pasos",
"2faWrong": "El código de autenticación en dos pasos es incorrecto"
},
"client": {
"empty": "No hay clientes todavía.",
"newShort": "Nuevo",
"sort": "Ordenar",
"create": "Crear cliente",
"created": "Cliente creado",
"new": "Nuevo cliente",
"name": "Nombre",
"expireDate": "Fecha de expiración",
"expireDateDesc": "Fecha en que el cliente será desactivado. En blanco = permanente",
"deleteClient": "Eliminar cliente",
"deleteDialog1": "¿Estás seguro de que deseas eliminar a",
"deleteDialog2": "Esta acción no se puede deshacer.",
"enabled": "Habilitado",
"address": "Dirección",
"serverAllowedIps": "IPs permitidas del servidor",
"otlDesc": "Generar enlace único de un solo uso",
"permanent": "Permanente",
"createdOn": "Creado el ",
"lastSeen": "Última conexión el ",
"totalDownload": "Descarga total: ",
"totalUpload": "Subida total: ",
"newClient": "Nuevo cliente",
"disableClient": "Desactivar cliente",
"enableClient": "Activar cliente",
"noPrivKey": "Este cliente no tiene clave privada conocida. No se puede crear la configuración.",
"showQR": "Mostrar código QR",
"downloadConfig": "Descargar configuración",
"allowedIpsDesc": "Qué IPs se enrutarán por la VPN (anula la configuración global)",
"serverAllowedIpsDesc": "Qué IPs el servidor enviará al cliente",
"mtuDesc": "Tamaño máximo de paquete (MTU) para el túnel VPN",
"persistentKeepaliveDesc": "Intervalo (en segundos) para los paquetes keep-alive. 0 lo desactiva",
"hooks": "Hooks",
"hooksDescription": "Los hooks solo funcionan con wg-quick",
"hooksLeaveEmpty": "Solo para wg-quick. En caso contrario, dejar vacío",
"dnsDesc": "Servidor DNS que usarán los clientes (anula la configuración global)",
"notConnected": "Cliente no conectado",
"endpoint": "Punto de conexión",
"endpointDesc": "IP del cliente desde donde se establece la conexión WireGuard"
},
"dialog": {
"change": "Cambiar",
"cancel": "Cancelar",
"create": "Crear"
},
"toast": {
"success": "Éxito",
"saved": "Guardado",
"error": "Error"
},
"form": {
"actions": "Acciones",
"save": "Guardar",
"revert": "Revertir",
"sectionGeneral": "General",
"sectionAdvanced": "Avanzado",
"noItems": "Sin elementos",
"nullNoItems": "Sin elementos. Usando configuración global",
"add": "Añadir"
},
"admin": {
"general": {
"sessionTimeout": "Tiempo de sesión",
"sessionTimeoutDesc": "Duración de sesión con 'Recordarme' (en segundos)",
"metrics": "Métricas",
"metricsPassword": "Contraseña",
"metricsPasswordDesc": "Contraseña Bearer para el endpoint de métricas (contraseña o hash argon2)",
"json": "JSON",
"jsonDesc": "Ruta para métricas en formato JSON",
"prometheus": "Prometheus",
"prometheusDesc": "Ruta para métricas de Prometheus"
},
"config": {
"connection": "Conexión",
"hostDesc": "Nombre de host público al que se conectarán los clientes (invalida config)",
"portDesc": "Puerto UDP público al que se conectarán los clientes (invalida config, también debes cambiar el puerto de interfaz)",
"allowedIpsDesc": "IPs permitidas que usarán los clientes (configuración global)",
"dnsDesc": "Servidor DNS que usarán los clientes (configuración global)",
"mtuDesc": "MTU que usarán los clientes (solo para nuevos clientes)",
"persistentKeepaliveDesc": "Intervalo en segundos para enviar keepalives al servidor. 0 = desactivado (solo para nuevos clientes)",
"suggest": "Sugerir",
"suggestDesc": "Elegir dirección IP o nombre de host para el campo Host"
},
"interface": {
"cidrSuccess": "CIDR cambiado",
"device": "Dispositivo",
"deviceDesc": "Dispositivo Ethernet por donde se reenviará el tráfico de WireGuard",
"mtuDesc": "MTU que usará WireGuard",
"portDesc": "Puerto UDP en el que escuchará WireGuard (debes cambiar también el puerto de config)",
"changeCidr": "Cambiar CIDR",
"restart": "Reiniciar interfaz",
"restartDesc": "Reiniciar la interfaz de WireGuard",
"restartWarn": "¿Estás seguro de reiniciar la interfaz? Esto desconectará a todos los clientes.",
"restartSuccess": "Interfaz reiniciada"
},
"introText": "Bienvenido al panel de administración.\n\nAquí puedes gestionar los ajustes generales, la configuración, la interfaz y los hooks.\n\nEmpieza eligiendo una de las secciones en la barra lateral."
},
"zod": {
"generic": {
"required": "{0} es obligatorio",
"validNumber": "{0} debe ser un número válido",
"validString": "{0} debe ser una cadena válida",
"validBoolean": "{0} debe ser un booleano válido",
"validArray": "{0} debe ser una lista válida",
"stringMin": "{0} debe tener al menos {1} caracteres",
"numberMin": "{0} debe ser al menos {1}"
},
"client": {
"id": "ID del cliente",
"name": "Nombre",
"expiresAt": "Expira el",
"address4": "Dirección IPv4",
"address6": "Dirección IPv6",
"serverAllowedIps": "IPs permitidas del servidor"
},
"user": {
"username": "Usuario",
"password": "Contraseña",
"remember": "Recordar",
"name": "Nombre",
"email": "Correo electrónico",
"emailInvalid": "El correo electrónico debe ser válido",
"passwordMatch": "Las contraseñas deben coincidir",
"totpEnable": "Activar TOTP",
"totpEnableTrue": "Debe estar activado",
"totpCode": "Código TOTP"
},
"userConfig": {
"host": "Host"
},
"general": {
"sessionTimeout": "Tiempo de sesión",
"metricsEnabled": "Métricas",
"metricsPassword": "Contraseña de métricas"
},
"interface": {
"cidr": "CIDR",
"device": "Dispositivo",
"cidrValid": "El CIDR debe ser válido"
},
"otl": "Enlace de un solo uso",
"stringMalformed": "Cadena malformada",
"body": "El cuerpo debe ser un objeto válido",
"hook": "Hook",
"enabled": "Habilitado",
"mtu": "MTU",
"port": "Puerto",
"persistentKeepalive": "Keepalive persistente",
"address": "Dirección IP",
"dns": "DNS",
"allowedIps": "IPs permitidas",
"file": "Archivo"
},
"hooks": {
"preUp": "PreUp",
"postUp": "PostUp",
"preDown": "PreDown",
"postDown": "PostDown"
}
}
+286
View File
@@ -0,0 +1,286 @@
{
"pages": {
"me": "Compte",
"clients": "Clients",
"admin": {
"panel": "Panel Admin",
"general": "Général",
"config": "Config",
"interface": "Interface",
"hooks": "Hooks"
}
},
"user": {
"email": "E-Mail"
},
"me": {
"currentPassword": "Mot de passe actuel",
"enable2fa": "Activer l'authentification à deux facteurs",
"enable2faDesc": "Scannez le code QR avec votre application d'authentification ou saisissez la clé manuellement.",
"2faKey": "Clé TOTP",
"2faCodeDesc": "Saisissez le code de votre application d'authentification.",
"disable2fa": "Désactiver l'authentification à deux facteurs",
"disable2faDesc": "Saisissez votre mot de passe pour désactiver l'authentification à deux facteurs."
},
"general": {
"name": "Nom",
"username": "Nom d'utilisateur",
"password": "Mot de passe",
"newPassword": "Nouveau mot de passe",
"updatePassword": "Mettre à jour le mot de passe",
"mtu": "MTU",
"allowedIps": "IPs autorisées",
"dns": "DNS",
"persistentKeepalive": "Keepalive persistant",
"logout": "Déconnexion",
"continue": "Continuer",
"host": "Hôte",
"port": "Port",
"yes": "Oui",
"no": "Non",
"confirmPassword": "Confirmer le mot de passe",
"loading": "Chargement...",
"2fa": "Authentification à deux facteurs",
"2faCode": "Code TOTP"
},
"setup": {
"welcome": "Bienvenue dans votre première installation de wg-easy",
"welcomeDesc": "Vous avez trouvé la façon la plus simple d'installer et de gérer WireGuard sur n'importe quel hôte Linux.",
"existingSetup": "Avez-vous une installation existante ?",
"createAdminDesc": "Veuillez d'abord saisir un nom d'utilisateur administrateur et un mot de passe sécurisé. Ces informations seront utilisées pour vous connecter à votre panel d'administration.",
"setupConfigDesc": "Veuillez saisir les informations relatives à l'hôte et au port. Ceci sera utilisé pour la configuration du client lors de la mise en place de WireGuard sur les appareils.",
"setupMigrationDesc": "Veuillez fournir le fichier de sauvegarde si vous souhaitez migrer vos données de la version précédente de wg-easy vers votre nouvelle installation.",
"upload": "Téléverser",
"migration": "Restaurer la sauvegarde:",
"createAccount": "Créer un compte",
"successful": "Installation réussie",
"hostDesc": "Nom d'hôte public auquel les clients se connecteront",
"portDesc": "Port UDP public auquel les clients se connecteront et sur lequel WireGuard écoutera"
},
"update": {
"updateAvailable": "Une mise à jour est disponible!",
"update": "Mise à jour"
},
"theme": {
"dark": "Thème sombre",
"light": "Thème clair",
"system": "Thème système"
},
"layout": {
"toggleCharts": "Afficher/masquer les graphiques",
"donate": "Donation"
},
"login": {
"signIn": "Se connecter",
"rememberMe": "Se souvenir de moi",
"rememberMeDesc": "Rester connecté après avoir fermé le navigateur",
"insecure": "Vous ne pouvez pas vous connecter avec une connexion non sécurisée. Utilisez HTTPS.",
"2faRequired": "L'authentification à deux facteurs est requise",
"2faWrong": "Le code d'authentification à deux facteurs est incorrect"
},
"client": {
"empty": "Il n'y a pas encore de clients.",
"newShort": "Nouveau",
"sort": "Trier",
"create": "Créer un client",
"created": "Client créé",
"new": "Nouveau client",
"name": "Nom",
"expireDate": "Date d'expiration",
"expireDateDesc": "Date à laquelle le client sera désactivé. Vide pour permanent",
"deleteClient": "Supprimer le client",
"deleteDialog1": "Êtes-vous sûr de vouloir supprimer",
"deleteDialog2": "Cette action ne peut être annulée.",
"enabled": "Activé",
"address": "Adresse",
"serverAllowedIps": "Serveur IPs autorisées",
"otlDesc": "Générer un lien court et unique",
"permanent": "Permanent",
"createdOn": "Créé le ",
"lastSeen": "Dernière visite le ",
"totalDownload": "Téléchargement total: ",
"totalUpload": "Téléversement total: ",
"newClient": "Nouveau client",
"disableClient": "Désactiver le client",
"enableClient": "Activer le client",
"noPrivKey": "Ce client n'a pas de clé privée connue. Impossible de créer une configuration.",
"showQR": "Afficher le code QR",
"downloadConfig": "Télécharger la configuration",
"allowedIpsDesc": "Quelles IPs seront acheminées par le VPN (remplace la configuration globale)",
"serverAllowedIpsDesc": "Les IPs que le serveur acheminera vers le client",
"mtuDesc": "Définit l'unité de transmission maximale (taille des paquets) pour le tunnel VPN",
"persistentKeepaliveDesc": "Définit l'intervalle (en secondes) pour les paquets keep-alive. 0 le désactive",
"hooks": "Hooks",
"hooksDescription": "Les hooks ne fonctionnent qu'avec wg-quick",
"hooksLeaveEmpty": "Uniquement pour wg-quick. Sinon, laissez-le vide",
"dnsDesc": "Serveur DNS que les clients utiliseront (remplace la configuration globale)",
"notConnected": "Client non connecté",
"endpoint": "Endpoint",
"endpointDesc": "Adresse IP du client à partir duquel la connexion WireGuard est établie",
"search": "Rechercher des clients...",
"config": "Configuration",
"viewConfig": "Voir la configuration",
"delete": "Supprimer"
},
"dialog": {
"change": "Modifier",
"cancel": "Annuler",
"create": "Créer"
},
"toast": {
"success": "Réussite",
"saved": "Sauvegardé",
"error": "Erreur"
},
"form": {
"actions": "Actions",
"save": "Sauvegarder",
"revert": "Revenir en arrière",
"sectionGeneral": "Général",
"sectionAdvanced": "Avancé",
"noItems": "Aucun élément",
"nullNoItems": "Aucun élément. Utilisation de la configuration globale",
"add": "Ajouter"
},
"admin": {
"general": {
"sessionTimeout": "Délai d'expiration de la session",
"sessionTimeoutDesc": "Durée de la session pour Se souvenir de moi (secondes)",
"metrics": "Métriques",
"metricsPassword": "Mot de passe",
"metricsPasswordDesc": "Mot de passe Bearer pour le endpoint des métriques (mot de passe ou argon2 hash)",
"json": "JSON",
"jsonDesc": "Route pour les métriques au format JSON",
"prometheus": "Prometheus",
"prometheusDesc": "Route pour les métriques Prometheus"
},
"config": {
"connection": "Connexion",
"hostDesc": "Nom d'hôte public auquel les clients se connecteront (invalide la configuration)",
"portDesc": "Port UDP public auquel les clients se connecteront (invalide la configuration, vous souhaiterez probablement modifier le port d'interface également)",
"allowedIpsDesc": "IPs autorisées que les clients utiliseront (configuration globale)",
"dnsDesc": "Serveur DNS que les clients utiliseront (configuration globale)",
"mtuDesc": "MTU que les clients utiliseront (uniquement pour les nouveaux clients)",
"persistentKeepaliveDesc": "Intervalle en secondes keepalives du serveur. 0 = désactivé (uniquement pour les nouveaux clients)",
"suggest": "Suggérer",
"suggestDesc": "Choisissez une adresse IP ou un nom d'hôte pour le champ Hôte."
},
"interface": {
"cidrSuccess": "CIDR modifié",
"device": "Périphérique",
"deviceDesc": "Périphérique Ethernet dans lequel le trafic wireguard sera transmis.",
"mtuDesc": "MTU que WireGuard utilisera",
"portDesc": "Port UDP sur lequel WireGuard écoutera (vous souhaiterez probablement changer le port de configuration aussi)",
"changeCidr": "Modifier CIDR",
"restart": "Redémarrer l'interface",
"restartDesc": "Redémarre l'interface WireGuard",
"restartWarn": "Êtes-vous sûr de redémarrer l'interface ? Cela déconnectera tous les clients.",
"restartSuccess": "Interface redémarrée"
},
"introText": "Bienvenue dans le panel d'administration.\n\nVous pouvez y gérer les paramètres généraux, la configuration, les paramètres de l'interface et les hooks.\n\nCommencez par choisir l'une des sections de la barre latérale."
},
"zod": {
"generic": {
"required": "{0} est requis",
"validNumber": "{0} doit être un nombre valide",
"validString": "{0} doit être une chaîne de caractères valide",
"validBoolean": "{0} doit être un booléen valide",
"validArray": "{0} doit être un tableau valide",
"stringMin": "{0} doit comporter au moins {1} caractère(s)",
"numberMin": "{0} doit être d'au moins {1}"
},
"client": {
"id": "ID du client",
"name": "Nom",
"expiresAt": "Expire le",
"address4": "Adresse IPv4",
"address6": "Adresse IPv6",
"serverAllowedIps": "Serveur IPs autorisées"
},
"user": {
"username": "Nom d'utilisateur",
"password": "Mot de passe",
"remember": "Se souvenir",
"name": "Nom",
"email": "Email",
"emailInvalid": "L'email doit être valide",
"passwordMatch": "Les mots de passe doivent correspondre",
"totpEnable": "Activer TOTP",
"totpEnableTrue": "Activer TOTP doit être activé",
"totpCode": "Code TOTP"
},
"userConfig": {
"host": "Hôte"
},
"general": {
"sessionTimeout": "Délai d'expiration de la session",
"metricsEnabled": "Métriques",
"metricsPassword": "Mot de passe métriques"
},
"interface": {
"cidr": "CIDR",
"device": "Périphérique",
"cidrValid": "CIDR doit être valide"
},
"otl": "Lien unique",
"stringMalformed": "La chaîne est malformée",
"body": "Le corps doit être un objet valide",
"hook": "Hook",
"enabled": "Activé",
"mtu": "MTU",
"port": "Port",
"persistentKeepalive": "Keepalive persistant",
"address": "Adresse IP",
"dns": "DNS",
"allowedIps": "IPs autorisées",
"file": "Fichier"
},
"hooks": {
"preUp": "PreUp",
"postUp": "PostUp",
"preDown": "PreDown",
"postDown": "PostDown"
},
"copy": {
"notSupported": "La copie n'est pas prise en charge",
"copied": "Copié !",
"failed": "Échec de la copie",
"copy": "Copier"
},
"awg": {
"jCLabel": "Nombre de paquets parasites (Jc)",
"jCDescription": "Nombre de paquets parasites à envoyer (1-128, recommandé : 4-12)",
"jMinLabel": "Taille min des paquets parasites (Jmin)",
"jMinDescription": "Taille minimale des paquets parasites (0-1279*, recommandé : 8, doit être < Jmax)",
"jMaxLabel": "Taille max des paquets parasites (Jmax)",
"jMaxDescription": "Taille maximale des paquets parasites (1-1280*, recommandé : 80, doit être > Jmin)",
"s1Label": "Taille parasite du paquet init (S1)",
"s1Description": "Taille parasite du paquet d'initialisation (0-1132[1280* - 148 = 1132], recommandé : 15-150, S1+56 ≠ S2)",
"s2Label": "Taille parasite du paquet réponse (S2)",
"s2Description": "Taille parasite du paquet de réponse (0-1188[1280* - 92 = 1188], recommandé : 15-150)",
"s3Label": "Taille parasite du paquet cookie reply (S3)",
"s3Description": "Taille parasite du paquet de réponse cookie",
"s4Label": "Taille parasite du paquet transport (S4)",
"s4Description": "Taille parasite du paquet de transport",
"i1Label": "Paquet parasite spécial 1 (I1)",
"i1Description": "Paquet de simulation de protocole en format hexadécimal : <b 0x...>",
"i2Label": "Paquet parasite spécial 2 (I2)",
"i2Description": "Paquet de simulation de protocole en format hexadécimal : <b 0x...>",
"i3Label": "Paquet parasite spécial 3 (I3)",
"i3Description": "Paquet de simulation de protocole en format hexadécimal : <b 0x...>",
"i4Label": "Paquet parasite spécial 4 (I4)",
"i4Description": "Paquet de simulation de protocole en format hexadécimal : <b 0x...>",
"i5Label": "Paquet parasite spécial 5 (I5)",
"i5Description": "Paquet de simulation de protocole en format hexadécimal : <b 0x...>",
"h1Label": "En-tête magique init (H1)",
"h1Description": "Valeur d'en-tête du paquet init (5-2147483647, doit être unique par rapport à H2-H4)",
"h2Label": "En-tête magique réponse (H2)",
"h2Description": "Valeur d'en-tête du paquet réponse (5-2147483647, doit être unique par rapport à H1, H3, H4)",
"h3Label": "En-tête magique cookie reply (H3)",
"h3Description": "Valeur d'en-tête du paquet cookie reply (5-2147483647, doit être unique par rapport à H1, H2, H4)",
"h4Label": "En-tête magique transport (H4)",
"h4Description": "Valeur d'en-tête du paquet transport (5-2147483647, doit être unique par rapport à H1-H3)",
"mtuNote": "Les valeurs dépendent du MTU",
"obfuscationParameters": "Paramètres d'obfuscation AmneziaWG"
}
}
+145
View File
@@ -0,0 +1,145 @@
{
"pages": {
"me": "Conta",
"clients": "Clientes",
"admin": {
"panel": "Panel de administración",
"general": "Xeral",
"config": "Configuración",
"interface": "Interface",
"hooks": "Hooks"
}
},
"user": {
"email": "Correo electrónico"
},
"me": {
"currentPassword": "Contrasinal actual",
"enable2fa": "Activar a autenticación de dobre factor",
"enable2faDesc": "Escanea o código QR coa túa aplicación de autenticación ou introduce a chave manualmente.",
"2faKey": "Chave TOTP",
"2faCodeDesc": "Introduce o código da túa aplicación de autenticación.",
"disable2fa": "Desactivar a autenticación de dobre factor",
"disable2faDesc": "Introduce o teu contrasinal para desactivar a autenticación de dobre factor."
},
"general": {
"name": "Nome",
"username": "Nome de usuario",
"password": "Contrasinal",
"newPassword": "Novo contrasinal",
"updatePassword": "Actualizar contrasinal",
"mtu": "MTU",
"allowedIps": "IP permitidas",
"dns": "DNS",
"persistentKeepalive": "Keepalive persistente",
"logout": "Pechar sesión",
"continue": "Continuar",
"host": "Host",
"port": "Porto",
"yes": "Si",
"no": "Non",
"confirmPassword": "Confirmar o contrasinal",
"loading": "Cargando...",
"2fa": "Autenticación de dobre factor",
"2faCode": "Código TOTP"
},
"setup": {
"welcome": "Benvido á túa primeira configuración de wg-easy",
"welcomeDesc": "Atopaches a forma máis doada de instalar e xestionar WireGuard en calquera sistema Linux",
"existingSetup": "Tes unha configuración existente?",
"createAdminDesc": "Por favor, introduce primeiro un usuario administrador cun contrasinal seguro. Esta información empregarase para acceder ao panel de administración.",
"setupConfigDesc": "Por favor, introduce a información do host e do porto. Isto empregarase para a configuración dos clientes ao configurar WireGuard nos seus dispositivos.",
"setupMigrationDesc": "Por favor, fornece o ficheiro da copia de seguridade se queres migrar os datos da túa versión anterior de wg-easy á nova configuración.",
"upload": "Subir",
"migration": "Recuperar a copia de seguridade:",
"createAccount": "Crear conta",
"successful": "Configuración completada con éxito",
"hostDesc": "Nome de host público ao que se conectarán os clientes",
"portDesc": "Porto UDP público ao que se conectarán os clientes e no que escoitará WireGuard"
},
"update": {
"updateAvailable": "Hai unha actualización dispoñible!",
"update": "Actualizar"
},
"theme": {
"dark": "Tema escuro",
"light": "Tema claro",
"system": "Tema do sistema"
},
"layout": {
"toggleCharts": "Amosar/Ocultar gráficas",
"donate": "Doar"
},
"login": {
"signIn": "Iniciar sesión",
"rememberMe": "Lembrarme",
"rememberMeDesc": "Manter a sesión iniciada ao pechar o navegador",
"insecure": "Non podes iniciar sesión cunha conexión insegura. Usa HTTPS.",
"2faRequired": "É necesaria a autenticación de dobre factor",
"2faWrong": "A autenticación de dobre factor é incorrecta"
},
"client": {
"empty": "Aínda non hai clientes.",
"newShort": "Novo",
"sort": "Ordenar",
"create": "Crear cliente",
"created": "Cliente creado",
"new": "Novo cliente",
"name": "Nome",
"expireDate": "Data de caducidade",
"expireDateDesc": "Data na que o cliente será desactivado. Déixao en branco para permanente",
"delete": "Eliminar",
"deleteClient": "Eliminar cliente",
"deleteDialog1": "Seguro que queres eliminar",
"deleteDialog2": "Esta acción non se pode desfacer.",
"enabled": "Activado",
"address": "Enderezo",
"serverAllowedIps": "IP permitidas polo servidor",
"otlDesc": "Xerar ligazón curta dun só uso",
"permanent": "Permanente",
"createdOn": "Creado o ",
"lastSeen": "Visto por última vez o ",
"totalDownload": "Descarga total: ",
"totalUpload": "Subida total: ",
"newClient": "Novo cliente",
"disableClient": "Desactivar cliente",
"enableClient": "Activar cliente",
"noPrivKey": "Este cliente non ten unha chave privada coñecida. Non se pode crear a configuración.",
"showQR": "Amosar código QR",
"downloadConfig": "Descargar configuración",
"allowedIpsDesc": "IP que se encamiñarán a través da VPN (sobrescribe a configuración global)",
"serverAllowedIpsDesc": "IP que o servidor encamiñará ao cliente",
"mtuDesc": "Define a unidade máxima de transmisión (tamaño do paquete) para o túnel VPN",
"persistentKeepaliveDesc": "Define o intervalo (en segundos) para os paquetes keep-alive. 0 desactívaos",
"hooks": "Hooks",
"hooksDescription": "Os hooks só funcionan con wg-quick",
"hooksLeaveEmpty": "Só para wg-quick. Noutro caso, déixao baleiro",
"dnsDesc": "Servidor DNS que empregarán os clientes (sobrescribe a configuración global)",
"notConnected": "Cliente non conectado",
"endpoint": "Punto final",
"endpointDesc": "IP do cliente desde a que se establece a conexión WireGuard",
"search": "Buscar clientes...",
"config": "Configuración",
"viewConfig": "Ver configuración"
},
"dialog": {
"change": "Cambiar",
"cancel": "Cancelar",
"create": "Crear"
},
"toast": {
"success": "Éxito",
"saved": "Gardado",
"error": "Erro"
},
"form": {
"actions": "Accións",
"save": "Gardar",
"revert": "Reverter",
"sectionGeneral": "Xeral",
"sectionAdvanced": "Avanzado",
"noItems": "Sen elementos",
"nullNoItems": "Sen elementos. Usando a configuración global",
"add": "Engadir"
}
}
+240
View File
@@ -0,0 +1,240 @@
{
"pages": {
"me": "Akun",
"clients": "Klien",
"admin": {
"panel": "Panel Admin",
"general": "General",
"config": "Umum",
"interface": "Antarmuka",
"hooks": "Hooks"
}
},
"user": {
"email": "E-Mail"
},
"me": {
"currentPassword": "Kata Sandi Saat Ini",
"enable2fa": "Aktifkan autentikasi dua faktor",
"enable2faDesc": "Pindai kode QR dengan aplikasi autentikator anda atau masukkan kuncinya secara manual.",
"2faKey": "Kunci TOTP",
"2faCodeDesc": "Masukkan kode dari aplikasi autentikator Anda.",
"disable2fa": "Nonaktifkan autentikasi dua faktor",
"disable2faDesc": "Masukkan kata sandi anda untuk menonaktifkan autentikasi dua faktor."
},
"general": {
"name": "Nama",
"username": "Name Pengguna",
"password": "Kata Sandi",
"newPassword": "Kata Sandi Baru",
"updatePassword": "Ubah Kata Sandi",
"mtu": "MTU",
"allowedIps": "IP yang diizinkan",
"dns": "DNS",
"persistentKeepalive": "Keepalive Persisten",
"logout": "Keluar",
"continue": "Lanjutkan",
"host": "Host",
"port": "Port",
"yes": "Ya",
"no": "Tidak",
"confirmPassword": "Konfirmasi Kata Sandi",
"loading": "Memuat...",
"2fa": "Autentikasi Dua Faktor",
"2faCode": "Kode TOTP"
},
"setup": {
"welcome": "Selamat datang di pengaturan pertama wg-easy anda",
"welcomeDesc": "Anda telah menemukan cara termudah untuk menginstal dan mengelola WireGuard di host Linux mana pun",
"existingSetup": "Apakah anda sudah memiliki pengaturan sebelumnya?",
"createAdminDesc": "Silakan masukkan dulu nama pengguna admin dan kata sandi yang kuat dan aman. Informasi ini akan digunakan untuk masuk ke panel administrasi Anda.",
"setupConfigDesc": "Silakan masukkan informasi host dan port. Ini akan digunakan untuk konfigurasi klien saat mengatur WireGuard di perangkat mereka.",
"setupMigrationDesc": "Silakan berikan file cadangan jika anda ingin memigrasikan data dari versi wg-easy sebelumnya ke pengaturan baru anda.",
"upload": "Unggah",
"migration": "Pulihkan cadangan:",
"createAccount": "Buat Akun",
"successful": "Pengaturan berhasil",
"hostDesc": "Hostname publik yang akan digunakan klien untuk terhubung",
"portDesc": "Port UDP publik yang akan digunakan klien untuk terhubung dan dibaca oleh WireGuard"
},
"update": {
"updateAvailable": "Ada pembaruan tersedia!",
"update": "Pembaruan"
},
"theme": {
"dark": "Tema gelap",
"light": "Tema terang",
"system": "Tema sistem"
},
"layout": {
"toggleCharts": "Tampilkan/sembunyikan Grafik",
"donate": "Donasi"
},
"login": {
"signIn": "Masuk",
"rememberMe": "Ingat saya",
"rememberMeDesc": "Tetap masuk setelah menutup browser",
"insecure": "Anda tidak dapat masuk dengan koneksi yang tidak aman. Gunakan HTTPS.",
"2faRequired": "Autentikasi dua faktor wajib digunakan",
"2faWrong": "Autentikasi dua faktor salah"
},
"client": {
"empty": "Belum ada klien.",
"newShort": "Baru",
"sort": "Urutkan",
"create": "Buat Klien",
"created": "Klien terbuat",
"new": "Klien Baru",
"name": "Nama",
"expireDate": "Tanggal Kedaluwarsa",
"expireDateDesc": "Tanggal klien akan dinonaktifkan. Kosongkan untuk opsi permanen.",
"deleteClient": "Hapus Klien",
"deleteDialog1": "Apakah anda yakin ingin menghapus",
"deleteDialog2": "Tindakan ini tidak dapat dibatalkan.",
"enabled": "Aktifkan",
"address": "Alamat",
"serverAllowedIps": "IP yang Diizinkan pada Server",
"otlDesc": "Buat tautan sekali pakai singkat",
"permanent": "Permanen",
"createdOn": "Dibuat pada ",
"lastSeen": "Terakhir terlihat pada ",
"totalDownload": "Total Unduhan: ",
"totalUpload": "Total Unggahan: ",
"newClient": "Klien Baru",
"disableClient": "Nonaktifkan Klien",
"enableClient": "Aktifkan Klien",
"noPrivKey": "Klien ini tidak memiliki kunci pribadi (private key) yang diketahui. Tidak dapat membuat konfigurasi.",
"showQR": "Tampilkan Kode QR",
"downloadConfig": "Unduh Konfigurasi",
"allowedIpsDesc": "IP mana yang akan dialihkan melalui VPN (menggantikan konfigurasi global)",
"serverAllowedIpsDesc": "IP mana yang akan dialihkan server ke klien",
"mtuDesc": "Menetapkan unit transmisi maksimum (ukuran paket) untuk terowongan VPN",
"persistentKeepaliveDesc": "Menetapkan interval (dalam detik) untuk paket keep-alive. 0 menonaktifkannya.",
"hooks": "Hooks",
"hooksDescription": "Hooks hanya berfungsi dengan wg-quick",
"hooksLeaveEmpty": "Hanya untuk wg-quick. Jika tidak, biarkan kosong.",
"dnsDesc": "Server DNS yang akan digunakan klien (menggantikan konfigurasi global)",
"notConnected": "Klien tidak terhubung",
"endpoint": "Titik Akhir (Endpoint)",
"endpointDesc": "IP klien dari mana koneksi WireGuard dibuat"
},
"dialog": {
"change": "Ubah",
"cancel": "Batal",
"create": "Buat"
},
"toast": {
"success": "Berhasil",
"saved": "Tersimpan",
"error": "Kesalahan"
},
"form": {
"actions": "Tindakan",
"save": "Simpan",
"revert": "Kembalikan",
"sectionGeneral": "Umum",
"sectionAdvanced": "Lanjutan",
"noItems": "Tidak ada item",
"nullNoItems": "Tidak ada item. Menggunakan konfigurasi global",
"add": "Tambah"
},
"admin": {
"general": {
"sessionTimeout": "Waktu Sesi Habis",
"sessionTimeoutDesc": "Durasi sesi untuk Ingat Saya (dalam detik)",
"metrics": "Metrik",
"metricsPassword": "Kata Sandi",
"metricsPasswordDesc": "Kata sandi Bearer untuk endpoint metrik (kata sandi atau hash argon2)",
"json": "JSON",
"jsonDesc": "Rute untuk metrik dalam format JSON",
"prometheus": "Prometheus",
"prometheusDesc": "Rute untuk metrik Prometheus"
},
"config": {
"connection": "Koneksi",
"hostDesc": "Hostname publik yang akan digunakan klien untuk terhubung (membatalkan konfigurasi)",
"portDesc": "Port UDP publik yang akan digunakan klien untuk terhubung (membatalkan konfigurasi, anda mungkin ingin mengubah Port Antarmuka juga)",
"allowedIpsDesc": "IP yang diizinkan untuk digunakan klien (konfigurasi global)",
"dnsDesc": "Server DNS yang akan digunakan klien (konfigurasi global)",
"mtuDesc": "MTU yang akan digunakan klien (hanya untuk klien baru)",
"persistentKeepaliveDesc": "Interval dalam detik untuk mengirim keepalive ke server. 0 = dinonaktifkan (hanya untuk klien baru)",
"suggest": "Menyarankan",
"suggestDesc": "Pilih alamat IP atau hostname untuk kolom Host"
},
"interface": {
"cidrSuccess": "CIDR diperbarui",
"device": "Perangkat",
"deviceDesc": "Perangkat Ethernet tempat lalu lintas WireGuard harus diteruskan",
"mtuDesc": "MTU yang akan digunakan oleh WireGuard",
"portDesc": "Port UDP yang akan didengarkan oleh WireGuard (Anda mungkin ingin mengubah Port Konfigurasi juga)",
"changeCidr": "Ubah CIDR",
"restart": "Mulai Ulang Antarmuka",
"restartDesc": "Mulai ulang antarmuka WireGuard",
"restartWarn": "Apakah Anda yakin ingin memulai ulang antarmuka? Ini akan membuat semua klien menjadi terputus.",
"restartSuccess": "Antarmuka telah dimulai ulang."
},
"introText": "Selamat datang di panel admin.\n\nDi sini Anda dapat mengelola pengaturan umum, konfigurasi, pengaturan antarmuka, dan hooks.\n\nMulailah dengan memilih salah satu bagian di bilah samping."
},
"zod": {
"generic": {
"required": "{0} diperlukan",
"validNumber": "{0} harus berupa angka yang valid",
"validString": "{0} harus berupa string yang valid",
"validBoolean": "{0} harus berupa boolean yang valid",
"validArray": "{0} harus berupa array yang valid",
"stringMin": "{0} harus memiliki setidaknya {1} karakter",
"numberMin": "{0} harus minimal {1}"
},
"client": {
"id": "ID Klien",
"name": "Nama",
"expiresAt": "Berakhir pada",
"address4": "Alamat IPv4",
"address6": "Alamat IPv6",
"serverAllowedIps": "IP yang diizinkan untuk Server"
},
"user": {
"username": "Nama Pengguna",
"password": "Kata Sandi",
"remember": "Ingat",
"name": "Nama",
"email": "Email",
"emailInvalid": "Harus berupa email yang valid",
"passwordMatch": "Kata sandi harus cocok",
"totpEnable": "Aktifkan TOTP",
"totpEnableTrue": "Aktifkan TOTP harus bernilai true",
"totpCode": "Kode TOTP"
},
"userConfig": {
"host": "Host"
},
"general": {
"sessionTimeout": "Waktu Sesi Habis",
"metricsEnabled": "Metrik",
"metricsPassword": "Kata Sandi Metrik"
},
"interface": {
"cidr": "CIDR",
"device": "Perangkat",
"cidrValid": "CIDR harus valid"
},
"otl": "Tautan Sekali Pakai",
"stringMalformed": "String tidak terformat dengan benar",
"body": "Body harus berupa objek yang valid",
"hook": "Hook",
"enabled": "Diaktifkan",
"mtu": "MTU",
"port": "Port",
"persistentKeepalive": "Keepalive Persisten",
"address": "Alamat IP",
"dns": "DNS",
"allowedIps": "IP yang diizinkan",
"file": "Berkas"
},
"hooks": {
"preUp": "PreUp",
"postUp": "PostUp",
"preDown": "PreDown",
"postDown": "PostDown"
}
}
+240
View File
@@ -0,0 +1,240 @@
{
"pages": {
"me": "Account",
"clients": "Client",
"admin": {
"panel": "Pannello di Amministrazione",
"general": "Generale",
"config": "Configurazione",
"interface": "Interfaccia",
"hooks": "Hooks"
}
},
"user": {
"email": "E-Mail"
},
"me": {
"currentPassword": "Password attuale",
"enable2fa": "Abilita Autenticazione a Due Fattori",
"enable2faDesc": "Scansiona il codice QR con la tua app di autenticazione o inserisci manualmente la chiave.",
"2faKey": "Chiave TOTP",
"2faCodeDesc": "Inserisci il codice generato dalla tua app di autenticazione.",
"disable2fa": "Disabilita Autenticazione a Due Fattori",
"disable2faDesc": "Inserisci la tua password per disabilitare lAutenticazione a Due Fattori."
},
"general": {
"name": "Nome",
"username": "Nome utente",
"password": "Password",
"newPassword": "Nuova Password",
"updatePassword": "Aggiorna Password",
"mtu": "MTU",
"allowedIps": "IP consentiti",
"dns": "DNS",
"persistentKeepalive": "Keepalive Persistente",
"logout": "Esci",
"continue": "Continua",
"host": "Host",
"port": "Porta",
"yes": "Sì",
"no": "No",
"confirmPassword": "Conferma Password",
"loading": "Caricamento...",
"2fa": "Autenticazione a Due Fattori",
"2faCode": "Codice TOTP"
},
"setup": {
"welcome": "Benvenuto alla tua prima configurazione di wg-easy",
"welcomeDesc": "Hai trovato il modo più semplice per installare e gestire WireGuard su qualsiasi host Linux",
"existingSetup": "Hai già una configurazione esistente?",
"createAdminDesc": "Inserisci prima un nome utente admin e una password forte e sicura. Queste informazioni verranno usate per accedere al pannello di amministrazione.",
"setupConfigDesc": "Inserisci le informazioni su host e porta. Saranno usate per la configurazione dei client quando imposteranno WireGuard sui loro dispositivi.",
"setupMigrationDesc": "Fornisci il file di backup se vuoi migrare i tuoi dati dalla precedente versione di wg-easy alla nuova installazione.",
"upload": "Carica",
"migration": "Ripristina backup:",
"createAccount": "Crea Account",
"successful": "Configurazione completata con successo",
"hostDesc": "Nome host pubblico a cui i client si connetteranno",
"portDesc": "Porta UDP pubblica a cui i client si connetteranno e su cui WireGuard resterà in ascolto"
},
"update": {
"updateAvailable": "È disponibile un aggiornamento!",
"update": "Aggiorna"
},
"theme": {
"dark": "Tema scuro",
"light": "Tema chiaro",
"system": "Tema di sistema"
},
"layout": {
"toggleCharts": "Mostra/nascondi Grafici",
"donate": "Dona"
},
"login": {
"signIn": "Accedi",
"rememberMe": "Ricordami",
"rememberMeDesc": "Rimani connesso dopo aver chiuso il browser",
"insecure": "Non puoi accedere con una connessione non sicura. Usa HTTPS.",
"2faRequired": "È richiesta lAutenticazione a Due Fattori",
"2faWrong": "Codice di Autenticazione a Due Fattori errato"
},
"client": {
"empty": "Non ci sono ancora client.",
"newShort": "Nuovo",
"sort": "Ordina",
"create": "Crea Client",
"created": "Client creato",
"new": "Nuovo Client",
"name": "Nome",
"expireDate": "Data di Scadenza",
"expireDateDesc": "Data in cui il client verrà disabilitato. Lascia vuoto per permanente",
"deleteClient": "Elimina Client",
"deleteDialog1": "Sei sicuro di voler eliminare",
"deleteDialog2": "Questa azione non può essere annullata.",
"enabled": "Abilitato",
"address": "Indirizzo",
"serverAllowedIps": "IP consentiti dal Server",
"otlDesc": "Genera link temporaneo monouso",
"permanent": "Permanente",
"createdOn": "Creato il ",
"lastSeen": "Ultima connessione il ",
"totalDownload": "Download Totale: ",
"totalUpload": "Upload Totale: ",
"newClient": "Nuovo Client",
"disableClient": "Disabilita Client",
"enableClient": "Abilita Client",
"noPrivKey": "Questo client non ha una chiave privata nota. Impossibile creare la configurazione.",
"showQR": "Mostra Codice QR",
"downloadConfig": "Scarica Configurazione",
"allowedIpsDesc": "Quali IP verranno instradati attraverso la VPN (sovrascrive la config globale)",
"serverAllowedIpsDesc": "Quali IP il server instraderà al client",
"mtuDesc": "Imposta la dimensione massima dei pacchetti (MTU) per il tunnel VPN",
"persistentKeepaliveDesc": "Imposta lintervallo (in secondi) dei pacchetti keep-alive. 0 lo disabilita",
"hooks": "Hooks",
"hooksDescription": "Gli hooks funzionano solo con wg-quick",
"hooksLeaveEmpty": "Solo per wg-quick. Altrimenti lascia vuoto",
"dnsDesc": "Server DNS che i client useranno (sovrascrive la config globale)",
"notConnected": "Client non connesso",
"endpoint": "Endpoint",
"endpointDesc": "IP del client da cui viene stabilita la connessione WireGuard"
},
"dialog": {
"change": "Modifica",
"cancel": "Annulla",
"create": "Crea"
},
"toast": {
"success": "Operazione riuscita",
"saved": "Salvato",
"error": "Errore"
},
"form": {
"actions": "Azioni",
"save": "Salva",
"revert": "Annulla modifiche",
"sectionGeneral": "Generale",
"sectionAdvanced": "Avanzate",
"noItems": "Nessun elemento",
"nullNoItems": "Nessun elemento. Uso configurazione globale",
"add": "Aggiungi"
},
"admin": {
"general": {
"sessionTimeout": "Timeout Sessione",
"sessionTimeoutDesc": "Durata della sessione per 'Ricordami' (in secondi)",
"metrics": "Metriche",
"metricsPassword": "Password",
"metricsPasswordDesc": "Password Bearer per lendpoint metriche (password o hash argon2)",
"json": "JSON",
"jsonDesc": "Percorso per metriche in formato JSON",
"prometheus": "Prometheus",
"prometheusDesc": "Percorso per metriche Prometheus"
},
"config": {
"connection": "Connessione",
"hostDesc": "Nome host pubblico a cui i client si connetteranno (invalida la config)",
"portDesc": "Porta UDP pubblica a cui i client si connetteranno (invalida la config, probabilmente vuoi cambiare anche la Porta Interfaccia)",
"allowedIpsDesc": "IP consentiti che i client useranno (config globale)",
"dnsDesc": "Server DNS che i client useranno (config globale)",
"mtuDesc": "MTU usata dai client (solo per i nuovi client)",
"persistentKeepaliveDesc": "Intervallo in secondi per inviare keepalive al server. 0 = disabilitato (solo per nuovi client)",
"suggest": "Suggerisci",
"suggestDesc": "Scegli un indirizzo IP o un Hostname per il campo Host"
},
"interface": {
"cidrSuccess": "CIDR modificato",
"device": "Dispositivo",
"deviceDesc": "Dispositivo di rete attraverso cui instradare il traffico WireGuard",
"mtuDesc": "MTU usata da WireGuard",
"portDesc": "Porta UDP su cui WireGuard resterà in ascolto (probabilmente vuoi cambiare anche la Porta Config)",
"changeCidr": "Modifica CIDR",
"restart": "Riavvia Interfaccia",
"restartDesc": "Riavvia linterfaccia WireGuard",
"restartWarn": "Sei sicuro di riavviare linterfaccia? Tutti i client verranno disconnessi.",
"restartSuccess": "Interfaccia riavviata"
},
"introText": "Benvenuto nel pannello di amministrazione.\n\nQui puoi gestire le impostazioni generali, la configurazione, le impostazioni dellinterfaccia e gli hooks.\n\nInizia scegliendo una delle sezioni nella barra laterale."
},
"zod": {
"generic": {
"required": "{0} è obbligatorio",
"validNumber": "{0} deve essere un numero valido",
"validString": "{0} deve essere una stringa valida",
"validBoolean": "{0} deve essere un valore booleano valido",
"validArray": "{0} deve essere un array valido",
"stringMin": "{0} deve contenere almeno {1} carattere",
"numberMin": "{0} deve essere almeno {1}"
},
"client": {
"id": "ID Client",
"name": "Nome",
"expiresAt": "Scadenza",
"address4": "Indirizzo IPv4",
"address6": "Indirizzo IPv6",
"serverAllowedIps": "IP consentiti dal Server"
},
"user": {
"username": "Nome utente",
"password": "Password",
"remember": "Ricorda",
"name": "Nome",
"email": "Email",
"emailInvalid": "Email deve essere un indirizzo valido",
"passwordMatch": "Le password devono coincidere",
"totpEnable": "Abilitazione TOTP",
"totpEnableTrue": "TOTP deve essere abilitato",
"totpCode": "Codice TOTP"
},
"userConfig": {
"host": "Host"
},
"general": {
"sessionTimeout": "Timeout Sessione",
"metricsEnabled": "Metriche",
"metricsPassword": "Password Metriche"
},
"interface": {
"cidr": "CIDR",
"device": "Dispositivo",
"cidrValid": "CIDR deve essere valido"
},
"otl": "Link Monouso",
"stringMalformed": "Stringa non valida",
"body": "Body deve essere un oggetto valido",
"hook": "Hook",
"enabled": "Abilitato",
"mtu": "MTU",
"port": "Porta",
"persistentKeepalive": "Keepalive Persistente",
"address": "Indirizzo IP",
"dns": "DNS",
"allowedIps": "IP consentiti",
"file": "File"
},
"hooks": {
"preUp": "PreUp",
"postUp": "PostUp",
"preDown": "PreDown",
"postDown": "PostDown"
}
}
+240
View File
@@ -0,0 +1,240 @@
{
"pages": {
"me": "계정",
"clients": "클라이언트",
"admin": {
"panel": "관리 패널",
"general": "일반",
"config": "구성",
"interface": "인터페이스",
"hooks": "후크"
}
},
"user": {
"email": "이메일"
},
"me": {
"currentPassword": "현재 비밀번호",
"enable2fa": "2단계 인증 활성화",
"enable2faDesc": "인증 앱으로 QR 코드를 스캔하거나 키를 수동으로 입력하세요.",
"2faKey": "TOTP 키",
"2faCodeDesc": "인증기 앱에서 코드를 입력하십시오.",
"disable2fa": "2단계 인증 비활성화",
"disable2faDesc": "2단계 인증을 비활성화하려면 비밀번호를 입력하세요."
},
"general": {
"name": "이름",
"username": "사용자 이름",
"password": "비밀번호",
"newPassword": "새 비밀번호",
"updatePassword": "비밀번호 업데이트",
"mtu": "MTU",
"allowedIps": "허용된 IP",
"dns": "DNS",
"persistentKeepalive": "지속적인 유지",
"logout": "로그아웃",
"continue": "계속",
"host": "호스트",
"port": "포트",
"yes": "예",
"no": "아니요",
"confirmPassword": "비밀번호 확인",
"loading": "로딩 중...",
"2fa": "2단계 인증",
"2faCode": "TOTP 코드"
},
"setup": {
"welcome": "wg-easy의 첫 번째 설정에 오신 것을 환영합니다.",
"welcomeDesc": "모든 Linux 호스트에서 WireGuard를 설치하고 관리하는 가장 쉬운 방법을 찾았습니다",
"existingSetup": "기존 설정이 있습니까?",
"createAdminDesc": "먼저 관리자 사용자 이름과 강력한 보안 비밀번호를 입력하십시오. 이 정보는 관리 패널에 로그인하는 데 사용됩니다.",
"setupConfigDesc": "호스트 및 포트 정보를 입력하십시오. 이는 장치에서 WireGuard를 설정할 때 클라이언트 구성에 사용됩니다.",
"setupMigrationDesc": "이전 wg-easy 버전에서 새 설정으로 데이터를 마이그레이션하려면 백업 파일을 제공하십시오.",
"upload": "업로드",
"migration": "백업 복원:",
"createAccount": "계정 생성",
"successful": "설정 성공",
"hostDesc": "클라이언트가 연결할 공개 호스트 이름",
"portDesc": "클라이언트가 연결할 공용 UDP 포트 및 WireGuard가 수신 대기할 포트"
},
"update": {
"updateAvailable": "업데이트가 가능합니다!",
"update": "업데이트"
},
"theme": {
"dark": "어두운 테마",
"light": "라이트 테마",
"system": "시스템 테마"
},
"layout": {
"toggleCharts": "차트 표시/숨기기",
"donate": "기부"
},
"login": {
"signIn": "로그인",
"rememberMe": "로그인 상태 유지",
"rememberMeDesc": "브라우저를 닫은 후에도 로그인 유지",
"insecure": "안전하지 않은 연결로 로그인할 수 없습니다. HTTPS를 사용하세요.",
"2faRequired": "2단계 인증이 필요합니다",
"2faWrong": "2단계 인증이 잘못되었습니다"
},
"client": {
"empty": "아직 클라이언트가 없습니다.",
"newShort": "새로 만들기",
"sort": "정렬",
"create": "클라이언트 생성",
"created": "클라이언트 생성됨",
"new": "새 클라이언트",
"name": "이름",
"expireDate": "만료 날짜",
"expireDateDesc": "클라이언트가 비활성화될 날짜. 영구적으로 비워두기",
"deleteClient": "클라이언트 삭제",
"deleteDialog1": "정말로 삭제하시겠습니까",
"deleteDialog2": "이 작업은 실행 취소할 수 없습니다.",
"enabled": "활성화됨",
"address": "주소",
"serverAllowedIps": "서버 허용된 IP",
"otlDesc": "짧은 일회성 링크 생성",
"permanent": "영구적",
"createdOn": "생성일 ",
"lastSeen": "마지막으로 본 시간 ",
"totalDownload": "총 다운로드: ",
"totalUpload": "총 업로드: ",
"newClient": "새 클라이언트",
"disableClient": "클라이언트 비활성화",
"enableClient": "클라이언트 활성화",
"noPrivKey": "이 클라이언트는 알려진 개인 키가 없습니다. 구성을 생성할 수 없습니다.",
"showQR": "QR 코드 표시",
"downloadConfig": "구성 다운로드",
"allowedIpsDesc": "VPN을 통해 라우팅될 IP(전역 구성 재정의)",
"serverAllowedIpsDesc": "서버가 클라이언트로 라우팅할 IPs",
"mtuDesc": "VPN 터널의 최대 전송 단위(패킷 크기)를 설정합니다",
"persistentKeepaliveDesc": "유지 관리 패킷의 간격(초 단위)을 설정합니다. 0은 비활성화합니다.",
"hooks": "후크",
"hooksDescription": "후크는 wg-quick과만 작동합니다",
"hooksLeaveEmpty": "wg-quick 전용입니다. 그렇지 않으면 비워 두십시오.",
"dnsDesc": "클라이언트가 사용할 DNS 서버(전역 구성 무시)",
"notConnected": "클라이언트가 연결되지 않음",
"endpoint": "엔드포인트",
"endpointDesc": "WireGuard에 연결된 클라이언트의 IP 주소"
},
"dialog": {
"change": "변경",
"cancel": "취소",
"create": "생성"
},
"toast": {
"success": "성공",
"saved": "저장됨",
"error": "오류"
},
"form": {
"actions": "작업",
"save": "저장",
"revert": "되돌리기",
"sectionGeneral": "일반",
"sectionAdvanced": "고급",
"noItems": "항목 없음",
"nullNoItems": "항목이 없습니다. 전역 구성 사용 중",
"add": "추가"
},
"admin": {
"general": {
"sessionTimeout": "세션 타임아웃",
"sessionTimeoutDesc": "기억하기 위한 세션 지속 시간(초)",
"metrics": "메트릭",
"metricsPassword": "비밀번호",
"metricsPasswordDesc": "메트릭 엔드포인트에 대한 베어러 비밀번호(비밀번호 또는 argon2 해시)",
"json": "JSON",
"jsonDesc": "JSON 형식의 메트릭 경로",
"prometheus": "프로메테우스",
"prometheusDesc": "Prometheus 메트릭을 위한 경로"
},
"config": {
"connection": "연결",
"hostDesc": "클라이언트가 연결할 공용 호스트 이름(구성 무효화)",
"portDesc": "공용 UDP 포트 클라이언트가 연결할 (구성을 무효화하며, 인터페이스 포트도 변경하는 것이 좋습니다)",
"allowedIpsDesc": "클라이언트가 사용할 수 있는 허용된 IP(전역 설정)",
"dnsDesc": "클라이언트가 사용할 DNS 서버(전역 설정)",
"mtuDesc": "MTU 클라이언트가 사용할 (신규 클라이언트 전용)",
"persistentKeepaliveDesc": "서버에 유지 신호를 보내기 위한 간격(초). 0 = 비활성화(새 클라이언트 전용)",
"suggest": "제안",
"suggestDesc": "호스트 필드에 사용할 IP 주소 또는 호스트 이름을 선택하세요."
},
"interface": {
"cidrSuccess": "CIDR가 변경되었습니다.",
"device": "장치",
"deviceDesc": "WireGuard 트래픽이 전달되어야 하는 이더넷 장치",
"mtuDesc": "MTU WireGuard가 사용할 값",
"portDesc": "WireGuard가 수신할 UDP 포트 (구성 포트도 변경하는 것이 좋습니다)",
"changeCidr": "CIDR 변경",
"restart": "인터페이스 재시작",
"restartDesc": "WireGuard 인터페이스를 재시작합니다.",
"restartWarn": "인터페이스를 재시작하시겠습니까? 이 작업은 모든 클라이언트를 연결 해제합니다.",
"restartSuccess": "인터페이스가 재시작되었습니다"
},
"introText": "관리 패널에 오신 것을 환영합니다.\n\n여기에서 일반 설정, 구성, 인터페이스 설정 및 후크를 관리할 수 있습니다.\n\n사이드바에서 섹션 중 하나를 선택하여 시작하세요."
},
"zod": {
"generic": {
"required": "{0}은(는) 필수입니다.",
"validNumber": "{0}은(는) 유효한 숫자여야 합니다.",
"validString": "{0}은 유효한 문자열이어야 합니다",
"validBoolean": "{0}은(는) 유효한 불리언이어야 합니다.",
"validArray": "{0}는 유효한 배열이어야 합니다",
"stringMin": "{0}은(는) 최소 {1}자 이상이어야 합니다.",
"numberMin": "{0}은(는) 최소 {1} 이상이어야 합니다."
},
"client": {
"id": "클라이언트 ID",
"name": "이름",
"expiresAt": "만료 시간",
"address4": "IPv4 주소",
"address6": "IPv6 주소",
"serverAllowedIps": "서버 허용된 IP"
},
"user": {
"username": "사용자 이름",
"password": "비밀번호",
"remember": "기억하기",
"name": "이름",
"email": "이메일",
"emailInvalid": "이메일은 유효한 이메일이어야 합니다.",
"passwordMatch": "비밀번호가 일치해야 합니다",
"totpEnable": "TOTP 활성화",
"totpEnableTrue": "TOTP 사용은 true여야 합니다.",
"totpCode": "TOTP 코드"
},
"userConfig": {
"host": "호스트"
},
"general": {
"sessionTimeout": "세션 타임아웃",
"metricsEnabled": "메트릭",
"metricsPassword": "메트릭 비밀번호"
},
"interface": {
"cidr": "CIDR",
"device": "장치",
"cidrValid": "CIDR는 유효해야 합니다."
},
"otl": "일회성 링크",
"stringMalformed": "문자열이 잘못되었습니다.",
"body": "본문은 유효한 객체여야 합니다",
"hook": "후크",
"enabled": "활성화됨",
"mtu": "MTU",
"port": "포트",
"persistentKeepalive": "지속적인 유지",
"address": "IP 주소",
"dns": "DNS",
"allowedIps": "허용된 IP",
"file": "파일"
},
"hooks": {
"preUp": "PreUp",
"postUp": "PostUp",
"preDown": "PreDown",
"postDown": "PostDown"
}
}
+286
View File
@@ -0,0 +1,286 @@
{
"pages": {
"me": "Konto",
"clients": "Klienter",
"admin": {
"panel": "Adminpanel",
"general": "Generelt",
"config": "Oppsett",
"interface": "Grensesnitt",
"hooks": "Hooks"
}
},
"user": {
"email": "E-post"
},
"me": {
"currentPassword": "Nåværende passord",
"enable2fa": "Aktiver tofaktorautentisering",
"enable2faDesc": "Skann QR-koden med autentiseringsappen din eller skriv inn nøkkelen manuelt.",
"2faKey": "TOTP-nøkkel",
"2faCodeDesc": "Skriv inn koden fra autentiseringsappen din.",
"disable2fa": "Deaktiver tofaktorautentisering",
"disable2faDesc": "Skriv inn passordet ditt for å deaktivere tofaktorautentisering."
},
"general": {
"name": "Navn",
"username": "Brukernavn",
"password": "Passord",
"newPassword": "Nytt passord",
"updatePassword": "Oppdater passord",
"mtu": "MTU",
"allowedIps": "Tillatte IP-er",
"dns": "DNS",
"persistentKeepalive": "Vedvarende keepalive",
"logout": "Logg ut",
"continue": "Fortsett",
"host": "Vert",
"port": "Port",
"yes": "Ja",
"no": "Nei",
"confirmPassword": "Bekreft passord",
"loading": "Laster...",
"2fa": "Tofaktorautentisering",
"2faCode": "TOTP-kode"
},
"setup": {
"welcome": "Velkommen til ditt oppsett av wg-easy",
"welcomeDesc": "Du har funnet den enkleste måten å installere og administrere WireGuard på en hvilken som helst Linux-vert",
"existingSetup": "Har du et eksisterende oppsett?",
"createAdminDesc": "Skriv først inn et adminbrukernavn og et sterkt, sikkert passord. Denne informasjonen brukes til å logge inn i administrasjonspanelet.",
"setupConfigDesc": "Skriv inn vert- og portinformasjon. Dette brukes til klientkonfigurasjonen når du setter opp WireGuard på enhetene deres.",
"setupMigrationDesc": "Oppgi sikkerhetskopifilen hvis du vil migrere dataene dine fra forrige wg-easy-versjon til det nye oppsettet.",
"upload": "Last opp",
"migration": "Gjenopprett sikkerhetskopien:",
"createAccount": "Opprett konto",
"successful": "Oppsett vellykket",
"hostDesc": "Offentlig vertsnavn klienter vil koble seg til",
"portDesc": "Offentlig UDP-port klienter vil koble til og WireGuard vil lytte på"
},
"update": {
"updateAvailable": "En oppdatering er tilgjengelig!",
"update": "Oppdater"
},
"theme": {
"dark": "Mørkt tema",
"light": "Lyst tema",
"system": "Systemtema"
},
"layout": {
"toggleCharts": "Vis/skjul diagrammer",
"donate": "Doner"
},
"login": {
"signIn": "Logg inn",
"rememberMe": "Husk meg",
"rememberMeDesc": "Hold deg innlogget etter at nettleseren lukkes",
"insecure": "Du kan ikke logge inn med en usikker tilkobling. Bruk HTTPS.",
"2faRequired": "Tofaktorautentisering er påkrevd",
"2faWrong": "Tofaktorautentisering er feil"
},
"client": {
"empty": "Det finnes ingen klienter ennå.",
"newShort": "Ny",
"sort": "Sorter",
"create": "Opprett klient",
"created": "Klient opprettet",
"new": "Ny klient",
"name": "Navn",
"expireDate": "Utløpsdato",
"expireDateDesc": "Datoen klienten blir deaktivert. Tomt for permanent",
"delete": "Slett",
"deleteClient": "Slett klient",
"deleteDialog1": "Er du sikker på at du vil slette",
"deleteDialog2": "Denne handlingen kan ikke angres.",
"enabled": "Aktivert",
"address": "Adresse",
"serverAllowedIps": "Server tillatte IP-er",
"otlDesc": "Generer kort engangslenke",
"permanent": "Permanent",
"createdOn": "Opprettet ",
"lastSeen": "Sist sett ",
"totalDownload": "Totalt nedlastet: ",
"totalUpload": "Totalt opplastet: ",
"newClient": "Ny klient",
"disableClient": "Deaktiver klient",
"enableClient": "Aktiver klient",
"noPrivKey": "Denne klienten har ingen kjent privat nøkkel. Kan ikke opprette konfigurasjon.",
"showQR": "Vis QR-kode",
"downloadConfig": "Last ned konfigurasjon",
"allowedIpsDesc": "Hvilke IP-er som rutes gjennom VPN (overstyrer global konfig)",
"serverAllowedIpsDesc": "Hvilke IP-er serveren ruter til klienten",
"mtuDesc": "Setter maksimal overføringsenhet (pakkestørrelse) for VPN-tunnelen",
"persistentKeepaliveDesc": "Setter intervallet (i sekunder) for keepalive-pakker. 0 deaktiverer det",
"hooks": "Hooks",
"hooksDescription": "Hooks fungerer bare med wg-quick",
"hooksLeaveEmpty": "Kun for wg-quick. Ellers la det være tomt",
"dnsDesc": "DNS-server klienter vil bruke (overstyrer global konfig)",
"notConnected": "Klient ikke tilkoblet",
"endpoint": "Endepunkt",
"endpointDesc": "IP-en til klienten som WireGuard-tilkoblingen etableres fra",
"search": "Søk etter klienter...",
"config": "Konfigurasjon",
"viewConfig": "Vis konfigurasjon"
},
"dialog": {
"change": "Endre",
"cancel": "Avbryt",
"create": "Opprett"
},
"toast": {
"success": "Vellykket",
"saved": "Lagret",
"error": "Feil"
},
"form": {
"actions": "Handlinger",
"save": "Lagre",
"revert": "Tilbakestill",
"sectionGeneral": "Generelt",
"sectionAdvanced": "Avansert",
"noItems": "Ingen elementer",
"nullNoItems": "Ingen elementer. Bruker global konfig",
"add": "Legg til"
},
"admin": {
"general": {
"sessionTimeout": "Øktutløp",
"sessionTimeoutDesc": "Øktvarighet for Husk meg (sekunder)",
"metrics": "Målinger",
"metricsPassword": "Passord",
"metricsPasswordDesc": "Bearer-passord for metrics-endepunktet (passord eller argon2-hash)",
"json": "JSON",
"jsonDesc": "Rute for metrics i JSON-format",
"prometheus": "Prometheus",
"prometheusDesc": "Rute for Prometheus-målinger"
},
"config": {
"connection": "Tilkobling",
"hostDesc": "Offentlig vertsnavn klienter vil koble til (ugyldiggjør konfig)",
"portDesc": "Offentlig UDP-port klienter vil koble til (ugyldiggjør konfig, du vil sannsynligvis også endre Grensesnitt-port)",
"allowedIpsDesc": "Tillatte IP-er klienter vil bruke (global konfig)",
"dnsDesc": "DNS-server klienter vil bruke (global konfig)",
"mtuDesc": "MTU klienter vil bruke (kun for nye klienter)",
"persistentKeepaliveDesc": "Intervall i sekunder for å sende keepalives til serveren. 0 = deaktivert (kun for nye klienter)",
"suggest": "Foreslå",
"suggestDesc": "Velg en IP-adresse eller et vertsnavn for Vert-feltet"
},
"interface": {
"cidrSuccess": "CIDR endret",
"device": "Enhet",
"deviceDesc": "Ethernet-enhet som WireGuard-trafikken skal videresendes gjennom",
"mtuDesc": "MTU WireGuard vil bruke",
"portDesc": "UDP-port WireGuard vil lytte på (du vil sannsynligvis også endre Konfig-port)",
"changeCidr": "Endre CIDR",
"restart": "Start grensesnitt på nytt",
"restartDesc": "Start WireGuard-grensesnittet på nytt",
"restartWarn": "Er du sikker på at du vil starte grensesnittet på nytt? Dette vil koble fra alle klienter.",
"restartSuccess": "Grensesnitt startet på nytt"
},
"introText": "Velkommen til adminpanelet.\n\nHer kan du administrere de generelle innstillingene, konfigurasjonen, grensesnittinnstillingene og hooks.\n\nStart med å velge en av seksjonene i sidepanelet."
},
"zod": {
"generic": {
"required": "{0} er påkrevd",
"validNumber": "{0} må være et gyldig tall",
"validString": "{0} må være en gyldig streng",
"validBoolean": "{0} må være en gyldig boolsk verdi",
"validArray": "{0} må være en gyldig liste",
"stringMin": "{0} må være minst {1} tegn",
"numberMin": "{0} må være minst {1}"
},
"client": {
"id": "Klient-ID",
"name": "Navn",
"expiresAt": "Utløper",
"address4": "IPv4-adresse",
"address6": "IPv6-adresse",
"serverAllowedIps": "Server tillatte IP-er"
},
"user": {
"username": "Brukernavn",
"password": "Passord",
"remember": "Husk",
"name": "Navn",
"email": "E-post",
"emailInvalid": "E-post må være en gyldig e-postadresse",
"passwordMatch": "Passord må være like",
"totpEnable": "TOTP aktivert",
"totpEnableTrue": "TOTP aktivert må være sant",
"totpCode": "TOTP-kode"
},
"userConfig": {
"host": "Vert"
},
"general": {
"sessionTimeout": "Øktutløp",
"metricsEnabled": "Målinger",
"metricsPassword": "Målingspassord"
},
"interface": {
"cidr": "CIDR",
"device": "Enhet",
"cidrValid": "CIDR må være gyldig"
},
"otl": "Engangslenke",
"stringMalformed": "Strengen er ugyldig",
"body": "Innholdet må være et gyldig objekt",
"hook": "Hook",
"enabled": "Aktivert",
"mtu": "MTU",
"port": "Port",
"persistentKeepalive": "Vedvarende keepalive",
"address": "IP-adresse",
"dns": "DNS",
"allowedIps": "Tillatte IP-er",
"file": "Fil"
},
"hooks": {
"preUp": "PreUp",
"postUp": "PostUp",
"preDown": "PreDown",
"postDown": "PostDown"
},
"copy": {
"notSupported": "Kopiering støttes ikke",
"copied": "Kopiert!",
"failed": "Kopiering mislyktes",
"copy": "Kopier"
},
"awg": {
"jCLabel": "Antall junk-pakker (Jc)",
"jCDescription": "Antall junk-pakker som skal sendes (1-128, anbefalt: 4-12)",
"jMinLabel": "Min. størrelse på junk-pakker (Jmin)",
"jMinDescription": "Minimum størrelse på junk-pakker (0-1279*, anbefalt: 8, må være < Jmax)",
"jMaxLabel": "Maks. størrelse på junk-pakker (Jmax)",
"jMaxDescription": "Maksimal størrelse på junk-pakker (1-1280*, anbefalt: 80, må være > Jmin)",
"s1Label": "Init-pakke junk-størrelse (S1)",
"s1Description": "Init-pakke junk-størrelse (0-1132[1280* - 148 = 1132], anbefalt: 15-150, S1+56 ≠ S2)",
"s2Label": "Svarpakke junk-størrelse (S2)",
"s2Description": "Svarpakke junk-størrelse (0-1188[1280* - 92 = 1188], anbefalt: 15-150)",
"s3Label": "Cookie-svarpakke junk-størrelse (S3)",
"s3Description": "Cookie-svarpakke junk-størrelse",
"s4Label": "Transportpakke junk-størrelse (S4)",
"s4Description": "Transportpakke junk-størrelse",
"i1Label": "Spesiell junk-pakke 1 (I1)",
"i1Description": "Protokolllignende pakke i heksformat: <b 0x...>",
"i2Label": "Spesiell junk-pakke 2 (I2)",
"i2Description": "Protokolllignende pakke i heksformat: <b 0x...>",
"i3Label": "Spesiell junk-pakke 3 (I3)",
"i3Description": "Protokolllignende pakke i heksformat: <b 0x...>",
"i4Label": "Spesiell junk-pakke 4 (I4)",
"i4Description": "Protokolllignende pakke i heksformat: <b 0x...>",
"i5Label": "Spesiell junk-pakke 5 (I5)",
"i5Description": "Protokolllignende pakke i heksformat: <b 0x...>",
"h1Label": "Init magisk header (H1)",
"h1Description": "Init-pakke header-verdi (5-2147483647, må være unik fra H2-H4)",
"h2Label": "Svar magisk header (H2)",
"h2Description": "Svarpakke header-verdi (5-2147483647, må være unik fra H1, H3, H4)",
"h3Label": "Cookie-svar magisk header (H3)",
"h3Description": "Cookie-svarpakke header-verdi (5-2147483647, må være unik fra H1, H2, H4)",
"h4Label": "Transport magisk header (H4)",
"h4Description": "Transportpakke header-verdi (5-2147483647, må være unik fra H1-H3)",
"mtuNote": "Verdier avhenger av MTU",
"obfuscationParameters": "AmneziaWG obfuskasjonsparametere"
}
}
+286
View File
@@ -0,0 +1,286 @@
{
"pages": {
"me": "Account",
"clients": "Cliënten",
"admin": {
"panel": "Admin-paneel",
"general": "Algemeen",
"config": "Config",
"interface": "Interface",
"hooks": "Hooks"
}
},
"user": {
"email": "E-mail"
},
"me": {
"currentPassword": "Huidig wachtwoord",
"enable2fa": "Twee-factor-authenticatie inschakelen",
"enable2faDesc": "Scan de QR-code met uw authenticator-app of voer de sleutel handmatig in.",
"2faKey": "TOTP-sleutel",
"2faCodeDesc": "Voer de code in van uw authenticator-app.",
"disable2fa": "Twee-factor-authenticatie uitschakelen",
"disable2faDesc": "Voer uw wachtwoord in om de twee-factor-authenticatie uit te schakelen."
},
"general": {
"name": "Naam",
"username": "Gebruikersnaam",
"password": "Wachtwoord",
"newPassword": "Nieuw wachtwoord",
"updatePassword": "Wachtwoord bijwerken",
"mtu": "MTU",
"allowedIps": "Toegestane IP's",
"dns": "DNS",
"persistentKeepalive": "Aanhoudende verbinding",
"logout": "Uitloggen",
"continue": "Doorgaan",
"host": "Host",
"port": "Port",
"yes": "Ja",
"no": "Nee",
"confirmPassword": "Wachtwoord bevestigen",
"loading": "Laden...",
"2fa": "Twee-factor-authenticatie uitschakelen",
"2faCode": "TOTP-code"
},
"setup": {
"welcome": "Welkom bij uw eerste installatie van wg-easy",
"welcomeDesc": "U hebt de gemakkelijkste manier gevonden om WireGuard op elke Linux-host te installeren en te beheren",
"existingSetup": "Heeft u een bestaande installatie?",
"createAdminDesc": "Voer eerst een beheerdersgebruikersnaam en een sterk veilig wachtwoord in. Deze gegevens worden gebruikt om in te loggen op uw beheerderspaneel.",
"setupConfigDesc": "Voer alstublieft de host- en poortinformatie in. Dit wordt gebruikt voor de clientconfiguratie bij het instellen van WireGuard op hun apparaten.",
"setupMigrationDesc": "Geef alstublieft het back-upbestand als u uw gegevens van uw vorige wg-easy-versie naar uw nieuwe installatie wilt overzetten.",
"upload": "Uploaden",
"migration": "Herstel de back-up:",
"createAccount": "Account aanmaken",
"successful": "Installatie succesvol",
"hostDesc": "Publieke hostnaam waar clients verbinding mee maken",
"portDesc": "Publieke UDP-poort waarop clients verbinding maken en waarop WireGuard luistert"
},
"update": {
"updateAvailable": "Er is een update beschikbaar!",
"update": "Bijwerken"
},
"theme": {
"dark": "Donker thema",
"light": "Licht thema",
"system": "Systeem-thema"
},
"layout": {
"toggleCharts": "Grafieken tonen/verbergen",
"donate": "Donatie"
},
"login": {
"signIn": "Inloggen",
"rememberMe": "Onthoud mij",
"rememberMeDesc": "Ingelogd blijven na het sluiten van de browser",
"insecure": "U kunt niet inloggen via een onveilige verbinding. Gebruik HTTPS.",
"2faRequired": "Twee-factor-authenticatie is vereist",
"2faWrong": "Twee-factor-authenticatiecode is fout"
},
"client": {
"empty": "Er zijn nog geen cliënten.",
"newShort": "Nieuw",
"sort": "Sortering",
"create": "Cliënt aanmaken",
"created": "Cliënt aangemaakt",
"new": "Nieuwe cliënt",
"name": "Naam",
"expireDate": "Verloopdatum",
"expireDateDesc": "Datum waarop de cliënt wordt uitgeschakeld. Laat leeg voor permanent.",
"delete": "Verwijderen",
"deleteClient": "Cliënt verwijderen",
"deleteDialog1": "Weet u zeker dat u wilt verwijderen",
"deleteDialog2": "Deze actie kan niet ongedaan worden gemaakt.",
"enabled": "Ingeschakeld",
"address": "Adres",
"serverAllowedIps": "Toegestane IP's van de server",
"otlDesc": "Korte eenmalige link genereren",
"permanent": "Permanent",
"createdOn": "Aangemaakt op ",
"lastSeen": "Laatst gezien op ",
"totalDownload": "Totaal gedownload: ",
"totalUpload": "Totaal geüpload: ",
"newClient": "Nieuwe cliënt",
"disableClient": "Cliënt uitschakelen",
"enableClient": "Cliënt inschakelen",
"noPrivKey": "Deze cliënt heeft geen bekende privésleutel. Kan de configuratie niet aanmaken.",
"showQR": "QR-code weergeven",
"downloadConfig": "Configuratie downloaden",
"allowedIpsDesc": "Welke IP's via de VPN worden geleid (overschrijft algemene instellingen)",
"serverAllowedIpsDesc": "Naar welke IP's de server het cliëntverkeer zal routeren",
"mtuDesc": "Stelt de maximale transmissie-eenheid (pakketgrootte) voor de VPN-tunnel in",
"persistentKeepaliveDesc": "Stelt het interval (seconden) in voor keep-alive-pakketten. 0 schakelt dit uit",
"hooks": "Hooks",
"hooksDescription": "Hooks functioneren alleen met wg-quick",
"hooksLeaveEmpty": "Alleen voor wg-quick. Anders leeg laten",
"dnsDesc": "DNS-serverclients zullen gebruiken (overschrijft algemene instellingen)",
"notConnected": "Cliënt niet verbonden",
"endpoint": "Eindpunt",
"endpointDesc": "IP van de cliënt vanaf welke de WireGuard-verbinding tot stand wordt gebracht",
"search": "Cliënten zoeken...",
"config": "Configuratie",
"viewConfig": "Configuratie weergeven"
},
"dialog": {
"change": "Wijzigen",
"cancel": "Annuleren",
"create": "Aanmaken"
},
"toast": {
"success": "Succes",
"saved": "Opgeslagen",
"error": "Fout"
},
"form": {
"actions": "Acties",
"save": "Opslaan",
"revert": "Terugzetten",
"sectionGeneral": "Algemeen",
"sectionAdvanced": "Geavanceerd",
"noItems": "Geen items",
"nullNoItems": "Geen items. Globale configuratie gebruiken",
"add": "Toevoegen"
},
"admin": {
"general": {
"sessionTimeout": "Sessie verlopen",
"sessionTimeoutDesc": "Sessieduur voor Onthoud mij (sec.)",
"metrics": "Metrics",
"metricsPassword": "Wachtwoord",
"metricsPasswordDesc": "Bearer-wachtwoord voor het metrics-eindpunt (wachtwoord of argon2-hash)",
"json": "JSON",
"jsonDesc": "Route voor metrics in JSON-formaat",
"prometheus": "Prometheus",
"prometheusDesc": "Route voor Prometheus-metrics"
},
"config": {
"connection": "Verbinding",
"hostDesc": "Publieke hostnaam waarmee cliënten verbinding maken (maakt configuratie ongedaan)",
"portDesc": "Publieke UDP-poort waarmee clients verbinding maken (maakt configuratie ongedaan; u dient waarschijnlijk ook de interfacepoort te wijzigen)",
"allowedIpsDesc": "Toegestane IP's die cliënten zullen gebruiken (algemene configuratie)",
"dnsDesc": "DNS-server die cliënten zullen gebruiken (algemene configuratie)",
"mtuDesc": "MTU die cliënten zullen gebruiken (alleen voor nieuwe cliënten)",
"persistentKeepaliveDesc": "Interval in seconden om keepalives naar de server te sturen. 0 = uitgeschakeld (alleen voor nieuwe cliënten)",
"suggest": "Voorstellen",
"suggestDesc": "Kies een IP-adres of hostnaam voor het veld Host"
},
"interface": {
"cidrSuccess": "CIDR gewijzigd",
"device": "Apparaat",
"deviceDesc": "Ethernet-apparaat waar het WireGuard-verkeer doorheen moet worden doorgestuurd",
"mtuDesc": "MTU die WireGuard zal toepassen",
"portDesc": "UDP-poort waarop WireGuard zal luisteren (u dient waarschijnlijk ook de Config-poort te wijzigen)",
"changeCidr": "CIDR wijzigen",
"restart": "Interface opnieuw starten",
"restartDesc": "WireGuard-interface opnieuw starten",
"restartWarn": "Weet u zeker dat u de interface wilt herstarten? Dit zal alle cliënten loskoppelen.",
"restartSuccess": "Interface opnieuw gestart"
},
"introText": "Welkom bij het Admin-paneel.\n\nHier kunt u de algemene instellingen, de configuratie, de interface-instellingen en de hooks beheren.\n\nBegin met het kiezen van een van de secties in de zijbalk."
},
"zod": {
"generic": {
"required": "{0} is vereist",
"validNumber": "{0} moet een geldig nummer zijn",
"validString": "{0} moet een geldige tekenreeks zijn",
"validBoolean": "{0} moet een geldige boolean zijn",
"validArray": "{0} moet een geldige array zijn",
"stringMin": "{0} moet minstens {1} teken bevatten",
"numberMin": "{0} moet minstens {1} zijn"
},
"client": {
"id": "Cliënt-ID",
"name": "Naam",
"expiresAt": "Verloopt op",
"address4": "IPv4-adres",
"address6": "IPv6-adres",
"serverAllowedIps": "Toegestane IP's van de server"
},
"user": {
"username": "Gebruikersnaam",
"password": "Wachtwoord",
"remember": "Onthouden",
"name": "Naam",
"email": "E-mail",
"emailInvalid": "E-mail moet een geldig e-mailadres zijn",
"passwordMatch": "Wachtwoorden moeten overeenkomen",
"totpEnable": "TOTP inschakelen",
"totpEnableTrue": "TOTP inschakelen moet waar zijn",
"totpCode": "TOTP-code"
},
"userConfig": {
"host": "Host"
},
"general": {
"sessionTimeout": "Sessie-verlooptijd",
"metricsEnabled": "Metrics",
"metricsPassword": "Metrics-wachtwoord"
},
"interface": {
"cidr": "CIDR",
"device": "Apparaat",
"cidrValid": "CIDR moet geldig zijn"
},
"otl": "Eenmalige link",
"stringMalformed": "Tekenreeks is beschadigd",
"body": "Body moet een geldig object bevatten",
"hook": "Hook",
"enabled": "Ingeschakeld",
"mtu": "MTU",
"port": "Poort",
"persistentKeepalive": "Aanhoudende verbinding",
"address": "IP-adres",
"dns": "DNS",
"allowedIps": "Toegestane IP's",
"file": "Bestand"
},
"hooks": {
"preUp": "Pre-Up",
"postUp": "Post-Up",
"preDown": "Pre-Down",
"postDown": "Post-Down"
},
"copy": {
"notSupported": "Kopiëren wordt niet ondersteund",
"copied": "Gekopieerd!",
"failed": "Kopiëren is mislukt",
"copy": "Kopiëren"
},
"awg": {
"jCLabel": "Junk packet count (Jc)",
"jCDescription": "Aantal te verzenden junk packets (1-128, aanbevolen: 4-12)",
"jMinLabel": "Junk packet min size (Jmin)",
"jMinDescription": "Minimale grootte van junk packets (0-1279*, aanbevolen: 8, moet zijn < Jmax)",
"jMaxLabel": "Junk packet max size (Jmax)",
"jMaxDescription": "Maximale grootte van junk packets (1-1280*, aanbevolen: 80, moet zijn > Jmin)",
"s1Label": "Init packet junk size (S1)",
"s1Description": "Grootte Init packet junk (0-1132[1280* - 148 = 1132], aanbevolen: 15-150, S1+56 ≠ S2)",
"s2Label": "Response packet junk size (S2)",
"s2Description": "Grootte Response packet junk (0-1188[1280* - 92 = 1188], aanbevolen: 15-150)",
"s3Label": "Cookie reply packet junk size (S3)",
"s3Description": "Grootte Cookie reply packet junk",
"s4Label": "Transport packet junk size (S4)",
"s4Description": "Grootte Transport packet junk",
"i1Label": "Special junk packet 1 (I1)",
"i1Description": "Protocol mimic packet in hex formaat: <b 0x...>",
"i2Label": "Special junk packet 2 (I2)",
"i2Description": "Protocol mimic packet in hex formaat: <b 0x...>",
"i3Label": "Special junk packet 3 (I3)",
"i3Description": "Protocol mimic packet in hex formaat: <b 0x...>",
"i4Label": "Special junk packet 4 (I4)",
"i4Description": "Protocol mimic packet in hex formaat: <b 0x...>",
"i5Label": "Special junk packet 5 (I5)",
"i5Description": "Protocol mimic packet in hex formaat: <b 0x...>",
"h1Label": "Init magic header (H1)",
"h1Description": "Waarde Init packet header (5-2147483647, moet uniek zijn t.o.v. H2-H4)",
"h2Label": "Response magic header (H2)",
"h2Description": "Waarde Response packet header (5-2147483647, moet uniek zijn t.o.v. H1, H3, H4)",
"h3Label": "Cookie reply magic header (H3)",
"h3Description": "Waarde Cookie reply packet header (5-2147483647, moet uniek zijn t.o.v. H1, H2, H4)",
"h4Label": "Transport magic header (H4)",
"h4Description": "Waarde Transport packet header (5-2147483647, moet uniek zijn t.o.v. H1-H3)",
"mtuNote": "Waarden zijn afhankelijk van de MTU",
"obfuscationParameters": "AmneziaWG Obfuscation Parameters"
}
}
+240
View File
@@ -0,0 +1,240 @@
{
"pages": {
"me": "Konto",
"clients": "Konta",
"admin": {
"panel": "Panel administracyjny",
"general": "Ogólne",
"config": "Konfiguracja",
"interface": "Interfejs",
"hooks": "Hooki"
}
},
"user": {
"email": "E-mail"
},
"me": {
"currentPassword": "Aktualne hasło",
"enable2fa": "Włącz uwierzytelnianie dwuskładnikowe",
"enable2faDesc": "Zeskanuj kod QR w aplikacji uwierzytelniającej lub wprowadź klucz ręcznie.",
"2faKey": "Klucz TOTP",
"2faCodeDesc": "Wprowadź kod z aplikacji uwierzytelniającej.",
"disable2fa": "Wyłącz uwierzytelnianie dwuskładnikowe",
"disable2faDesc": "Wprowadź swoje hasło, aby wyłączyć uwierzytelnianie dwuskładnikowe."
},
"general": {
"name": "Nazwa",
"username": "Nazwa użytkownika",
"password": "Hasło",
"newPassword": "Nowe hasło",
"updatePassword": "Zmień hasło",
"mtu": "MTU",
"allowedIps": "Dozwolone adresy IP",
"dns": "DNS",
"persistentKeepalive": "Stałe utrzymywanie połączenia",
"logout": "Wyloguj",
"continue": "Kontynuuj",
"host": "Host",
"port": "Port",
"yes": "Tak",
"no": "Nie",
"confirmPassword": "Potwierdź hasło",
"loading": "Ładowanie...",
"2fa": "Uwierzytelnianie dwuskładnikowe",
"2faCode": "Kod TOTP"
},
"setup": {
"welcome": "Witamy w pierwszej konfiguracji wg-easy",
"welcomeDesc": "Znalazłeś najprostszy sposób na instalację i zarządzanie WireGuard na dowolnym serwerze Linux",
"existingSetup": "Masz już istniejącą konfigurację?",
"createAdminDesc": "Podaj nazwę użytkownika administratora oraz silne, bezpieczne hasło. Informacje te będą używane do logowania w panelu administracyjnym.",
"setupConfigDesc": "Podaj informacje o hoście i porcie. Będą one używane w konfiguracji klienta podczas uruchamiania WireGuard na jego urządzeniach.",
"setupMigrationDesc": "Podaj plik kopii zapasowej, jeśli chcesz przenieść dane ze starszej wersji wg-easy do nowej instalacji.",
"upload": "Prześlij",
"migration": "Przywróć kopię zapasową:",
"createAccount": "Utwórz konto",
"successful": "Konfiguracja zakończona sukcesem",
"hostDesc": "Publiczny host, do którego będą łączyć się klienci",
"portDesc": "Publiczny port UDP, na którym WireGuard będzie nasłuchiwał i do którego będą łączyć się klienci"
},
"update": {
"updateAvailable": "Dostępna jest aktualizacja!",
"update": "Aktualizuj"
},
"theme": {
"dark": "Motyw ciemny",
"light": "Motyw jasny",
"system": "Motyw systemowy"
},
"layout": {
"toggleCharts": "Pokaż/ukryj wykresy",
"donate": "Wesprzyj"
},
"login": {
"signIn": "Zaloguj się",
"rememberMe": "Zapamiętaj mnie",
"rememberMeDesc": "Pozostań zalogowany po zamknięciu przeglądarki",
"insecure": "Nie możesz się zalogować przez niezabezpieczone połączenie. Użyj HTTPS.",
"2faRequired": "Wymagane uwierzytelnianie dwuskładnikowe",
"2faWrong": "Nieprawidłowy kod uwierzytelniania dwuskładnikowego"
},
"client": {
"empty": "Brak klientów.",
"newShort": "Nowy",
"sort": "Sortuj",
"create": "Utwórz klienta",
"created": "Klient utworzony",
"new": "Nowy klient",
"name": "Nazwa",
"expireDate": "Data wygaśnięcia",
"expireDateDesc": "Data, po której klient zostanie wyłączony. Puste = na stałe",
"deleteClient": "Usuń klienta",
"deleteDialog1": "Czy na pewno chcesz usunąć",
"deleteDialog2": "Tej akcji nie można cofnąć.",
"enabled": "Włączony",
"address": "Adres",
"serverAllowedIps": "Dozwolone adresy IP serwera",
"otlDesc": "Wygeneruj jednorazowy krótki link",
"permanent": "Stały",
"createdOn": "Utworzony ",
"lastSeen": "Ostatnio widziany ",
"totalDownload": "Łączne pobieranie: ",
"totalUpload": "Łączne wysyłanie: ",
"newClient": "Nowy klient",
"disableClient": "Wyłącz klienta",
"enableClient": "Włącz klienta",
"noPrivKey": "Ten klient nie ma znanego klucza prywatnego. Nie można utworzyć konfiguracji.",
"showQR": "Pokaż kod QR",
"downloadConfig": "Pobierz konfigurację",
"allowedIpsDesc": "Które adresy IP będą kierowane przez VPN (nadpisuje konfigurację globalną)",
"serverAllowedIpsDesc": "Które adresy IP serwer będzie kierował do klienta",
"mtuDesc": "Ustawia maksymalny rozmiar pakietu (MTU) dla tunelu VPN",
"persistentKeepaliveDesc": "Ustawia interwał (w sekundach) wysyłania pakietów keep-alive. 0 = wyłączone",
"hooks": "Hooki",
"hooksDescription": "Hooki działają tylko z wg-quick",
"hooksLeaveEmpty": "Tylko dla wg-quick. W innym przypadku pozostaw puste",
"dnsDesc": "Serwer DNS, którego będą używać klienci (nadpisuje konfigurację globalną)",
"notConnected": "Klient nie jest połączony",
"endpoint": "Punkt końcowy",
"endpointDesc": "Adres IP klienta, z którego ustanawiane jest połączenie WireGuard"
},
"dialog": {
"change": "Zmień",
"cancel": "Anuluj",
"create": "Utwórz"
},
"toast": {
"success": "Sukces",
"saved": "Zapisano",
"error": "Błąd"
},
"form": {
"actions": "Akcje",
"save": "Zapisz",
"revert": "Przywróć",
"sectionGeneral": "Ogólne",
"sectionAdvanced": "Zaawansowane",
"noItems": "Brak elementów",
"nullNoItems": "Brak elementów. Używana konfiguracja globalna",
"add": "Dodaj"
},
"admin": {
"general": {
"sessionTimeout": "Limit czasu sesji",
"sessionTimeoutDesc": "Czas trwania sesji dla opcji Zapamiętaj mnie (w sekundach)",
"metrics": "Metryki",
"metricsPassword": "Hasło",
"metricsPasswordDesc": "Hasło Bearer dla endpointu metryk (hasło lub hash argon2)",
"json": "JSON",
"jsonDesc": "Ścieżka dla metryk w formacie JSON",
"prometheus": "Prometheus",
"prometheusDesc": "Ścieżka dla metryk Prometheus"
},
"config": {
"connection": "Połączenie",
"hostDesc": "Publiczny host, do którego będą łączyć się klienci (unieważnia konfigurację)",
"portDesc": "Publiczny port UDP, do którego będą łączyć się klienci (unieważnia konfigurację, prawdopodobnie należy też zmienić port interfejsu)",
"allowedIpsDesc": "Dozwolone adresy IP klientów (konfiguracja globalna)",
"dnsDesc": "Serwer DNS klientów (konfiguracja globalna)",
"mtuDesc": "MTU klientów (tylko dla nowych klientów)",
"persistentKeepaliveDesc": "Interwał w sekundach dla keepalive do serwera. 0 = wyłączone (tylko dla nowych klientów)",
"suggest": "Sugeruj",
"suggestDesc": "Wybierz adres IP lub nazwę hosta dla pola Host"
},
"interface": {
"cidrSuccess": "Zmieniono CIDR",
"device": "Urządzenie",
"deviceDesc": "Urządzenie sieciowe, przez które ma być przekazywany ruch WireGuard",
"mtuDesc": "MTU używane przez WireGuard",
"portDesc": "Port UDP, na którym WireGuard będzie nasłuchiwał (prawdopodobnie trzeba też zmienić port w konfiguracji)",
"changeCidr": "Zmień CIDR",
"restart": "Restart interfejsu",
"restartDesc": "Zrestartuj interfejs WireGuard",
"restartWarn": "Czy na pewno chcesz zrestartować interfejs? Wszyscy klienci zostaną rozłączeni.",
"restartSuccess": "Interfejs zrestartowany"
},
"introText": "Witamy w panelu administracyjnym.\n\nTutaj możesz zarządzać ustawieniami ogólnymi, konfiguracją, interfejsem i hookami.\n\nZacznij od wybrania jednej z sekcji w pasku bocznym."
},
"zod": {
"generic": {
"required": "{0} jest wymagane",
"validNumber": "{0} musi być prawidłową liczbą",
"validString": "{0} musi być prawidłowym tekstem",
"validBoolean": "{0} musi być prawidłową wartością logiczną",
"validArray": "{0} musi być prawidłową tablicą",
"stringMin": "{0} musi mieć co najmniej {1} znaków",
"numberMin": "{0} musi być co najmniej {1}"
},
"client": {
"id": "ID klienta",
"name": "Nazwa",
"expiresAt": "Wygasa",
"address4": "Adres IPv4",
"address6": "Adres IPv6",
"serverAllowedIps": "Dozwolone adresy IP serwera"
},
"user": {
"username": "Nazwa użytkownika",
"password": "Hasło",
"remember": "Zapamiętaj",
"name": "Imię",
"email": "E-mail",
"emailInvalid": "E-mail musi być prawidłowy",
"passwordMatch": "Hasła muszą się zgadzać",
"totpEnable": "Włącz TOTP",
"totpEnableTrue": "TOTP musi być włączone",
"totpCode": "Kod TOTP"
},
"userConfig": {
"host": "Host"
},
"general": {
"sessionTimeout": "Limit czasu sesji",
"metricsEnabled": "Metryki",
"metricsPassword": "Hasło do metryk"
},
"interface": {
"cidr": "CIDR",
"device": "Urządzenie",
"cidrValid": "CIDR musi być prawidłowy"
},
"otl": "Jednorazowy link",
"stringMalformed": "Nieprawidłowy format tekstu",
"body": "Treść musi być prawidłowym obiektem",
"hook": "Hook",
"enabled": "Włączone",
"mtu": "MTU",
"port": "Port",
"persistentKeepalive": "Stałe utrzymywanie połączenia",
"address": "Adres IP",
"dns": "DNS",
"allowedIps": "Dozwolone adresy IP",
"file": "Plik"
},
"hooks": {
"preUp": "PreUp",
"postUp": "PostUp",
"preDown": "PreDown",
"postDown": "PostDown"
}
}
+240
View File
@@ -0,0 +1,240 @@
{
"pages": {
"me": "Conta",
"clients": "Clientes",
"admin": {
"panel": "Panel de administração.",
"general": "Geral",
"config": "Configuração",
"interface": "Interface",
"hooks": "Hooks"
}
},
"user": {
"email": "E-mail"
},
"me": {
"currentPassword": "Senha atual",
"enable2fa": "Habilitar autenticação em dois fatores",
"enable2faDesc": "Escaneie o QR Code com seu aplicativo autenticador ou insira a chave manualmente.",
"2faKey": "Chave TOTP",
"2faCodeDesc": "Digite o código do seu aplicativo autenticador.",
"disable2fa": "Desativar autenticação de dois fatores.",
"disable2faDesc": "Digite sua senha para desativar a autenticação de dois fatores."
},
"general": {
"name": "Nome",
"username": "Nome de usuário",
"password": "Senha",
"newPassword": "Nova senha",
"updatePassword": "Atualizar senha",
"mtu": "MTU",
"allowedIps": "IPs permitidos",
"dns": "DNS",
"persistentKeepalive": "Keepalive persistente",
"logout": "Sair",
"continue": "Continue",
"host": "Host",
"port": "Porta",
"yes": "Sim",
"no": "Não",
"confirmPassword": "Confirmar senha",
"loading": "Carregando...",
"2fa": "Autenticação de dois fatores",
"2faCode": "Código TOTP"
},
"setup": {
"welcome": "Bem-vindo à sua primeira configuração do wg-easy",
"welcomeDesc": "Você encontrou a maneira mais fácil de instalar e gerenciar o WireGuard em qualquer host Linux",
"existingSetup": "Você já tem uma configuração?",
"createAdminDesc": "Primeiro, insira um nome de usuário de administrador e uma senha forte e segura. Essas informações serão usadas para fazer login no seu painel de administração.",
"setupConfigDesc": "Insira as informações do host e da porta. Essas informações serão usadas para a configuração do cliente ao instalar o WireGuard em seus dispositivos.",
"setupMigrationDesc": "Forneça o arquivo de backup se quiser migrar seus dados da versão anterior do wg-easy para a nova configuração.",
"upload": "Upload",
"migration": "Restaurar backup:",
"createAccount": "Criar conta",
"successful": "Configuração bem-sucedida",
"hostDesc": "Nome de host público que os clientes se conectarão",
"portDesc": "Porta UDP pública que os clientes se conectarão e o WireGuard escutará"
},
"update": {
"updateAvailable": "Há uma atualização disponível!",
"update": "Atualizar"
},
"theme": {
"dark": "Tema escuro",
"light": "Tema claro",
"system": "Tema do sistema"
},
"layout": {
"toggleCharts": "Mostrar/ocultar gráficos",
"donate": "Doar"
},
"login": {
"signIn": "Entrar",
"rememberMe": "Lembrar de mim",
"rememberMeDesc": "Permanecer conectado após fechar o navegador",
"insecure": "Não é possível fazer login com uma conexão insegura. Use HTTPS.",
"2faRequired": "É necessária autenticação de dois fatores",
"2faWrong": "A autenticação de dois fatores está errada"
},
"client": {
"empty": "Ainda não há clientes.",
"newShort": "Novo",
"sort": "Organizar",
"create": "Criar cliente",
"created": "Cliente criado",
"new": "Novo cliente",
"name": "Nome",
"expireDate": "Data de expiração",
"expireDateDesc": "Data em que o cliente será desativado. Em branco para permanente",
"deleteClient": "Deletar cliente",
"deleteDialog1": "Tem certeza de que deseja excluir?",
"deleteDialog2": "Esta ação não pode ser desfeita.",
"enabled": "Ativado",
"address": "Endereço",
"serverAllowedIps": "IPs permitidos do servidor",
"otlDesc": "Gerar link curto e único",
"permanent": "Permanente",
"createdOn": "Criado em ",
"lastSeen": "Visto pela última vez em",
"totalDownload": "Download total: ",
"totalUpload": "Upload total: ",
"newClient": "Novo cliente",
"disableClient": "Desativar cliente",
"enableClient": "Ativar cliente",
"noPrivKey": "Este cliente não possui uma chave privada conhecida. Não é possível criar a configuração.",
"showQR": "Mostrar QR Code",
"downloadConfig": "Download da configuração",
"allowedIpsDesc": "Quais IPs serão roteados pela VPN (substitui a configuração global)",
"serverAllowedIpsDesc": "Quais IPs o servidor irá rotear para o cliente",
"mtuDesc": "Define a unidade máxima de transmissão (tamanho do pacote) para o túnel VPN",
"persistentKeepaliveDesc": "Define o intervalo (em segundos) para pacotes keep-alive. 0 desabilita-o",
"hooks": "Hooks",
"hooksDescription": "Os hooks só funcionam com wg-quick",
"hooksLeaveEmpty": "Somente para wg-quick. Caso contrário, deixe em branco.",
"dnsDesc": "Os clientes do servidor DNS usarão (substitui a configuração global)",
"notConnected": "Client não conectado",
"endpoint": "Endpoint",
"endpointDesc": "IP do cliente a partir do qual a conexão WireGuard é estabelecida"
},
"dialog": {
"change": "Mudar",
"cancel": "Cancelar",
"create": "Criar"
},
"toast": {
"success": "Sucesso",
"saved": "Salvo",
"error": "Erro"
},
"form": {
"actions": "Ação",
"save": "Salvar",
"revert": "Reverter",
"sectionGeneral": "Geral",
"sectionAdvanced": "Avançado",
"noItems": "Sem items",
"nullNoItems": "Sem items. Usando configuração global",
"add": "Adicionar"
},
"admin": {
"general": {
"sessionTimeout": "Tempo limite da sessão",
"sessionTimeoutDesc": "Duração da sessão para Lembrar de mim (segundos)",
"metrics": "Métricas",
"metricsPassword": "Senha",
"metricsPasswordDesc": "Senha do portador para o ponto final de métricas (senha ou hash argon2)",
"json": "JSON",
"jsonDesc": "Rota para métricas em formato JSON",
"prometheus": "Prometheus",
"prometheusDesc": "Rota para métricas do Prometheus"
},
"config": {
"connection": "Conexão",
"hostDesc": "Nome de host público ao qual os clientes se conectarão (invalida a configuração)",
"portDesc": "Porta UDP pública à qual os clientes se conectarão (invalida a configuração, você provavelmente desejará alterar a porta da interface também)",
"allowedIpsDesc": "IPs permitidos que os clientes usarão (configuração global)",
"dnsDesc": "Os clientes do servidor DNS usarão (configuração global)",
"mtuDesc": "Os clientes da MTU usarão (somente para novos clientes)",
"persistentKeepaliveDesc": "Intervalo em segundos para enviar keepalives para o servidor. 0 = desabilitado (somente para novos clientes)",
"suggest": "Sugestão",
"suggestDesc": "Escolha um endereço IP ou nome de host para o campo Host"
},
"interface": {
"cidrSuccess": "Mudar CIDR",
"device": "Dispositivo",
"deviceDesc": "Dispositivo Ethernet que o tráfego wireguard deve ser encaminhado",
"mtuDesc": "MTU que o WireGuard usará",
"portDesc": "A porta UDP que o WireGuard irá escutar (você provavelmente vai querer mudar a porta de configuração também)",
"changeCidr": "Mudar CIDR",
"restart": "Reiniciar interface",
"restartDesc": "Reiniciar a interface do WireGuard",
"restartWarn": "Tem certeza de que deseja reiniciar a interface? Isso desconectará todos os clientes.",
"restartSuccess": "Interface reiniciada"
},
"introText": "Bem-vindo ao painel de administração.\n\nAqui você pode gerenciar as configurações gerais, a configuração, as configurações da interface e os hooks.\n\nComece escolhendo uma das seções na barra lateral."
},
"zod": {
"generic": {
"required": "{0} é obrigatório",
"validNumber": "{0} deve ser um número válido",
"validString": "{0} deve ser uma string válida",
"validBoolean": "{0} deve ser um booleano válido",
"validArray": "{0} deve ser uma matriz válida",
"stringMin": "{0} deve ter pelo menos {1} caracteres",
"numberMin": "{0} deve ter pelo menos {1}"
},
"client": {
"id": "ID do cliente",
"name": "Nome",
"expiresAt": "Expira em",
"address4": "Endereço IPv4",
"address6": "Endereço IPv6",
"serverAllowedIps": "IPs permitidos do servidor"
},
"user": {
"username": "Usuário",
"password": "Senha",
"remember": "Lembrar",
"name": "Nome",
"email": "E-mail",
"emailInvalid": "O e-mail deve ser um e-mail válido",
"passwordMatch": "As senhas devem corresponder",
"totpEnable": "Habilitar TOTP",
"totpEnableTrue": "TOTP deve estar ativado",
"totpCode": "Código TOTP"
},
"userConfig": {
"host": "Host"
},
"general": {
"sessionTimeout": "Tempo limite da sessão",
"metricsEnabled": "Métricas",
"metricsPassword": "Senha de métricas"
},
"interface": {
"cidr": "CIDR",
"device": "Dispositivo",
"cidrValid": "O CIDR deve ser válido"
},
"otl": "Link de uso único",
"stringMalformed": "A string está malformada",
"body": "O corpo deve ser um objeto válido",
"hook": "Hook",
"enabled": "Ativado",
"mtu": "MTU",
"port": "Porta",
"persistentKeepalive": "Keepalive persistente",
"address": "Endereço IP",
"dns": "DNS",
"allowedIps": "IPs permitidos",
"file": "Arquivo"
},
"hooks": {
"preUp": "PreUp",
"postUp": "PostUp",
"preDown": "PreDown",
"postDown": "PostDown"
}
}
+286
View File
@@ -0,0 +1,286 @@
{
"pages": {
"me": "Аккаунт",
"clients": "Клиенты",
"admin": {
"panel": "Админ-панель",
"general": "Общие настройки",
"config": "Конфигурация",
"interface": "Интерфейс",
"hooks": "Хуки"
}
},
"user": {
"email": "E-Mail"
},
"me": {
"currentPassword": "Текущий пароль",
"enable2fa": "Включить двухфакторную аутентификацию",
"enable2faDesc": "Отсканируйте QR‑код с помощью приложения‑аутентификатора или введите ключ вручную.",
"2faKey": "Ключ TOTP",
"2faCodeDesc": "Введите код из приложения‑аутентификатора.",
"disable2fa": "Отключить двухфакторную аутентификацию",
"disable2faDesc": "Введите пароль, чтобы отключить двухфакторную аутентификацию."
},
"general": {
"name": "Имя",
"username": "Имя пользователя",
"password": "Пароль",
"newPassword": "Новый пароль",
"updatePassword": "Обновить пароль",
"mtu": "MTU",
"allowedIps": "Разрешённые IP‑адреса",
"dns": "DNS",
"persistentKeepalive": "Постоянное поддержание соединения",
"logout": "Выйти",
"continue": "Продолжить",
"host": "Хост",
"port": "Порт",
"yes": "Да",
"no": "Нет",
"confirmPassword": "Подтвердите пароль",
"loading": "Загрузка...",
"2fa": "Двухфакторная аутентификация",
"2faCode": "Код TOTP"
},
"setup": {
"welcome": "Добро пожаловать в первичную настройку wg-easy",
"welcomeDesc": "Вы нашли самый простой способ установить и управлять WireGuard на любом Linux‑хосте",
"existingSetup": "У вас уже есть существующая настройка?",
"createAdminDesc": "Сначала введите имя администратора и надёжный пароль. Эти данные будут использоваться для входа в Админ-панель.",
"setupConfigDesc": "Введите данные хоста и порта. Они будут использоваться для настройки клиента при установке WireGuard на устройствах.",
"setupMigrationDesc": "Укажите файл резервной копии, если хотите перенести данные из предыдущей версии wg-easy.",
"upload": "Загрузить",
"migration": "Восстановить из резервной копии:",
"createAccount": "Создать аккаунт",
"successful": "Настройка завершена успешно",
"hostDesc": "Публичное имя хоста, к которому будут подключаться клиенты",
"portDesc": "Публичный UDP‑порт, к которому будут подключаться клиенты и на котором будет слушать WireGuard"
},
"update": {
"updateAvailable": "Доступно обновление!",
"update": "Обновить"
},
"theme": {
"dark": "Тёмная тема",
"light": "Светлая тема",
"system": "Системная тема"
},
"layout": {
"toggleCharts": "Показать/скрыть графики",
"donate": "Поддержать"
},
"login": {
"signIn": "Войти",
"rememberMe": "Запомнить меня",
"rememberMeDesc": "Оставаться в системе после закрытия браузера",
"insecure": "Вы не можете войти по незащищённому соединению. Используйте HTTPS.",
"2faRequired": "Требуется двухфакторная аутентификация",
"2faWrong": "Неверный код двухфакторной аутентификации"
},
"client": {
"empty": "Клиентов пока нет.",
"newShort": "Новый",
"sort": "Сортировка",
"create": "Создать клиента",
"created": "Клиент создан",
"new": "Новый клиент",
"name": "Имя",
"expireDate": "Дата отключения",
"expireDateDesc": "Дата, когда клиент будет отключён. Оставьте пустым для бессрочного доступа",
"delete": "Удалить",
"deleteClient": "Удалить клиента",
"deleteDialog1": "Вы уверены, что хотите удалить",
"deleteDialog2": "Это действие нельзя отменить.",
"enabled": "Включён",
"address": "Адрес",
"serverAllowedIps": "Разрешённые IP‑адреса сервера",
"otlDesc": "Сгенерировать короткую одноразовую ссылку",
"permanent": "Бессрочный",
"createdOn": "Создан ",
"lastSeen": "Последнее подключение ",
"totalDownload": "Всего скачано: ",
"totalUpload": "Всего отправлено: ",
"newClient": "Новый клиент",
"disableClient": "Отключить клиента",
"enableClient": "Включить клиента",
"noPrivKey": "У этого клиента нет приватного ключа. Невозможно создать конфигурацию.",
"showQR": "Показать QR‑код",
"downloadConfig": "Скачать конфигурацию",
"allowedIpsDesc": "Какие IP‑адреса будут маршрутизироваться через VPN (переопределяет глобальную конфигурацию)",
"serverAllowedIpsDesc": "Какие IP‑адреса сервер будет отправлять клиенту",
"mtuDesc": "Максимальный размер пакета (MTU) для VPN‑туннеля",
"persistentKeepaliveDesc": "Устанавливает интервал (в секундах) для пакетов поддержания соединения. 0 — отключить",
"hooks": "Хуки",
"hooksDescription": "Хуки работают только с wg‑quick",
"hooksLeaveEmpty": "Только для wg‑quick. В остальных случаях оставьте пустым",
"dnsDesc": "DNS‑сервер, который будут использовать клиенты (переопределяет глобальную конфигурацию)",
"notConnected": "Клиент не подключен",
"endpoint": "Точка подключения",
"endpointDesc": "IP‑адрес клиента, с которого установлено соединение WireGuard",
"search": "Поиск клиентов...",
"config": "Конфигурация",
"viewConfig": "Просмотреть конфигурацию"
},
"dialog": {
"change": "Изменить",
"cancel": "Отменить",
"create": "Создать"
},
"toast": {
"success": "Успешно",
"saved": "Сохранено",
"error": "Ошибка"
},
"form": {
"actions": "Действия",
"save": "Сохранить",
"revert": "Отменить",
"sectionGeneral": "Общие",
"sectionAdvanced": "Расширенные",
"noItems": "Нет элементов",
"nullNoItems": "Нет элементов. Используется глобальная конфигурация",
"add": "Добавить"
},
"admin": {
"general": {
"sessionTimeout": "Время жизни сессии",
"sessionTimeoutDesc": "Длительность сессии для «Запомнить меня» (в секундах)",
"metrics": "Метрики",
"metricsPassword": "Пароль",
"metricsPasswordDesc": "Пароль Bearer для конечной точки метрик (пароль или хэш argon2)",
"json": "JSON",
"jsonDesc": "Путь для метрик в формате JSON",
"prometheus": "Prometheus",
"prometheusDesc": "Путь для метрик Prometheus"
},
"config": {
"connection": "Соединение",
"hostDesc": "Публичное имя хоста для подключения клиентов(обнуляет конфигурацию)",
"portDesc": "Публичный UDP‑порт для подключения клиентов (также рекомендуется изменить порт интерфейса)",
"allowedIpsDesc": "Разрешённые IP‑адреса для клиентов(глобальная конфигурация)",
"dnsDesc": "DNS‑сервер для клиентов (глобальная конфигурация)",
"mtuDesc": "MTU для клиентов (только для новых)",
"persistentKeepaliveDesc": "Интервал в секундах для отправки пакетов поддержания соединения на сервер. 0 = отключено (только для новых клиентов)",
"suggest": "Предложить",
"suggestDesc": "Выберите IP‑адрес или имя хоста для поля «Хост»"
},
"interface": {
"cidrSuccess": "CIDR изменён",
"device": "Устройство",
"deviceDesc": "Сетевое устройство Ethernet, через которое должен проходить трафик WireGuard",
"mtuDesc": "MTU, который будет использовать WireGuard",
"portDesc": "UDP‑порт, на котором будет слушать WireGuard (возможно, нужно также изменить порт конфигурации)",
"changeCidr": "Изменить CIDR",
"restart": "Перезапустить интерфейс",
"restartDesc": "Перезапустить интерфейс WireGuard",
"restartWarn": "Вы уверены, что хотите перезапустить интерфейс? Это приведёт к отключению всех клиентов.",
"restartSuccess": "Интерфейс перезапущен"
},
"introText": "Добро пожаловать в панель администратора.\n\nЗдесь вы можете управлять общими настройками, конфигурацией, настройками интерфейса и хуками.\n\nНачните с выбора одного из разделов на боковой панели."
},
"zod": {
"generic": {
"required": "{0} обязательно для заполнения",
"validNumber": "{0} должно быть числом",
"validString": "{0} должно быть строкой",
"validBoolean": "{0} должно быть логическим значением",
"validArray": "{0} должно быть массивом",
"stringMin": "{0} должно содержать не менее {1} символа",
"numberMin": "{0} должно быть не менее {1}"
},
"client": {
"id": "ID клиента",
"name": "Имя",
"expiresAt": "Дата окончания действия",
"address4": "IPv4‑адрес",
"address6": "IPv6‑адрес",
"serverAllowedIps": "Разрешённые IP‑адреса сервера"
},
"user": {
"username": "Имя пользователя",
"password": "Пароль",
"remember": "Запомнить",
"name": "Имя",
"email": "Электронная почта",
"emailInvalid": "Адрес электронной почты должен быть корректным",
"passwordMatch": "Пароли должны совпадать",
"totpEnable": "Включить TOTP",
"totpEnableTrue": "TOTP должен быть включён",
"totpCode": "Код TOTP"
},
"userConfig": {
"host": "Хост"
},
"general": {
"sessionTimeout": "Время жизни сессии",
"metricsEnabled": "Метрики",
"metricsPassword": "Пароль для метрик"
},
"interface": {
"cidr": "CIDR",
"device": "Устройство",
"cidrValid": "CIDR должен быть корректным"
},
"otl": "Одноразовая ссылка",
"stringMalformed": "Строка имеет неверный формат",
"body": "Тело должно быть корректным объектом",
"hook": "Хук",
"enabled": "Включено",
"mtu": "MTU",
"port": "Порт",
"persistentKeepalive": "Постоянное поддержание соединения",
"address": "IP‑адрес",
"dns": "DNS",
"allowedIps": "Разрешённые IP‑адреса",
"file": "Файл"
},
"hooks": {
"preUp": "PreUp",
"postUp": "PostUp",
"preDown": "PreDown",
"postDown": "PostDown"
},
"copy": {
"notSupported": "Копирование не поддерживается",
"copied": "Скопировано!",
"failed": "Ошибка копирования",
"copy": "Копировать"
},
"awg": {
"jCLabel": "Количество мусорных пакетов (Jc)",
"jCDescription": "Число мусорных пакетов для отправки (1-128, рекомендуется: 4-12)",
"jMinLabel": "Минимальный размер мусорных пакетов (Jmin)",
"jMinDescription": "Минимальный размер мусорных пакетов (0-1279*, рекомендуется: 8, должен быть < Jmax)",
"jMaxLabel": "Максимальный размер мусорных пакетов (Jmax)",
"jMaxDescription": "Максимальный размер мусорных пакетов (1-1280*, рекомендуется: 80, должен быть > Jmin)",
"s1Label": "Размер мусорных данных в init-пакете (S1)",
"s1Description": "Размер мусорных данных в init-пакете (0-1132[1280* - 148 = 1132], рекомендуется: 15-150, S1+56 ≠ S2)",
"s2Label": "Размер мусорных данных в ответном пакете (S2)",
"s2Description": "Размер мусорных данных в ответном пакете (0-1188[1280* - 92 = 1188], рекомендуется: 15-150)",
"s3Label": "Размер мусорных данных в cookie-reply пакете (S3)",
"s3Description": "Размер мусорных данных в cookie-reply пакете",
"s4Label": "Размер мусорных данных в транспортном пакете (S4)",
"s4Description": "Размер мусорных данных в транспортном пакете",
"i1Label": "Специальный мусорный пакет 1 (I1)",
"i1Description": "Пакет имитации протокола в hex формате: <b 0x...>",
"i2Label": "Специальный мусорный пакет 2 (I2)",
"i2Description": "Пакет имитации протокола в hex формате: <b 0x...>",
"i3Label": "Специальный мусорный пакет 3 (I3)",
"i3Description": "Пакет имитации протокола в hex формате: <b 0x...>",
"i4Label": "Специальный мусорный пакет 4 (I4)",
"i4Description": "Пакет имитации протокола в hex формате: <b 0x...>",
"i5Label": "Специальный мусорный пакет 5 (I5)",
"i5Description": "Пакет имитации протокола в hex формате: <b 0x...>",
"h1Label": "Init magic заголовок (H1)",
"h1Description": "Значение заголовка init-пакета (5-2147483647, должно отличаться от H2-H4)",
"h2Label": "Response magic заголовок (H2)",
"h2Description": "Значение заголовка ответного пакета (5-2147483647, должно отличаться от H1, H3, H4)",
"h3Label": "Cookie reply magic заголовок (H3)",
"h3Description": "Значение заголовка cookie-reply пакета (5-2147483647, должно отличаться от H1, H2, H4)",
"h4Label": "Transport magic заголовок (H4)",
"h4Description": "Значение заголовка транспортного пакета (5-2147483647, должно отличаться от H1-H3)",
"mtuNote": "Значения зависят от MTU",
"obfuscationParameters": "Параметры обфускации AmneziaWG"
}
}
+240
View File
@@ -0,0 +1,240 @@
{
"pages": {
"me": "Hesap",
"clients": "İstemciler",
"admin": {
"panel": "Yönetici Paneli",
"general": "Genel",
"config": "Yapılandırma",
"interface": "Arayüz",
"hooks": "Hook'lar"
}
},
"user": {
"email": "E-Posta"
},
"me": {
"currentPassword": "Mevcut Şifre",
"enable2fa": "İki Faktörlü Kimlik Doğrulamayı Etkinleştir",
"enable2faDesc": "QR kodunu kimlik doğrulayıcı uygulamanızla tarayın veya anahtarı manuel olarak girin.",
"2faKey": "TOTP Anahtarı",
"2faCodeDesc": "Kimlik doğrulayıcı uygulamanızdan kodu girin.",
"disable2fa": "İki Faktörlü Kimlik Doğrulamayı Devre Dışı Bırak",
"disable2faDesc": "İki Faktörlü Kimlik Doğrulamayı devre dışı bırakmak için şifrenizi girin."
},
"general": {
"name": "Ad",
"username": "Kullanıcı Adı",
"password": "Şifre",
"newPassword": "Yeni Şifre",
"updatePassword": "Şifreyi Güncelle",
"mtu": "MTU",
"allowedIps": "İzin Verilen IP'ler",
"dns": "DNS",
"persistentKeepalive": "Kalıcı Keepalive",
"logout": "Çıkış Yap",
"continue": "Devam Et",
"host": "Ana Bilgisayar",
"port": "Port",
"yes": "Evet",
"no": "Hayır",
"confirmPassword": "Şifreyi Onayla",
"loading": "Yükleniyor...",
"2fa": "İki Faktörlü Kimlik Doğrulama",
"2faCode": "TOTP Kodu"
},
"setup": {
"welcome": "wg-easy ilk kurulumunuza hoş geldiniz",
"welcomeDesc": "Herhangi bir Linux ana bilgisayarda WireGuard kurmanın ve yönetmenin en kolay yolunu buldunuz",
"existingSetup": "Mevcut bir kurulumunuz var mı?",
"createAdminDesc": "Lütfen önce bir yönetici kullanıcı adı ve güçlü bir güvenli şifre girin. Bu bilgiler yönetim panelinize giriş yapmak için kullanılacaktır.",
"setupConfigDesc": "Lütfen ana bilgisayar ve port bilgilerini girin. Bu, cihazlarında WireGuard kurulumu yaparken istemci yapılandırması için kullanılacaktır.",
"setupMigrationDesc": "Verilerinizi önceki wg-easy sürümünüzden yeni kurulumunuza taşımak istiyorsanız yedekleme dosyasını sağlayın.",
"upload": "Yükle",
"migration": "Yedeği geri yükle:",
"createAccount": "Hesap Oluştur",
"successful": "Kurulum başarılı",
"hostDesc": "İstemcilerin bağlanacağı genel ana bilgisayar adı",
"portDesc": "İstemcilerin bağlanacağı ve WireGuard'ın dinleyeceği genel UDP portu"
},
"update": {
"updateAvailable": "Güncelleme mevcut!",
"update": "Güncelle"
},
"theme": {
"dark": "Koyu tema",
"light": "Açık tema",
"system": "Sistem teması"
},
"layout": {
"toggleCharts": "Grafikleri Göster/Gizle",
"donate": "Bağış Yap"
},
"login": {
"signIn": "Giriş Yap",
"rememberMe": "Beni hatırla",
"rememberMeDesc": "Tarayıcıyı kapattıktan sonra giriş yapmış olarak kal",
"insecure": "Güvensiz bir bağlantı ile giriş yapamazsınız. HTTPS kullanın.",
"2faRequired": "İki Faktörlü Kimlik Doğrulama gerekli",
"2faWrong": "İki Faktörlü Kimlik Doğrulama yanlış"
},
"client": {
"empty": "Henüz istemci yok.",
"newShort": "Yeni",
"sort": "Sırala",
"create": "İstemci Oluştur",
"created": "İstemci oluşturuldu",
"new": "Yeni İstemci",
"name": "Ad",
"expireDate": "Son Kullanma Tarihi",
"expireDateDesc": "İstemcinin devre dışı bırakılacağı tarih. Kalıcı için boş bırakın",
"deleteClient": "İstemciyi Sil",
"deleteDialog1": "Silmek istediğinizden emin misiniz",
"deleteDialog2": "Bu eylem geri alınamaz.",
"enabled": "Etkin",
"address": "Adres",
"serverAllowedIps": "Sunucu İzin Verilen IP'ler",
"otlDesc": "Kısa tek seferlik bağlantı oluştur",
"permanent": "Kalıcı",
"createdOn": "Oluşturulma tarihi ",
"lastSeen": "Son görülme ",
"totalDownload": "Toplam İndirme: ",
"totalUpload": "Toplam Yükleme: ",
"newClient": "Yeni İstemci",
"disableClient": "İstemciyi Devre Dışı Bırak",
"enableClient": "İstemciyi Etkinleştir",
"noPrivKey": "Bu istemcinin bilinen özel anahtarı yok. Yapılandırma oluşturulamıyor.",
"showQR": "QR Kodunu Göster",
"downloadConfig": "Yapılandırmayı İndir",
"allowedIpsDesc": "Hangi IP'lerin VPN üzerinden yönlendirileceği (genel yapılandırmayı geçersiz kılar)",
"serverAllowedIpsDesc": "Sunucunun istemciye yönlendireceği IP'ler",
"mtuDesc": "VPN tüneli için maksimum iletim birimini (paket boyutu) ayarlar",
"persistentKeepaliveDesc": "Keepalive paketleri için aralığı (saniye cinsinden) ayarlar. 0 devre dışı bırakır",
"hooks": "Hook'lar",
"hooksDescription": "Hook'lar sadece wg-quick ile çalışır",
"hooksLeaveEmpty": "Sadece wg-quick için. Aksi takdirde boş bırakın",
"dnsDesc": "İstemcilerin kullanacağı DNS sunucusu (genel yapılandırmayı geçersiz kılar)",
"notConnected": "İstemci bağlı değil",
"endpoint": "Uç Nokta",
"endpointDesc": "WireGuard bağlantısının kurulduğu istemcinin IP'si"
},
"dialog": {
"change": "Değiştir",
"cancel": "İptal",
"create": "Oluştur"
},
"toast": {
"success": "Başarılı",
"saved": "Kaydedildi",
"error": "Hata"
},
"form": {
"actions": "Eylemler",
"save": "Kaydet",
"revert": "Geri Al",
"sectionGeneral": "Genel",
"sectionAdvanced": "Gelişmiş",
"noItems": "Öğe yok",
"nullNoItems": "Öğe yok. Genel yapılandırma kullanılıyor",
"add": "Ekle"
},
"admin": {
"general": {
"sessionTimeout": "Oturum Zaman Aşımı",
"sessionTimeoutDesc": "Beni Hatırla için oturum süresi (saniye)",
"metrics": "Metrikler",
"metricsPassword": "Şifre",
"metricsPasswordDesc": "Metrik uç noktası için Bearer şifresi (şifre veya argon2 hash)",
"json": "JSON",
"jsonDesc": "JSON formatında metrikler için rota",
"prometheus": "Prometheus",
"prometheusDesc": "Prometheus metrikleri için rota"
},
"config": {
"connection": "Bağlantı",
"hostDesc": "İstemcilerin bağlanacağı genel ana bilgisayar adı (yapılandırmayı geçersiz kılar)",
"portDesc": "İstemcilerin bağlanacağı genel UDP portu (yapılandırmayı geçersiz kılar, muhtemelen Arayüz Portunu da değiştirmek isteyeceksiniz)",
"allowedIpsDesc": "İstemcilerin kullanacağı İzin Verilen IP'ler (genel yapılandırma)",
"dnsDesc": "İstemcilerin kullanacağı DNS sunucusu (genel yapılandırma)",
"mtuDesc": "İstemcilerin kullanacağı MTU (sadece yeni istemciler için)",
"persistentKeepaliveDesc": "Sunucuya keepalive göndermek için saniye cinsinden aralık. 0 = devre dışı (sadece yeni istemciler için)",
"suggest": "Öner",
"suggestDesc": "Ana Bilgisayar alanı için bir IP Adresi veya Ana Bilgisayar Adı seçin"
},
"interface": {
"cidrSuccess": "CIDR değiştirildi",
"device": "Cihaz",
"deviceDesc": "WireGuard trafiğinin yönlendirileceği Ethernet cihazı",
"mtuDesc": "WireGuard'ın kullanacağı MTU",
"portDesc": "WireGuard'ın dinleyeceği UDP Portu (muhtemelen Yapılandırma Portunu da değiştirmek isteyeceksiniz)",
"changeCidr": "CIDR'ı Değiştir",
"restart": "Arayüzü Yeniden Başlat",
"restartDesc": "WireGuard arayüzünü yeniden başlat",
"restartWarn": "Arayüzü yeniden başlatmak istediğinizden emin misiniz? Bu tüm istemcilerin bağlantısını kesecektir.",
"restartSuccess": "Arayüz yeniden başlatıldı"
},
"introText": "Yönetici paneline hoş geldiniz.\n\nBurada genel ayarları, yapılandırmayı, arayüz ayarlarını ve hook'ları yönetebilirsiniz.\n\nKenar çubuğundaki bölümlerden birini seçerek başlayın."
},
"zod": {
"generic": {
"required": "{0} gerekli",
"validNumber": "{0} geçerli bir sayı olmalı",
"validString": "{0} geçerli bir dize olmalı",
"validBoolean": "{0} geçerli bir boolean olmalı",
"validArray": "{0} geçerli bir dizi olmalı",
"stringMin": "{0} en az {1} karakter olmalı",
"numberMin": "{0} en az {1} olmalı"
},
"client": {
"id": "İstemci ID",
"name": "Ad",
"expiresAt": "Son Kullanma Tarihi",
"address4": "IPv4 Adresi",
"address6": "IPv6 Adresi",
"serverAllowedIps": "Sunucu İzin Verilen IP'ler"
},
"user": {
"username": "Kullanıcı Adı",
"password": "Şifre",
"remember": "Hatırla",
"name": "Ad",
"email": "E-posta",
"emailInvalid": "E-posta geçerli bir e-posta olmalı",
"passwordMatch": "Şifreler eşleşmeli",
"totpEnable": "TOTP Etkinleştir",
"totpEnableTrue": "TOTP Etkinleştir doğru olmalı",
"totpCode": "TOTP Kodu"
},
"userConfig": {
"host": "Ana Bilgisayar"
},
"general": {
"sessionTimeout": "Oturum Zaman Aşımı",
"metricsEnabled": "Metrikler",
"metricsPassword": "Metrik Şifresi"
},
"interface": {
"cidr": "CIDR",
"device": "Cihaz",
"cidrValid": "CIDR geçerli olmalı"
},
"otl": "Tek seferlik bağlantı",
"stringMalformed": "Dize hatalı biçimlendirilmiş",
"body": "Gövde geçerli bir nesne olmalı",
"hook": "Hook",
"enabled": "Etkin",
"mtu": "MTU",
"port": "Port",
"persistentKeepalive": "Kalıcı Keepalive",
"address": "IP Adresi",
"dns": "DNS",
"allowedIps": "İzin Verilen IP'ler",
"file": "Dosya"
},
"hooks": {
"preUp": "PreUp",
"postUp": "PostUp",
"preDown": "PreDown",
"postDown": "PostDown"
}
}
+286
View File
@@ -0,0 +1,286 @@
{
"pages": {
"me": "Обліковий запис",
"clients": "Клієнти",
"admin": {
"panel": "Панель адміністратора",
"general": "Загальні налаштування",
"config": "Конфігурація",
"interface": "Інтерфейс",
"hooks": "Hooks"
}
},
"user": {
"email": "Електронна пошта"
},
"me": {
"currentPassword": "Поточний пароль",
"enable2fa": "Увімкнути двофакторну автентифікацію",
"enable2faDesc": "Відскануйте QR-код за допомогою програми автентифікації або введіть ключ вручну.",
"2faKey": "TOTP Ключ",
"2faCodeDesc": "Введіть код з вашої програми автентифікатора.",
"disable2fa": "Вимкнути двофакторну автентифікацію",
"disable2faDesc": "Введіть свій пароль, щоб вимкнути двофакторну автентифікацію."
},
"general": {
"name": "Ім'я",
"username": "Ім'я користувача",
"password": "Пароль",
"newPassword": "Новий пароль",
"updatePassword": "Оновити пароль",
"mtu": "MTU",
"allowedIps": "Дозволені IP",
"dns": "DNS",
"persistentKeepalive": "Постійна підтримка активності",
"logout": "Вийти",
"continue": "Продовжити",
"host": "Хост",
"port": "Порт",
"yes": "Так",
"no": "Ні",
"confirmPassword": "Підтвердити пароль",
"loading": "Завантаження...",
"2fa": "Двофакторна автентифікація",
"2faCode": "TOTP код"
},
"setup": {
"welcome": "Ласкаво просимо до вашого першого налаштування wg-easy",
"welcomeDesc": "Ви знайшли найпростіший спосіб встановити та керувати WireGuard на будь-якому хості Linux",
"existingSetup": "Ви маєте існуючу конфігурацію?",
"createAdminDesc": "Спочатку введіть ім'я адміністратора та надійний пароль. Ці дані використовуватимуться для входу в панель адміністратора.",
"setupConfigDesc": "Введіть інформацію про хост і порт. Вона буде використана у конфігурації клієнта при налаштуванні WireGuard на їх пристроях.",
"setupMigrationDesc": "Будь ласка, надайте файл резервної копії, якщо ви хочете перенести дані з попередньої версії wg-easy до нової конфігурації.",
"upload": "Завантажити",
"migration": "Відновити резервну копію:",
"createAccount": "Створити обліковий запис",
"successful": "Налаштування успішне",
"hostDesc": "Публічне ім'я хоста для підключення клієнтів",
"portDesc": "Публічний UDP порт, на якому клієнти підключаються і який слухає WireGuard"
},
"update": {
"updateAvailable": "Доступне оновлення!",
"update": "Оновлення"
},
"theme": {
"dark": "Темна тема",
"light": "Світла тема",
"system": "Системна тема"
},
"layout": {
"toggleCharts": "Показати/приховати діаграми",
"donate": "Пожертвувати"
},
"login": {
"signIn": "Увійти",
"rememberMe": "Запам'ятай мене",
"rememberMeDesc": "Залишатися в системі після закриття браузера",
"insecure": "Ви не можете увійти через незахищене з'єднання. Використовуйте HTTPS.",
"2faRequired": "Потрібна двофакторна автентифікація",
"2faWrong": "Неправильний код двофакторної автентифікації"
},
"client": {
"empty": "Клієнтів поки немає.",
"newShort": "Новий",
"sort": "Сортувати",
"create": "Створити клієнта",
"created": "Клієнт створено",
"new": "Новий клієнт",
"name": "Ім'я",
"expireDate": "Термін дії",
"expireDateDesc": "Дата, коли клієнт буде відключений. Порожнє для постійного користування",
"delete": "Видалити",
"deleteClient": "Видалити клієнта",
"deleteDialog1": "Ви впевнені, що бажаєте видалити",
"deleteDialog2": "Цю дію неможливо скасувати.",
"enabled": "Увімкнено",
"address": "Адреса",
"serverAllowedIps": "Дозволені IP-адреси сервера",
"otlDesc": "Створити коротке одноразове посилання",
"permanent": "Постійний",
"createdOn": "Створено ",
"lastSeen": "Останнє підключення в ",
"totalDownload": "Всього завантажено: ",
"totalUpload": "Всього відправлено: ",
"newClient": "Новий клієнт",
"disableClient": "Вимкнути клієнта",
"enableClient": "Увімкнути клієнта",
"noPrivKey": "У цього клієнта відсутній приватний ключ. Неможливо створити конфігурацію.",
"showQR": "Показати QR-код",
"downloadConfig": "Завантажити конфігурацію",
"allowedIpsDesc": "Які IP-адреси будуть маршрутизовані через VPN (перевизначає глобальну конфігурацію)",
"serverAllowedIpsDesc": "Які IP-адреси сервер буде перенаправляти до клієнта",
"mtuDesc": "Встановлює максимальний розмір пакета (одиницю передачі) для VPN-тунелю",
"persistentKeepaliveDesc": "Встановлює інтервал (у секундах) для пакетів keep-alive. 0 вимикає його",
"hooks": "Hooks",
"hooksDescription": "Hooks працюють лише з wg-quick",
"hooksLeaveEmpty": "Тільки для wg-quick. Інакше залиште порожнім",
"dnsDesc": "DNS сервер, який використовуватимуть клієнти (перевизначає глобальну конфігурацію)",
"notConnected": "Клієнт не підключений",
"endpoint": "Кінцева точка",
"endpointDesc": "IP-адреса клієнта, з якої встановлюється з’єднання WireGuard",
"search": "Пошук клієнтів...",
"config": "Конфігурація",
"viewConfig": "Переглянути конфігурацію"
},
"dialog": {
"change": "Змінити",
"cancel": "Скасувати",
"create": "Створити"
},
"toast": {
"success": "Успіх",
"saved": "Збережено",
"error": "Помилка"
},
"form": {
"actions": "Дії",
"save": "Зберегти",
"revert": "Повернути",
"sectionGeneral": "Загальні",
"sectionAdvanced": "Додатково",
"noItems": "Немає елементів",
"nullNoItems": "Немає елементів. Використовується глобальна конфігурація",
"add": "Додати"
},
"admin": {
"general": {
"sessionTimeout": "Час очікування сеансу",
"sessionTimeoutDesc": "Тривалість сеансу для функції 'Запам'ятати мене' (секунди)",
"metrics": "Метрики",
"metricsPassword": "Пароль",
"metricsPasswordDesc": "Пароль Bearer для точки доступу метрик (пароль або хеш argon2)",
"json": "JSON",
"jsonDesc": "Маршрут для метрик у форматі JSON",
"prometheus": "Prometheus",
"prometheusDesc": "Маршрут для метрики Prometheus"
},
"config": {
"connection": "З'єднання",
"hostDesc": "Публічне ім'я хоста для підключення клієнтів (спрацьовує при зміні конфігурації)",
"portDesc": "Публічний UDP порт для підключення клієнтів (спрацьовує при зміні конфігурації, можливо, варто змінити порт інтерфейсу теж)",
"allowedIpsDesc": "Дозволені IP-адреси, які використовуватимуть клієнти (глобальна конфігурація)",
"dnsDesc": "DNS-сервера, який використовуватимуть клієнти (глобальну конфігурацію)",
"mtuDesc": "MTU, який використовуватимуть клієнти (лише для нових клієнтів)",
"persistentKeepaliveDesc": "Інтервал у секундах для надсилання keepalive на сервер. 0 = вимкнено (лише для нових клієнтів)",
"suggest": "Запропонувати",
"suggestDesc": "Виберіть IP-адресу або ім'я хоста для поля 'Хост'"
},
"interface": {
"cidrSuccess": "CIDR змінено",
"device": "Пристрій",
"deviceDesc": "Ethernet-пристрій, через який має проходити трафік WireGuard",
"mtuDesc": "MTU, яке використовуватиме WireGuard",
"portDesc": "UDP порт, який слухатиме WireGuard (ймовірно, варто змінити порт у конфігурації теж)",
"changeCidr": "Змінити CIDR",
"restart": "Перезавантажити інтерфейс",
"restartDesc": "Перезавантажити інтерфейс WireGuard",
"restartWarn": "Ви впевнені, що бажаєте перезавантажити інтерфейс? Це призведе до відключення всіх клієнтів.",
"restartSuccess": "Інтерфейс перезавантажено"
},
"introText": "Ласкаво просимо до панелі адміністратора.\n\nТут ви можете керувати загальними налаштуваннями, конфігурацією, налаштуваннями інтерфейсу та перехоплювачами.\n\nПочніть з вибору одного з розділів на боковій панелі."
},
"zod": {
"generic": {
"required": "{0} обов'язковий",
"validNumber": "{0} має бути дійсним числом",
"validString": "{0} має бути дійсним рядком",
"validBoolean": "{0} має бути дійсним логічним значенням",
"validArray": "{0} має бути дійсним масивом",
"stringMin": "{0} має містити щонайменше {1} символів",
"numberMin": "{0} має бути щонайменше {1}"
},
"client": {
"id": "Ідентифікатор клієнта",
"name": "Ім'я",
"expiresAt": "Термін дії закінчується о",
"address4": "IPv4-адреса",
"address6": "IPv6-адреса",
"serverAllowedIps": "Дозволені IP-адреси сервера"
},
"user": {
"username": "Ім'я користувача",
"password": "Пароль",
"remember": "Пам'ятати",
"name": "Ім'я",
"email": "Електронна пошта",
"emailInvalid": "Email має бути дійсною",
"passwordMatch": "Паролі мають збігатися",
"totpEnable": "Увімкнути TOTP",
"totpEnableTrue": "Увімкнення TOTP має бути true",
"totpCode": "TOTP Код"
},
"userConfig": {
"host": "Хост"
},
"general": {
"sessionTimeout": "Час очікування сеансу",
"metricsEnabled": "Метрики",
"metricsPassword": "Пароль метрик"
},
"interface": {
"cidr": "CIDR",
"device": "Пристрій",
"cidrValid": "CIDR має бути дійсним"
},
"otl": "Одноразове посилання",
"stringMalformed": "Рядок має неправильний формат",
"body": "Тіло має бути коректним об'єктом",
"hook": "Hook",
"enabled": "Увімкнено",
"mtu": "MTU",
"port": "Порт",
"persistentKeepalive": "Постійна підтримка активності",
"address": "IP-адреса",
"dns": "DNS",
"allowedIps": "Дозволені IP-адреси",
"file": "Файл"
},
"hooks": {
"preUp": "PreUp",
"postUp": "PostUp",
"preDown": "PreDown",
"postDown": "PostDown"
},
"copy": {
"notSupported": "Копіювання не підтримується",
"copied": "Скопійовано!",
"failed": "Не вдалося скопіювати",
"copy": "Копіювати"
},
"awg": {
"jCLabel": "Кількість сміттєвих пакетів (Jc)",
"jCDescription": "Кількість сміттєвих пакетів для відправки (1–128, рекомендовано: 4–12)",
"jMinLabel": "Мінімальний розмір сміттєвого пакета (Jmin)",
"jMinDescription": "Мінімальний розмір сміттєвих пакетів (0–1279*, рекомендовано: 8, має бути < Jmax)",
"jMaxLabel": "Максимальний розмір сміттєвого пакета (Jmax)",
"jMaxDescription": "Максимальний розмір сміттєвих пакетів (1–1280*, рекомендовано: 80, має бути > Jmin)",
"s1Label": "Розмір сміттєвих даних у початковому пакеті (S1)",
"s1Description": "Розмір сміттєвих даних у початковому пакеті (0–1132 [1280* - 148 = 1132], рекомендовано: 15150, S1+56 ≠ S2)",
"s2Label": "Розмір сміттєвих даних у пакеті відповіді (S2)",
"s2Description": "Розмір сміттєвих даних у пакеті відповіді (0–1188 [1280* - 92 = 1188], рекомендовано: 15–150)",
"s3Label": "Розмір сміттєвих даних у пакеті «cookie reply» (S3)",
"s3Description": "Розмір сміттєвих даних у пакеті «cookie reply»",
"s4Label": "Розмір сміттєвих даних у транспортному пакеті (S4)",
"s4Description": "Розмір сміттєвих даних у транспортному пакеті",
"i1Label": "Спеціальний сміттєвий пакет 1 (I1)",
"i1Description": "Пакет-імітація протоколу у hex-форматі: <b 0x...>",
"i2Label": "Спеціальний сміттєвий пакет 2 (I2)",
"i2Description": "Пакет-імітація протоколу у hex-форматі: <b 0x...>",
"i3Label": "Спеціальний сміттєвий пакет 3 (I3)",
"i3Description": "Пакет-імітація протоколу у hex-форматі: <b 0x...>",
"i4Label": "Спеціальний сміттєвий пакет 4 (I4)",
"i4Description": "Пакет-імітація протоколу у hex-форматі: <b 0x...>",
"i5Label": "Спеціальний сміттєвий пакет 5 (I5)",
"i5Description": "Пакет-імітація протоколу у hex-форматі: <b 0x...>",
"h1Label": "Початковий магічний заголовок (H1)",
"h1Description": "Значення заголовка початкового пакета (5–2147483647, має бути унікальним від H2–H4)",
"h2Label": "Магічний заголовок відповіді (H2)",
"h2Description": "Значення заголовка пакета відповіді (5–2147483647, має бути унікальним від H1, H3, H4)",
"h3Label": "Магічний заголовок «cookie reply» (H3)",
"h3Description": "Значення заголовка пакета «cookie reply» (52147483647, має бути унікальним від H1, H2, H4)",
"h4Label": "Магічний заголовок транспортного пакета (H4)",
"h4Description": "Значення заголовка транспортного пакета (5–2147483647, має бути унікальним від H1–H3)",
"mtuNote": "Значення залежать від MTU",
"obfuscationParameters": "Параметри обфускації AmneziaWG"
}
}
+286
View File
@@ -0,0 +1,286 @@
{
"pages": {
"me": "账户管理",
"clients": "客户端管理",
"admin": {
"panel": "管理面板",
"general": "通用设置",
"config": "网络配置",
"interface": "接口配置",
"hooks": "钩子脚本"
}
},
"user": {
"email": "电子邮箱"
},
"me": {
"currentPassword": "当前密码",
"enable2fa": "启用双重认证",
"enable2faDesc": "使用认证器应用扫描二维码或手动输入密钥进行配置",
"2faKey": "TOTP密钥",
"2faCodeDesc": "请输入您的认证器应用生成的验证码",
"disable2fa": "禁用双重认证",
"disable2faDesc": "您需要输入当前密码来禁用双重认证功能"
},
"general": {
"name": "名称",
"username": "用户名",
"password": "密码",
"newPassword": "新密码",
"updatePassword": "更新密码",
"mtu": "MTU",
"allowedIps": "允许的IP",
"dns": "DNS",
"persistentKeepalive": "保活间隔",
"logout": "注销登录",
"continue": "继续",
"host": "主机",
"port": "端口",
"yes": "是",
"no": "否",
"confirmPassword": "确认密码",
"loading": "加载中...",
"2fa": "双重认证",
"2faCode": "验证码"
},
"setup": {
"welcome": "欢迎使用wg-easy安装向导",
"welcomeDesc": "您正在使用最简单的WireGuard Linux主机安装和管理方案",
"existingSetup": "是否已有现有配置?",
"createAdminDesc": "请首先输入管理员用户名和强密码。这些信息将用于登录管理面板。",
"setupConfigDesc": "请输入服务器主机和端口信息。这些设置将用于客户端设备连接WireGuard时的配置。",
"setupMigrationDesc": "如果您希望从旧版wg-easy迁移数据到新安装,请提供备份文件。",
"upload": "上传文件",
"migration": "从备份恢复配置:",
"createAccount": "创建账户",
"successful": "安装配置成功",
"hostDesc": "客户端将连接到的公共主机名或IP地址",
"portDesc": "客户端将连接到的公共UDP端口,也是WireGuard服务监听的端口"
},
"update": {
"updateAvailable": "检测到可用更新!",
"update": "立即更新"
},
"theme": {
"dark": "深色模式",
"light": "浅色模式",
"system": "系统默认"
},
"layout": {
"toggleCharts": "显示/隐藏 流量图表",
"donate": "捐赠支持"
},
"login": {
"signIn": "登录系统",
"rememberMe": "记住我",
"rememberMeDesc": "关闭浏览器后保持登录状态",
"insecure": "无法通过不安全连接登录。请使用HTTPS。",
"2faRequired": "需要进行双重认证",
"2faWrong": "双重认证验证码错误"
},
"client": {
"empty": "当前没有客户端配置",
"newShort": "新建",
"sort": "排序",
"create": "创建客户端",
"created": "客户端创建成功",
"new": "新建客户端",
"name": "客户端名称",
"expireDate": "过期日期",
"expireDateDesc": "客户端将被自动禁用的日期。留空表示永久有效",
"delete": "删除客户端",
"deleteClient": "删除客户端",
"deleteDialog1": "您确定要删除客户端",
"deleteDialog2": "此操作无法撤销。",
"enabled": "已启用",
"address": "IP地址",
"serverAllowedIps": "服务端允许的IP",
"otlDesc": "生成一次性使用的短链接配置",
"permanent": "永久有效",
"createdOn": "创建于 ",
"lastSeen": "最后在线时间 ",
"totalDownload": "总下载流量: ",
"totalUpload": "总上传流量: ",
"newClient": "新建客户端",
"disableClient": "禁用客户端",
"enableClient": "启用客户端",
"noPrivKey": "此客户端没有已知的私钥,无法创建配置文件",
"showQR": "显示二维码",
"downloadConfig": "下载配置文件",
"allowedIpsDesc": "指定将通过VPN路由的IP地址(覆盖全局配置)",
"serverAllowedIpsDesc": "指定服务端将路由到客户端的IP地址范围",
"mtuDesc": "设置VPN隧道的MTU(最大传输单元)",
"persistentKeepaliveDesc": "设置保活数据包的发送间隔(秒)。0表示禁用",
"hooks": "钩子脚本",
"hooksDescription": "钩子脚本仅在使用wg-quick时有效",
"hooksLeaveEmpty": "如果不使用wg-quick,请留空此字段",
"dnsDesc": "客户端将使用的 DNS 服务器(将覆盖全局配置)",
"notConnected": "客户端未连接",
"endpoint": "端点",
"endpointDesc": "建立 WireGuard 连接时客户端的 IP 地址",
"search": "搜索客户端...",
"config": "配置",
"viewConfig": "查看配置文本"
},
"dialog": {
"change": "确认修改",
"cancel": "取消",
"create": "创建"
},
"toast": {
"success": "操作成功",
"saved": "保存成功",
"error": "发生错误"
},
"form": {
"actions": "操作",
"save": "保存更改",
"revert": "恢复默认",
"sectionGeneral": "基本配置",
"sectionAdvanced": "高级选项",
"noItems": "未配置",
"nullNoItems": "未配置。将使用全局配置",
"add": "添加"
},
"admin": {
"general": {
"sessionTimeout": "会话超时时间",
"sessionTimeoutDesc": "'记住我'功能的会话持续时间(秒)",
"metrics": "监控指标",
"metricsPassword": "密码",
"metricsPasswordDesc": "用于监控端点的Bearer密码(支持密码或Argon2哈希)",
"json": "JSON格式",
"jsonDesc": "获取JSON格式的监控数据路由",
"prometheus": "Prometheus格式",
"prometheusDesc": "获取Prometheus格式监控数据的路由"
},
"config": {
"connection": "连接设置",
"hostDesc": "客户端将连接到的公共主机名(修改会使现有配置失效)",
"portDesc": "客户端将连接到的公共UDP端口(修改会使现有配置失效,通常需要同时修改接口端口)",
"allowedIpsDesc": "客户端使用的全局允许的IP范围",
"dnsDesc": "客户端使用的全局DNS设置",
"mtuDesc": "新客户端将使用的MTU(仅影响新客户端)",
"persistentKeepaliveDesc": "向服务器发送保活数据包的间隔秒数。0表示禁用(仅影响新客户端)",
"suggest": "检测",
"suggestDesc": "为'主机'字段选择IP地址或主机名"
},
"interface": {
"cidrSuccess": "CIDR修改成功",
"device": "网络设备",
"deviceDesc": "用于转发WireGuard流量的以太网设备",
"mtuDesc": "WireGuard接口使用的MTU",
"portDesc": "WireGuard监听的UDP端口(通常需要同时修改配置端口)",
"changeCidr": "修改CIDR",
"restart": "重启接口",
"restartDesc": "重新启动WireGuard接口",
"restartWarn": "确定要重启接口吗?这将断开所有客户端的连接。",
"restartSuccess": "接口重启成功"
},
"introText": "欢迎使用管理控制台。\n\n您可以在这里管理通用设置、网络配置、接口配置和钩子脚本。\n\n请从侧边栏选择一个功能模块开始。"
},
"zod": {
"generic": {
"required": "{0}是必填项",
"validNumber": "{0}必须是有效数字",
"validString": "{0}必须是有效文本",
"validBoolean": "{0}必须是是/否选项",
"validArray": "{0}必须是有效数组",
"stringMin": "{0}至少需要{1}个字符",
"numberMin": "{0}不能小于{1}"
},
"client": {
"id": "客户端ID",
"name": "客户端名称",
"expiresAt": "过期时间",
"address4": "IPv4地址",
"address6": "IPv6地址",
"serverAllowedIps": "服务端允许的IP"
},
"user": {
"username": "用户名",
"password": "密码",
"remember": "记住登录",
"name": "姓名",
"email": "电子邮箱",
"emailInvalid": "请输入有效的电子邮箱地址",
"passwordMatch": "两次输入的密码必须一致",
"totpEnable": "启用TOTP",
"totpEnableTrue": "必须启用双重认证",
"totpCode": "验证码"
},
"userConfig": {
"host": "服务器地址"
},
"general": {
"sessionTimeout": "会话超时",
"metricsEnabled": "启用监控",
"metricsPassword": "监控密码"
},
"interface": {
"cidr": "CIDR",
"device": "网络设备",
"cidrValid": "CIDR必须有效"
},
"otl": "一次性链接",
"stringMalformed": "文本格式错误",
"body": "请求体必须是有效对象",
"hook": "钩子脚本",
"enabled": "启用状态",
"mtu": "MTU",
"port": "端口",
"persistentKeepalive": "保活间隔",
"address": "IP地址",
"dns": "DNS",
"allowedIps": "允许的IP",
"file": "文件"
},
"hooks": {
"preUp": "启动前脚本",
"postUp": "启动后脚本",
"preDown": "停止前脚本",
"postDown": "停止后脚本"
},
"copy": {
"notSupported": "不支持复制",
"copied": "已复制!",
"failed": "复制失败",
"copy": "复制"
},
"awg": {
"jCLabel": "垃圾数据包计数(Jc",
"jCDescription": "发送的垃圾数据包数量(范围:1-128,推荐值:4-12",
"jMinLabel": "垃圾数据包最小尺寸(Jmin",
"jMinDescription": "垃圾数据包的最小尺寸(范围:0-1279*,推荐值:8,必须小于 Jmax",
"jMaxLabel": "垃圾数据包最大尺寸(Jmax",
"jMaxDescription": "垃圾数据包的最大尺寸(范围:1-1280*,推荐值:80,必须大于 Jmin",
"s1Label": "初始数据包垃圾数据大小(S1)",
"s1Description": "初始数据包中垃圾数据的大小(范围:0-1132[1280* - 148 = 1132],推荐值:15-150S1+56 ≠ S2",
"s2Label": "响应数据包垃圾数据大小(S2)",
"s2Description": "响应数据包中垃圾数据的大小(范围:0-1188[1280* - 92 = 1188],推荐值:15-150",
"s3Label": "Cookie 回复数据包垃圾数据大小(S3)",
"s3Description": "Cookie 回复数据包中垃圾数据的大小",
"s4Label": "传输数据包垃圾数据大小(S4)",
"s4Description": "传输数据包中垃圾数据的大小",
"i1Label": "特殊垃圾数据包 1I1",
"i1Description": "协议模拟数据包(十六进制格式):<b 0x...>",
"i2Label": "特殊垃圾数据包 2I2",
"i2Description": "协议模拟数据包(十六进制格式):<b 0x...>",
"i3Label": "特殊垃圾数据包 3I3",
"i3Description": "协议模拟数据包(十六进制格式):<b 0x...>",
"i4Label": "特殊垃圾数据包 4I4",
"i4Description": "协议模拟数据包(十六进制格式):<b 0x...>",
"i5Label": "特殊垃圾数据包 5I5",
"i5Description": "协议模拟数据包(十六进制格式):<b 0x...>",
"h1Label": "初始数据包魔术头部(H1",
"h1Description": "初始数据包头部值(范围:5-2147483647,必须与 H2-H4 不同)",
"h2Label": "响应数据包魔术头部(H2",
"h2Description": "响应数据包头部值(范围:5-2147483647,必须与 H1、H3、H4 不同)",
"h3Label": "Cookie 回复数据包魔术头部(H3",
"h3Description": "Cookie 回复数据包头部值(范围:5-2147483647,必须与 H1、H2、H4 不同)",
"h4Label": "传输数据包魔术头部(H4",
"h4Description": "传输数据包头部值(范围:5-2147483647,必须与 H1-H3 不同)",
"mtuNote": "具体数值取决于 MTU(最大传输单元)",
"obfuscationParameters": "AmneziaWG 混淆参数"
}
}
+238
View File
@@ -0,0 +1,238 @@
{
"pages": {
"me": "帳戶",
"clients": "客戶端",
"admin": {
"panel": "管理員版面",
"general": "一般設定",
"config": "配置設定",
"interface": "介面設定",
"hooks": "掛鉤設定"
}
},
"user": {
"email": "電郵"
},
"me": {
"currentPassword": "目前密碼",
"enable2fa": "啟用雙重認證",
"enable2faDesc": "使用認證應用程式掃描二維碼,或手動輸入密匙。",
"2faKey": "TOTP密匙",
"2faCodeDesc": "請輸入認證應用程式中的驗證碼。",
"disable2fa": "停用雙重認證",
"disable2faDesc": "請輸入密碼以停用雙重認證。"
},
"general": {
"name": "名稱",
"username": "用戶名",
"password": "密碼",
"newPassword": "新密碼",
"updatePassword": "更改密碼",
"mtu": "MTU",
"allowedIps": "IP白名單",
"dns": "域名系統",
"persistentKeepalive": "保持連線",
"logout": "登出",
"continue": "繼續",
"host": "主機",
"port": "連接埠",
"yes": "是",
"no": "否",
"confirmPassword": "確認新密碼",
"loading": "載入中...",
"2fa": "雙重認證",
"2faCode": "TOTP驗證碼"
},
"setup": {
"welcome": "歡迎首次設定wg-easy",
"welcomeDesc": "這是最簡單的方法讓你在任何Linux主機上安裝及管理WireGuard",
"existingSetup": "你有現存設定嗎?",
"createAdminDesc": "請輸入管理員用戶名及一個高強度密碼。這些資料將用於登入管理員版面。",
"setupConfigDesc": "請輸入主機及連接埠資料。這將用於客戶端設定,以便在他們的裝置上設定WireGuard。",
"setupMigrationDesc": "如果你想將舊版wg-easy的資料轉移到新設定,請提供備份檔案。",
"upload": "上傳",
"migration": "還原備份:",
"createAccount": "建立帳戶",
"successful": "設定成功",
"hostDesc": "客戶端連接的公共主機名稱",
"portDesc": "客戶端和WireGuard使用的公共UDP連接埠"
},
"update": {
"updateAvailable": "有新版本更新!",
"update": "更新"
},
"theme": {
"dark": "深色模式",
"light": "淺色模式",
"system": "系統預設"
},
"layout": {
"toggleCharts": "顯示或隱藏圖表",
"donate": "贊助"
},
"login": {
"signIn": "登入",
"rememberMe": "保持登入",
"rememberMeDesc": "關閉瀏覽器後仍保持登入",
"insecure": "連線不安全,請使用HTTPS。",
"2faRequired": "需要雙重認證",
"2faWrong": "雙重認證失敗"
},
"client": {
"empty": "目前沒有客戶端。",
"newShort": "新增",
"sort": "排序",
"create": "建立客戶端",
"created": "客戶端已建立",
"new": "新增客戶端",
"name": "名稱",
"expireDate": "有效期",
"expireDateDesc": "客戶端將於此日期停用。留空則為永久有效",
"deleteClient": "刪除客戶端",
"deleteDialog1": "你確定要刪除",
"deleteDialog2": "此操作無法還原。",
"enabled": "已啟用",
"address": "IP地址",
"serverAllowedIps": "伺服器IP白名單",
"otlDesc": "生成短暫單次超連結",
"permanent": "永久",
"createdOn": "建立於",
"lastSeen": "上次活動於",
"totalDownload": "總下載量:",
"totalUpload": "總上傳量:",
"newClient": "新客戶端",
"disableClient": "停用客戶端",
"enableClient": "啟用客戶端",
"noPrivKey": "此客戶端沒有已知的密匙。無法建立配置。",
"showQR": "顯示二維碼",
"downloadConfig": "下載配置",
"allowedIpsDesc": "通過VPN的IP地址(取代全局配置)",
"serverAllowedIpsDesc": "伺服器路由到客戶端的IP地址",
"mtuDesc": "設定VPN隧道的最大傳輸單位(封包大小)",
"persistentKeepaliveDesc": "設定保持連線封包的秒數間隔。0代表停用",
"hooks": "掛鉤",
"hooksDescription": "掛鉤僅適用於wg-quick",
"hooksLeaveEmpty": "僅適用於wg-quick,否則請留空",
"dnsDesc": "客戶端使用的域名系統伺服器(取代全局配置)",
"search": "搜尋客戶端..."
},
"dialog": {
"change": "更改",
"cancel": "取消",
"create": "創建"
},
"toast": {
"success": "成功",
"saved": "已保存",
"error": "錯誤"
},
"form": {
"actions": "操作",
"save": "保存",
"revert": "重置",
"sectionGeneral": "一般設定",
"sectionAdvanced": "進階",
"noItems": "未有設定",
"nullNoItems": "未有設定,使用全局配置",
"add": "新增"
},
"admin": {
"general": {
"sessionTimeout": "工作階段逾時",
"sessionTimeoutDesc": "「保持登入」的工作階段持續時間(秒)",
"metrics": "指標",
"metricsPassword": "密碼",
"metricsPasswordDesc": "指標端點的Bearer密碼(密碼或argon2雜湊)",
"json": "JSON",
"jsonDesc": "JSON格式指標的路由",
"prometheus": "Prometheus",
"prometheusDesc": "Prometheus指標的路由"
},
"config": {
"connection": "連線",
"hostDesc": "客戶端連接的公共主機名稱(使配置無效)",
"portDesc": "客戶端連接的公共UDP連接埠(使配置無效,你可能也想更改介面連接埠)",
"allowedIpsDesc": "客戶端使用的IP白名單(全局配置)",
"dnsDesc": "客戶端使用的域名系統伺服器(全局配置)",
"mtuDesc": "客戶端使用的MTU(僅適用於新客戶端)",
"persistentKeepaliveDesc": "向伺服器發送保持連線封包的秒數間隔。0代表停用(僅適用於新客戶端)",
"suggest": "建議",
"suggestDesc": "選擇一個IP地址或主機名稱"
},
"interface": {
"cidrSuccess": "成功更改CIDR",
"device": "裝置",
"deviceDesc": "WireGuard流量通過的乙太網路裝置",
"mtuDesc": "WireGuard使用的MTU",
"portDesc": "WireGuard監聽的UDP連接埠 (你可能也想更改設定連接埠)",
"changeCidr": "更改CIDR",
"restart": "重啟介面",
"restartDesc": "重啟WireGuard介面",
"restartWarn": "你確定要重新啟動介面嗎?這將中斷所有客戶端連線。",
"restartSuccess": "介面已重啟"
},
"introText": "歡迎來到管理員版面。\n\n你可以在側邊欄中管理一般、配置、介面和掛鉤設定。"
},
"zod": {
"generic": {
"required": "{0}為必填項",
"validNumber": "{0}必須是有效的數字",
"validString": "{0}必須是有效的字串",
"validBoolean": "{0}必須是有效的布林值",
"validArray": "{0}必須是有效的陣列",
"stringMin": "{0}至少需要{1}個字元",
"numberMin": "{0}至少為{1}"
},
"client": {
"id": "客戶端ID",
"name": "名稱",
"expiresAt": "到期於",
"address4": "IPv4地址",
"address6": "IPv6地址",
"serverAllowedIps": "伺服器IP白名單"
},
"user": {
"username": "用戶名",
"password": "密碼",
"remember": "保持",
"name": "名稱",
"email": "電郵",
"emailInvalid": "必須是有效的電郵地址",
"passwordMatch": "密碼必須一致",
"totpEnable": "TOTP啟用",
"totpEnableTrue": "TOTP啟用必須為正確",
"totpCode": "TOTP驗證碼"
},
"userConfig": {
"host": "主機"
},
"general": {
"sessionTimeout": "工作階段逾時",
"metricsEnabled": "指標",
"metricsPassword": "指標密碼"
},
"interface": {
"cidr": "CIDR",
"device": "裝置",
"cidrValid": "CIDR必須有效"
},
"otl": "單次超連結",
"stringMalformed": "字串格式不正確",
"body": "主體必須是有效的物件",
"hook": "掛鉤",
"enabled": "已啟動",
"mtu": "MTU",
"port": "連接埠",
"persistentKeepalive": "保持連線",
"address": "IP地址",
"dns": "域名系統",
"allowedIps": "IP白名單",
"file": "文件"
},
"hooks": {
"preUp": "PreUp",
"postUp": "PostUp",
"preDown": "PreDown",
"postDown": "PostDown"
}
}
+286
View File
@@ -0,0 +1,286 @@
{
"pages": {
"me": "帳戶",
"clients": "用戶端",
"admin": {
"panel": "管理面板",
"general": "一般設定",
"config": "組態設定",
"interface": "介面設定",
"hooks": "Hook 設定"
}
},
"user": {
"email": "電子郵件"
},
"me": {
"currentPassword": "目前密碼",
"enable2fa": "啟用兩步驟驗證",
"enable2faDesc": "請使用您的驗證碼應用程式掃描 QR Code,或手動輸入金鑰。",
"2faKey": "TOTP 金鑰",
"2faCodeDesc": "請輸入驗證碼應用程式提供的驗證碼。",
"disable2fa": "停用兩步驟驗證",
"disable2faDesc": "請輸入您的密碼以停用兩步驟驗證。"
},
"general": {
"name": "名稱",
"username": "使用者名稱",
"password": "密碼",
"newPassword": "新密碼",
"updatePassword": "更新密碼",
"mtu": "MTU",
"allowedIps": "允許的 IP",
"dns": "DNS",
"persistentKeepalive": "保持連線",
"logout": "登出",
"continue": "繼續",
"host": "主機",
"port": "連接埠",
"yes": "是",
"no": "否",
"confirmPassword": "確認密碼",
"loading": "正在載入...",
"2fa": "兩步驟驗證",
"2faCode": "TOTP 驗證碼"
},
"setup": {
"welcome": "歡迎首次設定您的 wg-easy",
"welcomeDesc": "這是您在任何 Linux 主機上安裝與管理 WireGuard 最簡單的方式",
"existingSetup": "您已有現存的設定了嗎?",
"createAdminDesc": "請先輸入管理員使用者名稱與高強度密碼。此資訊將用於登入管理面板。",
"setupConfigDesc": "請輸入主機與連接埠資訊。此資訊將用於設定用戶端的 WireGuard 連線。",
"setupMigrationDesc": "若要從先前的 wg-easy 版本移轉資料,請提供備份檔案。",
"upload": "上傳",
"migration": "還原備份:",
"createAccount": "建立帳戶",
"successful": "設定成功",
"hostDesc": "用戶端將連線的公開主機名稱",
"portDesc": "用戶端將連線的公開 UDP 連接埠,且 WireGuard 會在此監聽"
},
"update": {
"updateAvailable": "已有更新可供使用!",
"update": "更新"
},
"theme": {
"dark": "深色佈景主題",
"light": "淺色佈景主題",
"system": "系統佈景主題"
},
"layout": {
"toggleCharts": "顯示/隱藏圖表",
"donate": "贊助"
},
"login": {
"signIn": "登入",
"rememberMe": "記住我",
"rememberMeDesc": "關閉瀏覽器後仍保持登入狀態",
"insecure": "您無法在不安全的連線下登入。請使用 HTTPS。",
"2faRequired": "需要兩步驟驗證",
"2faWrong": "兩步驟驗證碼不正確"
},
"client": {
"empty": "尚無用戶端。",
"newShort": "新增",
"sort": "排序",
"create": "建立用戶端",
"created": "已建立用戶端",
"new": "新增用戶端",
"name": "名稱",
"expireDate": "到期日",
"expireDateDesc": "用戶端將被停用的日期。留白表示永久有效",
"delete": "刪除",
"deleteClient": "刪除用戶端",
"deleteDialog1": "您確定要刪除",
"deleteDialog2": "此動作無法復原。",
"enabled": "啟用",
"address": "位址",
"serverAllowedIps": "伺服器允許的 IP",
"otlDesc": "產生暫時性單次連結",
"permanent": "永久",
"createdOn": "建立於 ",
"lastSeen": "上次連線於 ",
"totalDownload": "總下載量: ",
"totalUpload": "總上傳量: ",
"newClient": "新增用戶端",
"disableClient": "停用用戶端",
"enableClient": "啟用用戶端",
"noPrivKey": "此用戶端沒有已知的私密金鑰,無法建立設定。",
"showQR": "顯示 QR Code",
"downloadConfig": "下載組態設定檔",
"allowedIpsDesc": "將透過 VPN 路由的 IP (會覆寫全域設定)",
"serverAllowedIpsDesc": "伺服器將路由至用戶端的 IP",
"mtuDesc": "設定 VPN 通道的最大傳輸單位 (封包大小)",
"persistentKeepaliveDesc": "Keep-alive 封包的間隔秒數。0 表示停用",
"hooks": "Hook 設定",
"hooksDescription": "Hook 設定僅適用於 wg-quick",
"hooksLeaveEmpty": "僅適用於 wg-quick,否則請保持空白",
"dnsDesc": "用戶端使用的 DNS 伺服器 (會覆寫全域設定)",
"notConnected": "用戶端未連線",
"endpoint": "端點",
"endpointDesc": "用戶端建立 WireGuard 連線的來源 IP",
"search": "搜尋用戶端...",
"config": "組態設定",
"viewConfig": "檢視組態設定"
},
"dialog": {
"change": "變更",
"cancel": "取消",
"create": "建立"
},
"toast": {
"success": "成功",
"saved": "已儲存",
"error": "錯誤"
},
"form": {
"actions": "操作",
"save": "儲存",
"revert": "還原",
"sectionGeneral": "一般設定",
"sectionAdvanced": "進階設定",
"noItems": "沒有項目",
"nullNoItems": "沒有項目。使用全域設定",
"add": "新增"
},
"admin": {
"general": {
"sessionTimeout": "工作階段逾時",
"sessionTimeoutDesc": "「記住我」的工作階段持續時間 (秒)",
"metrics": "計量",
"metricsPassword": "密碼",
"metricsPasswordDesc": "計量端點的 Bearer 密碼 (密碼或 argon2 雜湊)",
"json": "JSON",
"jsonDesc": "提供 JSON 格式計量的路由",
"prometheus": "Prometheus",
"prometheusDesc": "提供 Prometheus 計量的路由"
},
"config": {
"connection": "連線",
"hostDesc": "用戶端將連線的公開主機名稱 (變更後會使目前組態設定檔失效)",
"portDesc": "用戶端將連線的公開 UDP 連接埠 (變更後會使目前組態設定檔失效,您可能也需要變更介面連接埠)",
"allowedIpsDesc": "用戶端將使用的允許 IP (全域設定)",
"dnsDesc": "用戶端將使用的 DNS 伺服器 (全域設定)",
"mtuDesc": "用戶端使用的 MTU (僅適用於新用戶端)",
"persistentKeepaliveDesc": "傳送 keepalive 的間隔秒數。以 0 表示停用 (僅適用於新用戶端)",
"suggest": "建議",
"suggestDesc": "為主機欄位選擇 IP 位址或主機名稱"
},
"interface": {
"cidrSuccess": "已變更 CIDR",
"device": "裝置",
"deviceDesc": "用於轉送 WireGuard 流量的乙太網路裝置",
"mtuDesc": "WireGuard 將使用的 MTU",
"portDesc": "WireGuard 監聽的 UDP 連接埠 (您可能也需要變更連接埠組態設定檔)",
"changeCidr": "變更 CIDR",
"restart": "重新啟動介面",
"restartDesc": "重新啟動 WireGuard 介面",
"restartWarn": "您確定要重新啟動介面嗎? 所有用戶端將被中斷連線。",
"restartSuccess": "介面已重新啟動"
},
"introText": "歡迎使用管理面板。\n\n您可在此管理一般、組態、介面與 Hook 設定。\n\n請從側邊欄選擇任一項目開始。"
},
"zod": {
"generic": {
"required": "{0} 為必填項目",
"validNumber": "{0} 必須為有效的數字",
"validString": "{0} 必須為有效的字串",
"validBoolean": "{0} 必須為有效的布林值",
"validArray": "{0} 必須為有效的陣列",
"stringMin": "{0} 至少需要 {1} 個字元",
"numberMin": "{0} 不能小於 {1}"
},
"client": {
"id": "用戶端 ID",
"name": "名稱",
"expiresAt": "到期時間",
"address4": "IPv4 位址",
"address6": "IPv6 位址",
"serverAllowedIps": "伺服器允許的 IP"
},
"user": {
"username": "使用者名稱",
"password": "密碼",
"remember": "記住我",
"name": "名稱",
"email": "電子郵件",
"emailInvalid": "電子郵件格式無效",
"passwordMatch": "密碼必須一致",
"totpEnable": "啟用 TOTP",
"totpEnableTrue": "必須啟用 TOTP",
"totpCode": "TOTP 驗證碼"
},
"userConfig": {
"host": "主機"
},
"general": {
"sessionTimeout": "工作階段逾時",
"metricsEnabled": "計量",
"metricsPassword": "計量密碼"
},
"interface": {
"cidr": "CIDR",
"device": "裝置",
"cidrValid": "CIDR 格式無效"
},
"otl": "單次連結",
"stringMalformed": "字串格式錯誤",
"body": "Body 必須為有效的物件",
"hook": "Hook",
"enabled": "啟用",
"mtu": "MTU",
"port": "連接埠",
"persistentKeepalive": "保持連線",
"address": "IP 位址",
"dns": "DNS",
"allowedIps": "允許的 IP",
"file": "檔案"
},
"hooks": {
"preUp": "PreUp",
"postUp": "PostUp",
"preDown": "PreDown",
"postDown": "PostDown"
},
"copy": {
"notSupported": "無法複製",
"copied": "已複製!",
"failed": "複製失敗",
"copy": "複製"
},
"awg": {
"jCLabel": "填充封包數量 (Jc)",
"jCDescription": "要傳送的填充封包數量 (1-128,建議: 4-12)",
"jMinLabel": "填充封包最小大小 (Jmin)",
"jMinDescription": "填充封包的最小大小 (0-1279*,建議: 8,必須小於 Jmax)",
"jMaxLabel": "填充封包最大大小 (Jmax)",
"jMaxDescription": "填充封包的最大大小 (1-1280*,建議: 80,必須大於 Jmin)",
"s1Label": "初始封包填充大小 (S1)",
"s1Description": "初始封包填充大小 (0-1132 [1280* - 148 = 1132],建議: 15-150S1+56 ≠ S2)",
"s2Label": "回應封包填充大小 (S2)",
"s2Description": "回應封包填充大小 (0-1188 [1280* - 92 = 1188],建議: 15-150)",
"s3Label": "Cookie 回覆封包填充大小 (S3)",
"s3Description": "Cookie 回覆封包填充大小",
"s4Label": "傳輸封包填充大小 (S4)",
"s4Description": "傳輸封包填充大小",
"i1Label": "特殊填充封包 1 (I1)",
"i1Description": "協定模仿封包 (16 進位格式): <b 0x...>",
"i2Label": "特殊填充封包 2 (I2)",
"i2Description": "協定模仿封包 (16 進位格式): <b 0x...>",
"i3Label": "特殊填充封包 3 (I3)",
"i3Description": "協定模仿封包 (16 進位格式): <b 0x...>",
"i4Label": "特殊填充封包 4 (I4)",
"i4Description": "協定模仿封包 (16 進位格式): <b 0x...>",
"i5Label": "特殊填充封包 5 (I5)",
"i5Description": "協定模仿封包 (16 進位格式): <b 0x...>",
"h1Label": "初始特徵標頭 (H1)",
"h1Description": "初始封包標頭值 (5-2147483647,必須與 H2-H4 不同)",
"h2Label": "回應特徵標頭 (H2)",
"h2Description": "回應封包標頭值 (5-2147483647,必須與 H1、H3、H4 不同)",
"h3Label": "Cookie 回覆特徵標頭 (H3)",
"h3Description": "Cookie 回覆封包標頭值 (5-2147483647,必須與 H1、H2、H4 不同)",
"h4Label": "傳輸特徵標頭 (H4)",
"h4Description": "傳輸封包標頭值 (5-2147483647,必須與 H1-H3 不同)",
"mtuNote": "數值取決於 MTU",
"obfuscationParameters": "AmneziaWG 混淆參數"
}
}
+100 -7
View File
@@ -5,7 +5,7 @@ export default defineNuxtConfig({
future: {
compatibilityVersion: 4,
},
compatibilityDate: '2025-02-04',
compatibilityDate: '2026-02-06',
devtools: { enabled: true },
modules: [
'@nuxtjs/i18n',
@@ -13,7 +13,9 @@ export default defineNuxtConfig({
'@pinia/nuxt',
'@eschricht/nuxt-color-mode',
'radix-vue/nuxt',
'@vueuse/nuxt',
'@nuxt/eslint',
'@nuxt/test-utils/module',
],
colorMode: {
preference: 'system',
@@ -26,14 +28,108 @@ export default defineNuxtConfig({
experimental: {
localeDetector: './localeDetector.ts',
},
// https://wg-easy.github.io/wg-easy/latest/contributing/translation/
locales: [
{
// same as i18n.config.ts
code: 'en',
// BCP 47 language tag
language: 'en-US',
name: 'English',
},
{
code: 'de',
language: 'de-DE',
name: 'Deutsch',
},
{
code: 'es',
language: 'es-ES',
name: 'Español',
},
{
code: 'it',
language: 'it-IT',
name: 'Italiano',
},
{
code: 'fr',
language: 'fr-FR',
name: 'Français',
},
{
code: 'ko',
language: 'ko-KR',
name: '한국어',
},
{
code: 'ru',
language: 'ru-RU',
name: 'Русский',
},
{
code: 'uk',
language: 'uk-UA',
name: 'Українська',
},
{
code: 'zh-CN',
language: 'zh-CN',
name: '简体中文',
},
{
code: 'zh-HK',
language: 'zh-HK',
name: '繁體中文(香港)',
},
{
code: 'zh-TW',
language: 'zh-TW',
name: '正體中文 (台灣)',
},
{
code: 'pl',
language: 'pl-PL',
name: 'Polski',
},
{
code: 'pt-BR',
language: 'pt-BR',
name: 'Português (Brasil)',
},
{
code: 'tr',
language: 'tr-TR',
name: 'Türkçe',
},
{
code: 'bn',
language: 'bn-BD',
name: 'বাংলা',
},
{
code: 'id',
language: 'id-ID',
name: 'Bahasa Indonesia',
},
{
code: 'nl',
language: 'nl-NL',
name: 'Nederlands',
},
{
code: 'nb',
language: 'nb-NO',
name: 'Norsk bokmål',
},
{
code: 'bg',
language: 'bg-BG',
name: 'Български',
},
{
code: 'gl',
language: 'gl-ES',
name: 'Galego',
},
],
defaultLocale: 'en',
vueI18n: './i18n.config.ts',
@@ -41,15 +137,12 @@ export default defineNuxtConfig({
detectBrowserLanguage: {
useCookie: true,
},
bundle: {
optimizeTranslationDirective: false,
},
},
nitro: {
esbuild: {
options: {
// to support big int
target: 'es2020',
target: 'node20',
},
},
alias: {
+42 -40
View File
@@ -1,6 +1,6 @@
{
"name": "wg-easy",
"version": "15.0.0-beta.13",
"version": "15.2.2",
"description": "The easiest way to run WireGuard VPN + Web-based Admin UI.",
"private": true,
"type": "module",
@@ -17,60 +17,62 @@
"check:all": "pnpm typecheck && pnpm lint && pnpm format:check && pnpm build",
"db:generate": "drizzle-kit generate",
"cli:build": "node cli/build.js",
"cli:dev": "tsx cli/index.ts"
"cli:dev": "tsx cli/index.ts",
"test:unit": "vitest run --project unit"
},
"dependencies": {
"@eschricht/nuxt-color-mode": "^1.1.5",
"@eschricht/nuxt-color-mode": "^1.2.0",
"@heroicons/vue": "^2.2.0",
"@libsql/client": "^0.15.7",
"@nuxtjs/i18n": "^9.5.4",
"@libsql/client": "^0.17.0",
"@nuxtjs/i18n": "^10.2.3",
"@nuxtjs/tailwindcss": "^6.14.0",
"@phc/format": "^1.0.0",
"@pinia/nuxt": "^0.11.0",
"@tailwindcss/forms": "^0.5.10",
"apexcharts": "^4.7.0",
"argon2": "^0.43.0",
"cidr-tools": "^11.0.3",
"citty": "^0.1.6",
"@pinia/nuxt": "^0.11.3",
"@tailwindcss/forms": "^0.5.11",
"@vueuse/core": "^14.2.0",
"@vueuse/nuxt": "^14.2.0",
"apexcharts": "^5.3.6",
"argon2": "^0.44.0",
"cidr-tools": "^11.0.6",
"citty": "^0.2.0",
"consola": "^3.4.2",
"crc-32": "^1.2.2",
"debug": "^4.4.1",
"drizzle-orm": "^0.43.1",
"ip-bigint": "^8.2.1",
"is-cidr": "^5.1.1",
"debug": "^4.4.3",
"drizzle-orm": "^0.45.1",
"ip-bigint": "^8.2.4",
"is-cidr": "^6.0.2",
"is-ip": "^5.0.1",
"js-sha256": "^0.11.1",
"nuxt": "^3.17.4",
"otpauth": "^9.4.0",
"pinia": "^3.0.2",
"qr": "^0.4.2",
"nuxt": "^3.21.1",
"otpauth": "^9.5.0",
"pinia": "^3.0.4",
"qr": "^0.5.4",
"radix-vue": "^1.9.17",
"semver": "^7.7.2",
"tailwindcss": "^3.4.17",
"semver": "^7.7.4",
"tailwindcss": "^3.4.19",
"timeago.js": "^4.0.2",
"vue": "latest",
"vue3-apexcharts": "^1.8.0",
"zod": "^3.25.30"
"vue3-apexcharts": "^1.10.0",
"zod": "^4.3.6"
},
"devDependencies": {
"@nuxt/eslint": "^1.4.1",
"@nuxt/eslint": "^1.14.0",
"@nuxt/test-utils": "^3.23.0",
"@types/debug": "^4.1.12",
"@types/phc__format": "^1.0.1",
"@types/semver": "^7.7.0",
"drizzle-kit": "^0.31.1",
"esbuild": "^0.25.5",
"eslint": "^9.27.0",
"eslint-config-prettier": "^10.1.5",
"prettier": "^3.5.3",
"prettier-plugin-tailwindcss": "^0.6.11",
"tsx": "^4.19.4",
"typescript": "^5.8.3",
"vue-tsc": "^2.2.10"
"@types/semver": "^7.7.1",
"@vitest/coverage-v8": "^4.0.18",
"@vitest/ui": "4.0.18",
"drizzle-kit": "^0.31.8",
"esbuild": "^0.27.3",
"eslint": "^9.39.2",
"eslint-config-prettier": "^10.1.8",
"prettier": "^3.8.1",
"prettier-plugin-tailwindcss": "^0.7.2",
"tsx": "^4.21.0",
"typescript": "^5.9.3",
"vitest": "^4.0.18",
"vue-tsc": "^3.2.4"
},
"packageManager": "pnpm@10.11.0",
"pnpm": {
"overrides": {
"oxc-parser": "^0.70.0"
}
}
"packageManager": "pnpm@10.29.2"
}
+5118 -4171
View File
File diff suppressed because it is too large Load Diff
@@ -19,19 +19,14 @@ export default definePermissionEventHandler(
}
const config = await WireGuard.getClientConfiguration({ clientId });
const configName = client.name
.replace(/[^a-zA-Z0-9_=+.-]/g, '-')
.replace(/(-{2,}|-$)/g, '-')
.replace(/-$/, '')
.substring(0, 32);
setHeader(
event,
'Content-Disposition',
`attachment; filename="${configName || clientId}.conf"`
`attachment; filename="${WireGuard.cleanClientFilename(client.name) || clientId}.conf"`
);
setHeader(event, 'Content-Type', 'text/plain');
setHeader(event, 'Content-Type', 'application/octet-stream');
return config;
}
);
@@ -18,6 +18,13 @@ export default definePermissionEventHandler(
statusMessage: 'Client not found',
});
}
return result;
// data can be undefined if the client is disabled
const data = await WireGuard.dumpByPublicKey(result.publicKey);
return {
...result,
endpoint: data?.endpoint,
};
}
);
+16 -5
View File
@@ -1,6 +1,17 @@
export default definePermissionEventHandler('clients', 'custom', ({ user }) => {
if (user.role === roles.ADMIN) {
return WireGuard.getAllClients();
import { ClientQuerySchema } from '#db/repositories/client/types';
export default definePermissionEventHandler(
'clients',
'custom',
async ({ event, user }) => {
const { filter } = await getValidatedQuery(
event,
validateZod(ClientQuerySchema, event)
);
if (user.role === roles.ADMIN) {
return WireGuard.getAllClients(filter);
}
return WireGuard.getClientsForUser(user.id, filter);
}
return WireGuard.getClientsForUser(user.id);
});
);
+4 -2
View File
@@ -9,8 +9,10 @@ export default definePermissionEventHandler(
validateZod(ClientCreateSchema, event)
);
await Database.clients.create({ name, expiresAt });
const result = await Database.clients.create({ name, expiresAt });
await WireGuard.saveConfig();
return { success: true };
const clientId = result[0]!.clientId;
return { success: true, clientId };
}
);
+3
View File
@@ -4,10 +4,13 @@ export default defineEventHandler(async () => {
const latestRelease = await cachedFetchLatestRelease();
const updateAvailable = gt(latestRelease.version, RELEASE);
const insecure = WG_ENV.INSECURE;
const isAwg = WG_ENV.WG_EXECUTABLE === 'awg';
return {
currentRelease: RELEASE,
latestRelease: latestRelease,
updateAvailable,
insecure,
isAwg,
};
});
+7 -2
View File
@@ -1,9 +1,14 @@
import type { SharedPublicUser } from '~~/shared/utils/permissions';
export default defineEventHandler(async (event) => {
const session = await useWGSession(event);
if (!session.data.userId) {
// not logged in
return null;
throw createError({
statusCode: 401,
statusMessage: 'Not authenticated',
});
}
const user = await Database.users.get(session.data.userId);
@@ -21,5 +26,5 @@ export default defineEventHandler(async (event) => {
name: user.name,
email: user.email,
totpVerified: user.totpVerified,
};
} satisfies SharedPublicUser;
});
@@ -0,0 +1,32 @@
ALTER TABLE `clients_table` ADD `j_c` integer;--> statement-breakpoint
ALTER TABLE `clients_table` ADD `j_min` integer;--> statement-breakpoint
ALTER TABLE `clients_table` ADD `j_max` integer;--> statement-breakpoint
ALTER TABLE `clients_table` ADD `i1` text;--> statement-breakpoint
ALTER TABLE `clients_table` ADD `i2` text;--> statement-breakpoint
ALTER TABLE `clients_table` ADD `i3` text;--> statement-breakpoint
ALTER TABLE `clients_table` ADD `i4` text;--> statement-breakpoint
ALTER TABLE `clients_table` ADD `i5` text;--> statement-breakpoint
ALTER TABLE `interfaces_table` ADD `j_c` integer DEFAULT 7;--> statement-breakpoint
ALTER TABLE `interfaces_table` ADD `j_min` integer DEFAULT 10;--> statement-breakpoint
ALTER TABLE `interfaces_table` ADD `j_max` integer DEFAULT 1000;--> statement-breakpoint
ALTER TABLE `interfaces_table` ADD `s1` integer DEFAULT 128;--> statement-breakpoint
ALTER TABLE `interfaces_table` ADD `s2` integer DEFAULT 56;--> statement-breakpoint
ALTER TABLE `interfaces_table` ADD `s3` integer;--> statement-breakpoint
ALTER TABLE `interfaces_table` ADD `s4` integer;--> statement-breakpoint
ALTER TABLE `interfaces_table` ADD `i1` text;--> statement-breakpoint
ALTER TABLE `interfaces_table` ADD `i2` text;--> statement-breakpoint
ALTER TABLE `interfaces_table` ADD `i3` text;--> statement-breakpoint
ALTER TABLE `interfaces_table` ADD `i4` text;--> statement-breakpoint
ALTER TABLE `interfaces_table` ADD `i5` text;--> statement-breakpoint
ALTER TABLE `interfaces_table` ADD `h1` integer DEFAULT 0;--> statement-breakpoint
ALTER TABLE `interfaces_table` ADD `h2` integer DEFAULT 0;--> statement-breakpoint
ALTER TABLE `interfaces_table` ADD `h3` integer DEFAULT 0;--> statement-breakpoint
ALTER TABLE `interfaces_table` ADD `h4` integer DEFAULT 0;--> statement-breakpoint
ALTER TABLE `user_configs_table` ADD `default_j_c` integer DEFAULT 7;--> statement-breakpoint
ALTER TABLE `user_configs_table` ADD `default_j_min` integer DEFAULT 10;--> statement-breakpoint
ALTER TABLE `user_configs_table` ADD `default_j_max` integer DEFAULT 1000;--> statement-breakpoint
ALTER TABLE `user_configs_table` ADD `default_i1` text;--> statement-breakpoint
ALTER TABLE `user_configs_table` ADD `default_i2` text;--> statement-breakpoint
ALTER TABLE `user_configs_table` ADD `default_i3` text;--> statement-breakpoint
ALTER TABLE `user_configs_table` ADD `default_i4` text;--> statement-breakpoint
ALTER TABLE `user_configs_table` ADD `default_i5` text;
@@ -0,0 +1,976 @@
{
"version": "6",
"dialect": "sqlite",
"id": "e09bc17a-dab6-45a3-a09c-57af222b08fb",
"prevId": "78de2e52-c4a8-4900-86c5-92f34739623a",
"tables": {
"clients_table": {
"name": "clients_table",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"autoincrement": true
},
"user_id": {
"name": "user_id",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"interface_id": {
"name": "interface_id",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"ipv4_address": {
"name": "ipv4_address",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"ipv6_address": {
"name": "ipv6_address",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"pre_up": {
"name": "pre_up",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "''"
},
"post_up": {
"name": "post_up",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "''"
},
"pre_down": {
"name": "pre_down",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "''"
},
"post_down": {
"name": "post_down",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "''"
},
"private_key": {
"name": "private_key",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"public_key": {
"name": "public_key",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"pre_shared_key": {
"name": "pre_shared_key",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"expires_at": {
"name": "expires_at",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"allowed_ips": {
"name": "allowed_ips",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"server_allowed_ips": {
"name": "server_allowed_ips",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"persistent_keepalive": {
"name": "persistent_keepalive",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"mtu": {
"name": "mtu",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"j_c": {
"name": "j_c",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"j_min": {
"name": "j_min",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"j_max": {
"name": "j_max",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"i1": {
"name": "i1",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"i2": {
"name": "i2",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"i3": {
"name": "i3",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"i4": {
"name": "i4",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"i5": {
"name": "i5",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"dns": {
"name": "dns",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"server_endpoint": {
"name": "server_endpoint",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"enabled": {
"name": "enabled",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"created_at": {
"name": "created_at",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(CURRENT_TIMESTAMP)"
},
"updated_at": {
"name": "updated_at",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(CURRENT_TIMESTAMP)"
}
},
"indexes": {
"clients_table_ipv4_address_unique": {
"name": "clients_table_ipv4_address_unique",
"columns": [
"ipv4_address"
],
"isUnique": true
},
"clients_table_ipv6_address_unique": {
"name": "clients_table_ipv6_address_unique",
"columns": [
"ipv6_address"
],
"isUnique": true
}
},
"foreignKeys": {
"clients_table_user_id_users_table_id_fk": {
"name": "clients_table_user_id_users_table_id_fk",
"tableFrom": "clients_table",
"tableTo": "users_table",
"columnsFrom": [
"user_id"
],
"columnsTo": [
"id"
],
"onDelete": "restrict",
"onUpdate": "cascade"
},
"clients_table_interface_id_interfaces_table_name_fk": {
"name": "clients_table_interface_id_interfaces_table_name_fk",
"tableFrom": "clients_table",
"tableTo": "interfaces_table",
"columnsFrom": [
"interface_id"
],
"columnsTo": [
"name"
],
"onDelete": "cascade",
"onUpdate": "cascade"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"general_table": {
"name": "general_table",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"autoincrement": false,
"default": 1
},
"setup_step": {
"name": "setup_step",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"session_password": {
"name": "session_password",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"session_timeout": {
"name": "session_timeout",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"metrics_prometheus": {
"name": "metrics_prometheus",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"metrics_json": {
"name": "metrics_json",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"metrics_password": {
"name": "metrics_password",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"created_at": {
"name": "created_at",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(CURRENT_TIMESTAMP)"
},
"updated_at": {
"name": "updated_at",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(CURRENT_TIMESTAMP)"
}
},
"indexes": {},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"hooks_table": {
"name": "hooks_table",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"pre_up": {
"name": "pre_up",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"post_up": {
"name": "post_up",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"pre_down": {
"name": "pre_down",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"post_down": {
"name": "post_down",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"created_at": {
"name": "created_at",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(CURRENT_TIMESTAMP)"
},
"updated_at": {
"name": "updated_at",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(CURRENT_TIMESTAMP)"
}
},
"indexes": {},
"foreignKeys": {
"hooks_table_id_interfaces_table_name_fk": {
"name": "hooks_table_id_interfaces_table_name_fk",
"tableFrom": "hooks_table",
"tableTo": "interfaces_table",
"columnsFrom": [
"id"
],
"columnsTo": [
"name"
],
"onDelete": "cascade",
"onUpdate": "cascade"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"interfaces_table": {
"name": "interfaces_table",
"columns": {
"name": {
"name": "name",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"device": {
"name": "device",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"port": {
"name": "port",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"private_key": {
"name": "private_key",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"public_key": {
"name": "public_key",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"ipv4_cidr": {
"name": "ipv4_cidr",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"ipv6_cidr": {
"name": "ipv6_cidr",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"mtu": {
"name": "mtu",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"j_c": {
"name": "j_c",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false,
"default": 7
},
"j_min": {
"name": "j_min",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false,
"default": 10
},
"j_max": {
"name": "j_max",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false,
"default": 1000
},
"s1": {
"name": "s1",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false,
"default": 128
},
"s2": {
"name": "s2",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false,
"default": 56
},
"s3": {
"name": "s3",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"s4": {
"name": "s4",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"i1": {
"name": "i1",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"i2": {
"name": "i2",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"i3": {
"name": "i3",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"i4": {
"name": "i4",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"i5": {
"name": "i5",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"h1": {
"name": "h1",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false,
"default": 0
},
"h2": {
"name": "h2",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false,
"default": 0
},
"h3": {
"name": "h3",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false,
"default": 0
},
"h4": {
"name": "h4",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false,
"default": 0
},
"enabled": {
"name": "enabled",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"created_at": {
"name": "created_at",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(CURRENT_TIMESTAMP)"
},
"updated_at": {
"name": "updated_at",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(CURRENT_TIMESTAMP)"
}
},
"indexes": {
"interfaces_table_port_unique": {
"name": "interfaces_table_port_unique",
"columns": [
"port"
],
"isUnique": true
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"one_time_links_table": {
"name": "one_time_links_table",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"one_time_link": {
"name": "one_time_link",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"expires_at": {
"name": "expires_at",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"created_at": {
"name": "created_at",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(CURRENT_TIMESTAMP)"
},
"updated_at": {
"name": "updated_at",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(CURRENT_TIMESTAMP)"
}
},
"indexes": {
"one_time_links_table_one_time_link_unique": {
"name": "one_time_links_table_one_time_link_unique",
"columns": [
"one_time_link"
],
"isUnique": true
}
},
"foreignKeys": {
"one_time_links_table_id_clients_table_id_fk": {
"name": "one_time_links_table_id_clients_table_id_fk",
"tableFrom": "one_time_links_table",
"tableTo": "clients_table",
"columnsFrom": [
"id"
],
"columnsTo": [
"id"
],
"onDelete": "cascade",
"onUpdate": "cascade"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"users_table": {
"name": "users_table",
"columns": {
"id": {
"name": "id",
"type": "integer",
"primaryKey": true,
"notNull": true,
"autoincrement": true
},
"username": {
"name": "username",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"password": {
"name": "password",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"email": {
"name": "email",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"name": {
"name": "name",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"role": {
"name": "role",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"totp_key": {
"name": "totp_key",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"totp_verified": {
"name": "totp_verified",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"enabled": {
"name": "enabled",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"created_at": {
"name": "created_at",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(CURRENT_TIMESTAMP)"
},
"updated_at": {
"name": "updated_at",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(CURRENT_TIMESTAMP)"
}
},
"indexes": {
"users_table_username_unique": {
"name": "users_table_username_unique",
"columns": [
"username"
],
"isUnique": true
}
},
"foreignKeys": {},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
},
"user_configs_table": {
"name": "user_configs_table",
"columns": {
"id": {
"name": "id",
"type": "text",
"primaryKey": true,
"notNull": true,
"autoincrement": false
},
"default_mtu": {
"name": "default_mtu",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"default_persistent_keepalive": {
"name": "default_persistent_keepalive",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"default_dns": {
"name": "default_dns",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"default_allowed_ips": {
"name": "default_allowed_ips",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"default_j_c": {
"name": "default_j_c",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false,
"default": 7
},
"default_j_min": {
"name": "default_j_min",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false,
"default": 10
},
"default_j_max": {
"name": "default_j_max",
"type": "integer",
"primaryKey": false,
"notNull": false,
"autoincrement": false,
"default": 1000
},
"default_i1": {
"name": "default_i1",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"default_i2": {
"name": "default_i2",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"default_i3": {
"name": "default_i3",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"default_i4": {
"name": "default_i4",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"default_i5": {
"name": "default_i5",
"type": "text",
"primaryKey": false,
"notNull": false,
"autoincrement": false
},
"host": {
"name": "host",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"port": {
"name": "port",
"type": "integer",
"primaryKey": false,
"notNull": true,
"autoincrement": false
},
"created_at": {
"name": "created_at",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(CURRENT_TIMESTAMP)"
},
"updated_at": {
"name": "updated_at",
"type": "text",
"primaryKey": false,
"notNull": true,
"autoincrement": false,
"default": "(CURRENT_TIMESTAMP)"
}
},
"indexes": {},
"foreignKeys": {
"user_configs_table_id_interfaces_table_name_fk": {
"name": "user_configs_table_id_interfaces_table_name_fk",
"tableFrom": "user_configs_table",
"tableTo": "interfaces_table",
"columnsFrom": [
"id"
],
"columnsTo": [
"name"
],
"onDelete": "cascade",
"onUpdate": "cascade"
}
},
"compositePrimaryKeys": {},
"uniqueConstraints": {},
"checkConstraints": {}
}
},
"views": {},
"enums": {},
"_meta": {
"schemas": {},
"tables": {},
"columns": {}
},
"internal": {
"indexes": {}
}
}
@@ -15,6 +15,13 @@
"when": 1748427001203,
"tag": "0001_classy_the_stranger",
"breakpoints": true
},
{
"idx": 2,
"version": "6",
"when": 1761298328460,
"tag": "0002_keen_sleepwalker",
"breakpoints": true
}
]
}
@@ -36,6 +36,14 @@ export const client = sqliteTable('clients_table', {
.notNull(),
persistentKeepalive: int('persistent_keepalive').notNull(),
mtu: int().notNull(),
jC: int('j_c'),
jMin: int('j_min'),
jMax: int('j_max'),
i1: text(),
i2: text(),
i3: text(),
i4: text(),
i5: text(),
dns: text({ mode: 'json' }).$type<string[]>(),
serverEndpoint: text('server_endpoint'),
enabled: int({ mode: 'boolean' }).notNull(),
@@ -1,4 +1,4 @@
import { eq, sql } from 'drizzle-orm';
import { eq, sql, or, like, and } from 'drizzle-orm';
import { containsCidr, parseCidr } from 'cidr-tools';
import { client } from './schema';
import type {
@@ -18,6 +18,17 @@ function createPreparedStatement(db: DBType) {
},
})
.prepare(),
findAllPublic: db.query.client
.findMany({
with: {
oneTimeLink: true,
},
columns: {
privateKey: false,
preSharedKey: false,
},
})
.prepare(),
findById: db.query.client
.findFirst({ where: eq(client.id, sql.placeholder('id')) })
.prepare(),
@@ -25,6 +36,43 @@ function createPreparedStatement(db: DBType) {
.findMany({
where: eq(client.userId, sql.placeholder('userId')),
with: { oneTimeLink: true },
columns: {
privateKey: false,
preSharedKey: false,
},
})
.prepare(),
findAllPublicFiltered: db.query.client
.findMany({
where: or(
like(client.name, sql.placeholder('filter')),
like(client.ipv4Address, sql.placeholder('filter')),
like(client.ipv6Address, sql.placeholder('filter'))
),
with: {
oneTimeLink: true,
},
columns: {
privateKey: false,
preSharedKey: false,
},
})
.prepare(),
findByUserIdFiltered: db.query.client
.findMany({
where: and(
eq(client.userId, sql.placeholder('userId')),
or(
like(client.name, sql.placeholder('filter')),
like(client.ipv4Address, sql.placeholder('filter')),
like(client.ipv6Address, sql.placeholder('filter'))
)
),
with: { oneTimeLink: true },
columns: {
privateKey: false,
preSharedKey: false,
},
})
.prepare(),
toggle: db
@@ -57,6 +105,9 @@ export class ClientService {
}));
}
/**
* Never return values directly from this function. Use {@link getAllPublic} instead.
*/
async getAll() {
const result = await this.#statements.findAll.execute();
return result.map((row) => ({
@@ -66,6 +117,53 @@ export class ClientService {
}));
}
/**
* Returns all clients without sensitive data
*/
async getAllPublic() {
const result = await this.#statements.findAllPublic.execute();
return result.map((row) => ({
...row,
createdAt: new Date(row.createdAt),
updatedAt: new Date(row.updatedAt),
}));
}
/**
* Get clients based on user ID and filter conditions
*/
async getForUserFiltered(userId: ID, filter: string) {
const filterPattern = `%${filter.toLowerCase()}%`;
const result = await this.#statements.findByUserIdFiltered.execute({
userId,
filter: filterPattern,
});
return result.map((row) => ({
...row,
createdAt: new Date(row.createdAt),
updatedAt: new Date(row.updatedAt),
}));
}
/**
* Get all clients based on filter conditions without sensitive data
*/
async getAllPublicFiltered(filter: string) {
const filterPattern = `%${filter.toLowerCase()}%`;
const result = await this.#statements.findAllPublicFiltered.execute({
filter: filterPattern,
});
return result.map((row) => ({
...row,
createdAt: new Date(row.createdAt),
updatedAt: new Date(row.updatedAt),
}));
}
get(id: ID) {
return this.#statements.findById.execute({ id });
}
@@ -102,7 +200,7 @@ export class ClientService {
const ipv6Cidr = parseCidr(clientInterface.ipv6Cidr);
const ipv6Address = nextIP(6, ipv6Cidr, clients);
await tx
return await tx
.insert(client)
.values({
name,
@@ -116,10 +214,19 @@ export class ClientService {
ipv4Address,
ipv6Address,
mtu: clientConfig.defaultMtu,
jC: clientConfig.defaultJC,
jMin: clientConfig.defaultJMin,
jMax: clientConfig.defaultJMax,
i1: clientConfig.defaultI1,
i2: clientConfig.defaultI2,
i3: clientConfig.defaultI3,
i4: clientConfig.defaultI4,
i5: clientConfig.defaultI5,
persistentKeepalive: clientConfig.defaultPersistentKeepalive,
serverAllowedIps: [],
enabled: true,
})
.returning({ clientId: client.id })
.execute();
});
}
@@ -179,6 +286,13 @@ export class ClientService {
ipv4Address,
ipv6Address,
mtu: clientConfig.defaultMtu,
jC: clientConfig.defaultJC,
jMin: clientConfig.defaultJMin,
jMax: clientConfig.defaultJMax,
i1: clientConfig.defaultI1,
i2: clientConfig.defaultI2,
i3: clientConfig.defaultI3,
i4: clientConfig.defaultI4,
allowedIps: clientConfig.defaultAllowedIps,
dns: clientConfig.defaultDns,
persistentKeepalive: clientConfig.defaultPersistentKeepalive,
@@ -39,6 +39,8 @@ const address6 = z
.min(1, { message: t('zod.client.address6') })
.pipe(safeStringRefine);
const filter = z.string().optional();
const serverAllowedIps = z.array(AddressSchema, {
message: t('zod.client.serverAllowedIps'),
});
@@ -50,6 +52,12 @@ export const ClientCreateSchema = z.object({
export type ClientCreateType = z.infer<typeof ClientCreateSchema>;
export const ClientQuerySchema = z.object({
filter: filter,
});
export type ClientQueryType = z.infer<typeof ClientQuerySchema>;
export const ClientUpdateSchema = schemaForType<UpdateClientType>()(
z.object({
name: name,
@@ -64,6 +72,14 @@ export const ClientUpdateSchema = schemaForType<UpdateClientType>()(
allowedIps: AllowedIpsSchema.nullable(),
serverAllowedIps: serverAllowedIps,
mtu: MtuSchema,
jC: JcSchema,
jMin: JminSchema,
jMax: JmaxSchema,
i1: ISchema,
i2: ISchema,
i3: ISchema,
i4: ISchema,
i5: ISchema,
persistentKeepalive: PersistentKeepaliveSchema,
serverEndpoint: AddressSchema.nullable(),
dns: DnsSchema.nullable(),
@@ -71,7 +87,7 @@ export const ClientUpdateSchema = schemaForType<UpdateClientType>()(
);
// TODO: investigate if coerce is bad
const clientId = z.number({ message: t('zod.client.id'), coerce: true });
const clientId = z.coerce.number({ message: t('zod.client.id') });
export const ClientGetSchema = z.object({
clientId: clientId,
@@ -13,6 +13,22 @@ export const wgInterface = sqliteTable('interfaces_table', {
ipv4Cidr: text('ipv4_cidr').notNull(),
ipv6Cidr: text('ipv6_cidr').notNull(),
mtu: int().notNull(),
jC: int('j_c').default(7),
jMin: int('j_min').default(10),
jMax: int('j_max').default(1000),
s1: int().default(128),
s2: int().default(56),
s3: int(),
s4: int(),
i1: text(),
i2: text(),
i3: text(),
i4: text(),
i5: text(),
h1: int().default(0),
h2: int().default(0),
h3: int().default(0),
h4: int().default(0),
// does nothing yet
enabled: int({ mode: 'boolean' }).notNull(),
createdAt: text('created_at')
@@ -31,6 +31,22 @@ export const InterfaceUpdateSchema = schemaForType<InterfaceUpdateType>()(
ipv4Cidr: cidr,
ipv6Cidr: cidr,
mtu: MtuSchema,
jC: JcSchema,
jMin: JminSchema,
jMax: JmaxSchema,
s1: SSchema,
s2: SSchema,
s3: SSchema,
s4: SSchema,
i1: ISchema,
i2: ISchema,
i3: ISchema,
i4: ISchema,
i5: ISchema,
h1: HSchema,
h2: HSchema,
h3: HSchema,
h4: HSchema,
port: PortSchema,
device: device,
enabled: EnabledSchema,
@@ -16,6 +16,12 @@ function createPreparedStatement(db: DBType) {
oneTimeLink: sql.placeholder('oneTimeLink'),
expiresAt: sql.placeholder('expiresAt'),
})
.onConflictDoUpdate({
target: oneTimeLink.id,
set: {
expiresAt: sql.placeholder('expiresAt') as never as string,
},
})
.prepare(),
erase: db
.update(oneTimeLink)

Some files were not shown because too many files have changed in this diff Show More