Compare commits

...

42 Commits

Author SHA1 Message Date
Eugene Burkov
3918789ca7 aghnet: imp permissions logic 2023-02-06 16:11:55 +03:00
Eugene Burkov
da1b53a3b4 Merge branch 'master' into 4728-cap-check 2023-02-06 15:45:10 +03:00
Ainar Garipov
6a032bb821 Pull request: 5433-league-icon
Updates #5433.

Squashed commit of the following:

commit 4190845e5edb7f3a5f6970ec1d739aabf0a87f57
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Thu Feb 2 18:01:10 2023 +0300

    filtering: fix league of legends icon
2023-02-02 18:06:01 +03:00
Ainar Garipov
a5f059b1f5 Pull request: upd-chlog
Merge in DNS/adguard-home from upd-chlog to master

Squashed commit of the following:

commit ce9ebccf73e2418503cd905eebd62b95fdb7a71e
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Wed Feb 1 16:39:20 2023 +0300

    all: upd chlog; imp go-lint
2023-02-01 16:55:18 +03:00
Ainar Garipov
04f4993385 Pull request: upd-all
Merge in DNS/adguard-home from upd-all to master

Squashed commit of the following:

commit 1c71e4586daa7502f5dadd5ba4dc58a12a01f3b8
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Wed Feb 1 13:37:50 2023 +0300

    all: imp chlog; upd deps, i18n, services, trackers
2023-02-01 13:45:00 +03:00
Arseny Lisin
46382e8825 Fix dark theme bugs
Updates #5375

Squashed commit of the following:

commit 40666b010697381e11b3a36d9c2ed1c1507f27ed
Author: Arseny Lisin <a.lisin@adguard.com>
Date:   Tue Jan 31 18:34:06 2023 +0200

    Review fix

commit 44f3d6095bc9b426e8142f8c9d915a1441f3d791
Author: Arseny Lisin <a.lisin@adguard.com>
Date:   Tue Jan 31 17:02:38 2023 +0200

    Clear

commit 44274ba54c9ff2bd2caf5fa69bf06c587f8858e5
Author: Arseny Lisin <a.lisin@adguard.com>
Date:   Tue Jan 31 13:25:01 2023 +0200

    Clear

commit 8b48c523cbbe3f73160331a9c516388c7965a7a2
Author: Arseny Lisin <a.lisin@adguard.com>
Date:   Tue Jan 31 12:14:37 2023 +0200

    Review fix

commit 3b8cd94cdd8d3fc90cdc27053964489414055cc9
Author: Arseny Lisin <a.lisin@adguard.com>
Date:   Mon Jan 30 16:13:15 2023 +0200

    Fix query log popup bg

commit 14d4c87164200f7c918bac02c9cc5f1cffb83932
Author: Arseny Lisin <a.lisin@adguard.com>
Date:   Mon Jan 30 15:03:06 2023 +0200

    revert icons

commit 98b042726e1510f85c9cf5a4caba2d56885f120b
Author: Arseny Lisin <a.lisin@adguard.com>
Date:   Mon Jan 30 14:45:35 2023 +0200

    Fix dark theme bugs
2023-02-01 11:45:22 +03:00
Ainar Garipov
d52f1d0e70 Pull request 1720: 4940-version-check-error
Updates #4940.

Squashed commit of the following:

commit f8cc9aeb63478e17a7e5108e2ebacf49a79ed2a3
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Thu Jan 26 20:23:24 2023 +0300

    client: imp version check fail message
2023-01-27 13:00:58 +03:00
Eugene Burkov
6aa93f4ae7 Pull request: safebrowsing races
Merge in DNS/adguard-home from safebrowsing-races to master

Squashed commit of the following:

commit c7f4932d1ed8ea4fea99e04487ac77c23fb5f386
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Jan 26 16:36:32 2023 +0300

    filtering: imp code, naming

commit af83cf2e689d199c8280022c9ffb84775b74c4e4
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Wed Jan 25 19:47:30 2023 +0300

    filtering: DRY

commit 8bfe6b2bb397058af3b7de4d255ed13287e250c9
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Wed Jan 25 18:48:19 2023 +0300

    filtering: fix possible races
2023-01-26 17:13:18 +03:00
Eugene Burkov
99ec1d840c Pull request: use mathutil
Merge in DNS/adguard-home from use-mathutil to master

Squashed commit of the following:

commit cfe2c02a7bb727e81fcd91674aa777df37413a8e
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Tue Jan 24 18:12:32 2023 +0300

    all: use mathutil
2023-01-24 19:50:19 +03:00
Eugene Burkov
2ecf2a4c42 Pull request: 5117-dns64
Merge in DNS/adguard-home from 5117-dns64 to master

Updates #5117.

Squashed commit of the following:

commit 757d689134b85bdac9a6f5e43249866ec09ab7e3
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Jan 23 19:06:18 2023 +0300

    all: imp fmt

commit b7a73c68c0b40bd3bda520c045c8110975c1827a
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Jan 23 17:49:21 2023 +0300

    all: rm unused, imp code

commit 548feb6bd27b9774a9453d0570d37cdf557d4c3a
Merge: de3e84b5 54a141ab
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Jan 23 14:08:12 2023 +0300

    Merge branch 'master' into 5117-dns64

commit de3e84b52b8dbff70df3ca0ac3315c3d33576334
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Jan 23 12:04:48 2023 +0300

    dnsforward: imp code

commit a580e92119e3dbadc8b1a6572dbecc679f69db40
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Fri Jan 20 18:24:33 2023 +0400

    dnsforward: try again

commit 67b7a365194939fe15e4907a3dc2fee44b019d08
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Fri Jan 20 18:08:23 2023 +0400

    dnsforward: fix test on linux

commit ca83e4178a3383e326bf528d209d8766fb3c60d3
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Fri Jan 20 17:37:48 2023 +0400

    dnsforward: imp naming

commit c4e477c7a12af4966cbcd4e5f003a72966dc5d61
Merge: 42aa42a8 6e803375
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Fri Jan 20 17:30:03 2023 +0400

    Merge branch 'master' into 5117-dns64

commit 42aa42a8149b6bb42eb0da6e88ede4b5065bbf2f
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Fri Jan 20 17:26:54 2023 +0400

    dnsforward: imp test

commit 4e91c675703f1453456ef9eea08157009ce6237a
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Wed Jan 18 12:32:55 2023 +0400

    dnsforward: imp code, docs, add test

commit 766ef757f61e7a555b8151b4783fa7aba5f566f7
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Tue Jan 17 16:36:35 2023 +0400

    dnsforward: imp docs

commit 6825f372389988597d1879cf66342c410f3cfd47
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Tue Jan 17 14:33:33 2023 +0400

    internal: imp code, docs

commit 1215316a338496b5bea2b20d697c7451bfbcc84b
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Fri Jan 13 21:24:50 2023 +0400

    all: add dns64 support
2023-01-23 19:10:56 +03:00
Ainar Garipov
54a141abde Pull request 1717: remove-client2
Merge in DNS/adguard-home from remove-client2 to master

Squashed commit of the following:

commit 0a0923494b0d1003e4f02f3a5f93d5248f0f2ded
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Fri Jan 20 17:14:29 2023 +0300

    all: rm old experimental beta (dir client2/)

    This project was unfortunately abandoned.  v0.108.0 will have a
    different front-end and new APIs.
2023-01-23 12:47:59 +03:00
Ainar Garipov
6e8033750d Pull request 1716: upd-chlog
Merge in DNS/adguard-home from upd-chlog to master

Squashed commit of the following:

commit 149b99993f396b13993942e7fb223347e7ed493e
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Thu Jan 19 16:27:03 2023 +0300

    all: typo

commit 29a1c0155e88774094443a58d1cb4689514216d6
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Thu Jan 19 16:26:23 2023 +0300

    all: upd chlog
2023-01-19 16:34:38 +03:00
Ainar Garipov
46624c79de Pull request 1715: upd-all
Merge in DNS/adguard-home from upd-all to master

Squashed commit of the following:

commit 107fd015c773494a1eb5970708807238644dbb40
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Thu Jan 19 14:30:34 2023 +0300

    all: upd i18n, blocked svcs
2023-01-19 14:52:22 +03:00
Dimitry Kolyshev
a7dca7aa56 Pull request 1713: 613 dark theme vol.2
Updates #613.

Squashed commit of the following:

commit 9a3ba15bdb8476dde045631362d76572a68a4e5c
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Thu Jan 19 12:46:48 2023 +0700

    client: review dark theme colors

commit c456cdcb6ffec044917b0396ad3cfa8b5c3bce10
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Wed Jan 18 23:46:32 2023 +0700

    client: review dark theme colors

commit 4b042ba4f433c89488b18ec38f5864d5ffaf8657
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Wed Jan 18 23:34:37 2023 +0700

    client: review dark theme colors

commit 1ff34f751b4d9342495070af85f3dae86c285aee
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Wed Jan 18 18:59:46 2023 +0700

    client: default language

commit ca9abc11a8c155c78f73903906ed452e95764e99
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Wed Jan 18 12:23:50 2023 +0700

    client: default language

commit 01a057a40e879d1bc2013989d6eb56a296ba16a3
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Wed Jan 18 11:53:58 2023 +0700

    client: review dark theme colors

commit aa3658f35c49f8ae19077b333075207082383a17
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Wed Jan 18 11:14:08 2023 +0700

    client: review dark theme colors

commit 8df726382155fcc3b2e6e632d53f42d0be638c77
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Tue Jan 17 13:41:21 2023 +0700

    client: dark theme colors

commit bd84ae46272743874d2350291b22b90b7fbedf0e
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Tue Jan 17 13:05:46 2023 +0700

    client: dark theme colors

commit 136ea5608a1a22b6a54a362741b2fdd708f345e2
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Tue Jan 17 10:51:22 2023 +0700

    all: docs

commit 784be8741b730a12d665d7e2a29c140c0746e927
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Mon Jan 16 17:59:26 2023 +0700

    client: imp code

commit a83de0948fe034e7be35c04a607b1171915c0263
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Mon Jan 16 14:13:54 2023 +0700

    client: dark theme login

commit 6c4ef19da01efc6a1e4ea76085b7b7382c331eca
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Mon Jan 16 13:27:35 2023 +0700

    client: dark theme css

commit 5cf564ea1203e9472d200975ee98d93b6b868210
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Mon Jan 16 13:18:00 2023 +0700

    client: imp code

commit 1bbbd20972345c08e944b7c4bb0330c0d30d827a
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Mon Jan 16 12:49:03 2023 +0700

    client: imp code

commit cb07680d3cd7acdbdb7bdc9d9abaa388a9df8e4c
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Mon Jan 16 12:24:14 2023 +0700

    client: auto theme handling

commit d34910d4dd5edb694b6da55a2260b4fea784e7e0
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Fri Jan 13 23:31:24 2023 +0700

    home: imp docs

commit 8abe4f6f7182dc3dbcbbe73652294ee6584a4f2f
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Thu Jan 12 18:35:48 2023 +0700

    client: theme dropdown
2023-01-19 13:46:44 +03:00
Dimitry Kolyshev
cd76a30790 Pull request: 613-dark-theme vol.1
Merge in DNS/adguard-home from 613-dark-theme to master

Squashed commit of the following:

commit 1a286e9677c0bc9203ca0249edf0dd6f64db1609
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Fri Jan 13 22:37:36 2023 +0700

    home: imp docs

commit 45c4fac401788a1c5f0ab56869b13cce33690145
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Fri Jan 13 18:35:58 2023 +0700

    home: imp docs

commit e23b375611deb9562dfccaf45632e5235d06f96c
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Fri Jan 13 15:05:41 2023 +0700

    home: imp docs

commit 85d2cd6250c4bb558c9a9bd5066044f07827c263
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Fri Jan 13 15:04:28 2023 +0700

    home: imp code

commit bb00bfda90a809929639b241d7bbc31e7e6dfcb8
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Fri Jan 13 09:37:41 2023 +0700

    home: imp docs

commit 140fd0768ea2a0da7618a1f5ef6c53ff415753aa
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Fri Jan 13 09:34:27 2023 +0700

    home: imp code

commit 4e866b7c5b4d2ff777e4917cb91b34a4bbb5e995
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Thu Jan 12 19:11:33 2023 +0700

    home: imp docs

commit 0f13248165ef920d1dadb2e057b65cc3189a4b31
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Thu Jan 12 18:53:57 2023 +0700

    home: imp code

commit e04181f5fcd67cdd08fbf8a7c56933195999af31
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Thu Jan 12 18:48:44 2023 +0700

    home: imp code

commit bb9989bb9ab54bfb734880dcb999804c6f2ccda8
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Thu Jan 12 12:09:20 2023 +0700

    all: control/profile API
2023-01-13 19:24:17 +03:00
Ainar Garipov
68bc9969b7 Pull request: reduce-build-parallelism
Merge in DNS/adguard-home from reduce-build-parallelism to master

Squashed commit of the following:

commit 3c26331185f8402441334078eb73ad2615edd5e5
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Wed Jan 11 14:40:46 2023 +0300

    all: reduce build parallelism
2023-01-11 14:48:46 +03:00
Eugene Burkov
d8d7a5c335 Pull request: 5191-update-flag
Merge in DNS/adguard-home from 5191-update-flag to master

Updates #5191.
Updates #4223.

Squashed commit of the following:

commit fbace4942844dc67f2467479385e06843c3abb6a
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Jan 9 12:05:16 2023 +0400

    all: imp code, docs

commit 8237dceb771ba95f545f79565d76cbb4ebd0d805
Merge: ca9518f2 bbdcc673
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Fri Dec 30 14:45:55 2022 +0400

    Merge branch 'master' into 5191-update-flag

commit ca9518f20e5643572adf9734b93a5436ba30c865
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Dec 29 20:36:33 2022 +0400

    home: imp code

commit 1dc6c7c3480df3df4a5f3f923f1feab7761a7945
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Dec 29 18:26:08 2022 +0400

    all: imp code, docs

commit 7bbe893e98063b956482fd6f1c6be95a4f1956cf
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Dec 29 03:44:48 2022 +0400

    home: restart service on update

commit e0d3c287a7e1c05b1e397f4727c447a1fcd9f7f6
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Dec 29 03:22:49 2022 +0400

    all: update on first run

commit 0aa4e78f03bf3819425accb468ce59e747506ef3
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Dec 29 02:47:30 2022 +0400

    all: move some code to init less

commit 68aebfa050b9965afef26653e9b699ff4aaf5b8b
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Dec 29 00:36:00 2022 +0400

    WIP

commit 2c7fb97d701ac158613c5a3a4d4d35c5b79b3d59
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Wed Dec 28 14:15:59 2022 +0400

    home: imp logs

commit 4b06d089da835d6d187803bbb5ca1caf9973e2d3
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Tue Dec 27 19:21:17 2022 +0400

    all: fix update flag
2023-01-09 13:38:31 +03:00
Dimitry Kolyshev
bbdcc673a2 Pull request: 5270-updater-package-url
Merge in DNS/adguard-home from 5270-updater-package-url to master

Squashed commit of the following:

commit 50ee8edb6270e750ed82b14c174f88922aff86bb
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Wed Dec 28 12:21:24 2022 +0700

    updater: package url
2022-12-28 15:14:08 +03:00
Ildar Kamalov
e7fc61a997 Pull request: 4898 reload page on tls settings save
Merge in DNS/adguard-home from 4898-reload-page to master

Closes #4898.

Squashed commit of the following:

commit c2d78804d96d00b5ff10e23c0f275a6c73455b93
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Dec 26 18:03:31 2022 +0400

    all: fix changelog

commit e55db6a620e4aa74eb3562a4eb35bbd3d13c8712
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Dec 26 18:02:37 2022 +0400

    all: log changes

commit 3985dc4a42d1dc717def3011d7dfd24dd49da0da
Author: Ildar Kamalov <ik@adguard.com>
Date:   Mon Dec 26 15:20:38 2022 +0300

    client: reload page on tls settings save
2022-12-26 17:19:51 +03:00
Eugene Burkov
97af23b0af Pull request: 5290-rules-count
Merge in DNS/adguard-home from 5290-rules-count to master

Closes #5290.

Squashed commit of the following:

commit c29fd668dd8f25dbfe978fb95f850acbbd632b8b
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Fri Dec 23 14:42:57 2022 +0400

    all: log changes

commit fba4fe7cc046578f17cdf72dff93523558b8aa1f
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Fri Dec 23 14:33:57 2022 +0400

    filtering: fix rules count on err
2022-12-23 17:11:11 +03:00
Ildar Kamalov
e481922d91 Pull request: 4898 fix redirect to current protocol on tls settings change
Updates #4898

Squashed commit of the following:

commit b10b0a5adeeb44375912d34a9ef60a7f4ff9688c
Merge: 9d4bc0ef defde7d0
Author: Ildar Kamalov <ik@adguard.com>
Date:   Wed Dec 21 17:49:52 2022 +0300

    Merge branch 'master' into 4898-tls-redirect

commit 9d4bc0efaf1639380325f75684514386ec581206
Author: Ildar Kamalov <ik@adguard.com>
Date:   Wed Dec 21 16:39:17 2022 +0300

    fix helper

commit cb5b43e65c6224b6d9fe012b52a18ee8e2e1c19a
Author: Ildar Kamalov <ik@adguard.com>
Date:   Mon Dec 19 19:16:07 2022 +0300

    client: reload page on tls enable
2022-12-21 18:13:07 +03:00
Ildar Kamalov
defde7d0fe Pull request: 5249 fix search input outline
Updates #5249

Squashed commit of the following:

commit f1a16e79073d0b887a1c27becab0aeb039d7268b
Merge: b752c58e 0c03063c
Author: Ildar Kamalov <ik@adguard.com>
Date:   Wed Dec 21 17:06:59 2022 +0300

    Merge branch 'master' into 5249-outline

commit b752c58e0a79815d22853cd85419ffa64f38f530
Author: Ildar Kamalov <ik@adguard.com>
Date:   Wed Dec 21 12:34:15 2022 +0300

    fix input borders

commit 1c7d5da85a30ba951b6ad0a0b8e70780309686fa
Merge: 40fb0273 0ddd8e3d
Author: Ildar Kamalov <ik@adguard.com>
Date:   Wed Dec 21 12:27:25 2022 +0300

    Merge branch 'master' into 5249-outline

commit 40fb02734de1a525681d54295600897088c02ac9
Author: Ildar Kamalov <ik@adguard.com>
Date:   Tue Dec 20 13:29:15 2022 +0300

    5249 fix search input outline
2022-12-21 17:48:35 +03:00
Ildar Kamalov
0c03063c8a Pull request: 4962 trim client upstream field whitespace
Updates #4962

Squashed commit of the following:

commit d1382e197455987cf1539b28a09da7b5377dd784
Merge: 510d80bd 0ddd8e3d
Author: Ildar Kamalov <ik@adguard.com>
Date:   Wed Dec 21 12:26:05 2022 +0300

    Merge branch 'master' into 4962-trim-whitespace

commit 510d80bde01fb027f72b2371bda35c62c6b02ca6
Author: Ildar Kamalov <ik@adguard.com>
Date:   Tue Dec 20 13:57:13 2022 +0300

    4962 trim client upstream field whitespace
2022-12-21 12:38:51 +03:00
Eugene Burkov
0ddd8e3dcc Pull request: 5258-changelog
Merge in DNS/adguard-home from 5258-changelog to master

Updates #5258.

Squashed commit of the following:

commit a46f9435b91cfdd9f1da6132526707fe81004e51
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Tue Dec 20 18:36:41 2022 +0400

    all: log changes
2022-12-20 17:59:55 +03:00
Eugene Burkov
48cbc7bdf0 Pull request: 5258-good-old-filters
Merge in DNS/adguard-home from 5258-good-old-filters to master

Updates #5258.

Squashed commit of the following:

commit 8555e685a104713e552f017de63281749f41b6b2
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Tue Dec 20 16:07:52 2022 +0400

    filtering: imp tests, docs

commit 2ecfc18fc69850a06461620a24527158603cd7b8
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Tue Dec 20 11:00:59 2022 +0400

    filtering: fix docs

commit 1ea8d45a85f3fb6794b44134e8fdcbe2044d2199
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Dec 19 23:19:37 2022 +0400

    filtering: imp naming, docs

commit c52a3bba48738c002111c234fb4c312380e49cfc
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Dec 19 23:13:37 2022 +0400

    filtering: imp logic

commit 3ad4276ace40f05db47b49fb033d1b0fa208ec4e
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Dec 19 17:49:15 2022 +0400

    filtering: imp docs

commit 1bc3cc443bc8ec988532effaaf5f50474a1a69ab
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Dec 19 17:45:37 2022 +0400

    filtering: imp more

commit 7908339a0c9fcc29e8fe12b6c5d8c14bbfa51364
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Dec 19 16:57:42 2022 +0400

    filtering: imp code

commit 21bbd18b4ded83f354210ac32010d8fd1073452f
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Dec 19 12:11:21 2022 +0400

    filtering: imp src reading
2022-12-20 16:40:42 +03:00
Ainar Garipov
de08ef0077 Pull request: unignore-snap
Merge in DNS/adguard-home from unignore-snap to master

Squashed commit of the following:

commit 2901080c92d5316bcbf536ebdfeaff88cea0edd4
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Thu Dec 15 19:08:46 2022 +0300

    all: unignore snap
2022-12-15 19:13:59 +03:00
Ainar Garipov
cfab157146 Pull request: upd-chlog
Merge in DNS/adguard-home from upd-chlog to master

Squashed commit of the following:

commit 6d99abd2144219393be3997b723288c36ee72faf
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Thu Dec 15 18:14:07 2022 +0300

    all: upd chlog
2022-12-15 18:19:00 +03:00
Ainar Garipov
ec05ee16fe Pull request: skip-snap
Merge in DNS/adguard-home from skip-snap to master

Squashed commit of the following:

commit 3859612645826ccad025ab4ba7e03adac6d09842
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Thu Dec 15 17:19:48 2022 +0300

    all: skip snap upload temporarily; imp issue tmpl
2022-12-15 17:38:01 +03:00
Ainar Garipov
c1b537c14b Pull request: upd-all
Merge in DNS/adguard-home from upd-all to master

Squashed commit of the following:

commit 4031b9ca886c41f07ac949dfae8dd00d0969138f
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Thu Dec 15 15:19:01 2022 +0300

    all: upd blocked svcs, i18n, vetted flts
2022-12-15 15:31:42 +03:00
Eugene Burkov
d77b743c7b Pull request: 5251-close-ups
Merge in DNS/adguard-home from 5251-close-ups to master

Updates #5251.

Squashed commit of the following:

commit 98a4a9a45ae702df3cf26cab0b28bd83a6556085
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Wed Dec 14 18:31:17 2022 +0300

    all: log changes better

commit af25803925c15ba2d9b07865c3deb58033006c52
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Wed Dec 14 18:24:42 2022 +0300

    all: log changes

commit 65bb12d8b6d6bd2e37ee83bc4aca63aa573da63a
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Wed Dec 14 18:15:41 2022 +0300

    all: upd dnsproxy

commit 24039cd7f9c64ee5d9806e1146dbd1e76c298a20
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Wed Dec 14 17:19:15 2022 +0300

    dnsforward: imp code, docs

commit a40bbd55267c9904c14b89568408f86ccb3ef6c9
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Wed Dec 14 16:43:10 2022 +0300

    dnsforward: log errs instead of return
2022-12-14 18:39:31 +03:00
Ainar Garipov
8d453e75a4 Pull request: 5238-default-filter-urls
Updates #5238.

Squashed commit of the following:

commit 6a1b58bfa0f0bb8cc924e294485e8f650ce7f7aa
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Thu Dec 8 14:18:54 2022 +0300

    all: upd go in github actions

commit 98366880dc32290258dfae152be069cb84ed86c6
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Thu Dec 8 14:08:36 2022 +0300

    home: sync default filter urls
2022-12-08 16:27:10 +03:00
Ainar Garipov
de9f9e9eb8 Pull request: upd-chlog
Merge in DNS/adguard-home from upd-chlog to master

Squashed commit of the following:

commit 9117b734bfea2bcb5993c340c474f8c894902b70
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Wed Dec 7 17:41:24 2022 +0300

    all: upd chlog
2022-12-07 17:47:13 +03:00
Ainar Garipov
fa49d74aa8 Pull request: upd-all
Merge in DNS/adguard-home from upd-all to master

Squashed commit of the following:

commit 8fe5f029f2092ff1b23c6b734fef35937658c6d3
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Wed Dec 7 16:13:04 2022 +0300

    aghos: fix windows root dir

commit 57237df1d95c7c72cc02103eb869590a2b8fe50c
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Wed Dec 7 15:18:59 2022 +0300

    all: upd go, i18n, svcs
2022-12-07 16:29:06 +03:00
Eugene Burkov
f0cf6cce9a Pull request: 5208-dhcp-range
Merge in DNS/adguard-home from 5208-dhcp-range to master

Closes #5208.

Squashed commit of the following:

commit b7bd646823545d5d1f3c42c5461ec65b874e2bbc
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Tue Dec 6 18:55:03 2022 +0300

    client: restore non-en locales

commit 8e306201c2a35eccb525b84aef5d7e3aa54b5446
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Tue Dec 6 18:45:51 2022 +0300

    client: rm unused locales

commit 087cf2e3fe48245686a7e9631afe5322323e5add
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Tue Dec 6 18:25:54 2022 +0300

    all: log changes

commit f1f9d7908226e5ecce3a33d82f2ba32200f6af31
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Tue Dec 6 18:23:06 2022 +0300

    client: imp dhcp err msgs

commit b9d8d7029756a9ee482c7c855f48b0ca6136e833
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Tue Dec 6 15:44:44 2022 +0300

    WIP
2022-12-07 14:29:01 +03:00
Eugene Burkov
6d1adf74b1 Pull request: 5193-long-ups-check
Merge in DNS/adguard-home from 5193-long-ups-check to master

Closes #5193.

Squashed commit of the following:

commit 787e6b9950e85b79fe50e16cda5110fe53ec3e80
Merge: f62330bd 01652e6a
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Dec 5 17:07:40 2022 +0300

    Merge branch 'master' into 5193-long-ups-check

commit f62330bd17ec260bc8c7475c8f5ae236059cde35
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Dec 5 16:28:47 2022 +0300

    dnsforward: try to fix linux

commit 64bfacc58d2a4c2929d9c3cf80bc31bfca404d54
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Dec 5 15:55:48 2022 +0300

    all: log changes finally

commit 4331d1c2497a94a95e4eba0ebcb5a813260c188a
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Dec 5 15:26:45 2022 +0300

    all: imp log of chagnes

commit 62ed3c123eda100813a2de2ed95c1446c7a100f0
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Dec 5 15:23:17 2022 +0300

    all: log changes

commit 73f4d59796dc5de51cf9c9953a6a22342e1ce31a
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Dec 5 14:37:18 2022 +0300

    dnsforward: add defer

commit a15072f1ea3845ba135ddd61aa8d67d9c0dcd7ea
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Mon Dec 5 14:30:16 2022 +0300

    dnsforward: imp tests

commit e74219f594094f1e3d0001664ed3f79050747a4d
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Sat Dec 3 16:29:31 2022 +0300

    dnsforward: get rid of wg

commit 165da7dc186285d6ff8b949e12d95e0da5e828eb
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Fri Dec 2 15:42:55 2022 +0300

    dnsforward: add ups check test

commit 3045273997e45e952ba58e9c7fa5bba2d21ad286
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Dec 1 20:28:56 2022 +0300

    dnsforward: imp ups check perf
2022-12-05 17:24:32 +03:00
Dimitry Kolyshev
01652e6ab2 Pull request: 2499 rewrite: storage vol.2
Merge in DNS/adguard-home from 2499-rewrites-1 to master

Squashed commit of the following:

commit 6303107d6ca7dd88175e4e123128189e5958f060
Merge: e2040b95 09f88cf2
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Mon Dec 5 13:38:01 2022 +0200

    Merge remote-tracking branch 'origin/master' into 2499-rewrites-1

commit e2040b95dd3157d033d929bb45fc7662b9918a78
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Mon Dec 5 12:00:21 2022 +0200

    rewrite: item

commit c7278e8adeec1ba3a090cc93db30c80699617c52
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Sun Dec 4 12:57:59 2022 +0200

    rewrite: imp code

commit d23a740262a4fbdd9b25f7449ced707c0d2be634
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Fri Dec 2 13:08:25 2022 +0200

    rewrite: imp code

commit 773a5211b6662afd03a34219e7114c6f1e2bb579
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Fri Dec 2 13:05:20 2022 +0200

    rewrite: imp code

commit 48b54e19da9844d9b868d0be7e428ad6bacae6a5
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Fri Dec 2 13:02:47 2022 +0200

    rewrite: tests item

commit 62af2bd91f5559840e7948ac4bf7c36b1bee1dc2
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Thu Dec 1 17:11:21 2022 +0200

    rewrite: tests

commit f040b609391cb2275b11d4732bbac0380c01de07
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Thu Dec 1 17:04:59 2022 +0200

    rewrite: imp code

commit 4592b8c4e6107e5a746261d3335282827ce36b74
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Thu Dec 1 17:02:31 2022 +0200

    rewrite: imp code

commit cc1660695341c558dbac6acaa31ac160a45f6105
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Thu Dec 1 16:19:27 2022 +0200

    rewrite: imp code

commit cf3840b76d45bf319630256c01586159dd1e85fe
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Thu Dec 1 13:16:40 2022 +0200

    rewrite: tests

commit 6fd6f03ca4320d4345032139b43cb457b3ae4278
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Thu Dec 1 11:14:44 2022 +0200

    rewrite: imp code

commit 2ebd2a1e79afc8f486cf6533968c51ca61bc03ab
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Wed Nov 30 11:43:24 2022 +0200

    rewrite: tests

commit 7da987994303a3e7b16eb6b0baaa4b59a52b97be
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Wed Nov 30 10:54:57 2022 +0200

    filtering: imp code

commit ab98efc6710fac7cba28dab5bca9b60e9ec34ef7
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Mon Nov 28 13:31:12 2022 +0200

    filtering: rewritehttp
2022-12-05 14:46:51 +03:00
Ainar Garipov
09f88cf21d Pull request: 5190-clear-cache
Updates #4695.
Updates #5190.

Squashed commit of the following:

commit f4156f54ebd1b0c96318715441da1dc54cbbfb0f
Author: Ildar Kamalov <ik@adguard.com>
Date:   Fri Dec 2 16:19:03 2022 +0300

    client: button styles

commit 42cd8ac8ac1abb5c43a42065e2374d11f2d9a62b
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Fri Dec 2 15:39:15 2022 +0300

    all: upd dnsproxy

commit 87b04391afeaed28523448aa12a317300e718b72
Author: Ildar Kamalov <ik@adguard.com>
Date:   Fri Dec 2 15:19:07 2022 +0300

    client: add clear cache button

commit ee99548b3689ce47959d9bddc6a1e866e773dcc3
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Thu Dec 1 18:54:54 2022 +0300

    all: add cache clear
2022-12-02 18:06:50 +03:00
Dimitry Kolyshev
e6f8aeeebe Pull request: 2499 rewrite: storage vol.1
Merge in DNS/adguard-home from 2499-rewrites to master

Squashed commit of the following:

commit 3f5f8e1354cbfa2de2bea69b1caa5dfbcb84ddb1
Merge: c84a86fb fafd7a1e
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Mon Nov 28 13:13:31 2022 +0200

    Merge remote-tracking branch 'origin/master' into 2499-rewrites

commit c84a86fba1c9cd77c5893e056cd85f8aa6597afc
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Mon Nov 28 12:50:26 2022 +0200

    rewrite: todos

commit 3b33a79bea65650ee7dc920554773d1d1d2c67f5
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Mon Nov 28 11:45:05 2022 +0200

    rewrite: todos

commit 15022994e7af8e5ee5929edff8ce98356a1cb27b
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Fri Nov 25 12:15:27 2022 +0200

    rewrite: imp code

commit b3c1949a585a8ff83c046921288ce2fdb5b36cee
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Fri Nov 25 11:33:25 2022 +0200

    rewrite: imp code

commit 80fe50a86fc6e5ed5cf5b0d2e0be667b1b9221a8
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Fri Nov 25 11:13:39 2022 +0200

    rewrite: imp code

commit 5288ede0e8df5ca1d12c9e1e8341db703729c71a
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Fri Nov 25 11:04:11 2022 +0200

    Revert "all: rewrite"

    This reverts commit 32ad8d76861bd9919da61635e6f871adcc36c999.

commit cff6494fde44646f5ac54173380719557e0c0e02
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Fri Nov 25 11:04:11 2022 +0200

    Revert "all: rewrite"

    This reverts commit 65e44e92b009c561ddb2c68f56e04d57b83ba247.

commit e0fe877da4ee820838acc1ac6111809e7d0bc72e
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Fri Nov 25 11:04:11 2022 +0200

    Revert "filtering: imp code"

    This reverts commit c882da3309297f44ccaf38274ec4ef0ef2fec7b3.

commit 8e3f9d4a7ac2e5b114064e77ec009a2457b28a73
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Fri Nov 25 11:04:11 2022 +0200

    Revert "rewrite: imp code"

    This reverts commit ce2332932bef46186c0addf5e7a1ca648cdd9f22.

commit ce2332932bef46186c0addf5e7a1ca648cdd9f22
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Fri Nov 25 10:56:48 2022 +0200

    rewrite: imp code

commit c882da3309297f44ccaf38274ec4ef0ef2fec7b3
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Thu Nov 24 13:39:26 2022 +0200

    filtering: imp code

commit 65e44e92b009c561ddb2c68f56e04d57b83ba247
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Thu Nov 24 13:25:10 2022 +0200

    all: rewrite

commit 32ad8d76861bd9919da61635e6f871adcc36c999
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Thu Nov 24 13:19:55 2022 +0200

    all: rewrite

commit 941538abfe517e70e469cb5b121fa13f1a3b79f3
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Tue Nov 22 12:54:55 2022 +0200

    rewrite: storage tests

commit 0a1ad86ea766bc1e6015d06c872b08ecc0510aea
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Tue Nov 22 12:46:56 2022 +0200

    rewrite: imp code

commit f10a45361c343042d6348e0fa8049c9eb0299af8
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Mon Nov 21 14:29:44 2022 +0200

    rewrite: storage

commit ff91bb81a607737dd6845b0a4b13c2c75a4ad57d
Author: Dimitry Kolyshev <dkolyshev@adguard.com>
Date:   Sun Nov 20 13:25:05 2022 +0200

    rewrite: storage
2022-11-28 14:19:56 +03:00
Eugene Burkov
fafd7a1e82 Pull request: 4944-dhcp-creation
Merge in DNS/adguard-home from 4944-dhcp-creation to master

Updates #4944.
Updates #5191.

Squashed commit of the following:

commit f5bc5678bdf436e5eb7f17017dd78d8c8a127313
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Fri Nov 25 18:07:35 2022 +0300

    all: log changes, imp log

commit 526fe711a2103ea11ab46992ee897a7d430ef773
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Fri Nov 25 17:38:30 2022 +0300

    dhcpd: log creation err as debug
2022-11-25 18:21:25 +03:00
Eugene Burkov
53a366ed46 Pull request: 5189-run-bad-cert
Merge in DNS/adguard-home from 5189-run-bad-cert to master

Closes #5189.

Squashed commit of the following:

commit 9e6ac6218163c7408200ce5fd591e8e6f5181f00
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Nov 24 19:17:43 2022 +0300

    all: imp chlog again

commit 5870aee8efc3213feffbe1e61b2f5b411a69ece7
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Nov 24 18:57:54 2022 +0300

    all: imp chlog

commit ec0d4b6ead14a6a6698d4a27819e679b2d4c7a0b
Author: Eugene Burkov <E.Burkov@AdGuard.COM>
Date:   Thu Nov 24 18:43:04 2022 +0300

    home: rm fatal on tls init errors
2022-11-25 15:41:54 +03:00
Ainar Garipov
9c4bed31e7 Pull request: use-download-url
Merge in DNS/adguard-home from use-download-url to master

Squashed commit of the following:

commit d665794ef0594b87044c7a1aadac6ac9dc31722a
Author: Ainar Garipov <A.Garipov@AdGuard.COM>
Date:   Thu Nov 24 18:06:36 2022 +0300

    all: use download url for vetted lists
2022-11-24 18:44:39 +03:00
yscialom
b82c67405f Fix #4714: correctly check thread can bind to privileged ports 2022-07-09 17:21:56 +02:00
401 changed files with 5318 additions and 24426 deletions

View File

@@ -7,9 +7,9 @@
'name': 'AdGuard filters issues' 'name': 'AdGuard filters issues'
'url': 'https://link.adtidy.org/forward.html?action=report&app=home&from=github' 'url': 'https://link.adtidy.org/forward.html?action=report&app=home&from=github'
- 'about': > - 'about': >
Please send requests for addition to the vetted filtering lists to the Please send requests for new blocked services and vetted filtering lists
Hostlists Registry repository. to the Hostlists Registry repository
'name': 'AdGuard Hostlists Registry' 'name': 'Blocked services and vetted filtering rule lists: AdGuard Hostlists Registry'
'url': 'https://github.com/AdguardTeam/HostlistsRegistry' 'url': 'https://github.com/AdguardTeam/HostlistsRegistry'
- 'about': > - 'about': >
Please use GitHub Discussions for questions Please use GitHub Discussions for questions

View File

@@ -1,7 +1,7 @@
'name': 'build' 'name': 'build'
'env': 'env':
'GO_VERSION': '1.18.8' 'GO_VERSION': '1.18.9'
'NODE_VERSION': '14' 'NODE_VERSION': '14'
'on': 'on':

View File

@@ -1,7 +1,7 @@
'name': 'lint' 'name': 'lint'
'env': 'env':
'GO_VERSION': '1.18.8' 'GO_VERSION': '1.18.9'
'on': 'on':
'push': 'push':

2
.gitignore vendored
View File

@@ -12,7 +12,6 @@
/agh-backup/ /agh-backup/
/bin/ /bin/
/build/* /build/*
/build2/*
/data/ /data/
/dist/ /dist/
/filtering/tests/filtering.TestLotsOfRules*.pprof /filtering/tests/filtering.TestLotsOfRules*.pprof
@@ -26,4 +25,3 @@ leases.db
node_modules/ node_modules/
!/build/gitkeep !/build/gitkeep
!/build2/gitkeep

View File

@@ -13,17 +13,158 @@ and this project adheres to
<!-- <!--
## [v0.108.0] - TBA ## [v0.108.0] - TBA
## [v0.107.24] - 2023-02-22 (APPROX.)
See also the [v0.107.24 GitHub milestone][ms-v0.107.24].
[ms-v0.107.24]: https://github.com/AdguardTeam/AdGuardHome/milestone/60?closed=1
NOTE: Add new changes BELOW THIS COMMENT.
-->
### Fixed
- The icon for League Of Legends on the Blocked services page ([#5433]).
[#5433]: https://github.com/AdguardTeam/AdGuardHome/issues/5433
<!--
NOTE: Add new changes ABOVE THIS COMMENT.
--> -->
<!-- ## [v0.107.23] - 2023-02-01
## [v0.107.20] - 2022-12-07 (APPROX.)
See also the [v0.107.23 GitHub milestone][ms-v0.107.23].
### Added
- DNS64 support ([#5117]). The function may be enabled with new `use_dns64`
field under `dns` object in the configuration along with `dns64_prefixes`, the
set of exclusion prefixes to filter AAAA responses. The Well-Known Prefix
(`64:ff9b::/96`) is used if no custom prefixes are specified.
### Fixed
- Filtering rules with `*` as the hostname not working properly ([#5245]).
- Various dark theme bugs ([#5375]).
### Removed
- The “beta frontend” and the corresponding APIs. They never quite worked
properly, and the future new version of AdGuard Home API will probably be
different.
Correspondingly, the configuration parameter `beta_bind_port` has been removed
as well.
[#5117]: https://github.com/AdguardTeam/AdGuardHome/issues/5117
[#5245]: https://github.com/AdguardTeam/AdGuardHome/issues/5245
[#5375]: https://github.com/AdguardTeam/AdGuardHome/issues/5375
[ms-v0.107.23]: https://github.com/AdguardTeam/AdGuardHome/milestone/59?closed=1
## [v0.107.22] - 2023-01-19
See also the [v0.107.22 GitHub milestone][ms-v0.107.22].
### Added
- Experimental Dark UI theme ([#613]).
- The new HTTP API `PUT /control/profile/update`, that updates current user
language and UI theme. The format of request body is described in
`openapi/openapi.yaml`.
### Changed
- The HTTP API `GET /control/profile` now returns enhanced object with
current user's name, language, and UI theme. The format of response body is
described in `openapi/openapi.yaml` and `openapi/CHANGELOG.md`.
### Fixed
- `AdGuardHome --update` freezing when another instance of AdGuard Home is
running ([#4223], [#5191]).
- The `--update` flag performing an update even when there is no version change.
- Failing HTTPS redirection on saving the encryption settings ([#4898]).
- Zeroing rules counter of erroneously edited filtering rule lists ([#5290]).
- Filters updating strategy, which could sometimes lead to use of broken or
incompletely downloaded lists ([#5258]).
[#613]: https://github.com/AdguardTeam/AdGuardHome/issues/613
[#5191]: https://github.com/AdguardTeam/AdGuardHome/issues/5191
[#5290]: https://github.com/AdguardTeam/AdGuardHome/issues/5290
[#5258]: https://github.com/AdguardTeam/AdGuardHome/issues/5258
[ms-v0.107.22]: https://github.com/AdguardTeam/AdGuardHome/milestone/58?closed=1
## [v0.107.21] - 2022-12-15
See also the [v0.107.21 GitHub milestone][ms-v0.107.21].
### Changed
- The URLs of the default filters for new installations are synchronized to
those introduced in v0.107.20 ([#5238]).
**NOTE:** Some users may need to re-add the lists from the vetted filter lists
to update the URLs to the new ones. Custom filters added by users themselves
do not require re-adding.
### Fixed
- Errors popping up during updates of settings, which could sometimes cause the
server to stop responding ([#5251]).
[#5238]: https://github.com/AdguardTeam/AdGuardHome/issues/5238
[#5251]: https://github.com/AdguardTeam/AdGuardHome/issues/5251
[ms-v0.107.21]: https://github.com/AdguardTeam/AdGuardHome/milestone/57?closed=1
## [v0.107.20] - 2022-12-07
See also the [v0.107.20 GitHub milestone][ms-v0.107.20]. See also the [v0.107.20 GitHub milestone][ms-v0.107.20].
### Security
- Go version has been updated to prevent the possibility of exploiting the
CVE-2022-41717 and CVE-2022-41720 Go vulnerabilities fixed in [Go
1.18.9][go-1.18.9].
### Added
- The ability to clear the DNS cache ([#5190]).
### Changed
- DHCP server initialization errors are now logged at debug level if the server
itself disabled ([#4944]).
### Fixed
- Wrong validation error messages on the DHCP configuration page ([#5208]).
- Slow upstream checks making the API unresponsive ([#5193]).
- The TLS initialization errors preventing AdGuard Home from starting ([#5189]).
Instead, AdGuard Home disables encryption and shows an error message on the
encryption settings page in the UI, which was the intended previous behavior.
- URLs of some vetted blocklists.
[#4944]: https://github.com/AdguardTeam/AdGuardHome/issues/4944
[#5189]: https://github.com/AdguardTeam/AdGuardHome/issues/5189
[#5190]: https://github.com/AdguardTeam/AdGuardHome/issues/5190
[#5193]: https://github.com/AdguardTeam/AdGuardHome/issues/5193
[#5208]: https://github.com/AdguardTeam/AdGuardHome/issues/5208
[go-1.18.9]: https://groups.google.com/g/golang-announce/c/L_3rmdT0BMU
[ms-v0.107.20]: https://github.com/AdguardTeam/AdGuardHome/milestone/56?closed=1 [ms-v0.107.20]: https://github.com/AdguardTeam/AdGuardHome/milestone/56?closed=1
-->
@@ -1443,11 +1584,15 @@ See also the [v0.104.2 GitHub milestone][ms-v0.104.2].
<!-- <!--
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.20...HEAD [Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.24...HEAD
[v0.107.20]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.19...v0.107.20 [v0.107.24]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.23...v0.107.24
--> -->
[Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.19...HEAD [Unreleased]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.23...HEAD
[v0.107.23]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.22...v0.107.23
[v0.107.22]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.21...v0.107.22
[v0.107.21]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.20...v0.107.21
[v0.107.20]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.19...v0.107.20
[v0.107.19]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.18...v0.107.19 [v0.107.19]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.18...v0.107.19
[v0.107.18]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.17...v0.107.18 [v0.107.18]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.17...v0.107.18
[v0.107.17]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.16...v0.107.17 [v0.107.17]: https://github.com/AdguardTeam/AdGuardHome/compare/v0.107.16...v0.107.17

View File

@@ -5,7 +5,6 @@
.POSIX: .POSIX:
CHANNEL = development CHANNEL = development
CLIENT_BETA_DIR = client2
CLIENT_DIR = client CLIENT_DIR = client
COMMIT = $$( git rev-parse --short HEAD ) COMMIT = $$( git rev-parse --short HEAD )
DIST_DIR = dist DIST_DIR = dist
@@ -29,10 +28,6 @@ SIGN = 1
VERBOSE = 0 VERBOSE = 0
VERSION = v0.0.0 VERSION = v0.0.0
YARN = yarn YARN = yarn
YARN_FLAGS = --cwd $(CLIENT_BETA_DIR)
YARN_INSTALL_FLAGS = $(YARN_FLAGS) --network-timeout 120000 --silent\
--ignore-engines --ignore-optional --ignore-platform\
--ignore-scripts
NEXTAPI = 0 NEXTAPI = 0
@@ -93,17 +88,13 @@ init: ; git config core.hooksPath ./scripts/hooks
js-build: js-build:
$(NPM) $(NPM_FLAGS) run build-prod $(NPM) $(NPM_FLAGS) run build-prod
$(YARN) $(YARN_FLAGS) build
js-deps: js-deps:
$(NPM) $(NPM_INSTALL_FLAGS) ci $(NPM) $(NPM_INSTALL_FLAGS) ci
$(YARN) $(YARN_INSTALL_FLAGS) install
# TODO(a.garipov): Remove the legacy client tasks support once the new # TODO(a.garipov): Remove the legacy client tasks support once the new
# client is done and the old one is removed. # client is done and the old one is removed.
js-lint: ; $(NPM) $(NPM_FLAGS) run lint js-lint: ; $(NPM) $(NPM_FLAGS) run lint
js-test: ; $(NPM) $(NPM_FLAGS) run test js-test: ; $(NPM) $(NPM_FLAGS) run test
js-beta-lint: ; $(YARN) $(YARN_FLAGS) lint
js-beta-test: ; # TODO(v.abdulmyanov): Add tests for the new client.
go-build: ; $(ENV) "$(SHELL)" ./scripts/make/go-build.sh go-build: ; $(ENV) "$(SHELL)" ./scripts/make/go-build.sh
go-deps: ; $(ENV) "$(SHELL)" ./scripts/make/go-deps.sh go-deps: ; $(ENV) "$(SHELL)" ./scripts/make/go-deps.sh

View File

@@ -7,7 +7,7 @@
# Make sure to sync any changes with the branch overrides below. # Make sure to sync any changes with the branch overrides below.
'variables': 'variables':
'channel': 'edge' 'channel': 'edge'
'dockerGo': 'adguard/golang-ubuntu:5.3' 'dockerGo': 'adguard/golang-ubuntu:5.4'
'stages': 'stages':
- 'Build frontend': - 'Build frontend':
@@ -109,7 +109,8 @@
CHANNEL=${bamboo.channel}\ CHANNEL=${bamboo.channel}\
GPG_KEY_PASSPHRASE=${bamboo.gpgPassword}\ GPG_KEY_PASSPHRASE=${bamboo.gpgPassword}\
FRONTEND_PREBUILT=1\ FRONTEND_PREBUILT=1\
VERBOSE=1\ PARALLELISM=1\
VERBOSE=2\
build-release build-release
# TODO(a.garipov): Use more fine-grained artifact rules. # TODO(a.garipov): Use more fine-grained artifact rules.
'artifacts': 'artifacts':
@@ -322,7 +323,7 @@
# need to build a few of these. # need to build a few of these.
'variables': 'variables':
'channel': 'beta' 'channel': 'beta'
'dockerGo': 'adguard/golang-ubuntu:5.3' 'dockerGo': 'adguard/golang-ubuntu:5.4'
# release-vX.Y.Z branches are the branches from which the actual final release # release-vX.Y.Z branches are the branches from which the actual final release
# is built. # is built.
- '^release-v[0-9]+\.[0-9]+\.[0-9]+': - '^release-v[0-9]+\.[0-9]+\.[0-9]+':
@@ -337,4 +338,4 @@
# are the ones that actually get released. # are the ones that actually get released.
'variables': 'variables':
'channel': 'release' 'channel': 'release'
'dockerGo': 'adguard/golang-ubuntu:5.3' 'dockerGo': 'adguard/golang-ubuntu:5.4'

View File

@@ -5,7 +5,7 @@
'key': 'AHBRTSPECS' 'key': 'AHBRTSPECS'
'name': 'AdGuard Home - Build and run tests' 'name': 'AdGuard Home - Build and run tests'
'variables': 'variables':
'dockerGo': 'adguard/golang-ubuntu:5.3' 'dockerGo': 'adguard/golang-ubuntu:5.4'
'stages': 'stages':
- 'Tests': - 'Tests':

View File

@@ -1 +0,0 @@
Keep this file non-hidden for Go's embedding to work.

View File

@@ -37,8 +37,6 @@
"dhcp_ipv6_settings": "DHCP IPv6 إعدادات", "dhcp_ipv6_settings": "DHCP IPv6 إعدادات",
"form_error_required": "الحقل مطلوب", "form_error_required": "الحقل مطلوب",
"form_error_ip4_format": "عنوان IPv4 غير صالح", "form_error_ip4_format": "عنوان IPv4 غير صالح",
"form_error_ip4_range_start_format": "عناوين البداية لـIPv4 غير صالحة للنطاق",
"form_error_ip4_range_end_format": "عناوين IPv4 غير صالحة لنطاق النهاية",
"form_error_ip4_gateway_format": "عنوان IPv4 غير صالح للبوابة", "form_error_ip4_gateway_format": "عنوان IPv4 غير صالح للبوابة",
"form_error_ip6_format": "عنوان IPv6 غير صالح", "form_error_ip6_format": "عنوان IPv6 غير صالح",
"form_error_ip_format": "عنوان IP غير صحيح", "form_error_ip_format": "عنوان IP غير صحيح",
@@ -51,7 +49,6 @@
"out_of_range_error": "يجب أن يكون خارج النطاق \"{{start}}\" - \"{{end}}\"", "out_of_range_error": "يجب أن يكون خارج النطاق \"{{start}}\" - \"{{end}}\"",
"lower_range_start_error": "يجب أن يكون أقل من نطاق البداية", "lower_range_start_error": "يجب أن يكون أقل من نطاق البداية",
"greater_range_start_error": "يجب أن يكون أكبر من نطاق البداية", "greater_range_start_error": "يجب أن يكون أكبر من نطاق البداية",
"greater_range_end_error": "يجب أن يكون أكبر من نطاق النهاية",
"subnet_error": "يجب أن تكون العناوين في شبكة فرعية واحدة", "subnet_error": "يجب أن تكون العناوين في شبكة فرعية واحدة",
"gateway_or_subnet_invalid": "قناع الشبكة الفرعية غير صالح", "gateway_or_subnet_invalid": "قناع الشبكة الفرعية غير صالح",
"dhcp_form_gateway_input": "IP البوابة", "dhcp_form_gateway_input": "IP البوابة",
@@ -300,6 +297,8 @@
"blocking_mode_nxdomain": "NXDOMAIN: الرد باستخدام رمز NXDOMAIN", "blocking_mode_nxdomain": "NXDOMAIN: الرد باستخدام رمز NXDOMAIN",
"blocking_mode_null_ip": "IP Null: الاستجابة بعنوان IP صفري (0.0.0.0 لـ A ؛ :: لـ AAAA)", "blocking_mode_null_ip": "IP Null: الاستجابة بعنوان IP صفري (0.0.0.0 لـ A ؛ :: لـ AAAA)",
"blocking_mode_custom_ip": "استجابة IP مخصصة بعنوان IP تم تعيينه يدويًا", "blocking_mode_custom_ip": "استجابة IP مخصصة بعنوان IP تم تعيينه يدويًا",
"theme_light": "فاتح",
"theme_dark": "ليلي",
"upstream_dns_client_desc": "إذا احتفظت بهذا الحقل فارغًا ، فسيستخدم AdGuard Home الخوادم التي تم تكوينها في<0>DNS إعدادات</0>.", "upstream_dns_client_desc": "إذا احتفظت بهذا الحقل فارغًا ، فسيستخدم AdGuard Home الخوادم التي تم تكوينها في<0>DNS إعدادات</0>.",
"tracker_source": "مصدر المتعقب", "tracker_source": "مصدر المتعقب",
"source_label": "المصدر", "source_label": "المصدر",

View File

@@ -37,8 +37,6 @@
"dhcp_ipv6_settings": "Налады DHCP IPv6", "dhcp_ipv6_settings": "Налады DHCP IPv6",
"form_error_required": "Абавязковае поле", "form_error_required": "Абавязковае поле",
"form_error_ip4_format": "Няслушны IPv4-адрас", "form_error_ip4_format": "Няслушны IPv4-адрас",
"form_error_ip4_range_start_format": "Няслушны IPv4-адрас пачатку дыяпазону",
"form_error_ip4_range_end_format": "Няслушны IPv4-адрас канца дыяпазону",
"form_error_ip4_gateway_format": "Няслушны IPv4-адрас шлюза", "form_error_ip4_gateway_format": "Няслушны IPv4-адрас шлюза",
"form_error_ip6_format": "Няслушны IPv6-адрас", "form_error_ip6_format": "Няслушны IPv6-адрас",
"form_error_ip_format": "Няслушны IP-адрас", "form_error_ip_format": "Няслушны IP-адрас",
@@ -51,7 +49,6 @@
"out_of_range_error": "Павінна быць па-за дыяпазонам «{{start}}»-«{{end}}»", "out_of_range_error": "Павінна быць па-за дыяпазонам «{{start}}»-«{{end}}»",
"lower_range_start_error": "Павінна быць менш за пачатак дыяпазону", "lower_range_start_error": "Павінна быць менш за пачатак дыяпазону",
"greater_range_start_error": "Павінна быць больш за пачатак дыяпазону", "greater_range_start_error": "Павінна быць больш за пачатак дыяпазону",
"greater_range_end_error": "Павінна быць больш за канец дыяпазону",
"subnet_error": "Адрасы павінны быць усярэдзіне адной падсеткі", "subnet_error": "Адрасы павінны быць усярэдзіне адной падсеткі",
"gateway_or_subnet_invalid": "Некарэктная маска падсеткі", "gateway_or_subnet_invalid": "Некарэктная маска падсеткі",
"dhcp_form_gateway_input": "IP-адрас шлюза", "dhcp_form_gateway_input": "IP-адрас шлюза",
@@ -301,6 +298,9 @@
"blocking_mode_nxdomain": "NXDOMAIN: Адказвае з кодам NXDOMAIN\n", "blocking_mode_nxdomain": "NXDOMAIN: Адказвае з кодам NXDOMAIN\n",
"blocking_mode_null_ip": "Нулёвы IP: Адказвае з нулёвым IP-адрасам (0.0.0.0 для A; :: для AAAA)", "blocking_mode_null_ip": "Нулёвы IP: Адказвае з нулёвым IP-адрасам (0.0.0.0 для A; :: для AAAA)",
"blocking_mode_custom_ip": "Карыстацкі IP: Адказвае з ручна наладжаным IP-адрасам", "blocking_mode_custom_ip": "Карыстацкі IP: Адказвае з ручна наладжаным IP-адрасам",
"theme_auto": "Аўто",
"theme_light": "Светлая",
"theme_dark": "Цёмная",
"upstream_dns_client_desc": "Калі пакінуць поле пустым, AdGuard Home будзе звяртацца да сервераў, паказаных у <0>наладах DNS</0>.", "upstream_dns_client_desc": "Калі пакінуць поле пустым, AdGuard Home будзе звяртацца да сервераў, паказаных у <0>наладах DNS</0>.",
"tracker_source": "Крыніца трэкінгу", "tracker_source": "Крыніца трэкінгу",
"source_label": "Крыніца", "source_label": "Крыніца",
@@ -393,7 +393,7 @@
"encryption_issuer": "Выдавец", "encryption_issuer": "Выдавец",
"encryption_hostnames": "Імёны хастоў", "encryption_hostnames": "Імёны хастоў",
"encryption_reset": "Вы ўпэўнены, што хочаце скінуць налады шыфравання?", "encryption_reset": "Вы ўпэўнены, што хочаце скінуць налады шыфравання?",
"encryption_warning": "Увага", "encryption_warning": "Папярэджанне",
"topline_expiring_certificate": "Ваш SSL-сертыфікат хутка мінае. Абновіце <0>Налады шыфравання</0>.", "topline_expiring_certificate": "Ваш SSL-сертыфікат хутка мінае. Абновіце <0>Налады шыфравання</0>.",
"topline_expired_certificate": "Ваш SSL-сертыфікат мінуў. Абновіце <0>Налады шыфравання</0>.", "topline_expired_certificate": "Ваш SSL-сертыфікат мінуў. Абновіце <0>Налады шыфравання</0>.",
"form_error_port_range": "Увядзіце нумар порта з інтэрвалу 80-65535", "form_error_port_range": "Увядзіце нумар порта з інтэрвалу 80-65535",
@@ -454,6 +454,7 @@
"updates_checked": "Даступная новая версія AdGuard Home", "updates_checked": "Даступная новая версія AdGuard Home",
"updates_version_equal": "Версія AdGuard Home актуальная", "updates_version_equal": "Версія AdGuard Home актуальная",
"check_updates_now": "Праверыць абнаўленні", "check_updates_now": "Праверыць абнаўленні",
"version_request_error": "Памылка пры праверцы наяўнасці абнаўленняў. Праверце ваша інтэрнэт-злучэнне.",
"dns_privacy": "Зашыфраваны DNS", "dns_privacy": "Зашыфраваны DNS",
"setup_dns_privacy_1": "<0>DNS-over-TLS:</0> Ужывайце радок <1>{{address}}</1>.", "setup_dns_privacy_1": "<0>DNS-over-TLS:</0> Ужывайце радок <1>{{address}}</1>.",
"setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> Ужывайце радок <1>{{address}}</1>.", "setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> Ужывайце радок <1>{{address}}</1>.",
@@ -638,5 +639,8 @@
"safe_browsing": "Бяспечны інтэрнэт", "safe_browsing": "Бяспечны інтэрнэт",
"served_from_cache": "{{value}} <i>(атрымана з кэша)</i>", "served_from_cache": "{{value}} <i>(атрымана з кэша)</i>",
"form_error_password_length": "Пароль павінен быць не менш за {{value}} сімвалаў", "form_error_password_length": "Пароль павінен быць не менш за {{value}} сімвалаў",
"anonymizer_notification": "<0>Заўвага:</0> Ананімізацыя IP уключана. Вы можаце адключыць яго ў <1>Агульных наладах</1> ." "anonymizer_notification": "<0>Заўвага:</0> Ананімізацыя IP уключана. Вы можаце адключыць яго ў <1>Агульных наладах</1> .",
"confirm_dns_cache_clear": "Вы ўпэўнены, што хочаце ачысціць кэш DNS?",
"cache_cleared": "Кэш DNS паспяхова ачышчаны",
"clear_cache": "Ачысціць кэш"
} }

View File

@@ -37,8 +37,6 @@
"dhcp_ipv6_settings": "Nastavení DHCP IPv6", "dhcp_ipv6_settings": "Nastavení DHCP IPv6",
"form_error_required": "Povinné pole", "form_error_required": "Povinné pole",
"form_error_ip4_format": "Neplatná adresa IPv4", "form_error_ip4_format": "Neplatná adresa IPv4",
"form_error_ip4_range_start_format": "Neplatná adresa IPv4 na začátku rozsahu",
"form_error_ip4_range_end_format": "Neplatná adresa IPv4 na konci rozsahu",
"form_error_ip4_gateway_format": "Neplatná adresa IPv4 brány", "form_error_ip4_gateway_format": "Neplatná adresa IPv4 brány",
"form_error_ip6_format": "Neplatná adresa IPv6", "form_error_ip6_format": "Neplatná adresa IPv6",
"form_error_ip_format": "Neplatná IP adresa", "form_error_ip_format": "Neplatná IP adresa",
@@ -51,7 +49,6 @@
"out_of_range_error": "Musí být mimo rozsah \"{{start}}\"-\"{{end}}\"", "out_of_range_error": "Musí být mimo rozsah \"{{start}}\"-\"{{end}}\"",
"lower_range_start_error": "Musí být menší než začátek rozsahu", "lower_range_start_error": "Musí být menší než začátek rozsahu",
"greater_range_start_error": "Musí být větší než začátek rozsahu", "greater_range_start_error": "Musí být větší než začátek rozsahu",
"greater_range_end_error": "Musí být větší než konec rozsahu",
"subnet_error": "Adresy musí být v jedné podsíti", "subnet_error": "Adresy musí být v jedné podsíti",
"gateway_or_subnet_invalid": "Neplatná maska podsítě", "gateway_or_subnet_invalid": "Neplatná maska podsítě",
"dhcp_form_gateway_input": "IP brána", "dhcp_form_gateway_input": "IP brána",
@@ -168,8 +165,8 @@
"enabled_safe_browsing_toast": "Zapnuté bezpečné prohlížení", "enabled_safe_browsing_toast": "Zapnuté bezpečné prohlížení",
"disabled_parental_toast": "Vypnutá Rodičovská kontrola", "disabled_parental_toast": "Vypnutá Rodičovská kontrola",
"enabled_parental_toast": "Zapnutá Rodičovská kontrola", "enabled_parental_toast": "Zapnutá Rodičovská kontrola",
"disabled_safe_search_toast": "Zapnuté bezpečné vyhledávání", "disabled_safe_search_toast": "Vypnuté bezpečné vyhledávání",
"enabled_save_search_toast": "Vypnuté bezpečné vyhledávání", "enabled_save_search_toast": "Zapnuté bezpečné vyhledávání",
"enabled_table_header": "Zapnuto", "enabled_table_header": "Zapnuto",
"name_table_header": "Název", "name_table_header": "Název",
"list_url_table_header": "Seznam URL", "list_url_table_header": "Seznam URL",
@@ -301,6 +298,9 @@
"blocking_mode_nxdomain": "NXDOMAIN: Odezva s kódem NXDOMAIN", "blocking_mode_nxdomain": "NXDOMAIN: Odezva s kódem NXDOMAIN",
"blocking_mode_null_ip": "Nulová IP: Odezva s nulovou IP adresou (0.0.0.0 pro A; :: pro AAAA)", "blocking_mode_null_ip": "Nulová IP: Odezva s nulovou IP adresou (0.0.0.0 pro A; :: pro AAAA)",
"blocking_mode_custom_ip": "Vlastní IP. odezva s ručně nastavenou IP adresou", "blocking_mode_custom_ip": "Vlastní IP. odezva s ručně nastavenou IP adresou",
"theme_auto": "Autom.",
"theme_light": "Světlý",
"theme_dark": "Tmavý",
"upstream_dns_client_desc": "Pokud toto pole ponecháte prázdné, AdGuard Home použije servery nakonfigurované v<0>DNS nastavení</0>.", "upstream_dns_client_desc": "Pokud toto pole ponecháte prázdné, AdGuard Home použije servery nakonfigurované v<0>DNS nastavení</0>.",
"tracker_source": "Zdroj slídiče", "tracker_source": "Zdroj slídiče",
"source_label": "Zdroj", "source_label": "Zdroj",
@@ -454,6 +454,7 @@
"updates_checked": "Nová verze AdGuard Home je k dispozici\n", "updates_checked": "Nová verze AdGuard Home je k dispozici\n",
"updates_version_equal": "AdGuard Home je aktuální", "updates_version_equal": "AdGuard Home je aktuální",
"check_updates_now": "Zkontrolovat aktualizace nyní", "check_updates_now": "Zkontrolovat aktualizace nyní",
"version_request_error": "Kontrola aktualizace se nezdařila. Zkontrolujte prosím připojení k Internetu.",
"dns_privacy": "Soukromí DNS", "dns_privacy": "Soukromí DNS",
"setup_dns_privacy_1": "<0>DNS skrze TLS:</0> Použít <1>{{address}}</1> řetězec.", "setup_dns_privacy_1": "<0>DNS skrze TLS:</0> Použít <1>{{address}}</1> řetězec.",
"setup_dns_privacy_2": "<0>DNS skrze HTTPS:</0> Použít <1>{{address}}</1> řetězec.", "setup_dns_privacy_2": "<0>DNS skrze HTTPS:</0> Použít <1>{{address}}</1> řetězec.",
@@ -638,5 +639,8 @@
"safe_browsing": "Bezpečné prohlížení", "safe_browsing": "Bezpečné prohlížení",
"served_from_cache": "{{value}} <i>(převzato z mezipaměti)</i>", "served_from_cache": "{{value}} <i>(převzato z mezipaměti)</i>",
"form_error_password_length": "Heslo musí být alespoň {{value}} znaků dlouhé", "form_error_password_length": "Heslo musí být alespoň {{value}} znaků dlouhé",
"anonymizer_notification": "<0>Poznámka:</0> Anonymizace IP je zapnuta. Můžete ji vypnout v <1>Obecných nastaveních</1>." "anonymizer_notification": "<0>Poznámka:</0> Anonymizace IP je zapnuta. Můžete ji vypnout v <1>Obecných nastaveních</1>.",
"confirm_dns_cache_clear": "Opravdu chcete vymazat mezipaměť DNS?",
"cache_cleared": "Mezipaměť DNS úspěšně vymazána",
"clear_cache": "Vymazat mezipaměť"
} }

View File

@@ -37,8 +37,6 @@
"dhcp_ipv6_settings": "DHCP IPv6-indstillinger", "dhcp_ipv6_settings": "DHCP IPv6-indstillinger",
"form_error_required": "Obligatorisk felt", "form_error_required": "Obligatorisk felt",
"form_error_ip4_format": "Ugyldig IPv4-adresse", "form_error_ip4_format": "Ugyldig IPv4-adresse",
"form_error_ip4_range_start_format": "Ugyldig IPv4-startadresse for området",
"form_error_ip4_range_end_format": "Ugyldig IPv4-slutadresse for området",
"form_error_ip4_gateway_format": "Ugyldig IPv4 gateway-adresse", "form_error_ip4_gateway_format": "Ugyldig IPv4 gateway-adresse",
"form_error_ip6_format": "Ugyldig IPv6-adresse", "form_error_ip6_format": "Ugyldig IPv6-adresse",
"form_error_ip_format": "Ugyldig IP-adresse", "form_error_ip_format": "Ugyldig IP-adresse",
@@ -51,9 +49,8 @@
"out_of_range_error": "Skal være uden for området \"{{start}}\"-\"{{end}}\"", "out_of_range_error": "Skal være uden for området \"{{start}}\"-\"{{end}}\"",
"lower_range_start_error": "Skal være mindre end starten på området", "lower_range_start_error": "Skal være mindre end starten på området",
"greater_range_start_error": "Skal være større end starten på området", "greater_range_start_error": "Skal være større end starten på området",
"greater_range_end_error": "Skal være større end områdeslutning",
"subnet_error": "Adresser ska være i ét undernet", "subnet_error": "Adresser ska være i ét undernet",
"gateway_or_subnet_invalid": "Undernetmaske ugyldig", "gateway_or_subnet_invalid": "Ugyldig undernetmaske",
"dhcp_form_gateway_input": "Gateway IP", "dhcp_form_gateway_input": "Gateway IP",
"dhcp_form_subnet_input": "Undernetmaske", "dhcp_form_subnet_input": "Undernetmaske",
"dhcp_form_range_title": "Interval af IP-adresser", "dhcp_form_range_title": "Interval af IP-adresser",
@@ -301,6 +298,9 @@
"blocking_mode_nxdomain": "NXDOMAIN: Svar med NXDOMAIN-kode", "blocking_mode_nxdomain": "NXDOMAIN: Svar med NXDOMAIN-kode",
"blocking_mode_null_ip": "Null IP: Svar med nul IP-adresse (0.0.0.0 for A; :: for AAAA)", "blocking_mode_null_ip": "Null IP: Svar med nul IP-adresse (0.0.0.0 for A; :: for AAAA)",
"blocking_mode_custom_ip": "Tilpasset IP: Svar med en manuelt indstillet IP-adresse", "blocking_mode_custom_ip": "Tilpasset IP: Svar med en manuelt indstillet IP-adresse",
"theme_auto": "Auto",
"theme_light": "Lyst",
"theme_dark": "Mørkt",
"upstream_dns_client_desc": "Holdes dette felt tomt, bruger AdGuard Home de i <0>DNS-indstillingerne</0> opsatte servere.", "upstream_dns_client_desc": "Holdes dette felt tomt, bruger AdGuard Home de i <0>DNS-indstillingerne</0> opsatte servere.",
"tracker_source": "Tracker-kilde", "tracker_source": "Tracker-kilde",
"source_label": "Kilde", "source_label": "Kilde",
@@ -454,6 +454,7 @@
"updates_checked": "En ny version af AdGuard Home er tilgængelig\n", "updates_checked": "En ny version af AdGuard Home er tilgængelig\n",
"updates_version_equal": "AdGuard Home er opdateret", "updates_version_equal": "AdGuard Home er opdateret",
"check_updates_now": "Søg efter opdateringer nu", "check_updates_now": "Søg efter opdateringer nu",
"version_request_error": "Opdateringstjek mislykkedes. Tjek internetforbindelsen.",
"dns_privacy": "DNS-fortrolighed", "dns_privacy": "DNS-fortrolighed",
"setup_dns_privacy_1": "<0>DNS-over-TLS:</0> Brug <1>{{address}}</1> streng.", "setup_dns_privacy_1": "<0>DNS-over-TLS:</0> Brug <1>{{address}}</1> streng.",
"setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> Brug <1>{{address}}</1> streng.", "setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> Brug <1>{{address}}</1> streng.",
@@ -638,5 +639,8 @@
"safe_browsing": "Sikker Browsing", "safe_browsing": "Sikker Browsing",
"served_from_cache": "{{value}} <i>(leveret fra cache)</i>", "served_from_cache": "{{value}} <i>(leveret fra cache)</i>",
"form_error_password_length": "Adgangskoden skal udgøre mindst {{value}} tegn.", "form_error_password_length": "Adgangskoden skal udgøre mindst {{value}} tegn.",
"anonymizer_notification": "<0>Bemærk:</0> IP-anonymisering er aktiveret. Det kan deaktiveres via <1>Generelle indstillinger</1>." "anonymizer_notification": "<0>Bemærk:</0> IP-anonymisering er aktiveret. Det kan deaktiveres via <1>Generelle indstillinger</1>.",
"confirm_dns_cache_clear": "Sikker på, at DNS-cache skal ryddes?",
"cache_cleared": "DNS-cache hermed ryddet",
"clear_cache": "Ryd cache"
} }

View File

@@ -37,8 +37,6 @@
"dhcp_ipv6_settings": "DHCP-IPv6-Einstellungen", "dhcp_ipv6_settings": "DHCP-IPv6-Einstellungen",
"form_error_required": "Pflichtfeld", "form_error_required": "Pflichtfeld",
"form_error_ip4_format": "Ungültige IPv4-Adresse", "form_error_ip4_format": "Ungültige IPv4-Adresse",
"form_error_ip4_range_start_format": "Ungültiger Bereichsbeginn der IPv4-Adresse",
"form_error_ip4_range_end_format": "Ungültiges Bereichsende der IPv4-Adresse",
"form_error_ip4_gateway_format": "Ungültige IPv4-Adresse des Gateways", "form_error_ip4_gateway_format": "Ungültige IPv4-Adresse des Gateways",
"form_error_ip6_format": "Ungültige IPv6-Adresse", "form_error_ip6_format": "Ungültige IPv6-Adresse",
"form_error_ip_format": "Ungültige IP-Adresse", "form_error_ip_format": "Ungültige IP-Adresse",
@@ -51,7 +49,6 @@
"out_of_range_error": "Muss außerhalb des Bereichs „{{start}}“-„{{end}}“ liegen", "out_of_range_error": "Muss außerhalb des Bereichs „{{start}}“-„{{end}}“ liegen",
"lower_range_start_error": "Muss niedriger als der Bereichsbeginn sein", "lower_range_start_error": "Muss niedriger als der Bereichsbeginn sein",
"greater_range_start_error": "Muss größer als der Bereichsbeginn sein", "greater_range_start_error": "Muss größer als der Bereichsbeginn sein",
"greater_range_end_error": "Muss größer als das Bereichsende sein",
"subnet_error": "Die Adressen müssen innerhalb eines Subnetzes liegen", "subnet_error": "Die Adressen müssen innerhalb eines Subnetzes liegen",
"gateway_or_subnet_invalid": "Ungültige Subnetzmaske", "gateway_or_subnet_invalid": "Ungültige Subnetzmaske",
"dhcp_form_gateway_input": "Gateway-IP", "dhcp_form_gateway_input": "Gateway-IP",
@@ -301,6 +298,9 @@
"blocking_mode_nxdomain": "NXDOMAIN: Mit NXDOMAIN-Code antworten", "blocking_mode_nxdomain": "NXDOMAIN: Mit NXDOMAIN-Code antworten",
"blocking_mode_null_ip": "Null-IP: Antworten mit Null-IP-Adresse (0.0.0.0.0 für A; :: für AAAA)", "blocking_mode_null_ip": "Null-IP: Antworten mit Null-IP-Adresse (0.0.0.0.0 für A; :: für AAAA)",
"blocking_mode_custom_ip": "Benutzerdefinierte IP: Mit einer manuell eingestellten IP-Adresse antworten", "blocking_mode_custom_ip": "Benutzerdefinierte IP: Mit einer manuell eingestellten IP-Adresse antworten",
"theme_auto": "Auto",
"theme_light": "Hell",
"theme_dark": "Dunkel",
"upstream_dns_client_desc": "Wenn Sie dieses Feld leer lassen, verwendet AdGuard Home die Server, die in den <0>DNS-Einstellungen</0> konfiguriert sind.", "upstream_dns_client_desc": "Wenn Sie dieses Feld leer lassen, verwendet AdGuard Home die Server, die in den <0>DNS-Einstellungen</0> konfiguriert sind.",
"tracker_source": "Tracker-Quelle", "tracker_source": "Tracker-Quelle",
"source_label": "Quelle", "source_label": "Quelle",
@@ -454,6 +454,7 @@
"updates_checked": "Neue Version von AdGuard Home ist jetzt verfügbar", "updates_checked": "Neue Version von AdGuard Home ist jetzt verfügbar",
"updates_version_equal": "AdGuard Home ist aktuell", "updates_version_equal": "AdGuard Home ist aktuell",
"check_updates_now": "Jetzt nach Aktualisierungen suchen", "check_updates_now": "Jetzt nach Aktualisierungen suchen",
"version_request_error": "Aktualisierungsprüfung fehlgeschlagen. Bitte überprüfen Sie Ihre Internetverbindung.",
"dns_privacy": "DNS-Datenschutz", "dns_privacy": "DNS-Datenschutz",
"setup_dns_privacy_1": "<0>DNS-over-TLS:</0> Zeichenkette <1>{{address}}</1> verwenden.", "setup_dns_privacy_1": "<0>DNS-over-TLS:</0> Zeichenkette <1>{{address}}</1> verwenden.",
"setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> Zeichenkette <1>{{address}}</1> verwenden.", "setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> Zeichenkette <1>{{address}}</1> verwenden.",
@@ -638,5 +639,8 @@
"safe_browsing": "Internetsicherheit", "safe_browsing": "Internetsicherheit",
"served_from_cache": "{{value}} <i>(aus dem Cache abgerufen)</i>", "served_from_cache": "{{value}} <i>(aus dem Cache abgerufen)</i>",
"form_error_password_length": "Das Passwort muss mindestens {{value}} Zeichen enthalten", "form_error_password_length": "Das Passwort muss mindestens {{value}} Zeichen enthalten",
"anonymizer_notification": "<0>Hinweis:</0> Die IP-Anonymisierung ist aktiviert. Sie können sie in den <1>Allgemeinen Einstellungen</1> deaktivieren." "anonymizer_notification": "<0>Hinweis:</0> Die IP-Anonymisierung ist aktiviert. Sie können sie in den <1>Allgemeinen Einstellungen</1> deaktivieren.",
"confirm_dns_cache_clear": "Möchten Sie den DNS-Cache wirklich leeren?",
"cache_cleared": "DNS-Cache erfolgreich geleert",
"clear_cache": "Cache leeren"
} }

View File

@@ -37,8 +37,6 @@
"dhcp_ipv6_settings": "DHCP IPv6 Settings", "dhcp_ipv6_settings": "DHCP IPv6 Settings",
"form_error_required": "Required field", "form_error_required": "Required field",
"form_error_ip4_format": "Invalid IPv4 address", "form_error_ip4_format": "Invalid IPv4 address",
"form_error_ip4_range_start_format": "Invalid IPv4 address of the range start",
"form_error_ip4_range_end_format": "Invalid IPv4 address of the range end",
"form_error_ip4_gateway_format": "Invalid IPv4 address of the gateway", "form_error_ip4_gateway_format": "Invalid IPv4 address of the gateway",
"form_error_ip6_format": "Invalid IPv6 address", "form_error_ip6_format": "Invalid IPv6 address",
"form_error_ip_format": "Invalid IP address", "form_error_ip_format": "Invalid IP address",
@@ -51,9 +49,8 @@
"out_of_range_error": "Must be out of range \"{{start}}\"-\"{{end}}\"", "out_of_range_error": "Must be out of range \"{{start}}\"-\"{{end}}\"",
"lower_range_start_error": "Must be lower than range start", "lower_range_start_error": "Must be lower than range start",
"greater_range_start_error": "Must be greater than range start", "greater_range_start_error": "Must be greater than range start",
"greater_range_end_error": "Must be greater than range end",
"subnet_error": "Addresses must be in one subnet", "subnet_error": "Addresses must be in one subnet",
"gateway_or_subnet_invalid": "Subnet mask invalid", "gateway_or_subnet_invalid": "Invalid subnet mask",
"dhcp_form_gateway_input": "Gateway IP", "dhcp_form_gateway_input": "Gateway IP",
"dhcp_form_subnet_input": "Subnet mask", "dhcp_form_subnet_input": "Subnet mask",
"dhcp_form_range_title": "Range of IP addresses", "dhcp_form_range_title": "Range of IP addresses",
@@ -301,6 +298,9 @@
"blocking_mode_nxdomain": "NXDOMAIN: Respond with NXDOMAIN code", "blocking_mode_nxdomain": "NXDOMAIN: Respond with NXDOMAIN code",
"blocking_mode_null_ip": "Null IP: Respond with zero IP address (0.0.0.0 for A; :: for AAAA)", "blocking_mode_null_ip": "Null IP: Respond with zero IP address (0.0.0.0 for A; :: for AAAA)",
"blocking_mode_custom_ip": "Custom IP: Respond with a manually set IP address", "blocking_mode_custom_ip": "Custom IP: Respond with a manually set IP address",
"theme_auto": "Auto",
"theme_light": "Light",
"theme_dark": "Dark",
"upstream_dns_client_desc": "If you keep this field empty, AdGuard Home will use the servers configured in the <0>DNS settings</0>.", "upstream_dns_client_desc": "If you keep this field empty, AdGuard Home will use the servers configured in the <0>DNS settings</0>.",
"tracker_source": "Tracker source", "tracker_source": "Tracker source",
"source_label": "Source", "source_label": "Source",
@@ -454,6 +454,7 @@
"updates_checked": "A new version of AdGuard Home is available", "updates_checked": "A new version of AdGuard Home is available",
"updates_version_equal": "AdGuard Home is up-to-date", "updates_version_equal": "AdGuard Home is up-to-date",
"check_updates_now": "Check for updates now", "check_updates_now": "Check for updates now",
"version_request_error": "Update check failed. Please check your Internet connection.",
"dns_privacy": "DNS Privacy", "dns_privacy": "DNS Privacy",
"setup_dns_privacy_1": "<0>DNS-over-TLS:</0> Use <1>{{address}}</1> string.", "setup_dns_privacy_1": "<0>DNS-over-TLS:</0> Use <1>{{address}}</1> string.",
"setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> Use <1>{{address}}</1> string.", "setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> Use <1>{{address}}</1> string.",
@@ -638,5 +639,8 @@
"safe_browsing": "Safe Browsing", "safe_browsing": "Safe Browsing",
"served_from_cache": "{{value}} <i>(served from cache)</i>", "served_from_cache": "{{value}} <i>(served from cache)</i>",
"form_error_password_length": "Password must be at least {{value}} characters long", "form_error_password_length": "Password must be at least {{value}} characters long",
"anonymizer_notification": "<0>Note:</0> IP anonymization is enabled. You can disable it in <1>General settings</1>." "anonymizer_notification": "<0>Note:</0> IP anonymization is enabled. You can disable it in <1>General settings</1>.",
"confirm_dns_cache_clear": "Are you sure you want to clear DNS cache?",
"cache_cleared": "DNS cache successfully cleared",
"clear_cache": "Clear cache"
} }

View File

@@ -37,8 +37,6 @@
"dhcp_ipv6_settings": "Configuración DHCP IPv6", "dhcp_ipv6_settings": "Configuración DHCP IPv6",
"form_error_required": "Campo obligatorio", "form_error_required": "Campo obligatorio",
"form_error_ip4_format": "Dirección IPv4 no válida", "form_error_ip4_format": "Dirección IPv4 no válida",
"form_error_ip4_range_start_format": "Dirección IPv4 no válida del inicio de rango",
"form_error_ip4_range_end_format": "Dirección IPv4 no válida del final de rango",
"form_error_ip4_gateway_format": "Dirección IPv4 no válida de la puerta de enlace", "form_error_ip4_gateway_format": "Dirección IPv4 no válida de la puerta de enlace",
"form_error_ip6_format": "Dirección IPv6 no válida", "form_error_ip6_format": "Dirección IPv6 no válida",
"form_error_ip_format": "Dirección IP no válida", "form_error_ip_format": "Dirección IP no válida",
@@ -51,7 +49,6 @@
"out_of_range_error": "Debe estar fuera del rango \"{{start}}\"-\"{{end}}\"", "out_of_range_error": "Debe estar fuera del rango \"{{start}}\"-\"{{end}}\"",
"lower_range_start_error": "Debe ser inferior que el inicio de rango", "lower_range_start_error": "Debe ser inferior que el inicio de rango",
"greater_range_start_error": "Debe ser mayor que el inicio de rango", "greater_range_start_error": "Debe ser mayor que el inicio de rango",
"greater_range_end_error": "Debe ser mayor que el final de rango",
"subnet_error": "Las direcciones deben estar en una subred", "subnet_error": "Las direcciones deben estar en una subred",
"gateway_or_subnet_invalid": "Máscara de subred no válida", "gateway_or_subnet_invalid": "Máscara de subred no válida",
"dhcp_form_gateway_input": "IP de puerta de enlace", "dhcp_form_gateway_input": "IP de puerta de enlace",
@@ -301,6 +298,9 @@
"blocking_mode_nxdomain": "NXDOMAIN: Responde con el código NXDOMAIN", "blocking_mode_nxdomain": "NXDOMAIN: Responde con el código NXDOMAIN",
"blocking_mode_null_ip": "IP nulo: Responde con dirección IP cero (0.0.0.0 para A; :: para AAAA)", "blocking_mode_null_ip": "IP nulo: Responde con dirección IP cero (0.0.0.0 para A; :: para AAAA)",
"blocking_mode_custom_ip": "IP personalizada: Responde con una dirección IP establecida manualmente", "blocking_mode_custom_ip": "IP personalizada: Responde con una dirección IP establecida manualmente",
"theme_auto": "Auto",
"theme_light": "Claro",
"theme_dark": "Oscuro",
"upstream_dns_client_desc": "Si se mantiene este campo vacío, AdGuard Home utilizará los servidores configurados en la <0>configuración del DNS</0>.", "upstream_dns_client_desc": "Si se mantiene este campo vacío, AdGuard Home utilizará los servidores configurados en la <0>configuración del DNS</0>.",
"tracker_source": "Fuente del rastreador", "tracker_source": "Fuente del rastreador",
"source_label": "Fuente", "source_label": "Fuente",
@@ -454,6 +454,7 @@
"updates_checked": "La nueva versión de AdGuard Home está disponible", "updates_checked": "La nueva versión de AdGuard Home está disponible",
"updates_version_equal": "AdGuard Home está actualizado", "updates_version_equal": "AdGuard Home está actualizado",
"check_updates_now": "Buscar actualizaciones ahora", "check_updates_now": "Buscar actualizaciones ahora",
"version_request_error": "La búsqueda de actualizaciones falló. Por favor revisa tu conexión a Internet.",
"dns_privacy": "DNS cifrado", "dns_privacy": "DNS cifrado",
"setup_dns_privacy_1": "<0>DNS mediante TLS:</0> Utiliza la cadena <1>{{address}}</1>.", "setup_dns_privacy_1": "<0>DNS mediante TLS:</0> Utiliza la cadena <1>{{address}}</1>.",
"setup_dns_privacy_2": "<0>DNS mediante HTTPS:</0> Utiliza la cadena <1>{{address}}</1>.", "setup_dns_privacy_2": "<0>DNS mediante HTTPS:</0> Utiliza la cadena <1>{{address}}</1>.",
@@ -638,5 +639,8 @@
"safe_browsing": "Navegación segura", "safe_browsing": "Navegación segura",
"served_from_cache": "{{value}} <i>(servido desde la caché)</i>", "served_from_cache": "{{value}} <i>(servido desde la caché)</i>",
"form_error_password_length": "La contraseña debe tener al menos {{value}} caracteres", "form_error_password_length": "La contraseña debe tener al menos {{value}} caracteres",
"anonymizer_notification": "<0>Nota:</0> La anonimización de IP está habilitada. Puedes deshabilitarla en <1>Configuración general</1>." "anonymizer_notification": "<0>Nota:</0> La anonimización de IP está habilitada. Puedes deshabilitarla en <1>Configuración general</1>.",
"confirm_dns_cache_clear": "¿Estás seguro de que deseas borrar la caché de DNS?",
"cache_cleared": "Caché DNS borrado con éxito",
"clear_cache": "Borrar caché"
} }

View File

@@ -32,8 +32,6 @@
"dhcp_config_saved": "پیکربندی سرور DHCP ذخیره شده است", "dhcp_config_saved": "پیکربندی سرور DHCP ذخیره شده است",
"form_error_required": "فیلد مورد نیاز", "form_error_required": "فیلد مورد نیاز",
"form_error_ip4_format": "فرمت نامعتبر IPv4", "form_error_ip4_format": "فرمت نامعتبر IPv4",
"form_error_ip4_range_start_format": "قالب IPv4 شروع دامنه نامعتبر است",
"form_error_ip4_range_end_format": "قالب IPv4 پایان دامنه نامعتبر است",
"form_error_ip4_gateway_format": "قالب IPv4 درگاه نامعتبر است", "form_error_ip4_gateway_format": "قالب IPv4 درگاه نامعتبر است",
"form_error_ip6_format": "فرمت نامعتبر IPv6", "form_error_ip6_format": "فرمت نامعتبر IPv6",
"form_error_ip_format": "فرمت IPv4 نامعتبر است", "form_error_ip_format": "فرمت IPv4 نامعتبر است",
@@ -44,7 +42,6 @@
"out_of_range_error": "باید خارج از دامنه باشد\"{{start}}\"-\"{{end}}\"", "out_of_range_error": "باید خارج از دامنه باشد\"{{start}}\"-\"{{end}}\"",
"lower_range_start_error": "باید کمتر از شروع دامنه باشد", "lower_range_start_error": "باید کمتر از شروع دامنه باشد",
"greater_range_start_error": "باید بیشتر از شروع دامنه باشد", "greater_range_start_error": "باید بیشتر از شروع دامنه باشد",
"greater_range_end_error": "باید بیشتر از پایان دامنه باشد",
"subnet_error": "آدرس ها باید در یک زیرشبکه باشند", "subnet_error": "آدرس ها باید در یک زیرشبکه باشند",
"gateway_or_subnet_invalid": "پوشش زیرشبکه نامعتبر است", "gateway_or_subnet_invalid": "پوشش زیرشبکه نامعتبر است",
"dhcp_form_gateway_input": "آی پی دروازه", "dhcp_form_gateway_input": "آی پی دروازه",
@@ -422,6 +419,7 @@
"updates_checked": "نسخه جدیدی از AdGuard Home در دسترس است", "updates_checked": "نسخه جدیدی از AdGuard Home در دسترس است",
"updates_version_equal": "AdGuard Home بروز است", "updates_version_equal": "AdGuard Home بروز است",
"check_updates_now": "حالا بررسی برای بروز رسانی", "check_updates_now": "حالا بررسی برای بروز رسانی",
"version_request_error": "بررسی بروزرسانی موفق نشد.لطفا ارتباط اینترنتی خود را بررسی کنید",
"dns_privacy": "حریم خصوصی DNS", "dns_privacy": "حریم خصوصی DNS",
"setup_dns_privacy_1": "<0>DNS-over-TLS:</0> استفاده از<1>{{address}}</1> .", "setup_dns_privacy_1": "<0>DNS-over-TLS:</0> استفاده از<1>{{address}}</1> .",
"setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> استفاده از <1>{{address}}</1> .", "setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> استفاده از <1>{{address}}</1> .",

View File

@@ -37,8 +37,6 @@
"dhcp_ipv6_settings": "DHCP:n IPv6-asetukset", "dhcp_ipv6_settings": "DHCP:n IPv6-asetukset",
"form_error_required": "Pakollinen kenttä", "form_error_required": "Pakollinen kenttä",
"form_error_ip4_format": "Virheellinen IPv4-osoite", "form_error_ip4_format": "Virheellinen IPv4-osoite",
"form_error_ip4_range_start_format": "Virheellinen IPv4-osoitealueen aloitusosoite",
"form_error_ip4_range_end_format": "Virheellinen IPv4-osoitealueen päätösosoite",
"form_error_ip4_gateway_format": "Virheellinen yhdyskäytävän IPv4-osoite", "form_error_ip4_gateway_format": "Virheellinen yhdyskäytävän IPv4-osoite",
"form_error_ip6_format": "Virheellinen IPv6-osoite", "form_error_ip6_format": "Virheellinen IPv6-osoite",
"form_error_ip_format": "Virheellinen IP-osoite", "form_error_ip_format": "Virheellinen IP-osoite",
@@ -51,7 +49,6 @@
"out_of_range_error": "Oltava alueen \"{{start}}\" - \"{{end}}\" ulkopuolella", "out_of_range_error": "Oltava alueen \"{{start}}\" - \"{{end}}\" ulkopuolella",
"lower_range_start_error": "Oltava alueen aloitusarvoa pienempi", "lower_range_start_error": "Oltava alueen aloitusarvoa pienempi",
"greater_range_start_error": "Oltava alueen aloitusarvoa suurempi", "greater_range_start_error": "Oltava alueen aloitusarvoa suurempi",
"greater_range_end_error": "Oltava alueen päätösarvoa pienempi",
"subnet_error": "Osoitteiden tulee olla yhdessä aliverkossa", "subnet_error": "Osoitteiden tulee olla yhdessä aliverkossa",
"gateway_or_subnet_invalid": "Virheellinen aliverkon peite", "gateway_or_subnet_invalid": "Virheellinen aliverkon peite",
"dhcp_form_gateway_input": "Yhdyskäytävän IP-osoite", "dhcp_form_gateway_input": "Yhdyskäytävän IP-osoite",
@@ -275,7 +272,7 @@
"nxdomain": "NXDOMAIN", "nxdomain": "NXDOMAIN",
"refused": "REFUSED", "refused": "REFUSED",
"null_ip": "Tyhjä IP", "null_ip": "Tyhjä IP",
"custom_ip": "Oma IP-osoite", "custom_ip": "Mukautettu IP-osoite",
"blocking_ipv4": "IPv4-esto", "blocking_ipv4": "IPv4-esto",
"blocking_ipv6": "IPv6-esto", "blocking_ipv6": "IPv6-esto",
"dnscrypt": "DNSCrypt", "dnscrypt": "DNSCrypt",
@@ -300,7 +297,10 @@
"blocking_mode_refused": "REFUSED: Vastaa REFUSED-koodilla", "blocking_mode_refused": "REFUSED: Vastaa REFUSED-koodilla",
"blocking_mode_nxdomain": "NXDOMAIN: Vastaa NXDOMAIN-koodilla", "blocking_mode_nxdomain": "NXDOMAIN: Vastaa NXDOMAIN-koodilla",
"blocking_mode_null_ip": "Tyhjä IP: Vastaa IP-nollaosoitteella (0.0.0.0 korvaa A; :: korvaa AAAA)", "blocking_mode_null_ip": "Tyhjä IP: Vastaa IP-nollaosoitteella (0.0.0.0 korvaa A; :: korvaa AAAA)",
"blocking_mode_custom_ip": "Oma IP: Vastaa itse määritetyllä IP-osoitteella", "blocking_mode_custom_ip": "Mukautettu IP: Vastaa itse määritetyllä IP-osoitteella",
"theme_auto": "Automaattinen",
"theme_light": "Vaalea",
"theme_dark": "Tumma",
"upstream_dns_client_desc": "Jos tämä on tyhjä, käyttää AdGuard Home <0>DNS-asetuksissa</0> määritettyjä palvelimia.", "upstream_dns_client_desc": "Jos tämä on tyhjä, käyttää AdGuard Home <0>DNS-asetuksissa</0> määritettyjä palvelimia.",
"tracker_source": "Seurannan lähde", "tracker_source": "Seurannan lähde",
"source_label": "Lähde", "source_label": "Lähde",
@@ -454,6 +454,7 @@
"updates_checked": "Uusi versio AdGuard Home -ohjelmasta on saatavana\n", "updates_checked": "Uusi versio AdGuard Home -ohjelmasta on saatavana\n",
"updates_version_equal": "AdGuard Home on ajan tasalla", "updates_version_equal": "AdGuard Home on ajan tasalla",
"check_updates_now": "Tarkista päivitykset nyt", "check_updates_now": "Tarkista päivitykset nyt",
"version_request_error": "Päivitystarkistus epäonnistui. Tarkista Internet-yhteytesi.",
"dns_privacy": "DNS-tietosuoja", "dns_privacy": "DNS-tietosuoja",
"setup_dns_privacy_1": "<0>DNS-over-TLS:</0> Käytä merkkijonoa <1>{{address}}</1>.", "setup_dns_privacy_1": "<0>DNS-over-TLS:</0> Käytä merkkijonoa <1>{{address}}</1>.",
"setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> Käytä merkkijonoa <1>{{address}}</1>.", "setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> Käytä merkkijonoa <1>{{address}}</1>.",
@@ -617,7 +618,7 @@
"cache_ttl_max_override_desc": "Määritä DNS-välimuistin kohteiden enimmäiselinaika (sekunteina).", "cache_ttl_max_override_desc": "Määritä DNS-välimuistin kohteiden enimmäiselinaika (sekunteina).",
"ttl_cache_validation": "Välimuistin vähimmäiselinajan on oltava pienempi tai sama kuin enimmäiselinajan", "ttl_cache_validation": "Välimuistin vähimmäiselinajan on oltava pienempi tai sama kuin enimmäiselinajan",
"cache_optimistic": "Optimistinen välimuisti", "cache_optimistic": "Optimistinen välimuisti",
"cache_optimistic_desc": "Pakota AdGuard Home vastaamaan välimuistista vaikka sen tiedot olisivat vanhentuneet. Pyri samalla myös päivittämään tiedot.", "cache_optimistic_desc": "Pakota AdGuard Home vastaamaan välimuistista vaikka tiedot olisivat vanhentuneet. Pyri samalla myös päivittämään tiedot.",
"filter_category_general": "Yleiset", "filter_category_general": "Yleiset",
"filter_category_security": "Turvallisuus", "filter_category_security": "Turvallisuus",
"filter_category_regional": "Alueelliset", "filter_category_regional": "Alueelliset",
@@ -638,5 +639,8 @@
"safe_browsing": "Turvallinen selaus", "safe_browsing": "Turvallinen selaus",
"served_from_cache": "{{value}} <i>(jaettu välimuistista)</i>", "served_from_cache": "{{value}} <i>(jaettu välimuistista)</i>",
"form_error_password_length": "Salasanan on oltava ainakin {{value}} merkkiä", "form_error_password_length": "Salasanan on oltava ainakin {{value}} merkkiä",
"anonymizer_notification": "<0>Huomioi:</0> IP-osoitteen anonymisointi on käytössä. Voit poistaa sen käytöstä <1>Yleisistä asetuksista</1>." "anonymizer_notification": "<0>Huomioi:</0> IP-osoitteen anonymisointi on käytössä. Voit poistaa sen käytöstä <1>Yleisistä asetuksista</1>.",
"confirm_dns_cache_clear": "Haluatko varmasti tyhjentää DNS-välimuistin?",
"cache_cleared": "DNS-välimuistin tyhjennys onnistui",
"clear_cache": "Tyhjennä välimuisti"
} }

View File

@@ -37,8 +37,6 @@
"dhcp_ipv6_settings": "Paramètres IPv6 du DHCP", "dhcp_ipv6_settings": "Paramètres IPv6 du DHCP",
"form_error_required": "Champ requis", "form_error_required": "Champ requis",
"form_error_ip4_format": "Adresse IPv4 invalide", "form_error_ip4_format": "Adresse IPv4 invalide",
"form_error_ip4_range_start_format": "Adresse de début de plage IPv4 incorrecte",
"form_error_ip4_range_end_format": "Adresse de fin de plage IPv4 incorrecte",
"form_error_ip4_gateway_format": "Adresse de passerelle IPv4 invalide", "form_error_ip4_gateway_format": "Adresse de passerelle IPv4 invalide",
"form_error_ip6_format": "Adresse IPv6 invalide", "form_error_ip6_format": "Adresse IPv6 invalide",
"form_error_ip_format": "Adresse IP invalide", "form_error_ip_format": "Adresse IP invalide",
@@ -51,9 +49,8 @@
"out_of_range_error": "Doit être hors plage « {{start}} » - « {{end}} »", "out_of_range_error": "Doit être hors plage « {{start}} » - « {{end}} »",
"lower_range_start_error": "Doit être inférieur au début de plage", "lower_range_start_error": "Doit être inférieur au début de plage",
"greater_range_start_error": "Doit être supérieur au début de plage", "greater_range_start_error": "Doit être supérieur au début de plage",
"greater_range_end_error": "Doit être supérieur à la fin de plage",
"subnet_error": "Les adresses doivent être dans le même sous-réseau", "subnet_error": "Les adresses doivent être dans le même sous-réseau",
"gateway_or_subnet_invalid": "Masque de sous-réseau invalide", "gateway_or_subnet_invalid": "Masque de sous-réseau invalide.",
"dhcp_form_gateway_input": "IP de la passerelle", "dhcp_form_gateway_input": "IP de la passerelle",
"dhcp_form_subnet_input": "Masque de sous-réseau", "dhcp_form_subnet_input": "Masque de sous-réseau",
"dhcp_form_range_title": "Rangée des adresses IP", "dhcp_form_range_title": "Rangée des adresses IP",
@@ -225,7 +222,7 @@
"updated_upstream_dns_toast": "Serveurs en amont enregistrés", "updated_upstream_dns_toast": "Serveurs en amont enregistrés",
"dns_test_ok_toast": "Les serveurs DNS spécifiés fonctionnent correctement", "dns_test_ok_toast": "Les serveurs DNS spécifiés fonctionnent correctement",
"dns_test_not_ok_toast": "Impossible d'utiliser le serveur « {{key}} »: veuillez vérifier si le nom saisi est bien correct", "dns_test_not_ok_toast": "Impossible d'utiliser le serveur « {{key}} »: veuillez vérifier si le nom saisi est bien correct",
"dns_test_warning_toast": "L'amont «{{key}}» ne répond pas aux demandes de test et peut ne pas fonctionner correctement", "dns_test_warning_toast": "L'amont « {{key}} » ne répond pas aux demandes de test et peut ne pas fonctionner correctement",
"unblock": "Débloquer", "unblock": "Débloquer",
"block": "Bloquer", "block": "Bloquer",
"disallow_this_client": "Interdire ce client", "disallow_this_client": "Interdire ce client",
@@ -301,6 +298,9 @@
"blocking_mode_nxdomain": "NXDOMAIN : Répondre avec le code NXDOMAIN", "blocking_mode_nxdomain": "NXDOMAIN : Répondre avec le code NXDOMAIN",
"blocking_mode_null_ip": "IP nulle : Répondre avec une adresse IP nulle (0.0.0.0 pour A ; :: pour AAAA)", "blocking_mode_null_ip": "IP nulle : Répondre avec une adresse IP nulle (0.0.0.0 pour A ; :: pour AAAA)",
"blocking_mode_custom_ip": "IP personnalisée : Répondre avec une adresse IP définie manuellement", "blocking_mode_custom_ip": "IP personnalisée : Répondre avec une adresse IP définie manuellement",
"theme_auto": "Auto",
"theme_light": "Thème clair",
"theme_dark": "Thème sombre",
"upstream_dns_client_desc": "Si vous laissez ce champ vide, AdGuard Home utilisera les serveurs configurés dans les <0>paramètres DNS</0>.", "upstream_dns_client_desc": "Si vous laissez ce champ vide, AdGuard Home utilisera les serveurs configurés dans les <0>paramètres DNS</0>.",
"tracker_source": "Source du traceur", "tracker_source": "Source du traceur",
"source_label": "Source", "source_label": "Source",
@@ -454,6 +454,7 @@
"updates_checked": "Une nouvelle version de AdGuard Home est disponible", "updates_checked": "Une nouvelle version de AdGuard Home est disponible",
"updates_version_equal": "AdGuard Home est à jour", "updates_version_equal": "AdGuard Home est à jour",
"check_updates_now": "Vérifier les mises à jour", "check_updates_now": "Vérifier les mises à jour",
"version_request_error": "Impossible de vérifier les mises à jour. Veuillez vérifier votre connexion internet.",
"dns_privacy": "Confidentialité DNS", "dns_privacy": "Confidentialité DNS",
"setup_dns_privacy_1": "<0>DNS-over-TLS :</0> Utiliser le string <1>{{address}}</1>.", "setup_dns_privacy_1": "<0>DNS-over-TLS :</0> Utiliser le string <1>{{address}}</1>.",
"setup_dns_privacy_2": "<0>DNS-over-HTTPS :</0> Utiliser le string <1>{{address}}</1>.", "setup_dns_privacy_2": "<0>DNS-over-HTTPS :</0> Utiliser le string <1>{{address}}</1>.",
@@ -638,5 +639,8 @@
"safe_browsing": "Navigation sécurisée", "safe_browsing": "Navigation sécurisée",
"served_from_cache": "{{value}} <i>(depuis le cache)</i>", "served_from_cache": "{{value}} <i>(depuis le cache)</i>",
"form_error_password_length": "Le mot de passe doit comporter au moins {{value}} caractères", "form_error_password_length": "Le mot de passe doit comporter au moins {{value}} caractères",
"anonymizer_notification": "<0>Note :</0> L'anonymisation IP est activée. Vous pouvez la désactiver dans les <1>paramètres généraux</1>." "anonymizer_notification": "<0>Note :</0> L'anonymisation IP est activée. Vous pouvez la désactiver dans les <1>paramètres généraux</1>.",
"confirm_dns_cache_clear": "Voulez-vous vraiment vider le cache DNS ?",
"cache_cleared": "Le cache DNS a été vidé",
"clear_cache": "Vider le cache"
} }

View File

@@ -37,8 +37,6 @@
"dhcp_ipv6_settings": "DHCP IPv6 postavke", "dhcp_ipv6_settings": "DHCP IPv6 postavke",
"form_error_required": "Obavezno polje", "form_error_required": "Obavezno polje",
"form_error_ip4_format": "Nevažeća IPv4 adresa", "form_error_ip4_format": "Nevažeća IPv4 adresa",
"form_error_ip4_range_start_format": "Nepravilan početak ranga IPv4 adresa",
"form_error_ip4_range_end_format": "Nepravilan kraj ranga IPv4 adresa",
"form_error_ip4_gateway_format": "Nepravilna IPV4 adresa čvora", "form_error_ip4_gateway_format": "Nepravilna IPV4 adresa čvora",
"form_error_ip6_format": "Nevažeći IPv6 adresa", "form_error_ip6_format": "Nevažeći IPv6 adresa",
"form_error_ip_format": "Nepravilna IP adresa", "form_error_ip_format": "Nepravilna IP adresa",
@@ -51,9 +49,8 @@
"out_of_range_error": "Mora biti izvan ranga \"{{start}}\"-\"{{end}}\"", "out_of_range_error": "Mora biti izvan ranga \"{{start}}\"-\"{{end}}\"",
"lower_range_start_error": "Mora biti niže od početnog ranga", "lower_range_start_error": "Mora biti niže od početnog ranga",
"greater_range_start_error": "Mora biti veće od krajnjeg ranga", "greater_range_start_error": "Mora biti veće od krajnjeg ranga",
"greater_range_end_error": "Mora biti veće od krajnjeg ranga",
"subnet_error": "Adrese moraju biti iz iste podmreže", "subnet_error": "Adrese moraju biti iz iste podmreže",
"gateway_or_subnet_invalid": "Maska podmreže je neprvilna", "gateway_or_subnet_invalid": "Nevažeća podmrežna maska",
"dhcp_form_gateway_input": "Gateway IP", "dhcp_form_gateway_input": "Gateway IP",
"dhcp_form_subnet_input": "Subnet maskiranje", "dhcp_form_subnet_input": "Subnet maskiranje",
"dhcp_form_range_title": "Raspon IP adresa", "dhcp_form_range_title": "Raspon IP adresa",
@@ -301,6 +298,9 @@
"blocking_mode_nxdomain": "NXDOMAIN: Odgovor s NXDOMAIN kôdom", "blocking_mode_nxdomain": "NXDOMAIN: Odgovor s NXDOMAIN kôdom",
"blocking_mode_null_ip": "Nuliran IP: Odgovor s nuliranom IP adresom (0.0.0.0 za A; :: za AAAA)", "blocking_mode_null_ip": "Nuliran IP: Odgovor s nuliranom IP adresom (0.0.0.0 za A; :: za AAAA)",
"blocking_mode_custom_ip": "Prilagođeni IP: Odgovor s ručno postavljenom IP adresom", "blocking_mode_custom_ip": "Prilagođeni IP: Odgovor s ručno postavljenom IP adresom",
"theme_auto": "Auto",
"theme_light": "Svijetla",
"theme_dark": "Tamna",
"upstream_dns_client_desc": "Ako ovo polje ostane prazno, AdGuard Home će upotrijebiti poslužitelje postavljene u <0>DNS postavkama</0>.", "upstream_dns_client_desc": "Ako ovo polje ostane prazno, AdGuard Home će upotrijebiti poslužitelje postavljene u <0>DNS postavkama</0>.",
"tracker_source": "Izvor pratitelja", "tracker_source": "Izvor pratitelja",
"source_label": "Izvor", "source_label": "Izvor",
@@ -454,6 +454,7 @@
"updates_checked": "Dostupna je nova verzija AdGuard Home-a", "updates_checked": "Dostupna je nova verzija AdGuard Home-a",
"updates_version_equal": "AdGuard Home je ažuriran", "updates_version_equal": "AdGuard Home je ažuriran",
"check_updates_now": "Provjeri ažuriranja sada", "check_updates_now": "Provjeri ažuriranja sada",
"version_request_error": "Ne uspješna provjera ažuriranja. Provjerite vašu Internetsku vezu.",
"dns_privacy": "DNS privatnost", "dns_privacy": "DNS privatnost",
"setup_dns_privacy_1": "<0>DNS-over-TLS:</0> Koristite <1>{{address}}</1>.", "setup_dns_privacy_1": "<0>DNS-over-TLS:</0> Koristite <1>{{address}}</1>.",
"setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> Koristite <1>{{address}}</1>.", "setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> Koristite <1>{{address}}</1>.",
@@ -638,5 +639,8 @@
"safe_browsing": "Sigurno surfanje", "safe_browsing": "Sigurno surfanje",
"served_from_cache": "{{value}} <i>(dohvaćeno iz predmemorije)</i>", "served_from_cache": "{{value}} <i>(dohvaćeno iz predmemorije)</i>",
"form_error_password_length": "Lozinka mora imati najmanje {{value}} znakova", "form_error_password_length": "Lozinka mora imati najmanje {{value}} znakova",
"anonymizer_notification": "<0>Napomena:</0>IP anonimizacija je omogućena. Možete ju onemogućiti u <1>općim postavkama</1>." "anonymizer_notification": "<0>Napomena:</0>IP anonimizacija je omogućena. Možete ju onemogućiti u <1>općim postavkama</1>.",
"confirm_dns_cache_clear": "Jeste li sigurni da želite očistiti DNS predmemoriju?",
"cache_cleared": "DNS predmemorija je uspješno izbrisana",
"clear_cache": "Očisti predmemoriju"
} }

View File

@@ -37,8 +37,6 @@
"dhcp_ipv6_settings": "DHCP IPv6 Beállítások", "dhcp_ipv6_settings": "DHCP IPv6 Beállítások",
"form_error_required": "Kötelező mező", "form_error_required": "Kötelező mező",
"form_error_ip4_format": "Érvénytelen IPv4 cím", "form_error_ip4_format": "Érvénytelen IPv4 cím",
"form_error_ip4_range_start_format": "Érvénytelen IPv4-cím a tartomány kezdetéhez",
"form_error_ip4_range_end_format": "Érvénytelen IPv4-cím a tartomány végén",
"form_error_ip4_gateway_format": "Az átjáróhoz (gateway) érvénytelen IPv4 cím lett megadva", "form_error_ip4_gateway_format": "Az átjáróhoz (gateway) érvénytelen IPv4 cím lett megadva",
"form_error_ip6_format": "Érvénytelen IPv6 cím", "form_error_ip6_format": "Érvénytelen IPv6 cím",
"form_error_ip_format": "Érvénytelen IP-cím", "form_error_ip_format": "Érvénytelen IP-cím",
@@ -51,7 +49,6 @@
"out_of_range_error": "A következő tartományon kívül legyen: \"{{start}}\"-\"{{end}}\"", "out_of_range_error": "A következő tartományon kívül legyen: \"{{start}}\"-\"{{end}}\"",
"lower_range_start_error": "Kisebb legyen, mint a tartomány kezdete", "lower_range_start_error": "Kisebb legyen, mint a tartomány kezdete",
"greater_range_start_error": "Nagyobbnak kell lennie, mint a tartomány kezdete", "greater_range_start_error": "Nagyobbnak kell lennie, mint a tartomány kezdete",
"greater_range_end_error": "Nagyobb legyen, mint a tartomány vége",
"subnet_error": "A címeknek egy alhálózatban kell lenniük", "subnet_error": "A címeknek egy alhálózatban kell lenniük",
"gateway_or_subnet_invalid": "Az alhálózati maszk érvénytelen", "gateway_or_subnet_invalid": "Az alhálózati maszk érvénytelen",
"dhcp_form_gateway_input": "Átjáró IP", "dhcp_form_gateway_input": "Átjáró IP",
@@ -301,6 +298,9 @@
"blocking_mode_nxdomain": "NXDOMAIN: Az NXDOMAIN kóddal fog válaszolni", "blocking_mode_nxdomain": "NXDOMAIN: Az NXDOMAIN kóddal fog válaszolni",
"blocking_mode_null_ip": "Null IP: Nullákból álló IP-címmel válaszol (0.0.0.0 for A; :: for AAAA)", "blocking_mode_null_ip": "Null IP: Nullákból álló IP-címmel válaszol (0.0.0.0 for A; :: for AAAA)",
"blocking_mode_custom_ip": "Egyedi IP: Válasz egy kézzel beállított IP címmel", "blocking_mode_custom_ip": "Egyedi IP: Válasz egy kézzel beállított IP címmel",
"theme_auto": "Auto",
"theme_light": "Világos",
"theme_dark": "Sötét",
"upstream_dns_client_desc": "Ha üresen hagyja ezt a mezőt, az AdGuard Home azokat a szervereket fogja használni, amik a <0>DNS beállításokban</0> vannak beállítva.", "upstream_dns_client_desc": "Ha üresen hagyja ezt a mezőt, az AdGuard Home azokat a szervereket fogja használni, amik a <0>DNS beállításokban</0> vannak beállítva.",
"tracker_source": "Követő forrása", "tracker_source": "Követő forrása",
"source_label": "Forrás", "source_label": "Forrás",
@@ -454,6 +454,7 @@
"updates_checked": "Elérhető az AdGuard Home új verziója", "updates_checked": "Elérhető az AdGuard Home új verziója",
"updates_version_equal": "Az AdGuard Home naprakész", "updates_version_equal": "Az AdGuard Home naprakész",
"check_updates_now": "Frissítések ellenőrzése most", "check_updates_now": "Frissítések ellenőrzése most",
"version_request_error": "A frissítések ellenőrzése sikertelen. Ellenőrizze az internetkapcsolatot.",
"dns_privacy": "DNS Adatvédelem", "dns_privacy": "DNS Adatvédelem",
"setup_dns_privacy_1": "<0>DNS-over-TLS:</0> Használja a(z) <1>{{address}}</1> szöveget.", "setup_dns_privacy_1": "<0>DNS-over-TLS:</0> Használja a(z) <1>{{address}}</1> szöveget.",
"setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> Használja a(z) <1>{{address}}</1> szöveget.", "setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> Használja a(z) <1>{{address}}</1> szöveget.",
@@ -638,5 +639,8 @@
"safe_browsing": "Biztonságos böngészés", "safe_browsing": "Biztonságos böngészés",
"served_from_cache": "{{value}} <i>(gyorsítótárból kiszolgálva)</i>", "served_from_cache": "{{value}} <i>(gyorsítótárból kiszolgálva)</i>",
"form_error_password_length": "A jelszó legalább {{value}} karakter hosszú kell, hogy legyen", "form_error_password_length": "A jelszó legalább {{value}} karakter hosszú kell, hogy legyen",
"anonymizer_notification": "<0>Megjegyzés:</0> Az IP anonimizálás engedélyezve van. Az <1>Általános beállításoknál letilthatja</1> ." "anonymizer_notification": "<0>Megjegyzés:</0> Az IP anonimizálás engedélyezve van. Az <1>Általános beállításoknál letilthatja</1> .",
"confirm_dns_cache_clear": "Biztos benne, hogy törölni szeretné a DNS-gyorsítótárat?",
"cache_cleared": "A DNS gyorsítótár sikeresen törlődött",
"clear_cache": "Gyorsítótár törlése"
} }

View File

@@ -37,8 +37,6 @@
"dhcp_ipv6_settings": "Pengaturan DHCP IPv6", "dhcp_ipv6_settings": "Pengaturan DHCP IPv6",
"form_error_required": "Kolom yang harus diisi", "form_error_required": "Kolom yang harus diisi",
"form_error_ip4_format": "Alamat IPv4 tidak valid", "form_error_ip4_format": "Alamat IPv4 tidak valid",
"form_error_ip4_range_start_format": "Alamat IPv4 tidak valid dari rentang awal",
"form_error_ip4_range_end_format": "Alamat IPv4 tidak valid dari rentang akhir",
"form_error_ip4_gateway_format": "Alamat IPv4 gateway tidak valid", "form_error_ip4_gateway_format": "Alamat IPv4 gateway tidak valid",
"form_error_ip6_format": "Alamat IPv6 tidak valid", "form_error_ip6_format": "Alamat IPv6 tidak valid",
"form_error_ip_format": "Alamat IP tidak valid", "form_error_ip_format": "Alamat IP tidak valid",
@@ -51,7 +49,6 @@
"out_of_range_error": "Harus di luar rentang \"{{start}}\"-\"{{end}}\"", "out_of_range_error": "Harus di luar rentang \"{{start}}\"-\"{{end}}\"",
"lower_range_start_error": "Harus lebih rendah dari rentang awal", "lower_range_start_error": "Harus lebih rendah dari rentang awal",
"greater_range_start_error": "Harus lebih besar dari rentang awal", "greater_range_start_error": "Harus lebih besar dari rentang awal",
"greater_range_end_error": "Harus lebih besar dari rentang akhir",
"subnet_error": "Alamat harus dalam satu subnet", "subnet_error": "Alamat harus dalam satu subnet",
"gateway_or_subnet_invalid": "Subnet mask tidak valid", "gateway_or_subnet_invalid": "Subnet mask tidak valid",
"dhcp_form_gateway_input": "IP gateway", "dhcp_form_gateway_input": "IP gateway",
@@ -301,6 +298,9 @@
"blocking_mode_nxdomain": "NXDOMAIN: Respon pakai kode NXDOMAIN", "blocking_mode_nxdomain": "NXDOMAIN: Respon pakai kode NXDOMAIN",
"blocking_mode_null_ip": "Null IP: Respon pakai alamat IP kosong (0.0.0.0 untuk A; :: untuk AAAA)", "blocking_mode_null_ip": "Null IP: Respon pakai alamat IP kosong (0.0.0.0 untuk A; :: untuk AAAA)",
"blocking_mode_custom_ip": "IP kustom: respon dengan alamat IP yang diset secara manual", "blocking_mode_custom_ip": "IP kustom: respon dengan alamat IP yang diset secara manual",
"theme_auto": "Auto",
"theme_light": "Terang",
"theme_dark": "Gelap",
"upstream_dns_client_desc": "Jika Anda biarkan bidang ini kosong, AdGuard Home akan memakai server yang dikonfigurasi di<0>Pengaturan DNS</0>.", "upstream_dns_client_desc": "Jika Anda biarkan bidang ini kosong, AdGuard Home akan memakai server yang dikonfigurasi di<0>Pengaturan DNS</0>.",
"tracker_source": "Sumber pelacak", "tracker_source": "Sumber pelacak",
"source_label": "Sumber", "source_label": "Sumber",
@@ -638,5 +638,8 @@
"safe_browsing": "Penjelajahan Aman", "safe_browsing": "Penjelajahan Aman",
"served_from_cache": "{{value}} <i>(disajikan dari cache)</i>", "served_from_cache": "{{value}} <i>(disajikan dari cache)</i>",
"form_error_password_length": "Kata sandi harus minimal {{value}} karakter", "form_error_password_length": "Kata sandi harus minimal {{value}} karakter",
"anonymizer_notification": "<0>Catatan:</0> Anonimisasi IP diaktifkan. Anda dapat menonaktifkannya di <1>Pengaturan umum</1> ." "anonymizer_notification": "<0>Catatan:</0> Anonimisasi IP diaktifkan. Anda dapat menonaktifkannya di <1>Pengaturan umum</1> .",
"confirm_dns_cache_clear": "Apakah Anda yakin ingin menghapus cache DNS?",
"cache_cleared": "Cache DNS berhasil dibersihkan",
"clear_cache": "Hapus cache"
} }

View File

@@ -37,8 +37,6 @@
"dhcp_ipv6_settings": "Impostazioni DHCP IPv6", "dhcp_ipv6_settings": "Impostazioni DHCP IPv6",
"form_error_required": "Campo richiesto", "form_error_required": "Campo richiesto",
"form_error_ip4_format": "Indirizzo IPv4 non valido", "form_error_ip4_format": "Indirizzo IPv4 non valido",
"form_error_ip4_range_start_format": "Indirizzo IPV4 non valido dell'intervallo iniziale",
"form_error_ip4_range_end_format": "Indirizzo IPV4 non valido dell'intervallo finale",
"form_error_ip4_gateway_format": "Indirizzo gateway IPv4 non valido", "form_error_ip4_gateway_format": "Indirizzo gateway IPv4 non valido",
"form_error_ip6_format": "Indirizzo IPv6 non valido", "form_error_ip6_format": "Indirizzo IPv6 non valido",
"form_error_ip_format": "Indirizzo IP non valido", "form_error_ip_format": "Indirizzo IP non valido",
@@ -51,7 +49,6 @@
"out_of_range_error": "Deve essere fuori intervallo \"{{start}}\"-\"{{end}}\"", "out_of_range_error": "Deve essere fuori intervallo \"{{start}}\"-\"{{end}}\"",
"lower_range_start_error": "Deve essere inferiore dell'intervallo di inizio", "lower_range_start_error": "Deve essere inferiore dell'intervallo di inizio",
"greater_range_start_error": "Deve essere maggiore dell'intervallo di inizio", "greater_range_start_error": "Deve essere maggiore dell'intervallo di inizio",
"greater_range_end_error": "Deve essere maggiore dell'intervallo di fine",
"subnet_error": "Gli indirizzi devono trovarsi in una sottorete", "subnet_error": "Gli indirizzi devono trovarsi in una sottorete",
"gateway_or_subnet_invalid": "Maschera di sottorete non valida", "gateway_or_subnet_invalid": "Maschera di sottorete non valida",
"dhcp_form_gateway_input": "IP Gateway", "dhcp_form_gateway_input": "IP Gateway",
@@ -301,6 +298,9 @@
"blocking_mode_nxdomain": "NXDOMAIN: Rispondi con il codice NXDOMAIN", "blocking_mode_nxdomain": "NXDOMAIN: Rispondi con il codice NXDOMAIN",
"blocking_mode_null_ip": "IP nullo: Rispondi con indirizzo IP zero (0.0.0.0 per A; :: per AAAA)", "blocking_mode_null_ip": "IP nullo: Rispondi con indirizzo IP zero (0.0.0.0 per A; :: per AAAA)",
"blocking_mode_custom_ip": "IP personalizzato: Rispondi con un indirizzo IP impostato manualmente", "blocking_mode_custom_ip": "IP personalizzato: Rispondi con un indirizzo IP impostato manualmente",
"theme_auto": "Auto",
"theme_light": "Chiaro",
"theme_dark": "Scuro",
"upstream_dns_client_desc": "Se lasci questo spazio vuoto, AdGuard Home utilizzerà i server configurati nelle <0>impostazioni DNS</0>.", "upstream_dns_client_desc": "Se lasci questo spazio vuoto, AdGuard Home utilizzerà i server configurati nelle <0>impostazioni DNS</0>.",
"tracker_source": "Origine del tracciatore", "tracker_source": "Origine del tracciatore",
"source_label": "Fonte", "source_label": "Fonte",
@@ -454,6 +454,7 @@
"updates_checked": "Nuova versione di AdGuard Home è disponibile", "updates_checked": "Nuova versione di AdGuard Home è disponibile",
"updates_version_equal": "AdGuard Home è aggiornato", "updates_version_equal": "AdGuard Home è aggiornato",
"check_updates_now": "Ricerca aggiornamenti ora", "check_updates_now": "Ricerca aggiornamenti ora",
"version_request_error": "Ricerca aggiornamenti non riuscita. Per favore controlla la tua connessione internet.",
"dns_privacy": "Privacy DNS", "dns_privacy": "Privacy DNS",
"setup_dns_privacy_1": "<0>DNS su TLS:</0> Utilizza la stringa <1>{{address}}</1>.", "setup_dns_privacy_1": "<0>DNS su TLS:</0> Utilizza la stringa <1>{{address}}</1>.",
"setup_dns_privacy_2": "<0>DNS su HTTPS:</0> Utilizza la stringa <1>{{address}}</1>.", "setup_dns_privacy_2": "<0>DNS su HTTPS:</0> Utilizza la stringa <1>{{address}}</1>.",
@@ -638,5 +639,8 @@
"safe_browsing": "Navigazione Sicura", "safe_browsing": "Navigazione Sicura",
"served_from_cache": "{{value}} <i>(fornito dalla cache)</i>", "served_from_cache": "{{value}} <i>(fornito dalla cache)</i>",
"form_error_password_length": "La password deve contenere almeno {{value}} caratteri", "form_error_password_length": "La password deve contenere almeno {{value}} caratteri",
"anonymizer_notification": "<0>Attenzione:</0> L'anonimizzazione dell'IP è abilitata. Puoi disabilitarla in <1>Impostazioni generali</1>." "anonymizer_notification": "<0>Attenzione:</0> L'anonimizzazione dell'IP è abilitata. Puoi disabilitarla in <1>Impostazioni generali</1>.",
"confirm_dns_cache_clear": "Sei sicuro di voler cancellare la cache DNS?",
"cache_cleared": "Cache DNS è stata cancellata correttamente",
"clear_cache": "Cancella cache"
} }

View File

@@ -37,8 +37,6 @@
"dhcp_ipv6_settings": "DHCP IPv6 設定", "dhcp_ipv6_settings": "DHCP IPv6 設定",
"form_error_required": "必須項目です", "form_error_required": "必須項目です",
"form_error_ip4_format": "IPv4アドレスが無効です", "form_error_ip4_format": "IPv4アドレスが無効です",
"form_error_ip4_range_start_format": "範囲開始のIPv4アドレスが無効です",
"form_error_ip4_range_end_format": "範囲終了のIPv4アドレスが無効です",
"form_error_ip4_gateway_format": "ゲートウェイのIPv4アドレスが無効です", "form_error_ip4_gateway_format": "ゲートウェイのIPv4アドレスが無効です",
"form_error_ip6_format": "IPv6アドレスが無効です", "form_error_ip6_format": "IPv6アドレスが無効です",
"form_error_ip_format": "IPアドレスが無効です", "form_error_ip_format": "IPアドレスが無効です",
@@ -51,7 +49,6 @@
"out_of_range_error": "\"{{start}}\"〜\"{{end}}\" の範囲外である必要があります", "out_of_range_error": "\"{{start}}\"〜\"{{end}}\" の範囲外である必要があります",
"lower_range_start_error": "範囲開始よりも低い値である必要があります", "lower_range_start_error": "範囲開始よりも低い値である必要があります",
"greater_range_start_error": "範囲開始値より大きい値でなければなりません", "greater_range_start_error": "範囲開始値より大きい値でなければなりません",
"greater_range_end_error": "範囲終了値より大きい値でなければなりません",
"subnet_error": "両アドレスが同じサブネット内にある必要があります", "subnet_error": "両アドレスが同じサブネット内にある必要があります",
"gateway_or_subnet_invalid": "サブネットマスクが無効です", "gateway_or_subnet_invalid": "サブネットマスクが無効です",
"dhcp_form_gateway_input": "ゲートウェイIP", "dhcp_form_gateway_input": "ゲートウェイIP",
@@ -301,6 +298,9 @@
"blocking_mode_nxdomain": "NXDOMAINNXDOMAINコードで応答します", "blocking_mode_nxdomain": "NXDOMAINNXDOMAINコードで応答します",
"blocking_mode_null_ip": "Null IPゼロのIPアドレスで応答しますAの場合は0.0.0.0; AAAAの場合は::", "blocking_mode_null_ip": "Null IPゼロのIPアドレスで応答しますAの場合は0.0.0.0; AAAAの場合は::",
"blocking_mode_custom_ip": "カスタムIP手動で設定されたIPアドレスで応答します", "blocking_mode_custom_ip": "カスタムIP手動で設定されたIPアドレスで応答します",
"theme_auto": "自動",
"theme_light": "ライト",
"theme_dark": "ダーク",
"upstream_dns_client_desc": "このフィールドを未入力のままにすると、AdGuard Homeは<0>DNS設定</0>で構成されたサーバを使用します。", "upstream_dns_client_desc": "このフィールドを未入力のままにすると、AdGuard Homeは<0>DNS設定</0>で構成されたサーバを使用します。",
"tracker_source": "追跡元", "tracker_source": "追跡元",
"source_label": "ソース", "source_label": "ソース",
@@ -454,6 +454,7 @@
"updates_checked": "AdGuard Homeの新バージョンが利用可能です。", "updates_checked": "AdGuard Homeの新バージョンが利用可能です。",
"updates_version_equal": "AdGuard Homeは既に最新です", "updates_version_equal": "AdGuard Homeは既に最新です",
"check_updates_now": "今すぐアップデートを確認する", "check_updates_now": "今すぐアップデートを確認する",
"version_request_error": "アップデート確認に失敗しました。インターネット接続を確認してください。",
"dns_privacy": "DNSプライバシー", "dns_privacy": "DNSプライバシー",
"setup_dns_privacy_1": "<0>DNS-over-TLS:</0> <1>{{address}}</1>という文字列を使用してください。", "setup_dns_privacy_1": "<0>DNS-over-TLS:</0> <1>{{address}}</1>という文字列を使用してください。",
"setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> <1>{{address}}</1>という文字列を使用してください。", "setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> <1>{{address}}</1>という文字列を使用してください。",
@@ -638,5 +639,8 @@
"safe_browsing": "セーフブラウジング", "safe_browsing": "セーフブラウジング",
"served_from_cache": "{{value}} <i>(キャッシュから応答)</i>", "served_from_cache": "{{value}} <i>(キャッシュから応答)</i>",
"form_error_password_length": "パスワードは{{value}}文字以上にしてください", "form_error_password_length": "パスワードは{{value}}文字以上にしてください",
"anonymizer_notification": "【<0>注意</0>】IPの匿名化が有効になっています。 <1>一般設定</1>で無効にできます。" "anonymizer_notification": "【<0>注意</0>】IPの匿名化が有効になっています。 <1>一般設定</1>で無効にできます。",
"confirm_dns_cache_clear": "DNS キャッシュをクリアしてもよろしいですか?",
"cache_cleared": "DNSキャッシュのクリア完了です。",
"clear_cache": "キャッシュをクリアする"
} }

View File

@@ -37,8 +37,6 @@
"dhcp_ipv6_settings": "DHCP IPv6 설정", "dhcp_ipv6_settings": "DHCP IPv6 설정",
"form_error_required": "필수 영역", "form_error_required": "필수 영역",
"form_error_ip4_format": "잘못된 IPv4 형식", "form_error_ip4_format": "잘못된 IPv4 형식",
"form_error_ip4_range_start_format": "잘못된 범위 시작 IPv4 형식",
"form_error_ip4_range_end_format": "잘못된 범위 종료 IPv4 형식",
"form_error_ip4_gateway_format": "잘못된 게이트웨이 IPv4 형식", "form_error_ip4_gateway_format": "잘못된 게이트웨이 IPv4 형식",
"form_error_ip6_format": "잘못된 IPv6 주소", "form_error_ip6_format": "잘못된 IPv6 주소",
"form_error_ip_format": "잘못된 IP 주소", "form_error_ip_format": "잘못된 IP 주소",
@@ -51,7 +49,6 @@
"out_of_range_error": "'{{start}}'-'{{end}}' 범위 밖이어야 합니다", "out_of_range_error": "'{{start}}'-'{{end}}' 범위 밖이어야 합니다",
"lower_range_start_error": "범위 시작보다 작은 값이어야 합니다", "lower_range_start_error": "범위 시작보다 작은 값이어야 합니다",
"greater_range_start_error": "범위 시작보다 큰 값이어야 합니다", "greater_range_start_error": "범위 시작보다 큰 값이어야 합니다",
"greater_range_end_error": "범위 종료보다 큰 값이어야 합니다",
"subnet_error": "주소는 하나의 서브넷에 있어야 합니다", "subnet_error": "주소는 하나의 서브넷에 있어야 합니다",
"gateway_or_subnet_invalid": "잘못된 서브넷 마스크", "gateway_or_subnet_invalid": "잘못된 서브넷 마스크",
"dhcp_form_gateway_input": "게이트웨이 IP", "dhcp_form_gateway_input": "게이트웨이 IP",
@@ -223,7 +220,7 @@
"example_upstream_tcp_hostname": "일반 DNS (TCP를 통한, 호스트명);", "example_upstream_tcp_hostname": "일반 DNS (TCP를 통한, 호스트명);",
"all_lists_up_to_date_toast": "모든 리스트가 이미 최신입니다", "all_lists_up_to_date_toast": "모든 리스트가 이미 최신입니다",
"updated_upstream_dns_toast": "업스트림 서버가 성공적으로 저장되었습니다", "updated_upstream_dns_toast": "업스트림 서버가 성공적으로 저장되었습니다",
"dns_test_ok_toast": "특정 DNS 서버들은 정상적으로 동작 중입니다", "dns_test_ok_toast": "지정된 DNS 서버가 올바르게 작동하고 있습니다.",
"dns_test_not_ok_toast": "서버 '{{key}}': 사용할 수 없습니다, 제대로 작성했는지 확인하세요", "dns_test_not_ok_toast": "서버 '{{key}}': 사용할 수 없습니다, 제대로 작성했는지 확인하세요",
"dns_test_warning_toast": "업스트림 '{{key}}'이(가) 테스트 요청에 응답하지 않으며 제대로 작동하지 않을 수 있습니다", "dns_test_warning_toast": "업스트림 '{{key}}'이(가) 테스트 요청에 응답하지 않으며 제대로 작동하지 않을 수 있습니다",
"unblock": "차단 해제", "unblock": "차단 해제",
@@ -301,6 +298,9 @@
"blocking_mode_nxdomain": "NXDOMAIN: NXDOMAIN 코드로 응답", "blocking_mode_nxdomain": "NXDOMAIN: NXDOMAIN 코드로 응답",
"blocking_mode_null_ip": "Null IP: 제로 IP 주소 (A는 0.0.0.0; AAAA는 ::) 로 응답합니다", "blocking_mode_null_ip": "Null IP: 제로 IP 주소 (A는 0.0.0.0; AAAA는 ::) 로 응답합니다",
"blocking_mode_custom_ip": "커스텀 IP: 직접 설정한 IP 주소로 응답합니다", "blocking_mode_custom_ip": "커스텀 IP: 직접 설정한 IP 주소로 응답합니다",
"theme_auto": "자동",
"theme_light": "라이트 테마",
"theme_dark": "다크 테마",
"upstream_dns_client_desc": "이 값을 비워둔다면 AdGuard Home은 <0>DNS 설정</0>에 설정되어 있는 값을 사용합니다.", "upstream_dns_client_desc": "이 값을 비워둔다면 AdGuard Home은 <0>DNS 설정</0>에 설정되어 있는 값을 사용합니다.",
"tracker_source": "추적기 소스", "tracker_source": "추적기 소스",
"source_label": "소스", "source_label": "소스",
@@ -454,6 +454,7 @@
"updates_checked": "AdGuard Home의 새 버전을 사용할 수 있습니다", "updates_checked": "AdGuard Home의 새 버전을 사용할 수 있습니다",
"updates_version_equal": "AdGuard Home 최신 상태입니다.", "updates_version_equal": "AdGuard Home 최신 상태입니다.",
"check_updates_now": "지금 업데이트 확인", "check_updates_now": "지금 업데이트 확인",
"version_request_error": "업데이트 체크에 실패했습니다. 인터넷 연결 상태를 확인해주세요.",
"dns_privacy": "DNS 프라이버시", "dns_privacy": "DNS 프라이버시",
"setup_dns_privacy_1": "<0>DNS-over-TLS:</0> <1>{{address}}</1> 사용하세요.", "setup_dns_privacy_1": "<0>DNS-over-TLS:</0> <1>{{address}}</1> 사용하세요.",
"setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> <1>{{address}}</1> 사용하세요.", "setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> <1>{{address}}</1> 사용하세요.",
@@ -638,5 +639,8 @@
"safe_browsing": "세이프 브라우징", "safe_browsing": "세이프 브라우징",
"served_from_cache": "{{value}} <i>(캐시에서 제공)</i>", "served_from_cache": "{{value}} <i>(캐시에서 제공)</i>",
"form_error_password_length": "비밀번호는 {{value}}자 이상이어야 합니다", "form_error_password_length": "비밀번호는 {{value}}자 이상이어야 합니다",
"anonymizer_notification": "<0>참고:</0> IP 익명화가 활성화되었습니다. <1>일반 설정</1>에서 비활성화할 수 있습니다." "anonymizer_notification": "<0>참고:</0> IP 익명화가 활성화되었습니다. <1>일반 설정</1>에서 비활성화할 수 있습니다.",
"confirm_dns_cache_clear": "정말로 DNS 캐시를 지우시겠습니까?",
"cache_cleared": "DNS 캐시를 성공적으로 지웠습니다",
"clear_cache": "캐시 지우기"
} }

View File

@@ -37,8 +37,6 @@
"dhcp_ipv6_settings": "DHCP IPv6 instellingen", "dhcp_ipv6_settings": "DHCP IPv6 instellingen",
"form_error_required": "Vereist veld", "form_error_required": "Vereist veld",
"form_error_ip4_format": "Ongeldig IPv4-adres", "form_error_ip4_format": "Ongeldig IPv4-adres",
"form_error_ip4_range_start_format": "Ongeldig IPv4-adres start bereik",
"form_error_ip4_range_end_format": "Ongeldig IPv4-adres einde bereik",
"form_error_ip4_gateway_format": "Ongeldig IPv4-adres van de gateway", "form_error_ip4_gateway_format": "Ongeldig IPv4-adres van de gateway",
"form_error_ip6_format": "Ongeldig IPv6-adres", "form_error_ip6_format": "Ongeldig IPv6-adres",
"form_error_ip_format": "Ongeldig IP-adres", "form_error_ip_format": "Ongeldig IP-adres",
@@ -51,9 +49,8 @@
"out_of_range_error": "Moet buiten bereik zijn \"{{start}}\"-\"{{end}}\"", "out_of_range_error": "Moet buiten bereik zijn \"{{start}}\"-\"{{end}}\"",
"lower_range_start_error": "Moet lager zijn dan begin reeks", "lower_range_start_error": "Moet lager zijn dan begin reeks",
"greater_range_start_error": "Moet groter zijn dan begin reeks", "greater_range_start_error": "Moet groter zijn dan begin reeks",
"greater_range_end_error": "Moet groter zijn dan einde reeks",
"subnet_error": "Adressen moeten in één subnet vallen", "subnet_error": "Adressen moeten in één subnet vallen",
"gateway_or_subnet_invalid": "Subnetmasker ongeldig", "gateway_or_subnet_invalid": "Ongeldig subnetmasker",
"dhcp_form_gateway_input": "Gateway IP", "dhcp_form_gateway_input": "Gateway IP",
"dhcp_form_subnet_input": "Subnet mask", "dhcp_form_subnet_input": "Subnet mask",
"dhcp_form_range_title": "Bereik van IP adressen", "dhcp_form_range_title": "Bereik van IP adressen",
@@ -301,6 +298,9 @@
"blocking_mode_nxdomain": "NXDOMAIN: Reageer met NXDOMAIN code", "blocking_mode_nxdomain": "NXDOMAIN: Reageer met NXDOMAIN code",
"blocking_mode_null_ip": "Nul IP: Reageer met een nul IP address (0.0.0.0 voor A; :: voor AAAA)", "blocking_mode_null_ip": "Nul IP: Reageer met een nul IP address (0.0.0.0 voor A; :: voor AAAA)",
"blocking_mode_custom_ip": "Aangepast IP: Reageer met een handmatige ingesteld IP adres", "blocking_mode_custom_ip": "Aangepast IP: Reageer met een handmatige ingesteld IP adres",
"theme_auto": "Automatisch",
"theme_light": "Licht",
"theme_dark": "Donker",
"upstream_dns_client_desc": "Indien je dit veld leeglaat zal AdGuard Home de servers welke zijn ingesteld in de <0>DNS instellingen</0> gebruiken.", "upstream_dns_client_desc": "Indien je dit veld leeglaat zal AdGuard Home de servers welke zijn ingesteld in de <0>DNS instellingen</0> gebruiken.",
"tracker_source": "Bron volger", "tracker_source": "Bron volger",
"source_label": "Bron", "source_label": "Bron",
@@ -454,6 +454,7 @@
"updates_checked": "Een nieuwe versie van AdGuard Home is beschikbaar\n", "updates_checked": "Een nieuwe versie van AdGuard Home is beschikbaar\n",
"updates_version_equal": "AdGuard Home is actueel", "updates_version_equal": "AdGuard Home is actueel",
"check_updates_now": "Controleer op updates", "check_updates_now": "Controleer op updates",
"version_request_error": "Updatecontrole mislukt. Controleer je internetverbinding.",
"dns_privacy": "DNS Privacy", "dns_privacy": "DNS Privacy",
"setup_dns_privacy_1": "<0>DNS-via-TLS:</0> Gebruik <1>{{address}}</1> string.", "setup_dns_privacy_1": "<0>DNS-via-TLS:</0> Gebruik <1>{{address}}</1> string.",
"setup_dns_privacy_2": "<0>DNS-via-HTTPS:</0> Gebruik <1>{{address}}</1> string.", "setup_dns_privacy_2": "<0>DNS-via-HTTPS:</0> Gebruik <1>{{address}}</1> string.",
@@ -638,5 +639,8 @@
"safe_browsing": "Veilig browsen", "safe_browsing": "Veilig browsen",
"served_from_cache": "{{value}} <i>(geleverd vanuit cache)</i>", "served_from_cache": "{{value}} <i>(geleverd vanuit cache)</i>",
"form_error_password_length": "Wachtwoord moet minimaal {{value}} tekens lang zijn", "form_error_password_length": "Wachtwoord moet minimaal {{value}} tekens lang zijn",
"anonymizer_notification": "<0>Opmerking:</0> IP-anonimisering is ingeschakeld. Je kunt het uitschakelen in <1>Algemene instellingen</1>." "anonymizer_notification": "<0>Opmerking:</0> IP-anonimisering is ingeschakeld. Je kunt het uitschakelen in <1>Algemene instellingen</1>.",
"confirm_dns_cache_clear": "Weet je zeker dat je de DNS-cache wilt wissen?",
"cache_cleared": "DNS-cache succesvol gewist",
"clear_cache": "Cache wissen"
} }

View File

@@ -433,6 +433,7 @@
"updates_checked": "En ny versjon av AdGuard Home er tilgjengelig", "updates_checked": "En ny versjon av AdGuard Home er tilgjengelig",
"updates_version_equal": "AdGuard Home er fullt oppdatert", "updates_version_equal": "AdGuard Home er fullt oppdatert",
"check_updates_now": "Se etter oppdateringer nå", "check_updates_now": "Se etter oppdateringer nå",
"version_request_error": "Oppdateringssjekken mislyktes. Vennligst sjekk internettforbindelsen din.",
"dns_privacy": "DNS-privatliv", "dns_privacy": "DNS-privatliv",
"setup_dns_privacy_1": "<0>DNS-over-TLS:</0> Benytt <1>{{address}}</1>-strengen.", "setup_dns_privacy_1": "<0>DNS-over-TLS:</0> Benytt <1>{{address}}</1>-strengen.",
"setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> Benytt <1>{{address}}</1>-strengen.", "setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> Benytt <1>{{address}}</1>-strengen.",

View File

@@ -37,8 +37,6 @@
"dhcp_ipv6_settings": "Ustawienia serwera DHCP IPv6", "dhcp_ipv6_settings": "Ustawienia serwera DHCP IPv6",
"form_error_required": "Pole wymagane", "form_error_required": "Pole wymagane",
"form_error_ip4_format": "Nieprawidłowy adres IPv4", "form_error_ip4_format": "Nieprawidłowy adres IPv4",
"form_error_ip4_range_start_format": "Nieprawidłowy adres IPv4 początku zakresu",
"form_error_ip4_range_end_format": "Nieprawidłowy adres IPv4 końca zakresu",
"form_error_ip4_gateway_format": "Nieprawidłowy adres IPv4 bramy", "form_error_ip4_gateway_format": "Nieprawidłowy adres IPv4 bramy",
"form_error_ip6_format": "Nieprawidłowy adres IPv6", "form_error_ip6_format": "Nieprawidłowy adres IPv6",
"form_error_ip_format": "Nieprawidłowy adres IP", "form_error_ip_format": "Nieprawidłowy adres IP",
@@ -51,7 +49,6 @@
"out_of_range_error": "Musi być spoza zakresu \"{{start}}\"-\"{{end}}\"", "out_of_range_error": "Musi być spoza zakresu \"{{start}}\"-\"{{end}}\"",
"lower_range_start_error": "Musi być niższy niż początek zakresu", "lower_range_start_error": "Musi być niższy niż początek zakresu",
"greater_range_start_error": "Musi być większy niż początek zakresu", "greater_range_start_error": "Musi być większy niż początek zakresu",
"greater_range_end_error": "Musi być większy niż koniec zakresu",
"subnet_error": "Adresy muszą należeć do jednej podsieci", "subnet_error": "Adresy muszą należeć do jednej podsieci",
"gateway_or_subnet_invalid": "Nieprawidłowa maska podsieci", "gateway_or_subnet_invalid": "Nieprawidłowa maska podsieci",
"dhcp_form_gateway_input": "Adres IP bramy", "dhcp_form_gateway_input": "Adres IP bramy",
@@ -301,6 +298,9 @@
"blocking_mode_nxdomain": "NXDOMAIN: Odpowiedz kodem NXDOMAIN", "blocking_mode_nxdomain": "NXDOMAIN: Odpowiedz kodem NXDOMAIN",
"blocking_mode_null_ip": "Null IP: Odpowiedz z zerowym adresem IP (0.0.0.0 dla A; :: dla AAAA)", "blocking_mode_null_ip": "Null IP: Odpowiedz z zerowym adresem IP (0.0.0.0 dla A; :: dla AAAA)",
"blocking_mode_custom_ip": "Niestandardowy adres IP: Odpowiedz ręcznie ustawionym adresem IP", "blocking_mode_custom_ip": "Niestandardowy adres IP: Odpowiedz ręcznie ustawionym adresem IP",
"theme_auto": "Auto",
"theme_light": "Jasny",
"theme_dark": "Ciemny",
"upstream_dns_client_desc": "Jeśli to pole pozostanie puste, AdGuard Home użyje serwerów skonfigurowanych w <0>Ustawieniach DNS</0>.", "upstream_dns_client_desc": "Jeśli to pole pozostanie puste, AdGuard Home użyje serwerów skonfigurowanych w <0>Ustawieniach DNS</0>.",
"tracker_source": "Źródło skryptu śledzącego", "tracker_source": "Źródło skryptu śledzącego",
"source_label": "Źródło", "source_label": "Źródło",
@@ -454,6 +454,7 @@
"updates_checked": "Dostępna jest nowa wersja programu AdGuard Home\n", "updates_checked": "Dostępna jest nowa wersja programu AdGuard Home\n",
"updates_version_equal": "AdGuard Home jest aktualny", "updates_version_equal": "AdGuard Home jest aktualny",
"check_updates_now": "Sprawdź aktualizacje teraz", "check_updates_now": "Sprawdź aktualizacje teraz",
"version_request_error": "Sprawdzanie aktualizacji zakończone niepowodzeniem. Sprawdź swoje połączenie z internetem.",
"dns_privacy": "Prywatny DNS", "dns_privacy": "Prywatny DNS",
"setup_dns_privacy_1": "<0>DNS-over-TLS:</0> Skorzystaj z adresu <1>{{address}}</1>.", "setup_dns_privacy_1": "<0>DNS-over-TLS:</0> Skorzystaj z adresu <1>{{address}}</1>.",
"setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> Skorzystaj z adresu <1>{{address}}</1>.", "setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> Skorzystaj z adresu <1>{{address}}</1>.",
@@ -638,5 +639,8 @@
"safe_browsing": "Bezpieczne przeglądanie", "safe_browsing": "Bezpieczne przeglądanie",
"served_from_cache": "{{value}} <i>(podawane z pamięci podręcznej)</i>", "served_from_cache": "{{value}} <i>(podawane z pamięci podręcznej)</i>",
"form_error_password_length": "Hasło musi mieć co najmniej {{value}} znaków", "form_error_password_length": "Hasło musi mieć co najmniej {{value}} znaków",
"anonymizer_notification": "<0>Uwaga:</0> Anonimizacja IP jest włączona. Możesz ją wyłączyć w <1>Ustawieniach ogólnych</1>." "anonymizer_notification": "<0>Uwaga:</0> Anonimizacja IP jest włączona. Możesz ją wyłączyć w <1>Ustawieniach ogólnych</1>.",
"confirm_dns_cache_clear": "Czy na pewno chcesz wyczyścić pamięć podręczną DNS?",
"cache_cleared": "Pamięć podręczna DNS została pomyślnie wyczyszczona",
"clear_cache": "Wyczyść pamięć podręczną"
} }

View File

@@ -37,8 +37,6 @@
"dhcp_ipv6_settings": "Configurações DHCP IPv6", "dhcp_ipv6_settings": "Configurações DHCP IPv6",
"form_error_required": "Campo obrigatório", "form_error_required": "Campo obrigatório",
"form_error_ip4_format": "Endereço de IPv4 inválido", "form_error_ip4_format": "Endereço de IPv4 inválido",
"form_error_ip4_range_start_format": "Endereço IPv4 de início de intervalo inválido",
"form_error_ip4_range_end_format": "Endereço IPv4 de fim de intervalo inválido.",
"form_error_ip4_gateway_format": "Endereço IPv4 de gateway inválido", "form_error_ip4_gateway_format": "Endereço IPv4 de gateway inválido",
"form_error_ip6_format": "Endereço de IPv6 inválido", "form_error_ip6_format": "Endereço de IPv6 inválido",
"form_error_ip_format": "Endereço de IP inválido", "form_error_ip_format": "Endereço de IP inválido",
@@ -51,7 +49,6 @@
"out_of_range_error": "Deve estar fora do intervalo \"{{start}}\"-\"{{end}}\"", "out_of_range_error": "Deve estar fora do intervalo \"{{start}}\"-\"{{end}}\"",
"lower_range_start_error": "Deve ser inferior ao início do intervalo", "lower_range_start_error": "Deve ser inferior ao início do intervalo",
"greater_range_start_error": "Deve ser maior que o início do intervalo", "greater_range_start_error": "Deve ser maior que o início do intervalo",
"greater_range_end_error": "Deve ser maior que o fim do intervalo",
"subnet_error": "Endereços devem estar em uma sub-rede", "subnet_error": "Endereços devem estar em uma sub-rede",
"gateway_or_subnet_invalid": "Máscara de sub-rede inválida", "gateway_or_subnet_invalid": "Máscara de sub-rede inválida",
"dhcp_form_gateway_input": "IP do gateway", "dhcp_form_gateway_input": "IP do gateway",
@@ -301,6 +298,9 @@
"blocking_mode_nxdomain": "NXDOMAIN: Responder com o código NXDOMAIN", "blocking_mode_nxdomain": "NXDOMAIN: Responder com o código NXDOMAIN",
"blocking_mode_null_ip": "IP nulo: Responder com endereço IP zero (0.0.0.0 para A; :: para AAAA)", "blocking_mode_null_ip": "IP nulo: Responder com endereço IP zero (0.0.0.0 para A; :: para AAAA)",
"blocking_mode_custom_ip": "IP personalizado: Responder com um endereço IP definido manualmente", "blocking_mode_custom_ip": "IP personalizado: Responder com um endereço IP definido manualmente",
"theme_auto": "Automático",
"theme_light": "Claro",
"theme_dark": "Escuro",
"upstream_dns_client_desc": "Se você mantiver este campo vazio, o AdGuard Home usará os servidores configurados nas configurações <0>DNS</0>.", "upstream_dns_client_desc": "Se você mantiver este campo vazio, o AdGuard Home usará os servidores configurados nas configurações <0>DNS</0>.",
"tracker_source": "Fonte do rastreador", "tracker_source": "Fonte do rastreador",
"source_label": "Fonte", "source_label": "Fonte",
@@ -454,6 +454,7 @@
"updates_checked": "Uma nova versão do AdGuard Home está disponível\n", "updates_checked": "Uma nova versão do AdGuard Home está disponível\n",
"updates_version_equal": "O AdGuard Home está atualizado.", "updates_version_equal": "O AdGuard Home está atualizado.",
"check_updates_now": "Verificar atualizações", "check_updates_now": "Verificar atualizações",
"version_request_error": "A verificação de atualização falhou. Por favor, verifique sua conexão com a internet.",
"dns_privacy": "Privacidade de DNS", "dns_privacy": "Privacidade de DNS",
"setup_dns_privacy_1": "<0>DNS-sobre-TLS:</0> Use <1>{{address}}</1> string.", "setup_dns_privacy_1": "<0>DNS-sobre-TLS:</0> Use <1>{{address}}</1> string.",
"setup_dns_privacy_2": "<0>DNS-sobre-HTTPS:</0> Use <1>{{address}}</1> string.", "setup_dns_privacy_2": "<0>DNS-sobre-HTTPS:</0> Use <1>{{address}}</1> string.",
@@ -638,5 +639,8 @@
"safe_browsing": "Navegação segura", "safe_browsing": "Navegação segura",
"served_from_cache": "{{value}} <i>(servido do cache)</i>", "served_from_cache": "{{value}} <i>(servido do cache)</i>",
"form_error_password_length": "A senha deve ter pelo menos {{value}} caracteres", "form_error_password_length": "A senha deve ter pelo menos {{value}} caracteres",
"anonymizer_notification": "<0>Observação:</0> A anonimização de IP está ativada. Você pode desativá-lo em <1>Configurações gerais</1>." "anonymizer_notification": "<0>Observação:</0> A anonimização de IP está ativada. Você pode desativá-lo em <1>Configurações gerais</1>.",
"confirm_dns_cache_clear": "Tem certeza de que deseja limpar o cache DNS?",
"cache_cleared": "Cache DNS limpo com sucesso",
"clear_cache": "Limpar cache"
} }

View File

@@ -37,8 +37,6 @@
"dhcp_ipv6_settings": "Definições DHCP IPv6", "dhcp_ipv6_settings": "Definições DHCP IPv6",
"form_error_required": "Campo obrigatório", "form_error_required": "Campo obrigatório",
"form_error_ip4_format": "Endereço de IPv4 inválido", "form_error_ip4_format": "Endereço de IPv4 inválido",
"form_error_ip4_range_start_format": "Endereço IPv4 de início de intervalo inválido",
"form_error_ip4_range_end_format": "Endereço IPv4 de fim de intervalo inválido",
"form_error_ip4_gateway_format": "Endereço IPv4 de gateway inválido", "form_error_ip4_gateway_format": "Endereço IPv4 de gateway inválido",
"form_error_ip6_format": "Endereço de IPv6 inválido", "form_error_ip6_format": "Endereço de IPv6 inválido",
"form_error_ip_format": "Endereço de email inválido", "form_error_ip_format": "Endereço de email inválido",
@@ -51,8 +49,7 @@
"out_of_range_error": "Deve estar fora do intervalo \"{{start}}\"-\"{{end}}\"", "out_of_range_error": "Deve estar fora do intervalo \"{{start}}\"-\"{{end}}\"",
"lower_range_start_error": "Deve ser inferior ao início do intervalo", "lower_range_start_error": "Deve ser inferior ao início do intervalo",
"greater_range_start_error": "Deve ser maior que o início do intervalo", "greater_range_start_error": "Deve ser maior que o início do intervalo",
"greater_range_end_error": "Deve ser maior que o fim do intervalo", "subnet_error": "Os endereços devem estar numa sub-rede",
"subnet_error": "Os endereços devem estar em uma sub-rede",
"gateway_or_subnet_invalid": "Máscara de sub-rede inválida", "gateway_or_subnet_invalid": "Máscara de sub-rede inválida",
"dhcp_form_gateway_input": "IP do gateway", "dhcp_form_gateway_input": "IP do gateway",
"dhcp_form_subnet_input": "Máscara de sub-rede", "dhcp_form_subnet_input": "Máscara de sub-rede",
@@ -301,6 +298,9 @@
"blocking_mode_nxdomain": "NXDOMAIN: Responder com o código NXDOMAIN", "blocking_mode_nxdomain": "NXDOMAIN: Responder com o código NXDOMAIN",
"blocking_mode_null_ip": "IP nulo: Responder com endereço IP zero (0.0.0.0 para A; :: para AAAA)", "blocking_mode_null_ip": "IP nulo: Responder com endereço IP zero (0.0.0.0 para A; :: para AAAA)",
"blocking_mode_custom_ip": "IP personalizado: Responder com um endereço IP definido manualmente", "blocking_mode_custom_ip": "IP personalizado: Responder com um endereço IP definido manualmente",
"theme_auto": "Automático",
"theme_light": "Claro",
"theme_dark": "Escuro",
"upstream_dns_client_desc": "Se mantiver esse campo vazio, o AdGuard Home usará os servidores configurados nas <0>Definições de DNS</0>.", "upstream_dns_client_desc": "Se mantiver esse campo vazio, o AdGuard Home usará os servidores configurados nas <0>Definições de DNS</0>.",
"tracker_source": "Fonte do rastreador", "tracker_source": "Fonte do rastreador",
"source_label": "Fonte", "source_label": "Fonte",
@@ -335,10 +335,10 @@
"install_devices_router": "Router", "install_devices_router": "Router",
"install_devices_router_desc": "Esta configuração cobre automaticamente todos os dispositivos conectados ao seu router doméstico, sem a necessidade de configurar cada um deles manualmente.", "install_devices_router_desc": "Esta configuração cobre automaticamente todos os dispositivos conectados ao seu router doméstico, sem a necessidade de configurar cada um deles manualmente.",
"install_devices_address": "O servidor de DNS do AdGuard Home está a capturar os seguintes endereços", "install_devices_address": "O servidor de DNS do AdGuard Home está a capturar os seguintes endereços",
"install_devices_router_list_1": "Abra as preferências do seu roteador. Normalmente, tu podes acessá-lo de teu navegador por meio de um URL, como http://192.168.0.1/ ou http://192.168.1.1/. Tu podes ser solicitado a inserir uma palavra-passe. Se tu não se lembrar, muitas vezes tu podes repor a palavra-passe pressionando um botão no próprio roteador, mas esteja ciente de que se esse procedimento for escolhido, tu provavelmente perderás toda a definição do roteador. Se o teu roteador requer uma aplicação para configurá-lo, instale a aplicação no seu telefone ou PC e use-o para acessar as definições do roteador.", "install_devices_router_list_1": "Abra as preferências do seu router. Normalmente, tu podes acessá-lo de teu navegador por meio de um URL, como http://192.168.0.1/ ou http://192.168.1.1/. Tu podes ser solicitado a inserir uma palavra-passe. Se tu não se lembrar, muitas vezes tu podes repor a palavra-passe pressionando um botão no próprio roteador, mas esteja ciente de que se esse procedimento for escolhido, tu provavelmente perderás toda a definição do router. Se o teu router requer uma aplicação para configurá-lo, instale a aplicação no seu telefone ou PC e use-o para acessar as definições do router.",
"install_devices_router_list_2": "Encontre as configurações de DNS. Procure as letras DNS ao lado de um campo que permite dois ou três conjuntos de números, cada um dividido em quatro grupos de um a três números.", "install_devices_router_list_2": "Encontre as configurações de DNS. Procure as letras DNS ao lado de um campo que permite dois ou três conjuntos de números, cada um dividido em quatro grupos de um a três números.",
"install_devices_router_list_3": "Insira aqui seu servidor do AdGuard Home.", "install_devices_router_list_3": "Insira aqui seu servidor do AdGuard Home.",
"install_devices_router_list_4": "Em alguns tipos de roteador, um servidor DNS personalizado não pode ser configurado. Nesse caso, configurar o AdGuard Home como um <0>Servidor DHCP</0> pode ajudar. Caso contrário, tu deve verificar o manual do router sobre como personalizar os servidores DNS em seu modelo de router específico.", "install_devices_router_list_4": "Em alguns tipos de router, um servidor DNS personalizado não pode ser configurado. Nesse caso, configurar o AdGuard Home como um <0>Servidor DHCP</0> pode ajudar. Caso contrário, tu deves verificar o manual do router sobre como personalizar os servidores DNS no seu modelo de router específico.",
"install_devices_windows_list_1": "Abra o Painel de Controlo através do Menu Iniciar ou pela Pesquisa do Windows.", "install_devices_windows_list_1": "Abra o Painel de Controlo através do Menu Iniciar ou pela Pesquisa do Windows.",
"install_devices_windows_list_2": "Entre na categoria Rede e Internet e depois clique em Central de Rede e Partilha.", "install_devices_windows_list_2": "Entre na categoria Rede e Internet e depois clique em Central de Rede e Partilha.",
"install_devices_windows_list_3": "No painel esquerdo, clique em \"Alterar configurações do adaptador\".", "install_devices_windows_list_3": "No painel esquerdo, clique em \"Alterar configurações do adaptador\".",
@@ -454,6 +454,7 @@
"updates_checked": "Uma nova versão do AdGuard Home está disponível\n", "updates_checked": "Uma nova versão do AdGuard Home está disponível\n",
"updates_version_equal": "O AdGuard Home está atualizado", "updates_version_equal": "O AdGuard Home está atualizado",
"check_updates_now": "Verificar atualizações", "check_updates_now": "Verificar atualizações",
"version_request_error": "A verificação de atualização falhou. Verifique a sua ligação à internet.",
"dns_privacy": "Privacidade de DNS", "dns_privacy": "Privacidade de DNS",
"setup_dns_privacy_1": "<0>DNS-sobre-TLS:</0> Use <1>{{address}}</1> string.", "setup_dns_privacy_1": "<0>DNS-sobre-TLS:</0> Use <1>{{address}}</1> string.",
"setup_dns_privacy_2": "<0>DNS-sobre-HTTPS:</0> Use <1>{{address}}</1> string.", "setup_dns_privacy_2": "<0>DNS-sobre-HTTPS:</0> Use <1>{{address}}</1> string.",
@@ -582,7 +583,7 @@
"client_blocked": "Cliente \"{{ip}}\" foi bloqueado com sucesso", "client_blocked": "Cliente \"{{ip}}\" foi bloqueado com sucesso",
"client_unblocked": "Cliente \"{{ip}}\" foi desbloqueado com sucesso", "client_unblocked": "Cliente \"{{ip}}\" foi desbloqueado com sucesso",
"static_ip": "Endereço de IP estático", "static_ip": "Endereço de IP estático",
"static_ip_desc": "O AdGuard Home é um servidor, portanto, ele precisa de um endereço de IP estático para funcionar corretamente. Caso contrário, em algum momento, seu roteador poderá atribuir um novo endereço de IP neste dispositivo.", "static_ip_desc": "O AdGuard Home é um servidor, portanto, ele precisa de um endereço de IP estático para funcionar corretamente. Caso contrário, em algum momento, seu router poderá atribuir um novo endereço de IP neste dispositivo.",
"set_static_ip": "Definir um endereço de IP estático", "set_static_ip": "Definir um endereço de IP estático",
"install_static_ok": "Boas notícias! O endereço de IP estático já está configurado", "install_static_ok": "Boas notícias! O endereço de IP estático já está configurado",
"install_static_error": "O AdGuard Home não pode configurar automaticamente para esta interface de rede. Por favor, procure uma instrução sobre como fazer isso manualmente.", "install_static_error": "O AdGuard Home não pode configurar automaticamente para esta interface de rede. Por favor, procure uma instrução sobre como fazer isso manualmente.",
@@ -638,5 +639,8 @@
"safe_browsing": "Navegação segura", "safe_browsing": "Navegação segura",
"served_from_cache": "{{value}} <i>(servido do cache)</i>", "served_from_cache": "{{value}} <i>(servido do cache)</i>",
"form_error_password_length": "A palavra-passe deve ter pelo menos {{value}} caracteres", "form_error_password_length": "A palavra-passe deve ter pelo menos {{value}} caracteres",
"anonymizer_notification": "<0>Observação:</0> A anonimização de IP está ativada. Você pode desativá-la em <1>Definições gerais</1>." "anonymizer_notification": "<0>Observação:</0> A anonimização de IP está ativada. Você pode desativá-la em <1>Definições gerais</1>.",
"confirm_dns_cache_clear": "Tem certeza de que quer limpar a cache DNS?",
"cache_cleared": "O cache DNS foi apagado com sucesso",
"clear_cache": "Limpar cache"
} }

View File

@@ -37,8 +37,6 @@
"dhcp_ipv6_settings": "Setări DHCP IPv6", "dhcp_ipv6_settings": "Setări DHCP IPv6",
"form_error_required": "Câmp obligatoriu", "form_error_required": "Câmp obligatoriu",
"form_error_ip4_format": "Adresă IPv4 nevalidă", "form_error_ip4_format": "Adresă IPv4 nevalidă",
"form_error_ip4_range_start_format": "Adresă IPv4 nevalidă pentru începutul intervalului",
"form_error_ip4_range_end_format": "Adresă IPv4 nevalidă a sfârșitului intervalului",
"form_error_ip4_gateway_format": "Adresă IPv4 nevalidă a gateway-ului", "form_error_ip4_gateway_format": "Adresă IPv4 nevalidă a gateway-ului",
"form_error_ip6_format": "Adresa IPv6 nevalidă", "form_error_ip6_format": "Adresa IPv6 nevalidă",
"form_error_ip_format": "Adresă IP nevalidă", "form_error_ip_format": "Adresă IP nevalidă",
@@ -51,7 +49,6 @@
"out_of_range_error": "Trebuie să fie în afara intervalului „{{start}}”-„{{end}}”", "out_of_range_error": "Trebuie să fie în afara intervalului „{{start}}”-„{{end}}”",
"lower_range_start_error": "Trebuie să fie mai mică decât începutul intervalului", "lower_range_start_error": "Trebuie să fie mai mică decât începutul intervalului",
"greater_range_start_error": "Trebuie să fie mai mare decât începutul intervalului", "greater_range_start_error": "Trebuie să fie mai mare decât începutul intervalului",
"greater_range_end_error": "Trebuie să fie mai mare decât sfârșitul intervalului",
"subnet_error": "Adresele trebuie să fie în aceeași subrețea", "subnet_error": "Adresele trebuie să fie în aceeași subrețea",
"gateway_or_subnet_invalid": "Mască de subrețea nevalidă", "gateway_or_subnet_invalid": "Mască de subrețea nevalidă",
"dhcp_form_gateway_input": "IP Gateway", "dhcp_form_gateway_input": "IP Gateway",
@@ -301,6 +298,9 @@
"blocking_mode_nxdomain": "NXDOMAIN: Răspunde cu codul NXDOMAIN", "blocking_mode_nxdomain": "NXDOMAIN: Răspunde cu codul NXDOMAIN",
"blocking_mode_null_ip": "IP nul: răspunde cu o adresă IP zero (0.0.0.0 pentru A; :: pentru AAAA)", "blocking_mode_null_ip": "IP nul: răspunde cu o adresă IP zero (0.0.0.0 pentru A; :: pentru AAAA)",
"blocking_mode_custom_ip": "IP personalizat: răspunde cu o adresă IP setată manual", "blocking_mode_custom_ip": "IP personalizat: răspunde cu o adresă IP setată manual",
"theme_auto": "Auto",
"theme_light": "Luminoasă",
"theme_dark": "Sombră",
"upstream_dns_client_desc": "Dacă mențineți acest câmp gol, AdGuard Home va folosi serverele configurate în <0>setările DNS</0>.", "upstream_dns_client_desc": "Dacă mențineți acest câmp gol, AdGuard Home va folosi serverele configurate în <0>setările DNS</0>.",
"tracker_source": "Sursă tracker", "tracker_source": "Sursă tracker",
"source_label": "Sursă", "source_label": "Sursă",
@@ -454,6 +454,7 @@
"updates_checked": "Este disponibilă o nouă versiune de AdGuard Home\n", "updates_checked": "Este disponibilă o nouă versiune de AdGuard Home\n",
"updates_version_equal": "AdGuard Home este la zi", "updates_version_equal": "AdGuard Home este la zi",
"check_updates_now": "Verificați actualizările acum", "check_updates_now": "Verificați actualizările acum",
"version_request_error": "Verificarea actualizării nu a reușit. Verificați conexiunea internet.",
"dns_privacy": "Confidențialitate DNS", "dns_privacy": "Confidențialitate DNS",
"setup_dns_privacy_1": "<0>DNS-over-TLS:</0> Folosiți stringul <1>{{address}}</1>.", "setup_dns_privacy_1": "<0>DNS-over-TLS:</0> Folosiți stringul <1>{{address}}</1>.",
"setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> Folosiți stringul <1>{{address}}</1>.", "setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> Folosiți stringul <1>{{address}}</1>.",
@@ -638,5 +639,8 @@
"safe_browsing": "Navigare în siguranță", "safe_browsing": "Navigare în siguranță",
"served_from_cache": "{{value}} <i>(furnizat din cache)</i>", "served_from_cache": "{{value}} <i>(furnizat din cache)</i>",
"form_error_password_length": "Parola trebuie să aibă cel puțin {{value}} caractere", "form_error_password_length": "Parola trebuie să aibă cel puțin {{value}} caractere",
"anonymizer_notification": "<0>Nota:</0> Anonimizarea IP este activată. Puteți să o dezactivați în <1>Setări generale</1>." "anonymizer_notification": "<0>Nota:</0> Anonimizarea IP este activată. Puteți să o dezactivați în <1>Setări generale</1>.",
"confirm_dns_cache_clear": "Sunteți sigur că doriți să ștergeți memoria cache DNS?",
"cache_cleared": "Cache-ul DNS a fost golit cu succes",
"clear_cache": "Goliți memoria cache"
} }

View File

@@ -37,8 +37,6 @@
"dhcp_ipv6_settings": "Настройки DHCP IPv6", "dhcp_ipv6_settings": "Настройки DHCP IPv6",
"form_error_required": "Обязательное поле", "form_error_required": "Обязательное поле",
"form_error_ip4_format": "Некорректный IPv4-адрес", "form_error_ip4_format": "Некорректный IPv4-адрес",
"form_error_ip4_range_start_format": "Некорректный IPv4-адрес начала диапазона",
"form_error_ip4_range_end_format": "Некорректный IPv4-адрес конца диапазона",
"form_error_ip4_gateway_format": "Некорректный IPv4-адрес шлюза", "form_error_ip4_gateway_format": "Некорректный IPv4-адрес шлюза",
"form_error_ip6_format": "Некорректный IPv6-адрес", "form_error_ip6_format": "Некорректный IPv6-адрес",
"form_error_ip_format": "Некорректный IP-адрес", "form_error_ip_format": "Некорректный IP-адрес",
@@ -51,7 +49,6 @@
"out_of_range_error": "Должно быть вне диапазона «{{start}}»-«{{end}}»", "out_of_range_error": "Должно быть вне диапазона «{{start}}»-«{{end}}»",
"lower_range_start_error": "Должно быть меньше начала диапазона", "lower_range_start_error": "Должно быть меньше начала диапазона",
"greater_range_start_error": "Должно быть больше начала диапазона", "greater_range_start_error": "Должно быть больше начала диапазона",
"greater_range_end_error": "Должно быть больше конца диапазона",
"subnet_error": "Адреса должны быть внутри одной подсети", "subnet_error": "Адреса должны быть внутри одной подсети",
"gateway_or_subnet_invalid": "Некорректная маска подсети", "gateway_or_subnet_invalid": "Некорректная маска подсети",
"dhcp_form_gateway_input": "IP-адрес шлюза", "dhcp_form_gateway_input": "IP-адрес шлюза",
@@ -301,6 +298,9 @@
"blocking_mode_nxdomain": "NXDOMAIN: Отвечает с кодом NXDOMAIN\n", "blocking_mode_nxdomain": "NXDOMAIN: Отвечает с кодом NXDOMAIN\n",
"blocking_mode_null_ip": "Нулевой IP: Отвечает с нулевым IP-адресом (0.0.0.0 для A; :: для AAAA)", "blocking_mode_null_ip": "Нулевой IP: Отвечает с нулевым IP-адресом (0.0.0.0 для A; :: для AAAA)",
"blocking_mode_custom_ip": "Пользовательский IP: Отвечает с вручную настроенным IP-адресом", "blocking_mode_custom_ip": "Пользовательский IP: Отвечает с вручную настроенным IP-адресом",
"theme_auto": "Авто",
"theme_light": "Светлая",
"theme_dark": "Тёмная",
"upstream_dns_client_desc": "Если оставить поле пустым, AdGuard Home будет обращаться к серверам, указанным в <0>настройках DNS</0>.", "upstream_dns_client_desc": "Если оставить поле пустым, AdGuard Home будет обращаться к серверам, указанным в <0>настройках DNS</0>.",
"tracker_source": "Источник трекинга", "tracker_source": "Источник трекинга",
"source_label": "Источник", "source_label": "Источник",
@@ -454,6 +454,7 @@
"updates_checked": "Доступна новая версия AdGuard Home", "updates_checked": "Доступна новая версия AdGuard Home",
"updates_version_equal": "Версия AdGuard Home актуальна", "updates_version_equal": "Версия AdGuard Home актуальна",
"check_updates_now": "Проверить обновления", "check_updates_now": "Проверить обновления",
"version_request_error": "Ошибка при проверке наличия обновлений. Проверьте ваше интернет-соединение.",
"dns_privacy": "Зашифрованный DNS", "dns_privacy": "Зашифрованный DNS",
"setup_dns_privacy_1": "<0>DNS-over-TLS:</0> Используйте строку <1>{{address}}</1>.", "setup_dns_privacy_1": "<0>DNS-over-TLS:</0> Используйте строку <1>{{address}}</1>.",
"setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> Используйте строку <1>{{address}}</1>.", "setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> Используйте строку <1>{{address}}</1>.",
@@ -638,5 +639,8 @@
"safe_browsing": "Безопасный интернет", "safe_browsing": "Безопасный интернет",
"served_from_cache": "{{value}} <i>(получено из кеша)</i>", "served_from_cache": "{{value}} <i>(получено из кеша)</i>",
"form_error_password_length": "Пароль должен быть длиной не меньше {{value}} символов", "form_error_password_length": "Пароль должен быть длиной не меньше {{value}} символов",
"anonymizer_notification": "<0>Внимание:</0> включена анонимизация IP-адресов. Вы можете отключить её в разделе <1>Основные настройки</1>." "anonymizer_notification": "<0>Внимание:</0> включена анонимизация IP-адресов. Вы можете отключить её в разделе <1>Основные настройки</1>.",
"confirm_dns_cache_clear": "Вы уверены, что хотите очистить кеш DNS?",
"cache_cleared": "Кеш DNS успешно очищен",
"clear_cache": "Очистить кеш"
} }

View File

@@ -30,8 +30,6 @@
"dhcp_ipv6_settings": "ග.ධා.වි.කෙ. අ.ජා.කෙ. 6 සැකසුම්", "dhcp_ipv6_settings": "ග.ධා.වි.කෙ. අ.ජා.කෙ. 6 සැකසුම්",
"form_error_required": "ඇවැසි ක්‍ෂේත්‍රයකි", "form_error_required": "ඇවැසි ක්‍ෂේත්‍රයකි",
"form_error_ip4_format": "IPv4 ලිපිනය වලංගු නොවේ", "form_error_ip4_format": "IPv4 ලිපිනය වලංගු නොවේ",
"form_error_ip4_range_start_format": "පරාසය ආරම්භයේ වලංගු නොවන අ.ජා.කෙ.4 ලිපිනයකි",
"form_error_ip4_range_end_format": "පරාසය අවසානයේ වලංගු නොවන අ.ජා.කෙ.4 ලිපිනයකි",
"form_error_ip6_format": "වලංගු නොවන අ.ජා.කෙ.6 ලිපිනයකි", "form_error_ip6_format": "වලංගු නොවන අ.ජා.කෙ.6 ලිපිනයකි",
"form_error_ip_format": "අ.ජා.කෙ. (IP) ලිපිනය වලංගු නොවේ", "form_error_ip_format": "අ.ජා.කෙ. (IP) ලිපිනය වලංගු නොවේ",
"form_error_mac_format": "මා.ප්‍ර.පා. ලිපිනය වලංගු නොවේ", "form_error_mac_format": "මා.ප්‍ර.පා. ලිපිනය වලංගු නොවේ",
@@ -42,7 +40,6 @@
"out_of_range_error": "\"{{start}}\"-\"{{end}}\" පරාසයෙන් පිට විය යුතුය", "out_of_range_error": "\"{{start}}\"-\"{{end}}\" පරාසයෙන් පිට විය යුතුය",
"lower_range_start_error": "පරාසය ආරම්භයට වඩා අඩු විය යුතුය", "lower_range_start_error": "පරාසය ආරම්භයට වඩා අඩු විය යුතුය",
"greater_range_start_error": "පරාසය ආරම්භයට වඩා වැඩි විය යුතුය", "greater_range_start_error": "පරාසය ආරම්භයට වඩා වැඩි විය යුතුය",
"greater_range_end_error": "පරාසය අවසානයට වඩා වැඩි විය යුතුය",
"subnet_error": "ලිපින එක් අනුජාලයක තිබිය යුතුය", "subnet_error": "ලිපින එක් අනුජාලයක තිබිය යුතුය",
"dhcp_form_range_title": "අ.ජා. කෙ. (IP) ලිපින පරාසය", "dhcp_form_range_title": "අ.ජා. කෙ. (IP) ලිපින පරාසය",
"dhcp_form_range_start": "පරාසය ආරම්භය", "dhcp_form_range_start": "පරාසය ආරම්භය",

View File

@@ -37,8 +37,6 @@
"dhcp_ipv6_settings": "Nastavenia DHCP IPv6", "dhcp_ipv6_settings": "Nastavenia DHCP IPv6",
"form_error_required": "Povinná položka.", "form_error_required": "Povinná položka.",
"form_error_ip4_format": "Neplatná IPv4 adresa", "form_error_ip4_format": "Neplatná IPv4 adresa",
"form_error_ip4_range_start_format": "Neplatný začiatok rozsahu IPv4 formátu",
"form_error_ip4_range_end_format": "Neplatný koniec rozsahu IPv4 formátu",
"form_error_ip4_gateway_format": "Neplatná IPv4 adresa brány", "form_error_ip4_gateway_format": "Neplatná IPv4 adresa brány",
"form_error_ip6_format": "Neplatná IPv6 adresa", "form_error_ip6_format": "Neplatná IPv6 adresa",
"form_error_ip_format": "Neplatná IP adresa", "form_error_ip_format": "Neplatná IP adresa",
@@ -51,7 +49,6 @@
"out_of_range_error": "Musí byť mimo rozsahu \"{{start}}\"-\"{{end}}\"", "out_of_range_error": "Musí byť mimo rozsahu \"{{start}}\"-\"{{end}}\"",
"lower_range_start_error": "Musí byť nižšie ako začiatok rozsahu", "lower_range_start_error": "Musí byť nižšie ako začiatok rozsahu",
"greater_range_start_error": "Musí byť väčšie ako začiatok rozsahu", "greater_range_start_error": "Musí byť väčšie ako začiatok rozsahu",
"greater_range_end_error": "Musí byť väčšie ako koniec rozsahu",
"subnet_error": "Adresy musia byť v spoločnej podsieti", "subnet_error": "Adresy musia byť v spoločnej podsieti",
"gateway_or_subnet_invalid": "Maska podsiete je neplatná", "gateway_or_subnet_invalid": "Maska podsiete je neplatná",
"dhcp_form_gateway_input": "IP brána", "dhcp_form_gateway_input": "IP brána",
@@ -301,6 +298,9 @@
"blocking_mode_nxdomain": "NXDOMAIN: Odpovedať kódom NXDOMAIN", "blocking_mode_nxdomain": "NXDOMAIN: Odpovedať kódom NXDOMAIN",
"blocking_mode_null_ip": "Null IP: Odpoveď s nulovou IP adresou (0.0.0.0 pre A; :: pre AAAA)", "blocking_mode_null_ip": "Null IP: Odpoveď s nulovou IP adresou (0.0.0.0 pre A; :: pre AAAA)",
"blocking_mode_custom_ip": "Vlastná IP adresa: Odpovedzte s manuálne nastavenou IP adresou", "blocking_mode_custom_ip": "Vlastná IP adresa: Odpovedzte s manuálne nastavenou IP adresou",
"theme_auto": "Auto",
"theme_light": "Svetlá",
"theme_dark": "Tmavá",
"upstream_dns_client_desc": "Ak ponecháte toto pole prázdne, AdGuard Home použije servery nakonfigurované v <0>nastaveniach DNS</0>.", "upstream_dns_client_desc": "Ak ponecháte toto pole prázdne, AdGuard Home použije servery nakonfigurované v <0>nastaveniach DNS</0>.",
"tracker_source": "Zdroj sledovania", "tracker_source": "Zdroj sledovania",
"source_label": "Zdroj", "source_label": "Zdroj",
@@ -454,6 +454,7 @@
"updates_checked": "K dispozícii je nová verzia aplikácie AdGuard Home\n", "updates_checked": "K dispozícii je nová verzia aplikácie AdGuard Home\n",
"updates_version_equal": "AdGuard Home je aktuálny", "updates_version_equal": "AdGuard Home je aktuálny",
"check_updates_now": "Skontrolovať aktualizácie teraz", "check_updates_now": "Skontrolovať aktualizácie teraz",
"version_request_error": "Kontrola aktualizácie zlyhala. Skontrolujte svoje internetové pripojenie.",
"dns_privacy": "DNS súkromie", "dns_privacy": "DNS súkromie",
"setup_dns_privacy_1": "<0>DNS-over-TLS:</0> Použiť <1>{{address}}</1> reťazec.", "setup_dns_privacy_1": "<0>DNS-over-TLS:</0> Použiť <1>{{address}}</1> reťazec.",
"setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> Použiť <1>{{address}}</1> reťazec.", "setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> Použiť <1>{{address}}</1> reťazec.",
@@ -638,5 +639,8 @@
"safe_browsing": "Bezpečné prehliadanie", "safe_browsing": "Bezpečné prehliadanie",
"served_from_cache": "{{value}} <i>(prevzatá z cache pamäte)</i>", "served_from_cache": "{{value}} <i>(prevzatá z cache pamäte)</i>",
"form_error_password_length": "Heslo musí mať dĺžku aspoň {{value}} znakov", "form_error_password_length": "Heslo musí mať dĺžku aspoň {{value}} znakov",
"anonymizer_notification": "<0>Poznámka:</0> Anonymizácia IP je zapnutá. Môžete ju vypnúť vo <1>Všeobecných nastaveniach</1>." "anonymizer_notification": "<0>Poznámka:</0> Anonymizácia IP je zapnutá. Môžete ju vypnúť vo <1>Všeobecných nastaveniach</1>.",
"confirm_dns_cache_clear": "Naozaj chcete vymazať vyrovnávaciu pamäť DNS?",
"cache_cleared": "Vyrovnávacia pamäť DNS bola úspešne vymazaná",
"clear_cache": "Vymazať vyrovnávaciu pamäť"
} }

View File

@@ -37,8 +37,6 @@
"dhcp_ipv6_settings": "Nastavitve DHCP IPv6", "dhcp_ipv6_settings": "Nastavitve DHCP IPv6",
"form_error_required": "Zahtevano polje.", "form_error_required": "Zahtevano polje.",
"form_error_ip4_format": "Neveljaven naslov IPv4.", "form_error_ip4_format": "Neveljaven naslov IPv4.",
"form_error_ip4_range_start_format": "Neveljaven začetek razpona naslova IPv4",
"form_error_ip4_range_end_format": "Neveljaven konec razpona naslova IPv4",
"form_error_ip4_gateway_format": "Neveljaven naslov IPv4 prehoda", "form_error_ip4_gateway_format": "Neveljaven naslov IPv4 prehoda",
"form_error_ip6_format": "Neveljaven naslov IPv6", "form_error_ip6_format": "Neveljaven naslov IPv6",
"form_error_ip_format": "Neveljaven naslov IP", "form_error_ip_format": "Neveljaven naslov IP",
@@ -51,7 +49,6 @@
"out_of_range_error": "Mora biti izven razpona \"{{start}}\"-\"{{end}}\"", "out_of_range_error": "Mora biti izven razpona \"{{start}}\"-\"{{end}}\"",
"lower_range_start_error": "Mora biti manjši od začetka razpona", "lower_range_start_error": "Mora biti manjši od začetka razpona",
"greater_range_start_error": "Mora biti večji od začetka razpona", "greater_range_start_error": "Mora biti večji od začetka razpona",
"greater_range_end_error": "Mora biti večji od konca razpona",
"subnet_error": "Naslovi morajo biti v enem podomrežju", "subnet_error": "Naslovi morajo biti v enem podomrežju",
"gateway_or_subnet_invalid": "Maska podomrežja ni veljavna", "gateway_or_subnet_invalid": "Maska podomrežja ni veljavna",
"dhcp_form_gateway_input": "IP prehoda", "dhcp_form_gateway_input": "IP prehoda",
@@ -301,6 +298,9 @@
"blocking_mode_nxdomain": "NXDOMAIN: Odziv s kodo NXDOMAIN", "blocking_mode_nxdomain": "NXDOMAIN: Odziv s kodo NXDOMAIN",
"blocking_mode_null_ip": "Prazen IP: Odziv z ničelnim naslovom IP (0.0.0.0 za A; :: za AAAA)", "blocking_mode_null_ip": "Prazen IP: Odziv z ničelnim naslovom IP (0.0.0.0 za A; :: za AAAA)",
"blocking_mode_custom_ip": "IP po meri: Odziv z ročno nastavljenim naslovom IP", "blocking_mode_custom_ip": "IP po meri: Odziv z ročno nastavljenim naslovom IP",
"theme_auto": "Auto",
"theme_light": "Svetla tema",
"theme_dark": "Temna tema",
"upstream_dns_client_desc": "Če pustite to polje prazno, bo AdGuard Home uporabil strežnike, konfigurirane v <0>nastavitvah DNS</0>.", "upstream_dns_client_desc": "Če pustite to polje prazno, bo AdGuard Home uporabil strežnike, konfigurirane v <0>nastavitvah DNS</0>.",
"tracker_source": "Vir sledilca", "tracker_source": "Vir sledilca",
"source_label": "Vir", "source_label": "Vir",
@@ -454,6 +454,7 @@
"updates_checked": "Na voljo je nova različica programa AdGuard Home\n", "updates_checked": "Na voljo je nova različica programa AdGuard Home\n",
"updates_version_equal": "AdGuard Home je posodobljen", "updates_version_equal": "AdGuard Home je posodobljen",
"check_updates_now": "Preveri obstoj posodobitev zdaj", "check_updates_now": "Preveri obstoj posodobitev zdaj",
"version_request_error": "Posodobitev ni uspela. Preverite vašo internetno povezavo.",
"dns_privacy": "Zasebnost DNS", "dns_privacy": "Zasebnost DNS",
"setup_dns_privacy_1": "<0>DNS-prek-TLS:</0> Uporabite niz <1>{{address}}</1>.", "setup_dns_privacy_1": "<0>DNS-prek-TLS:</0> Uporabite niz <1>{{address}}</1>.",
"setup_dns_privacy_2": "<0>DNS-prek-HTTPS:</0> Uporabite niz <1>{{address}}</1>.", "setup_dns_privacy_2": "<0>DNS-prek-HTTPS:</0> Uporabite niz <1>{{address}}</1>.",
@@ -638,5 +639,8 @@
"safe_browsing": "Varno brskanje", "safe_browsing": "Varno brskanje",
"served_from_cache": "{{value}} <i>(postreženo iz predpomnilnika)</i>", "served_from_cache": "{{value}} <i>(postreženo iz predpomnilnika)</i>",
"form_error_password_length": "Geslo mora vsebovati najmanj {{value}} znakov", "form_error_password_length": "Geslo mora vsebovati najmanj {{value}} znakov",
"anonymizer_notification": "<0>Opomba:</0> Anonimizacija IP je omogočena. Onemogočite ga lahko v <1>Splošnih nastavitvah</1>." "anonymizer_notification": "<0>Opomba:</0> Anonimizacija IP je omogočena. Onemogočite ga lahko v <1>Splošnih nastavitvah</1>.",
"confirm_dns_cache_clear": "Ali ste prepričani, da želite počistiti predpomnilnik DNS?",
"cache_cleared": "Predpomnilnik DNS je bil uspešno počiščen",
"clear_cache": "Počisti predpomnilnik"
} }

View File

@@ -37,8 +37,6 @@
"dhcp_ipv6_settings": "DHCP IPv6 postavke", "dhcp_ipv6_settings": "DHCP IPv6 postavke",
"form_error_required": "Obavezno polje", "form_error_required": "Obavezno polje",
"form_error_ip4_format": "Nevažeća IPv4 adresa", "form_error_ip4_format": "Nevažeća IPv4 adresa",
"form_error_ip4_range_start_format": "Nevažeća IPv4 addresa početnog opsega",
"form_error_ip4_range_end_format": "Nevažeća IPv4 addresa završnog opsega",
"form_error_ip4_gateway_format": "Nevažeća IPv4 addresa prozala", "form_error_ip4_gateway_format": "Nevažeća IPv4 addresa prozala",
"form_error_ip6_format": "Nevažeća IPv6 adresa", "form_error_ip6_format": "Nevažeća IPv6 adresa",
"form_error_ip_format": "Nevažeća IP adresa", "form_error_ip_format": "Nevažeća IP adresa",
@@ -51,7 +49,6 @@
"out_of_range_error": "Mora biti izvan opsega \"{{start}}\"-\"{{end}}\"", "out_of_range_error": "Mora biti izvan opsega \"{{start}}\"-\"{{end}}\"",
"lower_range_start_error": "Mora biti manje od početnog opsega", "lower_range_start_error": "Mora biti manje od početnog opsega",
"greater_range_start_error": "Mora biti veće od početnog opsega", "greater_range_start_error": "Mora biti veće od početnog opsega",
"greater_range_end_error": "Mora biti veće od završnog opsega",
"subnet_error": "Asrese moraju biti u jednoj subnet", "subnet_error": "Asrese moraju biti u jednoj subnet",
"gateway_or_subnet_invalid": "Subnet mask nevažeća", "gateway_or_subnet_invalid": "Subnet mask nevažeća",
"dhcp_form_gateway_input": "IP mrežnog prolaza", "dhcp_form_gateway_input": "IP mrežnog prolaza",
@@ -301,6 +298,9 @@
"blocking_mode_nxdomain": "NXDOMAIN: Odgovara sa NXDOMAIN kodom", "blocking_mode_nxdomain": "NXDOMAIN: Odgovara sa NXDOMAIN kodom",
"blocking_mode_null_ip": "Null IP: Odgovara sa zero IP adresom (0.0.0.0 za A; :: za AAAA)", "blocking_mode_null_ip": "Null IP: Odgovara sa zero IP adresom (0.0.0.0 za A; :: za AAAA)",
"blocking_mode_custom_ip": "Prilagođeni IP: Odgovara sa ručno podešenom IP adresom", "blocking_mode_custom_ip": "Prilagođeni IP: Odgovara sa ručno podešenom IP adresom",
"theme_auto": "Auto",
"theme_light": "Svetla tema",
"theme_dark": "Tamna tema",
"upstream_dns_client_desc": "AKo ovo polje ostavite prazno, AdGuard Home će koristiti servere konfigurisane u <0>DNS postavkama</0>.", "upstream_dns_client_desc": "AKo ovo polje ostavite prazno, AdGuard Home će koristiti servere konfigurisane u <0>DNS postavkama</0>.",
"tracker_source": "Izvor praćenja", "tracker_source": "Izvor praćenja",
"source_label": "Izvor", "source_label": "Izvor",
@@ -454,6 +454,7 @@
"updates_checked": "Dostupna je nova verzija AdGuard Home-a", "updates_checked": "Dostupna je nova verzija AdGuard Home-a",
"updates_version_equal": "AdGuard Home je ažuriran na najnoviju verziju", "updates_version_equal": "AdGuard Home je ažuriran na najnoviju verziju",
"check_updates_now": "Proveri da li postoje ispravke", "check_updates_now": "Proveri da li postoje ispravke",
"version_request_error": "Provera ažuriranja nije uspela. Proverite svoju vezu sa internetom.",
"dns_privacy": "DNS privatnost", "dns_privacy": "DNS privatnost",
"setup_dns_privacy_1": "<0>DNS-over-TLS:</0> koristi <1>{{address}}</1> string.", "setup_dns_privacy_1": "<0>DNS-over-TLS:</0> koristi <1>{{address}}</1> string.",
"setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> koristi <1>{{address}}</1> string.", "setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> koristi <1>{{address}}</1> string.",
@@ -638,5 +639,8 @@
"safe_browsing": "Sigurno pregledanje", "safe_browsing": "Sigurno pregledanje",
"served_from_cache": "{{value}} <i>(posluženo iz predmemorije)</i>", "served_from_cache": "{{value}} <i>(posluženo iz predmemorije)</i>",
"form_error_password_length": "Lozinka mora imati najmanje {{value}} znakova", "form_error_password_length": "Lozinka mora imati najmanje {{value}} znakova",
"anonymizer_notification": "<0>Nota:</0> IP prepoznavanje je omogućeno. Možete ga onemogućiti u opštim <1>postavkama</1>." "anonymizer_notification": "<0>Nota:</0> IP prepoznavanje je omogućeno. Možete ga onemogućiti u opštim <1>postavkama</1>.",
"confirm_dns_cache_clear": "Želite li zaista da obrišite DNS keš?",
"cache_cleared": "DNS keš je uspešno očišćen",
"clear_cache": "Obriši keš memoriju"
} }

View File

@@ -37,8 +37,6 @@
"dhcp_ipv6_settings": "DHCP IPv6 inställningar", "dhcp_ipv6_settings": "DHCP IPv6 inställningar",
"form_error_required": "Obligatoriskt fält", "form_error_required": "Obligatoriskt fält",
"form_error_ip4_format": "Ogiltig IPv4-adress", "form_error_ip4_format": "Ogiltig IPv4-adress",
"form_error_ip4_range_start_format": "Ogiltig IPv4-adress för starten av intervallet",
"form_error_ip4_range_end_format": "Ogiltig IPv4-adress för slutet av intervallet",
"form_error_ip4_gateway_format": "Ogiltig IPv4 adress för gatewayen", "form_error_ip4_gateway_format": "Ogiltig IPv4 adress för gatewayen",
"form_error_ip6_format": "Ogiltig IPv6-adress", "form_error_ip6_format": "Ogiltig IPv6-adress",
"form_error_ip_format": "Ogiltig IP-adress", "form_error_ip_format": "Ogiltig IP-adress",
@@ -51,7 +49,6 @@
"out_of_range_error": "Måste vara utanför intervallet \"{{start}}\"-\"{{end}}\"", "out_of_range_error": "Måste vara utanför intervallet \"{{start}}\"-\"{{end}}\"",
"lower_range_start_error": "Måste vara lägre än starten på intervallet", "lower_range_start_error": "Måste vara lägre än starten på intervallet",
"greater_range_start_error": "Måste vara högre än starten på intervallet", "greater_range_start_error": "Måste vara högre än starten på intervallet",
"greater_range_end_error": "Måste vara större än intervallets slut",
"subnet_error": "Adresser måste finnas i ett subnät", "subnet_error": "Adresser måste finnas i ett subnät",
"gateway_or_subnet_invalid": "Subnätmask ogiltig", "gateway_or_subnet_invalid": "Subnätmask ogiltig",
"dhcp_form_gateway_input": "Gateway-IP", "dhcp_form_gateway_input": "Gateway-IP",
@@ -301,6 +298,9 @@
"blocking_mode_nxdomain": "NXDOMAIN: Svara med NXDOMAIN kod", "blocking_mode_nxdomain": "NXDOMAIN: Svara med NXDOMAIN kod",
"blocking_mode_null_ip": "Null IP: Svara med noll IP adress (0.0.0.0 för A; :: för AAAA)", "blocking_mode_null_ip": "Null IP: Svara med noll IP adress (0.0.0.0 för A; :: för AAAA)",
"blocking_mode_custom_ip": "Anpassad IP: Svara med en manuellt inställd IP adress", "blocking_mode_custom_ip": "Anpassad IP: Svara med en manuellt inställd IP adress",
"theme_auto": "Auto",
"theme_light": "Ljust",
"theme_dark": "Mörkt",
"upstream_dns_client_desc": "Om detta fält är tomt kommer AdGuard Home att använda de servrar som konfigurerats i <0>DNS inställningarna</0>.", "upstream_dns_client_desc": "Om detta fält är tomt kommer AdGuard Home att använda de servrar som konfigurerats i <0>DNS inställningarna</0>.",
"tracker_source": "Spårningskälla", "tracker_source": "Spårningskälla",
"source_label": "Källa", "source_label": "Källa",
@@ -454,6 +454,7 @@
"updates_checked": "En ny version av AdGuard Home är tillgänglig\n", "updates_checked": "En ny version av AdGuard Home är tillgänglig\n",
"updates_version_equal": "AdGuard Home är uppdaterat", "updates_version_equal": "AdGuard Home är uppdaterat",
"check_updates_now": "Sök efter uppdateringar nu", "check_updates_now": "Sök efter uppdateringar nu",
"version_request_error": "Uppdateringskontroll misslyckades. Kontrollera din internetanslutning.",
"dns_privacy": "DNS-Integritet", "dns_privacy": "DNS-Integritet",
"setup_dns_privacy_1": "<0>DNS-över-TLS:</0> Använd: <1>{{address}}</1>", "setup_dns_privacy_1": "<0>DNS-över-TLS:</0> Använd: <1>{{address}}</1>",
"setup_dns_privacy_2": "<0>DNS-över-HTTPS:</0> Använd: <1>{{address}}</1>", "setup_dns_privacy_2": "<0>DNS-över-HTTPS:</0> Använd: <1>{{address}}</1>",
@@ -638,5 +639,8 @@
"safe_browsing": "Säker surfning", "safe_browsing": "Säker surfning",
"served_from_cache": "{{value}} <i>(levereras från cache)</i>", "served_from_cache": "{{value}} <i>(levereras från cache)</i>",
"form_error_password_length": "Lösenordet måste vara minst {{value}} tecken långt", "form_error_password_length": "Lösenordet måste vara minst {{value}} tecken långt",
"anonymizer_notification": "<0>Observera:</0> IP-anonymisering är aktiverad. Du kan inaktivera den i <1>Allmänna inställningar</1>." "anonymizer_notification": "<0>Observera:</0> IP-anonymisering är aktiverad. Du kan inaktivera den i <1>Allmänna inställningar</1>.",
"confirm_dns_cache_clear": "Är du säker på att du vill rensa DNS-cache?",
"cache_cleared": "DNS-cacheminnet har rensats",
"clear_cache": "Rensa cache"
} }

View File

@@ -37,8 +37,6 @@
"dhcp_ipv6_settings": "DHCP IPv6 Ayarları", "dhcp_ipv6_settings": "DHCP IPv6 Ayarları",
"form_error_required": "Gerekli alan", "form_error_required": "Gerekli alan",
"form_error_ip4_format": "Geçersiz IPv4 adresi", "form_error_ip4_format": "Geçersiz IPv4 adresi",
"form_error_ip4_range_start_format": "Geçersiz başlangıç aralığı IPv4 biçimi",
"form_error_ip4_range_end_format": "Geçersiz bitiş aralığı IPv4 adresi",
"form_error_ip4_gateway_format": "Geçersiz ağ geçidi IPv4 adresi", "form_error_ip4_gateway_format": "Geçersiz ağ geçidi IPv4 adresi",
"form_error_ip6_format": "Geçersiz IPv6 adresi", "form_error_ip6_format": "Geçersiz IPv6 adresi",
"form_error_ip_format": "Geçersiz IP adresi", "form_error_ip_format": "Geçersiz IP adresi",
@@ -51,9 +49,8 @@
"out_of_range_error": "\"{{start}}\"-\"{{end}}\" aralığının dışında olmalıdır", "out_of_range_error": "\"{{start}}\"-\"{{end}}\" aralığının dışında olmalıdır",
"lower_range_start_error": "Başlangıç aralığından daha düşük olmalıdır", "lower_range_start_error": "Başlangıç aralığından daha düşük olmalıdır",
"greater_range_start_error": "Başlangıç aralığından daha büyük olmalıdır", "greater_range_start_error": "Başlangıç aralığından daha büyük olmalıdır",
"greater_range_end_error": "Bitiş aralığından daha büyük olmalıdır",
"subnet_error": "Adresler bir alt ağda olmalıdır", "subnet_error": "Adresler bir alt ağda olmalıdır",
"gateway_or_subnet_invalid": "Alt ağ maskesi geçersiz", "gateway_or_subnet_invalid": "Geçersiz alt ağ maskesi",
"dhcp_form_gateway_input": "Ağ geçidi IP", "dhcp_form_gateway_input": "Ağ geçidi IP",
"dhcp_form_subnet_input": "Alt ağ maskesi", "dhcp_form_subnet_input": "Alt ağ maskesi",
"dhcp_form_range_title": "IP adresi aralığı", "dhcp_form_range_title": "IP adresi aralığı",
@@ -131,14 +128,14 @@
"number_of_dns_query_days": "Son {{count}} gün boyunca işlenen DNS sorgularının sayısı", "number_of_dns_query_days": "Son {{count}} gün boyunca işlenen DNS sorgularının sayısı",
"number_of_dns_query_days_plural": "Son {{count}} gün boyunca işlenen DNS sorgularının sayısı", "number_of_dns_query_days_plural": "Son {{count}} gün boyunca işlenen DNS sorgularının sayısı",
"number_of_dns_query_24_hours": "Son 24 saat içinde işlenen DNS sorgularının sayısı", "number_of_dns_query_24_hours": "Son 24 saat içinde işlenen DNS sorgularının sayısı",
"number_of_dns_query_blocked_24_hours": "Reklam engelleme filtreleri ve ana makine engel listeleri tarafından engellenen DNS isteklerinin sayısı", "number_of_dns_query_blocked_24_hours": "Reklam engelleme filtreleri ve hosts engel listeleri tarafından engellenen DNS isteklerinin sayısı",
"number_of_dns_query_blocked_24_hours_by_sec": "AdGuard gezinti koruması modülü tarafından engellenen DNS isteklerinin sayısı", "number_of_dns_query_blocked_24_hours_by_sec": "AdGuard gezinti koruması modülü tarafından engellenen DNS isteklerinin sayısı",
"number_of_dns_query_blocked_24_hours_adult": "Engellenen yetişkin içerikli sitelerin sayısı", "number_of_dns_query_blocked_24_hours_adult": "Engellenen yetişkin içerikli sitelerin sayısı",
"enforced_save_search": "Uygulanan güvenli arama", "enforced_save_search": "Uygulanan güvenli arama",
"number_of_dns_query_to_safe_search": "Güvenli Aramanın uygulandığı arama motorlarına gönderilen DNS isteklerinin sayısı", "number_of_dns_query_to_safe_search": "Güvenli Aramanın uygulandığı arama motorlarına gönderilen DNS isteklerinin sayısı",
"average_processing_time": "Ortalama işlem süresi", "average_processing_time": "Ortalama işlem süresi",
"average_processing_time_hint": "Bir DNS isteğinin milisaniye cinsinden ortalama işlem süresi", "average_processing_time_hint": "Bir DNS isteğinin milisaniye cinsinden ortalama işlem süresi",
"block_domain_use_filters_and_hosts": "Filtre ve ana makine listelerini kullanarak alan adlarını engelle", "block_domain_use_filters_and_hosts": "Filtre ve hosts dosyalarını kullanarak alan adlarını engelle",
"filters_block_toggle_hint": "<a>Filtreler</a> ayarlarında engelleme kuralları oluşturabilirsiniz.", "filters_block_toggle_hint": "<a>Filtreler</a> ayarlarında engelleme kuralları oluşturabilirsiniz.",
"use_adguard_browsing_sec": "AdGuard gezinti koruması web hizmetini kullan", "use_adguard_browsing_sec": "AdGuard gezinti koruması web hizmetini kullan",
"use_adguard_browsing_sec_hint": "AdGuard Home, alan adının gezinti koruması web hizmeti tarafından engellenip engellenmediğini kontrol eder. Kontrolü gerçekleştirmek için gizlilik dostu arama API'sini kullanır: sunucuya yalnızca SHA256 karma alan adının kısa bir ön eki gönderilir.", "use_adguard_browsing_sec_hint": "AdGuard Home, alan adının gezinti koruması web hizmeti tarafından engellenip engellenmediğini kontrol eder. Kontrolü gerçekleştirmek için gizlilik dostu arama API'sini kullanır: sunucuya yalnızca SHA256 karma alan adının kısa bir ön eki gönderilir.",
@@ -180,7 +177,7 @@
"edit_table_action": "Düzenle", "edit_table_action": "Düzenle",
"delete_table_action": "Sil", "delete_table_action": "Sil",
"elapsed": "Geçen süre", "elapsed": "Geçen süre",
"filters_and_hosts_hint": "AdGuard Home, temel reklam engelleme kurallarını ve ana makine dosyalarının söz dizimini anlar.", "filters_and_hosts_hint": "AdGuard Home, temel reklam engelleme kurallarını ve hosts dosyalarının söz dizimini anlar.",
"no_blocklist_added": "Engel listesi eklenmedi", "no_blocklist_added": "Engel listesi eklenmedi",
"no_whitelist_added": "İzin listesi eklenmedi", "no_whitelist_added": "İzin listesi eklenmedi",
"add_blocklist": "Engel listesi ekle", "add_blocklist": "Engel listesi ekle",
@@ -200,8 +197,8 @@
"form_error_url_format": "Geçersiz URL biçimi", "form_error_url_format": "Geçersiz URL biçimi",
"form_error_url_or_path_format": "Geçersiz URL adresi veya dosya yolu", "form_error_url_or_path_format": "Geçersiz URL adresi veya dosya yolu",
"custom_filter_rules": "Özel filtreleme kuralları", "custom_filter_rules": "Özel filtreleme kuralları",
"custom_filter_rules_hint": "Her satıra bir kural girin. Reklam engelleme kuralı veya ana makine dosyası söz dizimi kullanabilirsiniz.", "custom_filter_rules_hint": "Her satıra bir kural girin. Reklam engelleme kuralı veya hosts dosyası söz dizimi kullanabilirsiniz.",
"system_host_files": "Sistem ana makine dosyaları", "system_host_files": "Sistem hosts dosyaları",
"examples_title": "Örnekler", "examples_title": "Örnekler",
"example_meaning_filter_block": "example.org'a ve tüm alt alanlarına erişimi engeller;", "example_meaning_filter_block": "example.org'a ve tüm alt alanlarına erişimi engeller;",
"example_meaning_filter_whitelist": "example.org'a ve tüm alt alanlarına erişimin engelini kaldırır;", "example_meaning_filter_whitelist": "example.org'a ve tüm alt alanlarına erişimin engelini kaldırır;",
@@ -301,6 +298,9 @@
"blocking_mode_nxdomain": "NXDOMAIN: NXDOMAIN koduyla yanıt verin", "blocking_mode_nxdomain": "NXDOMAIN: NXDOMAIN koduyla yanıt verin",
"blocking_mode_null_ip": "Boş IP: Sıfır IP adresiyle yanıt verin (A için 0.0.0.0; :: AAAA için)", "blocking_mode_null_ip": "Boş IP: Sıfır IP adresiyle yanıt verin (A için 0.0.0.0; :: AAAA için)",
"blocking_mode_custom_ip": "Özel IP: El ile ayarlanmış bir IP adresiyle yanıt verin", "blocking_mode_custom_ip": "Özel IP: El ile ayarlanmış bir IP adresiyle yanıt verin",
"theme_auto": "Otomatik",
"theme_light": "Açık",
"theme_dark": "Koyu",
"upstream_dns_client_desc": "Bu alanı boş bırakırsanız, AdGuard Home, <0>DNS ayarlarında</0> yapılandırılan sunucuları kullanır.", "upstream_dns_client_desc": "Bu alanı boş bırakırsanız, AdGuard Home, <0>DNS ayarlarında</0> yapılandırılan sunucuları kullanır.",
"tracker_source": "İzleyici kaynağı", "tracker_source": "İzleyici kaynağı",
"source_label": "Kaynak", "source_label": "Kaynak",
@@ -350,12 +350,12 @@
"install_devices_macos_list_3": "Listedeki ilk bağlantıyı seçin ve Gelişmiş öğesine tıklayın.", "install_devices_macos_list_3": "Listedeki ilk bağlantıyı seçin ve Gelişmiş öğesine tıklayın.",
"install_devices_macos_list_4": "DNS sekmesini seçin ve AdGuard Home sunucunuzun adreslerini girin.", "install_devices_macos_list_4": "DNS sekmesini seçin ve AdGuard Home sunucunuzun adreslerini girin.",
"install_devices_android_list_1": "Android Menüsü ana ekranından Ayarlar'a dokunun.", "install_devices_android_list_1": "Android Menüsü ana ekranından Ayarlar'a dokunun.",
"install_devices_android_list_2": "Menüde bulunan Wi-Fi öğesine dokunun. Mevcut tüm ağlar listelenecektir (mobil ağlar için özel DNS sunucusu ayarlanamaz).", "install_devices_android_list_2": "Menüde bulunan Wi-Fi öğesine dokunun. Mevcut tüm ağlar listelenecektir (telefon ağlar için özel DNS sunucusu ayarlanamaz).",
"install_devices_android_list_3": "Bağlı olduğunuz ağın üzerine basılı tutun ve Ağı Değiştir'e dokunun.", "install_devices_android_list_3": "Bağlı olduğunuz ağın üzerine basılı tutun ve Ağı Değiştir'e dokunun.",
"install_devices_android_list_4": "Bazı cihazlarda, diğer ayarları görmek için \"Gelişmiş\" seçeneğini seçmeniz gerekebilir. Android DNS ayarlarınızı yapmak için IP ayarlarını DHCP modundan Statik moda değiştirmeniz gerekir.", "install_devices_android_list_4": "Bazı cihazlarda, diğer ayarları görmek için \"Gelişmiş\" seçeneğini seçmeniz gerekebilir. Android DNS ayarlarınızı yapmak için IP ayarlarını DHCP modundan Statik moda değiştirmeniz gerekir.",
"install_devices_android_list_5": "DNS 1 ve DNS 2 değerlerini AdGuard Home sunucunuzun adresleriyle değiştirin.", "install_devices_android_list_5": "DNS 1 ve DNS 2 değerlerini AdGuard Home sunucunuzun adresleriyle değiştirin.",
"install_devices_ios_list_1": "Ana ekrandan Ayarlar'a dokunun.", "install_devices_ios_list_1": "Ana ekrandan Ayarlar'a dokunun.",
"install_devices_ios_list_2": "Sol menüde bulunan Wi-Fi bölümüne girin (mobil ağlar için özel DNS sunucusu ayarlanamaz).", "install_devices_ios_list_2": "Sol menüde bulunan Wi-Fi bölümüne girin (telefon ağlar için özel DNS sunucusu ayarlanamaz).",
"install_devices_ios_list_3": "O anda aktif olan ağın adına dokunun.", "install_devices_ios_list_3": "O anda aktif olan ağın adına dokunun.",
"install_devices_ios_list_4": "DNS alanına AdGuard Home sunucunuzun adreslerini girin.", "install_devices_ios_list_4": "DNS alanına AdGuard Home sunucunuzun adreslerini girin.",
"get_started": "Başlayın", "get_started": "Başlayın",
@@ -454,6 +454,7 @@
"updates_checked": "AdGuard Home'un yeni bir sürümü mevcut", "updates_checked": "AdGuard Home'un yeni bir sürümü mevcut",
"updates_version_equal": "AdGuard Home yazılımı güncel durumda", "updates_version_equal": "AdGuard Home yazılımı güncel durumda",
"check_updates_now": "Güncellemeleri şimdi denetle", "check_updates_now": "Güncellemeleri şimdi denetle",
"version_request_error": "Güncelleme denetimi başarısız. Lütfen internet bağlantınızı kontrol edin.",
"dns_privacy": "DNS Gizliliği", "dns_privacy": "DNS Gizliliği",
"setup_dns_privacy_1": "<0>DNS-over-TLS:</0> <1>{{address}}</1> dizesini kullan.", "setup_dns_privacy_1": "<0>DNS-over-TLS:</0> <1>{{address}}</1> dizesini kullan.",
"setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> <1>{{address}}</1> dizesini kullan.", "setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> <1>{{address}}</1> dizesini kullan.",
@@ -479,7 +480,7 @@
"rewrite_confirm_delete": "\"{{key}}\" için DNS yeniden yazımını silmek istediğinize emin misiniz?", "rewrite_confirm_delete": "\"{{key}}\" için DNS yeniden yazımını silmek istediğinize emin misiniz?",
"rewrite_desc": "Belirli bir alan adı için özel DNS yanıtını kolayca yapılandırmanızı sağlar.", "rewrite_desc": "Belirli bir alan adı için özel DNS yanıtını kolayca yapılandırmanızı sağlar.",
"rewrite_applied": "Yeniden yazım kuralı uygulandı", "rewrite_applied": "Yeniden yazım kuralı uygulandı",
"rewrite_hosts_applied": "Ana makine dosyası kuralı tarafından yeniden yazıldı", "rewrite_hosts_applied": "Hosts dosyası kuralı tarafından yeniden yazıldı",
"dns_rewrites": "DNS yeniden yazımları", "dns_rewrites": "DNS yeniden yazımları",
"form_domain": "Alan adı veya joker karakter girin", "form_domain": "Alan adı veya joker karakter girin",
"form_answer": "IP adresi veya alan adı girin", "form_answer": "IP adresi veya alan adı girin",
@@ -542,7 +543,7 @@
"network": "Ağ", "network": "Ağ",
"descr": "Açıklama", "descr": "Açıklama",
"whois": "WHOIS", "whois": "WHOIS",
"filtering_rules_learn_more": "Kendi ana makine listelerinizi oluşturma hakkında <0>daha fazla bilgi edinin</0>.", "filtering_rules_learn_more": "Kendi hosts listelerinizi oluşturma hakkında <0>daha fazla bilgi edinin</0>.",
"blocked_by_response": "Yanıt olarak CNAME veya IP tarafından engellendi", "blocked_by_response": "Yanıt olarak CNAME veya IP tarafından engellendi",
"blocked_by_cname_or_ip": "CNAME veya IP tarafından engellendi", "blocked_by_cname_or_ip": "CNAME veya IP tarafından engellendi",
"try_again": "Tekrar dene", "try_again": "Tekrar dene",
@@ -638,5 +639,8 @@
"safe_browsing": "Güvenli Gezinti", "safe_browsing": "Güvenli Gezinti",
"served_from_cache": "{{value}} <i>(önbellekten kullanıldı)</i>", "served_from_cache": "{{value}} <i>(önbellekten kullanıldı)</i>",
"form_error_password_length": "Parola en az {{value}} karakter uzunluğunda olmalıdır", "form_error_password_length": "Parola en az {{value}} karakter uzunluğunda olmalıdır",
"anonymizer_notification": "<0>Not:</0> IP anonimleştirme etkinleştirildi. Bunu <1>Genel ayarlardan</1> devre dışı bırakabilirsiniz." "anonymizer_notification": "<0>Not:</0> IP anonimleştirme etkinleştirildi. Bunu <1>Genel ayarlardan</1> devre dışı bırakabilirsiniz.",
"confirm_dns_cache_clear": "DNS önbelleğini temizlemek istediğinizden emin misiniz?",
"cache_cleared": "DNS önbelleği başarıyla temizlendi",
"clear_cache": "Önbelleği temizle"
} }

View File

@@ -37,8 +37,6 @@
"dhcp_ipv6_settings": "Налаштування DHCP IPv6", "dhcp_ipv6_settings": "Налаштування DHCP IPv6",
"form_error_required": "Обов'язкове поле", "form_error_required": "Обов'язкове поле",
"form_error_ip4_format": "Неправильна IPv4-адреса", "form_error_ip4_format": "Неправильна IPv4-адреса",
"form_error_ip4_range_start_format": "Неправильна IPv4-адреса початку діапазону",
"form_error_ip4_range_end_format": "Неправильна IPv4-адреса кінця діапазону",
"form_error_ip4_gateway_format": "Неправильна IPv4-адреса шлюзу", "form_error_ip4_gateway_format": "Неправильна IPv4-адреса шлюзу",
"form_error_ip6_format": "Неправильна IPv6-адреса", "form_error_ip6_format": "Неправильна IPv6-адреса",
"form_error_ip_format": "Неправильна IP-адреса", "form_error_ip_format": "Неправильна IP-адреса",
@@ -51,7 +49,6 @@
"out_of_range_error": "Не повинна бути в діапазоні «{{start}}»−«{{end}}»", "out_of_range_error": "Не повинна бути в діапазоні «{{start}}»−«{{end}}»",
"lower_range_start_error": "Має бути меншим за початкову адресу", "lower_range_start_error": "Має бути меншим за початкову адресу",
"greater_range_start_error": "Має бути більшим за початкову адресу", "greater_range_start_error": "Має бути більшим за початкову адресу",
"greater_range_end_error": "Має бути більшим за кінцеву адресу",
"subnet_error": "Адреси повинні бути в одній підмережі", "subnet_error": "Адреси повинні бути в одній підмережі",
"gateway_or_subnet_invalid": "Неправильна маска підмережі", "gateway_or_subnet_invalid": "Неправильна маска підмережі",
"dhcp_form_gateway_input": "IP-адреса шлюзу", "dhcp_form_gateway_input": "IP-адреса шлюзу",
@@ -301,6 +298,9 @@
"blocking_mode_nxdomain": "NXDOMAIN: Відповісти з кодом NXDOMAIN", "blocking_mode_nxdomain": "NXDOMAIN: Відповісти з кодом NXDOMAIN",
"blocking_mode_null_ip": "Нульовий IP: Відповісти з нульовою IP-адресою (0.0.0.0 для A; :: для AAAA)", "blocking_mode_null_ip": "Нульовий IP: Відповісти з нульовою IP-адресою (0.0.0.0 для A; :: для AAAA)",
"blocking_mode_custom_ip": "Спеціальна IP-адреса: Відповісти із вручну встановленою IP-адресою", "blocking_mode_custom_ip": "Спеціальна IP-адреса: Відповісти із вручну встановленою IP-адресою",
"theme_auto": "Авто",
"theme_light": "Світла",
"theme_dark": "Темна",
"upstream_dns_client_desc": "Якщо це поле залишатиметься порожнім, AdGuard Home використовуватиме сервери, вказані в <0>налаштуваннях DNS</0>.", "upstream_dns_client_desc": "Якщо це поле залишатиметься порожнім, AdGuard Home використовуватиме сервери, вказані в <0>налаштуваннях DNS</0>.",
"tracker_source": "Джерело відстежувача", "tracker_source": "Джерело відстежувача",
"source_label": "Джерело", "source_label": "Джерело",
@@ -393,7 +393,7 @@
"encryption_issuer": "Видавець", "encryption_issuer": "Видавець",
"encryption_hostnames": "Назви вузлів", "encryption_hostnames": "Назви вузлів",
"encryption_reset": "Ви впевнені, що хочете скинути налаштування шифрування?", "encryption_reset": "Ви впевнені, що хочете скинути налаштування шифрування?",
"encryption_warning": "Увага", "encryption_warning": "Попередження",
"topline_expiring_certificate": "Ваш сертифікат SSL скоро закінчиться. Оновіть <0>Налаштування шифрування</0>.", "topline_expiring_certificate": "Ваш сертифікат SSL скоро закінчиться. Оновіть <0>Налаштування шифрування</0>.",
"topline_expired_certificate": "Термін дії вашого сертифіката SSL закінчився. Оновіть <0>Налаштування шифрування</0>.", "topline_expired_certificate": "Термін дії вашого сертифіката SSL закінчився. Оновіть <0>Налаштування шифрування</0>.",
"form_error_port_range": "Введіть значення порту в діапазоні 8065535", "form_error_port_range": "Введіть значення порту в діапазоні 8065535",
@@ -454,6 +454,7 @@
"updates_checked": "Доступна нова версія AdGuard Home", "updates_checked": "Доступна нова версія AdGuard Home",
"updates_version_equal": "AdGuard Home останньої версії", "updates_version_equal": "AdGuard Home останньої версії",
"check_updates_now": "Перевірити наявність оновлень", "check_updates_now": "Перевірити наявність оновлень",
"version_request_error": "Не вдалося перевірити оновлення. Будь ласка, перевірте з'єднання з інтернетом.",
"dns_privacy": "Конфіденційність DNS", "dns_privacy": "Конфіденційність DNS",
"setup_dns_privacy_1": "<0>DNS-over-TLS: </0>Використайте рядок <1>{{address}}</1>.", "setup_dns_privacy_1": "<0>DNS-over-TLS: </0>Використайте рядок <1>{{address}}</1>.",
"setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> Використайте рядок <1>{{address}}</1>.", "setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> Використайте рядок <1>{{address}}</1>.",
@@ -638,5 +639,8 @@
"safe_browsing": "Безпечний перегляд", "safe_browsing": "Безпечний перегляд",
"served_from_cache": "{{value}} <i>(отримано з кешу)</i>", "served_from_cache": "{{value}} <i>(отримано з кешу)</i>",
"form_error_password_length": "Пароль мусить мати принаймні {{value}} символів", "form_error_password_length": "Пароль мусить мати принаймні {{value}} символів",
"anonymizer_notification": "<0>Примітка:</0> IP-анонімізацію ввімкнено. Ви можете вимкнути його в <1>Загальні налаштування</1> ." "anonymizer_notification": "<0>Примітка:</0> IP-анонімізацію ввімкнено. Ви можете вимкнути його в <1>Загальні налаштування</1> .",
"confirm_dns_cache_clear": "Ви впевнені, що бажаєте очистити кеш DNS?",
"cache_cleared": "Кеш DNS успішно очищено",
"clear_cache": "Очистити кеш"
} }

View File

@@ -37,8 +37,6 @@
"dhcp_ipv6_settings": "Cài đặt DHCP IPv6", "dhcp_ipv6_settings": "Cài đặt DHCP IPv6",
"form_error_required": "Trường bắt buộc", "form_error_required": "Trường bắt buộc",
"form_error_ip4_format": "Địa chỉ IPv4 không hợp lệ", "form_error_ip4_format": "Địa chỉ IPv4 không hợp lệ",
"form_error_ip4_range_start_format": "Địa chỉ IPv4 không hợp lệ của phạm vi bắt đầu",
"form_error_ip4_range_end_format": "Địa chỉ IPv4 không hợp lệ của cuối phạm vi",
"form_error_ip4_gateway_format": "Địa chỉ IPv4 không hợp lệ của cổng kết nối", "form_error_ip4_gateway_format": "Địa chỉ IPv4 không hợp lệ của cổng kết nối",
"form_error_ip6_format": "Địa chỉ IPv6 không hợp lệ", "form_error_ip6_format": "Địa chỉ IPv6 không hợp lệ",
"form_error_ip_format": "Địa chỉ IP không hợp lệ", "form_error_ip_format": "Địa chỉ IP không hợp lệ",
@@ -51,7 +49,6 @@
"out_of_range_error": "Phải nằm ngoài phạm vi \"{{start}}\"-\"{{end}}\"", "out_of_range_error": "Phải nằm ngoài phạm vi \"{{start}}\"-\"{{end}}\"",
"lower_range_start_error": "Phải thấp hơn khởi động phạm vi", "lower_range_start_error": "Phải thấp hơn khởi động phạm vi",
"greater_range_start_error": "Phải lớn hơn khoảng bắt đầu", "greater_range_start_error": "Phải lớn hơn khoảng bắt đầu",
"greater_range_end_error": "Phải lớn hơn phạm vi kết thúc",
"subnet_error": "Địa chỉ phải nằm trong một mạng con", "subnet_error": "Địa chỉ phải nằm trong một mạng con",
"gateway_or_subnet_invalid": "Mặt nạ mạng con không hợp lệ", "gateway_or_subnet_invalid": "Mặt nạ mạng con không hợp lệ",
"dhcp_form_gateway_input": "Cổng IP", "dhcp_form_gateway_input": "Cổng IP",
@@ -301,6 +298,9 @@
"blocking_mode_nxdomain": "NXDOMAIN: Phản hổi với mã NXDOMAIN", "blocking_mode_nxdomain": "NXDOMAIN: Phản hổi với mã NXDOMAIN",
"blocking_mode_null_ip": "Null IP: Trả lời bằng không địa chỉ IP (0.0.0.0 cho A; :: cho AAAA)", "blocking_mode_null_ip": "Null IP: Trả lời bằng không địa chỉ IP (0.0.0.0 cho A; :: cho AAAA)",
"blocking_mode_custom_ip": "IP tùy chỉnh: Phản hồi với địa chỉ IP đã được tiết lập", "blocking_mode_custom_ip": "IP tùy chỉnh: Phản hồi với địa chỉ IP đã được tiết lập",
"theme_auto": "Tự động",
"theme_light": "Light theme",
"theme_dark": "Dark theme",
"upstream_dns_client_desc": "Nếu để trống trường này, AdGuardHome sẽ sử dụng nhũng máy chủ được cấu hình ở <0>Cấu hình DNS</0>.", "upstream_dns_client_desc": "Nếu để trống trường này, AdGuardHome sẽ sử dụng nhũng máy chủ được cấu hình ở <0>Cấu hình DNS</0>.",
"tracker_source": "Nguồn theo dõi", "tracker_source": "Nguồn theo dõi",
"source_label": "Nguồn", "source_label": "Nguồn",
@@ -454,6 +454,7 @@
"updates_checked": "Phiên bản mới của AdGuard Home có sẵn", "updates_checked": "Phiên bản mới của AdGuard Home có sẵn",
"updates_version_equal": "AdGuard Home đã được cập nhật", "updates_version_equal": "AdGuard Home đã được cập nhật",
"check_updates_now": "Kiểm tra cập nhật ngay bây giờ", "check_updates_now": "Kiểm tra cập nhật ngay bây giờ",
"version_request_error": "Cập nhật không thành công. Hãy kiểm tra kết nối internet của bạn.",
"dns_privacy": "DNS Riêng Tư", "dns_privacy": "DNS Riêng Tư",
"setup_dns_privacy_1": "<0>DNS-over-TLS:</0> Sử dụng chuỗi <1>{{address}}</1>.", "setup_dns_privacy_1": "<0>DNS-over-TLS:</0> Sử dụng chuỗi <1>{{address}}</1>.",
"setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> Sử dụng chuỗi <1>{{address}}</1>.", "setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> Sử dụng chuỗi <1>{{address}}</1>.",
@@ -638,5 +639,8 @@
"safe_browsing": "Duyệt web an toàn", "safe_browsing": "Duyệt web an toàn",
"served_from_cache": "{{value}} <i>(được phục vụ từ bộ nhớ cache)</i>", "served_from_cache": "{{value}} <i>(được phục vụ từ bộ nhớ cache)</i>",
"form_error_password_length": "Mật khẩu phải có ít nhất {{value}} ký tự", "form_error_password_length": "Mật khẩu phải có ít nhất {{value}} ký tự",
"anonymizer_notification": "<0> Lưu ý:</0> Tính năng ẩn danh IP được bật. Bạn có thể tắt nó trong <1> Cài đặt chung</1>." "anonymizer_notification": "<0> Lưu ý:</0> Tính năng ẩn danh IP được bật. Bạn có thể tắt nó trong <1> Cài đặt chung</1>.",
"confirm_dns_cache_clear": "Bạn có chắc chắn muốn xóa bộ đệm ẩn DNS không?",
"cache_cleared": "Đã xóa thành công bộ đệm DNS",
"clear_cache": "Xóa bộ nhớ cache"
} }

View File

@@ -37,8 +37,6 @@
"dhcp_ipv6_settings": "DHCP IPv6设置", "dhcp_ipv6_settings": "DHCP IPv6设置",
"form_error_required": "必填字段", "form_error_required": "必填字段",
"form_error_ip4_format": "无效的 IPv4 地址", "form_error_ip4_format": "无效的 IPv4 地址",
"form_error_ip4_range_start_format": "范围起始值的 IPv4 地址无效",
"form_error_ip4_range_end_format": "范围终值的 IPv4 地址无效",
"form_error_ip4_gateway_format": "网关 IPv4 地址无效", "form_error_ip4_gateway_format": "网关 IPv4 地址无效",
"form_error_ip6_format": "无效的 IPv6 地址", "form_error_ip6_format": "无效的 IPv6 地址",
"form_error_ip_format": "无效的 IP 地址", "form_error_ip_format": "无效的 IP 地址",
@@ -51,7 +49,6 @@
"out_of_range_error": "必定超出了范围 \"{{start}}\"-\"{{end}}\"", "out_of_range_error": "必定超出了范围 \"{{start}}\"-\"{{end}}\"",
"lower_range_start_error": "必须小于范围起始值", "lower_range_start_error": "必须小于范围起始值",
"greater_range_start_error": "必须大于范围起始值", "greater_range_start_error": "必须大于范围起始值",
"greater_range_end_error": "必须大于范围终值",
"subnet_error": "地址必须在一个子网内", "subnet_error": "地址必须在一个子网内",
"gateway_or_subnet_invalid": "子网掩码无效", "gateway_or_subnet_invalid": "子网掩码无效",
"dhcp_form_gateway_input": "网关 IP", "dhcp_form_gateway_input": "网关 IP",
@@ -301,6 +298,9 @@
"blocking_mode_nxdomain": "NXDOMAIN以NXDOMAIN码响应", "blocking_mode_nxdomain": "NXDOMAIN以NXDOMAIN码响应",
"blocking_mode_null_ip": "空IP以零IP地址响应(A记录 0.0.0.0AAAA记录 ::)", "blocking_mode_null_ip": "空IP以零IP地址响应(A记录 0.0.0.0AAAA记录 ::)",
"blocking_mode_custom_ip": "自定IP以手动设置的IP地址响应", "blocking_mode_custom_ip": "自定IP以手动设置的IP地址响应",
"theme_auto": "自动",
"theme_light": "浅色主题",
"theme_dark": "深色主题",
"upstream_dns_client_desc": "如果将此字段留空AdGuard Home 将使用在<0>DNS设置</0>中配置的服务器。", "upstream_dns_client_desc": "如果将此字段留空AdGuard Home 将使用在<0>DNS设置</0>中配置的服务器。",
"tracker_source": "追踪器来源", "tracker_source": "追踪器来源",
"source_label": "源", "source_label": "源",
@@ -454,6 +454,7 @@
"updates_checked": "AdGuard Home 的新版本现在可用", "updates_checked": "AdGuard Home 的新版本现在可用",
"updates_version_equal": "AdGuard Home已经是最新版本", "updates_version_equal": "AdGuard Home已经是最新版本",
"check_updates_now": "立即检查更新", "check_updates_now": "立即检查更新",
"version_request_error": "检查更新失败。请检查您的因特网连接。",
"dns_privacy": "DNS 隐私", "dns_privacy": "DNS 隐私",
"setup_dns_privacy_1": "<0>DNS-over-TLS:</0> 使用 <1>{{address}}</1> 字符串。", "setup_dns_privacy_1": "<0>DNS-over-TLS:</0> 使用 <1>{{address}}</1> 字符串。",
"setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> 使用 <1>{{address}}</1> 字符串。", "setup_dns_privacy_2": "<0>DNS-over-HTTPS:</0> 使用 <1>{{address}}</1> 字符串。",
@@ -638,5 +639,8 @@
"safe_browsing": "安全浏览", "safe_browsing": "安全浏览",
"served_from_cache": "{{value}}<i>(由缓存提供)</i>", "served_from_cache": "{{value}}<i>(由缓存提供)</i>",
"form_error_password_length": "密码必须至少有 {{value}} 个字符", "form_error_password_length": "密码必须至少有 {{value}} 个字符",
"anonymizer_notification": "<0>注意:</0> IP 匿名化已启用。您可以在<1>常规设置</1>中禁用它。" "anonymizer_notification": "<0>注意:</0> IP 匿名化已启用。您可以在<1>常规设置</1>中禁用它。",
"confirm_dns_cache_clear": "您确定要清除 DNS 缓存吗?",
"cache_cleared": "已成功清除 DNS 缓存",
"clear_cache": "清除缓存"
} }

View File

@@ -38,8 +38,6 @@
"form_error_required": "必要欄位", "form_error_required": "必要欄位",
"form_error_ip4_format": "無效的 IPv4 格式", "form_error_ip4_format": "無效的 IPv4 格式",
"form_error_ip6_format": "無效的 IPv6 格式", "form_error_ip6_format": "無效的 IPv6 格式",
"form_error_ip4_range_start_format": "無效的 IPv4 範圍起始位址",
"form_error_ip4_range_end_format": "無效的 IPv4 範圍結束位址",
"form_error_ip4_gateway_format": "閘道的 IPv4 位址無效", "form_error_ip4_gateway_format": "閘道的 IPv4 位址無效",
"form_error_ip_format": "無效的 IP 位址", "form_error_ip_format": "無效的 IP 位址",
"form_error_mac_format": "無效的 「MAC 位址」格式", "form_error_mac_format": "無效的 「MAC 位址」格式",

View File

@@ -37,8 +37,6 @@
"dhcp_ipv6_settings": "DHCP IPv6 設定", "dhcp_ipv6_settings": "DHCP IPv6 設定",
"form_error_required": "必填的欄位", "form_error_required": "必填的欄位",
"form_error_ip4_format": "無效的 IPv4 位址", "form_error_ip4_format": "無效的 IPv4 位址",
"form_error_ip4_range_start_format": "無效起始範圍的 IPv4 位址",
"form_error_ip4_range_end_format": "無效結束範圍的 IPv4 位址",
"form_error_ip4_gateway_format": "無效閘道的 IPv4 位址", "form_error_ip4_gateway_format": "無效閘道的 IPv4 位址",
"form_error_ip6_format": "無效的 IPv6 位址", "form_error_ip6_format": "無效的 IPv6 位址",
"form_error_ip_format": "無效的 IP 位址", "form_error_ip_format": "無效的 IP 位址",
@@ -51,7 +49,6 @@
"out_of_range_error": "必須在\"{{start}}\"-\"{{end}}\"範圍之外", "out_of_range_error": "必須在\"{{start}}\"-\"{{end}}\"範圍之外",
"lower_range_start_error": "必須低於起始範圍", "lower_range_start_error": "必須低於起始範圍",
"greater_range_start_error": "必須大於起始範圍", "greater_range_start_error": "必須大於起始範圍",
"greater_range_end_error": "必須大於結束範圍",
"subnet_error": "位址必須在子網路中", "subnet_error": "位址必須在子網路中",
"gateway_or_subnet_invalid": "無效的子網路遮罩", "gateway_or_subnet_invalid": "無效的子網路遮罩",
"dhcp_form_gateway_input": "閘道 IP", "dhcp_form_gateway_input": "閘道 IP",
@@ -301,6 +298,9 @@
"blocking_mode_nxdomain": "不存在的網域NXDOMAIN以 NXDOMAIN 碼回覆", "blocking_mode_nxdomain": "不存在的網域NXDOMAIN以 NXDOMAIN 碼回覆",
"blocking_mode_null_ip": "無效的 IP以零值 IP 位址0.0.0.0 供 A:: 供 AAAA回覆", "blocking_mode_null_ip": "無效的 IP以零值 IP 位址0.0.0.0 供 A:: 供 AAAA回覆",
"blocking_mode_custom_ip": "自訂的 IP以一組手動地被設定的 IP 位址回覆", "blocking_mode_custom_ip": "自訂的 IP以一組手動地被設定的 IP 位址回覆",
"theme_auto": "自動",
"theme_light": "淺色",
"theme_dark": "深色",
"upstream_dns_client_desc": "如果您將此欄位留空AdGuard Home 將使用在 <0>DNS 設定</0>中被配置的伺服器。", "upstream_dns_client_desc": "如果您將此欄位留空AdGuard Home 將使用在 <0>DNS 設定</0>中被配置的伺服器。",
"tracker_source": "追蹤器來源", "tracker_source": "追蹤器來源",
"source_label": "來源", "source_label": "來源",
@@ -454,6 +454,7 @@
"updates_checked": "AdGuard Home 的新版本為可用的", "updates_checked": "AdGuard Home 的新版本為可用的",
"updates_version_equal": "AdGuard Home 為最新的", "updates_version_equal": "AdGuard Home 為最新的",
"check_updates_now": "立即檢查更新", "check_updates_now": "立即檢查更新",
"version_request_error": "更新檢查已失敗。請檢查您的網際網路連線。",
"dns_privacy": "DNS 隱私", "dns_privacy": "DNS 隱私",
"setup_dns_privacy_1": "<0>DNS-over-TLS</0>使用 <1>{{address}}</1> 字串。", "setup_dns_privacy_1": "<0>DNS-over-TLS</0>使用 <1>{{address}}</1> 字串。",
"setup_dns_privacy_2": "<0>DNS-over-HTTPS</0>使用 <1>{{address}}</1> 字串。", "setup_dns_privacy_2": "<0>DNS-over-HTTPS</0>使用 <1>{{address}}</1> 字串。",
@@ -638,5 +639,8 @@
"safe_browsing": "安全瀏覽", "safe_browsing": "安全瀏覽",
"served_from_cache": "{{value}} <i>(由快取提供)</i>", "served_from_cache": "{{value}} <i>(由快取提供)</i>",
"form_error_password_length": "密碼必須為至少長 {{value}} 個字元", "form_error_password_length": "密碼必須為至少長 {{value}} 個字元",
"anonymizer_notification": "<0>注意:</0>IP 匿名化被啟用。您可在<1>一般設定</1>中禁用它。" "anonymizer_notification": "<0>注意:</0>IP 匿名化被啟用。您可在<1>一般設定</1>中禁用它。",
"confirm_dns_cache_clear": "您確定您想要清除 DNS 快取嗎?",
"cache_cleared": "DNS 快取被成功地清除",
"clear_cache": "清除快取"
} }

View File

@@ -1,4 +1,5 @@
import { createAction } from 'redux-actions'; import { createAction } from 'redux-actions';
import i18next from 'i18next';
import apiClient from '../api/Api'; import apiClient from '../api/Api';
import { splitByNewLine } from '../helpers/helpers'; import { splitByNewLine } from '../helpers/helpers';
@@ -19,6 +20,22 @@ export const getDnsConfig = () => async (dispatch) => {
} }
}; };
export const clearDnsCacheRequest = createAction('CLEAR_DNS_CACHE_REQUEST');
export const clearDnsCacheFailure = createAction('CLEAR_DNS_CACHE_FAILURE');
export const clearDnsCacheSuccess = createAction('CLEAR_DNS_CACHE_SUCCESS');
export const clearDnsCache = () => async (dispatch) => {
dispatch(clearDnsCacheRequest());
try {
const data = await apiClient.clearCache();
dispatch(clearDnsCacheSuccess(data));
dispatch(addSuccessToast(i18next.t('cache_cleared')));
} catch (error) {
dispatch(addErrorToast({ error }));
dispatch(clearDnsCacheFailure());
}
};
export const setDnsConfigRequest = createAction('SET_DNS_CONFIG_REQUEST'); export const setDnsConfigRequest = createAction('SET_DNS_CONFIG_REQUEST');
export const setDnsConfigFailure = createAction('SET_DNS_CONFIG_FAILURE'); export const setDnsConfigFailure = createAction('SET_DNS_CONFIG_FAILURE');
export const setDnsConfigSuccess = createAction('SET_DNS_CONFIG_SUCCESS'); export const setDnsConfigSuccess = createAction('SET_DNS_CONFIG_SUCCESS');

View File

@@ -41,6 +41,12 @@ export const setTlsConfig = (config) => async (dispatch, getState) => {
response.certificate_chain = atob(response.certificate_chain); response.certificate_chain = atob(response.certificate_chain);
response.private_key = atob(response.private_key); response.private_key = atob(response.private_key);
if (values.enabled && values.force_https && window.location.protocol === 'http:') {
window.location.reload();
return;
}
redirectToCurrentProtocol(response, httpPort);
const dnsStatus = await apiClient.getGlobalStatus(); const dnsStatus = await apiClient.getGlobalStatus();
if (dnsStatus) { if (dnsStatus) {
dispatch(dnsStatusSuccess(dnsStatus)); dispatch(dnsStatusSuccess(dnsStatus));
@@ -48,7 +54,6 @@ export const setTlsConfig = (config) => async (dispatch, getState) => {
dispatch(setTlsConfigSuccess(response)); dispatch(setTlsConfigSuccess(response));
dispatch(addSuccessToast('encryption_config_saved')); dispatch(addSuccessToast('encryption_config_saved'));
redirectToCurrentProtocol(response, httpPort);
} catch (error) { } catch (error) {
dispatch(addErrorToast({ error })); dispatch(addErrorToast({ error }));
dispatch(setTlsConfigFailure()); dispatch(setTlsConfigFailure());

View File

@@ -141,7 +141,7 @@ export const getVersion = (recheck = false) => async (dispatch, getState) => {
} }
} }
} catch (error) { } catch (error) {
dispatch(addErrorToast({ error })); dispatch(addErrorToast({ error: 'version_request_error' }));
dispatch(getVersionFailure()); dispatch(getVersionFailure());
} }
}; };
@@ -363,18 +363,18 @@ export const changeLanguage = (lang) => async (dispatch) => {
} }
}; };
export const getLanguageRequest = createAction('GET_LANGUAGE_REQUEST'); export const changeThemeRequest = createAction('CHANGE_THEME_REQUEST');
export const getLanguageFailure = createAction('GET_LANGUAGE_FAILURE'); export const changeThemeFailure = createAction('CHANGE_THEME_FAILURE');
export const getLanguageSuccess = createAction('GET_LANGUAGE_SUCCESS'); export const changeThemeSuccess = createAction('CHANGE_THEME_SUCCESS');
export const getLanguage = () => async (dispatch) => { export const changeTheme = (theme) => async (dispatch) => {
dispatch(getLanguageRequest()); dispatch(changeThemeRequest());
try { try {
const langSettings = await apiClient.getCurrentLanguage(); await apiClient.changeTheme({ theme });
dispatch(getLanguageSuccess(langSettings.language)); dispatch(changeThemeSuccess({ theme }));
} catch (error) { } catch (error) {
dispatch(addErrorToast({ error })); dispatch(addErrorToast({ error }));
dispatch(getLanguageFailure()); dispatch(changeThemeFailure());
} }
}; };

View File

@@ -1,8 +1,12 @@
import axios from 'axios'; import axios from 'axios';
import { getPathWithQueryString } from '../helpers/helpers'; import { getPathWithQueryString } from '../helpers/helpers';
import { QUERY_LOGS_PAGE_LIMIT, HTML_PAGES, R_PATH_LAST_PART } from '../helpers/constants'; import {
QUERY_LOGS_PAGE_LIMIT, HTML_PAGES, R_PATH_LAST_PART, THEMES,
} from '../helpers/constants';
import { BASE_URL } from '../../constants'; import { BASE_URL } from '../../constants';
import i18n from '../i18n';
import { LANGUAGES } from '../helpers/twosky';
class Api { class Api {
baseUrl = BASE_URL; baseUrl = BASE_URL;
@@ -224,21 +228,21 @@ class Api {
} }
// Language // Language
CURRENT_LANGUAGE = { path: 'i18n/current_language', method: 'GET' };
CHANGE_LANGUAGE = { path: 'i18n/change_language', method: 'POST' }; async changeLanguage(config) {
const profile = await this.getProfile();
profile.language = config.language;
getCurrentLanguage() { return this.setProfile(profile);
const { path, method } = this.CURRENT_LANGUAGE;
return this.makeRequest(path, method);
} }
changeLanguage(config) { // Theme
const { path, method } = this.CHANGE_LANGUAGE;
const parameters = { async changeTheme(config) {
data: config, const profile = await this.getProfile();
}; profile.theme = config.theme;
return this.makeRequest(path, method, parameters);
return this.setProfile(profile);
} }
// DHCP // DHCP
@@ -571,11 +575,24 @@ class Api {
// Profile // Profile
GET_PROFILE = { path: 'profile', method: 'GET' }; GET_PROFILE = { path: 'profile', method: 'GET' };
UPDATE_PROFILE = { path: 'profile/update', method: 'PUT' };
getProfile() { getProfile() {
const { path, method } = this.GET_PROFILE; const { path, method } = this.GET_PROFILE;
return this.makeRequest(path, method); return this.makeRequest(path, method);
} }
setProfile(data) {
const theme = data.theme ? data.theme : THEMES.auto;
const defaultLanguage = i18n.language ? i18n.language : LANGUAGES.en;
const language = data.language ? data.language : defaultLanguage;
const { path, method } = this.UPDATE_PROFILE;
const config = { data: { theme, language } };
return this.makeRequest(path, method, config);
}
// DNS config // DNS config
GET_DNS_CONFIG = { path: 'dns_info', method: 'GET' }; GET_DNS_CONFIG = { path: 'dns_info', method: 'GET' };
@@ -593,6 +610,14 @@ class Api {
}; };
return this.makeRequest(path, method, config); return this.makeRequest(path, method, config);
} }
// Cache
CLEAR_CACHE = { path: 'cache_clear', method: 'POST' };
clearCache() {
const { path, method } = this.CLEAR_CACHE;
return this.makeRequest(path, method);
}
} }
const apiClient = new Api(); const apiClient = new Api();

View File

@@ -1,13 +1,66 @@
:root { :root {
--black: #131313;
--bgcolor: #f5f7fb;
--mcolor: #495057;
--scolor: rgba(74, 74, 74, 0.7);
--border-color: rgba(0, 40, 100, 0.12);
--header-bgcolor: #fff;
--card-bgcolor: #fff;
--card-border-color: rgba(0, 40, 100, 0.12);
--ctrl-bgcolor: #fff;
--ctrl-select-bgcolor: rgba(69, 79, 94, 0.12);
--ctrl-dropdown-color: #212529;
--ctrl-dropdown-bgcolor-focus: #f8f9fa;
--ctrl-dropdown-color-focus: #16181b;
--btn-success-bgcolor: #5eba00;
--form-disabled-bgcolor: #f8f9fa;
--form-disabled-color: #495057;
--rt-nodata-bgcolor: rgba(255,255,255,0.8);
--rt-nodata-color: rgba(0,0,0,0.5);
--modal-overlay-bgcolor: rgba(255, 255, 255, 0.75);
--logs__table-bgcolor: #fff;
--logs__row--blue-bgcolor: #e5effd;
--logs__row--white-bgcolor: #fff;
--detailed-info-color: #888888;
--yellow-pale: rgba(247, 181, 0, 0.1); --yellow-pale: rgba(247, 181, 0, 0.1);
--green79: #67b279; --green79: #67b279;
--gray-a5: #a5a5a5; --gray-a5: #a5a5a5;
--gray-d8: #d8d8d8; --gray-d8: #d8d8d8;
--gray-f3: #f3f3f3; --gray-f3: #f3f3f3;
--loading-bg: rgba(255, 255, 255, 0.48);
--font-family-monospace: Monaco, Menlo, "Ubuntu Mono", Consolas, source-code-pro, monospace; --font-family-monospace: Monaco, Menlo, "Ubuntu Mono", Consolas, source-code-pro, monospace;
--font-size-disable-autozoom: 1rem; --font-size-disable-autozoom: 1rem;
} }
[data-theme="dark"] {
--black: #ffffff;
--bgcolor: #131313;
--mcolor: #e6e6e6;
--scolor: #a5a5a5;
--header-bgcolor: #131313;
--border-color: #222;
--card-bgcolor: #1c1c1c;
--card-border-color: #3d3d3d;
--ctrl-bgcolor: #1c1c1c;
--ctrl-select-bgcolor: #3d3d3d;
--ctrl-dropdown-color: #fff;
--ctrl-dropdown-bgcolor-focus: #000;
--ctrl-dropdown-color-focus: #fff;
--btn-success-bgcolor: #67b279;
--form-disabled-bgcolor: #2d2d2d;
--form-disabled-color: #a5a5a5;
--logs__text-color: #f3f3f3;
--rt-nodata-bgcolor: #1c1c1c;
--rt-nodata-color: #fff;
--modal-overlay-bgcolor: rgba(19, 19, 19, 0.75);
--logs__table-bgcolor: #3d3d3d;
--logs__row--blue-bgcolor: #467fcf;
--logs__row--white-bgcolor: #1c1c1c;
--detailed-info-color: #fff;
--gray300: #f3f3f3;
--loading-bg: #131313;
}
body { body {
margin: 0; margin: 0;
padding: 0; padding: 0;

View File

@@ -20,8 +20,13 @@ import EncryptionTopline from '../ui/EncryptionTopline';
import Icons from '../ui/Icons'; import Icons from '../ui/Icons';
import i18n from '../../i18n'; import i18n from '../../i18n';
import Loading from '../ui/Loading'; import Loading from '../ui/Loading';
import { FILTERS_URLS, MENU_URLS, SETTINGS_URLS } from '../../helpers/constants'; import {
import { getLogsUrlParams, setHtmlLangAttr } from '../../helpers/helpers'; FILTERS_URLS,
MENU_URLS,
SETTINGS_URLS,
THEMES,
} from '../../helpers/constants';
import { getLogsUrlParams, setHtmlLangAttr, setUITheme } from '../../helpers/helpers';
import Header from '../Header'; import Header from '../Header';
import { changeLanguage, getDnsStatus } from '../../actions'; import { changeLanguage, getDnsStatus } from '../../actions';
@@ -109,6 +114,7 @@ const App = () => {
isCoreRunning, isCoreRunning,
isUpdateAvailable, isUpdateAvailable,
processing, processing,
theme,
} = useSelector((state) => state.dashboard, shallowEqual); } = useSelector((state) => state.dashboard, shallowEqual);
const { processing: processingEncryption } = useSelector(( const { processing: processingEncryption } = useSelector((
@@ -138,6 +144,41 @@ const App = () => {
setLanguage(); setLanguage();
}, [language]); }, [language]);
const handleAutoTheme = (e, accountTheme) => {
if (accountTheme !== THEMES.auto) {
return;
}
if (e.matches) {
setUITheme(THEMES.dark);
} else {
setUITheme(THEMES.light);
}
};
useEffect(() => {
if (theme !== THEMES.auto) {
setUITheme(theme);
return;
}
const colorSchemeMedia = window.matchMedia('(prefers-color-scheme: dark)');
const prefersDark = colorSchemeMedia.matches;
setUITheme(prefersDark ? THEMES.dark : THEMES.light);
if (colorSchemeMedia.addEventListener !== undefined) {
colorSchemeMedia.addEventListener('change', (e) => {
handleAutoTheme(e, theme);
});
} else {
// Deprecated addListener for older versions of Safari.
colorSchemeMedia.addListener((e) => {
handleAutoTheme(e, theme);
});
}
}, [theme]);
const reloadPage = () => { const reloadPage = () => {
window.location.reload(); window.location.reload();
}; };

View File

@@ -54,7 +54,7 @@
display: flex; display: flex;
align-items: center; align-items: center;
justify-content: space-between; justify-content: space-between;
border-top: 1px solid #dee2e6; border-top: 1px solid var(--card-border-color);
padding: 0.75rem 1.5rem; padding: 0.75rem 1.5rem;
} }

View File

@@ -1,12 +1,12 @@
.nav-tabs .nav-link.active { .nav-tabs .nav-link.active {
border-color: var(--green-74); border-color: var(--btn-success-bgcolor);
color: var(--green-74); color: var(--btn-success-bgcolor);
background: transparent; background: transparent;
} }
.nav-tabs .nav-link.active:hover { .nav-tabs .nav-link.active:hover {
border-color: #58a273; border-color: #4b9400;
color: #58a273; color: #4b9400;
} }
.nav-icon { .nav-icon {
@@ -47,7 +47,7 @@
width: 250px; width: 250px;
height: 100vh; height: 100vh;
transition: transform 0.3s ease; transition: transform 0.3s ease;
background-color: #fff; background-color: var(--header-bgcolor);
overflow-y: auto; overflow-y: auto;
} }

View File

@@ -4,7 +4,8 @@
box-shadow: 2px 4px 8px rgba(0, 0, 0, 0.2); box-shadow: 2px 4px 8px rgba(0, 0, 0, 0.2);
border-radius: 4px !important; border-radius: 4px !important;
pointer-events: auto !important; pointer-events: auto !important;
background-color: var(--white); background-color: var(--ctrl-bgcolor);
color: var(--mcolor);
z-index: 102; z-index: 102;
overflow-y: auto; overflow-y: auto;
max-height: 100%; max-height: 100%;

View File

@@ -155,7 +155,7 @@ const Form = (props) => {
name={FORM_NAMES.search} name={FORM_NAMES.search}
component={renderFilterField} component={renderFilterField}
type="text" type="text"
className={classNames('form-control--search form-control--transparent', className)} className={classNames('form-control form-control--search form-control--transparent', className)}
placeholder={t('domain_or_client')} placeholder={t('domain_or_client')}
tooltip={t('query_log_strict_search')} tooltip={t('query_log_strict_search')}
onClearInputClick={onInputClear} onClearInputClick={onInputClear}

View File

@@ -24,6 +24,12 @@
--option-border-radius: 4px; --option-border-radius: 4px;
} }
[data-theme="dark"] {
--red: rgba(223, 56, 18, 0.25);
--green-pale: rgba(103, 178, 121, 0.25);
--yellow: rgba(247, 181, 0, 0.2);
}
.logs__text { .logs__text {
padding: 0 1px; padding: 0 1px;
text-overflow: ellipsis; text-overflow: ellipsis;
@@ -31,11 +37,19 @@
overflow: hidden; overflow: hidden;
font-size: 1rem; font-size: 1rem;
font-family: var(--font-family-sans-serif); font-family: var(--font-family-sans-serif);
color: var(--gray-4d); color: var(--logs__text-color);
letter-spacing: 0; letter-spacing: 0;
line-height: 1.5rem; line-height: 1.5rem;
} }
[data-theme="dark"] .logs__text a {
color: var(--gray-f3);
}
[data-theme="dark"] .logs__text a:hover {
color: var(--gray-f3);
}
.logs__text--bold { .logs__text--bold {
font-weight: 600; font-weight: 600;
} }
@@ -48,7 +62,7 @@
.detailed-info { .detailed-info {
font-size: 0.8rem; font-size: 0.8rem;
line-height: 1.4; line-height: 1.4;
color: #888888; color: var(--detailed-info-color);
} }
.logs__text--link { .logs__text--link {
@@ -66,6 +80,10 @@
border-radius: 4px; border-radius: 4px;
} }
[data-theme=dark] .icon--selected {
opacity: 0.75;
}
.text-pre { .text-pre {
white-space: pre-wrap !important; white-space: pre-wrap !important;
overflow-wrap: break-word; overflow-wrap: break-word;
@@ -103,14 +121,12 @@
} }
.form-control--search { .form-control--search {
box-shadow: 0 1px 0 #ddd;
padding: 0 2.5rem; padding: 0 2.5rem;
height: 2.25rem; height: 2.25rem;
flex-grow: 1; flex-grow: 1;
} }
.form-control--transparent { .form-control--transparent {
border: 0 solid transparent !important;
background-color: transparent !important; background-color: transparent !important;
} }
@@ -174,10 +190,8 @@
display: inline-flex; display: inline-flex;
align-items: center; align-items: center;
justify-content: center; justify-content: center;
width: 2.5rem;
--size: 2.5rem; height: 2.5rem;
width: var(--size);
height: var(--size);
padding: 0; padding: 0;
margin-left: 0.9375rem; margin-left: 0.9375rem;
background-color: transparent; background-color: transparent;
@@ -209,6 +223,12 @@
position: relative; position: relative;
} }
@media screen and (min-width: 1025px) {
.logs__cell--client {
width: 13rem;
}
}
.logs__cell--header__container > .logs__cell--header__item { .logs__cell--header__container > .logs__cell--header__item {
border-right: 0; border-right: 0;
font-size: 1rem; font-size: 1rem;
@@ -344,6 +364,10 @@
overflow: hidden; overflow: hidden;
} }
[data-theme="dark"] .tooltip-custom__container .button-action--arrow-option:not(:disabled):hover {
background: var(--ctrl-dropdown-bgcolor-focus);
}
.button-action--arrow-option-container { .button-action--arrow-option-container {
overflow: visible; overflow: visible;
transform-origin: left; transform-origin: left;
@@ -373,7 +397,7 @@
/* QUERY_STATUS_COLORS */ /* QUERY_STATUS_COLORS */
.logs__row--blue { .logs__row--blue {
background-color: var(--blue); background-color: var(--logs__row--blue-bgcolor);
} }
.logs__row--green { .logs__row--green {
@@ -385,7 +409,7 @@
} }
.logs__row--white { .logs__row--white {
background-color: var(--white); background-color: var(--logs__row--white-bgcolor);
} }
.logs__row--yellow { .logs__row--yellow {
@@ -393,8 +417,8 @@
} }
.logs__no-data { .logs__no-data {
color: var(--gray-4d); color: var(--mcolor);
background-color: var(--white80); background-color: var(--logs__table-bgcolor);
pointer-events: none; pointer-events: none;
font-weight: 600; font-weight: 600;
text-align: center; text-align: center;
@@ -407,7 +431,7 @@
} }
.logs__table { .logs__table {
background-color: var(--white); background-color: var(--logs__table-bgcolor);
border: 0; border: 0;
border-radius: 8px; border-radius: 8px;
min-height: 43rem; min-height: 43rem;
@@ -474,7 +498,7 @@
.filteringRules__filter { .filteringRules__filter {
font-style: italic; font-style: italic;
font-weight: normal; font-weight: 400;
margin-bottom: 1rem; margin-bottom: 1rem;
} }
@@ -486,6 +510,10 @@
color: var(--green79); color: var(--green79);
} }
[data-theme="dark"] .logs__question.icon--lightgray {
color: var(--gray-f3);
}
@media (max-width: 1024px) { @media (max-width: 1024px) {
.logs__question { .logs__question {
display: none; display: none;
@@ -495,3 +523,8 @@
.logs__modal { .logs__modal {
max-width: 720px; max-width: 720px;
} }
.logs__modal-wrap {
padding: 1rem 1.5rem;
background-color: var(--card-bgcolor);
}

View File

@@ -195,11 +195,11 @@ const Logs = () => {
onRequestClose={closeModal} onRequestClose={closeModal}
style={{ style={{
content: { content: {
width: '100%', width: 'calc(100% - 32px)',
height: 'fit-content', height: 'fit-content',
left: '50%', left: '50%',
top: 47, top: 47,
padding: '1rem 1.5rem 1rem', padding: '0',
maxWidth: '720px', maxWidth: '720px',
transform: 'translateX(-50%)', transform: 'translateX(-50%)',
}, },

View File

@@ -11,12 +11,13 @@ import Select from 'react-select';
import i18n from '../../../i18n'; import i18n from '../../../i18n';
import Tabs from '../../ui/Tabs'; import Tabs from '../../ui/Tabs';
import Examples from '../Dns/Upstream/Examples'; import Examples from '../Dns/Upstream/Examples';
import { toggleAllServices } from '../../../helpers/helpers'; import { toggleAllServices, trimLinesAndRemoveEmpty } from '../../../helpers/helpers';
import { import {
renderInputField, renderInputField,
renderGroupField, renderGroupField,
CheckboxField, CheckboxField,
renderServiceField, renderServiceField,
renderTextareaField,
} from '../../../helpers/form'; } from '../../../helpers/form';
import { validateClientId, validateRequiredValue } from '../../../helpers/validators'; import { validateClientId, validateRequiredValue } from '../../../helpers/validators';
import { CLIENT_ID_LINK, FORM_NAME } from '../../../helpers/constants'; import { CLIENT_ID_LINK, FORM_NAME } from '../../../helpers/constants';
@@ -230,10 +231,11 @@ let Form = (props) => {
<Field <Field
id="upstreams" id="upstreams"
name="upstreams" name="upstreams"
component="textarea" component={renderTextareaField}
type="text" type="text"
className="form-control form-control--textarea mb-5" className="form-control form-control--textarea mb-5"
placeholder={t('upstream_dns')} placeholder={t('upstream_dns')}
normalizeOnBlur={trimLinesAndRemoveEmpty}
/> />
<Examples /> <Examples />
</div>, </div>,

View File

@@ -4,7 +4,7 @@
align-items: center; align-items: center;
margin-bottom: 15px; margin-bottom: 15px;
padding: 10px 15px; padding: 10px 15px;
border: 1px solid #eee; border: 1px solid var(--card-border-color);
border-radius: 4px; border-radius: 4px;
cursor: pointer; cursor: pointer;
} }

View File

@@ -74,7 +74,6 @@ const FormDHCPv4 = ({
className="form-control" className="form-control"
placeholder={t(ipv4placeholders.subnet_mask)} placeholder={t(ipv4placeholders.subnet_mask)}
validate={[ validate={[
validateIpv4,
validateRequired, validateRequired,
validateGatewaySubnetMask, validateGatewaySubnetMask,
]} ]}
@@ -97,7 +96,6 @@ const FormDHCPv4 = ({
placeholder={t(ipv4placeholders.range_start)} placeholder={t(ipv4placeholders.range_start)}
validate={[ validate={[
validateIpv4, validateIpv4,
validateGatewaySubnetMask,
validateIpForGatewaySubnetMask, validateIpForGatewaySubnetMask,
]} ]}
disabled={!isInterfaceIncludesIpv4} disabled={!isInterfaceIncludesIpv4}
@@ -113,7 +111,6 @@ const FormDHCPv4 = ({
validate={[ validate={[
validateIpv4, validateIpv4,
validateIpv4RangeEnd, validateIpv4RangeEnd,
validateGatewaySubnetMask,
validateIpForGatewaySubnetMask, validateIpForGatewaySubnetMask,
]} ]}
disabled={!isInterfaceIncludesIpv4} disabled={!isInterfaceIncludesIpv4}

View File

@@ -2,10 +2,12 @@ import React from 'react';
import PropTypes from 'prop-types'; import PropTypes from 'prop-types';
import { Field, reduxForm } from 'redux-form'; import { Field, reduxForm } from 'redux-form';
import { Trans, useTranslation } from 'react-i18next'; import { Trans, useTranslation } from 'react-i18next';
import { shallowEqual, useSelector } from 'react-redux'; import { shallowEqual, useDispatch, useSelector } from 'react-redux';
import { renderInputField, toNumber, CheckboxField } from '../../../../helpers/form'; import { renderInputField, toNumber, CheckboxField } from '../../../../helpers/form';
import { CACHE_CONFIG_FIELDS, FORM_NAME, UINT32_RANGE } from '../../../../helpers/constants'; import { CACHE_CONFIG_FIELDS, FORM_NAME, UINT32_RANGE } from '../../../../helpers/constants';
import { replaceZeroWithEmptyString } from '../../../../helpers/helpers'; import { replaceZeroWithEmptyString } from '../../../../helpers/helpers';
import { clearDnsCache } from '../../../../actions/dnsConfig';
const INPUTS_FIELDS = [ const INPUTS_FIELDS = [
{ {
@@ -32,6 +34,7 @@ const Form = ({
handleSubmit, submitting, invalid, handleSubmit, submitting, invalid,
}) => { }) => {
const { t } = useTranslation(); const { t } = useTranslation();
const dispatch = useDispatch();
const { processingSetConfig } = useSelector((state) => state.dnsConfig, shallowEqual); const { processingSetConfig } = useSelector((state) => state.dnsConfig, shallowEqual);
const { const {
@@ -40,6 +43,12 @@ const Form = ({
const minExceedsMax = cache_ttl_min > cache_ttl_max; const minExceedsMax = cache_ttl_min > cache_ttl_max;
const handleClearCache = () => {
if (window.confirm(t('confirm_dns_cache_clear'))) {
dispatch(clearDnsCache());
}
};
return <form onSubmit={handleSubmit}> return <form onSubmit={handleSubmit}>
<div className="row"> <div className="row">
{INPUTS_FIELDS.map(({ {INPUTS_FIELDS.map(({
@@ -97,6 +106,13 @@ const Form = ({
> >
<Trans>save_btn</Trans> <Trans>save_btn</Trans>
</button> </button>
<button
type="button"
className="btn btn-outline-secondary btn-standard form__button"
onClick={handleClearCache}
>
<Trans>clear_cache</Trans>
</button>
</form>; </form>;
}; };

View File

@@ -77,7 +77,7 @@
.form__desc { .form__desc {
margin-top: 10px; margin-top: 10px;
font-size: 13px; font-size: 13px;
color: rgba(74, 74, 74, 0.7); color: var(--scolor);
} }
.form__desc--top { .form__desc--top {

View File

@@ -107,5 +107,5 @@
.checkbox__label-subtitle { .checkbox__label-subtitle {
display: block; display: block;
line-height: 1.5; line-height: 1.5;
color: rgba(74, 74, 74, 0.7); color: var(--scolor);
} }

View File

@@ -1,6 +1,6 @@
.dropdown-item.active, .dropdown-item.active,
.dropdown-item:active { .dropdown-item:active {
background-color: var(--green-74); background-color: var(--btn-success-bgcolor);
} }
.dropdown-menu { .dropdown-menu {

View File

@@ -18,6 +18,11 @@
align-items: center; align-items: center;
} }
.footer__column--theme {
min-width: 220px;
margin-bottom: 0;
}
.footer__column--language { .footer__column--language {
min-width: 220px; min-width: 220px;
margin-bottom: 0; margin-bottom: 0;
@@ -49,6 +54,11 @@
} }
.footer__column--language { .footer__column--language {
min-width: initial;
margin-left: 20px;
}
.footer__column--theme {
min-width: initial; min-width: initial;
margin-left: auto; margin-left: auto;
} }

View File

@@ -1,15 +1,17 @@
import React from 'react'; import React, { useState, useEffect } from 'react';
import { useTranslation } from 'react-i18next'; import { useTranslation } from 'react-i18next';
import { useDispatch, useSelector } from 'react-redux';
import classNames from 'classnames'; import classNames from 'classnames';
import { REPOSITORY, PRIVACY_POLICY_LINK } from '../../helpers/constants'; import { REPOSITORY, PRIVACY_POLICY_LINK, THEMES } from '../../helpers/constants';
import { LANGUAGES } from '../../helpers/twosky'; import { LANGUAGES } from '../../helpers/twosky';
import i18n from '../../i18n'; import i18n from '../../i18n';
import Version from './Version'; import Version from './Version';
import './Footer.css'; import './Footer.css';
import './Select.css'; import './Select.css';
import { setHtmlLangAttr } from '../../helpers/helpers'; import { setHtmlLangAttr, setUITheme } from '../../helpers/helpers';
import { changeTheme } from '../../actions';
const linksData = [ const linksData = [
{ {
@@ -29,6 +31,18 @@ const linksData = [
const Footer = () => { const Footer = () => {
const { t } = useTranslation(); const { t } = useTranslation();
const dispatch = useDispatch();
const currentTheme = useSelector((state) => (state.dashboard ? state.dashboard.theme : 'auto'));
const profileName = useSelector((state) => (state.dashboard ? state.dashboard.name : ''));
const isLoggedIn = profileName !== '';
const [currentThemeLocal, setCurrentThemeLocal] = useState('auto');
useEffect(() => {
if (!isLoggedIn) {
setUITheme(window.matchMedia('(prefers-color-scheme: dark)').matches ? THEMES.dark : THEMES.light);
}
}, []);
const getYear = () => { const getYear = () => {
const today = new Date(); const today = new Date();
@@ -41,6 +55,17 @@ const Footer = () => {
setHtmlLangAttr(value); setHtmlLangAttr(value);
}; };
const onThemeChanged = (event) => {
const { value } = event.target;
dispatch(changeTheme(value));
};
const onThemeChangedLocal = (event) => {
const { value } = event.target;
setUITheme(value);
setCurrentThemeLocal(value);
};
const renderCopyright = () => <div className="footer__column"> const renderCopyright = () => <div className="footer__column">
<div className="footer__copyright"> <div className="footer__copyright">
{t('copyright')} &copy; {getYear()}{' '} {t('copyright')} &copy; {getYear()}{' '}
@@ -58,6 +83,35 @@ const Footer = () => {
{t(name)} {t(name)}
</a>); </a>);
const themeSelectOptions = () => (
Object.values(THEMES)
.map((theme) => (
<option key={theme} value={theme}>
{t(`theme_${theme}`)}
</option>
))
);
const renderThemeSelect = () => (
<select
className="form-control select select--theme"
value={currentTheme}
onChange={onThemeChanged}
>
{themeSelectOptions()}
</select>
);
const renderThemeSelectLocal = () => (
<select
className="form-control select select--theme"
value={currentThemeLocal}
onChange={onThemeChangedLocal}
>
{themeSelectOptions()}
</select>
);
return ( return (
<> <>
<footer className="footer"> <footer className="footer">
@@ -66,6 +120,9 @@ const Footer = () => {
<div className="footer__column footer__column--links"> <div className="footer__column footer__column--links">
{renderLinks(linksData)} {renderLinks(linksData)}
</div> </div>
<div className="footer__column footer__column--theme">
{isLoggedIn ? renderThemeSelect() : renderThemeSelectLocal()}
</div>
<div className="footer__column footer__column--language"> <div className="footer__column footer__column--language">
<select <select
className="form-control select select--language" className="form-control select select--language"

View File

@@ -11,6 +11,10 @@
font-size: 0.7rem; font-size: 0.7rem;
} }
.card-chart-bg {
color: var(--black);
}
.card-chart-bg path[d^="M0,32"] { .card-chart-bg path[d^="M0,32"] {
transform: translateY(32px); transform: translateY(32px);
} }

View File

@@ -25,9 +25,9 @@ const Line = ({
theme={{ theme={{
crosshair: { crosshair: {
line: { line: {
stroke: 'black', stroke: 'currentColor',
strokeWidth: 1, strokeWidth: 1,
strokeOpacity: 0.35, strokeOpacity: 0.5,
}, },
}, },
}} }}

View File

@@ -13,7 +13,7 @@
z-index: 100; z-index: 100;
width: 100%; width: 100%;
min-height: 100vh; min-height: 100vh;
background-color: rgba(255, 255, 255, 0.48); background-color: var(--loading-bg);
} }
.loading:after { .loading:after {

View File

@@ -11,6 +11,7 @@
.ReactModal__Overlay--after-open { .ReactModal__Overlay--after-open {
opacity: 1; opacity: 1;
transition: opacity 150ms ease-out; transition: opacity 150ms ease-out;
background-color: var(--modal-overlay-bgcolor) !important;
} }
.ReactModal__Content { .ReactModal__Content {

View File

@@ -13,6 +13,41 @@
overflow: visible; overflow: visible;
} }
.ReactTable .rt-noData {
color: var(--rt-nodata-color);
background-color: var(--rt-nodata-bgcolor);
}
.ReactTable .-loading {
color: var(--rt-nodata-color);
background-color: var(--rt-nodata-bgcolor);
}
.ReactTable .-loading .-loading-inner {
color: var(--gray300);
}
.ReactTable .-pagination input, .ReactTable .-pagination select {
color: var(--rt-nodata-color);
background-color: var(--rt-nodata-bgcolor);
}
[data-theme=dark] .ReactTable .rt-table::-webkit-scrollbar-track {
background-color: var(--card-bgcolor);
}
[data-theme=dark] .ReactTable .rt-table::-webkit-scrollbar-thumb {
background-color: #888888;
}
[data-theme=dark] .ReactTable .-pagination .-btn {
filter: invert(1);
}
[data-theme=dark] .ReactTable .-pagination .-btn:disabled {
opacity: 1;
}
.rt-tr-group.logs__row--red { .rt-tr-group.logs__row--red {
background-color: rgba(223, 56, 18, 0.05); background-color: rgba(223, 56, 18, 0.05);
} }

View File

@@ -1,8 +1,25 @@
.select.select--theme {
height: 45px;
padding: 0 32px 2px 11px;
outline: 0;
border-color: var(--ctrl-select-bgcolor);
background-image: url("./svg/chevron-down.svg");
background-repeat: no-repeat;
background-position: right 9px center;
background-size: 17px 20px;
appearance: none;
cursor: pointer;
}
.select--theme::-ms-expand {
opacity: 0;
}
.select.select--language { .select.select--language {
height: 45px; height: 45px;
padding: 0 32px 2px 33px; padding: 0 32px 2px 33px;
outline: 0; outline: 0;
border-color: rgba(69, 79, 94, 0.12); border-color: var(--ctrl-select-bgcolor);
background-image: url("./svg/globe.svg"), url("./svg/chevron-down.svg"); background-image: url("./svg/globe.svg"), url("./svg/chevron-down.svg");
background-repeat: no-repeat, no-repeat; background-repeat: no-repeat, no-repeat;
background-position: left 11px center, right 9px center; background-position: left 11px center, right 9px center;
@@ -16,8 +33,9 @@
} }
.basic-multi-select .select__control { .basic-multi-select .select__control {
border: 1px solid rgba(0, 40, 100, 0.12); border: 1px solid var(--card-border-color);;
border-radius: 3px; border-radius: 3px;
background-color: var(--ctrl-bgcolor);
} }
.basic-multi-select .select__control:hover { .basic-multi-select .select__control:hover {
@@ -36,4 +54,16 @@
.basic-multi-select .select__menu { .basic-multi-select .select__menu {
z-index: 3; z-index: 3;
background-color: var(--ctrl-bgcolor);
}
[data-theme=dark] .basic-multi-select .select__option:hover,
[data-theme=dark] .basic-multi-select .select__option--is-focused,
[data-theme=dark] .basic-multi-select .select__option--is-focused:hover {
background-color: var(--ctrl-select-bgcolor);
color: var(--ctrl-dropdown-color);
}
[data-theme=dark] .select__multi-value__remove svg {
filter: invert(1);
} }

View File

@@ -85,9 +85,9 @@ body {
font-size: 0.9375rem; font-size: 0.9375rem;
font-weight: 400; font-weight: 400;
line-height: 1.5; line-height: 1.5;
color: #495057; color: var(--mcolor);
text-align: left; text-align: left;
background-color: #f5f7fb; background-color: var(--bgcolor);
} }
[tabindex="-1"]:focus { [tabindex="-1"]:focus {
@@ -1943,10 +1943,10 @@ pre code {
padding: 0.375rem 0.75rem; padding: 0.375rem 0.75rem;
font-size: 0.9375rem; font-size: 0.9375rem;
line-height: 1.6; line-height: 1.6;
color: #495057; color: var(--mcolor);
background-color: #fff; background-color: var(--card-bgcolor);
background-clip: padding-box; background-clip: padding-box;
border: 1px solid rgba(0, 40, 100, 0.12); border: 1px solid var(--card-border-color);
border-radius: 3px; border-radius: 3px;
transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out; transition: border-color 0.15s ease-in-out, box-shadow 0.15s ease-in-out;
} }
@@ -1957,8 +1957,8 @@ pre code {
} }
.form-control:focus { .form-control:focus {
color: #495057; color: var(--mcolor);
background-color: #fff; background-color: var(--ctrl-bgcolor);
border-color: #1991eb; border-color: #1991eb;
outline: 0; outline: 0;
box-shadow: 0 0 0 2px rgba(70, 127, 207, 0.25); box-shadow: 0 0 0 2px rgba(70, 127, 207, 0.25);
@@ -1991,7 +1991,8 @@ pre code {
.form-control:disabled, .form-control:disabled,
.form-control[readonly] { .form-control[readonly] {
background-color: #f8f9fa; background-color: var(--form-disabled-bgcolor);
color: var(--form-disabled-color);
opacity: 1; opacity: 1;
} }
@@ -2578,16 +2579,58 @@ fieldset:disabled a.btn {
box-shadow: 0 0 0 2px rgba(134, 142, 150, 0.5); box-shadow: 0 0 0 2px rgba(134, 142, 150, 0.5);
} }
[data-theme=dark] .btn-secondary {
color: #868e96;
background-color: transparent;
background-image: none;
border-color: #868e96;
}
[data-theme=dark] .btn-secondary:hover {
color: #fff;
background-color: #868e96;
border-color: #868e96;
}
[data-theme=dark] .btn-secondary:focus,
[data-theme=dark] .btn-secondary.focus {
box-shadow: none;
}
[data-theme=dark] .btn-secondary:focus-visible,
[data-theme=dark] .btn-secondary.focus {
box-shadow: 0 0 0 2px rgba(134, 142, 150, 0.5);
}
[data-theme=dark] .btn-secondary.disabled,
[data-theme=dark] .btn-secondary:disabled {
color: #868e96;
background-color: transparent;
border: none;
}
[data-theme=dark] .btn-secondary:not(:disabled):not(.disabled):active,
[data-theme=dark] .btn-secondary:not(:disabled):not(.disabled).active {
color: #fff;
background-color: #868e96;
border-color: #868e96;
}
[data-theme=dark] .btn-secondary:not(:disabled):not(.disabled):active:focus,
[data-theme=dark] .btn-secondary:not(:disabled):not(.disabled).active:focus {
box-shadow: 0 0 0 2px rgba(134, 142, 150, 0.5);
}
.btn-success { .btn-success {
color: #fff; color: #fff;
background-color: #5eba00; background-color: var(--btn-success-bgcolor);
border-color: #5eba00; border-color: var(--btn-success-bgcolor);
} }
.btn-success:hover { .btn-success:hover {
color: #fff; color: #fff;
background-color: #4b9400; background-color: #4b9400;
border-color: #448700; border-color: #4b9400;
} }
.btn-success:focus, .btn-success:focus,
@@ -2607,7 +2650,7 @@ fieldset:disabled a.btn {
.show>.btn-success.dropdown-toggle { .show>.btn-success.dropdown-toggle {
color: #fff; color: #fff;
background-color: #448700; background-color: #448700;
border-color: #3e7a00; border-color: #448700;
} }
.btn-success:not(:disabled):not(.disabled):active:focus, .btn-success:not(:disabled):not(.disabled):active:focus,
@@ -3244,12 +3287,16 @@ tbody.collapse.show {
color: #495057; color: #495057;
text-align: left; text-align: left;
list-style: none; list-style: none;
background-color: #fff; background-color: var(--ctrl-bgcolor);
background-clip: padding-box; background-clip: padding-box;
border: 1px solid rgba(0, 40, 100, 0.12); border: 1px solid rgba(0, 40, 100, 0.12);
border-radius: 3px; border-radius: 3px;
} }
[data-theme=dark] .dropdown-menu {
border: 1px solid var(--card-border-color);
}
.dropup .dropdown-menu { .dropup .dropdown-menu {
margin-top: 0; margin-top: 0;
margin-bottom: 0.125rem; margin-bottom: 0.125rem;
@@ -3348,7 +3395,7 @@ tbody.collapse.show {
padding: 0.25rem 1.5rem; padding: 0.25rem 1.5rem;
clear: both; clear: both;
font-weight: 400; font-weight: 400;
color: #212529; color: var(--ctrl-dropdown-color);
text-align: inherit; text-align: inherit;
white-space: nowrap; white-space: nowrap;
background-color: transparent; background-color: transparent;
@@ -3357,9 +3404,9 @@ tbody.collapse.show {
.dropdown-item:hover, .dropdown-item:hover,
.dropdown-item:focus { .dropdown-item:focus {
color: #16181b; color: var(--ctrl-dropdown-color-focus);
text-decoration: none; text-decoration: none;
background-color: #f8f9fa; background-color: var(--ctrl-dropdown-bgcolor-focus);
} }
.dropdown-item.active, .dropdown-item.active,
@@ -3794,11 +3841,11 @@ tbody.collapse.show {
height: 2.375rem; height: 2.375rem;
padding: 0.5rem 1.75rem 0.5rem 0.75rem; padding: 0.5rem 1.75rem 0.5rem 0.75rem;
line-height: 1.5; line-height: 1.5;
color: #495057; color: var(--mcolor);
vertical-align: middle; vertical-align: middle;
background: #fff url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZpZXdCb3g9JzAgMCAxMCA1Jz48cGF0aCBmaWxsPScjOTk5JyBkPSdNMCAwTDEwIDBMNSA1TDAgMCcvPjwvc3ZnPg==") no-repeat right 0.75rem center; background: var(--card-bgcolor) url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnIHZpZXdCb3g9JzAgMCAxMCA1Jz48cGF0aCBmaWxsPScjOTk5JyBkPSdNMCAwTDEwIDBMNSA1TDAgMCcvPjwvc3ZnPg==") no-repeat right 0.75rem center;
background-size: 8px 10px; background-size: 8px 10px;
border: 1px solid rgba(0, 40, 100, 0.12); border: 1px solid var(--card-border-color);
border-radius: 3px; border-radius: 3px;
-webkit-appearance: none; -webkit-appearance: none;
-moz-appearance: none; -moz-appearance: none;
@@ -4469,9 +4516,9 @@ tbody.collapse.show {
flex-direction: column; flex-direction: column;
min-width: 0; min-width: 0;
word-wrap: break-word; word-wrap: break-word;
background-color: #fff; background-color: var(--card-bgcolor);
background-clip: border-box; background-clip: border-box;
border: 1px solid rgba(0, 40, 100, 0.12); border: 1px solid var(--card-border-color);
border-radius: 3px; border-radius: 3px;
} }
@@ -5475,9 +5522,9 @@ button.close {
flex-direction: column; flex-direction: column;
width: 100%; width: 100%;
pointer-events: auto; pointer-events: auto;
background-color: #fff; background-color: var(--card-bgcolor);
background-clip: padding-box; background-clip: padding-box;
border: 1px solid rgba(0, 0, 0, 0.2); border: 1px solid var(--card-border-color);
border-radius: 3px; border-radius: 3px;
outline: 0; outline: 0;
} }
@@ -5508,7 +5555,7 @@ button.close {
-ms-flex-pack: justify; -ms-flex-pack: justify;
justify-content: space-between; justify-content: space-between;
padding: 1rem; padding: 1rem;
border-bottom: 1px solid #e9ecef; border-bottom: 1px solid var(--card-border-color);
border-top-left-radius: 3px; border-top-left-radius: 3px;
border-top-right-radius: 3px; border-top-right-radius: 3px;
} }
@@ -5538,7 +5585,7 @@ button.close {
-ms-flex-pack: end; -ms-flex-pack: end;
justify-content: flex-end; justify-content: flex-end;
padding: 1rem; padding: 1rem;
border-top: 1px solid #e9ecef; border-top: 1px solid var(--card-border-color);
} }
.modal-footer> :not(:first-child) { .modal-footer> :not(:first-child) {
@@ -10268,8 +10315,8 @@ body.fixed-header .page {
.header { .header {
padding-top: 0.75rem; padding-top: 0.75rem;
padding-bottom: 0.75rem; padding-bottom: 0.75rem;
background: #fff; background: var(--header-bgcolor);
border-bottom: 1px solid rgba(0, 40, 100, 0.12); border-bottom: 1px solid var(--border-color);
} }
body.fixed-header .header { body.fixed-header .header {
@@ -10325,6 +10372,10 @@ body.fixed-header .header {
width: auto; width: auto;
} }
[data-theme=dark] .header-brand-img {
filter:invert(1);
}
.header-avatar { .header-avatar {
width: 2rem; width: 2rem;
height: 2rem; height: 2rem;
@@ -10382,8 +10433,8 @@ body.fixed-header .header {
} }
.footer { .footer {
background: #fff; background: var(--card-bgcolor);
border-top: 1px solid rgba(0, 40, 100, 0.12); border-top: 1px solid var(--card-border-color);
font-size: 0.875rem; font-size: 0.875rem;
padding: 1.25rem 0; padding: 1.25rem 0;
color: #9aa0ac; color: #9aa0ac;
@@ -13674,6 +13725,10 @@ Card alert
color: #6e7687; color: #6e7687;
} }
[data-theme=dark] .dropdown-item {
color: #ffffff;
}
.dropdown-menu-arrow:before { .dropdown-menu-arrow:before {
position: absolute; position: absolute;
top: -6px; top: -6px;
@@ -13686,17 +13741,25 @@ Card alert
content: ""; content: "";
} }
[data-theme=dark] .dropdown-menu-arrow:before {
border-bottom-color: var(--ctrl-bgcolor);
}
.dropdown-menu-arrow:after { .dropdown-menu-arrow:after {
position: absolute; position: absolute;
top: -5px; top: -5px;
left: 12px; left: 12px;
display: inline-block; display: inline-block;
border-right: 5px solid transparent; border-right: 5px solid transparent;
border-bottom: 5px solid #fff; border-bottom: 5px solid var(--ctrl-bgcolor);
border-left: 5px solid transparent; border-left: 5px solid transparent;
content: ""; content: "";
} }
[data-theme=dark] .dropdown-menu-arrow:after {
border-bottom: 5px solid var(--card-border-color);
}
.dropdown-menu-arrow.dropdown-menu-right:before, .dropdown-menu-arrow.dropdown-menu-right:before,
.dropdown-menu-arrow.dropdown-menu-right:after { .dropdown-menu-arrow.dropdown-menu-right:after {
left: auto; left: auto;
@@ -15464,6 +15527,10 @@ a.tag-addon:hover {
transition: 0.3s border-color, 0.3s background-color; transition: 0.3s border-color, 0.3s background-color;
} }
[data-theme=dark] .custom-switch-indicator {
opacity: 0.75;
}
.custom-switch-indicator:before { .custom-switch-indicator:before {
content: ""; content: "";
position: absolute; position: absolute;

View File

@@ -3,7 +3,7 @@
justify-content: space-between; justify-content: space-between;
margin-bottom: 15px; margin-bottom: 15px;
padding: 10px 0; padding: 10px 0;
border-bottom: 1px solid #e8e8e8; border-bottom: 1px solid var(--card-border-color);
overflow: auto; overflow: auto;
} }
@@ -40,6 +40,10 @@
opacity: 0.6; opacity: 0.6;
} }
[data-theme=dark] .tab__control {
filter: invert(1);
}
@media screen and (min-width: 768px) { @media screen and (min-width: 768px) {
.tab__control { .tab__control {
white-space: normal; white-space: normal;

View File

@@ -4,6 +4,11 @@
box-shadow: 1px 1px 6px rgba(0, 0, 0, 0.2); box-shadow: 1px 1px 6px rgba(0, 0, 0, 0.2);
} }
[data-theme=dark] .tooltip-container {
background-color: var(--ctrl-select-bgcolor);
color: var(--mcolor);
}
.tooltip-custom--narrow { .tooltip-custom--narrow {
max-width: 14rem; max-width: 14rem;
} }

View File

@@ -227,6 +227,14 @@ export const BLOCKING_MODES = {
custom_ip: 'custom_ip', custom_ip: 'custom_ip',
}; };
// Note that translation strings contain these modes (theme_CONSTANT)
// i.e. theme_auto, theme_light.
export const THEMES = {
auto: 'auto',
dark: 'dark',
light: 'light',
};
export const WHOIS_ICONS = { export const WHOIS_ICONS = {
location: 'location', location: 'location',
orgname: 'network', orgname: 'network',

View File

@@ -26,199 +26,229 @@ export default {
"name": "1Hosts (Lite)", "name": "1Hosts (Lite)",
"categoryId": "general", "categoryId": "general",
"homepage": "https://badmojr.github.io/1Hosts/", "homepage": "https://badmojr.github.io/1Hosts/",
"source": "https://badmojr.gitlab.io/1hosts/Lite/adblock.txt" "source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_24.txt"
},
"1hosts_mini": {
"name": "1Hosts (mini)",
"categoryId": "general",
"homepage": "https://badmojr.github.io/1Hosts/",
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_38.txt"
}, },
"CHN_adrules": { "CHN_adrules": {
"name": "CHN: AdRules DNS List", "name": "CHN: AdRules DNS List",
"categoryId": "regional", "categoryId": "regional",
"homepage": "https://github.com/Cats-Team/AdRules", "homepage": "https://github.com/Cats-Team/AdRules",
"source": "https://raw.githubusercontent.com/Cats-Team/AdRules/main/dns.txt" "source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_29.txt"
}, },
"CHN_anti_ad": { "CHN_anti_ad": {
"name": "CHN: anti-AD", "name": "CHN: anti-AD",
"categoryId": "regional", "categoryId": "regional",
"homepage": "https://anti-ad.net/", "homepage": "https://anti-ad.net/",
"source": "https://anti-ad.net/easylist.txt" "source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_21.txt"
},
"HUN_hufilter": {
"name": "HUN: Hufilter",
"categoryId": "regional",
"homepage": "https://github.com/hufilter/hufilter",
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_35.txt"
}, },
"IDN_abpindo": { "IDN_abpindo": {
"name": "IDN: ABPindo", "name": "IDN: ABPindo",
"categoryId": "regional", "categoryId": "regional",
"homepage": "https://github.com/ABPindo/indonesianadblockrules", "homepage": "https://github.com/ABPindo/indonesianadblockrules",
"source": "https://raw.githubusercontent.com/ABPindo/indonesianadblockrules/master/subscriptions/aghome.txt" "source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_22.txt"
}, },
"IRN_unwanted_iranian_domains": { "IRN_unwanted_iranian_domains": {
"name": "IRN: PersianBlocker list", "name": "IRN: PersianBlocker list",
"categoryId": "regional", "categoryId": "regional",
"homepage": "https://github.com/MasterKia/PersianBlocker", "homepage": "https://github.com/MasterKia/PersianBlocker",
"source": "https://raw.githubusercontent.com/MasterKia/PersianBlocker/main/PersianBlockerHosts.txt" "source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_19.txt"
}, },
"ITA_filtri_dns": { "ITA_filtri_dns": {
"name": "ITA: Filtri-DNS", "name": "ITA: Filtri-DNS",
"categoryId": "regional", "categoryId": "regional",
"homepage": "https://filtri-dns.ga/", "homepage": "https://filtri-dns.ga/",
"source": "https://filtri-dns.ga/filtri.txt" "source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_18.txt"
}, },
"KOR_list_kr": { "KOR_list_kr": {
"name": "KOR: List-KR DNS", "name": "KOR: List-KR DNS",
"categoryId": "regional", "categoryId": "regional",
"homepage": "https://github.com/List-KR/List-KR", "homepage": "https://github.com/List-KR/List-KR",
"source": "https://github.com/List-KR/List-KR" "source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_25.txt"
}, },
"KOR_youslist": { "KOR_youslist": {
"name": "KOR: YousList", "name": "KOR: YousList",
"categoryId": "regional", "categoryId": "regional",
"homepage": "https://github.com/yous/YousList", "homepage": "https://github.com/yous/YousList",
"source": "https://raw.githubusercontent.com/yous/YousList/master/hosts.txt" "source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_15.txt"
},
"LIT_easylist_lithuania": {
"name": "LIT: EasyList Lithuania",
"categoryId": "regional",
"homepage": "https://github.com/EasyList-Lithuania/easylist_lithuania",
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_36.txt"
}, },
"MKD_macedonian_pi_hole_blocklist": { "MKD_macedonian_pi_hole_blocklist": {
"name": "MKD: Macedonian Pi-hole Blocklist", "name": "MKD: Macedonian Pi-hole Blocklist",
"categoryId": "regional", "categoryId": "regional",
"homepage": "https://github.com/cchevy/macedonian-pi-hole-blocklist", "homepage": "https://github.com/cchevy/macedonian-pi-hole-blocklist",
"source": "https://raw.githubusercontent.com/cchevy/macedonian-pi-hole-blocklist/master/hosts.txt" "source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_20.txt"
}, },
"NOR_dandelion_sprouts_anti_malware_list": { "NOR_dandelion_sprouts_anti_malware_list": {
"name": "NOR: Dandelion Sprouts nordiske filtre", "name": "NOR: Dandelion Sprouts nordiske filtre",
"categoryId": "regional", "categoryId": "regional",
"homepage": "https://github.com/DandelionSprout/adfilt", "homepage": "https://github.com/DandelionSprout/adfilt",
"source": "https://raw.githubusercontent.com/DandelionSprout/adfilt/master/NorwegianExperimentalList%20alternate%20versions/NordicFiltersAdGuardHome.txt" "source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_13.txt"
}, },
"POL_polish_filters_for_pi_hole": { "POL_polish_filters_for_pi_hole": {
"name": "POL: Polish filters for Pi hole", "name": "POL: Polish filters for Pi hole",
"categoryId": "regional", "categoryId": "regional",
"homepage": "https://www.certyficate.it/", "homepage": "https://www.certyficate.it/",
"source": "https://raw.githubusercontent.com/MajkiIT/polish-ads-filter/master/polish-pihole-filters/hostfile.txt" "source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_14.txt"
}, },
"SWE_frellwit_swedish_hosts_file": { "SWE_frellwit_swedish_hosts_file": {
"name": "SWE: Frellwit's Swedish Hosts File", "name": "SWE: Frellwit's Swedish Hosts File",
"categoryId": "regional", "categoryId": "regional",
"homepage": "https://github.com/lassekongo83/Frellwits-filter-lists/", "homepage": "https://github.com/lassekongo83/Frellwits-filter-lists/",
"source": "https://raw.githubusercontent.com/lassekongo83/Frellwits-filter-lists/master/Frellwits-Swedish-Hosts-File.txt" "source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_17.txt"
}, },
"TUR_turk_adlist": { "TUR_turk_adlist": {
"name": "TUR: turk-adlist", "name": "TUR: turk-adlist",
"categoryId": "regional", "categoryId": "regional",
"homepage": "https://github.com/bkrucarci/turk-adlist", "homepage": "https://github.com/bkrucarci/turk-adlist",
"source": "https://raw.githubusercontent.com/bkrucarci/turk-adlist/master/hosts" "source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_26.txt"
}, },
"VNM_abpvn": { "VNM_abpvn": {
"name": "VNM: ABPVN List", "name": "VNM: ABPVN List",
"categoryId": "regional", "categoryId": "regional",
"homepage": "http://abpvn.com/", "homepage": "http://abpvn.com/",
"source": "https://abpvn.com/android/abpvn.txt" "source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_16.txt"
}, },
"adguard_dns_filter": { "adguard_dns_filter": {
"name": "AdGuard DNS filter", "name": "AdGuard DNS filter",
"categoryId": "general", "categoryId": "general",
"homepage": "https://github.com/AdguardTeam/AdGuardSDNSFilter", "homepage": "https://github.com/AdguardTeam/AdGuardSDNSFilter",
"source": "https://adguardteam.github.io/AdGuardSDNSFilter/Filters/filter.txt" "source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_1.txt"
}, },
"adway_default_blocklist": { "adway_default_blocklist": {
"name": "AdAway Default Blocklist", "name": "AdAway Default Blocklist",
"categoryId": "general", "categoryId": "general",
"homepage": "https://github.com/AdAway/adaway.github.io/", "homepage": "https://github.com/AdAway/adaway.github.io/",
"source": "https://adaway.org/hosts.txt" "source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_2.txt"
}, },
"curben_phishing_filter": { "curben_phishing_filter": {
"name": "Phishing URL Blocklist (PhishTank and OpenPhish)", "name": "Phishing URL Blocklist (PhishTank and OpenPhish)",
"categoryId": "security", "categoryId": "security",
"homepage": "https://gitlab.com/malware-filter/phishing-filter", "homepage": "https://gitlab.com/malware-filter/phishing-filter",
"source": "https://malware-filter.gitlab.io/malware-filter/phishing-filter-agh.txt" "source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_30.txt"
}, },
"dan_pollocks_list": { "dan_pollocks_list": {
"name": "Dan Pollock's List", "name": "Dan Pollock's List",
"categoryId": "general", "categoryId": "general",
"homepage": "https://someonewhocares.org/", "homepage": "https://someonewhocares.org/",
"source": "https://someonewhocares.org/hosts/zero/hosts" "source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_4.txt"
}, },
"dandelion_sprouts_anti_malware_list": { "dandelion_sprouts_anti_malware_list": {
"name": "Dandelion Sprout's Anti-Malware List", "name": "Dandelion Sprout's Anti-Malware List",
"categoryId": "security", "categoryId": "security",
"homepage": "https://github.com/DandelionSprout/adfilt", "homepage": "https://github.com/DandelionSprout/adfilt",
"source": "https://raw.githubusercontent.com/DandelionSprout/adfilt/master/Alternate%20versions%20Anti-Malware%20List/AntiMalwareAdGuardHome.txt" "source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_12.txt"
}, },
"dandelion_sprouts_game_console_adblock_list": { "dandelion_sprouts_game_console_adblock_list": {
"name": "Dandelion Sprout's Game Console Adblock List", "name": "Dandelion Sprout's Game Console Adblock List",
"categoryId": "other", "categoryId": "other",
"homepage": "https://github.com/DandelionSprout/adfilt", "homepage": "https://github.com/DandelionSprout/adfilt",
"source": "https://raw.githubusercontent.com/DandelionSprout/adfilt/master/GameConsoleAdblockList.txt" "source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_6.txt"
}, },
"energized_spark": { "energized_spark": {
"name": "Energized Spark", "name": "Energized Spark",
"categoryId": "general", "categoryId": "general",
"homepage": "https://energized.pro/", "homepage": "https://energized.pro/",
"source": "https://block.energized.pro/spark/formats/filter" "source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_28.txt"
},
"hagezi_personal": {
"name": "HaGeZi Personal Black \u0026 White",
"categoryId": "general",
"homepage": "https://github.com/hagezi/dns-blocklists",
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_34.txt"
},
"no_google": {
"name": "No Google",
"categoryId": "other",
"homepage": "https://github.com/nickspaargaren/no-google",
"source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_37.txt"
}, },
"nocoin_filter_list": { "nocoin_filter_list": {
"name": "NoCoin Filter List", "name": "NoCoin Filter List",
"categoryId": "security", "categoryId": "security",
"homepage": "https://github.com/hoshsadiq/adblock-nocoin-list/", "homepage": "https://github.com/hoshsadiq/adblock-nocoin-list/",
"source": "https://raw.githubusercontent.com/hoshsadiq/adblock-nocoin-list/master/hosts.txt" "source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_8.txt"
}, },
"notracking_hosts_blocklists": { "notracking_hosts_blocklists": {
"name": "The NoTracking blocklist", "name": "The NoTracking blocklist",
"categoryId": "general", "categoryId": "general",
"homepage": "https://github.com/notracking/hosts-blocklists", "homepage": "https://github.com/notracking/hosts-blocklists",
"source": "https://raw.githubusercontent.com/notracking/hosts-blocklists/master/adblock/adblock.txt" "source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_32.txt"
}, },
"oisd_basic": { "oisd_basic": {
"name": "OISD Blocklist Basic", "name": "OISD Blocklist Basic",
"categoryId": "general", "categoryId": "general",
"homepage": "https://oisd.nl/", "homepage": "https://oisd.nl/",
"source": "https://abp.oisd.nl/basic/" "source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_5.txt"
}, },
"oisd_full": { "oisd_full": {
"name": "OISD Blocklist Full", "name": "OISD Blocklist Full",
"categoryId": "general", "categoryId": "general",
"homepage": "https://oisd.nl/", "homepage": "https://oisd.nl/",
"source": "https://abp.oisd.nl/" "source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_27.txt"
}, },
"perflyst_dandelion_sprout_smart_tv_blocklist_for_adguard_home": { "perflyst_dandelion_sprout_smart_tv_blocklist_for_adguard_home": {
"name": "Perflyst and Dandelion Sprout's Smart-TV Blocklist", "name": "Perflyst and Dandelion Sprout's Smart-TV Blocklist",
"categoryId": "other", "categoryId": "other",
"homepage": "https://github.com/Perflyst/PiHoleBlocklist", "homepage": "https://github.com/Perflyst/PiHoleBlocklist",
"source": "https://raw.githubusercontent.com/Perflyst/PiHoleBlocklist/master/SmartTV-AGH.txt" "source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_7.txt"
}, },
"peter_lowe_list": { "peter_lowe_list": {
"name": "Peter Lowe's Blocklist", "name": "Peter Lowe's Blocklist",
"categoryId": "general", "categoryId": "general",
"homepage": "https://pgl.yoyo.org/adservers/", "homepage": "https://pgl.yoyo.org/adservers/",
"source": "https://pgl.yoyo.org/adservers/serverlist.php?hostformat=adblockplus\u0026showintro=1\u0026mimetype=plaintext" "source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_3.txt"
}, },
"scam_blocklist_by_durablenapkin": { "scam_blocklist_by_durablenapkin": {
"name": "Scam Blocklist by DurableNapkin", "name": "Scam Blocklist by DurableNapkin",
"categoryId": "security", "categoryId": "security",
"homepage": "https://github.com/durablenapkin/scamblocklist", "homepage": "https://github.com/durablenapkin/scamblocklist",
"source": "https://raw.githubusercontent.com/durablenapkin/scamblocklist/master/adguard.txt" "source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_10.txt"
}, },
"staklerware_indicators_list": { "staklerware_indicators_list": {
"name": "Stalkerware Indicators List", "name": "Stalkerware Indicators List",
"categoryId": "security", "categoryId": "security",
"homepage": "https://github.com/AssoEchap/stalkerware-indicators", "homepage": "https://github.com/AssoEchap/stalkerware-indicators",
"source": "https://raw.githubusercontent.com/AssoEchap/stalkerware-indicators/master/generated/hosts" "source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_31.txt"
}, },
"steven_blacks_list": { "steven_blacks_list": {
"name": "Steven Black's List", "name": "Steven Black's List",
"categoryId": "general", "categoryId": "general",
"homepage": "https://github.com/StevenBlack/hosts", "homepage": "https://github.com/StevenBlack/hosts",
"source": "https://raw.githubusercontent.com/StevenBlack/hosts/master/hosts" "source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_33.txt"
}, },
"the_big_list_of_hacked_malware_web_sites": { "the_big_list_of_hacked_malware_web_sites": {
"name": "The Big List of Hacked Malware Web Sites", "name": "The Big List of Hacked Malware Web Sites",
"categoryId": "security", "categoryId": "security",
"homepage": "https://github.com/mitchellkrogza/The-Big-List-of-Hacked-Malware-Web-Sites", "homepage": "https://github.com/mitchellkrogza/The-Big-List-of-Hacked-Malware-Web-Sites",
"source": "https://raw.githubusercontent.com/mitchellkrogza/The-Big-List-of-Hacked-Malware-Web-Sites/master/hosts" "source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_9.txt"
}, },
"urlhaus_filter_online": { "urlhaus_filter_online": {
"name": "Malicious URL Blocklist (URLHaus)", "name": "Malicious URL Blocklist (URLHaus)",
"categoryId": "security", "categoryId": "security",
"homepage": "https://gitlab.com/malware-filter/urlhaus-filter", "homepage": "https://gitlab.com/malware-filter/urlhaus-filter",
"source": "https://malware-filter.gitlab.io/malware-filter/urlhaus-filter-agh.txt" "source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_11.txt"
}, },
"windowsspyblocker_hosts_spy_rules": { "windowsspyblocker_hosts_spy_rules": {
"name": "WindowsSpyBlocker - Hosts spy rules", "name": "WindowsSpyBlocker - Hosts spy rules",
"categoryId": "other", "categoryId": "other",
"homepage": "https://github.com/crazy-max/WindowsSpyBlocker", "homepage": "https://github.com/crazy-max/WindowsSpyBlocker",
"source": "https://raw.githubusercontent.com/crazy-max/WindowsSpyBlocker/master/data/hosts/spy.txt" "source": "https://adguardteam.github.io/HostlistsRegistry/assets/filter_23.txt"
} }
} }
} }

View File

@@ -670,6 +670,15 @@ export const setHtmlLangAttr = (language) => {
window.document.documentElement.lang = language; window.document.documentElement.lang = language;
}; };
/**
* Sets UI theme.
*
* @param theme
*/
export const setUITheme = (theme) => {
document.body.dataset.theme = theme;
};
/** /**
* @param values {object} * @param values {object}
* @returns {object} * @returns {object}

View File

@@ -15,6 +15,8 @@
"11": "unknown", "11": "unknown",
"12": "extensions", "12": "extensions",
"13": "email", "13": "email",
"14": "consent",
"15": "telemetry",
"101": "mobile_analytics" "101": "mobile_analytics"
}, },
"trackers": { "trackers": {
@@ -149,6 +151,7 @@
"akadns.net": "akamai_technologies", "akadns.net": "akamai_technologies",
"akamaiedge.net": "akamai_technologies", "akamaiedge.net": "akamai_technologies",
"apple.com": "apple", "apple.com": "apple",
"apple.news": "apple",
"apple-dns.net": "apple", "apple-dns.net": "apple",
"aaplimg.com": "apple", "aaplimg.com": "apple",
"icloud.com": "apple", "icloud.com": "apple",

View File

@@ -77,11 +77,11 @@ export const validateNotInRange = (value, allValues) => {
const { range_start, range_end } = allValues.v4; const { range_start, range_end } = allValues.v4;
if (range_start && validateIpv4(range_start)) { if (range_start && validateIpv4(range_start)) {
return 'form_error_ip4_range_start_format'; return undefined;
} }
if (range_end && validateIpv4(range_end)) { if (range_end && validateIpv4(range_end)) {
return 'form_error_ip4_range_end_format'; return undefined;
} }
const isAboveMin = range_start && ip4ToInt(value) >= ip4ToInt(range_start); const isAboveMin = range_start && ip4ToInt(value) >= ip4ToInt(range_start);
@@ -94,14 +94,6 @@ export const validateNotInRange = (value, allValues) => {
}); });
} }
if (!range_end && isAboveMin) {
return 'lower_range_start_error';
}
if (!range_start && isBelowMax) {
return 'greater_range_end_error';
}
return undefined; return undefined;
}; };
@@ -118,7 +110,7 @@ export const validateGatewaySubnetMask = (_, allValues) => {
const { subnet_mask, gateway_ip } = allValues.v4; const { subnet_mask, gateway_ip } = allValues.v4;
if (validateIpv4(gateway_ip)) { if (validateIpv4(gateway_ip)) {
return 'form_error_ip4_gateway_format'; return 'gateway_or_subnet_invalid';
} }
return parseSubnetMask(subnet_mask) ? undefined : 'gateway_or_subnet_invalid'; return parseSubnetMask(subnet_mask) ? undefined : 'gateway_or_subnet_invalid';
@@ -138,6 +130,10 @@ export const validateIpForGatewaySubnetMask = (value, allValues) => {
gateway_ip, subnet_mask, gateway_ip, subnet_mask,
} = allValues.v4; } = allValues.v4;
if ((gateway_ip && validateIpv4(gateway_ip)) || (subnet_mask && validateIpv4(subnet_mask))) {
return undefined;
}
const subnetPrefix = parseSubnetMask(subnet_mask); const subnetPrefix = parseSubnetMask(subnet_mask);
if (!isIpInCidr(value, `${gateway_ip}/${subnetPrefix}`)) { if (!isIpInCidr(value, `${gateway_ip}/${subnetPrefix}`)) {

View File

@@ -21,11 +21,16 @@
margin: 0 auto; margin: 0 auto;
padding: 30px 20px; padding: 30px 20px;
line-height: 1.6; line-height: 1.6;
background-color: #fff; background-color: var(--card-bgcolor);
box-shadow: 0 1px 4px rgba(74, 74, 74, 0.36); box-shadow: 0 1px 4px rgba(74, 74, 74, 0.36);
border-radius: 3px; border-radius: 3px;
} }
[data-theme=dark] .setup__container {
box-shadow: none;
border: 1px solid var(--card-border-color);
}
@media screen and (min-width: 768px) { @media screen and (min-width: 768px) {
.setup__container { .setup__container {
width: 650px; width: 650px;
@@ -39,6 +44,10 @@
max-width: 140px; max-width: 140px;
} }
[data-theme=dark] .setup__logo {
filter: invert(1);
}
.setup__nav { .setup__nav {
text-align: center; text-align: center;
} }

View File

@@ -13,6 +13,10 @@
min-height: 100vh; min-height: 100vh;
} }
[data-theme=dark] .login__logo {
filter: invert(1);
}
.login__form { .login__form {
margin: auto; margin: auto;
padding: 40px 15px 100px; padding: 40px 15px 100px;

View File

@@ -36,7 +36,7 @@ class Login extends Component {
<div className="login"> <div className="login">
<div className="login__form"> <div className="login__form">
<div className="text-center mb-6"> <div className="text-center mb-6">
<img src={logo} className="h-6" alt="logo" /> <img src={logo} className="h-6 login__logo" alt="logo" />
</div> </div>
<Form onSubmit={this.handleSubmit} processing={processingLogin} /> <Form onSubmit={this.handleSubmit} processing={processingLogin} />
<div className="login__info"> <div className="login__info">

View File

@@ -112,14 +112,6 @@ const dashboard = handleActions(
return newState; return newState;
}, },
[actions.getLanguageSuccess]: (state, { payload }) => {
const newState = {
...state,
language: payload,
};
return newState;
},
[actions.getClientsRequest]: (state) => ({ [actions.getClientsRequest]: (state) => ({
...state, ...state,
processingClients: true, processingClients: true,
@@ -148,8 +140,13 @@ const dashboard = handleActions(
[actions.getProfileSuccess]: (state, { payload }) => ({ [actions.getProfileSuccess]: (state, { payload }) => ({
...state, ...state,
name: payload.name, name: payload.name,
theme: payload.theme,
processingProfile: false, processingProfile: false,
}), }),
[actions.changeThemeSuccess]: (state, { payload }) => ({
...state,
theme: payload.theme,
}),
}, },
{ {
processing: true, processing: true,
@@ -168,6 +165,7 @@ const dashboard = handleActions(
autoClients: [], autoClients: [],
supportedTags: [], supportedTags: [],
name: '', name: '',
theme: 'auto',
checkUpdateFlag: false, checkUpdateFlag: false,
}, },
); );

View File

@@ -1,6 +0,0 @@
scripts
node_modules
postcss.config.js
src/lib/entities
src/lib/apis
openApi

View File

@@ -1,5 +0,0 @@
{
"extends": [
"./scripts/lint/dev.js"
]
}

View File

@@ -1,18 +0,0 @@
declare module '*.pcss' {
const content: {[className: string]: string};
export default content;
}
declare module '*.css' {
const content: {[className: string]: string};
export default content;
}
declare module '*.png'
declare module '*.jpg'
declare let AUTH_TOKEN: string;
declare let MAIN_TOKEN: string | undefined;
declare let NO_CAPTCHA: boolean | undefined;
declare module 'dygraphs';
declare module '@novnc/novnc/core/rfb';
// cp - CloudPayments script
declare let cp: any;
declare const DEV: any;

View File

@@ -1,89 +0,0 @@
{
"author": "Performix",
"private": true,
"name": "adguard-home",
"version": "0.1.0",
"scripts": {
"build": "webpack --config ./scripts/webpack/webpack.config.prod.js",
"start": "webpack serve --config ./scripts/webpack/webpack.config.dev.js",
"generate": "rm -rf ./src/lib/entities ./src/lib/apis && ts-node --compiler-options '{ \"module\": \"CommonJS\" }' ./scripts/generator/index.ts",
"translations:check": "ts-node --compiler-options '{ \"module\": \"CommonJS\" }' ./scripts/plugins/checkTranslations.ts",
"lint": "eslint -c ./scripts/lint/prod.js --ext .tsx --ext .ts ./",
"go:build": "cd .. && make REBUILD_CLIENT=0 build",
"go:run": "sudo ../AdguardHome"
},
"license": "ISC",
"dependencies": {
"@adguard/translate": "^0.2.0",
"@ant-design/icons": "^4.4.0",
"@sentry/react": "^5.27.0",
"antd": "^4.7.2",
"classnames": "^2.2.6",
"dayjs": "^1.9.3",
"formik": "^2.2.0",
"mobx": "^6.0.1",
"mobx-react-lite": "^3.0.1",
"qs": "^6.9.4",
"react": "^17.0.0",
"react-dom": "^17.0.0",
"react-router-dom": "^5.2.0",
"recharts": "^2.0.3"
},
"devDependencies": {
"@types/classnames": "^2.2.10",
"@types/qs": "^6.9.5",
"@types/react": "^16.9.53",
"@types/react-dom": "^16.9.8",
"@types/react-redux": "^7.1.9",
"@types/react-router-dom": "^5.1.6",
"@typescript-eslint/eslint-plugin": "^4.5.0",
"@typescript-eslint/parser": "^4.5.0",
"antd-dayjs-webpack-plugin": "^1.0.1",
"autoprefixer": "^10.0.1",
"connect-history-api-fallback": "^1.6.0",
"copy-webpack-plugin": "^6.2.1",
"css-loader": "^5.0.0",
"eslint": "^7.11.0",
"eslint-config-airbnb-base": "^14.2.0",
"eslint-config-airbnb-typescript": "^12.0.0",
"eslint-import-resolver-typescript": "^2.3.0",
"eslint-loader": "^4.0.2",
"eslint-plugin-import": "^2.22.1",
"eslint-plugin-react": "^7.21.5",
"eslint-plugin-react-hooks": "^4.2.0",
"file-loader": "^6.1.1",
"html-webpack-plugin": "^4.5.0",
"http-proxy-middleware": "^1.0.6",
"less": "^3.12.2",
"less-loader": "^5.0.0",
"mini-css-extract-plugin": "^1.1.1",
"optimize-css-assets-webpack-plugin": "^5.0.4",
"postcss": "^8.1.2",
"postcss-calc": "^7.0.5",
"postcss-css-variables": "^0.17.0",
"postcss-custom-media": "^7.0.8",
"postcss-import": "^13.0.0",
"postcss-inline-svg": "^4.1.0",
"postcss-loader": "^4.0.4",
"postcss-mixins": "^7.0.1",
"postcss-modules": "^3.2.2",
"postcss-nested": "^5.0.1",
"postcss-preset-env": "^6.7.0",
"postcss-reporter": "^7.0.1",
"postcss-variables": "^1.1.1",
"style-loader": "^2.0.0",
"stylelint": "^13.7.2",
"stylelint-webpack-plugin": "^2.1.1",
"terser-webpack-plugin": "^5.0.0",
"ts-loader": "^8.0.6",
"ts-morph": "^8.1.2",
"ts-node": "^9.0.0",
"typescript": "^4.0.3",
"url-loader": "^4.1.1",
"webpack": "^5.10.0",
"webpack-cli": "^4.2.0",
"webpack-dev-server": "^3.11.0",
"webpack-merge": "^5.2.0",
"yaml": "^1.10.0"
}
}

View File

@@ -1,17 +0,0 @@
module.exports = {
plugins: [
['postcss-import', {}],
['postcss-nested', {}],
['postcss-custom-media', {}],
['postcss-variables', {}],
['postcss-calc', {}],
['postcss-mixins', {}],
['postcss-preset-env', { stage: 3, features: { 'nesting-rules': true } }],
['postcss-reporter', { clearMessages: true }],
['postcss-inline-svg', {
paths: ['frontend/icons', 'vendor/adguard/utils-bundle/src/Resources/frontend/icons'],
svgo: { plugins: [{ cleanupAttrs: true }] }
}],
['autoprefixer'],
]
};

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.1 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.3 KiB

View File

@@ -1,8 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="16pt" height="16pt"
viewBox="0 0 16 16" version="1.1">
<g id="surface1">
<path style=" stroke:none;fill-rule:evenodd;fill:rgb(0%,0%,0%);fill-opacity:1;"
d="M 8 0 C 10.5 0 13.515625 0.574219 16 1.835938 L 15.996094 2.542969 C 15.957031 5.605469 15.410156 11.71875 8 16 C 0.5 11.667969 0.03125 5.460938 0.00390625 2.433594 L 0 1.835938 C 2.484375 0.574219 5.5 0 8 0 Z M 11.769531 4.203125 L 11.761719 4.203125 L 7.890625 8.160156 L 6.433594 6.4375 C 5.738281 5.644531 4.792969 6.25 4.570312 6.40625 L 7.929688 10.285156 L 12.570312 4.136719 C 12.230469 3.867188 11.933594 4.054688 11.769531 4.203125 Z M 11.769531 4.203125 "/>
</g>
</svg>

Before

Width:  |  Height:  |  Size: 801 B

View File

@@ -1,23 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<meta name="google" content="notranslate">
<meta http-equiv="x-dns-prefetch-control" content="off">
<meta name="mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="default">
<link rel="apple-touch-icon" sizes="180x180" href="assets/apple-touch-icon-180x180.png" />
<link rel="mask-icon" href="assets/safari-pinned-tab.svg" color="#67B279">
<link rel="icon" type="image/png" href="assets/favicon.png" sizes="48x48">
<title>AdGuard Home</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="app"></div>
</body>
</html>

View File

@@ -1,22 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<meta name="google" content="notranslate">
<meta name="mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="default">
<link rel="apple-touch-icon" sizes="180x180" href="assets/apple-touch-icon-180x180.png" />
<link rel="mask-icon" href="assets/safari-pinned-tab.svg" color="#67B279">
<link rel="icon" type="image/png" href="assets/favicon.png" sizes="48x48">
<title>Setup AdGuard Home</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="app"></div>
</body>
</html>

View File

@@ -1,22 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, shrink-to-fit=no">
<meta name="theme-color" content="#000000">
<meta name="google" content="notranslate">
<link rel="apple-touch-icon" sizes="180x180" href="assets/apple-touch-icon-180x180.png" />
<meta name="mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="default">
<link rel="mask-icon" href="assets/safari-pinned-tab.svg" color="#67B279">
<link rel="icon" type="image/png" href="assets/favicon.png" sizes="48x48">
<title>Login</title>
</head>
<body>
<noscript>
You need to enable JavaScript to run this app.
</noscript>
<div id="app"></div>
</body>
</html>

View File

@@ -1,12 +0,0 @@
export const OPEN_API_PATH = '../openapi/openapi.yaml';
export const ENT_DIR = './src/lib/entities';
export const API_DIR = './src/lib/apis';
export const LOCALE_FOLDER_PATH = './src/lib/intl/__locales';
export const TRANSLATOR_CLASS_NAME = 'Translator';
export const USE_INTL_NAME = 'useIntl';
export const trimQuotes = (str: string) => {
return str.replace(/\'|\"/g, '');
};
export const GENERATOR_ENTITY_ALLIAS = 'Entities/';

View File

@@ -1,18 +0,0 @@
import * as fs from 'fs';
import * as YAML from 'yaml';
import { OPEN_API_PATH } from '../consts';
import EntitiesGenerator from './src/generateEntities';
import ApisGenerator from './src/generateApis';
const generateApi = (openApi: Record<string, any>) => {
const ent = new EntitiesGenerator(openApi);
ent.save();
const api = new ApisGenerator(openApi);
api.save();
}
const openApiFile = fs.readFileSync(OPEN_API_PATH, 'utf8');
generateApi(YAML.parse(openApiFile));

View File

@@ -1,317 +0,0 @@
/* eslint-disable no-template-curly-in-string */
/* eslint-disable @typescript-eslint/no-unused-expressions */
import * as fs from 'fs';
import * as path from 'path';
import { stringify } from 'qs';
// eslint-disable-next-line import/no-extraneous-dependencies
import * as morph from 'ts-morph';
import {
API_DIR as API_DIR_CONST,
GENERATOR_ENTITY_ALLIAS,
} from '../../consts';
import { toCamel, capitalize, schemaParamParser } from './utils';
const API_DIR = path.resolve(API_DIR_CONST);
if (!fs.existsSync(API_DIR)) {
fs.mkdirSync(API_DIR);
}
const { Project, QuoteKind } = morph;
class ApiGenerator {
project = new Project({
tsConfigFilePath: './tsconfig.json',
addFilesFromTsConfig: false,
manipulationSettings: {
quoteKind: QuoteKind.Single,
usePrefixAndSuffixTextForRename: false,
useTrailingCommas: true,
},
});
openapi: Record<string, any>;
serverUrl: string;
paths: any;
/* interface Controllers {
[controller: string]: {
[operationId: string]: { parameters - from opneApi, responses - from opneApi, method }
}
} */
controllers: Record<string, any> = {};
apis: morph.SourceFile[] = [];
constructor(openapi: Record<string, any>) {
this.openapi = openapi;
this.paths = openapi.paths;
this.serverUrl = openapi.servers[0].url;
Object.keys(this.paths).forEach((pathKey) => {
Object.keys(this.paths[pathKey]).forEach((method) => {
const {
tags, operationId, parameters, responses, requestBody, security,
} = this.paths[pathKey][method];
const controller = toCamel((tags ? tags[0] : pathKey.split('/')[1]).replace('-controller', ''));
if (this.controllers[controller]) {
this.controllers[controller][operationId] = {
parameters,
responses,
method,
requestBody,
security,
pathKey: pathKey.replace(/{/g, '${'),
};
} else {
this.controllers[controller] = { [operationId]: {
parameters,
responses,
method,
requestBody,
security,
pathKey: pathKey.replace(/{/g, '${'),
} };
}
});
});
this.generateApiFiles();
}
generateApiFiles = () => {
Object.keys(this.controllers).forEach(this.generateApiFile);
};
generateApiFile = (cName: string) => {
const apiFile = this.project.createSourceFile(`${API_DIR}/${cName}.ts`);
apiFile.addStatements([
'// This file was autogenerated. Please do not change.',
'// All changes will be overwrited on commit.',
'',
]);
// const schemaProperties = schemas[schemaName].properties;
const importEntities: any[] = [];
// add api class to file
const apiClass = apiFile.addClass({
name: `${capitalize(cName)}Api`,
isDefaultExport: true,
});
// get operations of controller
const controllerOperations = this.controllers[cName];
const operationList = Object.keys(controllerOperations).sort();
// for each operation add fetcher
operationList.forEach((operation) => {
const {
requestBody, responses, parameters, method, pathKey, security,
} = controllerOperations[operation];
const queryParams: any[] = []; // { name, type }
const bodyParam: any[] = []; // { name, type }
let hasResponseBodyType: /* boolean | ReturnType<schemaParamParser> */ false | [string, boolean, boolean, boolean, boolean] = false;
let contentType = '';
if (parameters) {
parameters.forEach((p: any) => {
const [
pType, isArray, isClass, isImport,
] = schemaParamParser(p.schema, this.openapi);
if (isImport) {
importEntities.push({ type: pType, isClass });
}
if (p.in === 'query') {
queryParams.push({
name: p.name, type: `${pType}${isArray ? '[]' : ''}`, hasQuestionToken: !p.required });
}
});
}
if (queryParams.length > 0) {
const imp = apiFile.getImportDeclaration((i) => {
return i.getModuleSpecifierValue() === 'qs';
}); if (!imp) {
apiFile.addImportDeclaration({
moduleSpecifier: 'qs',
defaultImport: 'qs',
});
}
}
if (requestBody) {
let content = requestBody.content;
const { $ref }: { $ref: string } = requestBody;
if (!content && $ref) {
const name = $ref.split('/').pop() as string;
content = this.openapi.components.requestBodies[name].content;
}
[contentType] = Object.keys(content);
const data = content[contentType];
const [
pType, isArray, isClass, isImport,
] = schemaParamParser(data.schema, this.openapi);
if (isImport) {
importEntities.push({ type: pType, isClass });
bodyParam.push({ name: pType.toLowerCase(), type: `${isClass ? 'I' : ''}${pType}${isArray ? '[]' : ''}`, isClass, pType });
} else {
bodyParam.push({ name: 'data', type: `${pType}${isArray ? '[]' : ''}` });
}
}
if (responses['200']) {
const { content, headers } = responses['200'];
if (content && (content['*/*'] || content['application/json'])) {
const { schema, examples } = content['*/*'] || content['application/json'];
if (!schema) {
process.exit(0);
}
const propType = schemaParamParser(schema, this.openapi);
const [pType, , isClass, isImport] = propType;
if (isImport) {
importEntities.push({ type: pType, isClass });
}
hasResponseBodyType = propType;
}
}
let returnType = '';
if (hasResponseBodyType) {
const [pType, isArray, isClass] = hasResponseBodyType as any;
let data = `Promise<${isClass ? 'I' : ''}${pType}${isArray ? '[]' : ''}`;
returnType = data;
} else {
returnType = 'Promise<number';
}
const shouldValidate = bodyParam.filter(b => b.isClass);
if (shouldValidate.length > 0) {
returnType += ' | string[]';
}
// append Error to default type return;
returnType += ' | Error>';
const fetcher = apiClass.addMethod({
isAsync: true,
isStatic: true,
name: operation,
returnType,
});
const params = [...queryParams, ...bodyParam].sort((a, b) => (Number(!!a.hasQuestionToken) - Number(!!b.hasQuestionToken)));
fetcher.addParameters(params);
fetcher.setBodyText((w) => {
// Add data to URLSearchParams
if (contentType === 'text/plain') {
bodyParam.forEach((b) => {
w.writeLine(`const params = String(${b.name});`);
});
} else {
if (shouldValidate.length > 0) {
w.writeLine(`const haveError: string[] = [];`);
shouldValidate.forEach((b) => {
w.writeLine(`const ${b.name}Valid = new ${b.pType}(${b.name});`);
w.writeLine(`haveError.push(...${b.name}Valid.validate());`);
});
w.writeLine(`if (haveError.length > 0) {`);
w.writeLine(` return Promise.resolve(haveError);`)
w.writeLine(`}`);
}
}
// Switch return of fetch in case on queryParams
if (queryParams.length > 0) {
w.writeLine('const queryParams = {');
queryParams.forEach((q) => {
w.writeLine(` ${q.name}: ${q.name},`);
});
w.writeLine('}');
w.writeLine(`return await fetch(\`${this.serverUrl}${pathKey}?\${qs.stringify(queryParams, { arrayFormat: 'comma' })}\`, {`);
} else {
w.writeLine(`return await fetch(\`${this.serverUrl}${pathKey}\`, {`);
}
// Add method
w.writeLine(` method: '${method.toUpperCase()}',`);
// add Fetch options
if (contentType && contentType !== 'multipart/form-data') {
w.writeLine(' headers: {');
w.writeLine(` 'Content-Type': '${contentType}',`);
w.writeLine(' },');
}
if (contentType) {
switch (contentType) {
case 'text/plain':
w.writeLine(' body: params,');
break;
default:
w.writeLine(` body: JSON.stringify(${bodyParam.map((b) => b.isClass ? `${b.name}Valid.serialize()` : b.name).join(', ')}),`);
break;
}
}
// Handle response
if (hasResponseBodyType) {
w.writeLine('}).then(async (res) => {');
w.writeLine(' if (res.status === 200) {');
w.writeLine(' return res.json();');
} else {
w.writeLine('}).then(async (res) => {');
w.writeLine(' if (res.status === 200) {');
w.writeLine(' return res.status;');
}
// Handle Error
w.writeLine(' } else {');
w.writeLine(' return new Error(String(res.status));');
w.writeLine(' }');
w.writeLine('})');
});
});
const imports: any[] = [];
const types: string[] = [];
importEntities.forEach((i) => {
const { type } = i;
if (!types.includes(type)) {
imports.push(i);
types.push(type);
}
});
imports.sort((a,b) => a.type > b.type ? 1 : -1).forEach((ie) => {
const { type: pType, isClass } = ie;
if (isClass) {
apiFile.addImportDeclaration({
moduleSpecifier: `${GENERATOR_ENTITY_ALLIAS}${pType}`,
defaultImport: pType,
namedImports: [`I${pType}`],
});
} else {
apiFile.addImportDeclaration({
moduleSpecifier: `${GENERATOR_ENTITY_ALLIAS}${pType}`,
namedImports: [pType],
});
}
});
this.apis.push(apiFile);
};
save = () => {
this.apis.forEach(async (e) => {
await e.saveSync();
});
};
}
export default ApiGenerator;

View File

@@ -1,603 +0,0 @@
import * as fs from 'fs';
import * as path from 'path';
// eslint-disable-next-line import/no-extraneous-dependencies
import * as morph from 'ts-morph';
import { ENT_DIR } from '../../consts';
import { TYPES, toCamel, schemaParamParser, uncapitalize } from './utils';
const { Project, QuoteKind } = morph;
const EntDir = path.resolve(ENT_DIR);
if (!fs.existsSync(EntDir)) {
fs.mkdirSync(EntDir);
}
class EntitiesGenerator {
project = new Project({
tsConfigFilePath: './tsconfig.json',
addFilesFromTsConfig: false,
manipulationSettings: {
quoteKind: QuoteKind.Single,
usePrefixAndSuffixTextForRename: false,
useTrailingCommas: true,
},
});
openapi: Record<string, any>;
schemas: Record<string, any>;
schemaNames: string[];
entities: morph.SourceFile[] = [];
constructor(openapi: Record<string, any>) {
this.openapi = openapi;
this.schemas = openapi.components.schemas;
this.schemaNames = Object.keys(this.schemas);
this.generateEntities();
}
generateEntities = () => {
this.schemaNames.forEach(this.generateEntity);
};
generateEntity = (sName: string) => {
const { properties, type, oneOf } = this.schemas[sName];
const notAClass = !properties && TYPES[type as keyof typeof TYPES];
if (oneOf) {
this.generateOneOf(sName);
return;
}
if (notAClass) {
this.generateEnum(sName);
} else {
this.generateClass(sName);
}
};
generateEnum = (sName: string) => {
const entityFile = this.project.createSourceFile(`${EntDir}/${sName}.ts`);
entityFile.addStatements([
'// This file was autogenerated. Please do not change.',
'// All changes will be overwrited on commit.',
'',
]);
const { enum: enumMembers } = this.schemas[sName];
entityFile.addEnum({
name: sName,
members: enumMembers.map((e: string) => ({ name: e.toUpperCase(), value: e })),
isExported: true,
});
this.entities.push(entityFile);
};
generateOneOf = (sName: string) => {
const entityFile = this.project.createSourceFile(`${EntDir}/${sName}.ts`);
entityFile.addStatements([
'// This file was autogenerated. Please do not change.',
'// All changes will be overwrited on commit.',
'',
]);
const importEntities: { type: string, isClass: boolean }[] = [];
const entities = this.schemas[sName].oneOf.map((elem: any) => {
const [
pType, isArray, isClass, isImport,
] = schemaParamParser(elem, this.openapi);
importEntities.push({ type: pType, isClass });
return { type: pType, isArray };
});
entityFile.addTypeAlias({
name: sName,
isExported: true,
type: entities.map((e: any) => e.isArray ? `I${e.type}[]` : `I${e.type}`).join(' | '),
})
// add import
importEntities.sort((a, b) => a.type > b.type ? 1 : -1).forEach((ie) => {
const { type: pType, isClass } = ie;
if (isClass) {
entityFile.addImportDeclaration({
moduleSpecifier: `./${pType}`,
namedImports: [`I${pType}`],
});
} else {
entityFile.addImportDeclaration({
moduleSpecifier: `./${pType}`,
namedImports: [pType],
});
}
});
this.entities.push(entityFile);
}
generateClass = (sName: string) => {
const entityFile = this.project.createSourceFile(`${EntDir}/${sName}.ts`);
entityFile.addStatements([
'// This file was autogenerated. Please do not change.',
'// All changes will be overwrited on commit.',
'',
]);
const { properties: sProps, required, $ref, additionalProperties } = this.schemas[sName];
if ($ref) {
const temp = $ref.split('/');
const importSchemaName = `${temp[temp.length - 1]}`;
entityFile.addImportDeclaration({
defaultImport: importSchemaName,
moduleSpecifier: `./${importSchemaName}`,
namedImports: [`I${importSchemaName}`],
});
entityFile.addTypeAlias({
name: `I${sName}`,
type: `I${importSchemaName}`,
isExported: true,
})
entityFile.addStatements(`export default ${importSchemaName};`);
this.entities.push(entityFile);
return;
}
const importEntities: { type: string, isClass: boolean }[] = [];
const entityInterface = entityFile.addInterface({
name: `I${sName}`,
isExported: true,
});
const sortedSProps = Object.keys(sProps || {}).sort();
const additionalPropsOnly = additionalProperties && sortedSProps.length === 0;
// add server response interface to entityFile
sortedSProps.forEach((sPropName) => {
const [
pType, isArray, isClass, isImport, isAdditional
] = schemaParamParser(sProps[sPropName], this.openapi);
if (isImport) {
importEntities.push({ type: pType, isClass });
}
const propertyType = isAdditional
? `{ [key: string]: ${isClass ? 'I' : ''}${pType}${isArray ? '[]' : ''} }`
: `${isClass ? 'I' : ''}${pType}${isArray ? '[]' : ''}`;
entityInterface.addProperty({
name: sPropName,
type: propertyType,
hasQuestionToken: !(
(required && required.includes(sPropName)) || sProps[sPropName].required
),
});
});
if (additionalProperties) {
const [
pType, isArray, isClass, isImport, isAdditional
] = schemaParamParser(additionalProperties, this.openapi);
if (isImport) {
importEntities.push({ type: pType, isClass });
}
const type = isAdditional
? `{ [key: string]: ${isClass ? 'I' : ''}${pType}${isArray ? '[]' : ''} }`
: `${isClass ? 'I' : ''}${pType}${isArray ? '[]' : ''}`;
entityInterface.addIndexSignature({
keyName: 'key',
keyType: 'string',
returnType: additionalPropsOnly ? type : `${type} | undefined`,
});
}
// add import
const imports: { type: string, isClass: boolean }[] = [];
const types: string[] = [];
importEntities.forEach((i) => {
const { type } = i;
if (!types.includes(type)) {
imports.push(i);
types.push(type);
}
});
imports.sort((a, b) => a.type > b.type ? 1 : -1).forEach((ie) => {
const { type: pType, isClass } = ie;
if (isClass) {
entityFile.addImportDeclaration({
defaultImport: pType,
moduleSpecifier: `./${pType}`,
namedImports: [`I${pType}`],
});
} else {
entityFile.addImportDeclaration({
moduleSpecifier: `./${pType}`,
namedImports: [pType],
});
}
});
const entityClass = entityFile.addClass({
name: sName,
isDefaultExport: true,
});
// addProperties to class;
sortedSProps.forEach((sPropName) => {
const [pType, isArray, isClass, isImport, isAdditional] = schemaParamParser(sProps[sPropName], this.openapi);
const isRequred = (required && required.includes(sPropName))
|| sProps[sPropName].required;
const propertyType = isAdditional
? `{ [key: string]: ${pType}${isArray ? '[]' : ''}${isRequred ? '' : ' | undefined'} }`
: `${pType}${isArray ? '[]' : ''}${isRequred ? '' : ' | undefined'}`;
entityClass.addProperty({
name: `_${sPropName}`,
isReadonly: true,
type: propertyType,
});
const getter = entityClass.addGetAccessor({
name: toCamel(sPropName),
returnType: propertyType,
statements: [`return this._${sPropName};`],
});
const { description, example, minItems, maxItems, maxLength, minLength, maximum, minimum } = sProps[sPropName];
if (description || example) {
getter.addJsDoc(`${example ? `Description: ${description}` : ''}${example ? `\nExample: ${example}` : ''}`);
}
if (minItems) {
entityClass.addGetAccessor({
isStatic: true,
name: `${toCamel(sPropName)}MinItems`,
statements: [`return ${minItems};`],
});
}
if (maxItems) {
entityClass.addGetAccessor({
isStatic: true,
name: `${toCamel(sPropName)}MaxItems`,
statements: [`return ${maxItems};`],
});
}
if (typeof minLength === 'number') {
entityClass.addGetAccessor({
isStatic: true,
name: `${toCamel(sPropName)}MinLength`,
statements: [`return ${minLength};`],
});
}
if (maxLength) {
entityClass.addGetAccessor({
isStatic: true,
name: `${toCamel(sPropName)}MaxLength`,
statements: [`return ${maxLength};`],
});
}
if (typeof minimum === 'number') {
entityClass.addGetAccessor({
isStatic: true,
name: `${toCamel(sPropName)}MinValue`,
statements: [`return ${minimum};`],
});
}
if (maximum) {
entityClass.addGetAccessor({
isStatic: true,
name: `${toCamel(sPropName)}MaxValue`,
statements: [`return ${maximum};`],
});
}
if (!(isArray && isClass) && !isClass) {
const isEnum = !isClass && isImport;
const isRequired = (required && required.includes(sPropName)) || sProps[sPropName].required;
const { maxLength, minLength, maximum, minimum } = sProps[sPropName];
const haveValidationFields = maxLength || typeof minLength === 'number' || maximum || typeof minimum === 'number';
if (isRequired || haveValidationFields) {
const prop = toCamel(sPropName);
const validateField = entityClass.addMethod({
isStatic: true,
name: `${prop}Validate`,
returnType: `boolean`,
parameters: [{
name: prop,
type: `${pType}${isArray ? '[]' : ''}${isRequred ? '' : ' | undefined'}`,
}],
})
validateField.setBodyText((w) => {
w.write('return ');
const nonRequiredCall = isRequired ? prop : `!${prop} ? true : ${prop}`;
if (pType === 'string') {
if (isArray) {
w.write(`${nonRequiredCall}.reduce<boolean>((result, p) => result && (typeof p === 'string' && !!p.trim()), true)`);
} else {
if (typeof minLength === 'number' && maxLength) {
w.write(`(${nonRequiredCall}.length >${minLength > 0 ? '=' : ''} ${minLength}) && (${nonRequiredCall}.length <= ${maxLength})`);
}
if (typeof minLength !== 'number' || !maxLength) {
w.write(`${isRequired ? `typeof ${prop} === 'string'` : `!${prop} ? true : typeof ${prop} === 'string'`} && !!${nonRequiredCall}.trim()`);
}
}
} else if (pType === 'number') {
if (isArray) {
w.write(`${nonRequiredCall}.reduce<boolean>((result, p) => result && typeof p === 'number', true)`);
} else {
if (typeof minimum === 'number' && maximum) {
w.write(`${isRequired ? `${prop} >= ${minimum} && ${prop} <= ${maximum}` : `!${prop} ? true : ((${prop} >= ${minimum}) && (${prop} <= ${maximum}))`}`);
}
if (typeof minimum !== 'number' || !maximum) {
w.write(`${isRequired ? `typeof ${prop} === 'number'` : `!${prop} ? true : typeof ${prop} === 'number'`}`);
}
}
} else if (pType === 'boolean') {
w.write(`${isRequired ? `typeof ${prop} === 'boolean'` : `!${prop} ? true : typeof ${prop} === 'boolean'`}`);
} else if (isEnum) {
if (isArray){
w.write(`${nonRequiredCall}.reduce<boolean>((result, p) => result && Object.keys(${pType}).includes(${prop}), true)`);
} else {
w.write(`${isRequired ? `Object.keys(${pType}).includes(${prop})` : `!${prop} ? true : typeof ${prop} === 'boolean'`}`);
}
}
w.write(';');
});
}
}
});
if (additionalProperties) {
const [
pType, isArray, isClass, isImport, isAdditional
] = schemaParamParser(additionalProperties, this.openapi);
const type = `Record<string, ${pType}${isArray ? '[]' : ''}>`;
entityClass.addProperty({
name: additionalPropsOnly ? 'data' : `${uncapitalize(pType)}Data`,
isReadonly: true,
type: type,
});
}
// add constructor;
const ctor = entityClass.addConstructor({
parameters: [{
name: 'props',
type: `I${sName}`,
}],
});
ctor.setBodyText((w) => {
if (additionalProperties) {
const [
pType, isArray, isClass, isImport, isAdditional
] = schemaParamParser(additionalProperties, this.openapi);
w.writeLine(`this.${additionalPropsOnly ? 'data' : `${uncapitalize(pType)}Data`} = Object.entries(props).reduce<Record<string, ${pType}>>((prev, [key, value]) => {`);
if (isClass) {
w.writeLine(` prev[key] = new ${pType}(value!);`);
} else {
w.writeLine(' prev[key] = value!;')
}
w.writeLine(' return prev;');
w.writeLine('}, {})');
return;
}
sortedSProps.forEach((sPropName) => {
const [
pType, isArray, isClass, , isAdditional
] = schemaParamParser(sProps[sPropName], this.openapi);
const req = (required && required.includes(sPropName))
|| sProps[sPropName].required;
if (!req) {
if ((pType === 'boolean' || pType === 'number' || pType ==='string') && !isClass && !isArray) {
w.writeLine(`if (typeof props.${sPropName} === '${pType}') {`);
} else {
w.writeLine(`if (props.${sPropName}) {`);
}
}
if (isAdditional) {
if (isArray && isClass) {
w.writeLine(`${!req ? ' ' : ''}this._${sPropName} = props.${sPropName}.map((p) => Object.keys(p).reduce((prev, key) => {
return { ...prev, [key]: new ${pType}(p[key])};
},{}))`);
} else if (isClass) {
w.writeLine(`${!req ? ' ' : ''}this._${sPropName} = Object.keys(props.${sPropName}).reduce((prev, key) => {
return { ...prev, [key]: new ${pType}(props.${sPropName}[key])};
},{})`);
} else {
if (pType === 'string' && !isArray) {
w.writeLine(`${!req ? ' ' : ''}this._${sPropName} = Object.keys(props.${sPropName}).reduce((prev, key) => {
return { ...prev, [key]: props.${sPropName}[key].trim()};
},{})`);
} else {
w.writeLine(`${!req ? ' ' : ''}this._${sPropName} = Object.keys(props.${sPropName}).reduce((prev, key) => {
return { ...prev, [key]: props.${sPropName}[key]};
},{})`);
}
}
} else {
if (isArray && isClass) {
w.writeLine(`${!req ? ' ' : ''}this._${sPropName} = props.${sPropName}.map((p) => new ${pType}(p));`);
} else if (isClass) {
w.writeLine(`${!req ? ' ' : ''}this._${sPropName} = new ${pType}(props.${sPropName});`);
} else {
if (pType === 'string' && !isArray) {
w.writeLine(`${!req ? ' ' : ''}this._${sPropName} = props.${sPropName}.trim();`);
} else {
w.writeLine(`${!req ? ' ' : ''}this._${sPropName} = props.${sPropName};`);
}
}
}
if (!req) {
w.writeLine('}');
}
});
});
// add serialize method;
const serialize = entityClass.addMethod({
isStatic: false,
name: 'serialize',
returnType: `I${sName}`,
});
serialize.setBodyText((w) => {
if (additionalProperties) {
const [
pType, isArray, isClass, isImport, isAdditional
] = schemaParamParser(additionalProperties, this.openapi);
w.writeLine(`return Object.entries(this.${additionalPropsOnly ? 'data' : `${uncapitalize(pType)}Data`}).reduce<Record<string, ${isClass ? 'I' : ''}${pType}>>((prev, [key, value]) => {`);
if (isClass) {
w.writeLine(` prev[key] = value.serialize();`);
} else {
w.writeLine(' prev[key] = value;')
}
w.writeLine(' return prev;');
w.writeLine('}, {})');
return;
}
w.writeLine(`const data: I${sName} = {`);
const unReqFields: string[] = [];
sortedSProps.forEach((sPropName) => {
const req = (required && required.includes(sPropName))
|| sProps[sPropName].required;
const [, isArray, isClass, , isAdditional] = schemaParamParser(sProps[sPropName], this.openapi);
if (!req) {
unReqFields.push(sPropName);
return;
}
if (isAdditional) {
if (isArray && isClass) {
w.writeLine(` ${sPropName}: this._${sPropName}.map((p) => Object.keys(p).reduce((prev, key) => ({ ...prev, [key]: p[key].serialize() }))),`);
} else if (isClass) {
w.writeLine(` ${sPropName}: Object.keys(this._${sPropName}).reduce<Record<string, any>>((prev, key) => ({ ...prev, [key]: this._${sPropName}[key].serialize() }), {}),`);
} else {
w.writeLine(` ${sPropName}: Object.keys(this._${sPropName}).reduce((prev, key) => ({ ...prev, [key]: this._${sPropName}[key] })),`);
}
} else {
if (isArray && isClass) {
w.writeLine(` ${sPropName}: this._${sPropName}.map((p) => p.serialize()),`);
} else if (isClass) {
w.writeLine(` ${sPropName}: this._${sPropName}.serialize(),`);
} else {
w.writeLine(` ${sPropName}: this._${sPropName},`);
}
}
});
w.writeLine('};');
unReqFields.forEach((sPropName) => {
const [, isArray, isClass, , isAdditional] = schemaParamParser(sProps[sPropName], this.openapi);
w.writeLine(`if (typeof this._${sPropName} !== 'undefined') {`);
if (isAdditional) {
if (isArray && isClass) {
w.writeLine(` data.${sPropName} = this._${sPropName}.map((p) => Object.keys(p).reduce((prev, key) => ({ ...prev, [key]: p[key].serialize() }), {}));`);
} else if (isClass) {
w.writeLine(` data.${sPropName} = Object.keys(this._${sPropName}).reduce((prev, key) => ({ ...prev, [key]: this._${sPropName}[key].serialize() }), {});`);
} else {
w.writeLine(` data.${sPropName} = Object.keys(this._${sPropName}).reduce((prev, key) => ({ ...prev, [key]: this._${sPropName}[key] }), {});`);
}
} else {
if (isArray && isClass) {
w.writeLine(` data.${sPropName} = this._${sPropName}.map((p) => p.serialize());`);
} else if (isClass) {
w.writeLine(` data.${sPropName} = this._${sPropName}.serialize();`);
} else {
w.writeLine(` data.${sPropName} = this._${sPropName};`);
}
}
w.writeLine(`}`);
});
w.writeLine('return data;');
});
// add validate method
const validate = entityClass.addMethod({
isStatic: false,
name: 'validate',
returnType: `string[]`,
})
validate.setBodyText((w) => {
if (additionalPropsOnly) {
w.writeLine('return []')
return;
}
w.writeLine('const validate = {');
Object.keys(sProps || {}).forEach((sPropName) => {
const [pType, isArray, isClass, , isAdditional] = schemaParamParser(sProps[sPropName], this.openapi);
const { maxLength, minLength, maximum, minimum } = sProps[sPropName];
const isRequired = (required && required.includes(sPropName)) || sProps[sPropName].required;
const nonRequiredCall = isRequired ? `this._${sPropName}` : `!this._${sPropName} ? true : this._${sPropName}`;
if (isArray && isClass) {
w.writeLine(` ${sPropName}: ${nonRequiredCall}.reduce((result, p) => result && p.validate().length === 0, true),`);
} else if (isClass && !isAdditional) {
w.writeLine(` ${sPropName}: ${nonRequiredCall}.validate().length === 0,`);
} else {
if (pType === 'string') {
if (isArray) {
w.writeLine(` ${sPropName}: ${nonRequiredCall}.reduce((result, p) => result && typeof p === 'string', true),`);
} else {
if (typeof minLength === 'number' && maxLength) {
w.writeLine(` ${sPropName}: (${nonRequiredCall}.length >${minLength > 0 ? '=' : ''} ${minLength}) && (${nonRequiredCall}.length <= ${maxLength}),`);
}
if (typeof minLength !== 'number' || !maxLength) {
w.writeLine(` ${sPropName}: ${isRequired ? `typeof this._${sPropName} === 'string'` : `!this._${sPropName} ? true : typeof this._${sPropName} === 'string'`} && !this._${sPropName} ? true : this._${sPropName},`);
}
}
} else if (pType === 'number') {
if (isArray) {
w.writeLine(` ${sPropName}: ${nonRequiredCall}.reduce((result, p) => result && typeof p === 'number', true),`);
} else {
if (typeof minimum === 'number' && maximum) {
w.writeLine(` ${sPropName}: ${isRequired ? `this._${sPropName} >= ${minimum} && this._${sPropName} <= ${maximum}` : `!this._${sPropName} ? true : ((this._${sPropName} >= ${minimum}) && (this._${sPropName} <= ${maximum}))`},`);
}
if (typeof minimum !== 'number' || !maximum) {
w.writeLine(` ${sPropName}: ${isRequired ? `typeof this._${sPropName} === 'number'` : `!this._${sPropName} ? true : typeof this._${sPropName} === 'number'`},`);
}
}
} else if (pType === 'boolean') {
w.writeLine(` ${sPropName}: ${isRequired ? `typeof this._${sPropName} === 'boolean'` : `!this._${sPropName} ? true : typeof this._${sPropName} === 'boolean'`},`);
}
}
});
w.writeLine('};');
w.writeLine('const isError: string[] = [];')
w.writeLine('Object.keys(validate).forEach((key) => {');
w.writeLine(' if (!(validate as any)[key]) {');
w.writeLine(' isError.push(key);');
w.writeLine(' }');
w.writeLine('});');
w.writeLine('return isError;');
});
// add update method;
const update = entityClass.addMethod({
isStatic: false,
name: 'update',
returnType: `${sName}`,
});
update.addParameter({
name: 'props',
type: additionalPropsOnly ? `I${sName}` : `Partial<I${sName}>`,
});
update.setBodyText((w) => { w.writeLine(`return new ${sName}({ ...this.serialize(), ...props });`); });
this.entities.push(entityFile);
};
save = () => {
this.entities.forEach(async (e) => {
await e.saveSync();
});
};
}
export default EntitiesGenerator;

View File

@@ -1,83 +0,0 @@
const toCamel = (s: string) => {
return s.replace(/([-_][a-z])/ig, ($1) => {
return $1.toUpperCase()
.replace('-', '')
.replace('_', '');
});
};
const capitalize = (s: string) => {
return s[0].toUpperCase() + s.slice(1);
};
const uncapitalize = (s: string) => {
return s[0].toLowerCase() + s.slice(1);
};
const TYPES = {
integer: 'number',
float: 'number',
number: 'number',
string: 'string',
boolean: 'boolean',
};
/**
* @param schemaProp: valueof shema.properties[key]
* @param openApi: openapi object
* @returns [propType - basicType or import one, isArray, isClass, isImport]
*/
const schemaParamParser = (schemaProp: any, openApi: any): [string, boolean, boolean, boolean, boolean] => {
let type = '';
let isImport = false;
let isClass = false;
let isArray = false;
let isAdditional = false;
if (schemaProp.$ref || schemaProp.additionalProperties?.$ref) {
const temp = (schemaProp.$ref || schemaProp.additionalProperties?.$ref).split('/');
if (schemaProp.additionalProperties) {
isAdditional = true;
}
type = `${temp[temp.length - 1]}`;
const cl = openApi ? openApi.components.schemas[type] : {};
if (cl.$ref) {
const link = schemaParamParser(cl, openApi);
link.shift();
return [type, ...link] as any;
}
if (cl.type === 'string' && cl.enum) {
isImport = true;
}
if (cl.type === 'object' && !cl.oneOf) {
isClass = true;
isImport = true;
} else if (cl.type === 'array') {
const temp: any = schemaParamParser(cl.items, openApi);
type = `${temp[0]}`;
isArray = true;
isClass = isClass || temp[2];
isImport = isImport || temp[3];
}
} else if (schemaProp.type === 'array') {
const temp: any = schemaParamParser(schemaProp.items, openApi);
type = `${temp[0]}`;
isArray = true;
isClass = isClass || temp[2];
isImport = isImport || temp[3];
} else {
type = (TYPES as Record<any, string>)[schemaProp.type];
}
if (!type) {
// TODO: Fix bug with Error fields.
type = 'any';
// throw new Error('Failed to find entity type');
}
return [type, isArray, isClass, isImport, isAdditional];
};
export { TYPES, toCamel, capitalize, uncapitalize, schemaParamParser };

View File

@@ -1,226 +0,0 @@
import * as fs from 'fs';
import {
Project,
VariableStatement,
SyntaxKind,
Node,
Statement,
ts,
Identifier,
SourceFile,
} from 'ts-morph';
import {
LOCALE_FOLDER_PATH,
TRANSLATOR_CLASS_NAME,
USE_INTL_NAME,
trimQuotes,
} from '../consts';
import { checkForms, AvailableLocales } from '../../src/localization/Translator';
const project = new Project({
tsConfigFilePath: './tsconfig.json',
});
let lang = 'ru';
let option = '';
if (process.argv.length > 2) {
lang = process.argv[2];
option = process.argv[3];
}
const usedTranslations: string[] = [];
const usedPluralTranslations: string[] = [];
const problemFiles: string[] = [];
const sourceFiles = project.getSourceFiles();
const sourceFilesWithIntl = sourceFiles.filter((sf) => {
return !!sf.getImportDeclarations().find((id) => {
return !!id.getNamedImports().find((ni) => ni.getName() === USE_INTL_NAME)
})
});
const getFileUsedIntl = (statements: Statement<ts.Statement>[]) => {
statements.forEach((s) => {
if (s instanceof VariableStatement) {
s.forEachDescendant((node) => {
let intVariableDeclaration: Identifier = null;
switch (node.getKind()) {
case SyntaxKind.VariableDeclaration:
if (node.getSymbol()) {
const name = node.getSymbol().getName();
const callExp = node.getChildren().find((n) => n.getKind() === SyntaxKind.CallExpression);
if (callExp) {
const callExpIden = callExp.getChildren().find(n => n.getKind() === SyntaxKind.Identifier);
if (callExpIden && callExpIden.getSymbol().getName() === USE_INTL_NAME) {
intVariableDeclaration = node as Identifier;
}
}
}
break;
default:
break;
}
if (intVariableDeclaration) {
intVariableDeclaration.findReferencesAsNodes().forEach((fr) => {
if (fr instanceof Node) {
const parent = fr.getParentIfKind(SyntaxKind.PropertyAccessExpression);
if (parent && (parent.getName() === 'getMessage' || parent.getName() === 'getPlural')) {
const syntaxList = parent.getNextSiblings().find((n) => n.getKind() === SyntaxKind.SyntaxList);
if (syntaxList) {
const id = syntaxList.getChildren()[0];
if (id && id.getKind() !== SyntaxKind.StringLiteral) {
problemFiles.push(fr.getSourceFile().getFilePath());
}
if (id) {
usedTranslations.push(trimQuotes(id.getText()));
if (parent.getName() === 'getPlural') {
usedPluralTranslations.push(trimQuotes(id.getText()));
}
}
}
}
}
})
}
});
}
})
}
const getFileUsedTranslations = (file: SourceFile) => {
const namedImport = file.getImportDeclarations().find((id) => !!id.getNamedImports().find((ni) => ni.getName() === TRANSLATOR_CLASS_NAME));
if (namedImport) {
const identifier = namedImport.getImportClause().getNamedImports().find((iden) => iden.getName() === TRANSLATOR_CLASS_NAME);
const translateReferences = identifier.getNodeProperty('name').findReferencesAsNodes();
if (translateReferences.length > 0) {
translateReferences.forEach((identifierNode) => {
if (identifierNode.getParentIfKind(SyntaxKind.TypeReference)) {
const translatorVariable = identifierNode.getParent().getPreviousSibling().getPreviousSiblingIfKind(SyntaxKind.Identifier);
if (translatorVariable) {
translatorVariable.findReferencesAsNodes().forEach((node) => {
const parent = node.getParentIfKind(SyntaxKind.PropertyAccessExpression);
if (parent && (parent.getName() === 'getMessage' || parent.getName() === 'getPlural')) {
const syntaxList = parent.getNextSiblings().find((n) => n.getKind() === SyntaxKind.SyntaxList);
if (syntaxList) {
const id = syntaxList.getChildren()[0];
if (id && id.getKind() !== SyntaxKind.StringLiteral) {
problemFiles.push(parent.getSourceFile().getFilePath());
}
if (id) {
usedTranslations.push(trimQuotes(id.getText()));
if (parent.getName() === 'getPlural') {
usedPluralTranslations.push(trimQuotes(id.getText()));
}
}
}
}
})
}
}
})
}
}
}
sourceFilesWithIntl.forEach((file) => {
getFileUsedIntl(file.getStatements());
})
const sourceFilesWithTranslator = project.getSourceFiles().filter((sf) => {
return !!sf.getImportDeclarations().find((id) => {
return !!id.getNamedImports().find((ni) => ni.getName() === TRANSLATOR_CLASS_NAME)
})
});
sourceFilesWithTranslator.forEach((file) => {
getFileUsedTranslations(file);
})
const filteredUsedTranslations = Array.from(new Set(usedTranslations));
const filteredUsedPluralTranslations = Array.from(new Set(usedPluralTranslations));
if (problemFiles.length) {
console.warn(`\n============== Files where translation id provided not as string ==============\n`);
console.log(problemFiles.join('\n'));
process.exit(255);
}
const allFiles = fs.readdirSync(LOCALE_FOLDER_PATH);
// Use ru or needed language
const translationFile = allFiles.find((file) => file.includes(`${lang}.json`));
if (!translationFile) {
console.error('File not found');
process.exit(255);
}
const translationsObject = JSON.parse(fs.readFileSync(`./src/lib/intl/__locales/${translationFile}`, { flag: 'r+' }) as unknown as string);
const translations = {
locale: translationFile,
messages: Object.keys(translationsObject),
};
const someMessagesNotFound: string[] = [];
const notUsed: string[] = [];
const notFound: string[] = [];
const checkLocaleMessages = (locale: string, messages: string[]) => {
filteredUsedTranslations.forEach(f => {
if (!messages.includes(f)) {
notFound.push(f);
}
});
messages.forEach(t => {
if (!filteredUsedTranslations.includes(t)) {
notUsed.push(t);
}
});
if (notFound.length > 0) {
someMessagesNotFound.push(locale);
}
}
const render = (data: string[], title: string) => {
console.log(`============ ${title} ============`);
console.table(data);
console.log(`============ ${title} ============`);
}
checkLocaleMessages(translations.locale, translations.messages);
const checkPluralForm = () => {
const pluralFormWrong: string[] = [];
filteredUsedPluralTranslations.forEach((id) => {
const message = translationsObject[id];
if (!checkForms(message, lang as AvailableLocales, id)) {
pluralFormWrong.push(id)
}
});
return pluralFormWrong;
}
const plural = checkPluralForm();
if (!option && (someMessagesNotFound.length || plural.length > 0 )) {
someMessagesNotFound.forEach(locale => console.error(`\nSome translatins for ${locale} was not found!\n`));
plural.forEach(id => console.error(`\nTranslation with id: "${id}" - have wrong number of plural forms!\n`));
process.exit(255);
}
if (option) {
switch (option) {
case '--show-missing': {
render(notFound, 'NotFound')
break;
}
case '--show-unused': {
render(notUsed, 'notUsed')
break;
}
case '--check-plurals': {
render(plural, 'Wrong Plural Form')
}
default: {
if (someMessagesNotFound.length) {
someMessagesNotFound.forEach(locale => console.error(`\nSome translatins for ${locale} was not found!\n\n`));
process.exit(255);
}
}
}
}

View File

@@ -1,79 +0,0 @@
module.exports = {
parser: '@typescript-eslint/parser',
parserOptions: {
project: './tsconfig.json',
ecmaFeatures: {
jsx: true
},
extraFileExtensions: ['mjs', 'tsx', 'ts'],
ecmaVersion: 2020,
sourceType: 'module'
},
plugins: ['react', '@typescript-eslint', 'import'],
env: {
browser: true,
commonjs: true,
es6: true,
es2020: true,
jest: true,
},
settings: {
react: {
pragma: 'React',
version: 'detect',
},
'import/resolver': {
typescript: {
alwaysTryTypes: true
}
},
'import/parsers': {
'@typescript-eslint/parser': ['.ts', '.tsx'],
},
},
rules: {
'@typescript-eslint/explicit-module-boundary-types': 0,
'@typescript-eslint/explicit-function-return-type': [0, { allowExpressions: true }],
'@typescript-eslint/indent': ['error', 4],
'@typescript-eslint/interface-name-prefix': [0, { prefixWithI: 'never' }],
'@typescript-eslint/no-explicit-any': [0],
'@typescript-eslint/naming-convention': [2, {
selector: 'enum', format: ['UPPER_CASE', 'PascalCase'],
}],
'@typescript-eslint/no-non-null-assertion': 0,
'arrow-body-style': 'off',
'consistent-return': 0,
curly: [2, 'all'],
'default-case': 0,
'import/no-cycle': 0,
'import/prefer-default-export': 'off',
'import/no-named-as-default': 0,
indent: [0, 4],
'no-alert': 2,
'no-console': 2,
'no-debugger': 2,
'no-underscore-dangle': 'off',
'no-useless-escape': 'off',
'object-curly-newline': 'off',
'react-hooks/exhaustive-deps': 0,
'react/display-name': 0,
'react/jsx-indent-props': ['error', 4],
'react/jsx-indent': ['error', 4],
'react/jsx-one-expression-per-line': 'off',
'react/jsx-props-no-spreading': 0,
'react/prop-types': 'off',
'react/state-in-constructor': 'off',
},
extends: [
'airbnb-base',
'airbnb-typescript/base',
'airbnb/hooks',
'plugin:react/recommended',
'plugin:@typescript-eslint/eslint-recommended',
'plugin:@typescript-eslint/recommended',
'plugin:import/errors',
'plugin:import/warnings',
'plugin:import/typescript',
],
globals: {},
};

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