Compare commits
58 Commits
v0.107.0-b
...
fix-stats-
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
02834e6b7b | ||
|
|
b45162a0f2 | ||
|
|
ce0df255be | ||
|
|
b735c8167c | ||
|
|
2ac2ad0609 | ||
|
|
37a3666a2a | ||
|
|
5aed8db5cf | ||
|
|
e1e064db59 | ||
|
|
b1242ee93f | ||
|
|
5f3131c799 | ||
|
|
1714a986e3 | ||
|
|
6ac28ee8ee | ||
|
|
bf1263628a | ||
|
|
176a344aee | ||
|
|
48b0cefb29 | ||
|
|
857f876486 | ||
|
|
eeb99db973 | ||
|
|
9a1d3ec694 | ||
|
|
fac574d324 | ||
|
|
53f7c0b2df | ||
|
|
424f20da98 | ||
|
|
8fdd789474 | ||
|
|
80548233ba | ||
|
|
eeda06f9b0 | ||
|
|
b77ceaaf55 | ||
|
|
bdd0ca5423 | ||
|
|
138718e6ec | ||
|
|
2365ddd2f2 | ||
|
|
bb4cd312c2 | ||
|
|
1265be507a | ||
|
|
e064e0f277 | ||
|
|
595441603f | ||
|
|
d1de47b636 | ||
|
|
e5c73877c8 | ||
|
|
77821ec816 | ||
|
|
9f52adf33d | ||
|
|
8454e65cd9 | ||
|
|
756c70644d | ||
|
|
16092e8ba9 | ||
|
|
b92db25e6a | ||
|
|
b81030ba70 | ||
|
|
9809ed8019 | ||
|
|
9246c1340e | ||
|
|
550b1798a1 | ||
|
|
d2c9052dde | ||
|
|
f8fe4b310f | ||
|
|
6013f7ce3e | ||
|
|
91c1c9e61d | ||
|
|
42b2c3ab85 | ||
|
|
784bc318ca | ||
|
|
8e667d3cc4 | ||
|
|
394c2f65e0 | ||
|
|
e3ad46876f | ||
|
|
506b459842 | ||
|
|
00f2927663 | ||
|
|
9bd7294fad | ||
|
|
133a1c57b1 | ||
|
|
89b3af128a |
1
.github/stale.yml
vendored
1
.github/stale.yml
vendored
@@ -5,6 +5,7 @@
|
|||||||
# Issues with these labels will never be considered stale.
|
# Issues with these labels will never be considered stale.
|
||||||
'exemptLabels':
|
'exemptLabels':
|
||||||
- 'bug'
|
- 'bug'
|
||||||
|
- 'documentation'
|
||||||
- 'enhancement'
|
- 'enhancement'
|
||||||
- 'feature request'
|
- 'feature request'
|
||||||
- 'localization'
|
- 'localization'
|
||||||
|
|||||||
@@ -19,7 +19,7 @@
|
|||||||
"it": "Italiano",
|
"it": "Italiano",
|
||||||
"ja": "日本語",
|
"ja": "日本語",
|
||||||
"ko": "한국어",
|
"ko": "한국어",
|
||||||
"nl": "Dutch",
|
"nl": "Nederlands",
|
||||||
"no": "Norsk",
|
"no": "Norsk",
|
||||||
"pl": "Polski",
|
"pl": "Polski",
|
||||||
"pt-br": "Português (BR)",
|
"pt-br": "Português (BR)",
|
||||||
|
|||||||
@@ -232,7 +232,7 @@ Deactivate DNSStubListener and update DNS server address. Create a new file: `/
|
|||||||
DNS=127.0.0.1
|
DNS=127.0.0.1
|
||||||
DNSStubListener=no
|
DNSStubListener=no
|
||||||
|
|
||||||
Specifying "127.0.0.1" as DNS server address is necessry because otherwise the nameserver will be "127.0.0.53" which doesn't work without DNSStubListener.
|
Specifying "127.0.0.1" as DNS server address is necessary because otherwise the nameserver will be "127.0.0.53" which doesn't work without DNSStubListener.
|
||||||
|
|
||||||
Activate another resolv.conf file:
|
Activate another resolv.conf file:
|
||||||
|
|
||||||
@@ -421,7 +421,8 @@ Enable DHCP server algorithm:
|
|||||||
|
|
||||||
DHCP leases are used in several ways by DNS module.
|
DHCP leases are used in several ways by DNS module.
|
||||||
|
|
||||||
* For "A" DNS reqeust we reply with an IP address leased by our DHCP server.
|
* For "A" DNS request we reply with an IP address leased by our DHCP server.
|
||||||
|
|
||||||
|
|
||||||
< A bills-notebook.lan.
|
< A bills-notebook.lan.
|
||||||
> A bills-notebook.lan. = 192.168.1.100
|
> A bills-notebook.lan. = 192.168.1.100
|
||||||
@@ -564,7 +565,7 @@ Request:
|
|||||||
"gateway_ip":"192.169.56.1",
|
"gateway_ip":"192.169.56.1",
|
||||||
"subnet_mask":"255.255.255.0",
|
"subnet_mask":"255.255.255.0",
|
||||||
"range_start":"192.169.56.100",
|
"range_start":"192.169.56.100",
|
||||||
"range_end":"192.169.56.200", // Note: first 3 octects must match "range_start"
|
"range_end":"192.169.56.200", // Note: first 3 octets must match "range_start"
|
||||||
"lease_duration":60,
|
"lease_duration":60,
|
||||||
},
|
},
|
||||||
"v6":{
|
"v6":{
|
||||||
|
|||||||
90
CHANGELOG.md
90
CHANGELOG.md
@@ -10,11 +10,15 @@ and this project adheres to
|
|||||||
## [Unreleased]
|
## [Unreleased]
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
## [v0.107.0] - 2021-08-03 (APPROX.)
|
## [v0.107.0] - 2021-09-28 (APPROX.)
|
||||||
-->
|
-->
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
- DNS server IP addresses to the `mobileconfig` API responses ([#3568],
|
||||||
|
[#3607]).
|
||||||
|
- Setting the timeout for IP address pinging in the "Fastest IP address" mode
|
||||||
|
through the new `fastest_timeout` field in the configuration file ([#1992]).
|
||||||
- Static IP address detection on FreeBSD ([#3289]).
|
- Static IP address detection on FreeBSD ([#3289]).
|
||||||
- Optimistic cache ([#2145]).
|
- Optimistic cache ([#2145]).
|
||||||
- New possible value of `6h` for `querylog_interval` setting ([#2504]).
|
- New possible value of `6h` for `querylog_interval` setting ([#2504]).
|
||||||
@@ -27,7 +31,8 @@ and this project adheres to
|
|||||||
- Settable timeouts for querying the upstream servers ([#2280]).
|
- Settable timeouts for querying the upstream servers ([#2280]).
|
||||||
- Configuration file parameters to change group and user ID on startup on Unix
|
- Configuration file parameters to change group and user ID on startup on Unix
|
||||||
([#2763]).
|
([#2763]).
|
||||||
- Experimental OpenBSD support for AMD64 and 64-bit ARM CPUs ([#2439]).
|
- Experimental OpenBSD support for AMD64 and 64-bit ARM CPUs ([#2439], [#3225],
|
||||||
|
[#3226]).
|
||||||
- Support for custom port in DNS-over-HTTPS profiles for Apple's devices
|
- Support for custom port in DNS-over-HTTPS profiles for Apple's devices
|
||||||
([#3172]).
|
([#3172]).
|
||||||
- `darwin/arm64` support ([#2443]).
|
- `darwin/arm64` support ([#2443]).
|
||||||
@@ -43,6 +48,13 @@ and this project adheres to
|
|||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
- The `systemd` service script will now create the `/var/log` directory when it
|
||||||
|
doesn't exist ([#3579]).
|
||||||
|
- Items in allowed clients, disallowed clients, and blocked hosts lists are now
|
||||||
|
required to be unique ([#3419]).
|
||||||
|
- The TLS private key previously saved as a string isn't shown in API responses
|
||||||
|
anymore ([#1898]).
|
||||||
|
- Better OpenWrt detection ([#3435]).
|
||||||
- DNS-over-HTTPS queries that come from HTTP proxies in the `trusted_proxies`
|
- DNS-over-HTTPS queries that come from HTTP proxies in the `trusted_proxies`
|
||||||
list now use the real IP address of the client instead of the address of the
|
list now use the real IP address of the client instead of the address of the
|
||||||
proxy ([#2799]).
|
proxy ([#2799]).
|
||||||
@@ -58,12 +70,64 @@ and this project adheres to
|
|||||||
file, together with the new `group` and `user` settings ([#2763]).
|
file, together with the new `group` and `user` settings ([#2763]).
|
||||||
- Permissions on filter files are now `0o644` instead of `0o600` ([#3198]).
|
- Permissions on filter files are now `0o644` instead of `0o600` ([#3198]).
|
||||||
|
|
||||||
|
#### Configuration Changes
|
||||||
|
|
||||||
|
In this release, the schema version has changed from 10 to 12.
|
||||||
|
|
||||||
|
- Parameter `dns.querylog_interval`, which in schema versions 11 and earlier
|
||||||
|
used to be an integer number of days, is now a string with a human-readable
|
||||||
|
duration:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# BEFORE:
|
||||||
|
'dns':
|
||||||
|
# …
|
||||||
|
'querylog_interval': 90
|
||||||
|
|
||||||
|
# AFTER:
|
||||||
|
'dns':
|
||||||
|
# …
|
||||||
|
'querylog_interval': '2160h'
|
||||||
|
```
|
||||||
|
|
||||||
|
To rollback this change, convert the parameter back into days and change the
|
||||||
|
`schema_version` back to `11`.
|
||||||
|
|
||||||
|
- Parameter `rlimit_nofile`, which in schema versions 10 and earlier used to be
|
||||||
|
on the top level, is now moved to the new `os` object:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
# BEFORE:
|
||||||
|
'rlimit_nofile': 42
|
||||||
|
|
||||||
|
# AFTER:
|
||||||
|
'os':
|
||||||
|
'group': ''
|
||||||
|
'rlimit_nofile': 42
|
||||||
|
'user': ''
|
||||||
|
```
|
||||||
|
|
||||||
|
To rollback this change, move the parameter on the top level and change the
|
||||||
|
`schema_version` back to `10`.
|
||||||
|
|
||||||
### Deprecated
|
### Deprecated
|
||||||
|
|
||||||
- Go 1.16 support. v0.108.0 will require at least Go 1.17 to build.
|
- Go 1.16 support. v0.108.0 will require at least Go 1.17 to build.
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
|
- Adding an IP into only one of the matching ipsets on Linux ([#3638]).
|
||||||
|
- Removal of temporary filter files ([#3567]).
|
||||||
|
- Panic when an upstream server responds with an empty question section
|
||||||
|
([#3551]).
|
||||||
|
- 9GAG blocking ([#3564]).
|
||||||
|
- DHCP now follows RFCs more closely when it comes to response sending and
|
||||||
|
option selection ([#3443], [#3538]).
|
||||||
|
- Occasional panics when reading old statistics databases ([#3506]).
|
||||||
|
- `reload` service action on macOS and FreeBSD ([#3457]).
|
||||||
|
- Inaccurate using of service actions in the installation script ([#3450]).
|
||||||
|
- Client ID checking ([#3437]).
|
||||||
|
- Discovering other DHCP servers on `darwin` and `freebsd` ([#3417]).
|
||||||
- Switching listening address to unspecified one when bound to a single
|
- Switching listening address to unspecified one when bound to a single
|
||||||
specified IPv4 address on Darwin (macOS) ([#2807]).
|
specified IPv4 address on Darwin (macOS) ([#2807]).
|
||||||
- Incomplete HTTP response for static IP address.
|
- Incomplete HTTP response for static IP address.
|
||||||
@@ -89,6 +153,8 @@ and this project adheres to
|
|||||||
|
|
||||||
[#1381]: https://github.com/AdguardTeam/AdGuardHome/issues/1381
|
[#1381]: https://github.com/AdguardTeam/AdGuardHome/issues/1381
|
||||||
[#1691]: https://github.com/AdguardTeam/AdGuardHome/issues/1691
|
[#1691]: https://github.com/AdguardTeam/AdGuardHome/issues/1691
|
||||||
|
[#1898]: https://github.com/AdguardTeam/AdGuardHome/issues/1898
|
||||||
|
[#1992]: https://github.com/AdguardTeam/AdGuardHome/issues/1992
|
||||||
[#2141]: https://github.com/AdguardTeam/AdGuardHome/issues/2141
|
[#2141]: https://github.com/AdguardTeam/AdGuardHome/issues/2141
|
||||||
[#2145]: https://github.com/AdguardTeam/AdGuardHome/issues/2145
|
[#2145]: https://github.com/AdguardTeam/AdGuardHome/issues/2145
|
||||||
[#2280]: https://github.com/AdguardTeam/AdGuardHome/issues/2280
|
[#2280]: https://github.com/AdguardTeam/AdGuardHome/issues/2280
|
||||||
@@ -112,6 +178,8 @@ and this project adheres to
|
|||||||
[#3194]: https://github.com/AdguardTeam/AdGuardHome/issues/3194
|
[#3194]: https://github.com/AdguardTeam/AdGuardHome/issues/3194
|
||||||
[#3198]: https://github.com/AdguardTeam/AdGuardHome/issues/3198
|
[#3198]: https://github.com/AdguardTeam/AdGuardHome/issues/3198
|
||||||
[#3217]: https://github.com/AdguardTeam/AdGuardHome/issues/3217
|
[#3217]: https://github.com/AdguardTeam/AdGuardHome/issues/3217
|
||||||
|
[#3225]: https://github.com/AdguardTeam/AdGuardHome/issues/3225
|
||||||
|
[#3226]: https://github.com/AdguardTeam/AdGuardHome/issues/3226
|
||||||
[#3256]: https://github.com/AdguardTeam/AdGuardHome/issues/3256
|
[#3256]: https://github.com/AdguardTeam/AdGuardHome/issues/3256
|
||||||
[#3257]: https://github.com/AdguardTeam/AdGuardHome/issues/3257
|
[#3257]: https://github.com/AdguardTeam/AdGuardHome/issues/3257
|
||||||
[#3289]: https://github.com/AdguardTeam/AdGuardHome/issues/3289
|
[#3289]: https://github.com/AdguardTeam/AdGuardHome/issues/3289
|
||||||
@@ -119,6 +187,22 @@ and this project adheres to
|
|||||||
[#3343]: https://github.com/AdguardTeam/AdGuardHome/issues/3343
|
[#3343]: https://github.com/AdguardTeam/AdGuardHome/issues/3343
|
||||||
[#3351]: https://github.com/AdguardTeam/AdGuardHome/issues/3351
|
[#3351]: https://github.com/AdguardTeam/AdGuardHome/issues/3351
|
||||||
[#3372]: https://github.com/AdguardTeam/AdGuardHome/issues/3372
|
[#3372]: https://github.com/AdguardTeam/AdGuardHome/issues/3372
|
||||||
|
[#3417]: https://github.com/AdguardTeam/AdGuardHome/issues/3417
|
||||||
|
[#3419]: https://github.com/AdguardTeam/AdGuardHome/issues/3419
|
||||||
|
[#3435]: https://github.com/AdguardTeam/AdGuardHome/issues/3435
|
||||||
|
[#3437]: https://github.com/AdguardTeam/AdGuardHome/issues/3437
|
||||||
|
[#3443]: https://github.com/AdguardTeam/AdGuardHome/issues/3443
|
||||||
|
[#3450]: https://github.com/AdguardTeam/AdGuardHome/issues/3450
|
||||||
|
[#3457]: https://github.com/AdguardTeam/AdGuardHome/issues/3457
|
||||||
|
[#3506]: https://github.com/AdguardTeam/AdGuardHome/issues/3506
|
||||||
|
[#3538]: https://github.com/AdguardTeam/AdGuardHome/issues/3538
|
||||||
|
[#3551]: https://github.com/AdguardTeam/AdGuardHome/issues/3551
|
||||||
|
[#3564]: https://github.com/AdguardTeam/AdGuardHome/issues/3564
|
||||||
|
[#3567]: https://github.com/AdguardTeam/AdGuardHome/issues/3567
|
||||||
|
[#3568]: https://github.com/AdguardTeam/AdGuardHome/issues/3568
|
||||||
|
[#3579]: https://github.com/AdguardTeam/AdGuardHome/issues/3579
|
||||||
|
[#3607]: https://github.com/AdguardTeam/AdGuardHome/issues/3607
|
||||||
|
[#3638]: https://github.com/AdguardTeam/AdGuardHome/issues/3638
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -322,7 +406,7 @@ and this project adheres to
|
|||||||
- The field `"range_start"` in the `GET /control/dhcp/status` HTTP API response
|
- The field `"range_start"` in the `GET /control/dhcp/status` HTTP API response
|
||||||
is now correctly named again ([#2678]).
|
is now correctly named again ([#2678]).
|
||||||
- DHCPv6 server's `ra_slaac_only` and `ra_allow_slaac` settings aren't reset to
|
- DHCPv6 server's `ra_slaac_only` and `ra_allow_slaac` settings aren't reset to
|
||||||
`false` on update any more ([#2653]).
|
`false` on update anymore ([#2653]).
|
||||||
- The `Vary` header is now added along with `Access-Control-Allow-Origin` to
|
- The `Vary` header is now added along with `Access-Control-Allow-Origin` to
|
||||||
prevent cache-related and other issues in browsers ([#2658]).
|
prevent cache-related and other issues in browsers ([#2658]).
|
||||||
- The request body size limit is now set for HTTPS requests as well.
|
- The request body size limit is now set for HTTPS requests as well.
|
||||||
|
|||||||
619
client/package-lock.json
generated
vendored
619
client/package-lock.json
generated
vendored
@@ -70,15 +70,6 @@
|
|||||||
"ms": "^2.1.1"
|
"ms": "^2.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"json5": {
|
|
||||||
"version": "2.1.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz",
|
|
||||||
"integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"minimist": "^1.2.5"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"ms": {
|
"ms": {
|
||||||
"version": "2.1.2",
|
"version": "2.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
|
||||||
@@ -1188,16 +1179,6 @@
|
|||||||
"regenerator-runtime": "^0.13.4"
|
"regenerator-runtime": "^0.13.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"@babel/runtime-corejs3": {
|
|
||||||
"version": "7.9.6",
|
|
||||||
"resolved": "https://registry.npmjs.org/@babel/runtime-corejs3/-/runtime-corejs3-7.9.6.tgz",
|
|
||||||
"integrity": "sha512-6toWAfaALQjt3KMZQc6fABqZwUDDuWzz+cAfPhqyEnzxvdWOAkjwPNxgF8xlmo7OWLsSjaKjsskpKHRLaMArOA==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"core-js-pure": "^3.0.0",
|
|
||||||
"regenerator-runtime": "^0.13.4"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"@babel/template": {
|
"@babel/template": {
|
||||||
"version": "7.8.6",
|
"version": "7.8.6",
|
||||||
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz",
|
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.8.6.tgz",
|
||||||
@@ -1909,11 +1890,6 @@
|
|||||||
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"kind-of": {
|
|
||||||
"version": "6.0.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.2.tgz",
|
|
||||||
"integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA=="
|
|
||||||
},
|
|
||||||
"micromatch": {
|
"micromatch": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.2.tgz",
|
||||||
@@ -2875,13 +2851,15 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"array-includes": {
|
"array-includes": {
|
||||||
"version": "3.1.1",
|
"version": "3.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.3.tgz",
|
||||||
"integrity": "sha512-c2VXaCHl7zPsvpkFsw4nxvFie4fh1ur9bpcgsVkIjqn0H/Xwdg+7fv3n2r/isyS8EBj5b06M9kHyZuIr4El6WQ==",
|
"integrity": "sha512-gcem1KlBU7c9rB+Rq8/3PPKsK2kjqeEBa3bD5kkQo4nYlOHQCJqIJFqBXDEfwaRuYTT4E+FxA9xez7Gf/e3Q7A==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
"call-bind": "^1.0.2",
|
||||||
"define-properties": "^1.1.3",
|
"define-properties": "^1.1.3",
|
||||||
"es-abstract": "^1.17.0",
|
"es-abstract": "^1.18.0-next.2",
|
||||||
|
"get-intrinsic": "^1.1.1",
|
||||||
"is-string": "^1.0.5"
|
"is-string": "^1.0.5"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -2907,13 +2885,26 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"array.prototype.flat": {
|
"array.prototype.flat": {
|
||||||
"version": "1.2.3",
|
"version": "1.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.3.tgz",
|
"resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.2.4.tgz",
|
||||||
"integrity": "sha512-gBlRZV0VSmfPIeWfuuy56XZMvbVfbEUnOXUvt3F/eUUUSyzlgLxhEX4YAEpxNAogRGehPSnfXyPtYyKAhkzQhQ==",
|
"integrity": "sha512-4470Xi3GAPAjZqFcljX2xzckv1qeKPizoNkiS0+O4IoPR2ZNpcjE0pkhdihlDouK+x6QOast26B4Q/O9DJnwSg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
"call-bind": "^1.0.0",
|
||||||
"define-properties": "^1.1.3",
|
"define-properties": "^1.1.3",
|
||||||
"es-abstract": "^1.17.0-next.1"
|
"es-abstract": "^1.18.0-next.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"array.prototype.flatmap": {
|
||||||
|
"version": "1.2.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.2.4.tgz",
|
||||||
|
"integrity": "sha512-r9Z0zYoxqHz60vvQbWEdXIEtCwHF0yxaWfno9qzXeNHvfyl3BZqygmGzb84dsubyaXLH4husF+NFgMSdpZhk2Q==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"call-bind": "^1.0.0",
|
||||||
|
"define-properties": "^1.1.3",
|
||||||
|
"es-abstract": "^1.18.0-next.1",
|
||||||
|
"function-bind": "^1.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"arrify": {
|
"arrify": {
|
||||||
@@ -3197,11 +3188,6 @@
|
|||||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"minimist": {
|
|
||||||
"version": "1.2.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz",
|
|
||||||
"integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ="
|
|
||||||
},
|
|
||||||
"supports-color": {
|
"supports-color": {
|
||||||
"version": "7.1.0",
|
"version": "7.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.1.0.tgz",
|
||||||
@@ -3863,6 +3849,15 @@
|
|||||||
"unset-value": "^1.0.0"
|
"unset-value": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"call-bind": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
|
||||||
|
"requires": {
|
||||||
|
"function-bind": "^1.1.1",
|
||||||
|
"get-intrinsic": "^1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"caller-callsite": {
|
"caller-callsite": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz",
|
||||||
@@ -4325,12 +4320,6 @@
|
|||||||
"integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=",
|
"integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"contains-path": {
|
|
||||||
"version": "0.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/contains-path/-/contains-path-0.1.0.tgz",
|
|
||||||
"integrity": "sha1-/ozxhP9mcLa67wGp1IYaXL7EEgo=",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"content-disposition": {
|
"content-disposition": {
|
||||||
"version": "0.5.3",
|
"version": "0.5.3",
|
||||||
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
|
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
|
||||||
@@ -4550,12 +4539,6 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"core-js-pure": {
|
|
||||||
"version": "3.6.5",
|
|
||||||
"resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.6.5.tgz",
|
|
||||||
"integrity": "sha512-lacdXOimsiD0QyNf9BC/mxivNJ/ybBGJXQFKzRekp1WTHoVUWsUHEn+2T8GJAzzIhyOuXA+gOxCVN3l+5PLPUA==",
|
|
||||||
"dev": true
|
|
||||||
},
|
|
||||||
"core-util-is": {
|
"core-util-is": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
|
||||||
@@ -5421,21 +5404,27 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"es-abstract": {
|
"es-abstract": {
|
||||||
"version": "1.17.5",
|
"version": "1.18.5",
|
||||||
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz",
|
"resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.18.5.tgz",
|
||||||
"integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==",
|
"integrity": "sha512-DDggyJLoS91CkJjgauM5c0yZMjiD1uK3KcaCeAmffGwZ+ODWzOkPN4QwRbsK5DOFf06fywmyLci3ZD8jLGhVYA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
|
"call-bind": "^1.0.2",
|
||||||
"es-to-primitive": "^1.2.1",
|
"es-to-primitive": "^1.2.1",
|
||||||
"function-bind": "^1.1.1",
|
"function-bind": "^1.1.1",
|
||||||
|
"get-intrinsic": "^1.1.1",
|
||||||
"has": "^1.0.3",
|
"has": "^1.0.3",
|
||||||
"has-symbols": "^1.0.1",
|
"has-symbols": "^1.0.2",
|
||||||
"is-callable": "^1.1.5",
|
"internal-slot": "^1.0.3",
|
||||||
"is-regex": "^1.0.5",
|
"is-callable": "^1.2.3",
|
||||||
"object-inspect": "^1.7.0",
|
"is-negative-zero": "^2.0.1",
|
||||||
|
"is-regex": "^1.1.3",
|
||||||
|
"is-string": "^1.0.6",
|
||||||
|
"object-inspect": "^1.11.0",
|
||||||
"object-keys": "^1.1.1",
|
"object-keys": "^1.1.1",
|
||||||
"object.assign": "^4.1.0",
|
"object.assign": "^4.1.2",
|
||||||
"string.prototype.trimleft": "^2.1.1",
|
"string.prototype.trimend": "^1.0.4",
|
||||||
"string.prototype.trimright": "^2.1.1"
|
"string.prototype.trimstart": "^1.0.4",
|
||||||
|
"unbox-primitive": "^1.0.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"es-to-primitive": {
|
"es-to-primitive": {
|
||||||
@@ -5658,22 +5647,38 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"eslint-import-resolver-node": {
|
"eslint-import-resolver-node": {
|
||||||
"version": "0.3.3",
|
"version": "0.3.6",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.3.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.6.tgz",
|
||||||
"integrity": "sha512-b8crLDo0M5RSe5YG8Pu2DYBj71tSB6OvXkfzwbJU2w7y8P4/yo0MyF8jU26IEuEuHF2K5/gcAJE3LhQGqBBbVg==",
|
"integrity": "sha512-0En0w03NRVMn9Uiyn8YRPDKvWjxCWkslUEhGNTdGx15RvPJYQ+lbOlqrlNI2vEAs4pDYK4f/HN2TbDmk5TP0iw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"debug": "^2.6.9",
|
"debug": "^3.2.7",
|
||||||
"resolve": "^1.13.1"
|
"resolve": "^1.20.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"debug": {
|
"debug": {
|
||||||
"version": "2.6.9",
|
"version": "3.2.7",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
|
||||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ms": "2.0.0"
|
"ms": "^2.1.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"ms": {
|
||||||
|
"version": "2.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||||
|
"dev": true
|
||||||
|
},
|
||||||
|
"resolve": {
|
||||||
|
"version": "1.20.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
|
||||||
|
"integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"is-core-module": "^2.2.0",
|
||||||
|
"path-parse": "^1.0.6"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5741,15 +5746,6 @@
|
|||||||
"path-exists": "^4.0.0"
|
"path-exists": "^4.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"json5": {
|
|
||||||
"version": "2.1.3",
|
|
||||||
"resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz",
|
|
||||||
"integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"minimist": "^1.2.5"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"loader-utils": {
|
"loader-utils": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
|
||||||
@@ -5837,44 +5833,53 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"eslint-module-utils": {
|
"eslint-module-utils": {
|
||||||
"version": "2.6.0",
|
"version": "2.6.2",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.6.2.tgz",
|
||||||
"integrity": "sha512-6j9xxegbqe8/kZY8cYpcp0xhbK0EgJlg3g9mib3/miLaExuuwc3n5UEfSnU6hWMbT0FAYVvDbL9RrRgpUeQIvA==",
|
"integrity": "sha512-QG8pcgThYOuqxupd06oYTZoNOGaUdTY1PqK+oS6ElF6vs4pBdk/aYxFVQQXzcrAqp9m7cl7lb2ubazX+g16k2Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"debug": "^2.6.9",
|
"debug": "^3.2.7",
|
||||||
"pkg-dir": "^2.0.0"
|
"pkg-dir": "^2.0.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"debug": {
|
"debug": {
|
||||||
"version": "2.6.9",
|
"version": "3.2.7",
|
||||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
|
||||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"ms": "2.0.0"
|
"ms": "^2.1.1"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"ms": {
|
||||||
|
"version": "2.1.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||||
|
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
|
||||||
|
"dev": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"eslint-plugin-import": {
|
"eslint-plugin-import": {
|
||||||
"version": "2.20.2",
|
"version": "2.24.1",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.20.2.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.24.1.tgz",
|
||||||
"integrity": "sha512-FObidqpXrR8OnCh4iNsxy+WACztJLXAHBO5hK79T1Hc77PgQZkyDGA5Ag9xAvRpglvLNxhH/zSmZ70/pZ31dHg==",
|
"integrity": "sha512-KSFWhNxPH8OGJwpRJJs+Z7I0a13E2iFQZJIvSnCu6KUs4qmgAm3xN9GYBCSoiGWmwA7gERZPXqYQjcoCROnYhQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"array-includes": "^3.0.3",
|
"array-includes": "^3.1.3",
|
||||||
"array.prototype.flat": "^1.2.1",
|
"array.prototype.flat": "^1.2.4",
|
||||||
"contains-path": "^0.1.0",
|
|
||||||
"debug": "^2.6.9",
|
"debug": "^2.6.9",
|
||||||
"doctrine": "1.5.0",
|
"doctrine": "^2.1.0",
|
||||||
"eslint-import-resolver-node": "^0.3.2",
|
"eslint-import-resolver-node": "^0.3.6",
|
||||||
"eslint-module-utils": "^2.4.1",
|
"eslint-module-utils": "^2.6.2",
|
||||||
|
"find-up": "^2.0.0",
|
||||||
"has": "^1.0.3",
|
"has": "^1.0.3",
|
||||||
|
"is-core-module": "^2.6.0",
|
||||||
"minimatch": "^3.0.4",
|
"minimatch": "^3.0.4",
|
||||||
"object.values": "^1.1.0",
|
"object.values": "^1.1.4",
|
||||||
"read-pkg-up": "^2.0.0",
|
"pkg-up": "^2.0.0",
|
||||||
"resolve": "^1.12.0"
|
"read-pkg-up": "^3.0.0",
|
||||||
|
"resolve": "^1.20.0",
|
||||||
|
"tsconfig-paths": "^3.10.1"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"debug": {
|
"debug": {
|
||||||
@@ -5887,20 +5892,23 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"doctrine": {
|
"doctrine": {
|
||||||
"version": "1.5.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-1.5.0.tgz",
|
"resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
|
||||||
"integrity": "sha1-N53Ocw9hZvds76TmcHoVmwLFpvo=",
|
"integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"esutils": "^2.0.2",
|
"esutils": "^2.0.2"
|
||||||
"isarray": "^1.0.0"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"isarray": {
|
"resolve": {
|
||||||
"version": "1.0.0",
|
"version": "1.20.0",
|
||||||
"resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
|
||||||
"integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=",
|
"integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==",
|
||||||
"dev": true
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"is-core-module": "^2.2.0",
|
||||||
|
"path-parse": "^1.0.6"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -5930,22 +5938,23 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"eslint-plugin-react": {
|
"eslint-plugin-react": {
|
||||||
"version": "7.20.0",
|
"version": "7.24.0",
|
||||||
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.20.0.tgz",
|
"resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.24.0.tgz",
|
||||||
"integrity": "sha512-rqe1abd0vxMjmbPngo4NaYxTcR3Y4Hrmc/jg4T+sYz63yqlmJRknpEQfmWY+eDWPuMmix6iUIK+mv0zExjeLgA==",
|
"integrity": "sha512-KJJIx2SYx7PBx3ONe/mEeMz4YE0Lcr7feJTCMyyKb/341NcjuAgim3Acgan89GfPv7nxXK2+0slu0CWXYM4x+Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"array-includes": "^3.1.1",
|
"array-includes": "^3.1.3",
|
||||||
|
"array.prototype.flatmap": "^1.2.4",
|
||||||
"doctrine": "^2.1.0",
|
"doctrine": "^2.1.0",
|
||||||
"has": "^1.0.3",
|
"has": "^1.0.3",
|
||||||
"jsx-ast-utils": "^2.2.3",
|
"jsx-ast-utils": "^2.4.1 || ^3.0.0",
|
||||||
"object.entries": "^1.1.1",
|
"minimatch": "^3.0.4",
|
||||||
"object.fromentries": "^2.0.2",
|
"object.entries": "^1.1.4",
|
||||||
"object.values": "^1.1.1",
|
"object.fromentries": "^2.0.4",
|
||||||
|
"object.values": "^1.1.4",
|
||||||
"prop-types": "^15.7.2",
|
"prop-types": "^15.7.2",
|
||||||
"resolve": "^1.15.1",
|
"resolve": "^2.0.0-next.3",
|
||||||
"string.prototype.matchall": "^4.0.2",
|
"string.prototype.matchall": "^4.0.5"
|
||||||
"xregexp": "^4.3.0"
|
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"doctrine": {
|
"doctrine": {
|
||||||
@@ -5957,6 +5966,16 @@
|
|||||||
"esutils": "^2.0.2"
|
"esutils": "^2.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"jsx-ast-utils": {
|
||||||
|
"version": "3.2.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.2.0.tgz",
|
||||||
|
"integrity": "sha512-EIsmt3O3ljsU6sot/J4E1zDRxfBNrhjyf/OKjlydwgEimQuznlM4Wv7U+ueONJMyEn1WRE0K8dhi3dVAXYT24Q==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"array-includes": "^3.1.2",
|
||||||
|
"object.assign": "^4.1.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"prop-types": {
|
"prop-types": {
|
||||||
"version": "15.7.2",
|
"version": "15.7.2",
|
||||||
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz",
|
"resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.7.2.tgz",
|
||||||
@@ -5967,6 +5986,16 @@
|
|||||||
"object-assign": "^4.1.1",
|
"object-assign": "^4.1.1",
|
||||||
"react-is": "^16.8.1"
|
"react-is": "^16.8.1"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"resolve": {
|
||||||
|
"version": "2.0.0-next.3",
|
||||||
|
"resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.3.tgz",
|
||||||
|
"integrity": "sha512-W8LucSynKUIDu9ylraa7ueVZ7hc0uAgJBxVsQSKOXOyle8a93qXhcz+XAXZ8bIq2d6i4Ehddn6Evt+0/UwKk6Q==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"is-core-module": "^2.2.0",
|
||||||
|
"path-parse": "^1.0.6"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -6883,6 +6912,16 @@
|
|||||||
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
|
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"get-intrinsic": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-kWZrnVM42QCiEA2Ig1bG8zjoIMOgxWwYCEeNdwY6Tv/cOSeGpcoX4pXHfKUxNKVoArnrEr2e9srnAxxGIraS9Q==",
|
||||||
|
"requires": {
|
||||||
|
"function-bind": "^1.1.1",
|
||||||
|
"has": "^1.0.3",
|
||||||
|
"has-symbols": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"get-package-type": {
|
"get-package-type": {
|
||||||
"version": "0.1.0",
|
"version": "0.1.0",
|
||||||
"resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
|
||||||
@@ -7191,15 +7230,28 @@
|
|||||||
"function-bind": "^1.1.1"
|
"function-bind": "^1.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"has-bigints": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA=="
|
||||||
|
},
|
||||||
"has-flag": {
|
"has-flag": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||||
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
|
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
|
||||||
},
|
},
|
||||||
"has-symbols": {
|
"has-symbols": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.2.tgz",
|
||||||
"integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg=="
|
"integrity": "sha512-chXa79rL/UC2KlX17jo3vRGz0azaWEx5tGqZg5pO3NUyEJVB17dMruQlzCCOfUvElghKcm5194+BCRvi2Rv/Gw=="
|
||||||
|
},
|
||||||
|
"has-tostringtag": {
|
||||||
|
"version": "1.0.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.0.tgz",
|
||||||
|
"integrity": "sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ==",
|
||||||
|
"requires": {
|
||||||
|
"has-symbols": "^1.0.2"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"has-value": {
|
"has-value": {
|
||||||
"version": "1.0.0",
|
"version": "1.0.0",
|
||||||
@@ -7824,14 +7876,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"internal-slot": {
|
"internal-slot": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.3",
|
||||||
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz",
|
||||||
"integrity": "sha512-2cQNfwhAfJIkU4KZPkDI+Gj5yNNnbqi40W9Gge6dfnk4TocEVm00B3bdiL+JINrbGJil2TeHvM4rETGzk/f/0g==",
|
"integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"es-abstract": "^1.17.0-next.1",
|
"get-intrinsic": "^1.1.0",
|
||||||
"has": "^1.0.3",
|
"has": "^1.0.3",
|
||||||
"side-channel": "^1.0.2"
|
"side-channel": "^1.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"interpret": {
|
"interpret": {
|
||||||
@@ -7929,6 +7980,14 @@
|
|||||||
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
|
||||||
"integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
|
"integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
|
||||||
},
|
},
|
||||||
|
"is-bigint": {
|
||||||
|
"version": "1.0.4",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
|
||||||
|
"integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
|
||||||
|
"requires": {
|
||||||
|
"has-bigints": "^1.0.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
"is-binary-path": {
|
"is-binary-path": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
|
||||||
@@ -7938,6 +7997,15 @@
|
|||||||
"binary-extensions": "^1.0.0"
|
"binary-extensions": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"is-boolean-object": {
|
||||||
|
"version": "1.1.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
|
||||||
|
"integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
|
||||||
|
"requires": {
|
||||||
|
"call-bind": "^1.0.2",
|
||||||
|
"has-tostringtag": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"is-buffer": {
|
"is-buffer": {
|
||||||
"version": "1.1.6",
|
"version": "1.1.6",
|
||||||
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
|
"resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
|
||||||
@@ -7945,9 +8013,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"is-callable": {
|
"is-callable": {
|
||||||
"version": "1.1.5",
|
"version": "1.2.4",
|
||||||
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz",
|
"resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz",
|
||||||
"integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q=="
|
"integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w=="
|
||||||
},
|
},
|
||||||
"is-ci": {
|
"is-ci": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
@@ -7958,6 +8026,15 @@
|
|||||||
"ci-info": "^2.0.0"
|
"ci-info": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"is-core-module": {
|
||||||
|
"version": "2.6.0",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.6.0.tgz",
|
||||||
|
"integrity": "sha512-wShG8vs60jKfPWpF2KZRaAtvt3a20OAn7+IJ6hLPECpSABLcKtFKTTI4ZtH5QcBruBHlq+WsdHWyz0BCZW7svQ==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"has": "^1.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"is-data-descriptor": {
|
"is-data-descriptor": {
|
||||||
"version": "0.1.4",
|
"version": "0.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
|
"resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
|
||||||
@@ -8060,6 +8137,11 @@
|
|||||||
"integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==",
|
"integrity": "sha512-gyPJuv83bHMpocVYoqof5VDiZveEoGoFL8m3BXNb2VW8Xs+rz9kqO8LOQ5DH6EsuvilT1ApazU0pyl+ytbPtlw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"is-negative-zero": {
|
||||||
|
"version": "2.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz",
|
||||||
|
"integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w=="
|
||||||
|
},
|
||||||
"is-number": {
|
"is-number": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
|
||||||
@@ -8080,6 +8162,14 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"is-number-object": {
|
||||||
|
"version": "1.0.6",
|
||||||
|
"resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz",
|
||||||
|
"integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==",
|
||||||
|
"requires": {
|
||||||
|
"has-tostringtag": "^1.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"is-path-cwd": {
|
"is-path-cwd": {
|
||||||
"version": "2.2.0",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz",
|
||||||
@@ -8131,11 +8221,12 @@
|
|||||||
"integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ=="
|
"integrity": "sha512-+lP4/6lKUBfQjZ2pdxThZvLUAafmZb8OAxFb8XXtiQmS35INgr85hdOGoEs124ez1FCnZJt6jau/T+alh58QFQ=="
|
||||||
},
|
},
|
||||||
"is-regex": {
|
"is-regex": {
|
||||||
"version": "1.0.5",
|
"version": "1.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
|
||||||
"integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==",
|
"integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"has": "^1.0.3"
|
"call-bind": "^1.0.2",
|
||||||
|
"has-tostringtag": "^1.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"is-regexp": {
|
"is-regexp": {
|
||||||
@@ -8150,10 +8241,12 @@
|
|||||||
"integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
|
"integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
|
||||||
},
|
},
|
||||||
"is-string": {
|
"is-string": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.7",
|
||||||
"resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
|
||||||
"integrity": "sha512-buY6VNRjhQMiF1qWDouloZlQbRhDPCebwxSjxMjxgemYT46YMd2NR0/H+fBhEfWX4A/w9TBJ+ol+okqJKFE6vQ==",
|
"integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
|
||||||
"dev": true
|
"requires": {
|
||||||
|
"has-tostringtag": "^1.0.0"
|
||||||
|
}
|
||||||
},
|
},
|
||||||
"is-symbol": {
|
"is-symbol": {
|
||||||
"version": "1.0.3",
|
"version": "1.0.3",
|
||||||
@@ -10121,9 +10214,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"json5": {
|
"json5": {
|
||||||
"version": "2.1.3",
|
"version": "2.2.0",
|
||||||
"resolved": "https://registry.npmjs.org/json5/-/json5-2.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz",
|
||||||
"integrity": "sha512-KXPvOm8K9IJKFM0bmdn8QXh7udDh1g/giieX0NLCaMnb4hEiVFqnop2ImTXCc5e0/oHz3LTqmHGtExn5hfMkOA==",
|
"integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"minimist": "^1.2.5"
|
"minimist": "^1.2.5"
|
||||||
@@ -10237,24 +10330,25 @@
|
|||||||
"integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA="
|
"integrity": "sha1-HADHQ7QzzQpOgHWPe2SldEDZ/wA="
|
||||||
},
|
},
|
||||||
"load-json-file": {
|
"load-json-file": {
|
||||||
"version": "2.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-4.0.0.tgz",
|
||||||
"integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=",
|
"integrity": "sha1-L19Fq5HjMhYjT9U62rZo607AmTs=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"graceful-fs": "^4.1.2",
|
"graceful-fs": "^4.1.2",
|
||||||
"parse-json": "^2.2.0",
|
"parse-json": "^4.0.0",
|
||||||
"pify": "^2.0.0",
|
"pify": "^3.0.0",
|
||||||
"strip-bom": "^3.0.0"
|
"strip-bom": "^3.0.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"parse-json": {
|
"parse-json": {
|
||||||
"version": "2.2.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
|
||||||
"integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=",
|
"integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"error-ex": "^1.2.0"
|
"error-ex": "^1.3.1",
|
||||||
|
"json-parse-better-errors": "^1.0.1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -11327,9 +11421,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"object-inspect": {
|
"object-inspect": {
|
||||||
"version": "1.7.0",
|
"version": "1.11.0",
|
||||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz",
|
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.0.tgz",
|
||||||
"integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw=="
|
"integrity": "sha512-jp7ikS6Sd3GxQfZJPyH3cjcbJF6GZPClgdV+EFygjFLQ5FmW/dRUnTd9PQ9k0JhoNDabWFbpF1yCdSWCC6gexg=="
|
||||||
},
|
},
|
||||||
"object-is": {
|
"object-is": {
|
||||||
"version": "1.1.2",
|
"version": "1.1.2",
|
||||||
@@ -11355,37 +11449,36 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"object.assign": {
|
"object.assign": {
|
||||||
"version": "4.1.0",
|
"version": "4.1.2",
|
||||||
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz",
|
"resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz",
|
||||||
"integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==",
|
"integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"define-properties": "^1.1.2",
|
"call-bind": "^1.0.0",
|
||||||
"function-bind": "^1.1.1",
|
"define-properties": "^1.1.3",
|
||||||
"has-symbols": "^1.0.0",
|
"has-symbols": "^1.0.1",
|
||||||
"object-keys": "^1.0.11"
|
"object-keys": "^1.1.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"object.entries": {
|
"object.entries": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.4.tgz",
|
||||||
"integrity": "sha512-ilqR7BgdyZetJutmDPfXCDffGa0/Yzl2ivVNpbx/g4UeWrCdRnFDUBrKJGLhGieRHDATnyZXWBeCb29k9CJysQ==",
|
"integrity": "sha512-h4LWKWE+wKQGhtMjZEBud7uLGhqyLwj8fpHOarZhD2uY3C9cRtk57VQ89ke3moByLXMedqs3XCHzyb4AmA2DjA==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
"call-bind": "^1.0.2",
|
||||||
"define-properties": "^1.1.3",
|
"define-properties": "^1.1.3",
|
||||||
"es-abstract": "^1.17.0-next.1",
|
"es-abstract": "^1.18.2"
|
||||||
"function-bind": "^1.1.1",
|
|
||||||
"has": "^1.0.3"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"object.fromentries": {
|
"object.fromentries": {
|
||||||
"version": "2.0.2",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.4.tgz",
|
||||||
"integrity": "sha512-r3ZiBH7MQppDJVLx6fhD618GKNG40CZYH9wgwdhKxBDDbQgjeWGGd4AtkZad84d291YxvWe7bJGuE65Anh0dxQ==",
|
"integrity": "sha512-EsFBshs5RUUpQEY1D4q/m59kMfz4YJvxuNCJcv/jWwOJr34EaVnG11ZrZa0UHB3wnzV1wx8m58T4hQL8IuNXlQ==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
"call-bind": "^1.0.2",
|
||||||
"define-properties": "^1.1.3",
|
"define-properties": "^1.1.3",
|
||||||
"es-abstract": "^1.17.0-next.1",
|
"es-abstract": "^1.18.0-next.2",
|
||||||
"function-bind": "^1.1.1",
|
|
||||||
"has": "^1.0.3"
|
"has": "^1.0.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@@ -11409,15 +11502,14 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"object.values": {
|
"object.values": {
|
||||||
"version": "1.1.1",
|
"version": "1.1.4",
|
||||||
"resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.1.tgz",
|
"resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.4.tgz",
|
||||||
"integrity": "sha512-WTa54g2K8iu0kmS/us18jEmdv1a4Wi//BZ/DTVYEcH0XhLM5NYdpDHja3gt57VrZLcNAO2WGA+KpWsDBaHt6eA==",
|
"integrity": "sha512-TnGo7j4XSnKQoK3MfvkzqKCi0nVe/D9I9IjwTNYdb/fxYHpjrluHVOgw0AF6jrRFGMPHdfuidR09tIDiIvnaSg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
"call-bind": "^1.0.2",
|
||||||
"define-properties": "^1.1.3",
|
"define-properties": "^1.1.3",
|
||||||
"es-abstract": "^1.17.0-next.1",
|
"es-abstract": "^1.18.2"
|
||||||
"function-bind": "^1.1.1",
|
|
||||||
"has": "^1.0.3"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"obuf": {
|
"obuf": {
|
||||||
@@ -11791,9 +11883,9 @@
|
|||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"pify": {
|
"pify": {
|
||||||
"version": "2.3.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
|
||||||
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=",
|
"integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY=",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"pinkie": {
|
"pinkie": {
|
||||||
@@ -12718,35 +12810,35 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"read-pkg": {
|
"read-pkg": {
|
||||||
"version": "2.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-3.0.0.tgz",
|
||||||
"integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=",
|
"integrity": "sha1-nLxoaXj+5l0WwA4rGcI3/Pbjg4k=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"load-json-file": "^2.0.0",
|
"load-json-file": "^4.0.0",
|
||||||
"normalize-package-data": "^2.3.2",
|
"normalize-package-data": "^2.3.2",
|
||||||
"path-type": "^2.0.0"
|
"path-type": "^3.0.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"path-type": {
|
"path-type": {
|
||||||
"version": "2.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
|
||||||
"integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=",
|
"integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"pify": "^2.0.0"
|
"pify": "^3.0.0"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"read-pkg-up": {
|
"read-pkg-up": {
|
||||||
"version": "2.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-3.0.0.tgz",
|
||||||
"integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=",
|
"integrity": "sha1-PtSWaF26D4/hGNBpHcUfSh/5bwc=",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
"find-up": "^2.0.0",
|
"find-up": "^2.0.0",
|
||||||
"read-pkg": "^2.0.0"
|
"read-pkg": "^3.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"readable-stream": {
|
"readable-stream": {
|
||||||
@@ -12894,12 +12986,12 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"regexp.prototype.flags": {
|
"regexp.prototype.flags": {
|
||||||
"version": "1.3.0",
|
"version": "1.3.1",
|
||||||
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz",
|
||||||
"integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==",
|
"integrity": "sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"define-properties": "^1.1.3",
|
"call-bind": "^1.0.2",
|
||||||
"es-abstract": "^1.17.0-next.1"
|
"define-properties": "^1.1.3"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"regexpp": {
|
"regexpp": {
|
||||||
@@ -13572,13 +13664,13 @@
|
|||||||
"optional": true
|
"optional": true
|
||||||
},
|
},
|
||||||
"side-channel": {
|
"side-channel": {
|
||||||
"version": "1.0.2",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
|
||||||
"integrity": "sha512-7rL9YlPHg7Ancea1S96Pa8/QWb4BtXL/TZvS6B8XFetGBeuhAsfmUspK6DokBeZ64+Kj9TCNRD/30pVz1BvQNA==",
|
"integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"es-abstract": "^1.17.0-next.1",
|
"call-bind": "^1.0.0",
|
||||||
"object-inspect": "^1.7.0"
|
"get-intrinsic": "^1.0.2",
|
||||||
|
"object-inspect": "^1.9.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"signal-exit": {
|
"signal-exit": {
|
||||||
@@ -14101,6 +14193,15 @@
|
|||||||
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-2.0.0.tgz",
|
||||||
"integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY="
|
"integrity": "sha1-ucczDHBChi9rFC3CdLvMWGbONUY="
|
||||||
},
|
},
|
||||||
|
"string_decoder": {
|
||||||
|
"version": "1.1.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
||||||
|
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"safe-buffer": "~5.1.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"string-length": {
|
"string-length": {
|
||||||
"version": "4.0.1",
|
"version": "4.0.1",
|
||||||
"resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.1.tgz",
|
||||||
@@ -14163,64 +14264,37 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"string.prototype.matchall": {
|
"string.prototype.matchall": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.5.tgz",
|
||||||
"integrity": "sha512-N/jp6O5fMf9os0JU3E72Qhf590RSRZU/ungsL/qJUYVTNv7hTG0P/dbPjxINVN9jpscu3nzYwKESU3P3RY5tOg==",
|
"integrity": "sha512-Z5ZaXO0svs0M2xd/6By3qpeKpLKd9mO4v4q3oMEQrk8Ck4xOD5d5XeBOOjGrmVZZ/AHB1S0CgG4N5r1G9N3E2Q==",
|
||||||
"dev": true,
|
"dev": true,
|
||||||
"requires": {
|
"requires": {
|
||||||
|
"call-bind": "^1.0.2",
|
||||||
"define-properties": "^1.1.3",
|
"define-properties": "^1.1.3",
|
||||||
"es-abstract": "^1.17.0",
|
"es-abstract": "^1.18.2",
|
||||||
"has-symbols": "^1.0.1",
|
"get-intrinsic": "^1.1.1",
|
||||||
"internal-slot": "^1.0.2",
|
"has-symbols": "^1.0.2",
|
||||||
"regexp.prototype.flags": "^1.3.0",
|
"internal-slot": "^1.0.3",
|
||||||
"side-channel": "^1.0.2"
|
"regexp.prototype.flags": "^1.3.1",
|
||||||
|
"side-channel": "^1.0.4"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"string.prototype.trimend": {
|
"string.prototype.trimend": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz",
|
||||||
"integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==",
|
"integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"define-properties": "^1.1.3",
|
"call-bind": "^1.0.2",
|
||||||
"es-abstract": "^1.17.5"
|
"define-properties": "^1.1.3"
|
||||||
}
|
|
||||||
},
|
|
||||||
"string.prototype.trimleft": {
|
|
||||||
"version": "2.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz",
|
|
||||||
"integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==",
|
|
||||||
"requires": {
|
|
||||||
"define-properties": "^1.1.3",
|
|
||||||
"es-abstract": "^1.17.5",
|
|
||||||
"string.prototype.trimstart": "^1.0.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"string.prototype.trimright": {
|
|
||||||
"version": "2.1.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/string.prototype.trimright/-/string.prototype.trimright-2.1.2.tgz",
|
|
||||||
"integrity": "sha512-ZNRQ7sY3KroTaYjRS6EbNiiHrOkjihL9aQE/8gfQ4DtAC/aEBRHFJa44OmoWxGGqXuJlfKkZW4WcXErGr+9ZFg==",
|
|
||||||
"requires": {
|
|
||||||
"define-properties": "^1.1.3",
|
|
||||||
"es-abstract": "^1.17.5",
|
|
||||||
"string.prototype.trimend": "^1.0.0"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"string.prototype.trimstart": {
|
"string.prototype.trimstart": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz",
|
"resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz",
|
||||||
"integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==",
|
"integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"define-properties": "^1.1.3",
|
"call-bind": "^1.0.2",
|
||||||
"es-abstract": "^1.17.5"
|
"define-properties": "^1.1.3"
|
||||||
}
|
|
||||||
},
|
|
||||||
"string_decoder": {
|
|
||||||
"version": "1.1.1",
|
|
||||||
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
|
|
||||||
"integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"safe-buffer": "~5.1.0"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"stringify-entities": {
|
"stringify-entities": {
|
||||||
@@ -15111,6 +15185,17 @@
|
|||||||
"integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==",
|
"integrity": "sha512-rvuRbTarPXmMb79SmzEp8aqXNKcK+y0XaB298IXueQ8I2PsrATcPBCSPyK/dDNa2iWOhKlfNnOjdAOTBU/nkFA==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
|
"tsconfig-paths": {
|
||||||
|
"version": "3.10.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.10.1.tgz",
|
||||||
|
"integrity": "sha512-rETidPDgCpltxF7MjBZlAFPUHv5aHH2MymyPvh+vEyWAED4Eb/WeMbsnD/JDr4OKPOA1TssDHgIcpTN5Kh0p6Q==",
|
||||||
|
"dev": true,
|
||||||
|
"requires": {
|
||||||
|
"json5": "^2.2.0",
|
||||||
|
"minimist": "^1.2.0",
|
||||||
|
"strip-bom": "^3.0.0"
|
||||||
|
}
|
||||||
|
},
|
||||||
"tslib": {
|
"tslib": {
|
||||||
"version": "1.13.0",
|
"version": "1.13.0",
|
||||||
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz",
|
"resolved": "https://registry.npmjs.org/tslib/-/tslib-1.13.0.tgz",
|
||||||
@@ -15194,6 +15279,17 @@
|
|||||||
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.22.tgz",
|
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.22.tgz",
|
||||||
"integrity": "sha512-YUxzMjJ5T71w6a8WWVcMGM6YWOTX27rCoIQgLXiWaxqXSx9D7DNjiGWn1aJIRSQ5qr0xuhra77bSIh6voR/46Q=="
|
"integrity": "sha512-YUxzMjJ5T71w6a8WWVcMGM6YWOTX27rCoIQgLXiWaxqXSx9D7DNjiGWn1aJIRSQ5qr0xuhra77bSIh6voR/46Q=="
|
||||||
},
|
},
|
||||||
|
"unbox-primitive": {
|
||||||
|
"version": "1.0.1",
|
||||||
|
"resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
|
||||||
|
"integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==",
|
||||||
|
"requires": {
|
||||||
|
"function-bind": "^1.1.1",
|
||||||
|
"has-bigints": "^1.0.1",
|
||||||
|
"has-symbols": "^1.0.2",
|
||||||
|
"which-boxed-primitive": "^1.0.2"
|
||||||
|
}
|
||||||
|
},
|
||||||
"unherit": {
|
"unherit": {
|
||||||
"version": "1.1.3",
|
"version": "1.1.3",
|
||||||
"resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz",
|
"resolved": "https://registry.npmjs.org/unherit/-/unherit-1.1.3.tgz",
|
||||||
@@ -16247,6 +16343,18 @@
|
|||||||
"isexe": "^2.0.0"
|
"isexe": "^2.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"which-boxed-primitive": {
|
||||||
|
"version": "1.0.2",
|
||||||
|
"resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
|
||||||
|
"integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
|
||||||
|
"requires": {
|
||||||
|
"is-bigint": "^1.0.1",
|
||||||
|
"is-boolean-object": "^1.1.0",
|
||||||
|
"is-number-object": "^1.0.4",
|
||||||
|
"is-string": "^1.0.5",
|
||||||
|
"is-symbol": "^1.0.3"
|
||||||
|
}
|
||||||
|
},
|
||||||
"which-module": {
|
"which-module": {
|
||||||
"version": "2.0.0",
|
"version": "2.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
|
||||||
@@ -16361,15 +16469,6 @@
|
|||||||
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
|
"integrity": "sha512-JZnDKK8B0RCDw84FNdDAIpZK+JuJw+s7Lz8nksI7SIuU3UXJJslUthsi+uWBUYOwPFwW7W7PRLRfUKpxjtjFCw==",
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"xregexp": {
|
|
||||||
"version": "4.3.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/xregexp/-/xregexp-4.3.0.tgz",
|
|
||||||
"integrity": "sha512-7jXDIFXh5yJ/orPn4SXjuVrWWoi4Cr8jfV1eHv9CixKSbU+jY4mxfrBwAuDvupPNKpMUY+FeIqsVw/JLT9+B8g==",
|
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
|
||||||
"@babel/runtime-corejs3": "^7.8.3"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"xtend": {
|
"xtend": {
|
||||||
"version": "4.0.2",
|
"version": "4.0.2",
|
||||||
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
|
||||||
|
|||||||
4
client/package.json
vendored
4
client/package.json
vendored
@@ -64,9 +64,9 @@
|
|||||||
"eslint-config-airbnb": "^18.1.0",
|
"eslint-config-airbnb": "^18.1.0",
|
||||||
"eslint-import-resolver-webpack": "^0.12.1",
|
"eslint-import-resolver-webpack": "^0.12.1",
|
||||||
"eslint-loader": "^4.0.2",
|
"eslint-loader": "^4.0.2",
|
||||||
"eslint-plugin-import": "^2.20.2",
|
"eslint-plugin-import": "^2.22.1",
|
||||||
"eslint-plugin-jsx-a11y": "^6.2.3",
|
"eslint-plugin-jsx-a11y": "^6.2.3",
|
||||||
"eslint-plugin-react": "^7.20.0",
|
"eslint-plugin-react": "^7.24.0",
|
||||||
"eslint-plugin-react-hooks": "^2.5.0",
|
"eslint-plugin-react-hooks": "^2.5.0",
|
||||||
"file-loader": "6.0.0",
|
"file-loader": "6.0.0",
|
||||||
"html-webpack-plugin": "^4.3.0",
|
"html-webpack-plugin": "^4.3.0",
|
||||||
|
|||||||
@@ -112,6 +112,8 @@
|
|||||||
"for_last_24_hours": "за 24 гадзіны",
|
"for_last_24_hours": "за 24 гадзіны",
|
||||||
"for_last_days": "за апошні {{count}} дзень",
|
"for_last_days": "за апошні {{count}} дзень",
|
||||||
"for_last_days_plural": "за апошнія {{count}} дзён",
|
"for_last_days_plural": "за апошнія {{count}} дзён",
|
||||||
|
"stats_disabled": "Статыстыка была адключаная. Вы можаце ўключыць яго <0>на старонцы налад </0>.",
|
||||||
|
"stats_disabled_short": "Статыстыка была адключаная",
|
||||||
"no_domains_found": "Дамены не знойдзены",
|
"no_domains_found": "Дамены не знойдзены",
|
||||||
"requests_count": "Колькасць запытаў",
|
"requests_count": "Колькасць запытаў",
|
||||||
"top_blocked_domains": "Часта блакаваныя дамены",
|
"top_blocked_domains": "Часта блакаваныя дамены",
|
||||||
@@ -326,7 +328,7 @@
|
|||||||
"install_devices_windows_list_2": "Перайдзіце ў \"Сеціва і інтэрнэт\", а потым у \"Цэнтр кіравання сеціва і агульным доступам\"",
|
"install_devices_windows_list_2": "Перайдзіце ў \"Сеціва і інтэрнэт\", а потым у \"Цэнтр кіравання сеціва і агульным доступам\"",
|
||||||
"install_devices_windows_list_3": "У левым боку экрана знайдзіце \"Змена параметраў адаптара\" і клікніце па ім.",
|
"install_devices_windows_list_3": "У левым боку экрана знайдзіце \"Змена параметраў адаптара\" і клікніце па ім.",
|
||||||
"install_devices_windows_list_4": "Вылучыце ваша актыўнае падлучэнне, потым клікніце па ім правай клавішай мышы і выберыце \"Уласцівасці\".",
|
"install_devices_windows_list_4": "Вылучыце ваша актыўнае падлучэнне, потым клікніце па ім правай клавішай мышы і выберыце \"Уласцівасці\".",
|
||||||
"install_devices_windows_list_5": "Знайдзіце ў спісе пункт \"IP версіі 4 (TCP/IP)\", вылучыце яго і потым ізноў націсніце \"Уласцівасці\".",
|
"install_devices_windows_list_5": "Знайдзіце ў спісе пункт \"IP версіі 4 (TCP/IPv4)\", вылучыце яго і потым ізноў націсніце \"Уласцівасці\".",
|
||||||
"install_devices_windows_list_6": "Абярыце \"Выкарыстаць наступныя адрасы DNS-сервераў\" і ўвядзіце адрас AdGuard Home.",
|
"install_devices_windows_list_6": "Абярыце \"Выкарыстаць наступныя адрасы DNS-сервераў\" і ўвядзіце адрас AdGuard Home.",
|
||||||
"install_devices_macos_list_1": "Клікніце па абразку Apple і перайдзіце ў «Сістэмныя налады».",
|
"install_devices_macos_list_1": "Клікніце па абразку Apple і перайдзіце ў «Сістэмныя налады».",
|
||||||
"install_devices_macos_list_2": "Клікніце па іконцы «Сеціва».",
|
"install_devices_macos_list_2": "Клікніце па іконцы «Сеціва».",
|
||||||
@@ -497,7 +499,7 @@
|
|||||||
"statistics_configuration": "Канфігурацыя статыстыкі",
|
"statistics_configuration": "Канфігурацыя статыстыкі",
|
||||||
"statistics_retention": "Захаванне статыстыкі",
|
"statistics_retention": "Захаванне статыстыкі",
|
||||||
"statistics_retention_desc": "Калі вы зменшыце значэнне інтэрвалу, некаторыя дадзеныя могуць быць згублены",
|
"statistics_retention_desc": "Калі вы зменшыце значэнне інтэрвалу, некаторыя дадзеныя могуць быць згублены",
|
||||||
"statistics_clear": " Ачысціць статыстыку",
|
"statistics_clear": "Ачысціць статыстыку",
|
||||||
"statistics_clear_confirm": "Вы ўпэўнены, што хочаце ачысціць статыстыку?",
|
"statistics_clear_confirm": "Вы ўпэўнены, што хочаце ачысціць статыстыку?",
|
||||||
"statistics_retention_confirm": "Вы ўпэўнены, што хочаце змяніць тэрмін захоўвання статыстыкі? Пры скарачэнні інтэрвалу дадзеныя могуць быць згублены",
|
"statistics_retention_confirm": "Вы ўпэўнены, што хочаце змяніць тэрмін захоўвання статыстыкі? Пры скарачэнні інтэрвалу дадзеныя могуць быць згублены",
|
||||||
"statistics_cleared": "Статыстыка паспяхова вычышчана",
|
"statistics_cleared": "Статыстыка паспяхова вычышчана",
|
||||||
@@ -595,6 +597,8 @@
|
|||||||
"cache_ttl_min_override_desc": "Перавызначыць TTL-значэнне (мінімальнае), атрыманае з upstream-сервера",
|
"cache_ttl_min_override_desc": "Перавызначыць TTL-значэнне (мінімальнае), атрыманае з upstream-сервера",
|
||||||
"cache_ttl_max_override_desc": "Усталюйце максімальнае TTL-значэнне (секунды) для запісаў у кэшы DNS",
|
"cache_ttl_max_override_desc": "Усталюйце максімальнае TTL-значэнне (секунды) для запісаў у кэшы DNS",
|
||||||
"ttl_cache_validation": "Мінімальнае значэнне TTL кэша павінна быць менш ці роўна максімальнаму значэнню",
|
"ttl_cache_validation": "Мінімальнае значэнне TTL кэша павінна быць менш ці роўна максімальнаму значэнню",
|
||||||
|
"cache_optimistic": "Аптымістычнае кэшаванне",
|
||||||
|
"cache_optimistic_desc": "Прымусьце AdGuard Home адказваць з кэша, нават калі тэрмін дзеяння запісаў скончыўся, а таксама паспрабуйце абнавіць іх.",
|
||||||
"filter_category_general": "Галоўныя",
|
"filter_category_general": "Галоўныя",
|
||||||
"filter_category_security": "Бяспека",
|
"filter_category_security": "Бяспека",
|
||||||
"filter_category_regional": "Рэгіянальныя",
|
"filter_category_regional": "Рэгіянальныя",
|
||||||
|
|||||||
@@ -218,6 +218,7 @@
|
|||||||
"reset_settings": "Изтрий всички настройки",
|
"reset_settings": "Изтрий всички настройки",
|
||||||
"update_announcement": "Има нова AdGuard Home {{version}}! <0>Цъкни тук</0> за повече информация.",
|
"update_announcement": "Има нова AdGuard Home {{version}}! <0>Цъкни тук</0> за повече информация.",
|
||||||
"disable_ipv6": "Изключете IPv6 протокола",
|
"disable_ipv6": "Изключете IPv6 протокола",
|
||||||
|
"check_updates_now": "Провери за актуализации",
|
||||||
"show_blocked_responses": "Блокирано",
|
"show_blocked_responses": "Блокирано",
|
||||||
"port_53_faq_link": "Порт 53 често е зает от \"DNSStubListener\" или \"systemd-resolved\" услуги. Моля, прочетете <0>тази инструкция</0> как да решите това."
|
"port_53_faq_link": "Порт 53 често е зает от \"DNSStubListener\" или \"systemd-resolved\" услуги. Моля, прочетете <0>тази инструкция</0> как да решите това."
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -208,7 +208,7 @@
|
|||||||
"example_upstream_sdns": "můžete použít <0>DNS razítka</0> pro <1>DNSCrypt</1> nebo <2>DNS skrze HTTPS</2> řešitele",
|
"example_upstream_sdns": "můžete použít <0>DNS razítka</0> pro <1>DNSCrypt</1> nebo <2>DNS skrze HTTPS</2> řešitele",
|
||||||
"example_upstream_tcp": "obyčejný DNS (přes TCP)",
|
"example_upstream_tcp": "obyčejný DNS (přes TCP)",
|
||||||
"all_lists_up_to_date_toast": "Všechny seznamy jsou již aktuální",
|
"all_lists_up_to_date_toast": "Všechny seznamy jsou již aktuální",
|
||||||
"updated_upstream_dns_toast": "Aktualizované upstream DNS servery",
|
"updated_upstream_dns_toast": "Odchozí servery byly úspěšně uloženy",
|
||||||
"dns_test_ok_toast": "Specifikované DNS servery pracují správně",
|
"dns_test_ok_toast": "Specifikované DNS servery pracují správně",
|
||||||
"dns_test_not_ok_toast": "Server \"{{key}}\": nemohl být použit, zkontrolujte, zda jste ho správně napsali",
|
"dns_test_not_ok_toast": "Server \"{{key}}\": nemohl být použit, zkontrolujte, zda jste ho správně napsali",
|
||||||
"unblock": "Odblokovat",
|
"unblock": "Odblokovat",
|
||||||
@@ -235,7 +235,7 @@
|
|||||||
"loading_table_status": "Načítání...",
|
"loading_table_status": "Načítání...",
|
||||||
"page_table_footer_text": "Stránka",
|
"page_table_footer_text": "Stránka",
|
||||||
"rows_table_footer_text": "řádky",
|
"rows_table_footer_text": "řádky",
|
||||||
"updated_custom_filtering_toast": "Aktualizovaná vlastní pravidla filtrování",
|
"updated_custom_filtering_toast": "Vlastní pravidla byla úspěšně uložena",
|
||||||
"rule_removed_from_custom_filtering_toast": "Pravidlo odstraněno z vlastních pravidel filtrování: {{rule}}",
|
"rule_removed_from_custom_filtering_toast": "Pravidlo odstraněno z vlastních pravidel filtrování: {{rule}}",
|
||||||
"rule_added_to_custom_filtering_toast": "Pravidlo přidáno do vlastních pravidel filtrování: {{rule}}",
|
"rule_added_to_custom_filtering_toast": "Pravidlo přidáno do vlastních pravidel filtrování: {{rule}}",
|
||||||
"query_log_response_status": "Status: {{value}}",
|
"query_log_response_status": "Status: {{value}}",
|
||||||
@@ -306,7 +306,7 @@
|
|||||||
"install_settings_dns_desc": "Budete muset nakonfigurovat Vaše zařízení nebo router, aby používali DNS server na následujících adresách:",
|
"install_settings_dns_desc": "Budete muset nakonfigurovat Vaše zařízení nebo router, aby používali DNS server na následujících adresách:",
|
||||||
"install_settings_all_interfaces": "Všechna rozhraní",
|
"install_settings_all_interfaces": "Všechna rozhraní",
|
||||||
"install_auth_title": "Ověřování",
|
"install_auth_title": "Ověřování",
|
||||||
"install_auth_desc": "Doporučujeme Vám nakonfigurovat v administrátorském webovém rozhraní AdGuard Home ověření Vaší identity heslem. I když je přístupné pouze ve Vaší lokální síti, je stále důležité chránit jej před neomezeným přístupem.",
|
"install_auth_desc": "V administrátorském webovém rozhraní AdGuard Home musí být nastaveno ověřovací heslo. I když je AdGuard Home přístupný pouze v místní síti, je důležité jej chránit před neomezeným přístupem.",
|
||||||
"install_auth_username": "Uživatelské jméno",
|
"install_auth_username": "Uživatelské jméno",
|
||||||
"install_auth_password": "Heslo",
|
"install_auth_password": "Heslo",
|
||||||
"install_auth_confirm": "Potvrďte heslo",
|
"install_auth_confirm": "Potvrďte heslo",
|
||||||
@@ -503,6 +503,7 @@
|
|||||||
"statistics_clear_confirm": "Opravdu chcete vyčistit statistiky?",
|
"statistics_clear_confirm": "Opravdu chcete vyčistit statistiky?",
|
||||||
"statistics_retention_confirm": "Opravdu chcete změnit uchovávání statistik? Pokud snížíte hodnotu intervalu, některá data budou ztracena",
|
"statistics_retention_confirm": "Opravdu chcete změnit uchovávání statistik? Pokud snížíte hodnotu intervalu, některá data budou ztracena",
|
||||||
"statistics_cleared": "Statistiky úspěšně vyčištěny",
|
"statistics_cleared": "Statistiky úspěšně vyčištěny",
|
||||||
|
"statistics_enable": "Povolit statistiky",
|
||||||
"interval_hours": "Hodiny: {{count}}",
|
"interval_hours": "Hodiny: {{count}}",
|
||||||
"interval_hours_plural": "Hodiny: {{count}}",
|
"interval_hours_plural": "Hodiny: {{count}}",
|
||||||
"filters_configuration": "Konfigurace filtrů",
|
"filters_configuration": "Konfigurace filtrů",
|
||||||
@@ -597,7 +598,7 @@
|
|||||||
"cache_ttl_min_override_desc": "Prodlužte nejkratší hodnotu TTL (v sekundách) obdrženou z odchozího serveru při ukládání DNS odpovědí do mezipaměti",
|
"cache_ttl_min_override_desc": "Prodlužte nejkratší hodnotu TTL (v sekundách) obdrženou z odchozího serveru při ukládání DNS odpovědí do mezipaměti",
|
||||||
"cache_ttl_max_override_desc": "Nastavte maximální hodnotu TTL (v sekundách) pro položky v mezipaměti DNS",
|
"cache_ttl_max_override_desc": "Nastavte maximální hodnotu TTL (v sekundách) pro položky v mezipaměti DNS",
|
||||||
"ttl_cache_validation": "Minimální hodnota TTL mezipaměti musí být menší nebo rovna maximální hodnotě",
|
"ttl_cache_validation": "Minimální hodnota TTL mezipaměti musí být menší nebo rovna maximální hodnotě",
|
||||||
"cache_optimistic": "Optimistický režim",
|
"cache_optimistic": "Optimistické ukládání do mezipaměti",
|
||||||
"cache_optimistic_desc": "Nechte AdGuard Home odpovědět z mezipaměti, i když už platnost položek skončila. Také se je pokuste obnovit.",
|
"cache_optimistic_desc": "Nechte AdGuard Home odpovědět z mezipaměti, i když už platnost položek skončila. Také se je pokuste obnovit.",
|
||||||
"filter_category_general": "Obecné",
|
"filter_category_general": "Obecné",
|
||||||
"filter_category_security": "Bezpečnost",
|
"filter_category_security": "Bezpečnost",
|
||||||
@@ -612,6 +613,8 @@
|
|||||||
"click_to_view_queries": "Klikněte pro zobrazení dotazů",
|
"click_to_view_queries": "Klikněte pro zobrazení dotazů",
|
||||||
"port_53_faq_link": "Port 53 je často obsazen službami \"DNSStubListener\" nebo \"systemd-resolved\". Přečtěte si <0>tento návod</0> o tom, jak to vyřešit.",
|
"port_53_faq_link": "Port 53 je často obsazen službami \"DNSStubListener\" nebo \"systemd-resolved\". Přečtěte si <0>tento návod</0> o tom, jak to vyřešit.",
|
||||||
"adg_will_drop_dns_queries": "AdGuard Home zruší všechny DNS dotazy tohoto klienta.",
|
"adg_will_drop_dns_queries": "AdGuard Home zruší všechny DNS dotazy tohoto klienta.",
|
||||||
"client_not_in_allowed_clients": "Tento klient není povolen, protože není na seznamu \"Povolení klienti\".",
|
"filter_allowlist": "VAROVÁNÍ: Tato akce také vyloučí pravidlo \"{{disallowed_rule}}\" ze seznamu povolených klientů.",
|
||||||
"experimental": "Experimentální"
|
"last_rule_in_allowlist": "Nelze zakázat tohoto klienta, protože vyloučení pravidla \"{{disallowed_rule}}\" ZRUŠÍ seznam \"Povolených klientů\".",
|
||||||
|
"experimental": "Experimentální",
|
||||||
|
"use_saved_key": "Použít dříve uložený klíče"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -208,7 +208,7 @@
|
|||||||
"example_upstream_sdns": "du kan bruge <0>DNS Stamps</0> til <1>DNSCrypt</1> eller <2>DNS-over-HTTPS</2>-resolvers",
|
"example_upstream_sdns": "du kan bruge <0>DNS Stamps</0> til <1>DNSCrypt</1> eller <2>DNS-over-HTTPS</2>-resolvers",
|
||||||
"example_upstream_tcp": "almindelig DNS (over TCP)",
|
"example_upstream_tcp": "almindelig DNS (over TCP)",
|
||||||
"all_lists_up_to_date_toast": "Alle lister er allerede opdaterede",
|
"all_lists_up_to_date_toast": "Alle lister er allerede opdaterede",
|
||||||
"updated_upstream_dns_toast": "Opdaterede upstream DNS-serverene",
|
"updated_upstream_dns_toast": "Upstream-servere er gemt",
|
||||||
"dns_test_ok_toast": "Angivne DNS-servere fungerer korrekt",
|
"dns_test_ok_toast": "Angivne DNS-servere fungerer korrekt",
|
||||||
"dns_test_not_ok_toast": "Server \"{{key}}\": Kunne ikke bruges. Tjek, at du har angivet den korrekt",
|
"dns_test_not_ok_toast": "Server \"{{key}}\": Kunne ikke bruges. Tjek, at du har angivet den korrekt",
|
||||||
"unblock": "Afblokering",
|
"unblock": "Afblokering",
|
||||||
@@ -235,7 +235,7 @@
|
|||||||
"loading_table_status": "Indlæser...",
|
"loading_table_status": "Indlæser...",
|
||||||
"page_table_footer_text": "Side",
|
"page_table_footer_text": "Side",
|
||||||
"rows_table_footer_text": "rækker",
|
"rows_table_footer_text": "rækker",
|
||||||
"updated_custom_filtering_toast": "Tilpassede filtreringsregler er nu opdateret",
|
"updated_custom_filtering_toast": "Tilpassede regler er gemt",
|
||||||
"rule_removed_from_custom_filtering_toast": "Regel fjernet fra de tilpassede filtreringsregler: {{rule}}",
|
"rule_removed_from_custom_filtering_toast": "Regel fjernet fra de tilpassede filtreringsregler: {{rule}}",
|
||||||
"rule_added_to_custom_filtering_toast": "Regel føjet til de tilpassede filtreringsregler: {{rule}}",
|
"rule_added_to_custom_filtering_toast": "Regel føjet til de tilpassede filtreringsregler: {{rule}}",
|
||||||
"query_log_response_status": "Status: {{value}}",
|
"query_log_response_status": "Status: {{value}}",
|
||||||
@@ -306,7 +306,7 @@
|
|||||||
"install_settings_dns_desc": "Du skal opsætte dine enheder eller router til at bruge DNS-serveren på flg. adresser:",
|
"install_settings_dns_desc": "Du skal opsætte dine enheder eller router til at bruge DNS-serveren på flg. adresser:",
|
||||||
"install_settings_all_interfaces": "Alle grænseflader",
|
"install_settings_all_interfaces": "Alle grænseflader",
|
||||||
"install_auth_title": "Godkendelse",
|
"install_auth_title": "Godkendelse",
|
||||||
"install_auth_desc": "Det anbefales stærkt at opsætte adgangskodegodkendelse på din AdGuard Home admin webgrænseflade. Selvom den kun er tilgængelig på dit lokalnetværk, er det stadig vigtigt at få den beskyttet mod ubegrænset adgang.",
|
"install_auth_desc": "Adgangskodegodkendelse på din AdGuard Home admin-webflade skal opsættes. Selv hvis AdGuard Home kun er tilgængelig på lokalnetværket, er beskyttelse mod uautoriseret og ubegrænset adgang stadig vigtig.",
|
||||||
"install_auth_username": "Brugernavn",
|
"install_auth_username": "Brugernavn",
|
||||||
"install_auth_password": "Adgangskode",
|
"install_auth_password": "Adgangskode",
|
||||||
"install_auth_confirm": "Bekræft adgangskode",
|
"install_auth_confirm": "Bekræft adgangskode",
|
||||||
@@ -326,10 +326,10 @@
|
|||||||
"install_devices_router_list_4": "På visse routertyper kan en tilpasset DNS-server ikke opsættes. I så tilfælde kan det hjælpe, hvis du opsætter AdGuard Home som en <0>DHCP-server</0>. Ellers bør du tjekke i routermanualen, hvordan du tilpasser DNS-servere i din givne routermodel.",
|
"install_devices_router_list_4": "På visse routertyper kan en tilpasset DNS-server ikke opsættes. I så tilfælde kan det hjælpe, hvis du opsætter AdGuard Home som en <0>DHCP-server</0>. Ellers bør du tjekke i routermanualen, hvordan du tilpasser DNS-servere i din givne routermodel.",
|
||||||
"install_devices_windows_list_1": "Åbn Kontrolpanel via menuen Start eller Windows-søgning.",
|
"install_devices_windows_list_1": "Åbn Kontrolpanel via menuen Start eller Windows-søgning.",
|
||||||
"install_devices_windows_list_2": "Gå til kategorien Netværk og Internet og derefter til Netværks- og delingscenter.",
|
"install_devices_windows_list_2": "Gå til kategorien Netværk og Internet og derefter til Netværks- og delingscenter.",
|
||||||
"install_devices_windows_list_3": "Til venstre finder du punktet Skift adapterindstillinger, klik på dette.",
|
"install_devices_windows_list_3": "Find punktet \"Skift adapterindstillinger\" til venstre på skærmen, klik på det.",
|
||||||
"install_devices_windows_list_4": "Vælg din aktive forbindelse, højreklik på den og vælg Egenskaber.",
|
"install_devices_windows_list_4": "Vælg din aktive forbindelse, højreklik på den og vælg Egenskaber.",
|
||||||
"install_devices_windows_list_5": "Find Internet Protocol Version 4 (TCP/IP) på listen, vælg den og klik derefter på Egenskaber igen.",
|
"install_devices_windows_list_5": "Find \"Internet Protocol Version 4 (TCP/IPv4)\" (eller for IPv6, \"Internet Protocol Version 6 (TCP/IPv6)\") på listen, vælg den og klik derefter på Egenskaber igen.",
|
||||||
"install_devices_windows_list_6": "Vælg Brug følgende DNS-serveradresser og angiv dine AdGuard Home-serveradresser.",
|
"install_devices_windows_list_6": "Vælg \"Brug følgende DNS-serveradresser og angiv dine AdGuard Home-serveradresser.",
|
||||||
"install_devices_macos_list_1": "Klik på Apple-ikonet og gå til Systemindstillinger.",
|
"install_devices_macos_list_1": "Klik på Apple-ikonet og gå til Systemindstillinger.",
|
||||||
"install_devices_macos_list_2": "Klik på Netværk.",
|
"install_devices_macos_list_2": "Klik på Netværk.",
|
||||||
"install_devices_macos_list_3": "Vælg den første forbindelse på din liste, og klik på Avanceret.",
|
"install_devices_macos_list_3": "Vælg den første forbindelse på din liste, og klik på Avanceret.",
|
||||||
@@ -499,10 +499,11 @@
|
|||||||
"statistics_configuration": "Statistikopsætning",
|
"statistics_configuration": "Statistikopsætning",
|
||||||
"statistics_retention": "Statistikbevarelse",
|
"statistics_retention": "Statistikbevarelse",
|
||||||
"statistics_retention_desc": "Mindskes intervalværdien, vil nogle data gå tabt",
|
"statistics_retention_desc": "Mindskes intervalværdien, vil nogle data gå tabt",
|
||||||
"statistics_clear": " Ryd statistikker",
|
"statistics_clear": "Ryd statistikker",
|
||||||
"statistics_clear_confirm": "Sikker på, at du vil slette statistikkerne?",
|
"statistics_clear_confirm": "Sikker på, at du vil slette statistikkerne?",
|
||||||
"statistics_retention_confirm": "Sikker på, at du vil ændre på statistikbevaring? Mindskes intervalværdien, vil nogle data gå tabt",
|
"statistics_retention_confirm": "Sikker på, at du vil ændre på statistikbevaring? Mindskes intervalværdien, vil nogle data gå tabt",
|
||||||
"statistics_cleared": "Statistikkerne er ryddet",
|
"statistics_cleared": "Statistikkerne er ryddet",
|
||||||
|
"statistics_enable": "Aktivér statistikker",
|
||||||
"interval_hours": "{{count}} time",
|
"interval_hours": "{{count}} time",
|
||||||
"interval_hours_plural": "{{count}} timer",
|
"interval_hours_plural": "{{count}} timer",
|
||||||
"filters_configuration": "Filteropsætninger",
|
"filters_configuration": "Filteropsætninger",
|
||||||
@@ -597,7 +598,7 @@
|
|||||||
"cache_ttl_min_override_desc": "Forlæng korte time-to-live værdier (sekunder) modtaget fra upstream-serveren, når DNS-svar cachelagres",
|
"cache_ttl_min_override_desc": "Forlæng korte time-to-live værdier (sekunder) modtaget fra upstream-serveren, når DNS-svar cachelagres",
|
||||||
"cache_ttl_max_override_desc": "Indstil en maksimal time-to-live (sekunder) for registreringer i DNS-cachen",
|
"cache_ttl_max_override_desc": "Indstil en maksimal time-to-live (sekunder) for registreringer i DNS-cachen",
|
||||||
"ttl_cache_validation": "Minimum cache TTL-værdi skal være mindre end eller lig med den maksimale værdi",
|
"ttl_cache_validation": "Minimum cache TTL-værdi skal være mindre end eller lig med den maksimale værdi",
|
||||||
"cache_optimistic": "Optimistisk",
|
"cache_optimistic": "Optimistisk caching",
|
||||||
"cache_optimistic_desc": "Får AdGuard Home til at svare fra cachen, selv når posterne er udløbet, og prøver også at opdatere dem.",
|
"cache_optimistic_desc": "Får AdGuard Home til at svare fra cachen, selv når posterne er udløbet, og prøver også at opdatere dem.",
|
||||||
"filter_category_general": "Generelt",
|
"filter_category_general": "Generelt",
|
||||||
"filter_category_security": "Sikkerhed",
|
"filter_category_security": "Sikkerhed",
|
||||||
@@ -612,6 +613,8 @@
|
|||||||
"click_to_view_queries": "Klik for at se forespørgsler",
|
"click_to_view_queries": "Klik for at se forespørgsler",
|
||||||
"port_53_faq_link": "Port 53 optages ofte af \"DNSStubListener\" eller \"systemd-resolved\" tjenester. Læs <0>denne instruktion</0> om, hvordan du løser dette.",
|
"port_53_faq_link": "Port 53 optages ofte af \"DNSStubListener\" eller \"systemd-resolved\" tjenester. Læs <0>denne instruktion</0> om, hvordan du løser dette.",
|
||||||
"adg_will_drop_dns_queries": "AdGuard Home vil afbryde alle DNS-forespørgsler fra denne klient.",
|
"adg_will_drop_dns_queries": "AdGuard Home vil afbryde alle DNS-forespørgsler fra denne klient.",
|
||||||
"client_not_in_allowed_clients": "Klienten er ikke tilladt, fordi den ikke er på listen \"Tilladte klienter\".",
|
"filter_allowlist": "ADVARSEL: Denne handling udelukker også reglen \"{{disallowed_rule}}\" fra listen over tilladte klienter.",
|
||||||
"experimental": "Eksperimentel"
|
"last_rule_in_allowlist": "Kan ikke afvise denne klient, da udelukkelse af reglen \"{{disallowed_rule}}\" DEAKTIVERER listen \"Tilladte klienter\".",
|
||||||
|
"experimental": "Eksperimentel",
|
||||||
|
"use_saved_key": "Brug den tidligere gemte nøgle"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -42,7 +42,7 @@
|
|||||||
"form_error_mac_format": "Ungültiges MAC-Format",
|
"form_error_mac_format": "Ungültiges MAC-Format",
|
||||||
"form_error_client_id_format": "Ungültiges Client-ID-Format",
|
"form_error_client_id_format": "Ungültiges Client-ID-Format",
|
||||||
"form_error_server_name": "Ungültiger Servername",
|
"form_error_server_name": "Ungültiger Servername",
|
||||||
"form_error_subnet": "Subnetz „{{cidr}}” enthält nicht die IP-Adresse „{{ip}}”",
|
"form_error_subnet": "Subnetz „{{cidr}}“ enthält nicht die IP-Adresse „{{ip}}“",
|
||||||
"form_error_positive": "Muss größer als 0 sein.",
|
"form_error_positive": "Muss größer als 0 sein.",
|
||||||
"form_error_negative": "Muss gleich oder größer als 0 (Null) sein",
|
"form_error_negative": "Muss gleich oder größer als 0 (Null) sein",
|
||||||
"range_end_error": "Muss größer als der Bereichsbeginn sein",
|
"range_end_error": "Muss größer als der Bereichsbeginn sein",
|
||||||
@@ -62,9 +62,9 @@
|
|||||||
"dhcp_warning": "Wenn Sie den DHCP-Server trotzdem aktivieren möchten, stellen Sie sicher, dass sich in Ihrem Netzwerk kein anderer aktiver DHCP-Server befindet. Andernfalls kann es bei angeschlossenen Geräten zu einem Ausfall des Internets kommen!",
|
"dhcp_warning": "Wenn Sie den DHCP-Server trotzdem aktivieren möchten, stellen Sie sicher, dass sich in Ihrem Netzwerk kein anderer aktiver DHCP-Server befindet. Andernfalls kann es bei angeschlossenen Geräten zu einem Ausfall des Internets kommen!",
|
||||||
"dhcp_error": "Es konnte nicht ermittelt werden, ob es einen anderen DHCP-Server im Netzwerk gibt.",
|
"dhcp_error": "Es konnte nicht ermittelt werden, ob es einen anderen DHCP-Server im Netzwerk gibt.",
|
||||||
"dhcp_static_ip_error": "Um den DHCP-Server nutzen zu können, muss eine statische IP-Adresse festgelegt werden. Es konnte nicht ermittelt werden, ob diese Netzwerkschnittstelle mit statischer IP-Adresse konfiguriert ist. Bitte legen Sie eine statische IP-Adresse manuell fest.",
|
"dhcp_static_ip_error": "Um den DHCP-Server nutzen zu können, muss eine statische IP-Adresse festgelegt werden. Es konnte nicht ermittelt werden, ob diese Netzwerkschnittstelle mit statischer IP-Adresse konfiguriert ist. Bitte legen Sie eine statische IP-Adresse manuell fest.",
|
||||||
"dhcp_dynamic_ip_found": "Ihr System verwendet die dynamische Konfiguration der IP-Adresse für die Schnittstelle <0>{{interfaceName}}</0>. Um den DHCP-Server nutzen zu können, muss eine statische IP-Adresse festgelegt werden. Ihre aktuelle IP-Adresse ist <0>{{ipAddress}}</0>. Diese IP-Adresse wird automatisch als statisch festgelegt, sobald Sie auf die Schaltfläche „DHCP-Server aktivieren” klicken.",
|
"dhcp_dynamic_ip_found": "Ihr System verwendet die dynamische Konfiguration der IP-Adresse für die Schnittstelle <0>{{interfaceName}}</0>. Um den DHCP-Server nutzen zu können, muss eine statische IP-Adresse festgelegt werden. Ihre aktuelle IP-Adresse ist <0>{{ipAddress}}</0>. Diese IP-Adresse wird automatisch als statisch festgelegt, sobald Sie auf die Schaltfläche „DHCP-Server aktivieren“ klicken.",
|
||||||
"dhcp_lease_added": "Statischer Lease „{{key}}” erfolgreich hinzugefügt",
|
"dhcp_lease_added": "Statischer Lease „{{key}}“ erfolgreich hinzugefügt",
|
||||||
"dhcp_lease_deleted": "Statischer Lease „{{key}}” erfolgreich entfernt",
|
"dhcp_lease_deleted": "Statischer Lease „{{key}}“ erfolgreich entfernt",
|
||||||
"dhcp_new_static_lease": "Neuer statischer Lease",
|
"dhcp_new_static_lease": "Neuer statischer Lease",
|
||||||
"dhcp_static_leases_not_found": "Keine statischen DHCP-Leases gefunden",
|
"dhcp_static_leases_not_found": "Keine statischen DHCP-Leases gefunden",
|
||||||
"dhcp_add_static_lease": "Statischen Lease hinzufügen",
|
"dhcp_add_static_lease": "Statischen Lease hinzufügen",
|
||||||
@@ -74,7 +74,7 @@
|
|||||||
"dhcp_reset": "Möchten Sie die DHCP-Konfiguration wirklich zurücksetzen?",
|
"dhcp_reset": "Möchten Sie die DHCP-Konfiguration wirklich zurücksetzen?",
|
||||||
"country": "Land",
|
"country": "Land",
|
||||||
"city": "Stadt",
|
"city": "Stadt",
|
||||||
"delete_confirm": "Möchten Sie „{{key}}” wirklich löschen?",
|
"delete_confirm": "Möchten Sie „{{key}}“ wirklich löschen?",
|
||||||
"form_enter_hostname": "Gerätenamen eingeben",
|
"form_enter_hostname": "Gerätenamen eingeben",
|
||||||
"error_details": "Fehlerdetails",
|
"error_details": "Fehlerdetails",
|
||||||
"response_details": "Einzelheiten der Antwort",
|
"response_details": "Einzelheiten der Antwort",
|
||||||
@@ -124,7 +124,7 @@
|
|||||||
"number_of_dns_query_days_plural": "Anzahl der DNS-Abfragen, die in den letzten {{count}} Tagen verarbeitet wurden",
|
"number_of_dns_query_days_plural": "Anzahl der DNS-Abfragen, die in den letzten {{count}} Tagen verarbeitet wurden",
|
||||||
"number_of_dns_query_24_hours": "Anzahl der in den letzten 24 Stunden durchgeführten DNS-Anfragen",
|
"number_of_dns_query_24_hours": "Anzahl der in den letzten 24 Stunden durchgeführten DNS-Anfragen",
|
||||||
"number_of_dns_query_blocked_24_hours": "Anzahl der durch Werbefilter und Host-Sperrlisten abgelehnte DNS-Anfragen",
|
"number_of_dns_query_blocked_24_hours": "Anzahl der durch Werbefilter und Host-Sperrlisten abgelehnte DNS-Anfragen",
|
||||||
"number_of_dns_query_blocked_24_hours_by_sec": "Anzahl der durch das AdGuard-Modul „Internetsicherheit” gesperrten DNS-Anfragen",
|
"number_of_dns_query_blocked_24_hours_by_sec": "Anzahl der durch das AdGuard-Modul „Internetsicherheit“ gesperrten DNS-Anfragen",
|
||||||
"number_of_dns_query_blocked_24_hours_adult": "Anzahl der gesperrten Webseiten mit jugendgefährdenden Inhalten",
|
"number_of_dns_query_blocked_24_hours_adult": "Anzahl der gesperrten Webseiten mit jugendgefährdenden Inhalten",
|
||||||
"enforced_save_search": "SafeSearch erzwungen",
|
"enforced_save_search": "SafeSearch erzwungen",
|
||||||
"number_of_dns_query_to_safe_search": "Anzahl der DNS-Anfragen bei denen SafeSearch für Suchanfragen erzwungen wurde",
|
"number_of_dns_query_to_safe_search": "Anzahl der DNS-Anfragen bei denen SafeSearch für Suchanfragen erzwungen wurde",
|
||||||
@@ -208,7 +208,7 @@
|
|||||||
"example_upstream_sdns": "Sie können <0>DNS-Stempel</0> für <1>DNSCrypt</1> oder <2>DNS-over-HTTPS</2> Resolver benutzen",
|
"example_upstream_sdns": "Sie können <0>DNS-Stempel</0> für <1>DNSCrypt</1> oder <2>DNS-over-HTTPS</2> Resolver benutzen",
|
||||||
"example_upstream_tcp": "regulärer DNS (über TCP)",
|
"example_upstream_tcp": "regulärer DNS (über TCP)",
|
||||||
"all_lists_up_to_date_toast": "Alle Listen sind bereits auf dem neuesten Stand",
|
"all_lists_up_to_date_toast": "Alle Listen sind bereits auf dem neuesten Stand",
|
||||||
"updated_upstream_dns_toast": "Upstream-DNS-Server wurden aktualisiert",
|
"updated_upstream_dns_toast": "Upstream-Server erfolgreich gespeichert",
|
||||||
"dns_test_ok_toast": "Angegebene DNS-Server arbeiten ordnungsgemäß",
|
"dns_test_ok_toast": "Angegebene DNS-Server arbeiten ordnungsgemäß",
|
||||||
"dns_test_not_ok_toast": "Server „{{key}}“: konnte nicht verwendet werden, bitte überprüfen Sie die korrekte Schreibweise",
|
"dns_test_not_ok_toast": "Server „{{key}}“: konnte nicht verwendet werden, bitte überprüfen Sie die korrekte Schreibweise",
|
||||||
"unblock": "Entsperren",
|
"unblock": "Entsperren",
|
||||||
@@ -235,7 +235,7 @@
|
|||||||
"loading_table_status": "Wird geladen …",
|
"loading_table_status": "Wird geladen …",
|
||||||
"page_table_footer_text": "Seite",
|
"page_table_footer_text": "Seite",
|
||||||
"rows_table_footer_text": "Reihen",
|
"rows_table_footer_text": "Reihen",
|
||||||
"updated_custom_filtering_toast": "Die benutzerdefinierten Filterregeln wurden aktualisiert",
|
"updated_custom_filtering_toast": "Benutzerdefinierten Filterregeln erfolgreich gespeichert",
|
||||||
"rule_removed_from_custom_filtering_toast": "Regel wurde aus den benutzerdefinierten Filterregeln entfernt: {{rule}}",
|
"rule_removed_from_custom_filtering_toast": "Regel wurde aus den benutzerdefinierten Filterregeln entfernt: {{rule}}",
|
||||||
"rule_added_to_custom_filtering_toast": "Regel wurde zu den benutzerdefinierten Filterregeln hinzugefügt: {{rule}}",
|
"rule_added_to_custom_filtering_toast": "Regel wurde zu den benutzerdefinierten Filterregeln hinzugefügt: {{rule}}",
|
||||||
"query_log_response_status": "Status: {{value}}",
|
"query_log_response_status": "Status: {{value}}",
|
||||||
@@ -306,7 +306,7 @@
|
|||||||
"install_settings_dns_desc": "Sie müssen Ihre Geräte oder Ihren Router so konfigurieren, dass er den DNS-Server unter den folgenden Adressen verwendet:",
|
"install_settings_dns_desc": "Sie müssen Ihre Geräte oder Ihren Router so konfigurieren, dass er den DNS-Server unter den folgenden Adressen verwendet:",
|
||||||
"install_settings_all_interfaces": "Alle Schnittstellen",
|
"install_settings_all_interfaces": "Alle Schnittstellen",
|
||||||
"install_auth_title": "Authentifizierung",
|
"install_auth_title": "Authentifizierung",
|
||||||
"install_auth_desc": "Es wird dringend empfohlen, die Passwortauthentifizierung für Ihre AdGuard Home Administrator-Weboberfläche zu konfigurieren. Auch wenn es nur in Ihrem lokalen Netzwerk zugänglich ist, ist es dennoch wichtig, es vor unbefugtem Zugriff zu schützen.",
|
"install_auth_desc": "Die Passwortauthentifizierung für Ihre AdGuard Home Administrator-Weboberfläche muss konfiguriert sein. Auch wenn AdGuard Home nur in Ihrem lokalen Netzwerk zugänglich ist, ist es dennoch wichtig, es vor unbefugtem Zugriff zu schützen.",
|
||||||
"install_auth_username": "Benutzername",
|
"install_auth_username": "Benutzername",
|
||||||
"install_auth_password": "Passwort",
|
"install_auth_password": "Passwort",
|
||||||
"install_auth_confirm": "Passwort bestätigen",
|
"install_auth_confirm": "Passwort bestätigen",
|
||||||
@@ -325,22 +325,22 @@
|
|||||||
"install_devices_router_list_3": "Geben Sie dort Ihre AdGuard Home Server-Adressen ein.",
|
"install_devices_router_list_3": "Geben Sie dort Ihre AdGuard Home Server-Adressen ein.",
|
||||||
"install_devices_router_list_4": "Bei einigen Routertypen kann kein eigener DNS-Server eingerichtet werden. In diesem Fall kann es helfen, AdGuard Home als <0>DHCP-Server</0> einzurichten. Andernfalls sollten Sie im Handbuch des Routers nachsehen, wie Sie DNS-Server auf Ihrem konkreten Router-Modell anpassen können.",
|
"install_devices_router_list_4": "Bei einigen Routertypen kann kein eigener DNS-Server eingerichtet werden. In diesem Fall kann es helfen, AdGuard Home als <0>DHCP-Server</0> einzurichten. Andernfalls sollten Sie im Handbuch des Routers nachsehen, wie Sie DNS-Server auf Ihrem konkreten Router-Modell anpassen können.",
|
||||||
"install_devices_windows_list_1": "Öffnen Sie die Systemsteuerung über das Startmenü oder die Windows-Suche.",
|
"install_devices_windows_list_1": "Öffnen Sie die Systemsteuerung über das Startmenü oder die Windows-Suche.",
|
||||||
"install_devices_windows_list_2": "Öffnen Sie die Kategorie „Netzwerk und Internet” und dann „Netzwerk- und Freigabecenter”.",
|
"install_devices_windows_list_2": "Öffnen Sie die Kategorie „Netzwerk und Internet“ und dann „Netzwerk- und Freigabecenter“.",
|
||||||
"install_devices_windows_list_3": "Suchen Sie auf der linken Seite des Bildschirms nach „Adaptereinstellungen ändern” und klicken Sie darauf.",
|
"install_devices_windows_list_3": "Suchen Sie auf der linken Seite des Bildschirms nach „Adaptereinstellungen ändern“ und klicken Sie darauf.",
|
||||||
"install_devices_windows_list_4": "Wählen Sie Ihre aktive Verbindung aus, klicken Sie mit der rechten Maustaste darauf und wählen Sie „Eigenschaften”.",
|
"install_devices_windows_list_4": "Wählen Sie Ihre aktive Verbindung aus, klicken Sie mit der rechten Maustaste darauf und wählen Sie „Eigenschaften“.",
|
||||||
"install_devices_windows_list_5": "Suchen Sie in der Liste nach „Internet Protokoll Version 4 (TCP/IP)” (oder, für IPv6, „Internet Protocol Version 6 (TCP/IPv6)“), markieren Sie diese und klicken Sie dann erneut auf „Eigenschaften”.",
|
"install_devices_windows_list_5": "Suchen Sie in der Liste nach „Internet Protokoll Version 4 (TCP/IP)“ (oder, für IPv6, „Internet Protocol Version 6 (TCP/IPv6)“), markieren Sie diese und klicken Sie dann erneut auf „Eigenschaften“.",
|
||||||
"install_devices_windows_list_6": "Wählen Sie „Folgende DNS-Serveradressen verwenden” und geben Sie Ihre AdGuard Home-Serveradressen ein.",
|
"install_devices_windows_list_6": "Wählen Sie „Folgende DNS-Serveradressen verwenden“ und geben Sie Ihre AdGuard Home-Serveradressen ein.",
|
||||||
"install_devices_macos_list_1": "Klicken Sie auf das Apple-Symbol (oben links in der Menüzeile) und wählen den Eintrag „Systemeinstellungen”.",
|
"install_devices_macos_list_1": "Klicken Sie auf das Apple-Symbol (oben links in der Menüzeile) und wählen den Eintrag „Systemeinstellungen“.",
|
||||||
"install_devices_macos_list_2": "Klicken Sie dort auf „Netzwerk”",
|
"install_devices_macos_list_2": "Klicken Sie dort auf „Netzwerk“",
|
||||||
"install_devices_macos_list_3": "Wählen Sie die erste Verbindung in Ihrer Liste aus und klicken Sie auf „Weitere Optionen”.",
|
"install_devices_macos_list_3": "Wählen Sie die erste Verbindung in Ihrer Liste aus und klicken Sie auf „Weitere Optionen“.",
|
||||||
"install_devices_macos_list_4": "Wählen Sie den Tab „DNS” und geben Sie dort Ihre AdGuard Home-Serveradressen ein.",
|
"install_devices_macos_list_4": "Wählen Sie den Tab „DNS“ und geben Sie dort Ihre AdGuard Home-Serveradressen ein.",
|
||||||
"install_devices_android_list_1": "Tippen Sie auf dem Startbildschirm des Android-Menüs auf „Einstellungen”.",
|
"install_devices_android_list_1": "Tippen Sie auf dem Startbildschirm des Android-Menüs auf „Einstellungen“.",
|
||||||
"install_devices_android_list_2": "Tippen Sie im Menü auf „WLAN”. Der Bildschirm mit allen verfügbaren Netzwerken wird angezeigt (es ist nicht möglich, einen benutzerdefinierten DNS für die mobile Verbindung einzustellen).",
|
"install_devices_android_list_2": "Tippen Sie im Menü auf „WLAN“. Der Bildschirm mit allen verfügbaren Netzwerken wird angezeigt (es ist nicht möglich, einen benutzerdefinierten DNS für die mobile Verbindung einzustellen).",
|
||||||
"install_devices_android_list_3": "Drücken Sie lange auf das Netzwerk, mit dem Sie verbunden sind, und tippen Sie auf „Netzwerk ändern”.",
|
"install_devices_android_list_3": "Drücken Sie lange auf das Netzwerk, mit dem Sie verbunden sind, und tippen Sie auf „Netzwerk ändern“.",
|
||||||
"install_devices_android_list_4": "Bei einigen Geräten müssen Sie möglicherweise das Kontrollkästchen für „Erweitert” aktivieren, um weitere Einstellungen anzuzeigen. Um Ihre Android-DNS-Einstellungen anzupassen, müssen Sie die IP-Einstellungen von „DHCP” auf „Statisch” umstellen.",
|
"install_devices_android_list_4": "Bei einigen Geräten müssen Sie möglicherweise das Kontrollkästchen für „Erweitert“ aktivieren, um weitere Einstellungen anzuzeigen. Um Ihre Android-DNS-Einstellungen anzupassen, müssen Sie die IP-Einstellungen von „DHCP“ auf „Statisch“ umstellen.",
|
||||||
"install_devices_android_list_5": "Ändern Sie die Werte für „DNS 1” und „DNS 2” auf Ihre AdGuard Home-Serveradressen.",
|
"install_devices_android_list_5": "Ändern Sie die Werte für „DNS 1“ und „DNS 2“ auf Ihre AdGuard Home-Serveradressen.",
|
||||||
"install_devices_ios_list_1": "Tippen Sie auf dem Startbildschirm auf „Einstellungen”.",
|
"install_devices_ios_list_1": "Tippen Sie auf dem Startbildschirm auf „Einstellungen“.",
|
||||||
"install_devices_ios_list_2": "Wählen Sie „WLAN” im linken Menü (es ist nicht möglich, DNS für mobile Netzwerke zu konfigurieren).",
|
"install_devices_ios_list_2": "Wählen Sie „WLAN“ im linken Menü (es ist nicht möglich, DNS für mobile Netzwerke zu konfigurieren).",
|
||||||
"install_devices_ios_list_3": "Tippen Sie auf den Namen des aktuell aktiven Netzwerks.",
|
"install_devices_ios_list_3": "Tippen Sie auf den Namen des aktuell aktiven Netzwerks.",
|
||||||
"install_devices_ios_list_4": "Geben Sie im DNS-Feld Ihre AdGuard Home-Serveradressen ein.",
|
"install_devices_ios_list_4": "Geben Sie im DNS-Feld Ihre AdGuard Home-Serveradressen ein.",
|
||||||
"get_started": "Anfangen",
|
"get_started": "Anfangen",
|
||||||
@@ -356,7 +356,7 @@
|
|||||||
"encryption_redirect": "Automatisch auf HTTPS umleiten",
|
"encryption_redirect": "Automatisch auf HTTPS umleiten",
|
||||||
"encryption_redirect_desc": "Wenn aktiviert, leitet AdGuard Home Sie automatisch von HTTP- auf HTTPS-Adressen um.",
|
"encryption_redirect_desc": "Wenn aktiviert, leitet AdGuard Home Sie automatisch von HTTP- auf HTTPS-Adressen um.",
|
||||||
"encryption_https": "HTTPS-Port",
|
"encryption_https": "HTTPS-Port",
|
||||||
"encryption_https_desc": "Wenn der HTTPS-Port konfiguriert ist, ist die AdGuard Home-Administrationsschnittstelle über HTTPS zugänglich und bietet auch DNS-over-HTTPS am Server „/dns-query”.",
|
"encryption_https_desc": "Wenn der HTTPS-Port konfiguriert ist, ist die AdGuard Home-Administrationsschnittstelle über HTTPS zugänglich und bietet auch DNS-over-HTTPS am Server „/dns-query“.",
|
||||||
"encryption_dot": "DNS-over-TLS",
|
"encryption_dot": "DNS-over-TLS",
|
||||||
"encryption_dot_desc": "Wenn dieser Port konfiguriert ist, führt AdGuard Home auf diesem Port einen DNS-over-TLS-Server aus.",
|
"encryption_dot_desc": "Wenn dieser Port konfiguriert ist, führt AdGuard Home auf diesem Port einen DNS-over-TLS-Server aus.",
|
||||||
"encryption_doq": "Port für DNS-over-QUIC",
|
"encryption_doq": "Port für DNS-over-QUIC",
|
||||||
@@ -410,18 +410,18 @@
|
|||||||
"ip_address": "IP-Adresse",
|
"ip_address": "IP-Adresse",
|
||||||
"client_identifier_desc": "Clients können durch die IP-Adresse, CIDR, MAC-Adresse oder eine spezielle Client-ID (können für DoT/DoH/DoQ verwendet werden) identifiziert werden. <0>Hier</0> erfahren Sie mehr darüber, wie Sie Kunden identifizieren.",
|
"client_identifier_desc": "Clients können durch die IP-Adresse, CIDR, MAC-Adresse oder eine spezielle Client-ID (können für DoT/DoH/DoQ verwendet werden) identifiziert werden. <0>Hier</0> erfahren Sie mehr darüber, wie Sie Kunden identifizieren.",
|
||||||
"form_enter_ip": "IP-Adresse eingeben",
|
"form_enter_ip": "IP-Adresse eingeben",
|
||||||
"form_enter_subnet_ip": "IP-Adresse zum Subnetz „{{cidr}}” hinzufügen",
|
"form_enter_subnet_ip": "IP-Adresse zum Subnetz „{{cidr}}“ hinzufügen",
|
||||||
"form_enter_mac": "MAC-Adresse eingeben",
|
"form_enter_mac": "MAC-Adresse eingeben",
|
||||||
"form_enter_id": "Kennung eingeben",
|
"form_enter_id": "Kennung eingeben",
|
||||||
"form_add_id": "Kennung hinzufügen",
|
"form_add_id": "Kennung hinzufügen",
|
||||||
"form_client_name": "Clientnamen eingeben",
|
"form_client_name": "Clientnamen eingeben",
|
||||||
"name": "Name",
|
"name": "Name",
|
||||||
"client_global_settings": "Allgemeine Einstellungen nutzen",
|
"client_global_settings": "Allgemeine Einstellungen nutzen",
|
||||||
"client_deleted": "Client „{{key}}” erfolgreich entfernt",
|
"client_deleted": "Client „{{key}}“ erfolgreich entfernt",
|
||||||
"client_added": "Client „{{key}}” erfolgreich hinzugefügt",
|
"client_added": "Client „{{key}}“ erfolgreich hinzugefügt",
|
||||||
"client_updated": "Client „{{key}}” erfolgreich aktualisiert",
|
"client_updated": "Client „{{key}}“ erfolgreich aktualisiert",
|
||||||
"clients_not_found": "Keine Clients gefunden",
|
"clients_not_found": "Keine Clients gefunden",
|
||||||
"client_confirm_delete": "Möchten Sie den Client „{{key}}” wirklich löschen?",
|
"client_confirm_delete": "Möchten Sie den Client „{{key}}“ wirklich löschen?",
|
||||||
"list_confirm_delete": "Möchten Sie diese Liste wirklich löschen?",
|
"list_confirm_delete": "Möchten Sie diese Liste wirklich löschen?",
|
||||||
"auto_clients_title": "Clients (Laufzeit)",
|
"auto_clients_title": "Clients (Laufzeit)",
|
||||||
"auto_clients_desc": "Daten zu den Clients, die AdGuard Home verwenden, aber nicht in der Konfiguration gespeichert sind",
|
"auto_clients_desc": "Daten zu den Clients, die AdGuard Home verwenden, aber nicht in der Konfiguration gespeichert sind",
|
||||||
@@ -441,11 +441,11 @@
|
|||||||
"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.",
|
||||||
"setup_dns_privacy_3": "<0>Hier ist eine Liste von Software, die Sie verwenden können.</0>",
|
"setup_dns_privacy_3": "<0>Hier ist eine Liste von Software, die Sie verwenden können.</0>",
|
||||||
"setup_dns_privacy_4": "Auf einem iOS 14 oder macOS Big Sur-Gerät können Sie eine spezielle Datei „.mobileconfig” herunterladen, die Server für <highlight>DNS-über-HTTPS</highlight> oder <highlight>DNS-über-TLS</highlight> zu den DNS-Einstellungen hinzufügt.",
|
"setup_dns_privacy_4": "Auf einem iOS 14 oder macOS Big Sur-Gerät können Sie eine spezielle Datei „.mobileconfig“ herunterladen, die Server für <highlight>DNS-über-HTTPS</highlight> oder <highlight>DNS-über-TLS</highlight> zu den DNS-Einstellungen hinzufügt.",
|
||||||
"setup_dns_privacy_android_1": "Android 9 unterstützt DNS-over-TLS nativ. Um es zu konfigurieren, gehen Sie zu „Einstellungen” → „Netzwerk & Internet” → „Erweitert” → „Privater DNS” und geben Sie dort Ihren Domainnamen ein.",
|
"setup_dns_privacy_android_1": "Android 9 unterstützt DNS-over-TLS nativ. Um es zu konfigurieren, gehen Sie zu „Einstellungen“ → „Netzwerk & Internet“ → „Erweitert“ → „Privater DNS“ und geben Sie dort Ihren Domainnamen ein.",
|
||||||
"setup_dns_privacy_android_2": "<0>AdGuard für Android</0> unterstützt <1>DNS-over-HTTTPS</1> und <1>DNS-over-TLS</1>.",
|
"setup_dns_privacy_android_2": "<0>AdGuard für Android</0> unterstützt <1>DNS-over-HTTTPS</1> und <1>DNS-over-TLS</1>.",
|
||||||
"setup_dns_privacy_android_3": "„<0>Intra</0>” fügt <1>DNS-over-HTTPS</1>-Unterstützung zu Android hinzu.",
|
"setup_dns_privacy_android_3": "„<0>Intra</0>“ fügt <1>DNS-over-HTTPS</1>-Unterstützung zu Android hinzu.",
|
||||||
"setup_dns_privacy_ios_1": "„<0>DNSCloak</0>” unterstützt <1>DNS-over-HTTPS</1>, aber um es so zu konfigurieren, dass es Ihren eigenen Server verwendet, müssen Sie einen <2>DNS-Stempel</2> dafür generieren.",
|
"setup_dns_privacy_ios_1": "„<0>DNSCloak</0>“ unterstützt <1>DNS-over-HTTPS</1>, aber um es so zu konfigurieren, dass es Ihren eigenen Server verwendet, müssen Sie einen <2>DNS-Stempel</2> dafür generieren.",
|
||||||
"setup_dns_privacy_ios_2": "<0>AdGuard für iOS</0> unterstützt die Einrichtung von <1>DNS-over-HTTTPS</1> und <1>DNS-over-TLS</1>.",
|
"setup_dns_privacy_ios_2": "<0>AdGuard für iOS</0> unterstützt die Einrichtung von <1>DNS-over-HTTTPS</1> und <1>DNS-over-TLS</1>.",
|
||||||
"setup_dns_privacy_other_title": "Weitere Umsetzungen",
|
"setup_dns_privacy_other_title": "Weitere Umsetzungen",
|
||||||
"setup_dns_privacy_other_1": "AdGuard Home selbst kann ein sicherer DNS-Client auf jeder Plattform sein.",
|
"setup_dns_privacy_other_1": "AdGuard Home selbst kann ein sicherer DNS-Client auf jeder Plattform sein.",
|
||||||
@@ -455,11 +455,11 @@
|
|||||||
"setup_dns_privacy_other_5": "Weitere Umsetzungen finden Sie <0>hier</0> und <1>hier</1>.",
|
"setup_dns_privacy_other_5": "Weitere Umsetzungen finden Sie <0>hier</0> und <1>hier</1>.",
|
||||||
"setup_dns_privacy_ioc_mac": "Konfiguration für iOS und macOS",
|
"setup_dns_privacy_ioc_mac": "Konfiguration für iOS und macOS",
|
||||||
"setup_dns_notice": "Um <1>DNS-over-HTTTPS</1> oder <1>DNS-over-TLS</1> verwenden zu können, müssen Sie in den AdGuard Home Einstellungen die <0>Verschlüsselung konfigurieren</0>.",
|
"setup_dns_notice": "Um <1>DNS-over-HTTTPS</1> oder <1>DNS-over-TLS</1> verwenden zu können, müssen Sie in den AdGuard Home Einstellungen die <0>Verschlüsselung konfigurieren</0>.",
|
||||||
"rewrite_added": "DNS-Umschreibung für „{{key}}” erfolgreich hinzugefügt",
|
"rewrite_added": "DNS-Umschreibung für „{{key}}“ erfolgreich hinzugefügt",
|
||||||
"rewrite_deleted": "DNS-Umschreibung für „{{key}}” erfolgreich entfernt",
|
"rewrite_deleted": "DNS-Umschreibung für „{{key}}“ erfolgreich entfernt",
|
||||||
"rewrite_add": "DNS-Umschreibung hinzufügen",
|
"rewrite_add": "DNS-Umschreibung hinzufügen",
|
||||||
"rewrite_not_found": "Keine DNS-Umschreibungen gefunden",
|
"rewrite_not_found": "Keine DNS-Umschreibungen gefunden",
|
||||||
"rewrite_confirm_delete": "Möchten Sie die DNS-Umschreibung für „{{key}}” wirklich entfernen?",
|
"rewrite_confirm_delete": "Möchten Sie die DNS-Umschreibung für „{{key}}“ wirklich entfernen?",
|
||||||
"rewrite_desc": "Ermöglicht die einfache Konfiguration der benutzerdefinierten DNS-Antwort für einen bestimmten Domainnamen.",
|
"rewrite_desc": "Ermöglicht die einfache Konfiguration der benutzerdefinierten DNS-Antwort für einen bestimmten Domainnamen.",
|
||||||
"rewrite_applied": "Umschreibungsregel ist angewendet",
|
"rewrite_applied": "Umschreibungsregel ist angewendet",
|
||||||
"rewrite_hosts_applied": "Von Hostdatei-Regel umgeschrieben",
|
"rewrite_hosts_applied": "Von Hostdatei-Regel umgeschrieben",
|
||||||
@@ -499,10 +499,11 @@
|
|||||||
"statistics_configuration": "Statistikkonfiguration",
|
"statistics_configuration": "Statistikkonfiguration",
|
||||||
"statistics_retention": "Statistiken speichern",
|
"statistics_retention": "Statistiken speichern",
|
||||||
"statistics_retention_desc": "Wenn Sie den Zeitraum verringern, werden einige Daten verloren gehen",
|
"statistics_retention_desc": "Wenn Sie den Zeitraum verringern, werden einige Daten verloren gehen",
|
||||||
"statistics_clear": " Statistiken leeren",
|
"statistics_clear": "Statistiken leeren",
|
||||||
"statistics_clear_confirm": "Möchten Sie die Statistiken wirklich löschen?",
|
"statistics_clear_confirm": "Möchten Sie die Statistiken wirklich löschen?",
|
||||||
"statistics_retention_confirm": "Möchten Sie wirklich die Aufbewahrung der Statistiken ändern? Wenn Sie den Zeitabstand verringern, gehen einige Daten verloren.",
|
"statistics_retention_confirm": "Möchten Sie wirklich die Aufbewahrung der Statistiken ändern? Wenn Sie den Zeitabstand verringern, gehen einige Daten verloren.",
|
||||||
"statistics_cleared": "Statistiken wurden erfolgreich gelöscht",
|
"statistics_cleared": "Statistiken wurden erfolgreich gelöscht",
|
||||||
|
"statistics_enable": "Statistiken aktivieren",
|
||||||
"interval_hours": "{{count}} Stunde",
|
"interval_hours": "{{count}} Stunde",
|
||||||
"interval_hours_plural": "{{count}} Stunden",
|
"interval_hours_plural": "{{count}} Stunden",
|
||||||
"filters_configuration": "Filterkonfiguration",
|
"filters_configuration": "Filterkonfiguration",
|
||||||
@@ -538,7 +539,7 @@
|
|||||||
"disable_ipv6_desc": "Löschen Sie alle DNS-Abfragen für IPv6-Adressen (Typ AAAA).",
|
"disable_ipv6_desc": "Löschen Sie alle DNS-Abfragen für IPv6-Adressen (Typ AAAA).",
|
||||||
"fastest_addr": "Schnellste IP-Adresse",
|
"fastest_addr": "Schnellste IP-Adresse",
|
||||||
"fastest_addr_desc": "Fragen Sie alle DNS-Server ab und geben Sie die schnellste IP-Adresse unter allen Antworten zurück. Dies verlangsamt DNS-Abfragen, da AdGuard Home auf Antworten von allen DNS-Servern warten muss, verbessert jedoch die Gesamtkonnektivität.",
|
"fastest_addr_desc": "Fragen Sie alle DNS-Server ab und geben Sie die schnellste IP-Adresse unter allen Antworten zurück. Dies verlangsamt DNS-Abfragen, da AdGuard Home auf Antworten von allen DNS-Servern warten muss, verbessert jedoch die Gesamtkonnektivität.",
|
||||||
"autofix_warning_text": "Wenn Sie auf „Beheben” klicken, konfiguriert AdGuardHome Ihr System für die Verwendung des AdGuardHome-DNS-Servers.",
|
"autofix_warning_text": "Wenn Sie auf „Beheben“ klicken, konfiguriert AdGuardHome Ihr System für die Verwendung des AdGuardHome-DNS-Servers.",
|
||||||
"autofix_warning_list": "Es werden folgende Aufgaben ausgeführt: <0>Deaktivieren des DNSStubListener-Systems</0> <0>Festlegen der DNS-Server-Adresse auf 127.0.0.1</0> <0>Ersetzen des symbolischen Linkziels von /etc/resolv.conf auf /run/systemd/resolve/resolv.conf</0> <0>Anhalten des DNSStubListener (systemseitig aufgelöster Dienst wird nachladen)</0>",
|
"autofix_warning_list": "Es werden folgende Aufgaben ausgeführt: <0>Deaktivieren des DNSStubListener-Systems</0> <0>Festlegen der DNS-Server-Adresse auf 127.0.0.1</0> <0>Ersetzen des symbolischen Linkziels von /etc/resolv.conf auf /run/systemd/resolve/resolv.conf</0> <0>Anhalten des DNSStubListener (systemseitig aufgelöster Dienst wird nachladen)</0>",
|
||||||
"autofix_warning_result": "Als Folge daraus werden alle DNS-Anforderungen von Ihrem System standardmäßig von AdGuardHome verarbeitet.",
|
"autofix_warning_result": "Als Folge daraus werden alle DNS-Anforderungen von Ihrem System standardmäßig von AdGuardHome verarbeitet.",
|
||||||
"tags_title": "Schlagwörter",
|
"tags_title": "Schlagwörter",
|
||||||
@@ -558,10 +559,10 @@
|
|||||||
"check_service": "Dienstname: {{service}}",
|
"check_service": "Dienstname: {{service}}",
|
||||||
"service_name": "Name des Dienstes",
|
"service_name": "Name des Dienstes",
|
||||||
"check_not_found": "Nicht in Ihren Filterlisten enthalten",
|
"check_not_found": "Nicht in Ihren Filterlisten enthalten",
|
||||||
"client_confirm_block": "Möchten Sie den Client „{{ip}}” wirklich sperren?",
|
"client_confirm_block": "Möchten Sie den Client „{{ip}}“ wirklich sperren?",
|
||||||
"client_confirm_unblock": "Möchten Sie den Client „{{ip}}” wirklich entsperren?",
|
"client_confirm_unblock": "Möchten Sie den Client „{{ip}}“ wirklich entsperren?",
|
||||||
"client_blocked": "Client „{{ip}}” erfolgreich gesperrt",
|
"client_blocked": "Client „{{ip}}“ erfolgreich gesperrt",
|
||||||
"client_unblocked": "Client „{{ip}}” erfolgreich entsperrt",
|
"client_unblocked": "Client „{{ip}}“ erfolgreich entsperrt",
|
||||||
"static_ip": "Feste IP-Adresse",
|
"static_ip": "Feste IP-Adresse",
|
||||||
"static_ip_desc": "AdGuard Home ist ein Server und benötigt daher eine feste IP-Adresse, um ordnungsgemäß zu funktionieren. Andernfalls weist Ihr Router diesem Gerät möglicherweise irgendwann eine andere IP-Adresse zu.",
|
"static_ip_desc": "AdGuard Home ist ein Server und benötigt daher eine feste IP-Adresse, um ordnungsgemäß zu funktionieren. Andernfalls weist Ihr Router diesem Gerät möglicherweise irgendwann eine andere IP-Adresse zu.",
|
||||||
"set_static_ip": "Feste IP-Adresse festlegen",
|
"set_static_ip": "Feste IP-Adresse festlegen",
|
||||||
@@ -597,7 +598,7 @@
|
|||||||
"cache_ttl_min_override_desc": "Überschreibt den TTL-Minimalwert, der vom vorgeschalteten Server empfangen wurde. Dieser Wert darf nicht mehr als 3600 (Sek.) (≙ 1 Stunde) betragen.",
|
"cache_ttl_min_override_desc": "Überschreibt den TTL-Minimalwert, der vom vorgeschalteten Server empfangen wurde. Dieser Wert darf nicht mehr als 3600 (Sek.) (≙ 1 Stunde) betragen.",
|
||||||
"cache_ttl_max_override_desc": "Überschreibt den TLL-Maximalwert, der vom vorgeschalteten Server empfangen wurde.",
|
"cache_ttl_max_override_desc": "Überschreibt den TLL-Maximalwert, der vom vorgeschalteten Server empfangen wurde.",
|
||||||
"ttl_cache_validation": "Der minimale Cache des TTL-Wertes muss kleiner oder gleich dem maximalen Wert sein",
|
"ttl_cache_validation": "Der minimale Cache des TTL-Wertes muss kleiner oder gleich dem maximalen Wert sein",
|
||||||
"cache_optimistic": "Optimistisch",
|
"cache_optimistic": "Optimistisches Caching",
|
||||||
"cache_optimistic_desc": "Sorgt dafür, dass AdGuard Home auch dann aus dem Zwischenspeicher antwortet, wenn die Einträge abgelaufen sind, und versucht zudem, diese zu aktualisieren.",
|
"cache_optimistic_desc": "Sorgt dafür, dass AdGuard Home auch dann aus dem Zwischenspeicher antwortet, wenn die Einträge abgelaufen sind, und versucht zudem, diese zu aktualisieren.",
|
||||||
"filter_category_general": "Allgemein",
|
"filter_category_general": "Allgemein",
|
||||||
"filter_category_security": "Sicherheit",
|
"filter_category_security": "Sicherheit",
|
||||||
@@ -610,8 +611,10 @@
|
|||||||
"setup_config_to_enable_dhcp_server": "Einrichten der Konfiguration zur Aktivierung des DHCP-Servers",
|
"setup_config_to_enable_dhcp_server": "Einrichten der Konfiguration zur Aktivierung des DHCP-Servers",
|
||||||
"original_response": "Ursprüngliche Antwort",
|
"original_response": "Ursprüngliche Antwort",
|
||||||
"click_to_view_queries": "Anklicken, um Abfragen anzuzeigen",
|
"click_to_view_queries": "Anklicken, um Abfragen anzuzeigen",
|
||||||
"port_53_faq_link": "Port 53 wird oft von Diensten wie „DNSStubListener” oder „systemresolved” belegt. Bitte lesen Sie <0>diese Anweisung</0>, wie dies behoben werden kann.",
|
"port_53_faq_link": "Port 53 wird oft von Diensten wie „DNSStubListener“ oder „systemresolved“ belegt. Bitte lesen Sie <0>diese Anweisung</0>, wie dies behoben werden kann.",
|
||||||
"adg_will_drop_dns_queries": "AdGuard Home wird alle DNS-Abfragen von diesem Client verwerfen.",
|
"adg_will_drop_dns_queries": "AdGuard Home wird alle DNS-Abfragen von diesem Client verwerfen.",
|
||||||
"client_not_in_allowed_clients": "Dieser Client ist nicht zugelassen, da dieser nicht in der Liste „Erlaubte Clients” aufgeführt ist.",
|
"filter_allowlist": "Warnhinweis: Durch diese Aktion wird außerdem die Regel „{{disallowed_rule}}“ aus der Liste der zugelassenen Clients ausgeschlossen.",
|
||||||
"experimental": "Experimentell"
|
"last_rule_in_allowlist": "Dieser Client kann nicht gesperrt werden, da das Ausschließen der Regel „{{disallowed_rule}}“ die Liste „Zugelassene Clients“ deaktivieren würde.",
|
||||||
|
"experimental": "Experimentell",
|
||||||
|
"use_saved_key": "Zuvor gespeicherten Schlüssel verwenden"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,7 +98,7 @@
|
|||||||
"copyright": "Copyright",
|
"copyright": "Copyright",
|
||||||
"homepage": "Homepage",
|
"homepage": "Homepage",
|
||||||
"report_an_issue": "Report an issue",
|
"report_an_issue": "Report an issue",
|
||||||
"privacy_policy": "Privacy policy",
|
"privacy_policy": "Privacy Policy",
|
||||||
"enable_protection": "Enable protection",
|
"enable_protection": "Enable protection",
|
||||||
"enabled_protection": "Enabled protection",
|
"enabled_protection": "Enabled protection",
|
||||||
"disable_protection": "Disable protection",
|
"disable_protection": "Disable protection",
|
||||||
@@ -208,7 +208,7 @@
|
|||||||
"example_upstream_sdns": "you can use <0>DNS Stamps</0> for <1>DNSCrypt</1> or <2>DNS-over-HTTPS</2> resolvers",
|
"example_upstream_sdns": "you can use <0>DNS Stamps</0> for <1>DNSCrypt</1> or <2>DNS-over-HTTPS</2> resolvers",
|
||||||
"example_upstream_tcp": "regular DNS (over TCP)",
|
"example_upstream_tcp": "regular DNS (over TCP)",
|
||||||
"all_lists_up_to_date_toast": "All lists are already up-to-date",
|
"all_lists_up_to_date_toast": "All lists are already up-to-date",
|
||||||
"updated_upstream_dns_toast": "Updated the upstream DNS servers",
|
"updated_upstream_dns_toast": "Upstream servers successfully saved",
|
||||||
"dns_test_ok_toast": "Specified DNS servers are working correctly",
|
"dns_test_ok_toast": "Specified DNS servers are working correctly",
|
||||||
"dns_test_not_ok_toast": "Server \"{{key}}\": could not be used, please check that you've written it correctly",
|
"dns_test_not_ok_toast": "Server \"{{key}}\": could not be used, please check that you've written it correctly",
|
||||||
"unblock": "Unblock",
|
"unblock": "Unblock",
|
||||||
@@ -235,7 +235,7 @@
|
|||||||
"loading_table_status": "Loading...",
|
"loading_table_status": "Loading...",
|
||||||
"page_table_footer_text": "Page",
|
"page_table_footer_text": "Page",
|
||||||
"rows_table_footer_text": "rows",
|
"rows_table_footer_text": "rows",
|
||||||
"updated_custom_filtering_toast": "Updated the custom filtering rules",
|
"updated_custom_filtering_toast": "Custom rules successfully saved",
|
||||||
"rule_removed_from_custom_filtering_toast": "Rule removed from the custom filtering rules: {{rule}}",
|
"rule_removed_from_custom_filtering_toast": "Rule removed from the custom filtering rules: {{rule}}",
|
||||||
"rule_added_to_custom_filtering_toast": "Rule added to the custom filtering rules: {{rule}}",
|
"rule_added_to_custom_filtering_toast": "Rule added to the custom filtering rules: {{rule}}",
|
||||||
"query_log_response_status": "Status: {{value}}",
|
"query_log_response_status": "Status: {{value}}",
|
||||||
@@ -306,7 +306,7 @@
|
|||||||
"install_settings_dns_desc": "You will need to configure your devices or router to use the DNS server on the following addresses:",
|
"install_settings_dns_desc": "You will need to configure your devices or router to use the DNS server on the following addresses:",
|
||||||
"install_settings_all_interfaces": "All interfaces",
|
"install_settings_all_interfaces": "All interfaces",
|
||||||
"install_auth_title": "Authentication",
|
"install_auth_title": "Authentication",
|
||||||
"install_auth_desc": "It is highly recommended to configure password authentication to your AdGuard Home admin web interface. Even if it is accessible only in your local network, it is still important to protect it from unrestricted access.",
|
"install_auth_desc": "Password authentication to your AdGuard Home admin web interface must be configured. Even if AdGuard Home is accessible only in your local network, it is still important to protect it from unrestricted access.",
|
||||||
"install_auth_username": "Username",
|
"install_auth_username": "Username",
|
||||||
"install_auth_password": "Password",
|
"install_auth_password": "Password",
|
||||||
"install_auth_confirm": "Confirm password",
|
"install_auth_confirm": "Confirm password",
|
||||||
@@ -499,10 +499,11 @@
|
|||||||
"statistics_configuration": "Statistics configuration",
|
"statistics_configuration": "Statistics configuration",
|
||||||
"statistics_retention": "Statistics retention",
|
"statistics_retention": "Statistics retention",
|
||||||
"statistics_retention_desc": "If you decrease the interval value, some data will be lost",
|
"statistics_retention_desc": "If you decrease the interval value, some data will be lost",
|
||||||
"statistics_clear": " Clear statistics",
|
"statistics_clear": "Clear statistics",
|
||||||
"statistics_clear_confirm": "Are you sure you want to clear statistics?",
|
"statistics_clear_confirm": "Are you sure you want to clear statistics?",
|
||||||
"statistics_retention_confirm": "Are you sure you want to change statistics retention? If you decrease the interval value, some data will be lost",
|
"statistics_retention_confirm": "Are you sure you want to change statistics retention? If you decrease the interval value, some data will be lost",
|
||||||
"statistics_cleared": "Statistics successfully cleared",
|
"statistics_cleared": "Statistics successfully cleared",
|
||||||
|
"statistics_enable": "Enable statistics",
|
||||||
"interval_hours": "{{count}} hour",
|
"interval_hours": "{{count}} hour",
|
||||||
"interval_hours_plural": "{{count}} hours",
|
"interval_hours_plural": "{{count}} hours",
|
||||||
"filters_configuration": "Filters configuration",
|
"filters_configuration": "Filters configuration",
|
||||||
@@ -597,7 +598,7 @@
|
|||||||
"cache_ttl_min_override_desc": "Extend short time-to-live values (seconds) received from the upstream server when caching DNS responses",
|
"cache_ttl_min_override_desc": "Extend short time-to-live values (seconds) received from the upstream server when caching DNS responses",
|
||||||
"cache_ttl_max_override_desc": "Set a maximum time-to-live value (seconds) for entries in the DNS cache",
|
"cache_ttl_max_override_desc": "Set a maximum time-to-live value (seconds) for entries in the DNS cache",
|
||||||
"ttl_cache_validation": "Minimum cache TTL value must be less than or equal to the maximum value",
|
"ttl_cache_validation": "Minimum cache TTL value must be less than or equal to the maximum value",
|
||||||
"cache_optimistic": "Optimistic",
|
"cache_optimistic": "Optimistic caching",
|
||||||
"cache_optimistic_desc": "Make AdGuard Home respond from the cache even when the entries are expired and also try to refresh them.",
|
"cache_optimistic_desc": "Make AdGuard Home respond from the cache even when the entries are expired and also try to refresh them.",
|
||||||
"filter_category_general": "General",
|
"filter_category_general": "General",
|
||||||
"filter_category_security": "Security",
|
"filter_category_security": "Security",
|
||||||
@@ -612,6 +613,8 @@
|
|||||||
"click_to_view_queries": "Click to view queries",
|
"click_to_view_queries": "Click to view queries",
|
||||||
"port_53_faq_link": "Port 53 is often occupied by \"DNSStubListener\" or \"systemd-resolved\" services. Please read <0>this instruction</0> on how to resolve this.",
|
"port_53_faq_link": "Port 53 is often occupied by \"DNSStubListener\" or \"systemd-resolved\" services. Please read <0>this instruction</0> on how to resolve this.",
|
||||||
"adg_will_drop_dns_queries": "AdGuard Home will be dropping all DNS queries from this client.",
|
"adg_will_drop_dns_queries": "AdGuard Home will be dropping all DNS queries from this client.",
|
||||||
"client_not_in_allowed_clients": "The client is not allowed because it is not in the \"Allowed clients\" list.",
|
"filter_allowlist": "WARNING: This action also will exclude the rule \"{{disallowed_rule}}\" from the list of allowed clients.",
|
||||||
"experimental": "Experimental"
|
"last_rule_in_allowlist": "Cannot disallow this client because excluding the rule \"{{disallowed_rule}}\" will DISABLE \"Allowed clients\" list.",
|
||||||
|
"experimental": "Experimental",
|
||||||
|
"use_saved_key": "Use the previously saved key"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -208,7 +208,7 @@
|
|||||||
"example_upstream_sdns": "puedes usar <0>DNS Stamps</0> para <1>DNSCrypt</1> o resolutores <2>DNS mediante HTTPS</2>",
|
"example_upstream_sdns": "puedes usar <0>DNS Stamps</0> para <1>DNSCrypt</1> o resolutores <2>DNS mediante HTTPS</2>",
|
||||||
"example_upstream_tcp": "DNS regular (mediante TCP)",
|
"example_upstream_tcp": "DNS regular (mediante TCP)",
|
||||||
"all_lists_up_to_date_toast": "Todas las listas ya están actualizadas",
|
"all_lists_up_to_date_toast": "Todas las listas ya están actualizadas",
|
||||||
"updated_upstream_dns_toast": "Servidores DNS de subida actualizados",
|
"updated_upstream_dns_toast": "Servidores DNS de subida guardados correctamente",
|
||||||
"dns_test_ok_toast": "Los servidores DNS especificados funcionan correctamente",
|
"dns_test_ok_toast": "Los servidores DNS especificados funcionan correctamente",
|
||||||
"dns_test_not_ok_toast": "Servidor \"{{key}}\": no se puede utilizar, por favor revisa si lo has escrito correctamente",
|
"dns_test_not_ok_toast": "Servidor \"{{key}}\": no se puede utilizar, por favor revisa si lo has escrito correctamente",
|
||||||
"unblock": "Desbloquear",
|
"unblock": "Desbloquear",
|
||||||
@@ -235,7 +235,7 @@
|
|||||||
"loading_table_status": "Cargando...",
|
"loading_table_status": "Cargando...",
|
||||||
"page_table_footer_text": "Página",
|
"page_table_footer_text": "Página",
|
||||||
"rows_table_footer_text": "filas",
|
"rows_table_footer_text": "filas",
|
||||||
"updated_custom_filtering_toast": "Reglas de filtrado personalizado actualizadas",
|
"updated_custom_filtering_toast": "Reglas personalizadas guardadas correctamente",
|
||||||
"rule_removed_from_custom_filtering_toast": "Regla eliminada de las reglas de filtrado personalizado: {{rule}}",
|
"rule_removed_from_custom_filtering_toast": "Regla eliminada de las reglas de filtrado personalizado: {{rule}}",
|
||||||
"rule_added_to_custom_filtering_toast": "Regla añadida a las reglas de filtrado personalizado: {{rule}}",
|
"rule_added_to_custom_filtering_toast": "Regla añadida a las reglas de filtrado personalizado: {{rule}}",
|
||||||
"query_log_response_status": "Estado: {{value}}",
|
"query_log_response_status": "Estado: {{value}}",
|
||||||
@@ -306,7 +306,7 @@
|
|||||||
"install_settings_dns_desc": "Deberás configurar tus dispositivos o router para usar el servidor DNS en las siguientes direcciones:",
|
"install_settings_dns_desc": "Deberás configurar tus dispositivos o router para usar el servidor DNS en las siguientes direcciones:",
|
||||||
"install_settings_all_interfaces": "Todas las interfaces",
|
"install_settings_all_interfaces": "Todas las interfaces",
|
||||||
"install_auth_title": "Autenticación",
|
"install_auth_title": "Autenticación",
|
||||||
"install_auth_desc": "Se recomienda encarecidamente configurar la autenticación por contraseña para la interfaz web de administración de AdGuard Home. Incluso si solo es accesible en tu red local, es importante que estés protegido contra el acceso no autorizado.",
|
"install_auth_desc": "Debe configurarse la autenticación por contraseña para la interfaz web de administración de AdGuard Home. Incluso si AdGuard Home es accesible solo en tu red local, es importante protegerlo del acceso no autorizado.",
|
||||||
"install_auth_username": "Usuario",
|
"install_auth_username": "Usuario",
|
||||||
"install_auth_password": "Contraseña",
|
"install_auth_password": "Contraseña",
|
||||||
"install_auth_confirm": "Confirmar contraseña",
|
"install_auth_confirm": "Confirmar contraseña",
|
||||||
@@ -503,6 +503,7 @@
|
|||||||
"statistics_clear_confirm": "¿Estás seguro de que deseas borrar las estadísticas?",
|
"statistics_clear_confirm": "¿Estás seguro de que deseas borrar las estadísticas?",
|
||||||
"statistics_retention_confirm": "¿Estás seguro de que deseas cambiar la retención de estadísticas? Si disminuye el valor del intervalo, se perderán algunos datos",
|
"statistics_retention_confirm": "¿Estás seguro de que deseas cambiar la retención de estadísticas? Si disminuye el valor del intervalo, se perderán algunos datos",
|
||||||
"statistics_cleared": "Estadísticas borradas correctamente",
|
"statistics_cleared": "Estadísticas borradas correctamente",
|
||||||
|
"statistics_enable": "Habilitar estadísticas",
|
||||||
"interval_hours": "{{count}} hora",
|
"interval_hours": "{{count}} hora",
|
||||||
"interval_hours_plural": "{{count}} horas",
|
"interval_hours_plural": "{{count}} horas",
|
||||||
"filters_configuration": "Configuración de filtros",
|
"filters_configuration": "Configuración de filtros",
|
||||||
@@ -597,7 +598,7 @@
|
|||||||
"cache_ttl_min_override_desc": "Amplia el corto tiempo de vida de los valores recibidos del servidor DNS de subida al almacenar en caché las respuestas DNS",
|
"cache_ttl_min_override_desc": "Amplia el corto tiempo de vida de los valores recibidos del servidor DNS de subida al almacenar en caché las respuestas DNS",
|
||||||
"cache_ttl_max_override_desc": "Establece un valor de tiempo de vida máximo para las entradas en la caché DNS",
|
"cache_ttl_max_override_desc": "Establece un valor de tiempo de vida máximo para las entradas en la caché DNS",
|
||||||
"ttl_cache_validation": "El valor TTL mínimo de la caché debe ser menor o igual al valor máximo",
|
"ttl_cache_validation": "El valor TTL mínimo de la caché debe ser menor o igual al valor máximo",
|
||||||
"cache_optimistic": "Optimista",
|
"cache_optimistic": "Caché optimista",
|
||||||
"cache_optimistic_desc": "Haz que AdGuard Home responda desde la caché incluso cuando las entradas estén expiradas y también intente actualizarlas.",
|
"cache_optimistic_desc": "Haz que AdGuard Home responda desde la caché incluso cuando las entradas estén expiradas y también intente actualizarlas.",
|
||||||
"filter_category_general": "General",
|
"filter_category_general": "General",
|
||||||
"filter_category_security": "Seguridad",
|
"filter_category_security": "Seguridad",
|
||||||
@@ -612,6 +613,8 @@
|
|||||||
"click_to_view_queries": "Clic para ver las consultas",
|
"click_to_view_queries": "Clic para ver las consultas",
|
||||||
"port_53_faq_link": "El puerto 53 suele estar ocupado por los servicios \"DNSStubListener\" o \"systemd-resolved\". Por favor lee <0>esta instrucción</0> sobre cómo resolver esto.",
|
"port_53_faq_link": "El puerto 53 suele estar ocupado por los servicios \"DNSStubListener\" o \"systemd-resolved\". Por favor lee <0>esta instrucción</0> sobre cómo resolver esto.",
|
||||||
"adg_will_drop_dns_queries": "AdGuard Home descartará todas las consultas DNS de este cliente.",
|
"adg_will_drop_dns_queries": "AdGuard Home descartará todas las consultas DNS de este cliente.",
|
||||||
"client_not_in_allowed_clients": "El cliente no está permitido porque no está en la lista de \"Clientes permitidos\".",
|
"filter_allowlist": "ADVERTENCIA: Esta acción también excluirá la regla \"{{disallowed_rule}}\" de la lista de clientes permitidos.",
|
||||||
"experimental": "experimental"
|
"last_rule_in_allowlist": "No se puede desautorizar a este cliente porque al excluir la regla \"{{disallowed_rule}}\" DESHABILITARÁ la lista de \"Clientes permitidos\".",
|
||||||
|
"experimental": "experimental",
|
||||||
|
"use_saved_key": "Usar la clave guardada previamente"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -208,7 +208,7 @@
|
|||||||
"example_upstream_sdns": "vous pouvez utiliser <0>DNS Stamps</0> pour <1>DNSCrypt</1> ou les resolveurs <2>DNS_over_HTTPS</2>",
|
"example_upstream_sdns": "vous pouvez utiliser <0>DNS Stamps</0> pour <1>DNSCrypt</1> ou les resolveurs <2>DNS_over_HTTPS</2>",
|
||||||
"example_upstream_tcp": "DNS classique (au-dessus de TCP)",
|
"example_upstream_tcp": "DNS classique (au-dessus de TCP)",
|
||||||
"all_lists_up_to_date_toast": "Toutes les listes sont déjà à jour",
|
"all_lists_up_to_date_toast": "Toutes les listes sont déjà à jour",
|
||||||
"updated_upstream_dns_toast": "Les serveurs DNS upstream sont mis à jour",
|
"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",
|
||||||
"unblock": "Débloquer",
|
"unblock": "Débloquer",
|
||||||
@@ -235,7 +235,7 @@
|
|||||||
"loading_table_status": "Chargement en cours ...",
|
"loading_table_status": "Chargement en cours ...",
|
||||||
"page_table_footer_text": "Page",
|
"page_table_footer_text": "Page",
|
||||||
"rows_table_footer_text": "lignes",
|
"rows_table_footer_text": "lignes",
|
||||||
"updated_custom_filtering_toast": "Règles de filtrage d'utilisateur mises à jour",
|
"updated_custom_filtering_toast": "Règles d'utilisateur enregistrées",
|
||||||
"rule_removed_from_custom_filtering_toast": "Règle retirée des règles d'utilisateur : {{rule}}",
|
"rule_removed_from_custom_filtering_toast": "Règle retirée des règles d'utilisateur : {{rule}}",
|
||||||
"rule_added_to_custom_filtering_toast": "Règle ajoutée aux règles d'utilisateur : {{rule}}",
|
"rule_added_to_custom_filtering_toast": "Règle ajoutée aux règles d'utilisateur : {{rule}}",
|
||||||
"query_log_response_status": "Statut : {{value}}",
|
"query_log_response_status": "Statut : {{value}}",
|
||||||
@@ -306,7 +306,7 @@
|
|||||||
"install_settings_dns_desc": "Vous devrez configurer vos appareils et votre routeur pour utiliser le serveur DNS sur les adresses suivantes :",
|
"install_settings_dns_desc": "Vous devrez configurer vos appareils et votre routeur pour utiliser le serveur DNS sur les adresses suivantes :",
|
||||||
"install_settings_all_interfaces": "Toutes les interfaces",
|
"install_settings_all_interfaces": "Toutes les interfaces",
|
||||||
"install_auth_title": "Authentification",
|
"install_auth_title": "Authentification",
|
||||||
"install_auth_desc": "Il est fortement recommandé de configurer un mot de passe pour accéder à l'interface web administrateur AdGuard Home. Même si elle est disponible que dans votre réseau local, cela reste important de se protéger contre des accès non désirés.",
|
"install_auth_desc": "C'est nécessaire de configurer l'authentification par aide de mot de passe pour accéder à l'interface web administrateur de votre AdGuard Home. Même si AdGuard Home n'est accessible que dans votre réseau local, c'est important d'y restreindre accès aux tiers.",
|
||||||
"install_auth_username": "Nom d'utilisateur",
|
"install_auth_username": "Nom d'utilisateur",
|
||||||
"install_auth_password": "Mot de passe",
|
"install_auth_password": "Mot de passe",
|
||||||
"install_auth_confirm": "Confirmer le mot de passe",
|
"install_auth_confirm": "Confirmer le mot de passe",
|
||||||
@@ -503,6 +503,7 @@
|
|||||||
"statistics_clear_confirm": "Voulez-vous vraiment effacer les statistiques ?",
|
"statistics_clear_confirm": "Voulez-vous vraiment effacer les statistiques ?",
|
||||||
"statistics_retention_confirm": "Êtes-vous sûr de vouloir modifier le maintien des statistiques ? Si vous diminuez la valeur de l'intervalle, certaines données seront perdues",
|
"statistics_retention_confirm": "Êtes-vous sûr de vouloir modifier le maintien des statistiques ? Si vous diminuez la valeur de l'intervalle, certaines données seront perdues",
|
||||||
"statistics_cleared": "Statistiques effacées",
|
"statistics_cleared": "Statistiques effacées",
|
||||||
|
"statistics_enable": "Activer les statistiques",
|
||||||
"interval_hours": "{{count}} heure",
|
"interval_hours": "{{count}} heure",
|
||||||
"interval_hours_plural": "{{count}} heures",
|
"interval_hours_plural": "{{count}} heures",
|
||||||
"filters_configuration": "Configuration des filtres",
|
"filters_configuration": "Configuration des filtres",
|
||||||
@@ -597,7 +598,7 @@
|
|||||||
"cache_ttl_min_override_desc": "Prolonger les valeurs courtes de durée de vie (en secondes) reçues du serveur en amont lors de la mise en cache des réponses DNS",
|
"cache_ttl_min_override_desc": "Prolonger les valeurs courtes de durée de vie (en secondes) reçues du serveur en amont lors de la mise en cache des réponses DNS",
|
||||||
"cache_ttl_max_override_desc": "Établir la valeur de durée de vie TTL maximale (en secondes) pour les saisies dans le cache du DNS",
|
"cache_ttl_max_override_desc": "Établir la valeur de durée de vie TTL maximale (en secondes) pour les saisies dans le cache du DNS",
|
||||||
"ttl_cache_validation": "La valeur TTL minimale du cache doit être inférieure ou égale à la valeur maximale",
|
"ttl_cache_validation": "La valeur TTL minimale du cache doit être inférieure ou égale à la valeur maximale",
|
||||||
"cache_optimistic": "Optimiste",
|
"cache_optimistic": "Caching optimiste",
|
||||||
"cache_optimistic_desc": "Faites en sorte qu'AdGuard Home réponde à partir du cache même lorsque les entrées ont expiré et essayez également de les actualiser.",
|
"cache_optimistic_desc": "Faites en sorte qu'AdGuard Home réponde à partir du cache même lorsque les entrées ont expiré et essayez également de les actualiser.",
|
||||||
"filter_category_general": "Général",
|
"filter_category_general": "Général",
|
||||||
"filter_category_security": "Sécurité",
|
"filter_category_security": "Sécurité",
|
||||||
@@ -612,6 +613,8 @@
|
|||||||
"click_to_view_queries": "Cliquez pour voir les requêtes",
|
"click_to_view_queries": "Cliquez pour voir les requêtes",
|
||||||
"port_53_faq_link": "Le port 53 est souvent occupé par les services « DNSStubListener » ou « systemd-resolved ». Veuillez lire <0>cette instruction</0> pour savoir comment résoudre ce problème.",
|
"port_53_faq_link": "Le port 53 est souvent occupé par les services « DNSStubListener » ou « systemd-resolved ». Veuillez lire <0>cette instruction</0> pour savoir comment résoudre ce problème.",
|
||||||
"adg_will_drop_dns_queries": "AdGuard Home ignorera toutes les requêtes DNS de ce client.",
|
"adg_will_drop_dns_queries": "AdGuard Home ignorera toutes les requêtes DNS de ce client.",
|
||||||
"client_not_in_allowed_clients": "Le client n’est pas autorisé car il ne figure pas dans la liste « Clients autorisés ».",
|
"filter_allowlist": "ATTENTION : Cette action exclura également la règle « {{disallowed_rule}} » de la liste des clients autorisés.",
|
||||||
"experimental": "Expérimental"
|
"last_rule_in_allowlist": "Impossible d’interdire ce client, car l’exclusion de la règle « {{disallowed_rule}} » DÉSACTIVERA la liste des « clients autorisés ».",
|
||||||
|
"experimental": "Expérimental",
|
||||||
|
"use_saved_key": "Utiliser la clef précédemment enregistrée"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -491,6 +491,7 @@
|
|||||||
"interval_days": "{{count}} dan",
|
"interval_days": "{{count}} dan",
|
||||||
"interval_days_plural": "{{count}} dana",
|
"interval_days_plural": "{{count}} dana",
|
||||||
"domain": "Domena",
|
"domain": "Domena",
|
||||||
|
"punycode": "Punycode",
|
||||||
"answer": "Odgovor",
|
"answer": "Odgovor",
|
||||||
"filter_added_successfully": "Popis je uspješno dodan",
|
"filter_added_successfully": "Popis je uspješno dodan",
|
||||||
"filter_removed_successfully": "Ovaj popis je uspješno uklonjen",
|
"filter_removed_successfully": "Ovaj popis je uspješno uklonjen",
|
||||||
@@ -596,7 +597,7 @@
|
|||||||
"cache_ttl_min_override_desc": "Povećajte kratke vrijednosti TTL-a (u sekundama) primljene od upstream poslužitelja prilikom predmemoriranja DNS odgovora",
|
"cache_ttl_min_override_desc": "Povećajte kratke vrijednosti TTL-a (u sekundama) primljene od upstream poslužitelja prilikom predmemoriranja DNS odgovora",
|
||||||
"cache_ttl_max_override_desc": "Postavite maksimalnu vrijednost TTL-a (u sekundama) za zapise u DNS predmemoriju",
|
"cache_ttl_max_override_desc": "Postavite maksimalnu vrijednost TTL-a (u sekundama) za zapise u DNS predmemoriju",
|
||||||
"ttl_cache_validation": "Minimalna vrijednost TTL predmemorije mora biti manja ili jednaka maksimalnoj vrijednosti",
|
"ttl_cache_validation": "Minimalna vrijednost TTL predmemorije mora biti manja ili jednaka maksimalnoj vrijednosti",
|
||||||
"cache_optimistic": "optimistički",
|
"cache_optimistic": "Optimistično predmemoriranje",
|
||||||
"cache_optimistic_desc": "Učinite da AdGuard Home reagira iz predmemorije čak i kada su unosi istekli i pokušajte ih osvježiti.",
|
"cache_optimistic_desc": "Učinite da AdGuard Home reagira iz predmemorije čak i kada su unosi istekli i pokušajte ih osvježiti.",
|
||||||
"filter_category_general": "Općenito",
|
"filter_category_general": "Općenito",
|
||||||
"filter_category_security": "Sigurnost",
|
"filter_category_security": "Sigurnost",
|
||||||
|
|||||||
@@ -5,14 +5,18 @@
|
|||||||
"upstream_parallel": "Használjon párhuzamos lekéréseket a domainek feloldásának felgyorsításához az összes upstream kiszolgálóra való egyidejű lekérdezéssel.",
|
"upstream_parallel": "Használjon párhuzamos lekéréseket a domainek feloldásának felgyorsításához az összes upstream kiszolgálóra való egyidejű lekérdezéssel.",
|
||||||
"parallel_requests": "Párhuzamos lekérések",
|
"parallel_requests": "Párhuzamos lekérések",
|
||||||
"load_balancing": "Terheléselosztás",
|
"load_balancing": "Terheléselosztás",
|
||||||
"load_balancing_desc": "Egyszerre csak egy szerverről történjen lekérdezés. Az AdGuard Home egy súlyozott, véletlenszerű algoritmust fog használni a megfelelő szerver kiválasztására, így a leggyorsabb szervert gyakrabban fogja használni.",
|
"load_balancing_desc": "Egyszerre csak egy szerverről történjen lekérdezés. Az AdGuard Home egy súlyozott, véletlenszerű algoritmust fog használni a megfelelő szerver kiválasztására, így a leggyorsabb szervert fogja a leggyakrabban használni.",
|
||||||
"bootstrap_dns": "Bootstrap DNS kiszolgálók",
|
"bootstrap_dns": "Bootstrap DNS kiszolgálók",
|
||||||
"bootstrap_dns_desc": "A Bootstrap DNS szerverek a DoH/DoT feloldók IP-címeinek feloldására szolgálnak.",
|
"bootstrap_dns_desc": "A Bootstrap DNS szerverek a DoH/DoT feloldók IP-címeinek feloldására szolgálnak.",
|
||||||
"local_ptr_title": "Privát DNS szerverek",
|
"local_ptr_title": "Privát DNS szerverek",
|
||||||
"local_ptr_desc": "Azok a DNS szerverek, amiket az AdGuard Home a helyi PTR kérésekhez használ. Ezeket a szervereket arra használjuk, hogy az rDNS segítségével fel lehessen oldani a kliensek hosztneveit. Ha nincs beállítva ilyen, akkor az AdGuard Home alapértelmezés szerint az OS nevét fogja feloldani.",
|
"local_ptr_desc": "Azok a DNS szerverek, amiket az AdGuard Home a helyi PTR kérésekhez használ. Ezeket a szervereket arra használjuk, hogy reverse DNS által feloldjuk a kliensek hosztneveit privát IP címekre, például \"192.168.12.34\". Ha nincs beállítva, akkor az AdGuard Home, kivéve az ő saját címét, az operációs rendszer alapértelmezett DNS feloldók címeit fogja használni.",
|
||||||
|
"local_ptr_default_resolver": "Alapesetben az AdGuard Home a következő reverse DNS feloldókat használja: {{ip}}.",
|
||||||
|
"local_ptr_no_default_resolver": "Az AdGuard Home nem tudta meghatározni a privát reverse DNS feloldókat ehhez a rendszerhez.",
|
||||||
"local_ptr_placeholder": "Adjon meg soronként egy kiszolgáló címet",
|
"local_ptr_placeholder": "Adjon meg soronként egy kiszolgáló címet",
|
||||||
"resolve_clients_title": "Kliensek IP címeinek fordított feloldása",
|
"resolve_clients_title": "Kliensek IP címeinek fordított feloldása",
|
||||||
"resolve_clients_desc": "Ha engedélyezve van, az AdGuard Home megpróbálja átfordítani a kliensek IP címeit hosztnevekre, PTR lekérdezéseket küldve a megfelelő feloldóknak (privát DNS szerverek a helyi kliensek számára, upstream szerverek a nyilvános IP címmel rendelkező ügyfelek számára).",
|
"resolve_clients_desc": "Fordítva oldja fel a kliensek IP címeit a hosztneveikre azáltal, hogy PTR lekérdezéseket küld a megfelelő feloldóknak (privát DNS szerverek a helyi kliensek számára, upstream szerverek a nyilvános IP címmel rendelkező kliensek számára).",
|
||||||
|
"use_private_ptr_resolvers_title": "Privát reverse DNS feloldók használata",
|
||||||
|
"use_private_ptr_resolvers_desc": "Reverse DNS keresések végzése a helyileg kiszolgált címekre ezeknek a szervereknek a használatával. Ha le van tiltva, az AdGuard Home az NXDOMAIN használatával válaszol minden ilyen PTR kérésre, kivéve azokat a klienseket, amelyeket már ismer a DHCP, /etc/hosts, stb. által.",
|
||||||
"check_dhcp_servers": "DHCP szerverek keresése",
|
"check_dhcp_servers": "DHCP szerverek keresése",
|
||||||
"save_config": "Konfiguráció mentése",
|
"save_config": "Konfiguráció mentése",
|
||||||
"enabled_dhcp": "DHCP szerver engedélyezve",
|
"enabled_dhcp": "DHCP szerver engedélyezve",
|
||||||
@@ -64,6 +68,9 @@
|
|||||||
"dhcp_new_static_lease": "Új statikus bérlet",
|
"dhcp_new_static_lease": "Új statikus bérlet",
|
||||||
"dhcp_static_leases_not_found": "Nem találhatóak statikus DHCP bérletek",
|
"dhcp_static_leases_not_found": "Nem találhatóak statikus DHCP bérletek",
|
||||||
"dhcp_add_static_lease": "Statikus bérlet hozzáadása",
|
"dhcp_add_static_lease": "Statikus bérlet hozzáadása",
|
||||||
|
"dhcp_reset_leases": "Bérletek alaphelyzetbe",
|
||||||
|
"dhcp_reset_leases_confirm": "Biztosan visszaállítja az összes bérletet?",
|
||||||
|
"dhcp_reset_leases_success": "DHCP bérletek alaphelyzetbe állítva",
|
||||||
"dhcp_reset": "Biztosan visszaállítja a DHCP beállításokat?",
|
"dhcp_reset": "Biztosan visszaállítja a DHCP beállításokat?",
|
||||||
"country": "Ország",
|
"country": "Ország",
|
||||||
"city": "Város",
|
"city": "Város",
|
||||||
@@ -105,6 +112,8 @@
|
|||||||
"for_last_24_hours": "az utóbbi 24 órában",
|
"for_last_24_hours": "az utóbbi 24 órában",
|
||||||
"for_last_days": "az utóbbi {{count}} napban",
|
"for_last_days": "az utóbbi {{count}} napban",
|
||||||
"for_last_days_plural": "az utóbbi {{count}} napban",
|
"for_last_days_plural": "az utóbbi {{count}} napban",
|
||||||
|
"stats_disabled": "Ezek a statisztikák ki lettek kapcsolva. Be tudja kapcsolni őket a <0>beállítások oldalon</0>.",
|
||||||
|
"stats_disabled_short": "A statisztikák ki lettek kapcsolva",
|
||||||
"no_domains_found": "Nem található domain",
|
"no_domains_found": "Nem található domain",
|
||||||
"requests_count": "Kérések száma",
|
"requests_count": "Kérések száma",
|
||||||
"top_blocked_domains": "Legtöbbet blokkolt domainek",
|
"top_blocked_domains": "Legtöbbet blokkolt domainek",
|
||||||
@@ -199,7 +208,7 @@
|
|||||||
"example_upstream_sdns": "használhatja a <0> DNS Stamps</0>-ot a <1>DNSCrypt</1> vagy a <2>DNS-over-HTTPS</2> feloldások érdekében",
|
"example_upstream_sdns": "használhatja a <0> DNS Stamps</0>-ot a <1>DNSCrypt</1> vagy a <2>DNS-over-HTTPS</2> feloldások érdekében",
|
||||||
"example_upstream_tcp": "hagyományos DNS (TCP felett)",
|
"example_upstream_tcp": "hagyományos DNS (TCP felett)",
|
||||||
"all_lists_up_to_date_toast": "Már minden lista naprakész",
|
"all_lists_up_to_date_toast": "Már minden lista naprakész",
|
||||||
"updated_upstream_dns_toast": "Frissítette az upstream DNS-kiszolgálókat",
|
"updated_upstream_dns_toast": "Upstream szerverek sikeresen mentve",
|
||||||
"dns_test_ok_toast": "A megadott DNS-kiszolgálók megfelelően működnek",
|
"dns_test_ok_toast": "A megadott DNS-kiszolgálók megfelelően működnek",
|
||||||
"dns_test_not_ok_toast": "Szerver \"{{key}}\": nem használható, ellenőrizze, hogy helyesen írta-e be",
|
"dns_test_not_ok_toast": "Szerver \"{{key}}\": nem használható, ellenőrizze, hogy helyesen írta-e be",
|
||||||
"unblock": "Feloldás",
|
"unblock": "Feloldás",
|
||||||
@@ -226,7 +235,7 @@
|
|||||||
"loading_table_status": "Betöltés...",
|
"loading_table_status": "Betöltés...",
|
||||||
"page_table_footer_text": "Oldal",
|
"page_table_footer_text": "Oldal",
|
||||||
"rows_table_footer_text": "sor",
|
"rows_table_footer_text": "sor",
|
||||||
"updated_custom_filtering_toast": "Egyéni szűrőszabályok frissítve",
|
"updated_custom_filtering_toast": "Egyéni szűrőszabályok sikeresen mentve",
|
||||||
"rule_removed_from_custom_filtering_toast": "Szabály eltávolítva az egyéni szűrőszabályok közül: {{rule}}",
|
"rule_removed_from_custom_filtering_toast": "Szabály eltávolítva az egyéni szűrőszabályok közül: {{rule}}",
|
||||||
"rule_added_to_custom_filtering_toast": "Szabály hozzáadva az egyéni szűrőszabályokhoz: {{rule}}",
|
"rule_added_to_custom_filtering_toast": "Szabály hozzáadva az egyéni szűrőszabályokhoz: {{rule}}",
|
||||||
"query_log_response_status": "Állapot: {{value}}",
|
"query_log_response_status": "Állapot: {{value}}",
|
||||||
@@ -307,9 +316,9 @@
|
|||||||
"install_devices_title": "Állítsa be az eszközeit",
|
"install_devices_title": "Állítsa be az eszközeit",
|
||||||
"install_devices_desc": "Az AdGuard Home használatának megkezdéséhez be kell állítania az eszközeit, hogy azok használni tudják.",
|
"install_devices_desc": "Az AdGuard Home használatának megkezdéséhez be kell állítania az eszközeit, hogy azok használni tudják.",
|
||||||
"install_submit_title": "Gratulálunk!",
|
"install_submit_title": "Gratulálunk!",
|
||||||
"install_submit_desc": "A telepítési folyamat befejeződött, minden készen áll az AdGuard Home használatára.",
|
"install_submit_desc": "A telepítési folyamat befejeződött, használatba veheti az AdGuard Home-ot.",
|
||||||
"install_devices_router": "Router",
|
"install_devices_router": "Router",
|
||||||
"install_devices_router_desc": "Ez a beállítás lefed minden eszközt, amik az Ön routeréhez csatlakoznak, így azokat nem kell külön, kézzel beállítania.",
|
"install_devices_router_desc": "Ez a beállítás automatikusan kihat az összes eszközre, amik az otthoni routeréhez kapcsolódnak, nem szükséges őket egyenként, kézileg beállítani.",
|
||||||
"install_devices_address": "Az AdGuard DNS szerver a következő címeket figyeli",
|
"install_devices_address": "Az AdGuard DNS szerver a következő címeket figyeli",
|
||||||
"install_devices_router_list_1": "Nyissa meg a router beállításait. Ez általában a böngészőn keresztül történik egy URL megadásával (pl. http://192.168.0.1/ vagy http://192.168.1.1/). Ez az oldal valószínűleg felhasználónevet és jelszót fog kérni. Ha nem tudja a belépési adatokat, ellenőrizze a router dobozát, a router alján levő fehér címkét vagy a technikai dokumentációt az interneten. Végső esetben visszaállíthatja a routert, azonban ne feledje, hogyha ezt az eljárást választja, akkor valószínűleg elveszíti annak összes beállítását. Ha a router beállításához alkalmazásra van szükség, telepítse az alkalmazást a telefonjára vagy a számítógépére, és használja azt az útválasztó beállításainak eléréséhez.",
|
"install_devices_router_list_1": "Nyissa meg a router beállításait. Ez általában a böngészőn keresztül történik egy URL megadásával (pl. http://192.168.0.1/ vagy http://192.168.1.1/). Ez az oldal valószínűleg felhasználónevet és jelszót fog kérni. Ha nem tudja a belépési adatokat, ellenőrizze a router dobozát, a router alján levő fehér címkét vagy a technikai dokumentációt az interneten. Végső esetben visszaállíthatja a routert, azonban ne feledje, hogyha ezt az eljárást választja, akkor valószínűleg elveszíti annak összes beállítását. Ha a router beállításához alkalmazásra van szükség, telepítse az alkalmazást a telefonjára vagy a számítógépére, és használja azt az útválasztó beállításainak eléréséhez.",
|
||||||
"install_devices_router_list_2": "Keresse meg a DHCP/DNS beállításokat. Keresse a DNS szót egy olyan mező mellett, amely egy 4 csoportból álló, 1-3 számjegyű számsort vár.",
|
"install_devices_router_list_2": "Keresse meg a DHCP/DNS beállításokat. Keresse a DNS szót egy olyan mező mellett, amely egy 4 csoportból álló, 1-3 számjegyű számsort vár.",
|
||||||
@@ -319,8 +328,8 @@
|
|||||||
"install_devices_windows_list_2": "Válassza a Hálózat és internet kategóriát, majd pedig a Hálózati és megosztási központot.",
|
"install_devices_windows_list_2": "Válassza a Hálózat és internet kategóriát, majd pedig a Hálózati és megosztási központot.",
|
||||||
"install_devices_windows_list_3": "A képernyő bal oldalán keresse meg az Adapterbeállítások módosítása lehetőséget és kattintson rá.",
|
"install_devices_windows_list_3": "A képernyő bal oldalán keresse meg az Adapterbeállítások módosítása lehetőséget és kattintson rá.",
|
||||||
"install_devices_windows_list_4": "Válassza ki a jelenleg is használt kapcsolatot, majd jobb egérgombbal kattintson rá és a megjelenő menüből válassza a Tulajdonságok elemet.",
|
"install_devices_windows_list_4": "Válassza ki a jelenleg is használt kapcsolatot, majd jobb egérgombbal kattintson rá és a megjelenő menüből válassza a Tulajdonságok elemet.",
|
||||||
"install_devices_windows_list_5": "Keresse meg az Internet Protocol Version 4 (TCP/IP) elemet a listában, válassza ki, majd ismét kattintson a Tulajdonságokra.",
|
"install_devices_windows_list_5": "Keresse meg az Internet Protocol Version 4 (TCP/IPv4) elemet a listában, válassza ki, majd ismét kattintson a Tulajdonságokra.",
|
||||||
"install_devices_windows_list_6": "Válassza a Következő DNS címek használata lehetőséget és adja meg az AdGuard Home szerver címeit.",
|
"install_devices_windows_list_6": "Válassza a \"Következő DNS címek használata\" lehetőséget és adja meg az AdGuard Home szerver címeit.",
|
||||||
"install_devices_macos_list_1": "Kattintson az Apple ikonra és válassza a Rendszerbeállításokat.",
|
"install_devices_macos_list_1": "Kattintson az Apple ikonra és válassza a Rendszerbeállításokat.",
|
||||||
"install_devices_macos_list_2": "Kattintson a Hálózat lehetőségre.",
|
"install_devices_macos_list_2": "Kattintson a Hálózat lehetőségre.",
|
||||||
"install_devices_macos_list_3": "Válassza ki az első kapcsolatot a listából és kattintson a Haladó beállításokra.",
|
"install_devices_macos_list_3": "Válassza ki az első kapcsolatot a listából és kattintson a Haladó beállításokra.",
|
||||||
@@ -419,11 +428,11 @@
|
|||||||
"access_title": "Hozzáférési beállítások",
|
"access_title": "Hozzáférési beállítások",
|
||||||
"access_desc": "Itt konfigurálhatja az AdGuard Home DNS-kiszolgáló hozzáférési szabályait.",
|
"access_desc": "Itt konfigurálhatja az AdGuard Home DNS-kiszolgáló hozzáférési szabályait.",
|
||||||
"access_allowed_title": "Engedélyezett kliensek",
|
"access_allowed_title": "Engedélyezett kliensek",
|
||||||
"access_allowed_desc": "A CIDR vagy IP címek listája. Ha konfigurálva van, az AdGuard Home csak az ezekről az IP-címekről fogadja el a kéréseket.",
|
"access_allowed_desc": "CIDR-ek, IP-címek vagy kliensazonosítók listája. Ha be van állítva, akkor az AdGuard Home csak azokat a lekérdezéseket engedélyezi, amelyek ezektől a kliensektől érkeznek.",
|
||||||
"access_disallowed_title": "Nem engedélyezett kliensek",
|
"access_disallowed_title": "Nem engedélyezett kliensek",
|
||||||
"access_disallowed_desc": "A CIDR vagy IP címek listája. Ha konfigurálva van, az AdGuard Home eldobja a lekérdezéseket ezekről az IP-címekről.",
|
"access_disallowed_desc": "CIDR-ek, IP-címek vagy kliensazonosítók listája. Ha be van állítva, akkor az AdGuard Home eldobja azokat a lekérdezéseket, amelyek ezektől a kliensektől érkeznek. Ha engedélyezett kliensek vannak ide bekonfigurálva, akkor pedig az a mező ki lesz hagyva.",
|
||||||
"access_blocked_title": "Nem engedélyezett domainek",
|
"access_blocked_title": "Nem engedélyezett domainek",
|
||||||
"access_blocked_desc": "Ne keverje össze ezt a szűrőkkel. Az AdGuard Home az összes DNS kérést el fogja dobni, ami ezekkel a domainekkel kapcsolatos. Itt megadhatja a pontos domainneveket, a helyettesítő karaktereket és az urlfilter-szabályokat, pl. 'example.org', '*.example.org' vagy '||example.org^'.",
|
"access_blocked_desc": "Ne keverje össze ezt a szűrőkkel. Az AdGuard Home az összes DNS kérést el fogja dobni, ami ezekkel a domainekkel megegyezik, és ezek a lekérések nem is fognak megjelenni a lekérdezési naplóban sem. Megadhatja a pontos domain neveket, a helyettesítő karaktereket vagy az URL szűrési szabályokat, pl. ennek megfelelően \"example.org\", \"*.example.org\", vagy \"||example.org^\".",
|
||||||
"access_settings_saved": "A hozzáférési beállítások sikeresen mentésre kerültek",
|
"access_settings_saved": "A hozzáférési beállítások sikeresen mentésre kerültek",
|
||||||
"updates_checked": "A frissítések sikeresen ellenőrizve lettek",
|
"updates_checked": "A frissítések sikeresen ellenőrizve lettek",
|
||||||
"updates_version_equal": "Az AdGuard Home naprakész",
|
"updates_version_equal": "Az AdGuard Home naprakész",
|
||||||
@@ -477,10 +486,12 @@
|
|||||||
"encryption_key_source_content": "Privát kulcs tartalmának megadása",
|
"encryption_key_source_content": "Privát kulcs tartalmának megadása",
|
||||||
"stats_params": "Statisztikai beállítások",
|
"stats_params": "Statisztikai beállítások",
|
||||||
"config_successfully_saved": "A beállítások sikeresen el lettek mentve",
|
"config_successfully_saved": "A beállítások sikeresen el lettek mentve",
|
||||||
|
"interval_6_hour": "6 óra",
|
||||||
"interval_24_hour": "24 óra",
|
"interval_24_hour": "24 óra",
|
||||||
"interval_days": "{{count}} nap",
|
"interval_days": "{{count}} nap",
|
||||||
"interval_days_plural": "{{count}} nap",
|
"interval_days_plural": "{{count}} nap",
|
||||||
"domain": "Domain",
|
"domain": "Domain",
|
||||||
|
"punycode": "Punycode",
|
||||||
"answer": "Válasz",
|
"answer": "Válasz",
|
||||||
"filter_added_successfully": "A lista sikeresen hozzá lett adva",
|
"filter_added_successfully": "A lista sikeresen hozzá lett adva",
|
||||||
"filter_removed_successfully": "A lista sikeresen el lett távolítva",
|
"filter_removed_successfully": "A lista sikeresen el lett távolítva",
|
||||||
@@ -488,10 +499,11 @@
|
|||||||
"statistics_configuration": "Statisztikai beállítások",
|
"statistics_configuration": "Statisztikai beállítások",
|
||||||
"statistics_retention": "Statisztika megőrzése",
|
"statistics_retention": "Statisztika megőrzése",
|
||||||
"statistics_retention_desc": "Ha csökkenti az intervallum értékét, az előtte levő adatok elvesznek",
|
"statistics_retention_desc": "Ha csökkenti az intervallum értékét, az előtte levő adatok elvesznek",
|
||||||
"statistics_clear": " Statisztikák visszaállítása",
|
"statistics_clear": "Statisztikák visszaállítása",
|
||||||
"statistics_clear_confirm": "Biztosan vissza akarja állítani a statisztikákat?",
|
"statistics_clear_confirm": "Biztosan vissza akarja állítani a statisztikákat?",
|
||||||
"statistics_retention_confirm": "Biztos benne, hogy megváltoztatja a statisztika megőrzési idejét? Ha csökkentette az értéket, a megadottnál korábbi adatok elvesznek",
|
"statistics_retention_confirm": "Biztos benne, hogy megváltoztatja a statisztika megőrzési idejét? Ha csökkentette az értéket, a megadottnál korábbi adatok elvesznek",
|
||||||
"statistics_cleared": "A statisztikák sikeresen vissza lettek állítva",
|
"statistics_cleared": "A statisztikák sikeresen vissza lettek állítva",
|
||||||
|
"statistics_enable": "Statisztikák engedélyezése",
|
||||||
"interval_hours": "{{count}} óra",
|
"interval_hours": "{{count}} óra",
|
||||||
"interval_hours_plural": "{{count}} óra",
|
"interval_hours_plural": "{{count}} óra",
|
||||||
"filters_configuration": "Szűrők beállításai",
|
"filters_configuration": "Szűrők beállításai",
|
||||||
@@ -523,8 +535,8 @@
|
|||||||
"rewrite_domain_name": "Domain név: CNAME rekord hozzáadása",
|
"rewrite_domain_name": "Domain név: CNAME rekord hozzáadása",
|
||||||
"rewrite_A": "<0>A</0>: speciális érték, megtartja az upstream felől érkező <0>A</0> rekordokat",
|
"rewrite_A": "<0>A</0>: speciális érték, megtartja az upstream felől érkező <0>A</0> rekordokat",
|
||||||
"rewrite_AAAA": "<0>AAAA</0>: speciális érték, megtartja az upstream felől érkező <0>AAAA</0> rekordokat",
|
"rewrite_AAAA": "<0>AAAA</0>: speciális érték, megtartja az upstream felől érkező <0>AAAA</0> rekordokat",
|
||||||
"disable_ipv6": "IPv6 letiltása",
|
"disable_ipv6": "IPv6 címek feloldásának tiltása",
|
||||||
"disable_ipv6_desc": "Ha ez a szolgáltatás engedélyezve van, akkor az összes IPv6-cím (AAAA típus) DNS-lekérdezése elveszik.",
|
"disable_ipv6_desc": "Összes DNS kérés eldobása az IPv6 címekhez (AAAA típus).",
|
||||||
"fastest_addr": "Leggyorsabb IP-cím",
|
"fastest_addr": "Leggyorsabb IP-cím",
|
||||||
"fastest_addr_desc": "Kérdezze le az összes DNS-kiszolgálót, és adja vissza a leggyorsabb IP-címet a válaszok közül. Ez lelassítja a DNS-lekérdezéseket, mivel az összes DNS-kiszolgáló esetében meg kell várnunk a válaszokat, de javítja az összeköttetést.",
|
"fastest_addr_desc": "Kérdezze le az összes DNS-kiszolgálót, és adja vissza a leggyorsabb IP-címet a válaszok közül. Ez lelassítja a DNS-lekérdezéseket, mivel az összes DNS-kiszolgáló esetében meg kell várnunk a válaszokat, de javítja az összeköttetést.",
|
||||||
"autofix_warning_text": "Ha a \"Javítás\" lehetőségre kattint, az AdGuard Home megpróbálja beállítani a rendszerét, hogy használja az AdGuard Home DNS szervert.",
|
"autofix_warning_text": "Ha a \"Javítás\" lehetőségre kattint, az AdGuard Home megpróbálja beállítani a rendszerét, hogy használja az AdGuard Home DNS szervert.",
|
||||||
@@ -561,7 +573,7 @@
|
|||||||
"list_updated": "{{count}} lista frissítve lett",
|
"list_updated": "{{count}} lista frissítve lett",
|
||||||
"list_updated_plural": "{{count}} lista frissítve lett",
|
"list_updated_plural": "{{count}} lista frissítve lett",
|
||||||
"dnssec_enable": "DNSSEC engedélyezése",
|
"dnssec_enable": "DNSSEC engedélyezése",
|
||||||
"dnssec_enable_desc": "Állítsa be a DNSSEC jelzőt a kimenő DNS-lekérdezésekbe, és ellenőrizze az eredményt (szükséges a DNSSEC-kompatibilis feloldás)",
|
"dnssec_enable_desc": "DNSSEC flag beállítása a kimenő DNS kérésekhez, majd az eredmény ellenőrzése (DNSSEC-engedélyezett feloldó szükséges).",
|
||||||
"validated_with_dnssec": "DNSSEC által ellenőrizve",
|
"validated_with_dnssec": "DNSSEC által ellenőrizve",
|
||||||
"all_queries": "Minden kérés",
|
"all_queries": "Minden kérés",
|
||||||
"show_blocked_responses": "Blokkolva",
|
"show_blocked_responses": "Blokkolva",
|
||||||
@@ -586,12 +598,14 @@
|
|||||||
"cache_ttl_min_override_desc": "Megnöveli a DNS kiszolgálótól kapott rövid TTL értékeket (másodpercben), ha gyorsítótárazza a DNS kéréseket",
|
"cache_ttl_min_override_desc": "Megnöveli a DNS kiszolgálótól kapott rövid TTL értékeket (másodpercben), ha gyorsítótárazza a DNS kéréseket",
|
||||||
"cache_ttl_max_override_desc": "Állítson be egy maximális TTL értéket (másodpercben) a DNS gyorsítótár bejegyzéseihez",
|
"cache_ttl_max_override_desc": "Állítson be egy maximális TTL értéket (másodpercben) a DNS gyorsítótár bejegyzéseihez",
|
||||||
"ttl_cache_validation": "A minimális gyorsítótár TTL értéknek kisebbnek vagy egyenlőnek kell lennie a maximum értékkel",
|
"ttl_cache_validation": "A minimális gyorsítótár TTL értéknek kisebbnek vagy egyenlőnek kell lennie a maximum értékkel",
|
||||||
|
"cache_optimistic": "Optimista gyorsítótár",
|
||||||
|
"cache_optimistic_desc": "Lehetővé teszi, hogy az AdGuard Home a gyorsítótárból válaszoljon, még abban az esetben is, ha az ott lévő bejegyzések lejértak, és próbálja meg frissíteni őket.",
|
||||||
"filter_category_general": "Általános",
|
"filter_category_general": "Általános",
|
||||||
"filter_category_security": "Biztonság",
|
"filter_category_security": "Biztonság",
|
||||||
"filter_category_regional": "Regionális",
|
"filter_category_regional": "Regionális",
|
||||||
"filter_category_other": "Egyéb",
|
"filter_category_other": "Egyéb",
|
||||||
"filter_category_general_desc": "Olyan listák, amelyek blokkolják a nyomkövetést és a hirdetéseket a legtöbb eszközön",
|
"filter_category_general_desc": "Olyan listák, amelyek blokkolják a nyomkövetést és a hirdetéseket a legtöbb eszközön",
|
||||||
"filter_category_security_desc": "Olyan listák, amelyek a kártékony, adathalász vagy átverős oldalak tiltására vannak kifejlesztve",
|
"filter_category_security_desc": "Kifejezetten a rosszindulatú, adathalász és átverős domainek blokkolására tervezett listák",
|
||||||
"filter_category_regional_desc": "Olyan listák, amelyek a regionális hirdetések, valamint a nyomkövető szerverek ellen vannak kifejlesztve",
|
"filter_category_regional_desc": "Olyan listák, amelyek a regionális hirdetések, valamint a nyomkövető szerverek ellen vannak kifejlesztve",
|
||||||
"filter_category_other_desc": "További tiltólisták",
|
"filter_category_other_desc": "További tiltólisták",
|
||||||
"setup_config_to_enable_dhcp_server": "Konfiguráció beállítása a DHCP-kiszolgáló engedélyezéséhez",
|
"setup_config_to_enable_dhcp_server": "Konfiguráció beállítása a DHCP-kiszolgáló engedélyezéséhez",
|
||||||
@@ -600,5 +614,6 @@
|
|||||||
"port_53_faq_link": "Az 53-as portot gyakran a \"DNSStubListener\" vagy a \"systemd-resolved\" (rendszer által feloldott) szolgáltatások használják. Kérjük, olvassa el <0>ezt az útmutatót</0> a probléma megoldásához.",
|
"port_53_faq_link": "Az 53-as portot gyakran a \"DNSStubListener\" vagy a \"systemd-resolved\" (rendszer által feloldott) szolgáltatások használják. Kérjük, olvassa el <0>ezt az útmutatót</0> a probléma megoldásához.",
|
||||||
"adg_will_drop_dns_queries": "Az AdGuard Home eldobja az összes DNS kérést erről a kliensről.",
|
"adg_will_drop_dns_queries": "Az AdGuard Home eldobja az összes DNS kérést erről a kliensről.",
|
||||||
"client_not_in_allowed_clients": "Ez a kliens nincs engedélyezve, mivel nincs rajta az \"Engedélyezett kliensek\" listáján.",
|
"client_not_in_allowed_clients": "Ez a kliens nincs engedélyezve, mivel nincs rajta az \"Engedélyezett kliensek\" listáján.",
|
||||||
"experimental": "Kísérleti"
|
"experimental": "Kísérleti",
|
||||||
|
"use_saved_key": "Előzőleg mentett kulcs használata"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,11 +8,15 @@
|
|||||||
"load_balancing_desc": "Permintaan satu server pada satu waktu. AdGuard Home akan menggunakan algoritma acak tertimbang untuk memilih server sehingga server tercepat akan lebih sering digunakan.",
|
"load_balancing_desc": "Permintaan satu server pada satu waktu. AdGuard Home akan menggunakan algoritma acak tertimbang untuk memilih server sehingga server tercepat akan lebih sering digunakan.",
|
||||||
"bootstrap_dns": "Server DNS bootstrap",
|
"bootstrap_dns": "Server DNS bootstrap",
|
||||||
"bootstrap_dns_desc": "Server Bootstrap DNS dapat digunakan untuk meresolve alamat IP pada DoH/DoT resolvers yang Anda tentukan sebagai upstreams.",
|
"bootstrap_dns_desc": "Server Bootstrap DNS dapat digunakan untuk meresolve alamat IP pada DoH/DoT resolvers yang Anda tentukan sebagai upstreams.",
|
||||||
"local_ptr_title": "Server DNS pribadi",
|
"local_ptr_title": "Server pembalik DNS pribadi",
|
||||||
"local_ptr_desc": "Server DNS yang digunakan AdGuard Home untuk kueri PTR lokal. Server ini digunakan untuk menetapkan nama host klien bersama alamat IP pribadi, sebagai contoh \"192.168.12.34\", menggunakan rDNS. Jika tidka diatur, AdGuard Home akan menggunakan resolver DNS bawaan/default OS Anda.",
|
"local_ptr_desc": "Server DNS yang digunakan AdGuard Home untuk kueri PTR lokal. Server ini digunakan untuk menyelesaikan nama host klien dengan alamat IP pribadi, misalnya \"192.168.12.34\", menggunakan DNS terbalik. Jika tidak disetel, AdGuard Home menggunakan alamat resolver DNS default OS Anda kecuali untuk alamat AdGuard Home itu sendiri.",
|
||||||
|
"local_ptr_default_resolver": "Secara bawaan, AdGuard Home menggunakan pemecah DNS terbalik: {{ip}}.",
|
||||||
|
"local_ptr_no_default_resolver": "AdGuard Home tidak dapat menentukan pemecah DNS terbalik yang sesuai untuk sistem ini.",
|
||||||
"local_ptr_placeholder": "Masukkan satu alamat server per baris",
|
"local_ptr_placeholder": "Masukkan satu alamat server per baris",
|
||||||
"resolve_clients_title": "Aktifkan resolusi hostname klien",
|
"resolve_clients_title": "Aktifkan resolusi hostname klien",
|
||||||
"resolve_clients_desc": "Jika diaktifkan, AdGuard Home akan mencoba menyelesaikan hostname klien secara otomatis dari alamat IP mereka dengan mengirimkan kueri PTR ke penyelesai yang sesuai (server DNS pribadi untuk klien lokal, server upstream untuk klien dengan IP publik).",
|
"resolve_clients_desc": "Menyelesaikan alamat IP klien secara terbalik ke nama host mereka dengan mengirimkan kueri PTR ke resolver yang sesuai (server DNS pribadi untuk klien lokal, server upstream untuk klien dengan alamat IP publik).",
|
||||||
|
"use_private_ptr_resolvers_title": "Gunakan server pembalik DNS pribadi",
|
||||||
|
"use_private_ptr_resolvers_desc": "Lakukan pencarian DNS terbalik untuk alamat yang disajikan secara lokal menggunakan server upstream ini. Jika dinonaktifkan, Adguard Home merespon dengan NXDOMAIN untuk semua permintaan PTR tersebut kecuali untuk klien yang diketahui dari DHCP, /etc/hosts, dan seterusnya.",
|
||||||
"check_dhcp_servers": "Cek untuk server DHCP",
|
"check_dhcp_servers": "Cek untuk server DHCP",
|
||||||
"save_config": "Simpan pengaturan",
|
"save_config": "Simpan pengaturan",
|
||||||
"enabled_dhcp": "Server DHCP diaktifkan",
|
"enabled_dhcp": "Server DHCP diaktifkan",
|
||||||
@@ -64,6 +68,9 @@
|
|||||||
"dhcp_new_static_lease": "Static lease baru",
|
"dhcp_new_static_lease": "Static lease baru",
|
||||||
"dhcp_static_leases_not_found": "DHCP static lease tidak ditemukan",
|
"dhcp_static_leases_not_found": "DHCP static lease tidak ditemukan",
|
||||||
"dhcp_add_static_lease": "Tambah static lease",
|
"dhcp_add_static_lease": "Tambah static lease",
|
||||||
|
"dhcp_reset_leases": "Atur ulang semua kontrak",
|
||||||
|
"dhcp_reset_leases_confirm": "Apakah Anda yakin ingin mengatur ulang kontrak Anda?",
|
||||||
|
"dhcp_reset_leases_success": "Kontrak DHCP berhasil diatur ulang",
|
||||||
"dhcp_reset": "Apakah anda yakin ingin mengatur ulang konfigurasi DHCP anda?",
|
"dhcp_reset": "Apakah anda yakin ingin mengatur ulang konfigurasi DHCP anda?",
|
||||||
"country": "Negara",
|
"country": "Negara",
|
||||||
"city": "Kota",
|
"city": "Kota",
|
||||||
@@ -105,6 +112,8 @@
|
|||||||
"for_last_24_hours": "untuk 24 jam terakhir",
|
"for_last_24_hours": "untuk 24 jam terakhir",
|
||||||
"for_last_days": "untuk {{count}} hari terakhir",
|
"for_last_days": "untuk {{count}} hari terakhir",
|
||||||
"for_last_days_plural": "selama {{count}} hari terakhir",
|
"for_last_days_plural": "selama {{count}} hari terakhir",
|
||||||
|
"stats_disabled": "Statistik telah dinonaktifkan. Anda dapat mengaktifkannya dari <0>halaman setelan</0>.",
|
||||||
|
"stats_disabled_short": "Statistik telah dinonaktifkan",
|
||||||
"no_domains_found": "Domain tidak ditemukan",
|
"no_domains_found": "Domain tidak ditemukan",
|
||||||
"requests_count": "Jumlah permintaan",
|
"requests_count": "Jumlah permintaan",
|
||||||
"top_blocked_domains": "Domain diblokir teratas",
|
"top_blocked_domains": "Domain diblokir teratas",
|
||||||
@@ -124,10 +133,10 @@
|
|||||||
"block_domain_use_filters_and_hosts": "Blokir domain menggunakan filter dan file hosts",
|
"block_domain_use_filters_and_hosts": "Blokir domain menggunakan filter dan file hosts",
|
||||||
"filters_block_toggle_hint": "Anda dapat menyiapkan aturan pemblokiran di pengaturan <a>Penyaringan</a>.",
|
"filters_block_toggle_hint": "Anda dapat menyiapkan aturan pemblokiran di pengaturan <a>Penyaringan</a>.",
|
||||||
"use_adguard_browsing_sec": "Gunakan layanan web Keamanan Penjelajahan AdGuard",
|
"use_adguard_browsing_sec": "Gunakan layanan web Keamanan Penjelajahan AdGuard",
|
||||||
"use_adguard_browsing_sec_hint": "AdGuard Home akan mengecek jika domain diblacklist oleh layanan web keamanan penjelajahan. Akan menggunakan lookup API yang ramah privasi untuk melakukan cek: hanya awalan singkat hash SHA256 dari nama domain yang dikirim ke server.",
|
"use_adguard_browsing_sec_hint": "AdGuard Home akan memeriksa apakah domain diblokir oleh layanan web keamanan penjelajahan. Ini akan menggunakan API pencarian yang ramah privasi untuk melakukan pemeriksaan: hanya awalan singkat dari hash nama domain SHA256 yang dikirim ke server.",
|
||||||
"use_adguard_parental": "Gunakan layanan web kontrol orang tua AdGuard",
|
"use_adguard_parental": "Gunakan layanan web kontrol orang tua AdGuard",
|
||||||
"use_adguard_parental_hint": "AdGuard Home akan mengecek jika domain mengandung materi dewasa. Akan menggunakan API yang ramah privasi yang sama sebagai layanan web keamanan penjelajahan.",
|
"use_adguard_parental_hint": "AdGuard Home akan mengecek jika domain mengandung materi dewasa. Akan menggunakan API yang ramah privasi yang sama sebagai layanan web keamanan penjelajahan.",
|
||||||
"enforce_safe_search": "Paksa penelusuran aman",
|
"enforce_safe_search": "Pakai pencarian aman",
|
||||||
"enforce_save_search_hint": "AdGuard Home dapat memaksa penelusuran aman pada mesin pencari berikut: Google, Youtube, Bing, DuckDuckGo, Yandex, dan Pixabay.",
|
"enforce_save_search_hint": "AdGuard Home dapat memaksa penelusuran aman pada mesin pencari berikut: Google, Youtube, Bing, DuckDuckGo, Yandex, dan Pixabay.",
|
||||||
"no_servers_specified": "Sever tidak disebutkan",
|
"no_servers_specified": "Sever tidak disebutkan",
|
||||||
"general_settings": "Pengaturan umum",
|
"general_settings": "Pengaturan umum",
|
||||||
@@ -226,7 +235,7 @@
|
|||||||
"loading_table_status": "Memuat...",
|
"loading_table_status": "Memuat...",
|
||||||
"page_table_footer_text": "Halaman",
|
"page_table_footer_text": "Halaman",
|
||||||
"rows_table_footer_text": "baris",
|
"rows_table_footer_text": "baris",
|
||||||
"updated_custom_filtering_toast": "Perbarui aturan penyaringan khusus",
|
"updated_custom_filtering_toast": "Aturan kustom berhasil disimpan",
|
||||||
"rule_removed_from_custom_filtering_toast": "Aturan dihapus dari aturan penyaringan khusus: {{rule}}",
|
"rule_removed_from_custom_filtering_toast": "Aturan dihapus dari aturan penyaringan khusus: {{rule}}",
|
||||||
"rule_added_to_custom_filtering_toast": "Aturan ditambah ke aturan penyaringan khusus: {{rule}}",
|
"rule_added_to_custom_filtering_toast": "Aturan ditambah ke aturan penyaringan khusus: {{rule}}",
|
||||||
"query_log_response_status": "Status: {{value}}",
|
"query_log_response_status": "Status: {{value}}",
|
||||||
@@ -268,7 +277,7 @@
|
|||||||
"form_enter_rate_limit": "Masukkan batas nilai",
|
"form_enter_rate_limit": "Masukkan batas nilai",
|
||||||
"rate_limit": "Batas nilai",
|
"rate_limit": "Batas nilai",
|
||||||
"edns_enable": "Aktifkan EDNS Klien Subnet",
|
"edns_enable": "Aktifkan EDNS Klien Subnet",
|
||||||
"edns_cs_desc": "Apabila dinyalakan, AdGuard Home akan mengirim subnet klien ke server-server DNS.",
|
"edns_cs_desc": "Kirim subnet klien ke server DNS.",
|
||||||
"rate_limit_desc": "Jumlah permintaan per detik yang diperbolehkan untuk satu klien. Atur ke 0 untuk tidak terbatas.",
|
"rate_limit_desc": "Jumlah permintaan per detik yang diperbolehkan untuk satu klien. Atur ke 0 untuk tidak terbatas.",
|
||||||
"blocking_ipv4_desc": "Alamat IP akan dikembalikan untuk permintaan A yang diblokir",
|
"blocking_ipv4_desc": "Alamat IP akan dikembalikan untuk permintaan A yang diblokir",
|
||||||
"blocking_ipv6_desc": "Alamat IP akan dipulihkan untuk permintaan AAAA yang diblokir",
|
"blocking_ipv6_desc": "Alamat IP akan dipulihkan untuk permintaan AAAA yang diblokir",
|
||||||
@@ -309,7 +318,7 @@
|
|||||||
"install_submit_title": "Selamat!",
|
"install_submit_title": "Selamat!",
|
||||||
"install_submit_desc": "Prosedur pengaturan telah selesai, dan anda siap untuk mulai menggunakan AdGuard Home.",
|
"install_submit_desc": "Prosedur pengaturan telah selesai, dan anda siap untuk mulai menggunakan AdGuard Home.",
|
||||||
"install_devices_router": "Router",
|
"install_devices_router": "Router",
|
||||||
"install_devices_router_desc": "Pengaturan ini akan secara otomatis mencakup semua perangkat yang terhubung ke router rumah anda dan anda tak perlu mengkonfigurasikan secara manual.",
|
"install_devices_router_desc": "Setelan ini akan secara otomatis mencakup semua perangkat yang terhubung ke router rumah anda dan anda tak perlu mengkonfigurasikan secara manual.",
|
||||||
"install_devices_address": "Server DNS AdGuard Home akan menggunakan alamat berikut",
|
"install_devices_address": "Server DNS AdGuard Home akan menggunakan alamat berikut",
|
||||||
"install_devices_router_list_1": "Buka preferensi untuk router Anda. Biasanya, Anda dapat mengaksesnya dari browser Anda melalui URL, seperti http://192.168.0.1/ atau http://192.168.1.1/. Anda mungkin diminta untuk memasukkan kata sandi. Jika Anda tidak mengingatnya, Anda sering kali dapat mengatur ulang kata sandi dengan menekan tombol pada perute itu sendiri, tetapi perlu diketahui bahwa jika prosedur ini dipilih, Anda mungkin akan kehilangan seluruh konfigurasi perute. Jika router Anda memerlukan aplikasi untuk menyiapkannya, instal aplikasi tersebut di ponsel atau PC Anda dan gunakan untuk mengakses pengaturan router.",
|
"install_devices_router_list_1": "Buka preferensi untuk router Anda. Biasanya, Anda dapat mengaksesnya dari browser Anda melalui URL, seperti http://192.168.0.1/ atau http://192.168.1.1/. Anda mungkin diminta untuk memasukkan kata sandi. Jika Anda tidak mengingatnya, Anda sering kali dapat mengatur ulang kata sandi dengan menekan tombol pada perute itu sendiri, tetapi perlu diketahui bahwa jika prosedur ini dipilih, Anda mungkin akan kehilangan seluruh konfigurasi perute. Jika router Anda memerlukan aplikasi untuk menyiapkannya, instal aplikasi tersebut di ponsel atau PC Anda dan gunakan untuk mengakses pengaturan router.",
|
||||||
"install_devices_router_list_2": "Temukan pengaturan DHCP / DNS. Cari huruf DNS di sebelah bidang yang memungkinkan dua atau tiga set angka, masing-masing dipecah menjadi empat grup dengan satu hingga tiga digit.",
|
"install_devices_router_list_2": "Temukan pengaturan DHCP / DNS. Cari huruf DNS di sebelah bidang yang memungkinkan dua atau tiga set angka, masing-masing dipecah menjadi empat grup dengan satu hingga tiga digit.",
|
||||||
@@ -317,10 +326,10 @@
|
|||||||
"install_devices_router_list_4": "Anda tidak dapat menyetel server DNS kustom pada beberapa tipe router. Dalam hal ini mungkin membantu jika Anda mengatur AdGuard Home sebagai <0>server DHCP</0>. Jika tidak, Anda harus mencari petunjuk tentang cara mengkustomisasi server DNS untuk model router khusus Anda.",
|
"install_devices_router_list_4": "Anda tidak dapat menyetel server DNS kustom pada beberapa tipe router. Dalam hal ini mungkin membantu jika Anda mengatur AdGuard Home sebagai <0>server DHCP</0>. Jika tidak, Anda harus mencari petunjuk tentang cara mengkustomisasi server DNS untuk model router khusus Anda.",
|
||||||
"install_devices_windows_list_1": "Buka Panel Kontrol melalui menu Start atau pencarian Windows.",
|
"install_devices_windows_list_1": "Buka Panel Kontrol melalui menu Start atau pencarian Windows.",
|
||||||
"install_devices_windows_list_2": "Masuk ke kategori Jaringan dan Internet (Network and Internet) dan kemudian ke Pusat Jaringan dan Berbagi (Network and Sharing Center).",
|
"install_devices_windows_list_2": "Masuk ke kategori Jaringan dan Internet (Network and Internet) dan kemudian ke Pusat Jaringan dan Berbagi (Network and Sharing Center).",
|
||||||
"install_devices_windows_list_3": "Di sisi kiri layar temukan Ubah pengaturan adaptor dan klik.",
|
"install_devices_windows_list_3": "Di sisi kiri layar temukan \"Ubah pengaturan adaptor\" dan klik di atasnya.",
|
||||||
"install_devices_windows_list_4": "Pilih koneksi aktif Anda, klik kanan padanya dan pilih Properties.",
|
"install_devices_windows_list_4": "Pilih koneksi aktif Anda, klik kanan padanya dan pilih Properties.",
|
||||||
"install_devices_windows_list_5": "Temukan Internet Protocol Version 4 (TCP / IP) dalam daftar, pilih dan kemudian klik Properties lagi.",
|
"install_devices_windows_list_5": "Temukan \"Internet Protocol Version 4 (TCP/IPv4)\" (atau, untuk IPv6, \"Internet Protocol Version 6 (TCP/IPv6)\") dalam daftar, pilih dan kemudian klik Properties lagi.",
|
||||||
"install_devices_windows_list_6": "Pilih Gunakan alamat server DNS dan masukkan alamat server AdGuard Anda.",
|
"install_devices_windows_list_6": "Pilih \"Gunakan alamat server DNS berikut\" dan masukkan alamat server Beranda AdGuard Anda.",
|
||||||
"install_devices_macos_list_1": "Klik pada ikon Apple dan pergi ke System Preferences.",
|
"install_devices_macos_list_1": "Klik pada ikon Apple dan pergi ke System Preferences.",
|
||||||
"install_devices_macos_list_2": "Klik pada Jaringan (Network)",
|
"install_devices_macos_list_2": "Klik pada Jaringan (Network)",
|
||||||
"install_devices_macos_list_3": "Pilih koneksi pertama dalam daftar dan klik Advanced.",
|
"install_devices_macos_list_3": "Pilih koneksi pertama dalam daftar dan klik Advanced.",
|
||||||
@@ -329,7 +338,7 @@
|
|||||||
"install_devices_android_list_2": "Ketuk Wi-Fi pada menu. Layar akan mencantumkan semua jaringan yang tersedia dan akan ditampilkan (tidak mungkin untuk mengatur DNS khusus untuk koneksi seluler).",
|
"install_devices_android_list_2": "Ketuk Wi-Fi pada menu. Layar akan mencantumkan semua jaringan yang tersedia dan akan ditampilkan (tidak mungkin untuk mengatur DNS khusus untuk koneksi seluler).",
|
||||||
"install_devices_android_list_3": "Tekan lama jaringan yang terhubung, dan ketuk Ubah Jaringan.",
|
"install_devices_android_list_3": "Tekan lama jaringan yang terhubung, dan ketuk Ubah Jaringan.",
|
||||||
"install_devices_android_list_4": "Pada beberapa perangkat, Anda mungkin perlu mencentang kotak Advanced untuk melihat pengaturan lebih lanjut. Untuk menyesuaikan pengaturan DNS Android Anda, Anda perlu mengalihkan pengaturan IP dari DHCP ke Statis.",
|
"install_devices_android_list_4": "Pada beberapa perangkat, Anda mungkin perlu mencentang kotak Advanced untuk melihat pengaturan lebih lanjut. Untuk menyesuaikan pengaturan DNS Android Anda, Anda perlu mengalihkan pengaturan IP dari DHCP ke Statis.",
|
||||||
"install_devices_android_list_5": "Ubah nilai DNS 1 & DNS 2 ke alamat server AdGuard Home",
|
"install_devices_android_list_5": "Ubah nilai DNS 1 dan DNS 2 ke alamat server AdGuard Home Anda.",
|
||||||
"install_devices_ios_list_1": "Dari layar beranda, ketuk Pengaturan.",
|
"install_devices_ios_list_1": "Dari layar beranda, ketuk Pengaturan.",
|
||||||
"install_devices_ios_list_2": "Pilih Wi-Fi di menu sebelah kiri (tidak mungkin untuk mengkonfigurasi DNS untuk jaringan seluler).",
|
"install_devices_ios_list_2": "Pilih Wi-Fi di menu sebelah kiri (tidak mungkin untuk mengkonfigurasi DNS untuk jaringan seluler).",
|
||||||
"install_devices_ios_list_3": "Ketuk nama jaringan yang saat ini aktif.",
|
"install_devices_ios_list_3": "Ketuk nama jaringan yang saat ini aktif.",
|
||||||
@@ -399,7 +408,7 @@
|
|||||||
"client_edit": "Ubah Klien",
|
"client_edit": "Ubah Klien",
|
||||||
"client_identifier": "Identifikasi",
|
"client_identifier": "Identifikasi",
|
||||||
"ip_address": "Alamat IP",
|
"ip_address": "Alamat IP",
|
||||||
"client_identifier_desc": "Klien dapat diidentifikasi oleh alamat IP, CIDR, alamat MAC atau ID klien khusus (dapat digunakan untuk DoT/DoH/DoQ). <0>Di sini</0> Anda dapat mempelajari lebih lanjut tentang bagaimana mengidentifikasi klien.",
|
"client_identifier_desc": "Klien dapat diidentifikasi oleh alamat IP, CIDR, alamat MAC atau ID klien khusus (dapat digunakan untuk DoT/DoH/DoQ). <0>Di sini</0> Anda dapat mempelajari lebih lanjut tentang cara mengidentifikasi klien.",
|
||||||
"form_enter_ip": "Masukkan IP",
|
"form_enter_ip": "Masukkan IP",
|
||||||
"form_enter_subnet_ip": "Masukkan alamat IP di subnet \"{{cidr}}\"",
|
"form_enter_subnet_ip": "Masukkan alamat IP di subnet \"{{cidr}}\"",
|
||||||
"form_enter_mac": "Masukkan MAC",
|
"form_enter_mac": "Masukkan MAC",
|
||||||
@@ -419,11 +428,11 @@
|
|||||||
"access_title": "Pengaturan akses",
|
"access_title": "Pengaturan akses",
|
||||||
"access_desc": "Disini anda dapat mengatur aturan akses untuk server AdGuard Home DNS.",
|
"access_desc": "Disini anda dapat mengatur aturan akses untuk server AdGuard Home DNS.",
|
||||||
"access_allowed_title": "Klien yang diizinkan",
|
"access_allowed_title": "Klien yang diizinkan",
|
||||||
"access_allowed_desc": "Daftar CIDR atau alamat IP. Jika dikonfigurasi, AdGuard Home hanya akan menerima permintaan dari alamat IP ini.",
|
"access_allowed_desc": "Daftar CIDR, alamat IP, atau ID klien. Jika dikonfigurasi, AdGuard Home hanya akan menerima permintaan dari klien ini.",
|
||||||
"access_disallowed_title": "Klien yang tidak diizinkan",
|
"access_disallowed_title": "Klien yang tidak diizinkan",
|
||||||
"access_disallowed_desc": "Daftar CIDR atau alamat IP. Jika dikonfigurasi, AdGuard Home akan membatalkan permintaan dari alamat IP ini.",
|
"access_disallowed_desc": "Daftar CIDR, alamat IP, atau ID klien. Jika dikonfigurasi, AdGuard Home akan menghapus permintaan dari klien ini. Jika klien yang diizinkan dikonfigurasi, bidang ini diabaikan.",
|
||||||
"access_blocked_title": "Domain yang diblokir",
|
"access_blocked_title": "Domain yang diblokir",
|
||||||
"access_blocked_desc": "Jangan bingung antara ini dengan filter. AdGuard Home akan membatalkan kueri DNS dengan domain ini dalam pertanyaan kueri. Di sini Anda dapat menentukan nama domain yang tepat, karakter pengganti, dan aturan filter URL, mis. \"example.org\", \"*.example.org\" atau \"||example.org^\".",
|
"access_blocked_desc": "Jangan bingung dengan filter. AdGuard Home menghapus kueri DNS yang cocok dengan domain ini, dan kueri ini bahkan tidak muncul di log kueri. Anda dapat menentukan nama domain, karakter pengganti, atau aturan filter URL yang tepat, mis. \"example.org\", \"*.example.org\", atau \"||example.org^\" yang sesuai.",
|
||||||
"access_settings_saved": "Pengaturan akses berhasil disimpan",
|
"access_settings_saved": "Pengaturan akses berhasil disimpan",
|
||||||
"updates_checked": "Pembaruan berhasil dicek",
|
"updates_checked": "Pembaruan berhasil dicek",
|
||||||
"updates_version_equal": "AdGuard Home sudah tebaru",
|
"updates_version_equal": "AdGuard Home sudah tebaru",
|
||||||
@@ -477,10 +486,12 @@
|
|||||||
"encryption_key_source_content": "Tempel konten kunci pribadi",
|
"encryption_key_source_content": "Tempel konten kunci pribadi",
|
||||||
"stats_params": "Konfigurasi statistik",
|
"stats_params": "Konfigurasi statistik",
|
||||||
"config_successfully_saved": "Konfigurasi berhasil disimpan",
|
"config_successfully_saved": "Konfigurasi berhasil disimpan",
|
||||||
|
"interval_6_hour": "6 jam",
|
||||||
"interval_24_hour": "24 jam",
|
"interval_24_hour": "24 jam",
|
||||||
"interval_days": "{{count}} hari",
|
"interval_days": "{{count}} hari",
|
||||||
"interval_days_plural": "{{count}} hari",
|
"interval_days_plural": "{{count}} hari",
|
||||||
"domain": "Domain",
|
"domain": "Domain",
|
||||||
|
"punycode": "Kode kecil",
|
||||||
"answer": "Jawab",
|
"answer": "Jawab",
|
||||||
"filter_added_successfully": "Filter telah berhasil ditambahkan",
|
"filter_added_successfully": "Filter telah berhasil ditambahkan",
|
||||||
"filter_removed_successfully": "Daftar ini telah sukses dihapus",
|
"filter_removed_successfully": "Daftar ini telah sukses dihapus",
|
||||||
@@ -488,7 +499,7 @@
|
|||||||
"statistics_configuration": "Konfigurasi statistik",
|
"statistics_configuration": "Konfigurasi statistik",
|
||||||
"statistics_retention": "Statistik disimpan",
|
"statistics_retention": "Statistik disimpan",
|
||||||
"statistics_retention_desc": "Jika Anda menurunkan nilai interval, beberapa data akan hilang",
|
"statistics_retention_desc": "Jika Anda menurunkan nilai interval, beberapa data akan hilang",
|
||||||
"statistics_clear": " Hapus statistik",
|
"statistics_clear": "Hapus statistik",
|
||||||
"statistics_clear_confirm": "Apakah Anda yakin ingin menghapus statistik?",
|
"statistics_clear_confirm": "Apakah Anda yakin ingin menghapus statistik?",
|
||||||
"statistics_retention_confirm": "Apakah Anda yakin ingin mengubah retensi statistik? Jika Anda menurunkan nilai interval, beberapa data akan hilang",
|
"statistics_retention_confirm": "Apakah Anda yakin ingin mengubah retensi statistik? Jika Anda menurunkan nilai interval, beberapa data akan hilang",
|
||||||
"statistics_cleared": "Statistik berhasil dihapus",
|
"statistics_cleared": "Statistik berhasil dihapus",
|
||||||
@@ -523,8 +534,8 @@
|
|||||||
"rewrite_domain_name": "Nama domain: tambah ke rekaman CNAME",
|
"rewrite_domain_name": "Nama domain: tambah ke rekaman CNAME",
|
||||||
"rewrite_A": "<0>A</0>: nilai khusus, biarkan <0>A</0> merekam dari upstream",
|
"rewrite_A": "<0>A</0>: nilai khusus, biarkan <0>A</0> merekam dari upstream",
|
||||||
"rewrite_AAAA": "<0>AAAA</0>: nilai khusus, biarkan <0>AAAA</0> merekam dari upstream",
|
"rewrite_AAAA": "<0>AAAA</0>: nilai khusus, biarkan <0>AAAA</0> merekam dari upstream",
|
||||||
"disable_ipv6": "Matikan IPv6",
|
"disable_ipv6": "Nonaktifkan penyelesaian alamat IPv6",
|
||||||
"disable_ipv6_desc": "Apabila fitur ini dinyalakan, semua permintaan DNS untuk alamat-alamat IPv6 (tipe AAAA) akan diputus.",
|
"disable_ipv6_desc": "Jatuhkan semua kueri DNS untuk alamat IPv6 (ketik AAAA).",
|
||||||
"fastest_addr": "Alamat IP tercepat",
|
"fastest_addr": "Alamat IP tercepat",
|
||||||
"fastest_addr_desc": "Kuiri semua server DNS dan kembalikan alamat IP tercepat diantara semua tanggapan. Ini memperlambat pencarian DNS Sebagai Rumah AdGuard harus menunggu tanggapan dari semua server DNS, tapi meningkatkan konektivitas keseluruhan.",
|
"fastest_addr_desc": "Kuiri semua server DNS dan kembalikan alamat IP tercepat diantara semua tanggapan. Ini memperlambat pencarian DNS Sebagai Rumah AdGuard harus menunggu tanggapan dari semua server DNS, tapi meningkatkan konektivitas keseluruhan.",
|
||||||
"autofix_warning_text": "Apabila anda menekan \"Perbaiki\", AdGuardHome akan mengatur sistem anda untuk menggunakan server DNS AdGuardHome.",
|
"autofix_warning_text": "Apabila anda menekan \"Perbaiki\", AdGuardHome akan mengatur sistem anda untuk menggunakan server DNS AdGuardHome.",
|
||||||
@@ -586,6 +597,8 @@
|
|||||||
"cache_ttl_min_override_desc": "Perpanjang nilai waktu-online singkat (detik) yang diterima dari server upstream saat menyimpan respons DNS",
|
"cache_ttl_min_override_desc": "Perpanjang nilai waktu-online singkat (detik) yang diterima dari server upstream saat menyimpan respons DNS",
|
||||||
"cache_ttl_max_override_desc": "Tetapkan nilai waktu-online maksimum (detik) untuk entri di cache DNS",
|
"cache_ttl_max_override_desc": "Tetapkan nilai waktu-online maksimum (detik) untuk entri di cache DNS",
|
||||||
"ttl_cache_validation": "Nilai TTL cache minimum harus kurang dari atau sama dengan nilai maksimum",
|
"ttl_cache_validation": "Nilai TTL cache minimum harus kurang dari atau sama dengan nilai maksimum",
|
||||||
|
"cache_optimistic": "Caching yang optimis",
|
||||||
|
"cache_optimistic_desc": "Buat AdGuard Home merespons dari cache bahkan ketika entri telah kedaluwarsa dan juga mencoba untuk menyegarkannya.",
|
||||||
"filter_category_general": "Umum",
|
"filter_category_general": "Umum",
|
||||||
"filter_category_security": "Keamanan",
|
"filter_category_security": "Keamanan",
|
||||||
"filter_category_regional": "Wilayah",
|
"filter_category_regional": "Wilayah",
|
||||||
@@ -600,5 +613,6 @@
|
|||||||
"port_53_faq_link": "Port 53 sering ditempati oleh layanan \"DNSStubListener\" atau \"systemd-resolved\". Silakan baca <0>instruksi ini</0> tentang cara menyelesaikan ini.",
|
"port_53_faq_link": "Port 53 sering ditempati oleh layanan \"DNSStubListener\" atau \"systemd-resolved\". Silakan baca <0>instruksi ini</0> tentang cara menyelesaikan ini.",
|
||||||
"adg_will_drop_dns_queries": "AdGuard Home akan menghapus semua permintaan DNS dari klien ini.",
|
"adg_will_drop_dns_queries": "AdGuard Home akan menghapus semua permintaan DNS dari klien ini.",
|
||||||
"client_not_in_allowed_clients": "Klien tidak diizinkan karena tidak ada dalam daftar \"Klien yang diizinkan\".",
|
"client_not_in_allowed_clients": "Klien tidak diizinkan karena tidak ada dalam daftar \"Klien yang diizinkan\".",
|
||||||
"experimental": "Eksperimental"
|
"experimental": "Eksperimental",
|
||||||
|
"use_saved_key": "Gunakan kunci yang disimpan sebelumnya"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -48,9 +48,9 @@
|
|||||||
"range_end_error": "Deve essere maggiore dell'intervallo di inizio",
|
"range_end_error": "Deve essere maggiore dell'intervallo di inizio",
|
||||||
"dhcp_form_gateway_input": "IP Gateway",
|
"dhcp_form_gateway_input": "IP Gateway",
|
||||||
"dhcp_form_subnet_input": "Maschera di sottorete",
|
"dhcp_form_subnet_input": "Maschera di sottorete",
|
||||||
"dhcp_form_range_title": "Range indirizzi IP",
|
"dhcp_form_range_title": "Intervallo di indirizzi IP",
|
||||||
"dhcp_form_range_start": "Inizio range",
|
"dhcp_form_range_start": "Intervallo iniziale",
|
||||||
"dhcp_form_range_end": "Fine range",
|
"dhcp_form_range_end": "Intervallo finale",
|
||||||
"dhcp_form_lease_title": "Tempo di lease DHCP (in secondi)",
|
"dhcp_form_lease_title": "Tempo di lease DHCP (in secondi)",
|
||||||
"dhcp_form_lease_input": "Durata lease",
|
"dhcp_form_lease_input": "Durata lease",
|
||||||
"dhcp_interface_select": "Seleziona l'interfaccia DHCP",
|
"dhcp_interface_select": "Seleziona l'interfaccia DHCP",
|
||||||
@@ -98,7 +98,7 @@
|
|||||||
"copyright": "Copyright",
|
"copyright": "Copyright",
|
||||||
"homepage": "Pagina principale",
|
"homepage": "Pagina principale",
|
||||||
"report_an_issue": "Segnala un problema",
|
"report_an_issue": "Segnala un problema",
|
||||||
"privacy_policy": "Politica sulla riservatezza",
|
"privacy_policy": "Politica sulla Riservatezza",
|
||||||
"enable_protection": "Attiva protezione",
|
"enable_protection": "Attiva protezione",
|
||||||
"enabled_protection": "Protezione attiva",
|
"enabled_protection": "Protezione attiva",
|
||||||
"disable_protection": "Disattiva protezione",
|
"disable_protection": "Disattiva protezione",
|
||||||
@@ -174,21 +174,21 @@
|
|||||||
"elapsed": "Trascorso",
|
"elapsed": "Trascorso",
|
||||||
"filters_and_hosts_hint": "AdGuard Home è in grado di comprendere la sintassi delle regole blocca-annunci o quelle dei file hosts.",
|
"filters_and_hosts_hint": "AdGuard Home è in grado di comprendere la sintassi delle regole blocca-annunci o quelle dei file hosts.",
|
||||||
"no_blocklist_added": "Non è stata aggiunta alcuna lista di blocco",
|
"no_blocklist_added": "Non è stata aggiunta alcuna lista di blocco",
|
||||||
"no_whitelist_added": "Non è stata aggiunta alcuna lista bianca",
|
"no_whitelist_added": "Non è stata aggiunta alcuna Lista bianca",
|
||||||
"add_blocklist": "Aggiungi lista di blocco",
|
"add_blocklist": "Aggiungi lista di blocco",
|
||||||
"add_allowlist": "Aggiungi lista bianca",
|
"add_allowlist": "Aggiungi Lista bianca",
|
||||||
"cancel_btn": "Annulla",
|
"cancel_btn": "Annulla",
|
||||||
"enter_name_hint": "Inserisci nome",
|
"enter_name_hint": "Inserisci nome",
|
||||||
"enter_url_or_path_hint": "Inmetti un URL o il percorso assoluto della lista",
|
"enter_url_or_path_hint": "Inmetti un URL o il percorso assoluto della lista",
|
||||||
"check_updates_btn": "Ricerca aggiornamenti",
|
"check_updates_btn": "Ricerca aggiornamenti",
|
||||||
"new_blocklist": "Nuova lista di blocco",
|
"new_blocklist": "Nuova lista di blocco",
|
||||||
"new_allowlist": "Nuova lista bianca",
|
"new_allowlist": "Nuova Lista bianca",
|
||||||
"edit_blocklist": "Modifica lista di blocco",
|
"edit_blocklist": "Modifica lista di blocco",
|
||||||
"edit_allowlist": "Modifica lista bianca",
|
"edit_allowlist": "Modifica Lista bianca",
|
||||||
"choose_blocklist": "Scegli liste di blocco",
|
"choose_blocklist": "Scegli liste di blocco",
|
||||||
"choose_allowlist": "Scegli liste bianche",
|
"choose_allowlist": "Scegli liste bianche",
|
||||||
"enter_valid_blocklist": "Inserisci un URL valido nella lista di blocco.",
|
"enter_valid_blocklist": "Inserisci un URL valido nella lista di blocco.",
|
||||||
"enter_valid_allowlist": "Inserisci un URL valido nella lista bianca.",
|
"enter_valid_allowlist": "Inserisci un URL valido nella Lista bianca.",
|
||||||
"form_error_url_format": "Formato url non valido",
|
"form_error_url_format": "Formato url non valido",
|
||||||
"form_error_url_or_path_format": "URL o percorso assoluto della lista non valido",
|
"form_error_url_or_path_format": "URL o percorso assoluto della lista non valido",
|
||||||
"custom_filter_rules": "Regole filtri personalizzate",
|
"custom_filter_rules": "Regole filtri personalizzate",
|
||||||
@@ -208,7 +208,7 @@
|
|||||||
"example_upstream_sdns": "puoi utilizzare <0>DNS Stamps</0> per <1>DNSCrypt</1> oppure dei risolutori <2>DNS-over-HTTPS</2>",
|
"example_upstream_sdns": "puoi utilizzare <0>DNS Stamps</0> per <1>DNSCrypt</1> oppure dei risolutori <2>DNS-over-HTTPS</2>",
|
||||||
"example_upstream_tcp": "DNS regolari (via TCP)",
|
"example_upstream_tcp": "DNS regolari (via TCP)",
|
||||||
"all_lists_up_to_date_toast": "Tutte le liste sono aggiornate",
|
"all_lists_up_to_date_toast": "Tutte le liste sono aggiornate",
|
||||||
"updated_upstream_dns_toast": "Server DNS upstream aggiornati",
|
"updated_upstream_dns_toast": "I server upstream sono stati salvati correttamente",
|
||||||
"dns_test_ok_toast": "I server DNS specificati funzionano correttamente",
|
"dns_test_ok_toast": "I server DNS specificati funzionano correttamente",
|
||||||
"dns_test_not_ok_toast": "Server \"{{key}}\": non può essere utilizzato, assicurati di averlo digitato correttamente",
|
"dns_test_not_ok_toast": "Server \"{{key}}\": non può essere utilizzato, assicurati di averlo digitato correttamente",
|
||||||
"unblock": "Sblocca",
|
"unblock": "Sblocca",
|
||||||
@@ -235,7 +235,7 @@
|
|||||||
"loading_table_status": "Caricamento...",
|
"loading_table_status": "Caricamento...",
|
||||||
"page_table_footer_text": "Pagina",
|
"page_table_footer_text": "Pagina",
|
||||||
"rows_table_footer_text": "righe",
|
"rows_table_footer_text": "righe",
|
||||||
"updated_custom_filtering_toast": "Le regole dei filtri personalizzate sono state aggiornate",
|
"updated_custom_filtering_toast": "Le regole personalizzate sono state correttamente salvate",
|
||||||
"rule_removed_from_custom_filtering_toast": "Regola rimossa dalle regole dei filtri personalizzate: {{rule}}",
|
"rule_removed_from_custom_filtering_toast": "Regola rimossa dalle regole dei filtri personalizzate: {{rule}}",
|
||||||
"rule_added_to_custom_filtering_toast": "Regola aggiunta alle regole dei filtri personalizzate: {{rule}}",
|
"rule_added_to_custom_filtering_toast": "Regola aggiunta alle regole dei filtri personalizzate: {{rule}}",
|
||||||
"query_log_response_status": "Stato: {{value}}",
|
"query_log_response_status": "Stato: {{value}}",
|
||||||
@@ -306,7 +306,7 @@
|
|||||||
"install_settings_dns_desc": "Sarà necessario configurare i dispositivi o il router per utilizzare il server DNS nei seguenti indirizzi:",
|
"install_settings_dns_desc": "Sarà necessario configurare i dispositivi o il router per utilizzare il server DNS nei seguenti indirizzi:",
|
||||||
"install_settings_all_interfaces": "Tutte le interfacce",
|
"install_settings_all_interfaces": "Tutte le interfacce",
|
||||||
"install_auth_title": "Autenticazione",
|
"install_auth_title": "Autenticazione",
|
||||||
"install_auth_desc": "Si consiglia vivamente di configurare l'autenticazione della password per l'interfaccia web di amministrazione di AdGuard Home. Anche se è accessibile solo nella rete locale, è comunque importante proteggerlo da accessi illimitati.",
|
"install_auth_desc": "L\\'autenticazione con password sulla tua interfaccia web da amministratore di AdGuard Home dev\\'esser configurata. Anche se AdGuard Home è accessibile solo dalla tua rete locale, è comunque importante proteggerlo da accessi non limitati.",
|
||||||
"install_auth_username": "Nome utente",
|
"install_auth_username": "Nome utente",
|
||||||
"install_auth_password": "Password",
|
"install_auth_password": "Password",
|
||||||
"install_auth_confirm": "Conferma password",
|
"install_auth_confirm": "Conferma password",
|
||||||
@@ -394,7 +394,7 @@
|
|||||||
"fix": "Risolvi",
|
"fix": "Risolvi",
|
||||||
"dns_providers": "Qui c\\'è una <0>lista di provider DNS</0> da cui scegliere.",
|
"dns_providers": "Qui c\\'è una <0>lista di provider DNS</0> da cui scegliere.",
|
||||||
"update_now": "Aggiorna ora",
|
"update_now": "Aggiorna ora",
|
||||||
"update_failed": "Aggiornamento automatico non riuscito. Si prega di <a>seguire questi passaggi</a>per aggiornare manualmente.",
|
"update_failed": "Aggiornamento automatico non riuscito. Ti suggeriamo di <a>seguire questi passaggi</a> per aggiornare manualmente.",
|
||||||
"processing_update": "Perfavore aspetta, AdGuard Home si sta aggiornando",
|
"processing_update": "Perfavore aspetta, AdGuard Home si sta aggiornando",
|
||||||
"clients_title": "Client",
|
"clients_title": "Client",
|
||||||
"clients_desc": "Configura i dispositivi connessi ad AdGuard Home",
|
"clients_desc": "Configura i dispositivi connessi ad AdGuard Home",
|
||||||
@@ -499,10 +499,11 @@
|
|||||||
"statistics_configuration": "Configurazione delle statistiche",
|
"statistics_configuration": "Configurazione delle statistiche",
|
||||||
"statistics_retention": "Conservazione delle statistiche",
|
"statistics_retention": "Conservazione delle statistiche",
|
||||||
"statistics_retention_desc": "Se il valore di intervallo dovesse diminuire, alcuni dati andranno persi",
|
"statistics_retention_desc": "Se il valore di intervallo dovesse diminuire, alcuni dati andranno persi",
|
||||||
"statistics_clear": " Azzera statistiche",
|
"statistics_clear": "Azzera statistiche",
|
||||||
"statistics_clear_confirm": "Sei sicuro di voler azzerare le statistiche?",
|
"statistics_clear_confirm": "Sei sicuro di voler azzerare le statistiche?",
|
||||||
"statistics_retention_confirm": "Sei sicuro di voler modificare la conservazione delle statistiche? Se il valore di intervallo dovesse diminuire, alcuni dati andranno persi",
|
"statistics_retention_confirm": "Sei sicuro di voler modificare la conservazione delle statistiche? Se il valore di intervallo dovesse diminuire, alcuni dati andranno persi",
|
||||||
"statistics_cleared": "Statistiche azzerate correttamente",
|
"statistics_cleared": "Statistiche azzerate correttamente",
|
||||||
|
"statistics_enable": "Attiva statistiche",
|
||||||
"interval_hours": "{{count}} ora",
|
"interval_hours": "{{count}} ora",
|
||||||
"interval_hours_plural": "{{count}} ore",
|
"interval_hours_plural": "{{count}} ore",
|
||||||
"filters_configuration": "Configurazione filtri",
|
"filters_configuration": "Configurazione filtri",
|
||||||
@@ -551,7 +552,7 @@
|
|||||||
"filtered_custom_rules": "Filtrato dalle regole filtro personalizzate",
|
"filtered_custom_rules": "Filtrato dalle regole filtro personalizzate",
|
||||||
"choose_from_list": "Scegli dalla lista",
|
"choose_from_list": "Scegli dalla lista",
|
||||||
"add_custom_list": "Aggiungi lista personalizzata",
|
"add_custom_list": "Aggiungi lista personalizzata",
|
||||||
"host_whitelisted": "L\\'host è stato aggiunto alla lista bianca",
|
"host_whitelisted": "L\\'host è stato aggiunto alla Lista bianca",
|
||||||
"check_ip": "Indirizzi IP: {{ip}}",
|
"check_ip": "Indirizzi IP: {{ip}}",
|
||||||
"check_cname": "CNAME: {{cname}}",
|
"check_cname": "CNAME: {{cname}}",
|
||||||
"check_reason": "Motivo: {{reason}}",
|
"check_reason": "Motivo: {{reason}}",
|
||||||
@@ -566,7 +567,7 @@
|
|||||||
"static_ip_desc": "AdGuard Home è un server quindi ha bisogno di un indirizzo IP statico per funzionare correttamente. In caso contrario, ad un certo punto, il router potrebbe assegnare un indirizzo IP differente a questo dispositivo.",
|
"static_ip_desc": "AdGuard Home è un server quindi ha bisogno di un indirizzo IP statico per funzionare correttamente. In caso contrario, ad un certo punto, il router potrebbe assegnare un indirizzo IP differente a questo dispositivo.",
|
||||||
"set_static_ip": "Imposta un indirizzo IP statico",
|
"set_static_ip": "Imposta un indirizzo IP statico",
|
||||||
"install_static_ok": "Buone notizie! L'indirizzo IP statico è già configurato",
|
"install_static_ok": "Buone notizie! L'indirizzo IP statico è già configurato",
|
||||||
"install_static_error": "AdGuard Home non può configurarlo automaticamente per questa interfaccia di rete. Si prega di cercare un'istruzione su come farlo manualmente.",
|
"install_static_error": "AdGuard Home non può configurarlo automaticamente per questa interfaccia di rete. Ti suggeriamo di cercare un metodo alternativo per effettuare tale operazione manualmente.",
|
||||||
"install_static_configure": "AdGuard Home ha rilevato l\\'utilizzo dell\\'indirizzo IP dinamico <0> {{ip}} </0>. Desideri impostarlo come indirizzo statico?",
|
"install_static_configure": "AdGuard Home ha rilevato l\\'utilizzo dell\\'indirizzo IP dinamico <0> {{ip}} </0>. Desideri impostarlo come indirizzo statico?",
|
||||||
"confirm_static_ip": "AdGuard Home configurerà {{ip}} come indirizzo IP statico. Desideri procedere?",
|
"confirm_static_ip": "AdGuard Home configurerà {{ip}} come indirizzo IP statico. Desideri procedere?",
|
||||||
"list_updated": "{{count}} lista aggiornata",
|
"list_updated": "{{count}} lista aggiornata",
|
||||||
@@ -597,7 +598,7 @@
|
|||||||
"cache_ttl_min_override_desc": "Estende i valori brevi (in secondi) ricevuti dal server upstream durante la memorizzazione nella cache delle risposte DNS",
|
"cache_ttl_min_override_desc": "Estende i valori brevi (in secondi) ricevuti dal server upstream durante la memorizzazione nella cache delle risposte DNS",
|
||||||
"cache_ttl_max_override_desc": "Imposta un periodo massimo di attivazione (in secondi) per le voci nella cache DNS",
|
"cache_ttl_max_override_desc": "Imposta un periodo massimo di attivazione (in secondi) per le voci nella cache DNS",
|
||||||
"ttl_cache_validation": "Il valore minimo della cache TTL deve essere inferiore o uguale al valore massimo",
|
"ttl_cache_validation": "Il valore minimo della cache TTL deve essere inferiore o uguale al valore massimo",
|
||||||
"cache_optimistic": "Ottimistico",
|
"cache_optimistic": "Optimistic caching",
|
||||||
"cache_optimistic_desc": "Fai in modo che AdGuard Home risponda dalla cache anche quando le voci risultano scadute e prova anche ad aggiornarle.",
|
"cache_optimistic_desc": "Fai in modo che AdGuard Home risponda dalla cache anche quando le voci risultano scadute e prova anche ad aggiornarle.",
|
||||||
"filter_category_general": "Generali",
|
"filter_category_general": "Generali",
|
||||||
"filter_category_security": "Sicurezza",
|
"filter_category_security": "Sicurezza",
|
||||||
@@ -610,8 +611,10 @@
|
|||||||
"setup_config_to_enable_dhcp_server": "Configurazione dell\\'installazione per l\\'attivazione del server DHCP",
|
"setup_config_to_enable_dhcp_server": "Configurazione dell\\'installazione per l\\'attivazione del server DHCP",
|
||||||
"original_response": "Responso originale",
|
"original_response": "Responso originale",
|
||||||
"click_to_view_queries": "Clicca per visualizzare le richieste",
|
"click_to_view_queries": "Clicca per visualizzare le richieste",
|
||||||
"port_53_faq_link": "La Porta 53 è spesso occupata dai servizi \"DNSStubListener\" o \"systemd-resolved\". Si prega di leggere <0>queste istruzioni</0> per risolvere il problema.",
|
"port_53_faq_link": "La Porta 53 è spesso occupata dai servizi \"DNSStubListener\" o \"systemd-resolved\". Ti suggeriamo di leggere <0>queste istruzioni</0> per risolvere il problema.",
|
||||||
"adg_will_drop_dns_queries": "AdGuard Home eliminerà tutte le richieste DNS da questo client.",
|
"adg_will_drop_dns_queries": "AdGuard Home eliminerà tutte le richieste DNS da questo client.",
|
||||||
"client_not_in_allowed_clients": "Il client non è consentito perché non è nell'elenco \"Client consentiti\".",
|
"filter_allowlist": "ATTENZIONE: Quest\\'azione escluderà anche la regola \"{{disallowed_rule}}\" dall\\'elenco di clienti consentiti.",
|
||||||
"experimental": "Sperimentale"
|
"last_rule_in_allowlist": "Impossibile bloccare questo client perché escludere la regola \"{{disallowed_rule}}\" DISATIVERÁ l\\'elenco \"Clienti consentiti\".",
|
||||||
|
"experimental": "Sperimentale",
|
||||||
|
"use_saved_key": "Utilizza la chiave salvata in precedenza"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -208,7 +208,7 @@
|
|||||||
"example_upstream_sdns": "<1>DNSCrypt</1> または <2>DNS-over-HTTPS</2> リゾルバのために <0>DNS Stamps</0> を使えます",
|
"example_upstream_sdns": "<1>DNSCrypt</1> または <2>DNS-over-HTTPS</2> リゾルバのために <0>DNS Stamps</0> を使えます",
|
||||||
"example_upstream_tcp": "通常のDNS(TCPでの問い合わせ)",
|
"example_upstream_tcp": "通常のDNS(TCPでの問い合わせ)",
|
||||||
"all_lists_up_to_date_toast": "すべてのリストは既に最新です",
|
"all_lists_up_to_date_toast": "すべてのリストは既に最新です",
|
||||||
"updated_upstream_dns_toast": "上流DNSサーバを更新しました",
|
"updated_upstream_dns_toast": "上流DNSサーバを保存しました。",
|
||||||
"dns_test_ok_toast": "指定されたDNSサーバは正しく動作しています",
|
"dns_test_ok_toast": "指定されたDNSサーバは正しく動作しています",
|
||||||
"dns_test_not_ok_toast": "サーバ \"{{key}}\": 使用できませんでした。正しく入力されているかどうかを確認してください",
|
"dns_test_not_ok_toast": "サーバ \"{{key}}\": 使用できませんでした。正しく入力されているかどうかを確認してください",
|
||||||
"unblock": "ブロック解除",
|
"unblock": "ブロック解除",
|
||||||
@@ -235,7 +235,7 @@
|
|||||||
"loading_table_status": "読み込み中…",
|
"loading_table_status": "読み込み中…",
|
||||||
"page_table_footer_text": "ページ",
|
"page_table_footer_text": "ページ",
|
||||||
"rows_table_footer_text": "行",
|
"rows_table_footer_text": "行",
|
||||||
"updated_custom_filtering_toast": "カスタム・フィルタリングルールを更新しました",
|
"updated_custom_filtering_toast": "カスタムルールを保存しました。",
|
||||||
"rule_removed_from_custom_filtering_toast": "ルールをカスタム・フィルタリングルールから除去しました {{rule}}",
|
"rule_removed_from_custom_filtering_toast": "ルールをカスタム・フィルタリングルールから除去しました {{rule}}",
|
||||||
"rule_added_to_custom_filtering_toast": "ルールをカスタム・フィルタリングルールに追加しました {{rule}}",
|
"rule_added_to_custom_filtering_toast": "ルールをカスタム・フィルタリングルールに追加しました {{rule}}",
|
||||||
"query_log_response_status": "ステータス: {{value}}",
|
"query_log_response_status": "ステータス: {{value}}",
|
||||||
@@ -306,7 +306,7 @@
|
|||||||
"install_settings_dns_desc": "次のアドレスでDNSサーバを使用するようにあなたのデバイスまたはルータを設定する必要があります:",
|
"install_settings_dns_desc": "次のアドレスでDNSサーバを使用するようにあなたのデバイスまたはルータを設定する必要があります:",
|
||||||
"install_settings_all_interfaces": "すべてのインターフェイス",
|
"install_settings_all_interfaces": "すべてのインターフェイス",
|
||||||
"install_auth_title": "認証",
|
"install_auth_title": "認証",
|
||||||
"install_auth_desc": "AdGuard Homeの管理ウェブインターフェースにパスワード認証を設定することを強くお勧めします。ローカルネットワークでのみアクセス可能であっても、制限のないアクセスから保護することは重要です。",
|
"install_auth_desc": "AdGuard Homeの管理ウェブインターフェースにパスワード認証を設定する必要があります。AdGuard Homeがローカルネットワークでのみアクセス可能であっても、制限のないアクセスから保護することは重要です。",
|
||||||
"install_auth_username": "ユーザ名",
|
"install_auth_username": "ユーザ名",
|
||||||
"install_auth_password": "パスワード",
|
"install_auth_password": "パスワード",
|
||||||
"install_auth_confirm": "パスワード(確認用)",
|
"install_auth_confirm": "パスワード(確認用)",
|
||||||
@@ -503,6 +503,7 @@
|
|||||||
"statistics_clear_confirm": "統計を消去してもよろしいですか?",
|
"statistics_clear_confirm": "統計を消去してもよろしいですか?",
|
||||||
"statistics_retention_confirm": "統計の保持を変更してもよろしいですか? 期間を短くすると、一部のデータが失われます",
|
"statistics_retention_confirm": "統計の保持を変更してもよろしいですか? 期間を短くすると、一部のデータが失われます",
|
||||||
"statistics_cleared": "統計の消去に成功しました",
|
"statistics_cleared": "統計の消去に成功しました",
|
||||||
|
"statistics_enable": "統計を有効にする",
|
||||||
"interval_hours": "{{count}}時間",
|
"interval_hours": "{{count}}時間",
|
||||||
"interval_hours_plural": "{{count}}時間",
|
"interval_hours_plural": "{{count}}時間",
|
||||||
"filters_configuration": "フィルタ設定",
|
"filters_configuration": "フィルタ設定",
|
||||||
@@ -597,7 +598,7 @@
|
|||||||
"cache_ttl_min_override_desc": "DNS応答をキャッシュするとき、上流サーバから受信した短いTTL(秒単位)を延長します",
|
"cache_ttl_min_override_desc": "DNS応答をキャッシュするとき、上流サーバから受信した短いTTL(秒単位)を延長します",
|
||||||
"cache_ttl_max_override_desc": "DNSキャッシュ内のエントリの最大TTL(秒単位)を設定します",
|
"cache_ttl_max_override_desc": "DNSキャッシュ内のエントリの最大TTL(秒単位)を設定します",
|
||||||
"ttl_cache_validation": "最小キャッシュTTL値は最大値以下にする必要があります",
|
"ttl_cache_validation": "最小キャッシュTTL値は最大値以下にする必要があります",
|
||||||
"cache_optimistic": "Optimistic (オプティミスティック)",
|
"cache_optimistic": "Optimistic cashing (オプティミスティック・キャッシュ)",
|
||||||
"cache_optimistic_desc": "エントリの有効期限が切れた場合でも、AdGuard Homeがキャッシュから応答するようにし、エントリの更新も試みます。",
|
"cache_optimistic_desc": "エントリの有効期限が切れた場合でも、AdGuard Homeがキャッシュから応答するようにし、エントリの更新も試みます。",
|
||||||
"filter_category_general": "一般",
|
"filter_category_general": "一般",
|
||||||
"filter_category_security": "セキュリティ",
|
"filter_category_security": "セキュリティ",
|
||||||
@@ -612,6 +613,8 @@
|
|||||||
"click_to_view_queries": "クエリを表示するにはクリックしてください",
|
"click_to_view_queries": "クエリを表示するにはクリックしてください",
|
||||||
"port_53_faq_link": "多くの場合、ポート53は \"DNSStubListener\" または \"systemd-resolved\" サービスによって利用されています。これを解決する方法については、<0>この手順</0>をお読みください。",
|
"port_53_faq_link": "多くの場合、ポート53は \"DNSStubListener\" または \"systemd-resolved\" サービスによって利用されています。これを解決する方法については、<0>この手順</0>をお読みください。",
|
||||||
"adg_will_drop_dns_queries": "AdGuard Homeは、このクライアントからすべてのDNSクエリを落とします。",
|
"adg_will_drop_dns_queries": "AdGuard Homeは、このクライアントからすべてのDNSクエリを落とします。",
|
||||||
"client_not_in_allowed_clients": "「許可されたクライアント」リストにないため、このクライアントは許可されていません。",
|
"filter_allowlist": "【注意】このアクションは、許可されたクライアントのリストから「{{disallowed_rule}}」というルールも除外します。",
|
||||||
"experimental": "実験用"
|
"last_rule_in_allowlist": "ルール「{{disallowed_rule}}」を除外すると「許可されたクライアント」リストが無効になるため、このクライアントを拒否することはできません。",
|
||||||
|
"experimental": "実験用",
|
||||||
|
"use_saved_key": "以前に保存したキーを使用する"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -208,7 +208,7 @@
|
|||||||
"example_upstream_sdns": "<1>DNSCrypt</1>나 <2>DNS-over-HTTPS</2> 리졸버를 위해 <0>DNS 스탬프</0>를 사용할 수 있습니다",
|
"example_upstream_sdns": "<1>DNSCrypt</1>나 <2>DNS-over-HTTPS</2> 리졸버를 위해 <0>DNS 스탬프</0>를 사용할 수 있습니다",
|
||||||
"example_upstream_tcp": "사용자 지정 DNS (TCP를 통한 접속)",
|
"example_upstream_tcp": "사용자 지정 DNS (TCP를 통한 접속)",
|
||||||
"all_lists_up_to_date_toast": "모든 리스트가 이미 최신입니다",
|
"all_lists_up_to_date_toast": "모든 리스트가 이미 최신입니다",
|
||||||
"updated_upstream_dns_toast": "업스트림 DNS 서버를 업데이트하였습니다",
|
"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}}\": 사용할 수 없습니다, 제대로 작성했는지 확인하세요.",
|
||||||
"unblock": "차단 해제",
|
"unblock": "차단 해제",
|
||||||
@@ -235,7 +235,7 @@
|
|||||||
"loading_table_status": "로딩중...",
|
"loading_table_status": "로딩중...",
|
||||||
"page_table_footer_text": "페이지",
|
"page_table_footer_text": "페이지",
|
||||||
"rows_table_footer_text": "행",
|
"rows_table_footer_text": "행",
|
||||||
"updated_custom_filtering_toast": "사용자 정의 필터링 규칙 업데이트",
|
"updated_custom_filtering_toast": "사용자 정의 규칙이 성공적으로 저장되었습니다",
|
||||||
"rule_removed_from_custom_filtering_toast": "사용자 정의 필터링 규칙에서 규칙 제거 {{rule}}",
|
"rule_removed_from_custom_filtering_toast": "사용자 정의 필터링 규칙에서 규칙 제거 {{rule}}",
|
||||||
"rule_added_to_custom_filtering_toast": "사용자 정의 필터링 규칙에 추가된 규칙 {{rule}}",
|
"rule_added_to_custom_filtering_toast": "사용자 정의 필터링 규칙에 추가된 규칙 {{rule}}",
|
||||||
"query_log_response_status": "상태: {{value}}",
|
"query_log_response_status": "상태: {{value}}",
|
||||||
@@ -499,10 +499,11 @@
|
|||||||
"statistics_configuration": "통계 구성",
|
"statistics_configuration": "통계 구성",
|
||||||
"statistics_retention": "통계 저장 기간",
|
"statistics_retention": "통계 저장 기간",
|
||||||
"statistics_retention_desc": "값을 줄이면 설정한 값보다 오래된 데이터가 소멸됩니다.",
|
"statistics_retention_desc": "값을 줄이면 설정한 값보다 오래된 데이터가 소멸됩니다.",
|
||||||
"statistics_clear": " 통계 초기화",
|
"statistics_clear": "통계 초기화",
|
||||||
"statistics_clear_confirm": "통계를 정말로 초기화하시겠습니까?",
|
"statistics_clear_confirm": "통계를 정말로 초기화하시겠습니까?",
|
||||||
"statistics_retention_confirm": "정말로 통계 저장 기간을 변경하시겠습니까? 저장 주기를 낮출 경우, 일부 데이터가 손실됩니다",
|
"statistics_retention_confirm": "정말로 통계 저장 기간을 변경하시겠습니까? 저장 주기를 낮출 경우, 일부 데이터가 손실됩니다",
|
||||||
"statistics_cleared": "통계를 성공적으로 초기화했습니다.",
|
"statistics_cleared": "통계를 성공적으로 초기화했습니다.",
|
||||||
|
"statistics_enable": "통계 활성화",
|
||||||
"interval_hours": "{{count}} 시간",
|
"interval_hours": "{{count}} 시간",
|
||||||
"interval_hours_plural": "{{count}} 시간",
|
"interval_hours_plural": "{{count}} 시간",
|
||||||
"filters_configuration": "필터 구성",
|
"filters_configuration": "필터 구성",
|
||||||
@@ -597,7 +598,7 @@
|
|||||||
"cache_ttl_min_override_desc": "업스트림 서버에서 수신한 TTL 값(최소)을 무시합니다",
|
"cache_ttl_min_override_desc": "업스트림 서버에서 수신한 TTL 값(최소)을 무시합니다",
|
||||||
"cache_ttl_max_override_desc": "업스트림 서버에서 수신한 TTL 값(최대)을 무시합니다",
|
"cache_ttl_max_override_desc": "업스트림 서버에서 수신한 TTL 값(최대)을 무시합니다",
|
||||||
"ttl_cache_validation": "최소 캐시 TTL 값은 최대 값보다 이하여야 합니다",
|
"ttl_cache_validation": "최소 캐시 TTL 값은 최대 값보다 이하여야 합니다",
|
||||||
"cache_optimistic": "캐시 유지",
|
"cache_optimistic": "옵티미스틱 캐시",
|
||||||
"cache_optimistic_desc": "세션이 만료되었거나 새로고침을 시도하는 경우에도 AdGuard Home이 캐시를 기반으로 응답하도록 합니다.",
|
"cache_optimistic_desc": "세션이 만료되었거나 새로고침을 시도하는 경우에도 AdGuard Home이 캐시를 기반으로 응답하도록 합니다.",
|
||||||
"filter_category_general": "일반 목록",
|
"filter_category_general": "일반 목록",
|
||||||
"filter_category_security": "보안 목록",
|
"filter_category_security": "보안 목록",
|
||||||
@@ -612,6 +613,8 @@
|
|||||||
"click_to_view_queries": "쿼리를 보려면 클릭합니다",
|
"click_to_view_queries": "쿼리를 보려면 클릭합니다",
|
||||||
"port_53_faq_link": "53번 포트는 보통 \"DNSStubListener\"나 \"systemd-resolved\" 서비스가 이미 사용하고 있습니다. 이 문제에 대한 해결 방법을 <0>설명</0>에서 찾아보세요.",
|
"port_53_faq_link": "53번 포트는 보통 \"DNSStubListener\"나 \"systemd-resolved\" 서비스가 이미 사용하고 있습니다. 이 문제에 대한 해결 방법을 <0>설명</0>에서 찾아보세요.",
|
||||||
"adg_will_drop_dns_queries": "AdGuard Home은 이 클라이언트에서 모든 DNS 쿼리를 삭제합니다.",
|
"adg_will_drop_dns_queries": "AdGuard Home은 이 클라이언트에서 모든 DNS 쿼리를 삭제합니다.",
|
||||||
"client_not_in_allowed_clients": "이 클라이언트는 허용된 클라이언트 목록에 없으므로 허용되지 않습니다.",
|
"filter_allowlist": "경고: 이 경우 허용된 클라이언트 목록에서 '{{disallowed_rule}}' 규칙 또한 제외됩니다.",
|
||||||
"experimental": "실험"
|
"last_rule_in_allowlist": "'{{disallowed_rule}}' 규칙을 제외하면 '허용된 클라이언트' 목록이 꺼지므로 해당 클라이언트를 제외할 수 없습니다.",
|
||||||
|
"experimental": "실험",
|
||||||
|
"use_saved_key": "이전에 저장했던 키 사용하기"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"client_settings": "Cliënt Instellingen",
|
"client_settings": "Cliëntinstellingen",
|
||||||
"example_upstream_reserved": "Je kan een DNS upstream specifiëren <0>voor specifieke domein(en)</0>",
|
"example_upstream_reserved": "Je kan een DNS-upstream opgeven <0>voor specifieke domein(en)</0>",
|
||||||
"example_upstream_comment": "Je kan je commentaar specifiëren",
|
"example_upstream_comment": "Je kan je commentaar specifiëren",
|
||||||
"upstream_parallel": "Parallelle verzoeken gebruiken om te versnellen door gelijktijdig verzoeken te sturen naar alle upstream servers.",
|
"upstream_parallel": "Parallelle verzoeken gebruiken om te versnellen door gelijktijdig verzoeken te sturen naar alle upstream servers.",
|
||||||
"parallel_requests": "Parallelle verzoeken",
|
"parallel_requests": "Parallelle verzoeken",
|
||||||
@@ -208,7 +208,7 @@
|
|||||||
"example_upstream_sdns": "je kunt <0>DNS Stamps</0> voor <1>DNSCrypt</1> of <2>DNS-via-HTTPS</2> oplossingen gebruiken",
|
"example_upstream_sdns": "je kunt <0>DNS Stamps</0> voor <1>DNSCrypt</1> of <2>DNS-via-HTTPS</2> oplossingen gebruiken",
|
||||||
"example_upstream_tcp": "standaard DNS (over TCP)",
|
"example_upstream_tcp": "standaard DNS (over TCP)",
|
||||||
"all_lists_up_to_date_toast": "Alle lijsten zijn reeds up-to-date",
|
"all_lists_up_to_date_toast": "Alle lijsten zijn reeds up-to-date",
|
||||||
"updated_upstream_dns_toast": "De upstream DNS-servers zijn bijgewerkt",
|
"updated_upstream_dns_toast": "Upstream-servers succesvol opgeslagen",
|
||||||
"dns_test_ok_toast": "Opgegeven DNS-servers werken correct",
|
"dns_test_ok_toast": "Opgegeven DNS-servers werken correct",
|
||||||
"dns_test_not_ok_toast": "Server \"{{key}}\": kon niet worden gebruikt, controleer of je het correct hebt geschreven",
|
"dns_test_not_ok_toast": "Server \"{{key}}\": kon niet worden gebruikt, controleer of je het correct hebt geschreven",
|
||||||
"unblock": "Deblokkeren",
|
"unblock": "Deblokkeren",
|
||||||
@@ -223,7 +223,7 @@
|
|||||||
"domain_or_client": "Domein of cliënt",
|
"domain_or_client": "Domein of cliënt",
|
||||||
"type_table_header": "Type",
|
"type_table_header": "Type",
|
||||||
"response_table_header": "Antwoord",
|
"response_table_header": "Antwoord",
|
||||||
"response_code": "Reactie code",
|
"response_code": "Reactiecode",
|
||||||
"client_table_header": "Gebruiker",
|
"client_table_header": "Gebruiker",
|
||||||
"empty_response_status": "Leeg",
|
"empty_response_status": "Leeg",
|
||||||
"show_all_filter_type": "Toon alles",
|
"show_all_filter_type": "Toon alles",
|
||||||
@@ -235,7 +235,7 @@
|
|||||||
"loading_table_status": "Laden...",
|
"loading_table_status": "Laden...",
|
||||||
"page_table_footer_text": "Pagina",
|
"page_table_footer_text": "Pagina",
|
||||||
"rows_table_footer_text": "rijen",
|
"rows_table_footer_text": "rijen",
|
||||||
"updated_custom_filtering_toast": "Aangepaste filter regels zijn bijgewerkt",
|
"updated_custom_filtering_toast": "Aangepaste regels succesvol opgeslagen",
|
||||||
"rule_removed_from_custom_filtering_toast": "Regel verwijderd uit de aangepaste filterregels: {{rule}}",
|
"rule_removed_from_custom_filtering_toast": "Regel verwijderd uit de aangepaste filterregels: {{rule}}",
|
||||||
"rule_added_to_custom_filtering_toast": "Regel toegevoegd aan de aangepaste filterregels: {{rule}}",
|
"rule_added_to_custom_filtering_toast": "Regel toegevoegd aan de aangepaste filterregels: {{rule}}",
|
||||||
"query_log_response_status": "Status: {{value}}",
|
"query_log_response_status": "Status: {{value}}",
|
||||||
@@ -306,7 +306,7 @@
|
|||||||
"install_settings_dns_desc": "Je moet jouw apparaten of router configureren om de DNS-server te gebruiken op de volgende adressen:",
|
"install_settings_dns_desc": "Je moet jouw apparaten of router configureren om de DNS-server te gebruiken op de volgende adressen:",
|
||||||
"install_settings_all_interfaces": "Alle interfaces",
|
"install_settings_all_interfaces": "Alle interfaces",
|
||||||
"install_auth_title": "Authenticatie",
|
"install_auth_title": "Authenticatie",
|
||||||
"install_auth_desc": "Het wordt ten zeerste aanbevolen om wachtwoordverificatie te configureren voor de AdGuard Home admin webinterface. Zelfs als het alleen toegankelijk is in uw lokale netwerk, is het nog steeds belangrijk om het te beschermen tegen onbeperkte toegang.",
|
"install_auth_desc": "Wachtwoordverificatie voor je AdGuard Home-beheerderswebinterface moet worden geconfigureerd. Zelfs als AdGuard Home alleen toegankelijk is in je lokale netwerk, is het nog steeds belangrijk om het te beschermen tegen onbeperkte toegang.",
|
||||||
"install_auth_username": "Gebruikersnaam",
|
"install_auth_username": "Gebruikersnaam",
|
||||||
"install_auth_password": "Wachtwoord",
|
"install_auth_password": "Wachtwoord",
|
||||||
"install_auth_confirm": "Bevestig wachtwoord",
|
"install_auth_confirm": "Bevestig wachtwoord",
|
||||||
@@ -499,10 +499,11 @@
|
|||||||
"statistics_configuration": "Statistieken configuratie",
|
"statistics_configuration": "Statistieken configuratie",
|
||||||
"statistics_retention": "Statistieken retentie",
|
"statistics_retention": "Statistieken retentie",
|
||||||
"statistics_retention_desc": "Als je de interval waarde vermindert, zullen sommige gegevens verloren gaan",
|
"statistics_retention_desc": "Als je de interval waarde vermindert, zullen sommige gegevens verloren gaan",
|
||||||
"statistics_clear": " Statistieken wissen",
|
"statistics_clear": "Statistieken wissen",
|
||||||
"statistics_clear_confirm": "Alle statistieken werkelijk wissen?",
|
"statistics_clear_confirm": "Alle statistieken werkelijk wissen?",
|
||||||
"statistics_retention_confirm": "Weet u zeker dat u de bewaartermijn van de statistieken wilt wijzigen? Als u de intervalwaarde verlaagt, gaan sommige gegevens verloren",
|
"statistics_retention_confirm": "Weet u zeker dat u de bewaartermijn van de statistieken wilt wijzigen? Als u de intervalwaarde verlaagt, gaan sommige gegevens verloren",
|
||||||
"statistics_cleared": "Statistieken succesvol gewist",
|
"statistics_cleared": "Statistieken succesvol gewist",
|
||||||
|
"statistics_enable": "Statistieken inschakelen",
|
||||||
"interval_hours": "{{count}} uur",
|
"interval_hours": "{{count}} uur",
|
||||||
"interval_hours_plural": "{{count}} uren",
|
"interval_hours_plural": "{{count}} uren",
|
||||||
"filters_configuration": "Filters instellingen",
|
"filters_configuration": "Filters instellingen",
|
||||||
@@ -597,7 +598,7 @@
|
|||||||
"cache_ttl_min_override_desc": "Uitbreiden van korte Time-To-Live waardes (seconden) ontvangen van de upstream server bij het cachen van DNS antwoorden",
|
"cache_ttl_min_override_desc": "Uitbreiden van korte Time-To-Live waardes (seconden) ontvangen van de upstream server bij het cachen van DNS antwoorden",
|
||||||
"cache_ttl_max_override_desc": "Instellen van maximum time-to-live waarde (seconden) voor opslag in de DNS cache",
|
"cache_ttl_max_override_desc": "Instellen van maximum time-to-live waarde (seconden) voor opslag in de DNS cache",
|
||||||
"ttl_cache_validation": "Minimale waarde TTL-cache moet kleiner dan of gelijk zijn aan de maximale waarde",
|
"ttl_cache_validation": "Minimale waarde TTL-cache moet kleiner dan of gelijk zijn aan de maximale waarde",
|
||||||
"cache_optimistic": "Optimistisch",
|
"cache_optimistic": "Optimistisch cachen",
|
||||||
"cache_optimistic_desc": "Laat AdGuard Home reageren vanuit de cache, zelfs als de vermeldingen zijn verlopen en probeer deze ook te vernieuwen.",
|
"cache_optimistic_desc": "Laat AdGuard Home reageren vanuit de cache, zelfs als de vermeldingen zijn verlopen en probeer deze ook te vernieuwen.",
|
||||||
"filter_category_general": "Algemeen",
|
"filter_category_general": "Algemeen",
|
||||||
"filter_category_security": "Beveiliging",
|
"filter_category_security": "Beveiliging",
|
||||||
@@ -612,6 +613,8 @@
|
|||||||
"click_to_view_queries": "Klik om queries te bekijken",
|
"click_to_view_queries": "Klik om queries te bekijken",
|
||||||
"port_53_faq_link": "Poort 53 wordt vaak gebruikt door services als DNSStubListener- of de systeem DNS-resolver. Lees a.u.b. <0>deze instructie</0> hoe dit is op te lossen.",
|
"port_53_faq_link": "Poort 53 wordt vaak gebruikt door services als DNSStubListener- of de systeem DNS-resolver. Lees a.u.b. <0>deze instructie</0> hoe dit is op te lossen.",
|
||||||
"adg_will_drop_dns_queries": "AdGuard Home zal alle DNS verzoeken van deze toepassing/dit systeem negeren.",
|
"adg_will_drop_dns_queries": "AdGuard Home zal alle DNS verzoeken van deze toepassing/dit systeem negeren.",
|
||||||
"client_not_in_allowed_clients": "De toepassing is niet toegestaan omdat deze niet in de lijst \"Toegestane toepassingen\" voorkomt.",
|
"filter_allowlist": "WAARSCHUWING: Deze actie zal ook de regel \"{{disallowed_rule}}\" uitsluiten van de lijst met toegestane clients.",
|
||||||
"experimental": "Experimenteel"
|
"last_rule_in_allowlist": "Kan deze client niet weigeren omdat het uitsluiten van de regel \"{{disallowed_rule}}\" de lijst \"Toegestane clients\" zal UITSCHAKELEN.",
|
||||||
|
"experimental": "Experimenteel",
|
||||||
|
"use_saved_key": "De eerder opgeslagen sleutel gebruiken"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -253,6 +253,7 @@
|
|||||||
"source_label": "Kilde",
|
"source_label": "Kilde",
|
||||||
"found_in_known_domain_db": "Funnet i databasen over kjente domener.",
|
"found_in_known_domain_db": "Funnet i databasen over kjente domener.",
|
||||||
"category_label": "Kategori",
|
"category_label": "Kategori",
|
||||||
|
"rule_label": "Oppføring",
|
||||||
"list_label": "Liste",
|
"list_label": "Liste",
|
||||||
"unknown_filter": "Ukjent filter {{filterId}}",
|
"unknown_filter": "Ukjent filter {{filterId}}",
|
||||||
"known_tracker": "Kjent sporer",
|
"known_tracker": "Kjent sporer",
|
||||||
@@ -262,6 +263,7 @@
|
|||||||
"install_settings_listen": "Lytt til grensesnitt",
|
"install_settings_listen": "Lytt til grensesnitt",
|
||||||
"install_settings_port": "Port",
|
"install_settings_port": "Port",
|
||||||
"install_settings_interface_link": "Ditt AdGuard Home-admin-nettgrensesnitt vil være tilgjengelig på de følgende adressene:",
|
"install_settings_interface_link": "Ditt AdGuard Home-admin-nettgrensesnitt vil være tilgjengelig på de følgende adressene:",
|
||||||
|
"form_error_port": "Skriv inn en gyldig portverdi",
|
||||||
"install_settings_dns": "DNS-tjener",
|
"install_settings_dns": "DNS-tjener",
|
||||||
"install_settings_dns_desc": "Du vil måtte sette opp enhetene eller ruteren din(e) til å bruke DNS-tjeneren på disse adressene:",
|
"install_settings_dns_desc": "Du vil måtte sette opp enhetene eller ruteren din(e) til å bruke DNS-tjeneren på disse adressene:",
|
||||||
"install_settings_all_interfaces": "Alle grensesnitt",
|
"install_settings_all_interfaces": "Alle grensesnitt",
|
||||||
|
|||||||
@@ -98,7 +98,7 @@
|
|||||||
"copyright": "Prawo autorskie",
|
"copyright": "Prawo autorskie",
|
||||||
"homepage": "Strona główna",
|
"homepage": "Strona główna",
|
||||||
"report_an_issue": "Zgłoś problem",
|
"report_an_issue": "Zgłoś problem",
|
||||||
"privacy_policy": "Polityka prywatności",
|
"privacy_policy": "Polityka Prywatności",
|
||||||
"enable_protection": "Włącz ochronę",
|
"enable_protection": "Włącz ochronę",
|
||||||
"enabled_protection": "Ochrona włączona ",
|
"enabled_protection": "Ochrona włączona ",
|
||||||
"disable_protection": "Wyłącz ochronę",
|
"disable_protection": "Wyłącz ochronę",
|
||||||
@@ -208,7 +208,7 @@
|
|||||||
"example_upstream_sdns": "możesz użyć adresu <0>DNS Stamps</0> dla protokołu <1>DNSCrypt</1> lub <2>DNS-over-HTTPS</2>",
|
"example_upstream_sdns": "możesz użyć adresu <0>DNS Stamps</0> dla protokołu <1>DNSCrypt</1> lub <2>DNS-over-HTTPS</2>",
|
||||||
"example_upstream_tcp": "zwykły DNS (przez TCP)",
|
"example_upstream_tcp": "zwykły DNS (przez TCP)",
|
||||||
"all_lists_up_to_date_toast": "Wszystkie listy są już aktualne",
|
"all_lists_up_to_date_toast": "Wszystkie listy są już aktualne",
|
||||||
"updated_upstream_dns_toast": "Główne serwery DNS zostały zaktualizowane",
|
"updated_upstream_dns_toast": "Serwery nadrzędne zostały pomyślnie zapisane",
|
||||||
"dns_test_ok_toast": "Określone serwery DNS działają poprawnie",
|
"dns_test_ok_toast": "Określone serwery DNS działają poprawnie",
|
||||||
"dns_test_not_ok_toast": "Serwer \"{{key}}\": nie można go użyć, sprawdź, czy napisałeś go poprawnie",
|
"dns_test_not_ok_toast": "Serwer \"{{key}}\": nie można go użyć, sprawdź, czy napisałeś go poprawnie",
|
||||||
"unblock": "Odblokuj",
|
"unblock": "Odblokuj",
|
||||||
@@ -235,7 +235,7 @@
|
|||||||
"loading_table_status": "Wczytuję...",
|
"loading_table_status": "Wczytuję...",
|
||||||
"page_table_footer_text": "Strona",
|
"page_table_footer_text": "Strona",
|
||||||
"rows_table_footer_text": "wierszy",
|
"rows_table_footer_text": "wierszy",
|
||||||
"updated_custom_filtering_toast": "Zaktualizowano niestandardowe reguły filtrowania",
|
"updated_custom_filtering_toast": "Reguły niestandardowe zapisane pomyślnie",
|
||||||
"rule_removed_from_custom_filtering_toast": "Reguła usunięta z niestandardowych reguł filtrowania: {{rule}}",
|
"rule_removed_from_custom_filtering_toast": "Reguła usunięta z niestandardowych reguł filtrowania: {{rule}}",
|
||||||
"rule_added_to_custom_filtering_toast": "Reguła dodana do niestandardowych reguł filtrowania: {{rule}}",
|
"rule_added_to_custom_filtering_toast": "Reguła dodana do niestandardowych reguł filtrowania: {{rule}}",
|
||||||
"query_log_response_status": "Status: {{value}}",
|
"query_log_response_status": "Status: {{value}}",
|
||||||
@@ -306,7 +306,7 @@
|
|||||||
"install_settings_dns_desc": "Konieczne będzie skonfigurowanie urządzenia lub routera do korzystania z serwera DNS pod następującymi adresami:",
|
"install_settings_dns_desc": "Konieczne będzie skonfigurowanie urządzenia lub routera do korzystania z serwera DNS pod następującymi adresami:",
|
||||||
"install_settings_all_interfaces": "Wszystkie interfejsy",
|
"install_settings_all_interfaces": "Wszystkie interfejsy",
|
||||||
"install_auth_title": "Uwierzytelnianie",
|
"install_auth_title": "Uwierzytelnianie",
|
||||||
"install_auth_desc": "Zalecamy skonfigurowanie strony AdGuard Home Admin, aby zweryfikować swoją tożsamość za pomocą hasła. Chociaż jest dostępny tylko w sieci lokalnej, nadal ważne jest, aby chronić go przed nieograniczonym dostępem.",
|
"install_auth_desc": "Należy skonfigurować uwierzytelnianie hasłem do interfejsu internetowego administratora AdGuard Home. Nawet jeśli AdGuard Home jest dostępny tylko w sieci lokalnej, nadal ważne jest, aby chronić go przed nieograniczonym dostępem.",
|
||||||
"install_auth_username": "Nazwa użytkownika",
|
"install_auth_username": "Nazwa użytkownika",
|
||||||
"install_auth_password": "Hasło",
|
"install_auth_password": "Hasło",
|
||||||
"install_auth_confirm": "Potwierdź hasło",
|
"install_auth_confirm": "Potwierdź hasło",
|
||||||
@@ -499,10 +499,11 @@
|
|||||||
"statistics_configuration": "Konfiguracja statystyk",
|
"statistics_configuration": "Konfiguracja statystyk",
|
||||||
"statistics_retention": "Przechowywanie statystyk",
|
"statistics_retention": "Przechowywanie statystyk",
|
||||||
"statistics_retention_desc": "Jeśli zmniejszysz wartość interwału, niektóre dane zostaną utracone",
|
"statistics_retention_desc": "Jeśli zmniejszysz wartość interwału, niektóre dane zostaną utracone",
|
||||||
"statistics_clear": " Wyczyść statystyki",
|
"statistics_clear": "Wyczyść statystyki",
|
||||||
"statistics_clear_confirm": "Czy na pewno chcesz wyczyścić statystyki?",
|
"statistics_clear_confirm": "Czy na pewno chcesz wyczyścić statystyki?",
|
||||||
"statistics_retention_confirm": "Czy chcesz zmienić sposób przechowania statystyk? Jeżeli obniżysz wartość interwału, niektóre dane będą utracone",
|
"statistics_retention_confirm": "Czy chcesz zmienić sposób przechowania statystyk? Jeżeli obniżysz wartość interwału, niektóre dane będą utracone",
|
||||||
"statistics_cleared": "Statystyki zostały pomyślnie wyczyszczone",
|
"statistics_cleared": "Statystyki zostały pomyślnie wyczyszczone",
|
||||||
|
"statistics_enable": "Włącz statystyki",
|
||||||
"interval_hours": "{{count}} godzina",
|
"interval_hours": "{{count}} godzina",
|
||||||
"interval_hours_plural": "{{count}} godziny",
|
"interval_hours_plural": "{{count}} godziny",
|
||||||
"filters_configuration": "Konfiguracja filtrów",
|
"filters_configuration": "Konfiguracja filtrów",
|
||||||
@@ -597,7 +598,7 @@
|
|||||||
"cache_ttl_min_override_desc": "Zastąp wartość TTL (w sekundach) otrzymaną z serwera nadrzędnego podczas buforowania odpowiedzi DNS",
|
"cache_ttl_min_override_desc": "Zastąp wartość TTL (w sekundach) otrzymaną z serwera nadrzędnego podczas buforowania odpowiedzi DNS",
|
||||||
"cache_ttl_max_override_desc": "Ustaw maksymalną wartość TTL (w sekundach) dla wpisów w pamięci podręcznej DNS",
|
"cache_ttl_max_override_desc": "Ustaw maksymalną wartość TTL (w sekundach) dla wpisów w pamięci podręcznej DNS",
|
||||||
"ttl_cache_validation": "Minimalna pamięć podręczna wartości TTL musi być mniejsza lub równa maksymalnej wartości",
|
"ttl_cache_validation": "Minimalna pamięć podręczna wartości TTL musi być mniejsza lub równa maksymalnej wartości",
|
||||||
"cache_optimistic": "Optymistyczny",
|
"cache_optimistic": "Optymistyczne buforowanie",
|
||||||
"cache_optimistic_desc": "Spraw, aby AdGuard Home odpowiadał z pamięci podręcznej, nawet gdy wpisy wygasły, a także spróbuj je odświeżyć.",
|
"cache_optimistic_desc": "Spraw, aby AdGuard Home odpowiadał z pamięci podręcznej, nawet gdy wpisy wygasły, a także spróbuj je odświeżyć.",
|
||||||
"filter_category_general": "Ogólne",
|
"filter_category_general": "Ogólne",
|
||||||
"filter_category_security": "Bezpieczeństwo",
|
"filter_category_security": "Bezpieczeństwo",
|
||||||
@@ -612,6 +613,8 @@
|
|||||||
"click_to_view_queries": "Kliknij, aby wyświetlić zapytania",
|
"click_to_view_queries": "Kliknij, aby wyświetlić zapytania",
|
||||||
"port_53_faq_link": "Port 53 jest często zajęty przez usługi \"DNSStubListener\" lub \"systemd-resolved\". Przeczytaj <0>tę instrukcję</0> jak to rozwiązać.",
|
"port_53_faq_link": "Port 53 jest często zajęty przez usługi \"DNSStubListener\" lub \"systemd-resolved\". Przeczytaj <0>tę instrukcję</0> jak to rozwiązać.",
|
||||||
"adg_will_drop_dns_queries": "AdGuard Home odrzuci zapytanie DNS od tego klienta.",
|
"adg_will_drop_dns_queries": "AdGuard Home odrzuci zapytanie DNS od tego klienta.",
|
||||||
"client_not_in_allowed_clients": "Klient nie jest dozwolony, ponieważ nie ma go na liście „Dozwoleni klienci”.",
|
"filter_allowlist": "OSTRZEŻENIE: To działanie spowoduje również wykluczenie reguły \"{{disallowed_rule}}\" z listy dozwolonych klientów.",
|
||||||
"experimental": "Funkcja eksperymentalna"
|
"last_rule_in_allowlist": "Nie można odrzucić tego klienta, ponieważ wykluczenie reguły \"{{disallowed_rule}}\" spowoduje WYŁĄCZENIE listy „Dozwolonych klientów”.",
|
||||||
|
"experimental": "Funkcja eksperymentalna",
|
||||||
|
"use_saved_key": "Użyj wcześniej zapisanego klucza"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -208,7 +208,7 @@
|
|||||||
"example_upstream_sdns": "você pode usar <0>DNS Stamps</0> para o <1>DNSCrypt</1> ou usar os resolvedores <2>DNS-sobre-HTTPS</2>",
|
"example_upstream_sdns": "você pode usar <0>DNS Stamps</0> para o <1>DNSCrypt</1> ou usar os resolvedores <2>DNS-sobre-HTTPS</2>",
|
||||||
"example_upstream_tcp": "DNS regular (através do TCP)",
|
"example_upstream_tcp": "DNS regular (através do TCP)",
|
||||||
"all_lists_up_to_date_toast": "Todas as listas já estão atualizadas",
|
"all_lists_up_to_date_toast": "Todas as listas já estão atualizadas",
|
||||||
"updated_upstream_dns_toast": "Atualizado os servidores DNS primário",
|
"updated_upstream_dns_toast": "Servidores DNS primário salvos com sucesso",
|
||||||
"dns_test_ok_toast": "Os servidores DNS especificados estão funcionando corretamente",
|
"dns_test_ok_toast": "Os servidores DNS especificados estão funcionando corretamente",
|
||||||
"dns_test_not_ok_toast": "O servidor \"{{key}}\": não pôde ser utilizado. Por favor, verifique se você escreveu corretamente",
|
"dns_test_not_ok_toast": "O servidor \"{{key}}\": não pôde ser utilizado. Por favor, verifique se você escreveu corretamente",
|
||||||
"unblock": "Desbloquear",
|
"unblock": "Desbloquear",
|
||||||
@@ -235,7 +235,7 @@
|
|||||||
"loading_table_status": "Carregando",
|
"loading_table_status": "Carregando",
|
||||||
"page_table_footer_text": "Página",
|
"page_table_footer_text": "Página",
|
||||||
"rows_table_footer_text": "linhas",
|
"rows_table_footer_text": "linhas",
|
||||||
"updated_custom_filtering_toast": "Regras de filtragem personalizadas atualizadas",
|
"updated_custom_filtering_toast": "Regras personalizadas salvas com sucesso",
|
||||||
"rule_removed_from_custom_filtering_toast": "Regra removida das regras de filtragem personalizadas: {{rule}}",
|
"rule_removed_from_custom_filtering_toast": "Regra removida das regras de filtragem personalizadas: {{rule}}",
|
||||||
"rule_added_to_custom_filtering_toast": "Regra adicionada às regras de filtragem personalizadas: {{rule}}",
|
"rule_added_to_custom_filtering_toast": "Regra adicionada às regras de filtragem personalizadas: {{rule}}",
|
||||||
"query_log_response_status": "Status: {{value}}",
|
"query_log_response_status": "Status: {{value}}",
|
||||||
@@ -306,7 +306,7 @@
|
|||||||
"install_settings_dns_desc": "Você precisa configurar seu dispositivo ou roteador para usar o servidor DNS nos seguintes endereços:",
|
"install_settings_dns_desc": "Você precisa configurar seu dispositivo ou roteador para usar o servidor DNS nos seguintes endereços:",
|
||||||
"install_settings_all_interfaces": "Todas interfaces",
|
"install_settings_all_interfaces": "Todas interfaces",
|
||||||
"install_auth_title": "Autenticação",
|
"install_auth_title": "Autenticação",
|
||||||
"install_auth_desc": "É altamente recomendável configurar a autenticação por senha na interface web de administração do AdGuard Home. Mesmo que ela seja acessível somente em sua rede local, ainda assim é importante protegê-la contra acesso irrestrito.",
|
"install_auth_desc": "A autenticação de senha para a interface da web de administrador do AdGuard Home deve ser configurada. Mesmo que o AdGuard Home esteja acessível apenas em sua rede local, ainda é importante protegê-la de acesso irrestrito.",
|
||||||
"install_auth_username": "Nome de usuário",
|
"install_auth_username": "Nome de usuário",
|
||||||
"install_auth_password": "Senha",
|
"install_auth_password": "Senha",
|
||||||
"install_auth_confirm": "Confirmar senha",
|
"install_auth_confirm": "Confirmar senha",
|
||||||
@@ -503,6 +503,7 @@
|
|||||||
"statistics_clear_confirm": "Você tem certeza de que deseja limpar as estatísticas?",
|
"statistics_clear_confirm": "Você tem certeza de que deseja limpar as estatísticas?",
|
||||||
"statistics_retention_confirm": "Você tem certeza que quer alterar o arquivamento das estatísticas? Se diminuir o valor do intervalo, alguns dados serão perdidos",
|
"statistics_retention_confirm": "Você tem certeza que quer alterar o arquivamento das estatísticas? Se diminuir o valor do intervalo, alguns dados serão perdidos",
|
||||||
"statistics_cleared": "As estatísticas foram limpas com sucesso",
|
"statistics_cleared": "As estatísticas foram limpas com sucesso",
|
||||||
|
"statistics_enable": "Ativar estatísticas",
|
||||||
"interval_hours": "{{count}} hora",
|
"interval_hours": "{{count}} hora",
|
||||||
"interval_hours_plural": "{{count}} horas",
|
"interval_hours_plural": "{{count}} horas",
|
||||||
"filters_configuration": "Configuração de filtros",
|
"filters_configuration": "Configuração de filtros",
|
||||||
@@ -597,7 +598,7 @@
|
|||||||
"cache_ttl_min_override_desc": "Prolongue os valores de curta duração (segundos) recebidos do servidor primário ao armazenar em cache as respostas DNS",
|
"cache_ttl_min_override_desc": "Prolongue os valores de curta duração (segundos) recebidos do servidor primário ao armazenar em cache as respostas DNS",
|
||||||
"cache_ttl_max_override_desc": "Defina um valor máximo de tempo de vida (segundos) para entradas no cache DNS",
|
"cache_ttl_max_override_desc": "Defina um valor máximo de tempo de vida (segundos) para entradas no cache DNS",
|
||||||
"ttl_cache_validation": "O valor TTL mínimo do cache deve ser menor ou igual ao valor máximo",
|
"ttl_cache_validation": "O valor TTL mínimo do cache deve ser menor ou igual ao valor máximo",
|
||||||
"cache_optimistic": "Otimista",
|
"cache_optimistic": "Cache otimista",
|
||||||
"cache_optimistic_desc": "Faz o AdGuard Home responder a partir do cache mesmo quando as entradas expirarem e também tenta atualizá-las.",
|
"cache_optimistic_desc": "Faz o AdGuard Home responder a partir do cache mesmo quando as entradas expirarem e também tenta atualizá-las.",
|
||||||
"filter_category_general": "Geral",
|
"filter_category_general": "Geral",
|
||||||
"filter_category_security": "Segurança",
|
"filter_category_security": "Segurança",
|
||||||
@@ -612,6 +613,8 @@
|
|||||||
"click_to_view_queries": "Clique para ver as consultas",
|
"click_to_view_queries": "Clique para ver as consultas",
|
||||||
"port_53_faq_link": "A porta 53 é frequentemente ocupada por serviços \"DNSStubListener\" ou \"systemd-resolved\". Por favor leia <0>essa instrução</0> para resolver isso.",
|
"port_53_faq_link": "A porta 53 é frequentemente ocupada por serviços \"DNSStubListener\" ou \"systemd-resolved\". Por favor leia <0>essa instrução</0> para resolver isso.",
|
||||||
"adg_will_drop_dns_queries": "O AdGuard Home descartará todas as consultas DNS deste cliente.",
|
"adg_will_drop_dns_queries": "O AdGuard Home descartará todas as consultas DNS deste cliente.",
|
||||||
"client_not_in_allowed_clients": "O cliente não é permitido porque não está na lista \"Clientes permitidos\".",
|
"filter_allowlist": "AVISO: Esta ação também excluirá a regra \"{{disallowed_rule}}\" da lista de clientes permitidos.",
|
||||||
"experimental": "Experimental"
|
"last_rule_in_allowlist": "Não é possível desautorizar este cliente porque excluir a regra \"{{disallowed_rule}}\" DESATIVARÁ a lista de \"Clientes permitidos\".",
|
||||||
|
"experimental": "Experimental",
|
||||||
|
"use_saved_key": "Use a chave salva anteriormente"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,11 +98,11 @@
|
|||||||
"copyright": "Copyright",
|
"copyright": "Copyright",
|
||||||
"homepage": "Página inicial",
|
"homepage": "Página inicial",
|
||||||
"report_an_issue": "Comunicar um problema",
|
"report_an_issue": "Comunicar um problema",
|
||||||
"privacy_policy": "Política de Privacidade",
|
"privacy_policy": "Política de privacidade",
|
||||||
"enable_protection": "Ativar protecção",
|
"enable_protection": "Ativar proteção",
|
||||||
"enabled_protection": "Ativar protecção",
|
"enabled_protection": "Ativar proteção",
|
||||||
"disable_protection": "Desativar protecção",
|
"disable_protection": "Desativar proteção",
|
||||||
"disabled_protection": "Desativar protecção",
|
"disabled_protection": "Desativar proteção",
|
||||||
"refresh_statics": "Repor estatísticas",
|
"refresh_statics": "Repor estatísticas",
|
||||||
"dns_query": "Consultas de DNS",
|
"dns_query": "Consultas de DNS",
|
||||||
"blocked_by": "<0>Bloqueado por filtros</0>",
|
"blocked_by": "<0>Bloqueado por filtros</0>",
|
||||||
@@ -208,7 +208,7 @@
|
|||||||
"example_upstream_sdns": "pode usar <0>DNS Stamps</0> para o <1>DNSCrypt</1> ou usar os resolvedores <2>DNS-sobre-HTTPS</2>",
|
"example_upstream_sdns": "pode usar <0>DNS Stamps</0> para o <1>DNSCrypt</1> ou usar os resolvedores <2>DNS-sobre-HTTPS</2>",
|
||||||
"example_upstream_tcp": "dNS regular (através do TCP)",
|
"example_upstream_tcp": "dNS regular (através do TCP)",
|
||||||
"all_lists_up_to_date_toast": "Todas as listas já estão atualizadas",
|
"all_lists_up_to_date_toast": "Todas as listas já estão atualizadas",
|
||||||
"updated_upstream_dns_toast": "A atualizar os servidores DNS primário",
|
"updated_upstream_dns_toast": "Servidores DNS primário guardados com sucesso",
|
||||||
"dns_test_ok_toast": "Os servidores DNS especificados estão a funcionar corretamente",
|
"dns_test_ok_toast": "Os servidores DNS especificados estão a funcionar corretamente",
|
||||||
"dns_test_not_ok_toast": "O servidor \"{{key}}\": não pôde ser utilizado. Por favor, verifique se o escreveu corretamente",
|
"dns_test_not_ok_toast": "O servidor \"{{key}}\": não pôde ser utilizado. Por favor, verifique se o escreveu corretamente",
|
||||||
"unblock": "Desbloquear",
|
"unblock": "Desbloquear",
|
||||||
@@ -235,7 +235,7 @@
|
|||||||
"loading_table_status": "A carregar...",
|
"loading_table_status": "A carregar...",
|
||||||
"page_table_footer_text": "Página",
|
"page_table_footer_text": "Página",
|
||||||
"rows_table_footer_text": "linhas",
|
"rows_table_footer_text": "linhas",
|
||||||
"updated_custom_filtering_toast": "Regras de filtragem personalizadas atualizadas",
|
"updated_custom_filtering_toast": "Regras personalizadas guardadas com sucesso",
|
||||||
"rule_removed_from_custom_filtering_toast": "Regra removida das regras de filtragem personalizadas: {{rule}}",
|
"rule_removed_from_custom_filtering_toast": "Regra removida das regras de filtragem personalizadas: {{rule}}",
|
||||||
"rule_added_to_custom_filtering_toast": "Regra adicionada às regras de filtragem personalizadas: {{rule}}",
|
"rule_added_to_custom_filtering_toast": "Regra adicionada às regras de filtragem personalizadas: {{rule}}",
|
||||||
"query_log_response_status": "Status: {{value}}",
|
"query_log_response_status": "Status: {{value}}",
|
||||||
@@ -306,7 +306,7 @@
|
|||||||
"install_settings_dns_desc": "Precisa de configurar o seu dispositivo ou router para usar o servidor DNS nos seguintes endereços:",
|
"install_settings_dns_desc": "Precisa de configurar o seu dispositivo ou router para usar o servidor DNS nos seguintes endereços:",
|
||||||
"install_settings_all_interfaces": "Todas as interfaces",
|
"install_settings_all_interfaces": "Todas as interfaces",
|
||||||
"install_auth_title": "Autenticação",
|
"install_auth_title": "Autenticação",
|
||||||
"install_auth_desc": "É altamente recomendável configurar a autenticação por palavra-passe para a sua interface web de administrador do AdGuard Home. Mesmo que seja acessível apenas na sua rede local, ainda assim é importante protegê-lo contra o acesso irrestrito.",
|
"install_auth_desc": "A autenticação de palavra-passe para a interface da web de administrador do AdGuard Home deve ser configurada. Mesmo que o AdGuard Home esteja acessível apenas em sua rede local, ainda é importante protegê-la de acesso irrestrito.",
|
||||||
"install_auth_username": "Nome do utilizador",
|
"install_auth_username": "Nome do utilizador",
|
||||||
"install_auth_password": "Palavra-passe",
|
"install_auth_password": "Palavra-passe",
|
||||||
"install_auth_confirm": "Confirmar palavra-passe",
|
"install_auth_confirm": "Confirmar palavra-passe",
|
||||||
@@ -499,10 +499,11 @@
|
|||||||
"statistics_configuration": "Definição das estatísticas",
|
"statistics_configuration": "Definição das estatísticas",
|
||||||
"statistics_retention": "Retenção de estatísticas",
|
"statistics_retention": "Retenção de estatísticas",
|
||||||
"statistics_retention_desc": "Se diminuir o valor do intervalo, alguns dados serão perdidos",
|
"statistics_retention_desc": "Se diminuir o valor do intervalo, alguns dados serão perdidos",
|
||||||
"statistics_clear": " Limpar estatísticas",
|
"statistics_clear": "Limpar estatísticas",
|
||||||
"statistics_clear_confirm": "Tem a certeza de que deseja limpar as estatísticas?",
|
"statistics_clear_confirm": "Tem a certeza de que deseja limpar as estatísticas?",
|
||||||
"statistics_retention_confirm": "Tem a certeza que quer alterar a retenção de estatísticas? Se diminuir o valor do intervalo, alguns dados serão perdidos",
|
"statistics_retention_confirm": "Tem a certeza que quer alterar a retenção de estatísticas? Se diminuir o valor do intervalo, alguns dados serão perdidos",
|
||||||
"statistics_cleared": "As estatísticas foram apagadas com sucesso",
|
"statistics_cleared": "As estatísticas foram apagadas com sucesso",
|
||||||
|
"statistics_enable": "Ativar estatísticas",
|
||||||
"interval_hours": "{{count}} hora",
|
"interval_hours": "{{count}} hora",
|
||||||
"interval_hours_plural": "{{count}} horas",
|
"interval_hours_plural": "{{count}} horas",
|
||||||
"filters_configuration": "Definição dos filtros",
|
"filters_configuration": "Definição dos filtros",
|
||||||
@@ -597,7 +598,7 @@
|
|||||||
"cache_ttl_min_override_desc": "Prolongue os valores de curta duração (segundos) recebidos do servidor primário ao armazenar em cache as respostas DNS",
|
"cache_ttl_min_override_desc": "Prolongue os valores de curta duração (segundos) recebidos do servidor primário ao armazenar em cache as respostas DNS",
|
||||||
"cache_ttl_max_override_desc": "Defina um valor máximo de tempo de vida (segundos) para entradas no cache DNS",
|
"cache_ttl_max_override_desc": "Defina um valor máximo de tempo de vida (segundos) para entradas no cache DNS",
|
||||||
"ttl_cache_validation": "O valor TTL mínimo do cache deve ser menor ou igual ao valor máximo",
|
"ttl_cache_validation": "O valor TTL mínimo do cache deve ser menor ou igual ao valor máximo",
|
||||||
"cache_optimistic": "Otimista",
|
"cache_optimistic": "Cache otimista",
|
||||||
"cache_optimistic_desc": "Faz o AdGuard Home responder a partir do cache mesmo quando as entradas expirarem e também tenta atualizá-las.",
|
"cache_optimistic_desc": "Faz o AdGuard Home responder a partir do cache mesmo quando as entradas expirarem e também tenta atualizá-las.",
|
||||||
"filter_category_general": "Geral",
|
"filter_category_general": "Geral",
|
||||||
"filter_category_security": "Segurança",
|
"filter_category_security": "Segurança",
|
||||||
@@ -612,6 +613,8 @@
|
|||||||
"click_to_view_queries": "Clique para ver as consultas",
|
"click_to_view_queries": "Clique para ver as consultas",
|
||||||
"port_53_faq_link": "A porta 53 é frequentemente ocupada por serviços \"DNSStubListener\" ou \"systemd-resolved\". Por favor leia <0>essa instrução</0> para resolver isso.",
|
"port_53_faq_link": "A porta 53 é frequentemente ocupada por serviços \"DNSStubListener\" ou \"systemd-resolved\". Por favor leia <0>essa instrução</0> para resolver isso.",
|
||||||
"adg_will_drop_dns_queries": "O AdGuard Home descartará todas as consultas DNS deste cliente.",
|
"adg_will_drop_dns_queries": "O AdGuard Home descartará todas as consultas DNS deste cliente.",
|
||||||
"client_not_in_allowed_clients": "O cliente não é permitido porque não está na lista \"Clientes permitidos\".",
|
"filter_allowlist": "AVISO: Esta ação também excluirá a regra \"{{disallowed_rule}}\" da lista de clientes permitidos.",
|
||||||
"experimental": "Experimental"
|
"last_rule_in_allowlist": "Não é possível desautorizar este cliente porque excluir a regra \"{{disallowed_rule}}\" DESATIVARÁ a lista de \"Clientes permitidos\".",
|
||||||
|
"experimental": "Experimental",
|
||||||
|
"use_saved_key": "Use a chave guardada anteriormente"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -326,7 +326,7 @@
|
|||||||
"install_devices_windows_list_2": "Accesați categoria \"Rețea și Internet\", apoi la \"Centrul de Rețea și Partajare\".",
|
"install_devices_windows_list_2": "Accesați categoria \"Rețea și Internet\", apoi la \"Centrul de Rețea și Partajare\".",
|
||||||
"install_devices_windows_list_3": "În partea stângă a ecranului găsiți \"Schimbare setări adaptor\" și clicați pe el.",
|
"install_devices_windows_list_3": "În partea stângă a ecranului găsiți \"Schimbare setări adaptor\" și clicați pe el.",
|
||||||
"install_devices_windows_list_4": "Selectați conexiunea activă, faceți clic dreapta pe ea și alegeți \"Proprietăți\".",
|
"install_devices_windows_list_4": "Selectați conexiunea activă, faceți clic dreapta pe ea și alegeți \"Proprietăți\".",
|
||||||
"install_devices_windows_list_5": "Găsiți Internet Protocol Versiunea 4 (TCP/IP) din listă, selectați-l și apoi clicați din nou pe Proprietăți.",
|
"install_devices_windows_list_5": "Găsiți Internet Protocol Versiunea 4 (TCP/IPv4) din listă, selectați-l și apoi clicați din nou pe Proprietăți.",
|
||||||
"install_devices_windows_list_6": "Alegeți Utilizați următoarele adrese de server DNS și introduceți adresele de server AdGuard Home.",
|
"install_devices_windows_list_6": "Alegeți Utilizați următoarele adrese de server DNS și introduceți adresele de server AdGuard Home.",
|
||||||
"install_devices_macos_list_1": "Clicați pe icoana Apple și accesați Preferințele Sistemului.",
|
"install_devices_macos_list_1": "Clicați pe icoana Apple și accesați Preferințele Sistemului.",
|
||||||
"install_devices_macos_list_2": "Clicați pe Network.",
|
"install_devices_macos_list_2": "Clicați pe Network.",
|
||||||
|
|||||||
@@ -208,7 +208,7 @@
|
|||||||
"example_upstream_sdns": "вы можете использовать <0>DNS Stamps</0> для <1>DNSCrypt</1> или <2>DNS-over-HTTPS</2> резолверов",
|
"example_upstream_sdns": "вы можете использовать <0>DNS Stamps</0> для <1>DNSCrypt</1> или <2>DNS-over-HTTPS</2> резолверов",
|
||||||
"example_upstream_tcp": "обычный DNS (поверх TCP)",
|
"example_upstream_tcp": "обычный DNS (поверх TCP)",
|
||||||
"all_lists_up_to_date_toast": "Все списки уже обновлены",
|
"all_lists_up_to_date_toast": "Все списки уже обновлены",
|
||||||
"updated_upstream_dns_toast": "Upstream DNS-серверы обновлены",
|
"updated_upstream_dns_toast": "DNS-серверы успешно обновлены",
|
||||||
"dns_test_ok_toast": "Указанные серверы DNS работают корректно",
|
"dns_test_ok_toast": "Указанные серверы DNS работают корректно",
|
||||||
"dns_test_not_ok_toast": "Сервер «{{key}}»: невозможно использовать, проверьте правильность написания",
|
"dns_test_not_ok_toast": "Сервер «{{key}}»: невозможно использовать, проверьте правильность написания",
|
||||||
"unblock": "Разблокировать",
|
"unblock": "Разблокировать",
|
||||||
@@ -235,7 +235,7 @@
|
|||||||
"loading_table_status": "Загрузка…",
|
"loading_table_status": "Загрузка…",
|
||||||
"page_table_footer_text": "Страница",
|
"page_table_footer_text": "Страница",
|
||||||
"rows_table_footer_text": "строк",
|
"rows_table_footer_text": "строк",
|
||||||
"updated_custom_filtering_toast": "Внесены изменения в пользовательские правила",
|
"updated_custom_filtering_toast": "Пользовательские правила успешно сохранены",
|
||||||
"rule_removed_from_custom_filtering_toast": "Пользовательское правило удалено: {{rule}}",
|
"rule_removed_from_custom_filtering_toast": "Пользовательское правило удалено: {{rule}}",
|
||||||
"rule_added_to_custom_filtering_toast": "Пользовательское правило добавлено: {{rule}}",
|
"rule_added_to_custom_filtering_toast": "Пользовательское правило добавлено: {{rule}}",
|
||||||
"query_log_response_status": "Статус: {{value}}",
|
"query_log_response_status": "Статус: {{value}}",
|
||||||
@@ -277,7 +277,7 @@
|
|||||||
"form_enter_rate_limit": "Введите rate limit",
|
"form_enter_rate_limit": "Введите rate limit",
|
||||||
"rate_limit": "Rate limit",
|
"rate_limit": "Rate limit",
|
||||||
"edns_enable": "Включить отправку EDNS Client Subnet",
|
"edns_enable": "Включить отправку EDNS Client Subnet",
|
||||||
"edns_cs_desc": "Отправлять подсети клиентов на DNS-сервера.",
|
"edns_cs_desc": "Отправлять подсети клиентов на DNS-серверы.",
|
||||||
"rate_limit_desc": "Ограничение на количество запросов в секунду для каждого клиента (0 — неограниченно).",
|
"rate_limit_desc": "Ограничение на количество запросов в секунду для каждого клиента (0 — неограниченно).",
|
||||||
"blocking_ipv4_desc": "IP-адрес, возвращаемый при блокировке A-запроса",
|
"blocking_ipv4_desc": "IP-адрес, возвращаемый при блокировке A-запроса",
|
||||||
"blocking_ipv6_desc": "IP-адрес, возвращаемый при блокировке AAAA-запроса",
|
"blocking_ipv6_desc": "IP-адрес, возвращаемый при блокировке AAAA-запроса",
|
||||||
@@ -306,7 +306,7 @@
|
|||||||
"install_settings_dns_desc": "Вам будет нужно настроить свои устройства или роутер на использование DNS-сервера на одном из следующих адресов:",
|
"install_settings_dns_desc": "Вам будет нужно настроить свои устройства или роутер на использование DNS-сервера на одном из следующих адресов:",
|
||||||
"install_settings_all_interfaces": "Все интерфейсы",
|
"install_settings_all_interfaces": "Все интерфейсы",
|
||||||
"install_auth_title": "Авторизация",
|
"install_auth_title": "Авторизация",
|
||||||
"install_auth_desc": "Настоятельно рекомендуется настроить аутентификацию паролем для веб-интерфейса AdGuard Home. Даже если он доступен только в вашей локальной сети, важно защитить его от неограниченного доступа.",
|
"install_auth_desc": "Должна быть настроена аутентификация паролем для веб-интерфейса AdGuard Home. Даже если он доступен только в вашей локальной сети, важно защитить его от неограниченного доступа.",
|
||||||
"install_auth_username": "Имя пользователя",
|
"install_auth_username": "Имя пользователя",
|
||||||
"install_auth_password": "Пароль",
|
"install_auth_password": "Пароль",
|
||||||
"install_auth_confirm": "Подтвердить пароль",
|
"install_auth_confirm": "Подтвердить пароль",
|
||||||
@@ -499,10 +499,11 @@
|
|||||||
"statistics_configuration": "Конфигурация статистики",
|
"statistics_configuration": "Конфигурация статистики",
|
||||||
"statistics_retention": "Сохранение статистики",
|
"statistics_retention": "Сохранение статистики",
|
||||||
"statistics_retention_desc": "Если вы уменьшите значение интервала, некоторые данные могут быть утеряны",
|
"statistics_retention_desc": "Если вы уменьшите значение интервала, некоторые данные могут быть утеряны",
|
||||||
"statistics_clear": " Очистить статистику",
|
"statistics_clear": "Очистить статистику",
|
||||||
"statistics_clear_confirm": "Вы уверены, что хотите очистить статистику?",
|
"statistics_clear_confirm": "Вы уверены, что хотите очистить статистику?",
|
||||||
"statistics_retention_confirm": "Вы уверены, что хотите изменить срок хранения статистики? При сокращении интервала данные могут быть утеряны",
|
"statistics_retention_confirm": "Вы уверены, что хотите изменить срок хранения статистики? При сокращении интервала данные могут быть утеряны",
|
||||||
"statistics_cleared": "Статистика успешно очищена",
|
"statistics_cleared": "Статистика успешно очищена",
|
||||||
|
"statistics_enable": "Включить статистику",
|
||||||
"interval_hours": "{{count}} час",
|
"interval_hours": "{{count}} час",
|
||||||
"interval_hours_plural": "{{count}} часов",
|
"interval_hours_plural": "{{count}} часов",
|
||||||
"filters_configuration": "Настройка фильтров",
|
"filters_configuration": "Настройка фильтров",
|
||||||
@@ -597,7 +598,7 @@
|
|||||||
"cache_ttl_min_override_desc": "Расширить короткие TTL-значения (в секундах), полученные с upstream-сервера при кешировании DNS-ответов",
|
"cache_ttl_min_override_desc": "Расширить короткие TTL-значения (в секундах), полученные с upstream-сервера при кешировании DNS-ответов",
|
||||||
"cache_ttl_max_override_desc": "Установить максимальное TTL-значение (в секундах) для записей в DNS-кэше",
|
"cache_ttl_max_override_desc": "Установить максимальное TTL-значение (в секундах) для записей в DNS-кэше",
|
||||||
"ttl_cache_validation": "Минимальное значение TTL-кеша должно быть меньше или равно максимальному значению",
|
"ttl_cache_validation": "Минимальное значение TTL-кеша должно быть меньше или равно максимальному значению",
|
||||||
"cache_optimistic": "Оптимистичный",
|
"cache_optimistic": "Оптимистическое кеширование",
|
||||||
"cache_optimistic_desc": "AdGuard Home будет отвечать из кеша, даже если ответы в нём неактуальны, и попытается обновить их.",
|
"cache_optimistic_desc": "AdGuard Home будет отвечать из кеша, даже если ответы в нём неактуальны, и попытается обновить их.",
|
||||||
"filter_category_general": "Общие",
|
"filter_category_general": "Общие",
|
||||||
"filter_category_security": "Безопасность",
|
"filter_category_security": "Безопасность",
|
||||||
@@ -612,6 +613,8 @@
|
|||||||
"click_to_view_queries": "Нажмите, чтобы просмотреть запросы",
|
"click_to_view_queries": "Нажмите, чтобы просмотреть запросы",
|
||||||
"port_53_faq_link": "Порт 53 часто занят службами «DNSStubListener» или «systemd-resolved». Ознакомьтесь с <0>инструкцией</0> о том, как это разрешить.",
|
"port_53_faq_link": "Порт 53 часто занят службами «DNSStubListener» или «systemd-resolved». Ознакомьтесь с <0>инструкцией</0> о том, как это разрешить.",
|
||||||
"adg_will_drop_dns_queries": "AdGuard Home AdGuard Home сбросит все DNS-запросы от этого клиента.",
|
"adg_will_drop_dns_queries": "AdGuard Home AdGuard Home сбросит все DNS-запросы от этого клиента.",
|
||||||
"client_not_in_allowed_clients": "Клиент не разрешён, так как его нет в списке «Разрешённых клиентов».",
|
"filter_allowlist": "ВНИМАНИЕ: Это действие также исключит правило «{{disallowed_rule}}» из списка разрешённых клиентов.",
|
||||||
"experimental": "Экспериментальный"
|
"last_rule_in_allowlist": "Нельзя заблокировать этого клиента, так как исключение правила «{{disallowed_rule}}» ОТКЛЮЧИТ режим белого списка.",
|
||||||
|
"experimental": "Экспериментальный",
|
||||||
|
"use_saved_key": "Использовать сохранённый ранее ключ"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -16,8 +16,8 @@
|
|||||||
"dhcp_enable": "ග.ධා.වි.කෙ. සේවාදායකය සබල කරන්න",
|
"dhcp_enable": "ග.ධා.වි.කෙ. සේවාදායකය සබල කරන්න",
|
||||||
"dhcp_disable": "ග.ධා.වි.කෙ. සේවාදායකය අබල කරන්න",
|
"dhcp_disable": "ග.ධා.වි.කෙ. සේවාදායකය අබල කරන්න",
|
||||||
"dhcp_config_saved": "ග.ධා.වි.කෙ. වින්යාසය සාර්ථකව සුරකින ලදි",
|
"dhcp_config_saved": "ග.ධා.වි.කෙ. වින්යාසය සාර්ථකව සුරකින ලදි",
|
||||||
"dhcp_ipv4_settings": "ග.ධා.වි.කෙ. අයිපීවී 4 සැකසුම්",
|
"dhcp_ipv4_settings": "ග.ධා.වි.කෙ. අ.ජා.කෙ. 4 සැකසුම්",
|
||||||
"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_ip6_format": "වලංගු නොවන IPv6 ආකෘතියකි",
|
"form_error_ip6_format": "වලංගු නොවන IPv6 ආකෘතියකි",
|
||||||
@@ -44,7 +44,7 @@
|
|||||||
"country": "රට",
|
"country": "රට",
|
||||||
"city": "නගරය",
|
"city": "නගරය",
|
||||||
"delete_confirm": "\"{{key}}\" මකා දැමීමට අවශ්ය බව ඔබට විශ්වාසද?",
|
"delete_confirm": "\"{{key}}\" මකා දැමීමට අවශ්ය බව ඔබට විශ්වාසද?",
|
||||||
"form_enter_hostname": "ධාරක නාමය ඇතුළත් කරන්න",
|
"form_enter_hostname": "ධාරක නාමය ඇතුල් කරන්න",
|
||||||
"error_details": "දෝෂ විස්තර",
|
"error_details": "දෝෂ විස්තර",
|
||||||
"response_details": "ප්රතිචාරයෙහි විස්තර",
|
"response_details": "ප්රතිචාරයෙහි විස්තර",
|
||||||
"request_details": "ඉල්ලීමෙහි විස්තර",
|
"request_details": "ඉල්ලීමෙහි විස්තර",
|
||||||
@@ -108,14 +108,14 @@
|
|||||||
"general_settings": "පොදු සැකසුම්",
|
"general_settings": "පොදු සැකසුම්",
|
||||||
"dns_settings": "ව.නා.ප. සැකසුම්",
|
"dns_settings": "ව.නා.ප. සැකසුම්",
|
||||||
"dns_blocklists": "ව.නා.ප. අවහිර කිරීමේ ලැයිස්තු",
|
"dns_blocklists": "ව.නා.ප. අවහිර කිරීමේ ලැයිස්තු",
|
||||||
"dns_allowlists": "ව.නා.ප. අවසර දීමේ ලැයිස්තු",
|
"dns_allowlists": "ව.නා.ප. ඉඩ දීමේ ලැයිස්තු",
|
||||||
"dns_blocklists_desc": "ඇඩ්ගාර්ඩ් හෝම් විසින් අවහිර කිරීමේ ලැයිස්තු වලට ගැලපෙන වසම් අවහිර කරනු ඇත.",
|
"dns_blocklists_desc": "ඇඩ්ගාර්ඩ් හෝම් විසින් අවහිර කිරීමේ ලැයිස්තු වලට ගැලපෙන වසම් අවහිර කරනු ඇත.",
|
||||||
"dns_allowlists_desc": "අවසර දීමේ ව.නා.ප. ලැයිස්තුවල වසම් කිසියම් අවහිර කිරීමේ ලැයිස්තුවක අඩංගු වුවද එය නොසලකා හැර අවසර දෙනු ලැබේ.",
|
"dns_allowlists_desc": "ඉඩ දීමේ ව.නා.ප. ලැයිස්තුවල වසම් කිසියම් අවහිර කිරීමේ ලැයිස්තුවක අඩංගු වුවද එය නොසලකා හැර ඉඩ දෙනු ලැබේ.",
|
||||||
"custom_filtering_rules": "අභිරුචි පෙරීමේ නීති",
|
"custom_filtering_rules": "අභිරුචි පෙරීමේ නීති",
|
||||||
"encryption_settings": "සංකේතාංකන සැකසුම්",
|
"encryption_settings": "සංකේතාංකන සැකසුම්",
|
||||||
"dhcp_settings": "ග.ධා.වි.කෙ. සැකසුම්",
|
"dhcp_settings": "ග.ධා.වි.කෙ. සැකසුම්",
|
||||||
"upstream_dns": "Upstream ව.නා.ප. සේවාදායකයන්",
|
"upstream_dns": "Upstream ව.නා.ප. සේවාදායකයන්",
|
||||||
"upstream_dns_help": "පේළියකට එක් සේවාදායක ලිපිනය බැගින් ඇතුළත් කරන්න. upstream ව.නා.ප. (DNS) \n සේවාදායකයන් වින්යාසගත කිරීම ගැන <a>තව දැනගන්න</a>.",
|
"upstream_dns_help": "පේළියකට එක් සේවාදායක ලිපිනය බැගින් ඇතුල් කරන්න. upstream ව.නා.ප. (DNS) \n සේවාදායකයන් වින්යාසගත කිරීම ගැන <a>තව දැනගන්න</a>.",
|
||||||
"upstream_dns_configured_in_file": "{{path}} හි වින්යාසගත කර ඇත",
|
"upstream_dns_configured_in_file": "{{path}} හි වින්යාසගත කර ඇත",
|
||||||
"apply_btn": "යොදන්න",
|
"apply_btn": "යොදන්න",
|
||||||
"disabled_filtering_toast": "පෙරීම අබල කර ඇත",
|
"disabled_filtering_toast": "පෙරීම අබල කර ඇත",
|
||||||
@@ -138,25 +138,25 @@
|
|||||||
"elapsed": "ගත වූූූ කාලය",
|
"elapsed": "ගත වූූූ කාලය",
|
||||||
"filters_and_hosts_hint": "ඇඩ්ගාර්ඩ් හෝම් මූලික දැන්වීම් වාරණ නීති සහ ධාරක ගොනු පද ගැලපුම් තේරුම් ගනී.",
|
"filters_and_hosts_hint": "ඇඩ්ගාර්ඩ් හෝම් මූලික දැන්වීම් වාරණ නීති සහ ධාරක ගොනු පද ගැලපුම් තේරුම් ගනී.",
|
||||||
"no_blocklist_added": "අවහිර කිරීමේ ලැයිස්තු එකතු කර නැත",
|
"no_blocklist_added": "අවහිර කිරීමේ ලැයිස්තු එකතු කර නැත",
|
||||||
"no_whitelist_added": "අවසර දීමේ ලැයිස්තු එකතු කර නැත",
|
"no_whitelist_added": "ඉඩ දීමේ ලැයිස්තු එකතු කර නැත",
|
||||||
"add_blocklist": "අවහිර කිරීමේ ලැයිස්තුවක් එකතු කරන්න",
|
"add_blocklist": "අවහිර කිරීමේ ලැයිස්තුවක් එකතු කරන්න",
|
||||||
"add_allowlist": "අවසර දීමේ ලැයිස්තුවක් එකතු කරන්න",
|
"add_allowlist": "ඉඩ දීමේ ලැයිස්තුවක් එකතු කරන්න",
|
||||||
"cancel_btn": "අහෝසි කරන්න",
|
"cancel_btn": "අහෝසි කරන්න",
|
||||||
"enter_name_hint": "නම ඇතුළත් කරන්න",
|
"enter_name_hint": "නම ඇතුල් කරන්න",
|
||||||
"enter_url_or_path_hint": "ලැයිස්තුවක ඒ.ස.නි.(URL) හෝ ස්ථීර මාර්ගයක් ඇතුළත් කරන්න",
|
"enter_url_or_path_hint": "ලැයිස්තුවක ඒ.ස.නි.(URL) හෝ ස්ථීර මාර්ගයක් ඇතුල් කරන්න",
|
||||||
"check_updates_btn": "යාවත්කාල පරීක්ෂා කරන්න",
|
"check_updates_btn": "යාවත්කාල පරීක්ෂා කරන්න",
|
||||||
"new_blocklist": "නව අවහිර කිරීමේ ලැයිස්තුව",
|
"new_blocklist": "නව අවහිර කිරීමේ ලැයිස්තුව",
|
||||||
"new_allowlist": "නව අවසර දීමේ ලැයිස්තුව",
|
"new_allowlist": "නව ඉඩ දීමේ ලැයිස්තුව",
|
||||||
"edit_blocklist": "අවහිර කිරීමේ ලැයිස්තුව සංස්කරණය කරන්න",
|
"edit_blocklist": "අවහිර කිරීමේ ලැයිස්තුව සංස්කරණය කරන්න",
|
||||||
"edit_allowlist": "අවසර දීමේ ලැයිස්තුව සංස්කරණය කරන්න",
|
"edit_allowlist": "ඉඩ දීමේ ලැයිස්තුව සංස්කරණය කරන්න",
|
||||||
"choose_blocklist": "අවහිර කීරීමේ ලැයිස්තුවක් තෝරන්න",
|
"choose_blocklist": "අවහිර කීරීමේ ලැයිස්තුවක් තෝරන්න",
|
||||||
"choose_allowlist": "අනවහිර කීරීමේ ලැයිස්තුවක් තෝරන්න",
|
"choose_allowlist": "ඉඩ දීමේ ලැයිස්තු තෝරන්න",
|
||||||
"enter_valid_blocklist": "අවහිර කිරීමේ ලැයිස්තුවට වලංගු ඒ.ස.නි.(URL) ලිපිනයක් ඇතුළත් කරන්න.",
|
"enter_valid_blocklist": "අවහිර කිරීමේ ලැයිස්තුවට වලංගු ඒ.ස.නි.(URL) ලිපිනයක් ඇතුල් කරන්න.",
|
||||||
"enter_valid_allowlist": "අවසර දීමේ ලැයිස්තුවට වලංගු ඒ.ස.නි.(URL) ලිපිනයක් ඇතුළත් කරන්න.",
|
"enter_valid_allowlist": "ඉඩ දීමේ ලැයිස්තුවට වලංගු ඒ.ස.නි.(URL) ලිපිනයක් ඇතුල් කරන්න.",
|
||||||
"form_error_url_format": "වලංගු නොවන ඒ.ස.නි.(URL) ආකෘතියකි",
|
"form_error_url_format": "වලංගු නොවන ඒ.ස.නි.(URL) ආකෘතියකි",
|
||||||
"form_error_url_or_path_format": "ලැයිස්තුවක වලංගු නොවන ඒ.ස.නි.(URL) හෝ ස්ථීර මාර්ගයකි",
|
"form_error_url_or_path_format": "ලැයිස්තුවක වලංගු නොවන ඒ.ස.නි.(URL) හෝ ස්ථීර මාර්ගයකි",
|
||||||
"custom_filter_rules": "අභිරුචි පෙරීමේ නීති",
|
"custom_filter_rules": "අභිරුචි පෙරීමේ නීති",
|
||||||
"custom_filter_rules_hint": "පේළියකට එක් නීතියක් බැගින් ඇතුළත් කරන්න. ඔබට දැන්වීම් අවහිර කිරීමේ නීති හෝ ධාරක ගොනු පද ගැලපුම් භාවිතා කළ හැකිය.",
|
"custom_filter_rules_hint": "පේළියකට එක් නීතියක් බැගින් ඇතුල් කරන්න. ඔබට දැන්වීම් අවහිර කිරීමේ නීති හෝ ධාරක ගොනු පද ගැලපුම් භාවිතා කළ හැකිය.",
|
||||||
"examples_title": "උදාහරණ",
|
"examples_title": "උදාහරණ",
|
||||||
"example_meaning_filter_block": "example.org වසමට සහ එහි සියලුම උප වසම් වලට පිවිසීම අවහිර කරයි",
|
"example_meaning_filter_block": "example.org වසමට සහ එහි සියලුම උප වසම් වලට පිවිසීම අවහිර කරයි",
|
||||||
"example_meaning_filter_whitelist": "example.org වසමට සහ එහි සියලුම උප වසම් වලට ප්රවේශය අවහිර නොකරයි",
|
"example_meaning_filter_whitelist": "example.org වසමට සහ එහි සියලුම උප වසම් වලට ප්රවේශය අවහිර නොකරයි",
|
||||||
@@ -175,8 +175,8 @@
|
|||||||
"dns_test_not_ok_toast": "සේවාදායක \"{{key}}\": භාවිතා කළ නොහැකි විය, කරුණාකර ඔබ එය නිවැරදිව ලියා ඇත්දැයි පරීක්ෂා කරන්න",
|
"dns_test_not_ok_toast": "සේවාදායක \"{{key}}\": භාවිතා කළ නොහැකි විය, කරුණාකර ඔබ එය නිවැරදිව ලියා ඇත්දැයි පරීක්ෂා කරන්න",
|
||||||
"unblock": "අනවහිර",
|
"unblock": "අනවහිර",
|
||||||
"block": "අවහිර",
|
"block": "අවහිර",
|
||||||
"disallow_this_client": "මෙම අනුග්රාහකයට අවසර නොදෙන්න",
|
"disallow_this_client": "මෙම අනුග්රාහකයට නොඉඩ දෙන්න",
|
||||||
"allow_this_client": "මෙම අනුග්රාහකයට අවසර දෙන්න",
|
"allow_this_client": "මෙම අනුග්රාහකයට ඉඩ දෙන්න",
|
||||||
"block_for_this_client_only": "මෙම අනුග්රාහකයට පමණක් අවහිර කරන්න",
|
"block_for_this_client_only": "මෙම අනුග්රාහකයට පමණක් අවහිර කරන්න",
|
||||||
"unblock_for_this_client_only": "මෙම අනුග්රාහකයට පමණක් අනවහිර කරන්න",
|
"unblock_for_this_client_only": "මෙම අනුග්රාහකයට පමණක් අනවහිර කරන්න",
|
||||||
"time_table_header": "වේලාව",
|
"time_table_header": "වේලාව",
|
||||||
@@ -221,17 +221,17 @@
|
|||||||
"refused": "REFUSED",
|
"refused": "REFUSED",
|
||||||
"null_ip": "අභිශූන්යය අ.ජා. කෙ.",
|
"null_ip": "අභිශූන්යය අ.ජා. කෙ.",
|
||||||
"custom_ip": "අභිරුචි අ.ජා. කෙ.",
|
"custom_ip": "අභිරුචි අ.ජා. කෙ.",
|
||||||
"blocking_ipv4": "අයි.පී.වී.4 අවහිර කිරීම\n",
|
"blocking_ipv4": "අ.ජා.කෙ.4 අවහිර කිරීම",
|
||||||
"blocking_ipv6": "අයි.පී.වී.6 අවහිර කිරීම",
|
"blocking_ipv6": "අ.ජා.කෙ.6 අවහිර කිරීම",
|
||||||
"client_id": "අනුග්රාහකයේ හැඳුනුම",
|
"client_id": "අනුග්රාහකයේ හැඳුනුම",
|
||||||
"client_id_placeholder": "අනුග්රාහකයේ හැඳුනුම යොදන්න",
|
"client_id_placeholder": "අනුග්රාහකයේ හැඳුනුම යොදන්න",
|
||||||
"download_mobileconfig": "වින්යාසගත ගොනුව බාගන්න",
|
"download_mobileconfig": "වින්යාසගත ගොනුව බාගන්න",
|
||||||
"plain_dns": "සරල ව.නා.ප.",
|
"plain_dns": "සරල ව.නා.ප.",
|
||||||
"form_enter_rate_limit": "අනුපාත සීමාව ඇතුළත් කරන්න",
|
"form_enter_rate_limit": "අනුපාත සීමාව ඇතුල් කරන්න",
|
||||||
"rate_limit": "අනුපාත සීමාව",
|
"rate_limit": "අනුපාත සීමාව",
|
||||||
"edns_enable": "EDNS අනුග්රාහක අනුජාලය සබල කරන්න",
|
"rate_limit_desc": "එක් අනුග්රාහකයකට ඉඩ දී ඇති තත්පරයට ඉල්ලීම් ගණන. එය 0 ලෙස සැකසීම යනුවෙන් අදහස් කරන්නේ සීමාවක් නැති බවයි.",
|
||||||
"blocking_ipv4_desc": "අවහිර කළ A ඉල්ලීමක් සඳහා ආපසු එවිය යුතු අ.ජා. කෙ. (IP) ලිපිනය",
|
"blocking_ipv4_desc": "අවහිර කළ A ඉල්ලීමක් සඳහා ආපසු එවිය යුතු අ.ජා.කෙ. (IP) ලිපිනය",
|
||||||
"blocking_ipv6_desc": "අවහිර කළ AAAA ඉල්ලීමක් සඳහා ආපසු එවිය යුතු අ.ජා. කෙ. (IP) ලිපිනය",
|
"blocking_ipv6_desc": "අවහිර කළ AAAA ඉල්ලීමක් සඳහා ආපසු එවිය යුතු අ.ජා.කෙ. (IP) ලිපිනය",
|
||||||
"blocking_mode_default": "පොදු: දැන්වීම් අවහිර කරන ආකාරයේ නීතියක් මගින් අවහිර කළ විට REFUSED සමඟ ප්රතිචාර දක්වයි; /etc/host-style ආකාරයේ නීතියක් මගින් අවහිර කළ විට නීතියේ දක්වා ඇති අ.ජා. කෙ. ලිපිනය සමඟ ප්රතිචාර දක්වයි",
|
"blocking_mode_default": "පොදු: දැන්වීම් අවහිර කරන ආකාරයේ නීතියක් මගින් අවහිර කළ විට REFUSED සමඟ ප්රතිචාර දක්වයි; /etc/host-style ආකාරයේ නීතියක් මගින් අවහිර කළ විට නීතියේ දක්වා ඇති අ.ජා. කෙ. ලිපිනය සමඟ ප්රතිචාර දක්වයි",
|
||||||
"blocking_mode_refused": "REFUSED: REFUSED කේතය සමඟ ප්රතිචාර දක්වයි",
|
"blocking_mode_refused": "REFUSED: REFUSED කේතය සමඟ ප්රතිචාර දක්වයි",
|
||||||
"blocking_mode_nxdomain": "නොපවතින වසම (NXDOMAIN): NXDOMAIN කේතය සමඟ ප්රතිචාර දක්වයි",
|
"blocking_mode_nxdomain": "නොපවතින වසම (NXDOMAIN): NXDOMAIN කේතය සමඟ ප්රතිචාර දක්වයි",
|
||||||
@@ -250,9 +250,9 @@
|
|||||||
"install_welcome_desc": "ඇඩ්ගාර්ඩ් හෝම් යනු ජාලය පුරා ඇති දැන්වීම් සහ ලුහුබැඳීම අවහිර කරන ව.නා.ප. සේවාදායකි. ඔබගේ මුළු ජාලය සහ සියලුම උපාංග පාලනය කිරීමට ඉඩ සලසා දීම එහි පරමාර්ථය යි, එයට අනුග්රාහක පාර්ශවීය වැඩසටහනක් භාවිතා කිරීම අවශ්ය නොවේ.",
|
"install_welcome_desc": "ඇඩ්ගාර්ඩ් හෝම් යනු ජාලය පුරා ඇති දැන්වීම් සහ ලුහුබැඳීම අවහිර කරන ව.නා.ප. සේවාදායකි. ඔබගේ මුළු ජාලය සහ සියලුම උපාංග පාලනය කිරීමට ඉඩ සලසා දීම එහි පරමාර්ථය යි, එයට අනුග්රාහක පාර්ශවීය වැඩසටහනක් භාවිතා කිරීම අවශ්ය නොවේ.",
|
||||||
"install_settings_title": "පරිපාලක වියමන අතුරු මුහුණත",
|
"install_settings_title": "පරිපාලක වියමන අතුරු මුහුණත",
|
||||||
"install_settings_listen": "සවන් දෙන අතුරු මුහුණත",
|
"install_settings_listen": "සවන් දෙන අතුරු මුහුණත",
|
||||||
"install_settings_port": "කවුළුව",
|
"install_settings_port": "කෙවෙනිය",
|
||||||
"install_settings_interface_link": "ඔබගේ ඇඩ්ගාර්ඩ් හෝම් පරිපාලක වියමන අතුරු මුහුණත පහත ලිපිනයන්ගෙන් ප්රවේශ විය හැකිය:",
|
"install_settings_interface_link": "ඔබගේ ඇඩ්ගාර්ඩ් හෝම් පරිපාලක වියමන අතුරු මුහුණත පහත ලිපිනයන්ගෙන් ප්රවේශ විය හැකිය:",
|
||||||
"form_error_port": "වලංගු කවුළුවක අගයක් යොදන්න",
|
"form_error_port": "වලංගු කෙවෙනියක අගයක් යොදන්න",
|
||||||
"install_settings_dns": "ව.නා.ප. සේවාදායකය",
|
"install_settings_dns": "ව.නා.ප. සේවාදායකය",
|
||||||
"install_settings_dns_desc": "පහත ලිපිනයන්හි ව.නා.ප. සේවාදායකය භාවිතා කිරීම සඳහා ඔබගේ උපාංග හෝ මාර්ගකාරකය වින්යාසගත කිරීමට අවශ්ය වනු ඇත:",
|
"install_settings_dns_desc": "පහත ලිපිනයන්හි ව.නා.ප. සේවාදායකය භාවිතා කිරීම සඳහා ඔබගේ උපාංග හෝ මාර්ගකාරකය වින්යාසගත කිරීමට අවශ්ය වනු ඇත:",
|
||||||
"install_settings_all_interfaces": "සියලුම අතුරුමුහුණත්",
|
"install_settings_all_interfaces": "සියලුම අතුරුමුහුණත්",
|
||||||
@@ -261,8 +261,8 @@
|
|||||||
"install_auth_username": "පරිශීලක නාමය",
|
"install_auth_username": "පරිශීලක නාමය",
|
||||||
"install_auth_password": "මුරපදය",
|
"install_auth_password": "මුරපදය",
|
||||||
"install_auth_confirm": "මුරපදය තහවුරු කරන්න",
|
"install_auth_confirm": "මුරපදය තහවුරු කරන්න",
|
||||||
"install_auth_username_enter": "පරිශීලක නාමය ඇතුළත් කරන්න",
|
"install_auth_username_enter": "පරිශීලක නාමය ඇතුල් කරන්න",
|
||||||
"install_auth_password_enter": "මුරපදය ඇතුළත් කරන්න",
|
"install_auth_password_enter": "මුරපදය ඇතුල් කරන්න",
|
||||||
"install_step": "පියවර",
|
"install_step": "පියවර",
|
||||||
"install_devices_title": "ඔබගේ උපාංග වින්යාසගත කරන්න",
|
"install_devices_title": "ඔබගේ උපාංග වින්යාසගත කරන්න",
|
||||||
"install_devices_desc": "ඇඩ්ගාර්ඩ් හෝම් භාවිතා කිරීම ආරම්භයට, ඔබගේ උපාංග එය පරිශ්රීලනයට වින්යාසගත කිරීම අවශ්ය වේ.",
|
"install_devices_desc": "ඇඩ්ගාර්ඩ් හෝම් භාවිතා කිරීම ආරම්භයට, ඔබගේ උපාංග එය පරිශ්රීලනයට වින්යාසගත කිරීම අවශ්ය වේ.",
|
||||||
@@ -272,7 +272,7 @@
|
|||||||
"install_devices_router_desc": "මෙම පිහිටුම ඔබගේ නිවසේ මාර්ගකාරකයට සම්බන්ධ සියලුම උපාංග ස්වයංක්රීයව ආවරණය කරන අතර ඔබට ඒ සෑම එකක්ම අතින් වින්යාසගත කිරීමට අවශ්ය නොවේ.",
|
"install_devices_router_desc": "මෙම පිහිටුම ඔබගේ නිවසේ මාර්ගකාරකයට සම්බන්ධ සියලුම උපාංග ස්වයංක්රීයව ආවරණය කරන අතර ඔබට ඒ සෑම එකක්ම අතින් වින්යාසගත කිරීමට අවශ්ය නොවේ.",
|
||||||
"install_devices_address": "ඇඩ්ගාර්ඩ් හෝම් ව.නා.ප. සේවාදායකය පහත ලිපිනයන්ට සවන් දෙමින් පවතී",
|
"install_devices_address": "ඇඩ්ගාර්ඩ් හෝම් ව.නා.ප. සේවාදායකය පහත ලිපිනයන්ට සවන් දෙමින් පවතී",
|
||||||
"install_devices_router_list_2": "ග.ධා.වි.කෙ. (DHCP)/ ව.නා.ප. (DNS) සැකසුම් සොයා ගන්න. ඉලක්කම් කට්ටල දෙකකට හෝ තුනකට ඉඩ දෙන ක්ෂේත්රයක් අසල ඇති ව.නා.ප. අක්ෂර සොයන්න, සෑම එකක්ම ඉලක්කම් එකේ සිට තුන දක්වා කාණ්ඩ හතරකට බෙදා ඇත.",
|
"install_devices_router_list_2": "ග.ධා.වි.කෙ. (DHCP)/ ව.නා.ප. (DNS) සැකසුම් සොයා ගන්න. ඉලක්කම් කට්ටල දෙකකට හෝ තුනකට ඉඩ දෙන ක්ෂේත්රයක් අසල ඇති ව.නා.ප. අක්ෂර සොයන්න, සෑම එකක්ම ඉලක්කම් එකේ සිට තුන දක්වා කාණ්ඩ හතරකට බෙදා ඇත.",
|
||||||
"install_devices_router_list_3": "ඔබගේ ඇඩ්ගාර්ඩ් හෝම් සේවාදායක ලිපින එහි ඇතුළත් කරන්න.",
|
"install_devices_router_list_3": "ඔබගේ ඇඩ්ගාර්ඩ් හෝම් සේවාදායක ලිපින එහි ඇතුල් කරන්න.",
|
||||||
"install_devices_router_list_4": "ඔබට සමහර වර්ගයේ මාර්ගකාරකය වල අභිරුචි ව.නා.ප. සේවාදායකයක් සැකසිය නොහැක. මෙම අවස්ථාවේදී ඇඩ්ගාර්ඩ් හෝම් <0>ග.ධා.වි.කෙ. සේවාදායකයක්</0> ලෙස පිහිටුවන්නේ නම් එය උපකාර වනු ඇත. එසේ නොමැතිනම්, ඔබගේ විශේෂිත මාර්ගකාරක මාදිළිය සඳහා වූ ව.නා.ප. සේවාදායකයන් රිසිකරණය කරන්නේ කෙසේද යන්න පිළිබඳ අත්පොත පරීක්ෂා කළ යුතුය.",
|
"install_devices_router_list_4": "ඔබට සමහර වර්ගයේ මාර්ගකාරකය වල අභිරුචි ව.නා.ප. සේවාදායකයක් සැකසිය නොහැක. මෙම අවස්ථාවේදී ඇඩ්ගාර්ඩ් හෝම් <0>ග.ධා.වි.කෙ. සේවාදායකයක්</0> ලෙස පිහිටුවන්නේ නම් එය උපකාර වනු ඇත. එසේ නොමැතිනම්, ඔබගේ විශේෂිත මාර්ගකාරක මාදිළිය සඳහා වූ ව.නා.ප. සේවාදායකයන් රිසිකරණය කරන්නේ කෙසේද යන්න පිළිබඳ අත්පොත පරීක්ෂා කළ යුතුය.",
|
||||||
"install_devices_windows_list_1": "ආරම්භක මෙනුව හෝ වින්ඩෝස් සෙවුම හරහා පාලක පැනලය විවෘත කරන්න.",
|
"install_devices_windows_list_1": "ආරම්භක මෙනුව හෝ වින්ඩෝස් සෙවුම හරහා පාලක පැනලය විවෘත කරන්න.",
|
||||||
"install_devices_windows_list_2": "ජාල සහ අන්තර්ජාල ප්රවර්ගයට ගොස් පසුව ජාල සහ බෙදාගැනීමේ මධ්යස්ථානය වෙත යන්න.",
|
"install_devices_windows_list_2": "ජාල සහ අන්තර්ජාල ප්රවර්ගයට ගොස් පසුව ජාල සහ බෙදාගැනීමේ මධ්යස්ථානය වෙත යන්න.",
|
||||||
@@ -283,7 +283,7 @@
|
|||||||
"install_devices_macos_list_1": "ඇපල් අයිකනය මත ක්ලික් කර පද්ධති මනාපයන් වෙත යන්න.",
|
"install_devices_macos_list_1": "ඇපල් අයිකනය මත ක්ලික් කර පද්ධති මනාපයන් වෙත යන්න.",
|
||||||
"install_devices_macos_list_2": "ජාලය මත ක්ලික් කරන්න.",
|
"install_devices_macos_list_2": "ජාලය මත ක්ලික් කරන්න.",
|
||||||
"install_devices_macos_list_3": "ඔබගේ ලැයිස්තුවේ පළමු සම්බන්ධතාවය තෝරා උසස් මත ක්ලික් කරන්න.",
|
"install_devices_macos_list_3": "ඔබගේ ලැයිස්තුවේ පළමු සම්බන්ධතාවය තෝරා උසස් මත ක්ලික් කරන්න.",
|
||||||
"install_devices_macos_list_4": "ව.නා.ප. (DNS) තීරුව තෝරා ඔබගේ ඇඩ්ගාර්ඩ් හෝම් සේවාදායක ලිපින ඇතුළත් කරන්න.",
|
"install_devices_macos_list_4": "ව.නා.ප. (DNS) තීරුව තෝරා ඔබගේ ඇඩ්ගාර්ඩ් හෝම් සේවාදායක ලිපින ඇතුල් කරන්න.",
|
||||||
"install_devices_android_list_1": "ඇන්ඩ්රොයිඩ් මෙනුවෙහි මුල් තිරයෙන්, සැකසීම් මත තට්ටු කරන්න.",
|
"install_devices_android_list_1": "ඇන්ඩ්රොයිඩ් මෙනුවෙහි මුල් තිරයෙන්, සැකසීම් මත තට්ටු කරන්න.",
|
||||||
"install_devices_android_list_2": "මෙනුවේ වයි-ෆයි මත තට්ටු කරන්න. පවතින සියලුම ජාල ලැයිස්තුගත කර ඇති තිරය පෙන්වනු ඇත (ජංගම සම්බන්ධතාවය සඳහා අභිරුචි ව.නා.ප. සැකසිය නොහැක).",
|
"install_devices_android_list_2": "මෙනුවේ වයි-ෆයි මත තට්ටු කරන්න. පවතින සියලුම ජාල ලැයිස්තුගත කර ඇති තිරය පෙන්වනු ඇත (ජංගම සම්බන්ධතාවය සඳහා අභිරුචි ව.නා.ප. සැකසිය නොහැක).",
|
||||||
"install_devices_android_list_3": "ඔබ සම්බන්ධ වී ඇති ජාලය මත දිගු වේලාවක් ඔබන්න, ඉන්පසුව ජාලය වෙනස් කිරීම මත තට්ටු කරන්න.",
|
"install_devices_android_list_3": "ඔබ සම්බන්ධ වී ඇති ජාලය මත දිගු වේලාවක් ඔබන්න, ඉන්පසුව ජාලය වෙනස් කිරීම මත තට්ටු කරන්න.",
|
||||||
@@ -292,7 +292,7 @@
|
|||||||
"install_devices_ios_list_1": "මුල් තිරයේ සිට, සැකසුම් මත තට්ටු කරන්න.",
|
"install_devices_ios_list_1": "මුල් තිරයේ සිට, සැකසුම් මත තට්ටු කරන්න.",
|
||||||
"install_devices_ios_list_2": "වම්පස මෙනුවෙහි වයි-ෆයි තෝරන්න (ජංගම දුරකථන සඳහා ව.නා.ප. වින්යාසගත කිරීමට නොහැකිය).",
|
"install_devices_ios_list_2": "වම්පස මෙනුවෙහි වයි-ෆයි තෝරන්න (ජංගම දුරකථන සඳහා ව.නා.ප. වින්යාසගත කිරීමට නොහැකිය).",
|
||||||
"install_devices_ios_list_3": "දැනට ක්රියාකාරී ජාලයයහෙි නම මත තට්ටු කරන්න.",
|
"install_devices_ios_list_3": "දැනට ක්රියාකාරී ජාලයයහෙි නම මත තට්ටු කරන්න.",
|
||||||
"install_devices_ios_list_4": "ව.නා.ප. (DNS) ක්ෂේත්රය තුළ ඔබගේ ඇඩ්ගාර්ඩ් හෝම් සේවාදායක ලිපින ඇතුළත් කරන්න.",
|
"install_devices_ios_list_4": "ව.නා.ප. (DNS) ක්ෂේත්රය තුළ ඔබගේ ඇඩ්ගාර්ඩ් හෝම් සේවාදායක ලිපින ඇතුල් කරන්න.",
|
||||||
"get_started": "ආරම්භ කර ගන්න",
|
"get_started": "ආරම්භ කර ගන්න",
|
||||||
"next": "ඊළඟ",
|
"next": "ඊළඟ",
|
||||||
"open_dashboard": "උපකරණ පුවරුව විවෘත කරන්න",
|
"open_dashboard": "උපකරණ පුවරුව විවෘත කරන්න",
|
||||||
@@ -301,15 +301,15 @@
|
|||||||
"encryption_desc": "ගුප්තකේතනය (HTTPS/TLS) සඳහා ව.නා.ප. සහ පරිපාලක වියමන අතුරු මුහුණත සහය දක්වයි",
|
"encryption_desc": "ගුප්තකේතනය (HTTPS/TLS) සඳහා ව.නා.ප. සහ පරිපාලක වියමන අතුරු මුහුණත සහය දක්වයි",
|
||||||
"encryption_config_saved": "සංකේතාංකන වින්යාසය සුරකින ලදි",
|
"encryption_config_saved": "සංකේතාංකන වින්යාසය සුරකින ලදි",
|
||||||
"encryption_server": "සේවාදායකයේ නම",
|
"encryption_server": "සේවාදායකයේ නම",
|
||||||
"encryption_server_enter": "ඔබගේ වසම් නාමය ඇතුළත් කරන්න",
|
"encryption_server_enter": "ඔබගේ වසම් නාමය ඇතුල් කරන්න",
|
||||||
"encryption_redirect": "ස්වයංක්රීයව HTTPS වෙත හරවා යවන්න",
|
"encryption_redirect": "ස්වයංක්රීයව HTTPS වෙත හරවා යවන්න",
|
||||||
"encryption_redirect_desc": "සබල කර ඇත්නම්, ඇඩ්ගාර්ඩ් හෝම් ඔබව ස්වයංක්රීයව HTTP සිට HTTPS ලිපින වෙත හරවා යවනු ඇත.",
|
"encryption_redirect_desc": "සබල කර ඇත්නම්, ඇඩ්ගාර්ඩ් හෝම් ඔබව ස්වයංක්රීයව HTTP සිට HTTPS ලිපින වෙත හරවා යවනු ඇත.",
|
||||||
"encryption_https": "HTTPS කවුළුව",
|
"encryption_https": "HTTPS කෙවෙනිය",
|
||||||
"encryption_https_desc": "HTTPS කවුළුව වින්යාසගත කර ඇත්නම්, ඇඩ්ගාර්ඩ් හෝම් පරිපාලක අතුරුමුහුණත HTTPS හරහා ප්රවේශ විය හැකි අතර එය '/dns-query' ස්ථානයේ DNS-over-HTTPS ද ලබා දෙනු ඇත.",
|
"encryption_https_desc": "HTTPS කෙවෙනිය වින්යාසගත කර ඇත්නම්, ඇඩ්ගාර්ඩ් හෝම් පරිපාලක අතුරුමුහුණත HTTPS හරහා ප්රවේශ විය හැකි අතර එය '/dns-query' ස්ථානයේ DNS-over-HTTPS ද ලබා දෙනු ඇත.",
|
||||||
"encryption_dot": "DNS-over-TLS කවුළුව",
|
"encryption_dot": "DNS-over-TLS කෙවෙනිය",
|
||||||
"encryption_dot_desc": "මෙම කවුළුව වින්යාසගත කර ඇත්නම්, ඇඩ්ගාර්ඩ් හෝම් විසින් මෙම කවුළුව හරහා DNS-over-TLS සේවාදායකයක් ක්රියාත්මක කරනු ඇත.",
|
"encryption_dot_desc": "මෙම කෙවෙනිය වින්යාසගත කර ඇත්නම්, ඇඩ්ගාර්ඩ් හෝම් විසින් මෙම කවුළුව හරහා DNS-over-TLS සේවාදායකයක් ධාවනය කරනු ඇත.",
|
||||||
"encryption_doq": "DNS-over-QUIC කවුළුව",
|
"encryption_doq": "DNS-over-QUIC කෙවෙනිය",
|
||||||
"encryption_doq_desc": "මෙම කවුළුව වින්යාසගත කර ඇත්නම්, ඇඩ්ගාර්ඩ් හෝම් විසින් මෙම කවුළුව හරහා DNS-over-QUIC සේවාදායකයක් ක්රියාත්මක කරනු ඇත. එය පර්යේෂණාත්මක වන අතර විශ්වාසදායක නොවිය හැකිය. එසේම, මේ වන විට එයට සහාය දක්වන බොහෝ අනුග්රාහකයින් නොමැත.",
|
"encryption_doq_desc": "මෙම කෙවෙනිය වින්යාසගත කර ඇත්නම්, ඇඩ්ගාර්ඩ් හෝම් විසින් මෙම කෙවෙනිය හරහා DNS-over-QUIC සේවාදායකයක් ධාවනය කරනු ඇත. එය පර්යේෂණාත්මක වන අතර විශ්වාසදායක නොවිය හැකිය. එසේම, මේ වන විට එයට සහාය දක්වන බොහෝ අනුග්රාහකයින් නැත.",
|
||||||
"encryption_certificates": "සහතික",
|
"encryption_certificates": "සහතික",
|
||||||
"encryption_certificates_input": "ඔබගේ PEM-කේතාංකනය කළ සහතික පිටපත් කර මෙහි අලවන්න.",
|
"encryption_certificates_input": "ඔබගේ PEM-කේතාංකනය කළ සහතික පිටපත් කර මෙහි අලවන්න.",
|
||||||
"encryption_status": "තත්ත්වය",
|
"encryption_status": "තත්ත්වය",
|
||||||
@@ -328,8 +328,8 @@
|
|||||||
"encryption_reset": "සංකේතාංකන සැකසුම් යළි පිහිටුවීමට අවශ්ය බව ඔබට විශ්වාස ද?",
|
"encryption_reset": "සංකේතාංකන සැකසුම් යළි පිහිටුවීමට අවශ්ය බව ඔබට විශ්වාස ද?",
|
||||||
"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 පරාසය හි කෙවෙනියක අගයක් ඇතුල් කරන්න",
|
||||||
"form_error_port_unsafe": "මෙය අනාරක්ෂිත කවුළුවකි",
|
"form_error_port_unsafe": "මෙය අනාරක්ෂිත කෙවෙනියකි",
|
||||||
"form_error_equal": "සමාන නොවිය යුතුය",
|
"form_error_equal": "සමාන නොවිය යුතුය",
|
||||||
"form_error_password": "මුරපදය නොගැලපුුුුුුණි",
|
"form_error_password": "මුරපදය නොගැලපුුුුුුණි",
|
||||||
"reset_settings": "සැකසුම් යළි පිහිටුවන්න",
|
"reset_settings": "සැකසුම් යළි පිහිටුවන්න",
|
||||||
@@ -356,12 +356,12 @@
|
|||||||
"client_edit": "අනුග්රාහකය සංස්කරණය කරන්න",
|
"client_edit": "අනුග්රාහකය සංස්කරණය කරන්න",
|
||||||
"client_identifier": "හඳුන්වනය",
|
"client_identifier": "හඳුන්වනය",
|
||||||
"ip_address": "අ.ජා. කෙ. (IP) ලිපිනය",
|
"ip_address": "අ.ජා. කෙ. (IP) ලිපිනය",
|
||||||
"form_enter_ip": "අ.ජා. කෙ. (IP) ඇතුළත් කරන්න",
|
"form_enter_ip": "අ.ජා. කෙ. (IP) ඇතුල් කරන්න",
|
||||||
"form_enter_subnet_ip": "\"{{cidr}}\" අනුජාලයෙහි අ.ජා. කෙ. ලිපිනයක් යොදන්න.",
|
"form_enter_subnet_ip": "\"{{cidr}}\" අනුජාලයෙහි අ.ජා. කෙ. ලිපිනයක් යොදන්න.",
|
||||||
"form_enter_mac": "මා.ප්ර.පා. (MAC) ඇතුළත් කරන්න",
|
"form_enter_mac": "මා.ප්ර.පා. (MAC) ඇතුල් කරන්න",
|
||||||
"form_enter_id": "හඳුන්වනය ඇතුළත් කරන්න",
|
"form_enter_id": "හඳුන්වනය ඇතුල් කරන්න",
|
||||||
"form_add_id": "හඳුන්වනයක් එක් කරන්න",
|
"form_add_id": "හඳුන්වනයක් එකතු කරන්න",
|
||||||
"form_client_name": "අනුග්රාහකයේ නම ඇතුළත් කරන්න",
|
"form_client_name": "අනුග්රාහකයේ නම ඇතුල් කරන්න",
|
||||||
"name": "නම",
|
"name": "නම",
|
||||||
"client_global_settings": "ගෝලීය සැකසුම් භාවිතා කරන්න",
|
"client_global_settings": "ගෝලීය සැකසුම් භාවිතා කරන්න",
|
||||||
"client_deleted": "\"{{key}}\" අනුග්රාහකය සාර්ථකව ඉවත් කරන ලදි",
|
"client_deleted": "\"{{key}}\" අනුග්රාහකය සාර්ථකව ඉවත් කරන ලදි",
|
||||||
@@ -373,11 +373,11 @@
|
|||||||
"auto_clients_desc": "ඇඩ්ගාර්ඩ් හෝම් භාවිතා කරන අනුග්රාහකයන්ගේ දත්ත, නමුත් වින්යාසය තුළ ගබඩා කර නොමැති",
|
"auto_clients_desc": "ඇඩ්ගාර්ඩ් හෝම් භාවිතා කරන අනුග්රාහකයන්ගේ දත්ත, නමුත් වින්යාසය තුළ ගබඩා කර නොමැති",
|
||||||
"access_title": "ප්රවේශවීමට සැකසුම්",
|
"access_title": "ප්රවේශවීමට සැකසුම්",
|
||||||
"access_desc": "මෙහිදී ඔබට ඇඩ්ගාර්ඩ් හෝම් ව.නා.ප. සේවාදායකය සඳහා ප්රවේශ වීමේ නීති වින්යාසගත කළ හැකිය.",
|
"access_desc": "මෙහිදී ඔබට ඇඩ්ගාර්ඩ් හෝම් ව.නා.ප. සේවාදායකය සඳහා ප්රවේශ වීමේ නීති වින්යාසගත කළ හැකිය.",
|
||||||
"access_allowed_title": "අවසර ලත් අනුග්රාහකයන්",
|
"access_allowed_title": "ඉඩ ලත් අනුග්රාහකයින්",
|
||||||
"access_allowed_desc": "CIDR හෝ අ.ජා. කෙ. ලිපින ලැයිස්තුවක් වින්යාසගත කර ඇත්නම්, ඇඩ්ගාර්ඩ් හෝම් විසින් එම අ.ජා. කෙ. ලිපින වලින් පමණක් ඉල්ලීම් පිළිගනු ඇත.",
|
"access_allowed_desc": "CIDR හෝ අ.ජා. කෙ. ලිපින ලැයිස්තුවක් වින්යාසගත කර ඇත්නම්, ඇඩ්ගාර්ඩ් හෝම් විසින් එම අ.ජා. කෙ. ලිපින වලින් පමණක් ඉල්ලීම් පිළිගනු ඇත.",
|
||||||
"access_disallowed_title": "අවසර නොලත් අනුග්රාහකයන්",
|
"access_disallowed_title": "නොඉඩ ලත් අනුග්රාහකයින්",
|
||||||
"access_disallowed_desc": "CIDR හෝ අ.ජා. කෙ. ලිපින ලැයිස්තුවක් වින්යාසගත කර ඇත්නම්, ඇඩ්ගාර්ඩ් හෝම් විසින් එම අ.ජා. කෙ. ලිපින වලින් ඉල්ලීම් අත්හරිනු ඇත.",
|
"access_disallowed_desc": "CIDR හෝ අ.ජා. කෙ. ලිපින ලැයිස්තුවක් වින්යාසගත කර ඇත්නම්, ඇඩ්ගාර්ඩ් හෝම් විසින් එම අ.ජා. කෙ. ලිපින වලින් ඉල්ලීම් අත්හරිනු ඇත.",
|
||||||
"access_blocked_title": "අවහිර කළ වසම්",
|
"access_blocked_title": "නොඉඩ ලත් වසම්",
|
||||||
"access_settings_saved": "ප්රවේශ වීමේ සැකසුම් සාර්ථකව සුරකින ලදි",
|
"access_settings_saved": "ප්රවේශ වීමේ සැකසුම් සාර්ථකව සුරකින ලදි",
|
||||||
"updates_checked": "යාවත්කාලීන කිරීම් සාර්ථකව පරික්ෂා කර ඇත",
|
"updates_checked": "යාවත්කාලීන කිරීම් සාර්ථකව පරික්ෂා කර ඇත",
|
||||||
"updates_version_equal": "ඇඩ්ගාර්ඩ් හෝම් යාවත්කාලීනයි",
|
"updates_version_equal": "ඇඩ්ගාර්ඩ් හෝම් යාවත්කාලීනයි",
|
||||||
@@ -385,9 +385,9 @@
|
|||||||
"dns_privacy": "ව.නා.ප. රහස්යතා",
|
"dns_privacy": "ව.නා.ප. රහස්යතා",
|
||||||
"setup_dns_privacy_3": "<0>මෙහි ඔබට භාවිතා කළ හැකි මෘදුකාංග ලැයිස්තුවක් ඇත.</0>",
|
"setup_dns_privacy_3": "<0>මෙහි ඔබට භාවිතා කළ හැකි මෘදුකාංග ලැයිස්තුවක් ඇත.</0>",
|
||||||
"setup_dns_privacy_other_title": "වෙනත් ක්රියාවට නැංවූ දෑ",
|
"setup_dns_privacy_other_title": "වෙනත් ක්රියාවට නැංවූ දෑ",
|
||||||
"setup_dns_privacy_other_2": "<0>ඩීඑන්එස්ප්රොක්සි</0> දන්නා සියලුම ආරක්ෂිත ව.නා.ප. කෙටුම්පත් සඳහා සහය දක්වයි.",
|
"setup_dns_privacy_other_2": "<0>ඩීඑන්එස්ප්රොක්සි</0> දන්නා සියලුම ආරක්ෂිත ව.නා.ප. කෙටුම්පත් සඳහා සහාය දක්වයි.",
|
||||||
"setup_dns_privacy_other_3": "<1>DNS-over-HTTPS</1> සඳහා <0>dnscrypt-පෙරකලාසිය</0> සහය දක්වයි.",
|
"setup_dns_privacy_other_3": "<1>DNS-over-HTTPS</1> සඳහා <0>dnscrypt-පෙරකලාසිය</0> සහාය දක්වයි.",
|
||||||
"setup_dns_privacy_other_4": "<1>DNS-over-HTTPS</1> සඳහා <0>මොසිල්ලා ෆයර්ෆොක්ස්</0> සහය දක්වයි.",
|
"setup_dns_privacy_other_4": "<1>DNS-over-HTTPS</1> සඳහා <0>මොසිල්ලා ෆයර්ෆොක්ස්</0> සහාය දක්වයි.",
|
||||||
"setup_dns_privacy_other_5": "<0>මෙහි</0> සහ <1>මෙහි</1> තවත් ක්රියාවට නැංවූ දෑ ඔබට හමුවනු ඇත.",
|
"setup_dns_privacy_other_5": "<0>මෙහි</0> සහ <1>මෙහි</1> තවත් ක්රියාවට නැංවූ දෑ ඔබට හමුවනු ඇත.",
|
||||||
"setup_dns_privacy_ioc_mac": "අයිඕඑස් සහ මැක්ඕඑස් වින්යාසය",
|
"setup_dns_privacy_ioc_mac": "අයිඕඑස් සහ මැක්ඕඑස් වින්යාසය",
|
||||||
"setup_dns_notice": "ඔබට <1>DNS-over-HTTPS</1> හෝ <1>DNS-over-TLS</1> භාවිතා කිරීම සඳහා ඇඩ්ගාර්ඩ් හෝම් සැකසුම් තුළ <0>සංකේතාංකනය වින්යාසගත</0> කිරීමට අවශ්ය වේ.",
|
"setup_dns_notice": "ඔබට <1>DNS-over-HTTPS</1> හෝ <1>DNS-over-TLS</1> භාවිතා කිරීම සඳහා ඇඩ්ගාර්ඩ් හෝම් සැකසුම් තුළ <0>සංකේතාංකනය වින්යාසගත</0> කිරීමට අවශ්ය වේ.",
|
||||||
@@ -399,7 +399,7 @@
|
|||||||
"rewrite_applied": "නැවත ලිවීමේ නීතිය යොදා ඇත",
|
"rewrite_applied": "නැවත ලිවීමේ නීතිය යොදා ඇත",
|
||||||
"rewrite_hosts_applied": "ධාරක ගොනු නීතිය මගින් නැවත ලියා ඇත",
|
"rewrite_hosts_applied": "ධාරක ගොනු නීතිය මගින් නැවත ලියා ඇත",
|
||||||
"dns_rewrites": "ව.නා.ප. නැවත ලිවීම්",
|
"dns_rewrites": "ව.නා.ප. නැවත ලිවීම්",
|
||||||
"form_answer": "අ.ජා. කෙ. (IP) ලිපිනය හෝ වසම ඇතුළත් කරන්න ",
|
"form_answer": "අ.ජා. කෙ. (IP) ලිපිනය හෝ වසම ඇතුල් කරන්න ",
|
||||||
"form_error_domain_format": "වලංගු නොවන වසම් ආකෘතියකි",
|
"form_error_domain_format": "වලංගු නොවන වසම් ආකෘතියකි",
|
||||||
"form_error_answer_format": "වලංගු නොවන පිළිතුරු ආකෘතියකි",
|
"form_error_answer_format": "වලංගු නොවන පිළිතුරු ආකෘතියකි",
|
||||||
"configure": "වින්යාසගත කරන්න",
|
"configure": "වින්යාසගත කරන්න",
|
||||||
@@ -443,9 +443,9 @@
|
|||||||
"filters_interval": "පෙරහන් යාවත්කාල කාල පරතරය",
|
"filters_interval": "පෙරහන් යාවත්කාල කාල පරතරය",
|
||||||
"disabled": "අබල කර ඇත",
|
"disabled": "අබල කර ඇත",
|
||||||
"username_label": "පරිශීලක නාමය",
|
"username_label": "පරිශීලක නාමය",
|
||||||
"username_placeholder": "පරිශීලක නාමය ඇතුළත් කරන්න",
|
"username_placeholder": "පරිශීලක නාමය ඇතුල් කරන්න",
|
||||||
"password_label": "මුරපදය",
|
"password_label": "මුරපදය",
|
||||||
"password_placeholder": "මුරපදය ඇතුළත් කරන්න",
|
"password_placeholder": "මුරපදය ඇතුල් කරන්න",
|
||||||
"sign_in": "පුරන්න",
|
"sign_in": "පුරන්න",
|
||||||
"sign_out": "වරන්න",
|
"sign_out": "වරන්න",
|
||||||
"forgot_password": "මුරපදය අමතක වුණා ද?",
|
"forgot_password": "මුරපදය අමතක වුණා ද?",
|
||||||
@@ -464,23 +464,23 @@
|
|||||||
"example_rewrite_wildcard": "<0>example.org</0> සහ එහි සියලුම උප වසම් සඳහා ප්රතිචාර නැවත ලියයි.",
|
"example_rewrite_wildcard": "<0>example.org</0> සහ එහි සියලුම උප වසම් සඳහා ප්රතිචාර නැවත ලියයි.",
|
||||||
"rewrite_ip_address": "අ.ජා. කෙ. ලිපිනය: මෙම අ.ජා. කෙටුම්පත A හෝ AAAA ප්රතිචාරයකට භාවිතා කරන්න",
|
"rewrite_ip_address": "අ.ජා. කෙ. ලිපිනය: මෙම අ.ජා. කෙටුම්පත A හෝ AAAA ප්රතිචාරයකට භාවිතා කරන්න",
|
||||||
"rewrite_domain_name": "වසම් නාමය: අන්. නා. (CNAME) වාර්තාවක් එක් කරන්න",
|
"rewrite_domain_name": "වසම් නාමය: අන්. නා. (CNAME) වාර්තාවක් එක් කරන්න",
|
||||||
"disable_ipv6": "IPv6 අබල කරන්න",
|
"disable_ipv6": "IPv6 ලිපින විසඳීම අබල කරන්න",
|
||||||
"disable_ipv6_desc": "මෙම අංගය සක්රීය කර ඇත්නම්, IPv6 ලිපින සඳහා වන සියලුම ව.නා.ප. විමසුම් (AAAA වර්ගය) අතහැර දමනු ලැබේ.",
|
"disable_ipv6_desc": "අ.ජා.කෙ. අනු. 6 ලිපින (AAAA වර්ගය) සඳහා වන සියලුම ව.නා.ප. විමසුම් අතහැර දමනු ලැබේ.",
|
||||||
"fastest_addr": "වේගවත්ම අන්තර්ජාල කෙටුම්පත් (IP) ලිපිනය",
|
"fastest_addr": "වේගවත්ම අන්තර්ජාල කෙටුම්පත් (IP) ලිපිනය",
|
||||||
"fastest_addr_desc": "සියලුම ව.නා.ප. සේවාදායකයන්ගෙන් විමසා සියලු ප්රතිචාර අතරින් වේගවත්ම අ.ජා. කෙ. ලිපිනය ලබා දෙයි. සියලුම ව.නා.ප. සේවාදායකයන්ගේ ප්රතිචාර සඳහා ඇඩ්ගාර්ඩ් හෝම් රැඳී සිටිය යුතු බැවින් මෙය ව.නා.ප. විමසුම් මන්දගාමී කරන නමුත් සමස්ත සම්බන්ධතාවය වැඩි දියුණු කරයි.",
|
"fastest_addr_desc": "සියලුම ව.නා.ප. සේවාදායකයන්ගෙන් විමසා සියලු ප්රතිචාර අතරින් වේගවත්ම අ.ජා. කෙ. ලිපිනය ලබා දෙයි. සියලුම ව.නා.ප. සේවාදායකයන්ගේ ප්රතිචාර සඳහා ඇඩ්ගාර්ඩ් හෝම් රැඳී සිටිය යුතු බැවින් මෙය ව.නා.ප. විමසුම් මන්දගාමී කරන නමුත් සමස්ත සම්බන්ධතාවය වැඩි දියුණු කරයි.",
|
||||||
"autofix_warning_text": "ඔබ \"නිරාකරණය කරන්න\" බොත්තම එබුවහොත්, ඔබගේ පද්ධතිය ඇඩ්ගාර්ඩ් හෝම් ව.නා.ප. සේවාදායකය භාවිතා කිරීමට වින්යාසගත කරනු ඇත.",
|
"autofix_warning_text": "ඔබ \"නිරාකරණය කරන්න\" බොත්තම එබුවහොත්, ඔබගේ පද්ධතිය ඇඩ්ගාර්ඩ් හෝම් ව.නා.ප. සේවාදායකය භාවිතා කිරීමට වින්යාසගත කරනු ඇත.",
|
||||||
"autofix_warning_result": "ප්රතිඵලයක් ලෙස ඔබගේ පද්ධතියෙන් ලැබෙන සියලුම ව.නා.ප. ඉල්ලීම් මූලිකවම ඇඩ්ගාර්ඩ් හෝම් විසින් සකසනු ඇත.",
|
"autofix_warning_result": "ප්රතිඵලයක් ලෙස ඔබගේ පද්ධතියෙන් ලැබෙන සියලුම ව.නා.ප. ඉල්ලීම් මූලිකවම ඇඩ්ගාර්ඩ් හෝම් විසින් සකසනු ඇත.",
|
||||||
"tags_title": "හැඳුනුම් සංකේත",
|
"tags_title": "හැඳුනුම් සංකේත",
|
||||||
"tags_desc": "අනුග්රාහකයට අනුරූප වන හැඳුනුම් සංකේත ඔබට තෝරා ගත හැකිය. පෙරහන් නීති වලට හැඳුනුම් සංකේත ඇතුළත් කළ හැකි අතර ඒවා වඩාත් නිවැරදිව යෙදීමට ඔබට ඉඩ සලසයි. <0>වැඩිදුර ඉගෙන ගන්න</0>",
|
"tags_desc": "අනුග්රාහකයට අනුරූප වන හැඳුනුම් සංකේත ඔබට තෝරා ගත හැකිය. පෙරහන් නීති වලට හැඳුනුම් සංකේත ඇතුළත් කළ හැකි අතර ඒවා වඩාත් නිවැරදිව යෙදීමට ඔබට ඉඩ සලසයි. <0>තව දැන ගන්න</0>",
|
||||||
"form_select_tags": "අනුග්රාහක හැඳුනුම් සංකේත",
|
"form_select_tags": "අනුග්රාහක හැඳුනුම් සංකේත",
|
||||||
"check_title": "පෙරීම පරීක්ෂා කරන්න",
|
"check_title": "පෙරීම පරීක්ෂා කරන්න",
|
||||||
"check_desc": "ධාරක නාමය පෙරහන් කර ඇත්දැයි පරීක්ෂා කරන්න",
|
"check_desc": "ධාරක නාමය පෙරහන් කර ඇත්දැයි පරීක්ෂා කරන්න",
|
||||||
"check": "පරීක්ෂා කරන්න",
|
"check": "පරීක්ෂා කරන්න",
|
||||||
"form_enter_host": "ධාරක නාමයක් ඇතුළත් කරන්න",
|
"form_enter_host": "ධාරක නාමයක් ඇතුල් කරන්න",
|
||||||
"filtered_custom_rules": "අභිරුචි පෙරීමේ නීති මගින් පෙරහන් කරන ලදි",
|
"filtered_custom_rules": "අභිරුචි පෙරීමේ නීති මගින් පෙරහන් කරන ලදි",
|
||||||
"choose_from_list": "ලැයිස්තුවෙන් තෝරන්න",
|
"choose_from_list": "ලැයිස්තුවෙන් තෝරන්න",
|
||||||
"add_custom_list": "අභිරුචි ලැයිස්තුවක් එකතු කරන්න",
|
"add_custom_list": "අභිරුචි ලැයිස්තුවක් එකතු කරන්න",
|
||||||
"host_whitelisted": "ධාරකය සුදු ලැයිස්තු ගත කර ඇත",
|
"host_whitelisted": "ධාරකයට ඉඩ දී ඇත",
|
||||||
"check_ip": "අ.ජා. කෙ. (IP) ලිපින: {{ip}}",
|
"check_ip": "අ.ජා. කෙ. (IP) ලිපින: {{ip}}",
|
||||||
"check_cname": "අන්. නාමය (CNAME): {{cname}}",
|
"check_cname": "අන්. නාමය (CNAME): {{cname}}",
|
||||||
"check_reason": "හේතුව: {{reason}}",
|
"check_reason": "හේතුව: {{reason}}",
|
||||||
@@ -502,12 +502,12 @@
|
|||||||
"list_updated_plural": "ලැයිස්තු {{count}} ක් යාවත්කාලීන කරන ලදි",
|
"list_updated_plural": "ලැයිස්තු {{count}} ක් යාවත්කාලීන කරන ලදි",
|
||||||
"all_queries": "සියලුම විමසුම්",
|
"all_queries": "සියලුම විමසුම්",
|
||||||
"show_blocked_responses": "අවහිර කර ඇත",
|
"show_blocked_responses": "අවහිර කර ඇත",
|
||||||
"show_whitelisted_responses": "සුදු ලැයිස්තුගත කර ඇත",
|
"show_whitelisted_responses": "ඉඩ දී ඇත",
|
||||||
"show_processed_responses": "සකසා ඇත",
|
"show_processed_responses": "සකසා ඇත",
|
||||||
"blocked_safebrowsing": "ආරක්ෂිත සෙවීම මගින් අවහිර කරන ලද",
|
"blocked_safebrowsing": "ආරක්ෂිත සෙවීම මගින් අවහිර කරන ලද",
|
||||||
"blocked_adult_websites": "අවහිර කළ වැඩිහිටි වියමන අඩවි",
|
"blocked_adult_websites": "අවහිර කළ වැඩිහිටි වියමන අඩවි",
|
||||||
"blocked_threats": "අවහිර කළ තර්ජන",
|
"blocked_threats": "අවහිර කළ තර්ජන",
|
||||||
"allowed": "අවසර ලත්",
|
"allowed": "ඉඩ දී ඇත",
|
||||||
"filtered": "පෙරහන් කරන ලද",
|
"filtered": "පෙරහන් කරන ලද",
|
||||||
"rewritten": "නැවත ලියන ලද",
|
"rewritten": "නැවත ලියන ලද",
|
||||||
"safe_search": "ආරක්ෂිත සෙවීම",
|
"safe_search": "ආරක්ෂිත සෙවීම",
|
||||||
@@ -517,24 +517,26 @@
|
|||||||
"cache_size_desc": "ව.නා.ප. නිහිතයෙහි ප්රමාණය (බයිට වලින්)",
|
"cache_size_desc": "ව.නා.ප. නිහිතයෙහි ප්රමාණය (බයිට වලින්)",
|
||||||
"cache_ttl_min_override": "අවම පව. කා. අභිබවන්න",
|
"cache_ttl_min_override": "අවම පව. කා. අභිබවන්න",
|
||||||
"cache_ttl_max_override": "උපරිම පව. කා. අභිබවන්න",
|
"cache_ttl_max_override": "උපරිම පව. කා. අභිබවන්න",
|
||||||
"enter_cache_size": "ව.නා.ප. නිහිතයෙහි ප්රමාණය ඇතුළත් කරන්න (බයිට)",
|
"enter_cache_size": "ව.නා.ප. නිහිතයෙහි ප්රමාණය ඇතුල් කරන්න (බයිට)",
|
||||||
"enter_cache_ttl_min_override": "අවම පව. කා. (TTL) ඇතුළත් කරන්න",
|
"enter_cache_ttl_min_override": "අවම පව. කා. (TTL) ඇතුල් කරන්න",
|
||||||
"enter_cache_ttl_max_override": "උපරිම පව. කා. (TTL) ඇතුළත් කරන්න",
|
"enter_cache_ttl_max_override": "උපරිම පව. කා. (TTL) ඇතුල් කරන්න",
|
||||||
"cache_ttl_max_override_desc": "ව.නා.ප. නිහිතයෙහි ඇති ඇතුළත් කිරීම් සඳහා ඉතා වැඩි පවත්නා කාලයක අගයක් (තත්පර) සකසන්න",
|
"cache_ttl_max_override_desc": "ව.නා.ප. නිහිතයෙහි ඇති ඇතුළත් කිරීම් සඳහා ඉතා වැඩි පවත්නා කාලයක අගයක් (තත්පර) සකසන්න",
|
||||||
"ttl_cache_validation": "නිහිතයෙහි අවම පව. කා. (TTL) අගය උපරිම අගයට වඩා අඩු හෝ සමාන විය යුතුය",
|
"ttl_cache_validation": "නිහිතයෙහි අවම පව. කා. (TTL) අගය උපරිම අගයට වඩා අඩු හෝ සමාන විය යුතුය",
|
||||||
|
"cache_optimistic_desc": "නිවේශිත කල් ඉකුත් වූ විට පවා ඇඩ්ගාර්ඩ් හෝම් ට නිහිතයෙන් ප්රතිචාර දැක්වීමට සලස්වයි එමෙන්ම ඒවා නැවත නැවුම් කිරීමට ද උත්සාහ කරයි.",
|
||||||
"filter_category_general": "පොදු",
|
"filter_category_general": "පොදු",
|
||||||
"filter_category_security": "ආරක්ෂණ",
|
"filter_category_security": "ආරක්ෂණ",
|
||||||
"filter_category_regional": "ප්රාදේශ්රීය",
|
"filter_category_regional": "ප්රාදේශ්රීය",
|
||||||
"filter_category_other": "වෙනත්",
|
"filter_category_other": "වෙනත්",
|
||||||
"filter_category_general_desc": "බොහෝ උපාංගවල ලුහුබැඳීම් සහ දැන්වීම් අවහිර කරන ලැයිස්තු",
|
"filter_category_general_desc": "බොහෝ උපාංගවල ලුහුබැඳීම් සහ දැන්වීම් අවහිර කරන ලැයිස්තු",
|
||||||
"filter_category_security_desc": "අනිෂ්ට මෘදුකාංග, තතුබෑම් හෝ වංචනික වසම් අවහිර කිරීමට විශේෂ වූ ලැයිස්තු",
|
"filter_category_security_desc": "ද්වේෂසහගත, තතුබෑම් සහ වංචනික වසම් අවහිර කිරීමට නිර්මාණය කළ ලැයිස්තු",
|
||||||
"filter_category_regional_desc": "ප්රාදේශ්රීය දැන්වීම් සහ ලුහුබැඳීමේ සේවාදායකයන් කෙරෙහි අවධානය යොමු කරන ලැයිස්තු",
|
"filter_category_regional_desc": "ප්රාදේශ්රීය දැන්වීම් සහ ලුහුබැඳීමේ සේවාදායකයන් කෙරෙහි අවධානය යොමු කරන ලැයිස්තු",
|
||||||
"filter_category_other_desc": "වෙනත් අවහිර කිරීමේ ලැයිස්තු",
|
"filter_category_other_desc": "වෙනත් අවහිර කිරීමේ ලැයිස්තු",
|
||||||
"setup_config_to_enable_dhcp_server": "ග.ධා.වි.කෙ. සේවාදායකය සක්රීය කිරීම සඳහා වින්යාසය පිහිටුවන්න",
|
"setup_config_to_enable_dhcp_server": "ග.ධා.වි.කෙ. සේවාදායකය සක්රීය කිරීම සඳහා වින්යාසය පිහිටුවන්න",
|
||||||
"original_response": "මුල් ප්රතිචාරය",
|
"original_response": "මුල් ප්රතිචාරය",
|
||||||
"click_to_view_queries": "විමසුම් බැලීමට ඔබන්න",
|
"click_to_view_queries": "විමසුම් බැලීමට ඔබන්න",
|
||||||
"port_53_faq_link": "53 කවුළුව බොහෝ විට \"DNSStubListener\" හෝ \"systemd-resolved\" සේවාවන් භාවිතයට ගනු ලැබේ. කරුණාකර මෙය විසඳන්නේ කෙසේද යන්න පිළිබඳ <0>මෙම උපදෙස්</0> කියවන්න.",
|
"port_53_faq_link": "53 වන කෙවෙනිය බොහෝ විට \"DNSStubListener\" හෝ \"systemd-resolved\" සේවාවන් භාවිතයට ගනු ලැබේ. කරුණාකර මෙය විසඳන්නේ කෙසේද යන්න පිළිබඳ <0>මෙම උපදෙස්</0> කියවන්න.",
|
||||||
"adg_will_drop_dns_queries": "ඇඩ්ගාර්ඩ් හෝම් විසින් මෙම අනුග්රාහකයේ සියලුම ව.නා.ප. විමසුම් අතහැර දමනු ඇත.",
|
"adg_will_drop_dns_queries": "ඇඩ්ගාර්ඩ් හෝම් විසින් මෙම අනුග්රාහකයේ සියලුම ව.නා.ප. විමසුම් අතහැර දමනු ඇත.",
|
||||||
"client_not_in_allowed_clients": "\"අවසර ලත් අනුග්රාහකයින්\" ලැයිස්තුවේ නොමැති නිසා අනුග්රාහකයට අවසර නැත.",
|
"client_not_in_allowed_clients": "\"ඉඩ දුන් අනුග්රාහකයින්\" ලැයිස්තුවේ නැති නිසා අනුග්රාහකයට ඉඩ දී නැත.",
|
||||||
"experimental": "පරීක්ෂණාත්මක"
|
"experimental": "පරීක්ෂණාත්මක",
|
||||||
|
"use_saved_key": "පෙර සුරැකි යතුර භාවිතා කරන්න"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -208,7 +208,7 @@
|
|||||||
"example_upstream_sdns": "môžete použiť <0>DNS pečiatky</0> pre <1>DNSCrypt</1> alebo <2>DNS-over-HTTPS</2>",
|
"example_upstream_sdns": "môžete použiť <0>DNS pečiatky</0> pre <1>DNSCrypt</1> alebo <2>DNS-over-HTTPS</2>",
|
||||||
"example_upstream_tcp": "radová DNS (cez TCP)",
|
"example_upstream_tcp": "radová DNS (cez TCP)",
|
||||||
"all_lists_up_to_date_toast": "Všetky zoznamy sú už aktuálne",
|
"all_lists_up_to_date_toast": "Všetky zoznamy sú už aktuálne",
|
||||||
"updated_upstream_dns_toast": "Aktualizované upstream DNS servery",
|
"updated_upstream_dns_toast": "Upstream servery boli úspešne uložené",
|
||||||
"dns_test_ok_toast": "Špecifikované DNS servery pracujú korektne",
|
"dns_test_ok_toast": "Špecifikované DNS servery pracujú korektne",
|
||||||
"dns_test_not_ok_toast": "Server \"{{key}}\": nemohol byť použitý, skontrolujte, či ste ho správne napísali",
|
"dns_test_not_ok_toast": "Server \"{{key}}\": nemohol byť použitý, skontrolujte, či ste ho správne napísali",
|
||||||
"unblock": "Odblokovať",
|
"unblock": "Odblokovať",
|
||||||
@@ -235,7 +235,7 @@
|
|||||||
"loading_table_status": "Načítavam...",
|
"loading_table_status": "Načítavam...",
|
||||||
"page_table_footer_text": "Stránka",
|
"page_table_footer_text": "Stránka",
|
||||||
"rows_table_footer_text": "riadky",
|
"rows_table_footer_text": "riadky",
|
||||||
"updated_custom_filtering_toast": "Aktualizované vlastné filtračné pravidlá",
|
"updated_custom_filtering_toast": "Vlastné pravidlá boli úspešne uložené",
|
||||||
"rule_removed_from_custom_filtering_toast": "Pravidlo odstránené z vlastných filtračných pravidiel: {{rule}}",
|
"rule_removed_from_custom_filtering_toast": "Pravidlo odstránené z vlastných filtračných pravidiel: {{rule}}",
|
||||||
"rule_added_to_custom_filtering_toast": "Pravidlo pridané do vlastných filtračných pravidiel: {{rule}}",
|
"rule_added_to_custom_filtering_toast": "Pravidlo pridané do vlastných filtračných pravidiel: {{rule}}",
|
||||||
"query_log_response_status": "Stav: {{value}}",
|
"query_log_response_status": "Stav: {{value}}",
|
||||||
@@ -306,7 +306,7 @@
|
|||||||
"install_settings_dns_desc": "Budete musieť konfigurovať Vaše zariadenia alebo smerovač, aby používali DNS server na nasledujúcich adresách:",
|
"install_settings_dns_desc": "Budete musieť konfigurovať Vaše zariadenia alebo smerovač, aby používali DNS server na nasledujúcich adresách:",
|
||||||
"install_settings_all_interfaces": "Všetky rozhrania",
|
"install_settings_all_interfaces": "Všetky rozhrania",
|
||||||
"install_auth_title": "Overenie identity",
|
"install_auth_title": "Overenie identity",
|
||||||
"install_auth_desc": "Odporúčame Vám nakonfigurovať na administrátorskom webovom rozhraní AdGuard Home overenie Vašej identity heslom. Aj keď je prístupné iba vo Vašej lokálnej sieti, je stále dôležité chrániť ho pred neobmedzeným prístupom.",
|
"install_auth_desc": "Je potrebné nakonfigurovať autentifikáciu heslom do administrátorského webového rozhrania AdGuard Home. Aj keď je AdGuard Home prístupný iba vo Vašej lokálnej sieti, je stále dôležité chrániť ho pred neobmedzeným prístupom.",
|
||||||
"install_auth_username": "Meno používateľa",
|
"install_auth_username": "Meno používateľa",
|
||||||
"install_auth_password": "Heslo",
|
"install_auth_password": "Heslo",
|
||||||
"install_auth_confirm": "Potvrdenie hesla",
|
"install_auth_confirm": "Potvrdenie hesla",
|
||||||
@@ -326,10 +326,10 @@
|
|||||||
"install_devices_router_list_4": "Na niektorých typoch smerovačov nemôžete nastaviť vlastný DNS server. V takom prípade môže pomôcť, ak nastavíte AdGuard Home ako <0>DHCP server</0>. V opačnom prípade by ste mali vyhľadať príručku, ako prispôsobiť DNS servery konkrétnemu modelu smerovača.",
|
"install_devices_router_list_4": "Na niektorých typoch smerovačov nemôžete nastaviť vlastný DNS server. V takom prípade môže pomôcť, ak nastavíte AdGuard Home ako <0>DHCP server</0>. V opačnom prípade by ste mali vyhľadať príručku, ako prispôsobiť DNS servery konkrétnemu modelu smerovača.",
|
||||||
"install_devices_windows_list_1": "Otvorte panel Nastavenia cez menu Štart alebo vyhľadávanie Windows.",
|
"install_devices_windows_list_1": "Otvorte panel Nastavenia cez menu Štart alebo vyhľadávanie Windows.",
|
||||||
"install_devices_windows_list_2": "Prejdite do kategórie Sieť a internet a potom do Centra sietí a zdieľania.",
|
"install_devices_windows_list_2": "Prejdite do kategórie Sieť a internet a potom do Centra sietí a zdieľania.",
|
||||||
"install_devices_windows_list_3": "Vyhľadajte položku Zmeniť možnosti adaptéra a kliknite na ňu",
|
"install_devices_windows_list_3": "Na ľavej strane obrazovky nájdite položku \"Zmeniť nastavenia adaptéra\" a kliknite na ňu.",
|
||||||
"install_devices_windows_list_4": "Zvoľte aktívne pripojený adaptér a pravým klikom otvorte Vlastnosti",
|
"install_devices_windows_list_4": "Zvoľte aktívne pripojený adaptér a pravým klikom otvorte Vlastnosti",
|
||||||
"install_devices_windows_list_5": "Vyhľadajte položku Protokol TCP/IPv4, zvoľte ju a dvojklikom otvorte jej vlastnosti.",
|
"install_devices_windows_list_5": "Nájdite v zozname položku \"Internet Protocol verzia 4 (TCP/IPv4)\" (alebo pre IPv6, \"Internet Protocol verzia 6 (TCP/IPv6)\"), vyberte ju a potom znova kliknite na Vlastnosti.",
|
||||||
"install_devices_windows_list_6": "Zvoľte Použiť tieto adresy serverov DNS a zadajte adresy Vašich AdGuard Home serverov.",
|
"install_devices_windows_list_6": "Zvoľte \"Použiť nasledujúce adresy DNS servera\" a zadajte adresy domáceho AdGuard servera.",
|
||||||
"install_devices_macos_list_1": "Kliknite na ikonu Apple a prejdite na položku Systémové predvoľby.",
|
"install_devices_macos_list_1": "Kliknite na ikonu Apple a prejdite na položku Systémové predvoľby.",
|
||||||
"install_devices_macos_list_2": "Kliknite na Sieť.",
|
"install_devices_macos_list_2": "Kliknite na Sieť.",
|
||||||
"install_devices_macos_list_3": "Zvoľte prvé pripojenie vo Vašom zozname a kliknite na Pokročilé.",
|
"install_devices_macos_list_3": "Zvoľte prvé pripojenie vo Vašom zozname a kliknite na Pokročilé.",
|
||||||
@@ -499,10 +499,11 @@
|
|||||||
"statistics_configuration": "Konfigurácia štatistiky",
|
"statistics_configuration": "Konfigurácia štatistiky",
|
||||||
"statistics_retention": "Štatistika za obdobie",
|
"statistics_retention": "Štatistika za obdobie",
|
||||||
"statistics_retention_desc": "Ak znížite hodnotu intervalu, niektoré údaje sa stratia",
|
"statistics_retention_desc": "Ak znížite hodnotu intervalu, niektoré údaje sa stratia",
|
||||||
"statistics_clear": " Vynulovať štatistiku",
|
"statistics_clear": "Vynulovať štatistiku",
|
||||||
"statistics_clear_confirm": "Naozaj chcete vynulovať štatistiku?",
|
"statistics_clear_confirm": "Naozaj chcete vynulovať štatistiku?",
|
||||||
"statistics_retention_confirm": "Naozaj chcete zmeniť uchovávanie štatistík? Ak znížite hodnotu intervalu, niektoré údaje sa stratia",
|
"statistics_retention_confirm": "Naozaj chcete zmeniť uchovávanie štatistík? Ak znížite hodnotu intervalu, niektoré údaje sa stratia",
|
||||||
"statistics_cleared": "Štatistika bola úspešne vynulovaná",
|
"statistics_cleared": "Štatistika bola úspešne vynulovaná",
|
||||||
|
"statistics_enable": "Zapnúť štatistiku",
|
||||||
"interval_hours": "{{count}} hodina",
|
"interval_hours": "{{count}} hodina",
|
||||||
"interval_hours_plural": "{{count}} hodín",
|
"interval_hours_plural": "{{count}} hodín",
|
||||||
"filters_configuration": "Konfigurácia filtrov",
|
"filters_configuration": "Konfigurácia filtrov",
|
||||||
@@ -612,6 +613,8 @@
|
|||||||
"click_to_view_queries": "Kliknite pre zobrazenie dopytov",
|
"click_to_view_queries": "Kliknite pre zobrazenie dopytov",
|
||||||
"port_53_faq_link": "Port 53 je často obsadený službami \"DNSStubListener\" alebo \"systemd-resolved\". Prečítajte si <0>tento návod</0> o tom, ako to vyriešiť.",
|
"port_53_faq_link": "Port 53 je často obsadený službami \"DNSStubListener\" alebo \"systemd-resolved\". Prečítajte si <0>tento návod</0> o tom, ako to vyriešiť.",
|
||||||
"adg_will_drop_dns_queries": "AdGuard Home zruší všetky DNS dopyty od tohto klienta.",
|
"adg_will_drop_dns_queries": "AdGuard Home zruší všetky DNS dopyty od tohto klienta.",
|
||||||
"client_not_in_allowed_clients": "Klient nemá povolenie, pretože sa nenachádza v zozname „Povolení klienti“.",
|
"filter_allowlist": "UPOZORNENIE: Táto akcia tiež vylúči pravidlo \"\"{{disallowed_rule}}\"\" zo zoznamu povolených klientov.",
|
||||||
"experimental": "Experimentálne"
|
"last_rule_in_allowlist": "Nemôžete zakázať tohto klienta, pretože vylúčenie pravidla \"{{disallowed_rule}}\" zakáže zoznam \"povolených klientov\".",
|
||||||
|
"experimental": "Experimentálne",
|
||||||
|
"use_saved_key": "Použiť predtým uložený kľúč"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -208,7 +208,7 @@
|
|||||||
"example_upstream_sdns": "lahko uporabite <0>DNS Žige</0> za reševalce <1>DNSCrypt</1> ali <2>DNS-prek-HTTPS</2>",
|
"example_upstream_sdns": "lahko uporabite <0>DNS Žige</0> za reševalce <1>DNSCrypt</1> ali <2>DNS-prek-HTTPS</2>",
|
||||||
"example_upstream_tcp": "redni DNS (nad TCP)",
|
"example_upstream_tcp": "redni DNS (nad TCP)",
|
||||||
"all_lists_up_to_date_toast": "Vsi seznami so že posodobljeni",
|
"all_lists_up_to_date_toast": "Vsi seznami so že posodobljeni",
|
||||||
"updated_upstream_dns_toast": "Posodobljeni Zagonske strežnike DNS",
|
"updated_upstream_dns_toast": "Gorvodni trežniki so uspešno shranjeni",
|
||||||
"dns_test_ok_toast": "Navedeni strežniki DNS delujejo pravilno",
|
"dns_test_ok_toast": "Navedeni strežniki DNS delujejo pravilno",
|
||||||
"dns_test_not_ok_toast": "Ni mogoče uporabiti: strežnika \"{{key}}\". Preverite, ali ste ga pravilno napisali",
|
"dns_test_not_ok_toast": "Ni mogoče uporabiti: strežnika \"{{key}}\". Preverite, ali ste ga pravilno napisali",
|
||||||
"unblock": "Omogoči",
|
"unblock": "Omogoči",
|
||||||
@@ -235,7 +235,7 @@
|
|||||||
"loading_table_status": "Nalaganje...",
|
"loading_table_status": "Nalaganje...",
|
||||||
"page_table_footer_text": "Stran",
|
"page_table_footer_text": "Stran",
|
||||||
"rows_table_footer_text": "vrstic",
|
"rows_table_footer_text": "vrstic",
|
||||||
"updated_custom_filtering_toast": "Posodobljena pravila filtriranja po meri",
|
"updated_custom_filtering_toast": "Pravila po meri so uspešno shranjena",
|
||||||
"rule_removed_from_custom_filtering_toast": "Pravilo je odstranjeno iz pravil filtriranja po meri: {{rule}}",
|
"rule_removed_from_custom_filtering_toast": "Pravilo je odstranjeno iz pravil filtriranja po meri: {{rule}}",
|
||||||
"rule_added_to_custom_filtering_toast": "Pravilo je dodano pravilom filtriranja po meri: {{rule}}",
|
"rule_added_to_custom_filtering_toast": "Pravilo je dodano pravilom filtriranja po meri: {{rule}}",
|
||||||
"query_log_response_status": "Stanje: {{value}}",
|
"query_log_response_status": "Stanje: {{value}}",
|
||||||
@@ -306,7 +306,7 @@
|
|||||||
"install_settings_dns_desc": "Vaše naprave ali usmerjevalnik boste morali konfigurirati za uporabo strežnika DNS na naslednjih naslovih:",
|
"install_settings_dns_desc": "Vaše naprave ali usmerjevalnik boste morali konfigurirati za uporabo strežnika DNS na naslednjih naslovih:",
|
||||||
"install_settings_all_interfaces": "Vsi vmesniki",
|
"install_settings_all_interfaces": "Vsi vmesniki",
|
||||||
"install_auth_title": "Preverjanje pristnosti",
|
"install_auth_title": "Preverjanje pristnosti",
|
||||||
"install_auth_desc": "Zelo priporočljivo je, da konfigurirate overovitev pristnosti gesla za vaš skrbniški spletni vmesnik AdGuard Home. Tudi če je dostopen v vašem lokalnem omrežju, je še vedno pomembno, da ga zaščitite pred neomejenim dostopom.",
|
"install_auth_desc": "Nastavljeno mora biti preverjanje pristnosti gesla za skrbniški spletni vmesnik AdGuard Home. Tudi če je AdGuard Home dostopen samo v vašem lokalnem omrežju, je še vedno pomembno, da ga zaščitite pred neomejenim dostopom.",
|
||||||
"install_auth_username": "Uporabniško ime",
|
"install_auth_username": "Uporabniško ime",
|
||||||
"install_auth_password": "Geslo",
|
"install_auth_password": "Geslo",
|
||||||
"install_auth_confirm": "Potrdite geslo",
|
"install_auth_confirm": "Potrdite geslo",
|
||||||
@@ -503,6 +503,7 @@
|
|||||||
"statistics_clear_confirm": "Ali ste prepričani, da želite počistiti statistiko?",
|
"statistics_clear_confirm": "Ali ste prepričani, da želite počistiti statistiko?",
|
||||||
"statistics_retention_confirm": "Ali ste prepričani, da želite spremeniti zadrževanje statistike? Če zmanjšate vrednost intervala, bodo nekateri podatki izgubljeni",
|
"statistics_retention_confirm": "Ali ste prepričani, da želite spremeniti zadrževanje statistike? Če zmanjšate vrednost intervala, bodo nekateri podatki izgubljeni",
|
||||||
"statistics_cleared": "Statistika je bila uspešno počiščena",
|
"statistics_cleared": "Statistika je bila uspešno počiščena",
|
||||||
|
"statistics_enable": "Omogoči statistiko",
|
||||||
"interval_hours": "{{count}} ur",
|
"interval_hours": "{{count}} ur",
|
||||||
"interval_hours_plural": "{{count}} ur",
|
"interval_hours_plural": "{{count}} ur",
|
||||||
"filters_configuration": "Nastavitve filtrov",
|
"filters_configuration": "Nastavitve filtrov",
|
||||||
@@ -597,7 +598,7 @@
|
|||||||
"cache_ttl_min_override_desc": "Razširite kratke vrednosti časa v živo (v sekundah), ki jih prejme strežnik za predpomnjenje, ko predpomni odzive DNS",
|
"cache_ttl_min_override_desc": "Razširite kratke vrednosti časa v živo (v sekundah), ki jih prejme strežnik za predpomnjenje, ko predpomni odzive DNS",
|
||||||
"cache_ttl_max_override_desc": "Nastavi največjo vrednost časa v živo (v sekundah) za vnose v predpomnilnik DNS",
|
"cache_ttl_max_override_desc": "Nastavi največjo vrednost časa v živo (v sekundah) za vnose v predpomnilnik DNS",
|
||||||
"ttl_cache_validation": "Najmanjša vrednost predpomnilnika TTL mora biti manjša ali enaka največji vrednosti",
|
"ttl_cache_validation": "Najmanjša vrednost predpomnilnika TTL mora biti manjša ali enaka največji vrednosti",
|
||||||
"cache_optimistic": "Optimistično",
|
"cache_optimistic": "Optimistično predpomnjenje",
|
||||||
"cache_optimistic_desc": "Poskrbi, da se AdGuard Home odzove iz predpomnilnika, tudi ko vnosi potečejo, in jih tudi poskusi osvežiti.",
|
"cache_optimistic_desc": "Poskrbi, da se AdGuard Home odzove iz predpomnilnika, tudi ko vnosi potečejo, in jih tudi poskusi osvežiti.",
|
||||||
"filter_category_general": "Splošno",
|
"filter_category_general": "Splošno",
|
||||||
"filter_category_security": "Varnost",
|
"filter_category_security": "Varnost",
|
||||||
@@ -612,6 +613,8 @@
|
|||||||
"click_to_view_queries": "Kliknite za prikaz poizvedb",
|
"click_to_view_queries": "Kliknite za prikaz poizvedb",
|
||||||
"port_53_faq_link": "Vrata 53 pogosto zasedajo storitve 'DNSStubListener' ali 'Sistemsko razrešene storitve'. Preberite <0>to navodilo</0> o tem, kako to rešiti.",
|
"port_53_faq_link": "Vrata 53 pogosto zasedajo storitve 'DNSStubListener' ali 'Sistemsko razrešene storitve'. Preberite <0>to navodilo</0> o tem, kako to rešiti.",
|
||||||
"adg_will_drop_dns_queries": "AdGuard Home bo izpustil vse poizvedbe DNS iz tega odjemalca.",
|
"adg_will_drop_dns_queries": "AdGuard Home bo izpustil vse poizvedbe DNS iz tega odjemalca.",
|
||||||
"client_not_in_allowed_clients": "Odjemalec ni dovoljen, ker ga ni na seznamu \"Dovoljeni odjemalci\".",
|
"filter_allowlist": "OPOZORILO: S to akcijo bo pravilo \"{{disallowed_rule}}\" izključeno s seznama dovoljenih odjemalcev.",
|
||||||
"experimental": "Eksperimentalno"
|
"last_rule_in_allowlist": "Tega odjemalca ni mogoče onemogočiti, ker izključitev pravila \"{{disallowed_rule}}\" bo ONEMOGOČILO seznam 'Dovoljeni odjemalci'.",
|
||||||
|
"experimental": "Eksperimentalno",
|
||||||
|
"use_saved_key": "Uporabi prej shranjeni ključ"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -247,6 +247,7 @@
|
|||||||
"source_label": "Izvor",
|
"source_label": "Izvor",
|
||||||
"found_in_known_domain_db": "Pronađeno u poznatim bazama podataka domena.",
|
"found_in_known_domain_db": "Pronađeno u poznatim bazama podataka domena.",
|
||||||
"category_label": "Kategorija",
|
"category_label": "Kategorija",
|
||||||
|
"rule_label": "Pravilo(-a)",
|
||||||
"list_label": "Lista",
|
"list_label": "Lista",
|
||||||
"unknown_filter": "Nepoznat filter {{filterId}}",
|
"unknown_filter": "Nepoznat filter {{filterId}}",
|
||||||
"known_tracker": "Poznato praćenje",
|
"known_tracker": "Poznato praćenje",
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
"client_settings": "Klientinställningar",
|
"client_settings": "Klientinställningar",
|
||||||
"bootstrap_dns": "Bootstrap-DNS-servrar",
|
"bootstrap_dns": "Bootstrap-DNS-servrar",
|
||||||
"bootstrap_dns_desc": "Bootstrap-DNS-servrar används för att slå upp DoH/DoT-resolvrarnas IP-adresser som du specificerat som uppström.",
|
"bootstrap_dns_desc": "Bootstrap-DNS-servrar används för att slå upp DoH/DoT-resolvrarnas IP-adresser som du specificerat som uppström.",
|
||||||
|
"local_ptr_placeholder": "Ange en serveradress per rad",
|
||||||
"check_dhcp_servers": "Letar efter DHCP-servrar",
|
"check_dhcp_servers": "Letar efter DHCP-servrar",
|
||||||
|
"save_config": "Spara konfiguration",
|
||||||
"enabled_dhcp": "DHCP-server aktiverad",
|
"enabled_dhcp": "DHCP-server aktiverad",
|
||||||
"disabled_dhcp": "Dhcp-server avaktiverad",
|
"disabled_dhcp": "Dhcp-server avaktiverad",
|
||||||
"dhcp_title": "DHCP-server (experimentell)",
|
"dhcp_title": "DHCP-server (experimentell)",
|
||||||
@@ -102,7 +104,7 @@
|
|||||||
"last_time_updated_table_header": "Uppdaterades senast",
|
"last_time_updated_table_header": "Uppdaterades senast",
|
||||||
"actions_table_header": "Åtgärder",
|
"actions_table_header": "Åtgärder",
|
||||||
"edit_table_action": "Redigera",
|
"edit_table_action": "Redigera",
|
||||||
"delete_table_action": "Ta bort",
|
"delete_table_action": "Radera",
|
||||||
"filters_and_hosts_hint": "AdGuard tillämpar grundläggande annonsblockeringsregler och värdfiltersyntaxer",
|
"filters_and_hosts_hint": "AdGuard tillämpar grundläggande annonsblockeringsregler och värdfiltersyntaxer",
|
||||||
"cancel_btn": "Avbryt",
|
"cancel_btn": "Avbryt",
|
||||||
"enter_name_hint": "Skriv in namn",
|
"enter_name_hint": "Skriv in namn",
|
||||||
@@ -175,7 +177,7 @@
|
|||||||
"install_auth_username": "Användarnamn",
|
"install_auth_username": "Användarnamn",
|
||||||
"install_auth_password": "Lösenord",
|
"install_auth_password": "Lösenord",
|
||||||
"install_auth_confirm": "Bekräfta lösenord",
|
"install_auth_confirm": "Bekräfta lösenord",
|
||||||
"install_auth_username_enter": "Skriv in användarnamn",
|
"install_auth_username_enter": "Ange användarnamn",
|
||||||
"install_auth_password_enter": "Skriv in lösenord",
|
"install_auth_password_enter": "Skriv in lösenord",
|
||||||
"install_step": "Steg",
|
"install_step": "Steg",
|
||||||
"install_devices_title": "Ställ in dina enheter",
|
"install_devices_title": "Ställ in dina enheter",
|
||||||
@@ -265,6 +267,7 @@
|
|||||||
"form_enter_ip": "Skriv in IP",
|
"form_enter_ip": "Skriv in IP",
|
||||||
"form_enter_mac": "Skriv in MAC",
|
"form_enter_mac": "Skriv in MAC",
|
||||||
"form_client_name": "Skriv in klientnamn",
|
"form_client_name": "Skriv in klientnamn",
|
||||||
|
"name": "Namn",
|
||||||
"client_global_settings": "Använda globala inställningar",
|
"client_global_settings": "Använda globala inställningar",
|
||||||
"client_deleted": "Klient \"{{key}}\" har raderats",
|
"client_deleted": "Klient \"{{key}}\" har raderats",
|
||||||
"client_added": "Klient \"{{key}}\" har lagts till",
|
"client_added": "Klient \"{{key}}\" har lagts till",
|
||||||
@@ -301,14 +304,18 @@
|
|||||||
"setup_dns_notice": "För att kunna använda <1>DNS-över-HTTPS</1> eller <1>DNS-över-TLS</1>, behöver du <0>konfigurera Kryptering</0> i AdGuard Home-inställningar.",
|
"setup_dns_notice": "För att kunna använda <1>DNS-över-HTTPS</1> eller <1>DNS-över-TLS</1>, behöver du <0>konfigurera Kryptering</0> i AdGuard Home-inställningar.",
|
||||||
"rewrite_added": "DNS-omskrivning för \"{{key}}\" lyckad",
|
"rewrite_added": "DNS-omskrivning för \"{{key}}\" lyckad",
|
||||||
"rewrite_deleted": "DNS-omskrivning för \"{{key}}\" har tagits bort",
|
"rewrite_deleted": "DNS-omskrivning för \"{{key}}\" har tagits bort",
|
||||||
|
"interval_6_hour": "6 timmar",
|
||||||
"interval_24_hour": "24 timmar",
|
"interval_24_hour": "24 timmar",
|
||||||
|
"interval_days": "{{count}} dag",
|
||||||
|
"interval_days_plural": "{{count}} dagar",
|
||||||
"domain": "Domän",
|
"domain": "Domän",
|
||||||
"answer": "Svar",
|
"answer": "Svar",
|
||||||
"statistics_retention_desc": "Om du minskar intervallet kommer viss data att gå förlorad",
|
"statistics_retention_desc": "Om du minskar intervallet kommer viss data att gå förlorad",
|
||||||
"statistics_clear": " Rensa statistik",
|
"statistics_clear": "Rensa statistik",
|
||||||
"statistics_clear_confirm": "Är du säker på att du vill radera statistiken?",
|
"statistics_clear_confirm": "Är du säker på att du vill radera statistiken?",
|
||||||
"statistics_retention_confirm": "Är du säker på att du vill ändra retentionstiden för statistik? Om du minskar intervallet kommer viss data att gå förlorad",
|
"statistics_retention_confirm": "Är du säker på att du vill ändra retentionstiden för statistik? Om du minskar intervallet kommer viss data att gå förlorad",
|
||||||
"statistics_cleared": "Statistiken har rensats",
|
"statistics_cleared": "Statistiken har rensats",
|
||||||
|
"statistics_enable": "Aktivera statistik",
|
||||||
"interval_hours": "{{count}} timme",
|
"interval_hours": "{{count}} timme",
|
||||||
"interval_hours_plural": "{{count}} timmar",
|
"interval_hours_plural": "{{count}} timmar",
|
||||||
"filters_configuration": "Filterinställningar",
|
"filters_configuration": "Filterinställningar",
|
||||||
@@ -329,7 +336,9 @@
|
|||||||
"descr": "Beskrivning",
|
"descr": "Beskrivning",
|
||||||
"whois": "Whois",
|
"whois": "Whois",
|
||||||
"filtering_rules_learn_more": "<0>Mer info</0> om att skapa dina egna blockeringslistor för värdar.",
|
"filtering_rules_learn_more": "<0>Mer info</0> om att skapa dina egna blockeringslistor för värdar.",
|
||||||
|
"try_again": "Försök igen",
|
||||||
"show_blocked_responses": "Blockerade",
|
"show_blocked_responses": "Blockerade",
|
||||||
"blocked_adult_websites": "Blockerade vuxensajter",
|
"blocked_adult_websites": "Blockerade vuxensajter",
|
||||||
"blocked_threats": "Blockerade hot"
|
"blocked_threats": "Blockerade hot",
|
||||||
|
"use_saved_key": "Använd den tidigare sparade nyckeln"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,19 +95,19 @@
|
|||||||
"protocol": "Protokol",
|
"protocol": "Protokol",
|
||||||
"on": "AÇIK",
|
"on": "AÇIK",
|
||||||
"off": "KAPALI",
|
"off": "KAPALI",
|
||||||
"copyright": "Telif hakkı",
|
"copyright": "Telif Hakkı",
|
||||||
"homepage": "Ana sayfa",
|
"homepage": "Ana Sayfa",
|
||||||
"report_an_issue": "Bir sorun bildir",
|
"report_an_issue": "Bir sorun bildir",
|
||||||
"privacy_policy": "Gizlilik ilkesi",
|
"privacy_policy": "Gizlilik Politikası",
|
||||||
"enable_protection": "Korumayı etkinleştir",
|
"enable_protection": "Korumayı etkinleştir",
|
||||||
"enabled_protection": "Koruma etkileştirildi",
|
"enabled_protection": "Koruma etkileştirildi",
|
||||||
"disable_protection": "Korumayı durdur",
|
"disable_protection": "Korumayı durdur",
|
||||||
"disabled_protection": "Koruma durduruldu",
|
"disabled_protection": "Koruma durduruldu",
|
||||||
"refresh_statics": "İstatistikleri yenile",
|
"refresh_statics": "İstatistikleri yenile",
|
||||||
"dns_query": "DNS Sorguları",
|
"dns_query": "DNS Sorguları",
|
||||||
"blocked_by": "<0>Filtreler tarafından engellendi</0>",
|
"blocked_by": "<0>Filtreler tarafından engellenen</0>",
|
||||||
"stats_malware_phishing": "Kötü amaçlı yazılım ve kimlik avı engellendi",
|
"stats_malware_phishing": "Engellenen kötü amaçlı yazılım ve kimlik avı",
|
||||||
"stats_adult": "Yetişkin içerikli site engellendi",
|
"stats_adult": "Engellenen yetişkin içerikli siteler",
|
||||||
"stats_query_domain": "En fazla sorgulanan alan adları",
|
"stats_query_domain": "En fazla sorgulanan alan adları",
|
||||||
"for_last_24_hours": "son 24 saat içindekiler",
|
"for_last_24_hours": "son 24 saat içindekiler",
|
||||||
"for_last_days": "son {{count}} gün boyunca",
|
"for_last_days": "son {{count}} gün boyunca",
|
||||||
@@ -123,34 +123,34 @@
|
|||||||
"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 engelleme listeleri tarafından engellenen DNS isteklerinin sayısı",
|
"number_of_dns_query_blocked_24_hours": "Reklam engelleme filtreleri ve 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 mili saniye 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 bilgisayar listelerini kullanarak alan adlarını engelle",
|
"block_domain_use_filters_and_hosts": "Filtre ve ana bilgisayar listelerini kullanarak alan adlarını engelle",
|
||||||
"filters_block_toggle_hint": "<a>Filtreler</a> sayfasından engelleme kurallarını ayarlayabilirsiniz.",
|
"filters_block_toggle_hint": "<a>Filtreler</a> sayfasından engelleme kurallarını ayarlayabilirsiniz.",
|
||||||
"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.",
|
||||||
"use_adguard_parental": "AdGuard ebeveyn kontrolü web hizmetini kullan",
|
"use_adguard_parental": "AdGuard ebeveyn denetimi web hizmetini kullan",
|
||||||
"use_adguard_parental_hint": "AdGuard Home, alan adının yetişkin içerik bulundurup bulundurmadığını kontrol eder. Gezinti koruması web hizmeti ile kullandığımız aynı gizlilik dostu API'yi kullanır.",
|
"use_adguard_parental_hint": "AdGuard Home, alan adının yetişkin içerik bulundurup bulundurmadığını kontrol eder. Gezinti koruması web hizmeti ile kullandığımız aynı gizlilik dostu API'yi kullanır.",
|
||||||
"enforce_safe_search": "Güvenli aramayı kullan",
|
"enforce_safe_search": "Güvenli aramayı kullan",
|
||||||
"enforce_save_search_hint": "AdGuard Home, şu arama motorlarında güvenli aramayı uygular: Google, YouTube, Bing, DuckDuckGo, Yandex ve Pixabay.",
|
"enforce_save_search_hint": "AdGuard Home, şu arama motorlarında güvenli aramayı uygular: Google, YouTube, Bing, DuckDuckGo, Yandex ve Pixabay.",
|
||||||
"no_servers_specified": "Sunucu belirtilmedi",
|
"no_servers_specified": "Sunucu belirtilmedi",
|
||||||
"general_settings": "Genel ayarlar",
|
"general_settings": "Genel ayarlar",
|
||||||
"dns_settings": "DNS ayarları",
|
"dns_settings": "DNS ayarları",
|
||||||
"dns_blocklists": "DNS engelleme listeleri",
|
"dns_blocklists": "DNS engel listeleri",
|
||||||
"dns_allowlists": "DNS izin listeleri",
|
"dns_allowlists": "DNS izin listeleri",
|
||||||
"dns_blocklists_desc": "AdGuard Home, engelleme listeleriyle eşleşen alan adlarını engeller.",
|
"dns_blocklists_desc": "AdGuard Home, engel listeleriyle eşleşen alan adlarını engeller.",
|
||||||
"dns_allowlists_desc": "DNS izin listesindeki alan adlarına, engelleme listesinde olsa bile izin verilir.",
|
"dns_allowlists_desc": "DNS izin listesindeki alan adlarına, engel listesinde olsa bile izin verilir.",
|
||||||
"custom_filtering_rules": "Özel filtreleme kuralları",
|
"custom_filtering_rules": "Özel filtreleme kuralları",
|
||||||
"encryption_settings": "Şifreleme ayarları",
|
"encryption_settings": "Şifreleme ayarları",
|
||||||
"dhcp_settings": "DHCP ayarları",
|
"dhcp_settings": "DHCP ayarları",
|
||||||
"upstream_dns": "Üst DNS sunucusu",
|
"upstream_dns": "Üst DNS sunucusu",
|
||||||
"upstream_dns_help": "Her satıra bir sunucu adresi girin. Üst DNS sunucularını yapılandırma hakkında <a>daha fazla bilgi edinin</a>.",
|
"upstream_dns_help": "Her satıra bir sunucu adresi girin. Üst DNS sunucularını yapılandırma hakkında <a>daha fazla bilgi edinin</a>.",
|
||||||
"upstream_dns_configured_in_file": "{{path}} içinde yapılandırıldı",
|
"upstream_dns_configured_in_file": "{{path}} dosyasında yapılandırıldı",
|
||||||
"test_upstream_btn": "Üst sunucuyu test et",
|
"test_upstream_btn": "Üst sunucuyu test et",
|
||||||
"upstreams": "Üst kaynak",
|
"upstreams": "Üst kaynak",
|
||||||
"apply_btn": "Uygula",
|
"apply_btn": "Uygula",
|
||||||
@@ -158,8 +158,8 @@
|
|||||||
"enabled_filtering_toast": "Filtreleme etkin",
|
"enabled_filtering_toast": "Filtreleme etkin",
|
||||||
"disabled_safe_browsing_toast": "Güvenli gezinti devre dışı",
|
"disabled_safe_browsing_toast": "Güvenli gezinti devre dışı",
|
||||||
"enabled_safe_browsing_toast": "Güvenli gezinti etkin",
|
"enabled_safe_browsing_toast": "Güvenli gezinti etkin",
|
||||||
"disabled_parental_toast": "Ebeveyn kontrolü devre dışı",
|
"disabled_parental_toast": "Ebeveyn denetimi devre dışı",
|
||||||
"enabled_parental_toast": "Ebeveyn kontrolü etkin",
|
"enabled_parental_toast": "Ebeveyn denetimi etkin",
|
||||||
"disabled_safe_search_toast": "Güvenli arama devre dışı",
|
"disabled_safe_search_toast": "Güvenli arama devre dışı",
|
||||||
"enabled_save_search_toast": "Güvenli arama etkin",
|
"enabled_save_search_toast": "Güvenli arama etkin",
|
||||||
"enabled_table_header": "Etkin",
|
"enabled_table_header": "Etkin",
|
||||||
@@ -173,21 +173,21 @@
|
|||||||
"delete_table_action": "Sil",
|
"delete_table_action": "Sil",
|
||||||
"elapsed": "Geçen zaman",
|
"elapsed": "Geçen zaman",
|
||||||
"filters_and_hosts_hint": "AdGuard Home, temel reklam engelleme kurallarını ve ana bilgisayar engelleme dosyalarının söz dizimini anlar.",
|
"filters_and_hosts_hint": "AdGuard Home, temel reklam engelleme kurallarını ve ana bilgisayar engelleme dosyalarının söz dizimini anlar.",
|
||||||
"no_blocklist_added": "Engelleme listesi eklenmedi",
|
"no_blocklist_added": "Engel listesi eklenmedi",
|
||||||
"no_whitelist_added": "İzin listesi eklenmedi",
|
"no_whitelist_added": "İzin listesi eklenmedi",
|
||||||
"add_blocklist": "Engelleme listesi ekle",
|
"add_blocklist": "Engel listesi ekle",
|
||||||
"add_allowlist": "İzin listesi ekle",
|
"add_allowlist": "İzin listesi ekle",
|
||||||
"cancel_btn": "İptal",
|
"cancel_btn": "İptal",
|
||||||
"enter_name_hint": "İsim girin",
|
"enter_name_hint": "İsim girin",
|
||||||
"enter_url_or_path_hint": "Listenin URL adresini veya dosya konumunu girin",
|
"enter_url_or_path_hint": "Listenin URL adresini veya dosya konumunu girin",
|
||||||
"check_updates_btn": "Güncellemeleri denetle",
|
"check_updates_btn": "Güncellemeleri denetle",
|
||||||
"new_blocklist": "Yeni engelleme listesi",
|
"new_blocklist": "Yeni engel listesi",
|
||||||
"new_allowlist": "Yeni izin listesi",
|
"new_allowlist": "Yeni izin listesi",
|
||||||
"edit_blocklist": "Engelleme listesini düzenle",
|
"edit_blocklist": "Engel listesini düzenle",
|
||||||
"edit_allowlist": "İzin listesini düzenle",
|
"edit_allowlist": "İzin listesini düzenle",
|
||||||
"choose_blocklist": "Engelleme listelerini seçin",
|
"choose_blocklist": "Engel listelerini seçin",
|
||||||
"choose_allowlist": "İzin listelerini seçin",
|
"choose_allowlist": "İzin listelerini seçin",
|
||||||
"enter_valid_blocklist": "Engelleme listesine geçerli bir URL girin.",
|
"enter_valid_blocklist": "Engel listesine geçerli bir URL girin.",
|
||||||
"enter_valid_allowlist": "İzin listesine geçerli bir URL girin.",
|
"enter_valid_allowlist": "İzin listesine geçerli bir URL girin.",
|
||||||
"form_error_url_format": "Geçersiz URL biçimi",
|
"form_error_url_format": "Geçersiz URL biçimi",
|
||||||
"form_error_url_or_path_format": "Listenin URL adresi veya dosya konumu geçersiz",
|
"form_error_url_or_path_format": "Listenin URL adresi veya dosya konumu geçersiz",
|
||||||
@@ -208,7 +208,7 @@
|
|||||||
"example_upstream_sdns": "<1>DNSCrypt</1> veya <2>DNS-over-HTTPS</2> çözümleyicileri için <0>DNS Damgaları</0> kullanabilirsiniz",
|
"example_upstream_sdns": "<1>DNSCrypt</1> veya <2>DNS-over-HTTPS</2> çözümleyicileri için <0>DNS Damgaları</0> kullanabilirsiniz",
|
||||||
"example_upstream_tcp": "normal DNS (TCP üzerinden)",
|
"example_upstream_tcp": "normal DNS (TCP üzerinden)",
|
||||||
"all_lists_up_to_date_toast": "Tüm listeler güncel durumda",
|
"all_lists_up_to_date_toast": "Tüm listeler güncel durumda",
|
||||||
"updated_upstream_dns_toast": "Üst DNS sunucuları güncellendi",
|
"updated_upstream_dns_toast": "Üst sunucular başarıyla kaydedildi",
|
||||||
"dns_test_ok_toast": "Belirtilen DNS sunucuları düzgün çalışıyor",
|
"dns_test_ok_toast": "Belirtilen DNS sunucuları düzgün çalışıyor",
|
||||||
"dns_test_not_ok_toast": "Sunucu \"{{key}}\": kullanılamıyor, lütfen doğru yazdığınızdan emin olun",
|
"dns_test_not_ok_toast": "Sunucu \"{{key}}\": kullanılamıyor, lütfen doğru yazdığınızdan emin olun",
|
||||||
"unblock": "Engeli kaldır",
|
"unblock": "Engeli kaldır",
|
||||||
@@ -235,7 +235,7 @@
|
|||||||
"loading_table_status": "Yükleniyor...",
|
"loading_table_status": "Yükleniyor...",
|
||||||
"page_table_footer_text": "Sayfa",
|
"page_table_footer_text": "Sayfa",
|
||||||
"rows_table_footer_text": "satır",
|
"rows_table_footer_text": "satır",
|
||||||
"updated_custom_filtering_toast": "Özel filtreleme kuralları güncellendi",
|
"updated_custom_filtering_toast": "Özel kurallar başarıyla kaydedildi",
|
||||||
"rule_removed_from_custom_filtering_toast": "Özel filtreleme kurallarından kaldırıldı: {{rule}}",
|
"rule_removed_from_custom_filtering_toast": "Özel filtreleme kurallarından kaldırıldı: {{rule}}",
|
||||||
"rule_added_to_custom_filtering_toast": "Özel filtreleme kurallarına eklendi: {{rule}}",
|
"rule_added_to_custom_filtering_toast": "Özel filtreleme kurallarına eklendi: {{rule}}",
|
||||||
"query_log_response_status": "Durum: {{value}}",
|
"query_log_response_status": "Durum: {{value}}",
|
||||||
@@ -306,7 +306,7 @@
|
|||||||
"install_settings_dns_desc": "Cihazlarınızı veya yönlendiricinizi şu adresteki DNS sunucusunu kullanması için ayarlamanız gerekecek:",
|
"install_settings_dns_desc": "Cihazlarınızı veya yönlendiricinizi şu adresteki DNS sunucusunu kullanması için ayarlamanız gerekecek:",
|
||||||
"install_settings_all_interfaces": "Tüm arayüzler",
|
"install_settings_all_interfaces": "Tüm arayüzler",
|
||||||
"install_auth_title": "Kimlik Doğrulama",
|
"install_auth_title": "Kimlik Doğrulama",
|
||||||
"install_auth_desc": "AdGuard Home yönetici web arayüzüne erişim için kullanıcı adı ve şifre yapılandırmanız önemle tavsiye edilir. Yalnızca yerel ağınızdan erişilebilir olsa bile izinsiz erişimden korumak yine de önemlidir.",
|
"install_auth_desc": "AdGuard Home yönetim web arayüzü için şifre doğrulaması yapılandırılmalıdır. AdGuard Home'a yalnızca yerel ağınızdan erişilebilir olsa bile, onu sınırsız erişimden korumak yine de önemlidir.",
|
||||||
"install_auth_username": "Kullanıcı adı",
|
"install_auth_username": "Kullanıcı adı",
|
||||||
"install_auth_password": "Parola",
|
"install_auth_password": "Parola",
|
||||||
"install_auth_confirm": "Parolayı onayla",
|
"install_auth_confirm": "Parolayı onayla",
|
||||||
@@ -352,7 +352,7 @@
|
|||||||
"encryption_config_saved": "Şifreleme yapılandırması kaydedildi",
|
"encryption_config_saved": "Şifreleme yapılandırması kaydedildi",
|
||||||
"encryption_server": "Sunucu adı",
|
"encryption_server": "Sunucu adı",
|
||||||
"encryption_server_enter": "Alan adınızı girin",
|
"encryption_server_enter": "Alan adınızı girin",
|
||||||
"encryption_server_desc": "HTTPS kullanmak için SSL sertifikanızla veya Willcard sertifikanızla eşleşen sunucu adını girmeniz gerekir. Bu alan ayarlanmazsa, herhangi bir alan adının TLS bağlantılarını kabul eder.",
|
"encryption_server_desc": "HTTPS kullanmak için SSL sertifikanızla veya joker sertifikanızla eşleşen sunucu adını girmeniz gerekir. Bu alan ayarlanmazsa, herhangi bir alan adının TLS bağlantılarını kabul eder.",
|
||||||
"encryption_redirect": "Otomatik olarak HTTPS'e yönlendir",
|
"encryption_redirect": "Otomatik olarak HTTPS'e yönlendir",
|
||||||
"encryption_redirect_desc": "Etkinleştirirseniz, AdGuard Home sizi HTTP adresi yerine HTTPS adresine yönlendirir.",
|
"encryption_redirect_desc": "Etkinleştirirseniz, AdGuard Home sizi HTTP adresi yerine HTTPS adresine yönlendirir.",
|
||||||
"encryption_https": "HTTPS bağlantı noktası",
|
"encryption_https": "HTTPS bağlantı noktası",
|
||||||
@@ -362,7 +362,7 @@
|
|||||||
"encryption_doq": "DNS-over-QUIC bağlantı noktası",
|
"encryption_doq": "DNS-over-QUIC bağlantı noktası",
|
||||||
"encryption_doq_desc": "Bu bağlantı noktası yapılandırılırsa, AdGuard Home, DNS-over-QUIC sunucusunu bu bağlantı noktası üzerinden çalıştıracaktır. Bu özellik deneme aşamasındadır ve güvenilir olmayabilir. Ayrıca, şu anda bu özelliği destekleyen çok fazla istemci yok.",
|
"encryption_doq_desc": "Bu bağlantı noktası yapılandırılırsa, AdGuard Home, DNS-over-QUIC sunucusunu bu bağlantı noktası üzerinden çalıştıracaktır. Bu özellik deneme aşamasındadır ve güvenilir olmayabilir. Ayrıca, şu anda bu özelliği destekleyen çok fazla istemci yok.",
|
||||||
"encryption_certificates": "Sertifikalar",
|
"encryption_certificates": "Sertifikalar",
|
||||||
"encryption_certificates_desc": "Şifrelemeyi kullanmak için alan adınız için geçerli bir SSL sertifika zinciri sağlamanız gerekir. <0>{{link}}</0> adresinden ücretsiz bir sertifika alabilir veya güvenilir Sertifika Yetkililerinden satın alabilirsiniz.",
|
"encryption_certificates_desc": "Şifrelemeyi kullanmak için alan adınıza geçerli bir SSL sertifika zinciri sağlamanız gerekir. <0>{{link}}</0> adresinden ücretsiz bir sertifika alabilir veya güvenilir Sertifika Yetkililerinden satın alabilirsiniz.",
|
||||||
"encryption_certificates_input": "PEM biçimindeki sertifikalarınızı kopyalayıp buraya yapıştırın.",
|
"encryption_certificates_input": "PEM biçimindeki sertifikalarınızı kopyalayıp buraya yapıştırın.",
|
||||||
"encryption_status": "Durum",
|
"encryption_status": "Durum",
|
||||||
"encryption_expire": "Bitiş tarihi",
|
"encryption_expire": "Bitiş tarihi",
|
||||||
@@ -476,7 +476,7 @@
|
|||||||
"blocked_services_saved": "Engellenen hizmetler başarıyla kaydedildi",
|
"blocked_services_saved": "Engellenen hizmetler başarıyla kaydedildi",
|
||||||
"blocked_services_global": "Genel olarak engellenen hizmetleri kullan",
|
"blocked_services_global": "Genel olarak engellenen hizmetleri kullan",
|
||||||
"blocked_service": "Engellenen hizmet",
|
"blocked_service": "Engellenen hizmet",
|
||||||
"block_all": "Hepsini engelle",
|
"block_all": "Tümünü engelle",
|
||||||
"unblock_all": "Tüm engellemeyi kaldır",
|
"unblock_all": "Tüm engellemeyi kaldır",
|
||||||
"encryption_certificate_path": "Sertifika yolu",
|
"encryption_certificate_path": "Sertifika yolu",
|
||||||
"encryption_private_key_path": "Özel anahtar yolu",
|
"encryption_private_key_path": "Özel anahtar yolu",
|
||||||
@@ -503,11 +503,12 @@
|
|||||||
"statistics_clear_confirm": "İstatistikleri temizlemek istediğinizden emin misiniz?",
|
"statistics_clear_confirm": "İstatistikleri temizlemek istediğinizden emin misiniz?",
|
||||||
"statistics_retention_confirm": "İstatistik saklama süresini değiştirmek istediğinizden emin misiniz? Zaman değerini azaltırsanız, bazı veriler kaybolacaktır",
|
"statistics_retention_confirm": "İstatistik saklama süresini değiştirmek istediğinizden emin misiniz? Zaman değerini azaltırsanız, bazı veriler kaybolacaktır",
|
||||||
"statistics_cleared": "İstatistikler başarıyla temizlendi",
|
"statistics_cleared": "İstatistikler başarıyla temizlendi",
|
||||||
|
"statistics_enable": "İstatistikleri etkinleştir",
|
||||||
"interval_hours": "{{count}} saat",
|
"interval_hours": "{{count}} saat",
|
||||||
"interval_hours_plural": "{{count}} saat",
|
"interval_hours_plural": "{{count}} saat",
|
||||||
"filters_configuration": "Filtre yapılandırması",
|
"filters_configuration": "Filtre yapılandırması",
|
||||||
"filters_enable": "Filtreleri etkinleştir",
|
"filters_enable": "Filtreleri etkinleştir",
|
||||||
"filters_interval": "Filtreleri güncelleme sıklığı",
|
"filters_interval": "Filtre güncelleme sıklığı",
|
||||||
"disabled": "Devre dışı",
|
"disabled": "Devre dışı",
|
||||||
"username_label": "Kullanıcı adı",
|
"username_label": "Kullanıcı adı",
|
||||||
"username_placeholder": "Kullanıcı adını girin",
|
"username_placeholder": "Kullanıcı adını girin",
|
||||||
@@ -576,16 +577,16 @@
|
|||||||
"validated_with_dnssec": "DNSSEC ile doğrulandı",
|
"validated_with_dnssec": "DNSSEC ile doğrulandı",
|
||||||
"all_queries": "Tüm sorgular",
|
"all_queries": "Tüm sorgular",
|
||||||
"show_blocked_responses": "Engellendi",
|
"show_blocked_responses": "Engellendi",
|
||||||
"show_whitelisted_responses": "İzin verildi",
|
"show_whitelisted_responses": "İzin verilen",
|
||||||
"show_processed_responses": "İşlendi",
|
"show_processed_responses": "İşlendi",
|
||||||
"blocked_safebrowsing": "Güvenli gezinti tarafından engellendi",
|
"blocked_safebrowsing": "Güvenli gezinti tarafından engellendi",
|
||||||
"blocked_adult_websites": "Yetişkin içerikli site engellendi",
|
"blocked_adult_websites": "Engellenen yetişkin içerikli siteler",
|
||||||
"blocked_threats": "Engellenen Tehditler",
|
"blocked_threats": "Engellenen tehditler",
|
||||||
"allowed": "İzin verilen",
|
"allowed": "İzin verildi",
|
||||||
"filtered": "Filtrelenen",
|
"filtered": "Filtrelenen",
|
||||||
"rewritten": "Yeniden yazılan",
|
"rewritten": "Yeniden yazılan",
|
||||||
"safe_search": "Güvenli arama",
|
"safe_search": "Güvenli arama",
|
||||||
"blocklist": "Engelleme listesi",
|
"blocklist": "Engel listesi",
|
||||||
"milliseconds_abbreviation": "ms",
|
"milliseconds_abbreviation": "ms",
|
||||||
"cache_size": "Önbellek boyutu",
|
"cache_size": "Önbellek boyutu",
|
||||||
"cache_size_desc": "DNS önbellek boyutu (bayt cinsinden)",
|
"cache_size_desc": "DNS önbellek boyutu (bayt cinsinden)",
|
||||||
@@ -597,7 +598,7 @@
|
|||||||
"cache_ttl_min_override_desc": "DNS yanıtlarını önbelleğe alırken üst sunucudan alınan kullanım süresi değerini uzatın (saniye olarak)",
|
"cache_ttl_min_override_desc": "DNS yanıtlarını önbelleğe alırken üst sunucudan alınan kullanım süresi değerini uzatın (saniye olarak)",
|
||||||
"cache_ttl_max_override_desc": "DNS önbelleğindeki girişler için maksimum kullanım süresi değerini ayarlayın (saniye olarak)",
|
"cache_ttl_max_override_desc": "DNS önbelleğindeki girişler için maksimum kullanım süresi değerini ayarlayın (saniye olarak)",
|
||||||
"ttl_cache_validation": "Minimum önbellek TTL değeri, maksimum değerden küçük veya bu değere eşit olmalıdır",
|
"ttl_cache_validation": "Minimum önbellek TTL değeri, maksimum değerden küçük veya bu değere eşit olmalıdır",
|
||||||
"cache_optimistic": "İyimser",
|
"cache_optimistic": "İyimser önbelleğe alma",
|
||||||
"cache_optimistic_desc": "Girişlerin süresi dolduğunda bile AdGuard Home'un önbellekten yanıt vermesini sağlayın ve bunları yenilemeye çalışın.",
|
"cache_optimistic_desc": "Girişlerin süresi dolduğunda bile AdGuard Home'un önbellekten yanıt vermesini sağlayın ve bunları yenilemeye çalışın.",
|
||||||
"filter_category_general": "Genel",
|
"filter_category_general": "Genel",
|
||||||
"filter_category_security": "Güvenlik",
|
"filter_category_security": "Güvenlik",
|
||||||
@@ -606,12 +607,14 @@
|
|||||||
"filter_category_general_desc": "Çoğu cihazda izlemeyi ve reklamları engelleyen listeler",
|
"filter_category_general_desc": "Çoğu cihazda izlemeyi ve reklamları engelleyen listeler",
|
||||||
"filter_category_security_desc": "Kötü amaçlı, kimlik avı ve dolandırıcılık alan adlarını engellemek için özel olarak tasarlanmış listeler",
|
"filter_category_security_desc": "Kötü amaçlı, kimlik avı ve dolandırıcılık alan adlarını engellemek için özel olarak tasarlanmış listeler",
|
||||||
"filter_category_regional_desc": "Bölgesel reklamlara ve izleme sunucularına odaklanan listeler",
|
"filter_category_regional_desc": "Bölgesel reklamlara ve izleme sunucularına odaklanan listeler",
|
||||||
"filter_category_other_desc": "Diğer engelleme listeleri",
|
"filter_category_other_desc": "Diğer engel listeleri",
|
||||||
"setup_config_to_enable_dhcp_server": "DHCP sunucusunu etkinleştirmek için kurulum yapılandırması",
|
"setup_config_to_enable_dhcp_server": "DHCP sunucusunu etkinleştirmek için kurulum yapılandırması",
|
||||||
"original_response": "Gerçek yanıt",
|
"original_response": "Gerçek yanıt",
|
||||||
"click_to_view_queries": "Sorguları görmek için tıklayın",
|
"click_to_view_queries": "Sorguları görmek için tıklayın",
|
||||||
"port_53_faq_link": "53 numaralı bağlantı noktası genellikle \"DNSStubListener\" veya \"systemd-resolved\" hizmetleri tarafından kullanılır. Lütfen bu sorunun nasıl çözüleceğine ilişkin <0>bu talimatı</0> okuyun.",
|
"port_53_faq_link": "53 numaralı bağlantı noktası genellikle \"DNSStubListener\" veya \"systemd-resolved\" hizmetleri tarafından kullanılır. Lütfen bu sorunun nasıl çözüleceğine ilişkin <0>bu talimatı</0> okuyun.",
|
||||||
"adg_will_drop_dns_queries": "AdGuard Home, bu istemciden gelen tüm DNS sorgularını yok sayar.",
|
"adg_will_drop_dns_queries": "AdGuard Home, bu istemciden gelen tüm DNS sorgularını yok sayar.",
|
||||||
"client_not_in_allowed_clients": "\"İzin verilen istemciler\" listesinde olmadığı için istemciye izin verilmiyor.",
|
"filter_allowlist": "UYARI: Bu işlem ayrıca \"{{disallowed_rule}}\" kuralını izin verilen istemciler listesinden hariç tutacaktır.",
|
||||||
"experimental": "Deneysel"
|
"last_rule_in_allowlist": "\"{{disallowed_rule}}\" kuralı hariç tutulduğunda \"İzin verilen istemciler\" listesi DEVRE DIŞI bırakılacağı için bu istemciye izin verilemez.",
|
||||||
|
"experimental": "Deneysel",
|
||||||
|
"use_saved_key": "Önceden kaydedilmiş anahtarı kullan"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -8,10 +8,15 @@
|
|||||||
"load_balancing_desc": "Chỉ truy xuất một máy chủ trong cùng thời điểm. AdGuard Home sẽ sử dụng thuật toán trọng số ngẫu nhiên để chọn một máy chủ nhanh nhất và sử dụng máy chủ đó thường xuyên hơn.",
|
"load_balancing_desc": "Chỉ truy xuất một máy chủ trong cùng thời điểm. AdGuard Home sẽ sử dụng thuật toán trọng số ngẫu nhiên để chọn một máy chủ nhanh nhất và sử dụng máy chủ đó thường xuyên hơn.",
|
||||||
"bootstrap_dns": "Máy chủ DNS Bootstrap",
|
"bootstrap_dns": "Máy chủ DNS Bootstrap",
|
||||||
"bootstrap_dns_desc": "Máy chủ DNS Bootstrap được sử dụng để phân giải địa chỉ IP của bộ phân giải DoH/DoT mà bạn chỉ định là ngược tuyến.",
|
"bootstrap_dns_desc": "Máy chủ DNS Bootstrap được sử dụng để phân giải địa chỉ IP của bộ phân giải DoH/DoT mà bạn chỉ định là ngược tuyến.",
|
||||||
|
"local_ptr_title": "Máy chủ DNS riêng tư",
|
||||||
"local_ptr_desc": "Máy chủ DNS hoặc các máy chủ mà AdGuard Home sẽ sử dụng cho các truy vấn về tài nguyên được phân phối cục bộ. Ví dụ: máy chủ này sẽ được sử dụng để phân giải tên máy khách của máy khách cho các máy khách có địa chỉ IP riêng. Nếu không được cài đặt, AdGuard Home sẽ tự động sử dụng trình phân giải DNS mặc định của bạn.",
|
"local_ptr_desc": "Máy chủ DNS hoặc các máy chủ mà AdGuard Home sẽ sử dụng cho các truy vấn về tài nguyên được phân phối cục bộ. Ví dụ: máy chủ này sẽ được sử dụng để phân giải tên máy khách của máy khách cho các máy khách có địa chỉ IP riêng. Nếu không được cài đặt, AdGuard Home sẽ tự động sử dụng trình phân giải DNS mặc định của bạn.",
|
||||||
|
"local_ptr_default_resolver": "Theo mặc định, AdGuard Home sử dụng các hệ thống phân giải tên miền ngược sau: {{ip}}.",
|
||||||
|
"local_ptr_no_default_resolver": "AdGuard Home không thể xác định hệ thống phân giải tên miền ngược riêng phù hợp cho hệ thống này.",
|
||||||
"local_ptr_placeholder": "Nhập một địa chỉ máy chủ trên mỗi dòng",
|
"local_ptr_placeholder": "Nhập một địa chỉ máy chủ trên mỗi dòng",
|
||||||
"resolve_clients_title": "Kích hoạt cho phép phân giải ngược về địa chỉ IP của máy khách",
|
"resolve_clients_title": "Kích hoạt cho phép phân giải ngược về địa chỉ IP của máy khách",
|
||||||
"resolve_clients_desc": "Nếu được bật, AdGuard Home sẽ cố gắng phân giải ngược lại địa chỉ IP của khách hàng thành tên máy chủ của họ bằng cách gửi các truy vấn PTR tới trình phân giải tương ứng (máy chủ DNS riêng cho máy khách cục bộ, máy chủ ngược dòng cho máy khách có địa chỉ IP công cộng).",
|
"resolve_clients_desc": "Nếu được bật, AdGuard Home sẽ cố gắng phân giải ngược lại địa chỉ IP của khách hàng thành tên máy chủ của họ bằng cách gửi các truy vấn PTR tới trình phân giải tương ứng (máy chủ DNS riêng cho máy khách cục bộ, máy chủ ngược dòng cho máy khách có địa chỉ IP công cộng).",
|
||||||
|
"use_private_ptr_resolvers_title": "Sử dụng trình rDNS riêng tư",
|
||||||
|
"use_private_ptr_resolvers_desc": "Thực hiện tra cứu ngược DNS cho các địa chỉ được phân phối cục bộ bằng cách sử dụng các máy chủ nguồn. Nếu bị vô hiệu hóa, AdGuard Home sẽ phản hồi với NXDOMAIN cho tất cả các yêu cầu PTR ngoại trừ các ứng dụng khách được biết đến bởi DHCP, / etc / hosts, v. v.",
|
||||||
"check_dhcp_servers": "Kiểm tra máy chủ DHCP",
|
"check_dhcp_servers": "Kiểm tra máy chủ DHCP",
|
||||||
"save_config": "Lưu thiết lập",
|
"save_config": "Lưu thiết lập",
|
||||||
"enabled_dhcp": "Máy chủ DHCP đã kích hoạt",
|
"enabled_dhcp": "Máy chủ DHCP đã kích hoạt",
|
||||||
@@ -63,6 +68,9 @@
|
|||||||
"dhcp_new_static_lease": "Cho thuê tĩnh mới",
|
"dhcp_new_static_lease": "Cho thuê tĩnh mới",
|
||||||
"dhcp_static_leases_not_found": "Không tìm thấy DHCP cho thuê tĩnh",
|
"dhcp_static_leases_not_found": "Không tìm thấy DHCP cho thuê tĩnh",
|
||||||
"dhcp_add_static_lease": "Thêm thuê tĩnh",
|
"dhcp_add_static_lease": "Thêm thuê tĩnh",
|
||||||
|
"dhcp_reset_leases": "Đặt lại tất cả các hợp đồng thuê",
|
||||||
|
"dhcp_reset_leases_confirm": "Bạn có chắc chắn muốn đặt lại tất cả các hợp đồng thuê không?",
|
||||||
|
"dhcp_reset_leases_success": "DHCP cho thuê đã đặt lại thành công",
|
||||||
"dhcp_reset": "Bạn có chắc chắn muốn đặt lại thiết lập DHCP?",
|
"dhcp_reset": "Bạn có chắc chắn muốn đặt lại thiết lập DHCP?",
|
||||||
"country": "Quốc gia",
|
"country": "Quốc gia",
|
||||||
"city": "Thành phố",
|
"city": "Thành phố",
|
||||||
@@ -104,6 +112,8 @@
|
|||||||
"for_last_24_hours": "trong 24 giờ qua",
|
"for_last_24_hours": "trong 24 giờ qua",
|
||||||
"for_last_days": "trong {{count}} ngày qua",
|
"for_last_days": "trong {{count}} ngày qua",
|
||||||
"for_last_days_plural": "trong {{count}} ngày qua",
|
"for_last_days_plural": "trong {{count}} ngày qua",
|
||||||
|
"stats_disabled": "Số liệu thống kê đã bị vô hiệu hóa. Bạn có thể bật nó từ <0> trang cài đặt </0>.",
|
||||||
|
"stats_disabled_short": "Số liệu thống kê đã bị vô hiệu hóa",
|
||||||
"no_domains_found": "Không có tên miền nào",
|
"no_domains_found": "Không có tên miền nào",
|
||||||
"requests_count": "Số lần yêu cầu",
|
"requests_count": "Số lần yêu cầu",
|
||||||
"top_blocked_domains": "Tên miền chặn nhiều",
|
"top_blocked_domains": "Tên miền chặn nhiều",
|
||||||
@@ -198,7 +208,7 @@
|
|||||||
"example_upstream_sdns": "bạn có thể sử dụng <0>DNS Stamps</0> for <1>DNSCrypt</1> hoặc <2>DNS-over-HTTPS</2> ",
|
"example_upstream_sdns": "bạn có thể sử dụng <0>DNS Stamps</0> for <1>DNSCrypt</1> hoặc <2>DNS-over-HTTPS</2> ",
|
||||||
"example_upstream_tcp": "DNS thông thường(dùng TCP)",
|
"example_upstream_tcp": "DNS thông thường(dùng TCP)",
|
||||||
"all_lists_up_to_date_toast": "Tất cả danh sách đã ở phiên bản mới nhất",
|
"all_lists_up_to_date_toast": "Tất cả danh sách đã ở phiên bản mới nhất",
|
||||||
"updated_upstream_dns_toast": "Đã cập nhật máy chủ DNS tìm kiếm",
|
"updated_upstream_dns_toast": "Các máy chủ thượng nguồn đã được lưu thành công",
|
||||||
"dns_test_ok_toast": "Máy chủ DNS có thể sử dụng",
|
"dns_test_ok_toast": "Máy chủ DNS có thể sử dụng",
|
||||||
"dns_test_not_ok_toast": "Máy chủ \"\"': không thể sử dụng, vui lòng kiểm tra lại",
|
"dns_test_not_ok_toast": "Máy chủ \"\"': không thể sử dụng, vui lòng kiểm tra lại",
|
||||||
"unblock": "Bỏ chặn",
|
"unblock": "Bỏ chặn",
|
||||||
@@ -225,7 +235,7 @@
|
|||||||
"loading_table_status": "Đang tải...",
|
"loading_table_status": "Đang tải...",
|
||||||
"page_table_footer_text": "Trang",
|
"page_table_footer_text": "Trang",
|
||||||
"rows_table_footer_text": "hàng",
|
"rows_table_footer_text": "hàng",
|
||||||
"updated_custom_filtering_toast": "Đã cập nhật bộ lọc tùy chỉnh",
|
"updated_custom_filtering_toast": "Đã cập nhật quy tắc lọc tuỳ chỉnh",
|
||||||
"rule_removed_from_custom_filtering_toast": "Quy tắc đã được xoá khỏi quy tắc lọc tuỳ chỉnh {{rule}}",
|
"rule_removed_from_custom_filtering_toast": "Quy tắc đã được xoá khỏi quy tắc lọc tuỳ chỉnh {{rule}}",
|
||||||
"rule_added_to_custom_filtering_toast": "Quy tắc đã được thêm vào quy tắc lọc tuỳ chỉnh: {{rule}}",
|
"rule_added_to_custom_filtering_toast": "Quy tắc đã được thêm vào quy tắc lọc tuỳ chỉnh: {{rule}}",
|
||||||
"query_log_response_status": "Trạng thái: {{value}}",
|
"query_log_response_status": "Trạng thái: {{value}}",
|
||||||
@@ -306,7 +316,9 @@
|
|||||||
"install_devices_title": "Định cấu hình thiết bị của bạn",
|
"install_devices_title": "Định cấu hình thiết bị của bạn",
|
||||||
"install_devices_desc": "Để bắt đầu sử dụng AdGuard Home, bạn cần định cấu hình thiết bị của mình để sử dụng nó.",
|
"install_devices_desc": "Để bắt đầu sử dụng AdGuard Home, bạn cần định cấu hình thiết bị của mình để sử dụng nó.",
|
||||||
"install_submit_title": "Xin chúc mừng!",
|
"install_submit_title": "Xin chúc mừng!",
|
||||||
|
"install_submit_desc": "Quy trình thiết lập đã kết thúc và bạn đã sẵn sàng bắt đầu sử dụng AdGuard Home.",
|
||||||
"install_devices_router": "Bộ định tuyến",
|
"install_devices_router": "Bộ định tuyến",
|
||||||
|
"install_devices_router_desc": "Thiết lập này sẽ tự động bao gồm tất cả các thiết bị được kết nối với bộ định tuyến gia đình của bạn và bạn sẽ không cần phải định cấu hình từng thiết bị theo cách thủ công.",
|
||||||
"install_devices_address": "Máy chủ DNS của AdGuard Home đang lắng nghe các địa chỉ sau",
|
"install_devices_address": "Máy chủ DNS của AdGuard Home đang lắng nghe các địa chỉ sau",
|
||||||
"install_devices_router_list_1": "Mở tùy chọn cho bộ định tuyến của bạn. Thông thường, bạn có thể truy cập nó từ trình duyệt của mình thông qua một URL, chẳng hạn như http://192.168.0.1/ hoặc http://192.168.1.1/. Bạn có thể được nhắc nhập mật khẩu. Nếu bạn không nhớ nó, bạn có thể đặt lại mật khẩu bằng cách nhấn nút khởi động lại trên chính bộ định tuyến, nhưng lưu ý rằng nếu khởi động lại, bạn có thể sẽ mất toàn bộ cấu hình bộ định tuyến. Một số bộ định tuyến sẽ yêu cầu đăng nhập từ một ứng dụng cụ thể đã được cài đặt trên máy tính hoặc điện thoại của bạn.",
|
"install_devices_router_list_1": "Mở tùy chọn cho bộ định tuyến của bạn. Thông thường, bạn có thể truy cập nó từ trình duyệt của mình thông qua một URL, chẳng hạn như http://192.168.0.1/ hoặc http://192.168.1.1/. Bạn có thể được nhắc nhập mật khẩu. Nếu bạn không nhớ nó, bạn có thể đặt lại mật khẩu bằng cách nhấn nút khởi động lại trên chính bộ định tuyến, nhưng lưu ý rằng nếu khởi động lại, bạn có thể sẽ mất toàn bộ cấu hình bộ định tuyến. Một số bộ định tuyến sẽ yêu cầu đăng nhập từ một ứng dụng cụ thể đã được cài đặt trên máy tính hoặc điện thoại của bạn.",
|
||||||
"install_devices_router_list_2": "Tìm cài đặt DHCP/DNS. Tìm các chữ cái DNS bên cạnh một trường cho phép hai hoặc ba bộ số, mỗi bộ được chia thành bốn nhóm từ một đến ba chữ số.",
|
"install_devices_router_list_2": "Tìm cài đặt DHCP/DNS. Tìm các chữ cái DNS bên cạnh một trường cho phép hai hoặc ba bộ số, mỗi bộ được chia thành bốn nhóm từ một đến ba chữ số.",
|
||||||
@@ -326,6 +338,7 @@
|
|||||||
"install_devices_android_list_2": "Nhấp Wi-Fi trên trình đơn. Màn hình liệt kê tất cả các mạng khả dụng sẽ được hiển thị (không thể đặt DNS tùy chỉnh cho kết nối di động).",
|
"install_devices_android_list_2": "Nhấp Wi-Fi trên trình đơn. Màn hình liệt kê tất cả các mạng khả dụng sẽ được hiển thị (không thể đặt DNS tùy chỉnh cho kết nối di động).",
|
||||||
"install_devices_android_list_3": "Nhấn và giữ mạng mà bạn đã kết nối và chạm Sửa Đổi Mạng.",
|
"install_devices_android_list_3": "Nhấn và giữ mạng mà bạn đã kết nối và chạm Sửa Đổi Mạng.",
|
||||||
"install_devices_android_list_4": "Trên một số thiết bị, bạn có thể cần chọn hộp Nâng cao để xem thêm cài đặt. Để điều chỉnh cài đặt DNS Android của bạn, bạn sẽ cần chuyển cài đặt IP từ DHCP sang Tĩnh.",
|
"install_devices_android_list_4": "Trên một số thiết bị, bạn có thể cần chọn hộp Nâng cao để xem thêm cài đặt. Để điều chỉnh cài đặt DNS Android của bạn, bạn sẽ cần chuyển cài đặt IP từ DHCP sang Tĩnh.",
|
||||||
|
"install_devices_android_list_5": "Thay đổi giá trị DNS 1 và DNS 2 thành địa chỉ máy chủ AdGuard Home của bạn.",
|
||||||
"install_devices_ios_list_1": "Từ màn hình chính, chạm Cài đặt.",
|
"install_devices_ios_list_1": "Từ màn hình chính, chạm Cài đặt.",
|
||||||
"install_devices_ios_list_2": "Chọn Wi-Fi trong trình đơn bên trái (không thể định cấu hình DNS cho mạng di động).",
|
"install_devices_ios_list_2": "Chọn Wi-Fi trong trình đơn bên trái (không thể định cấu hình DNS cho mạng di động).",
|
||||||
"install_devices_ios_list_3": "Chạm vào tên của mạng hiện đang hoạt động.",
|
"install_devices_ios_list_3": "Chạm vào tên của mạng hiện đang hoạt động.",
|
||||||
@@ -395,6 +408,7 @@
|
|||||||
"client_edit": "Chỉnh Sửa Máy Khách",
|
"client_edit": "Chỉnh Sửa Máy Khách",
|
||||||
"client_identifier": "Định danh",
|
"client_identifier": "Định danh",
|
||||||
"ip_address": "Địa chỉ IP",
|
"ip_address": "Địa chỉ IP",
|
||||||
|
"client_identifier_desc": "Các máy khách có thể được xác định bằng địa chỉ IP, CIDR, địa chỉ MAC hoặc một ID khách đặc biệt(có thể được dùng cho DoT/DoH/DoQ). Xem thêm cách xác định máy khách tại <0>đây</0>.",
|
||||||
"form_enter_ip": "Nhập IP",
|
"form_enter_ip": "Nhập IP",
|
||||||
"form_enter_subnet_ip": "Nhập địa chỉ IP vào mạng con \"{{cidr}}\"",
|
"form_enter_subnet_ip": "Nhập địa chỉ IP vào mạng con \"{{cidr}}\"",
|
||||||
"form_enter_mac": "Nhập MAC",
|
"form_enter_mac": "Nhập MAC",
|
||||||
@@ -418,6 +432,7 @@
|
|||||||
"access_disallowed_title": "Máy chủ không được phép",
|
"access_disallowed_title": "Máy chủ không được phép",
|
||||||
"access_disallowed_desc": "Một danh sách các địa chỉ CIDR hoặc IP. Nếu được định cấu hình, AdGuard Home sẽ bỏ yêu cầu từ các địa chỉ IP này.",
|
"access_disallowed_desc": "Một danh sách các địa chỉ CIDR hoặc IP. Nếu được định cấu hình, AdGuard Home sẽ bỏ yêu cầu từ các địa chỉ IP này.",
|
||||||
"access_blocked_title": "Tên miền bị chặn",
|
"access_blocked_title": "Tên miền bị chặn",
|
||||||
|
"access_blocked_desc": "Đừng nhầm lẫn điều này với các bộ lọc. AdGuard Home sẽ bỏ các truy vấn DNS với các tên miền này trong câu hỏi của truy vấn.",
|
||||||
"access_settings_saved": "Cài đặt truy cập đã lưu thành công",
|
"access_settings_saved": "Cài đặt truy cập đã lưu thành công",
|
||||||
"updates_checked": "Đã kiểm tra thành công cập nhật",
|
"updates_checked": "Đã kiểm tra thành công cập nhật",
|
||||||
"updates_version_equal": "AdGuard Home đã được cập nhật",
|
"updates_version_equal": "AdGuard Home đã được cập nhật",
|
||||||
@@ -471,10 +486,12 @@
|
|||||||
"encryption_key_source_content": "Dán nội dung khóa riêng",
|
"encryption_key_source_content": "Dán nội dung khóa riêng",
|
||||||
"stats_params": "Cấu hình thống kê",
|
"stats_params": "Cấu hình thống kê",
|
||||||
"config_successfully_saved": "Cấu hình được lưu thành công",
|
"config_successfully_saved": "Cấu hình được lưu thành công",
|
||||||
|
"interval_6_hour": "6 tiếng",
|
||||||
"interval_24_hour": "24 giờ",
|
"interval_24_hour": "24 giờ",
|
||||||
"interval_days": "{{count}} ngày",
|
"interval_days": "{{count}} ngày",
|
||||||
"interval_days_plural": "{{count}} ngày",
|
"interval_days_plural": "{{count}} ngày",
|
||||||
"domain": "Tên miền",
|
"domain": "Tên miền",
|
||||||
|
"punycode": "Punycode",
|
||||||
"answer": "Trả lời",
|
"answer": "Trả lời",
|
||||||
"filter_added_successfully": "Thêm bộ lọc thành công",
|
"filter_added_successfully": "Thêm bộ lọc thành công",
|
||||||
"filter_removed_successfully": "Xóa bộ lọc thành công",
|
"filter_removed_successfully": "Xóa bộ lọc thành công",
|
||||||
@@ -482,10 +499,11 @@
|
|||||||
"statistics_configuration": "Cấu hình thống kê",
|
"statistics_configuration": "Cấu hình thống kê",
|
||||||
"statistics_retention": "Duy trì thống kê",
|
"statistics_retention": "Duy trì thống kê",
|
||||||
"statistics_retention_desc": "Nếu bạn giảm giá trị khoảng, một số dữ liệu sẽ bị mất",
|
"statistics_retention_desc": "Nếu bạn giảm giá trị khoảng, một số dữ liệu sẽ bị mất",
|
||||||
"statistics_clear": " Xoá thống kê",
|
"statistics_clear": "Xoá thống kê",
|
||||||
"statistics_clear_confirm": "Bạn có chắc chắn muốn xóa số liệu thống kê?",
|
"statistics_clear_confirm": "Bạn có chắc chắn muốn xóa số liệu thống kê?",
|
||||||
"statistics_retention_confirm": "Bạn có chắc chắn muốn thay đổi lưu giữ số liệu thống kê? Nếu bạn giảm giá trị khoảng, một số dữ liệu sẽ bị mất",
|
"statistics_retention_confirm": "Bạn có chắc chắn muốn thay đổi lưu giữ số liệu thống kê? Nếu bạn giảm giá trị khoảng, một số dữ liệu sẽ bị mất",
|
||||||
"statistics_cleared": "Xoá thống kê thành công",
|
"statistics_cleared": "Xoá thống kê thành công",
|
||||||
|
"statistics_enable": "Bật thống kê",
|
||||||
"interval_hours": "{{count}} giờ",
|
"interval_hours": "{{count}} giờ",
|
||||||
"interval_hours_plural": "{{count}} giờ",
|
"interval_hours_plural": "{{count}} giờ",
|
||||||
"filters_configuration": "Cấu hình bộ lọc",
|
"filters_configuration": "Cấu hình bộ lọc",
|
||||||
@@ -520,6 +538,7 @@
|
|||||||
"disable_ipv6": "Tắt IPv6",
|
"disable_ipv6": "Tắt IPv6",
|
||||||
"disable_ipv6_desc": "Nếu tính năng này được bật, tất cả các truy vấn DNS cho địa chỉ IPv6 (loại AAAA) sẽ bị loại bỏ.",
|
"disable_ipv6_desc": "Nếu tính năng này được bật, tất cả các truy vấn DNS cho địa chỉ IPv6 (loại AAAA) sẽ bị loại bỏ.",
|
||||||
"fastest_addr": "Địa chỉ IP nhanh nhất",
|
"fastest_addr": "Địa chỉ IP nhanh nhất",
|
||||||
|
"fastest_addr_desc": "Truy vấn tất cả các máy chủ DNS và trả về địa chỉ IP nhanh nhất trong số tất cả các phản hồi",
|
||||||
"autofix_warning_text": "Nếu bạn nhấp vào \"Khắc phục\", AdGuard Home sẽ định cấu hình hệ thống của bạn để sử dụng máy chủ DNS của AdGuard Home.",
|
"autofix_warning_text": "Nếu bạn nhấp vào \"Khắc phục\", AdGuard Home sẽ định cấu hình hệ thống của bạn để sử dụng máy chủ DNS của AdGuard Home.",
|
||||||
"autofix_warning_list": "Nó sẽ thực hiện các tác vụ sau: <0> Hủy kích hoạt hệ thống DNSStubListener </0> <0> Đặt địa chỉ máy chủ DNS thành 127.0.0.1 </0> <0> Thay thế mục tiêu liên kết tượng trưng của /etc/resolv.conf bằng / run / systemd /resolve/resolv.conf </0> <0> Dừng DNSStubListener (tải lại dịch vụ do hệ thống phân giải) </0>",
|
"autofix_warning_list": "Nó sẽ thực hiện các tác vụ sau: <0> Hủy kích hoạt hệ thống DNSStubListener </0> <0> Đặt địa chỉ máy chủ DNS thành 127.0.0.1 </0> <0> Thay thế mục tiêu liên kết tượng trưng của /etc/resolv.conf bằng / run / systemd /resolve/resolv.conf </0> <0> Dừng DNSStubListener (tải lại dịch vụ do hệ thống phân giải) </0>",
|
||||||
"autofix_warning_result": "Do đó, tất cả các yêu cầu DNS từ hệ thống của bạn sẽ được AdGuard Home xử lý theo mặc định.",
|
"autofix_warning_result": "Do đó, tất cả các yêu cầu DNS từ hệ thống của bạn sẽ được AdGuard Home xử lý theo mặc định.",
|
||||||
@@ -584,6 +603,7 @@
|
|||||||
"filter_category_regional": "Khu vực",
|
"filter_category_regional": "Khu vực",
|
||||||
"filter_category_other": "Khác",
|
"filter_category_other": "Khác",
|
||||||
"filter_category_general_desc": "Bộ lọc chặn quảng cáo và theo dõi cho hầu hết các thiết bị",
|
"filter_category_general_desc": "Bộ lọc chặn quảng cáo và theo dõi cho hầu hết các thiết bị",
|
||||||
|
"filter_category_security_desc": "Bộ lọc chuyên biệt chặn tên miền chứa mã độc và lừa đảo",
|
||||||
"filter_category_regional_desc": "Bộ lọc tập trung vào từng khu vực",
|
"filter_category_regional_desc": "Bộ lọc tập trung vào từng khu vực",
|
||||||
"filter_category_other_desc": "Bộ lọc chặn khác",
|
"filter_category_other_desc": "Bộ lọc chặn khác",
|
||||||
"setup_config_to_enable_dhcp_server": "Thiết lập cấu hình để bật máy chủ DHCP",
|
"setup_config_to_enable_dhcp_server": "Thiết lập cấu hình để bật máy chủ DHCP",
|
||||||
@@ -591,6 +611,7 @@
|
|||||||
"click_to_view_queries": "Nhấp để xem truy xuất",
|
"click_to_view_queries": "Nhấp để xem truy xuất",
|
||||||
"port_53_faq_link": "Cổng 53 thường được sử dụng \"DNSStubListener\" hoặc \"systemd-resolved\". Vui lòng đọc <0>hướng dẫn</0> để giải quyết vấn đề này.",
|
"port_53_faq_link": "Cổng 53 thường được sử dụng \"DNSStubListener\" hoặc \"systemd-resolved\". Vui lòng đọc <0>hướng dẫn</0> để giải quyết vấn đề này.",
|
||||||
"adg_will_drop_dns_queries": "AdGuard Home sẽ loại bỏ tất cả các truy vấn DNS từ ứng dụng khách này.",
|
"adg_will_drop_dns_queries": "AdGuard Home sẽ loại bỏ tất cả các truy vấn DNS từ ứng dụng khách này.",
|
||||||
"client_not_in_allowed_clients": "Ứng dụng khách không được phép vì nó không có trong danh sách \"Ứng dụng khách được phép\".",
|
"filter_allowlist": "CẢNH BÁO: Hành động này cũng sẽ loại trừ quy tắc \"{{disallowed_rule}}\" khỏi danh sách các ứng dụng khách được phép.",
|
||||||
|
"last_rule_in_allowlist": "Không thể không cho phép ứng dụng khách này vì việc loại trừ quy tắc \"{{disallowed_rule}}\" sẽ TẮT danh sách \"Ứng dụng khách được phép\".",
|
||||||
"experimental": "Thử nghiệm"
|
"experimental": "Thử nghiệm"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -98,7 +98,7 @@
|
|||||||
"copyright": "版权",
|
"copyright": "版权",
|
||||||
"homepage": "主页",
|
"homepage": "主页",
|
||||||
"report_an_issue": "问题反馈",
|
"report_an_issue": "问题反馈",
|
||||||
"privacy_policy": "隐私策略",
|
"privacy_policy": "隐私政策",
|
||||||
"enable_protection": "启用保护",
|
"enable_protection": "启用保护",
|
||||||
"enabled_protection": "保护已启用",
|
"enabled_protection": "保护已启用",
|
||||||
"disable_protection": "禁用保护",
|
"disable_protection": "禁用保护",
|
||||||
@@ -208,7 +208,7 @@
|
|||||||
"example_upstream_sdns": "你可以使用 <1>DNSCrypt</1> 的 <0>DNS Stamps</0> 或者 <2>DNS-over-HTTPS</2> 解析器",
|
"example_upstream_sdns": "你可以使用 <1>DNSCrypt</1> 的 <0>DNS Stamps</0> 或者 <2>DNS-over-HTTPS</2> 解析器",
|
||||||
"example_upstream_tcp": "常规 DNS(基于 TCP )",
|
"example_upstream_tcp": "常规 DNS(基于 TCP )",
|
||||||
"all_lists_up_to_date_toast": "所有列表都是最新的",
|
"all_lists_up_to_date_toast": "所有列表都是最新的",
|
||||||
"updated_upstream_dns_toast": "上游 DNS 已更新",
|
"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}}\":无法使用,请检查你输入的是否正确",
|
||||||
"unblock": "放行",
|
"unblock": "放行",
|
||||||
@@ -235,7 +235,7 @@
|
|||||||
"loading_table_status": "加载中……",
|
"loading_table_status": "加载中……",
|
||||||
"page_table_footer_text": "页",
|
"page_table_footer_text": "页",
|
||||||
"rows_table_footer_text": "行",
|
"rows_table_footer_text": "行",
|
||||||
"updated_custom_filtering_toast": "自定义过滤规则已更新",
|
"updated_custom_filtering_toast": "自定义规则保存成功",
|
||||||
"rule_removed_from_custom_filtering_toast": "规则已从自定义过滤规则列表中移除 {{rule}}",
|
"rule_removed_from_custom_filtering_toast": "规则已从自定义过滤规则列表中移除 {{rule}}",
|
||||||
"rule_added_to_custom_filtering_toast": "规则已添加到自定义过滤规则列表中 {{rule}}",
|
"rule_added_to_custom_filtering_toast": "规则已添加到自定义过滤规则列表中 {{rule}}",
|
||||||
"query_log_response_status": "状态: {{value}}",
|
"query_log_response_status": "状态: {{value}}",
|
||||||
@@ -306,7 +306,7 @@
|
|||||||
"install_settings_dns_desc": "您将需要使用以下地址来设置您的设备或路由器的 DNS 服务器:",
|
"install_settings_dns_desc": "您将需要使用以下地址来设置您的设备或路由器的 DNS 服务器:",
|
||||||
"install_settings_all_interfaces": "所有接口",
|
"install_settings_all_interfaces": "所有接口",
|
||||||
"install_auth_title": "身份认证",
|
"install_auth_title": "身份认证",
|
||||||
"install_auth_desc": "我们强烈建议您为 AdGuard Home 的网页管理界面配置密码。即使该页面只能通过您的本地网络访问,但避免它被不加限制地访问仍十分重要。",
|
"install_auth_desc": "您需要对 AdGuard Home 的网页管理界面配置密码认证。即使该 AdGuard Home 只能通过您的本地网络访问,避免 AdGuard Home 被不受限制地访问依旧十分重要。",
|
||||||
"install_auth_username": "用户名",
|
"install_auth_username": "用户名",
|
||||||
"install_auth_password": "密码",
|
"install_auth_password": "密码",
|
||||||
"install_auth_confirm": "确认密码",
|
"install_auth_confirm": "确认密码",
|
||||||
@@ -503,6 +503,7 @@
|
|||||||
"statistics_clear_confirm": "您确定要清除统计数据?",
|
"statistics_clear_confirm": "您确定要清除统计数据?",
|
||||||
"statistics_retention_confirm": "您确定要更改统计记录保留时间吗? 如果您减少间隔时间的值, 某些数据可能会丢失。",
|
"statistics_retention_confirm": "您确定要更改统计记录保留时间吗? 如果您减少间隔时间的值, 某些数据可能会丢失。",
|
||||||
"statistics_cleared": "统计数据已成功清除",
|
"statistics_cleared": "统计数据已成功清除",
|
||||||
|
"statistics_enable": "启用统计数据",
|
||||||
"interval_hours": "{{count}} 小时",
|
"interval_hours": "{{count}} 小时",
|
||||||
"interval_hours_plural": "{{count}} 小时",
|
"interval_hours_plural": "{{count}} 小时",
|
||||||
"filters_configuration": "过滤器配置",
|
"filters_configuration": "过滤器配置",
|
||||||
@@ -597,7 +598,7 @@
|
|||||||
"cache_ttl_min_override_desc": "缓存 DNS 响应时,延长从上游服务器接收到的 TTL 值 (秒)",
|
"cache_ttl_min_override_desc": "缓存 DNS 响应时,延长从上游服务器接收到的 TTL 值 (秒)",
|
||||||
"cache_ttl_max_override_desc": "设定 DNS 缓存条目的最大 TTL 值(秒)",
|
"cache_ttl_max_override_desc": "设定 DNS 缓存条目的最大 TTL 值(秒)",
|
||||||
"ttl_cache_validation": "最小缓存TTL值必须小于或等于最大值",
|
"ttl_cache_validation": "最小缓存TTL值必须小于或等于最大值",
|
||||||
"cache_optimistic": "优化的",
|
"cache_optimistic": "乐观缓存",
|
||||||
"cache_optimistic_desc": "即使条目已过期,也让 AdGuard Home 从缓存中响应,并尝试刷新它们。",
|
"cache_optimistic_desc": "即使条目已过期,也让 AdGuard Home 从缓存中响应,并尝试刷新它们。",
|
||||||
"filter_category_general": "常规",
|
"filter_category_general": "常规",
|
||||||
"filter_category_security": "安全",
|
"filter_category_security": "安全",
|
||||||
@@ -612,6 +613,8 @@
|
|||||||
"click_to_view_queries": "点击查看查询",
|
"click_to_view_queries": "点击查看查询",
|
||||||
"port_53_faq_link": "53端口常被DNSStubListener或systemdn解析的服务占用。请阅读<0>这份关于如何解决这一问题的说明</0>",
|
"port_53_faq_link": "53端口常被DNSStubListener或systemdn解析的服务占用。请阅读<0>这份关于如何解决这一问题的说明</0>",
|
||||||
"adg_will_drop_dns_queries": "AdGuard Home 会终止所有来自此客户端的DNS查询。",
|
"adg_will_drop_dns_queries": "AdGuard Home 会终止所有来自此客户端的DNS查询。",
|
||||||
"client_not_in_allowed_clients": "此客户端不被允许,因为它不在“允许的客户端”列表中。",
|
"filter_allowlist": "警告:此操作将把规则 \"{{disallowed_rule}}\" 排除在允许客户端的列表之外。",
|
||||||
"experimental": "实验性的"
|
"last_rule_in_allowlist": "无法禁止此客户端,因为排除 “{{disallowed_rule}}” 规则将禁用“允许客户端”的列表。",
|
||||||
|
"experimental": "实验性的",
|
||||||
|
"use_saved_key": "使用之前保存的密钥"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -208,7 +208,7 @@
|
|||||||
"example_upstream_sdns": "您可使用關於 <1>DNSCrypt</1> 或 <2>DNS-over-HTTPS</2> 解析器之 <0>DNS 戳記</0>",
|
"example_upstream_sdns": "您可使用關於 <1>DNSCrypt</1> 或 <2>DNS-over-HTTPS</2> 解析器之 <0>DNS 戳記</0>",
|
||||||
"example_upstream_tcp": "一般的 DNS(透過 TCP)",
|
"example_upstream_tcp": "一般的 DNS(透過 TCP)",
|
||||||
"all_lists_up_to_date_toast": "所有的清單已是最新的",
|
"all_lists_up_to_date_toast": "所有的清單已是最新的",
|
||||||
"updated_upstream_dns_toast": "已更新上游的 DNS 伺服器",
|
"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}}\":無法被使用,請檢查您已正確地填寫它",
|
||||||
"unblock": "解除封鎖",
|
"unblock": "解除封鎖",
|
||||||
@@ -235,7 +235,7 @@
|
|||||||
"loading_table_status": "正在載入…",
|
"loading_table_status": "正在載入…",
|
||||||
"page_table_footer_text": "頁面",
|
"page_table_footer_text": "頁面",
|
||||||
"rows_table_footer_text": "列",
|
"rows_table_footer_text": "列",
|
||||||
"updated_custom_filtering_toast": "已更新自訂的過濾規則",
|
"updated_custom_filtering_toast": "自訂的規則被成功地儲存",
|
||||||
"rule_removed_from_custom_filtering_toast": "從自訂的過濾規則中被移除的規則:{{rule}}",
|
"rule_removed_from_custom_filtering_toast": "從自訂的過濾規則中被移除的規則:{{rule}}",
|
||||||
"rule_added_to_custom_filtering_toast": "被加至自訂的過濾規則中的規則:{{rule}}",
|
"rule_added_to_custom_filtering_toast": "被加至自訂的過濾規則中的規則:{{rule}}",
|
||||||
"query_log_response_status": "狀態:{{value}}",
|
"query_log_response_status": "狀態:{{value}}",
|
||||||
@@ -306,7 +306,7 @@
|
|||||||
"install_settings_dns_desc": "您將需要配置您的裝置或路由器以使用於下列的位址上之 DNS 伺服器:",
|
"install_settings_dns_desc": "您將需要配置您的裝置或路由器以使用於下列的位址上之 DNS 伺服器:",
|
||||||
"install_settings_all_interfaces": "所有的介面",
|
"install_settings_all_interfaces": "所有的介面",
|
||||||
"install_auth_title": "驗證",
|
"install_auth_title": "驗證",
|
||||||
"install_auth_desc": "配置屬於您的 AdGuard Home 管理員網路介面之密碼驗證是被非常建議的。即使它僅在您的區域網路中為可存取的,保護它免於不受限制的存取為仍然重要的。",
|
"install_auth_desc": "往您的 AdGuard Home 管理員網路介面之密碼驗證必須被配置。即使 AdGuard Home 僅在您的區域網路中為可存取的,保護它免於不受限制的存取為仍然重要的。",
|
||||||
"install_auth_username": "使用者名稱",
|
"install_auth_username": "使用者名稱",
|
||||||
"install_auth_password": "密碼",
|
"install_auth_password": "密碼",
|
||||||
"install_auth_confirm": "確認密碼",
|
"install_auth_confirm": "確認密碼",
|
||||||
@@ -503,6 +503,7 @@
|
|||||||
"statistics_clear_confirm": "您確定您想要清除統計資料嗎?",
|
"statistics_clear_confirm": "您確定您想要清除統計資料嗎?",
|
||||||
"statistics_retention_confirm": "您確定您想要更改統計資料保留嗎?如果您減少該間隔值,某些資料將被丟失",
|
"statistics_retention_confirm": "您確定您想要更改統計資料保留嗎?如果您減少該間隔值,某些資料將被丟失",
|
||||||
"statistics_cleared": "統計資料被成功地清除",
|
"statistics_cleared": "統計資料被成功地清除",
|
||||||
|
"statistics_enable": "啟用統計資料",
|
||||||
"interval_hours": "{{count}} 小時",
|
"interval_hours": "{{count}} 小時",
|
||||||
"interval_hours_plural": "{{count}} 小時",
|
"interval_hours_plural": "{{count}} 小時",
|
||||||
"filters_configuration": "過濾器配置",
|
"filters_configuration": "過濾器配置",
|
||||||
@@ -597,7 +598,7 @@
|
|||||||
"cache_ttl_min_override_desc": "當快取 DNS 回應時,延長從上游的伺服器收到的短存活時間數值(秒)",
|
"cache_ttl_min_override_desc": "當快取 DNS 回應時,延長從上游的伺服器收到的短存活時間數值(秒)",
|
||||||
"cache_ttl_max_override_desc": "設定最大的存活時間數值(秒)供在 DNS 快取中的項目",
|
"cache_ttl_max_override_desc": "設定最大的存活時間數值(秒)供在 DNS 快取中的項目",
|
||||||
"ttl_cache_validation": "最小的快取存活時間(TTL)數值必須小於或等於最大的數值",
|
"ttl_cache_validation": "最小的快取存活時間(TTL)數值必須小於或等於最大的數值",
|
||||||
"cache_optimistic": "樂觀快取模式",
|
"cache_optimistic": "樂觀快取",
|
||||||
"cache_optimistic_desc": "即使當項目為已到期的,從快取使 AdGuard Home 回覆,並還嘗試重新整理它們。",
|
"cache_optimistic_desc": "即使當項目為已到期的,從快取使 AdGuard Home 回覆,並還嘗試重新整理它們。",
|
||||||
"filter_category_general": "一般的",
|
"filter_category_general": "一般的",
|
||||||
"filter_category_security": "安全性",
|
"filter_category_security": "安全性",
|
||||||
@@ -612,6 +613,8 @@
|
|||||||
"click_to_view_queries": "點擊以檢視查詢",
|
"click_to_view_queries": "點擊以檢視查詢",
|
||||||
"port_53_faq_link": "連接埠 53 常被 \"DNSStubListener\" 或 \"systemd-resolved\" 服務佔用。請閱讀有關如何解決這個的<0>用法說明</0>。",
|
"port_53_faq_link": "連接埠 53 常被 \"DNSStubListener\" 或 \"systemd-resolved\" 服務佔用。請閱讀有關如何解決這個的<0>用法說明</0>。",
|
||||||
"adg_will_drop_dns_queries": "AdGuard Home 將持續排除來自此用戶端之所有的 DNS 查詢。",
|
"adg_will_drop_dns_queries": "AdGuard Home 將持續排除來自此用戶端之所有的 DNS 查詢。",
|
||||||
"client_not_in_allowed_clients": "該用戶端未被允許,因為它不在\"已允許的用戶端\"清單中。",
|
"filter_allowlist": "警告:此操作將把 \"{{disallowed_rule}}\" 規則排除在已允許用戶端的清單之外。",
|
||||||
"experimental": "實驗性的"
|
"last_rule_in_allowlist": "無法禁止此用戶端,因為排除 “{{disallowed_rule}}” 規則將禁用“已允許用戶端”的清單。",
|
||||||
|
"experimental": "實驗性的",
|
||||||
|
"use_saved_key": "使用該先前已儲存的金鑰"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -52,25 +52,34 @@ export const toggleClientBlock = (ip, disallowed, disallowed_rule) => async (dis
|
|||||||
dispatch(toggleClientBlockRequest());
|
dispatch(toggleClientBlockRequest());
|
||||||
try {
|
try {
|
||||||
const accessList = await apiClient.getAccessList();
|
const accessList = await apiClient.getAccessList();
|
||||||
const allowed_clients = accessList.allowed_clients ?? [];
|
|
||||||
const blocked_hosts = accessList.blocked_hosts ?? [];
|
const blocked_hosts = accessList.blocked_hosts ?? [];
|
||||||
const disallowed_clients = accessList.disallowed_clients ?? [];
|
let allowed_clients = accessList.allowed_clients ?? [];
|
||||||
|
let disallowed_clients = accessList.disallowed_clients ?? [];
|
||||||
const updatedDisallowedClients = disallowed
|
|
||||||
? disallowed_clients.filter((client) => client !== disallowed_rule)
|
|
||||||
: disallowed_clients.concat(ip);
|
|
||||||
|
|
||||||
|
if (disallowed) {
|
||||||
|
if (!disallowed_rule) {
|
||||||
|
allowed_clients = allowed_clients.concat(ip);
|
||||||
|
} else {
|
||||||
|
disallowed_clients = disallowed_clients
|
||||||
|
.filter((client) => client !== disallowed_rule);
|
||||||
|
}
|
||||||
|
} else if (allowed_clients.length > 1) {
|
||||||
|
allowed_clients = allowed_clients
|
||||||
|
.filter((client) => client !== disallowed_rule);
|
||||||
|
} else {
|
||||||
|
disallowed_clients = disallowed_clients.concat(ip);
|
||||||
|
}
|
||||||
const values = {
|
const values = {
|
||||||
allowed_clients,
|
allowed_clients,
|
||||||
blocked_hosts,
|
blocked_hosts,
|
||||||
disallowed_clients: updatedDisallowedClients,
|
disallowed_clients,
|
||||||
};
|
};
|
||||||
|
|
||||||
await apiClient.setAccessList(values);
|
await apiClient.setAccessList(values);
|
||||||
dispatch(toggleClientBlockSuccess(values));
|
dispatch(toggleClientBlockSuccess(values));
|
||||||
|
|
||||||
if (disallowed) {
|
if (disallowed) {
|
||||||
dispatch(addSuccessToast(i18next.t('client_unblocked', { ip: disallowed_rule })));
|
dispatch(addSuccessToast(i18next.t('client_unblocked', { ip: disallowed_rule || ip })));
|
||||||
} else {
|
} else {
|
||||||
dispatch(addSuccessToast(i18next.t('client_blocked', { ip })));
|
dispatch(addSuccessToast(i18next.t('client_blocked', { ip })));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -451,7 +451,6 @@ export const findActiveDhcp = (name) => async (dispatch, getState) => {
|
|||||||
dispatch(addErrorToast({ error: 'dhcp_static_ip_error' }));
|
dispatch(addErrorToast({ error: 'dhcp_static_ip_error' }));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (isError) {
|
if (isError) {
|
||||||
dispatch(addErrorToast({ error: 'dhcp_error' }));
|
dispatch(addErrorToast({ error: 'dhcp_error' }));
|
||||||
}
|
}
|
||||||
@@ -638,7 +637,11 @@ export const toggleBlocking = (
|
|||||||
};
|
};
|
||||||
|
|
||||||
export const toggleBlockingForClient = (type, domain, client) => {
|
export const toggleBlockingForClient = (type, domain, client) => {
|
||||||
const baseRule = `||${domain}^$client='${client.replace(/'/g, '/\'')}'`;
|
const escapedClientName = client.replace(/'/g, '\\\'')
|
||||||
|
.replace(/"/g, '\\"')
|
||||||
|
.replace(/,/g, '\\,')
|
||||||
|
.replace(/\|/g, '\\|');
|
||||||
|
const baseRule = `||${domain}^$client='${escapedClientName}'`;
|
||||||
const baseUnblocking = `@@${baseRule}`;
|
const baseUnblocking = `@@${baseRule}`;
|
||||||
|
|
||||||
return toggleBlocking(type, domain, baseRule, baseUnblocking);
|
return toggleBlocking(type, domain, baseRule, baseUnblocking);
|
||||||
|
|||||||
@@ -52,7 +52,7 @@ body {
|
|||||||
|
|
||||||
.modal-body--medium {
|
.modal-body--medium {
|
||||||
max-height: 20rem;
|
max-height: 20rem;
|
||||||
overflow-y: scroll;
|
overflow-y: auto;
|
||||||
}
|
}
|
||||||
|
|
||||||
.modal-body__item:not(:first-child) {
|
.modal-body__item:not(:first-child) {
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ import CustomRules from '../../containers/CustomRules';
|
|||||||
import Services from '../Filters/Services';
|
import Services from '../Filters/Services';
|
||||||
import Logs from '../Logs';
|
import Logs from '../Logs';
|
||||||
|
|
||||||
|
|
||||||
const ROUTES = [
|
const ROUTES = [
|
||||||
{
|
{
|
||||||
path: MENU_URLS.root,
|
path: MENU_URLS.root,
|
||||||
|
|||||||
@@ -38,15 +38,23 @@ const renderBlockingButton = (ip, disallowed, disallowed_rule) => {
|
|||||||
const dispatch = useDispatch();
|
const dispatch = useDispatch();
|
||||||
const { t } = useTranslation();
|
const { t } = useTranslation();
|
||||||
const processingSet = useSelector((state) => state.access.processingSet);
|
const processingSet = useSelector((state) => state.access.processingSet);
|
||||||
|
const allowedСlients = useSelector((state) => state.access.allowed_clients, shallowEqual);
|
||||||
|
|
||||||
const buttonClass = classNames('button-action button-action--main', {
|
const buttonClass = classNames('button-action button-action--main', {
|
||||||
'button-action--unblock': disallowed,
|
'button-action--unblock': disallowed,
|
||||||
});
|
});
|
||||||
|
|
||||||
const toggleClientStatus = async (ip, disallowed, disallowed_rule) => {
|
const toggleClientStatus = async (ip, disallowed, disallowed_rule) => {
|
||||||
const confirmMessage = disallowed
|
let confirmMessage;
|
||||||
? t('client_confirm_unblock', { ip: disallowed_rule })
|
|
||||||
: `${t('adg_will_drop_dns_queries')} ${t('client_confirm_block', { ip })}`;
|
if (disallowed) {
|
||||||
|
confirmMessage = t('client_confirm_unblock', { ip: disallowed_rule || ip });
|
||||||
|
} else {
|
||||||
|
confirmMessage = `${t('adg_will_drop_dns_queries')} ${t('client_confirm_block', { ip })}`;
|
||||||
|
if (allowedСlients.length > 0) {
|
||||||
|
confirmMessage = confirmMessage.concat(`\n\n${t('filter_allowlist', { disallowed_rule })}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (window.confirm(confirmMessage)) {
|
if (window.confirm(confirmMessage)) {
|
||||||
await dispatch(toggleClientBlock(ip, disallowed, disallowed_rule));
|
await dispatch(toggleClientBlock(ip, disallowed, disallowed_rule));
|
||||||
@@ -58,15 +66,16 @@ const renderBlockingButton = (ip, disallowed, disallowed_rule) => {
|
|||||||
|
|
||||||
const text = disallowed ? BLOCK_ACTIONS.UNBLOCK : BLOCK_ACTIONS.BLOCK;
|
const text = disallowed ? BLOCK_ACTIONS.UNBLOCK : BLOCK_ACTIONS.BLOCK;
|
||||||
|
|
||||||
const isNotInAllowedList = disallowed && disallowed_rule === '';
|
const lastRuleInAllowlist = !disallowed && allowedСlients === disallowed_rule;
|
||||||
|
const disabled = processingSet || lastRuleInAllowlist;
|
||||||
return (
|
return (
|
||||||
<div className="table__action pl-4">
|
<div className="table__action pl-4">
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
className={buttonClass}
|
className={buttonClass}
|
||||||
onClick={isNotInAllowedList ? undefined : onClick}
|
onClick={onClick}
|
||||||
disabled={isNotInAllowedList || processingSet}
|
disabled={disabled}
|
||||||
title={t(isNotInAllowedList ? 'client_not_in_allowed_clients' : text)}
|
title={lastRuleInAllowlist ? t('last_rule_in_allowlist', { disallowed_rule }) : ''}
|
||||||
>
|
>
|
||||||
<Trans>{text}</Trans>
|
<Trans>{text}</Trans>
|
||||||
</button>
|
</button>
|
||||||
|
|||||||
@@ -16,18 +16,31 @@ const Row = ({
|
|||||||
? <LogsSearchLink response_status={response_status}>{formatNumber(count)}</LogsSearchLink>
|
? <LogsSearchLink response_status={response_status}>{formatNumber(count)}</LogsSearchLink>
|
||||||
: count;
|
: count;
|
||||||
|
|
||||||
return <tr key={label}>
|
return (
|
||||||
<td>
|
<div className="counters__row" key={label}>
|
||||||
<Trans components={translationComponents}>{label}</Trans>
|
<div className="counters__column">
|
||||||
<Tooltip content={tooltipTitle} placement="top"
|
<span className="counters__title">
|
||||||
className="tooltip-container tooltip-custom--narrow text-center">
|
<Trans components={translationComponents}>
|
||||||
<svg className="icons icon--20 icon--lightgray ml-2">
|
{label}
|
||||||
<use xlinkHref="#question" />
|
</Trans>
|
||||||
</svg>
|
</span>
|
||||||
</Tooltip>
|
<span className="counters__tooltip">
|
||||||
</td>
|
<Tooltip
|
||||||
<td className="text-right"><strong>{content}</strong></td>
|
content={tooltipTitle}
|
||||||
</tr>;
|
placement="top"
|
||||||
|
className="tooltip-container tooltip-custom--narrow text-center"
|
||||||
|
>
|
||||||
|
<svg className="icons icon--20 icon--lightgray ml-2">
|
||||||
|
<use xlinkHref="#question" />
|
||||||
|
</svg>
|
||||||
|
</Tooltip>
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<div className="counters__column counters__column--value">
|
||||||
|
<strong>{content}</strong>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
const Counters = ({ refreshButton, subtitle }) => {
|
const Counters = ({ refreshButton, subtitle }) => {
|
||||||
@@ -88,9 +101,9 @@ const Counters = ({ refreshButton, subtitle }) => {
|
|||||||
bodyType="card-table"
|
bodyType="card-table"
|
||||||
refresh={refreshButton}
|
refresh={refreshButton}
|
||||||
>
|
>
|
||||||
<table className="table card-table">
|
<div className="counters">
|
||||||
<tbody>{rows.map(Row)}</tbody>
|
{rows.map(Row)}
|
||||||
</table>
|
</div>
|
||||||
</Card>
|
</Card>
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -49,3 +49,39 @@
|
|||||||
display: block;
|
display: block;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.counters__row {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
justify-content: space-between;
|
||||||
|
border-top: 1px solid #dee2e6;
|
||||||
|
padding: 0.75rem 1.5rem;
|
||||||
|
}
|
||||||
|
|
||||||
|
.counters__column--value {
|
||||||
|
flex-shrink: 0;
|
||||||
|
margin-left: 1.5rem;
|
||||||
|
text-align: right;
|
||||||
|
white-space: nowrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
@media screen and (min-width: 768px) {
|
||||||
|
.counters__column {
|
||||||
|
display: flex;
|
||||||
|
align-items: center;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.counters__title {
|
||||||
|
display: block;
|
||||||
|
max-width: 100%;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
overflow: hidden;
|
||||||
|
}
|
||||||
|
|
||||||
|
.counters__tooltip {
|
||||||
|
display: block;
|
||||||
|
flex-shrink: 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ const renderLink = ({ url, name }) => <a
|
|||||||
<strong>{name}</strong>
|
<strong>{name}</strong>
|
||||||
</a>;
|
</a>;
|
||||||
|
|
||||||
|
|
||||||
const getTrackerInfo = (trackerData) => [{
|
const getTrackerInfo = (trackerData) => [{
|
||||||
key: 'name_table_header',
|
key: 'name_table_header',
|
||||||
value: trackerData,
|
value: trackerData,
|
||||||
|
|||||||
@@ -1,13 +1,12 @@
|
|||||||
import React, { Component } from 'react';
|
import React, { Component } from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Trans, withTranslation } from 'react-i18next';
|
import { Trans, withTranslation } from 'react-i18next';
|
||||||
import classnames from 'classnames';
|
|
||||||
import Card from '../ui/Card';
|
import Card from '../ui/Card';
|
||||||
import PageTitle from '../ui/PageTitle';
|
import PageTitle from '../ui/PageTitle';
|
||||||
import Examples from './Examples';
|
import Examples from './Examples';
|
||||||
import Check from './Check';
|
import Check from './Check';
|
||||||
import { getTextareaCommentsHighlight, syncScroll } from '../../helpers/highlightTextareaComments';
|
import { getTextareaCommentsHighlight, syncScroll } from '../../helpers/highlightTextareaComments';
|
||||||
import { COMMENT_LINE_DEFAULT_TOKEN, isFirefox } from '../../helpers/constants';
|
import { COMMENT_LINE_DEFAULT_TOKEN } from '../../helpers/constants';
|
||||||
import '../ui/texareaCommentsHighlight.css';
|
import '../ui/texareaCommentsHighlight.css';
|
||||||
|
|
||||||
class CustomRules extends Component {
|
class CustomRules extends Component {
|
||||||
@@ -52,26 +51,19 @@ class CustomRules extends Component {
|
|||||||
return (
|
return (
|
||||||
<>
|
<>
|
||||||
<PageTitle title={t('custom_filtering_rules')} />
|
<PageTitle title={t('custom_filtering_rules')} />
|
||||||
<Card
|
<Card subtitle={t('custom_filter_rules_hint')}>
|
||||||
subtitle={t('custom_filter_rules_hint')}
|
|
||||||
>
|
|
||||||
<form onSubmit={this.handleSubmit}>
|
<form onSubmit={this.handleSubmit}>
|
||||||
<div className={classnames('col-12 text-edit-container form-control--textarea-large', {
|
<div className="text-edit-container mb-4">
|
||||||
'mb-4': !isFirefox,
|
<textarea
|
||||||
'mb-6': isFirefox,
|
className="form-control font-monospace text-input"
|
||||||
})}>
|
|
||||||
<textarea
|
|
||||||
className={classnames('form-control font-monospace text-input form-control--textarea-large', {
|
|
||||||
'text-input--largest': isFirefox,
|
|
||||||
})}
|
|
||||||
value={userRules}
|
value={userRules}
|
||||||
onChange={this.handleChange}
|
onChange={this.handleChange}
|
||||||
onScroll={this.onScroll}
|
onScroll={this.onScroll}
|
||||||
/>
|
/>
|
||||||
{getTextareaCommentsHighlight(
|
{getTextareaCommentsHighlight(
|
||||||
this.ref,
|
this.ref,
|
||||||
userRules,
|
userRules,
|
||||||
classnames({ 'form-control--textarea-large': isFirefox }),
|
undefined,
|
||||||
[COMMENT_LINE_DEFAULT_TOKEN, '!'],
|
[COMMENT_LINE_DEFAULT_TOKEN, '!'],
|
||||||
)}
|
)}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -28,6 +28,8 @@ const ClientCell = ({
|
|||||||
const autoClients = useSelector((state) => state.dashboard.autoClients, shallowEqual);
|
const autoClients = useSelector((state) => state.dashboard.autoClients, shallowEqual);
|
||||||
const processingRules = useSelector((state) => state.filtering.processingRules);
|
const processingRules = useSelector((state) => state.filtering.processingRules);
|
||||||
const isDetailed = useSelector((state) => state.queryLogs.isDetailed);
|
const isDetailed = useSelector((state) => state.queryLogs.isDetailed);
|
||||||
|
const processingSet = useSelector((state) => state.access.processingSet);
|
||||||
|
const allowedСlients = useSelector((state) => state.access.allowed_clients, shallowEqual);
|
||||||
const [isOptionsOpened, setOptionsOpened] = useState(false);
|
const [isOptionsOpened, setOptionsOpened] = useState(false);
|
||||||
|
|
||||||
const autoClient = autoClients.find((autoClient) => autoClient.name === client);
|
const autoClient = autoClients.find((autoClient) => autoClient.name === client);
|
||||||
@@ -71,11 +73,12 @@ const ClientCell = ({
|
|||||||
const {
|
const {
|
||||||
confirmMessage,
|
confirmMessage,
|
||||||
buttonKey: blockingClientKey,
|
buttonKey: blockingClientKey,
|
||||||
isNotInAllowedList,
|
lastRuleInAllowlist,
|
||||||
} = getBlockClientInfo(
|
} = getBlockClientInfo(
|
||||||
client,
|
client,
|
||||||
client_info?.disallowed || false,
|
client_info?.disallowed || false,
|
||||||
client_info?.disallowed_rule || '',
|
client_info?.disallowed_rule || '',
|
||||||
|
allowedСlients,
|
||||||
);
|
);
|
||||||
|
|
||||||
const blockingForClientKey = isFiltered ? 'unblock_for_this_client_only' : 'block_for_this_client_only';
|
const blockingForClientKey = isFiltered ? 'unblock_for_this_client_only' : 'block_for_this_client_only';
|
||||||
@@ -100,7 +103,7 @@ const ClientCell = ({
|
|||||||
await dispatch(updateLogs());
|
await dispatch(updateLogs());
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
disabled: isNotInAllowedList,
|
disabled: processingSet || lastRuleInAllowlist,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|||||||
@@ -6,7 +6,7 @@
|
|||||||
pointer-events: auto !important;
|
pointer-events: auto !important;
|
||||||
background-color: var(--white);
|
background-color: var(--white);
|
||||||
z-index: 102;
|
z-index: 102;
|
||||||
overflow-y: scroll;
|
overflow-y: auto;
|
||||||
max-height: 100%;
|
max-height: 100%;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -2,17 +2,24 @@ import i18next from 'i18next';
|
|||||||
|
|
||||||
export const BUTTON_PREFIX = 'btn_';
|
export const BUTTON_PREFIX = 'btn_';
|
||||||
|
|
||||||
export const getBlockClientInfo = (ip, disallowed, disallowed_rule) => {
|
export const getBlockClientInfo = (ip, disallowed, disallowed_rule, allowedСlients) => {
|
||||||
const confirmMessage = disallowed
|
let confirmMessage;
|
||||||
? i18next.t('client_confirm_unblock', { ip: disallowed_rule })
|
|
||||||
: `${i18next.t('adg_will_drop_dns_queries')} ${i18next.t('client_confirm_block', { ip })}`;
|
if (disallowed) {
|
||||||
|
confirmMessage = i18next.t('client_confirm_unblock', { ip: disallowed_rule || ip });
|
||||||
|
} else {
|
||||||
|
confirmMessage = `${i18next.t('adg_will_drop_dns_queries')} ${i18next.t('client_confirm_block', { ip })}`;
|
||||||
|
if (allowedСlients.length > 0) {
|
||||||
|
confirmMessage = confirmMessage.concat(`\n\n${i18next.t('filter_allowlist', { disallowed_rule })}`);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const buttonKey = i18next.t(disallowed ? 'allow_this_client' : 'disallow_this_client');
|
const buttonKey = i18next.t(disallowed ? 'allow_this_client' : 'disallow_this_client');
|
||||||
const isNotInAllowedList = disallowed && disallowed_rule === '';
|
const lastRuleInAllowlist = !disallowed && allowedСlients === disallowed_rule;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
confirmMessage,
|
confirmMessage,
|
||||||
buttonKey,
|
buttonKey,
|
||||||
isNotInAllowedList,
|
lastRuleInAllowlist,
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ const Row = memo(({
|
|||||||
const filters = useSelector((state) => state.filtering.filters, shallowEqual);
|
const filters = useSelector((state) => state.filtering.filters, shallowEqual);
|
||||||
const whitelistFilters = useSelector((state) => state.filtering.whitelistFilters, shallowEqual);
|
const whitelistFilters = useSelector((state) => state.filtering.whitelistFilters, shallowEqual);
|
||||||
const autoClients = useSelector((state) => state.dashboard.autoClients, shallowEqual);
|
const autoClients = useSelector((state) => state.dashboard.autoClients, shallowEqual);
|
||||||
|
const processingSet = useSelector((state) => state.access.processingSet);
|
||||||
|
const allowedСlients = useSelector((state) => state.access.allowed_clients, shallowEqual);
|
||||||
|
|
||||||
const clients = useSelector((state) => state.dashboard.clients);
|
const clients = useSelector((state) => state.dashboard.clients);
|
||||||
|
|
||||||
@@ -104,11 +106,12 @@ const Row = memo(({
|
|||||||
const {
|
const {
|
||||||
confirmMessage,
|
confirmMessage,
|
||||||
buttonKey: blockingClientKey,
|
buttonKey: blockingClientKey,
|
||||||
isNotInAllowedList,
|
lastRuleInAllowlist,
|
||||||
} = getBlockClientInfo(
|
} = getBlockClientInfo(
|
||||||
client,
|
client,
|
||||||
client_info?.disallowed || false,
|
client_info?.disallowed || false,
|
||||||
client_info?.disallowed_rule || '',
|
client_info?.disallowed_rule || '',
|
||||||
|
allowedСlients,
|
||||||
);
|
);
|
||||||
|
|
||||||
const blockingForClientKey = isFiltered ? 'unblock_for_this_client_only' : 'block_for_this_client_only';
|
const blockingForClientKey = isFiltered ? 'unblock_for_this_client_only' : 'block_for_this_client_only';
|
||||||
@@ -147,7 +150,7 @@ const Row = memo(({
|
|||||||
const blockClientButton = <button
|
const blockClientButton = <button
|
||||||
className='text-center font-weight-bold py-2 button-action--arrow-option'
|
className='text-center font-weight-bold py-2 button-action--arrow-option'
|
||||||
onClick={onBlockingClientClick}
|
onClick={onBlockingClientClick}
|
||||||
disabled={isNotInAllowedList}>
|
disabled={processingSet || lastRuleInAllowlist}>
|
||||||
{t(blockingClientKey)}
|
{t(blockingClientKey)}
|
||||||
</button>;
|
</button>;
|
||||||
|
|
||||||
|
|||||||
@@ -388,7 +388,7 @@
|
|||||||
border-collapse: collapse;
|
border-collapse: collapse;
|
||||||
contain: layout;
|
contain: layout;
|
||||||
overflow-x: hidden;
|
overflow-x: hidden;
|
||||||
overflow-y: scroll;
|
overflow-y: auto;
|
||||||
will-change: scroll-position;
|
will-change: scroll-position;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import Disabled from './Disabled';
|
|||||||
import { getFilteringStatus } from '../../actions/filtering';
|
import { getFilteringStatus } from '../../actions/filtering';
|
||||||
import { getClients } from '../../actions';
|
import { getClients } from '../../actions';
|
||||||
import { getDnsConfig } from '../../actions/dnsConfig';
|
import { getDnsConfig } from '../../actions/dnsConfig';
|
||||||
|
import { getAccessList } from '../../actions/access';
|
||||||
import {
|
import {
|
||||||
getLogsConfig,
|
getLogsConfig,
|
||||||
resetFilteredLogs,
|
resetFilteredLogs,
|
||||||
@@ -76,8 +77,8 @@ const Logs = () => {
|
|||||||
const filter = useSelector((state) => state.queryLogs.filter, shallowEqual);
|
const filter = useSelector((state) => state.queryLogs.filter, shallowEqual);
|
||||||
const logs = useSelector((state) => state.queryLogs.logs, shallowEqual);
|
const logs = useSelector((state) => state.queryLogs.logs, shallowEqual);
|
||||||
|
|
||||||
const search = filter?.search || search_url_param || '';
|
const search = search_url_param || filter?.search || '';
|
||||||
const response_status = filter?.response_status || response_status_url_param || '';
|
const response_status = response_status_url_param || filter?.response_status || '';
|
||||||
|
|
||||||
const [isSmallScreen, setIsSmallScreen] = useState(window.innerWidth < SMALL_SCREEN_SIZE);
|
const [isSmallScreen, setIsSmallScreen] = useState(window.innerWidth < SMALL_SCREEN_SIZE);
|
||||||
const [detailedDataCurrent, setDetailedDataCurrent] = useState({});
|
const [detailedDataCurrent, setDetailedDataCurrent] = useState({});
|
||||||
@@ -126,6 +127,7 @@ const Logs = () => {
|
|||||||
await Promise.all([
|
await Promise.all([
|
||||||
dispatch(getLogsConfig()),
|
dispatch(getLogsConfig()),
|
||||||
dispatch(getDnsConfig()),
|
dispatch(getDnsConfig()),
|
||||||
|
dispatch(getAccessList()),
|
||||||
]);
|
]);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
console.error(err);
|
console.error(err);
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ const renderInterfaces = (interfaces) => Object.keys(interfaces)
|
|||||||
return <option value={name} key={name}>{optionContent}</option>;
|
return <option value={name} key={name}>{optionContent}</option>;
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
const getInterfaceValues = ({
|
const getInterfaceValues = ({
|
||||||
gateway_ip,
|
gateway_ip,
|
||||||
hardware_address,
|
hardware_address,
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import React from 'react';
|
import React from 'react';
|
||||||
import PropTypes from 'prop-types';
|
import PropTypes from 'prop-types';
|
||||||
import { Field, reduxForm } from 'redux-form';
|
import { connect } from 'react-redux';
|
||||||
|
import { Field, reduxForm, formValueSelector } from 'redux-form';
|
||||||
import { Trans, withTranslation } from 'react-i18next';
|
import { Trans, withTranslation } from 'react-i18next';
|
||||||
import flow from 'lodash/flow';
|
import flow from 'lodash/flow';
|
||||||
import { renderTextareaField } from '../../../../helpers/form';
|
import { renderTextareaField } from '../../../../helpers/form';
|
||||||
@@ -31,16 +32,20 @@ const fields = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
const Form = (props) => {
|
let Form = (props) => {
|
||||||
const {
|
const {
|
||||||
handleSubmit, submitting, invalid, processingSet,
|
allowedClients, handleSubmit, submitting, invalid, processingSet,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const renderField = ({
|
const renderField = ({
|
||||||
id, title, subtitle, disabled = processingSet, normalizeOnBlur,
|
id, title, subtitle, disabled = false, processingSet, normalizeOnBlur,
|
||||||
}) => <div key={id} className="form__group mb-5">
|
}) => <div key={id} className="form__group mb-5">
|
||||||
<label className="form__label form__label--with-desc" htmlFor={id}>
|
<label className="form__label form__label--with-desc" htmlFor={id}>
|
||||||
<Trans>{title}</Trans>
|
<Trans>{title}</Trans>
|
||||||
|
{disabled && <>
|
||||||
|
<span> </span>
|
||||||
|
(<Trans>disabled</Trans>)
|
||||||
|
</>}
|
||||||
</label>
|
</label>
|
||||||
<div className="form__desc form__desc--top">
|
<div className="form__desc form__desc--top">
|
||||||
<Trans>{subtitle}</Trans>
|
<Trans>{subtitle}</Trans>
|
||||||
@@ -51,7 +56,7 @@ const Form = (props) => {
|
|||||||
component={renderTextareaField}
|
component={renderTextareaField}
|
||||||
type="text"
|
type="text"
|
||||||
className="form-control form-control--textarea font-monospace"
|
className="form-control form-control--textarea font-monospace"
|
||||||
disabled={disabled}
|
disabled={disabled || processingSet}
|
||||||
normalizeOnBlur={normalizeOnBlur}
|
normalizeOnBlur={normalizeOnBlur}
|
||||||
/>
|
/>
|
||||||
</div>;
|
</div>;
|
||||||
@@ -66,7 +71,15 @@ const Form = (props) => {
|
|||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit}>
|
<form onSubmit={handleSubmit}>
|
||||||
{fields.map(renderField)}
|
{
|
||||||
|
fields.map((f) => {
|
||||||
|
const props = { ...f };
|
||||||
|
if (allowedClients && f.id === 'disallowed_clients') {
|
||||||
|
props.disabled = true;
|
||||||
|
}
|
||||||
|
return renderField(props);
|
||||||
|
})
|
||||||
|
}
|
||||||
<div className="card-actions">
|
<div className="card-actions">
|
||||||
<div className="btn-list">
|
<div className="btn-list">
|
||||||
<button
|
<button
|
||||||
@@ -90,6 +103,21 @@ Form.propTypes = {
|
|||||||
processingSet: PropTypes.bool.isRequired,
|
processingSet: PropTypes.bool.isRequired,
|
||||||
t: PropTypes.func.isRequired,
|
t: PropTypes.func.isRequired,
|
||||||
textarea: PropTypes.bool,
|
textarea: PropTypes.bool,
|
||||||
|
allowedClients: PropTypes.string,
|
||||||
};
|
};
|
||||||
|
|
||||||
export default flow([withTranslation(), reduxForm({ form: FORM_NAME.ACCESS })])(Form);
|
const selector = formValueSelector(FORM_NAME.ACCESS);
|
||||||
|
|
||||||
|
Form = connect((state) => {
|
||||||
|
const allowedClients = selector(state, 'allowed_clients');
|
||||||
|
return {
|
||||||
|
allowedClients,
|
||||||
|
};
|
||||||
|
})(Form);
|
||||||
|
|
||||||
|
export default flow([
|
||||||
|
withTranslation(),
|
||||||
|
reduxForm({
|
||||||
|
form: FORM_NAME.ACCESS,
|
||||||
|
}),
|
||||||
|
])(Form);
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import { renderRadioField, renderTextareaField, CheckboxField } from '../../../.
|
|||||||
import {
|
import {
|
||||||
DNS_REQUEST_OPTIONS,
|
DNS_REQUEST_OPTIONS,
|
||||||
FORM_NAME,
|
FORM_NAME,
|
||||||
isFirefox,
|
|
||||||
UPSTREAM_CONFIGURATION_WIKI_LINK,
|
UPSTREAM_CONFIGURATION_WIKI_LINK,
|
||||||
} from '../../../../helpers/constants';
|
} from '../../../../helpers/constants';
|
||||||
import { testUpstreamWithFormValues } from '../../../../actions';
|
import { testUpstreamWithFormValues } from '../../../../actions';
|
||||||
@@ -90,25 +89,10 @@ renderTextareaWithHighlightField.propTypes = {
|
|||||||
normalizeOnBlur: PropTypes.func,
|
normalizeOnBlur: PropTypes.func,
|
||||||
onScroll: PropTypes.func,
|
onScroll: PropTypes.func,
|
||||||
placeholder: PropTypes.string.isRequired,
|
placeholder: PropTypes.string.isRequired,
|
||||||
subtitle: PropTypes.string.isRequired,
|
|
||||||
type: PropTypes.string.isRequired,
|
type: PropTypes.string.isRequired,
|
||||||
};
|
};
|
||||||
|
|
||||||
const INPUT_FIELDS = [
|
const INPUT_FIELDS = [
|
||||||
{
|
|
||||||
name: UPSTREAM_DNS_NAME,
|
|
||||||
type: 'text',
|
|
||||||
component: renderTextareaWithHighlightField,
|
|
||||||
className: classnames('form-control form-control--textarea font-monospace text-input', {
|
|
||||||
'text-input--larger': isFirefox,
|
|
||||||
}),
|
|
||||||
containerClass: classnames('text-edit-container', {
|
|
||||||
'mb-4': !isFirefox,
|
|
||||||
'mb-6': isFirefox,
|
|
||||||
}),
|
|
||||||
placeholder: 'upstream_dns',
|
|
||||||
normalizeOnBlur: removeEmptyLines,
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
name: UPSTREAM_MODE_NAME,
|
name: UPSTREAM_MODE_NAME,
|
||||||
type: 'radio',
|
type: 'radio',
|
||||||
@@ -176,6 +160,20 @@ const Form = ({
|
|||||||
dns_providers
|
dns_providers
|
||||||
</Trans>
|
</Trans>
|
||||||
</label>
|
</label>
|
||||||
|
<div className="col-12 mb-4">
|
||||||
|
<div className="text-edit-container">
|
||||||
|
<Field
|
||||||
|
id={UPSTREAM_DNS_NAME}
|
||||||
|
name={UPSTREAM_DNS_NAME}
|
||||||
|
component={renderTextareaWithHighlightField}
|
||||||
|
type="text"
|
||||||
|
className="form-control form-control--textarea font-monospace text-input"
|
||||||
|
placeholder={t('upstream_dns')}
|
||||||
|
disabled={processingSetConfig || processingTestUpstream}
|
||||||
|
normalizeOnBlur={removeEmptyLines}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
{INPUT_FIELDS.map(renderField)}
|
{INPUT_FIELDS.map(renderField)}
|
||||||
<div className="col-12">
|
<div className="col-12">
|
||||||
<Examples />
|
<Examples />
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ import i18n from '../../../i18n';
|
|||||||
import KeyStatus from './KeyStatus';
|
import KeyStatus from './KeyStatus';
|
||||||
import CertificateStatus from './CertificateStatus';
|
import CertificateStatus from './CertificateStatus';
|
||||||
import {
|
import {
|
||||||
DNS_OVER_QUIC_PORT, DNS_OVER_TLS_PORT, FORM_NAME, STANDARD_HTTPS_PORT,
|
DNS_OVER_QUIC_PORT, DNS_OVER_TLS_PORT, FORM_NAME, STANDARD_HTTPS_PORT, ENCRYPTION_SOURCE,
|
||||||
} from '../../../helpers/constants';
|
} from '../../../helpers/constants';
|
||||||
|
|
||||||
const validate = (values) => {
|
const validate = (values) => {
|
||||||
@@ -46,6 +46,7 @@ const clearFields = (change, setTlsConfig, t) => {
|
|||||||
server_name: '',
|
server_name: '',
|
||||||
force_https: false,
|
force_https: false,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
|
private_key_saved: false,
|
||||||
};
|
};
|
||||||
// eslint-disable-next-line no-alert
|
// eslint-disable-next-line no-alert
|
||||||
if (window.confirm(t('encryption_reset'))) {
|
if (window.confirm(t('encryption_reset'))) {
|
||||||
@@ -83,6 +84,7 @@ let Form = (props) => {
|
|||||||
setTlsConfig,
|
setTlsConfig,
|
||||||
certificateSource,
|
certificateSource,
|
||||||
privateKeySource,
|
privateKeySource,
|
||||||
|
privateKeySaved,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
const isSavingDisabled = invalid
|
const isSavingDisabled = invalid
|
||||||
@@ -265,7 +267,7 @@ let Form = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{certificateSource === 'content' && (
|
{certificateSource === ENCRYPTION_SOURCE.CONTENT && (
|
||||||
<Field
|
<Field
|
||||||
id="certificate_chain"
|
id="certificate_chain"
|
||||||
name="certificate_chain"
|
name="certificate_chain"
|
||||||
@@ -277,7 +279,7 @@ let Form = (props) => {
|
|||||||
disabled={!isEnabled}
|
disabled={!isEnabled}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
{certificateSource === 'path' && (
|
{certificateSource === ENCRYPTION_SOURCE.PATH && (
|
||||||
<Field
|
<Field
|
||||||
id="certificate_path"
|
id="certificate_path"
|
||||||
name="certificate_path"
|
name="certificate_path"
|
||||||
@@ -318,7 +320,7 @@ let Form = (props) => {
|
|||||||
component={renderRadioField}
|
component={renderRadioField}
|
||||||
type="radio"
|
type="radio"
|
||||||
className="form-control mr-2"
|
className="form-control mr-2"
|
||||||
value="path"
|
value={ENCRYPTION_SOURCE.PATH}
|
||||||
placeholder={t('encryption_key_source_path')}
|
placeholder={t('encryption_key_source_path')}
|
||||||
disabled={!isEnabled}
|
disabled={!isEnabled}
|
||||||
/>
|
/>
|
||||||
@@ -327,28 +329,15 @@ let Form = (props) => {
|
|||||||
component={renderRadioField}
|
component={renderRadioField}
|
||||||
type="radio"
|
type="radio"
|
||||||
className="form-control mr-2"
|
className="form-control mr-2"
|
||||||
value="content"
|
value={ENCRYPTION_SOURCE.CONTENT}
|
||||||
placeholder={t('encryption_key_source_content')}
|
placeholder={t('encryption_key_source_content')}
|
||||||
disabled={!isEnabled}
|
disabled={!isEnabled}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
{privateKeySource === 'content' && (
|
{privateKeySource === ENCRYPTION_SOURCE.PATH && (
|
||||||
<Field
|
<Field
|
||||||
id="private_key"
|
|
||||||
name="private_key"
|
|
||||||
component="textarea"
|
|
||||||
type="text"
|
|
||||||
className="form-control form-control--textarea"
|
|
||||||
placeholder={t('encryption_key_input')}
|
|
||||||
onChange={handleChange}
|
|
||||||
disabled={!isEnabled}
|
|
||||||
/>
|
|
||||||
)}
|
|
||||||
{privateKeySource === 'path' && (
|
|
||||||
<Field
|
|
||||||
id="private_key_path"
|
|
||||||
name="private_key_path"
|
name="private_key_path"
|
||||||
component={renderInputField}
|
component={renderInputField}
|
||||||
type="text"
|
type="text"
|
||||||
@@ -358,6 +347,36 @@ let Form = (props) => {
|
|||||||
disabled={!isEnabled}
|
disabled={!isEnabled}
|
||||||
/>
|
/>
|
||||||
)}
|
)}
|
||||||
|
{privateKeySource === ENCRYPTION_SOURCE.CONTENT && [
|
||||||
|
<Field
|
||||||
|
key="private_key_saved"
|
||||||
|
name="private_key_saved"
|
||||||
|
type="checkbox"
|
||||||
|
className="form__group form__group--settings mb-2"
|
||||||
|
component={CheckboxField}
|
||||||
|
disabled={!isEnabled}
|
||||||
|
placeholder={t('use_saved_key')}
|
||||||
|
onChange={(event) => {
|
||||||
|
if (event.target.checked) {
|
||||||
|
change('private_key', '');
|
||||||
|
}
|
||||||
|
if (handleChange) {
|
||||||
|
handleChange(event);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>,
|
||||||
|
<Field
|
||||||
|
id="private_key"
|
||||||
|
key="private_key"
|
||||||
|
name="private_key"
|
||||||
|
component="textarea"
|
||||||
|
type="text"
|
||||||
|
className="form-control form-control--textarea"
|
||||||
|
placeholder={t('encryption_key_input')}
|
||||||
|
onChange={handleChange}
|
||||||
|
disabled={!isEnabled || privateKeySaved}
|
||||||
|
/>,
|
||||||
|
]}
|
||||||
</div>
|
</div>
|
||||||
<div className="form__status">
|
<div className="form__status">
|
||||||
{(privateKey || privateKeyPath) && (
|
{(privateKey || privateKeyPath) && (
|
||||||
@@ -422,6 +441,7 @@ Form.propTypes = {
|
|||||||
setTlsConfig: PropTypes.func.isRequired,
|
setTlsConfig: PropTypes.func.isRequired,
|
||||||
certificateSource: PropTypes.string,
|
certificateSource: PropTypes.string,
|
||||||
privateKeySource: PropTypes.string,
|
privateKeySource: PropTypes.string,
|
||||||
|
privateKeySaved: PropTypes.bool,
|
||||||
};
|
};
|
||||||
|
|
||||||
const selector = formValueSelector(FORM_NAME.ENCRYPTION);
|
const selector = formValueSelector(FORM_NAME.ENCRYPTION);
|
||||||
@@ -434,6 +454,7 @@ Form = connect((state) => {
|
|||||||
const privateKeyPath = selector(state, 'private_key_path');
|
const privateKeyPath = selector(state, 'private_key_path');
|
||||||
const certificateSource = selector(state, 'certificate_source');
|
const certificateSource = selector(state, 'certificate_source');
|
||||||
const privateKeySource = selector(state, 'key_source');
|
const privateKeySource = selector(state, 'key_source');
|
||||||
|
const privateKeySaved = selector(state, 'private_key_saved');
|
||||||
return {
|
return {
|
||||||
isEnabled,
|
isEnabled,
|
||||||
certificateChain,
|
certificateChain,
|
||||||
@@ -442,6 +463,7 @@ Form = connect((state) => {
|
|||||||
privateKeyPath,
|
privateKeyPath,
|
||||||
certificateSource,
|
certificateSource,
|
||||||
privateKeySource,
|
privateKeySource,
|
||||||
|
privateKeySaved,
|
||||||
};
|
};
|
||||||
})(Form);
|
})(Form);
|
||||||
|
|
||||||
|
|||||||
@@ -29,9 +29,13 @@ class Encryption extends Component {
|
|||||||
}, DEBOUNCE_TIMEOUT);
|
}, DEBOUNCE_TIMEOUT);
|
||||||
|
|
||||||
getInitialValues = (data) => {
|
getInitialValues = (data) => {
|
||||||
const { certificate_chain, private_key } = data;
|
const { certificate_chain, private_key, private_key_saved } = data;
|
||||||
const certificate_source = certificate_chain ? 'content' : 'path';
|
const certificate_source = certificate_chain
|
||||||
const key_source = private_key ? 'content' : 'path';
|
? ENCRYPTION_SOURCE.CONTENT
|
||||||
|
: ENCRYPTION_SOURCE.PATH;
|
||||||
|
const key_source = private_key || private_key_saved
|
||||||
|
? ENCRYPTION_SOURCE.CONTENT
|
||||||
|
: ENCRYPTION_SOURCE.PATH;
|
||||||
|
|
||||||
return {
|
return {
|
||||||
...data,
|
...data,
|
||||||
@@ -41,7 +45,9 @@ class Encryption extends Component {
|
|||||||
};
|
};
|
||||||
|
|
||||||
getSubmitValues = (values) => {
|
getSubmitValues = (values) => {
|
||||||
const { certificate_source, key_source, ...config } = values;
|
const {
|
||||||
|
certificate_source, key_source, private_key_saved, ...config
|
||||||
|
} = values;
|
||||||
|
|
||||||
if (certificate_source === ENCRYPTION_SOURCE.PATH) {
|
if (certificate_source === ENCRYPTION_SOURCE.PATH) {
|
||||||
config.certificate_chain = '';
|
config.certificate_chain = '';
|
||||||
@@ -49,10 +55,15 @@ class Encryption extends Component {
|
|||||||
config.certificate_path = '';
|
config.certificate_path = '';
|
||||||
}
|
}
|
||||||
|
|
||||||
if (values.key_source === ENCRYPTION_SOURCE.PATH) {
|
if (key_source === ENCRYPTION_SOURCE.PATH) {
|
||||||
config.private_key = '';
|
config.private_key = '';
|
||||||
} else {
|
} else {
|
||||||
config.private_key_path = '';
|
config.private_key_path = '';
|
||||||
|
|
||||||
|
if (private_key_saved) {
|
||||||
|
config.private_key = '';
|
||||||
|
config.private_key_saved = private_key_saved;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return config;
|
return config;
|
||||||
@@ -71,6 +82,7 @@ class Encryption extends Component {
|
|||||||
private_key,
|
private_key,
|
||||||
certificate_path,
|
certificate_path,
|
||||||
private_key_path,
|
private_key_path,
|
||||||
|
private_key_saved,
|
||||||
} = encryption;
|
} = encryption;
|
||||||
|
|
||||||
const initialValues = this.getInitialValues({
|
const initialValues = this.getInitialValues({
|
||||||
@@ -84,6 +96,7 @@ class Encryption extends Component {
|
|||||||
private_key,
|
private_key,
|
||||||
certificate_path,
|
certificate_path,
|
||||||
private_key_path,
|
private_key_path,
|
||||||
|
private_key_saved,
|
||||||
});
|
});
|
||||||
|
|
||||||
return (
|
return (
|
||||||
|
|||||||
@@ -4,14 +4,12 @@ import { Field, reduxForm } from 'redux-form';
|
|||||||
import { Trans, withTranslation } from 'react-i18next';
|
import { Trans, withTranslation } from 'react-i18next';
|
||||||
import flow from 'lodash/flow';
|
import flow from 'lodash/flow';
|
||||||
|
|
||||||
import { renderRadioField, toNumber } from '../../../helpers/form';
|
import { renderRadioField, toNumber, CheckboxField } from '../../../helpers/form';
|
||||||
import { FORM_NAME, STATS_INTERVALS_DAYS } from '../../../helpers/constants';
|
import { FORM_NAME, STATS_INTERVALS_DAYS, DISABLED_STATS_INTERVAL } from '../../../helpers/constants';
|
||||||
import '../FormButton.css';
|
import '../FormButton.css';
|
||||||
|
|
||||||
const getIntervalTitle = (interval, t) => {
|
const getIntervalTitle = (interval, t) => {
|
||||||
switch (interval) {
|
switch (interval) {
|
||||||
case 0:
|
|
||||||
return t('disabled');
|
|
||||||
case 1:
|
case 1:
|
||||||
return t('interval_24_hour');
|
return t('interval_24_hour');
|
||||||
default:
|
default:
|
||||||
@@ -19,24 +17,36 @@ const getIntervalTitle = (interval, t) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
const getIntervalFields = (processing, t, toNumber) => STATS_INTERVALS_DAYS.map((interval) => <Field
|
|
||||||
key={interval}
|
|
||||||
name="interval"
|
|
||||||
type="radio"
|
|
||||||
component={renderRadioField}
|
|
||||||
value={interval}
|
|
||||||
placeholder={getIntervalTitle(interval, t)}
|
|
||||||
normalize={toNumber}
|
|
||||||
disabled={processing}
|
|
||||||
/>);
|
|
||||||
|
|
||||||
const Form = (props) => {
|
const Form = (props) => {
|
||||||
const {
|
const {
|
||||||
handleSubmit, processing, submitting, invalid, handleReset, processingReset, t,
|
handleSubmit,
|
||||||
|
change,
|
||||||
|
processing,
|
||||||
|
submitting,
|
||||||
|
invalid,
|
||||||
|
handleReset,
|
||||||
|
processingReset,
|
||||||
|
t,
|
||||||
} = props;
|
} = props;
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<form onSubmit={handleSubmit}>
|
<form onSubmit={handleSubmit}>
|
||||||
|
<div className="form__group form__group--settings">
|
||||||
|
<Field
|
||||||
|
name="enabled"
|
||||||
|
type="checkbox"
|
||||||
|
component={CheckboxField}
|
||||||
|
placeholder={t('statistics_enable')}
|
||||||
|
disabled={processing}
|
||||||
|
onChange={(event) => {
|
||||||
|
if (event.target.checked) {
|
||||||
|
change('interval', STATS_INTERVALS_DAYS[0]);
|
||||||
|
} else {
|
||||||
|
change('interval', DISABLED_STATS_INTERVAL);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
<label className="form__label form__label--with-desc">
|
<label className="form__label form__label--with-desc">
|
||||||
<Trans>statistics_retention</Trans>
|
<Trans>statistics_retention</Trans>
|
||||||
</label>
|
</label>
|
||||||
@@ -45,7 +55,23 @@ const Form = (props) => {
|
|||||||
</div>
|
</div>
|
||||||
<div className="form__group form__group--settings mt-2">
|
<div className="form__group form__group--settings mt-2">
|
||||||
<div className="custom-controls-stacked">
|
<div className="custom-controls-stacked">
|
||||||
{getIntervalFields(processing, t, toNumber)}
|
{STATS_INTERVALS_DAYS.map((interval) => (
|
||||||
|
<Field
|
||||||
|
key={interval}
|
||||||
|
name="interval"
|
||||||
|
type="radio"
|
||||||
|
component={renderRadioField}
|
||||||
|
value={interval}
|
||||||
|
placeholder={getIntervalTitle(interval, t)}
|
||||||
|
normalize={toNumber}
|
||||||
|
disabled={processing}
|
||||||
|
onChange={(event) => {
|
||||||
|
if (event.target.checked) {
|
||||||
|
change('enabled', true);
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
))}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div className="mt-5">
|
<div className="mt-5">
|
||||||
|
|||||||
@@ -8,13 +8,14 @@ import Form from './Form';
|
|||||||
class StatsConfig extends Component {
|
class StatsConfig extends Component {
|
||||||
handleFormSubmit = (values) => {
|
handleFormSubmit = (values) => {
|
||||||
const { t, interval: prevInterval } = this.props;
|
const { t, interval: prevInterval } = this.props;
|
||||||
|
const config = { interval: values.interval };
|
||||||
|
|
||||||
if (values.interval < prevInterval) {
|
if (config.interval < prevInterval) {
|
||||||
if (window.confirm(t('statistics_retention_confirm'))) {
|
if (window.confirm(t('statistics_retention_confirm'))) {
|
||||||
this.props.setStatsConfig(values);
|
this.props.setStatsConfig(config);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
this.props.setStatsConfig(values);
|
this.props.setStatsConfig(config);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -39,7 +40,10 @@ class StatsConfig extends Component {
|
|||||||
>
|
>
|
||||||
<div className="form">
|
<div className="form">
|
||||||
<Form
|
<Form
|
||||||
initialValues={{ interval }}
|
initialValues={{
|
||||||
|
interval,
|
||||||
|
enabled: !!interval,
|
||||||
|
}}
|
||||||
onSubmit={this.handleFormSubmit}
|
onSubmit={this.handleFormSubmit}
|
||||||
processing={processing}
|
processing={processing}
|
||||||
processingReset={processingReset}
|
processingReset={processingReset}
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
.text-edit-container {
|
.text-edit-container {
|
||||||
position: relative;
|
position: relative;
|
||||||
height: 10rem;
|
min-height: 240px;
|
||||||
|
overflow: hidden;
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-input,
|
.text-input,
|
||||||
@@ -10,33 +11,20 @@
|
|||||||
left: 0;
|
left: 0;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
height: 100%;
|
height: 100%;
|
||||||
padding: 1rem;
|
padding: 16px;
|
||||||
background: transparent;
|
background: transparent;
|
||||||
white-space: pre-wrap;
|
white-space: pre-wrap;
|
||||||
line-height: 1.5rem;
|
line-height: 24px;
|
||||||
word-wrap: break-word;
|
word-wrap: break-word;
|
||||||
font-size: var(--font-size-disable-autozoom);
|
font-size: var(--font-size-disable-autozoom);
|
||||||
margin: 0;
|
margin: 0;
|
||||||
}
|
overscroll-behavior: none;
|
||||||
|
|
||||||
.form--upstream .text-input,
|
|
||||||
.form--upstream .text-output {
|
|
||||||
width: 98%;
|
|
||||||
left: 1%;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-input {
|
.text-input {
|
||||||
|
position: relative;
|
||||||
opacity: 1;
|
opacity: 1;
|
||||||
resize: none;
|
min-height: 240px;
|
||||||
height: 10rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-input--larger {
|
|
||||||
height: 11rem;
|
|
||||||
}
|
|
||||||
|
|
||||||
.text-input--largest {
|
|
||||||
height: 16rem;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.text-output {
|
.text-output {
|
||||||
|
|||||||
@@ -202,7 +202,7 @@ export const FILTERS_URLS = {
|
|||||||
export const SERVICES = [
|
export const SERVICES = [
|
||||||
{
|
{
|
||||||
id: '9gag',
|
id: '9gag',
|
||||||
name: '9Gag',
|
name: '9GAG',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: 'amazon',
|
id: 'amazon',
|
||||||
@@ -355,7 +355,8 @@ export const ENCRYPTION_SOURCE = {
|
|||||||
export const FILTERED = 'Filtered';
|
export const FILTERED = 'Filtered';
|
||||||
export const NOT_FILTERED = 'NotFiltered';
|
export const NOT_FILTERED = 'NotFiltered';
|
||||||
|
|
||||||
export const STATS_INTERVALS_DAYS = [0, 1, 7, 30, 90];
|
export const DISABLED_STATS_INTERVAL = 0;
|
||||||
|
export const STATS_INTERVALS_DAYS = [1, 7, 30, 90];
|
||||||
|
|
||||||
export const QUERY_LOG_INTERVALS_DAYS = [0.25, 1, 7, 30, 90];
|
export const QUERY_LOG_INTERVALS_DAYS = [0.25, 1, 7, 30, 90];
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
// eslint-disable-next-line import/no-extraneous-dependencies
|
||||||
import twosky from 'MainRoot/.twosky.json';
|
import twosky from 'MainRoot/.twosky.json';
|
||||||
|
|
||||||
export const {
|
export const {
|
||||||
|
|||||||
@@ -47,7 +47,6 @@ Submit = connect((state) => {
|
|||||||
};
|
};
|
||||||
})(Submit);
|
})(Submit);
|
||||||
|
|
||||||
|
|
||||||
export default flow([
|
export default flow([
|
||||||
withTranslation(),
|
withTranslation(),
|
||||||
reduxForm({
|
reduxForm({
|
||||||
|
|||||||
17
go.mod
17
go.mod
@@ -3,11 +3,11 @@ module github.com/AdguardTeam/AdGuardHome
|
|||||||
go 1.16
|
go 1.16
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/AdguardTeam/dnsproxy v0.39.2
|
github.com/AdguardTeam/dnsproxy v0.39.8
|
||||||
github.com/AdguardTeam/golibs v0.8.4
|
github.com/AdguardTeam/golibs v0.9.3
|
||||||
github.com/AdguardTeam/urlfilter v0.14.6
|
github.com/AdguardTeam/urlfilter v0.14.6
|
||||||
github.com/NYTimes/gziphandler v1.1.1
|
github.com/NYTimes/gziphandler v1.1.1
|
||||||
github.com/ameshkov/dnscrypt/v2 v2.2.1
|
github.com/ameshkov/dnscrypt/v2 v2.2.2
|
||||||
github.com/digineo/go-ipset/v2 v2.2.1
|
github.com/digineo/go-ipset/v2 v2.2.1
|
||||||
github.com/fsnotify/fsnotify v1.4.9
|
github.com/fsnotify/fsnotify v1.4.9
|
||||||
github.com/go-ping/ping v0.0.0-20210506233800-ff8be3320020
|
github.com/go-ping/ping v0.0.0-20210506233800-ff8be3320020
|
||||||
@@ -18,18 +18,19 @@ require (
|
|||||||
github.com/lucas-clemente/quic-go v0.21.1
|
github.com/lucas-clemente/quic-go v0.21.1
|
||||||
github.com/mdlayher/netlink v1.4.0
|
github.com/mdlayher/netlink v1.4.0
|
||||||
github.com/mdlayher/raw v0.0.0-20210412142147-51b895745faf // indirect
|
github.com/mdlayher/raw v0.0.0-20210412142147-51b895745faf // indirect
|
||||||
github.com/miekg/dns v1.1.42
|
github.com/miekg/dns v1.1.43
|
||||||
github.com/satori/go.uuid v1.2.0
|
github.com/satori/go.uuid v1.2.0
|
||||||
github.com/stretchr/objx v0.1.1 // indirect
|
github.com/stretchr/objx v0.1.1 // indirect
|
||||||
github.com/stretchr/testify v1.7.0
|
github.com/stretchr/testify v1.7.0
|
||||||
github.com/ti-mo/netfilter v0.4.0
|
github.com/ti-mo/netfilter v0.4.0
|
||||||
go.etcd.io/bbolt v1.3.5
|
go.etcd.io/bbolt v1.3.6
|
||||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a
|
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5
|
||||||
golang.org/x/net v0.0.0-20210510120150-4163338589ed
|
golang.org/x/net v0.0.0-20210825183410-e898025ed96a
|
||||||
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015
|
golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0
|
gopkg.in/natefinch/lumberjack.v2 v2.0.0
|
||||||
gopkg.in/yaml.v2 v2.4.0
|
gopkg.in/yaml.v2 v2.4.0
|
||||||
howett.net/plist v0.0.0-20201203080718-1454fab16a06
|
howett.net/plist v0.0.0-20201203080718-1454fab16a06
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// TODO(e.burkov): Get rid of the fork in v0.108.0.
|
||||||
replace github.com/insomniacslk/dhcp => github.com/AdguardTeam/dhcp v0.0.0-20210519141215-51808c73c0bf
|
replace github.com/insomniacslk/dhcp => github.com/AdguardTeam/dhcp v0.0.0-20210519141215-51808c73c0bf
|
||||||
|
|||||||
39
go.sum
39
go.sum
@@ -9,13 +9,13 @@ dmitri.shuralyov.com/state v0.0.0-20180228185332-28bcc343414c/go.mod h1:0PRwlb0D
|
|||||||
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
|
git.apache.org/thrift.git v0.0.0-20180902110319-2566ecd5d999/go.mod h1:fPE2ZNJGynbRyZ4dJvy6G277gSllfV2HJqblrnkyeyg=
|
||||||
github.com/AdguardTeam/dhcp v0.0.0-20210519141215-51808c73c0bf h1:gc042VRSIRSUzZ+Px6xQCRWNJZTaPkomisDfUZmoFNk=
|
github.com/AdguardTeam/dhcp v0.0.0-20210519141215-51808c73c0bf h1:gc042VRSIRSUzZ+Px6xQCRWNJZTaPkomisDfUZmoFNk=
|
||||||
github.com/AdguardTeam/dhcp v0.0.0-20210519141215-51808c73c0bf/go.mod h1:TKl4jN3Voofo4UJIicyNhWGp/nlQqQkFxmwIFTvBkKI=
|
github.com/AdguardTeam/dhcp v0.0.0-20210519141215-51808c73c0bf/go.mod h1:TKl4jN3Voofo4UJIicyNhWGp/nlQqQkFxmwIFTvBkKI=
|
||||||
github.com/AdguardTeam/dnsproxy v0.39.2 h1:GqsR1S4fFfVsVCSrdrfa0RfsQ2u+MeNUMqDkxdTD3gU=
|
github.com/AdguardTeam/dnsproxy v0.39.8 h1:miRhkZBx/19Rs1o10r3QC0D0Zc2J2Id/cqXwfvLOyM0=
|
||||||
github.com/AdguardTeam/dnsproxy v0.39.2/go.mod h1:aNXKNdTyKfgAG2OS712SYSaGIM9AasZsZxfiY4YiR/0=
|
github.com/AdguardTeam/dnsproxy v0.39.8/go.mod h1:eDpJKAdkHORRwAedjuERv+7SWlcz4cn+5uwrbUAWHRY=
|
||||||
github.com/AdguardTeam/golibs v0.4.0/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4=
|
github.com/AdguardTeam/golibs v0.4.0/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4=
|
||||||
github.com/AdguardTeam/golibs v0.4.2/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4=
|
github.com/AdguardTeam/golibs v0.4.2/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4=
|
||||||
github.com/AdguardTeam/golibs v0.8.0/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4=
|
github.com/AdguardTeam/golibs v0.9.2/go.mod h1:fCAMwPBJ8S7YMYbTWvYS+eeTLblP5E04IDtNAo7y7IY=
|
||||||
github.com/AdguardTeam/golibs v0.8.4 h1:jd6GwvQQtfSLOKn30qisDVujvas3q7Agjm3BOEqRWpQ=
|
github.com/AdguardTeam/golibs v0.9.3 h1:noeKHJEzrSwxzX0Zi3USM3cXf1qQV99SO772jet/uEY=
|
||||||
github.com/AdguardTeam/golibs v0.8.4/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4=
|
github.com/AdguardTeam/golibs v0.9.3/go.mod h1:fCAMwPBJ8S7YMYbTWvYS+eeTLblP5E04IDtNAo7y7IY=
|
||||||
github.com/AdguardTeam/gomitmproxy v0.2.0/go.mod h1:Qdv0Mktnzer5zpdpi5rAwixNJzW2FN91LjKJCkVbYGU=
|
github.com/AdguardTeam/gomitmproxy v0.2.0/go.mod h1:Qdv0Mktnzer5zpdpi5rAwixNJzW2FN91LjKJCkVbYGU=
|
||||||
github.com/AdguardTeam/urlfilter v0.14.6 h1:emqoKZElooHACYehRBYENeKVN1a/rspxiqTIMYLuoIo=
|
github.com/AdguardTeam/urlfilter v0.14.6 h1:emqoKZElooHACYehRBYENeKVN1a/rspxiqTIMYLuoIo=
|
||||||
github.com/AdguardTeam/urlfilter v0.14.6/go.mod h1:klx4JbOfc4EaNb5lWLqOwfg+pVcyRukmoJRvO55lL5U=
|
github.com/AdguardTeam/urlfilter v0.14.6/go.mod h1:klx4JbOfc4EaNb5lWLqOwfg+pVcyRukmoJRvO55lL5U=
|
||||||
@@ -29,9 +29,8 @@ github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da h1:KjTM2ks9d14ZYCvmH
|
|||||||
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA=
|
github.com/aead/chacha20 v0.0.0-20180709150244-8b13a72661da/go.mod h1:eHEWzANqSiWQsof+nXEI9bUVUyV6F53Fp89EuCh2EAA=
|
||||||
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 h1:52m0LGchQBBVqJRyYYufQuIbVqRawmubW3OFGqK1ekw=
|
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635 h1:52m0LGchQBBVqJRyYYufQuIbVqRawmubW3OFGqK1ekw=
|
||||||
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635/go.mod h1:lmLxL+FV291OopO93Bwf9fQLQeLyt33VJRUg5VJ30us=
|
github.com/aead/poly1305 v0.0.0-20180717145839-3fee0db0b635/go.mod h1:lmLxL+FV291OopO93Bwf9fQLQeLyt33VJRUg5VJ30us=
|
||||||
github.com/ameshkov/dnscrypt/v2 v2.1.3/go.mod h1:+8SbPbVXpxxcUsgGi8eodkqWPo1MyNHxKYC8hDpqLSo=
|
github.com/ameshkov/dnscrypt/v2 v2.2.2 h1:lxtS1iSA2EjTOMToSi+2+rwspNA+b/wG5/JpccvE9CU=
|
||||||
github.com/ameshkov/dnscrypt/v2 v2.2.1 h1:+cApRxzeBZqjUNsN26TTz7r5A8U+buON3kJgIYE3QWQ=
|
github.com/ameshkov/dnscrypt/v2 v2.2.2/go.mod h1:+8SbPbVXpxxcUsgGi8eodkqWPo1MyNHxKYC8hDpqLSo=
|
||||||
github.com/ameshkov/dnscrypt/v2 v2.2.1/go.mod h1:+8SbPbVXpxxcUsgGi8eodkqWPo1MyNHxKYC8hDpqLSo=
|
|
||||||
github.com/ameshkov/dnsstamps v1.0.1/go.mod h1:Ii3eUu73dx4Vw5O4wjzmT5+lkCwovjzaEZZ4gKyIH5A=
|
github.com/ameshkov/dnsstamps v1.0.1/go.mod h1:Ii3eUu73dx4Vw5O4wjzmT5+lkCwovjzaEZZ4gKyIH5A=
|
||||||
github.com/ameshkov/dnsstamps v1.0.3 h1:Srzik+J9mivH1alRACTbys2xOxs0lRH9qnTA7Y1OYVo=
|
github.com/ameshkov/dnsstamps v1.0.3 h1:Srzik+J9mivH1alRACTbys2xOxs0lRH9qnTA7Y1OYVo=
|
||||||
github.com/ameshkov/dnsstamps v1.0.3/go.mod h1:Ii3eUu73dx4Vw5O4wjzmT5+lkCwovjzaEZZ4gKyIH5A=
|
github.com/ameshkov/dnsstamps v1.0.3/go.mod h1:Ii3eUu73dx4Vw5O4wjzmT5+lkCwovjzaEZZ4gKyIH5A=
|
||||||
@@ -171,8 +170,8 @@ github.com/mdlayher/raw v0.0.0-20210412142147-51b895745faf/go.mod h1:7EpbotpCmVZ
|
|||||||
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
|
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
|
||||||
github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
|
github.com/miekg/dns v1.1.35/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
|
||||||
github.com/miekg/dns v1.1.40/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
|
github.com/miekg/dns v1.1.40/go.mod h1:KNUDUusw/aVsxyTYZM1oqvCicbwhgbNgztCETuNZ7xM=
|
||||||
github.com/miekg/dns v1.1.42 h1:gWGe42RGaIqXQZ+r3WUGEKBEtvPHY2SXo4dqixDNxuY=
|
github.com/miekg/dns v1.1.43 h1:JKfpVSCB84vrAmHzyrsxB5NAr5kLoMXZArPSw7Qlgyg=
|
||||||
github.com/miekg/dns v1.1.42/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
|
github.com/miekg/dns v1.1.43/go.mod h1:+evo5L0630/F6ca/Z9+GAqzhjGyn8/c+TBaOyfEl0V4=
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
|
||||||
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3RllmbCylyMrvgv0=
|
||||||
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
|
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
|
||||||
@@ -250,8 +249,8 @@ github.com/u-root/u-root v7.0.0+incompatible/go.mod h1:RYkpo8pTHrNjW08opNd/U6p/R
|
|||||||
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
|
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
|
||||||
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
|
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
|
||||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
go.etcd.io/bbolt v1.3.5 h1:XAzx9gjCb0Rxj7EoqcClPD1d5ZBxZJk0jbuoPHenBt0=
|
go.etcd.io/bbolt v1.3.6 h1:/ecaJf0sk1l4l6V4awd65v2C3ILy7MSj+s/x1ADCIMU=
|
||||||
go.etcd.io/bbolt v1.3.5/go.mod h1:G5EMThwa9y8QZGBClrRx5EY+Yw9kAhnjy3bSjsnlVTQ=
|
go.etcd.io/bbolt v1.3.6/go.mod h1:qXsaaIqmgQH0T+OPdb99Bf+PKfBBQVAdyD6TY9G8XM4=
|
||||||
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
|
go.opencensus.io v0.18.0/go.mod h1:vKdFvxhtzZ9onBp9VKHK8z/sRpBMnKAsufL7wlDrCOA=
|
||||||
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
|
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
|
||||||
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
|
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
|
||||||
@@ -263,8 +262,8 @@ golang.org/x/crypto v0.0.0-20200221231518-2aa609cf4a9d/go.mod h1:LzIPMQfyMNhhGPh
|
|||||||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
golang.org/x/crypto v0.0.0-20201208171446-5f87f3452ae9/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
|
||||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a h1:kr2P4QFmQr29mSLA43kwrOcgcReGTfbE9N577tCTuBc=
|
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5 h1:HWj/xjIHfjYU5nVXpTM0s39J9CbLn7Cc5a7IC5rwsMQ=
|
||||||
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
|
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||||
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20180702182130-06c8688daad7/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||||
@@ -300,8 +299,9 @@ golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v
|
|||||||
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||||
golang.org/x/net v0.0.0-20210510120150-4163338589ed h1:p9UgmWI9wKpfYmgaV/IZKGdXc5qEK45tDwwwDyjS26I=
|
golang.org/x/net v0.0.0-20210726213435-c6fcb2dbf985/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20210510120150-4163338589ed/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20210825183410-e898025ed96a h1:bRuuGXV8wwSdGTB+CtJf+FjgO1APK1CoO39T4BN/XBw=
|
||||||
|
golang.org/x/net v0.0.0-20210825183410-e898025ed96a/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20181017192945-9dcd33a902f4/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20181203162652-d668ce993890/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
@@ -337,6 +337,7 @@ golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200331124033-c3d80250170d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200519105757-fe76b779f299/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
|
golang.org/x/sys v0.0.0-20200923182605-d9f96fdee20d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201009025420-dfb3f7c4e634/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201015000850-e3ed0017c211/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -354,15 +355,15 @@ golang.org/x/sys v0.0.0-20210303074136-134d130e1a04/go.mod h1:h1NjWce9XRLGQEsW7w
|
|||||||
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015 h1:hZR0X1kPW+nwyJ9xRxqZk1vx5RUObAPBdKVvXPDUH/E=
|
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210514084401-e8d321eab015/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e h1:XMgFehsDnnLGtjvjOfqWSUzt0alpTR1RSEuznObga2c=
|
||||||
|
golang.org/x/sys v0.0.0-20210831042530-f4d43177bf5e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
golang.org/x/term v0.0.0-20201117132131-f5c789dd3221/go.mod h1:Nr5EML6q2oocZ2LXRh80K7BxOlk5/8JxuGnuhpl+muw=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.1-0.20180807135948-17ff2d5776d2/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.4/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
|
||||||
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
golang.org/x/text v0.3.6 h1:aRYxNxv6iGQlyVaZmk6ZgYEDa+Jg18DxebPSrd6bg1M=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.0.0-20180412165947-fbb02b2291d2/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
|
|||||||
@@ -1,206 +0,0 @@
|
|||||||
package aghnet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
|
||||||
"golang.org/x/net/idna"
|
|
||||||
)
|
|
||||||
|
|
||||||
// CloneIP returns a clone of an IP address.
|
|
||||||
func CloneIP(ip net.IP) (clone net.IP) {
|
|
||||||
if ip != nil && len(ip) == 0 {
|
|
||||||
return net.IP{}
|
|
||||||
}
|
|
||||||
|
|
||||||
return append(clone, ip...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// CloneMAC returns a clone of a MAC address.
|
|
||||||
func CloneMAC(mac net.HardwareAddr) (clone net.HardwareAddr) {
|
|
||||||
if mac != nil && len(mac) == 0 {
|
|
||||||
return net.HardwareAddr{}
|
|
||||||
}
|
|
||||||
|
|
||||||
return append(clone, mac...)
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPFromAddr returns an IP address from addr. If addr is neither
|
|
||||||
// a *net.TCPAddr nor a *net.UDPAddr, it returns nil.
|
|
||||||
func IPFromAddr(addr net.Addr) (ip net.IP) {
|
|
||||||
switch addr := addr.(type) {
|
|
||||||
case *net.TCPAddr:
|
|
||||||
return addr.IP
|
|
||||||
case *net.UDPAddr:
|
|
||||||
return addr.IP
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// IsValidHostOuterRune returns true if r is a valid initial or final rune for
|
|
||||||
// a hostname label.
|
|
||||||
func IsValidHostOuterRune(r rune) (ok bool) {
|
|
||||||
return (r >= 'a' && r <= 'z') ||
|
|
||||||
(r >= 'A' && r <= 'Z') ||
|
|
||||||
(r >= '0' && r <= '9')
|
|
||||||
}
|
|
||||||
|
|
||||||
// JoinHostPort is a convinient wrapper for net.JoinHostPort with port of type
|
|
||||||
// int.
|
|
||||||
func JoinHostPort(host string, port int) (hostport string) {
|
|
||||||
return net.JoinHostPort(host, strconv.Itoa(port))
|
|
||||||
}
|
|
||||||
|
|
||||||
// isValidHostRune returns true if r is a valid rune for a hostname label.
|
|
||||||
func isValidHostRune(r rune) (ok bool) {
|
|
||||||
return r == '-' || IsValidHostOuterRune(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidateHardwareAddress returns an error if hwa is not a valid EUI-48,
|
|
||||||
// EUI-64, or 20-octet InfiniBand link-layer address.
|
|
||||||
func ValidateHardwareAddress(hwa net.HardwareAddr) (err error) {
|
|
||||||
defer func() { err = errors.Annotate(err, "validating hardware address %q: %w", hwa) }()
|
|
||||||
|
|
||||||
switch l := len(hwa); l {
|
|
||||||
case 0:
|
|
||||||
return errors.Error("address is empty")
|
|
||||||
case 6, 8, 20:
|
|
||||||
return nil
|
|
||||||
default:
|
|
||||||
return fmt.Errorf("bad len: %d", l)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// maxDomainLabelLen is the maximum allowed length of a domain name label
|
|
||||||
// according to RFC 1035.
|
|
||||||
const maxDomainLabelLen = 63
|
|
||||||
|
|
||||||
// MaxDomainNameLen is the maximum allowed length of a full domain name
|
|
||||||
// according to RFC 1035.
|
|
||||||
//
|
|
||||||
// See https://stackoverflow.com/a/32294443/1892060.
|
|
||||||
const MaxDomainNameLen = 253
|
|
||||||
|
|
||||||
// ValidateDomainNameLabel returns an error if label is not a valid label of
|
|
||||||
// a domain name.
|
|
||||||
func ValidateDomainNameLabel(label string) (err error) {
|
|
||||||
defer func() { err = errors.Annotate(err, "validating label %q: %w", label) }()
|
|
||||||
|
|
||||||
l := len(label)
|
|
||||||
if l > maxDomainLabelLen {
|
|
||||||
return fmt.Errorf("label is too long, max: %d", maxDomainLabelLen)
|
|
||||||
} else if l == 0 {
|
|
||||||
return errors.Error("label is empty")
|
|
||||||
}
|
|
||||||
|
|
||||||
if r := label[0]; !IsValidHostOuterRune(rune(r)) {
|
|
||||||
return fmt.Errorf("invalid char %q at index %d", r, 0)
|
|
||||||
} else if l == 1 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
for i, r := range label[1 : l-1] {
|
|
||||||
if !isValidHostRune(r) {
|
|
||||||
return fmt.Errorf("invalid char %q at index %d", r, i+1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if r := label[l-1]; !IsValidHostOuterRune(rune(r)) {
|
|
||||||
return fmt.Errorf("invalid char %q at index %d", r, l-1)
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// ValidateDomainName validates the domain name in accordance to RFC 952, RFC
|
|
||||||
// 1035, and with RFC-1123's inclusion of digits at the start of the host. It
|
|
||||||
// doesn't validate against two or more hyphens to allow punycode and
|
|
||||||
// internationalized domains.
|
|
||||||
//
|
|
||||||
// TODO(a.garipov): After making sure that this works correctly, port this into
|
|
||||||
// module golibs.
|
|
||||||
func ValidateDomainName(name string) (err error) {
|
|
||||||
defer func() { err = errors.Annotate(err, "validating domain name %q: %w", name) }()
|
|
||||||
|
|
||||||
name, err = idna.ToASCII(name)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
l := len(name)
|
|
||||||
if l == 0 {
|
|
||||||
return errors.Error("domain name is empty")
|
|
||||||
} else if l > MaxDomainNameLen {
|
|
||||||
return fmt.Errorf("too long, max: %d", MaxDomainNameLen)
|
|
||||||
}
|
|
||||||
|
|
||||||
labels := strings.Split(name, ".")
|
|
||||||
for i, l := range labels {
|
|
||||||
err = ValidateDomainNameLabel(l)
|
|
||||||
if err != nil {
|
|
||||||
return fmt.Errorf("invalid domain name label at index %d: %w", i, err)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// The maximum lengths of generated hostnames for different IP versions.
|
|
||||||
const (
|
|
||||||
ipv4HostnameMaxLen = len("192-168-100-100")
|
|
||||||
ipv6HostnameMaxLen = len("ff80-f076-0000-0000-0000-0000-0000-0010")
|
|
||||||
)
|
|
||||||
|
|
||||||
// generateIPv4Hostname generates the hostname for specific IP version.
|
|
||||||
func generateIPv4Hostname(ipv4 net.IP) (hostname string) {
|
|
||||||
hnData := make([]byte, 0, ipv4HostnameMaxLen)
|
|
||||||
for i, part := range ipv4 {
|
|
||||||
if i > 0 {
|
|
||||||
hnData = append(hnData, '-')
|
|
||||||
}
|
|
||||||
hnData = strconv.AppendUint(hnData, uint64(part), 10)
|
|
||||||
}
|
|
||||||
|
|
||||||
return string(hnData)
|
|
||||||
}
|
|
||||||
|
|
||||||
// generateIPv6Hostname generates the hostname for specific IP version.
|
|
||||||
func generateIPv6Hostname(ipv6 net.IP) (hostname string) {
|
|
||||||
hnData := make([]byte, 0, ipv6HostnameMaxLen)
|
|
||||||
for i, partsNum := 0, net.IPv6len/2; i < partsNum; i++ {
|
|
||||||
if i > 0 {
|
|
||||||
hnData = append(hnData, '-')
|
|
||||||
}
|
|
||||||
for _, val := range ipv6[i*2 : i*2+2] {
|
|
||||||
if val < 10 {
|
|
||||||
hnData = append(hnData, '0')
|
|
||||||
}
|
|
||||||
hnData = strconv.AppendUint(hnData, uint64(val), 16)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return string(hnData)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GenerateHostname generates the hostname from ip. In case of using IPv4 the
|
|
||||||
// result should be like:
|
|
||||||
//
|
|
||||||
// 192-168-10-1
|
|
||||||
//
|
|
||||||
// In case of using IPv6, the result is like:
|
|
||||||
//
|
|
||||||
// ff80-f076-0000-0000-0000-0000-0000-0010
|
|
||||||
//
|
|
||||||
func GenerateHostname(ip net.IP) (hostname string) {
|
|
||||||
if ipv4 := ip.To4(); ipv4 != nil {
|
|
||||||
return generateIPv4Hostname(ipv4)
|
|
||||||
} else if ipv6 := ip.To16(); ipv6 != nil {
|
|
||||||
return generateIPv6Hostname(ipv6)
|
|
||||||
}
|
|
||||||
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
@@ -1,228 +0,0 @@
|
|||||||
package aghnet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"strings"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestCloneIP(t *testing.T) {
|
|
||||||
assert.Equal(t, net.IP(nil), CloneIP(nil))
|
|
||||||
assert.Equal(t, net.IP{}, CloneIP(net.IP{}))
|
|
||||||
|
|
||||||
ip := net.IP{1, 2, 3, 4}
|
|
||||||
clone := CloneIP(ip)
|
|
||||||
assert.Equal(t, ip, clone)
|
|
||||||
assert.NotSame(t, &ip[0], &clone[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestCloneMAC(t *testing.T) {
|
|
||||||
assert.Equal(t, net.HardwareAddr(nil), CloneMAC(nil))
|
|
||||||
assert.Equal(t, net.HardwareAddr{}, CloneMAC(net.HardwareAddr{}))
|
|
||||||
|
|
||||||
mac := net.HardwareAddr{0x12, 0x34, 0x56, 0x78, 0x9A, 0xBC}
|
|
||||||
clone := CloneMAC(mac)
|
|
||||||
assert.Equal(t, mac, clone)
|
|
||||||
assert.NotSame(t, &mac[0], &clone[0])
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIPFromAddr(t *testing.T) {
|
|
||||||
ip := net.IP{1, 2, 3, 4}
|
|
||||||
assert.Equal(t, net.IP(nil), IPFromAddr(nil))
|
|
||||||
assert.Equal(t, net.IP(nil), IPFromAddr(struct{ net.Addr }{}))
|
|
||||||
assert.Equal(t, ip, IPFromAddr(&net.TCPAddr{IP: ip}))
|
|
||||||
assert.Equal(t, ip, IPFromAddr(&net.UDPAddr{IP: ip}))
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestValidateHardwareAddress(t *testing.T) {
|
|
||||||
testCases := []struct {
|
|
||||||
name string
|
|
||||||
wantErrMsg string
|
|
||||||
in net.HardwareAddr
|
|
||||||
}{{
|
|
||||||
name: "success_eui_48",
|
|
||||||
wantErrMsg: "",
|
|
||||||
in: net.HardwareAddr{0x00, 0x01, 0x02, 0x03, 0x04, 0x05},
|
|
||||||
}, {
|
|
||||||
name: "success_eui_64",
|
|
||||||
wantErrMsg: "",
|
|
||||||
in: net.HardwareAddr{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07},
|
|
||||||
}, {
|
|
||||||
name: "success_infiniband",
|
|
||||||
wantErrMsg: "",
|
|
||||||
in: net.HardwareAddr{
|
|
||||||
0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07,
|
|
||||||
0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f,
|
|
||||||
0x10, 0x11, 0x12, 0x13,
|
|
||||||
},
|
|
||||||
}, {
|
|
||||||
name: "error_nil",
|
|
||||||
wantErrMsg: `validating hardware address "": address is empty`,
|
|
||||||
in: nil,
|
|
||||||
}, {
|
|
||||||
name: "error_empty",
|
|
||||||
wantErrMsg: `validating hardware address "": address is empty`,
|
|
||||||
in: net.HardwareAddr{},
|
|
||||||
}, {
|
|
||||||
name: "error_bad",
|
|
||||||
wantErrMsg: `validating hardware address "00:01:02:03": bad len: 4`,
|
|
||||||
in: net.HardwareAddr{0x00, 0x01, 0x02, 0x03},
|
|
||||||
}}
|
|
||||||
|
|
||||||
for _, tc := range testCases {
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
|
||||||
err := ValidateHardwareAddress(tc.in)
|
|
||||||
if tc.wantErrMsg == "" {
|
|
||||||
assert.NoError(t, err)
|
|
||||||
} else {
|
|
||||||
require.Error(t, err)
|
|
||||||
|
|
||||||
assert.Equal(t, tc.wantErrMsg, err.Error())
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestJoinHostPort(t *testing.T) {
|
|
||||||
assert.Equal(t, ":0", JoinHostPort("", 0))
|
|
||||||
assert.Equal(t, "host:12345", JoinHostPort("host", 12345))
|
|
||||||
assert.Equal(t, "1.2.3.4:12345", JoinHostPort("1.2.3.4", 12345))
|
|
||||||
assert.Equal(t, "[1234::5678]:12345", JoinHostPort("1234::5678", 12345))
|
|
||||||
assert.Equal(t, "[1234::5678%lo]:12345", JoinHostPort("1234::5678%lo", 12345))
|
|
||||||
}
|
|
||||||
|
|
||||||
func repeatStr(b *strings.Builder, s string, n int) {
|
|
||||||
for i := 0; i < n; i++ {
|
|
||||||
_, _ = b.WriteString(s)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestValidateDomainName(t *testing.T) {
|
|
||||||
b := &strings.Builder{}
|
|
||||||
repeatStr(b, "a", 255)
|
|
||||||
longDomainName := b.String()
|
|
||||||
|
|
||||||
b.Reset()
|
|
||||||
repeatStr(b, "a", 64)
|
|
||||||
longLabel := b.String()
|
|
||||||
|
|
||||||
_, _ = b.WriteString(".com")
|
|
||||||
longLabelDomainName := b.String()
|
|
||||||
|
|
||||||
testCases := []struct {
|
|
||||||
name string
|
|
||||||
in string
|
|
||||||
wantErrMsg string
|
|
||||||
}{{
|
|
||||||
name: "success",
|
|
||||||
in: "example.com",
|
|
||||||
wantErrMsg: "",
|
|
||||||
}, {
|
|
||||||
name: "success_idna",
|
|
||||||
in: "пример.рф",
|
|
||||||
wantErrMsg: "",
|
|
||||||
}, {
|
|
||||||
name: "success_one",
|
|
||||||
in: "e",
|
|
||||||
wantErrMsg: "",
|
|
||||||
}, {
|
|
||||||
name: "empty",
|
|
||||||
in: "",
|
|
||||||
wantErrMsg: `validating domain name "": domain name is empty`,
|
|
||||||
}, {
|
|
||||||
name: "bad_symbol",
|
|
||||||
in: "!!!",
|
|
||||||
wantErrMsg: `validating domain name "!!!": invalid domain name label at index 0: ` +
|
|
||||||
`validating label "!!!": invalid char '!' at index 0`,
|
|
||||||
}, {
|
|
||||||
name: "bad_length",
|
|
||||||
in: longDomainName,
|
|
||||||
wantErrMsg: `validating domain name "` + longDomainName + `": too long, max: 253`,
|
|
||||||
}, {
|
|
||||||
name: "bad_label_length",
|
|
||||||
in: longLabelDomainName,
|
|
||||||
wantErrMsg: `validating domain name "` + longLabelDomainName + `": ` +
|
|
||||||
`invalid domain name label at index 0: validating label "` + longLabel +
|
|
||||||
`": label is too long, max: 63`,
|
|
||||||
}, {
|
|
||||||
name: "bad_label_empty",
|
|
||||||
in: "example..com",
|
|
||||||
wantErrMsg: `validating domain name "example..com": ` +
|
|
||||||
`invalid domain name label at index 1: ` +
|
|
||||||
`validating label "": label is empty`,
|
|
||||||
}, {
|
|
||||||
name: "bad_label_first_symbol",
|
|
||||||
in: "example.-aa.com",
|
|
||||||
wantErrMsg: `validating domain name "example.-aa.com": ` +
|
|
||||||
`invalid domain name label at index 1: ` +
|
|
||||||
`validating label "-aa": invalid char '-' at index 0`,
|
|
||||||
}, {
|
|
||||||
name: "bad_label_last_symbol",
|
|
||||||
in: "example-.aa.com",
|
|
||||||
wantErrMsg: `validating domain name "example-.aa.com": ` +
|
|
||||||
`invalid domain name label at index 0: ` +
|
|
||||||
`validating label "example-": invalid char '-' at index 7`,
|
|
||||||
}, {
|
|
||||||
name: "bad_label_symbol",
|
|
||||||
in: "example.a!!!.com",
|
|
||||||
wantErrMsg: `validating domain name "example.a!!!.com": ` +
|
|
||||||
`invalid domain name label at index 1: ` +
|
|
||||||
`validating label "a!!!": invalid char '!' at index 1`,
|
|
||||||
}}
|
|
||||||
|
|
||||||
for _, tc := range testCases {
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
|
||||||
err := ValidateDomainName(tc.in)
|
|
||||||
if tc.wantErrMsg == "" {
|
|
||||||
assert.NoError(t, err)
|
|
||||||
} else {
|
|
||||||
require.Error(t, err)
|
|
||||||
|
|
||||||
assert.Equal(t, tc.wantErrMsg, err.Error())
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestGenerateHostName(t *testing.T) {
|
|
||||||
testCases := []struct {
|
|
||||||
name string
|
|
||||||
want string
|
|
||||||
ip net.IP
|
|
||||||
}{{
|
|
||||||
name: "good_ipv4",
|
|
||||||
want: "127-0-0-1",
|
|
||||||
ip: net.IP{127, 0, 0, 1},
|
|
||||||
}, {
|
|
||||||
name: "bad_ipv4",
|
|
||||||
want: "",
|
|
||||||
ip: net.IP{127, 0, 0, 1, 0},
|
|
||||||
}, {
|
|
||||||
name: "good_ipv6",
|
|
||||||
want: "fe00-0000-0000-0000-0000-0000-0000-0001",
|
|
||||||
ip: net.ParseIP("fe00::1"),
|
|
||||||
}, {
|
|
||||||
name: "bad_ipv6",
|
|
||||||
want: "",
|
|
||||||
ip: net.IP{
|
|
||||||
0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff, 0xff,
|
|
||||||
0xff, 0xff, 0xff,
|
|
||||||
},
|
|
||||||
}, {
|
|
||||||
name: "nil",
|
|
||||||
want: "",
|
|
||||||
ip: nil,
|
|
||||||
}}
|
|
||||||
|
|
||||||
for _, tc := range testCases {
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
|
||||||
hostname := GenerateHostname(tc.ip)
|
|
||||||
assert.Equal(t, tc.want, hostname)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
6
internal/aghnet/dhcp.go
Normal file
6
internal/aghnet/dhcp.go
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
package aghnet
|
||||||
|
|
||||||
|
// CheckOtherDHCP tries to discover another DHCP server in the network.
|
||||||
|
func CheckOtherDHCP(ifaceName string) (ok4, ok6 bool, err4, err6 error) {
|
||||||
|
return checkOtherDHCP(ifaceName)
|
||||||
|
}
|
||||||
@@ -1,95 +1,132 @@
|
|||||||
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
|
//go:build aix || darwin || dragonfly || freebsd || linux || netbsd || openbsd || solaris
|
||||||
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
// +build aix darwin dragonfly freebsd linux netbsd openbsd solaris
|
||||||
|
|
||||||
package dhcpd
|
package aghnet
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"runtime"
|
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/aghnet"
|
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/aghos"
|
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
"github.com/AdguardTeam/golibs/log"
|
"github.com/AdguardTeam/golibs/log"
|
||||||
|
"github.com/AdguardTeam/golibs/netutil"
|
||||||
"github.com/insomniacslk/dhcp/dhcpv4"
|
"github.com/insomniacslk/dhcp/dhcpv4"
|
||||||
"github.com/insomniacslk/dhcp/dhcpv4/nclient4"
|
|
||||||
"github.com/insomniacslk/dhcp/dhcpv6"
|
"github.com/insomniacslk/dhcp/dhcpv6"
|
||||||
"github.com/insomniacslk/dhcp/dhcpv6/nclient6"
|
"github.com/insomniacslk/dhcp/dhcpv6/nclient6"
|
||||||
"github.com/insomniacslk/dhcp/iana"
|
"github.com/insomniacslk/dhcp/iana"
|
||||||
)
|
)
|
||||||
|
|
||||||
// CheckIfOtherDHCPServersPresentV4 sends a DHCP request to the specified network interface,
|
// defaultDiscoverTime is the
|
||||||
// and waits for a response for a period defined by defaultDiscoverTime
|
const defaultDiscoverTime = 3 * time.Second
|
||||||
func CheckIfOtherDHCPServersPresentV4(ifaceName string) (ok bool, err error) {
|
|
||||||
|
func checkOtherDHCP(ifaceName string) (ok4, ok6 bool, err4, err6 error) {
|
||||||
iface, err := net.InterfaceByName(ifaceName)
|
iface, err := net.InterfaceByName(ifaceName)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("couldn't find interface by name %s: %w", ifaceName, err)
|
err = fmt.Errorf("couldn't find interface by name %s: %w", ifaceName, err)
|
||||||
|
err4, err6 = err, err
|
||||||
|
|
||||||
|
return false, false, err4, err6
|
||||||
}
|
}
|
||||||
|
|
||||||
ifaceIPNet, err := ifaceIPAddrs(iface, ipVersion4)
|
ok4, err4 = checkOtherDHCPv4(iface)
|
||||||
if err != nil {
|
ok6, err6 = checkOtherDHCPv6(iface)
|
||||||
return false, fmt.Errorf("getting ipv4 addrs for iface %s: %w", ifaceName, err)
|
|
||||||
}
|
return ok4, ok6, err4, err6
|
||||||
if len(ifaceIPNet) == 0 {
|
}
|
||||||
return false, fmt.Errorf("interface %s has no ipv4 addresses", ifaceName)
|
|
||||||
|
// ifaceIPv4Subnet returns the first suitable IPv4 subnetwork iface has.
|
||||||
|
func ifaceIPv4Subnet(iface *net.Interface) (subnet *net.IPNet, err error) {
|
||||||
|
var addrs []net.Addr
|
||||||
|
if addrs, err = iface.Addrs(); err != nil {
|
||||||
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(a.garipov): Find out what this is about. Perhaps this
|
for _, a := range addrs {
|
||||||
// information is outdated or at least incomplete.
|
switch a := a.(type) {
|
||||||
if runtime.GOOS == "darwin" {
|
case *net.IPAddr:
|
||||||
return false, aghos.Unsupported("CheckIfOtherDHCPServersPresentV4")
|
subnet = &net.IPNet{
|
||||||
|
IP: a.IP,
|
||||||
|
Mask: a.IP.DefaultMask(),
|
||||||
|
}
|
||||||
|
case *net.IPNet:
|
||||||
|
subnet = a
|
||||||
|
default:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
if ip4 := subnet.IP.To4(); ip4 != nil {
|
||||||
|
subnet.IP = ip4
|
||||||
|
|
||||||
|
return subnet, nil
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
srcIP := ifaceIPNet[0]
|
return nil, fmt.Errorf("interface %s has no ipv4 addresses", iface.Name)
|
||||||
src := aghnet.JoinHostPort(srcIP.String(), 68)
|
}
|
||||||
dst := "255.255.255.255:67"
|
|
||||||
|
|
||||||
hostname, _ := os.Hostname()
|
// checkOtherDHCPv4 sends a DHCP request to the specified network interface, and
|
||||||
|
// waits for a response for a period defined by defaultDiscoverTime.
|
||||||
req, err := dhcpv4.NewDiscovery(iface.HardwareAddr)
|
func checkOtherDHCPv4(iface *net.Interface) (ok bool, err error) {
|
||||||
if err != nil {
|
var subnet *net.IPNet
|
||||||
return false, fmt.Errorf("dhcpv4.NewDiscovery: %w", err)
|
if subnet, err = ifaceIPv4Subnet(iface); err != nil {
|
||||||
}
|
return false, err
|
||||||
req.Options.Update(dhcpv4.OptClientIdentifier(iface.HardwareAddr))
|
|
||||||
req.Options.Update(dhcpv4.OptHostName(hostname))
|
|
||||||
|
|
||||||
// resolve 0.0.0.0:68
|
|
||||||
udpAddr, err := net.ResolveUDPAddr("udp4", src)
|
|
||||||
if err != nil {
|
|
||||||
return false, fmt.Errorf("couldn't resolve UDP address %s: %w", src, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if !udpAddr.IP.To4().Equal(srcIP) {
|
// Resolve broadcast addr.
|
||||||
return false, fmt.Errorf("resolved UDP address is not %s: %w", src, err)
|
dst := netutil.IPPort{
|
||||||
}
|
IP: BroadcastFromIPNet(subnet),
|
||||||
|
Port: 67,
|
||||||
// resolve 255.255.255.255:67
|
}.String()
|
||||||
dstAddr, err := net.ResolveUDPAddr("udp4", dst)
|
var dstAddr *net.UDPAddr
|
||||||
if err != nil {
|
if dstAddr, err = net.ResolveUDPAddr("udp4", dst); err != nil {
|
||||||
return false, fmt.Errorf("couldn't resolve UDP address %s: %w", dst, err)
|
return false, fmt.Errorf("couldn't resolve UDP address %s: %w", dst, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// bind to 0.0.0.0:68
|
var hostname string
|
||||||
log.Tracef("Listening to udp4 %+v", udpAddr)
|
if hostname, err = os.Hostname(); err != nil {
|
||||||
c, err := nclient4.NewRawUDPConn(ifaceName, 68)
|
return false, fmt.Errorf("couldn't get hostname: %w", err)
|
||||||
if err != nil {
|
|
||||||
return false, fmt.Errorf("couldn't listen on :68: %w", err)
|
|
||||||
}
|
|
||||||
if c != nil {
|
|
||||||
defer func() { err = errors.WithDeferred(err, c.Close()) }()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// send to 255.255.255.255:67
|
return discover4(iface, dstAddr, hostname)
|
||||||
_, err = c.WriteTo(req.ToBytes(), dstAddr)
|
}
|
||||||
if err != nil {
|
|
||||||
return false, fmt.Errorf("couldn't send a packet to %s: %w", dst, err)
|
func discover4(iface *net.Interface, dstAddr *net.UDPAddr, hostname string) (ok bool, err error) {
|
||||||
|
var req *dhcpv4.DHCPv4
|
||||||
|
if req, err = dhcpv4.NewDiscovery(iface.HardwareAddr); err != nil {
|
||||||
|
return false, fmt.Errorf("dhcpv4.NewDiscovery: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
req.Options.Update(dhcpv4.OptClientIdentifier(iface.HardwareAddr))
|
||||||
|
req.Options.Update(dhcpv4.OptHostName(hostname))
|
||||||
|
req.SetBroadcast()
|
||||||
|
|
||||||
|
// Bind to 0.0.0.0:68.
|
||||||
|
//
|
||||||
|
// On OpenBSD binding to the port 68 competes with dhclient's binding,
|
||||||
|
// so that all incoming packets are ignored and the discovering process
|
||||||
|
// is spoiled.
|
||||||
|
//
|
||||||
|
// It's also known that listening on the specified interface's address
|
||||||
|
// ignores broadcasted packets when reading.
|
||||||
|
var c net.PacketConn
|
||||||
|
if c, err = listenPacketReusable(iface.Name, "udp4", ":68"); err != nil {
|
||||||
|
return false, fmt.Errorf("couldn't listen on :68: %w", err)
|
||||||
|
}
|
||||||
|
defer func() { err = errors.WithDeferred(err, c.Close()) }()
|
||||||
|
|
||||||
|
// Send to broadcast.
|
||||||
|
if _, err = c.WriteTo(req.ToBytes(), dstAddr); err != nil {
|
||||||
|
return false, fmt.Errorf("couldn't send a packet to %s: %w", dstAddr, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
|
if err = c.SetDeadline(time.Now().Add(defaultDiscoverTime)); err != nil {
|
||||||
|
return false, fmt.Errorf("setting deadline: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
var next bool
|
var next bool
|
||||||
ok, next, err = tryConn4(req, c, iface)
|
ok, next, err = tryConn4(req, c, iface)
|
||||||
if next {
|
if next {
|
||||||
@@ -116,11 +153,6 @@ func tryConn4(req *dhcpv4.DHCPv4, c net.PacketConn, iface *net.Interface) (ok, n
|
|||||||
log.Tracef("dhcpv4: waiting %v for an answer", defaultDiscoverTime)
|
log.Tracef("dhcpv4: waiting %v for an answer", defaultDiscoverTime)
|
||||||
|
|
||||||
b := make([]byte, 1500)
|
b := make([]byte, 1500)
|
||||||
err = c.SetDeadline(time.Now().Add(defaultDiscoverTime))
|
|
||||||
if err != nil {
|
|
||||||
return false, false, fmt.Errorf("setting deadline: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
n, _, err := c.ReadFrom(b)
|
n, _, err := c.ReadFrom(b)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if isTimeout(err) {
|
if isTimeout(err) {
|
||||||
@@ -159,31 +191,21 @@ func tryConn4(req *dhcpv4.DHCPv4, c net.PacketConn, iface *net.Interface) (ok, n
|
|||||||
return true, false, nil
|
return true, false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// CheckIfOtherDHCPServersPresentV6 sends a DHCP request to the specified network interface,
|
// checkOtherDHCPv6 sends a DHCP request to the specified network interface, and
|
||||||
// and waits for a response for a period defined by defaultDiscoverTime
|
// waits for a response for a period defined by defaultDiscoverTime.
|
||||||
func CheckIfOtherDHCPServersPresentV6(ifaceName string) (ok bool, err error) {
|
func checkOtherDHCPv6(iface *net.Interface) (ok bool, err error) {
|
||||||
iface, err := net.InterfaceByName(ifaceName)
|
ifaceIPNet, err := IfaceIPAddrs(iface, IPVersion6)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("dhcpv6: net.InterfaceByName: %s: %w", ifaceName, err)
|
return false, fmt.Errorf("getting ipv6 addrs for iface %s: %w", iface.Name, err)
|
||||||
}
|
|
||||||
|
|
||||||
ifaceIPNet, err := ifaceIPAddrs(iface, ipVersion6)
|
|
||||||
if err != nil {
|
|
||||||
return false, fmt.Errorf("getting ipv6 addrs for iface %s: %w", ifaceName, err)
|
|
||||||
}
|
}
|
||||||
if len(ifaceIPNet) == 0 {
|
if len(ifaceIPNet) == 0 {
|
||||||
return false, fmt.Errorf("interface %s has no ipv6 addresses", ifaceName)
|
return false, fmt.Errorf("interface %s has no ipv6 addresses", iface.Name)
|
||||||
}
|
}
|
||||||
|
|
||||||
srcIP := ifaceIPNet[0]
|
srcIP := ifaceIPNet[0]
|
||||||
src := aghnet.JoinHostPort(srcIP.String(), 546)
|
src := netutil.JoinHostPort(srcIP.String(), 546)
|
||||||
dst := "[ff02::1:2]:547"
|
dst := "[ff02::1:2]:547"
|
||||||
|
|
||||||
req, err := dhcpv6.NewSolicit(iface.HardwareAddr)
|
|
||||||
if err != nil {
|
|
||||||
return false, fmt.Errorf("dhcpv6: dhcpv6.NewSolicit: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
udpAddr, err := net.ResolveUDPAddr("udp6", src)
|
udpAddr, err := net.ResolveUDPAddr("udp6", src)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("dhcpv6: Couldn't resolve UDP address %s: %w", src, err)
|
return false, fmt.Errorf("dhcpv6: Couldn't resolve UDP address %s: %w", src, err)
|
||||||
@@ -198,18 +220,25 @@ func CheckIfOtherDHCPServersPresentV6(ifaceName string) (ok bool, err error) {
|
|||||||
return false, fmt.Errorf("dhcpv6: Couldn't resolve UDP address %s: %w", dst, err)
|
return false, fmt.Errorf("dhcpv6: Couldn't resolve UDP address %s: %w", dst, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return discover6(iface, udpAddr, dstAddr)
|
||||||
|
}
|
||||||
|
|
||||||
|
func discover6(iface *net.Interface, udpAddr, dstAddr *net.UDPAddr) (ok bool, err error) {
|
||||||
|
req, err := dhcpv6.NewSolicit(iface.HardwareAddr)
|
||||||
|
if err != nil {
|
||||||
|
return false, fmt.Errorf("dhcpv6: dhcpv6.NewSolicit: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
log.Debug("DHCPv6: Listening to udp6 %+v", udpAddr)
|
log.Debug("DHCPv6: Listening to udp6 %+v", udpAddr)
|
||||||
c, err := nclient6.NewIPv6UDPConn(ifaceName, dhcpv6.DefaultClientPort)
|
c, err := nclient6.NewIPv6UDPConn(iface.Name, dhcpv6.DefaultClientPort)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("dhcpv6: Couldn't listen on :546: %w", err)
|
return false, fmt.Errorf("dhcpv6: Couldn't listen on :546: %w", err)
|
||||||
}
|
}
|
||||||
if c != nil {
|
defer func() { err = errors.WithDeferred(err, c.Close()) }()
|
||||||
defer func() { err = errors.WithDeferred(err, c.Close()) }()
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = c.WriteTo(req.ToBytes(), dstAddr)
|
_, err = c.WriteTo(req.ToBytes(), dstAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, fmt.Errorf("dhcpv6: Couldn't send a packet to %s: %w", dst, err)
|
return false, fmt.Errorf("dhcpv6: Couldn't send a packet to %s: %w", dstAddr, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
for {
|
for {
|
||||||
@@ -288,3 +317,15 @@ func tryConn6(req *dhcpv6.Message, c net.PacketConn) (ok, next bool, err error)
|
|||||||
|
|
||||||
return true, false, nil
|
return true, false, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// isTimeout returns true if err is an operation timeout error from net package.
|
||||||
|
//
|
||||||
|
// TODO(e.burkov): Consider moving into netutil.
|
||||||
|
func isTimeout(err error) (ok bool) {
|
||||||
|
var operr *net.OpError
|
||||||
|
if errors.As(err, &operr) {
|
||||||
|
return operr.Timeout()
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
13
internal/aghnet/dhcp_windows.go
Normal file
13
internal/aghnet/dhcp_windows.go
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
//go:build windows
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
package aghnet
|
||||||
|
|
||||||
|
import "github.com/AdguardTeam/AdGuardHome/internal/aghos"
|
||||||
|
|
||||||
|
func checkOtherDHCP(ifaceName string) (ok4, ok6 bool, err4, err6 error) {
|
||||||
|
return false,
|
||||||
|
false,
|
||||||
|
aghos.Unsupported("CheckIfOtherDHCPServersPresentV4"),
|
||||||
|
aghos.Unsupported("CheckIfOtherDHCPServersPresentV6")
|
||||||
|
}
|
||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/AdguardTeam/AdGuardHome/internal/aghos"
|
"github.com/AdguardTeam/AdGuardHome/internal/aghos"
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
"github.com/AdguardTeam/golibs/log"
|
"github.com/AdguardTeam/golibs/log"
|
||||||
|
"github.com/AdguardTeam/golibs/netutil"
|
||||||
"github.com/fsnotify/fsnotify"
|
"github.com/fsnotify/fsnotify"
|
||||||
"github.com/miekg/dns"
|
"github.com/miekg/dns"
|
||||||
)
|
)
|
||||||
@@ -29,7 +30,7 @@ type EtcHostsContainer struct {
|
|||||||
table map[string][]net.IP
|
table map[string][]net.IP
|
||||||
// tableReverse is the IP-to-hosts map. The type of the values in the
|
// tableReverse is the IP-to-hosts map. The type of the values in the
|
||||||
// map is []string.
|
// map is []string.
|
||||||
tableReverse *IPMap
|
tableReverse *netutil.IPMap
|
||||||
|
|
||||||
hostsFn string // path to the main hosts-file
|
hostsFn string // path to the main hosts-file
|
||||||
hostsDirs []string // paths to OS-specific directories with hosts-files
|
hostsDirs []string // paths to OS-specific directories with hosts-files
|
||||||
@@ -150,8 +151,10 @@ func (ehc *EtcHostsContainer) ProcessReverse(addr string, qtype uint16) (hosts [
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
ip := UnreverseAddr(addr)
|
ip, err := netutil.IPFromReversedAddr(addr)
|
||||||
if ip == nil {
|
if err != nil {
|
||||||
|
log.Error("etchosts: reversed addr: %s", err)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -179,7 +182,7 @@ func (ehc *EtcHostsContainer) ProcessReverse(addr string, qtype uint16) (hosts [
|
|||||||
|
|
||||||
// List returns an IP-to-hostnames table. The type of the values in the map is
|
// List returns an IP-to-hostnames table. The type of the values in the map is
|
||||||
// []string. It is safe for concurrent use.
|
// []string. It is safe for concurrent use.
|
||||||
func (ehc *EtcHostsContainer) List() (ipToHosts *IPMap) {
|
func (ehc *EtcHostsContainer) List() (ipToHosts *netutil.IPMap) {
|
||||||
ehc.lock.RLock()
|
ehc.lock.RLock()
|
||||||
defer ehc.lock.RUnlock()
|
defer ehc.lock.RUnlock()
|
||||||
|
|
||||||
@@ -211,7 +214,7 @@ func (ehc *EtcHostsContainer) updateTable(table map[string][]net.IP, host string
|
|||||||
}
|
}
|
||||||
|
|
||||||
// updateTableRev updates the reverse address table.
|
// updateTableRev updates the reverse address table.
|
||||||
func (ehc *EtcHostsContainer) updateTableRev(tableRev *IPMap, newHost string, ip net.IP) {
|
func (ehc *EtcHostsContainer) updateTableRev(tableRev *netutil.IPMap, newHost string, ip net.IP) {
|
||||||
v, ok := tableRev.Get(ip)
|
v, ok := tableRev.Get(ip)
|
||||||
if !ok {
|
if !ok {
|
||||||
tableRev.Set(ip, []string{newHost})
|
tableRev.Set(ip, []string{newHost})
|
||||||
@@ -258,7 +261,7 @@ func parseHostsLine(fields []string) (hosts []string) {
|
|||||||
// line for one IP are supported.
|
// line for one IP are supported.
|
||||||
func (ehc *EtcHostsContainer) load(
|
func (ehc *EtcHostsContainer) load(
|
||||||
table map[string][]net.IP,
|
table map[string][]net.IP,
|
||||||
tableRev *IPMap,
|
tableRev *netutil.IPMap,
|
||||||
fn string,
|
fn string,
|
||||||
) {
|
) {
|
||||||
f, err := os.Open(fn)
|
f, err := os.Open(fn)
|
||||||
@@ -353,7 +356,7 @@ func (ehc *EtcHostsContainer) watcherLoop() {
|
|||||||
// updateHosts - loads system hosts
|
// updateHosts - loads system hosts
|
||||||
func (ehc *EtcHostsContainer) updateHosts() {
|
func (ehc *EtcHostsContainer) updateHosts() {
|
||||||
table := make(map[string][]net.IP)
|
table := make(map[string][]net.IP)
|
||||||
tableRev := NewIPMap(0)
|
tableRev := netutil.NewIPMap(0)
|
||||||
|
|
||||||
ehc.load(table, tableRev, ehc.hostsFn)
|
ehc.load(table, tableRev, ehc.hostsFn)
|
||||||
|
|
||||||
|
|||||||
@@ -117,8 +117,8 @@ func TestEtcHostsContainerFSNotify(t *testing.T) {
|
|||||||
assertWriting(t, f, "127.0.0.2 newhost\n")
|
assertWriting(t, f, "127.0.0.2 newhost\n")
|
||||||
require.NoError(t, f.Sync())
|
require.NoError(t, f.Sync())
|
||||||
|
|
||||||
// Wait until fsnotify has triggerred and processed the
|
// Wait until fsnotify has triggered and processed the file-modification
|
||||||
// file-modification event.
|
// event.
|
||||||
time.Sleep(50 * time.Millisecond)
|
time.Sleep(50 * time.Millisecond)
|
||||||
|
|
||||||
t.Run("notified", func(t *testing.T) {
|
t.Run("notified", func(t *testing.T) {
|
||||||
|
|||||||
62
internal/aghnet/hostgen.go
Normal file
62
internal/aghnet/hostgen.go
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
package aghnet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"strconv"
|
||||||
|
)
|
||||||
|
|
||||||
|
// The maximum lengths of generated hostnames for different IP versions.
|
||||||
|
const (
|
||||||
|
ipv4HostnameMaxLen = len("192-168-100-100")
|
||||||
|
ipv6HostnameMaxLen = len("ff80-f076-0000-0000-0000-0000-0000-0010")
|
||||||
|
)
|
||||||
|
|
||||||
|
// generateIPv4Hostname generates the hostname for specific IP version.
|
||||||
|
func generateIPv4Hostname(ipv4 net.IP) (hostname string) {
|
||||||
|
hnData := make([]byte, 0, ipv4HostnameMaxLen)
|
||||||
|
for i, part := range ipv4 {
|
||||||
|
if i > 0 {
|
||||||
|
hnData = append(hnData, '-')
|
||||||
|
}
|
||||||
|
hnData = strconv.AppendUint(hnData, uint64(part), 10)
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(hnData)
|
||||||
|
}
|
||||||
|
|
||||||
|
// generateIPv6Hostname generates the hostname for specific IP version.
|
||||||
|
func generateIPv6Hostname(ipv6 net.IP) (hostname string) {
|
||||||
|
hnData := make([]byte, 0, ipv6HostnameMaxLen)
|
||||||
|
for i, partsNum := 0, net.IPv6len/2; i < partsNum; i++ {
|
||||||
|
if i > 0 {
|
||||||
|
hnData = append(hnData, '-')
|
||||||
|
}
|
||||||
|
for _, val := range ipv6[i*2 : i*2+2] {
|
||||||
|
if val < 10 {
|
||||||
|
hnData = append(hnData, '0')
|
||||||
|
}
|
||||||
|
hnData = strconv.AppendUint(hnData, uint64(val), 16)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return string(hnData)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GenerateHostname generates the hostname from ip. In case of using IPv4 the
|
||||||
|
// result should be like:
|
||||||
|
//
|
||||||
|
// 192-168-10-1
|
||||||
|
//
|
||||||
|
// In case of using IPv6, the result is like:
|
||||||
|
//
|
||||||
|
// ff80-f076-0000-0000-0000-0000-0000-0010
|
||||||
|
//
|
||||||
|
func GenerateHostname(ip net.IP) (hostname string) {
|
||||||
|
if ipv4 := ip.To4(); ipv4 != nil {
|
||||||
|
return generateIPv4Hostname(ipv4)
|
||||||
|
} else if ipv6 := ip.To16(); ipv6 != nil {
|
||||||
|
return generateIPv6Hostname(ipv6)
|
||||||
|
}
|
||||||
|
|
||||||
|
return ""
|
||||||
|
}
|
||||||
48
internal/aghnet/hostgen_test.go
Normal file
48
internal/aghnet/hostgen_test.go
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
package aghnet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestGenerateHostName(t *testing.T) {
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
want string
|
||||||
|
ip net.IP
|
||||||
|
}{{
|
||||||
|
name: "good_ipv4",
|
||||||
|
want: "127-0-0-1",
|
||||||
|
ip: net.IP{127, 0, 0, 1},
|
||||||
|
}, {
|
||||||
|
name: "bad_ipv4",
|
||||||
|
want: "",
|
||||||
|
ip: net.IP{127, 0, 0, 1, 0},
|
||||||
|
}, {
|
||||||
|
name: "good_ipv6",
|
||||||
|
want: "fe00-0000-0000-0000-0000-0000-0000-0001",
|
||||||
|
ip: net.ParseIP("fe00::1"),
|
||||||
|
}, {
|
||||||
|
name: "bad_ipv6",
|
||||||
|
want: "",
|
||||||
|
ip: net.IP{
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff, 0xff,
|
||||||
|
0xff, 0xff, 0xff,
|
||||||
|
},
|
||||||
|
}, {
|
||||||
|
name: "nil",
|
||||||
|
want: "",
|
||||||
|
ip: nil,
|
||||||
|
}}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
hostname := GenerateHostname(tc.ip)
|
||||||
|
assert.Equal(t, tc.want, hostname)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
118
internal/aghnet/interfaces.go
Normal file
118
internal/aghnet/interfaces.go
Normal file
@@ -0,0 +1,118 @@
|
|||||||
|
package aghnet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/AdguardTeam/golibs/log"
|
||||||
|
)
|
||||||
|
|
||||||
|
// IPVersion is a documentational alias for int. Use it when the integer means
|
||||||
|
// IP version.
|
||||||
|
type IPVersion = int
|
||||||
|
|
||||||
|
// IP version constants.
|
||||||
|
const (
|
||||||
|
IPVersion4 IPVersion = 4
|
||||||
|
IPVersion6 IPVersion = 6
|
||||||
|
)
|
||||||
|
|
||||||
|
// NetIface is the interface for network interface methods.
|
||||||
|
type NetIface interface {
|
||||||
|
Addrs() ([]net.Addr, error)
|
||||||
|
}
|
||||||
|
|
||||||
|
// IfaceIPAddrs returns the interface's IP addresses.
|
||||||
|
func IfaceIPAddrs(iface NetIface, ipv IPVersion) (ips []net.IP, err error) {
|
||||||
|
addrs, err := iface.Addrs()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, a := range addrs {
|
||||||
|
var ip net.IP
|
||||||
|
switch a := a.(type) {
|
||||||
|
case *net.IPAddr:
|
||||||
|
ip = a.IP
|
||||||
|
case *net.IPNet:
|
||||||
|
ip = a.IP
|
||||||
|
default:
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// Assume that net.(*Interface).Addrs can only return valid IPv4
|
||||||
|
// and IPv6 addresses. Thus, if it isn't an IPv4 address, it
|
||||||
|
// must be an IPv6 one.
|
||||||
|
switch ipv {
|
||||||
|
case IPVersion4:
|
||||||
|
if ip4 := ip.To4(); ip4 != nil {
|
||||||
|
ips = append(ips, ip4)
|
||||||
|
}
|
||||||
|
case IPVersion6:
|
||||||
|
if ip6 := ip.To4(); ip6 == nil {
|
||||||
|
ips = append(ips, ip)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
return nil, fmt.Errorf("invalid ip version %d", ipv)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ips, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// IfaceDNSIPAddrs returns IP addresses of the interface suitable to send to
|
||||||
|
// clients as DNS addresses. If err is nil, addrs contains either no addresses
|
||||||
|
// or at least two.
|
||||||
|
//
|
||||||
|
// It makes up to maxAttempts attempts to get the addresses if there are none,
|
||||||
|
// each time using the provided backoff. Sometimes an interface needs a few
|
||||||
|
// seconds to really ititialize.
|
||||||
|
//
|
||||||
|
// See https://github.com/AdguardTeam/AdGuardHome/issues/2304.
|
||||||
|
func IfaceDNSIPAddrs(
|
||||||
|
iface NetIface,
|
||||||
|
ipv IPVersion,
|
||||||
|
maxAttempts int,
|
||||||
|
backoff time.Duration,
|
||||||
|
) (addrs []net.IP, err error) {
|
||||||
|
var n int
|
||||||
|
for n = 1; n <= maxAttempts; n++ {
|
||||||
|
addrs, err = IfaceIPAddrs(iface, ipv)
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("getting ip addrs: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(addrs) > 0 {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debug("dhcpv%d: attempt %d: no ip addresses", ipv, n)
|
||||||
|
|
||||||
|
time.Sleep(backoff)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch len(addrs) {
|
||||||
|
case 0:
|
||||||
|
// Don't return errors in case the users want to try and enable
|
||||||
|
// the DHCP server later.
|
||||||
|
t := time.Duration(n) * backoff
|
||||||
|
log.Error("dhcpv%d: no ip for iface after %d attempts and %s", ipv, n, t)
|
||||||
|
|
||||||
|
return nil, nil
|
||||||
|
case 1:
|
||||||
|
// Some Android devices use 8.8.8.8 if there is not a secondary
|
||||||
|
// DNS server. Fix that by setting the secondary DNS address to
|
||||||
|
// the same address.
|
||||||
|
//
|
||||||
|
// See https://github.com/AdguardTeam/AdGuardHome/issues/1708.
|
||||||
|
log.Debug("dhcpv%d: setting secondary dns ip to itself", ipv)
|
||||||
|
addrs = append(addrs, addrs[0])
|
||||||
|
default:
|
||||||
|
// Go on.
|
||||||
|
}
|
||||||
|
|
||||||
|
log.Debug("dhcpv%d: got addresses %s after %d attempts", ipv, addrs, n)
|
||||||
|
|
||||||
|
return addrs, nil
|
||||||
|
}
|
||||||
24
internal/aghnet/interfaces_linux.go
Normal file
24
internal/aghnet/interfaces_linux.go
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
//go:build linux
|
||||||
|
// +build linux
|
||||||
|
|
||||||
|
package aghnet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/AdguardTeam/golibs/netutil"
|
||||||
|
"github.com/insomniacslk/dhcp/dhcpv4/nclient4"
|
||||||
|
)
|
||||||
|
|
||||||
|
// listenPacketReusable announces on the local network address additionally
|
||||||
|
// configuring the socket to have a reusable binding.
|
||||||
|
func listenPacketReusable(ifaceName, network, address string) (c net.PacketConn, err error) {
|
||||||
|
var port int
|
||||||
|
_, port, err = netutil.SplitHostPort(address)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO(e.burkov): Inspect nclient4.NewRawUDPConn and implement here.
|
||||||
|
return nclient4.NewRawUDPConn(ifaceName, port)
|
||||||
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
package dhcpd
|
package aghnet
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net"
|
"net"
|
||||||
@@ -14,7 +14,7 @@ type fakeIface struct {
|
|||||||
err error
|
err error
|
||||||
}
|
}
|
||||||
|
|
||||||
// Addrs implements the netIface interface for *fakeIface.
|
// Addrs implements the NetIface interface for *fakeIface.
|
||||||
func (iface *fakeIface) Addrs() (addrs []net.Addr, err error) {
|
func (iface *fakeIface) Addrs() (addrs []net.Addr, err error) {
|
||||||
if iface.err != nil {
|
if iface.err != nil {
|
||||||
return nil, iface.err
|
return nil, iface.err
|
||||||
@@ -34,51 +34,51 @@ func TestIfaceIPAddrs(t *testing.T) {
|
|||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
iface netIface
|
iface NetIface
|
||||||
ipv ipVersion
|
ipv IPVersion
|
||||||
want []net.IP
|
want []net.IP
|
||||||
wantErr error
|
wantErr error
|
||||||
}{{
|
}{{
|
||||||
name: "ipv4_success",
|
name: "ipv4_success",
|
||||||
iface: &fakeIface{addrs: []net.Addr{addr4}, err: nil},
|
iface: &fakeIface{addrs: []net.Addr{addr4}, err: nil},
|
||||||
ipv: ipVersion4,
|
ipv: IPVersion4,
|
||||||
want: []net.IP{ip4},
|
want: []net.IP{ip4},
|
||||||
wantErr: nil,
|
wantErr: nil,
|
||||||
}, {
|
}, {
|
||||||
name: "ipv4_success_with_ipv6",
|
name: "ipv4_success_with_ipv6",
|
||||||
iface: &fakeIface{addrs: []net.Addr{addr6, addr4}, err: nil},
|
iface: &fakeIface{addrs: []net.Addr{addr6, addr4}, err: nil},
|
||||||
ipv: ipVersion4,
|
ipv: IPVersion4,
|
||||||
want: []net.IP{ip4},
|
want: []net.IP{ip4},
|
||||||
wantErr: nil,
|
wantErr: nil,
|
||||||
}, {
|
}, {
|
||||||
name: "ipv4_error",
|
name: "ipv4_error",
|
||||||
iface: &fakeIface{addrs: []net.Addr{addr4}, err: errTest},
|
iface: &fakeIface{addrs: []net.Addr{addr4}, err: errTest},
|
||||||
ipv: ipVersion4,
|
ipv: IPVersion4,
|
||||||
want: nil,
|
want: nil,
|
||||||
wantErr: errTest,
|
wantErr: errTest,
|
||||||
}, {
|
}, {
|
||||||
name: "ipv6_success",
|
name: "ipv6_success",
|
||||||
iface: &fakeIface{addrs: []net.Addr{addr6}, err: nil},
|
iface: &fakeIface{addrs: []net.Addr{addr6}, err: nil},
|
||||||
ipv: ipVersion6,
|
ipv: IPVersion6,
|
||||||
want: []net.IP{ip6},
|
want: []net.IP{ip6},
|
||||||
wantErr: nil,
|
wantErr: nil,
|
||||||
}, {
|
}, {
|
||||||
name: "ipv6_success_with_ipv4",
|
name: "ipv6_success_with_ipv4",
|
||||||
iface: &fakeIface{addrs: []net.Addr{addr6, addr4}, err: nil},
|
iface: &fakeIface{addrs: []net.Addr{addr6, addr4}, err: nil},
|
||||||
ipv: ipVersion6,
|
ipv: IPVersion6,
|
||||||
want: []net.IP{ip6},
|
want: []net.IP{ip6},
|
||||||
wantErr: nil,
|
wantErr: nil,
|
||||||
}, {
|
}, {
|
||||||
name: "ipv6_error",
|
name: "ipv6_error",
|
||||||
iface: &fakeIface{addrs: []net.Addr{addr6}, err: errTest},
|
iface: &fakeIface{addrs: []net.Addr{addr6}, err: errTest},
|
||||||
ipv: ipVersion6,
|
ipv: IPVersion6,
|
||||||
want: nil,
|
want: nil,
|
||||||
wantErr: errTest,
|
wantErr: errTest,
|
||||||
}}
|
}}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
got, gotErr := ifaceIPAddrs(tc.iface, tc.ipv)
|
got, gotErr := IfaceIPAddrs(tc.iface, tc.ipv)
|
||||||
require.True(t, errors.Is(gotErr, tc.wantErr))
|
require.True(t, errors.Is(gotErr, tc.wantErr))
|
||||||
assert.Equal(t, tc.want, got)
|
assert.Equal(t, tc.want, got)
|
||||||
})
|
})
|
||||||
@@ -91,7 +91,7 @@ type waitingFakeIface struct {
|
|||||||
n int
|
n int
|
||||||
}
|
}
|
||||||
|
|
||||||
// Addrs implements the netIface interface for *waitingFakeIface.
|
// Addrs implements the NetIface interface for *waitingFakeIface.
|
||||||
func (iface *waitingFakeIface) Addrs() (addrs []net.Addr, err error) {
|
func (iface *waitingFakeIface) Addrs() (addrs []net.Addr, err error) {
|
||||||
if iface.err != nil {
|
if iface.err != nil {
|
||||||
return nil, iface.err
|
return nil, iface.err
|
||||||
@@ -117,63 +117,63 @@ func TestIfaceDNSIPAddrs(t *testing.T) {
|
|||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
iface netIface
|
iface NetIface
|
||||||
ipv ipVersion
|
ipv IPVersion
|
||||||
want []net.IP
|
want []net.IP
|
||||||
wantErr error
|
wantErr error
|
||||||
}{{
|
}{{
|
||||||
name: "ipv4_success",
|
name: "ipv4_success",
|
||||||
iface: &fakeIface{addrs: []net.Addr{addr4}, err: nil},
|
iface: &fakeIface{addrs: []net.Addr{addr4}, err: nil},
|
||||||
ipv: ipVersion4,
|
ipv: IPVersion4,
|
||||||
want: []net.IP{ip4, ip4},
|
want: []net.IP{ip4, ip4},
|
||||||
wantErr: nil,
|
wantErr: nil,
|
||||||
}, {
|
}, {
|
||||||
name: "ipv4_success_with_ipv6",
|
name: "ipv4_success_with_ipv6",
|
||||||
iface: &fakeIface{addrs: []net.Addr{addr6, addr4}, err: nil},
|
iface: &fakeIface{addrs: []net.Addr{addr6, addr4}, err: nil},
|
||||||
ipv: ipVersion4,
|
ipv: IPVersion4,
|
||||||
want: []net.IP{ip4, ip4},
|
want: []net.IP{ip4, ip4},
|
||||||
wantErr: nil,
|
wantErr: nil,
|
||||||
}, {
|
}, {
|
||||||
name: "ipv4_error",
|
name: "ipv4_error",
|
||||||
iface: &fakeIface{addrs: []net.Addr{addr4}, err: errTest},
|
iface: &fakeIface{addrs: []net.Addr{addr4}, err: errTest},
|
||||||
ipv: ipVersion4,
|
ipv: IPVersion4,
|
||||||
want: nil,
|
want: nil,
|
||||||
wantErr: errTest,
|
wantErr: errTest,
|
||||||
}, {
|
}, {
|
||||||
name: "ipv4_wait",
|
name: "ipv4_wait",
|
||||||
iface: &waitingFakeIface{addrs: []net.Addr{addr4}, err: nil, n: 1},
|
iface: &waitingFakeIface{addrs: []net.Addr{addr4}, err: nil, n: 1},
|
||||||
ipv: ipVersion4,
|
ipv: IPVersion4,
|
||||||
want: []net.IP{ip4, ip4},
|
want: []net.IP{ip4, ip4},
|
||||||
wantErr: nil,
|
wantErr: nil,
|
||||||
}, {
|
}, {
|
||||||
name: "ipv6_success",
|
name: "ipv6_success",
|
||||||
iface: &fakeIface{addrs: []net.Addr{addr6}, err: nil},
|
iface: &fakeIface{addrs: []net.Addr{addr6}, err: nil},
|
||||||
ipv: ipVersion6,
|
ipv: IPVersion6,
|
||||||
want: []net.IP{ip6, ip6},
|
want: []net.IP{ip6, ip6},
|
||||||
wantErr: nil,
|
wantErr: nil,
|
||||||
}, {
|
}, {
|
||||||
name: "ipv6_success_with_ipv4",
|
name: "ipv6_success_with_ipv4",
|
||||||
iface: &fakeIface{addrs: []net.Addr{addr6, addr4}, err: nil},
|
iface: &fakeIface{addrs: []net.Addr{addr6, addr4}, err: nil},
|
||||||
ipv: ipVersion6,
|
ipv: IPVersion6,
|
||||||
want: []net.IP{ip6, ip6},
|
want: []net.IP{ip6, ip6},
|
||||||
wantErr: nil,
|
wantErr: nil,
|
||||||
}, {
|
}, {
|
||||||
name: "ipv6_error",
|
name: "ipv6_error",
|
||||||
iface: &fakeIface{addrs: []net.Addr{addr6}, err: errTest},
|
iface: &fakeIface{addrs: []net.Addr{addr6}, err: errTest},
|
||||||
ipv: ipVersion6,
|
ipv: IPVersion6,
|
||||||
want: nil,
|
want: nil,
|
||||||
wantErr: errTest,
|
wantErr: errTest,
|
||||||
}, {
|
}, {
|
||||||
name: "ipv6_wait",
|
name: "ipv6_wait",
|
||||||
iface: &waitingFakeIface{addrs: []net.Addr{addr6}, err: nil, n: 1},
|
iface: &waitingFakeIface{addrs: []net.Addr{addr6}, err: nil, n: 1},
|
||||||
ipv: ipVersion6,
|
ipv: IPVersion6,
|
||||||
want: []net.IP{ip6, ip6},
|
want: []net.IP{ip6, ip6},
|
||||||
wantErr: nil,
|
wantErr: nil,
|
||||||
}}
|
}}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
got, gotErr := ifaceDNSIPAddrs(tc.iface, tc.ipv, 2, 0)
|
got, gotErr := IfaceDNSIPAddrs(tc.iface, tc.ipv, 2, 0)
|
||||||
require.True(t, errors.Is(gotErr, tc.wantErr))
|
require.True(t, errors.Is(gotErr, tc.wantErr))
|
||||||
assert.Equal(t, tc.want, got)
|
assert.Equal(t, tc.want, got)
|
||||||
})
|
})
|
||||||
51
internal/aghnet/interfaces_unix.go
Normal file
51
internal/aghnet/interfaces_unix.go
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
//go:build aix || darwin || dragonfly || freebsd || netbsd || openbsd || solaris
|
||||||
|
// +build aix darwin dragonfly freebsd netbsd openbsd solaris
|
||||||
|
|
||||||
|
package aghnet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net"
|
||||||
|
"os"
|
||||||
|
"syscall"
|
||||||
|
|
||||||
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
|
"golang.org/x/sys/unix"
|
||||||
|
)
|
||||||
|
|
||||||
|
// reuseAddrCtrl is the function to be set to net.ListenConfig.Control. It
|
||||||
|
// configures the socket to have a reusable port binding.
|
||||||
|
func reuseAddrCtrl(_, _ string, c syscall.RawConn) (err error) {
|
||||||
|
cerr := c.Control(func(fd uintptr) {
|
||||||
|
// TODO(e.burkov): Consider using SO_REUSEPORT.
|
||||||
|
err = unix.SetsockoptInt(int(fd), unix.SOL_SOCKET, unix.SO_REUSEADDR, 1)
|
||||||
|
if err != nil {
|
||||||
|
err = os.NewSyscallError("setsockopt", err)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
const (
|
||||||
|
errMsg = "setting control options"
|
||||||
|
errMsgFmt = errMsg + ": %w"
|
||||||
|
)
|
||||||
|
|
||||||
|
if err != nil && cerr != nil {
|
||||||
|
err = errors.List(errMsg, err, cerr)
|
||||||
|
} else if err != nil {
|
||||||
|
err = fmt.Errorf(errMsgFmt, err)
|
||||||
|
} else if cerr != nil {
|
||||||
|
err = fmt.Errorf(errMsgFmt, cerr)
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// listenPacketReusable announces on the local network address additionally
|
||||||
|
// configuring the socket to have a reusable binding.
|
||||||
|
func listenPacketReusable(_, network, address string) (c net.PacketConn, err error) {
|
||||||
|
var lc net.ListenConfig
|
||||||
|
lc.Control = reuseAddrCtrl
|
||||||
|
|
||||||
|
return lc.ListenPacket(context.Background(), network, address)
|
||||||
|
}
|
||||||
18
internal/aghnet/interfaces_windows.go
Normal file
18
internal/aghnet/interfaces_windows.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
//go:build windows
|
||||||
|
// +build windows
|
||||||
|
|
||||||
|
package aghnet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/AdguardTeam/AdGuardHome/internal/aghos"
|
||||||
|
)
|
||||||
|
|
||||||
|
// listenPacketReusable announces on the local network address additionally
|
||||||
|
// configuring the socket to have a reusable binding.
|
||||||
|
func listenPacketReusable(_, _, _ string) (c net.PacketConn, err error) {
|
||||||
|
// TODO(e.burkov): Check if we are able to control sockets on Windows
|
||||||
|
// in the same way as on Unix.
|
||||||
|
return nil, aghos.Unsupported("listening packet reusable")
|
||||||
|
}
|
||||||
@@ -1,117 +0,0 @@
|
|||||||
package aghnet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
)
|
|
||||||
|
|
||||||
// ipArr is a representation of an IP address as an array of bytes.
|
|
||||||
type ipArr [16]byte
|
|
||||||
|
|
||||||
// String implements the fmt.Stringer interface for ipArr.
|
|
||||||
func (a ipArr) String() (s string) {
|
|
||||||
return net.IP(a[:]).String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// IPMap is a map of IP addresses.
|
|
||||||
type IPMap struct {
|
|
||||||
m map[ipArr]interface{}
|
|
||||||
}
|
|
||||||
|
|
||||||
// NewIPMap returns a new empty IP map using hint as a size hint for the
|
|
||||||
// underlying map.
|
|
||||||
func NewIPMap(hint int) (m *IPMap) {
|
|
||||||
return &IPMap{
|
|
||||||
m: make(map[ipArr]interface{}, hint),
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// ipToArr converts a net.IP into an ipArr.
|
|
||||||
//
|
|
||||||
// TODO(a.garipov): Use the slice-to-array conversion in Go 1.17.
|
|
||||||
func ipToArr(ip net.IP) (a ipArr) {
|
|
||||||
copy(a[:], ip.To16())
|
|
||||||
|
|
||||||
return a
|
|
||||||
}
|
|
||||||
|
|
||||||
// Del deletes ip from the map. Calling Del on a nil *IPMap has no effect, just
|
|
||||||
// like delete on an empty map doesn't.
|
|
||||||
func (m *IPMap) Del(ip net.IP) {
|
|
||||||
if m != nil {
|
|
||||||
delete(m.m, ipToArr(ip))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get returns the value from the map. Calling Get on a nil *IPMap returns nil
|
|
||||||
// and false, just like indexing on an empty map does.
|
|
||||||
func (m *IPMap) Get(ip net.IP) (v interface{}, ok bool) {
|
|
||||||
if m != nil {
|
|
||||||
v, ok = m.m[ipToArr(ip)]
|
|
||||||
|
|
||||||
return v, ok
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, false
|
|
||||||
}
|
|
||||||
|
|
||||||
// Len returns the length of the map. A nil *IPMap has a length of zero, just
|
|
||||||
// like an empty map.
|
|
||||||
func (m *IPMap) Len() (n int) {
|
|
||||||
if m == nil {
|
|
||||||
return 0
|
|
||||||
}
|
|
||||||
|
|
||||||
return len(m.m)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Range calls f for each key and value present in the map in an undefined
|
|
||||||
// order. If cont is false, range stops the iteration. Calling Range on a nil
|
|
||||||
// *IPMap has no effect, just like ranging over a nil map.
|
|
||||||
func (m *IPMap) Range(f func(ip net.IP, v interface{}) (cont bool)) {
|
|
||||||
if m == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
for k, v := range m.m {
|
|
||||||
// Array slicing produces a pointer, so copy the array here.
|
|
||||||
//
|
|
||||||
// See https://github.com/AdguardTeam/AdGuardHome/issues/3346
|
|
||||||
// as well as https://github.com/kyoh86/looppointer/issues/9.
|
|
||||||
k := k
|
|
||||||
if !f(net.IP(k[:]), v) {
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set sets the value. Set panics if the m is a nil *IPMap, just like a nil map
|
|
||||||
// does.
|
|
||||||
func (m *IPMap) Set(ip net.IP, v interface{}) {
|
|
||||||
m.m[ipToArr(ip)] = v
|
|
||||||
}
|
|
||||||
|
|
||||||
// ShallowClone returns a shallow clone of the map.
|
|
||||||
func (m *IPMap) ShallowClone() (sclone *IPMap) {
|
|
||||||
if m == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
sclone = NewIPMap(m.Len())
|
|
||||||
m.Range(func(ip net.IP, v interface{}) (cont bool) {
|
|
||||||
sclone.Set(ip, v)
|
|
||||||
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
return sclone
|
|
||||||
}
|
|
||||||
|
|
||||||
// String implements the fmt.Stringer interface for *IPMap.
|
|
||||||
func (m *IPMap) String() (s string) {
|
|
||||||
if m == nil {
|
|
||||||
return "<nil>"
|
|
||||||
}
|
|
||||||
|
|
||||||
return fmt.Sprint(m.m)
|
|
||||||
}
|
|
||||||
@@ -1,142 +0,0 @@
|
|||||||
package aghnet
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net"
|
|
||||||
"testing"
|
|
||||||
|
|
||||||
"github.com/stretchr/testify/assert"
|
|
||||||
"github.com/stretchr/testify/require"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestIPMap_allocs(t *testing.T) {
|
|
||||||
ip4 := net.IP{1, 2, 3, 4}
|
|
||||||
m := NewIPMap(0)
|
|
||||||
m.Set(ip4, 42)
|
|
||||||
|
|
||||||
t.Run("get", func(t *testing.T) {
|
|
||||||
var v interface{}
|
|
||||||
var ok bool
|
|
||||||
allocs := testing.AllocsPerRun(100, func() {
|
|
||||||
v, ok = m.Get(ip4)
|
|
||||||
})
|
|
||||||
|
|
||||||
require.True(t, ok)
|
|
||||||
require.Equal(t, 42, v)
|
|
||||||
|
|
||||||
assert.Equal(t, float64(0), allocs)
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("len", func(t *testing.T) {
|
|
||||||
var n int
|
|
||||||
allocs := testing.AllocsPerRun(100, func() {
|
|
||||||
n = m.Len()
|
|
||||||
})
|
|
||||||
|
|
||||||
require.Equal(t, 1, n)
|
|
||||||
|
|
||||||
assert.Equal(t, float64(0), allocs)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestIPMap(t *testing.T) {
|
|
||||||
ip4 := net.IP{1, 2, 3, 4}
|
|
||||||
ip6 := net.IP{
|
|
||||||
0x12, 0x34, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x00, 0x00,
|
|
||||||
0x00, 0x00, 0x56, 0x78,
|
|
||||||
}
|
|
||||||
|
|
||||||
val := 42
|
|
||||||
|
|
||||||
t.Run("nil", func(t *testing.T) {
|
|
||||||
var m *IPMap
|
|
||||||
|
|
||||||
assert.NotPanics(t, func() {
|
|
||||||
m.Del(ip4)
|
|
||||||
m.Del(ip6)
|
|
||||||
})
|
|
||||||
|
|
||||||
assert.NotPanics(t, func() {
|
|
||||||
v, ok := m.Get(ip4)
|
|
||||||
assert.Nil(t, v)
|
|
||||||
assert.False(t, ok)
|
|
||||||
|
|
||||||
v, ok = m.Get(ip6)
|
|
||||||
assert.Nil(t, v)
|
|
||||||
assert.False(t, ok)
|
|
||||||
})
|
|
||||||
|
|
||||||
assert.NotPanics(t, func() {
|
|
||||||
assert.Equal(t, 0, m.Len())
|
|
||||||
})
|
|
||||||
|
|
||||||
assert.NotPanics(t, func() {
|
|
||||||
n := 0
|
|
||||||
m.Range(func(_ net.IP, _ interface{}) (cont bool) {
|
|
||||||
n++
|
|
||||||
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
|
|
||||||
assert.Equal(t, 0, n)
|
|
||||||
})
|
|
||||||
|
|
||||||
assert.Panics(t, func() {
|
|
||||||
m.Set(ip4, val)
|
|
||||||
})
|
|
||||||
|
|
||||||
assert.Panics(t, func() {
|
|
||||||
m.Set(ip6, val)
|
|
||||||
})
|
|
||||||
|
|
||||||
assert.NotPanics(t, func() {
|
|
||||||
sclone := m.ShallowClone()
|
|
||||||
assert.Nil(t, sclone)
|
|
||||||
})
|
|
||||||
})
|
|
||||||
|
|
||||||
testIPMap := func(t *testing.T, ip net.IP, s string) {
|
|
||||||
m := NewIPMap(0)
|
|
||||||
assert.Equal(t, 0, m.Len())
|
|
||||||
|
|
||||||
v, ok := m.Get(ip)
|
|
||||||
assert.Nil(t, v)
|
|
||||||
assert.False(t, ok)
|
|
||||||
|
|
||||||
m.Set(ip, val)
|
|
||||||
v, ok = m.Get(ip)
|
|
||||||
assert.Equal(t, val, v)
|
|
||||||
assert.True(t, ok)
|
|
||||||
|
|
||||||
n := 0
|
|
||||||
m.Range(func(ipKey net.IP, v interface{}) (cont bool) {
|
|
||||||
assert.Equal(t, ip.To16(), ipKey)
|
|
||||||
assert.Equal(t, val, v)
|
|
||||||
|
|
||||||
n++
|
|
||||||
|
|
||||||
return false
|
|
||||||
})
|
|
||||||
assert.Equal(t, 1, n)
|
|
||||||
|
|
||||||
sclone := m.ShallowClone()
|
|
||||||
assert.Equal(t, m, sclone)
|
|
||||||
|
|
||||||
assert.Equal(t, s, m.String())
|
|
||||||
|
|
||||||
m.Del(ip)
|
|
||||||
v, ok = m.Get(ip)
|
|
||||||
assert.Nil(t, v)
|
|
||||||
assert.False(t, ok)
|
|
||||||
assert.Equal(t, 0, m.Len())
|
|
||||||
}
|
|
||||||
|
|
||||||
t.Run("ipv4", func(t *testing.T) {
|
|
||||||
testIPMap(t, ip4, "map[1.2.3.4:42]")
|
|
||||||
})
|
|
||||||
|
|
||||||
t.Run("ipv6", func(t *testing.T) {
|
|
||||||
testIPMap(t, ip6, "map[1234::5678:42]")
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -10,6 +10,7 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
|
"github.com/AdguardTeam/golibs/log"
|
||||||
"github.com/digineo/go-ipset/v2"
|
"github.com/digineo/go-ipset/v2"
|
||||||
"github.com/mdlayher/netlink"
|
"github.com/mdlayher/netlink"
|
||||||
"github.com/ti-mo/netfilter"
|
"github.com/ti-mo/netfilter"
|
||||||
@@ -67,6 +68,15 @@ type ipsetProps struct {
|
|||||||
// unit is a convenient alias for struct{}.
|
// unit is a convenient alias for struct{}.
|
||||||
type unit = struct{}
|
type unit = struct{}
|
||||||
|
|
||||||
|
// ipsInIpset is the type of a set of IP-address-to-ipset mappings.
|
||||||
|
type ipsInIpset map[ipInIpsetEntry]unit
|
||||||
|
|
||||||
|
// ipInIpsetEntry is the type for entries in an ipsInIpset set.
|
||||||
|
type ipInIpsetEntry struct {
|
||||||
|
ipsetName string
|
||||||
|
ipArr [net.IPv6len]byte
|
||||||
|
}
|
||||||
|
|
||||||
// ipsetMgr is the Linux Netfilter ipset manager.
|
// ipsetMgr is the Linux Netfilter ipset manager.
|
||||||
type ipsetMgr struct {
|
type ipsetMgr struct {
|
||||||
nameToIpset map[string]ipsetProps
|
nameToIpset map[string]ipsetProps
|
||||||
@@ -82,7 +92,7 @@ type ipsetMgr struct {
|
|||||||
// are either added to all corresponding ipsets or not. When that stops
|
// are either added to all corresponding ipsets or not. When that stops
|
||||||
// being the case, for example if we add dynamic reconfiguration of
|
// being the case, for example if we add dynamic reconfiguration of
|
||||||
// ipsets, this map will need to become a per-ipset-name one.
|
// ipsets, this map will need to become a per-ipset-name one.
|
||||||
addedIPs map[[16]byte]unit
|
addedIPs ipsInIpset
|
||||||
|
|
||||||
ipv4Conn ipsetConn
|
ipv4Conn ipsetConn
|
||||||
ipv6Conn ipsetConn
|
ipv6Conn ipsetConn
|
||||||
@@ -199,7 +209,7 @@ func newIpsetMgrWithDialer(ipsetConf []string, dial ipsetDialer) (mgr IpsetManag
|
|||||||
|
|
||||||
dial: dial,
|
dial: dial,
|
||||||
|
|
||||||
addedIPs: make(map[[16]byte]unit),
|
addedIPs: make(ipsInIpset),
|
||||||
}
|
}
|
||||||
|
|
||||||
err = m.dialNetfilter(&netlink.Config{})
|
err = m.dialNetfilter(&netlink.Config{})
|
||||||
@@ -265,16 +275,19 @@ func (m *ipsetMgr) addIPs(host string, set ipsetProps, ips []net.IP) (n int, err
|
|||||||
}
|
}
|
||||||
|
|
||||||
var entries []*ipset.Entry
|
var entries []*ipset.Entry
|
||||||
var newAddedIPs [][16]byte
|
var newAddedEntries []ipInIpsetEntry
|
||||||
for _, ip := range ips {
|
for _, ip := range ips {
|
||||||
var iparr [16]byte
|
e := ipInIpsetEntry{
|
||||||
copy(iparr[:], ip.To16())
|
ipsetName: set.name,
|
||||||
if _, added := m.addedIPs[iparr]; added {
|
}
|
||||||
|
copy(e.ipArr[:], ip.To16())
|
||||||
|
|
||||||
|
if _, added := m.addedIPs[e]; added {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
entries = append(entries, ipset.NewEntry(ipset.EntryIP(ip)))
|
entries = append(entries, ipset.NewEntry(ipset.EntryIP(ip)))
|
||||||
newAddedIPs = append(newAddedIPs, iparr)
|
newAddedEntries = append(newAddedEntries, e)
|
||||||
}
|
}
|
||||||
|
|
||||||
n = len(entries)
|
n = len(entries)
|
||||||
@@ -299,8 +312,8 @@ func (m *ipsetMgr) addIPs(host string, set ipsetProps, ips []net.IP) (n int, err
|
|||||||
|
|
||||||
// Only add these to the cache once we're sure that all of them were
|
// Only add these to the cache once we're sure that all of them were
|
||||||
// actually sent to the ipset.
|
// actually sent to the ipset.
|
||||||
for _, iparr := range newAddedIPs {
|
for _, e := range newAddedEntries {
|
||||||
m.addedIPs[iparr] = unit{}
|
m.addedIPs[e] = unit{}
|
||||||
}
|
}
|
||||||
|
|
||||||
return n, nil
|
return n, nil
|
||||||
@@ -330,6 +343,8 @@ func (m *ipsetMgr) addToSets(
|
|||||||
return n, fmt.Errorf("unexpected family %s for ipset %q", set.family, set.name)
|
return n, fmt.Errorf("unexpected family %s for ipset %q", set.family, set.name)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Debug("ipset: added %d ips to set %s", nn, set.name)
|
||||||
|
|
||||||
n += nn
|
n += nn
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -346,6 +361,8 @@ func (m *ipsetMgr) Add(host string, ip4s, ip6s []net.IP) (n int, err error) {
|
|||||||
return 0, nil
|
return 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
log.Debug("ipset: found %d sets", len(sets))
|
||||||
|
|
||||||
return m.addToSets(host, ip4s, ip6s, sets)
|
return m.addToSets(host, ip4s, ip6s, sets)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -8,14 +8,13 @@ import (
|
|||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
"syscall"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
"github.com/AdguardTeam/golibs/log"
|
"github.com/AdguardTeam/golibs/log"
|
||||||
"github.com/AdguardTeam/golibs/stringutil"
|
"github.com/AdguardTeam/golibs/netutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
// ErrNoStaticIPInfo is returned by IfaceHasStaticIP when no information about
|
// ErrNoStaticIPInfo is returned by IfaceHasStaticIP when no information about
|
||||||
@@ -79,14 +78,14 @@ func CanBindPrivilegedPorts() (can bool, err error) {
|
|||||||
|
|
||||||
// NetInterface represents an entry of network interfaces map.
|
// NetInterface represents an entry of network interfaces map.
|
||||||
type NetInterface struct {
|
type NetInterface struct {
|
||||||
MTU int `json:"mtu"`
|
// Addresses are the network interface addresses.
|
||||||
|
Addresses []net.IP `json:"ip_addresses,omitempty"`
|
||||||
|
// Subnets are the IP networks for this network interface.
|
||||||
|
Subnets []*net.IPNet `json:"-"`
|
||||||
Name string `json:"name"`
|
Name string `json:"name"`
|
||||||
HardwareAddr net.HardwareAddr `json:"hardware_address"`
|
HardwareAddr net.HardwareAddr `json:"hardware_address"`
|
||||||
Flags net.Flags `json:"flags"`
|
Flags net.Flags `json:"flags"`
|
||||||
// Array with the network interface addresses.
|
MTU int `json:"mtu"`
|
||||||
Addresses []net.IP `json:"ip_addresses,omitempty"`
|
|
||||||
// Array with IP networks for this network interface.
|
|
||||||
Subnets []*net.IPNet `json:"-"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// MarshalJSON implements the json.Marshaler interface for NetInterface.
|
// MarshalJSON implements the json.Marshaler interface for NetInterface.
|
||||||
@@ -192,7 +191,7 @@ func GetSubnet(ifaceName string) *net.IPNet {
|
|||||||
|
|
||||||
// CheckPortAvailable - check if TCP port is available
|
// CheckPortAvailable - check if TCP port is available
|
||||||
func CheckPortAvailable(host net.IP, port int) error {
|
func CheckPortAvailable(host net.IP, port int) error {
|
||||||
ln, err := net.Listen("tcp", JoinHostPort(host.String(), port))
|
ln, err := net.Listen("tcp", netutil.JoinHostPort(host.String(), port))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -206,7 +205,7 @@ func CheckPortAvailable(host net.IP, port int) error {
|
|||||||
|
|
||||||
// CheckPacketPortAvailable - check if UDP port is available
|
// CheckPacketPortAvailable - check if UDP port is available
|
||||||
func CheckPacketPortAvailable(host net.IP, port int) error {
|
func CheckPacketPortAvailable(host net.IP, port int) error {
|
||||||
ln, err := net.ListenPacket("udp", JoinHostPort(host.String(), port))
|
ln, err := net.ListenPacket("udp", netutil.JoinHostPort(host.String(), port))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -265,141 +264,6 @@ func SplitHost(hostport string) (host string, err error) {
|
|||||||
return host, nil
|
return host, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(e.burkov): Inspect the charToHex, ipParseARPA6, ipReverse and
|
|
||||||
// UnreverseAddr and maybe refactor it.
|
|
||||||
|
|
||||||
// charToHex converts character to a hexadecimal.
|
|
||||||
func charToHex(n byte) int8 {
|
|
||||||
if n >= '0' && n <= '9' {
|
|
||||||
return int8(n) - '0'
|
|
||||||
} else if (n|0x20) >= 'a' && (n|0x20) <= 'f' {
|
|
||||||
return (int8(n) | 0x20) - 'a' + 10
|
|
||||||
}
|
|
||||||
return -1
|
|
||||||
}
|
|
||||||
|
|
||||||
// ipParseARPA6 parse IPv6 reverse address
|
|
||||||
func ipParseARPA6(s string) (ip6 net.IP) {
|
|
||||||
if len(s) != 63 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
ip6 = make(net.IP, 16)
|
|
||||||
|
|
||||||
for i := 0; i != 64; i += 4 {
|
|
||||||
// parse "0.1."
|
|
||||||
n := charToHex(s[i])
|
|
||||||
n2 := charToHex(s[i+2])
|
|
||||||
if s[i+1] != '.' || (i != 60 && s[i+3] != '.') ||
|
|
||||||
n < 0 || n2 < 0 {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
ip6[16-i/4-1] = byte(n2<<4) | byte(n&0x0f)
|
|
||||||
}
|
|
||||||
return ip6
|
|
||||||
}
|
|
||||||
|
|
||||||
// ipReverse inverts byte order of ip.
|
|
||||||
func ipReverse(ip net.IP) (rev net.IP) {
|
|
||||||
ipLen := len(ip)
|
|
||||||
rev = make(net.IP, ipLen)
|
|
||||||
for i, b := range ip {
|
|
||||||
rev[ipLen-i-1] = b
|
|
||||||
}
|
|
||||||
|
|
||||||
return rev
|
|
||||||
}
|
|
||||||
|
|
||||||
// ARPA addresses' suffixes.
|
|
||||||
const (
|
|
||||||
arpaV4Suffix = ".in-addr.arpa"
|
|
||||||
arpaV6Suffix = ".ip6.arpa"
|
|
||||||
)
|
|
||||||
|
|
||||||
// UnreverseAddr tries to convert reversed ARPA to a normal IP address.
|
|
||||||
func UnreverseAddr(arpa string) (unreversed net.IP) {
|
|
||||||
// Unify the input data.
|
|
||||||
arpa = strings.TrimSuffix(arpa, ".")
|
|
||||||
arpa = strings.ToLower(arpa)
|
|
||||||
|
|
||||||
if strings.HasSuffix(arpa, arpaV4Suffix) {
|
|
||||||
ip := strings.TrimSuffix(arpa, arpaV4Suffix)
|
|
||||||
ip4 := net.ParseIP(ip).To4()
|
|
||||||
if ip4 == nil {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return ipReverse(ip4)
|
|
||||||
|
|
||||||
} else if strings.HasSuffix(arpa, arpaV6Suffix) {
|
|
||||||
ip := strings.TrimSuffix(arpa, arpaV6Suffix)
|
|
||||||
return ipParseARPA6(ip)
|
|
||||||
}
|
|
||||||
|
|
||||||
// The suffix unrecognizable.
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// The length of extreme cases of arpa formatted addresses.
|
|
||||||
//
|
|
||||||
// The example of IPv4 with maximum length:
|
|
||||||
//
|
|
||||||
// 49.91.20.104.in-addr.arpa
|
|
||||||
//
|
|
||||||
// The example of IPv6 with maximum length:
|
|
||||||
//
|
|
||||||
// 1.3.b.5.4.1.8.6.0.0.0.0.0.0.0.0.0.0.0.0.0.1.0.0.0.0.7.4.6.0.6.2.ip6.arpa
|
|
||||||
//
|
|
||||||
const (
|
|
||||||
arpaV4MaxLen = len("000.000.000.000") + len(arpaV4Suffix)
|
|
||||||
arpaV6MaxLen = len("0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0") +
|
|
||||||
len(arpaV6Suffix)
|
|
||||||
)
|
|
||||||
|
|
||||||
// ReverseAddr returns the ARPA hostname of the ip suitable for reverse DNS
|
|
||||||
// (PTR) record lookups. This is the modified version of ReverseAddr from
|
|
||||||
// github.com/miekg/dns package with no error among returned values.
|
|
||||||
func ReverseAddr(ip net.IP) (arpa string) {
|
|
||||||
const dot = "."
|
|
||||||
|
|
||||||
var strLen int
|
|
||||||
var suffix string
|
|
||||||
var writeByte func(val byte)
|
|
||||||
b := &strings.Builder{}
|
|
||||||
if ip4 := ip.To4(); ip4 != nil {
|
|
||||||
strLen, suffix = arpaV4MaxLen, arpaV4Suffix[1:]
|
|
||||||
ip = ip4
|
|
||||||
writeByte = func(val byte) {
|
|
||||||
stringutil.WriteToBuilder(b, strconv.Itoa(int(val)), dot)
|
|
||||||
}
|
|
||||||
|
|
||||||
} else if ip6 := ip.To16(); ip6 != nil {
|
|
||||||
strLen, suffix = arpaV6MaxLen, arpaV6Suffix[1:]
|
|
||||||
ip = ip6
|
|
||||||
writeByte = func(val byte) {
|
|
||||||
stringutil.WriteToBuilder(
|
|
||||||
b,
|
|
||||||
strconv.FormatUint(uint64(val&0xF), 16),
|
|
||||||
dot,
|
|
||||||
strconv.FormatUint(uint64(val>>4), 16),
|
|
||||||
dot,
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
b.Grow(strLen)
|
|
||||||
for i := len(ip) - 1; i >= 0; i-- {
|
|
||||||
writeByte(ip[i])
|
|
||||||
}
|
|
||||||
stringutil.WriteToBuilder(b, suffix)
|
|
||||||
|
|
||||||
return b.String()
|
|
||||||
}
|
|
||||||
|
|
||||||
// CollectAllIfacesAddrs returns the slice of all network interfaces IP
|
// CollectAllIfacesAddrs returns the slice of all network interfaces IP
|
||||||
// addresses without port number.
|
// addresses without port number.
|
||||||
func CollectAllIfacesAddrs() (addrs []string, err error) {
|
func CollectAllIfacesAddrs() (addrs []string, err error) {
|
||||||
@@ -430,3 +294,19 @@ func CollectAllIfacesAddrs() (addrs []string, err error) {
|
|||||||
|
|
||||||
return addrs, nil
|
return addrs, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// BroadcastFromIPNet calculates the broadcast IP address for n.
|
||||||
|
func BroadcastFromIPNet(n *net.IPNet) (dc net.IP) {
|
||||||
|
dc = netutil.CloneIP(n.IP)
|
||||||
|
|
||||||
|
mask := n.Mask
|
||||||
|
if mask == nil {
|
||||||
|
mask = dc.DefaultMask()
|
||||||
|
}
|
||||||
|
|
||||||
|
for i, b := range mask {
|
||||||
|
dc[i] |= ^b
|
||||||
|
}
|
||||||
|
|
||||||
|
return dc
|
||||||
|
}
|
||||||
|
|||||||
@@ -48,9 +48,14 @@ func getCurrentHardwarePortInfo(ifaceName string) (hardwarePortInfo, error) {
|
|||||||
return getHardwarePortInfo(hardwarePort)
|
return getHardwarePortInfo(hardwarePort)
|
||||||
}
|
}
|
||||||
|
|
||||||
// getNetworkSetupHardwareReports parses the output of the `networksetup -listallhardwareports` command
|
// getNetworkSetupHardwareReports parses the output of the `networksetup
|
||||||
// it returns a map where the key is the interface name, and the value is the "hardware port"
|
// -listallhardwareports` command it returns a map where the key is the
|
||||||
// returns nil if it fails to parse the output
|
// interface name, and the value is the "hardware port" returns nil if it fails
|
||||||
|
// to parse the output
|
||||||
|
//
|
||||||
|
// TODO(e.burkov): There should be more proper approach than parsing the
|
||||||
|
// command output. For example, see
|
||||||
|
// https://developer.apple.com/documentation/systemconfiguration.
|
||||||
func getNetworkSetupHardwareReports() map[string]string {
|
func getNetworkSetupHardwareReports() map[string]string {
|
||||||
_, out, err := aghos.RunCommand("networksetup", "-listallhardwareports")
|
_, out, err := aghos.RunCommand("networksetup", "-listallhardwareports")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -8,69 +8,47 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/aghio"
|
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/aghos"
|
"github.com/AdguardTeam/AdGuardHome/internal/aghos"
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func canBindPrivilegedPorts() (can bool, err error) {
|
func canBindPrivilegedPorts() (can bool, err error) {
|
||||||
return aghos.HaveAdminRights()
|
return aghos.HaveAdminRights()
|
||||||
}
|
}
|
||||||
|
|
||||||
// maxCheckedFileSize is the maximum acceptable length of the /etc/rc.conf file.
|
|
||||||
const maxCheckedFileSize = 1024 * 1024
|
|
||||||
|
|
||||||
func ifaceHasStaticIP(ifaceName string) (ok bool, err error) {
|
func ifaceHasStaticIP(ifaceName string) (ok bool, err error) {
|
||||||
const filename = "/etc/rc.conf"
|
const filename = "/etc/rc.conf"
|
||||||
|
|
||||||
var f *os.File
|
return aghos.FileWalker(interfaceName(ifaceName).rcConfStaticConfig).Walk(filename)
|
||||||
f, err = os.Open(filename)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
defer func() { err = errors.WithDeferred(err, f.Close()) }()
|
|
||||||
|
|
||||||
var r io.Reader
|
|
||||||
r, err = aghio.LimitReader(f, maxCheckedFileSize)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
return rcConfStaticConfig(r, ifaceName)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// rcConfStaticConfig checks if the interface is configured by /etc/rc.conf to
|
// rcConfStaticConfig checks if the interface is configured by /etc/rc.conf to
|
||||||
// have a static IP.
|
// have a static IP.
|
||||||
func rcConfStaticConfig(r io.Reader, ifaceName string) (has bool, err error) {
|
func (n interfaceName) rcConfStaticConfig(r io.Reader) (_ []string, cont bool, err error) {
|
||||||
s := bufio.NewScanner(r)
|
s := bufio.NewScanner(r)
|
||||||
for ifaceLinePref := fmt.Sprintf("ifconfig_%s", ifaceName); s.Scan(); {
|
for pref := fmt.Sprintf("ifconfig_%s=", n); s.Scan(); {
|
||||||
line := strings.TrimSpace(s.Text())
|
line := strings.TrimSpace(s.Text())
|
||||||
if !strings.HasPrefix(line, ifaceLinePref) {
|
if !strings.HasPrefix(line, pref) {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
eqIdx := len(ifaceLinePref)
|
cfgLeft, cfgRight := len(pref)+1, len(line)-1
|
||||||
if line[eqIdx] != '=' {
|
if cfgLeft >= cfgRight {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
fieldsStart, fieldsEnd := eqIdx+2, len(line)-1
|
// TODO(e.burkov): Expand the check to cover possible
|
||||||
if fieldsStart >= fieldsEnd {
|
// configurations from man rc.conf(5).
|
||||||
continue
|
fields := strings.Fields(line[cfgLeft:cfgRight])
|
||||||
}
|
|
||||||
|
|
||||||
fields := strings.Fields(line[fieldsStart:fieldsEnd])
|
|
||||||
if len(fields) >= 2 &&
|
if len(fields) >= 2 &&
|
||||||
strings.ToLower(fields[0]) == "inet" &&
|
strings.EqualFold(fields[0], "inet") &&
|
||||||
net.ParseIP(fields[1]) != nil {
|
net.ParseIP(fields[1]) != nil {
|
||||||
return true, s.Err()
|
return nil, false, s.Err()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return false, s.Err()
|
return nil, true, s.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
func ifaceSetStaticIP(string) (err error) {
|
func ifaceSetStaticIP(string) (err error) {
|
||||||
|
|||||||
@@ -12,49 +12,48 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func TestRcConfStaticConfig(t *testing.T) {
|
func TestRcConfStaticConfig(t *testing.T) {
|
||||||
const ifaceName = `em0`
|
const iface interfaceName = `em0`
|
||||||
const nl = "\n"
|
const nl = "\n"
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
rcconfData string
|
rcconfData string
|
||||||
wantHas bool
|
wantCont bool
|
||||||
}{{
|
}{{
|
||||||
name: "simple",
|
name: "simple",
|
||||||
rcconfData: `ifconfig_em0="inet 127.0.0.253 netmask 0xffffffff"` + nl,
|
rcconfData: `ifconfig_em0="inet 127.0.0.253 netmask 0xffffffff"` + nl,
|
||||||
wantHas: true,
|
wantCont: false,
|
||||||
}, {
|
}, {
|
||||||
name: "case_insensitiveness",
|
name: "case_insensitiveness",
|
||||||
rcconfData: `ifconfig_em0="InEt 127.0.0.253 NeTmAsK 0xffffffff"` + nl,
|
rcconfData: `ifconfig_em0="InEt 127.0.0.253 NeTmAsK 0xffffffff"` + nl,
|
||||||
wantHas: true,
|
wantCont: false,
|
||||||
}, {
|
}, {
|
||||||
name: "comments_and_trash",
|
name: "comments_and_trash",
|
||||||
rcconfData: `# comment 1` + nl +
|
rcconfData: `# comment 1` + nl +
|
||||||
`` + nl +
|
`` + nl +
|
||||||
`# comment 2` + nl +
|
`# comment 2` + nl +
|
||||||
`ifconfig_em0="inet 127.0.0.253 netmask 0xffffffff"` + nl,
|
`ifconfig_em0="inet 127.0.0.253 netmask 0xffffffff"` + nl,
|
||||||
wantHas: true,
|
wantCont: false,
|
||||||
}, {
|
}, {
|
||||||
name: "aliases",
|
name: "aliases",
|
||||||
rcconfData: `ifconfig_em0_alias="inet 127.0.0.1/24"` + nl +
|
rcconfData: `ifconfig_em0_alias="inet 127.0.0.1/24"` + nl +
|
||||||
`ifconfig_em0="inet 127.0.0.253 netmask 0xffffffff"` + nl,
|
`ifconfig_em0="inet 127.0.0.253 netmask 0xffffffff"` + nl,
|
||||||
wantHas: true,
|
wantCont: false,
|
||||||
}, {
|
}, {
|
||||||
name: "incorrect_config",
|
name: "incorrect_config",
|
||||||
rcconfData: `ifconfig_em0="inet6 127.0.0.253 netmask 0xffffffff"` + nl +
|
rcconfData: `ifconfig_em0="inet6 127.0.0.253 netmask 0xffffffff"` + nl +
|
||||||
`ifconfig_em0="inet 127.0.0.253 net-mask 0xffffffff"` + nl +
|
|
||||||
`ifconfig_em0="inet 256.256.256.256 netmask 0xffffffff"` + nl +
|
`ifconfig_em0="inet 256.256.256.256 netmask 0xffffffff"` + nl +
|
||||||
`ifconfig_em0=""` + nl,
|
`ifconfig_em0=""` + nl,
|
||||||
wantHas: false,
|
wantCont: true,
|
||||||
}}
|
}}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
r := strings.NewReader(tc.rcconfData)
|
r := strings.NewReader(tc.rcconfData)
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
has, err := rcConfStaticConfig(r, ifaceName)
|
_, cont, err := iface.rcConfStaticConfig(r)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, tc.wantHas, has)
|
assert.Equal(t, tc.wantCont, cont)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,131 +9,72 @@ import (
|
|||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/aghio"
|
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/aghos"
|
"github.com/AdguardTeam/AdGuardHome/internal/aghos"
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
"github.com/AdguardTeam/golibs/stringutil"
|
|
||||||
"github.com/google/renameio/maybe"
|
"github.com/google/renameio/maybe"
|
||||||
"golang.org/x/sys/unix"
|
"golang.org/x/sys/unix"
|
||||||
)
|
)
|
||||||
|
|
||||||
// recurrentChecker is used to check all the files which may include references
|
// dhcpcdStaticConfig checks if interface is configured by /etc/dhcpcd.conf to
|
||||||
// for other ones.
|
// have a static IP.
|
||||||
type recurrentChecker struct {
|
func (n interfaceName) dhcpcdStaticConfig(r io.Reader) (subsources []string, cont bool, err error) {
|
||||||
// checker is the function to check if r's stream contains the desired
|
s := bufio.NewScanner(r)
|
||||||
// attribute. It must return all the patterns for files which should
|
ifaceFound := findIfaceLine(s, string(n))
|
||||||
// also be checked and each of them should be valid for filepath.Glob
|
if !ifaceFound {
|
||||||
// function.
|
return nil, true, s.Err()
|
||||||
checker func(r io.Reader, desired string) (patterns []string, has bool, err error)
|
}
|
||||||
// initPath is the path of the first member in the sequence of checked
|
|
||||||
// files.
|
for s.Scan() {
|
||||||
initPath string
|
line := strings.TrimSpace(s.Text())
|
||||||
|
fields := strings.Fields(line)
|
||||||
|
if len(fields) >= 2 &&
|
||||||
|
fields[0] == "static" &&
|
||||||
|
strings.HasPrefix(fields[1], "ip_address=") {
|
||||||
|
return nil, false, s.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(fields) > 0 && fields[0] == "interface" {
|
||||||
|
// Another interface found.
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, true, s.Err()
|
||||||
}
|
}
|
||||||
|
|
||||||
// maxCheckedFileSize is the maximum length of the file that recurrentChecker
|
// ifacesStaticConfig checks if the interface is configured by any file of
|
||||||
// may check.
|
// /etc/network/interfaces format to have a static IP.
|
||||||
const maxCheckedFileSize = 1024 * 1024
|
func (n interfaceName) ifacesStaticConfig(r io.Reader) (sub []string, cont bool, err error) {
|
||||||
|
s := bufio.NewScanner(r)
|
||||||
// checkFile tries to open and to check single file located on the sourcePath.
|
for s.Scan() {
|
||||||
func (rc *recurrentChecker) checkFile(sourcePath, desired string) (
|
line := strings.TrimSpace(s.Text())
|
||||||
subsources []string,
|
if len(line) == 0 || line[0] == '#' {
|
||||||
has bool,
|
continue
|
||||||
err error,
|
|
||||||
) {
|
|
||||||
var f *os.File
|
|
||||||
f, err = os.Open(sourcePath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() { err = errors.WithDeferred(err, f.Close()) }()
|
|
||||||
|
|
||||||
var r io.Reader
|
|
||||||
r, err = aghio.LimitReader(f, maxCheckedFileSize)
|
|
||||||
if err != nil {
|
|
||||||
return nil, false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
subsources, has, err = rc.checker(r, desired)
|
|
||||||
if err != nil {
|
|
||||||
return nil, false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if has {
|
|
||||||
return nil, true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return subsources, has, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// handlePatterns parses the patterns and takes care of duplicates.
|
|
||||||
func (rc *recurrentChecker) handlePatterns(sourcesSet *stringutil.Set, patterns []string) (
|
|
||||||
subsources []string,
|
|
||||||
err error,
|
|
||||||
) {
|
|
||||||
subsources = make([]string, 0, len(patterns))
|
|
||||||
for _, p := range patterns {
|
|
||||||
var matches []string
|
|
||||||
matches, err = filepath.Glob(p)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("invalid pattern %q: %w", p, err)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, m := range matches {
|
// TODO(e.burkov): As man page interfaces(5) says, a line may be
|
||||||
if sourcesSet.Has(m) {
|
// extended across multiple lines by making the last character a
|
||||||
continue
|
// backslash. Provide extended lines support.
|
||||||
}
|
|
||||||
|
|
||||||
sourcesSet.Add(m)
|
fields := strings.Fields(line)
|
||||||
subsources = append(subsources, m)
|
fieldsNum := len(fields)
|
||||||
|
|
||||||
|
// Man page interfaces(5) declares that interface definition
|
||||||
|
// should consist of the key word "iface" followed by interface
|
||||||
|
// name, and method at fourth field.
|
||||||
|
if fieldsNum >= 4 &&
|
||||||
|
fields[0] == "iface" && fields[1] == string(n) && fields[3] == "static" {
|
||||||
|
return nil, false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if fieldsNum >= 2 && fields[0] == "source" {
|
||||||
|
sub = append(sub, fields[1])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return subsources, nil
|
return sub, true, s.Err()
|
||||||
}
|
|
||||||
|
|
||||||
// check walks through all the files searching for the desired attribute.
|
|
||||||
func (rc *recurrentChecker) check(desired string) (has bool, err error) {
|
|
||||||
var i int
|
|
||||||
sources := []string{rc.initPath}
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if i >= len(sources) {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
err = errors.Annotate(err, "checking %q: %w", sources[i])
|
|
||||||
}()
|
|
||||||
|
|
||||||
var patterns, subsources []string
|
|
||||||
// The slice of sources is separate from the set of sources to keep the
|
|
||||||
// order in which the files are walked.
|
|
||||||
for sourcesSet := stringutil.NewSet(rc.initPath); i < len(sources); i++ {
|
|
||||||
patterns, has, err = rc.checkFile(sources[i], desired)
|
|
||||||
if err != nil {
|
|
||||||
if errors.Is(err, os.ErrNotExist) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if has {
|
|
||||||
return true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
subsources, err = rc.handlePatterns(sourcesSet, patterns)
|
|
||||||
if err != nil {
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
sources = append(sources, subsources...)
|
|
||||||
}
|
|
||||||
|
|
||||||
return false, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func ifaceHasStaticIP(ifaceName string) (has bool, err error) {
|
func ifaceHasStaticIP(ifaceName string) (has bool, err error) {
|
||||||
@@ -142,14 +83,19 @@ func ifaceHasStaticIP(ifaceName string) (has bool, err error) {
|
|||||||
// /etc/network/interfaces doesn't, it will return true. Perhaps this
|
// /etc/network/interfaces doesn't, it will return true. Perhaps this
|
||||||
// is not the most desirable behavior.
|
// is not the most desirable behavior.
|
||||||
|
|
||||||
for _, rc := range []*recurrentChecker{{
|
iface := interfaceName(ifaceName)
|
||||||
checker: dhcpcdStaticConfig,
|
|
||||||
initPath: "/etc/dhcpcd.conf",
|
for _, pair := range []struct {
|
||||||
|
aghos.FileWalker
|
||||||
|
filename string
|
||||||
|
}{{
|
||||||
|
FileWalker: iface.dhcpcdStaticConfig,
|
||||||
|
filename: "/etc/dhcpcd.conf",
|
||||||
}, {
|
}, {
|
||||||
checker: ifacesStaticConfig,
|
FileWalker: iface.ifacesStaticConfig,
|
||||||
initPath: "/etc/network/interfaces",
|
filename: "/etc/network/interfaces",
|
||||||
}} {
|
}} {
|
||||||
has, err = rc.check(ifaceName)
|
has, err = pair.Walk(pair.filename)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return false, err
|
return false, err
|
||||||
}
|
}
|
||||||
@@ -184,67 +130,6 @@ func findIfaceLine(s *bufio.Scanner, name string) (ok bool) {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
// dhcpcdStaticConfig checks if interface is configured by /etc/dhcpcd.conf to
|
|
||||||
// have a static IP.
|
|
||||||
func dhcpcdStaticConfig(r io.Reader, ifaceName string) (subsources []string, has bool, err error) {
|
|
||||||
s := bufio.NewScanner(r)
|
|
||||||
ifaceFound := findIfaceLine(s, ifaceName)
|
|
||||||
if !ifaceFound {
|
|
||||||
return nil, false, s.Err()
|
|
||||||
}
|
|
||||||
|
|
||||||
for s.Scan() {
|
|
||||||
line := strings.TrimSpace(s.Text())
|
|
||||||
fields := strings.Fields(line)
|
|
||||||
if len(fields) >= 2 &&
|
|
||||||
fields[0] == "static" &&
|
|
||||||
strings.HasPrefix(fields[1], "ip_address=") {
|
|
||||||
return nil, true, s.Err()
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(fields) > 0 && fields[0] == "interface" {
|
|
||||||
// Another interface found.
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return nil, false, s.Err()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ifacesStaticConfig checks if the interface is configured by any file of
|
|
||||||
// /etc/network/interfaces format to have a static IP.
|
|
||||||
func ifacesStaticConfig(r io.Reader, ifaceName string) (subsources []string, has bool, err error) {
|
|
||||||
s := bufio.NewScanner(r)
|
|
||||||
for s.Scan() {
|
|
||||||
line := strings.TrimSpace(s.Text())
|
|
||||||
if len(line) == 0 || line[0] == '#' {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO(e.burkov): As man page interfaces(5) says, a line may be
|
|
||||||
// extended across multiple lines by making the last character a
|
|
||||||
// backslash. Provide extended lines and "source-directory"
|
|
||||||
// stanzas support.
|
|
||||||
|
|
||||||
fields := strings.Fields(line)
|
|
||||||
fieldsNum := len(fields)
|
|
||||||
|
|
||||||
// Man page interfaces(5) declares that interface definition
|
|
||||||
// should consist of the key word "iface" followed by interface
|
|
||||||
// name, and method at fourth field.
|
|
||||||
if fieldsNum >= 4 &&
|
|
||||||
fields[0] == "iface" && fields[1] == ifaceName && fields[3] == "static" {
|
|
||||||
return nil, true, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if fieldsNum >= 2 && fields[0] == "source" {
|
|
||||||
subsources = append(subsources, fields[1])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return subsources, false, s.Err()
|
|
||||||
}
|
|
||||||
|
|
||||||
// ifaceSetStaticIP configures the system to retain its current IP on the
|
// ifaceSetStaticIP configures the system to retain its current IP on the
|
||||||
// interface through dhcpdc.conf.
|
// interface through dhcpdc.conf.
|
||||||
func ifaceSetStaticIP(ifaceName string) (err error) {
|
func ifaceSetStaticIP(ifaceName string) (err error) {
|
||||||
|
|||||||
@@ -12,101 +12,90 @@ import (
|
|||||||
"github.com/stretchr/testify/require"
|
"github.com/stretchr/testify/require"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestRecurrentChecker(t *testing.T) {
|
|
||||||
c := &recurrentChecker{
|
|
||||||
checker: ifacesStaticConfig,
|
|
||||||
initPath: "./testdata/include-subsources",
|
|
||||||
}
|
|
||||||
|
|
||||||
has, err := c.check("sample_name")
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.True(t, has)
|
|
||||||
|
|
||||||
has, err = c.check("another_name")
|
|
||||||
require.NoError(t, err)
|
|
||||||
assert.False(t, has)
|
|
||||||
}
|
|
||||||
|
|
||||||
const nl = "\n"
|
const nl = "\n"
|
||||||
|
|
||||||
func TestDHCPCDStaticConfig(t *testing.T) {
|
func TestDHCPCDStaticConfig(t *testing.T) {
|
||||||
|
const iface interfaceName = `wlan0`
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
data []byte
|
data []byte
|
||||||
want bool
|
wantCont bool
|
||||||
}{{
|
}{{
|
||||||
name: "has_not",
|
name: "has_not",
|
||||||
data: []byte(`#comment` + nl +
|
data: []byte(`#comment` + nl +
|
||||||
`# comment` + nl +
|
`# comment` + nl +
|
||||||
`interface eth0` + nl +
|
`interface eth0` + nl +
|
||||||
`static ip_address=192.168.0.1/24` + nl +
|
`static ip_address=192.168.0.1/24` + nl +
|
||||||
`# interface wlan0` + nl +
|
`# interface ` + iface + nl +
|
||||||
`static ip_address=192.168.1.1/24` + nl +
|
`static ip_address=192.168.1.1/24` + nl +
|
||||||
`# comment` + nl,
|
`# comment` + nl,
|
||||||
),
|
),
|
||||||
want: false,
|
wantCont: true,
|
||||||
}, {
|
}, {
|
||||||
name: "has",
|
name: "has",
|
||||||
data: []byte(`#comment` + nl +
|
data: []byte(`#comment` + nl +
|
||||||
`# comment` + nl +
|
`# comment` + nl +
|
||||||
`interface eth0` + nl +
|
`interface eth0` + nl +
|
||||||
`static ip_address=192.168.0.1/24` + nl +
|
`static ip_address=192.168.0.1/24` + nl +
|
||||||
`# interface wlan0` + nl +
|
`# interface ` + iface + nl +
|
||||||
`static ip_address=192.168.1.1/24` + nl +
|
`static ip_address=192.168.1.1/24` + nl +
|
||||||
`# comment` + nl +
|
`# comment` + nl +
|
||||||
`interface wlan0` + nl +
|
`interface ` + iface + nl +
|
||||||
`# comment` + nl +
|
`# comment` + nl +
|
||||||
`static ip_address=192.168.2.1/24` + nl,
|
`static ip_address=192.168.2.1/24` + nl,
|
||||||
),
|
),
|
||||||
want: true,
|
wantCont: false,
|
||||||
}}
|
}}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
r := bytes.NewReader(tc.data)
|
r := bytes.NewReader(tc.data)
|
||||||
_, has, err := dhcpcdStaticConfig(r, "wlan0")
|
_, cont, err := iface.dhcpcdStaticConfig(r)
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, tc.want, has)
|
assert.Equal(t, tc.wantCont, cont)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestIfacesStaticConfig(t *testing.T) {
|
func TestIfacesStaticConfig(t *testing.T) {
|
||||||
|
const iface interfaceName = `enp0s3`
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
data []byte
|
data []byte
|
||||||
want bool
|
wantCont bool
|
||||||
wantPatterns []string
|
wantPatterns []string
|
||||||
}{{
|
}{{
|
||||||
name: "has_not",
|
name: "has_not",
|
||||||
data: []byte(`allow-hotplug enp0s3` + nl +
|
data: []byte(`allow-hotplug ` + iface + nl +
|
||||||
`#iface enp0s3 inet static` + nl +
|
`#iface enp0s3 inet static` + nl +
|
||||||
`# address 192.168.0.200` + nl +
|
`# address 192.168.0.200` + nl +
|
||||||
`# netmask 255.255.255.0` + nl +
|
`# netmask 255.255.255.0` + nl +
|
||||||
`# gateway 192.168.0.1` + nl +
|
`# gateway 192.168.0.1` + nl +
|
||||||
`iface enp0s3 inet dhcp` + nl,
|
`iface ` + iface + ` inet dhcp` + nl,
|
||||||
),
|
),
|
||||||
want: false,
|
wantCont: true,
|
||||||
wantPatterns: []string{},
|
wantPatterns: []string{},
|
||||||
}, {
|
}, {
|
||||||
name: "has",
|
name: "has",
|
||||||
data: []byte(`allow-hotplug enp0s3` + nl +
|
data: []byte(`allow-hotplug ` + iface + nl +
|
||||||
`iface enp0s3 inet static` + nl +
|
`iface ` + iface + ` inet static` + nl +
|
||||||
` address 192.168.0.200` + nl +
|
` address 192.168.0.200` + nl +
|
||||||
` netmask 255.255.255.0` + nl +
|
` netmask 255.255.255.0` + nl +
|
||||||
` gateway 192.168.0.1` + nl +
|
` gateway 192.168.0.1` + nl +
|
||||||
`#iface enp0s3 inet dhcp` + nl,
|
`#iface ` + iface + ` inet dhcp` + nl,
|
||||||
),
|
),
|
||||||
want: true,
|
wantCont: false,
|
||||||
wantPatterns: []string{},
|
wantPatterns: []string{},
|
||||||
}, {
|
}, {
|
||||||
name: "return_patterns",
|
name: "return_patterns",
|
||||||
data: []byte(`source hello` + nl +
|
data: []byte(`source hello` + nl +
|
||||||
`source world` + nl +
|
`source world` + nl +
|
||||||
`#iface enp0s3 inet static` + nl,
|
`#iface ` + iface + ` inet static` + nl,
|
||||||
),
|
),
|
||||||
want: false,
|
wantCont: true,
|
||||||
wantPatterns: []string{"hello", "world"},
|
wantPatterns: []string{"hello", "world"},
|
||||||
}, {
|
}, {
|
||||||
// This one tests if the first found valid interface prevents
|
// This one tests if the first found valid interface prevents
|
||||||
@@ -114,19 +103,19 @@ func TestIfacesStaticConfig(t *testing.T) {
|
|||||||
name: "ignore_patterns",
|
name: "ignore_patterns",
|
||||||
data: []byte(`source hello` + nl +
|
data: []byte(`source hello` + nl +
|
||||||
`source world` + nl +
|
`source world` + nl +
|
||||||
`iface enp0s3 inet static` + nl,
|
`iface ` + iface + ` inet static` + nl,
|
||||||
),
|
),
|
||||||
want: true,
|
wantCont: false,
|
||||||
wantPatterns: []string{},
|
wantPatterns: []string{},
|
||||||
}}
|
}}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
|
r := bytes.NewReader(tc.data)
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
r := bytes.NewReader(tc.data)
|
patterns, has, err := iface.ifacesStaticConfig(r)
|
||||||
patterns, has, err := ifacesStaticConfig(r, "enp0s3")
|
|
||||||
require.NoError(t, err)
|
require.NoError(t, err)
|
||||||
|
|
||||||
assert.Equal(t, tc.want, has)
|
assert.Equal(t, tc.wantCont, has)
|
||||||
assert.ElementsMatch(t, tc.wantPatterns, patterns)
|
assert.ElementsMatch(t, tc.wantPatterns, patterns)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
43
internal/aghnet/net_openbsd.go
Normal file
43
internal/aghnet/net_openbsd.go
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
//go:build openbsd
|
||||||
|
// +build openbsd
|
||||||
|
|
||||||
|
package aghnet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/AdguardTeam/AdGuardHome/internal/aghos"
|
||||||
|
)
|
||||||
|
|
||||||
|
func canBindPrivilegedPorts() (can bool, err error) {
|
||||||
|
return aghos.HaveAdminRights()
|
||||||
|
}
|
||||||
|
|
||||||
|
func ifaceHasStaticIP(ifaceName string) (ok bool, err error) {
|
||||||
|
filename := fmt.Sprintf("/etc/hostname.%s", ifaceName)
|
||||||
|
|
||||||
|
return aghos.FileWalker(hostnameIfStaticConfig).Walk(filename)
|
||||||
|
}
|
||||||
|
|
||||||
|
// hostnameIfStaticConfig checks if the interface is configured by
|
||||||
|
// /etc/hostname.* to have a static IP.
|
||||||
|
func hostnameIfStaticConfig(r io.Reader) (_ []string, ok bool, err error) {
|
||||||
|
s := bufio.NewScanner(r)
|
||||||
|
for s.Scan() {
|
||||||
|
line := strings.TrimSpace(s.Text())
|
||||||
|
fields := strings.Fields(line)
|
||||||
|
if len(fields) >= 2 && fields[0] == "inet" && net.ParseIP(fields[1]) != nil {
|
||||||
|
return nil, false, s.Err()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, true, s.Err()
|
||||||
|
}
|
||||||
|
|
||||||
|
func ifaceSetStaticIP(string) (err error) {
|
||||||
|
return aghos.Unsupported("setting static ip")
|
||||||
|
}
|
||||||
52
internal/aghnet/net_openbsd_test.go
Normal file
52
internal/aghnet/net_openbsd_test.go
Normal file
@@ -0,0 +1,52 @@
|
|||||||
|
//go:build openbsd
|
||||||
|
// +build openbsd
|
||||||
|
|
||||||
|
package aghnet
|
||||||
|
|
||||||
|
import (
|
||||||
|
"strings"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestHostnameIfStaticConfig(t *testing.T) {
|
||||||
|
const nl = "\n"
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
rcconfData string
|
||||||
|
wantHas bool
|
||||||
|
}{{
|
||||||
|
name: "simple",
|
||||||
|
rcconfData: `inet 127.0.0.253` + nl,
|
||||||
|
wantHas: true,
|
||||||
|
}, {
|
||||||
|
name: "case_sensitiveness",
|
||||||
|
rcconfData: `InEt 127.0.0.253` + nl,
|
||||||
|
wantHas: false,
|
||||||
|
}, {
|
||||||
|
name: "comments_and_trash",
|
||||||
|
rcconfData: `# comment 1` + nl +
|
||||||
|
`` + nl +
|
||||||
|
`# inet 127.0.0.253` + nl +
|
||||||
|
`inet` + nl,
|
||||||
|
wantHas: false,
|
||||||
|
}, {
|
||||||
|
name: "incorrect_config",
|
||||||
|
rcconfData: `inet6 127.0.0.253` + nl +
|
||||||
|
`inet 256.256.256.256` + nl,
|
||||||
|
wantHas: false,
|
||||||
|
}}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
r := strings.NewReader(tc.rcconfData)
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
_, has, err := hostnameIfStaticConfig(r)
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, tc.wantHas, has)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
//go:build !(linux || darwin || freebsd)
|
//go:build !(linux || darwin || freebsd || openbsd)
|
||||||
// +build !linux,!darwin,!freebsd
|
// +build !linux,!darwin,!freebsd,!openbsd
|
||||||
|
|
||||||
package aghnet
|
package aghnet
|
||||||
|
|
||||||
|
|||||||
@@ -17,91 +17,50 @@ func TestGetValidNetInterfacesForWeb(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestUnreverseAddr(t *testing.T) {
|
func TestBroadcastFromIPNet(t *testing.T) {
|
||||||
|
known6 := net.IP{
|
||||||
|
1, 2, 3, 4,
|
||||||
|
5, 6, 7, 8,
|
||||||
|
9, 10, 11, 12,
|
||||||
|
13, 14, 15, 16,
|
||||||
|
}
|
||||||
|
|
||||||
testCases := []struct {
|
testCases := []struct {
|
||||||
name string
|
name string
|
||||||
have string
|
subnet *net.IPNet
|
||||||
want net.IP
|
want net.IP
|
||||||
}{{
|
}{{
|
||||||
name: "good_ipv4",
|
name: "full",
|
||||||
have: "1.0.0.127.in-addr.arpa",
|
subnet: &net.IPNet{
|
||||||
want: net.IP{127, 0, 0, 1},
|
IP: net.IP{192, 168, 0, 1},
|
||||||
|
Mask: net.IPMask{255, 255, 15, 0},
|
||||||
|
},
|
||||||
|
want: net.IP{192, 168, 240, 255},
|
||||||
}, {
|
}, {
|
||||||
name: "good_ipv6",
|
name: "ipv6_no_mask",
|
||||||
have: "4.3.2.1.d.c.b.a.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa",
|
subnet: &net.IPNet{
|
||||||
want: net.ParseIP("::abcd:1234"),
|
IP: known6,
|
||||||
|
},
|
||||||
|
want: known6,
|
||||||
}, {
|
}, {
|
||||||
name: "good_ipv6_case",
|
name: "ipv4_no_mask",
|
||||||
have: "4.3.2.1.d.c.B.A.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.iP6.ArPa",
|
subnet: &net.IPNet{
|
||||||
want: net.ParseIP("::abcd:1234"),
|
IP: net.IP{192, 168, 1, 2},
|
||||||
|
},
|
||||||
|
want: net.IP{192, 168, 1, 255},
|
||||||
}, {
|
}, {
|
||||||
name: "good_ipv4_dot",
|
name: "unspecified",
|
||||||
have: "1.0.0.127.in-addr.arpa.",
|
subnet: &net.IPNet{
|
||||||
want: net.IP{127, 0, 0, 1},
|
IP: net.IP{0, 0, 0, 0},
|
||||||
}, {
|
Mask: net.IPMask{0, 0, 0, 0},
|
||||||
name: "good_ipv4_case",
|
},
|
||||||
have: "1.0.0.127.In-Addr.Arpa",
|
want: net.IPv4bcast,
|
||||||
want: net.IP{127, 0, 0, 1},
|
|
||||||
}, {
|
|
||||||
name: "wrong_ipv4",
|
|
||||||
have: ".0.0.127.in-addr.arpa",
|
|
||||||
want: nil,
|
|
||||||
}, {
|
|
||||||
name: "wrong_ipv6",
|
|
||||||
have: ".3.2.1.d.c.b.a.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa",
|
|
||||||
want: nil,
|
|
||||||
}, {
|
|
||||||
name: "bad_ipv6_dot",
|
|
||||||
have: "4.3.2.1.d.c.b.a.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0..ip6.arpa",
|
|
||||||
want: nil,
|
|
||||||
}, {
|
|
||||||
name: "bad_ipv6_space",
|
|
||||||
have: "4.3.2.1.d.c.b. .0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa",
|
|
||||||
want: nil,
|
|
||||||
}}
|
}}
|
||||||
|
|
||||||
for _, tc := range testCases {
|
for _, tc := range testCases {
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
ip := UnreverseAddr(tc.have)
|
bc := BroadcastFromIPNet(tc.subnet)
|
||||||
assert.True(t, tc.want.Equal(ip))
|
assert.True(t, bc.Equal(tc.want), bc)
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func TestReverseAddr(t *testing.T) {
|
|
||||||
testCases := []struct {
|
|
||||||
name string
|
|
||||||
want string
|
|
||||||
ip net.IP
|
|
||||||
}{{
|
|
||||||
name: "valid_ipv4",
|
|
||||||
want: "4.3.2.1.in-addr.arpa",
|
|
||||||
ip: net.IP{1, 2, 3, 4},
|
|
||||||
}, {
|
|
||||||
name: "valid_ipv6",
|
|
||||||
want: "1.3.b.5.4.1.8.6.0.0.0.0.0.0.0.0.0.0.0.0.0.1.0.0.0.0.7.4.6.0.6.2.ip6.arpa",
|
|
||||||
ip: net.ParseIP("2606:4700:10::6814:5b31"),
|
|
||||||
}, {
|
|
||||||
name: "nil_ip",
|
|
||||||
want: "",
|
|
||||||
ip: nil,
|
|
||||||
}, {
|
|
||||||
name: "unspecified_ipv6",
|
|
||||||
want: "0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.0.ip6.arpa",
|
|
||||||
ip: net.IPv6unspecified,
|
|
||||||
}, {
|
|
||||||
name: "unspecified_ipv4",
|
|
||||||
want: "0.0.0.0.in-addr.arpa",
|
|
||||||
ip: net.IPv4zero,
|
|
||||||
}, {
|
|
||||||
name: "wrong_length_ip",
|
|
||||||
want: "",
|
|
||||||
ip: net.IP{1, 2, 3, 4, 5},
|
|
||||||
}}
|
|
||||||
|
|
||||||
for _, tc := range testCases {
|
|
||||||
t.Run(tc.name, func(t *testing.T) {
|
|
||||||
assert.Equal(t, tc.want, ReverseAddr(tc.ip))
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
8
internal/aghnet/net_unix.go
Normal file
8
internal/aghnet/net_unix.go
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
//go:build openbsd || freebsd || linux
|
||||||
|
// +build openbsd freebsd linux
|
||||||
|
|
||||||
|
package aghnet
|
||||||
|
|
||||||
|
// interfaceName is a string containing network interface's name. The name is
|
||||||
|
// used in file walking methods.
|
||||||
|
type interfaceName string
|
||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
|
"github.com/AdguardTeam/golibs/netutil"
|
||||||
"github.com/AdguardTeam/golibs/stringutil"
|
"github.com/AdguardTeam/golibs/stringutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -104,7 +105,7 @@ const dockerEmbeddedDNS = "127.0.0.11"
|
|||||||
func (sr *systemResolvers) dialFunc(_ context.Context, _, address string) (_ net.Conn, err error) {
|
func (sr *systemResolvers) dialFunc(_ context.Context, _, address string) (_ net.Conn, err error) {
|
||||||
// Just validate the passed address is a valid IP.
|
// Just validate the passed address is a valid IP.
|
||||||
var host string
|
var host string
|
||||||
host, err = SplitHost(address)
|
host, err = netutil.SplitHost(address)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// TODO(e.burkov): Maybe use a structured errBadAddrPassed to
|
// TODO(e.burkov): Maybe use a structured errBadAddrPassed to
|
||||||
// allow unwrapping of the real error.
|
// allow unwrapping of the real error.
|
||||||
|
|||||||
@@ -13,8 +13,6 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/aghio"
|
|
||||||
"github.com/AdguardTeam/AdGuardHome/internal/aghos"
|
|
||||||
"github.com/AdguardTeam/golibs/errors"
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
"github.com/AdguardTeam/golibs/log"
|
"github.com/AdguardTeam/golibs/log"
|
||||||
)
|
)
|
||||||
@@ -101,7 +99,13 @@ func scanAddrs(s *bufio.Scanner) (addrs []string) {
|
|||||||
// local resolvers addresses on Windows. We execute the external command for
|
// local resolvers addresses on Windows. We execute the external command for
|
||||||
// now that is not the most accurate way.
|
// now that is not the most accurate way.
|
||||||
func (sr *systemResolvers) getAddrs() (addrs []string, err error) {
|
func (sr *systemResolvers) getAddrs() (addrs []string, err error) {
|
||||||
cmd := exec.Command("nslookup")
|
var cmdPath string
|
||||||
|
cmdPath, err = exec.LookPath("nslookup.exe")
|
||||||
|
if err != nil {
|
||||||
|
return nil, fmt.Errorf("looking up cmd path: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
cmd := exec.Command(cmdPath)
|
||||||
|
|
||||||
var stdin io.WriteCloser
|
var stdin io.WriteCloser
|
||||||
stdin, err = cmd.StdinPipe()
|
stdin, err = cmd.StdinPipe()
|
||||||
@@ -115,12 +119,6 @@ func (sr *systemResolvers) getAddrs() (addrs []string, err error) {
|
|||||||
return nil, fmt.Errorf("getting the command's stdout pipe: %w", err)
|
return nil, fmt.Errorf("getting the command's stdout pipe: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
var stdoutLimited io.Reader
|
|
||||||
stdoutLimited, err = aghio.LimitReader(stdout, aghos.MaxCmdOutputSize)
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("limiting stdout reader: %w", err)
|
|
||||||
}
|
|
||||||
|
|
||||||
go writeExit(stdin)
|
go writeExit(stdin)
|
||||||
|
|
||||||
err = cmd.Start()
|
err = cmd.Start()
|
||||||
@@ -128,7 +126,7 @@ func (sr *systemResolvers) getAddrs() (addrs []string, err error) {
|
|||||||
return nil, fmt.Errorf("start command executing: %w", err)
|
return nil, fmt.Errorf("start command executing: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
s := bufio.NewScanner(stdoutLimited)
|
s := bufio.NewScanner(stdout)
|
||||||
addrs = scanAddrs(s)
|
addrs = scanAddrs(s)
|
||||||
|
|
||||||
err = cmd.Wait()
|
err = cmd.Wait()
|
||||||
|
|||||||
119
internal/aghos/filewalker.go
Normal file
119
internal/aghos/filewalker.go
Normal file
@@ -0,0 +1,119 @@
|
|||||||
|
package aghos
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/AdguardTeam/AdGuardHome/internal/aghio"
|
||||||
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
|
"github.com/AdguardTeam/golibs/stringutil"
|
||||||
|
)
|
||||||
|
|
||||||
|
// FileWalker is the signature of a function called for files in the file tree.
|
||||||
|
// As opposed to filepath.Walk it only walk the files (not directories) matching
|
||||||
|
// the provided pattern and those returned by function itself. All patterns
|
||||||
|
// should be valid for filepath.Glob. If cont is false, the walking terminates.
|
||||||
|
// Each opened file is also limited for reading to MaxWalkedFileSize.
|
||||||
|
//
|
||||||
|
// TODO(e.burkov): Consider moving to the separate package like pathutil.
|
||||||
|
//
|
||||||
|
// TODO(e.burkov): Think about passing filename or any additional data.
|
||||||
|
type FileWalker func(r io.Reader) (patterns []string, cont bool, err error)
|
||||||
|
|
||||||
|
// MaxWalkedFileSize is the maximum length of the file that FileWalker can
|
||||||
|
// check.
|
||||||
|
const MaxWalkedFileSize = 1024 * 1024
|
||||||
|
|
||||||
|
// checkFile tries to open and process a single file located on sourcePath.
|
||||||
|
func checkFile(c FileWalker, sourcePath string) (patterns []string, cont bool, err error) {
|
||||||
|
var f *os.File
|
||||||
|
f, err = os.Open(sourcePath)
|
||||||
|
if err != nil {
|
||||||
|
if errors.Is(err, os.ErrNotExist) {
|
||||||
|
// Ignore non-existing files since this may only happen
|
||||||
|
// when the file was removed after filepath.Glob matched
|
||||||
|
// it.
|
||||||
|
return nil, true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil, false, err
|
||||||
|
}
|
||||||
|
defer func() { err = errors.WithDeferred(err, f.Close()) }()
|
||||||
|
|
||||||
|
var r io.Reader
|
||||||
|
// Ignore the error since LimitReader function returns error only if
|
||||||
|
// passed limit value is less than zero, but the constant used.
|
||||||
|
//
|
||||||
|
// TODO(e.burkov): Make variable.
|
||||||
|
r, _ = aghio.LimitReader(f, MaxWalkedFileSize)
|
||||||
|
|
||||||
|
return c(r)
|
||||||
|
}
|
||||||
|
|
||||||
|
// handlePatterns parses the patterns and ignores duplicates using srcSet.
|
||||||
|
// srcSet must be non-nil.
|
||||||
|
func handlePatterns(srcSet *stringutil.Set, patterns ...string) (sub []string, err error) {
|
||||||
|
sub = make([]string, 0, len(patterns))
|
||||||
|
for _, p := range patterns {
|
||||||
|
var matches []string
|
||||||
|
matches, err = filepath.Glob(p)
|
||||||
|
if err != nil {
|
||||||
|
// Enrich error with the pattern because filepath.Glob
|
||||||
|
// doesn't do it.
|
||||||
|
return nil, fmt.Errorf("invalid pattern %q: %w", p, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, m := range matches {
|
||||||
|
if srcSet.Has(m) {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
srcSet.Add(m)
|
||||||
|
sub = append(sub, m)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sub, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Walk starts walking the files defined by initPattern. It only returns true
|
||||||
|
// if c signed to stop walking.
|
||||||
|
func (c FileWalker) Walk(initPattern string) (ok bool, err error) {
|
||||||
|
// The slice of sources keeps the order in which the files are walked
|
||||||
|
// since srcSet.Values() returns strings in undefined order.
|
||||||
|
srcSet := stringutil.NewSet()
|
||||||
|
var src []string
|
||||||
|
src, err = handlePatterns(srcSet, initPattern)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
var filename string
|
||||||
|
defer func() { err = errors.Annotate(err, "checking %q: %w", filename) }()
|
||||||
|
|
||||||
|
for i := 0; i < len(src); i++ {
|
||||||
|
var patterns []string
|
||||||
|
var cont bool
|
||||||
|
filename = src[i]
|
||||||
|
patterns, cont, err = checkFile(c, src[i])
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if !cont {
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var subsrc []string
|
||||||
|
subsrc, err = handlePatterns(srcSet, patterns...)
|
||||||
|
if err != nil {
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
src = append(src, subsrc...)
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
209
internal/aghos/filewalker_test.go
Normal file
209
internal/aghos/filewalker_test.go
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
package aghos
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bufio"
|
||||||
|
"io"
|
||||||
|
"io/fs"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"testing"
|
||||||
|
|
||||||
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
// testFSDir maps entries' names to entries which should either be a testFSDir
|
||||||
|
// or byte slice.
|
||||||
|
type testFSDir map[string]interface{}
|
||||||
|
|
||||||
|
// testFSGen is used to generate a temporary filesystem consisting of
|
||||||
|
// directories and plain text files from itself.
|
||||||
|
type testFSGen testFSDir
|
||||||
|
|
||||||
|
// gen returns the name of top directory of the generated filesystem.
|
||||||
|
func (g testFSGen) gen(t *testing.T) (dirName string) {
|
||||||
|
t.Helper()
|
||||||
|
|
||||||
|
dirName = t.TempDir()
|
||||||
|
g.rangeThrough(t, dirName)
|
||||||
|
|
||||||
|
return dirName
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g testFSGen) rangeThrough(t *testing.T, dirName string) {
|
||||||
|
const perm fs.FileMode = 0o777
|
||||||
|
|
||||||
|
for k, e := range g {
|
||||||
|
switch e := e.(type) {
|
||||||
|
case []byte:
|
||||||
|
require.NoError(t, os.WriteFile(filepath.Join(dirName, k), e, perm))
|
||||||
|
|
||||||
|
case testFSDir:
|
||||||
|
newDir := filepath.Join(dirName, k)
|
||||||
|
require.NoError(t, os.Mkdir(newDir, perm))
|
||||||
|
|
||||||
|
testFSGen(e).rangeThrough(t, newDir)
|
||||||
|
default:
|
||||||
|
t.Fatalf("unexpected entry type %T", e)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestFileWalker_Walk(t *testing.T) {
|
||||||
|
const attribute = `000`
|
||||||
|
|
||||||
|
makeFileWalker := func(dirName string) (fw FileWalker) {
|
||||||
|
return func(r io.Reader) (patterns []string, cont bool, err error) {
|
||||||
|
s := bufio.NewScanner(r)
|
||||||
|
for s.Scan() {
|
||||||
|
line := s.Text()
|
||||||
|
if line == attribute {
|
||||||
|
return nil, false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(line) != 0 {
|
||||||
|
patterns = append(patterns, filepath.Join(dirName, line))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return patterns, true, s.Err()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const nl = "\n"
|
||||||
|
|
||||||
|
testCases := []struct {
|
||||||
|
name string
|
||||||
|
testFS testFSGen
|
||||||
|
initPattern string
|
||||||
|
want bool
|
||||||
|
}{{
|
||||||
|
name: "simple",
|
||||||
|
testFS: testFSGen{
|
||||||
|
"simple_0001.txt": []byte(attribute + nl),
|
||||||
|
},
|
||||||
|
initPattern: "simple_0001.txt",
|
||||||
|
want: true,
|
||||||
|
}, {
|
||||||
|
name: "chain",
|
||||||
|
testFS: testFSGen{
|
||||||
|
"chain_0001.txt": []byte(`chain_0002.txt` + nl),
|
||||||
|
"chain_0002.txt": []byte(`chain_0003.txt` + nl),
|
||||||
|
"chain_0003.txt": []byte(attribute + nl),
|
||||||
|
},
|
||||||
|
initPattern: "chain_0001.txt",
|
||||||
|
want: true,
|
||||||
|
}, {
|
||||||
|
name: "several",
|
||||||
|
testFS: testFSGen{
|
||||||
|
"several_0001.txt": []byte(`several_*` + nl),
|
||||||
|
"several_0002.txt": []byte(`several_0001.txt` + nl),
|
||||||
|
"several_0003.txt": []byte(attribute + nl),
|
||||||
|
},
|
||||||
|
initPattern: "several_0001.txt",
|
||||||
|
want: true,
|
||||||
|
}, {
|
||||||
|
name: "no",
|
||||||
|
testFS: testFSGen{
|
||||||
|
"no_0001.txt": []byte(nl),
|
||||||
|
"no_0002.txt": []byte(nl),
|
||||||
|
"no_0003.txt": []byte(nl),
|
||||||
|
},
|
||||||
|
initPattern: "no_*",
|
||||||
|
want: false,
|
||||||
|
}, {
|
||||||
|
name: "subdirectory",
|
||||||
|
testFS: testFSGen{
|
||||||
|
"dir": testFSDir{
|
||||||
|
"subdir_0002.txt": []byte(attribute + nl),
|
||||||
|
},
|
||||||
|
"subdir_0001.txt": []byte(`dir/*`),
|
||||||
|
},
|
||||||
|
initPattern: "subdir_0001.txt",
|
||||||
|
want: true,
|
||||||
|
}}
|
||||||
|
|
||||||
|
for _, tc := range testCases {
|
||||||
|
testDir := tc.testFS.gen(t)
|
||||||
|
fw := makeFileWalker(testDir)
|
||||||
|
|
||||||
|
t.Run(tc.name, func(t *testing.T) {
|
||||||
|
ok, err := fw.Walk(filepath.Join(testDir, tc.initPattern))
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
assert.Equal(t, tc.want, ok)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
t.Run("pattern_malformed", func(t *testing.T) {
|
||||||
|
ok, err := makeFileWalker("").Walk("[]")
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
assert.False(t, ok)
|
||||||
|
assert.ErrorIs(t, err, filepath.ErrBadPattern)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("bad_filename", func(t *testing.T) {
|
||||||
|
dir := testFSGen{
|
||||||
|
"bad_filename.txt": []byte("[]"),
|
||||||
|
}.gen(t)
|
||||||
|
fw := FileWalker(func(r io.Reader) (patterns []string, cont bool, err error) {
|
||||||
|
s := bufio.NewScanner(r)
|
||||||
|
for s.Scan() {
|
||||||
|
patterns = append(patterns, s.Text())
|
||||||
|
}
|
||||||
|
|
||||||
|
return patterns, true, s.Err()
|
||||||
|
})
|
||||||
|
|
||||||
|
ok, err := fw.Walk(filepath.Join(dir, "bad_filename.txt"))
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
assert.False(t, ok)
|
||||||
|
assert.ErrorIs(t, err, filepath.ErrBadPattern)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("itself_error", func(t *testing.T) {
|
||||||
|
const rerr errors.Error = "returned error"
|
||||||
|
|
||||||
|
dir := testFSGen{
|
||||||
|
"mockfile.txt": []byte(`mockdata`),
|
||||||
|
}.gen(t)
|
||||||
|
|
||||||
|
ok, err := FileWalker(func(r io.Reader) (patterns []string, ok bool, err error) {
|
||||||
|
return nil, true, rerr
|
||||||
|
}).Walk(filepath.Join(dir, "*"))
|
||||||
|
require.Error(t, err)
|
||||||
|
require.False(t, ok)
|
||||||
|
|
||||||
|
assert.ErrorIs(t, err, rerr)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestWalkerFunc_CheckFile(t *testing.T) {
|
||||||
|
t.Run("non-existing", func(t *testing.T) {
|
||||||
|
_, ok, err := checkFile(nil, "lol")
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
assert.True(t, ok)
|
||||||
|
})
|
||||||
|
|
||||||
|
t.Run("invalid_argument", func(t *testing.T) {
|
||||||
|
const badPath = "\x00"
|
||||||
|
|
||||||
|
_, ok, err := checkFile(nil, badPath)
|
||||||
|
require.Error(t, err)
|
||||||
|
|
||||||
|
assert.False(t, ok)
|
||||||
|
// TODO(e.burkov): Use assert.ErrorsIs within the error from
|
||||||
|
// less platform-dependent package instead of syscall.EINVAL.
|
||||||
|
//
|
||||||
|
// See https://github.com/golang/go/issues/46849 and
|
||||||
|
// https://github.com/golang/go/issues/30322.
|
||||||
|
pathErr := &os.PathError{}
|
||||||
|
require.ErrorAs(t, err, &pathErr)
|
||||||
|
assert.Equal(t, "open", pathErr.Op)
|
||||||
|
assert.Equal(t, badPath, pathErr.Path)
|
||||||
|
})
|
||||||
|
}
|
||||||
@@ -4,10 +4,17 @@
|
|||||||
package aghos
|
package aghos
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bufio"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
|
"path"
|
||||||
"runtime"
|
"runtime"
|
||||||
"syscall"
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/AdguardTeam/golibs/errors"
|
||||||
|
"github.com/AdguardTeam/golibs/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
// UnsupportedError is returned by functions and methods when a particular
|
// UnsupportedError is returned by functions and methods when a particular
|
||||||
@@ -43,11 +50,6 @@ func HaveAdminRights() (bool, error) {
|
|||||||
return haveAdminRights()
|
return haveAdminRights()
|
||||||
}
|
}
|
||||||
|
|
||||||
// SendProcessSignal sends signal to a process.
|
|
||||||
func SendProcessSignal(pid int, sig syscall.Signal) error {
|
|
||||||
return sendProcessSignal(pid, sig)
|
|
||||||
}
|
|
||||||
|
|
||||||
// MaxCmdOutputSize is the maximum length of performed shell command output.
|
// MaxCmdOutputSize is the maximum length of performed shell command output.
|
||||||
const MaxCmdOutputSize = 2 * 1024
|
const MaxCmdOutputSize = 2 * 1024
|
||||||
|
|
||||||
@@ -58,13 +60,101 @@ func RunCommand(command string, arguments ...string) (int, string, error) {
|
|||||||
if len(out) > MaxCmdOutputSize {
|
if len(out) > MaxCmdOutputSize {
|
||||||
out = out[:MaxCmdOutputSize]
|
out = out[:MaxCmdOutputSize]
|
||||||
}
|
}
|
||||||
if err != nil {
|
|
||||||
return 1, "", fmt.Errorf("exec.Command(%s) failed: %v: %s", command, err, string(out))
|
if errors.As(err, new(*exec.ExitError)) {
|
||||||
|
return cmd.ProcessState.ExitCode(), string(out), nil
|
||||||
|
} else if err != nil {
|
||||||
|
return 1, "", fmt.Errorf("exec.Command(%s) failed: %w: %s", command, err, string(out))
|
||||||
}
|
}
|
||||||
|
|
||||||
return cmd.ProcessState.ExitCode(), string(out), nil
|
return cmd.ProcessState.ExitCode(), string(out), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// PIDByCommand searches for process named command and returns its PID ignoring
|
||||||
|
// the PIDs from except. If no processes found, the error returned.
|
||||||
|
func PIDByCommand(command string, except ...int) (pid int, err error) {
|
||||||
|
// Don't use -C flag here since it's a feature of linux's ps
|
||||||
|
// implementation. Use POSIX-compatible flags instead.
|
||||||
|
//
|
||||||
|
// See https://github.com/AdguardTeam/AdGuardHome/issues/3457.
|
||||||
|
cmd := exec.Command("ps", "-A", "-o", "pid=", "-o", "comm=")
|
||||||
|
|
||||||
|
var stdout io.ReadCloser
|
||||||
|
if stdout, err = cmd.StdoutPipe(); err != nil {
|
||||||
|
return 0, fmt.Errorf("getting the command's stdout pipe: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = cmd.Start(); err != nil {
|
||||||
|
return 0, fmt.Errorf("start command executing: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
var instNum int
|
||||||
|
pid, instNum, err = parsePSOutput(stdout, command, except...)
|
||||||
|
if err != nil {
|
||||||
|
return 0, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err = cmd.Wait(); err != nil {
|
||||||
|
return 0, fmt.Errorf("executing the command: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
switch instNum {
|
||||||
|
case 0:
|
||||||
|
// TODO(e.burkov): Use constant error.
|
||||||
|
return 0, fmt.Errorf("no %s instances found", command)
|
||||||
|
case 1:
|
||||||
|
// Go on.
|
||||||
|
default:
|
||||||
|
log.Info("warning: %d %s instances found", instNum, command)
|
||||||
|
}
|
||||||
|
|
||||||
|
if code := cmd.ProcessState.ExitCode(); code != 0 {
|
||||||
|
return 0, fmt.Errorf("ps finished with code %d", code)
|
||||||
|
}
|
||||||
|
|
||||||
|
return pid, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// parsePSOutput scans the output of ps searching the largest PID of the process
|
||||||
|
// associated with cmdName ignoring PIDs from ignore. Valid r's line shoud be
|
||||||
|
// like:
|
||||||
|
//
|
||||||
|
// 123 ./example-cmd
|
||||||
|
// 1230 some/base/path/example-cmd
|
||||||
|
// 3210 example-cmd
|
||||||
|
//
|
||||||
|
func parsePSOutput(r io.Reader, cmdName string, ignore ...int) (largest, instNum int, err error) {
|
||||||
|
s := bufio.NewScanner(r)
|
||||||
|
ScanLoop:
|
||||||
|
for s.Scan() {
|
||||||
|
fields := strings.Fields(s.Text())
|
||||||
|
if len(fields) != 2 || path.Base(fields[1]) != cmdName {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
cur, aerr := strconv.Atoi(fields[0])
|
||||||
|
if aerr != nil || cur < 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, pid := range ignore {
|
||||||
|
if cur == pid {
|
||||||
|
continue ScanLoop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
instNum++
|
||||||
|
if cur > largest {
|
||||||
|
largest = cur
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err = s.Err(); err != nil {
|
||||||
|
return 0, 0, fmt.Errorf("scanning stdout: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
return largest, instNum, nil
|
||||||
|
}
|
||||||
|
|
||||||
// IsOpenWrt returns true if host OS is OpenWrt.
|
// IsOpenWrt returns true if host OS is OpenWrt.
|
||||||
func IsOpenWrt() (ok bool) {
|
func IsOpenWrt() (ok bool) {
|
||||||
return isOpenWrt()
|
return isOpenWrt()
|
||||||
|
|||||||
@@ -20,10 +20,6 @@ func haveAdminRights() (bool, error) {
|
|||||||
return os.Getuid() == 0, nil
|
return os.Getuid() == 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendProcessSignal(pid int, sig syscall.Signal) error {
|
|
||||||
return syscall.Kill(pid, sig)
|
|
||||||
}
|
|
||||||
|
|
||||||
func isOpenWrt() (ok bool) {
|
func isOpenWrt() (ok bool) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -20,10 +20,6 @@ func haveAdminRights() (bool, error) {
|
|||||||
return os.Getuid() == 0, nil
|
return os.Getuid() == 0, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func sendProcessSignal(pid int, sig syscall.Signal) error {
|
|
||||||
return syscall.Kill(pid, sig)
|
|
||||||
}
|
|
||||||
|
|
||||||
func isOpenWrt() (ok bool) {
|
func isOpenWrt() (ok bool) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user