From 0500aa9591d1fb52f24182734859c398203d6962 Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Thu, 28 May 2020 17:14:50 +0300 Subject: [PATCH 01/38] + new query logs API + "upstream" + filteringStatusProcessed + ctDomainOrClient remove ctQuestionType, ctDomain, ctClient --- AGHTechDoc.md | 23 ++++++++++++++-------- querylog/json.go | 2 ++ querylog/qlog_http.go | 10 ++-------- querylog/qlog_test.go | 8 ++++---- querylog/search_criteria.go | 38 ++++++++++++++++--------------------- 5 files changed, 39 insertions(+), 42 deletions(-) diff --git a/AGHTechDoc.md b/AGHTechDoc.md index 5a3b001c..ee9e7ee8 100644 --- a/AGHTechDoc.md +++ b/AGHTechDoc.md @@ -1200,8 +1200,8 @@ When a new DNS request is received and processed, we store information about thi "QH":"...", // target host name without the last dot "QT":"...", // question type "QC":"...", // question class - "Answer":"...", - "OrigAnswer":"...", + "Answer":"base64 data", + "OrigAnswer":"base64 data", "Result":{ "IsFiltered":true, "Reason":3, @@ -1234,16 +1234,22 @@ Request: GET /control/querylog ?older_than=2006-01-02T15:04:05.999999999Z07:00 - &filter_domain=... - &filter_client=... - &filter_question_type=A | AAAA - &filter_response_status= | filtered + &search=... + &response_status=""|blocked|whitelisted|processed `older_than` setting is used for paging. UI uses an empty value for `older_than` on the first request and gets the latest log entries. To get the older entries, UI sets `older_than` to the `oldest` value from the server's response. -If "filter" settings are set, server returns only entries that match the specified request. +If search settings are set, server returns only entries that match the specified request. -For `filter.domain` and `filter.client` the server matches substrings by default: `adguard.com` matches `www.adguard.com`. Strict matching can be enabled by enclosing the value in double quotes: `"adguard.com"` matches `adguard.com` but doesn't match `www.adguard.com`. +`search`: +match by domain name or client IP address. +The server matches substrings by default: e.g. `adguard.com` matches `www.adguard.com`. +Strict matching can be enabled by enclosing the value in double quotes: e.g. `"adguard.com"` matches `adguard.com` but doesn't match `www.adguard.com`. + +`response_status`: +* blocked: only blocked entries +* whitelisted: only white-listed entries +* processed: all not blocked, not white-listed entries Response: @@ -1266,6 +1272,7 @@ Response: } ... ], + "upstream":"...", // Upstream URL starting with tcp://, tls://, https://, or with an IP address "answer_dnssec": true, "client":"127.0.0.1", "elapsedMs":"0.098403", diff --git a/querylog/json.go b/querylog/json.go index 86f35e11..cc7e6c39 100644 --- a/querylog/json.go +++ b/querylog/json.go @@ -112,6 +112,8 @@ func (l *queryLog) logEntryToJSONEntry(entry *logEntry) map[string]interface{} { } } + jsonEntry["upstream"] = entry.Upstream + return jsonEntry } diff --git a/querylog/qlog_http.go b/querylog/qlog_http.go index 19caa35c..cf804c47 100644 --- a/querylog/qlog_http.go +++ b/querylog/qlog_http.go @@ -142,10 +142,6 @@ func (l *queryLog) parseSearchCriteria(q url.Values, name string, ct criteriaTyp c.strict = true } - if ct == ctClient && l.conf.AnonymizeClientIP { - c.value = l.getClientIP(c.value) - } - if ct == ctFilteringStatus && !util.ContainsString(filteringStatusValues, c.value) { return false, c, fmt.Errorf("invalid value %s", c.value) } @@ -180,10 +176,8 @@ func (l *queryLog) parseSearchParams(r *http.Request) (*searchParams, error) { } paramNames := map[string]criteriaType{ - "filter_domain": ctDomain, - "filter_client": ctClient, - "filter_question_type": ctQuestionType, - "filter_response_status": ctFilteringStatus, + "search": ctDomainOrClient, + "response_status": ctFilteringStatus, } for k, v := range paramNames { diff --git a/querylog/qlog_test.go b/querylog/qlog_test.go index 921d2870..c087fa4d 100644 --- a/querylog/qlog_test.go +++ b/querylog/qlog_test.go @@ -57,7 +57,7 @@ func TestQueryLog(t *testing.T) { // search by domain (strict) params = newSearchParams() params.searchCriteria = append(params.searchCriteria, searchCriteria{ - criteriaType: ctDomain, + criteriaType: ctDomainOrClient, strict: true, value: "test.example.org", }) @@ -68,7 +68,7 @@ func TestQueryLog(t *testing.T) { // search by domain (not strict) params = newSearchParams() params.searchCriteria = append(params.searchCriteria, searchCriteria{ - criteriaType: ctDomain, + criteriaType: ctDomainOrClient, strict: false, value: "example.org", }) @@ -81,7 +81,7 @@ func TestQueryLog(t *testing.T) { // search by client IP (strict) params = newSearchParams() params.searchCriteria = append(params.searchCriteria, searchCriteria{ - criteriaType: ctClient, + criteriaType: ctDomainOrClient, strict: true, value: "2.2.2.2", }) @@ -92,7 +92,7 @@ func TestQueryLog(t *testing.T) { // search by client IP (part of) params = newSearchParams() params.searchCriteria = append(params.searchCriteria, searchCriteria{ - criteriaType: ctClient, + criteriaType: ctDomainOrClient, strict: false, value: "2.2.2", }) diff --git a/querylog/search_criteria.go b/querylog/search_criteria.go index b2ba63f6..bc2aa435 100644 --- a/querylog/search_criteria.go +++ b/querylog/search_criteria.go @@ -9,9 +9,7 @@ import ( type criteriaType int const ( - ctDomain criteriaType = iota // domain name - ctClient // client IP address - ctQuestionType // question type + ctDomainOrClient criteriaType = iota // domain name or client IP address ctFilteringStatus // filtering status ) @@ -25,6 +23,7 @@ const ( filteringStatusWhitelisted = "whitelisted" // whitelisted filteringStatusRewritten = "rewritten" // all kinds of rewrites filteringStatusSafeSearch = "safe_search" // enforced safe search + filteringStatusProcessed = "processed" // not blocked, not white-listed entries ) // filteringStatusValues -- array with all possible filteringStatus values @@ -32,6 +31,7 @@ var filteringStatusValues = []string{ filteringStatusAll, filteringStatusFiltered, filteringStatusBlocked, filteringStatusBlockedSafebrowsing, filteringStatusBlockedParental, filteringStatusWhitelisted, filteringStatusRewritten, filteringStatusSafeSearch, + filteringStatusProcessed, } // searchCriteria - every search request may contain a list of different search criteria @@ -48,12 +48,9 @@ func (c *searchCriteria) quickMatch(line string) bool { // note that we do this only for a limited set of criteria switch c.criteriaType { - case ctDomain: - return c.quickMatchJSONValue(line, "QH") - case ctClient: - return c.quickMatchJSONValue(line, "IP") - case ctQuestionType: - return c.quickMatchJSONValue(line, "QT") + case ctDomainOrClient: + return c.quickMatchJSONValue(line, "QH") || + c.quickMatchJSONValue(line, "IP") default: return true } @@ -80,29 +77,23 @@ func (c *searchCriteria) quickMatchJSONValue(line string, propertyName string) b // nolint (gocyclo) func (c *searchCriteria) match(entry *logEntry) bool { switch c.criteriaType { - case ctDomain: + case ctDomainOrClient: if c.strict && entry.QHost == c.value { return true } if !c.strict && strings.Contains(entry.QHost, c.value) { return true } - return false - case ctClient: + if c.strict && entry.IP == c.value { return true } if !c.strict && strings.Contains(entry.IP, c.value) { return true } + return false - case ctQuestionType: - if c.strict && entry.QType == c.value { - return true - } - if !c.strict && strings.Contains(entry.QType, c.value) { - return true - } + case ctFilteringStatus: res := entry.Result @@ -127,12 +118,15 @@ func (c *searchCriteria) match(entry *logEntry) bool { res.Reason == dnsfilter.RewriteEtcHosts) case filteringStatusSafeSearch: return res.IsFiltered && res.Reason == dnsfilter.FilteredSafeSearch + + case filteringStatusProcessed: + return !(res.Reason == dnsfilter.FilteredBlackList || + res.Reason == dnsfilter.FilteredBlockedService || + res.Reason == dnsfilter.NotFilteredWhiteList) + default: return false } - - default: - return false } return false From 0adbce5d385f233087f365028bb98f5772862b41 Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Thu, 28 May 2020 17:58:56 +0300 Subject: [PATCH 02/38] * openapi --- openapi/openapi.yaml | 25 ++++++++++--------------- 1 file changed, 10 insertions(+), 15 deletions(-) diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index 304c8dc5..f1a5b11a 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -163,29 +163,21 @@ paths: description: Limit the number of records to be returned schema: type: integer - - name: filter_domain + - name: search in: query - description: Filter by domain name + description: Filter by domain name or client IP schema: type: string - - name: filter_client - in: query - description: Filter by client - schema: - type: string - - name: filter_question_type - in: query - description: Filter by question type - schema: - type: string - - name: filter_response_status + - name: response_status in: query description: Filter by response status schema: type: string enum: - - null - - filtered + - "" + - blocked + - whitelisted + - processed responses: "200": description: OK @@ -1421,6 +1413,9 @@ components: description: Answer from upstream server (optional) items: $ref: "#/components/schemas/DnsAnswer" + upstream: + type: string + description: Upstream URL starting with tcp://, tls://, https://, or with an IP address answer_dnssec: type: boolean client: From 0904eeffa8ec75fb7342dae3ec5e0b11a8a7df1d Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Fri, 29 May 2020 11:15:22 +0300 Subject: [PATCH 03/38] + client_proto --- AGHTechDoc.md | 2 ++ dnsforward/stats.go | 5 +++++ querylog/decode.go | 3 +++ querylog/json.go | 9 +++++---- querylog/qlog.go | 9 ++++++--- querylog/querylog.go | 15 ++++++++------- 6 files changed, 29 insertions(+), 14 deletions(-) diff --git a/AGHTechDoc.md b/AGHTechDoc.md index ee9e7ee8..e5f120d7 100644 --- a/AGHTechDoc.md +++ b/AGHTechDoc.md @@ -1200,6 +1200,7 @@ When a new DNS request is received and processed, we store information about thi "QH":"...", // target host name without the last dot "QT":"...", // question type "QC":"...", // question class + "CP":"" | "doh", // client connection protocol "Answer":"base64 data", "OrigAnswer":"base64 data", "Result":{ @@ -1275,6 +1276,7 @@ Response: "upstream":"...", // Upstream URL starting with tcp://, tls://, https://, or with an IP address "answer_dnssec": true, "client":"127.0.0.1", + "client_proto": "" (plain) | "doh", "elapsedMs":"0.098403", "filterId":1, "question":{ diff --git a/dnsforward/stats.go b/dnsforward/stats.go index e9591abc..3f3ee10c 100644 --- a/dnsforward/stats.go +++ b/dnsforward/stats.go @@ -39,6 +39,11 @@ func processQueryLogsAndStats(ctx *dnsContext) int { Elapsed: elapsed, ClientIP: getIP(d.Addr), } + + if d.HTTPRequest != nil { + p.ClientProto = "doh" + } + if d.Upstream != nil { p.Upstream = d.Upstream.Address() } diff --git a/querylog/decode.go b/querylog/decode.go index 3f381140..fc3f84eb 100644 --- a/querylog/decode.go +++ b/querylog/decode.go @@ -37,6 +37,9 @@ func decodeLogEntry(ent *logEntry, str string) { case "QC": ent.QClass = v + case "CP": + ent.ClientProto = v + case "Answer": ent.Answer, err = base64.StdEncoding.DecodeString(v) case "OrigAnswer": diff --git a/querylog/json.go b/querylog/json.go index cc7e6c39..a1a481f0 100644 --- a/querylog/json.go +++ b/querylog/json.go @@ -63,10 +63,11 @@ func (l *queryLog) logEntryToJSONEntry(entry *logEntry) map[string]interface{} { } jsonEntry := map[string]interface{}{ - "reason": entry.Result.Reason.String(), - "elapsedMs": strconv.FormatFloat(entry.Elapsed.Seconds()*1000, 'f', -1, 64), - "time": entry.Time.Format(time.RFC3339Nano), - "client": l.getClientIP(entry.IP), + "reason": entry.Result.Reason.String(), + "elapsedMs": strconv.FormatFloat(entry.Elapsed.Seconds()*1000, 'f', -1, 64), + "time": entry.Time.Format(time.RFC3339Nano), + "client": l.getClientIP(entry.IP), + "client_proto": entry.ClientProto, } jsonEntry["question"] = map[string]interface{}{ "host": entry.QHost, diff --git a/querylog/qlog.go b/querylog/qlog.go index 27bcc01e..a5780ef1 100644 --- a/querylog/qlog.go +++ b/querylog/qlog.go @@ -38,6 +38,8 @@ type logEntry struct { QType string `json:"QT"` QClass string `json:"QC"` + ClientProto string `json:"CP"` // "" or "doh" + Answer []byte `json:",omitempty"` // sometimes empty answers happen like binerdunt.top or rev2.globalrootservers.net OrigAnswer []byte `json:",omitempty"` @@ -119,9 +121,10 @@ func (l *queryLog) Add(params AddParams) { IP: l.getClientIP(params.ClientIP.String()), Time: now, - Result: *params.Result, - Elapsed: params.Elapsed, - Upstream: params.Upstream, + Result: *params.Result, + Elapsed: params.Elapsed, + Upstream: params.Upstream, + ClientProto: params.ClientProto, } q := params.Question.Question[0] entry.QHost = strings.ToLower(q.Name[:len(q.Name)-1]) // remove the last dot diff --git a/querylog/querylog.go b/querylog/querylog.go index 2fa7ac9d..5431ef1e 100644 --- a/querylog/querylog.go +++ b/querylog/querylog.go @@ -41,13 +41,14 @@ type Config struct { // AddParams - parameters for Add() type AddParams struct { - Question *dns.Msg - Answer *dns.Msg // The response we sent to the client (optional) - OrigAnswer *dns.Msg // The response from an upstream server (optional) - Result *dnsfilter.Result // Filtering result (optional) - Elapsed time.Duration // Time spent for processing the request - ClientIP net.IP - Upstream string + Question *dns.Msg + Answer *dns.Msg // The response we sent to the client (optional) + OrigAnswer *dns.Msg // The response from an upstream server (optional) + Result *dnsfilter.Result // Filtering result (optional) + Elapsed time.Duration // Time spent for processing the request + ClientIP net.IP + Upstream string // Upstream server URL + ClientProto string // Protocol for the client connection: "" (plain), "doh" } // New - create a new instance of the query log From d971bb9957a6ec28a61cfbfc5fa5111fec71efa6 Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Fri, 29 May 2020 11:15:31 +0300 Subject: [PATCH 04/38] * minor --- dnsforward/dnsforward_http.go | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/dnsforward/dnsforward_http.go b/dnsforward/dnsforward_http.go index c2c94061..5f916a3f 100644 --- a/dnsforward/dnsforward_http.go +++ b/dnsforward/dnsforward_http.go @@ -385,6 +385,11 @@ func checkDNS(input string, bootstrap []string) error { return nil } +// Control flow: +// web +// -> dnsforward.handleDOH -> dnsforward.ServeHTTP +// -> proxy.ServeHTTP -> proxy.handleDNSRequest +// -> dnsforward.handleDNSRequest func (s *Server) handleDOH(w http.ResponseWriter, r *http.Request) { if !s.conf.TLSAllowUnencryptedDOH && r.TLS == nil { httpError(r, w, http.StatusNotFound, "Not Found") From 78648649fe2e2e944d87e8e25db0c0dcc4e15c7e Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Fri, 29 May 2020 11:19:31 +0300 Subject: [PATCH 05/38] openapi --- openapi/openapi.yaml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index f1a5b11a..94eb6717 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -1421,6 +1421,8 @@ components: client: type: string example: 192.168.0.1 + client_proto: + type: string elapsedMs: type: string example: "54.023928" From bccb9393464cb6ac897bb0e34e21c340dcf54a87 Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Fri, 29 May 2020 11:46:37 +0300 Subject: [PATCH 06/38] + "dot" --- AGHTechDoc.md | 2 +- dnsforward/stats.go | 4 +++- openapi/openapi.yaml | 5 ++++- querylog/querylog.go | 2 +- 4 files changed, 9 insertions(+), 4 deletions(-) diff --git a/AGHTechDoc.md b/AGHTechDoc.md index e5f120d7..cc20d60a 100644 --- a/AGHTechDoc.md +++ b/AGHTechDoc.md @@ -1276,7 +1276,7 @@ Response: "upstream":"...", // Upstream URL starting with tcp://, tls://, https://, or with an IP address "answer_dnssec": true, "client":"127.0.0.1", - "client_proto": "" (plain) | "doh", + "client_proto": "" (plain) | "doh" | "dot", "elapsedMs":"0.098403", "filterId":1, "question":{ diff --git a/dnsforward/stats.go b/dnsforward/stats.go index 3f3ee10c..231ead78 100644 --- a/dnsforward/stats.go +++ b/dnsforward/stats.go @@ -40,8 +40,10 @@ func processQueryLogsAndStats(ctx *dnsContext) int { ClientIP: getIP(d.Addr), } - if d.HTTPRequest != nil { + if d.Proto == "https" { p.ClientProto = "doh" + } else if d.Proto == "tls" { + p.ClientProto = "dot" } if d.Upstream != nil { diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index 94eb6717..858ae735 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -1422,7 +1422,10 @@ components: type: string example: 192.168.0.1 client_proto: - type: string + enum: + - dot + - doh + - "" elapsedMs: type: string example: "54.023928" diff --git a/querylog/querylog.go b/querylog/querylog.go index 5431ef1e..7f6b4c87 100644 --- a/querylog/querylog.go +++ b/querylog/querylog.go @@ -48,7 +48,7 @@ type AddParams struct { Elapsed time.Duration // Time spent for processing the request ClientIP net.IP Upstream string // Upstream server URL - ClientProto string // Protocol for the client connection: "" (plain), "doh" + ClientProto string // Protocol for the client connection: "" (plain), "doh", "dot" } // New - create a new instance of the query log From 6a0194c7a184b7f4b10b71d9b531efb59056c548 Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Thu, 11 Jun 2020 15:39:54 +0300 Subject: [PATCH 07/38] fix whois test --- home/whois_test.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/home/whois_test.go b/home/whois_test.go index 75af9f14..da93426f 100644 --- a/home/whois_test.go +++ b/home/whois_test.go @@ -27,9 +27,9 @@ func TestWhois(t *testing.T) { w := Whois{timeoutMsec: 5000} resp, err := w.queryAll("8.8.8.8") - assert.True(t, err == nil) + assert.Nil(t, err) m := whoisParse(resp) - assert.True(t, m["orgname"] == "Google LLC") - assert.True(t, m["country"] == "US") - assert.True(t, m["city"] == "Mountain View") + assert.Equal(t, "Google LLC", m["orgname"]) + assert.Equal(t, "US", m["country"]) + assert.Equal(t, "Mountain View", m["city"]) } From b6052a4cd1c11f5f34db23781138eb7b6cb710f7 Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Tue, 16 Jun 2020 11:14:04 +0300 Subject: [PATCH 08/38] doc --- AGHTechDoc.md | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) diff --git a/AGHTechDoc.md b/AGHTechDoc.md index cc20d60a..b2f4ab73 100644 --- a/AGHTechDoc.md +++ b/AGHTechDoc.md @@ -1236,7 +1236,7 @@ Request: GET /control/querylog ?older_than=2006-01-02T15:04:05.999999999Z07:00 &search=... - &response_status=""|blocked|whitelisted|processed + &response_status="..." `older_than` setting is used for paging. UI uses an empty value for `older_than` on the first request and gets the latest log entries. To get the older entries, UI sets `older_than` to the `oldest` value from the server's response. @@ -1248,9 +1248,15 @@ The server matches substrings by default: e.g. `adguard.com` matches `www.adguar Strict matching can be enabled by enclosing the value in double quotes: e.g. `"adguard.com"` matches `adguard.com` but doesn't match `www.adguard.com`. `response_status`: -* blocked: only blocked entries -* whitelisted: only white-listed entries -* processed: all not blocked, not white-listed entries +* all +* filtered - all kinds of filtering +* blocked - blocked or blocked service +* blocked_safebrowsing - blocked by safebrowsing +* blocked_parental - blocked by parental control +* whitelisted - whitelisted +* rewritten - all kinds of rewrites +* safe_search - enforced safe search +* processed - not blocked, not white-listed entries Response: From 15e714350cf7dfa3ed39ff2a02a083fa1f4fa46d Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Tue, 16 Jun 2020 11:47:26 +0300 Subject: [PATCH 09/38] fix search by "whitelisted", "rewritten" --- querylog/search_criteria.go | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/querylog/search_criteria.go b/querylog/search_criteria.go index bc2aa435..3c1ee0de 100644 --- a/querylog/search_criteria.go +++ b/querylog/search_criteria.go @@ -101,7 +101,10 @@ func (c *searchCriteria) match(entry *logEntry) bool { case filteringStatusAll: return true case filteringStatusFiltered: - return res.IsFiltered + return res.IsFiltered || + res.Reason == dnsfilter.NotFilteredWhiteList || + res.Reason == dnsfilter.ReasonRewrite || + res.Reason == dnsfilter.RewriteEtcHosts case filteringStatusBlocked: return res.IsFiltered && (res.Reason == dnsfilter.FilteredBlackList || @@ -111,11 +114,10 @@ func (c *searchCriteria) match(entry *logEntry) bool { case filteringStatusBlockedSafebrowsing: return res.IsFiltered && res.Reason == dnsfilter.FilteredSafeBrowsing case filteringStatusWhitelisted: - return res.IsFiltered && res.Reason == dnsfilter.NotFilteredWhiteList + return res.Reason == dnsfilter.NotFilteredWhiteList case filteringStatusRewritten: - return res.IsFiltered && - (res.Reason == dnsfilter.ReasonRewrite || - res.Reason == dnsfilter.RewriteEtcHosts) + return (res.Reason == dnsfilter.ReasonRewrite || + res.Reason == dnsfilter.RewriteEtcHosts) case filteringStatusSafeSearch: return res.IsFiltered && res.Reason == dnsfilter.FilteredSafeSearch From bbc4eda39e7bda7f2f476aab75e16ccd4e91c01b Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Tue, 16 Jun 2020 12:10:17 +0300 Subject: [PATCH 10/38] If there are no more older entries, `"oldest":""` is returned. --- AGHTechDoc.md | 2 ++ querylog/querylog_search.go | 4 +++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/AGHTechDoc.md b/AGHTechDoc.md index b2f4ab73..ad9854d3 100644 --- a/AGHTechDoc.md +++ b/AGHTechDoc.md @@ -1302,6 +1302,8 @@ Response: The most recent entries are at the top of list. +If there are no more older entries, `"oldest":""` is returned. + ### API: Set querylog parameters diff --git a/querylog/querylog_search.go b/querylog/querylog_search.go index eda1f92d..afa8afc2 100644 --- a/querylog/querylog_search.go +++ b/querylog/querylog_search.go @@ -129,7 +129,9 @@ func (l *queryLog) searchFiles(params *searchParams) ([]*logEntry, time.Time, in } } - oldest = time.Unix(0, oldestNano) + if oldestNano != 0 { + oldest = time.Unix(0, oldestNano) + } return entries, oldest, total } From 59c4a2886a97143e3a36912ec895dc1a06be88cc Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Tue, 16 Jun 2020 12:12:32 +0300 Subject: [PATCH 11/38] openapi --- openapi/openapi.yaml | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index 858ae735..13e330eb 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -174,9 +174,14 @@ paths: schema: type: string enum: - - "" + - all + - filtered - blocked + - blocked_safebrowsing + - blocked_parental - whitelisted + - rewritten + - safe_search - processed responses: "200": From 4870da7f94e040fea63f2ff99bf1b79ee5da457e Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Wed, 17 Jun 2020 19:36:35 +0300 Subject: [PATCH 12/38] * auto-hosts: support '#' comments after ip and hosts Close #1807 Squashed commit of the following: commit 9d3e2809df056354bb6195abf8106616c1e214b1 Author: Simon Zolin Date: Wed Jun 17 19:23:15 2020 +0300 improve commit 9b8c7104560c9c80f848f15818d49a065a38e498 Author: Simon Zolin Date: Wed Jun 17 11:07:56 2020 +0300 * auto-hosts: support '#' comments after ip and hosts --- util/auto_hosts.go | 10 ++++++++++ util/auto_hosts_test.go | 8 ++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/util/auto_hosts.go b/util/auto_hosts.go index a980f5a2..f36ee1e7 100644 --- a/util/auto_hosts.go +++ b/util/auto_hosts.go @@ -172,8 +172,18 @@ func (a *AutoHosts) load(table map[string][]net.IP, tableRev map[string]string, if len(host) == 0 { break } + sharp := strings.IndexByte(host, '#') + if sharp == 0 { + break // skip the rest of the line after # + } else if sharp > 0 { + host = host[:sharp] + } + a.updateTable(table, host, ipAddr) a.updateTableRev(tableRev, host, ipAddr) + if sharp >= 0 { + break // skip the rest of the line after # + } } } } diff --git a/util/auto_hosts_test.go b/util/auto_hosts_test.go index 17055e50..322e7e9c 100644 --- a/util/auto_hosts_test.go +++ b/util/auto_hosts_test.go @@ -29,8 +29,8 @@ func TestAutoHostsResolution(t *testing.T) { defer func() { _ = os.Remove(f.Name()) }() defer f.Close() - _, _ = f.WriteString(" 127.0.0.1 host localhost \n") - _, _ = f.WriteString(" ::1 localhost \n") + _, _ = f.WriteString(" 127.0.0.1 host localhost # comment \n") + _, _ = f.WriteString(" ::1 localhost#comment \n") ah.Init(f.Name()) @@ -47,6 +47,10 @@ func TestAutoHostsResolution(t *testing.T) { ips = ah.Process("newhost", dns.TypeA) assert.Nil(t, ips) + // Unknown host (comment) + ips = ah.Process("comment", dns.TypeA) + assert.Nil(t, ips) + // Test hosts file table := ah.List() name, ok := table["127.0.0.1"] From e39fe1b913839bb6d72c09672145ef187332fd27 Mon Sep 17 00:00:00 2001 From: Artem Baskal Date: Thu, 18 Jun 2020 00:36:19 +0300 Subject: [PATCH 13/38] Merge: fix #1421 Full rework of the query log Squashed commit of the following: commit e8a72eb223551f17e637136713dae03accf8ab9e Author: Andrey Meshkov Date: Thu Jun 18 00:31:53 2020 +0300 fix race in whois test commit 801d28197f888fa21f83c9a0b49e3c9472c08513 Merge: 9d9787fd b1c951fb Author: Andrey Meshkov Date: Thu Jun 18 00:28:13 2020 +0300 Merge branch 'master' into feature/1421 commit 9d9787fd79b17f76c7baed52c12ac462fd00a5e4 Merge: 4ce337ca 08e238ab Author: Andrey Meshkov Date: Thu Jun 18 00:27:32 2020 +0300 Merge commit 4ce337ca7aec163edf87a038bb25fb44e64f8613 Author: Andrey Meshkov Date: Thu Jun 18 00:22:49 2020 +0300 -(home): fix whois test commit 08e238ab0e723b1e354f58245e9a8d5017b392c9 Author: ArtemBaskal Date: Thu Jun 18 00:13:41 2020 +0300 Add comments commit 5f108065952bcc25dce1c2eee3f9401d2641a6e9 Author: ArtemBaskal Date: Wed Jun 17 23:47:50 2020 +0300 Make tooltip position absolute for touch commit 4c30a583165e5d007d4b01b657de8751a7bd8c7b Author: ArtemBaskal Date: Wed Jun 17 20:39:44 2020 +0300 Prevent scroll hide for touch devices commit 62da97931f5921613762614717c62c77ddb6b8db Author: ArtemBaskal Date: Wed Jun 17 20:06:24 2020 +0300 Review changes: ipad tooltip commit 12dddcca8caca51c157b5d25dfa3ca03ba7f0c06 Author: ArtemBaskal Date: Wed Jun 17 16:59:16 2020 +0300 Add close tooltip event for ipad commit 62191e41d5bf67317f9f1dc6c6af08cbabb4bf90 Author: ArtemBaskal Date: Wed Jun 17 16:39:40 2020 +0300 Add success toast on logs refresh commit 2ebdd6a8124269d737c8060c3247aaf35d85cb8b Author: ArtemBaskal Date: Wed Jun 17 16:01:37 2020 +0300 Fix pagination commit 5820c92bacd93d05a3d66d42ee95f099e1c5d9e9 Author: ArtemBaskal Date: Wed Jun 17 11:31:15 2020 +0300 Revert "Render table in chunks" This reverts commit cdfcd849ccddc1bc35591edac7904129431470c9. commit cdfcd849ccddc1bc35591edac7904129431470c9 Author: ArtemBaskal Date: Tue Jun 16 18:42:18 2020 +0300 Render table in chunks commit cc8c5e64274bf6e806e2e8a4bf305af745c3ed2a Author: ArtemBaskal Date: Tue Jun 16 17:35:24 2020 +0300 Add pagination button hover effect commit f7e134091a1556784a5fea9d83c50353536126ef Author: ArtemBaskal Date: Tue Jun 16 16:28:00 2020 +0300 Make loader position absolute commit a7b887b57d903f1f7ac967b861b5cc677728efc4 Author: ArtemBaskal Date: Tue Jun 16 15:42:20 2020 +0300 Ignore clients find without params commit ecb322fefd4a161d79f28d17fe27827ee91701e4 Author: ArtemBaskal Date: Tue Jun 16 15:30:48 2020 +0300 Styles changes commit 9323ce3938bf04e1290eade09201ba0790a250c0 Author: ArtemBaskal Date: Tue Jun 16 14:32:23 2020 +0300 Review styles changes commit e0faa04ba3643f01b2ca99524cdd52b0731725c7 Merge: 98576823 15e71435 Author: ArtemBaskal Date: Tue Jun 16 12:08:45 2020 +0300 Merge branch '1421-new-qlog-v2' into feature/1421 commit 9857682371e8d9a3a91933cfb58a26b3470675d9 Author: ArtemBaskal Date: Mon Jun 15 18:32:02 2020 +0300 Fix response cell ... and 88 more commits --- AGHTechDoc.md | 2 +- client/package-lock.json | 16 + client/package.json | 2 + client/src/__locales/bg.json | 12 +- client/src/__locales/cs.json | 45 +- client/src/__locales/da.json | 45 +- client/src/__locales/de.json | 42 +- client/src/__locales/en.json | 46 +- client/src/__locales/es.json | 57 +- client/src/__locales/fa.json | 39 +- client/src/__locales/fr.json | 47 +- client/src/__locales/hr.json | 43 +- client/src/__locales/id.json | 15 +- client/src/__locales/it.json | 45 +- client/src/__locales/ja.json | 49 +- client/src/__locales/ko.json | 39 +- client/src/__locales/nl.json | 47 +- client/src/__locales/no.json | 21 +- client/src/__locales/pl.json | 42 +- client/src/__locales/pt-br.json | 41 +- client/src/__locales/pt-pt.json | 15 +- client/src/__locales/ro.json | 141 ++-- client/src/__locales/ru.json | 17 +- client/src/__locales/sk.json | 43 +- client/src/__locales/sl.json | 45 +- client/src/__locales/sr-cs.json | 12 +- client/src/__locales/sv.json | 14 +- client/src/__locales/th.json | 8 +- client/src/__locales/tr.json | 15 +- client/src/__locales/vi.json | 24 +- client/src/__locales/zh-cn.json | 14 +- client/src/__locales/zh-tw.json | 49 +- client/src/actions/access.js | 10 +- client/src/actions/queryLogs.js | 16 +- client/src/components/App/index.css | 26 +- client/src/components/App/index.js | 2 +- client/src/components/Dashboard/Clients.js | 6 +- client/src/components/Dashboard/index.js | 4 +- .../src/components/Filters/Rewrites/Table.js | 24 +- client/src/components/Filters/Table.js | 23 +- .../components/Logs/Cells/getClientCell.js | 106 +++ .../src/components/Logs/Cells/getDateCell.js | 28 + .../components/Logs/Cells/getDomainCell.js | 121 ++++ .../components/Logs/Cells/getHintElement.js | 76 +++ .../components/Logs/Cells/getResponseCell.js | 120 ++++ client/src/components/Logs/Disabled.js | 30 + client/src/components/Logs/Filters/Form.js | 151 ++--- client/src/components/Logs/Filters/index.js | 74 +- client/src/components/Logs/Logs.css | 421 +++++++++++- client/src/components/Logs/Table.js | 399 +++++++++++ .../components/Logs/Tooltip/CustomTooltip.js | 44 ++ .../components/Logs/Tooltip/ReactTooltip.css | 129 ++++ client/src/components/Logs/Tooltip/index.js | 48 ++ client/src/components/Logs/chevron-down.svg | 1 + client/src/components/Logs/index.js | 634 ++++++------------ .../Settings/Clients/AutoClients.js | 20 +- .../Settings/Clients/ClientsTable.js | 28 +- .../src/components/Settings/Clients/Form.js | 2 +- .../components/Settings/Clients/whoisCell.js | 8 +- client/src/components/Settings/Dhcp/Leases.js | 8 +- .../Settings/Dhcp/StaticLeases/index.js | 10 +- client/src/components/Settings/Settings.css | 5 + client/src/components/Toasts/Toast.css | 7 + client/src/components/Toasts/Toast.js | 33 +- client/src/components/ui/CellWrap.js | 2 +- client/src/components/ui/Icons.css | 18 +- client/src/components/ui/Icons.js | 324 ++++++--- client/src/components/ui/Loading.js | 2 +- client/src/components/ui/PageTitle.css | 23 +- client/src/components/ui/PageTitle.js | 10 +- client/src/components/ui/ReactTable.css | 19 +- client/src/components/ui/Tooltip.css | 2 - client/src/components/ui/Tooltip.js | 5 +- client/src/containers/Logs.js | 18 +- client/src/helpers/constants.js | 146 +++- client/src/helpers/form.js | 4 +- client/src/helpers/formatClientCell.js | 41 +- client/src/helpers/helpers.js | 60 +- client/src/helpers/trackers/trackers.js | 99 +-- client/src/reducers/queryLogs.js | 12 +- home/whois_test.go | 11 +- 81 files changed, 3415 insertions(+), 1087 deletions(-) create mode 100644 client/src/components/Logs/Cells/getClientCell.js create mode 100644 client/src/components/Logs/Cells/getDateCell.js create mode 100644 client/src/components/Logs/Cells/getDomainCell.js create mode 100644 client/src/components/Logs/Cells/getHintElement.js create mode 100644 client/src/components/Logs/Cells/getResponseCell.js create mode 100644 client/src/components/Logs/Disabled.js create mode 100644 client/src/components/Logs/Table.js create mode 100644 client/src/components/Logs/Tooltip/CustomTooltip.js create mode 100644 client/src/components/Logs/Tooltip/ReactTooltip.css create mode 100644 client/src/components/Logs/Tooltip/index.js create mode 100644 client/src/components/Logs/chevron-down.svg diff --git a/AGHTechDoc.md b/AGHTechDoc.md index 41a36d2e..51dc3442 100644 --- a/AGHTechDoc.md +++ b/AGHTechDoc.md @@ -1236,7 +1236,7 @@ Request: &search=... &response_status="..." -`older_than` setting is used for paging. UI uses an empty value for `older_than` on the first request and gets the latest log entries. To get the older entries, UI sets `older_than` to the `oldest` value from the server's response. +`older_than` setting is used for paging. UI uses an empty value for `older_than` on the first request and gets the latest log entries. To get the older entries, UI sets `older_than` to the `oldest` value from the server's response. If search settings are set, server returns only entries that match the specified request. diff --git a/client/package-lock.json b/client/package-lock.json index 7b98442f..a7055f32 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -12427,6 +12427,22 @@ "react-is": "^16.8.1" } }, + "react-tooltip": { + "version": "4.2.6", + "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-4.2.6.tgz", + "integrity": "sha512-KX/zCsPFCI8RuulzBX86U+Ur7FvgGNRBdb7dUu0ndo8Urinn48nANq9wfq4ABlehweQjPzLl7XdNAtLKza+I3w==", + "requires": { + "prop-types": "^15.7.2", + "uuid": "^7.0.3" + }, + "dependencies": { + "uuid": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", + "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==" + } + } + }, "react-transition-group": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.1.tgz", diff --git a/client/package.json b/client/package.json index dbfab086..9ff53f0f 100644 --- a/client/package.json +++ b/client/package.json @@ -7,6 +7,7 @@ "watch": "cross-env BUILD_ENV=dev webpack --config webpack.dev.js --watch", "build-prod": "cross-env BUILD_ENV=prod webpack --config webpack.prod.js", "lint": "eslint src", + "lint:fix": "eslint src --fix", "test": "jest", "test:watch": "jest --watch" }, @@ -32,6 +33,7 @@ "react-router-hash-link": "^1.2.2", "react-select": "^3.1.0", "react-table": "^6.11.4", + "react-tooltip": "^4.2.6", "react-transition-group": "^4.4.1", "redux": "^4.0.5", "redux-actions": "^2.6.5", diff --git a/client/src/__locales/bg.json b/client/src/__locales/bg.json index 9a9857ef..fa930888 100644 --- a/client/src/__locales/bg.json +++ b/client/src/__locales/bg.json @@ -28,6 +28,7 @@ "dhcp_table_hostname": "Име на устройство", "dhcp_table_expires": "История", "dhcp_warning": "Ако искате да използвате вградения DHCP сървър, трябва да няма друг активен DHCP в мрежата Ви!", + "city": "Град", "back": "Назад", "dashboard": "Табло", "settings": "Настройки", @@ -35,7 +36,7 @@ "query_log": "История на заявките", "faq": "ЧЗВ", "version": "версия", - "address": "адрес", + "address": "Адрес", "on": "ВКЛЮЧЕНО", "off": "ИЗКЛЮЧЕНО", "copyright": "Авторско право", @@ -106,6 +107,7 @@ "example_comment": "! Това е коментар", "example_comment_meaning": "пример за коментар", "example_comment_hash": "# Това е също коментар", + "example_regex_meaning": "блокирай достъп до домейни който съвпадат със следното", "example_upstream_regular": "класически DNS (UDP протокол)", "example_upstream_dot": "криптиран DNS-върху-TLS", "example_upstream_doh": "криптиран DNS-върху-HTTPS", @@ -114,9 +116,10 @@ "updated_upstream_dns_toast": "Глобалните DNS сървъри са обновени", "dns_test_ok_toast": "Въведените DNS сървъри работят коректно", "dns_test_not_ok_toast": "Сървър \"{{key}}\": не работи, моля проверете дали е въведен коректно", - "unblock_btn": "Отблокирай", - "block_btn": "Блокирай", + "unblock": "Отблокирай", + "block": "Блокирай", "time_table_header": "Време", + "date": "Дата", "domain_name_table_header": "Име на домейн", "type_table_header": "Тип", "response_table_header": "Отговор", @@ -226,5 +229,6 @@ "form_error_equal": "Не трябва да съвпада", "form_error_password": "Паролата не съвпада", "reset_settings": "Изтрий всички настройки", - "update_announcement": "Има нова AdGuard Home {{version}}! <0>Цъкни тук за повече информация." + "update_announcement": "Има нова AdGuard Home {{version}}! <0>Цъкни тук за повече информация.", + "show_blocked_responses": "Блокирано" } \ No newline at end of file diff --git a/client/src/__locales/cs.json b/client/src/__locales/cs.json index e872d7b7..dd5488e6 100644 --- a/client/src/__locales/cs.json +++ b/client/src/__locales/cs.json @@ -37,6 +37,7 @@ "dhcp_interface_select": "Vybrat rozhraní DHCP", "dhcp_hardware_address": "Hardwarová adresa", "dhcp_ip_addresses": "IP adresa", + "ip": "IP adresa", "dhcp_table_hostname": "Název hostitele", "dhcp_table_expires": "Vyprší", "dhcp_warning": "Pokud chcete server DHCP povolit, ujistěte se, že ve Vaší síti není žádný aktivní server DHCP. V opačném případě může dojít k přerušení internetu pro připojená zařízení!", @@ -49,17 +50,26 @@ "dhcp_static_leases_not_found": "Nebyly nalezeny žádné statické pronájmy DHCP", "dhcp_add_static_lease": "Přidat statický pronájem", "dhcp_reset": "Opravdu chcete resetovat konfiguraci DHCP?", + "country": "Země", + "city": "Město", "delete_confirm": "Opravdu chcete odstranit \"{{key}}\"?", "form_enter_hostname": "Zadejte název hostitele", "error_details": "Podrobnosti chyby", + "response_details": "Detail odpovědi", + "request_details": "Detail požadavku", + "client_details": "Detaily klienta", + "details": "Detaily", "back": "Zpět", "dashboard": "Hlavní panel", "settings": "Nastavení", "filters": "Filtry", + "filter": "Filtr", "query_log": "Protokol dotazů", + "empty_log": "Záznam dotazů je prázdný", "faq": "FAQ", "version": "Verze", - "address": "adresa", + "address": "Adresa", + "protocol": "Protokol", "on": "ZAPNUTO", "off": "VYPNUTO", "copyright": "Autorská práva", @@ -113,7 +123,7 @@ "custom_filtering_rules": "Vlastní pravidla filtrování", "encryption_settings": "Nastavení šifrování", "dhcp_settings": "Nastavení DHCP", - "upstream_dns": "Upstream DNS servery", + "upstream_dns": "Odchozí DNS servery", "upstream_dns_hint": "Pokud toto pole ponecháte prázdné, AdGuard Home použije Quad9 jako upstream.", "test_upstream_btn": "Test upstreamů", "upstreams": "Odesláno", @@ -132,8 +142,10 @@ "rules_count_table_header": "Počet pravidel", "last_time_updated_table_header": "Čas poslední aktualizace", "actions_table_header": "Akce", + "request_table_header": "Požadavek", "edit_table_action": "Upravit", "delete_table_action": "Vymazat", + "elapsed": "Uplynulý čas", "filters_and_hosts_hint": "AdGuard Home zná základní pravidla blokování reklam a syntaxe hostsitelských souborů.", "no_blocklist_added": "Nebyl přidán žádný seznam blokovaných", "no_whitelist_added": "Nebyl přidán žádný seznam povolených", @@ -170,10 +182,12 @@ "updated_upstream_dns_toast": "Aktualizované upstream DNS servery", "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", - "unblock_btn": "Odblokovat", - "block_btn": "Blokovat", + "unblock": "Odblokovat", + "block": "Blokovat", "time_table_header": "Čas", + "date": "Datum", "domain_name_table_header": "Název domény", + "domain_or_client": "Doména nebo klient", "type_table_header": "Typ", "response_table_header": "Odezva", "client_table_header": "Klient", @@ -211,6 +225,7 @@ "custom_ip": "Vlastní IP", "blocking_ipv4": "Blokování IPv4", "blocking_ipv6": "Blokování IPv6", + "plain_dns": "Čisté DNS", "form_enter_rate_limit": "Zadejte rychlostní limit", "rate_limit": "Rychlostní limit", "edns_enable": "Povolit klientskou podsíť EDNS", @@ -229,6 +244,7 @@ "rule_label": "Pravidlo", "list_label": "Seznam", "unknown_filter": "Neznámý filtr {{filterId}}", + "known_tracker": "Známý slídič", "install_welcome_title": "Vítejte v AdGuard Home!", "install_welcome_desc": "AdGuard Home je síťový DNS server pro blokování reklam a slídičů. Jeho cílem je, abyste ovládali celou Vaši síť a všechny Vaše zařízení, přičemž se nevyžaduje použití jakéhokoliv programu na straně klienta.", "install_settings_title": "Administrátorské webové rozhraní", @@ -257,7 +273,7 @@ "install_devices_router_list_1": "Otevřete předvolby pro router. Obvykle k němu můžete přistupovat z prohlížeče prostřednictvím adresy URL (např. http://192.168.0.1/ nebo http://192.168.1.1/). Můžete být vyzváni k zadání hesla. Pokud si ho nepamatujete, můžete heslo resetovat stisknutím tlačítka na samotném routeru. Některé routery vyžadují specifickou aplikaci, která by v takovém případě měla být již nainstalována v počítači/telefonu.", "install_devices_router_list_2": "Vyhledejte nastavení DHCP/DNS. Hledejte zkratku DNS vedle pole, které umožňuje vložit dvě nebo tři sady čísel, každé rozděleno do čtyř skupin s jedním až třemi číslicemi.", "install_devices_router_list_3": "Zadejte adresy Vašeho serveru AdGuard Home.", - "install_devices_router_list_4": "Na některých typech routerů nemůžete nastavit vlastní DNS server. V tomto případě může AdGuard Home pomoct pokud jej nastavíte jako DHCP server. V ostatních případech byste si v manuálu k Vašemu routeru měli zjistit, jak nastavit vlastní DNS servery.", + "install_devices_router_list_4": "Na některých typech routerů nemůžete nastavit vlastní DNS server. V tomto případě může AdGuard Home pomoci, pokud jej nastavíte jako <0>DHCP server. V ostatních případech byste si v manuálu k Vašemu routeru měli zjistit, jak nastavit vlastní DNS servery.", "install_devices_windows_list_1": "Otevřete ovládací panel prostřednictvím nabídky Start nebo vyhledání v systému Windows.", "install_devices_windows_list_2": "Přejděte na kategorii Síť a Internet a poté na Centrum sítí a sdílení.", "install_devices_windows_list_3": "Na levé straně obrazovky najděte možnost Změnit nastavení adaptéru a klepněte na něj.", @@ -346,6 +362,7 @@ "form_enter_id": "Zadejte identifikátor", "form_add_id": "Přidat identifikátor", "form_client_name": "Zadejte název klienta", + "name": "Název", "client_global_settings": "Použít globální nastavení", "client_deleted": "Klient \"{{key}}\" byl úspěšně odstraněn", "client_added": "Klient \"{{key}}\" byl úspěšně přidán", @@ -445,6 +462,7 @@ "location": "Umístění", "orgname": "Název organizace", "netname": "Název sítě", + "network": "Síť", "descr": "Popis", "whois": "Whois", "filtering_rules_learn_more": "<0>Další informace o vytváření vlastních seznamů hostitelů.", @@ -456,7 +474,7 @@ "disable_ipv6": "Zakázat IPv6", "disable_ipv6_desc": "Pokud je tato funkce povolena, budou všechny dotazy DNS pro adresy IPv6 (typ AAAA) zrušeny.", "fastest_addr": "Nejrychlejší IP adresa", - "fastest_addr_desc": "Dotazovat všechny DNS servery a vrátit nejrychlejší IP adresu ze všech odpovědí", + "fastest_addr_desc": "Dotazovat všechny DNS servery a vrátit nejrychlejší IP adresu ze všech odpovědí. To zpomalí dotazy DNS, protože musíme čekat na odpovědi ze všech serverů DNS, ale celková konektivita se zlepší.", "autofix_warning_text": "Pokud kliknete na „Opravit“, AdGuard Home nakonfiguruje váš systém tak, aby používal DNS server AdGuard Home.", "autofix_warning_list": "Jsou prováděny následující úlohy: <0>Deaktivace systému DNSStubListener <0>Nastavení adresy serveru DNS na 127.0.0.1 <0>Nahrazení cíle symbolického odkazu z /etc/resolv.conf do /run/systemd/resolve/resolv.conf <0>Zastavení služby DNSStubListener (znovu načtení služby systemd-resolved)", "autofix_warning_result": "Výsledkem je, že všechny požadavky DNS z vašeho systému jsou ve výchozím nastavení zpracovány službou AdGuard Home.", @@ -489,5 +507,18 @@ "list_updated": "Byl aktualizován {{count}} seznam", "list_updated_plural": "Aktualizované seznamy: {{count}}", "dnssec_enable": "Zapnout DNSSEC", - "dnssec_enable_desc": "Nastavte příznak DNSSEC v následujících DNS dotazech a zkontrolujte výsledek (je potřebný překladač se zapnutým DNSSEC)" + "dnssec_enable_desc": "Nastavte příznak DNSSEC v následujících DNS dotazech a zkontrolujte výsledek (je potřebný překladač se zapnutým DNSSEC)", + "validated_with_dnssec": "Ověřeno pomocí DNSSEC", + "show_all_responses": "Všechny odpovědi", + "show_blocked_responses": "Zablokované", + "show_whitelisted_responses": "Povolené", + "blocked_safebrowsing": "Blokované bezpečné prohlížení", + "blocked_adult_websites": "Blokované stránky pro dospělé", + "blocked_threats": "Blokované hrozby", + "allowed": "Povoleno", + "filtered": "Filtrováno", + "rewritten": "Přepsáno", + "safe_search": "Bezpečné vyhledávání", + "blocklist": "Zakázaný", + "milliseconds_abbreviation": "ms" } \ No newline at end of file diff --git a/client/src/__locales/da.json b/client/src/__locales/da.json index ad02e1ea..7f50a4c7 100644 --- a/client/src/__locales/da.json +++ b/client/src/__locales/da.json @@ -3,6 +3,8 @@ "example_upstream_reserved": "Du kan specificere DNS upstream <0>for det(de) specifikke domæne(r)", "upstream_parallel": "Brug parallelle forespørgsler til at fremskynde behandlingen ved samtidig at spørge alle upstream servere", "parallel_requests": "Parallelle forespørgsler", + "load_balancing": "Belastningsfordeling", + "load_balancing_desc": "Forespørg en server ad gangen. AdGuard Home bruger den vægtede tilfældige algoritme til at vælge serveren, så den hurtigste server bliver brugt oftere.", "bootstrap_dns": "Bootstrap DNS-servere", "bootstrap_dns_desc": "Bootstrap DNS-servere bliver brugt til at behandle IP-adresser af de DoH/DoT resolvere, som du angiver som upstream.", "check_dhcp_servers": "Tjek for DHCP-servere", @@ -37,6 +39,7 @@ "dhcp_interface_select": "Vælg DHCP-interface", "dhcp_hardware_address": "Hardware-adresse", "dhcp_ip_addresses": "IP-adresser", + "ip": "IP", "dhcp_table_hostname": "Værtsnavn", "dhcp_table_expires": "Udløber", "dhcp_warning": "Hvis du vil aktivere DHCP-serveren alligevel, skal du sørge for, at der ikke er nogen anden aktiv DHCP-server på dit netværk. Ellers kan det ødelægge internettet for tilsluttede enheder!", @@ -49,17 +52,24 @@ "dhcp_static_leases_not_found": "Ingen DHCP static leases fundet", "dhcp_add_static_lease": "Tilføj static lease", "dhcp_reset": "Er du sikker på, at du vil nulstille DHCP-konfigurationen?", + "country": "Land", "delete_confirm": "Er du sikker på, at du vil slette \"{{key}}\"?", "form_enter_hostname": "Indtast værtsnavn", "error_details": "Fejloplysninger", + "request_details": "Anmod om detaljer", + "client_details": "Klientoplysninger", + "details": "Detaljer", "back": "Tilbage", "dashboard": "Kontrolpanel", "settings": "Indstillinger", "filters": "Filtre", + "filter": "Filter", "query_log": "Forespørgselslog", + "empty_log": "Forespørgselsloggen er tom", "faq": "FAQ", "version": "Version", - "address": "adresse", + "address": "Adresse", + "protocol": "Protokol", "on": "TÆNDT", "off": "SLUKKET", "copyright": "Copyright", @@ -132,8 +142,10 @@ "rules_count_table_header": "Antal regler", "last_time_updated_table_header": "Sidst opdateret", "actions_table_header": "Handlinger", + "request_table_header": "Forespørgsel", "edit_table_action": "Rediger", "delete_table_action": "Slet", + "elapsed": "Varighed", "filters_and_hosts_hint": "AdGuard Home forstår de grundlæggende annonceblokeringsregler og værtsfilsyntaks.", "no_blocklist_added": "Ingen blokeringslister tilføjet", "no_whitelist_added": "Ingen lister over tilladte tilføjet", @@ -170,10 +182,12 @@ "updated_upstream_dns_toast": "Opdaterede upstream DNS-servere", "dns_test_ok_toast": "De angivne DNS-servere fungerer korrekt", "dns_test_not_ok_toast": "Server \"{{key}}\": kunne ikke bruges, kontroller venligst at du har skrevet det korrekt", - "unblock_btn": "Fjern blokering", - "block_btn": "Bloker", + "unblock": "Fjern blokering", + "block": "Bloker", "time_table_header": "Tid", + "date": "Dato", "domain_name_table_header": "Domænenavn", + "domain_or_client": "Domæne eller klient", "type_table_header": "Type", "response_table_header": "Svar", "client_table_header": "Klient", @@ -211,6 +225,8 @@ "custom_ip": "Tilpasset IP", "blocking_ipv4": "IPv4-blokering", "blocking_ipv6": "IPv6-blokering", + "dns_over_https": "DNS-over-HTTPS", + "dns_over_tls": "DNS-over-TLS", "form_enter_rate_limit": "Indtast hyppighedsgrænse", "rate_limit": "Hyppighedsgrænse", "edns_enable": "Aktiver EDNS Client Subnet", @@ -229,6 +245,7 @@ "rule_label": "Regel", "list_label": "Liste", "unknown_filter": "Ukendt filter {{filterId}}", + "known_tracker": "Kendt tracker", "install_welcome_title": "Velkommen til AdGuard Home!", "install_welcome_desc": "AdGuard Home er en netværksbaseret annonce-og-tracker blokerende DNS-server. Formålet er at lade dig kontrollere hele dit netværk og alle dine enheder, og det kræver ikke at man bruger klientsoftware.", "install_settings_title": "Administrator Webgrænseflade", @@ -257,7 +274,7 @@ "install_devices_router_list_1": "Åbn præferencerne for din router. Normalt kan du få adgang til den fra din browser via en URL (som http://192.168.0.1/ eller http://192.168.1.1/). Du bliver muligvis bedt om at indtaste adgangskoden. Hvis du ikke kan huske den, kan du ofte nulstille adgangskoden ved at trykke på en knap på selve routeren. Nogle routere kræver et bestemt program, som i det tilfælde allerede skulle være installeret på din computer/telefon.", "install_devices_router_list_2": "Find DHCP/DNS-indstillingerne. Kig efter DNS-bogstaverne ved siden af et felt, der tillader to eller tre sæt tal, hver opdelt i fire grupper med et til tre cifre.", "install_devices_router_list_3": "Indtast dine AdGuard Home serveradresser der.", - "install_devices_router_list_4": "Du kan ikke opsætte en tilpasset DNS-server på nogle typer routere. I dette tilfælde kan det hjælpe, hvis du konfigurerer AdGuard Home som en DHCP-server. Du kan ellers søge efter manualen om, hvordan du tilpasser DNS-servere til din bestemte routermodel.", + "install_devices_router_list_4": "Du kan ikke opsætte en tilpasset DNS-server på nogle typer routere. I dette tilfælde kan det hjælpe, hvis du konfigurerer AdGuard Home som en <0>DHCP-server. Du kan ellers søge efter manualen om, hvordan du tilpasser DNS-servere til din bestemte routermodel.", "install_devices_windows_list_1": "Åbn Kontrolpanel gennem menuen Start eller Windows søgning.", "install_devices_windows_list_2": "Gå til Netværk og internet kategorien og derefter til Netværks- og delingscenter.", "install_devices_windows_list_3": "På venstre side af skærmen finder du Skift adapterindstillinger og klik på den.", @@ -346,6 +363,7 @@ "form_enter_id": "Indtast identifikator", "form_add_id": "Tilføj identifikator", "form_client_name": "Indtast klientnavn", + "name": "Navn", "client_global_settings": "Brug globale indstillinger", "client_deleted": "Klient \"{{key}}\" succesfuldt slettet", "client_added": "Klient \"{{key}}\" succesfuldt tilføjet", @@ -445,6 +463,7 @@ "location": "Placering", "orgname": "Organisationens navn", "netname": "Netværksnavn", + "network": "Netværk", "descr": "Beskrivelse", "whois": "Whois", "filtering_rules_learn_more": "<0>Lær mere om at oprette dine egne værtslister.", @@ -456,7 +475,7 @@ "disable_ipv6": "Deaktiver IPv6", "disable_ipv6_desc": "Hvis denne funktion er aktiveret, slettes alle DNS-forespørgsler til IPv6-adresser (type AAAA).", "fastest_addr": "Hurtigste IP-adresse", - "fastest_addr_desc": "Forespørg alle DNS-servere, og returner den hurtigste IP-adresse blandt alle svar", + "fastest_addr_desc": "Forespørg alle DNS-servere, og returner den hurtigste IP-adresse blandt alle svar. Dette vil gøre DNS-forespørgslerne langsommere, da vi er nødt til at vente på svar fra alle DNS-servere, men forbedrer samlet set forbindelsen.", "autofix_warning_text": "Hvis du klikker på \"Reparer\", vil AdGuardHome konfigurere dit system til at bruge AdGuardHome DNS-server.", "autofix_warning_list": "Den vil udføre disse opgaver: <0>Deaktivering af DNSStubListener systemet <0>Indstille DNS-serveradressen til 127.0.0.1 <0>Erstatte det symbolske linkmål for /etc/resolv.conf til /run/systemd/resolve/resolv.conf <0>Stop DNSStubListener (genindlæs systemd-løst tjeneste)", "autofix_warning_result": "Som et resultat behandles alle DNS-anmodninger fra dit system som standard af AdGuard Home.", @@ -489,5 +508,19 @@ "list_updated": "{{count}} liste opdateret", "list_updated_plural": "{{count}} lister opdateret", "dnssec_enable": "Aktivér DNSSEC", - "dnssec_enable_desc": "Sæt DNSSEC-flag i de udgående DNS-forespørgsler, og kontroller resultatet (DNSSEC-aktiveret resolver er krævet)" + "dnssec_enable_desc": "Sæt DNSSEC-flag i de udgående DNS-forespørgsler, og kontroller resultatet (DNSSEC-aktiveret resolver er krævet)", + "validated_with_dnssec": "Valideret med DNSSEC", + "show_all_responses": "Alle svar", + "show_blocked_responses": "Blokeret", + "show_whitelisted_responses": "Hvidlistet", + "show_processed_responses": "Behandlet", + "blocked_safebrowsing": "Blokeret af Safebrowsing", + "blocked_adult_websites": "Blokerede Websteder for Voksne", + "blocked_threats": "Blokerede Trusler", + "allowed": "Tilladt", + "filtered": "Filtreret", + "rewritten": "Omskrevet", + "safe_search": "Sikker søgning", + "blocklist": "Blokeringsliste", + "milliseconds_abbreviation": "ms" } \ No newline at end of file diff --git a/client/src/__locales/de.json b/client/src/__locales/de.json index 15a1c511..ddf15657 100644 --- a/client/src/__locales/de.json +++ b/client/src/__locales/de.json @@ -3,6 +3,8 @@ "example_upstream_reserved": "Sie können DNS-Upstream <0>für bestimmte Domain(s) angeben", "upstream_parallel": "Parallele Abfragen verwenden, um die Lösung zu beschleunigen, indem Sie alle Upstream-Server gleichzeitig abfragen", "parallel_requests": "Parallele Abfragen", + "load_balancing": "Lastverteilung", + "load_balancing_desc": "Einen Server nach dem anderen abfragen. AdGuard Home verwendet den gewichteten Zufallsalgorithmus, um den Server so auszuwählen, dass der schnellste Server häufiger verwendet wird.", "bootstrap_dns": "Bootstrap DNS-Server starten", "bootstrap_dns_desc": "Bootstrap-DNS-Server werden verwendet, um IP-Adressen der DoH/DoT-Resolver aufzulösen, die Sie als Upstreams angeben.", "check_dhcp_servers": "Auf DHCP-Server prüfen", @@ -37,6 +39,7 @@ "dhcp_interface_select": "DHCP-Benutzeroberfläche auswählen", "dhcp_hardware_address": "Hardware-Adresse", "dhcp_ip_addresses": "IP-Adressen", + "ip": "IP", "dhcp_table_hostname": "Hostname", "dhcp_table_expires": "Läuft ab", "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!", @@ -49,17 +52,24 @@ "dhcp_static_leases_not_found": "Keine statischen DHCP-Leases gefunden", "dhcp_add_static_lease": "Statischen Lease hinzufügen", "dhcp_reset": "Möchten Sie die DHCP-Konfiguration wirklich zurücksetzen?", + "country": "Land", + "city": "Stadt", "delete_confirm": "Möchten Sie „{{key}}” wirklich löschen?", "form_enter_hostname": "Gerätenamen eingeben", "error_details": "Fehlerdetails", + "client_details": "Einzelheiten des Clients", + "details": "Details", "back": "Zurück", "dashboard": "Übersicht", "settings": "Einstellungen", "filters": "Filter", + "filter": "Filter", "query_log": "Anfragenprotokoll", + "empty_log": "Abfrageprotokoll ist leer", "faq": "FAQ", "version": "Version", "address": "Adresse", + "protocol": "Protokoll", "on": "AN", "off": "AUS", "copyright": "Urheberrecht", @@ -132,8 +142,10 @@ "rules_count_table_header": "Anzahl Regeln", "last_time_updated_table_header": "Letztes Update", "actions_table_header": "Aktionen", + "request_table_header": "Anfrage", "edit_table_action": "Bearbeiten", "delete_table_action": "Löschen", + "elapsed": "Verstrichen", "filters_and_hosts_hint": "AdGuard Home versteht grundlegende Werbefilterregeln und Host-Datei-Syntax.", "no_blocklist_added": "Keine Sperrliste hinzugefügt", "no_whitelist_added": "Keine Freigabeliste hinzugefügt", @@ -170,10 +182,11 @@ "updated_upstream_dns_toast": "Upstream-DNS-Server wurden aktualisiert", "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", - "unblock_btn": "Entblocken", - "block_btn": "Blockieren", + "block": "Blockieren", "time_table_header": "Zeit", + "date": "Datum", "domain_name_table_header": "Domainname", + "domain_or_client": "Domain oder Client", "type_table_header": "Typ", "response_table_header": "Antwort", "client_table_header": "Client", @@ -211,6 +224,8 @@ "custom_ip": "Benutzerdefinierte IP", "blocking_ipv4": "IPv4-Sperren", "blocking_ipv6": "IPv6-Sperren", + "dns_over_https": "DNS-over-HTTPS (DNS-Abrage über HTTPS)", + "dns_over_tls": "DNS-over-TLS (DNS-Abrage über TLS)", "form_enter_rate_limit": "Begrenzungswert eingeben", "rate_limit": "Begrenzungswert", "edns_enable": "EDNS Client Subnetz aktivieren", @@ -229,6 +244,7 @@ "rule_label": "Regel", "list_label": "Liste", "unknown_filter": "Unbekannter Filter {{filterId}}", + "known_tracker": "Bekannte Tracker", "install_welcome_title": "Willkommen bei AdGuard Home!", "install_welcome_desc": "AdGuard Home ist ein netzwerkweiter Werbung- und Tracking sperrender DNS-Server. Sein Zweck ist es, Ihnen die Kontrolle über Ihr gesamtes Netzwerk und alle Ihre Geräte zu ermöglichen, und es ist nicht erforderlich, eine clientseitige Anwendung zu verwenden.", "install_settings_title": "Admin Weboberfläche", @@ -257,7 +273,7 @@ "install_devices_router_list_1": "Öffnen Sie die Einstellungen für Ihren Router. In der Regel können Sie von Ihrem Browser aus über eine URL (wie http://192.168.0.1/ oder http://192.168.1.1/) darauf zugreifen. Möglicherweise werden Sie aufgefordert, das Passwort einzugeben. Wenn Sie sich nicht mehr daran erinnern, können Sie das Passwort oft durch Drücken einer Taste auf dem Router selbst zurücksetzen. Einige Router benötigen eine bestimmte Anwendung, die in diesem Fall bereits auf Ihrem Computer/Telefon installiert sein sollte.", "install_devices_router_list_2": "DHCP/DNS-Einstellungen suchen. Suchen Sie nach den DNS-Buchstaben neben einem Feld, das zwei oder drei Zahlensätze erlaubt, die jeweils in vier Gruppen von ein bis drei Ziffern unterteilt sind.", "install_devices_router_list_3": "Geben Sie dort Ihre AdGuard Home Server-Adressen ein.", - "install_devices_router_list_4": "Sie können auf einigen Routern keine beliebigen DNS-Server festlegen. In diesem Fall kann es hilfreich sein, dass Sie AdGuard Home als DHCP-Server festlegen. Andernfalls sollten Sie nach einer Bedienungsanleitung zum Anpassen des DNS-Server für Ihr Router-Modell suchen.", + "install_devices_router_list_4": "Sie können auf einigen Routern keine beliebigen DNS-Server festlegen. In diesem Fall kann es hilfreich sein, dass Sie AdGuard Home als <0>DHCP-Server festlegen. Andernfalls sollten Sie nach einer Bedienungsanleitung zum Anpassen des DNS-Server für Ihr Router-Modell suchen.", "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_3": "Suchen Sie auf der linken Seite des Bildschirms nach „Adaptereinstellungen ändern” und klicken Sie darauf.", @@ -346,6 +362,7 @@ "form_enter_id": "Kennung eingeben", "form_add_id": "Kennung hinzufügen", "form_client_name": "Clientnamen eingeben", + "name": "Name", "client_global_settings": "Allgemeine Einstellungen nutzen", "client_deleted": "Client „{{key}}” erfolgreich entfernt", "client_added": "Client „{{key}}” erfolgreich hinzugefügt", @@ -445,6 +462,7 @@ "location": "Ort", "orgname": "Name der Organisation", "netname": "Netzwerkname", + "network": "Netzwerk", "descr": "Beschreibung", "whois": "Whois", "filtering_rules_learn_more": "<0>Erfahren Sie mehr über die Erstellung eigener Hosts-Listen.", @@ -489,5 +507,19 @@ "list_updated": "{{count}} Liste aktualisiert", "list_updated_plural": "{{count}} Listen aktualisiert", "dnssec_enable": "DNSSEC aktivieren", - "dnssec_enable_desc": "DNSSEC-Flag in den ausgehenden DNS-Abfragen mitsenden und das Ergebnis überprüfen (DNSSEC-fähiger Resolver erforderlich)" -} + "dnssec_enable_desc": "DNSSEC-Flag in den ausgehenden DNS-Abfragen mitsenden und das Ergebnis überprüfen (DNSSEC-fähiger Resolver erforderlich)", + "validated_with_dnssec": "Bestätigt mit DNSSEC", + "show_all_responses": "Alle Antworten", + "show_blocked_responses": "Gesperrt", + "show_whitelisted_responses": "Auf der Positivliste", + "show_processed_responses": "Verarbeitet", + "blocked_safebrowsing": "Durch Internetsicherheit gesperrt", + "blocked_adult_websites": "Gesperrte jugendgefährdende Webseiten", + "blocked_threats": "Gesperrte Bedrohungen", + "allowed": "Zugelassen", + "filtered": "Gefiltert", + "rewritten": "Umgeschrieben", + "safe_search": "Sichere Suche", + "blocklist": "Sperrliste", + "milliseconds_abbreviation": "ms" +} \ No newline at end of file diff --git a/client/src/__locales/en.json b/client/src/__locales/en.json index f1178b81..3f638b81 100644 --- a/client/src/__locales/en.json +++ b/client/src/__locales/en.json @@ -39,6 +39,7 @@ "dhcp_interface_select": "Select DHCP interface", "dhcp_hardware_address": "Hardware address", "dhcp_ip_addresses": "IP addresses", + "ip": "IP", "dhcp_table_hostname": "Hostname", "dhcp_table_expires": "Expires", "dhcp_warning": "If you want to enable DHCP server anyway, make sure that there is no other active DHCP server in your network. Otherwise, it can break the Internet for connected devices!", @@ -51,17 +52,27 @@ "dhcp_static_leases_not_found": "No DHCP static leases found", "dhcp_add_static_lease": "Add static lease", "dhcp_reset": "Are you sure you want to reset DHCP config?", + "country": "Country", + "city": "City", "delete_confirm": "Are you sure you want to delete \"{{key}}\"?", "form_enter_hostname": "Enter hostname", "error_details": "Error details", + "response_details": "Response details", + "request_details": "Request details", + "client_details": "Client details", + "details": "Details", "back": "Back", "dashboard": "Dashboard", "settings": "Settings", "filters": "Filters", + "filter": "Filter", "query_log": "Query Log", + "compact": "Compact", + "nothing_found": "Nothing is found", "faq": "FAQ", "version": "Version", - "address": "address", + "address": "Address", + "protocol": "Protocol", "on": "ON", "off": "OFF", "copyright": "Copyright", @@ -134,8 +145,10 @@ "rules_count_table_header": "Rules count", "last_time_updated_table_header": "Last time updated", "actions_table_header": "Actions", + "request_table_header": "Request", "edit_table_action": "Edit", "delete_table_action": "Delete", + "elapsed": "Elapsed", "filters_and_hosts_hint": "AdGuard Home understands basic adblock rules and hosts files syntax.", "no_blocklist_added": "No blocklists added", "no_whitelist_added": "No allowlists added", @@ -172,12 +185,15 @@ "updated_upstream_dns_toast": "Updated the upstream DNS servers", "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", - "unblock_btn": "Unblock", - "block_btn": "Block", + "unblock": "Unblock", + "block": "Block", "time_table_header": "Time", + "date": "Date", "domain_name_table_header": "Domain name", + "domain_or_client": "Domain or client", "type_table_header": "Type", "response_table_header": "Response", + "response_code": "Response code", "client_table_header": "Client", "empty_response_status": "Empty", "show_all_filter_type": "Show all", @@ -196,6 +212,7 @@ "query_log_filtered": "Filtered by {{filter}}", "query_log_confirm_clear": "Are you sure you want to clear the entire query log?", "query_log_cleared": "The query log has been successfully cleared", + "query_log_updated": "The query log has been successfully updated", "query_log_clear": "Clear query logs", "query_log_retention": "Query logs retention", "query_log_enable": "Enable log", @@ -213,6 +230,9 @@ "custom_ip": "Custom IP", "blocking_ipv4": "Blocking IPv4", "blocking_ipv6": "Blocking IPv6", + "dns_over_https": "DNS-over-HTTPS", + "dns_over_tls": "DNS-over-TLS", + "plain_dns": "Plain DNS", "form_enter_rate_limit": "Enter rate limit", "rate_limit": "Rate limit", "edns_enable": "Enable EDNS Client Subnet", @@ -225,12 +245,14 @@ "blocking_mode_null_ip": "Null IP: Respond with zero IP address (0.0.0.0 for A; :: for AAAA)", "blocking_mode_custom_ip": "Custom IP: Respond with a manually set IP address", "upstream_dns_client_desc": "If you keep this field empty, AdGuard Home will use the servers configured in the <0>DNS settings.", + "tracker_source": "Tracker source", "source_label": "Source", "found_in_known_domain_db": "Found in the known domains database.", "category_label": "Category", "rule_label": "Rule", "list_label": "List", "unknown_filter": "Unknown filter {{filterId}}", + "known_tracker": "Known tracker", "install_welcome_title": "Welcome to AdGuard Home!", "install_welcome_desc": "AdGuard Home is a network-wide ad-and-tracker blocking DNS server. Its purpose is to let you control your entire network and all your devices, and it does not require using a client-side program.", "install_settings_title": "Admin Web Interface", @@ -348,6 +370,7 @@ "form_enter_id": "Enter identifier", "form_add_id": "Add identifier", "form_client_name": "Enter client name", + "name": "Name", "client_global_settings": "Use global settings", "client_deleted": "Client \"{{key}}\" successfully deleted", "client_added": "Client \"{{key}}\" successfully added", @@ -447,6 +470,7 @@ "location": "Location", "orgname": "Organization name", "netname": "Network name", + "network": "Network", "descr": "Description", "whois": "Whois", "filtering_rules_learn_more": "<0>Learn more about creating your own hosts lists.", @@ -491,5 +515,19 @@ "list_updated": "{{count}} list updated", "list_updated_plural": "{{count}} lists updated", "dnssec_enable": "Enable DNSSEC", - "dnssec_enable_desc": "Set DNSSEC flag in the outcoming DNS queries and check the result (DNSSEC-enabled resolver is required)" + "dnssec_enable_desc": "Set DNSSEC flag in the outcoming DNS queries and check the result (DNSSEC-enabled resolver is required)", + "validated_with_dnssec": "Validated with DNSSEC", + "show_all_responses": "All responses", + "show_blocked_responses": "Blocked", + "show_whitelisted_responses": "Whitelisted", + "show_processed_responses": "Processed", + "blocked_safebrowsing": "Blocked Safebrowsing", + "blocked_adult_websites": "Blocked Adult Websites", + "blocked_threats": "Blocked Threats", + "allowed": "Allowed", + "filtered": "Filtered", + "rewritten": "Rewritten", + "safe_search": "Safe search", + "blocklist": "Blocklist", + "milliseconds_abbreviation": "ms" } diff --git a/client/src/__locales/es.json b/client/src/__locales/es.json index 4611caf5..bb22c1c6 100644 --- a/client/src/__locales/es.json +++ b/client/src/__locales/es.json @@ -3,6 +3,8 @@ "example_upstream_reserved": "puedes especificar el DNS de subida <0>para un dominio específico", "upstream_parallel": "Usar peticiones paralelas para acelerar la resolución al consultar simultáneamente a todos los servidores de subida", "parallel_requests": "Peticiones paralelas", + "load_balancing": "Balanceo de carga", + "load_balancing_desc": "Consulta un servidor a la vez. AdGuard Home utilizará el algoritmo aleatorio ponderado para elegir el servidor más rápido y sea utilizado con más frecuencia.", "bootstrap_dns": "Servidores DNS de arranque", "bootstrap_dns_desc": "Los servidores DNS de arranque se utilizan para resolver las direcciones IP de los resolutores DoH/DoT que usted especifique como DNS de subida.", "check_dhcp_servers": "Comprobar si hay servidores DHCP", @@ -37,6 +39,7 @@ "dhcp_interface_select": "Seleccione la interfaz DHCP", "dhcp_hardware_address": "Dirección MAC", "dhcp_ip_addresses": "Direcciones IP", + "ip": "IP", "dhcp_table_hostname": "Nombre del host", "dhcp_table_expires": "Expira", "dhcp_warning": "Si de todos modos desea habilitar el servidor DHCP, asegúrese de que no hay otro servidor DHCP activo en tu red. ¡De lo contrario, puede dejar sin Internet a los dispositivos conectados!", @@ -49,17 +52,24 @@ "dhcp_static_leases_not_found": "No se han encontrado asignaciones DHCP estáticas", "dhcp_add_static_lease": "Añadir asignación estática", "dhcp_reset": "¿Está seguro de que desea restablecer la configuración DHCP?", + "country": "País", "delete_confirm": "¿Está seguro de que desea eliminar \"{{key}}\"?", "form_enter_hostname": "Ingresa el nombre del host", "error_details": "Detalles del error", + "request_details": "Detalles de la petición", + "client_details": "Detalles del cliente", + "details": "Detalles", "back": "Atrás", "dashboard": "Panel de control", "settings": "Configuración", "filters": "Filtros", + "filter": "Filtro", "query_log": "Registro de consultas", + "empty_log": "El registro de consultas está vacío", "faq": "Preguntas frecuentes", "version": "Versión", - "address": "dirección", + "address": "Dirección", + "protocol": "Protocolo", "on": "Activo", "off": "Inactivo", "copyright": "Copyright", @@ -85,7 +95,7 @@ "top_clients": "Clientes más frecuentes", "no_clients_found": "No se han encontrado clientes", "general_statistics": "Estadísticas generales", - "number_of_dns_query_days": "Número de consultas DNS procesadas durante los últimos {{count}} días", + "number_of_dns_query_days": "Número de consultas DNS procesadas durante el último {{count}} día", "number_of_dns_query_days_plural": "Número de consultas DNS procesadas durante los últimos {{count}} días", "number_of_dns_query_24_hours": "Número de consultas DNS procesadas durante las últimas 24 horas", "number_of_dns_query_blocked_24_hours": "Número de peticiones DNS bloqueadas por los filtros y listas de bloqueo de hosts", @@ -114,14 +124,14 @@ "encryption_settings": "Configuración de cifrado", "dhcp_settings": "Configuración DHCP", "upstream_dns": "Servidores DNS de subida", - "upstream_dns_hint": "Si mantiene este campo vacío, AdGuard Home utilizará Quad9 como DNS de subida.", + "upstream_dns_hint": "Si se mantiene este campo vacío, AdGuard Home utilizará Quad9 como DNS de subida.", "test_upstream_btn": "Probar DNS de subida", "upstreams": "DNS de subida", "apply_btn": "Aplicar", "disabled_filtering_toast": "Filtrado deshabilitado", "enabled_filtering_toast": "Filtrado habilitado", - "disabled_safe_browsing_toast": "Búsqueda segura deshabilitada", - "enabled_safe_browsing_toast": "Búsqueda segura habilitada", + "disabled_safe_browsing_toast": "Navegación segura deshabilitada", + "enabled_safe_browsing_toast": "Navegación segura habilitada", "disabled_parental_toast": "Control parental deshabilitado", "enabled_parental_toast": "Control parental habilitado", "disabled_safe_search_toast": "Búsqueda segura deshabilitada", @@ -132,8 +142,10 @@ "rules_count_table_header": "Número de reglas", "last_time_updated_table_header": "Última actualización", "actions_table_header": "Acciones", + "request_table_header": "Petición", "edit_table_action": "Editar", "delete_table_action": "Eliminar", + "elapsed": "Transcurrido", "filters_and_hosts_hint": "AdGuard Home entiende las reglas básicas de bloqueo y la sintaxis de los archivos hosts.", "no_blocklist_added": "No se han añadido listas de bloqueo", "no_whitelist_added": "No se han añadido listas de permitido", @@ -170,10 +182,12 @@ "updated_upstream_dns_toast": "Servidores DNS de subida actualizados", "dns_test_ok_toast": "Los servidores DNS especificados funcionan correctamente", "dns_test_not_ok_toast": "Servidor \"{{key}}\": no se puede utilizar, por favor revise si lo ha escrito correctamente", - "unblock_btn": "Desbloquear", - "block_btn": "Bloquear", + "unblock": "Desbloquear", + "block": "Bloquear", "time_table_header": "Hora", + "date": "Fecha", "domain_name_table_header": "Nombre del dominio", + "domain_or_client": "Dominio o cliente", "type_table_header": "Tipo", "response_table_header": "Respuesta", "client_table_header": "Cliente", @@ -211,6 +225,8 @@ "custom_ip": "IP personalizada", "blocking_ipv4": "Bloqueo de IPv4", "blocking_ipv6": "Bloqueo de IPv6", + "dns_over_https": "DNS mediante HTTPS", + "dns_over_tls": "DNS mediante TLS", "form_enter_rate_limit": "Ingresa el límite de cantidad", "rate_limit": "Límite de cantidad", "edns_enable": "Habilitar subred de cliente EDNS", @@ -222,13 +238,14 @@ "blocking_mode_nxdomain": "NXDOMAIN: Responde con el código NXDOMAIN", "blocking_mode_null_ip": "IP nulo: Responde con dirección IP cero (0.0.0.0 para A; :: para AAAA)", "blocking_mode_custom_ip": "IP personalizada: Responde con una dirección IP establecida manualmente", - "upstream_dns_client_desc": "Si mantiene este campo vacío, AdGuard Home utilizará los servidores configurados en la <0>configuración del DNS.", + "upstream_dns_client_desc": "Si se mantiene este campo vacío, AdGuard Home utilizará los servidores configurados en la <0>configuración del DNS.", "source_label": "Fuente", "found_in_known_domain_db": "Encontrado en la base de datos de dominios conocidos.", "category_label": "Categoría", "rule_label": "Regla", "list_label": "Lista", "unknown_filter": "Filtro desconocido {{filterId}}", + "known_tracker": "Rastreador conocido", "install_welcome_title": "¡Bienvenido a AdGuard Home!", "install_welcome_desc": "AdGuard Home es un servidor DNS para bloqueo de anuncios y rastreadores a nivel de red. Su propósito es permitirte controlar toda tu red y todos tus dispositivos, y no requiere el uso de un programa del lado del cliente.", "install_settings_title": "Interfaz web de administración", @@ -257,7 +274,7 @@ "install_devices_router_list_1": "Abre las preferencias de tu router. Por lo general, puedes acceder a él desde tu navegador a través de una URL (como http://192.168.0.1/ o http://192.168.1.1/). Es posible que se te pida que ingreses la contraseña. Si no lo recuerdas, a menudo puedes restablecer la contraseña presionando un botón en el router. Algunos routers requieren una aplicación específica, que en ese caso ya debería estar instalada en tu computadora/teléfono.", "install_devices_router_list_2": "Busca la configuración de DHCP/DNS. Busca las letras DNS junto a un campo que permita ingresar dos o tres grupos de números, cada uno dividido en cuatro grupos de uno a tres dígitos.", "install_devices_router_list_3": "Ingresa las direcciones de tu servidor AdGuard Home allí.", - "install_devices_router_list_4": "No se puede configurar un servidor DNS personalizado en algunos tipos de routers. En este caso puede ayudar si configuras AdGuard Home como un servidor DHCP. De lo contrario, deberías buscar el manual sobre cómo personalizar los servidores DNS para tu modelo de router en particular.", + "install_devices_router_list_4": "No se puede configurar un servidor DNS personalizado en algunos tipos de routers. En este caso puede ayudar si configuras AdGuard Home como un <0>servidor DHCP. De lo contrario, deberías buscar el manual sobre cómo personalizar los servidores DNS para tu modelo de router en particular.", "install_devices_windows_list_1": "Abre el Panel de control a través del menú Inicio o en el buscador de Windows.", "install_devices_windows_list_2": "Ve a la categoría Redes e Internet, luego a Centro de redes y recursos compartidos.", "install_devices_windows_list_3": "En el lado izquierdo de la pantalla, busca Cambiar configuración del adaptador y luego haz clic en él.", @@ -346,6 +363,7 @@ "form_enter_id": "Ingresa el identificador", "form_add_id": "Añadir identificador", "form_client_name": "Ingresa el nombre del cliente", + "name": "Nombre", "client_global_settings": "Usar configuración global", "client_deleted": "Cliente \"{{key}}\" eliminado correctamente", "client_added": "Cliente \"{{key}}\" añadido correctamente", @@ -445,6 +463,7 @@ "location": "Ubicación", "orgname": "Nombre de la organización", "netname": "Nombre de la red", + "network": "Red", "descr": "Descripción", "whois": "Whois", "filtering_rules_learn_more": "<0>Más información sobre cómo crear tus propias listas de hosts.", @@ -456,8 +475,8 @@ "disable_ipv6": "Deshabilitar IPv6", "disable_ipv6_desc": "Si esta función está habilitada, se eliminarán todas las consultas DNS para direcciones IPv6 (tipo AAAA).", "fastest_addr": "Dirección IP más rápida", - "fastest_addr_desc": "Consulta todos los servidores DNS y devuelve la dirección IP más rápida de todas las respuestas", - "autofix_warning_text": "Si hace clic en \"Corregir\", AdGuard Home configurará tu sistema para utilizar el servidor DNS de AdGuard Home.", + "fastest_addr_desc": "Consulta todos los servidores DNS y devuelve la dirección IP más rápida de todas las respuestas. Esto ralentizará las consultas DNS, y se debe esperar las respuestas de todos los servidores DNS, pero mejora la conectividad general.", + "autofix_warning_text": "Si haces clic en \"Corregir\", AdGuard Home configurará tu sistema para utilizar el servidor DNS de AdGuard Home.", "autofix_warning_list": "Realizará estas tareas: <0>Deshabilitar el sistema DNSStubListener <0>Establecer la dirección del servidor DNS en 127.0.0.1 <0>Reemplazar el destino del enlace simbólico de /etc/resolv.conf por /run/systemd/resolve/resolv.conf <0>Detener DNSStubListener (recargar el servicio systemd-resolved)", "autofix_warning_result": "Como resultado, todas las peticiones DNS de tu sistema serán procesadas por AdGuard Home de manera predeterminada.", "tags_title": "Etiquetas", @@ -489,5 +508,19 @@ "list_updated": "{{count}} lista actualizada", "list_updated_plural": "{{count}} listas actualizadas", "dnssec_enable": "Habilitar DNSSEC", - "dnssec_enable_desc": "Establece el indicador DNSSEC en las consultas DNS salientes y comprueba el resultado (se requiere un resolutor habilitado para DNSSEC)" + "dnssec_enable_desc": "Establece el indicador DNSSEC en las consultas DNS salientes y comprueba el resultado (se requiere un resolutor habilitado para DNSSEC)", + "validated_with_dnssec": "Validado con DNSSEC", + "show_all_responses": "Todas las respuestas", + "show_blocked_responses": "Bloqueado", + "show_whitelisted_responses": "En lista blanca", + "show_processed_responses": "Procesado", + "blocked_safebrowsing": "Bloqueado por navegación segura", + "blocked_adult_websites": "Sitios web para adultos bloqueado", + "blocked_threats": "Amenazas bloqueadas", + "allowed": "Permitido", + "filtered": "Filtrado", + "rewritten": "Reescrito", + "safe_search": "Búsqueda segura", + "blocklist": "Lista de bloqueo", + "milliseconds_abbreviation": "ms" } \ No newline at end of file diff --git a/client/src/__locales/fa.json b/client/src/__locales/fa.json index 65c141f7..5e198b75 100644 --- a/client/src/__locales/fa.json +++ b/client/src/__locales/fa.json @@ -37,6 +37,7 @@ "dhcp_interface_select": "رابط DHCP را انتخاب کنید", "dhcp_hardware_address": "آدرس سخت افزار", "dhcp_ip_addresses": "آدرس آی پی", + "ip": "IP", "dhcp_table_hostname": "نام میزبان", "dhcp_table_expires": "انقضاء", "dhcp_warning": "اگر میخواهید DHCP سرور توکار را فعال کنید،مطمئن شوید DHCP سرور دیگری فعال نباشد.در غیر اینصورت،آن دسترسی به اینترنت را برای دستگاه های وصل شده قطع می کند!", @@ -49,17 +50,26 @@ "dhcp_static_leases_not_found": "هیچ اجاره DHCP ایستا یافت نشد", "dhcp_add_static_lease": "افزودن اجاره ایستا", "dhcp_reset": "آیا میخواهید پیکربندی DHCP را ریست کنید؟", + "country": "کشور", + "city": "شهر", "delete_confirm": "آیا میخواهید \"{{key}}\" را حذف کنید؟", "form_enter_hostname": "نام میزبان را وارد کنید", "error_details": "جزئیات خطا", + "response_details": "جزئیات پاسخ", + "request_details": "درخواست جزئیات", + "client_details": "جزئیات کلاینت", + "details": "جزئیات", "back": "قبلی", "dashboard": "داشبورد", "settings": "تنظيمات", "filters": "فيلترها", + "filter": "فیلتر", "query_log": "جستار وقایع", + "empty_log": "وقایع جستار خالی است", "faq": "پرسش و پاسخ", "version": "نسخه", "address": "آدرس", + "protocol": "پروتکل", "on": "روشن", "off": "خاموش", "copyright": "حق مالکیت", @@ -132,8 +142,10 @@ "rules_count_table_header": "تعداد دستور", "last_time_updated_table_header": "زمان آخرین بروزرسانی", "actions_table_header": "اقدامات", + "request_table_header": "درخواست", "edit_table_action": "ويرايش", "delete_table_action": "حذف", + "elapsed": "سپری شده", "filters_and_hosts_hint": "AdGuard Home دستورات پایه مسدودساز تبلیغ و نحو فایل های میزبان را درک می کند.", "no_blocklist_added": "به لیست سیاه اضافه نشد", "no_whitelist_added": "به لیست مجاز اضافه نشد", @@ -170,10 +182,12 @@ "updated_upstream_dns_toast": "سرورهای DNS جریان ارسالی بروز رسانی شده است", "dns_test_ok_toast": "سرورهای DNS تعیین شده بدرستی کار می کنند", "dns_test_not_ok_toast": "سرور \"{{key}}\": نمیتواند مورد استفاده قرار گیرد،لطفا بررسی کنید آن را بدرستی نوشته اید", - "unblock_btn": "باز کن", - "block_btn": "مسدود کن", + "unblock": "رفع انسداد", + "block": "مسدود کردن", "time_table_header": "زمان", + "date": "تاریخ", "domain_name_table_header": "نام دامنه", + "domain_or_client": "دامنه یا کلاینت", "type_table_header": "نوع", "response_table_header": "پاسخ", "client_table_header": "کلاینت", @@ -211,6 +225,8 @@ "custom_ip": "آی پی دستی", "blocking_ipv4": "مسدودسازی IPv4", "blocking_ipv6": "مسدودسازی IPv6", + "dns_over_https": "DNS-over-HTTPS", + "dns_over_tls": "DNS-over-TLS", "form_enter_rate_limit": "میزان محدودیت را وارد کنید", "rate_limit": "میزان محدودیت", "edns_enable": "فعالسازی زیرشبکه کلاینت EDNS", @@ -229,6 +245,7 @@ "rule_label": "دستور", "list_label": "لیست", "unknown_filter": "فیلتر ناشناخته {{filterId}}", + "known_tracker": "ردیاب های شناخته شده", "install_welcome_title": "به AdGuard Home خوش آمدید!", "install_welcome_desc": "AdGuard Home یک شبکه گسترده و ردیاب و مسدوساز تبلیغ با سرور DNS است.هدف آن این است که به شما اجازه کنترل کل شبکه و همه دستگاه های شما را بدهد و آن نیازی به برنامه سمت-کاربر ندارد.", "install_settings_title": "رابط وب آدمین", @@ -346,6 +363,7 @@ "form_enter_id": "خطای احرازکننده", "form_add_id": "افزودن احرازکننده", "form_client_name": "نام کلاینت را وارد کنید", + "name": "نام", "client_global_settings": "استفاده از تنظیمات سراسری", "client_deleted": "کلاینت \"{{key}}\" را با موفقیت حذف کرد", "client_added": "کلاینت \"{{key}}\" را با موفقیت اضافه کرد", @@ -445,6 +463,7 @@ "location": "مکان", "orgname": "نام سازمان", "netname": "نام شبکه", + "network": "شبکه", "descr": "توضيحات", "whois": "هوئیز", "filtering_rules_learn_more": "درباره ایجاد لیست سیاه میزبان برای خود <0>بیشتر بدانید.", @@ -489,5 +508,19 @@ "list_updated": "{{count}} لیست بروز رسانی شد", "list_updated_plural": "{{count}} لیست بروز رسانی شد", "dnssec_enable": "فعالسازی DNSSEC", - "dnssec_enable_desc": "تنظیم نشان DNSSEC در جستارهای حاصل DNS و بررسی نتیجه (تفکیک کننده DNSSEC-فعال شده نیاز است)" + "dnssec_enable_desc": "تنظیم نشان DNSSEC در جستارهای حاصل DNS و بررسی نتیجه (تفکیک کننده DNSSEC-فعال شده نیاز است)", + "validated_with_dnssec": "معتبر سازی با DNSSEC", + "show_all_responses": "همه پاسخ ها", + "show_blocked_responses": "مسدود شده", + "show_whitelisted_responses": "لیست سفید", + "show_processed_responses": "پردازش شده", + "blocked_safebrowsing": "بستن وب گردی اَمن", + "blocked_adult_websites": "وبسایت غیراخلاقی مسدود شده", + "blocked_threats": "تهدیدات مسدود شده", + "allowed": "اجازه داده شده", + "filtered": "فیلتر شده", + "rewritten": "بازنویسی شده", + "safe_search": "جستجوی اَمن", + "blocklist": "لیست سیاه", + "milliseconds_abbreviation": "هـ ثـ" } \ No newline at end of file diff --git a/client/src/__locales/fr.json b/client/src/__locales/fr.json index 422e3a40..82ce9940 100644 --- a/client/src/__locales/fr.json +++ b/client/src/__locales/fr.json @@ -3,6 +3,8 @@ "example_upstream_reserved": "Vous pouvez spécifier un DNS en amont <0>pour un/des domaine(s) spécifique(s)", "upstream_parallel": "Utiliser des requêtes parallèles pour accélérer la résolution en requêtant simultanément tous les serveurs upstream", "parallel_requests": "Demandes en parallèle", + "load_balancing": "Équilibrage de charge", + "load_balancing_desc": "Interroger un serveur à la fois. AdGuard Home utilisera l’algorithme aléatoire pondéré pour choisir le serveur afin que celui le plus rapide soit utilisé plus souvent.", "bootstrap_dns": "Serveurs DNS d'amorçage", "bootstrap_dns_desc": "Les serveurs DNS d'amorçage sont utilisés pour résoudre les adresses IP des résolveurs DoH/DoT que vous spécifiez comme upstream.", "check_dhcp_servers": "Rechercher les serveurs DHCP", @@ -37,6 +39,7 @@ "dhcp_interface_select": "Sélectionner l'interface du serveur DHCP", "dhcp_hardware_address": "Adresse de la machine", "dhcp_ip_addresses": "Adresses IP", + "ip": "IP", "dhcp_table_hostname": "Nom de machine", "dhcp_table_expires": "Expire le", "dhcp_warning": "Si vous souhaitez tout de même activer le serveur DHCP, assurez-vous qu'il n'y a d'autre serveur DHCP actif sur votre réseau. Sinon, cela peut faire dysfonctionner Internet sur tous les appareils connectés au réseau !", @@ -49,17 +52,25 @@ "dhcp_static_leases_not_found": "Aucun bail statique DHCP trouvé", "dhcp_add_static_lease": "Ajoutez un bail statique", "dhcp_reset": "Voulez-vous vraiment réinitialiser votre configuration DHCP ?", + "country": "Pays", + "city": "Ville", "delete_confirm": "Voulez-vous vraiment supprimer \"{{key}}\" ?", "form_enter_hostname": "Saisissez un nom d'hôte", "error_details": "Détails des erreurs", + "request_details": "Demander des détails", + "client_details": "Détails du client", + "details": "Détails", "back": "Retour", "dashboard": "Tableau de bord", "settings": "Paramètres", "filters": "Filtres", + "filter": "Filtre", "query_log": "Journal des requêtes", + "empty_log": "Le journal des requêtes est vide", "faq": "FAQ", "version": "version", - "address": "addresse", + "address": "Addresse", + "protocol": "Protocole", "on": "Activé", "off": "Éteint", "copyright": "Copyright", @@ -132,8 +143,10 @@ "rules_count_table_header": "Nombre des règles", "last_time_updated_table_header": "Dernière mise à jour", "actions_table_header": "Actions", + "request_table_header": "Requête", "edit_table_action": "Modifier", "delete_table_action": "Supprimer", + "elapsed": "Écoulé", "filters_and_hosts_hint": "AdGuard Home comprend les règles basiques de blocage ainsi que la syntaxe des fichiers hosts.", "no_blocklist_added": "Aucune liste de blocage ajoutée", "no_whitelist_added": "Aucune liste d’autorisation ajoutée", @@ -170,10 +183,12 @@ "updated_upstream_dns_toast": "Les serveurs DNS upstream sont mis à jour", "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", - "unblock_btn": "Débloquer", - "block_btn": "Bloquer", + "unblock": "Débloquer", + "block": "Bloquer", "time_table_header": "Temps", + "date": "Date", "domain_name_table_header": "Nom de domaine", + "domain_or_client": "Domaine ou client", "type_table_header": "Type", "response_table_header": "Réponse", "client_table_header": "Client", @@ -211,6 +226,8 @@ "custom_ip": "IP personnalisée", "blocking_ipv4": "Blocage IPv4", "blocking_ipv6": "Blocage IPv6", + "dns_over_https": "DNS-over-HTTPS", + "dns_over_tls": "DNS-over-TLS", "form_enter_rate_limit": "Entrez la limite de taux", "rate_limit": "Limite de taux", "edns_enable": "Activer le sous-réseau du client EDNS", @@ -229,6 +246,7 @@ "rule_label": "Règle", "list_label": "Liste", "unknown_filter": "Filtre inconnu {{filterId}}", + "known_tracker": "Pisteur connu", "install_welcome_title": "Bienvenue sur AdGuard Home !", "install_welcome_desc": "AdGuard Home est un seveur DNS pour bloquer les pubs et traceurs sur tout un réseau. Son but est de vous donner le contrôle sur l'ensemble de votre réseau et tous vos appareils sans programme côté client supplémentaire.", "install_settings_title": "Interface web administrateur", @@ -257,7 +275,7 @@ "install_devices_router_list_1": "Ouvrez les préférences de votre routeur. Normalement, vous pouvez y accéder depuis votre navigateur Web via une URL (exemple http://192.168.0.1/ ou http://192.168.1.1/). Vous devrez peut-être saisir le mot de passe. Si vous ne vous en rappelez plus, vous pouvez le réinitialiser en appuyant sur le bouton du routeur. Certains routeurs fonctionnent sous une application spécifique, qui devrait être déjà installée sur votre ordinateur/téléphone.", "install_devices_router_list_2": "Trouvez les paramètres DHCP/DNS. Recherchez les lettres DNS près d'une zone qui permet la saisie de 2 ou 3 blocs de chiffres, chacun composé de 4 parties de 1 à 3 chiffres.", "install_devices_router_list_3": "Saisissez vos adresses de serveur AdGuard Home ici.", - "install_devices_router_list_4": "Vous ne pouvez pas définir un serveur DNS personnalisé sur certains types de routeurs. Dans ce cas, cela peut être utile si vous configurez AdGuard Home en tant que serveur DHCP. Sinon, vous devez rechercher le manuel sur la façon de personnaliser les serveurs DNS pour votre modèle de routeur particulier.", + "install_devices_router_list_4": "Vous ne pouvez pas définir un serveur DNS personnalisé sur certains types de routeurs. Dans ce cas, cela peut être utile si vous configurez AdGuard Home en tant que <0>serveur DHCP. Sinon, vous devez rechercher le manuel sur la façon de personnaliser les serveurs DNS pour votre modèle de routeur particulier.", "install_devices_windows_list_1": "Ouvrez votre Panneau de configuration depuis le menu Démarrer ou la recherche Windows.", "install_devices_windows_list_2": "Allez dans la catégorie Réseau et Internet et ensuite dans le Centre Réseau et Partage.", "install_devices_windows_list_3": "Sur la partie gauche de l'écran, recherchez Modifier les paramètres de la carte et cliquez dessus.", @@ -346,6 +364,7 @@ "form_enter_id": "Entrer identifiant", "form_add_id": "Ajouter identifiant", "form_client_name": "Saisissez le nom du client", + "name": "Nom", "client_global_settings": "Utiliser les paramètres généraux", "client_deleted": "Le client \"{{key}}\" a été supprimé avec succès", "client_added": "Le client \"{{key}}\" a été ajouté", @@ -361,6 +380,7 @@ "access_allowed_desc": "Une liste d'adresses IP ou CIDR. Si configuré, AdGuard Home acceptera uniquement les requêtes provenant de ces adresses IP.", "access_disallowed_title": "Clients non autorisés", "access_disallowed_desc": "Une liste d'adresses IP ou CIDR. Si configuré, AdGuard Home bloquera les requêtes provenant de ces adresses IP.", + "access_blocked_title": "Domaines interdits", "access_blocked_desc": "Ne confondez pas ceci avec les filtres. AdGuard Home ignorera les requêtes DNS portant sur les domaines ci-dessous.", "access_settings_saved": "Paramètres d'accès enregistrés avec succès", "updates_checked": "Mises à jour vérifiées", @@ -444,6 +464,7 @@ "location": "Localisation", "orgname": "Nom de l'organisation", "netname": "Nom du réseau", + "network": "Réseau", "descr": "Description", "whois": "Whois", "filtering_rules_learn_more": "<0>Apprenez-en plus à propos de la création de vos propres listes de blocage d’hôtes.", @@ -488,5 +509,19 @@ "list_updated": "{{count}} liste mise à jour", "list_updated_plural": "{{count}} listes mises à jour", "dnssec_enable": "Activer DNSSEC", - "dnssec_enable_desc": "Définir l’indicateur DNSSEC dans les requêtes DNS sortantes et vérifier le résultat (résolveur compatible DNSSEC requis)" -} + "dnssec_enable_desc": "Définir l’indicateur DNSSEC dans les requêtes DNS sortantes et vérifier le résultat (résolveur compatible DNSSEC requis)", + "validated_with_dnssec": "Validé avec DNSSEC", + "show_all_responses": "Toutes les réponses", + "show_blocked_responses": "Bloqué", + "show_whitelisted_responses": "Ajouté à la liste blanche", + "show_processed_responses": "Traité", + "blocked_safebrowsing": "Navigation sécurisée bloquée", + "blocked_adult_websites": "Sites à contenu adulte bloqués", + "blocked_threats": "Menaces bloquées", + "allowed": "Autorisé", + "filtered": "Filtré", + "rewritten": "Réécrit", + "safe_search": "Recherche sécurisée", + "blocklist": "Liste de blocage", + "milliseconds_abbreviation": "ms" +} \ No newline at end of file diff --git a/client/src/__locales/hr.json b/client/src/__locales/hr.json index 3356799a..a0fbbecd 100644 --- a/client/src/__locales/hr.json +++ b/client/src/__locales/hr.json @@ -37,6 +37,7 @@ "dhcp_interface_select": "Odaberite DHCP sučelje", "dhcp_hardware_address": "Adresa hardvera", "dhcp_ip_addresses": "IP adrese", + "ip": "IP", "dhcp_table_hostname": "Naziv računala", "dhcp_table_expires": "Istječe", "dhcp_warning": "Ako svejedno želite omogućiti DHCP poslužitelj, provjerite da nema drugog aktivnog DHCP poslužitelja na vašoj mreži. Inače može pokvariti Internet za ostale povezane uređaje!", @@ -49,17 +50,24 @@ "dhcp_static_leases_not_found": "Nisu pronađeni statični DHCP leases", "dhcp_add_static_lease": "Dodaj static lease", "dhcp_reset": "Jeste li sigurni da želite poništiti DHCP postavke?", + "country": "Država", "delete_confirm": "Jeste li sigurni da želite ukloniti \"{{key}}\"?", "form_enter_hostname": "Unesite naziv računala", "error_details": "Detalji o pogrešci", + "request_details": "Detalji zahtjeva", + "client_details": "Detalji o klijentu", + "details": "Detalji", "back": "Natrag", "dashboard": "Upravljačka ploča", "settings": "Postavke", "filters": "Filtri", + "filter": "Filtar", "query_log": "Zapisnik upita", + "empty_log": "Zapisik upita je prazan", "faq": "ČPP", "version": "Verzija", - "address": "adresa", + "address": "Adresa", + "protocol": "Protokol", "on": "UKLJUČENO", "off": "ISKLJUČENO", "copyright": "Autorsko pravo", @@ -132,8 +140,10 @@ "rules_count_table_header": "Broj pravila", "last_time_updated_table_header": "Zadnje ažurirano", "actions_table_header": "Radnje", + "request_table_header": "Zahtjev", "edit_table_action": "Uredi", "delete_table_action": "Ukloni", + "elapsed": "Proteklo", "filters_and_hosts_hint": "AdGuard Home razumije osnovna pravila blokiranja oglasa i sintaksu hosts datoteka.", "no_blocklist_added": "Nema dodanih popisa blokiranih", "no_whitelist_added": "Nema dodanih popisa omogućenih", @@ -170,10 +180,12 @@ "updated_upstream_dns_toast": "Ažurirani su upstream DNS poslužitelji", "dns_test_ok_toast": "Odabrani DNS poslužitelji su trenutno aktivni", "dns_test_not_ok_toast": "\"{{key}}\" poslužitelja: ne može se upotrijebiti, provjerite jeste li to ispravno napisali", - "unblock_btn": "Odblokiraj", - "block_btn": "Blokiraj", + "unblock": "Odblokiraj", + "block": "Blokiraj", "time_table_header": "Vrijeme", + "date": "Datum", "domain_name_table_header": "Naziv domene", + "domain_or_client": "Domena ili klijent", "type_table_header": "Vrsta", "response_table_header": "Odgovor", "client_table_header": "Klijent", @@ -211,6 +223,8 @@ "custom_ip": "Prilagođen IP", "blocking_ipv4": "Blokiranje IPv4", "blocking_ipv6": "Blokiranje IPv6", + "dns_over_https": "DNS-over-HTTPS", + "dns_over_tls": "DNS-over-TLS", "form_enter_rate_limit": "Unesite ograničenje", "rate_limit": "Ograničenje", "edns_enable": "Omogući EDNS Client Subnet", @@ -229,6 +243,7 @@ "rule_label": "Pravilo", "list_label": "Popis", "unknown_filter": "Nepoznati filtar {{filterId}}", + "known_tracker": "Poznati pratitelj", "install_welcome_title": "Dobrodošli u AdGuard Home!", "install_welcome_desc": "AdGuard Home je DNS poslužitelj za blokiranje oglasa i pratitelja na cijeloj mreži. Njegova je svrha omogućiti vam upravljanje cijelom mrežom i svim svojim uređajima, a da to ne zahtijeva korištenje programa na strani klijenta.", "install_settings_title": "Administratorsko web sučelje", @@ -257,7 +272,7 @@ "install_devices_router_list_1": "Otvorite postavke za router. Obično mu možete pristupiti iz preglednika putem URL-a (kao što je http://192.168.0.1/ ili http://192.168.1.1/). Od vas će se možda tražiti da unesete lozinku. Ako je se ne sjećate, lozinku možete često poništiti pritiskom na dumge na samom routeru. Neki routeri trebaju određenu aplikaciju, koja bi u tom slučaju trebala biti već instalirana na vašem računalu/telefonu.", "install_devices_router_list_2": "Pronađite DHCP/DNS postavke. Potražite DNS slova pored polja koje dopušta dva ili tri skupa brojeva, svaki razdvojen u četiri skupine od jedne do tri znamenke.", "install_devices_router_list_3": "Unesite adresu AdGuard Home poslužitelja ovdje.", - "install_devices_router_list_4": "Ne možete postaviti prilagođeni DNS poslužitelj na nekim vrstama routera. U ovom slučaju, može vam pomoći ako postavite AdGuard Home kao DHCP poslužitelj. U suprotnom, trebali biste potražiti priručnik o tome kako prilagoditi DNS poslužitelje za vaš određeni model routera.", + "install_devices_router_list_4": "Ne možete postaviti prilagođeni DNS poslužitelj na nekim vrstama routera. U ovom slučaju, može vam pomoći ako postavite AdGuard Home kao <0>DHCP poslužitelj. U suprotnom, trebali biste potražiti priručnik o tome kako prilagoditi DNS poslužitelje za vaš određeni model routera.", "install_devices_windows_list_1": "Otvorite Upravljačku ploču putem Start izbornika ili Windows pretrage.", "install_devices_windows_list_2": "Idite na kategoriju Mreža i Internet i odaberite Centar za mreže i zajedničko korištenje.", "install_devices_windows_list_3": "Na lijevoj strani zaslona pronađite Promjeni postavke adaptera i pritisnite na to.", @@ -346,6 +361,7 @@ "form_enter_id": "Unesi identifikator", "form_add_id": "Dodaj identifikator", "form_client_name": "Unesite naziv klijenta", + "name": "Naziv", "client_global_settings": "Koristi globalne postavke", "client_deleted": "Klijent \"{{key}}\" je uspješno uklonjen", "client_added": "Klijent \"{{key}}\" je uspješno dodan", @@ -445,6 +461,7 @@ "location": "Lokacija", "orgname": "Naziv organizacije", "netname": "Naziv mreže", + "network": "Mreža", "descr": "Opis", "whois": "Whois", "filtering_rules_learn_more": "<0>Saznajte više o stvaranju vlastitog popisa poslužitelja.", @@ -456,7 +473,7 @@ "disable_ipv6": "Onemogući IPv6", "disable_ipv6_desc": "Ukoliko je ova značajka omogućena, svi DNS upiti za IPv6 adrese (AAAA tip) će biti odbačeni.", "fastest_addr": "Najbrža IP adresa", - "fastest_addr_desc": "Ispitajte sve DNS poslužitelje i vratite najbržu IP adresu među svim odgovorima", + "fastest_addr_desc": "Ispitajte sve DNS poslužitelje i vratite najbržu IP adresu među svim odgovorima. Ovo će usporiti DNS upite jer moramo čekati odgovore sa svih DNS poslužitelja, ali će poboljšati cjelokupnu povezanost.", "autofix_warning_text": "Ako pritisnete \"Popravi\", AdGuard Home će postaviti vaš sustav da koristi AdGuardHome DNS poslužitelj.", "autofix_warning_list": "Izvodi sljedeće radnje: <0>Deaktiviraj DNSStubListener sustav <0>Postavi adresu DNS poslužitelja na 127.0.0.1 <0>Zamijeni simbolički cilj veze iz /etc/resolv.conf u /run/systemd/resolve/resolv.conf <0>Zaustavi DNSStubListener (ponovno pokreni systemd-resolved uslugu)", "autofix_warning_result": "Kao rezultat toga, sve DNS zahtjeve iz vašeg sustava će AdGuard Home obraditi prema zadanim postavkama.", @@ -489,5 +506,19 @@ "list_updated": "{{count}} popis ažuriran", "list_updated_plural": "{{count}} popisa ažurirana", "dnssec_enable": "Omogući DNSSEC", - "dnssec_enable_desc": "Omogućite DNSSEC u izlaznim DNS upitima i provjerite rezultat (potreban je resolver s omogućenim DNSSEC-om)" + "dnssec_enable_desc": "Omogućite DNSSEC u izlaznim DNS upitima i provjerite rezultat (potreban je resolver s omogućenim DNSSEC-om)", + "validated_with_dnssec": "Potvrđeno s DNSSEC-om", + "show_all_responses": "Svi odgovori", + "show_blocked_responses": "Blokirano", + "show_whitelisted_responses": "Na popisu dopuštenih", + "show_processed_responses": "Obrađeno", + "blocked_safebrowsing": "Blokirano s Sigurnom pretragom", + "blocked_adult_websites": "Blokirane web stranice za odrasle", + "blocked_threats": "Blokirane prijetnje", + "allowed": "Dopušteno", + "filtered": "Filtrirano", + "rewritten": "Prepisano", + "safe_search": "Sigurno pretraživanje", + "blocklist": "Popis neželjenih", + "milliseconds_abbreviation": "ms" } \ No newline at end of file diff --git a/client/src/__locales/id.json b/client/src/__locales/id.json index 480c3057..512879f5 100644 --- a/client/src/__locales/id.json +++ b/client/src/__locales/id.json @@ -52,6 +52,7 @@ "delete_confirm": "Apakah anda yakin ingin menghapus \"{{key}}\"?", "form_enter_hostname": "Masukkan hostname", "error_details": "Detail kesalahan", + "request_details": "Detai permintaan", "back": "Kembali", "dashboard": "Beranda", "settings": "Pengaturan", @@ -59,7 +60,8 @@ "query_log": "Catatan Kueri", "faq": "Tanya Jawab", "version": "versi", - "address": "alamat", + "address": "Alamat", + "protocol": "Protokol", "on": "HIDUP", "off": "MATI", "copyright": "Hak cipta", @@ -107,6 +109,7 @@ "general_settings": "Pengaturan umum", "dns_settings": "Pengaturan DNS", "dns_blocklists": "Daftar blokir DNS", + "custom_filtering_rules": "Aturan penyaringan khusus", "encryption_settings": "Pengaturan enkripsi", "dhcp_settings": "Pengaturan DHCP", "upstream_dns": "Server DNS hulu", @@ -152,9 +155,10 @@ "updated_upstream_dns_toast": "Server DNS hulu terbarui", "dns_test_ok_toast": "Server DNS yang ditentukan bekerja dengan benar", "dns_test_not_ok_toast": "Server \"{{key}}\": tidak dapat digunakan, mohon cek bahwa Anda telah menulisnya dengan benar", - "unblock_btn": "Buka Blokir", - "block_btn": "Blokir", + "unblock": "Buka Blokir", + "block": "Blok", "time_table_header": "Waktu", + "date": "Tanggal", "domain_name_table_header": "Nama domain", "type_table_header": "Tipe", "response_table_header": "Respon", @@ -184,6 +188,7 @@ "query_log_strict_search": "Gunakan tanda kutip ganda untuk pencarian ketat", "query_log_retention_confirm": "Apakah Anda yakin ingin mengubah retensi kueri log? Jika Anda menurunkan nilai interval, beberapa data akan hilang", "blocking_mode": "Mode blokir", + "default": "Standar", "blocking_ipv4": "Blokiran IPv4", "blocking_ipv6": "Blokiran IPv6", "edns_cs_desc": "Apabila dinyalakan, AdGuard Home akan mengirim subnet klien ke server-server DNS.", @@ -222,7 +227,7 @@ "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 memasukkan kata sandi. Jika Anda tidak mengingatnya, Anda dapat mengatur ulang kata sandi dengan menekan tombol atur ulang (reset) pada router. Beberapa router ada yang memerlukan aplikasi tertentu, dalam hal ini harus sudah diinstal pada komputer / telepon Anda.", "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_3": "Masukkan alamat server AdGuard Home disana", - "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 server DHCP. 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. 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_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.", @@ -428,4 +433,4 @@ "client_blocked": "Klien \"{{ip}}\" sukses di blokir", "client_unblocked": "Klien \"{{ip}}\" sukses di unblock", "static_ip": "Alamat IP statis" -} +} \ No newline at end of file diff --git a/client/src/__locales/it.json b/client/src/__locales/it.json index 95046b4c..d317a081 100644 --- a/client/src/__locales/it.json +++ b/client/src/__locales/it.json @@ -3,6 +3,8 @@ "example_upstream_reserved": "Puoi specificare un server DNS<0>per uno specifico dominio(i)", "upstream_parallel": "Usa le query parallele per accelerare la risoluzione interrogando simultaneamente tutti i server", "parallel_requests": "Richieste parallele", + "load_balancing": "Bilanciamento del carico", + "load_balancing_desc": "Interroga un server per volta. AdGuardHome userà l'algoritmo soppesato casualmente per scegliere il server così che quello più veloce sarà usato più spesso.", "bootstrap_dns": "Server DNS di avvio", "bootstrap_dns_desc": "Server DNS usati per risolvere gli indirizzi IP dei risolutori DoH/DoT specificati come upstreams.", "check_dhcp_servers": "Controlla la presenza di server DHCP", @@ -37,6 +39,7 @@ "dhcp_interface_select": "Seleziona l'interfaccia DHCP", "dhcp_hardware_address": "Indirizzo hardware", "dhcp_ip_addresses": "Indirizzi IP", + "ip": "IP", "dhcp_table_hostname": "Nome host", "dhcp_table_expires": "Scaduto", "dhcp_warning": "Se si desidera abilitare il server DHCP integrato, assicurarsi che non vi siano altri server DHCP attivi. Altrimenti, possono sussistere problemi di rete per i dispositivi collegati!", @@ -49,17 +52,24 @@ "dhcp_static_leases_not_found": "Non è stato trovato nessun leases statico DHCP", "dhcp_add_static_lease": "Aggiungi lease statico", "dhcp_reset": "Sei sicuro di voler ripristinare la configurazione DHCP?", + "country": "Regione", "delete_confirm": "Sei sicuro di voler cancellare \"{{key}}\"?", "form_enter_hostname": "Inserisci hostname", "error_details": "Dettagli errore", + "request_details": "Dettagli della richiesta", + "client_details": "Dettagli client", + "details": "Dettagli", "back": "Indietro", "dashboard": "Cruscotto", "settings": "Impostazioni", "filters": "Filtri", + "filter": "Filtro", "query_log": "Query Log", + "empty_log": "Il log query è vuoto", "faq": "FAQ", "version": "versione", - "address": "indirizzo IP", + "address": "Indirizzo", + "protocol": "Protocollo", "on": "ATTIVO", "off": "DISATTIVATO", "copyright": "Copyright", @@ -132,8 +142,10 @@ "rules_count_table_header": "Numero regole", "last_time_updated_table_header": "Ultimo aggiornamento", "actions_table_header": "Azioni", + "request_table_header": "Richiesta", "edit_table_action": "Modifica", "delete_table_action": "Elimina", + "elapsed": "Trascorso", "filters_and_hosts_hint": "AdGuard Home è in grado di comprendere la sintassi delle regole di adblock o quelle dei file hosts", "no_blocklist_added": "Non è stata aggiunta alcuna lista di blocco", "no_whitelist_added": "Non è stata aggiunta alcuna lista dei consentiti", @@ -170,10 +182,12 @@ "updated_upstream_dns_toast": "Server DNS upstream aggiornati", "dns_test_ok_toast": "I server DNS specificati funzionano correttamente", "dns_test_not_ok_toast": "Server \"{{key}}\": non può essere usato, assicurati di averlo digitato correttamente", - "unblock_btn": "Sblocca", - "block_btn": "Blocca", + "unblock": "Sblocca", + "block": "Blocca", "time_table_header": "Ora", + "date": "Data", "domain_name_table_header": "Nome dominio", + "domain_or_client": "Dominio o client", "type_table_header": "Tipo", "response_table_header": "Risposta", "client_table_header": "Client", @@ -211,6 +225,8 @@ "custom_ip": "IP personalizzato", "blocking_ipv4": "Blocca IPv4", "blocking_ipv6": "Blocca IPv6", + "dns_over_https": "DNS-over-HTTPS", + "dns_over_tls": "DNS-over-TLS", "form_enter_rate_limit": "Imposta limite delle richieste", "rate_limit": "Limite delle richieste", "edns_enable": "Abilita client di sottorete EDNS", @@ -229,6 +245,7 @@ "rule_label": "Regola", "list_label": "Lista", "unknown_filter": "Filtro sconosciuto {{filterId}}", + "known_tracker": "Tracker conosciuto", "install_welcome_title": "Benvenuto nella Home di AdGuard!", "install_welcome_desc": "AdGuard Home è un server DNS che blocca annunci e tracker in tutta la rete. Il suo scopo è quello di consentire di controllare l'intera rete e tutti i dispositivi, e non richiede l'utilizzo di un programma sul lato client.", "install_settings_title": "Interfaccia Web dell'Admin", @@ -257,7 +274,7 @@ "install_devices_router_list_1": "Apri le preferenze per il tuo router. Di solito, puoi accedervi dal tuo browser tramite un URL (come http://192.168.0.1/ o http://192.168.1.1/). Potrebbe essere richiesto di inserire la password. Se non lo ricordi, puoi spesso reimpostare la password premendo un pulsante sul router stesso. Alcuni router richiedono un'applicazione specifica, che in quel caso dovrebbe essere già installata sul tuo computer / telefono.", "install_devices_router_list_2": "Trova le impostazioni DHCP / DNS. Cerca le lettere DNS accanto a un campo che consente due o tre serie di numeri, ciascuno suddiviso in quattro gruppi di 1-3 cifre.", "install_devices_router_list_3": "Inserisci qui gli indirizzi del tuo server AdGuard Home.", - "install_devices_router_list_4": "Non puoi impostare un server DNS personalizzato o alcun tipo di router. In questi casi potrebbe essere di aiuto impostare la pagina principale di AdGuard come server DHCP. In alternativa, dovresti cercare sul manuale il modo per personalizzare i server DNS per il tuo particolare modello di router.", + "install_devices_router_list_4": "Non puoi impostare un server DNS personalizzato o alcun tipo di router. In questi casi potrebbe essere di aiuto impostare la pagina principale di AdGuard come <0>server DHCP. In alternativa, dovresti cercare sul manuale il modo per personalizzare i server DNS per il tuo particolare modello di router.", "install_devices_windows_list_1": "Aprire il Pannello di controllo tramite il menu Start o la ricerca di Windows.", "install_devices_windows_list_2": "Vai a Rete e categoria Internet e poi a Centro connessioni di rete e condivisione.", "install_devices_windows_list_3": "Sul lato sinistro dello schermo, trova le impostazioni della scheda Cambia e fai clic su di esso.", @@ -346,6 +363,7 @@ "form_enter_id": "Inserisci identificatore", "form_add_id": "Aggiungi identificatore", "form_client_name": "Inserisci nome client", + "name": "Nome", "client_global_settings": "Usa le impostazioni globali", "client_deleted": "Client \"{{key}}\" eliminato correttamente", "client_added": "Client \"{{key}}\" aggiunto correttamente", @@ -445,6 +463,7 @@ "location": "Locazione", "orgname": "Nome dell'organizzazione", "netname": "Nome Network", + "network": "Rete", "descr": "Descrizione", "whois": "Chi è", "filtering_rules_learn_more": "<0>Leggi altro su come creare i tuoi host blacklist.", @@ -489,5 +508,19 @@ "list_updated": "{{count}} lista aggiornata", "list_updated_plural": "{{count}} liste aggiornate", "dnssec_enable": "Abilita DNSSEC", - "dnssec_enable_desc": "Imposta la spunta DNSSEC nelle interrogazioni DNS in uscita e verifica il risultato (è richiesta l'attivazione del risolutore DNSSEC)" -} + "dnssec_enable_desc": "Imposta la spunta DNSSEC nelle interrogazioni DNS in uscita e verifica il risultato (è richiesta l'attivazione del risolutore DNSSEC)", + "validated_with_dnssec": "Verificato con DNSSEC", + "show_all_responses": "Tutti i responsi", + "show_blocked_responses": "Bloccato", + "show_whitelisted_responses": "Nella whitelist", + "show_processed_responses": "Processato", + "blocked_safebrowsing": "Blocco Navigazione sicura", + "blocked_adult_websites": "Siti per adulti bloccati", + "blocked_threats": "Minacce bloccate", + "allowed": "Consentito", + "filtered": "Filtrato", + "rewritten": "Riscritto", + "safe_search": "Ricerca sicura", + "blocklist": "Lista di blocco", + "milliseconds_abbreviation": "ms" +} \ No newline at end of file diff --git a/client/src/__locales/ja.json b/client/src/__locales/ja.json index 3783311d..d88fc067 100644 --- a/client/src/__locales/ja.json +++ b/client/src/__locales/ja.json @@ -3,6 +3,8 @@ "example_upstream_reserved": "<0>特定のドメインに対してDNSアップストリームを指定できます", "upstream_parallel": "並列リクエストを使用する(すべてのアップストリームサーバーを同時に照会することで解決スピードが向上します)", "parallel_requests": "並列リクエスト", + "load_balancing": "ロードバランシング", + "load_balancing_desc": "一度に1つのサーバを照会します。 AdGuard Homeは、重み付きランダムアルゴリズムを使用してサーバを選択するため、最速のサーバがより頻繁に使用されます。", "bootstrap_dns": "ブートストラップDNSサーバ", "bootstrap_dns_desc": "ブートストラップDNSサーバは、上流として指定したDoH/DoTリゾルバのIPアドレスを解決するために使用されます。", "check_dhcp_servers": "DHCPサーバをチェックする", @@ -37,6 +39,7 @@ "dhcp_interface_select": "DHCPインタフェースの選択", "dhcp_hardware_address": "MACアドレス", "dhcp_ip_addresses": "IPアドレス", + "ip": "IP", "dhcp_table_hostname": "ホスト名", "dhcp_table_expires": "有効期限", "dhcp_warning": "内蔵しているDHCPサーバを有効にしたい場合は、稼働中のDHCPサーバがないことを確認してください。そうでなければ、接続されたデバイスのためにインターネットを壊すかもしれません!", @@ -49,17 +52,26 @@ "dhcp_static_leases_not_found": "DHCP静的割り当てはありません", "dhcp_add_static_lease": "静的割り当てを追加する", "dhcp_reset": "DHCP設定をリセットして良いですか?", + "country": "国", + "city": "街", "delete_confirm": "\"{{key}}\" を削除してもよろしいですか?", "form_enter_hostname": "ホスト名を入力してください", "error_details": "エラー詳細", + "response_details": "応答の詳細", + "request_details": "要求の詳細", + "client_details": "クライアントの詳細", + "details": "詳細", "back": "戻る", "dashboard": "ダッシュボード", "settings": "設定", "filters": "フィルタ", + "filter": "フィルタ", "query_log": "クエリ・ログ", + "empty_log": "クエリ・ログは空です", "faq": "よくある質問", "version": "バージョン", "address": "アドレス", + "protocol": "プロトコル", "on": "オン", "off": "オフ", "copyright": "著作権", @@ -132,8 +144,10 @@ "rules_count_table_header": "ルール数", "last_time_updated_table_header": "最終更新時刻", "actions_table_header": "操作", + "request_table_header": "リクエスト", "edit_table_action": "編集する", "delete_table_action": "削除する", + "elapsed": "経過", "filters_and_hosts_hint": "AdGuard Homeは、基本的な広告ブロックルールとhostsファイルの構文を理解します。", "no_blocklist_added": "ブロックリストには何も追加されていません", "no_whitelist_added": "許可リストには何も追加されていません", @@ -170,10 +184,12 @@ "updated_upstream_dns_toast": "上流DNSサーバを更新しました", "dns_test_ok_toast": "指定されたDNSサーバは正しく動作しています", "dns_test_not_ok_toast": "サーバ \"{{key}}\": 使用できませんでした。正しく入力されているかどうかを確認してください", - "unblock_btn": "ブロック解除", - "block_btn": "ブロックする", + "unblock": "ブロック解除", + "block": "ブロック", "time_table_header": "時刻", + "date": "購入日時", "domain_name_table_header": "ドメイン名", + "domain_or_client": "ドメインまたはクライアント", "type_table_header": "種類", "response_table_header": "応答", "client_table_header": "クライアント", @@ -211,6 +227,9 @@ "custom_ip": "カスタムIP", "blocking_ipv4": "ブロック中のIPv4", "blocking_ipv6": "ブロック中のIPv6", + "dns_over_https": "DNS-over-HTTPS", + "dns_over_tls": "DNS-over-TLS", + "plain_dns": "通常のDNS", "form_enter_rate_limit": "頻度制限を入力してください", "rate_limit": "頻度制限", "edns_enable": "EDNSクライアント・サブネットを有効にする", @@ -229,6 +248,7 @@ "rule_label": "ルール", "list_label": "リスト", "unknown_filter": "不明なフィルタ {{filterId}}", + "known_tracker": "既知のトラッカー", "install_welcome_title": "ようこそ、AdGuard Home へ!", "install_welcome_desc": "AdGuard Homeは、ネットワーク全体で広告と追跡をブロックするDNSサーバです。その目的は、ネットワークとデバイスのすべてをあなたが制御できるようにすることであり、クライアント側のプログラムを使用する必要はありません。", "install_settings_title": "管理用ウェブインターフェイス", @@ -257,7 +277,7 @@ "install_devices_router_list_1": "ルータの設定を開きます。通常は、URL(http://192.168.0.1/ または http://192.168.1.1/ など)を介してブラウザからアクセスできます。パスワードの入力を求められることがあります。パスワードを覚えていない場合は、ルータにあるボタンを押してパスワードをリセットできます。一部のルータは特定のアプリケーションを必要とします。その場合、アプリケーションはあなたのコンピュータ/電話に既にインストールされているはずです。", "install_devices_router_list_2": "DHCP/DNSの設定を見つけます。DNSの文字のある入力欄を探します。それは、1〜3桁の数字で4つのグループに分けられた入力欄で、2〜3セットを許可されている欄です。", "install_devices_router_list_3": "そこにAdGuard Homeサーバのアドレスを入力します。", - "install_devices_router_list_4": "一部のタイプのルータではカスタムDNSサーバを設定できません。この場合、AdGuard HomeをDHCPサーバとして設定することがおすすめです。それ以外の場合は、特定のルータモデルに合わせてDNSサーバをカスタマイズする方法に関するマニュアルを検索する必要があります。", + "install_devices_router_list_4": "一部のタイプのルータではカスタムDNSサーバを設定できません。この場合、AdGuard Homeを<0>DHCPサーバとして設定するとお役に立ちます。それ以外の場合は、特定のルータモデルに合わせてDNSサーバをカスタマイズする方法に関するマニュアルを検索する必要があります。", "install_devices_windows_list_1": "「スタート」メニューまたはWindowsの検索から「設定」を開きます。", "install_devices_windows_list_2": "「ネットワークとインターネット」カテゴリに移動し、さらに「ネットワークと共有センター」へ移動します。", "install_devices_windows_list_3": "画面の左側にある「アダプターの設定の変更」を見つけてクリックします。", @@ -346,6 +366,7 @@ "form_enter_id": "識別子を入力してください", "form_add_id": "識別子を追加する", "form_client_name": "クライアント名を入力してください", + "name": "名前", "client_global_settings": "グローバル設定を使用する", "client_deleted": "クライアント \"{{key}}\" の削除に成功しました", "client_added": "クライアント \"{{key}}\" の追加に成功しました", @@ -361,6 +382,8 @@ "access_allowed_desc": "CIDRまたはIPアドレスのリスト。設定されると、AdGuard HomeはこれらのIPアドレスからのリクエストのみを許可します。", "access_disallowed_title": "拒否するクライアント", "access_disallowed_desc": "CIDRまたはIPアドレスのリスト。設定されると、AdGuard HomeはこれらのIPアドレスからのリクエストを破棄します。", + "access_blocked_title": "拒否するドメイン", + "access_blocked_desc": "これをフィルタと混同しないでください。AdGuard Homeは、これらのドメインを含むDNSクエリを破棄します。", "access_settings_saved": "アクセス設定の保存に成功しました", "updates_checked": "アップデートの確認に成功しました", "updates_version_equal": "AdGuard Homeは既に最新です", @@ -443,6 +466,7 @@ "location": "ロケーション", "orgname": "組織名", "netname": "ネットワーク名", + "network": "ネットワーク", "descr": "説明", "whois": "Whois", "filtering_rules_learn_more": "独自ホストリストの作成についての<0>詳細はこちら。", @@ -486,5 +510,20 @@ "confirm_static_ip": "AdGuard Homeは、{{ip}}を静的IPアドレスとして設定します。よろしいですか?", "list_updated": "{{count}}個のリストが更新されました", "list_updated_plural": "{{count}}個のリストが更新されました", - "dnssec_enable": "DNSSECを有効にする" -} + "dnssec_enable": "DNSSECを有効にする", + "dnssec_enable_desc": "DNSクエリの応答にDNSSECフラグを設定し、結果を確認します(DNSSEC対応のリゾルバが必要です)", + "validated_with_dnssec": "DNSSECにて検証済", + "show_all_responses": "すべての応答", + "show_blocked_responses": "ブロック済", + "show_whitelisted_responses": "ホワイトリストにあり", + "show_processed_responses": "処理済", + "blocked_safebrowsing": "ブロックされたセーフブラウジング", + "blocked_adult_websites": "ブロックされたアダルトウェブサイト", + "blocked_threats": "ブロックされた脅威", + "allowed": "許可", + "filtered": "フィルタで処理", + "rewritten": "書換", + "safe_search": "セーフサーチ", + "blocklist": "ブロックリスト", + "milliseconds_abbreviation": "ms" +} \ No newline at end of file diff --git a/client/src/__locales/ko.json b/client/src/__locales/ko.json index 6b3b7636..bc6f4e3d 100644 --- a/client/src/__locales/ko.json +++ b/client/src/__locales/ko.json @@ -37,6 +37,7 @@ "dhcp_interface_select": "DHCP 인터페이스 선택", "dhcp_hardware_address": "하드웨어 주소", "dhcp_ip_addresses": "IP 주소", + "ip": "IP", "dhcp_table_hostname": "호스트 이름", "dhcp_table_expires": "만료", "dhcp_warning": "DHCP 서버를 사용하려면 네트워크에 다른 활성 DHCP 서버가 없는지 확인해주세요. 다른 활성 DHCP 서버가 있다면, 연결된 장치의 인터넷을 끊을 수 있습니다.", @@ -49,17 +50,24 @@ "dhcp_static_leases_not_found": "DHCP 고정 임대를 찾을 수 없음", "dhcp_add_static_lease": "고정 임대 추가", "dhcp_reset": "정말로 DHCP 설정을 초기화할까요?", + "country": "지역", "delete_confirm": "\"{{key}}\"을 삭제하시겠습니까?", "form_enter_hostname": "호스트 이름을 입력해주세요", "error_details": "오류 상세 정보", + "request_details": "요청 세부 사항", + "client_details": "클라이언트 정보", + "details": "정보", "back": "뒤로", "dashboard": "대시보드", "settings": "설정", "filters": "필터", + "filter": "필터", "query_log": "쿼리 로그", + "empty_log": "질의 로그가 비어있음", "faq": "자주 묻는 질문", "version": "버전", "address": "주소", + "protocol": "프로토콜", "on": "ON", "off": "OFF", "copyright": "Copyright", @@ -132,8 +140,10 @@ "rules_count_table_header": "규칙 개수", "last_time_updated_table_header": "마지막 업데이트", "actions_table_header": "가능한 동작", + "request_table_header": "요청", "edit_table_action": "편집", "delete_table_action": "삭제", + "elapsed": "소요", "filters_and_hosts_hint": "AdGuard Home은 기본적인 광고 차단 규칙과 호스트 파일 문법을 읽을 수 있습니다", "no_blocklist_added": "차단 목록이 추가되지 않음", "no_whitelist_added": "허용 목록이 추가되지 않음", @@ -170,10 +180,12 @@ "updated_upstream_dns_toast": "업스트림 DNS 서버를 업데이트하였습니다", "dns_test_ok_toast": "특정 DNS 서버들은 정상적으로 동작 중입니다", "dns_test_not_ok_toast": "서버 \"{{key}}\": 사용할 수 없습니다, 제대로 작성했는지 확인하세요.", - "unblock_btn": "차단 해제", - "block_btn": "차단", + "unblock": "차단 해제", + "block": "차단", "time_table_header": "시간", + "date": "날짜", "domain_name_table_header": "도메인명", + "domain_or_client": "도메인 또는 클라이언트", "type_table_header": "유형", "response_table_header": "응답", "client_table_header": "클라이언트", @@ -211,6 +223,8 @@ "custom_ip": "사용자 지정 IP", "blocking_ipv4": "IPv4 차단", "blocking_ipv6": "IPv6 차단", + "dns_over_https": "DNS-over-HTTPS", + "dns_over_tls": "DNS-over-TLS", "form_enter_rate_limit": "한도 제한 입력하기", "rate_limit": "한도 제한", "edns_enable": "EDNS 클라이언트 서브넷 활성화", @@ -229,6 +243,7 @@ "rule_label": "규칙", "list_label": "목록", "unknown_filter": "알려지지 않은 필터 {{filterId}}", + "known_tracker": "알려진 추적기", "install_welcome_title": "AdGuard Home에 오신 것을 환영합니다!", "install_welcome_desc": "AdGuard Home은 광범위한 네트워크 광고와 추적 DNS 서버를 차단 합니다. 그것의 목적은 당신이 당신의 전체 네트워크와 당신의 모든 기기를 제어하는 것이며, 그것은 클라이언트의 프로그램을 사용할 필요가 없습니다.", "install_settings_title": "관리자 웹 인터페이스", @@ -257,7 +272,7 @@ "install_devices_router_list_1": "라우터의 환경 설정을 여세요. 환경 설정은 다음의 주소(http://192.168.0.1/ 혹은 http://192.168.1.1/)를 통해 브라우저로 접근 가능합니다. 비밀번호를 입력해야할 수 있습니다. 비밀번호를 잊었다면 대개 라우터 기기에 있는 버튼을 눌러 비밀번호를 초기화할 수 있습니다. 어떤 라우터들은 당신의 컴퓨터/핸드폰에 설치할 수 있는 특정 어플리케이션을 필요로합니다.", "install_devices_router_list_2": "각각 1~3자리 숫자의 네 그룹으로 분할된 두 세트의 숫자를 허용하는 필드 옆에 있는 DNS 문자를 찾으세요.", "install_devices_router_list_3": "AdGuard Home 서버 주소를 입력하세요", - "install_devices_router_list_4": "일부 라우터는 DNS서버의 커스텀 설정이 불가합니다. 간혹 AdGuard Home을 DHCP서버로 이용하여 문제를 해결하는 경우가 있지만 문제가 지속될 경우 사용하시는 라우터 모델의 매뉴얼을 참고하시어 DNS서버 커스텀 설정 방법을 직접 살펴보셔야 합니다.", + "install_devices_router_list_4": "일부 라우터는 DNS서버의 커스텀 설정이 불가합니다. 간혹 AdGuard Home을 DHCP서버로 이용하여 문제를 해결하는 경우가 있지만 문제가 지속될 경우 사용하시는 라우터 모델의 매뉴얼을 참고하시어 <0>DNS서버 커스텀 설정 방법을 직접 살펴보셔야 합니다.", "install_devices_windows_list_1": "시작 메뉴 또는 윈도우 검색을 통해 제어판을 여세요", "install_devices_windows_list_2": "네트워크 및 인터넷 카테고리로 이동한 다음 네트워크 및 공유 센터로 이동하세요.", "install_devices_windows_list_3": "화면 왼쪽에서 어댑터 설정 변경을 찾아 클릭하세요.", @@ -346,6 +361,7 @@ "form_enter_id": "식별자 입력", "form_add_id": "식별자 추가", "form_client_name": "클라이언트 이름 입력", + "name": "이름", "client_global_settings": "글로벌 설정 사용", "client_deleted": "클라이언트 \"{{key}}\"가 정상적으로 삭제되었습니다", "client_added": "클라이언트 \"{{key}}\"가 정상적으로 추가되었습니다", @@ -445,6 +461,7 @@ "location": "위치", "orgname": "단체 이름", "netname": "네트워크 이름", + "network": "네트워크", "descr": "설명", "whois": "후이즈", "filtering_rules_learn_more": "차단 리스트를 직접 호스트하는 법을 <0>알아보세요.", @@ -489,5 +506,19 @@ "list_updated": "{{count}} 리스트 업데이트됨", "list_updated_plural": "{{count}} 리스트 업데이트됨", "dnssec_enable": "DNSSEC 활성화", - "dnssec_enable_desc": "발신 DNS 쿼리에서 DNSSEC 플래그를 설정하고 결과를 확인합니다 (DNSSEC-enabled resolver 필수)" + "dnssec_enable_desc": "발신 DNS 쿼리에서 DNSSEC 플래그를 설정하고 결과를 확인합니다 (DNSSEC-enabled resolver 필수)", + "validated_with_dnssec": "DNSSEC로 검증됨", + "show_all_responses": "모든 응답", + "show_blocked_responses": "차단됨", + "show_whitelisted_responses": "예외 적용됨", + "show_processed_responses": "처리됨", + "blocked_safebrowsing": "차단된 세이프 브라우징", + "blocked_adult_websites": "차단된 성인 웹사이트", + "blocked_threats": "차단된 위협", + "allowed": "허용됨", + "filtered": "필터링됨", + "rewritten": "재작성됨", + "safe_search": "세이프 서치", + "blocklist": "차단 목록", + "milliseconds_abbreviation": "ms" } \ No newline at end of file diff --git a/client/src/__locales/nl.json b/client/src/__locales/nl.json index a21d2ace..5b6bbf38 100644 --- a/client/src/__locales/nl.json +++ b/client/src/__locales/nl.json @@ -3,6 +3,8 @@ "example_upstream_reserved": "Je kan DNS upstream <0>specifiëren voor specifieke domein(en)", "upstream_parallel": "Gebruik parallelle verzoeken om te versnellen door gelijktijdig verzoeken te sturen naar alle upstream servers", "parallel_requests": "Parallelle verzoeken", + "load_balancing": "Volume balanceren", + "load_balancing_desc": "Eén server per keer bevragen. AdGuard Home gebruikt hiervoor een gewogen willekeurig algoritme om de server te kiezen zodat de snelste server meer zal gebruikt worden.", "bootstrap_dns": "Bootstrap DNS servers", "bootstrap_dns_desc": "Bootstrap DNS-servers worden gebruikt om IP-adressen op te lossen van de DoH / DoT-resolvers die u opgeeft als upstreams.", "check_dhcp_servers": "Zoek achter DHCP servers", @@ -36,6 +38,7 @@ "dhcp_interface_select": "Selecteer DHCP interface", "dhcp_hardware_address": "Hardware adres", "dhcp_ip_addresses": "IP adressen", + "ip": "IP", "dhcp_table_hostname": "Host naam", "dhcp_table_expires": "Verloopt op", "dhcp_warning": "Indien je de ingebouwde DHCP server wilt inschakelen, let dan op dat er geen andere actieve DHCP server aanwezig is. Dit kan de internet verbinding instabiel maken!.", @@ -48,17 +51,26 @@ "dhcp_static_leases_not_found": "Geen DHCP static lease gevonden", "dhcp_add_static_lease": "Voeg statische lease toe", "dhcp_reset": "Weet je zeker dat je de DHCP configuratie wil resetten?", + "country": "Land", + "city": "Stad", "delete_confirm": "Ben je zeker dat je \"{{key}}\" wilt verwijderen?", "form_enter_hostname": "Vul hostnaam in", "error_details": "Fout details", + "response_details": "Antwoorddetails", + "request_details": "Verzoekdetails", + "client_details": "Client details", + "details": "Details", "back": "Terug", "dashboard": "Dashboard", "settings": "Instellingen", "filters": "Filters", + "filter": "Filter", "query_log": "Query log", + "empty_log": "Logboek leeg", "faq": "Veel gestelde vragen", "version": "Versie", - "address": "IP-adres", + "address": "Adres", + "protocol": "Protocol", "on": "Aan", "off": "Uit", "copyright": "Copyright", @@ -131,8 +143,10 @@ "rules_count_table_header": "Aantal regels", "last_time_updated_table_header": "Laatste update", "actions_table_header": "Actie", + "request_table_header": "Verzoek", "edit_table_action": "Bewerk", "delete_table_action": "Verwijderen", + "elapsed": "Verstreken", "filters_and_hosts_hint": "AdGuard Home kan overweg met basic adblock regels en hosts bestanden syntaxis.", "no_blocklist_added": "Geen blokkeerlijsten toegevoegd", "no_whitelist_added": "Geen toestemmingslijsten toegevoegd", @@ -169,10 +183,12 @@ "updated_upstream_dns_toast": "De upstream DNS-servers zijn bijgewerkt", "dns_test_ok_toast": "Opgegeven DNS-servers werken correct", "dns_test_not_ok_toast": "Server \"{{key}}\": kon niet worden gebruikt, controleer of u het correct hebt geschreven", - "unblock_btn": "Deblokkeren", - "block_btn": "Blokkeren", + "unblock": "Deblokkeren", + "block": "Blokkeren", "time_table_header": "Tijd", + "date": "Datum", "domain_name_table_header": "Domein naam", + "domain_or_client": "Domein of cliënt", "type_table_header": "Type", "response_table_header": "Antwoord", "client_table_header": "Gebruiker", @@ -202,13 +218,17 @@ "query_log_retention_confirm": "Weet u zeker dat u de bewaartermijn van het query logboek wilt wijzigen? Als u de intervalwaarde verlaagt, gaan sommige gegevens verloren", "anonymize_client_ip": "Cliënt IP anonimiseren", "anonymize_client_ip_desc": "Het volledige IP-adres van de cliënt niet opnemen in log- en statistiekbestanden", + "default": "Standaard", "custom_ip": "Aangepast IP", + "dns_over_https": "DNS-via-HTTPS", + "dns_over_tls": "DNS-via-TLS", "source_label": "Bron", "found_in_known_domain_db": "Gevonden in de bekende domeingegevensbank.", "category_label": "Categorie", "rule_label": "Regel", "list_label": "Lijst", "unknown_filter": "Onbekend filter {{filterId}}", + "known_tracker": "Bekende volger", "install_welcome_title": "Welkom bij AdGuard Home!", "install_welcome_desc": "AdGuard Home is een netwerk DNS server die advertenties en trackers blokkeert. Het doel is om jou controle te geven over je gehele netwerk en al je apparaten, en er hoeft geen client-side programma te worden gebruikt.", "install_settings_title": "Admin webinterface", @@ -237,7 +257,7 @@ "install_devices_router_list_1": "Open de instellingen pagina voor uw router. Meestal kunt u deze vanuit uw browser openen via een URL (zoals http://192.168.0.1/ of http://192.168.1.1/). Mogelijk wordt u gevraagd om het wachtwoord in te voeren. Als u het niet meer weet, kunt u het wachtwoord vaak opnieuw instellen door op een knop op de router zelf te drukken. Voor sommige routers is een specifieke toepassing vereist, die in dat geval al op uw computer / telefoon moet zijn geïnstalleerd.", "install_devices_router_list_2": "Zoek de DHCP/DNS-instellingen. Zoek naar de DNS-letters naast een veld dat twee of drie reeksen nummers toestaat, elk verdeeld in vier groepen van één tot drie cijfers.", "install_devices_router_list_3": "Voer je AdGuard Home server adressen daar in.", - "install_devices_router_list_4": "Je kan de DNS server niet aanpassen op sommige routers. In dat geval kan het een oplossing zijn om AdGuard Home te definiëren als een DHCP server. Je kan ook in de handleiding van je router kijken hoe je een DNS server aanpast.", + "install_devices_router_list_4": "Je kan de DNS server niet aanpassen op sommige routers. In dat geval kan het een oplossing zijn om AdGuard Home te definiëren als een <0>DHCP server. Je kan ook in de handleiding van je router kijken hoe je een DNS server aanpast.", "install_devices_windows_list_1": "Open het Configuratiescherm via het menu Start of Windows zoeken.", "install_devices_windows_list_2": "Ga naar de categorie Netwerk en Internet en vervolgens naar Netwerkcentrum.", "install_devices_windows_list_3": "Zoek aan de linkerkant van het scherm Adapter-instellingen wijzigen en klik erop.", @@ -326,6 +346,7 @@ "form_enter_id": "ID invoeren", "form_add_id": "ID toevoegen", "form_client_name": "Vul gebruikersnaam in", + "name": "Naam", "client_global_settings": "Gebruik globale instelling", "client_deleted": "Gebruiker \"{{key}}\" met succes verwijderd", "client_added": "Gebruiker \"{{key}}\" met succes toegevoegd", @@ -425,6 +446,7 @@ "location": "Locatie", "orgname": "Naam organisatie", "netname": "Netwerk naam", + "network": "Netwerk", "descr": "Beschrijving", "whois": "Whois", "filtering_rules_learn_more": "<0>Meer informatie over het maken van je eigen host lijsten.", @@ -446,5 +468,18 @@ "check_service": "Servicenaam: {{service}}", "list_updated": "{{count}} lijst geüpdatet", "list_updated_plural": "{{count}} lijsten geüpdatet", - "dnssec_enable": "DNSSEC inschakelen" -} + "dnssec_enable": "DNSSEC inschakelen", + "validated_with_dnssec": "Gevalideerd met DNSSEC", + "show_all_responses": "Alle reacties", + "show_blocked_responses": "Geblokkeerd", + "show_whitelisted_responses": "Op toestemmingslijst", + "show_processed_responses": "Verwerkt", + "blocked_adult_websites": "Geblokkeerde 18+ websites", + "blocked_threats": "Geblokkeerde bedreigingen", + "allowed": "Toegestaan", + "filtered": "Gefilterd", + "rewritten": "Herschreven", + "safe_search": "Veilig zoeken", + "blocklist": "Blokkeerlijst", + "milliseconds_abbreviation": "ms" +} \ No newline at end of file diff --git a/client/src/__locales/no.json b/client/src/__locales/no.json index ccd189b0..319cb917 100644 --- a/client/src/__locales/no.json +++ b/client/src/__locales/no.json @@ -51,14 +51,17 @@ "delete_confirm": "Er du sikker på at du vil slette «{{key}}»?", "form_enter_hostname": "Skriv inn vertsnavnet", "error_details": "Feildetaljer", + "request_details": "Detaljer over forespørsel", + "details": "Detaljer", "back": "Tilbake", "dashboard": "Kontrollsenter", "settings": "Innstillinger", "filters": "Filtre", + "filter": "Filter", "query_log": "Forespørselslogg", "faq": "OSS", "version": "Versjon", - "address": "adresse", + "address": "Adresse", "on": "PÅ", "off": "AV", "copyright": "Opphavsrett", @@ -167,9 +170,10 @@ "updated_upstream_dns_toast": "Oppdaterte oppstrøms-DNS-tjenerne", "dns_test_ok_toast": "De spesifiserte DNS-tjenerne fungerer riktig", "dns_test_not_ok_toast": "Tjeneren «{{key}}» kunne ikke brukes, vennligst dobbeltsjekk at du har skrevet den riktig", - "unblock_btn": "Tillat", - "block_btn": "Blokker", + "unblock": "Tillat", + "block": "Blokker", "time_table_header": "Tidspunkt", + "date": "Dato", "domain_name_table_header": "Domenenavn", "type_table_header": "Type", "response_table_header": "Respons", @@ -206,6 +210,7 @@ "custom_ip": "Tilpasset IP", "blocking_ipv4": "IPv4-blokkering", "blocking_ipv6": "IPv6-blokkering", + "dns_over_tls": "DNS-over-TLS", "form_enter_rate_limit": "Skriv inn forespørselsfrekvensgrense", "rate_limit": "Forespørselsfrekvensgrense", "edns_enable": "Aktiver EDNS-klientundernett", @@ -340,6 +345,7 @@ "form_enter_id": "Skriv inn identifikator", "form_add_id": "Legg til identifikator", "form_client_name": "Skriv inn klientnavnet", + "name": "Navn", "client_global_settings": "Bruk de overbestyrte innstillingene", "client_deleted": "Klienten «{{key}}» ble vellykket slettet", "client_added": "Klienten «{{key}}» ble vellykket lagt til", @@ -438,6 +444,7 @@ "location": "Posisjon", "orgname": "Firmanavn", "netname": "Nettverksnavn", + "network": "Network", "descr": "Beskrivelse", "whois": "Whois", "filtering_rules_learn_more": "<0>Lær mer om å lage dine egne filterlister for AdGuard Home.", @@ -478,5 +485,11 @@ "install_static_configure": "Vi har oppdaget at det brukes en dynamisk IP-adresse — <0>{{ip}}. Vil du bruke det som din statiske adresse?", "confirm_static_ip": "AdGuard Home vil sette opp {{ip}} til å bli din statiske IP-adresse. Vil du fortsette?", "list_updated": "{{count}} liste oppdatert", - "list_updated_plural": "{{count}} lister oppdatert" + "list_updated_plural": "{{count}} lister oppdatert", + "show_blocked_responses": "Blokkért", + "show_processed_responses": "Bearbeidet", + "blocked_adult_websites": "Blokkerte voksennettsteder", + "blocked_threats": "Blokkerte trusler", + "allowed": "Unntak", + "blocklist": "Blokkeringsliste" } \ No newline at end of file diff --git a/client/src/__locales/pl.json b/client/src/__locales/pl.json index 19061fbf..db23df06 100644 --- a/client/src/__locales/pl.json +++ b/client/src/__locales/pl.json @@ -37,6 +37,7 @@ "dhcp_interface_select": "Wybierz interfejs DHCP", "dhcp_hardware_address": "Adres sprzętowy", "dhcp_ip_addresses": "Adresy IP", + "ip": "Adres IP", "dhcp_table_hostname": "Nazwa hosta", "dhcp_table_expires": "Wygasa", "dhcp_warning": "Aby włączyć wbudowany serwer DHCP, upewnij się, że nie ma innego aktywnego serwera DHCP. W przeciwnym razie może przerwać połączenie internetowe dla podłączonych urządzeń!", @@ -49,17 +50,23 @@ "dhcp_static_leases_not_found": "Nie znaleziono statycznych dzierżaw DHCP", "dhcp_add_static_lease": "Dodaj dzierżawę statyczną", "dhcp_reset": "Czy na pewno chcesz zresetować konfigurację DHCP?", + "country": "Kraj", + "city": "Miasto", "delete_confirm": "Czy na pewno chcesz usunąć \"{{key}}\"?", "form_enter_hostname": "Wpisz nazwę hosta", "error_details": "Szczegóły błędu", + "client_details": "Szczegóły klienta", + "details": "Szczegóły", "back": "Wróć", "dashboard": "Panel kontrolny", "settings": "Ustawienia", "filters": "Filtry", + "filter": "Filtr", "query_log": "Dziennik zapytań", + "empty_log": "Dziennik zapytań jest pusty", "faq": "FAQ", "version": "wersja", - "address": "adres", + "address": "Adres", "on": "WŁĄCZONY", "off": "WYŁĄCZONY", "copyright": "Prawo autorskie", @@ -132,8 +139,10 @@ "rules_count_table_header": "Liczba reguł", "last_time_updated_table_header": "Ostatnia aktualizacja", "actions_table_header": "Akcje", + "request_table_header": "Żądanie", "edit_table_action": "Edytuj", "delete_table_action": "Usuń", + "elapsed": "Upłynęło", "filters_and_hosts_hint": "AdGuard Home rozumie podstawowe reguły adblocka i składnię plików hostów.", "no_blocklist_added": "Nie dodano listy zablokowanych", "no_whitelist_added": "Nie dodano listy dozwolonych", @@ -170,10 +179,12 @@ "updated_upstream_dns_toast": "Główne serwery DNS zostały zaktualizowane", "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", - "unblock_btn": "Odblokuj", - "block_btn": "Zablokuj", + "unblock": "Odblokuj", + "block": "Zablokuj", "time_table_header": "Czas", + "date": "Data", "domain_name_table_header": "Nazwa domeny", + "domain_or_client": "Domena lub klient", "type_table_header": "Typ", "response_table_header": "Odpowiedź ", "client_table_header": "Klient", @@ -211,6 +222,8 @@ "custom_ip": "Niestandardowy adres IP", "blocking_ipv4": "Blokowanie IPv4", "blocking_ipv6": "Blokowanie IPv6", + "dns_over_https": "DNS-over-HTTPS", + "dns_over_tls": "DNS-over-TLS", "form_enter_rate_limit": "Wpisz limit ilościowy", "rate_limit": "Limit ilościowy", "edns_enable": "Włącz podsieć klienta EDNS", @@ -229,6 +242,7 @@ "rule_label": "Reguła", "list_label": "Lista", "unknown_filter": "Nieznany filtr {{filterId}}", + "known_tracker": "Znany element śledzący", "install_welcome_title": "Witaj w AdGuard Home!", "install_welcome_desc": "AdGuard Home to w pełni funkcjonalny serwer DNS do blokowania reklam i śledzenia. Jego celem jest kontrolowanie całej sieci i wszystkich urządzeń, bez konieczności korzystania z jakiegokolwiek programu po stronie klienta.", "install_settings_title": "Interfejs internetowy administratora", @@ -257,7 +271,7 @@ "install_devices_router_list_1": "Otwórz ustawienia routera. Zazwyczaj możesz uzyskać do niego dostęp przez przeglądarkę za pośrednictwem adresu URL (na przykład http://192.168.0.1/ lub http://192.168.1.1/). Możesz zostać poproszony o wpisanie hasła. Jeśli nie pamiętasz hasła, możesz je odzyskać, naciskając przycisk na samym routerze. Niektóre routery wymagają określonej aplikacji, która powinna być już zainstalowana na komputerze lub telefonie.", "install_devices_router_list_2": "Znajdź ustawienia DHCP/DNS. Poszukaj skrótu DNS obok pola, które pozwala wstawić dwa lub trzy zestawy liczb, z których każdy jest podzielony na cztery grupy z jedną do trzech cyfr.", "install_devices_router_list_3": "Wpisz adresy swojego serwera AdGuard Home.", - "install_devices_router_list_4": "Nie możesz ustawić niestandardowego serwera DNS na niektórych routerach. W takim przypadku może pomóc Ci skonfigurowanie AdGuard Home jako serwera DHCP. W przeciwnym razie musisz poszukać instrukcji ustawienia serwerów DNS dla konkretnego modelu routera.", + "install_devices_router_list_4": "Nie możesz ustawić niestandardowego serwera DNS na niektórych routerach. W takim przypadku może pomóc Ci skonfigurowanie AdGuard Home jako <0>serwera DHCP. W przeciwnym razie musisz poszukać instrukcji ustawienia serwerów DNS dla konkretnego modelu routera.", "install_devices_windows_list_1": "Otwórz panel Ustawienia w menu Start lub w Windows.", "install_devices_windows_list_2": "Przejdź do kategorii Sieć i Internet, a następnie do Centrum sieci i udostępniania.", "install_devices_windows_list_3": "Po lewej stronie ekranu znajdź Zmień ustawienia adaptera i kliknij na niego.", @@ -346,6 +360,7 @@ "form_enter_id": "Wpisz identyfikator", "form_add_id": "Dodaj identyfikator", "form_client_name": "Wpisz nazwę klienta", + "name": "Nazwa", "client_global_settings": "Użyj ustawień globalnych", "client_deleted": "Klient \"{{key}}\" został pomyślnie usunięty", "client_added": "Klient \"{{key}}\" został pomyślnie dodany", @@ -445,6 +460,7 @@ "location": "Lokalizacja", "orgname": "Nazwa firmy", "netname": "Nazwa sieci", + "network": "Sieć", "descr": "Opis", "whois": "Whois", "filtering_rules_learn_more": "<0>Dowiedz się więcej o tworzeniu własnych list blokowania hostów.", @@ -489,5 +505,19 @@ "list_updated": "{{count}} lista zaktualizowana", "list_updated_plural": "{{count}} list zaktualizowanych", "dnssec_enable": "Włącz DNSSEC", - "dnssec_enable_desc": "Ustaw flagę DNSSEC w wychodzących zapytaniach DNS i sprawdź wynik (wymagany jest resolver z obsługą zabezpieczania DNSSEC)" -} + "dnssec_enable_desc": "Ustaw flagę DNSSEC w wychodzących zapytaniach DNS i sprawdź wynik (wymagany jest usługodawca z obsługą zabezpieczania DNSSEC)", + "validated_with_dnssec": "Zweryfikowany przez DNSSEC", + "show_all_responses": "Wszystkie odpowiedzi", + "show_blocked_responses": "Zablokowane", + "show_whitelisted_responses": "Biała lista", + "show_processed_responses": "Przetworzono", + "blocked_safebrowsing": "Zablokowane przez bezpieczne przeglądanie", + "blocked_adult_websites": "Zablokowane witryny dla dorosłych", + "blocked_threats": "Zablokowane zagrożenia", + "allowed": "Dozwolone", + "filtered": "Filtrowane", + "rewritten": "Przepisane", + "safe_search": "Bezpieczne wyszukiwanie", + "blocklist": "Lista zablokowanych", + "milliseconds_abbreviation": "ms" +} \ No newline at end of file diff --git a/client/src/__locales/pt-br.json b/client/src/__locales/pt-br.json index a57b4d16..86c9dd7c 100644 --- a/client/src/__locales/pt-br.json +++ b/client/src/__locales/pt-br.json @@ -37,6 +37,7 @@ "dhcp_interface_select": "Selecione a interface DHCP", "dhcp_hardware_address": "Endereço de hardware", "dhcp_ip_addresses": "Endereço de IP", + "ip": "IP", "dhcp_table_hostname": "Nome do servidor", "dhcp_table_expires": "Expira", "dhcp_warning": "Se você quiser ativar o servidor DHCP, verifique se não há outro servidor DHCP ativo na sua rede. Caso contrário, a internet pode parar de funcionar para outros dispositivos conectados!", @@ -49,17 +50,22 @@ "dhcp_static_leases_not_found": "Nenhuma concessão DHCP estática foi encontrada", "dhcp_add_static_lease": "Adicionar nova concessão estática", "dhcp_reset": "Você tem certeza de que deseja redefinir a configuração DHCP?", + "country": "País", "delete_confirm": "Você tem certeza de que deseja excluir \"{{key}}\"?", "form_enter_hostname": "Digite o hostname", "error_details": "Detalhes do erro", + "client_details": "Detalhes do cliente", + "details": "Detalhes", "back": "Voltar", "dashboard": "Painel", "settings": "Configurações", "filters": "Filtros", + "filter": "Filtro", "query_log": "Registro de consultas", + "empty_log": "O registro de consulta está vazio", "faq": "FAQ", "version": "Versão", - "address": "endereço", + "address": "Endereço", "on": "Ligado", "off": "Desligado", "copyright": "Copyright", @@ -132,8 +138,10 @@ "rules_count_table_header": "Quantidade de regras", "last_time_updated_table_header": "Última atualização", "actions_table_header": "Ações", + "request_table_header": "Solicitação", "edit_table_action": "Editar", "delete_table_action": "Excluir", + "elapsed": "Tempo decorrido", "filters_and_hosts_hint": "O AdGuard Home entende regras básicas de bloqueio de anúncios e a sintaxe de arquivos de hosts.", "no_blocklist_added": "Nenhuma lista negra foi adicionada", "no_whitelist_added": "Nenhuma lista branca foi adicionada", @@ -170,10 +178,12 @@ "updated_upstream_dns_toast": "Atualizado os servidores DNS upstream", "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", - "unblock_btn": "Desbloquear", - "block_btn": "Bloquear", + "unblock": "Desbloquear", + "block": "Bloquear", "time_table_header": "Data", + "date": "Data", "domain_name_table_header": "Nome de domínio", + "domain_or_client": "Domínio ou cliente", "type_table_header": "Tipo", "response_table_header": "Resposta", "client_table_header": "Cliente", @@ -211,6 +221,8 @@ "custom_ip": "IP personalizado", "blocking_ipv4": "Bloqueando IPv4", "blocking_ipv6": "Bloqueando IPv6", + "dns_over_https": "DNS-sobre-HTTPS", + "dns_over_tls": "DNS-sobre-TLS", "form_enter_rate_limit": "Insira a taxa limite", "rate_limit": "Taxa limite", "edns_enable": "Ativar a sub-rede do cliente EDNS", @@ -229,6 +241,7 @@ "rule_label": "Regra", "list_label": "Lista", "unknown_filter": "Filtro desconhecido {{filterId}}", + "known_tracker": "Rastreador conhecido", "install_welcome_title": "Bem-vindo(a) ao AdGuard Home!", "install_welcome_desc": "O AdGuard Home é um servidor de DNS para bloqueio de anúncios e rastreamento em toda a rede. Sua finalidade é permitir que você controle toda a sua rede e seus dispositivos sem precisar ter um programa instalado.", "install_settings_title": "Interface web de administrador", @@ -257,7 +270,7 @@ "install_devices_router_list_1": "Abra as configurações do seu roteador\nNo navegador digite o IP do roteador, o padrão é (http://192.168.0.1/ ou http://192.168.1.1/), e o login e senha é admin/admin; Se você não se lembra da senha, você pode redefinir a senha rapidamente pressionando um botão no próprio roteador. Alguns roteadores têm um aplicativo específico que já deve estar instalado em seu computador/telefone.", "install_devices_router_list_2": "Encontre as Configurações de DNS. Procure as letras DNS ao lado de um campo que permite dois ou três conjuntos de números, cada um dividido em quatro grupos de um a três números.", "install_devices_router_list_3": "Digite aqui seu servidor do AdGuard Home.", - "install_devices_router_list_4": "Você não pode definir um servidor DNS personalizado em alguns tipos de roteadores. Nesse caso, pode ajudar se você configurar o AdGuard Home como um servidor DHCP. Caso contrário, você deve procurar o manual sobre como personalizar os servidores DNS para o seu modelo de roteador específico.", + "install_devices_router_list_4": "Você não pode definir um servidor DNS personalizado em alguns tipos de roteadores. Nesse caso, pode ajudar se você configurar o AdGuard Home como um <0>servidor DHCP. Caso contrário, você deve procurar o manual sobre como personalizar os servidores DNS para o seu modelo de roteador específico.", "install_devices_windows_list_1": "Abra o Painel de Controle pelo Menu Iniciar ou pela Pesquisa do Windows.", "install_devices_windows_list_2": "Entre na categoria Rede e Internet e depois clique em Central de Rede e Compartilhamento.", "install_devices_windows_list_3": "No lado esquerdo da janela clique em Alterar as configurações do adaptador.", @@ -346,6 +359,7 @@ "form_enter_id": "Inserir identificador", "form_add_id": "Adicionar identificador", "form_client_name": "Digite o nome do cliente", + "name": "Nome", "client_global_settings": "Usar configurações global", "client_deleted": "Cliente \"{{key}}\" excluído com sucesso", "client_added": "Cliente \"{{key}}\" adicionado com sucesso", @@ -445,6 +459,7 @@ "location": "Localização", "orgname": "Nome da organização", "netname": "Nome da rede", + "network": "Rede", "descr": "Descrição", "whois": "Whois", "filtering_rules_learn_more": "<0>Saiba mais sobre como criar as suas próprias listas negras de servidores.", @@ -456,7 +471,7 @@ "disable_ipv6": "Desativar IPv6", "disable_ipv6_desc": "Se este recurso estiver ativado, todas as consultas de DNS para endereços IPv6 (tipo AAAA) serão ignoradas.", "fastest_addr": "Endereço de IP mais rápido", - "fastest_addr_desc": "Consulte todos os servidores de DNS e retorne o endereço de IP mais rápido entre todas as respostas", + "fastest_addr_desc": "Consulta todos os servidores DNS e retorna o endereço IP mais rápido entre todas as respostas. Isso irá retardar as consultas ao DNS, pois temos que esperar por respostas de todos os servidores DNS, porém melhorando a conectividade em geral.", "autofix_warning_text": "Se clicar em \"Corrigir\", o AdGuardHome irá configurar o seu sistema para utilizar o servidor DNS do AdGuardHome.", "autofix_warning_list": "Ele irá realizar estas tarefas: <0>Desativar sistema DNSStubListener <0>Definir endereço do servidor DNS para 127.0.0.1 <0>Substituir o alvo simbólico do link /etc/resolv.conf para /run/systemd/resolv.conf <0>Parar DNSStubListener (recarregar serviço resolvido pelo sistema)", "autofix_warning_result": "Como resultado, todos as solicitações DNS do seu sistema serão processadas pelo AdGuardHome por padrão.", @@ -489,5 +504,19 @@ "list_updated": "{{count}} lista atualizada", "list_updated_plural": "{{count}} listas atualizadas", "dnssec_enable": "Ativar DNSSEC", - "dnssec_enable_desc": "Definir a flag DNSSEC nas consultas de DNS em andamento e verificar o resultado (é necessário um resolvedor DNSSEC ativado)" + "dnssec_enable_desc": "Definir a flag DNSSEC nas consultas de DNS em andamento e verificar o resultado (é necessário um resolvedor DNSSEC ativado)", + "validated_with_dnssec": "Validado com DNSSEC", + "show_all_responses": "Todas as respostas", + "show_blocked_responses": "Bloqueado", + "show_whitelisted_responses": "Na lista branca", + "show_processed_responses": "Processado", + "blocked_safebrowsing": "Bloqueado pela navegação segura", + "blocked_adult_websites": "Sites adultos bloqueados", + "blocked_threats": "Ameaças bloqueadas", + "allowed": "Permitido", + "filtered": "Filtrado", + "rewritten": "Reescrito", + "safe_search": "Pesquisa segura", + "blocklist": "Lista negra", + "milliseconds_abbreviation": "ms" } \ No newline at end of file diff --git a/client/src/__locales/pt-pt.json b/client/src/__locales/pt-pt.json index 0f1ad5e0..0b0b4cfe 100644 --- a/client/src/__locales/pt-pt.json +++ b/client/src/__locales/pt-pt.json @@ -58,7 +58,7 @@ "query_log": "Registo de consultas", "faq": "Perguntas frequentes", "version": "Versão", - "address": "endereço", + "address": "Endereço", "on": "LIGADO", "off": "DESLIGADO", "copyright": "Copyright", @@ -149,9 +149,10 @@ "updated_upstream_dns_toast": "A actualizar os servidores DNS upstream", "dns_test_ok_toast": "Os servidores DNS especificados estão a funcionar correctamente", "dns_test_not_ok_toast": "O servidor \"{{key}}\": não pôde ser utilizado. Por favor, verifique se o escreveu correctamente", - "unblock_btn": "Desbloquear", - "block_btn": "Bloquear", + "unblock": "Desbloquear", + "block": "Bloquear", "time_table_header": "Data", + "date": "Data", "domain_name_table_header": "Nome do domínio", "type_table_header": "Tipo", "response_table_header": "Resposta", @@ -316,6 +317,7 @@ "form_enter_id": "Inserir identificador", "form_add_id": "Adicionar identificador", "form_client_name": "Insira o nome do cliente", + "name": "Nome", "client_global_settings": "Usar configurações globais", "client_deleted": "Cliente \"{{key}}\" excluído com sucesso", "client_added": "Cliente \"{{key}}\" adicionado com sucesso", @@ -412,6 +414,7 @@ "location": "Localização", "orgname": "Nome da organização", "netname": "Nome da rede", + "network": "Network", "descr": "Descrição", "whois": "Whois", "filtering_rules_learn_more": "<0>Saiba maissobre como criar as suas próprias listas negras de servidores.", @@ -419,5 +422,9 @@ "try_again": "Tente novamente", "domain_desc": "Insere o nome do domínio para ser reescrito.", "example_rewrite_domain": "reescrever resposta apenas para este domínio.", - "example_rewrite_wildcard": "reescrever resposta para todos <0>example.org sub-domínios." + "example_rewrite_wildcard": "reescrever resposta para todos <0>example.org sub-domínios.", + "form_enter_host": "Insira o hostname", + "show_blocked_responses": "Bloqueado", + "show_whitelisted_responses": "Lista Branca", + "show_processed_responses": "Processado" } \ No newline at end of file diff --git a/client/src/__locales/ro.json b/client/src/__locales/ro.json index b3adae4b..747f9c04 100644 --- a/client/src/__locales/ro.json +++ b/client/src/__locales/ro.json @@ -1,8 +1,10 @@ { "client_settings": "Setări client", - "example_upstream_reserved": "Puteți preciza un DNS upstream <0>de domeni/u(ii) specific(e)", + "example_upstream_reserved": "Puteți preciza un DNS upstream <0>de domeniu(ii) specific(e)", "upstream_parallel": "Folosiți interogări paralele pentru rezolvări rapide interogând simultan toate serverele în amonte", "parallel_requests": "Solicitări paralele", + "load_balancing": "Echilibrare-sarcini", + "load_balancing_desc": "Fiecare server este interogat aparte. AdGuard Home alege serverul folosind algoritmul ponderat aleatoriu, astfel încât cel mai rapid server să fie utilizat mai des.", "bootstrap_dns": "Serverele DNS Bootstrap", "bootstrap_dns_desc": "Serverele DNS Bootstrap sunt folosite pentru a rezolva adresele IP ale resolverelor DoH/DoT indicate ca upstreams.", "check_dhcp_servers": "Căutați servere DHCP", @@ -20,11 +22,11 @@ "dhcp_leases_not_found": "Nu s-au găsit DHCP închiriate", "dhcp_config_saved": "Configurare DHCP salvată cu succes", "form_error_required": "Câmp necesar", - "form_error_ip4_format": "Format IPv4 nevalid", - "form_error_ip6_format": "Format IPv6 nevalid", - "form_error_ip_format": "Format IP nevalid", - "form_error_mac_format": "Format MAC nevalid", - "form_error_client_id_format": "Format ID de client nevalid", + "form_error_ip4_format": "Format IPv4 invalid", + "form_error_ip6_format": "Format IPv6 invalid", + "form_error_ip_format": "Format IP invalid", + "form_error_mac_format": "Format MAC invalid", + "form_error_client_id_format": "Format ID de client invalid", "form_error_positive": "Trebuie să fie mai mare de 0", "form_error_negative": "Trebuie să fie egală cu 0 sau mai mare", "dhcp_form_gateway_input": "IP Gateway", @@ -37,6 +39,7 @@ "dhcp_interface_select": "Selectați interfața DHCP", "dhcp_hardware_address": "Adresa mașinii", "dhcp_ip_addresses": "Adrese IP", + "ip": "IP", "dhcp_table_hostname": "Hostname", "dhcp_table_expires": "Expiră", "dhcp_warning": "Dacă doriți oricum să activați serverul DHCP, verificați că nu există un alt server DHCP activ în rețeaua dvs. Altfel, poate întrerupe Internetul pe toate aparatele conectate!", @@ -49,17 +52,22 @@ "dhcp_static_leases_not_found": "Nu s-au găsit închirieri statice DHCP", "dhcp_add_static_lease": "Adăugați închiriere statică", "dhcp_reset": "Sunteți sigur că doriți să resetați configurația DHCP?", + "country": "Țara", "delete_confirm": "Sunteți sigur că doriți să ștergeți \"{{key}}\"?", "form_enter_hostname": "Intrați hostname", "error_details": "Detalii eroare", + "client_details": "Detalii client", + "details": "Detalii", "back": "Înapoi", "dashboard": "Tablou de bord", "settings": "Setări", "filters": "Filtre", + "filter": "Filtru", "query_log": "Jurnal interogări", + "empty_log": "Jurnal de interogări gol", "faq": "FAQ", "version": "Versiune", - "address": "adresă", + "address": "Adresă", "on": "ON", "off": "OFF", "copyright": "Copyright", @@ -77,7 +85,7 @@ "stats_adult": "Site-uri cu conținut adult blocate", "stats_query_domain": "Domeniile cele mai căutate", "for_last_24_hours": "în ultimele 24 ore", - "for_last_days": "în ultimele {{count}} zile", + "for_last_days": "în ultima {{count}} zi", "for_last_days_plural": "pentru ultimele {{count}} zile", "no_domains_found": "Nu s-au găsit domenii", "requests_count": "Cont interogări", @@ -99,8 +107,8 @@ "filters_block_toggle_hint": "Puteți configura regulile de blocare în setările Filtre .", "use_adguard_browsing_sec": "Utilizați serviciul Navigarea în Securitate AdGuard", "use_adguard_browsing_sec_hint": "AdGuard Home va verifica dacă domeniul este în lista negră a serviciul web de securitate de navigare. Pentru acesta va utiliza un lookup API discret: un prefix scurt al numelui de domeniu SHA256 hash este trimis serverului.", - "use_adguard_parental": "Utilizați controlul parental AdGuard", - "use_adguard_parental_hint": "AdGuard Home va verifica dacă este conținut adult pe domeniu. Utilizează aceeași API discret ca cel utilizat de serviciul de securitate de navigare.", + "use_adguard_parental": "Utilizați Controlul Parental AdGuard", + "use_adguard_parental_hint": "AdGuard Home va verifica pentru conținut adult pe domeniu. Utilizează același API discret ca cel utilizat de serviciul de securitate de navigare.", "enforce_safe_search": "Căutare protejată întărită", "enforce_save_search_hint": "AdGuard Home poate impune căutarea protejată în următoarele motoare de căutare: Google, Youtube, Bing, DuckDuckGo, Yandex, Pixabay.", "no_servers_specified": "Nu sunt specificate servere", @@ -120,8 +128,8 @@ "apply_btn": "Aplică", "disabled_filtering_toast": "Filtrare dezactivată", "enabled_filtering_toast": "Filtrare activată", - "disabled_safe_browsing_toast": "Navigare protejată dezactivată", - "enabled_safe_browsing_toast": "Navigare protejată activată", + "disabled_safe_browsing_toast": "Navigare securitară dezactivată", + "enabled_safe_browsing_toast": "Navigare securitară activată", "disabled_parental_toast": "Control parental dezactivat", "enabled_parental_toast": "Control parental activat", "disabled_safe_search_toast": "Căutare protejată dezactivată", @@ -132,8 +140,10 @@ "rules_count_table_header": "Număr de reguli", "last_time_updated_table_header": "Ultima aducere la zi", "actions_table_header": "Acțiuni", + "request_table_header": "Solicitare", "edit_table_action": "Editare", - "delete_table_action": "Sterge", + "delete_table_action": "Șterge", + "elapsed": "Scurs", "filters_and_hosts_hint": "AdGuard Home înțelege regulile de bază de blocare cât și sintaxa fișierelor hosts.", "no_blocklist_added": "Listă blocări goală", "no_whitelist_added": "Listă autorizări goală", @@ -156,24 +166,26 @@ "examples_title": "Exemple", "example_meaning_filter_block": "blochează accesul la domeniul exemplu.org și la toate subdomeniile sale", "example_meaning_filter_whitelist": "deblochează accesul la domeniul exemplu.org și la toate subdomeniile sale", - "example_meaning_host_block": "AdGuard Home va returna acum adresa 127.0.0.1 pentru domeniul example.org (dar nu și subdomeniile sale).", + "example_meaning_host_block": "AdGuard Home va returna acum adresa 127.0.0.1 pentru domeniul exemplu.org (dar nu și subdomeniile sale).", "example_comment": "! Iată cum se adăugă o descriere", "example_comment_meaning": "comentariu", "example_comment_hash": "# Astfel putem lăsa comentarii", "example_regex_meaning": "blocare acces la domenii care corespund expresiei obișnuite specificate", - "example_upstream_regular": "DNS clasic (peste UDP)", + "example_upstream_regular": "DNS clasic (over UDP)", "example_upstream_dot": "<0>DNS-over-TLS criptat", "example_upstream_doh": "<0>DNS-over-HTTPS criptat", "example_upstream_sdns": "puteți utiliza <0>DNS Stamps pentru rezolvere <1>DNSCrypt sau <2>DNS-over-HTTPS", - "example_upstream_tcp": "DNS clasic (peste TCP)", + "example_upstream_tcp": "DNS clasic (over TCP)", "all_lists_up_to_date_toast": "Toate listele sunt deja la zi", "updated_upstream_dns_toast": "Serverele DNS upstream aduse la zi", "dns_test_ok_toast": "Serverele DNS specificate funcționează corect", "dns_test_not_ok_toast": "Serverul \"{{key}}\": nu a putut fi utilizat, verificați dacă l-ați scris corect", - "unblock_btn": "Deblocați", - "block_btn": "Blocați", + "unblock": "Deblocați", + "block": "Blocați", "time_table_header": "Ora", + "date": "Data", "domain_name_table_header": "Nume domeniu", + "domain_or_client": "Domeniu sau client", "type_table_header": "Tip", "response_table_header": "Răspuns", "client_table_header": "Client", @@ -189,7 +201,7 @@ "rows_table_footer_text": "linii", "updated_custom_filtering_toast": "Reguli personalizate de filtrare aduse la zi", "rule_removed_from_custom_filtering_toast": "Regulă scoasă din regullei personalizate de filtrare", - "rule_added_to_custom_filtering_toast": "Regula adăugată la regulile de filtrare personalizate", + "rule_added_to_custom_filtering_toast": "Regulă adăugată la regulile de filtrare personalizate", "query_log_response_status": "Statut: {{value}}", "query_log_filtered": "Filtrat de {{filter}}", "query_log_confirm_clear": "Sunteți sigur că doriți să ștergeți întregul jurnal de interogări?", @@ -211,14 +223,16 @@ "custom_ip": "IP personalizat", "blocking_ipv4": "Blocarea IPv4", "blocking_ipv6": "Blocarea IPv6", + "dns_over_https": "DNS-over-HTTPS", + "dns_over_tls": "DNS-over-TLS", "form_enter_rate_limit": "Intrați limita ratei", "rate_limit": "Limita ratei", "edns_enable": "Activați clientul subnet EDNS", - "edns_cs_desc": "Dacă este activat, AdGuard Home va trimite subnet-ele clienților către serverele DNS.", + "edns_cs_desc": "Dacă este activat, AdGuard Home va trimite subnet-ul clienților către serverele DNS.", "rate_limit_desc": "Numărul de solicitări pe secundă pe care un singur client este permis să le facă (0: nelimitat)", "blocking_ipv4_desc": "Adresa IP de returnat pentru o cerere A de blocare", "blocking_ipv6_desc": "Adresa IP de returnat pentru o cerere AAAA de blocare", - "blocking_mode_default": "Implicit: Răspunde cu NXDOMAIN cînd sunt blocate de regula Adblock-style; răspunde cu adresa IP specificată în regulă când sunt blocate de regula /etc/hosts-style", + "blocking_mode_default": "Implicit: Răspunde cu NXDOMAIN când sunt blocate de regulă tip Adblock; răspunde cu adresa IP specificată în regulă când sunt blocate de regula tip /etc/hosts", "blocking_mode_nxdomain": "NXDOMAIN: Răspunde cu codul NXDOMAIN", "blocking_mode_null_ip": "IP nul: răspunde cu o adresă IP zero (0.0.0.0 pentru A; :: pentru AAAA)", "blocking_mode_custom_ip": "IP personalizat: răspunde cu o adresă IP setată manual", @@ -229,8 +243,9 @@ "rule_label": "Regulă", "list_label": "Listă", "unknown_filter": "Filtru necunoscut {{filterId}}", + "known_tracker": "Tracker cunoscut", "install_welcome_title": "Bun venit la AdGuard Home!", - "install_welcome_desc": "AdGuard Home este un server DNS care blochează anunțuri și trackere la nivel de rețea. Scopul său este de a vă da controlul pe întreaga rețea și toate aparatele dvs. și fără un program din partea clientului.", + "install_welcome_desc": "AdGuard Home este un server DNS care blochează reclame și trackere la nivel de rețea. Scopul său este de a vă da controlul pe întreaga rețea și toate aparatele dvs. și fără un program din partea clientului.", "install_settings_title": "Interfață administrator web", "install_settings_listen": "Interfață de ascultare", "install_settings_port": "Port", @@ -254,29 +269,29 @@ "install_devices_router": "Router", "install_devices_router_desc": "Această configurație va acoperi automat toate aparatele conectate la routerul de acasă și nu va trebui să le configurați manual pe fiecare.", "install_devices_address": "Serverul DNS AdGuard Home ascultă pe următoarele adrese", - "install_devices_router_list_1": "Deschideți preferințele pentru routerul dvs. De obicei, îl puteți accesa din browserul dvs. printr-o adresă URL (cum ar fi http://192.168.0.1/ sau http://192.168.1.1/). Vi se poate cere să introduceți parola. Dacă nu v-o amintiți, puteți reseta adesea parola apăsând un buton de pe routerul propriu-zis. Unele routere necesită o aplicație specifică, care în acest caz ar trebui să fie deja instalată pe computerul/telefonul dvs.", + "install_devices_router_list_1": "Deschideți preferințele pentru routerul dvs. De obicei, îl puteți accesa din browserul dvs. printr-o adresă URL (cum ar fi http://192.168.0.1/ sau http://192.168.1.1/). Vi se poate cere să intrați parola. Dacă nu v-o amintiți, puteți reseta adesea parola apăsând un buton de pe routerul propriu-zis. Unele routere necesită o aplicație specifică, care în acest caz ar trebui să fie deja instalată pe computerul/telefonul dvs.", "install_devices_router_list_2": "Găsiți setările DHCP/DNS. Căutați literele DNS lângă un câmp care să permită două sau trei seturi de numere, fiecare împărțit în patru grupuri de una până la trei cifre.", "install_devices_router_list_3": "Intrați adresele serverului dvs. AdGuard Home aici.", - "install_devices_router_list_4": "Unele routere nu permit setarea unui server DNS personalizat. În acest caz, vă poate ajuta dacă configurați AdGuard Home ca server DHCP. Dacă nu, trebuie căutat manualul modelului dvs. de router ca să aflați cum se pot personaliza serverele DNS.", + "install_devices_router_list_4": "Unele routere nu permit setarea unui server DNS personalizat. În acest caz, vă poate ajuta dacă configurați AdGuard Home ca <0>server DHCP. Dacă nu, trebuie căutat manualul modelului dvs. de router ca să aflați cum se pot personaliza serverele DNS.", "install_devices_windows_list_1": "Deschideți panoul de control prin meniul Start sau căutare Windows.", "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 faceți clic 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_5": "Găsiți Internet Protocol Versiunea 4 (TCP/IP) din listă, selectați-l și apoi faceți din nou clic 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_macos_list_1": "Faceți clic pe pictograma Apple și accesați Preferințele Sistemului.", - "install_devices_macos_list_2": "Faceți clic pe Network.", - "install_devices_macos_list_3": "Selectați prima conexiune din listă și faceți clic pe Avansat.", - "install_devices_macos_list_4": "Selectați fila DNS și introduceți adresele serverului dvs. AdGuard Home.", + "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_6": "Alegeți Utilizați următoarele adrese de server DNS și intraț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_2": "Clicați pe Network.", + "install_devices_macos_list_3": "Selectați prima conexiune din listă și clicați pe Avansat.", + "install_devices_macos_list_4": "Selectați fila DNS și intrați adresele serverului dvs. AdGuard Home.", "install_devices_android_list_1": "Din ecranul principal al Meniului Android, tapați Setări.", "install_devices_android_list_2": "Tapați Wi-Fi din meniu. Ecranul cu toate rețelele disponibile va fi afișat (este imposibil să setați DNS personalizat pentru conexiunea mobilă).", "install_devices_android_list_3": "Apăsați lung pe rețeaua la care sunteți conectat și tapați Modificare Rețea.", - "install_devices_android_list_4": "Pe unele aparate, poate fi necesar să bifați caseta Advanced pentru a vedea setările ulterioare. Pentru a ajusta setările DNS Android, va trebui să comutați setările IP de la DHCP la Static.", + "install_devices_android_list_4": "Pe unele aparate, poate fi necesar să bifați caseta Advanced pentru a vedea setările adiționale. Pentru a ajusta setările DNS Android, va trebui să comutați setările IP de la DHCP la Static.", "install_devices_android_list_5": "Schimbați valorile DNS 1 și DNS 2 la cele ale serverului dvs. AdGuard Home.", "install_devices_ios_list_1": "Din ecranul de start, tapați Setări.", "install_devices_ios_list_2": "Alegeți Wi-Fi în meniul din stânga (este imposibil să configurați DNS pentru rețelele mobile).", "install_devices_ios_list_3": "Tapați numele rețelei active curente.", - "install_devices_ios_list_4": "În câmpul DNS, introduceți adresele serverului dvs. AdGuard Home.", + "install_devices_ios_list_4": "În câmpul DNS, intrați adresele serverului dvs. AdGuard Home.", "get_started": "Să începem", "next": "Următor", "open_dashboard": "Deschideți Tabloul de bord", @@ -302,10 +317,10 @@ "encryption_key_input": "Copiați/lipiți cheia dvs. privată PEM-codată pentru certificatul dvs. aici.", "encryption_enable": "Activați criptarea (HTTPS, DNS-over-HTTPS, și DNS-over-TLS)", "encryption_enable_desc": "Dacă este activată criptarea, interfața administrator AdGuard Home va lucra peste HTTPS, și serverul DNS va asculta pentru cereri peste DNS-over-HTTPS și DNS-over-TLS.", - "encryption_chain_valid": "Lanțul de certificate valid", - "encryption_chain_invalid": "Lanțul de certificate nevalid", + "encryption_chain_valid": "Lanț de certificate valid", + "encryption_chain_invalid": "Lanț de certificate invalid", "encryption_key_valid": "Aceasta este o cheie privată {{type}} validă", - "encryption_key_invalid": "Aceasta este o cheie privată {{type}} nevalidă", + "encryption_key_invalid": "Aceasta este o cheie privată {{type}} invalidă", "encryption_subject": "Obiect", "encryption_issuer": "Emitent", "encryption_hostnames": "Nume de host", @@ -317,7 +332,7 @@ "form_error_equal": "Nu trebuie să fie egale", "form_error_password": "Parolele nu corespund", "reset_settings": "Resetare setări", - "update_announcement": "AdGuard Home {{version}} este disponibil! <0>Faceți clic aici pentru mai multe informații.", + "update_announcement": "AdGuard Home {{version}} este disponibil! <0>Clicați aici pentru mai multe informații.", "setup_guide": "Ghid de instalare", "dns_addresses": "Adrese DNS", "dns_start": "Serverul DNS demarează", @@ -346,6 +361,7 @@ "form_enter_id": "Intrați identificator", "form_add_id": "Adăugați identificator", "form_client_name": "Intrați nume client", + "name": "Nume", "client_global_settings": "Folosiți setări globale", "client_deleted": "Clientul \"{{key}}\" a fost șters cu succes", "client_added": "Clientul \"{{key}}\" a fost adăugat cu succes", @@ -354,7 +370,7 @@ "client_confirm_delete": "Sunteți sigur că doriți să ștergeți clientul \"{{key}}\"?", "list_confirm_delete": "Sigur doriți să ștergeți această listă?", "auto_clients_title": "Clienți (runtime)", - "auto_clients_desc": "Date despre clienții folosite de AdGuard Home, dar care nu sunt stocate în configurație", + "auto_clients_desc": "Date despre clienții care folosesc AdGuard Home, dar care nu sunt stocate în configurație", "access_title": "Setări de acces", "access_desc": "Aici puteți configura regulile de acces pentru serverul DNS AdGuard Home.", "access_allowed_title": "Clienți autorizați", @@ -362,20 +378,20 @@ "access_disallowed_title": "Clienți neautorizați", "access_disallowed_desc": "O listă de adrese CIDR sau IP. Dacă este configurat, AdGuard Home va elimina cererile de la aceste adrese IP.", "access_blocked_title": "Domenii blocate", - "access_blocked_desc": "Nu confundați acest lucru cu filtrele. AdGuard Home va bloca interogări DNS cu aceste domenii în întrebare. Aici puteți specifica exact numele de domeniu, wildcard și reguli-urlfilter, de ex. 'examplu.org', '*.examplu.org' sau '||exemplu.org^'.", + "access_blocked_desc": "Nu confundați acest lucru cu filtrele. AdGuard Home va bloca interogări DNS cu aceste domenii în întrebare. Aici puteți specifica exact numele de domeniu, wildcard și reguli-urlfilter, de ex. 'exemplu.org', '*.exemplu.org' sau '||exemplu.org^'.", "access_settings_saved": "Setările de acces au fost salvate cu succes", "updates_checked": "Actualizările au fost verificate cu succes", "updates_version_equal": "AdGuard Home este la zi", "check_updates_now": "Verificați actualizările acum", "dns_privacy": "Confidențialitate DNS", "setup_dns_privacy_1": "<0>DNS-over-TLS: Folosiți stringul <1>{{address}}.", - "setup_dns_privacy_2": "<0>DNS-over-HTTPS: Utilizați stringul <1>{{address}}.", - "setup_dns_privacy_3": "<0>Rețineți că protocoalele DNS criptate sunt acceptate numai pe Android 9. Așadar, trebuie să instalați software suplimentar pentru alte sisteme de operare.<0>Iată o listă de software pe care o puteți utiliza.", - "setup_dns_privacy_android_1": "Android 9 acceptă nativ DNS-over-TLS. Pentru a o configura, accesați Setări → Rețea și internet → Advanced → Private DNS și introduceți numele de domeniu acolo.", + "setup_dns_privacy_2": "<0>DNS-over-HTTPS: Folosiți stringul <1>{{address}}.", + "setup_dns_privacy_3": "<0>Rețineți că protocoalele DNS criptate sunt acceptate numai pe Android 9. Așadar, trebuie să instalați programe suplimentare pentru alte sisteme de operare.<0>Iată o listă de software pe care o puteți utiliza.", + "setup_dns_privacy_android_1": "Android 9 acceptă nativ DNS-over-TLS. Pentru a-l configura, accesați Setări → Rețea și internet → Advanced → Private DNS și intrați numele de domeniu acolo.", "setup_dns_privacy_android_2": "<0>AdGuard pentru Android acceptă <1>DNS-over-HTTPS și <1>DNS-over-TLS.", "setup_dns_privacy_android_3": "<0>Intra adaugă <1>DNS-over-HTTPS suport pentru Android.", - "setup_dns_privacy_ios_1": "<0>DNSCloak acceptă <1>DNS-over-HTTPS, dar pentru a-l configura pentru a utiliza propriul server, va trebui să generezi un <2>DNS Stamp pentru aceasta.", - "setup_dns_privacy_ios_2": "<0>AdGuard pentru iOS acceptă instalarea<1>DNS-over-HTTPS și <1>DNS-over-TLS.", + "setup_dns_privacy_ios_1": "<0>DNSCloak acceptă <1>DNS-over-HTTPS, dar pentru a-l configura pentru a utiliza propriul server, va trebui să generați un <2>DNS Stamp pentru aceasta.", + "setup_dns_privacy_ios_2": "<0>AdGuard pentru iOS acceptă instalarea <1>DNS-over-HTTPS și <1>DNS-over-TLS.", "setup_dns_privacy_other_title": "Alte implementări", "setup_dns_privacy_other_1": "AdGuard Home poate fi un client DNS sigur pe orice platformă.", "setup_dns_privacy_other_2": "<0>dnsproxy acceptă toate protocoalele DNS securizate cunoscute.", @@ -383,7 +399,7 @@ "setup_dns_privacy_other_4": "<0>Mozilla Firefox acceptă <1>DNS-over-HTTPS.", "setup_dns_privacy_other_5": "Veți găsi mai multe implementări <0>aici și <1>aici.", "setup_dns_notice": "Pentru a utiliza <1>DNS-over-HTTPS sau <1>DNS-over-TLS, trebuie să <0>configurați Criptarea în setările AdGuard Home.", - "rewrite_added": "Rescriere DNS pentru \"{{key}}\" adăugat cu succes", + "rewrite_added": "Rescriere DNS pentru \"{{key}}\" adăugată cu succes", "rewrite_deleted": "Rescriere DNS pentru \"{{key}}\" ștearsă cu succes", "rewrite_add": "Adăugați rescriere DNS", "rewrite_not_found": "Nu s-au găsit rescrieri DNS", @@ -394,11 +410,11 @@ "dns_rewrites": "Rescrieri DNS", "form_domain": "Intrați un nume de domeniu sau wildcard", "form_answer": "Intrați adresa IP sau numele de domeniu", - "form_error_domain_format": "Format de răspuns nevalid", - "form_error_answer_format": "Format de răspuns nevalid", + "form_error_domain_format": "Format de răspuns invalid", + "form_error_answer_format": "Format de răspuns invalid", "configure": "Configurați", "main_settings": "Setări principale", - "block_services": "Blocare anumite servicii", + "block_services": "Blochează anumite servicii", "blocked_services": "Servicii blocate", "blocked_services_desc": "Permite blocarea rapidă a site-urilor și serviciilor populare.", "blocked_services_saved": "Serviciile blocate au fost salvate cu succes", @@ -422,11 +438,11 @@ "filter_added_successfully": "Filtrul a fost adăugat cu succes", "filter_updated": "Filtrul a fost actualizat cu succes", "statistics_configuration": "Configurația statisticilor", - "statistics_retention": "Statistică retenții", + "statistics_retention": "Păstrarea statisticilor", "statistics_retention_desc": "Dacă reduceți valoarea intervalului, unele date vor fi pierdute", "statistics_clear": " Șterge statisticile", "statistics_clear_confirm": "Sunteți sigur că doriți să ștergeți statisticile?", - "statistics_retention_confirm": "Sunteți sigur că doriți să schimbați retenția statisticilor? Dacă reduceți valoarea intervalului, unele date vor fi pierdute", + "statistics_retention_confirm": "Sunteți sigur că doriți să schimbați păstrarea statisticilor? Dacă reduceți valoarea intervalului, unele date vor fi pierdute", "statistics_cleared": "Statisticile au fost șterse cu succes", "interval_hours": "{{count}} oră", "interval_hours_plural": "{{count}} ore", @@ -445,6 +461,7 @@ "location": "Locația", "orgname": "Numele organizației", "netname": "Numele rețelei", + "network": "Rețea", "descr": "Descriere", "whois": "Whois", "filtering_rules_learn_more": "<0>Aflați mai multe despre crearea propriilor liste hosts.", @@ -456,10 +473,10 @@ "disable_ipv6": "Dezactivați IPv6", "disable_ipv6_desc": "Dacă această opțiune este activată, toate interogările DNS pentru adrese IPv6 (tip AAAA) vor fi anulate.", "fastest_addr": "Cea mai rapidă adresă IP", - "fastest_addr_desc": "Interogați toate serverele DNS și returnați cea mai rapidă adresă IP din răspunsuri", - "autofix_warning_text": "Dacă faceți clic pe \"Fix\", AdGuardHome va configura sistemul dvs. pentru a utiliza serverul DNS AdGuardHome.", - "autofix_warning_list": "Va efectua aceste sarcini: <0>Dezactivare sistem DNSStubListener <0>Setare adresă server DNS la 127.0.0.1 <0>Înlocuire țintei legăturii simbolice a /etc/resolv.conf pentru /run/systemd/resolve/resolv.conf <0>Oprire DNSStubListener (reîncărcare servici rezolvat prin sistem)", - "autofix_warning_result": "Ca urmare, toate cererile DNS de la sistemul dvs. vor fi procesate în mod implicit de AdGuardHome.", + "fastest_addr_desc": "Interogările la toate serverele DNS întorc adresa IP cea mai rapidă din răspunsuri. Așteptarea răspunsului tuturor serverelor DNS face interogările DNS mai lente dar se ameliorează conectivitatea generală.", + "autofix_warning_text": "Dacă clicați pe \"Fix\", AdGuardHome va configura sistemul dvs. pentru a utiliza serverul DNS AdGuardHome.", + "autofix_warning_list": "Va efectua aceste sarcini: <0>Dezactivare sistem DNSStubListener <0>Setare adresă server DNS la 127.0.0.1 <0>Înlocuire link simbolic țintă /etc/resolv.conf cu /run/systemd/resolve/resolv.conf <0>Oprire DNSStubListener (reîncărcare servici rezolvat prin sistem)", + "autofix_warning_result": "Ca urmare, toate cererile DNS ale sistemul dvs. vor fi procesate în mod implicit de AdGuardHome.", "tags_title": "Etichete", "tags_desc": "Puteți selecta etichetele care corespund clientului. Etichetele pot fi incluse în regulile de filtrare și vă permit să le aplicați mai exact. <0>Aflați mai multe", "form_select_tags": "Selectați etichete client", @@ -489,5 +506,19 @@ "list_updated": "{{count}} listă actualizată", "list_updated_plural": "{{count}} liste actualizate", "dnssec_enable": "Activați DNSSEC", - "dnssec_enable_desc": "Setați steagul DNSSEC pe interogările DNS de ieșire și verificați rezultatul (este necesar un resolver DNSSEC activat)" + "dnssec_enable_desc": "Setați steagul DNSSEC pe interogările DNS de ieșire și verificați rezultatul (este necesar un resolver DNSSEC activat)", + "validated_with_dnssec": "Validat cu DNSSEC", + "show_all_responses": "Toate răspunsurile", + "show_blocked_responses": "Blocat", + "show_whitelisted_responses": "Pe lista albă", + "show_processed_responses": "Tratat", + "blocked_safebrowsing": "Blocat de Navigarea securitară", + "blocked_adult_websites": "Site-uri pentru adulți blocate", + "blocked_threats": "Amenințări blocate", + "allowed": "Permise", + "filtered": "Filtrate", + "rewritten": "Rescrise", + "safe_search": "Căutare sigură", + "blocklist": "Lista neagră", + "milliseconds_abbreviation": "ms" } \ No newline at end of file diff --git a/client/src/__locales/ru.json b/client/src/__locales/ru.json index 2ee509fe..d0f3d1cf 100644 --- a/client/src/__locales/ru.json +++ b/client/src/__locales/ru.json @@ -59,7 +59,7 @@ "query_log": "Журнал", "faq": "FAQ", "version": "версия", - "address": "адрес", + "address": "Адрес", "on": "Вкл", "off": "Выкл", "copyright": "Все права защищены", @@ -170,9 +170,10 @@ "updated_upstream_dns_toast": "Upstream DNS-серверы обновлены", "dns_test_ok_toast": "Указанные серверы DNS работают корректно", "dns_test_not_ok_toast": "Сервер \"{{key}}\": невозможно использовать, проверьте правильность написания", - "unblock_btn": "Разблокировать", - "block_btn": "Заблокировать", + "unblock": "Разблокировать", + "block": "Заблокировать", "time_table_header": "Время", + "date": "Дата", "domain_name_table_header": "Домен", "type_table_header": "Тип", "response_table_header": "Ответ", @@ -257,7 +258,7 @@ "install_devices_router_list_1": "Откройте настройки вашего роутера. Обычно вы можете открыть их в вашем браузере (например, http://192.168.0.1/ или http://192.168.1.1/). Вас могут попросить ввести пароль. Если вы не помните его, пароль часто можно сбросить, нажав на кнопку на самом роутере. Некоторые роутеры требуют специального приложения, которое в этом случае должно быть уже установлено на ваш компьютер или телефон.", "install_devices_router_list_2": "Найдите настройки DHCP или DNS. Найдите буквы \"DNS\" рядом с текстовым полем, в которое можно ввести два или три ряда цифр, разделенных на 4 группы от одной до трёх цифр.", "install_devices_router_list_3": "Введите туда адрес вашего AdGuard Home.", - "install_devices_router_list_4": "Вы не можете установить собственный DNS-сервер на некоторых типах маршрутизаторов. В этом случае может помочь настройка AdGuard Home в качестве DHCP-сервера. В противном случае вам следует обратиться к руководству по настройке DNS-серверов для вашей конкретной модели маршрутизатора.", + "install_devices_router_list_4": "Вы не можете установить собственный DNS-сервер на некоторых типах маршрутизаторов. В этом случае может помочь настройка AdGuard Home в качестве <0>DHCP-сервера. В противном случае вам следует обратиться к руководству по настройке DNS-серверов для вашей конкретной модели маршрутизатора.", "install_devices_windows_list_1": "Откройте Панель управления через меню \"Пуск\" или через поиск Windows.", "install_devices_windows_list_2": "Перейдите в \"Сеть и интернет\", а затем в \"Центр управления сетями и общим доступом\"", "install_devices_windows_list_3": "В левой стороне экрана найдите \"Изменение параметров адаптера\" и кликните по нему.", @@ -489,5 +490,9 @@ "list_updated": "Обновлен {{count}} список", "list_updated_plural": "Обновлено списков: {{count}}", "dnssec_enable": "Включить DNSSEC", - "dnssec_enable_desc": "Установите флаг DNSSEC в исходящих DNS-запросах и проверьте результат (требуется резолвер с поддержкой DNSSEC)" -} + "dnssec_enable_desc": "Установите флаг DNSSEC в исходящих DNS-запросах и проверьте результат (требуется резолвер с поддержкой DNSSEC)", + "show_blocked_responses": "Blocked", + "blocked_adult_websites": "Заблокированные \"взрослые\" сайты", + "blocked_threats": "Заблокировано угроз", + "blocklist": "Черный список" +} \ No newline at end of file diff --git a/client/src/__locales/sk.json b/client/src/__locales/sk.json index f3013867..7d956d0f 100644 --- a/client/src/__locales/sk.json +++ b/client/src/__locales/sk.json @@ -3,6 +3,8 @@ "example_upstream_reserved": "Môžete zadať DNS upstream <0>pre konkrétnu doménu (domény)", "upstream_parallel": "Používať paralelné dopyty na zrýchlenie súčasným dopytovaním všetkých serverov", "parallel_requests": "Paralelné dopyty", + "load_balancing": "Vyrovnávanie záťaže", + "load_balancing_desc": "Dopytujte jeden server súčasne. AdGuard Home použije na výber servera vážený náhodný algoritmus, aby sa najrýchlejší server používal častejšie.", "bootstrap_dns": "Bootstrap DNS servery", "bootstrap_dns_desc": "Bootstrap DNS servery sa používajú na rozlíšenie IP adries DoH/DoT rezolverov, ktoré zadáte ako upstreams.", "check_dhcp_servers": "Skontrolovať DHCP servery", @@ -37,6 +39,7 @@ "dhcp_interface_select": "Zvoľte DHCP rozhranie", "dhcp_hardware_address": "Hardware adresa", "dhcp_ip_addresses": "IP adresy", + "ip": "IP", "dhcp_table_hostname": "Meno hostiteľa", "dhcp_table_expires": "Vyprší", "dhcp_warning": "Ak chcete server DHCP napriek tomu povoliť, uistite sa, že v sieti nie je žiadny iný aktívny DHCP server. V opačnom prípade sa môže prerušiť internet pre už pripojené zariadenia!", @@ -49,17 +52,22 @@ "dhcp_static_leases_not_found": "Nebol nájdený žiadny statický DHCP prenájom", "dhcp_add_static_lease": "Pridať statický prenájom", "dhcp_reset": "Naozaj chcete obnoviť konfiguráciu DHCP?", + "country": "Krajina", "delete_confirm": "Naozaj chcete vymazať \"{{key}}\"?", "form_enter_hostname": "Zadajte meno hostiteľa", "error_details": "Podrobnosti chyby", + "client_details": "Podrobnosti klienta", + "details": "Podrobnosti", "back": "Naspäť", "dashboard": "Riadiaci panel", "settings": "Nastavenia", "filters": "Filtre", + "filter": "Filter", "query_log": "Denník dopytov", + "empty_log": "Denník dopytov je prázdny", "faq": "FAQ", "version": "Verzia", - "address": "adresa", + "address": "Adresa", "on": "ZAP.", "off": "VYP.", "copyright": "Copyright", @@ -132,8 +140,10 @@ "rules_count_table_header": "Počet pravidiel", "last_time_updated_table_header": "Posledná aktualizácia", "actions_table_header": "Akcie", + "request_table_header": "Dopyt", "edit_table_action": "Upraviť", "delete_table_action": "Vymazať", + "elapsed": "Uplynuté", "filters_and_hosts_hint": "AdGuard Home pozná základné pravidlá adblock a syntax hosts súborov.", "no_blocklist_added": "Nebol pridaný žiaden zoznam blokovaných DNS", "no_whitelist_added": "Nebol pridaný žiaden zoznam povolených DNS", @@ -170,10 +180,12 @@ "updated_upstream_dns_toast": "Aktualizované upstream DNS servery", "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", - "unblock_btn": "Odblokovať", - "block_btn": "Zablokovať", + "unblock": "Odblokovať", + "block": "Blokovať", "time_table_header": "Čas", + "date": "Dátum", "domain_name_table_header": "Meno domény", + "domain_or_client": "Doména alebo klient", "type_table_header": "Typ", "response_table_header": "Odozva", "client_table_header": "Klient", @@ -211,6 +223,8 @@ "custom_ip": "Vlastná IP adresa", "blocking_ipv4": "Blokovanie IPv4", "blocking_ipv6": "Blokovanie IPv6", + "dns_over_https": "DNS-over-HTTPS", + "dns_over_tls": "DNS-over-TLS", "form_enter_rate_limit": "Zadajte rýchlostný limit", "rate_limit": "Rýchlostný limit", "edns_enable": "Povoliť klientsku podsiete EDNS", @@ -229,6 +243,7 @@ "rule_label": "Pravidlo", "list_label": "Zoznam", "unknown_filter": "Neznámy filter {{filterId}}", + "known_tracker": "Známy sledovač", "install_welcome_title": "Vitajte na stránkach AdGuard Home!", "install_welcome_desc": "Doména AdGuard Home je celosieťový DNS server pre blokovanie reklám a sledovačov. Jeho cieľom je, aby ste ovládali celú Vašu sieť a všetky Vaše zariadenia, pričom sa nevyžaduje použitie akéhokoľvek programu na strane klienta.", "install_settings_title": "Administrátorské webové rozhranie", @@ -257,7 +272,7 @@ "install_devices_router_list_1": "Otvorte predvoľby Vášho smerovača. Zvyčajne ho môžete získať z prehliadača prostredníctvom adresy URL (napríklad http://192.168.0.1/ alebo http://192.168.1.1/). Možno bude potrebné zadať heslo. Ak si to nepamätáte, heslo môžete často obnoviť stlačením tlačidla na samotnom smerovači. Niektoré smerovače vyžadujú konkrétnu aplikáciu, ktorá by v takom prípade mala byť už nainštalovaná na Vašom počítači alebo telefóne.", "install_devices_router_list_2": "Nájdite nastavenia DHCP/DNS. Hľadajte skratku DNS vedľa poľa, ktoré umožňuje vložiť dve alebo tri sady čísel, každé rozdelené do štyroch skupín s jedným až tromi číslicami.", "install_devices_router_list_3": "Zadajte tam adresy Vášho AdGuard Home servera.", - "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 DHCP server. 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 domovskú stránku AdGuard ako <0>DHCP server. V opačnom prípade by ste mali vyhľadať príručku, ako prispôsobiť servery DNS 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_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", @@ -346,6 +361,7 @@ "form_enter_id": "Zadajte identifikátor", "form_add_id": "Pridajte identifikátor", "form_client_name": "Zadajte meno klienta", + "name": "Meno", "client_global_settings": "Použiť globálne nastavenia", "client_deleted": "\"{{key}}\" klienta bol úspešne vymazaný", "client_added": "\"{{key}}\" klienta bol úspešne pridaný", @@ -445,6 +461,7 @@ "location": "Poloha", "orgname": "Meno organizácie", "netname": "Meno siete", + "network": "Sieť", "descr": "Popis", "whois": "Whois", "filtering_rules_learn_more": "<0>Dozvedieť sa viac o tvorbe vlastných zoznamov hostiteľov.", @@ -456,7 +473,7 @@ "disable_ipv6": "Vypnúť IPv6", "disable_ipv6_desc": "Ak je táto funkcia zapnutá, všetky dotazy DNS na adresy IPv6 (typ AAAA) budú zrušené.", "fastest_addr": "Najrýchlejšia IP adresa", - "fastest_addr_desc": "Dopytovať všetky DNS servery a vrátiť najrýchlejšiu IP adresu zo všetkých odpovedí", + "fastest_addr_desc": "Dopytovať všetky servery DNS a vrátiť najrýchlejšiu IP adresu zo všetkých odpovedí. Toto spomalí dotazy DNS, pretože musíme čakať na odpovede zo všetkých serverov DNS, ale zlepší sa celkové pripojenie.", "autofix_warning_text": "Ak kliknete na „Opraviť“, AdGuardHome nakonfiguruje Váš systém tak, aby používal DNS server AdGuardHome.", "autofix_warning_list": "Bude vykonávať tieto úlohy: <0>Deaktivovať systém DNSStubListener <0>Nastaviť adresu servera DNS na 127.0.0.1 <0>Nahradiť cieľový symbolický odkaz /etc/resolv.conf na /run/systemd/resolve/resolv.conf <0>Zastaviť službu DNSStubListener (znova načítať službu systemd-resolved)", "autofix_warning_result": "Výsledkom bude, že všetky DNS dopyty z Vášho systému budú štandardne spracované službou AdGuard Home.", @@ -489,5 +506,19 @@ "list_updated": "{{count}} zoznam aktualizovaný", "list_updated_plural": "{{count}} zoznamov aktualizovaných", "dnssec_enable": "Zapnúť DNSSEC", - "dnssec_enable_desc": "Nastavte príznak DNSSEC v nasledujúcich DNS dopytoch a skontrolujte výsledok (je potrebný prekladač so zapnutým DNSSEC)" + "dnssec_enable_desc": "Nastavte príznak DNSSEC v nasledujúcich DNS dopytoch a skontrolujte výsledok (je potrebný prekladač so zapnutým DNSSEC)", + "validated_with_dnssec": "Overené pomocou DNSSEC", + "show_all_responses": "Všetky odpovede", + "show_blocked_responses": "Zablokované", + "show_whitelisted_responses": "Obsiahnuté v bielej listine", + "show_processed_responses": "Spracované", + "blocked_safebrowsing": "Zablokované modulom Bezpečné prehliadanie", + "blocked_adult_websites": "Zablokovaná stránka pre dospelých", + "blocked_threats": "Zablokované hrozby", + "allowed": "Povolené", + "filtered": "Filtrované", + "rewritten": "Prepísané", + "safe_search": "Bezpečné vyhľadávanie", + "blocklist": "Zoznam blokovaní", + "milliseconds_abbreviation": "ms" } \ No newline at end of file diff --git a/client/src/__locales/sl.json b/client/src/__locales/sl.json index 8739390a..51a8e1c1 100644 --- a/client/src/__locales/sl.json +++ b/client/src/__locales/sl.json @@ -3,6 +3,8 @@ "example_upstream_reserved": "lahko določite nazgornji DNS <0>za določene domene", "upstream_parallel": "Uporabite vzporedne zahteve za pospešitev reševanja s hkratnim poizvedovanjem vseh gorvodnih strežnikov", "parallel_requests": "Vzporedne zahteve", + "load_balancing": "Uravnavanje obremenitve", + "load_balancing_desc": "Poizvedujte po en strežnik. AdGuard Home bo uporabil uteženi naključni algoritem za izbiro strežnika, tako da bo najhitrejši strežnik uporabljen pogosteje.", "bootstrap_dns": "Zagonski DNS strežniki", "bootstrap_dns_desc": "Zagonski DNS strežniki se uporabljajo za razreševanje IP naslovov DoH/DoT reševalcev, ki jih določite kot navzgornje.", "check_dhcp_servers": "Preveri strežnike DHCP", @@ -37,6 +39,7 @@ "dhcp_interface_select": "Izberite DHCP vmesnik", "dhcp_hardware_address": "Naslov strojne opreme", "dhcp_ip_addresses": "IP naslovi", + "ip": "IP", "dhcp_table_hostname": "Ime gostitelja", "dhcp_table_expires": "Poteče", "dhcp_warning": "Če želite omogočiti DHCP strežnik, prepričajte se, da v vašem omrežju ni drugega aktivnega strežnika DHCP. V nasprotnem primeru lahko ta prekine internet za povezane naprave!", @@ -49,17 +52,22 @@ "dhcp_static_leases_not_found": "Ni najdenih statičnih najemov DHCP", "dhcp_add_static_lease": "Dodaj statičen najem", "dhcp_reset": "Ali ste prepričani, da želite ponastaviti konfiguracijo DHCP?", + "country": "Dežela", "delete_confirm": "Ali ste prepričani, da želite izbrisati \"{{key}}\"?", "form_enter_hostname": "Vnesite ime gostitelja", "error_details": "Podrobnosti o napaki", + "client_details": "Podatki o odjemalcu", + "details": "Podrobnosti", "back": "Nazaj", "dashboard": "Nadzorna plošča", "settings": "Nastavitve", "filters": "Filtri", + "filter": "Filtriraj", "query_log": "Dnevnik poizvedb", + "empty_log": "Dnevnik poizvedb je prazen", "faq": "Pogosta vprašanja in odgovori (FAQ)", "version": "različica", - "address": "naslov", + "address": "Naslov", "on": "VKL", "off": "IZK", "copyright": "Avtorske pravice", @@ -132,8 +140,10 @@ "rules_count_table_header": "Število pravil", "last_time_updated_table_header": "Zadnjič posodobljeno", "actions_table_header": "Akcij", + "request_table_header": "Zahteva", "edit_table_action": "Uredi", "delete_table_action": "Izbriši", + "elapsed": "Potekla", "filters_and_hosts_hint": "AdGuard Home razume osnovna pravila zaviranja oglasov in sintakso datotek gostiteljev.", "no_blocklist_added": "Ni dodanih nobenih seznamov nedovoljenih", "no_whitelist_added": "Ni dodanih nobenih dovoljenih seznamov", @@ -170,10 +180,12 @@ "updated_upstream_dns_toast": "Posodobljeni Zagonske strežnike DNS", "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", - "unblock_btn": "Omogoči", - "block_btn": "Onemogoči", + "unblock": "Omogoči", + "block": "Onemogoči", "time_table_header": "Čas", + "date": "Datum", "domain_name_table_header": "Ime domene", + "domain_or_client": "Domena ali odjemalec", "type_table_header": "Vrsta", "response_table_header": "Odgovor", "client_table_header": "Odjemalec", @@ -211,6 +223,8 @@ "custom_ip": "IP po meri", "blocking_ipv4": "Onemogočanje IPv4", "blocking_ipv6": "Onemogočanje IPv6", + "dns_over_https": "DNS-prek-HTTPS", + "dns_over_tls": "DNS-prek-TLS", "form_enter_rate_limit": "Vnesite omejitev hitrosti", "rate_limit": "Omejitev hitrosti", "edns_enable": "Omogoči podmrežje odjemalcev EDNS", @@ -229,6 +243,7 @@ "rule_label": "Pravilo", "list_label": "Seznam", "unknown_filter": "Neznan filter {{filterId}}", + "known_tracker": "Znan sledilec", "install_welcome_title": "Dobrodošli v AdGuard Home!", "install_welcome_desc": "AdGuard Home je omrežni strežnik DNS, ki zavira oglase in sledilce v celotnem omrežju. Njegov namen je omogočanje nadzora nad celotnim omrežjem in vsemi vašimi napravami in ne zahteva uporabo odjemalskega programa.", "install_settings_title": "Skrbniški spletni vmesnik", @@ -257,7 +272,7 @@ "install_devices_router_list_1": "Odprite nastavitve usmerjevalnika. Ponavadi lahko do nje dostopate iz brskalnika prek URL-ja (npr. http://192.168.0.1/ ali http://192.168.1.1/). Morda boste morali vnesti geslo. Če se ne spomnite gesla, lahko pogosto ponastavite geslo s pritiskom na gumb na samem usmerjevalniku. Nekateri usmerjevalniki zahtevajo posebno aplikacijo, ki bi morala biti v tem primeru že nameščena na vašem računalniku/telefonu.", "install_devices_router_list_2": "Poiščite nastavitve DHCP/DNS. Poiščite črke DNS poleg polja, ki dovoljuje dva ali tri naborov številk, pri čemer je vsaka razdeljena na štiri skupine z enim do tremi števili.", "install_devices_router_list_3": "Tam vnesite svoje naslove strežnikov AdGuard Home.", - "install_devices_router_list_4": "Na nekaterih usmerjevalnikih ne morete nastaviti strežnika DNS po meri. V tem primeru bo morda pomagalo, če boste AdGuard Home postavili kot strežnik DHCP. V nasprotnem primeru poiščite priročnik, kako prilagoditi strežnike DNS za vaš določen model usmerjevalnika.", + "install_devices_router_list_4": "Na nekaterih vrstah usmerjevalnikov ne morete nastaviti strežnika DNS po meri. V tem primeru bo morda pomagalo, če boste AdGuard Home postavili kot <0>strežnik DHCP. V nasprotnem primeru poiščite priročnik, kako prilagoditi strežnike DNS za vaš določen model usmerjevalnika.", "install_devices_windows_list_1": "Odprite 'Nadzorno ploščo' prek menija 'Začetek' ali 'Iskanja v sistemu Windows'.", "install_devices_windows_list_2": "Pojdite v 'Omrežje' in 'Kategorija interneta' in nato v 'Omrežje' in 'Središče za skupno rabo'.", "install_devices_windows_list_3": "Na levi strani zaslona poiščite 'Spremeni nastavitve kartice' in kliknite nanjo.", @@ -346,6 +361,7 @@ "form_enter_id": "Vnesi identifikatorja", "form_add_id": "Dodaj identifikatorja", "form_client_name": "Vnesite ime odjemalca", + "name": "Ime", "client_global_settings": "Uporabi splošne nastavitve", "client_deleted": "Odjemalec \"{{key}}\" je bil uspešno izbrisan", "client_added": "Odjemalec \"{{key}}\" je bil uspešno dodan", @@ -381,7 +397,7 @@ "setup_dns_privacy_other_2": "<0>dnsproxy podpira vse znane varne protokole DNS.", "setup_dns_privacy_other_3": "<0>dnscrypt-proxy podpira <1>DNS-prek-HTTPS.", "setup_dns_privacy_other_4": "<0>Mozilla Firefox podpira <1>DNS-prek-HTTPS.", - "setup_dns_privacy_other_5": "Več izvedb boste najdli <0>tukaj in <1>tukaj.", + "setup_dns_privacy_other_5": "Našli boste več izvedb <0>tukaj in <1>tukaj.", "setup_dns_notice": "Za uporabo <1>DNS-prek-HTTPS ali <1>DNS-prek-TLS, morate <0>konfigurirati šifriranje v nastavitvah AdGuard Home.", "rewrite_added": "Uspešno je dodano DNS prepisovanje za \"{{key}}\"", "rewrite_deleted": "Uspešno je izbrisano DNS prepisovanje za \"{{key}}\"", @@ -445,6 +461,7 @@ "location": "Lokacija", "orgname": "Ime organizacije", "netname": "Ime omrežja", + "network": "Omrežje", "descr": "Opis", "whois": "Whois", "filtering_rules_learn_more": "<0>Več o ustvarjanju lastnih seznamov gostiteljev.", @@ -456,7 +473,7 @@ "disable_ipv6": "Onemogoči IPv6", "disable_ipv6_desc": "Če je ta funkcija omogočena, bodo vse poizvedbe DNS za naslove IPv6 (vrste AAAA) izpadle.", "fastest_addr": "Najhitrejši IP naslov", - "fastest_addr_desc": "Poišči vse strežnike DNS in vrni najhitrejši IP naslov med vsemi odgovori", + "fastest_addr_desc": "Poizve vse strežnike DNS in vrne najhitrejši IP naslov med vsemi odgovori. To bo upočasnilo poizvedbe DNS, saj moramo čakati na odgovore vseh DNS strežnikov, vendar bo izboljšalo splošno povezljivost.", "autofix_warning_text": "Če kliknete 'Popravi', bo AdGuardHome konfiguriral vaš sistem za uporabo strežnika AdGuardHome DNS.", "autofix_warning_list": "To bo izvedlo naslednja opravila: <0>Deaktiviraj sistemski DNSStubListener <0>Nastavi naslov strežnika DNS na 127.0.0.1 <0>Zamenjaj cilj simbolične povezave /etc/resolv.conf with /run/systemd/resolve/resolv.conf <0>Zaustavi DNSStubListener (znova naloži storitev systemd-resolved)", "autofix_warning_result": "Kot rezultat, bo vse zahteve DNS iz vašega sistema privzeto obdelal AdGuard Home.", @@ -489,5 +506,19 @@ "list_updated": "{{count}} posodobljen seznam", "list_updated_plural": "{{count}} posodobljenih seznamov", "dnssec_enable": "Omogoči DNSSEC", - "dnssec_enable_desc": "V odhodnih poizvedbah DNS nastavite zastavico DNSSEC in preverite rezultat (zahtevan je omogočen reševalnik DNSSEC)" + "dnssec_enable_desc": "V odhodnih poizvedbah DNS nastavite zastavico DNSSEC in preverite rezultat (zahtevan je omogočen reševalnik DNSSEC)", + "validated_with_dnssec": "Potrjen z DNSSEC", + "show_all_responses": "Vsi odgovori", + "show_blocked_responses": "Onemogočen", + "show_whitelisted_responses": "Na seznamu dovoljenih", + "show_processed_responses": "Obdelan", + "blocked_safebrowsing": "Onemogočeno z 'Varnim brskanjem'", + "blocked_adult_websites": "Onemogočeno spletnih strani za odrasle", + "blocked_threats": "Onemogočeno groženj", + "allowed": "Dovoljeno", + "filtered": "Filtrirano", + "rewritten": "Znova napisano", + "safe_search": "Varno iskanje", + "blocklist": "Seznam nedovoljenih", + "milliseconds_abbreviation": "ms" } \ No newline at end of file diff --git a/client/src/__locales/sr-cs.json b/client/src/__locales/sr-cs.json index 74da21ea..d472a4ae 100644 --- a/client/src/__locales/sr-cs.json +++ b/client/src/__locales/sr-cs.json @@ -58,7 +58,7 @@ "query_log": "Dnevnik zahteva", "faq": "ČPP", "version": "Verzija", - "address": "adresa", + "address": "Adresa", "on": "Uključeno", "off": "Isključeno", "copyright": "Autorska prava", @@ -167,9 +167,10 @@ "updated_upstream_dns_toast": "Ažurirani upstream DNS serveri", "dns_test_ok_toast": "Dati DNS serveri rade ispravno", "dns_test_not_ok_toast": "Server \"{{key}}\": se ne može koristiti. Proverite da li ste ga ispravno uneli", - "unblock_btn": "Odblokiraj", - "block_btn": "Blokiraj", + "unblock": "Odblokiraj", + "block": "Blokiraj", "time_table_header": "Vreme", + "date": "Datum", "domain_name_table_header": "Ime domena", "type_table_header": "Vrsta", "response_table_header": "Odgovor", @@ -478,5 +479,8 @@ "install_static_configure": "Otkrili smo da se koristi dinamička IP adresa — <0>{{ip}}. Želite li da je koristite kao vašu statičku adresu?", "confirm_static_ip": "AdGuard Home će konfigurisati {{ip}} da bude vaša statička IP adresa. Želite li da nastavite?", "list_updated": "{{count}} lista ažurirana", - "list_updated_plural": "{{count}} lista ažurirano" + "list_updated_plural": "{{count}} lista ažurirano", + "show_blocked_responses": "Blokirano", + "blocked_adult_websites": "Blokiraj sajtove za odrasle", + "blocked_threats": "Blokiranih pretnji" } \ No newline at end of file diff --git a/client/src/__locales/sv.json b/client/src/__locales/sv.json index 933e0746..a20e467e 100644 --- a/client/src/__locales/sv.json +++ b/client/src/__locales/sv.json @@ -53,7 +53,7 @@ "query_log": "Förfrågningslogg", "faq": "FAQ", "version": "version", - "address": "adress", + "address": "Adress", "on": "PÅ", "off": "AV", "copyright": "Copyright", @@ -143,9 +143,10 @@ "updated_upstream_dns_toast": "Uppdaterade uppströms-dns-servrar", "dns_test_ok_toast": "Angivna DNS servrar fungerar korrekt", "dns_test_not_ok_toast": "Server \"{{key}}\": kunde inte användas. Var snäll och kolla att du skrivit in rätt", - "unblock_btn": "Avblockera", - "block_btn": "Blockera", + "unblock": "Avblockera", + "block": "Blockera", "time_table_header": "Tid", + "date": "Datum", "domain_name_table_header": "Domännamn", "type_table_header": "Typ", "response_table_header": "Svar", @@ -356,5 +357,8 @@ "netname": "Nätverksnamn", "descr": "Beskrivning", "whois": "Whois", - "filtering_rules_learn_more": "<0>Mer info om att skapa dina egna blockeringslistor för värdar." -} + "filtering_rules_learn_more": "<0>Mer info om att skapa dina egna blockeringslistor för värdar.", + "show_blocked_responses": "Blockerade", + "blocked_adult_websites": "Blockerade vuxensajter", + "blocked_threats": "Blockerade hot" +} \ No newline at end of file diff --git a/client/src/__locales/th.json b/client/src/__locales/th.json index 6336d631..9aa4f98c 100644 --- a/client/src/__locales/th.json +++ b/client/src/__locales/th.json @@ -149,8 +149,8 @@ "updated_upstream_dns_toast": "อัปเดตเซิร์ฟเวอร์ DNS ต้นทาง", "dns_test_ok_toast": "เซิร์ฟเวอร์ DNS ที่ระบุทำงานอย่างถูกต้อง", "dns_test_not_ok_toast": "เซิร์ฟเวอร์ \"{{key}}\": ไม่สามารถใช้งานได้ โปรดตรวจสอบว่าคุณเขียนถูกต้อง", - "unblock_btn": "เลิกปิดกั้น", - "block_btn": "ปิดกั้น", + "unblock": "เลิกปิดกั้น", + "block": "ปิดกั้น", "time_table_header": "เวลา", "domain_name_table_header": "ชื่อโดเมน", "type_table_header": "ประเภท", @@ -394,6 +394,7 @@ "location": "ตำแหน่ง", "orgname": "ชื่อองค์กร", "netname": "ชื่อเครือข่าย", + "network": "เครือข่าย", "descr": "คำอธิบาย", "whois": "Whois", "filtering_rules_learn_more": "<0>เรียนรู้เพิ่มเติม เกี่ยวกับการสร้างรายการปิดกั้นโฮสต์ของคุณเอง", @@ -411,5 +412,6 @@ "tags_desc": "คุณสามารถเลือกแท็กที่สอดคล้องกับลูกค้า แท็กสามารถรวมอยู่ในกฎการกรองและอนุญาตให้คุณใช้งานได้อย่างถูกต้องมากขึ้น <0>เรียนรู้เพิ่มเติม", "form_select_tags": "เลือกแท็กเครื่อง", "check_title": "ตรวจสอบการกรอง", - "check_desc": "ตรวจสอบว่าชื่อโฮสต์ถูกกรอง" + "check_desc": "ตรวจสอบว่าชื่อโฮสต์ถูกกรอง", + "form_enter_host": "ป้อนชื่อโฮสต์" } \ No newline at end of file diff --git a/client/src/__locales/tr.json b/client/src/__locales/tr.json index 9cbafdd8..a1cee624 100644 --- a/client/src/__locales/tr.json +++ b/client/src/__locales/tr.json @@ -59,7 +59,7 @@ "query_log": "Sorgu Günlüğü", "faq": "SSS", "version": "Sürüm", - "address": "adres", + "address": "Adres", "on": "AÇIK", "off": "KAPALI", "copyright": "Tüm hakları saklıdır", @@ -170,9 +170,10 @@ "updated_upstream_dns_toast": "Üst DNS sunucuları güncellendi", "dns_test_ok_toast": "Belirtilmiş 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", - "unblock_btn": "Engeli kaldır", - "block_btn": "Engelle", + "unblock": "Engeli kaldır", + "block": "Engelle", "time_table_header": "Saat", + "date": "Tarih", "domain_name_table_header": "Alan adı", "type_table_header": "Tür", "response_table_header": "Yanıt", @@ -257,7 +258,7 @@ "install_devices_router_list_1": "Yönlendiricinizin ayarlarına girin. Genelde internet tarayıcınızdan bir URL vasıtasıyla erişebilirsiniz (http://192.168.0.1/ veya http://192.168.1.1/ gibi). Sizden şifre girmenizi isteyebilir. Hatırlamıyorsanız yönlendiricinizin arkasındaki 'reset' tuşuna basılı tutup fabrika ayarlarına sıfırlayabilirsiniz. Bazı yönlendiriciler belirli uygulamalarla çalışır, bu durumda bilgisayarınıza/telefonunuza kurulması gerekir.", "install_devices_router_list_2": "DHCP/DNS ayarlarını bulun. DNS satırlarını arayın, genelde iki veya üç tanedir, üç rakam girilebilen dört ayrı grup içeren satırdır.", "install_devices_router_list_3": "AdGuard Home sunucusunun adresini o kısma yazın.", - "install_devices_router_list_4": "Bazı yönlendirici tiplerinde özel bir DNS sunucusu ayarlayamazsınız. Bu durumda AdGuard Home'u bir DHCP sunucu olarak ayarlamanız yardımcı olabilir. Aksi halde, yönlendirici modeliniz için DNS sunucularını elle nasıl özelleştirebileceğinizi aramalısınız.", + "install_devices_router_list_4": "Bazı yönlendirici tiplerinde özel bir DNS sunucusu ayarlayamazsınız. Bu durumda AdGuard Home'u bir DHCP sunucu olarak ayarlamanız yardımcı olabilir. Aksi halde, yönlendirici modeliniz için <0>DNS sunucularını elle nasıl özelleştirebileceğinizi aramalısınız.", "install_devices_windows_list_1": "Başlat menüsünden veya Windows aramasıyla Denetim Masası'na girin.", "install_devices_windows_list_2": "Ağ ve Internet kategorisine girin, sonra Ağ ve Paylaşım Merkezi'ne girin.", "install_devices_windows_list_3": "Sol taraftaki Bağdaştırıcı ayarlarını değiştir ayarını bulun ve ona tıklayın.", @@ -489,5 +490,9 @@ "list_updated": "{{count}} liste güncellendi", "list_updated_plural": "{{count}} liste güncellendi", "dnssec_enable": "DNSSEC'i etkinleştir", - "dnssec_enable_desc": "DNSSEC'i giden DNS sorguları için etkinleştir ve sonucu kontrol et (DNSSEC-etkin sorgulama gerekli)" + "dnssec_enable_desc": "DNSSEC'i giden DNS sorguları için etkinleştir ve sonucu kontrol et (DNSSEC-etkin sorgulama gerekli)", + "show_blocked_responses": "Engellendi", + "blocked_adult_websites": "Yetişkin içerikli site engellendi", + "blocked_threats": "Engellenen Tehditler", + "blocklist": "Engellenen listesi" } \ No newline at end of file diff --git a/client/src/__locales/vi.json b/client/src/__locales/vi.json index 6ff45758..5faabe28 100644 --- a/client/src/__locales/vi.json +++ b/client/src/__locales/vi.json @@ -2,6 +2,7 @@ "client_settings": "Cài đặt máy khách", "example_upstream_reserved": "bạn có thể chỉ định DNS ngược tuyến <0>cho một tên miền cụ thể(hoặc nhiều)", "upstream_parallel": "Sử dụng truy vấn song song để tăng tốc độ giải quyết bằng cách truy vấn đồng thời tất cả các máy chủ ngược tuyến", + "parallel_requests": "Yêu cầu song song", "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.", "check_dhcp_servers": "Kiểm tra máy chủ DHCP", @@ -36,6 +37,7 @@ "dhcp_interface_select": "Chọn một card mạng", "dhcp_hardware_address": "Địa chỉ phần cứng", "dhcp_ip_addresses": "Các địa chỉ IP", + "ip": "IP", "dhcp_table_hostname": "Tên máy chủ", "dhcp_table_expires": "Hết hạn", "dhcp_warning": "Nếu bạn vẫn muốn bật máy chủ DHCP, hãy đảm bảo rằng không có máy chủ DHCP hoạt động nào khác trong mạng của bạn. Nếu không, nó có thể phá vỡ Internet cho các thiết bị được kết nối!", @@ -48,9 +50,11 @@ "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_reset": "Bạn có chắc chắn muốn đặt lại thiết lập DHCP?", + "country": "Quốc gia", "delete_confirm": "Bạn có chắc chắn muốn xóa \"{{key}}\" không?", "form_enter_hostname": "Nhập tên máy chủ", "error_details": "Chi tiết lỗi", + "details": "Chi tiết", "back": "Quay lại", "dashboard": "Tổng quan", "settings": "Cài đặt", @@ -121,6 +125,7 @@ "enabled_save_search_toast": "Đã bật tìm kiếm an toàn", "enabled_table_header": "Kích hoạt", "name_table_header": "Tên", + "list_url_table_header": "Danh sách liên kết", "rules_count_table_header": "Số quy tắc", "last_time_updated_table_header": "Cập nhật cuối", "actions_table_header": "Thao tác", @@ -148,10 +153,11 @@ "updated_upstream_dns_toast": "Đã cập nhật máy chủ DNS tìm kiếm", "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", - "unblock_btn": "Bỏ chặn", - "block_btn": "Chặn", + "unblock": "Bỏ chặn", + "block": "Chặn", "time_table_header": "Thời gian", "domain_name_table_header": "Tên miền", + "domain_or_client": "Tên miền hoặc khách hàng", "type_table_header": "Loại", "response_table_header": "Phản hồi", "client_table_header": "Người dùng cuối", @@ -190,6 +196,9 @@ "blocking_ipv6": "Chặn IPv6", "form_enter_rate_limit": "Nhập giới hạn yêu cầu", "rate_limit": "Giới hạn yêu cầu", + "edns_cs_desc": "Nếu được bật, AdGuard Home sẽ gửi các mạng con của khách hàng đến các máy chủ DNS.", + "rate_limit_desc": "Số lượng yêu cầu mỗi giây mà một khách hàng được phép thực hiện (0: không giới hạn)", + "blocking_ipv4_desc": "Địa chỉ IP được trả lại cho một yêu cầu A bị chặn", "source_label": "Nguồn", "found_in_known_domain_db": "Tìm thấy trong cơ sở dữ liệu tên miền", "category_label": "Thể loại", @@ -413,5 +422,12 @@ "blocked_by_response": "Chặn bởi CNAME hoặc địa IP ở phản hồi", "try_again": "Hãy thử lại", "dnssec_enable": "Bật DNSSEC", - "dnssec_enable_desc": "Cắm mốc DNSSEC trong các truy vấn DNS sắp tới và kiểm tra kết quả (buộc phải có trình sửa lỗi hỗ trợ DNSSEC)" -} + "dnssec_enable_desc": "Cắm mốc DNSSEC trong các truy vấn DNS sắp tới và kiểm tra kết quả (buộc phải có trình sửa lỗi hỗ trợ DNSSEC)", + "show_blocked_responses": "Bị chặn", + "show_whitelisted_responses": "Đã thêm vào danh sách cho phép", + "show_processed_responses": "Đã xử lý", + "blocked_adult_websites": "Website người lớn đã chặn", + "blocked_threats": "Mối nguy hiểm đã chặn", + "allowed": "Được phép", + "safe_search": "Tìm kiếm an toàn" +} \ No newline at end of file diff --git a/client/src/__locales/zh-cn.json b/client/src/__locales/zh-cn.json index 8f962a04..6ac4faae 100644 --- a/client/src/__locales/zh-cn.json +++ b/client/src/__locales/zh-cn.json @@ -170,9 +170,10 @@ "updated_upstream_dns_toast": "上游 DNS 已更新", "dns_test_ok_toast": "指定的 DNS 服务器现已正常运行", "dns_test_not_ok_toast": "服务器 \"{{key}}\":无法使用,请检查你输入的是否正确", - "unblock_btn": "放行", - "block_btn": "拦截", + "unblock": "放行", + "block": "拦截", "time_table_header": "时间", + "date": "日起", "domain_name_table_header": "域名", "type_table_header": "类型", "response_table_header": "响应", @@ -488,5 +489,10 @@ "list_updated": "{{count}} 列表已更新", "list_updated_plural": "{{count}} 条列表已更新", "dnssec_enable": "启用DNSSEC", - "dnssec_enable_desc": "在发出DNS查询中设置DNSSEC标志并检查结果(需要启用DNSSEC的解析器)" -} + "dnssec_enable_desc": "在发出DNS查询中设置DNSSEC标志并检查结果(需要启用DNSSEC的解析器)", + "show_blocked_responses": "已拦截", + "blocked_safebrowsing": "安全浏览阻止项目", + "blocked_adult_websites": "拦截的成人网站", + "blocked_threats": "拦截的威胁", + "blocklist": "拦截列表" +} \ No newline at end of file diff --git a/client/src/__locales/zh-tw.json b/client/src/__locales/zh-tw.json index a17aa8ad..8d8994a6 100644 --- a/client/src/__locales/zh-tw.json +++ b/client/src/__locales/zh-tw.json @@ -1,8 +1,10 @@ { "client_settings": "用戶端設定", "example_upstream_reserved": "您可明確指定<0>用於特定的網域之 DNS 上游", - "upstream_parallel": "透過同時地查詢所有上游的伺服器,使用並行的請求以加速解析", + "upstream_parallel": "透過同時地查詢所有上游的伺服器,使用並行的查詢以加速解析網域", "parallel_requests": "並行的請求", + "load_balancing": "負載平衡", + "load_balancing_desc": "每次查詢一個伺服器。AdGuard Home 將使用加權隨機的演算法來選擇伺服器,以便最快的伺服器將被更常使用。", "bootstrap_dns": "自我啟動(Bootstrap)DNS 伺服器", "bootstrap_dns_desc": "自我啟動(Bootstrap)DNS 伺服器被用於解析您明確指定作為上游的 DoH/DoT 解析器之 IP 位址。", "check_dhcp_servers": "檢查動態主機設定協定(DHCP)伺服器", @@ -37,6 +39,7 @@ "dhcp_interface_select": "選擇動態主機設定協定(DHCP)介面", "dhcp_hardware_address": "硬體位址", "dhcp_ip_addresses": "IP 位址", + "ip": "IP", "dhcp_table_hostname": "主機名稱", "dhcp_table_expires": "到期", "dhcp_warning": "如果您無論如何想要啟用動態主機設定協定(DHCP)伺服器,確保在您的網路中無其它現行的 DHCP 伺服器。否則,它可能會破壞供已連線的裝置之網際網路!", @@ -49,14 +52,19 @@ "dhcp_static_leases_not_found": "無已發現之動態主機設定協定(DHCP)靜態租約", "dhcp_add_static_lease": "增加靜態租約", "dhcp_reset": "您確定您想要重置動態主機設定協定(DHCP)配置嗎?", + "country": "國家", "delete_confirm": "您確定您想要刪除 \"{{key}}\" 嗎?", "form_enter_hostname": "輸入主機名稱", "error_details": "錯誤細節", + "client_details": "用戶端細節", + "details": "細節", "back": "返回", "dashboard": "儀表板", "settings": "設定", "filters": "過濾器", + "filter": "過濾器", "query_log": "查詢記錄", + "empty_log": "查詢記錄為空", "faq": "常見問答集", "version": "版本", "address": "位址", @@ -88,7 +96,7 @@ "number_of_dns_query_days": "在最近的 {{count}} 日內已處理的 DNS 查詢之數量", "number_of_dns_query_days_plural": "在最近的 {{count}} 日內已處理的 DNS 查詢之數量", "number_of_dns_query_24_hours": "在最近的 24 小時內已處理的 DNS 查詢之數量", - "number_of_dns_query_blocked_24_hours": "被廣告封鎖過濾器和主機封鎖清單封鎖的 DNS 請求之數量", + "number_of_dns_query_blocked_24_hours": "被廣告封鎖過濾器和主機封鎖清單阻擋的 DNS 請求之數量", "number_of_dns_query_blocked_24_hours_by_sec": "被 AdGuard 瀏覽安全模組封鎖的 DNS 請求之數量", "number_of_dns_query_blocked_24_hours_adult": "已封鎖的成人網站之數量", "enforced_save_search": "已強制執行的安全搜尋", @@ -108,7 +116,7 @@ "dns_settings": "DNS 設定", "dns_blocklists": "DNS 封鎖清單", "dns_allowlists": "DNS 允許清單", - "dns_blocklists_desc": "AdGuard Home 將封鎖與封鎖清單相符的網域。", + "dns_blocklists_desc": "AdGuard Home 將阻擋與封鎖清單相符的網域。", "dns_allowlists_desc": "即使來自 DNS 允許清單的網域在任何的封鎖清單中,它們將被允許。", "custom_filtering_rules": "自訂的過濾規則", "encryption_settings": "加密設定", @@ -132,8 +140,10 @@ "rules_count_table_header": "規則總數", "last_time_updated_table_header": "最近的更新時間", "actions_table_header": "動作", + "request_table_header": "請求", "edit_table_action": "編輯", "delete_table_action": "刪除", + "elapsed": "已經過", "filters_and_hosts_hint": "AdGuard Home 懂得基本的廣告封鎖規則和主機檔案語法。", "no_blocklist_added": "無已加入的封鎖清單", "no_whitelist_added": "無已加入的允許清單", @@ -170,10 +180,12 @@ "updated_upstream_dns_toast": "已更新上游的 DNS 伺服器", "dns_test_ok_toast": "已明確指定的 DNS 伺服器正在正確地運作", "dns_test_not_ok_toast": "伺服器 \"{{key}}\":無法被使用,請檢查您已正確地填寫它", - "unblock_btn": "解除封鎖", - "block_btn": "封鎖", + "unblock": "解除封鎖", + "block": "封鎖", "time_table_header": "時間", + "date": "日期", "domain_name_table_header": "域名", + "domain_or_client": "網域或用戶端", "type_table_header": "類型", "response_table_header": "回應", "client_table_header": "用戶端", @@ -211,6 +223,8 @@ "custom_ip": "自訂的 IP", "blocking_ipv4": "封鎖 IPv4", "blocking_ipv6": "封鎖 IPv6", + "dns_over_https": "DNS-over-HTTPS", + "dns_over_tls": "DNS-over-TLS", "form_enter_rate_limit": "輸入速率限制", "rate_limit": "速率限制", "edns_enable": "啟用對於 DNS 的擴充機制(EDNS)用戶端子網路", @@ -229,6 +243,7 @@ "rule_label": "規則", "list_label": "清單", "unknown_filter": "未知的過濾器 {{filterId}}", + "known_tracker": "已知的追蹤器", "install_welcome_title": "歡迎至 AdGuard Home!", "install_welcome_desc": "AdGuard Home 是全網路範圍廣告和追蹤器封鎖的 DNS 伺服器。它的目的為讓您控制您的整個網路和所有您的裝置,且不需要使用用戶端程式。", "install_settings_title": "管理員網路介面", @@ -257,7 +272,7 @@ "install_devices_router_list_1": "開啟關於您的路由器之偏好設定。通常地,您可透過網址(如 http://192.168.0.1/ 或 http://192.168.1.1/)從您的瀏覽器中存取它。您可能被要求輸入該密碼。如果您不記得它,您經常可透過按壓於該路由器本身上的按鈕來重置密碼。某些路由器需要特定的應用程式,既然如此其應已被安裝於您的電腦/手機上。", "install_devices_router_list_2": "找到 DHCP/DNS 設定。尋找緊鄰著允許兩組或三組數字集的欄位之 DNS 字母,每組被拆成四個含有一至三個數字的群集。", "install_devices_router_list_3": "在那裡輸入您的 AdGuard Home 伺服器位址。", - "install_devices_router_list_4": "您無法於某些類型的路由器上設定自訂的 DNS 伺服器。在這種情況下,如果您設置 AdGuard Home 作為 DHCP 伺服器,其可能有所幫助。否則,您應搜尋有關如何為您的特定路由器型號自訂 DNS 伺服器之用法說明。", + "install_devices_router_list_4": "您無法於某些類型的路由器上設定自訂的 DNS 伺服器。在這種情況下,如果您設置 AdGuard Home 作為 <0>DHCP 伺服器,其可能有所幫助。否則,您應搜尋有關如何為您的特定路由器型號自訂 DNS 伺服器之用法說明。", "install_devices_windows_list_1": "通過開始功能表或 Windows 搜尋,開啟控制台。", "install_devices_windows_list_2": "去網路和網際網路類別,然後去網路和共用中心。", "install_devices_windows_list_3": "於畫面之左側上找到變更介面卡設定並於它上點擊。", @@ -346,6 +361,7 @@ "form_enter_id": "輸入識別碼", "form_add_id": "增加識別碼", "form_client_name": "輸入用戶端名稱", + "name": "名稱", "client_global_settings": "使用全域的設定", "client_deleted": "用戶端 \"{{key}}\" 被成功地刪除", "client_added": "用戶端 \"{{key}}\" 被成功地加入", @@ -445,6 +461,7 @@ "location": "位置", "orgname": "組織名稱", "netname": "網路名稱", + "network": "網路", "descr": "說明", "whois": "Whois", "filtering_rules_learn_more": "<0>了解更多有關創建您自己的主機(hosts)清單。", @@ -456,7 +473,7 @@ "disable_ipv6": "禁用 IPv6", "disable_ipv6_desc": "如果此功能被啟用,所有對於 IPv6 位址(類型 AAAA)的 DNS 查詢將被丟棄。", "fastest_addr": "最快的 IP 位址", - "fastest_addr_desc": "查詢所有的 DNS 伺服器並返回在所有的回應之中最快的 IP 位址", + "fastest_addr_desc": "查詢所有的 DNS 伺服器並返回在所有的回應之中最快的 IP 位址。因為我們必須等待來自所有的 DNS 伺服器之回應,這將使 DNS 查詢變慢,但改善總體的連線。", "autofix_warning_text": "如果您點擊\"修復\",AdGuard Home 將配置您的系統使用 AdGuard Home DNS 伺服器。", "autofix_warning_list": "它將執行這些任務:<0>撤銷系統 DNSStubListener <0>設定 DNS 伺服器位址為 127.0.0.1 <0>用 /run/systemd/resolve/resolv.conf 取代 /etc/resolv.conf 的符號連結目標 <0>停止 DNSStubListener(重新載入 systemd 已解析的服務)", "autofix_warning_result": "因此,預設下,來自您的系統之所有的 DNS 請求將被 AdGuard Home 處理。", @@ -474,7 +491,7 @@ "check_reason": "原因:{{reason}}", "check_rule": "規則:{{rule}}", "check_service": "服務名稱:{{service}}", - "check_not_found": "未在您的過濾器清單中被找到", + "check_not_found": "未在您的過濾器中被找到", "client_confirm_block": "您確定您想要封鎖該用戶端 \"{{ip}}\" 嗎?", "client_confirm_unblock": "您確定您想要解除封鎖該用戶端 \"{{ip}}\" 嗎?", "client_blocked": "用戶端 \"{{ip}}\" 被成功地封鎖", @@ -489,5 +506,19 @@ "list_updated": "{{count}} 清單被更新", "list_updated_plural": "{{count}} 清單被更新", "dnssec_enable": "啟用網域名稱系統安全性擴充功能(DNSSEC)", - "dnssec_enable_desc": "在發出的 DNS 查詢中設定 DNSSEC 標記並檢查該結果(已啟用 DNSSEC 的解析器是必須的)" + "dnssec_enable_desc": "在發出的 DNS 查詢中設定 DNSSEC 標記並檢查該結果(已啟用 DNSSEC 的解析器是必須的)", + "validated_with_dnssec": "已用網域名稱系統安全性擴充功能(DNSSEC)驗證", + "show_all_responses": "所有的回應", + "show_blocked_responses": "已封鎖的", + "show_whitelisted_responses": "已列入白名單的", + "show_processed_responses": "已處理的", + "blocked_safebrowsing": "被安全瀏覽封鎖", + "blocked_adult_websites": "已封鎖的成人網站", + "blocked_threats": "已封鎖的威脅", + "allowed": "已允許的", + "filtered": "已過濾的", + "rewritten": "已改寫的", + "safe_search": "安全搜尋", + "blocklist": "封鎖清單", + "milliseconds_abbreviation": "ms" } \ No newline at end of file diff --git a/client/src/actions/access.js b/client/src/actions/access.js index 9b720872..8e1efab0 100644 --- a/client/src/actions/access.js +++ b/client/src/actions/access.js @@ -3,8 +3,8 @@ import i18next from 'i18next'; import apiClient from '../api/Api'; import { normalizeTextarea } from '../helpers/helpers'; -import { ACTION } from '../helpers/constants'; import { addErrorToast, addSuccessToast } from './toasts'; +import { BLOCK_ACTIONS } from '../helpers/constants'; export const getAccessListRequest = createAction('GET_ACCESS_LIST_REQUEST'); export const getAccessListFailure = createAction('GET_ACCESS_LIST_FAILURE'); @@ -57,9 +57,9 @@ export const toggleClientBlock = (type, ip) => async (dispatch) => { } = await apiClient.getAccessList(); let updatedDisallowedClients = disallowed_clients || []; - if (type === ACTION.unblock && updatedDisallowedClients.includes(ip)) { + if (type === BLOCK_ACTIONS.UNBLOCK && updatedDisallowedClients.includes(ip)) { updatedDisallowedClients = updatedDisallowedClients.filter((client) => client !== ip); - } else if (type === ACTION.block && !updatedDisallowedClients.includes(ip)) { + } else if (type === BLOCK_ACTIONS.BLOCK && !updatedDisallowedClients.includes(ip)) { updatedDisallowedClients.push(ip); } @@ -72,9 +72,9 @@ export const toggleClientBlock = (type, ip) => async (dispatch) => { await apiClient.setAccessList(values); dispatch(toggleClientBlockSuccess(values)); - if (type === ACTION.unblock) { + if (type === BLOCK_ACTIONS.UNBLOCK) { dispatch(addSuccessToast(i18next.t('client_unblocked', { ip }))); - } else if (type === ACTION.block) { + } else if (type === BLOCK_ACTIONS.BLOCK) { dispatch(addSuccessToast(i18next.t('client_blocked', { ip }))); } } catch (error) { diff --git a/client/src/actions/queryLogs.js b/client/src/actions/queryLogs.js index 76d7089b..2a230622 100644 --- a/client/src/actions/queryLogs.js +++ b/client/src/actions/queryLogs.js @@ -2,20 +2,23 @@ import { createAction } from 'redux-actions'; import apiClient from '../api/Api'; import { normalizeLogs, getParamsForClientsSearch, addClientInfo } from '../helpers/helpers'; -import { TABLE_DEFAULT_PAGE_SIZE } from '../helpers/constants'; +import { TABLE_DEFAULT_PAGE_SIZE, TABLE_FIRST_PAGE } from '../helpers/constants'; import { addErrorToast, addSuccessToast } from './toasts'; const getLogsWithParams = async (config) => { const { older_than, filter, ...values } = config; const rawLogs = await apiClient.getQueryLog({ ...filter, older_than }); const { data, oldest } = rawLogs; - const logs = normalizeLogs(data); + let logs = normalizeLogs(data); const clientsParams = getParamsForClientsSearch(logs, 'client'); - const clients = await apiClient.findClients(clientsParams); - const logsWithClientInfo = addClientInfo(logs, clients, 'client'); + + if (Object.keys(clientsParams).length > 0) { + const clients = await apiClient.findClients(clientsParams); + logs = addClientInfo(logs, clients, 'client'); + } return { - logs: logsWithClientInfo, oldest, older_than, filter, ...values, + logs, oldest, older_than, filter, ...values, }; }; @@ -56,6 +59,7 @@ const checkFilteredLogs = async (data, filter, dispatch, total) => { export const setLogsPagination = createAction('LOGS_PAGINATION'); export const setLogsPage = createAction('SET_LOG_PAGE'); +export const toggleDetailedLogs = createAction('TOGGLE_DETAILED_LOGS'); export const getLogsRequest = createAction('GET_LOGS_REQUEST'); export const getLogsFailure = createAction('GET_LOGS_FAILURE'); @@ -93,7 +97,7 @@ export const setLogsFilter = (filter) => async (dispatch) => { const updatedData = additionalData.logs ? { ...data, ...additionalData } : data; dispatch(setLogsFilterSuccess({ ...updatedData, filter })); - dispatch(setLogsPage(0)); + dispatch(setLogsPage(TABLE_FIRST_PAGE)); } catch (error) { dispatch(addErrorToast({ error })); dispatch(setLogsFilterFailure(error)); diff --git a/client/src/components/App/index.css b/client/src/components/App/index.css index 00d5bf50..b24edfd3 100644 --- a/client/src/components/App/index.css +++ b/client/src/components/App/index.css @@ -1,4 +1,9 @@ :root { + --yellow-pale: rgba(247, 181, 0, 0.1); + --green79: #67B279; + --gray-a5: #a5a5a5; + --gray-d8: #d8d8d8; + --gray-f3: #F3F3F3; --font-family-monospace: Monaco, Menlo, "Ubuntu Mono", Consolas, source-code-pro, monospace; } @@ -22,6 +27,16 @@ body { } } +@media screen and (max-width: 992px) { + .container { + padding: 0 !important; + } + + .container--wrap { + min-height: calc(100vh); + } +} + .loading-bar { position: fixed; top: 0; @@ -31,10 +46,17 @@ body { background: linear-gradient(45deg, rgba(99, 125, 120, 1) 0%, rgba(88, 177, 101, 1) 100%); } -.hidden { - display: none; +@media (max-width: 575px) { + .container { + padding-right: 0; + padding-left: 0; + } } .font-monospace { font-family: var(--font-family-monospace); } + +.mw-75 { + max-width: 75% !important; +} diff --git a/client/src/components/App/index.js b/client/src/components/App/index.js index a25941a0..2318c7a9 100644 --- a/client/src/components/App/index.js +++ b/client/src/components/App/index.js @@ -94,7 +94,7 @@ class App extends Component { )} -
+
{dashboard.processing && } {!dashboard.isCoreRunning && (
diff --git a/client/src/components/Dashboard/Clients.js b/client/src/components/Dashboard/Clients.js index 8d35eae1..acb46a57 100644 --- a/client/src/components/Dashboard/Clients.js +++ b/client/src/components/Dashboard/Clients.js @@ -32,17 +32,17 @@ const renderBlockingButton = (ipMatchListStatus, ip, handleClick, processing) => const buttonProps = ipMatchListStatus === IP_MATCH_LIST_STATUS.NOT_FOUND ? { className: 'btn-outline-danger', - text: 'block_btn', + text: 'block', type: 'block', } : { className: 'btn-outline-secondary', - text: 'unblock_btn', + text: 'unblock', type: 'unblock', }; return ( -
+
+
+ ); + }; + + return ( +
+ {processedData && getHintElement({ + className: hintClass, + columnClass: 'grid grid--limited', + tooltipClass: 'px-5 pb-5 pt-4 mw-75', + dataTip: true, + xlinkHref: 'question', + contentItemClass: 'text-truncate key-colon', + title: 'client_details', + content: processedData, + place: 'bottom', + })} +
+
{formatClientCell(row, t, isDetailed)}
+ {isDetailed && name + &&
{name}
} +
+ {renderBlockingButton(isFiltered, domain)} +
+ ); +}; + +getClientCell.propTypes = { + row: PropTypes.object.isRequired, + t: PropTypes.func.isRequired, + isDetailed: PropTypes.bool.isRequired, + toggleBlocking: PropTypes.func.isRequired, + autoClients: PropTypes.array.isRequired, + processingRules: PropTypes.bool.isRequired, +}; + +export default getClientCell; diff --git a/client/src/components/Logs/Cells/getDateCell.js b/client/src/components/Logs/Cells/getDateCell.js new file mode 100644 index 00000000..1b00133b --- /dev/null +++ b/client/src/components/Logs/Cells/getDateCell.js @@ -0,0 +1,28 @@ +import React from 'react'; + +import { formatTime, formatDateTime } from '../../../helpers/helpers'; +import { + DEFAULT_SHORT_DATE_FORMAT_OPTIONS, + DEFAULT_TIME_FORMAT, +} from '../../../helpers/constants'; + +const getDateCell = (row, isDetailed) => { + const { time } = row.original; + + if (!time) { + return '–'; + } + + const formattedTime = formatTime(time, DEFAULT_TIME_FORMAT); + const formattedDate = formatDateTime(time, DEFAULT_SHORT_DATE_FORMAT_OPTIONS); + + return ( +
+
{formattedTime}
+ {isDetailed &&
{formattedDate}
} +
+ ); +}; + +export default getDateCell; diff --git a/client/src/components/Logs/Cells/getDomainCell.js b/client/src/components/Logs/Cells/getDomainCell.js new file mode 100644 index 00000000..423211b5 --- /dev/null +++ b/client/src/components/Logs/Cells/getDomainCell.js @@ -0,0 +1,121 @@ +import React from 'react'; +import classNames from 'classnames'; +import PropTypes from 'prop-types'; +import getHintElement from './getHintElement'; +import { + DEFAULT_SHORT_DATE_FORMAT_OPTIONS, + LONG_TIME_FORMAT, + SCHEME_TO_PROTOCOL_MAP, +} from '../../../helpers/constants'; +import { formatDateTime, formatTime } from '../../../helpers/helpers'; + +const getDomainCell = (props) => { + const { + row, t, isDetailed, dnssec_enabled, + } = props; + + const { + tracker, type, answer_dnssec, client_proto, domain, time, + } = row.original; + + const hasTracker = !!tracker; + + const source = tracker && tracker.sourceData && tracker.sourceData.name; + + const lockIconClass = classNames('icons', 'icon--small', 'd-none', 'd-sm-block', 'cursor--pointer', { + 'icon--active': answer_dnssec, + 'icon--disabled': !answer_dnssec, + 'my-3': isDetailed, + }); + + const privacyIconClass = classNames('icons', 'mx-2', 'icon--small', 'd-none', 'd-sm-block', 'cursor--pointer', { + 'icon--active': hasTracker, + 'icon--disabled': !hasTracker, + 'my-3': isDetailed, + }); + + const dnssecHint = getHintElement({ + className: lockIconClass, + tooltipClass: 'py-4 px-5 pb-45', + dataTip: answer_dnssec, + xlinkHref: 'lock', + columnClass: 'w-100', + content: 'validated_with_dnssec', + place: 'bottom', + }); + + const protocol = t(SCHEME_TO_PROTOCOL_MAP[client_proto]) || ''; + const ip = type ? `${t('type_table_header')}: ${type}` : ''; + + const requestDetailsObj = { + time_table_header: formatTime(time, LONG_TIME_FORMAT), + date: formatDateTime(time, DEFAULT_SHORT_DATE_FORMAT_OPTIONS), + domain, + type_table_header: type, + protocol, + }; + + const knownTrackerDataObj = { + name_table_header: tracker && tracker.name, + category_label: tracker && tracker.category, + source_label: source &&
{source}, + }; + + const renderGrid = (content, idx) => { + const preparedContent = typeof content === 'string' ? t(content) : content; + const className = classNames('text-truncate key-colon o-hidden', { + 'word-break--break-all white-space--normal': preparedContent.length > 100, + }); + return
{preparedContent}
; + }; + + const getGrid = (contentObj, title, className) => [ +
{t(title)}
, +
{React.Children.map(Object.entries(contentObj), renderGrid)}
, + ]; + + const requestDetails = getGrid(requestDetailsObj, 'request_details'); + + const renderContent = hasTracker ? requestDetails.concat(getGrid(knownTrackerDataObj, 'known_tracker', 'pt-4')) : requestDetails; + + const trackerHint = getHintElement({ + className: privacyIconClass, + tooltipClass: 'pt-4 pb-5 px-5 mw-75', + dataTip: true, + xlinkHref: 'privacy', + contentItemClass: 'key-colon', + renderContent, + place: 'bottom', + }); + + const valueClass = classNames('w-100', { + 'px-2 d-flex justify-content-center flex-column': isDetailed, + }); + + const details = [ip, protocol].filter(Boolean) + .join(', '); + + return ( +
+ {dnssec_enabled && dnssecHint} + {trackerHint} +
+
{domain}
+ {details && isDetailed + &&
{details}
} +
+
+ ); +}; + +getDomainCell.propTypes = { + row: PropTypes.object.isRequired, + t: PropTypes.func.isRequired, + isDetailed: PropTypes.bool.isRequired, + toggleBlocking: PropTypes.func.isRequired, + autoClients: PropTypes.array.isRequired, + dnssec_enabled: PropTypes.bool.isRequired, +}; + +export default getDomainCell; diff --git a/client/src/components/Logs/Cells/getHintElement.js b/client/src/components/Logs/Cells/getHintElement.js new file mode 100644 index 00000000..ad38fe2d --- /dev/null +++ b/client/src/components/Logs/Cells/getHintElement.js @@ -0,0 +1,76 @@ +import React, { useState } from 'react'; +import PropTypes from 'prop-types'; +import CustomTooltip from '../Tooltip/CustomTooltip'; + +const getHintElement = ({ + className, + contentItemClass, + columnClass, + dataTip, + xlinkHref, + content, + title, + place, + tooltipClass, + trigger, + overridePosition, + scrollHide, + renderContent, +}) => { + const id = 'id'; + + const [isHovered, hover] = useState(false); + + const openTooltip = () => hover(true); + const closeTooltip = () => hover(false); + + return
+
+ {xlinkHref && + + } +
+ {isHovered && dataTip + && } +
; +}; + +getHintElement.propTypes = { + className: PropTypes.string, + contentItemClass: PropTypes.string, + columnClass: PropTypes.string, + tooltipClass: PropTypes.string, + title: PropTypes.string, + place: PropTypes.string, + dataTip: PropTypes.string, + xlinkHref: PropTypes.string, + overridePosition: PropTypes.func, + scrollHide: PropTypes.bool, + trigger: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.arrayOf(PropTypes.string), + ]), + content: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.array, + ]), + renderContent: PropTypes.arrayOf(PropTypes.element), +}; + +export default getHintElement; diff --git a/client/src/components/Logs/Cells/getResponseCell.js b/client/src/components/Logs/Cells/getResponseCell.js new file mode 100644 index 00000000..f7fec2cf --- /dev/null +++ b/client/src/components/Logs/Cells/getResponseCell.js @@ -0,0 +1,120 @@ +import React from 'react'; +import classNames from 'classnames'; +import { formatElapsedMs } from '../../../helpers/helpers'; +import { + CUSTOM_FILTERING_RULES_ID, + FILTERED_STATUS, + FILTERED_STATUS_TO_META_MAP, +} from '../../../helpers/constants'; +import getHintElement from './getHintElement'; + +const getFilterName = (filters, whitelistFilters, filterId, t) => { + if (filterId === CUSTOM_FILTERING_RULES_ID) { + return t('custom_filter_rules'); + } + + const filter = filters.find((filter) => filter.id === filterId) + || whitelistFilters.find((filter) => filter.id === filterId); + let filterName = ''; + + if (filter) { + filterName = filter.name; + } + + if (!filterName) { + filterName = t('unknown_filter', { filterId }); + } + + return filterName; +}; + +const getResponseCell = (row, filtering, t, isDetailed) => { + const { + reason, filterId, rule, status, upstream, elapsedMs, domain, response, + } = row.original; + + const { filters, whitelistFilters } = filtering; + const formattedElapsedMs = formatElapsedMs(elapsedMs, t); + + const statusLabel = t((FILTERED_STATUS_TO_META_MAP[reason] + && FILTERED_STATUS_TO_META_MAP[reason].label) || reason); + const boldStatusLabel = {statusLabel}; + const filter = getFilterName(filters, whitelistFilters, filterId, t); + + const renderResponses = (responseArr) => { + if (responseArr.length === 0) { + return ''; + } + + return
{responseArr.map((response) => { + const className = classNames('white-space--nowrap', { + 'white-space--normal': response.length > 100, + }); + + return
{`${response}\n`}
; + })}
; + }; + + const FILTERED_STATUS_TO_FIELDS_MAP = { + [FILTERED_STATUS.NOT_FILTERED_NOT_FOUND]: { + domain, + encryption_status: boldStatusLabel, + install_settings_dns: upstream, + elapsed: formattedElapsedMs, + response_code: status, + response_table_header: renderResponses(response), + }, + [FILTERED_STATUS.FILTERED_BLOCKED_SERVICE]: { + domain, + encryption_status: boldStatusLabel, + filter, + rule_label: rule, + response_code: status, + }, + [FILTERED_STATUS.FILTERED_SAFE_SEARCH]: { + domain, + encryption_status: boldStatusLabel, + install_settings_dns: upstream, + elapsed: formattedElapsedMs, + response_code: status, + }, + [FILTERED_STATUS.FILTERED_BLACK_LIST]: { + domain, + encryption_status: boldStatusLabel, + install_settings_dns: upstream, + elapsed: formattedElapsedMs, + response_code: status, + }, + }; + + const fields = FILTERED_STATUS_TO_FIELDS_MAP[reason] + ? Object.entries(FILTERED_STATUS_TO_FIELDS_MAP[reason]) + : Object.entries(FILTERED_STATUS_TO_FIELDS_MAP.NotFilteredNotFound); + + const detailedInfo = reason === FILTERED_STATUS.FILTERED_BLOCKED_SERVICE + || reason === FILTERED_STATUS.FILTERED_BLACK_LIST + ? filter : formattedElapsedMs; + + return ( +
+ {fields && getHintElement({ + className: classNames('icons mr-4 icon--small cursor--pointer icon--light-gray', { 'my-3': isDetailed }), + columnClass: 'grid grid--limited', + tooltipClass: 'px-5 pb-5 pt-4 mw-75 custom-tooltip__response-details', + contentItemClass: 'text-truncate key-colon o-hidden', + dataTip: true, + xlinkHref: 'question', + title: 'response_details', + content: fields, + place: 'bottom', + })} +
+
{statusLabel}
+ {isDetailed &&
{detailedInfo}
} +
+
+ ); +}; + +export default getResponseCell; diff --git a/client/src/components/Logs/Disabled.js b/client/src/components/Logs/Disabled.js new file mode 100644 index 00000000..8d2b45a4 --- /dev/null +++ b/client/src/components/Logs/Disabled.js @@ -0,0 +1,30 @@ +import React, { Fragment } from 'react'; +import { Trans } from 'react-i18next'; +import { HashLink as Link } from 'react-router-hash-link'; + +import Card from '../ui/Card'; + +const Disabled = () => ( + +
+

+ query_log +

+
+ +
+ + link + , + ]} + > + query_log_disabled + +
+
+
+); + +export default Disabled; diff --git a/client/src/components/Logs/Filters/Form.js b/client/src/components/Logs/Filters/Form.js index 9a10442f..df0bc483 100644 --- a/client/src/components/Logs/Filters/Form.js +++ b/client/src/components/Logs/Filters/Form.js @@ -1,11 +1,9 @@ -import React, { Fragment } from 'react'; +import React from 'react'; import PropTypes from 'prop-types'; import { Field, reduxForm } from 'redux-form'; -import { withTranslation } from 'react-i18next'; -import flow from 'lodash/flow'; - -import { renderInputField } from '../../../helpers/form'; -import { FORM_NAME, RESPONSE_FILTER } from '../../../helpers/constants'; +import { useTranslation } from 'react-i18next'; +import debounce from 'lodash/debounce'; +import { DEBOUNCE_FILTER_TIMEOUT, FORM_NAME, RESPONSE_FILTER } from '../../../helpers/constants'; import Tooltip from '../../ui/Tooltip'; const renderFilterField = ({ @@ -18,25 +16,28 @@ const renderFilterField = ({ autoComplete, tooltip, meta: { touched, error }, -}) => -
- - +}) => <> +
+ + + +
+ + - {!disabled - && touched - && (error && {error})} -
-
; + {!disabled + && touched + && (error && {error})} +; renderFilterField.propTypes = { input: PropTypes.object.isRequired, @@ -55,62 +56,47 @@ renderFilterField.propTypes = { const Form = (props) => { const { - t, - handleChange, + className = '', + responseStatusClass, + submit, } = props; + const [t] = useTranslation(); + + const debouncedSubmit = debounce(submit, DEBOUNCE_FILTER_TIMEOUT); + const zeroDelaySubmit = () => setTimeout(submit, 0); + return ( -
-
-
- -
-
- -
-
- - - - -
-
- -
+ { + e.preventDefault(); + zeroDelaySubmit(); + debouncedSubmit.cancel(); + }} + > + +
+ + {Object.values(RESPONSE_FILTER) + .map(({ + query, label, disabled, + }) => )} +
); @@ -118,12 +104,11 @@ const Form = (props) => { Form.propTypes = { handleChange: PropTypes.func, - t: PropTypes.func.isRequired, + className: PropTypes.string, + responseStatusClass: PropTypes.string, + submit: PropTypes.func.isRequired, }; -export default flow([ - withTranslation(), - reduxForm({ - form: FORM_NAME.LOGS_FILTER, - }), -])(Form); +export default reduxForm({ + form: FORM_NAME.LOGS_FILTER, +})(Form); diff --git a/client/src/components/Logs/Filters/index.js b/client/src/components/Logs/Filters/index.js index ab654cbe..49744af3 100644 --- a/client/src/components/Logs/Filters/index.js +++ b/client/src/components/Logs/Filters/index.js @@ -1,52 +1,48 @@ -import React, { Component } from 'react'; +import React from 'react'; import PropTypes from 'prop-types'; -import debounce from 'lodash/debounce'; -import classnames from 'classnames'; - -import { DEBOUNCE_FILTER_TIMEOUT, RESPONSE_FILTER } from '../../../helpers/constants'; -import { isValidQuestionType } from '../../../helpers/helpers'; +import { Trans } from 'react-i18next'; +import { useDispatch } from 'react-redux'; import Form from './Form'; -import Card from '../../ui/Card'; +import { setLogsFilter } from '../../../actions/queryLogs'; -class Filters extends Component { - getFilters = ({ - filter_domain, filter_question_type, filter_response_status, filter_client, - }) => ({ - filter_domain: filter_domain || '', - filter_question_type: isValidQuestionType(filter_question_type) ? filter_question_type.toUpperCase() : '', - filter_response_status: filter_response_status === RESPONSE_FILTER.FILTERED ? filter_response_status : '', - filter_client: filter_client || '', - }); +const Filters = ({ filter, refreshLogs, setIsLoading }) => { + const dispatch = useDispatch(); - handleFormChange = debounce((values) => { - const filter = this.getFilters(values); - this.props.setLogsFilter(filter); - }, DEBOUNCE_FILTER_TIMEOUT); + const onSubmit = async (values) => { + setIsLoading(true); + await dispatch(setLogsFilter(values)); + setIsLoading(false); + }; - render() { - const { filter, processingAdditionalLogs } = this.props; + return ( +
+

+ query_log + - const cardBodyClass = classnames({ - 'card-body': true, - 'card-body--loading': processingAdditionalLogs, - }); - - return ( - -
- - ); - } -} +

+ +
+ ); +}; Filters.propTypes = { filter: PropTypes.object.isRequired, - setLogsFilter: PropTypes.func.isRequired, + refreshLogs: PropTypes.func.isRequired, processingGetLogs: PropTypes.bool.isRequired, - processingAdditionalLogs: PropTypes.bool.isRequired, + setIsLoading: PropTypes.func.isRequired, }; export default Filters; diff --git a/client/src/components/Logs/Logs.css b/client/src/components/Logs/Logs.css index 4eb4a0fb..5a405918 100644 --- a/client/src/components/Logs/Logs.css +++ b/client/src/components/Logs/Logs.css @@ -1,8 +1,15 @@ +:root { + --gray-4d: #4D4D4D; + --gray-8: #888; + --danger: #DF3812; +} + .logs__row { position: relative; display: flex; - align-items: center; min-height: 26px; + overflow: hidden; + text-overflow: ellipsis; } .logs__row--center { @@ -15,10 +22,6 @@ justify-content: center; } -.logs__row--overflow { - overflow: hidden; -} - .logs__row--icons { max-width: 180px; flex-flow: row wrap; @@ -35,6 +38,15 @@ text-overflow: ellipsis; white-space: nowrap; overflow: hidden; + font-size: 1rem; + font-family: var(--font-family-sans-serif); + color: var(--gray-4d); + letter-spacing: 0; + line-height: 1.5rem; +} + +.logs__text--bold { + font-weight: bold; } .logs__text--full { @@ -51,6 +63,11 @@ white-space: normal; } +.logs__text--nowrap { + line-height: 1.4; + white-space: nowrap; +} + .logs__text--whois { line-height: 1.2; } @@ -61,11 +78,18 @@ margin-right: 5px; } -.logs__action, -.table__action { - position: absolute; - top: 11px; - right: 15px; +.tooltip__option { + height: 2.5rem !important; + width: 10.5rem; + padding: 0.3125rem 1.5rem 0.6875rem; +} + +.tooltip__option:hover { + background-color: var(--gray-f3); + cursor: pointer; +} + +.button__action { background-color: #fff; border-radius: 4px; transition: opacity 0.2s ease, visibility 0.2s ease; @@ -73,11 +97,31 @@ opacity: 0; } +.table__action { + position: absolute; + top: 11px; + right: 15px; +} + +.logs__action { + position: absolute; + top: 0; + right: 1rem; +} + +.logs__action--detailed { + top: 5px; +} + .logs__table .rt-td, .clients__table .rt-td { position: relative; } +.logs__table .rt-thead, .logs__table .rt-tbody { + min-width: 100% !important; +} + .logs__table .rt-tr:hover .logs__action, .clients__table .rt-tr:hover .table__action { visibility: visible; @@ -152,14 +196,14 @@ } .logs__notice { - position: absolute; + position: relative; z-index: 1; - top: 8px; - right: 10px; - margin-top: 3px; - font-size: 12px; + top: 0.5rem; + right: 2rem; + margin-top: 0.1875rem; + font-size: 0.75rem; text-align: left; - color: #a5a5a5; + color: var(--gray-a5); } .logs__whois { @@ -185,3 +229,348 @@ margin-right: 1px; opacity: 0.5; } + +/* New logs */ +.logs__table { + background-color: #fff; + border: 0; + border-radius: 8px; + min-height: 42rem; + max-width: 71rem; +} + +.logs__table--detailed { + min-height: 50rem; +} + +.logs__table .rt-thead.-header { + box-shadow: none; + font-weight: bold; +} + +.logs__table .rt-thead .rt-th { + padding: 0.9375rem 0.9375rem 0.875rem 0; + text-align: left; + border-right: 0; +} + +.logs__table .rt-tbody .rt-td { + padding: 1rem 1rem 0.5rem 0; + border-right: 0; +} + +.logs__table .rt-thead .rt-th:last-child, +.logs__table .rt-tbody .rt-td:last-child { + padding-right: 0; +} + +.logs__table .rt-tbody .rt-tr-group { + border-bottom: 0; +} + +.logs__table .rt-tr { + position: relative; + padding: 0 24px; +} + +.logs__table .rt-tr { + position: relative; + padding: 0 1.5rem; +} + +.logs__table .rt-tr-group:not(:first-child) .rt-tr:before { + content: ""; + position: absolute; + left: 1.5rem; + right: 1.5rem; + top: 0; + width: calc(100% - 3rem); + height: 2px; + background-color: rgba(216, 216, 216, 0.23); +} + +.logs__table .rt-tr-group:last-child .rt-tr:after, +.logs__table .rt-thead .rt-tr:after { + display: none; +} + +.logs__time { + font-size: 1rem; + line-height: 1.5; +} + +.detailed-info { + font-size: 0.8rem; + line-height: 1.4; + color: #888888; +} + +.icon--selected { + background-color: var(--gray-f3); + border: solid 1px var(--gray-d8); + border-radius: 4px; +} + +/* Hide 3 and 4 column on mobile */ +.logs__table .rt-thead .rt-th:nth-child(3), +.logs__table .rt-thead .rt-th:nth-child(4), +.logs__table .rt-tbody .rt-td:nth-child(3), +.logs__table .rt-tbody .rt-td:nth-child(4) { + display: none; +} + +@media screen and (min-width: 768px) { + .logs__table .rt-thead .rt-th:nth-child(3), + .logs__table .rt-thead .rt-th:nth-child(4), + .logs__table .rt-tbody .rt-td:nth-child(3), + .logs__table .rt-tbody .rt-td:nth-child(4) { + display: block; + } +} + +.text-pre { + white-space: pre-wrap !important; + overflow-wrap: break-word; + overflow: visible; +} + +.custom-pagination { + width: 11.875rem !important; + background-color: transparent; + box-shadow: none !important; + border: none !important; + align-items: center !important; +} + +.custom-pagination--padding { + padding: 2.5rem 0 2.5rem !important; +} + +.custom-pagination .-btn { + --side-size: 2rem; + background-color: transparent !important; + border: 1px solid var(--gray-d8) !important; + border-radius: 4px !important; + width: var(--side-size) !important; + height: var(--side-size) !important; +} + +.custom-pagination .-btn:enabled:hover { + background-color: var(--gray-f3) !important; +} + +.custom-pagination .-previous { + flex: 0 1 !important; +} + +.custom-pagination .-next { + flex: 0 1 !important; +} + +.custom-pagination .-btn { + display: flex !important; +} + +.-pageInfo { + --side-size: 2rem; + font-variant-numeric: tabular-nums !important; + background-color: transparent !important; + border: 1px solid var(--gray-d8) !important; + border-radius: 4px !important; + width: var(--side-size) !important; + height: var(--side-size) !important; + margin: 0 !important; + display: flex !important; + justify-content: center; + align-items: center; +} + +.pagination-bottom { + justify-content: center !important; + display: flex !important; +} + +.-center:before { + content: '...'; + transform: translateY(-0.25rem); + margin: auto; +} + +.-center:after { + content: '...'; + transform: translateY(-0.25rem); + margin: auto; +} + +.icon--detailed-info { + position: absolute; + right: 0; + top: 0.5rem; +} + +.icon--light-gray { + color: var(--gray-8); +} + +.link--green { + color: var(--green79); +} + +.row--detailed { + height: 4.9rem +} + +.w-90 { + max-width: 90% !important; +} + +.h-85 { + height: 85% !important; +} + +.pt-45 { + padding-top: 1.25rem !important; +} + +.pb-45 { + padding-bottom: 1.25rem !important; +} + +.py-45 { + padding-top: 1.25rem !important; + padding-bottom: 1.25rem !important; +} + +.mh-100 { + max-height: 100% !important; +} + +.cursor--pointer { + cursor: pointer; +} + +.custom-select__arrow--left { + background: #fff url('./chevron-down.svg') no-repeat left 0.2rem center; + background-size: 1.5rem; +} + +.custom-select--logs { + padding: 0.5rem 0.75rem 0.5rem 1.75rem !important; +} + +.bg--danger { + color: var(--danger); +} + +.ml-small { + margin-left: 3.3125rem; +} + +.form-control--search { + width: 39.125rem; + box-shadow: 0 1px 0 #ddd; + padding: 0 2.5rem; + height: 2.25rem; +} + +.form-control--transparent { + border: 0 solid transparent !important; + background-color: transparent !important; +} + +.input-group-search { + background-color: transparent; + position: relative; + left: 2rem; + top: 0.4rem; + width: 1.5rem; + height: 1.5rem; +} + +.form-control--container { + max-width: 100%; +} + +@media (max-width: 1279.98px) { + .form-control--search { + max-width: 30.125rem; + } + + .form-control--container { + max-width: 70%; + } + + .form-control--search { + max-width: 50%; + } +} + +@media (max-width: 991.98px) { + .form-control--search { + max-width: 40%; + } + + .form-control--container { + max-width: 100%; + } +} + +@media (max-width: 767.98px) { + .rt-tr .logs__row .logs__text { + max-width: calc(100% - 1.5rem); + } + + .ml-small { + margin-left: 1.5rem; + } +} + +@media (max-width: 575px) { + .logs__table .rt-tr { + height: 3.125rem; + } + + .logs__table .rt-tbody .rt-td { + padding: 0.625rem 1rem 0.875rem 0; + } + + .logs__table { + min-height: 42rem; + } +} + +@media (max-width: 500px) { + .form-control--search { + max-width: 85%; + } + + .field__select { + margin-top: 1.5rem; + } +} + +.loading__container > .-loading-inner { + top: 10rem !important; + bottom: initial !important; +} + +.loading__text { + transform: translateY(3rem); +} + +/*reset position to make absolute position of tooltip on tablets, may cause problems https://github.com/wwayne/react-tooltip/issues/204*/ +@media (hover: none) { + .logs__action { + top: 1rem !important; + right: 1rem; + } + + .logs__table .rt-td, + .clients__table .rt-td { + position: initial; + } + + .logs__row { + position: initial; + } +} diff --git a/client/src/components/Logs/Table.js b/client/src/components/Logs/Table.js new file mode 100644 index 00000000..586fca12 --- /dev/null +++ b/client/src/components/Logs/Table.js @@ -0,0 +1,399 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { useTranslation, Trans } from 'react-i18next'; +import ReactTable from 'react-table'; +import classNames from 'classnames'; +import endsWith from 'lodash/endsWith'; +import escapeRegExp from 'lodash/escapeRegExp'; +import { + BLOCK_ACTIONS, + DEFAULT_SHORT_DATE_FORMAT_OPTIONS, + LONG_TIME_FORMAT, + FILTERED_STATUS_TO_META_MAP, + TABLE_DEFAULT_PAGE_SIZE, + SCHEME_TO_PROTOCOL_MAP, +} from '../../helpers/constants'; +import getDateCell from './Cells/getDateCell'; +import getDomainCell from './Cells/getDomainCell'; +import getClientCell from './Cells/getClientCell'; +import getResponseCell from './Cells/getResponseCell'; + +import { + checkFiltered, + formatDateTime, + formatElapsedMs, + formatTime, + +} from '../../helpers/helpers'; +import Loading from '../ui/Loading'; + +const Table = (props) => { + const { + setDetailedDataCurrent, + setButtonType, + setModalOpened, + isSmallScreen, + setIsLoading, + filtering, + isDetailed, + toggleDetailedLogs, + setLogsPage, + setLogsPagination, + processingGetLogs, + logs, + pages, + page, + isLoading, + } = props; + + const [t] = useTranslation(); + + const toggleBlocking = (type, domain) => { + const { + setRules, getFilteringStatus, addSuccessToast, + } = props; + const { userRules } = filtering; + + const lineEnding = !endsWith(userRules, '\n') ? '\n' : ''; + const baseRule = `||${domain}^$important`; + const baseUnblocking = `@@${baseRule}`; + + const blockingRule = type === BLOCK_ACTIONS.BLOCK ? baseUnblocking : baseRule; + const unblockingRule = type === BLOCK_ACTIONS.BLOCK ? baseRule : baseUnblocking; + const preparedBlockingRule = new RegExp(`(^|\n)${escapeRegExp(blockingRule)}($|\n)`); + const preparedUnblockingRule = new RegExp(`(^|\n)${escapeRegExp(unblockingRule)}($|\n)`); + + const matchPreparedBlockingRule = userRules.match(preparedBlockingRule); + const matchPreparedUnblockingRule = userRules.match(preparedUnblockingRule); + + if (matchPreparedBlockingRule) { + setRules(userRules.replace(`${blockingRule}`, '')); + addSuccessToast(`${t('rule_removed_from_custom_filtering_toast')}: ${blockingRule}`); + } else if (!matchPreparedUnblockingRule) { + setRules(`${userRules}${lineEnding}${unblockingRule}\n`); + addSuccessToast(`${t('rule_added_to_custom_filtering_toast')}: ${unblockingRule}`); + } else if (matchPreparedUnblockingRule) { + addSuccessToast(`${t('rule_added_to_custom_filtering_toast')}: ${unblockingRule}`); + return; + } else if (!matchPreparedBlockingRule) { + addSuccessToast(`${t('rule_removed_from_custom_filtering_toast')}: ${blockingRule}`); + return; + } + + getFilteringStatus(); + }; + + const columns = [ + { + Header: t('time_table_header'), + accessor: 'time', + Cell: (row) => getDateCell(row, isDetailed), + minWidth: 70, + maxHeight: 60, + headerClassName: 'logs__text', + }, + { + Header: t('request_table_header'), + accessor: 'domain', + Cell: (row) => { + const { + isDetailed, + autoClients, + dnssec_enabled, + } = props; + + return getDomainCell({ + row, + t, + isDetailed, + toggleBlocking, + autoClients, + dnssec_enabled, + }); + }, + minWidth: 180, + maxHeight: 60, + headerClassName: 'logs__text', + }, + { + Header: t('response_table_header'), + accessor: 'response', + Cell: (row) => getResponseCell( + row, + filtering, + t, + isDetailed, + ), + minWidth: 150, + maxHeight: 60, + headerClassName: 'logs__text', + }, + { + Header: () => { + const plainSelected = classNames('cursor--pointer', { + 'icon--selected': !isDetailed, + }); + + const detailedSelected = classNames('cursor--pointer', { + 'icon--selected': isDetailed, + }); + + return
+ {t('client_table_header')} + { + toggleDetailedLogs(false)} + > + compact + + + toggleDetailedLogs(true)} + > + default + + + } +
; + }, + accessor: 'client', + Cell: (row) => { + const { + isDetailed, + autoClients, + filtering: { processingRules }, + } = props; + + return getClientCell({ + row, + t, + isDetailed, + toggleBlocking, + autoClients, + processingRules, + }); + }, + minWidth: 123, + maxHeight: 60, + headerClassName: 'logs__text', + }, + ]; + + const changePage = async (page) => { + setIsLoading(true); + + const { oldest, getLogs, pages } = props; + const isLastPage = pages && (page + 1 === pages); + + await Promise.all([ + setLogsPage(page), + setLogsPagination({ + page, + pageSize: TABLE_DEFAULT_PAGE_SIZE, + }), + ].concat(isLastPage ? getLogs(oldest, page) : [])); + + setIsLoading(false); + }; + + const tableClass = classNames('logs__table', { + 'logs__table--detailed': isDetailed, + }); + + return ( + + +
{t('loading_table_status')}
+ + } + getLoadingProps={() => ({ className: 'loading__container' })} + rowsText={t('rows_table_footer_text')} + noDataText={!processingGetLogs + && } + pageText='' + ofText='' + showPagination={logs.length > 0} + getPaginationProps={() => ({ className: 'custom-pagination custom-pagination--padding' })} + getTbodyProps={() => ({ className: 'd-block' })} + previousText={ + + previous_btn + + } + nextText={ + + next_btn + + } + renderTotalPagesCount={() => false} + getTrGroupProps={(_state, rowInfo) => { + if (!rowInfo) { + return {}; + } + + const { reason } = rowInfo.original; + const colorClass = FILTERED_STATUS_TO_META_MAP[reason] ? FILTERED_STATUS_TO_META_MAP[reason].color : 'white'; + + return { className: colorClass }; + }} + getTrProps={(state, rowInfo) => ({ + className: isDetailed ? 'row--detailed' : '', + onClick: () => { + if (isSmallScreen) { + const { dnssec_enabled, autoClients } = props; + const { + answer_dnssec, + client, + domain, + elapsedMs, + info, + reason, + response, + time, + tracker, + upstream, + type, + client_proto, + } = rowInfo.original; + + const hasTracker = !!tracker; + + const autoClient = autoClients.find( + (autoClient) => autoClient.name === client, + ); + + const country = autoClient && autoClient.whois_info + && autoClient.whois_info.country; + + const network = autoClient && autoClient.whois_info + && autoClient.whois_info.orgname; + + const city = autoClient && autoClient.whois_info + && autoClient.whois_info.city; + + const source = autoClient && autoClient.source; + + const formattedElapsedMs = formatElapsedMs(elapsedMs, t); + const isFiltered = checkFiltered(reason); + + const buttonType = isFiltered ? BLOCK_ACTIONS.UNBLOCK : BLOCK_ACTIONS.BLOCK; + const onToggleBlock = () => { + toggleBlocking(buttonType, domain); + }; + + const tracker_source = tracker && tracker.sourceData + && tracker.sourceData.name; + + const status = t((FILTERED_STATUS_TO_META_MAP[reason] + && FILTERED_STATUS_TO_META_MAP[reason].label) || reason); + const statusBlocked =
{status}
; + + const protocol = t(SCHEME_TO_PROTOCOL_MAP[client_proto]) || ''; + + const detailedData = { + time_table_header: formatTime(time, LONG_TIME_FORMAT), + date: formatDateTime(time, DEFAULT_SHORT_DATE_FORMAT_OPTIONS), + encryption_status: status, + domain, + type_table_header: type, + protocol, + known_tracker: hasTracker && 'title', + table_name: hasTracker && tracker.name, + category_label: hasTracker && tracker.category, + tracker_source: hasTracker && tracker_source && {tracker_source}, + response_details: 'title', + install_settings_dns: upstream, + elapsed: formattedElapsedMs, + response_table_header: response && response.join('\n'), + client_details: 'title', + ip_address: client, + name: info && info.name, + country, + city, + network, + source_label: source, + validated_with_dnssec: dnssec_enabled ? Boolean(answer_dnssec) : false, + [buttonType]:
{t(buttonType)}
, + }; + + const detailedDataBlocked = { + time_table_header: formatTime(time, LONG_TIME_FORMAT), + date: formatDateTime(time, DEFAULT_SHORT_DATE_FORMAT_OPTIONS), + encryption_status: statusBlocked, + domain, + type_table_header: type, + protocol, + known_tracker: 'title', + table_name: hasTracker && tracker.name, + category_label: hasTracker && tracker.category, + source_label: hasTracker && source + && {source}, + response_details: 'title', + install_settings_dns: upstream, + elapsed: formattedElapsedMs, + response_table_header: response && response.join('\n'), + [buttonType]:
{t(buttonType)}
, + }; + + const detailedDataCurrent = isFiltered ? detailedDataBlocked : detailedData; + + setDetailedDataCurrent(detailedDataCurrent); + setButtonType(buttonType); + setModalOpened(true); + } + }, + })} + /> + ); +}; + +Table.propTypes = { + logs: PropTypes.array.isRequired, + pages: PropTypes.number.isRequired, + page: PropTypes.number.isRequired, + autoClients: PropTypes.array.isRequired, + defaultPageSize: PropTypes.number, + oldest: PropTypes.string.isRequired, + filtering: PropTypes.object.isRequired, + processingGetLogs: PropTypes.bool.isRequired, + processingGetConfig: PropTypes.bool.isRequired, + isDetailed: PropTypes.bool.isRequired, + setLogsPage: PropTypes.func.isRequired, + setLogsPagination: PropTypes.func.isRequired, + getLogs: PropTypes.func.isRequired, + toggleDetailedLogs: PropTypes.func.isRequired, + setRules: PropTypes.func.isRequired, + addSuccessToast: PropTypes.func.isRequired, + getFilteringStatus: PropTypes.func.isRequired, + isLoading: PropTypes.bool.isRequired, + setIsLoading: PropTypes.func.isRequired, + dnssec_enabled: PropTypes.bool.isRequired, + setDetailedDataCurrent: PropTypes.func.isRequired, + setButtonType: PropTypes.func.isRequired, + setModalOpened: PropTypes.func.isRequired, + isSmallScreen: PropTypes.bool.isRequired, +}; + +export default Table; diff --git a/client/src/components/Logs/Tooltip/CustomTooltip.js b/client/src/components/Logs/Tooltip/CustomTooltip.js new file mode 100644 index 00000000..1a0cf64f --- /dev/null +++ b/client/src/components/Logs/Tooltip/CustomTooltip.js @@ -0,0 +1,44 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Trans } from 'react-i18next'; +import classNames from 'classnames'; +import Tooltip from './index'; + +const CustomTooltip = ({ + id, title, className, contentItemClass, place = 'right', columnClass = '', content, trigger, overridePosition, scrollHide, + renderContent = React.Children.map( + content, + (item, idx) =>
+ {item || '—'} +
, + ), +}) => + {title + &&
{title}
} +
{renderContent}
+
; + +CustomTooltip.propTypes = { + id: PropTypes.string.isRequired, + title: PropTypes.string, + place: PropTypes.string, + className: PropTypes.string, + columnClass: PropTypes.string, + contentItemClass: PropTypes.string, + overridePosition: PropTypes.func, + scrollHide: PropTypes.bool, + content: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.array, + ]), + trigger: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.arrayOf(PropTypes.string), + ]), + renderContent: PropTypes.arrayOf(PropTypes.element), +}; + +export default CustomTooltip; diff --git a/client/src/components/Logs/Tooltip/ReactTooltip.css b/client/src/components/Logs/Tooltip/ReactTooltip.css new file mode 100644 index 00000000..bc8de6c5 --- /dev/null +++ b/client/src/components/Logs/Tooltip/ReactTooltip.css @@ -0,0 +1,129 @@ +.custom-tooltip { + padding: 1rem 1.5rem 1.25rem 1.5rem; + font-size: 16px !important; + box-shadow: 2px 4px 8px rgba(0, 0, 0, 0.2); + border-radius: 4px !important; + pointer-events: auto !important; +} + +/*crutch, may cause problems https://github.com/wwayne/react-tooltip/issues/204*/ +@media (hover: none) { + .custom-tooltip { + position: absolute !important; + top: 4rem !important; + } +} + +.white-space--nowrap { + white-space: nowrap !important; +} + +.white-space--normal { + white-space: normal !important; +} + +.word-break--break-all { + word-break: break-all !important; +} + +.grid { + display: grid; + grid-template-columns: repeat(2, min-content); + grid-row-gap: 0.5rem; + grid-column-gap: 1rem; +} + +.grid--limited { + grid-template-columns: repeat(2, minmax(0, min-content)); +} + +.grid--gap-bg { + grid-column-gap: 1.5rem; +} + +.grid--title { + font-weight: bold; +} + +.grid--title:not(:first-child) { + padding-top: 1rem; +} + +@media (max-width: 767.98px) { + .grid { + grid-template-columns: 35% 55%; + } + + .grid * { + grid-column: 1 / -1; + } + + .grid > :nth-child(even) { + margin: -0.5rem 0 0; + } + + .grid > .key__time_table_header, .grid > .key__data, .grid > .key__encryption_status, .grid > .key__elapsed { + grid-column: 1 / span 1; + } + + .grid > .value__time_table_header, .grid > .value__data, .grid > .value__encryption_status, .grid > .value__elapsed { + grid-column: 2 / span 1; + margin: 0 !important; + } + + .grid .key-colon, .grid .title--border { + font-weight: bold; + } + + .custom-tooltip { + overflow-y: scroll; + } +} + +.grid .key-colon:nth-child(odd)::after { + content: ':'; +} + +.grid__one-row { + grid-template-columns: 15rem; +} + +.grid__flow-column { + grid-auto-flow: column; +} + +.custom-tooltip.show { + opacity: 1 !important; +} + +.custom-tooltip:hover { + opacity: 1 !important; +} + +.grid-content > * { + justify-content: space-between !important; + width: 100% !important; + overflow: hidden; + -o-text-overflow: ellipsis; + text-overflow: ellipsis; + white-space: nowrap; +} + +.title--border { + padding-top: 2rem; +} + +.title--border:before { + content: ''; + position: absolute; + left: 0; + border-top: 0.5px solid var(--gray-d8) !important; + width: 100%; + margin-top: -1rem; +} + +.icon-cross { + position: absolute; + right: 0.5rem; + top: 0.5rem; +} diff --git a/client/src/components/Logs/Tooltip/index.js b/client/src/components/Logs/Tooltip/index.js new file mode 100644 index 00000000..6844249a --- /dev/null +++ b/client/src/components/Logs/Tooltip/index.js @@ -0,0 +1,48 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import ReactTooltip from 'react-tooltip'; +import classNames from 'classnames'; +import './ReactTooltip.css'; +import { touchMediaQuery } from '../../../helpers/constants'; + +const Tooltip = ({ + id, children, className = '', place = 'right', trigger = 'hover', overridePosition, scrollHide = true, +}) => { + const tooltipClassName = classNames('custom-tooltip', className); + + return ( + + {children} + + ); +}; + +Tooltip.propTypes = { + id: PropTypes.string.isRequired, + children: PropTypes.node.isRequired, + className: PropTypes.string, + place: PropTypes.string, + overridePosition: PropTypes.func, + scrollHide: PropTypes.bool, + trigger: PropTypes.oneOfType([ + PropTypes.string, + PropTypes.arrayOf(PropTypes.string), + ]), +}; + +export default Tooltip; diff --git a/client/src/components/Logs/chevron-down.svg b/client/src/components/Logs/chevron-down.svg new file mode 100644 index 00000000..e7851196 --- /dev/null +++ b/client/src/components/Logs/chevron-down.svg @@ -0,0 +1 @@ + \ No newline at end of file diff --git a/client/src/components/Logs/index.js b/client/src/components/Logs/index.js index 186934e5..3ac21857 100644 --- a/client/src/components/Logs/index.js +++ b/client/src/components/Logs/index.js @@ -1,457 +1,210 @@ -import React, { Component, Fragment } from 'react'; +import React, { Fragment, useEffect, useState } from 'react'; import PropTypes from 'prop-types'; -import ReactTable from 'react-table'; -import escapeRegExp from 'lodash/escapeRegExp'; -import endsWith from 'lodash/endsWith'; -import { Trans, withTranslation } from 'react-i18next'; -import { HashLink as Link } from 'react-router-hash-link'; - +import { Trans } from 'react-i18next'; +import Modal from 'react-modal'; +import { useDispatch } from 'react-redux'; import { - formatTime, - formatDateTime, - isToday, - checkFiltered, - checkRewrite, - checkRewriteHosts, - checkWhiteList, - checkBlackList, - checkBlockedService, -} from '../../helpers/helpers'; -import { - SERVICES, TABLE_DEFAULT_PAGE_SIZE, CUSTOM_FILTERING_RULES_ID, FILTERED, + BLOCK_ACTIONS, smallScreenSize, + TABLE_DEFAULT_PAGE_SIZE, + TABLE_FIRST_PAGE, } from '../../helpers/constants'; -import { getTrackerData } from '../../helpers/trackers/trackers'; -import { formatClientCell } from '../../helpers/formatClientCell'; - -import Filters from './Filters'; -import PageTitle from '../ui/PageTitle'; -import Card from '../ui/Card'; import Loading from '../ui/Loading'; -import PopoverFiltered from '../ui/PopoverFilter'; -import Popover from '../ui/Popover'; +import Filters from './Filters'; +import Table from './Table'; +import Disabled from './Disabled'; import './Logs.css'; -import CellWrap from '../ui/CellWrap'; +import { getFilteringStatus } from '../../actions/filtering'; +import { getClients } from '../../actions'; +import { getDnsConfig } from '../../actions/dnsConfig'; +import { getLogsConfig } from '../../actions/queryLogs'; +import { addSuccessToast } from '../../actions/toasts'; -const TABLE_FIRST_PAGE = 0; const INITIAL_REQUEST = true; const INITIAL_REQUEST_DATA = ['', TABLE_FIRST_PAGE, INITIAL_REQUEST]; -class Logs extends Component { - componentDidMount() { - this.props.setLogsPage(TABLE_FIRST_PAGE); - this.getLogs(...INITIAL_REQUEST_DATA); - this.props.getFilteringStatus(); - this.props.getLogsConfig(); - } +export const processContent = (data, buttonType) => Object.entries(data) + .map(([key, value]) => { + const isTitle = value === 'title'; + const isButton = key === buttonType; + const isBoolean = typeof value === 'boolean'; + const isHidden = isBoolean && value === false; - getLogs = (older_than, page, initial) => { - if (this.props.queryLogs.enabled) { - this.props.getLogs({ - older_than, page, pageSize: TABLE_DEFAULT_PAGE_SIZE, initial, + let keyClass = 'key-colon'; + + if (isTitle) { + keyClass = 'title--border'; + } + if (isButton || isBoolean) { + keyClass = ''; + } + + return isHidden ? null : +
+ {isButton ? value : key} +
+
+ {(isTitle || isButton || isBoolean) ? '' : value || '—'} +
+
; + }); + + +const Logs = (props) => { + const dispatch = useDispatch(); + const [isSmallScreen, setIsSmallScreen] = useState(window.innerWidth < smallScreenSize); + const [detailedDataCurrent, setDetailedDataCurrent] = useState({}); + const [buttonType, setButtonType] = useState(BLOCK_ACTIONS.BLOCK); + const [isModalOpened, setModalOpened] = useState(false); + const [isLoading, setIsLoading] = useState(false); + + const { + filtering, + setLogsPage, + setLogsPagination, + setLogsFilter, + toggleDetailedLogs, + dashboard, + dnsConfig, + queryLogs: { + filter, + enabled, + processingGetConfig, + processingAdditionalLogs, + processingGetLogs, + oldest, + logs, + pages, + page, + isDetailed, + }, + } = props; + + const mediaQuery = window.matchMedia(`(max-width: ${smallScreenSize}px)`); + const mediaQueryHandler = (e) => { + setIsSmallScreen(e.matches); + if (e.matches) { + toggleDetailedLogs(false); + } + }; + + useEffect(() => { + mediaQuery.addListener(mediaQueryHandler); + + return () => mediaQuery.removeListener(mediaQueryHandler); + }, []); + + const closeModal = () => setModalOpened(false); + + const getLogs = (older_than, page, initial) => { + if (props.queryLogs.enabled) { + props.getLogs({ + older_than, + page, + pageSize: TABLE_DEFAULT_PAGE_SIZE, + initial, }); } }; - refreshLogs = () => { - window.location.reload(); + useEffect(() => { + (async () => { + setIsLoading(true); + dispatch(setLogsPage(TABLE_FIRST_PAGE)); + dispatch(getFilteringStatus()); + dispatch(getClients()); + try { + await Promise.all([ + getLogs(...INITIAL_REQUEST_DATA), + dispatch(getLogsConfig()), + dispatch(getDnsConfig()), + ]); + } catch (err) { + console.error(err); + } finally { + setIsLoading(false); + } + })(); + }, []); + + const refreshLogs = async () => { + setIsLoading(true); + await Promise.all([ + dispatch(setLogsPage(TABLE_FIRST_PAGE)), + getLogs(...INITIAL_REQUEST_DATA), + ]); + dispatch(addSuccessToast('query_log_updated')); + setIsLoading(false); }; - renderTooltip = (isFiltered, rule, filter, service) => isFiltered - && ; - - renderResponseList = (response, status) => { - if (response.length > 0) { - const listItems = response.map((response, index) => ( -
  • - {response} -
  • - )); - - return
      {listItems}
    ; - } - - return ( -
    - query_log_response_status -
    - ); - }; - - toggleBlocking = (type, domain) => { - const { userRules } = this.props.filtering; - const { t } = this.props; - const lineEnding = !endsWith(userRules, '\n') ? '\n' : ''; - const baseRule = `||${domain}^$important`; - const baseUnblocking = `@@${baseRule}`; - const blockingRule = type === 'block' ? baseUnblocking : baseRule; - const unblockingRule = type === 'block' ? baseRule : baseUnblocking; - const preparedBlockingRule = new RegExp(`(^|\n)${escapeRegExp(blockingRule)}($|\n)`); - const preparedUnblockingRule = new RegExp(`(^|\n)${escapeRegExp(unblockingRule)}($|\n)`); - - if (userRules.match(preparedBlockingRule)) { - this.props.setRules(userRules.replace(`${blockingRule}`, '')); - this.props.addSuccessToast(`${t('rule_removed_from_custom_filtering_toast')}: ${blockingRule}`); - } else if (!userRules.match(preparedUnblockingRule)) { - this.props.setRules(`${userRules}${lineEnding}${unblockingRule}\n`); - this.props.addSuccessToast(`${t('rule_added_to_custom_filtering_toast')}: ${unblockingRule}`); - } - - this.props.getFilteringStatus(); - }; - - renderBlockingButton(isFiltered, domain) { - const buttonClass = isFiltered ? 'btn-outline-secondary' : 'btn-outline-danger'; - const buttonText = isFiltered ? 'unblock_btn' : 'block_btn'; - const buttonType = isFiltered ? 'unblock' : 'block'; - - return ( -
    - -
    - ); - } - - getDateCell = (row) => CellWrap( - row, - (isToday(row.value) ? formatTime : formatDateTime), - formatDateTime, + return ( + <> + {enabled && processingGetConfig && } + {enabled && !processingGetConfig && ( + + + + + + + + {processContent(detailedDataCurrent, buttonType)} + + + )} + {!enabled && !processingGetConfig && ( + + )} + ); - - getDomainCell = (row) => { - const response = row.value; - const trackerData = getTrackerData(response); - - return ( -
    -
    {response}
    - {trackerData && } -
    - ); - }; - - normalizeResponse = (response) => ( - response.map((response) => { - const { value, type, ttl } = response; - return `${type}: ${value} (ttl=${ttl})`; - }) - ); - - getFilterName = (filters, whitelistFilters, filterId, t) => { - if (filterId === CUSTOM_FILTERING_RULES_ID) { - return t('custom_filter_rules'); - } - - const filter = filters.find((filter) => filter.id === filterId) - || whitelistFilters.find((filter) => filter.id === filterId); - let filterName = ''; - - if (filter) { - filterName = filter.name; - } - - if (!filterName) { - filterName = t('unknown_filter', { filterId }); - } - - return filterName; - } - - getResponseCell = ({ value: responses, original }) => { - const { - reason, filterId, rule, status, originalAnswer, - } = original; - const { t, filtering } = this.props; - const { filters, whitelistFilters } = filtering; - - const isFiltered = checkFiltered(reason); - const isBlackList = checkBlackList(reason); - const isRewrite = checkRewrite(reason); - const isRewriteAuto = checkRewriteHosts(reason); - const isWhiteList = checkWhiteList(reason); - const isBlockedService = checkBlockedService(reason); - const isBlockedCnameIp = originalAnswer; - - const filterKey = reason.replace(FILTERED, ''); - const parsedFilteredReason = t('query_log_filtered', { filter: filterKey }); - const currentService = SERVICES.find((service) => service.id === original.serviceName); - const serviceName = currentService && currentService.name; - const filterName = this.getFilterName(filters, whitelistFilters, filterId, t); - - if (isBlockedCnameIp) { - const normalizedAnswer = this.normalizeResponse(originalAnswer); - - return ( -
    -
    - - blocked_by_response - - {this.renderTooltip(isFiltered, rule, filterName)} -
    -
    - {this.renderResponseList(normalizedAnswer, status)} -
    -
    - ); - } - - return ( -
    -
    - {(isFiltered || isBlockedService) && !isBlackList && ( - - {parsedFilteredReason} - - )} - {isBlackList && ( - - - query_log_filtered - - - )} - {isBlockedService - ? this.renderTooltip(isFiltered, '', '', serviceName) - : this.renderTooltip(isFiltered, rule, filterName)} - {isRewrite && ( - - rewrite_applied - - )} - {isRewriteAuto && ( - - - rewrite_hosts_applied - - - )} -
    -
    - {this.renderResponseList(responses, status)} - {isWhiteList && this.renderTooltip(isWhiteList, rule, filterName)} -
    -
    - ); - }; - - getClientCell = (row) => { - const { original } = row; - const { t } = this.props; - const { reason, domain } = original; - const isFiltered = checkFiltered(reason); - const isRewrite = checkRewrite(reason); - const isAutoRewrite = checkRewriteHosts(reason); - - if (isAutoRewrite) { - return ( -
    - {formatClientCell(row, t)} -
    - ); - } - - return ( - -
    - {formatClientCell(row, t)} -
    - {isRewrite ? ( -
    - - configure - -
    - ) : ( - this.renderBlockingButton(isFiltered, domain) - )} -
    - ); - }; - - fetchData = (state) => { - const { pages } = state; - const { oldest, page } = this.props.queryLogs; - const isLastPage = pages && (page + 1 === pages); - - if (isLastPage) { - this.getLogs(oldest, page); - } - }; - - changePage = (page) => { - this.props.setLogsPage(page); - this.props.setLogsPagination({ page, pageSize: TABLE_DEFAULT_PAGE_SIZE }); - }; - - renderLogs() { - const { queryLogs, t } = this.props; - const { - processingGetLogs, processingGetConfig, logs, pages, page, - } = queryLogs; - const isLoading = processingGetLogs || processingGetConfig; - - const columns = [ - { - Header: t('time_table_header'), - accessor: 'time', - minWidth: 105, - Cell: this.getDateCell, - }, - { - Header: t('domain_name_table_header'), - accessor: 'domain', - minWidth: 180, - Cell: this.getDomainCell, - }, - { - Header: t('type_table_header'), - accessor: 'type', - maxWidth: 60, - }, - { - Header: t('response_table_header'), - accessor: 'response', - minWidth: 250, - Cell: this.getResponseCell, - }, - { - Header: t('client_table_header'), - accessor: 'client', - maxWidth: 240, - minWidth: 240, - Cell: this.getClientCell, - }, - ]; - - return ( - false} - defaultFilterMethod={(filter, row) => { - const id = filter.pivotId || filter.id; - return row[id] !== undefined - ? String(row[id]).indexOf(filter.value) !== -1 - : true; - }} - defaultSorted={[ - { - id: 'time', - desc: true, - }, - ]} - getTrProps={(_state, rowInfo) => { - if (!rowInfo) { - return {}; - } - - const { reason } = rowInfo.original; - - if (checkFiltered(reason)) { - return { - className: 'red', - }; - } if (checkWhiteList(reason)) { - return { - className: 'green', - }; - } if (checkRewrite(reason) || checkRewriteHosts(reason)) { - return { - className: 'blue', - }; - } - - return { - className: '', - }; - }} - /> - ); - } - - render() { - const { queryLogs, t } = this.props; - const { - enabled, processingGetConfig, processingAdditionalLogs, processingGetLogs, - } = queryLogs; - - const refreshButton = enabled ? ( - - ) : ( - '' - ); - - return ( - - {refreshButton} - {enabled && processingGetConfig && } - {enabled && !processingGetConfig && ( - - - {this.renderLogs()} - - )} - {!enabled && !processingGetConfig && ( - -
    - - link - , - ]} - > - query_log_disabled - -
    -
    - )} -
    - ); - } -} +}; Logs.propTypes = { getLogs: PropTypes.func.isRequired, @@ -461,12 +214,11 @@ Logs.propTypes = { filtering: PropTypes.object.isRequired, setRules: PropTypes.func.isRequired, addSuccessToast: PropTypes.func.isRequired, - getClients: PropTypes.func.isRequired, - getLogsConfig: PropTypes.func.isRequired, setLogsPagination: PropTypes.func.isRequired, setLogsFilter: PropTypes.func.isRequired, setLogsPage: PropTypes.func.isRequired, - t: PropTypes.func.isRequired, + toggleDetailedLogs: PropTypes.func.isRequired, + dnsConfig: PropTypes.object.isRequired, }; -export default withTranslation()(Logs); +export default Logs; diff --git a/client/src/components/Settings/Clients/AutoClients.js b/client/src/components/Settings/Clients/AutoClients.js index 38d6ea3b..90995f31 100644 --- a/client/src/components/Settings/Clients/AutoClients.js +++ b/client/src/components/Settings/Clients/AutoClients.js @@ -79,16 +79,26 @@ class AutoClients extends Component { }, ]} className="-striped -highlight card-table-overflow" - showPagination={true} + showPagination defaultPageSize={10} minRows={5} - previousText={t('previous_btn')} - nextText={t('next_btn')} + showPageSizeOptions={false} + showPageJump={false} + renderTotalPagesCount={() => false} + previousText={ + + + } + nextText={ + + + } loadingText={t('loading_table_status')} - pageText={t('page_table_footer_text')} - ofText="/" + pageText='' + ofText='' rowsText={t('rows_table_footer_text')} noDataText={t('clients_not_found')} + getPaginationProps={() => ({ className: 'custom-pagination' })} /> ); diff --git a/client/src/components/Settings/Clients/ClientsTable.js b/client/src/components/Settings/Clients/ClientsTable.js index 5ca75fa1..6d3fc01a 100644 --- a/client/src/components/Settings/Clients/ClientsTable.js +++ b/client/src/components/Settings/Clients/ClientsTable.js @@ -91,7 +91,7 @@ class ClientsTable extends Component { const { value } = row; return ( -
    +
    {value.map((address) => (
    @@ -121,7 +121,7 @@ class ClientsTable extends Component { ); return ( -
    +
    {title}
    ); @@ -167,7 +167,7 @@ class ClientsTable extends Component { ); return ( -
    +
    {title}
    ); @@ -185,7 +185,7 @@ class ClientsTable extends Component { } return ( -
    +
    {value.map((tag) => (
    @@ -282,16 +282,26 @@ class ClientsTable extends Component { }, ]} className="-striped -highlight card-table-overflow" - showPagination={true} + showPagination defaultPageSize={10} minRows={5} - previousText={t('previous_btn')} - nextText={t('next_btn')} + showPageSizeOptions={false} + showPageJump={false} + renderTotalPagesCount={() => false} + previousText={ + + + } + nextText={ + + + } loadingText={t('loading_table_status')} - pageText={t('page_table_footer_text')} - ofText="/" + pageText='' + ofText='' rowsText={t('rows_table_footer_text')} noDataText={t('clients_not_found')} + getPaginationProps={() => ({ className: 'custom-pagination' })} /> diff --git a/client/src/components/Settings/Clients/whoisCell.js b/client/src/components/Settings/Clients/whoisCell.js index 7766e19d..94afd6cc 100644 --- a/client/src/components/Settings/Clients/whoisCell.js +++ b/client/src/components/Settings/Clients/whoisCell.js @@ -32,11 +32,9 @@ const getFormattedWhois = (value, t) => { const whoisCell = (t) => function cell(row) { const { value } = row; - return ( -
    - {getFormattedWhois(value, t)} -
    - ); + return
    +
    {getFormattedWhois(value, t)}
    +
    ; }; export default whoisCell; diff --git a/client/src/components/Settings/Dhcp/Leases.js b/client/src/components/Settings/Dhcp/Leases.js index 6339d1d6..5ba00819 100644 --- a/client/src/components/Settings/Dhcp/Leases.js +++ b/client/src/components/Settings/Dhcp/Leases.js @@ -2,11 +2,11 @@ import React, { Component } from 'react'; import PropTypes from 'prop-types'; import ReactTable from 'react-table'; import { Trans, withTranslation } from 'react-i18next'; -import { SMALL_TABLE_DEFAULT_PAGE_SIZE } from '../../../helpers/constants'; +import { LEASES_TABLE_DEFAULT_PAGE_SIZE } from '../../../helpers/constants'; class Leases extends Component { cellWrap = ({ value }) => ( -
    +
    {value} @@ -37,9 +37,9 @@ class Leases extends Component { Cell: this.cellWrap, }, ]} - pageSize={SMALL_TABLE_DEFAULT_PAGE_SIZE} + pageSize={LEASES_TABLE_DEFAULT_PAGE_SIZE} showPageSizeOptions={false} - showPagination={leases.length > SMALL_TABLE_DEFAULT_PAGE_SIZE} + showPagination={leases.length > LEASES_TABLE_DEFAULT_PAGE_SIZE} noDataText={t('dhcp_leases_not_found')} minRows={6} className="-striped -highlight card-table-overflow" diff --git a/client/src/components/Settings/Dhcp/StaticLeases/index.js b/client/src/components/Settings/Dhcp/StaticLeases/index.js index dea7c056..7a24a3b0 100644 --- a/client/src/components/Settings/Dhcp/StaticLeases/index.js +++ b/client/src/components/Settings/Dhcp/StaticLeases/index.js @@ -2,13 +2,13 @@ import React, { Component, Fragment } from 'react'; import PropTypes from 'prop-types'; import ReactTable from 'react-table'; import { Trans, withTranslation } from 'react-i18next'; -import { SMALL_TABLE_DEFAULT_PAGE_SIZE } from '../../../../helpers/constants'; +import { LEASES_TABLE_DEFAULT_PAGE_SIZE } from '../../../../helpers/constants'; import Modal from './Modal'; class StaticLeases extends Component { cellWrap = ({ value }) => ( -
    +
    {value} @@ -67,7 +67,7 @@ class StaticLeases extends Component {
    ); diff --git a/client/src/components/ui/CellWrap.js b/client/src/components/ui/CellWrap.js index b23bceff..f97b4d42 100644 --- a/client/src/components/ui/CellWrap.js +++ b/client/src/components/ui/CellWrap.js @@ -9,7 +9,7 @@ const CellWrap = ({ value }, formatValue, formatTitle = formatValue) => { const cellTitle = typeof formatTitle === 'function' ? formatTitle(value) : value; return ( -
    +
    {cellValue} diff --git a/client/src/components/ui/Icons.css b/client/src/components/ui/Icons.css index da2c5f4e..c534d5a4 100644 --- a/client/src/components/ui/Icons.css +++ b/client/src/components/ui/Icons.css @@ -4,7 +4,19 @@ height: 100%; } -.icon--close { - width: 24px; - height: 24px; +.icon--small { + width: 1.5rem; + height: 1.5rem; +} + +.icon--gray { + color: var(--gray-a5); +} + +.icon--disabled { + color: var(--gray-d8); +} + +.icon--active { + color: #66b574; } diff --git a/client/src/components/ui/Icons.js b/client/src/components/ui/Icons.js index 8ef53ff2..bc3eceae 100644 --- a/client/src/components/ui/Icons.js +++ b/client/src/components/ui/Icons.js @@ -3,173 +3,337 @@ import React from 'react'; import './Icons.css'; const Icons = () => ( - + - + - + - + + + + - + - + - - + + + - - + + + + + - - + + + - - + + + - - + + - - + + + + + + - - + + + + - - + + + - - + + + - - + + - - + + - - + + + + + + - - + + + - - + + - - + + + - - + + - - + + - - + + + - - + + + - - + + - - + + + + - - + + - - + + - - + + + - - + + - - + + + + - - + + - - + + - - + + - - + + + - - + + - - + + + + + - - + + - - + + - - + + + - - + + + - - + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + ); diff --git a/client/src/components/ui/Loading.js b/client/src/components/ui/Loading.js index 2c6fe5e8..61834932 100644 --- a/client/src/components/ui/Loading.js +++ b/client/src/components/ui/Loading.js @@ -3,7 +3,7 @@ import React from 'react'; import './Loading.css'; const Loading = () => ( -
    +
    ); export default Loading; diff --git a/client/src/components/ui/PageTitle.css b/client/src/components/ui/PageTitle.css index 7cdd0ca1..c9d1095b 100644 --- a/client/src/components/ui/PageTitle.css +++ b/client/src/components/ui/PageTitle.css @@ -3,13 +3,32 @@ align-items: flex-start; } +.page-header--logs { + flex-direction: row; + align-items: flex-end; + margin: 2rem 0 3rem; +} + +@media (max-width: 991px) { + .page-header--logs { + flex-direction: column; + align-items: center; + margin-bottom: 1.5rem; + } + + .page-header--logs .page-title { + padding-bottom: 2.5rem;; + } +} + .page-subtitle { margin-left: 0; font-size: 0.9rem; } -.page-title { - line-height: 2.2rem; +.page-title--large { + font-size: 36px; + line-height: 46px; } .page-title__actions { diff --git a/client/src/components/ui/PageTitle.js b/client/src/components/ui/PageTitle.js index 90e912f3..c5a2d51a 100644 --- a/client/src/components/ui/PageTitle.js +++ b/client/src/components/ui/PageTitle.js @@ -3,15 +3,15 @@ import PropTypes from 'prop-types'; import './PageTitle.css'; -const PageTitle = (props) => ( +const PageTitle = ({ title, subtitle, children }) => (

    - {props.title} - {props.children} + {title} + {children}

    - {props.subtitle && ( + {subtitle && (
    - {props.subtitle} + {subtitle}
    )}
    diff --git a/client/src/components/ui/ReactTable.css b/client/src/components/ui/ReactTable.css index 48a35dc7..42da9557 100644 --- a/client/src/components/ui/ReactTable.css +++ b/client/src/components/ui/ReactTable.css @@ -1,21 +1,26 @@ .ReactTable .rt-th, .ReactTable .rt-td { padding: 10px 15px; - overflow: visible; + overflow: hidden; + text-overflow: ellipsis; } .ReactTable .rt-tbody { overflow: visible; } -.rt-tr-group .red { - background-color: #fff4f2; +.rt-tr-group.red { + background-color: rgba(223, 56, 18, 0.05); } -.rt-tr-group .green { - background-color: #f1faf3; +.rt-tr-group.green { + background-color: rgba(103, 178, 121, 0.1); } -.rt-tr-group .blue { - background-color: #ecf7ff; +.rt-tr-group.blue { + background-color: #e5effd; +} + +.rt-tr-group.yellow { + background-color: var(--yellow-pale); } diff --git a/client/src/components/ui/Tooltip.css b/client/src/components/ui/Tooltip.css index 9ad8af3b..32903064 100644 --- a/client/src/components/ui/Tooltip.css +++ b/client/src/components/ui/Tooltip.css @@ -6,7 +6,6 @@ width: 18px; height: 18px; flex-shrink: 0; - margin-left: 5px; background-image: url("./svg/help-circle.svg"); background-size: 100%; cursor: pointer; @@ -56,7 +55,6 @@ .tooltip-custom--logs { border-radius: 50%; background-image: url("./svg/help-circle-gray.svg"); - background-color: #fff; } .tooltip-custom--logs:before { diff --git a/client/src/components/ui/Tooltip.js b/client/src/components/ui/Tooltip.js index 206a2c3b..90bd69e1 100644 --- a/client/src/components/ui/Tooltip.js +++ b/client/src/components/ui/Tooltip.js @@ -3,9 +3,8 @@ import PropTypes from 'prop-types'; import './Tooltip.css'; -const Tooltip = (props) => ( -
    -); +const Tooltip = ({ text, type = '' }) =>
    ; Tooltip.propTypes = { text: PropTypes.string.isRequired, diff --git a/client/src/containers/Logs.js b/client/src/containers/Logs.js index ac56f614..f25aab3b 100644 --- a/client/src/containers/Logs.js +++ b/client/src/containers/Logs.js @@ -1,15 +1,22 @@ import { connect } from 'react-redux'; -import { getClients } from '../actions'; import { getFilteringStatus, setRules } from '../actions/filtering'; import { - getLogs, getLogsConfig, setLogsPagination, setLogsFilter, setLogsPage, + getLogs, setLogsPagination, setLogsFilter, setLogsPage, toggleDetailedLogs, } from '../actions/queryLogs'; import Logs from '../components/Logs'; import { addSuccessToast } from '../actions/toasts'; const mapStateToProps = (state) => { - const { queryLogs, dashboard, filtering } = state; - const props = { queryLogs, dashboard, filtering }; + const { + queryLogs, dashboard, filtering, dnsConfig, + } = state; + + const props = { + queryLogs, + dashboard, + filtering, + dnsConfig, + }; return props; }; @@ -18,11 +25,10 @@ const mapDispatchToProps = { getFilteringStatus, setRules, addSuccessToast, - getClients, - getLogsConfig, setLogsPagination, setLogsFilter, setLogsPage, + toggleDetailedLogs, }; export default connect( diff --git a/client/src/helpers/constants.js b/client/src/helpers/constants.js index 60c22264..4778b085 100644 --- a/client/src/helpers/constants.js +++ b/client/src/helpers/constants.js @@ -55,7 +55,8 @@ export const EMPTY_DATE = '0001-01-01T00:00:00Z'; export const DEBOUNCE_TIMEOUT = 300; export const DEBOUNCE_FILTER_TIMEOUT = 500; export const CHECK_TIMEOUT = 1000; -export const STOP_TIMEOUT = 10000; +export const SUCCESS_TOAST_TIMEOUT = 5000; +export const FAILURE_TOAST_TIMEOUT = 30000; export const UNSAFE_PORTS = [ 1, @@ -256,18 +257,6 @@ export const ENCRYPTION_SOURCE = { CONTENT: 'content', }; -export const FILTERED_STATUS = { - FILTERED_BLACK_LIST: 'FilteredBlackList', - NOT_FILTERED_WHITE_LIST: 'NotFilteredWhiteList', - NOT_FILTERED_NOT_FOUND: 'NotFilteredNotFound', - FILTERED_BLOCKED_SERVICE: 'FilteredBlockedService', - REWRITE: 'Rewrite', - REWRITE_HOSTS: 'RewriteEtcHosts', - FILTERED_SAFE_SEARCH: 'FilteredSafeSearch', - FILTERED_SAFE_BROWSING: 'FilteredSafeBrowsing', - FILTERED_PARENTAL: 'FilteredParental', -}; - export const FILTERED = 'Filtered'; export const NOT_FILTERED = 'NotFiltered'; @@ -336,25 +325,124 @@ export const DNS_RECORD_TYPES = [ ]; export const DEFAULT_LOGS_FILTER = { - filter_domain: '', - filter_client: '', - filter_question_type: '', - filter_response_status: '', + search: '', + response_status: '', }; export const DEFAULT_LANGUAGE = 'en'; -export const TABLE_DEFAULT_PAGE_SIZE = 100; +export const TABLE_DEFAULT_PAGE_SIZE = 50; -export const SMALL_TABLE_DEFAULT_PAGE_SIZE = 20; +export const TABLE_FIRST_PAGE = 0; + +export const LEASES_TABLE_DEFAULT_PAGE_SIZE = 20; + +export const FILTERED_STATUS = { + FILTERED_BLACK_LIST: 'FilteredBlackList', + NOT_FILTERED_WHITE_LIST: 'NotFilteredWhiteList', + NOT_FILTERED_NOT_FOUND: 'NotFilteredNotFound', + FILTERED_BLOCKED_SERVICE: 'FilteredBlockedService', + REWRITE: 'Rewrite', + REWRITE_HOSTS: 'RewriteEtcHosts', + FILTERED_SAFE_SEARCH: 'FilteredSafeSearch', + FILTERED_SAFE_BROWSING: 'FilteredSafeBrowsing', + FILTERED_PARENTAL: 'FilteredParental', +}; export const RESPONSE_FILTER = { - ALL: 'all', - FILTERED: 'filtered', + ALL: { + query: 'all', + label: 'show_all_responses', + }, + FILTERED: { + query: 'filtered', + label: 'filtered', + }, + PROCESSED: { + query: 'processed', + label: 'show_processed_responses', + }, + SPACE: { + query: 'all', + label: '', + disabled: true, + }, + BLOCKED: { + query: 'blocked', + label: 'show_blocked_responses', + }, + BLOCKED_THREATS: { + query: 'blocked_safebrowsing', + label: 'blocked_threats', + }, + BLOCKED_ADULT_WEBSITES: { + query: 'blocked_parental', + label: 'blocked_adult_websites', + }, + ALLOWED: { + query: 'whitelisted', + label: 'allowed', + }, + REWRITTEN: { + query: 'rewritten', + label: 'rewritten', + }, + SAFE_SEARCH: { + query: 'safe_search', + label: 'safe_search', + }, +}; + +export const FILTERED_STATUS_TO_META_MAP = { + [FILTERED_STATUS.NOT_FILTERED_WHITE_LIST]: { + label: RESPONSE_FILTER.ALLOWED.label, + color: 'green', + }, + [FILTERED_STATUS.NOT_FILTERED_NOT_FOUND]: { + label: RESPONSE_FILTER.PROCESSED.label, + color: 'white', + }, + [FILTERED_STATUS.FILTERED_BLOCKED_SERVICE]: { + label: RESPONSE_FILTER.BLOCKED.label, + color: 'red', + }, + [FILTERED_STATUS.FILTERED_SAFE_SEARCH]: { + label: RESPONSE_FILTER.SAFE_SEARCH.label, + color: 'yellow', + }, + [FILTERED_STATUS.FILTERED_BLACK_LIST]: { + label: RESPONSE_FILTER.BLOCKED.label, + color: 'red', + }, + [FILTERED_STATUS.REWRITE]: { + label: RESPONSE_FILTER.REWRITTEN.label, + color: 'blue', + }, + [FILTERED_STATUS.REWRITE_HOSTS]: { + label: RESPONSE_FILTER.REWRITTEN.label, + color: 'blue', + }, + [FILTERED_STATUS.FILTERED_SAFE_BROWSING]: { + label: RESPONSE_FILTER.BLOCKED_THREATS.label, + color: 'yellow', + }, + [FILTERED_STATUS.FILTERED_PARENTAL]: { + label: RESPONSE_FILTER.BLOCKED_ADULT_WEBSITES.label, + color: 'yellow', + }, }; export const DEFAULT_TIME_FORMAT = 'HH:mm:ss'; +export const LONG_TIME_FORMAT = 'HH:mm:ss.SSS'; + +export const DEFAULT_SHORT_DATE_FORMAT_OPTIONS = { + year: 'numeric', + month: 'numeric', + day: 'numeric', + hour12: false, +}; + export const DEFAULT_DATE_FORMAT_OPTIONS = { year: 'numeric', month: 'numeric', @@ -371,9 +459,15 @@ export const DETAILED_DATE_FORMAT_OPTIONS = { export const CUSTOM_FILTERING_RULES_ID = 0; -export const ACTION = { - block: 'block', - unblock: 'unblock', +export const BLOCK_ACTIONS = { + BLOCK: 'block', + UNBLOCK: 'unblock', +}; + +export const SCHEME_TO_PROTOCOL_MAP = { + doh: 'dns_over_https', + dot: 'dns_over_tls', + '': 'plain_dns', }; export const DNS_REQUEST_OPTIONS = { @@ -407,3 +501,7 @@ export const FORM_NAME = { INSTALL: 'install', LOGIN: 'login', }; + +export const smallScreenSize = 767; + +export const touchMediaQuery = '(hover: none)'; diff --git a/client/src/helpers/form.js b/client/src/helpers/form.js index bace77b5..b39d7864 100644 --- a/client/src/helpers/form.js +++ b/client/src/helpers/form.js @@ -85,10 +85,10 @@ export const renderGroupField = ({ && diff --git a/client/src/helpers/formatClientCell.js b/client/src/helpers/formatClientCell.js index 0de3af79..2c2d4b5a 100644 --- a/client/src/helpers/formatClientCell.js +++ b/client/src/helpers/formatClientCell.js @@ -5,37 +5,40 @@ import { WHOIS_ICONS } from './constants'; const getFormattedWhois = (whois, t) => { const whoisInfo = normalizeWhois(whois); return ( - Object.keys(whoisInfo).map((key) => { - const icon = WHOIS_ICONS[key]; - return ( - + Object.keys(whoisInfo) + .map((key) => { + const icon = WHOIS_ICONS[key]; + return ( + {icon && ( -   + +   )}{whoisInfo[key]} - ); - }) + ); + }) ); }; -export const formatClientCell = (row, t) => { - const { value, original: { info } } = row; +export const formatClientCell = (row, t, isDetailed = false) => { + const { info, client } = row.original; let whoisContainer = ''; - let nameContainer = value; + let nameContainer = client; if (info) { const { name, whois_info } = info; if (name) { - nameContainer = ( - - {name} ({value}) - - ); + nameContainer = isDetailed ? {client} + :
    + {name} + {`(${client})`} +
    ; } if (whois_info) { @@ -48,11 +51,11 @@ export const formatClientCell = (row, t) => { } return ( - - +
    + <> {nameContainer} {whoisContainer} - - + +
    ); }; diff --git a/client/src/helpers/helpers.js b/client/src/helpers/helpers.js index be8e884e..253a0506 100644 --- a/client/src/helpers/helpers.js +++ b/client/src/helpers/helpers.js @@ -1,4 +1,3 @@ -/* eslint-disable no-bitwise */ import 'url-polyfill'; import dateParse from 'date-fns/parse'; import dateFormat from 'date-fns/format'; @@ -13,29 +12,30 @@ import i18n from 'i18next'; import uniqBy from 'lodash/uniqBy'; import ipaddr from 'ipaddr.js'; import versionCompare from './versionCompare'; +import { getTrackerData } from './trackers/trackers'; import { - STANDARD_DNS_PORT, - STANDARD_WEB_PORT, - STANDARD_HTTPS_PORT, CHECK_TIMEOUT, - DNS_RECORD_TYPES, - DEFAULT_TIME_FORMAT, DEFAULT_DATE_FORMAT_OPTIONS, - DETAILED_DATE_FORMAT_OPTIONS, DEFAULT_LANGUAGE, - FILTERED_STATUS, + DEFAULT_TIME_FORMAT, + DETAILED_DATE_FORMAT_OPTIONS, + DNS_RECORD_TYPES, FILTERED, + FILTERED_STATUS, IP_MATCH_LIST_STATUS, + STANDARD_DNS_PORT, + STANDARD_HTTPS_PORT, + STANDARD_WEB_PORT, } from './constants'; /** * @param time {string} The time to format * @returns {string} Returns the time in the format HH:mm:ss */ -export const formatTime = (time) => { +export const formatTime = (time, options = DEFAULT_TIME_FORMAT) => { const parsedTime = dateParse(time); - return dateFormat(parsedTime, DEFAULT_TIME_FORMAT); + return dateFormat(parsedTime, options); }; /** @@ -68,34 +68,48 @@ export const isToday = (date) => isSameDay(new Date(date), new Date()); export const normalizeLogs = (logs) => logs.map((log) => { const { - time, - question, - answer: response, - reason, + answer, + answer_dnssec, client, + client_proto, + elapsedMs, + question, + reason, + status, + time, filterId, rule, service_name, - status, original_answer, + upstream, } = log; + const { host: domain, type } = question; - const responsesArray = response ? response.map((response) => { + + const response = answer ? answer.map((response) => { const { value, type, ttl } = response; return `${type}: ${value} (ttl=${ttl})`; }) : []; + + const tracker = getTrackerData(domain); + return { time, domain, type, - response: responsesArray, + response, reason, client, + client_proto, filterId, rule, status, serviceName: service_name, originalAnswer: original_answer, + tracker, + answer_dnssec, + elapsedMs, + upstream, }; }); @@ -562,3 +576,15 @@ export const getIpMatchListStatus = (ip, list) => { return IP_MATCH_LIST_STATUS.NOT_FOUND; } }; + + +/** + * @param {string} elapsedMs + * @param {function} t translate + * @returns {string} + */ +export const formatElapsedMs = (elapsedMs, t) => { + const formattedElapsedMs = parseInt(elapsedMs, 10) || parseFloat(elapsedMs) + .toFixed(2); + return `${formattedElapsedMs} ${t('milliseconds_abbreviation')}`; +}; diff --git a/client/src/helpers/trackers/trackers.js b/client/src/helpers/trackers/trackers.js index e51e9b5e..7af6dcb4 100644 --- a/client/src/helpers/trackers/trackers.js +++ b/client/src/helpers/trackers/trackers.js @@ -3,13 +3,13 @@ import adguardDb from './adguard.json'; import { REPOSITORY } from '../constants'; /** - @typedef TrackerData - @type {object} - @property {string} id - tracker ID. - @property {string} name - tracker name. - @property {string} url - tracker website url. - @property {number} category - tracker category. - @property {source} source - tracker data source. + @typedef TrackerData + @type {object} + @property {string} id - tracker ID. + @property {string} name - tracker name. + @property {string} url - tracker website url. + @property {number} category - tracker category. + @property {source} source - tracker data source. */ /** @@ -20,45 +20,6 @@ export const sources = { ADGUARD: 2, }; -/** - * Gets tracker data in the specified database - * - * @param {String} domainName domain name to check - * @param {*} trackersDb trackers database - * @param {number} source source ID - * @returns {TrackerData} tracker data or null if no matching tracker found - */ -const getTrackerDataFromDb = (domainName, trackersDb, source) => { - if (!domainName) { - return null; - } - - const parts = domainName.split(/\./g).reverse(); - let hostToCheck = ''; - - // Check every subdomain - for (let i = 0; i < parts.length; i += 1) { - hostToCheck = parts[i] + (i > 0 ? '.' : '') + hostToCheck; - const trackerId = trackersDb.trackerDomains[hostToCheck]; - - if (trackerId) { - const trackerData = trackersDb.trackers[trackerId]; - const categoryName = trackersDb.categories[trackerData.categoryId]; - - return { - id: trackerId, - name: trackerData.name, - url: trackerData.url, - category: categoryName, - source, - }; - } - } - - // No tracker found for the specified domain - return null; -}; - /** * Gets the source metadata for the specified tracker * @param {TrackerData} trackerData tracker data @@ -74,7 +35,8 @@ export const getSourceData = (trackerData) => { name: 'Whotracks.me', url: `https://whotracks.me/trackers/${trackerData.id}.html`, }; - } if (trackerData.source === sources.ADGUARD) { + } + if (trackerData.source === sources.ADGUARD) { return { name: 'AdGuard', url: REPOSITORY.TRACKERS_DB, @@ -84,6 +46,49 @@ export const getSourceData = (trackerData) => { return null; }; +/** + * Gets tracker data in the specified database + * + * @param {String} domainName domain name to check + * @param {*} trackersDb trackers database + * @param {number} source source ID + * @returns {TrackerData} tracker data or null if no matching tracker found + */ +const getTrackerDataFromDb = (domainName, trackersDb, source) => { + if (!domainName) { + return null; + } + + const parts = domainName.split(/\./g) + .reverse(); + let hostToCheck = ''; + + // Check every subdomain + for (let i = 0; i < parts.length; i += 1) { + hostToCheck = parts[i] + (i > 0 ? '.' : '') + hostToCheck; + const trackerId = trackersDb.trackerDomains[hostToCheck]; + + if (trackerId) { + const trackerData = trackersDb.trackers[trackerId]; + const categoryName = trackersDb.categories[trackerData.categoryId]; + trackerData.source = source; + const sourceData = getSourceData(trackerData); + + return { + id: trackerId, + name: trackerData.name, + url: trackerData.url, + category: categoryName, + source, + sourceData, + }; + } + } + + // No tracker found for the specified domain + return null; +}; + /** * Gets tracker data from the trackers database * diff --git a/client/src/reducers/queryLogs.js b/client/src/reducers/queryLogs.js index 1145bd3f..bff4896d 100644 --- a/client/src/reducers/queryLogs.js +++ b/client/src/reducers/queryLogs.js @@ -1,7 +1,7 @@ import { handleActions } from 'redux-actions'; import * as actions from '../actions/queryLogs'; -import { DEFAULT_LOGS_FILTER } from '../helpers/constants'; +import { DEFAULT_LOGS_FILTER, TABLE_DEFAULT_PAGE_SIZE } from '../helpers/constants'; const queryLogs = handleActions( { @@ -27,15 +27,20 @@ const queryLogs = handleActions( [actions.setLogsFilterRequest]: (state) => ({ ...state, processingGetLogs: true }), [actions.setLogsFilterFailure]: (state) => ({ ...state, processingGetLogs: false }), + [actions.toggleDetailedLogs]: (state, { payload }) => ({ + ...state, + isDetailed: payload, + }), + [actions.setLogsFilterSuccess]: (state, { payload }) => { const { logs, oldest, filter } = payload; - const pageSize = 100; + const pageSize = TABLE_DEFAULT_PAGE_SIZE; const page = 0; const pages = Math.ceil(logs.length / pageSize); const total = logs.length; const rowsStart = pageSize * page; - const rowsEnd = (pageSize * page) + pageSize; + const rowsEnd = rowsStart + pageSize; const logsSlice = logs.slice(rowsStart, rowsEnd); const isFiltered = Object.keys(filter).some((key) => filter[key]); @@ -135,6 +140,7 @@ const queryLogs = handleActions( filter: DEFAULT_LOGS_FILTER, isFiltered: false, anonymize_client_ip: false, + isDetailed: true, }, ); diff --git a/home/whois_test.go b/home/whois_test.go index da93426f..31e6aba2 100644 --- a/home/whois_test.go +++ b/home/whois_test.go @@ -2,10 +2,8 @@ package home import ( "testing" - "time" "github.com/AdguardTeam/AdGuardHome/dnsforward" - "github.com/AdguardTeam/dnsproxy/proxy" "github.com/stretchr/testify/assert" ) @@ -13,17 +11,12 @@ func prepareTestDNSServer() error { config.DNS.Port = 1234 Context.dnsServer = dnsforward.NewServer(nil, nil, nil) conf := &dnsforward.ServerConfig{} - uc, err := proxy.ParseUpstreamsConfig([]string{"1.1.1.1"}, nil, time.Second*5) - if err != nil { - return err - } - conf.UpstreamConfig = &uc + conf.UpstreamDNS = []string{"8.8.8.8"} return Context.dnsServer.Prepare(conf) } func TestWhois(t *testing.T) { - err := prepareTestDNSServer() - assert.Nil(t, err) + assert.Nil(t, prepareTestDNSServer()) w := Whois{timeoutMsec: 5000} resp, err := w.queryAll("8.8.8.8") From 523aeb5c9800f887e7f94cd468d4e1ed942de5a8 Mon Sep 17 00:00:00 2001 From: Andrey Meshkov Date: Thu, 18 Jun 2020 00:53:39 +0300 Subject: [PATCH 14/38] fix log table width --- client/src/components/Logs/Logs.css | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/src/components/Logs/Logs.css b/client/src/components/Logs/Logs.css index 5a405918..35bdd0b0 100644 --- a/client/src/components/Logs/Logs.css +++ b/client/src/components/Logs/Logs.css @@ -236,7 +236,7 @@ border: 0; border-radius: 8px; min-height: 42rem; - max-width: 71rem; + max-width: 100%; } .logs__table--detailed { From ec6e0bea07cb387494397a10f8a9e875ea27e102 Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Thu, 18 Jun 2020 13:49:52 +0300 Subject: [PATCH 15/38] * openapi: describe top_* array entries in /stats Squashed commit of the following: commit d0b640cb36985c82f1020de99fba2201a1c54738 Author: Simon Zolin Date: Thu Jun 18 11:53:16 2020 +0300 * openapi: describe top_* array entries in /stats --- openapi/openapi.yaml | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/openapi/openapi.yaml b/openapi/openapi.yaml index b30ccc2e..15e2963b 100644 --- a/openapi/openapi.yaml +++ b/openapi/openapi.yaml @@ -1213,15 +1213,15 @@ components: top_queried_domains: type: array items: - type: object + $ref: "#/components/schemas/TopArrayEntry" top_clients: type: array items: - type: object + $ref: "#/components/schemas/TopArrayEntry" top_blocked_domains: type: array items: - type: object + $ref: "#/components/schemas/TopArrayEntry" dns_queries: type: array items: @@ -1238,6 +1238,12 @@ components: type: array items: type: integer + TopArrayEntry: + type: object + description: Represent the number of hits per key (domain or client IP) + properties: + domain_or_ip: + type: integer StatsConfig: type: object description: Statistics configuration From 7e7103dc08cd7e062d6ec6ebd4aaec1ee044f3d2 Mon Sep 17 00:00:00 2001 From: ArtemBaskal Date: Thu, 18 Jun 2020 14:21:54 +0300 Subject: [PATCH 16/38] -client: Fix query log bugs --- client/src/components/Dashboard/Clients.js | 6 ++--- .../components/Logs/Cells/getHintElement.js | 15 +++++++----- .../components/Logs/Cells/getResponseCell.js | 7 ++++++ client/src/components/Logs/Logs.css | 24 +++---------------- .../components/Logs/Tooltip/ReactTooltip.css | 11 +++------ client/src/components/Logs/Tooltip/index.js | 8 +++---- client/src/helpers/constants.js | 2 -- client/src/helpers/formatClientCell.js | 15 ++++++------ 8 files changed, 35 insertions(+), 53 deletions(-) diff --git a/client/src/components/Dashboard/Clients.js b/client/src/components/Dashboard/Clients.js index acb46a57..8cd30234 100644 --- a/client/src/components/Dashboard/Clients.js +++ b/client/src/components/Dashboard/Clients.js @@ -1,4 +1,4 @@ -import React, { Fragment } from 'react'; +import React from 'react'; import ReactTable from 'react-table'; import PropTypes from 'prop-types'; import { Trans, withTranslation } from 'react-i18next'; @@ -60,13 +60,13 @@ const clientCell = (t, toggleClientStatus, processing, disallowedClients) => fun const ipMatchListStatus = getIpMatchListStatus(value, disallowedClients); return ( - + <>
    {formatClientCell(row, t)}
    {ipMatchListStatus !== IP_MATCH_LIST_STATUS.CIDR && renderBlockingButton(ipMatchListStatus, value, toggleClientStatus, processing)} -
    + ); }; diff --git a/client/src/components/Logs/Cells/getHintElement.js b/client/src/components/Logs/Cells/getHintElement.js index ad38fe2d..f1a2e151 100644 --- a/client/src/components/Logs/Cells/getHintElement.js +++ b/client/src/components/Logs/Cells/getHintElement.js @@ -19,13 +19,16 @@ const getHintElement = ({ }) => { const id = 'id'; - const [isHovered, hover] = useState(false); + const [isTooltipOpen, setTooltipOpen] = useState(false); - const openTooltip = () => hover(true); - const closeTooltip = () => hover(false); + const closeTooltip = () => setTooltipOpen(false); - return
    + const openTooltip = () => { + window.document.addEventListener('click', closeTooltip); + setTooltipOpen(true); + }; + // TODO: close previous tooltip on new tooltip open + return
    }
    - {isHovered && dataTip + {isTooltipOpen && dataTip && { rule_label: rule, response_code: status, }, + [FILTERED_STATUS.NOT_FILTERED_WHITE_LIST]: { + domain, + encryption_status: boldStatusLabel, + filter, + rule_label: rule, + response_code: status, + }, [FILTERED_STATUS.FILTERED_SAFE_SEARCH]: { domain, encryption_status: boldStatusLabel, diff --git a/client/src/components/Logs/Logs.css b/client/src/components/Logs/Logs.css index 35bdd0b0..a8c17940 100644 --- a/client/src/components/Logs/Logs.css +++ b/client/src/components/Logs/Logs.css @@ -5,7 +5,6 @@ } .logs__row { - position: relative; display: flex; min-height: 26px; overflow: hidden; @@ -105,7 +104,7 @@ .logs__action { position: absolute; - top: 0; + top: 1rem !important; right: 1rem; } @@ -113,10 +112,10 @@ top: 5px; } -.logs__table .rt-td, +/*.logs__table .rt-td, .clients__table .rt-td { position: relative; -} +}*/ .logs__table .rt-thead, .logs__table .rt-tbody { min-width: 100% !important; @@ -557,20 +556,3 @@ .loading__text { transform: translateY(3rem); } - -/*reset position to make absolute position of tooltip on tablets, may cause problems https://github.com/wwayne/react-tooltip/issues/204*/ -@media (hover: none) { - .logs__action { - top: 1rem !important; - right: 1rem; - } - - .logs__table .rt-td, - .clients__table .rt-td { - position: initial; - } - - .logs__row { - position: initial; - } -} diff --git a/client/src/components/Logs/Tooltip/ReactTooltip.css b/client/src/components/Logs/Tooltip/ReactTooltip.css index bc8de6c5..38084d31 100644 --- a/client/src/components/Logs/Tooltip/ReactTooltip.css +++ b/client/src/components/Logs/Tooltip/ReactTooltip.css @@ -4,14 +4,9 @@ box-shadow: 2px 4px 8px rgba(0, 0, 0, 0.2); border-radius: 4px !important; pointer-events: auto !important; -} - -/*crutch, may cause problems https://github.com/wwayne/react-tooltip/issues/204*/ -@media (hover: none) { - .custom-tooltip { - position: absolute !important; - top: 4rem !important; - } + /*may cause problems https://github.com/wwayne/react-tooltip/issues/204*/ + position: absolute !important; + top: 4rem !important; } .white-space--nowrap { diff --git a/client/src/components/Logs/Tooltip/index.js b/client/src/components/Logs/Tooltip/index.js index 6844249a..6d967838 100644 --- a/client/src/components/Logs/Tooltip/index.js +++ b/client/src/components/Logs/Tooltip/index.js @@ -3,10 +3,9 @@ import PropTypes from 'prop-types'; import ReactTooltip from 'react-tooltip'; import classNames from 'classnames'; import './ReactTooltip.css'; -import { touchMediaQuery } from '../../../helpers/constants'; const Tooltip = ({ - id, children, className = '', place = 'right', trigger = 'hover', overridePosition, scrollHide = true, + id, children, className = '', place = 'right', overridePosition, scrollHide = false, }) => { const tooltipClassName = classNames('custom-tooltip', className); @@ -20,9 +19,8 @@ const Tooltip = ({ backgroundColor="#fff" arrowColor="transparent" textColor="#4d4d4d" - delayHide={300} - scrollHide={window.matchMedia(touchMediaQuery).matches ? false : scrollHide} - trigger={trigger} + delayHide={30000} + scrollHide={scrollHide} overridePosition={overridePosition} globalEventOff="click touchend" clickable diff --git a/client/src/helpers/constants.js b/client/src/helpers/constants.js index 4778b085..9f2fad40 100644 --- a/client/src/helpers/constants.js +++ b/client/src/helpers/constants.js @@ -503,5 +503,3 @@ export const FORM_NAME = { }; export const smallScreenSize = 767; - -export const touchMediaQuery = '(hover: none)'; diff --git a/client/src/helpers/formatClientCell.js b/client/src/helpers/formatClientCell.js index 2c2d4b5a..22dbd26d 100644 --- a/client/src/helpers/formatClientCell.js +++ b/client/src/helpers/formatClientCell.js @@ -25,19 +25,18 @@ const getFormattedWhois = (whois, t) => { }; export const formatClientCell = (row, t, isDetailed = false) => { - const { info, client } = row.original; + const { value, original: { info } } = row; let whoisContainer = ''; - let nameContainer = client; + let nameContainer = value; if (info) { const { name, whois_info } = info; if (name) { - nameContainer = isDetailed ? {client} - :
    - {name} - {`(${client})`} + nameContainer = isDetailed + ? {value} + :
    + {name}{`(${value})`}
    ; } @@ -51,7 +50,7 @@ export const formatClientCell = (row, t, isDetailed = false) => { } return ( -
    +
    <> {nameContainer} {whoisContainer} From 19c013378ddac69126475147ca4f0dc9f9ba0428 Mon Sep 17 00:00:00 2001 From: ArtemBaskal Date: Thu, 18 Jun 2020 17:17:46 +0300 Subject: [PATCH 17/38] Replace tooltip component --- client/package-lock.json | 98 ++++++++++--------- client/package.json | 2 +- .../ReactTooltip.css => Cells/Tooltip.css} | 24 ++--- .../components/Logs/Cells/getClientCell.js | 3 +- .../components/Logs/Cells/getDomainCell.js | 7 +- .../components/Logs/Cells/getHintElement.js | 84 +++++++--------- .../components/Logs/Cells/getResponseCell.js | 5 +- client/src/components/Logs/Logs.css | 7 +- .../components/Logs/Tooltip/CustomTooltip.js | 44 --------- client/src/components/Logs/Tooltip/index.js | 46 --------- 10 files changed, 106 insertions(+), 214 deletions(-) rename client/src/components/Logs/{Tooltip/ReactTooltip.css => Cells/Tooltip.css} (84%) delete mode 100644 client/src/components/Logs/Tooltip/CustomTooltip.js delete mode 100644 client/src/components/Logs/Tooltip/index.js diff --git a/client/package-lock.json b/client/package-lock.json index a7055f32..91b1f414 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -4498,6 +4498,15 @@ "sha.js": "^2.4.8" } }, + "create-react-context": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/create-react-context/-/create-react-context-0.3.0.tgz", + "integrity": "sha512-dNldIoSuNSvlTJ7slIKC/ZFGKexBMBrrcc+TTe1NdmROnaASuLPvqpwj9v4XS4uXZ8+YPu0sNmShX2rXI5LNsw==", + "requires": { + "gud": "^1.0.0", + "warning": "^4.0.3" + } + }, "cross-env": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.2.tgz", @@ -4800,7 +4809,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", - "dev": true, "requires": { "is-arguments": "^1.0.4", "is-date-object": "^1.0.1", @@ -4836,7 +4844,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, "requires": { "object-keys": "^1.0.12" } @@ -5264,7 +5271,6 @@ "version": "1.17.5", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", - "dev": true, "requires": { "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", @@ -5283,7 +5289,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, "requires": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -6706,8 +6711,7 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "functional-red-black-tree": { "version": "1.0.1", @@ -6989,6 +6993,11 @@ "dev": true, "optional": true }, + "gud": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz", + "integrity": "sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw==" + }, "handle-thing": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", @@ -7021,7 +7030,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -7034,8 +7042,7 @@ "has-symbols": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" }, "has-value": { "version": "1.0.0", @@ -7759,8 +7766,7 @@ "is-arguments": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", - "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", - "dev": true + "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==" }, "is-arrayish": { "version": "0.2.1", @@ -7785,8 +7791,7 @@ "is-callable": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", - "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", - "dev": true + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==" }, "is-ci": { "version": "2.0.0", @@ -7820,8 +7825,7 @@ "is-date-object": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==" }, "is-decimal": { "version": "1.0.4", @@ -7974,7 +7978,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", - "dev": true, "requires": { "has": "^1.0.3" } @@ -8000,7 +8003,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, "requires": { "has-symbols": "^1.0.1" } @@ -11117,14 +11119,12 @@ "object-inspect": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", - "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", - "dev": true + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==" }, "object-is": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.2.tgz", "integrity": "sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ==", - "dev": true, "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" @@ -11133,8 +11133,7 @@ "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" }, "object-visit": { "version": "1.0.1", @@ -11149,7 +11148,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, "requires": { "define-properties": "^1.1.2", "function-bind": "^1.1.1", @@ -11630,6 +11628,11 @@ "find-up": "^2.1.0" } }, + "popper.js": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", + "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==" + }, "portfinder": { "version": "1.0.26", "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.26.tgz", @@ -12300,6 +12303,29 @@ "raf": "^3.1.0" } }, + "react-popper": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-1.3.7.tgz", + "integrity": "sha512-nmqYTx7QVjCm3WUZLeuOomna138R1luC4EqkW3hxJUrAe+3eNz3oFCLYdnPwILfn0mX1Ew2c3wctrjlUMYYUww==", + "requires": { + "@babel/runtime": "^7.1.2", + "create-react-context": "^0.3.0", + "deep-equal": "^1.1.1", + "popper.js": "^1.14.4", + "prop-types": "^15.6.1", + "typed-styles": "^0.0.7", + "warning": "^4.0.2" + } + }, + "react-popper-tooltip": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/react-popper-tooltip/-/react-popper-tooltip-2.11.1.tgz", + "integrity": "sha512-04A2f24GhyyMicKvg/koIOQ5BzlrRbKiAgP6L+Pdj1MVX3yJ1NeZ8+EidndQsbejFT55oW1b++wg2Z8KlAyhfQ==", + "requires": { + "@babel/runtime": "^7.9.2", + "react-popper": "^1.3.7" + } + }, "react-redux": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.0.tgz", @@ -12427,22 +12453,6 @@ "react-is": "^16.8.1" } }, - "react-tooltip": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-4.2.6.tgz", - "integrity": "sha512-KX/zCsPFCI8RuulzBX86U+Ur7FvgGNRBdb7dUu0ndo8Urinn48nANq9wfq4ABlehweQjPzLl7XdNAtLKza+I3w==", - "requires": { - "prop-types": "^15.7.2", - "uuid": "^7.0.3" - }, - "dependencies": { - "uuid": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", - "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==" - } - } - }, "react-transition-group": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.1.tgz", @@ -12632,7 +12642,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", - "dev": true, "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.17.0-next.1" @@ -13892,7 +13901,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", - "dev": true, "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" @@ -13902,7 +13910,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz", "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==", - "dev": true, "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5", @@ -13913,7 +13920,6 @@ "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==", - "dev": true, "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5", @@ -13924,7 +13930,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", - "dev": true, "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" @@ -14924,6 +14929,11 @@ "mime-types": "~2.1.24" } }, + "typed-styles": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/typed-styles/-/typed-styles-0.0.7.tgz", + "integrity": "sha512-pzP0PWoZUhsECYjABgCGQlRGL1n7tOHsgwYv3oIiEpJwGhFTuty/YNeduxQYzXXa3Ge5BdT6sHYIQYpl4uJ+5Q==" + }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", diff --git a/client/package.json b/client/package.json index 9ff53f0f..7f154d4d 100644 --- a/client/package.json +++ b/client/package.json @@ -27,13 +27,13 @@ "react-dom": "^16.13.1", "react-i18next": "^11.4.0", "react-modal": "^3.11.2", + "react-popper-tooltip": "^2.11.1", "react-redux": "^7.2.0", "react-redux-loading-bar": "^4.6.0", "react-router-dom": "^5.2.0", "react-router-hash-link": "^1.2.2", "react-select": "^3.1.0", "react-table": "^6.11.4", - "react-tooltip": "^4.2.6", "react-transition-group": "^4.4.1", "redux": "^4.0.5", "redux-actions": "^2.6.5", diff --git a/client/src/components/Logs/Tooltip/ReactTooltip.css b/client/src/components/Logs/Cells/Tooltip.css similarity index 84% rename from client/src/components/Logs/Tooltip/ReactTooltip.css rename to client/src/components/Logs/Cells/Tooltip.css index 38084d31..6f4b11fd 100644 --- a/client/src/components/Logs/Tooltip/ReactTooltip.css +++ b/client/src/components/Logs/Cells/Tooltip.css @@ -1,24 +1,20 @@ -.custom-tooltip { +.tooltip__container { padding: 1rem 1.5rem 1.25rem 1.5rem; font-size: 16px !important; box-shadow: 2px 4px 8px rgba(0, 0, 0, 0.2); border-radius: 4px !important; pointer-events: auto !important; - /*may cause problems https://github.com/wwayne/react-tooltip/issues/204*/ - position: absolute !important; - top: 4rem !important; + background-color: var(--white); + z-index: 102; } .white-space--nowrap { white-space: nowrap !important; } -.white-space--normal { +.overflow-break { white-space: normal !important; -} - -.word-break--break-all { - word-break: break-all !important; + overflow-wrap: break-word; } .grid { @@ -70,7 +66,7 @@ font-weight: bold; } - .custom-tooltip { + .tooltip__container { overflow-y: scroll; } } @@ -87,14 +83,6 @@ grid-auto-flow: column; } -.custom-tooltip.show { - opacity: 1 !important; -} - -.custom-tooltip:hover { - opacity: 1 !important; -} - .grid-content > * { justify-content: space-between !important; width: 100% !important; diff --git a/client/src/components/Logs/Cells/getClientCell.js b/client/src/components/Logs/Cells/getClientCell.js index 188ce94c..b842e0e6 100644 --- a/client/src/components/Logs/Cells/getClientCell.js +++ b/client/src/components/Logs/Cells/getClientCell.js @@ -75,12 +75,11 @@ const getClientCell = ({ className: hintClass, columnClass: 'grid grid--limited', tooltipClass: 'px-5 pb-5 pt-4 mw-75', - dataTip: true, xlinkHref: 'question', contentItemClass: 'text-truncate key-colon', title: 'client_details', content: processedData, - place: 'bottom', + placement: 'bottom', })}
    diff --git a/client/src/components/Logs/Cells/getDomainCell.js b/client/src/components/Logs/Cells/getDomainCell.js index 423211b5..d0a44cff 100644 --- a/client/src/components/Logs/Cells/getDomainCell.js +++ b/client/src/components/Logs/Cells/getDomainCell.js @@ -37,11 +37,11 @@ const getDomainCell = (props) => { const dnssecHint = getHintElement({ className: lockIconClass, tooltipClass: 'py-4 px-5 pb-45', - dataTip: answer_dnssec, + canShowTooltip: answer_dnssec, xlinkHref: 'lock', columnClass: 'w-100', content: 'validated_with_dnssec', - place: 'bottom', + placement: 'bottom', }); const protocol = t(SCHEME_TO_PROTOCOL_MAP[client_proto]) || ''; @@ -64,7 +64,7 @@ const getDomainCell = (props) => { const renderGrid = (content, idx) => { const preparedContent = typeof content === 'string' ? t(content) : content; const className = classNames('text-truncate key-colon o-hidden', { - 'word-break--break-all white-space--normal': preparedContent.length > 100, + 'overflow-break': preparedContent.length > 100, }); return
    {preparedContent}
    ; }; @@ -81,7 +81,6 @@ const getDomainCell = (props) => { const trackerHint = getHintElement({ className: privacyIconClass, tooltipClass: 'pt-4 pb-5 px-5 mw-75', - dataTip: true, xlinkHref: 'privacy', contentItemClass: 'key-colon', renderContent, diff --git a/client/src/components/Logs/Cells/getHintElement.js b/client/src/components/Logs/Cells/getHintElement.js index f1a2e151..30c62daa 100644 --- a/client/src/components/Logs/Cells/getHintElement.js +++ b/client/src/components/Logs/Cells/getHintElement.js @@ -1,58 +1,49 @@ -import React, { useState } from 'react'; +import React from 'react'; import PropTypes from 'prop-types'; -import CustomTooltip from '../Tooltip/CustomTooltip'; +import TooltipTrigger from 'react-popper-tooltip'; +import { Trans } from 'react-i18next'; +import classNames from 'classnames'; +import './Tooltip.css'; +import 'react-popper-tooltip/dist/styles.css'; const getHintElement = ({ className, contentItemClass, columnClass, - dataTip, + canShowTooltip = true, xlinkHref, - content, title, - place, + placement, tooltipClass, - trigger, - overridePosition, - scrollHide, - renderContent, -}) => { - const id = 'id'; - - const [isTooltipOpen, setTooltipOpen] = useState(false); - - const closeTooltip = () => setTooltipOpen(false); - - const openTooltip = () => { - window.document.addEventListener('click', closeTooltip); - setTooltipOpen(true); - }; - // TODO: close previous tooltip on new tooltip open - return
    -
    + {item || '—'} +
    , + ), +}) =>
    + {title &&
    + {title} +
    } +
    {renderContent}
    +
    + }>{({ + getTriggerProps, triggerRef, + }) => {xlinkHref && } -
    - {isTooltipOpen && dataTip - && } -
    ; -}; + } + ; getHintElement.propTypes = { className: PropTypes.string, @@ -60,15 +51,10 @@ getHintElement.propTypes = { columnClass: PropTypes.string, tooltipClass: PropTypes.string, title: PropTypes.string, - place: PropTypes.string, - dataTip: PropTypes.string, + placement: PropTypes.string, + canShowTooltip: PropTypes.string, xlinkHref: PropTypes.string, - overridePosition: PropTypes.func, scrollHide: PropTypes.bool, - trigger: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.arrayOf(PropTypes.string), - ]), content: PropTypes.oneOfType([ PropTypes.string, PropTypes.array, diff --git a/client/src/components/Logs/Cells/getResponseCell.js b/client/src/components/Logs/Cells/getResponseCell.js index 6532c19f..cbfbb639 100644 --- a/client/src/components/Logs/Cells/getResponseCell.js +++ b/client/src/components/Logs/Cells/getResponseCell.js @@ -48,7 +48,7 @@ const getResponseCell = (row, filtering, t, isDetailed) => { return
    {responseArr.map((response) => { const className = classNames('white-space--nowrap', { - 'white-space--normal': response.length > 100, + 'overflow-break': response.length > 100, }); return
    {`${response}\n`}
    ; @@ -109,11 +109,10 @@ const getResponseCell = (row, filtering, t, isDetailed) => { columnClass: 'grid grid--limited', tooltipClass: 'px-5 pb-5 pt-4 mw-75 custom-tooltip__response-details', contentItemClass: 'text-truncate key-colon o-hidden', - dataTip: true, xlinkHref: 'question', title: 'response_details', content: fields, - place: 'bottom', + placement: 'bottom', })}
    {statusLabel}
    diff --git a/client/src/components/Logs/Logs.css b/client/src/components/Logs/Logs.css index a8c17940..abdf9611 100644 --- a/client/src/components/Logs/Logs.css +++ b/client/src/components/Logs/Logs.css @@ -5,6 +5,7 @@ } .logs__row { + position: relative; display: flex; min-height: 26px; overflow: hidden; @@ -104,7 +105,7 @@ .logs__action { position: absolute; - top: 1rem !important; + top: 0; right: 1rem; } @@ -112,10 +113,10 @@ top: 5px; } -/*.logs__table .rt-td, +.logs__table .rt-td, .clients__table .rt-td { position: relative; -}*/ +} .logs__table .rt-thead, .logs__table .rt-tbody { min-width: 100% !important; diff --git a/client/src/components/Logs/Tooltip/CustomTooltip.js b/client/src/components/Logs/Tooltip/CustomTooltip.js deleted file mode 100644 index 1a0cf64f..00000000 --- a/client/src/components/Logs/Tooltip/CustomTooltip.js +++ /dev/null @@ -1,44 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { Trans } from 'react-i18next'; -import classNames from 'classnames'; -import Tooltip from './index'; - -const CustomTooltip = ({ - id, title, className, contentItemClass, place = 'right', columnClass = '', content, trigger, overridePosition, scrollHide, - renderContent = React.Children.map( - content, - (item, idx) =>
    - {item || '—'} -
    , - ), -}) => - {title - &&
    {title}
    } -
    {renderContent}
    -
    ; - -CustomTooltip.propTypes = { - id: PropTypes.string.isRequired, - title: PropTypes.string, - place: PropTypes.string, - className: PropTypes.string, - columnClass: PropTypes.string, - contentItemClass: PropTypes.string, - overridePosition: PropTypes.func, - scrollHide: PropTypes.bool, - content: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.array, - ]), - trigger: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.arrayOf(PropTypes.string), - ]), - renderContent: PropTypes.arrayOf(PropTypes.element), -}; - -export default CustomTooltip; diff --git a/client/src/components/Logs/Tooltip/index.js b/client/src/components/Logs/Tooltip/index.js deleted file mode 100644 index 6d967838..00000000 --- a/client/src/components/Logs/Tooltip/index.js +++ /dev/null @@ -1,46 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import ReactTooltip from 'react-tooltip'; -import classNames from 'classnames'; -import './ReactTooltip.css'; - -const Tooltip = ({ - id, children, className = '', place = 'right', overridePosition, scrollHide = false, -}) => { - const tooltipClassName = classNames('custom-tooltip', className); - - return ( - - {children} - - ); -}; - -Tooltip.propTypes = { - id: PropTypes.string.isRequired, - children: PropTypes.node.isRequired, - className: PropTypes.string, - place: PropTypes.string, - overridePosition: PropTypes.func, - scrollHide: PropTypes.bool, - trigger: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.arrayOf(PropTypes.string), - ]), -}; - -export default Tooltip; From 15db9e9c1daec31d5d6f1d6d77a59bc125fb00d5 Mon Sep 17 00:00:00 2001 From: ArtemBaskal Date: Thu, 18 Jun 2020 19:01:10 +0300 Subject: [PATCH 18/38] Open tooltip on hover, show scroll on overflow y --- client/src/components/Logs/Cells/Tooltip.css | 6 ++---- client/src/components/Logs/Cells/getHintElement.js | 4 ++-- client/src/helpers/constants.js | 1 + 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/client/src/components/Logs/Cells/Tooltip.css b/client/src/components/Logs/Cells/Tooltip.css index 6f4b11fd..30e5cded 100644 --- a/client/src/components/Logs/Cells/Tooltip.css +++ b/client/src/components/Logs/Cells/Tooltip.css @@ -6,6 +6,8 @@ pointer-events: auto !important; background-color: var(--white); z-index: 102; + overflow-y: scroll; + max-height: 100%; } .white-space--nowrap { @@ -65,10 +67,6 @@ .grid .key-colon, .grid .title--border { font-weight: bold; } - - .tooltip__container { - overflow-y: scroll; - } } .grid .key-colon:nth-child(odd)::after { diff --git a/client/src/components/Logs/Cells/getHintElement.js b/client/src/components/Logs/Cells/getHintElement.js index 30c62daa..dcb5fed1 100644 --- a/client/src/components/Logs/Cells/getHintElement.js +++ b/client/src/components/Logs/Cells/getHintElement.js @@ -5,6 +5,7 @@ import { Trans } from 'react-i18next'; import classNames from 'classnames'; import './Tooltip.css'; import 'react-popper-tooltip/dist/styles.css'; +import { HIDE_TOOLTIP_DELAY } from '../../../helpers/constants'; const getHintElement = ({ className, @@ -22,7 +23,7 @@ const getHintElement = ({ {item || '—'}
    , ), -}) => Date: Thu, 18 Jun 2020 22:53:02 +0300 Subject: [PATCH 19/38] Fix #1810 - client: Fix query log bugs Squashed commit of the following: commit 188bbad32a2af8a1867fc3ef91d81cda6aa94853 Merge: 15db9e9c ec6e0bea Author: Andrey Meshkov Date: Thu Jun 18 22:43:11 2020 +0300 Merge branch 'master' into fix/1810 commit 15db9e9c1daec31d5d6f1d6d77a59bc125fb00d5 Author: ArtemBaskal Date: Thu Jun 18 19:01:10 2020 +0300 Open tooltip on hover, show scroll on overflow y commit 19c013378ddac69126475147ca4f0dc9f9ba0428 Author: ArtemBaskal Date: Thu Jun 18 17:17:46 2020 +0300 Replace tooltip component commit 7e7103dc08cd7e062d6ec6ebd4aaec1ee044f3d2 Author: ArtemBaskal Date: Thu Jun 18 14:21:54 2020 +0300 -client: Fix query log bugs --- client/package-lock.json | 98 ++++++++++--------- client/package.json | 2 +- client/src/components/Dashboard/Clients.js | 6 +- .../ReactTooltip.css => Cells/Tooltip.css} | 33 ++----- .../components/Logs/Cells/getClientCell.js | 3 +- .../components/Logs/Cells/getDomainCell.js | 7 +- .../components/Logs/Cells/getHintElement.js | 83 +++++++--------- .../components/Logs/Cells/getResponseCell.js | 12 ++- client/src/components/Logs/Logs.css | 17 ---- .../components/Logs/Tooltip/CustomTooltip.js | 44 --------- client/src/components/Logs/Tooltip/index.js | 48 --------- client/src/helpers/constants.js | 3 +- client/src/helpers/formatClientCell.js | 15 ++- 13 files changed, 122 insertions(+), 249 deletions(-) rename client/src/components/Logs/{Tooltip/ReactTooltip.css => Cells/Tooltip.css} (80%) delete mode 100644 client/src/components/Logs/Tooltip/CustomTooltip.js delete mode 100644 client/src/components/Logs/Tooltip/index.js diff --git a/client/package-lock.json b/client/package-lock.json index a7055f32..91b1f414 100644 --- a/client/package-lock.json +++ b/client/package-lock.json @@ -4498,6 +4498,15 @@ "sha.js": "^2.4.8" } }, + "create-react-context": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/create-react-context/-/create-react-context-0.3.0.tgz", + "integrity": "sha512-dNldIoSuNSvlTJ7slIKC/ZFGKexBMBrrcc+TTe1NdmROnaASuLPvqpwj9v4XS4uXZ8+YPu0sNmShX2rXI5LNsw==", + "requires": { + "gud": "^1.0.0", + "warning": "^4.0.3" + } + }, "cross-env": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.2.tgz", @@ -4800,7 +4809,6 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz", "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==", - "dev": true, "requires": { "is-arguments": "^1.0.4", "is-date-object": "^1.0.1", @@ -4836,7 +4844,6 @@ "version": "1.1.3", "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz", "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==", - "dev": true, "requires": { "object-keys": "^1.0.12" } @@ -5264,7 +5271,6 @@ "version": "1.17.5", "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.17.5.tgz", "integrity": "sha512-BR9auzDbySxOcfog0tLECW8l28eRGpDpU3Dm3Hp4q/N+VtLTmyj4EUN088XZWQDW/hzj6sYRDXeOFsaAODKvpg==", - "dev": true, "requires": { "es-to-primitive": "^1.2.1", "function-bind": "^1.1.1", @@ -5283,7 +5289,6 @@ "version": "1.2.1", "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", - "dev": true, "requires": { "is-callable": "^1.1.4", "is-date-object": "^1.0.1", @@ -6706,8 +6711,7 @@ "function-bind": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.1.tgz", - "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==", - "dev": true + "integrity": "sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A==" }, "functional-red-black-tree": { "version": "1.0.1", @@ -6989,6 +6993,11 @@ "dev": true, "optional": true }, + "gud": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/gud/-/gud-1.0.0.tgz", + "integrity": "sha512-zGEOVKFM5sVPPrYs7J5/hYEw2Pof8KCyOwyhG8sAF26mCAeUFAcYPu1mwB7hhpIP29zOIBaDqwuHdLp0jvZXjw==" + }, "handle-thing": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz", @@ -7021,7 +7030,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz", "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==", - "dev": true, "requires": { "function-bind": "^1.1.1" } @@ -7034,8 +7042,7 @@ "has-symbols": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.1.tgz", - "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==", - "dev": true + "integrity": "sha512-PLcsoqu++dmEIZB+6totNFKq/7Do+Z0u4oT0zKOJNl3lYK6vGwwu2hjHs+68OEZbTjiUE9bgOABXbP/GvrS0Kg==" }, "has-value": { "version": "1.0.0", @@ -7759,8 +7766,7 @@ "is-arguments": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.0.4.tgz", - "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==", - "dev": true + "integrity": "sha512-xPh0Rmt8NE65sNzvyUmWgI1tz3mKq74lGA0mL8LYZcoIzKOzDh6HmrYm3d18k60nHerC8A9Km8kYu87zfSFnLA==" }, "is-arrayish": { "version": "0.2.1", @@ -7785,8 +7791,7 @@ "is-callable": { "version": "1.1.5", "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.1.5.tgz", - "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==", - "dev": true + "integrity": "sha512-ESKv5sMCJB2jnHTWZ3O5itG+O128Hsus4K4Qh1h2/cgn2vbgnLSVqfV46AeJA9D5EeeLa9w81KUXMtn34zhX+Q==" }, "is-ci": { "version": "2.0.0", @@ -7820,8 +7825,7 @@ "is-date-object": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.2.tgz", - "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==", - "dev": true + "integrity": "sha512-USlDT524woQ08aoZFzh3/Z6ch9Y/EWXEHQ/AaRN0SkKq4t2Jw2R2339tSXmwuVoY7LLlBCbOIlx2myP/L5zk0g==" }, "is-decimal": { "version": "1.0.4", @@ -7974,7 +7978,6 @@ "version": "1.0.5", "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.0.5.tgz", "integrity": "sha512-vlKW17SNq44owv5AQR3Cq0bQPEb8+kF3UKZ2fiZNOWtztYE5i0CzCZxFDwO58qAOWtxdBRVO/V5Qin1wjCqFYQ==", - "dev": true, "requires": { "has": "^1.0.3" } @@ -8000,7 +8003,6 @@ "version": "1.0.3", "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.3.tgz", "integrity": "sha512-OwijhaRSgqvhm/0ZdAcXNZt9lYdKFpcRDT5ULUuYXPoT794UNOdU+gpT6Rzo7b4V2HUl/op6GqY894AZwv9faQ==", - "dev": true, "requires": { "has-symbols": "^1.0.1" } @@ -11117,14 +11119,12 @@ "object-inspect": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.7.0.tgz", - "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==", - "dev": true + "integrity": "sha512-a7pEHdh1xKIAgTySUGgLMx/xwDZskN1Ud6egYYN3EdRW4ZMPNEDUTF+hwy2LUC+Bl+SyLXANnwz/jyh/qutKUw==" }, "object-is": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.2.tgz", "integrity": "sha512-5lHCz+0uufF6wZ7CRFWJN3hp8Jqblpgve06U5CMQ3f//6iDjPr2PEo9MWCjEssDsa+UZEL4PkFpr+BMop6aKzQ==", - "dev": true, "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" @@ -11133,8 +11133,7 @@ "object-keys": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", - "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", - "dev": true + "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==" }, "object-visit": { "version": "1.0.1", @@ -11149,7 +11148,6 @@ "version": "4.1.0", "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.0.tgz", "integrity": "sha512-exHJeq6kBKj58mqGyTQ9DFvrZC/eR6OwxzoM9YRoGBqrXYonaFyGiFMuc9VZrXf7DarreEwMpurG3dd+CNyW5w==", - "dev": true, "requires": { "define-properties": "^1.1.2", "function-bind": "^1.1.1", @@ -11630,6 +11628,11 @@ "find-up": "^2.1.0" } }, + "popper.js": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", + "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==" + }, "portfinder": { "version": "1.0.26", "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.26.tgz", @@ -12300,6 +12303,29 @@ "raf": "^3.1.0" } }, + "react-popper": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/react-popper/-/react-popper-1.3.7.tgz", + "integrity": "sha512-nmqYTx7QVjCm3WUZLeuOomna138R1luC4EqkW3hxJUrAe+3eNz3oFCLYdnPwILfn0mX1Ew2c3wctrjlUMYYUww==", + "requires": { + "@babel/runtime": "^7.1.2", + "create-react-context": "^0.3.0", + "deep-equal": "^1.1.1", + "popper.js": "^1.14.4", + "prop-types": "^15.6.1", + "typed-styles": "^0.0.7", + "warning": "^4.0.2" + } + }, + "react-popper-tooltip": { + "version": "2.11.1", + "resolved": "https://registry.npmjs.org/react-popper-tooltip/-/react-popper-tooltip-2.11.1.tgz", + "integrity": "sha512-04A2f24GhyyMicKvg/koIOQ5BzlrRbKiAgP6L+Pdj1MVX3yJ1NeZ8+EidndQsbejFT55oW1b++wg2Z8KlAyhfQ==", + "requires": { + "@babel/runtime": "^7.9.2", + "react-popper": "^1.3.7" + } + }, "react-redux": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-7.2.0.tgz", @@ -12427,22 +12453,6 @@ "react-is": "^16.8.1" } }, - "react-tooltip": { - "version": "4.2.6", - "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-4.2.6.tgz", - "integrity": "sha512-KX/zCsPFCI8RuulzBX86U+Ur7FvgGNRBdb7dUu0ndo8Urinn48nANq9wfq4ABlehweQjPzLl7XdNAtLKza+I3w==", - "requires": { - "prop-types": "^15.7.2", - "uuid": "^7.0.3" - }, - "dependencies": { - "uuid": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-7.0.3.tgz", - "integrity": "sha512-DPSke0pXhTZgoF/d+WSt2QaKMCFSfx7QegxEWT+JOuHF5aWrKEn0G+ztjuJg/gG8/ItK+rbPCD/yNv8yyih6Cg==" - } - } - }, "react-transition-group": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.1.tgz", @@ -12632,7 +12642,6 @@ "version": "1.3.0", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.0.tgz", "integrity": "sha512-2+Q0C5g951OlYlJz6yu5/M33IcsESLlLfsyIaLJaG4FA2r4yP8MvVMJUUP/fVBkSpbbbZlS5gynbEWLipiiXiQ==", - "dev": true, "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.17.0-next.1" @@ -13892,7 +13901,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.1.tgz", "integrity": "sha512-LRPxFUaTtpqYsTeNKaFOw3R4bxIzWOnbQ837QfBylo8jIxtcbK/A/sMV7Q+OAV/vWo+7s25pOE10KYSjaSO06g==", - "dev": true, "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" @@ -13902,7 +13910,6 @@ "version": "2.1.2", "resolved": "https://registry.npmjs.org/string.prototype.trimleft/-/string.prototype.trimleft-2.1.2.tgz", "integrity": "sha512-gCA0tza1JBvqr3bfAIFJGqfdRTyPae82+KTnm3coDXkZN9wnuW3HjGgN386D7hfv5CHQYCI022/rJPVlqXyHSw==", - "dev": true, "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5", @@ -13913,7 +13920,6 @@ "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==", - "dev": true, "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5", @@ -13924,7 +13930,6 @@ "version": "1.0.1", "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.1.tgz", "integrity": "sha512-XxZn+QpvrBI1FOcg6dIpxUPgWCPuNXvMD72aaRaUQv1eD4e/Qy8i/hFTe0BUmD60p/QA6bh1avmuPTfNjqVWRw==", - "dev": true, "requires": { "define-properties": "^1.1.3", "es-abstract": "^1.17.5" @@ -14924,6 +14929,11 @@ "mime-types": "~2.1.24" } }, + "typed-styles": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/typed-styles/-/typed-styles-0.0.7.tgz", + "integrity": "sha512-pzP0PWoZUhsECYjABgCGQlRGL1n7tOHsgwYv3oIiEpJwGhFTuty/YNeduxQYzXXa3Ge5BdT6sHYIQYpl4uJ+5Q==" + }, "typedarray": { "version": "0.0.6", "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz", diff --git a/client/package.json b/client/package.json index 9ff53f0f..7f154d4d 100644 --- a/client/package.json +++ b/client/package.json @@ -27,13 +27,13 @@ "react-dom": "^16.13.1", "react-i18next": "^11.4.0", "react-modal": "^3.11.2", + "react-popper-tooltip": "^2.11.1", "react-redux": "^7.2.0", "react-redux-loading-bar": "^4.6.0", "react-router-dom": "^5.2.0", "react-router-hash-link": "^1.2.2", "react-select": "^3.1.0", "react-table": "^6.11.4", - "react-tooltip": "^4.2.6", "react-transition-group": "^4.4.1", "redux": "^4.0.5", "redux-actions": "^2.6.5", diff --git a/client/src/components/Dashboard/Clients.js b/client/src/components/Dashboard/Clients.js index acb46a57..8cd30234 100644 --- a/client/src/components/Dashboard/Clients.js +++ b/client/src/components/Dashboard/Clients.js @@ -1,4 +1,4 @@ -import React, { Fragment } from 'react'; +import React from 'react'; import ReactTable from 'react-table'; import PropTypes from 'prop-types'; import { Trans, withTranslation } from 'react-i18next'; @@ -60,13 +60,13 @@ const clientCell = (t, toggleClientStatus, processing, disallowedClients) => fun const ipMatchListStatus = getIpMatchListStatus(value, disallowedClients); return ( - + <>
    {formatClientCell(row, t)}
    {ipMatchListStatus !== IP_MATCH_LIST_STATUS.CIDR && renderBlockingButton(ipMatchListStatus, value, toggleClientStatus, processing)} -
    + ); }; diff --git a/client/src/components/Logs/Tooltip/ReactTooltip.css b/client/src/components/Logs/Cells/Tooltip.css similarity index 80% rename from client/src/components/Logs/Tooltip/ReactTooltip.css rename to client/src/components/Logs/Cells/Tooltip.css index bc8de6c5..30e5cded 100644 --- a/client/src/components/Logs/Tooltip/ReactTooltip.css +++ b/client/src/components/Logs/Cells/Tooltip.css @@ -1,29 +1,22 @@ -.custom-tooltip { +.tooltip__container { padding: 1rem 1.5rem 1.25rem 1.5rem; font-size: 16px !important; box-shadow: 2px 4px 8px rgba(0, 0, 0, 0.2); border-radius: 4px !important; pointer-events: auto !important; -} - -/*crutch, may cause problems https://github.com/wwayne/react-tooltip/issues/204*/ -@media (hover: none) { - .custom-tooltip { - position: absolute !important; - top: 4rem !important; - } + background-color: var(--white); + z-index: 102; + overflow-y: scroll; + max-height: 100%; } .white-space--nowrap { white-space: nowrap !important; } -.white-space--normal { +.overflow-break { white-space: normal !important; -} - -.word-break--break-all { - word-break: break-all !important; + overflow-wrap: break-word; } .grid { @@ -74,10 +67,6 @@ .grid .key-colon, .grid .title--border { font-weight: bold; } - - .custom-tooltip { - overflow-y: scroll; - } } .grid .key-colon:nth-child(odd)::after { @@ -92,14 +81,6 @@ grid-auto-flow: column; } -.custom-tooltip.show { - opacity: 1 !important; -} - -.custom-tooltip:hover { - opacity: 1 !important; -} - .grid-content > * { justify-content: space-between !important; width: 100% !important; diff --git a/client/src/components/Logs/Cells/getClientCell.js b/client/src/components/Logs/Cells/getClientCell.js index 188ce94c..b842e0e6 100644 --- a/client/src/components/Logs/Cells/getClientCell.js +++ b/client/src/components/Logs/Cells/getClientCell.js @@ -75,12 +75,11 @@ const getClientCell = ({ className: hintClass, columnClass: 'grid grid--limited', tooltipClass: 'px-5 pb-5 pt-4 mw-75', - dataTip: true, xlinkHref: 'question', contentItemClass: 'text-truncate key-colon', title: 'client_details', content: processedData, - place: 'bottom', + placement: 'bottom', })}
    diff --git a/client/src/components/Logs/Cells/getDomainCell.js b/client/src/components/Logs/Cells/getDomainCell.js index 423211b5..d0a44cff 100644 --- a/client/src/components/Logs/Cells/getDomainCell.js +++ b/client/src/components/Logs/Cells/getDomainCell.js @@ -37,11 +37,11 @@ const getDomainCell = (props) => { const dnssecHint = getHintElement({ className: lockIconClass, tooltipClass: 'py-4 px-5 pb-45', - dataTip: answer_dnssec, + canShowTooltip: answer_dnssec, xlinkHref: 'lock', columnClass: 'w-100', content: 'validated_with_dnssec', - place: 'bottom', + placement: 'bottom', }); const protocol = t(SCHEME_TO_PROTOCOL_MAP[client_proto]) || ''; @@ -64,7 +64,7 @@ const getDomainCell = (props) => { const renderGrid = (content, idx) => { const preparedContent = typeof content === 'string' ? t(content) : content; const className = classNames('text-truncate key-colon o-hidden', { - 'word-break--break-all white-space--normal': preparedContent.length > 100, + 'overflow-break': preparedContent.length > 100, }); return
    {preparedContent}
    ; }; @@ -81,7 +81,6 @@ const getDomainCell = (props) => { const trackerHint = getHintElement({ className: privacyIconClass, tooltipClass: 'pt-4 pb-5 px-5 mw-75', - dataTip: true, xlinkHref: 'privacy', contentItemClass: 'key-colon', renderContent, diff --git a/client/src/components/Logs/Cells/getHintElement.js b/client/src/components/Logs/Cells/getHintElement.js index ad38fe2d..dcb5fed1 100644 --- a/client/src/components/Logs/Cells/getHintElement.js +++ b/client/src/components/Logs/Cells/getHintElement.js @@ -1,55 +1,50 @@ -import React, { useState } from 'react'; +import React from 'react'; import PropTypes from 'prop-types'; -import CustomTooltip from '../Tooltip/CustomTooltip'; +import TooltipTrigger from 'react-popper-tooltip'; +import { Trans } from 'react-i18next'; +import classNames from 'classnames'; +import './Tooltip.css'; +import 'react-popper-tooltip/dist/styles.css'; +import { HIDE_TOOLTIP_DELAY } from '../../../helpers/constants'; const getHintElement = ({ className, contentItemClass, columnClass, - dataTip, + canShowTooltip = true, xlinkHref, - content, title, - place, + placement, tooltipClass, - trigger, - overridePosition, - scrollHide, - renderContent, -}) => { - const id = 'id'; - - const [isHovered, hover] = useState(false); - - const openTooltip = () => hover(true); - const closeTooltip = () => hover(false); - - return
    -
    + {item || '—'} +
    , + ), +}) =>
    + {title &&
    + {title} +
    } +
    {renderContent}
    +
    + }>{({ + getTriggerProps, triggerRef, + }) => {xlinkHref && } -
    - {isHovered && dataTip - && } -
    ; -}; + } + ; getHintElement.propTypes = { className: PropTypes.string, @@ -57,15 +52,9 @@ getHintElement.propTypes = { columnClass: PropTypes.string, tooltipClass: PropTypes.string, title: PropTypes.string, - place: PropTypes.string, - dataTip: PropTypes.string, + placement: PropTypes.string, + canShowTooltip: PropTypes.string, xlinkHref: PropTypes.string, - overridePosition: PropTypes.func, - scrollHide: PropTypes.bool, - trigger: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.arrayOf(PropTypes.string), - ]), content: PropTypes.oneOfType([ PropTypes.string, PropTypes.array, diff --git a/client/src/components/Logs/Cells/getResponseCell.js b/client/src/components/Logs/Cells/getResponseCell.js index f7fec2cf..cbfbb639 100644 --- a/client/src/components/Logs/Cells/getResponseCell.js +++ b/client/src/components/Logs/Cells/getResponseCell.js @@ -48,7 +48,7 @@ const getResponseCell = (row, filtering, t, isDetailed) => { return
    {responseArr.map((response) => { const className = classNames('white-space--nowrap', { - 'white-space--normal': response.length > 100, + 'overflow-break': response.length > 100, }); return
    {`${response}\n`}
    ; @@ -71,6 +71,13 @@ const getResponseCell = (row, filtering, t, isDetailed) => { rule_label: rule, response_code: status, }, + [FILTERED_STATUS.NOT_FILTERED_WHITE_LIST]: { + domain, + encryption_status: boldStatusLabel, + filter, + rule_label: rule, + response_code: status, + }, [FILTERED_STATUS.FILTERED_SAFE_SEARCH]: { domain, encryption_status: boldStatusLabel, @@ -102,11 +109,10 @@ const getResponseCell = (row, filtering, t, isDetailed) => { columnClass: 'grid grid--limited', tooltipClass: 'px-5 pb-5 pt-4 mw-75 custom-tooltip__response-details', contentItemClass: 'text-truncate key-colon o-hidden', - dataTip: true, xlinkHref: 'question', title: 'response_details', content: fields, - place: 'bottom', + placement: 'bottom', })}
    {statusLabel}
    diff --git a/client/src/components/Logs/Logs.css b/client/src/components/Logs/Logs.css index 35bdd0b0..abdf9611 100644 --- a/client/src/components/Logs/Logs.css +++ b/client/src/components/Logs/Logs.css @@ -557,20 +557,3 @@ .loading__text { transform: translateY(3rem); } - -/*reset position to make absolute position of tooltip on tablets, may cause problems https://github.com/wwayne/react-tooltip/issues/204*/ -@media (hover: none) { - .logs__action { - top: 1rem !important; - right: 1rem; - } - - .logs__table .rt-td, - .clients__table .rt-td { - position: initial; - } - - .logs__row { - position: initial; - } -} diff --git a/client/src/components/Logs/Tooltip/CustomTooltip.js b/client/src/components/Logs/Tooltip/CustomTooltip.js deleted file mode 100644 index 1a0cf64f..00000000 --- a/client/src/components/Logs/Tooltip/CustomTooltip.js +++ /dev/null @@ -1,44 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import { Trans } from 'react-i18next'; -import classNames from 'classnames'; -import Tooltip from './index'; - -const CustomTooltip = ({ - id, title, className, contentItemClass, place = 'right', columnClass = '', content, trigger, overridePosition, scrollHide, - renderContent = React.Children.map( - content, - (item, idx) =>
    - {item || '—'} -
    , - ), -}) => - {title - &&
    {title}
    } -
    {renderContent}
    -
    ; - -CustomTooltip.propTypes = { - id: PropTypes.string.isRequired, - title: PropTypes.string, - place: PropTypes.string, - className: PropTypes.string, - columnClass: PropTypes.string, - contentItemClass: PropTypes.string, - overridePosition: PropTypes.func, - scrollHide: PropTypes.bool, - content: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.array, - ]), - trigger: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.arrayOf(PropTypes.string), - ]), - renderContent: PropTypes.arrayOf(PropTypes.element), -}; - -export default CustomTooltip; diff --git a/client/src/components/Logs/Tooltip/index.js b/client/src/components/Logs/Tooltip/index.js deleted file mode 100644 index 6844249a..00000000 --- a/client/src/components/Logs/Tooltip/index.js +++ /dev/null @@ -1,48 +0,0 @@ -import React from 'react'; -import PropTypes from 'prop-types'; -import ReactTooltip from 'react-tooltip'; -import classNames from 'classnames'; -import './ReactTooltip.css'; -import { touchMediaQuery } from '../../../helpers/constants'; - -const Tooltip = ({ - id, children, className = '', place = 'right', trigger = 'hover', overridePosition, scrollHide = true, -}) => { - const tooltipClassName = classNames('custom-tooltip', className); - - return ( - - {children} - - ); -}; - -Tooltip.propTypes = { - id: PropTypes.string.isRequired, - children: PropTypes.node.isRequired, - className: PropTypes.string, - place: PropTypes.string, - overridePosition: PropTypes.func, - scrollHide: PropTypes.bool, - trigger: PropTypes.oneOfType([ - PropTypes.string, - PropTypes.arrayOf(PropTypes.string), - ]), -}; - -export default Tooltip; diff --git a/client/src/helpers/constants.js b/client/src/helpers/constants.js index 4778b085..a58d7529 100644 --- a/client/src/helpers/constants.js +++ b/client/src/helpers/constants.js @@ -57,6 +57,7 @@ export const DEBOUNCE_FILTER_TIMEOUT = 500; export const CHECK_TIMEOUT = 1000; export const SUCCESS_TOAST_TIMEOUT = 5000; export const FAILURE_TOAST_TIMEOUT = 30000; +export const HIDE_TOOLTIP_DELAY = 300; export const UNSAFE_PORTS = [ 1, @@ -503,5 +504,3 @@ export const FORM_NAME = { }; export const smallScreenSize = 767; - -export const touchMediaQuery = '(hover: none)'; diff --git a/client/src/helpers/formatClientCell.js b/client/src/helpers/formatClientCell.js index 2c2d4b5a..22dbd26d 100644 --- a/client/src/helpers/formatClientCell.js +++ b/client/src/helpers/formatClientCell.js @@ -25,19 +25,18 @@ const getFormattedWhois = (whois, t) => { }; export const formatClientCell = (row, t, isDetailed = false) => { - const { info, client } = row.original; + const { value, original: { info } } = row; let whoisContainer = ''; - let nameContainer = client; + let nameContainer = value; if (info) { const { name, whois_info } = info; if (name) { - nameContainer = isDetailed ? {client} - :
    - {name} - {`(${client})`} + nameContainer = isDetailed + ? {value} + :
    + {name}{`(${value})`}
    ; } @@ -51,7 +50,7 @@ export const formatClientCell = (row, t, isDetailed = false) => { } return ( -
    +
    <> {nameContainer} {whoisContainer} From 2c47053cfe127e2a2b98160e1528dfcc0f8db445 Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Fri, 19 Jun 2020 14:27:23 +0300 Subject: [PATCH 20/38] - autohosts: fix crash on startup if filesystem watcher couldn't be initialized Close #1814 Squashed commit of the following: commit ba17a5b3c61a8a5282beb0cca470e2302e83c0d6 Author: Simon Zolin Date: Fri Jun 19 10:08:44 2020 +0300 - autohosts: fix crash on startup if filesystem watcher couldn't be initialized --- util/auto_hosts.go | 24 ++++++++++++++---------- 1 file changed, 14 insertions(+), 10 deletions(-) diff --git a/util/auto_hosts.go b/util/auto_hosts.go index f36ee1e7..34a979da 100644 --- a/util/auto_hosts.go +++ b/util/auto_hosts.go @@ -76,17 +76,19 @@ func (a *AutoHosts) Start() { go a.updateLoop() a.updateChan <- true - go a.watcherLoop() + if a.watcher != nil { + go a.watcherLoop() - err := a.watcher.Add(a.hostsFn) - if err != nil { - log.Error("Error while initializing watcher for a file %s: %s", a.hostsFn, err) - } - - for _, dir := range a.hostsDirs { - err = a.watcher.Add(dir) + err := a.watcher.Add(a.hostsFn) if err != nil { - log.Error("Error while initializing watcher for a directory %s: %s", dir, err) + log.Error("Error while initializing watcher for a file %s: %s", a.hostsFn, err) + } + + for _, dir := range a.hostsDirs { + err = a.watcher.Add(dir) + if err != nil { + log.Error("Error while initializing watcher for a directory %s: %s", dir, err) + } } } } @@ -95,7 +97,9 @@ func (a *AutoHosts) Start() { func (a *AutoHosts) Close() { a.updateChan <- false close(a.updateChan) - _ = a.watcher.Close() + if a.watcher != nil { + _ = a.watcher.Close() + } } // update table From 679b79a89da64c08a1a1a8291c92d2229ac45748 Mon Sep 17 00:00:00 2001 From: ArtemBaskal Date: Fri, 19 Jun 2020 14:44:23 +0300 Subject: [PATCH 21/38] minor --- client/src/components/Logs/Cells/getResponseCell.js | 4 ++++ client/src/helpers/formatClientCell.js | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/client/src/components/Logs/Cells/getResponseCell.js b/client/src/components/Logs/Cells/getResponseCell.js index cbfbb639..c300a00d 100644 --- a/client/src/components/Logs/Cells/getResponseCell.js +++ b/client/src/components/Logs/Cells/getResponseCell.js @@ -67,6 +67,8 @@ const getResponseCell = (row, filtering, t, isDetailed) => { [FILTERED_STATUS.FILTERED_BLOCKED_SERVICE]: { domain, encryption_status: boldStatusLabel, + install_settings_dns: upstream, + elapsed: formattedElapsedMs, filter, rule_label: rule, response_code: status, @@ -74,6 +76,8 @@ const getResponseCell = (row, filtering, t, isDetailed) => { [FILTERED_STATUS.NOT_FILTERED_WHITE_LIST]: { domain, encryption_status: boldStatusLabel, + install_settings_dns: upstream, + elapsed: formattedElapsedMs, filter, rule_label: rule, response_code: status, diff --git a/client/src/helpers/formatClientCell.js b/client/src/helpers/formatClientCell.js index 22dbd26d..37776af1 100644 --- a/client/src/helpers/formatClientCell.js +++ b/client/src/helpers/formatClientCell.js @@ -36,7 +36,9 @@ export const formatClientCell = (row, t, isDetailed = false) => { nameContainer = isDetailed ? {value} :
    - {name}{`(${value})`} + {name} + {' '} + {`(${value})`}
    ; } From 49a92605b8894ac66d0c290106ee63114ef4047a Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Tue, 23 Jun 2020 12:13:13 +0300 Subject: [PATCH 22/38] + dns: respond to PTR requests for internal IP addresses from DHCP Close #1682 Squashed commit of the following: commit 2fad3544bf8853b1f8f19ad8b7bc8a490c96e533 Author: Simon Zolin Date: Mon Jun 22 17:32:45 2020 +0300 minor commit 7c17992424702d95e6de91f30e8ae2dfcd8de257 Author: Simon Zolin Date: Mon Jun 22 16:09:34 2020 +0300 build commit 16a52e11a015a97d3cbf30362482a4abd052192b Merge: 7b6a73c8 2c47053c Author: Simon Zolin Date: Mon Jun 22 16:08:32 2020 +0300 Merge remote-tracking branch 'origin/master' into 1682-dhcp-resolve commit 7b6a73c84b5cb9a073a9dfb7d7bdecd22e1e1318 Author: Simon Zolin Date: Mon Jun 22 16:01:34 2020 +0300 tests commit c2654abb2e5e7b7e3a04e4ddb8e1064b37613929 Author: Simon Zolin Date: Mon Jun 1 15:15:13 2020 +0300 + dnsforward: respond to PTR requests for internal IP addresses {[IP] => "host"} <- DNSforward <-(leases)-- DHCP --- dhcpd/dhcpd.go | 10 +++-- dnsforward/dnsforward.go | 37 ++++++++++++----- dnsforward/dnsforward_test.go | 43 ++++++++++++++++++-- dnsforward/handle_dns.go | 75 +++++++++++++++++++++++++++++++++++ home/dns.go | 8 +++- home/whois_test.go | 2 +- util/auto_hosts.go | 66 +----------------------------- util/auto_hosts_test.go | 14 ++++--- util/dns.go | 70 ++++++++++++++++++++++++++++++++ 9 files changed, 236 insertions(+), 89 deletions(-) create mode 100644 util/dns.go diff --git a/dhcpd/dhcpd.go b/dhcpd/dhcpd.go index f95a9867..0ec83370 100644 --- a/dhcpd/dhcpd.go +++ b/dhcpd/dhcpd.go @@ -92,7 +92,7 @@ type Server struct { conf ServerConfig // Called when the leases DB is modified - onLeaseChanged onLeaseChangedT + onLeaseChanged []onLeaseChangedT } // Print information about the available network interfaces @@ -146,14 +146,16 @@ func (s *Server) Init(config ServerConfig) error { // SetOnLeaseChanged - set callback func (s *Server) SetOnLeaseChanged(onLeaseChanged onLeaseChangedT) { - s.onLeaseChanged = onLeaseChanged + s.onLeaseChanged = append(s.onLeaseChanged, onLeaseChanged) } func (s *Server) notify(flags int) { - if s.onLeaseChanged == nil { + if len(s.onLeaseChanged) == 0 { return } - s.onLeaseChanged(flags) + for _, f := range s.onLeaseChanged { + f(flags) + } } // WriteDiskConfig - write configuration diff --git a/dnsforward/dnsforward.go b/dnsforward/dnsforward.go index e8d8a6b0..36f5445e 100644 --- a/dnsforward/dnsforward.go +++ b/dnsforward/dnsforward.go @@ -8,6 +8,7 @@ import ( "sync" "time" + "github.com/AdguardTeam/AdGuardHome/dhcpd" "github.com/AdguardTeam/AdGuardHome/dnsfilter" "github.com/AdguardTeam/AdGuardHome/querylog" "github.com/AdguardTeam/AdGuardHome/stats" @@ -43,11 +44,15 @@ var webRegistered bool // // The zero Server is empty and ready for use. type Server struct { - dnsProxy *proxy.Proxy // DNS proxy instance - dnsFilter *dnsfilter.Dnsfilter // DNS filter instance - queryLog querylog.QueryLog // Query log instance - stats stats.Stats - access *accessCtx + dnsProxy *proxy.Proxy // DNS proxy instance + dnsFilter *dnsfilter.Dnsfilter // DNS filter instance + dhcpServer *dhcpd.Server // DHCP server instance (optional) + queryLog querylog.QueryLog // Query log instance + stats stats.Stats + access *accessCtx + + tablePTR map[string]string // "IP -> hostname" table for reverse lookup + tablePTRLock sync.Mutex // DNS proxy instance for internal usage // We don't Start() it and so no listen port is required. @@ -59,13 +64,27 @@ type Server struct { conf ServerConfig } +// DNSCreateParams - parameters for NewServer() +type DNSCreateParams struct { + DNSFilter *dnsfilter.Dnsfilter + Stats stats.Stats + QueryLog querylog.QueryLog + DHCPServer *dhcpd.Server +} + // NewServer creates a new instance of the dnsforward.Server // Note: this function must be called only once -func NewServer(dnsFilter *dnsfilter.Dnsfilter, stats stats.Stats, queryLog querylog.QueryLog) *Server { +func NewServer(p DNSCreateParams) *Server { s := &Server{} - s.dnsFilter = dnsFilter - s.stats = stats - s.queryLog = queryLog + s.dnsFilter = p.DNSFilter + s.stats = p.Stats + s.queryLog = p.QueryLog + s.dhcpServer = p.DHCPServer + + if s.dhcpServer != nil { + s.dhcpServer.SetOnLeaseChanged(s.onDHCPLeaseChanged) + s.onDHCPLeaseChanged(dhcpd.LeaseChangedAdded) + } if runtime.GOARCH == "mips" || runtime.GOARCH == "mipsle" { // Use plain DNS on MIPS, encryption is too slow diff --git a/dnsforward/dnsforward_test.go b/dnsforward/dnsforward_test.go index 42018265..773769ee 100644 --- a/dnsforward/dnsforward_test.go +++ b/dnsforward/dnsforward_test.go @@ -15,6 +15,7 @@ import ( "testing" "time" + "github.com/AdguardTeam/AdGuardHome/dhcpd" "github.com/AdguardTeam/AdGuardHome/dnsfilter" "github.com/AdguardTeam/dnsproxy/proxy" "github.com/AdguardTeam/dnsproxy/upstream" @@ -496,7 +497,7 @@ func TestBlockedCustomIP(t *testing.T) { c := dnsfilter.Config{} f := dnsfilter.New(&c, filters) - s := NewServer(f, nil, nil) + s := NewServer(DNSCreateParams{DNSFilter: f}) conf := ServerConfig{} conf.UDPListenAddr = &net.UDPAddr{Port: 0} conf.TCPListenAddr = &net.TCPAddr{Port: 0} @@ -648,7 +649,7 @@ func TestRewrite(t *testing.T) { } f := dnsfilter.New(&c, nil) - s := NewServer(f, nil, nil) + s := NewServer(DNSCreateParams{DNSFilter: f}) conf := ServerConfig{} conf.UDPListenAddr = &net.UDPAddr{Port: 0} conf.TCPListenAddr = &net.TCPAddr{Port: 0} @@ -705,7 +706,7 @@ func createTestServer(t *testing.T) *Server { c.CacheTime = 30 f := dnsfilter.New(&c, filters) - s := NewServer(f, nil, nil) + s := NewServer(DNSCreateParams{DNSFilter: f}) s.conf.UDPListenAddr = &net.UDPAddr{Port: 0} s.conf.TCPListenAddr = &net.TCPAddr{Port: 0} s.conf.UpstreamDNS = []string{"8.8.8.8:53", "8.8.4.4:53"} @@ -1012,3 +1013,39 @@ func TestMatchDNSName(t *testing.T) { assert.True(t, !matchDNSName(dnsNames, "")) assert.True(t, !matchDNSName(dnsNames, "*.host2")) } + +func TestPTRResponse(t *testing.T) { + dhcp := &dhcpd.Server{} + dhcp.IPpool = make(map[[4]byte]net.HardwareAddr) + + c := dnsfilter.Config{} + f := dnsfilter.New(&c, nil) + s := NewServer(DNSCreateParams{DNSFilter: f, DHCPServer: dhcp}) + s.conf.UDPListenAddr = &net.UDPAddr{Port: 0} + s.conf.TCPListenAddr = &net.TCPAddr{Port: 0} + s.conf.UpstreamDNS = []string{"127.0.0.1:53"} + s.conf.FilteringConfig.ProtectionEnabled = true + err := s.Prepare(nil) + assert.True(t, err == nil) + assert.Nil(t, s.Start()) + + l := dhcpd.Lease{} + l.IP = net.ParseIP("127.0.0.1").To4() + l.HWAddr, _ = net.ParseMAC("aa:aa:aa:aa:aa:aa") + l.Hostname = "localhost" + dhcp.AddStaticLease(l) + + addr := s.dnsProxy.Addr(proxy.ProtoUDP) + req := createTestMessage("1.0.0.127.in-addr.arpa.") + req.Question[0].Qtype = dns.TypePTR + + resp, err := dns.Exchange(req, addr.String()) + assert.Nil(t, err) + assert.Equal(t, 1, len(resp.Answer)) + assert.Equal(t, dns.TypePTR, resp.Answer[0].Header().Rrtype) + assert.Equal(t, "1.0.0.127.in-addr.arpa.", resp.Answer[0].Header().Name) + ptr := resp.Answer[0].(*dns.PTR) + assert.Equal(t, "localhost.", ptr.Ptr) + + s.Close() +} diff --git a/dnsforward/handle_dns.go b/dnsforward/handle_dns.go index 87230e9b..462f3750 100644 --- a/dnsforward/handle_dns.go +++ b/dnsforward/handle_dns.go @@ -1,9 +1,12 @@ package dnsforward import ( + "strings" "time" + "github.com/AdguardTeam/AdGuardHome/dhcpd" "github.com/AdguardTeam/AdGuardHome/dnsfilter" + "github.com/AdguardTeam/AdGuardHome/util" "github.com/AdguardTeam/dnsproxy/proxy" "github.com/AdguardTeam/golibs/log" "github.com/miekg/dns" @@ -39,6 +42,7 @@ func (s *Server) handleDNSRequest(_ *proxy.Proxy, d *proxy.DNSContext) error { type modProcessFunc func(ctx *dnsContext) int mods := []modProcessFunc{ processInitial, + processInternalIPAddrs, processFilteringBeforeRequest, processUpstream, processDNSSECAfterResponse, @@ -88,11 +92,82 @@ func processInitial(ctx *dnsContext) int { return resultDone } +func (s *Server) onDHCPLeaseChanged(flags int) { + switch flags { + case dhcpd.LeaseChangedAdded, + dhcpd.LeaseChangedAddedStatic, + dhcpd.LeaseChangedRemovedStatic: + // + default: + return + } + + m := make(map[string]string) + ll := s.dhcpServer.Leases(dhcpd.LeasesAll) + for _, l := range ll { + if len(l.Hostname) == 0 { + continue + } + m[l.IP.String()] = l.Hostname + } + log.Debug("DNS: added %d PTR entries from DHCP", len(m)) + s.tablePTRLock.Lock() + s.tablePTR = m + s.tablePTRLock.Unlock() +} + +// Respond to PTR requests if the target IP address is leased by our DHCP server +func processInternalIPAddrs(ctx *dnsContext) int { + s := ctx.srv + req := ctx.proxyCtx.Req + if req.Question[0].Qtype != dns.TypePTR { + return resultDone + } + + arpa := req.Question[0].Name + arpa = strings.TrimSuffix(arpa, ".") + arpa = strings.ToLower(arpa) + ip := util.DNSUnreverseAddr(arpa) + if ip == nil { + return resultDone + } + + s.tablePTRLock.Lock() + if s.tablePTR == nil { + s.tablePTRLock.Unlock() + return resultDone + } + host, ok := s.tablePTR[ip.String()] + s.tablePTRLock.Unlock() + if !ok { + return resultDone + } + + log.Debug("DNS: reverse-lookup: %s -> %s", arpa, host) + + resp := s.makeResponse(req) + ptr := &dns.PTR{} + ptr.Hdr = dns.RR_Header{ + Name: req.Question[0].Name, + Rrtype: dns.TypePTR, + Ttl: s.conf.BlockedResponseTTL, + Class: dns.ClassINET, + } + ptr.Ptr = host + "." + resp.Answer = append(resp.Answer, ptr) + ctx.proxyCtx.Res = resp + return resultDone +} + // Apply filtering logic func processFilteringBeforeRequest(ctx *dnsContext) int { s := ctx.srv d := ctx.proxyCtx + if d.Res != nil { + return resultDone // response is already set - nothing to do + } + s.RLock() // Synchronize access to s.dnsFilter so it won't be suddenly uninitialized while in use. // This could happen after proxy server has been stopped, but its workers are not yet exited. diff --git a/home/dns.go b/home/dns.go index db05f99a..a5547627 100644 --- a/home/dns.go +++ b/home/dns.go @@ -61,7 +61,13 @@ func initDNSServer() error { filterConf.HTTPRegister = httpRegister Context.dnsFilter = dnsfilter.New(&filterConf, nil) - Context.dnsServer = dnsforward.NewServer(Context.dnsFilter, Context.stats, Context.queryLog) + p := dnsforward.DNSCreateParams{ + DNSFilter: Context.dnsFilter, + Stats: Context.stats, + QueryLog: Context.queryLog, + DHCPServer: Context.dhcpServer, + } + Context.dnsServer = dnsforward.NewServer(p) dnsConfig := generateServerConfig() err = Context.dnsServer.Prepare(&dnsConfig) if err != nil { diff --git a/home/whois_test.go b/home/whois_test.go index 31e6aba2..3ea73c53 100644 --- a/home/whois_test.go +++ b/home/whois_test.go @@ -9,7 +9,7 @@ import ( func prepareTestDNSServer() error { config.DNS.Port = 1234 - Context.dnsServer = dnsforward.NewServer(nil, nil, nil) + Context.dnsServer = dnsforward.NewServer(dnsforward.DNSCreateParams{}) conf := &dnsforward.ServerConfig{} conf.UpstreamDNS = []string{"8.8.8.8"} return Context.dnsServer.Prepare(conf) diff --git a/util/auto_hosts.go b/util/auto_hosts.go index 34a979da..b12acd81 100644 --- a/util/auto_hosts.go +++ b/util/auto_hosts.go @@ -296,70 +296,6 @@ func (a *AutoHosts) Process(host string, qtype uint16) []net.IP { return ipsCopy } -// convert character to hex number -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 -} - -// parse IPv6 reverse address -func ipParseArpa6(s string) 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 - reverse IP address: 1.0.0.127 -> 127.0.0.1 -func ipReverse(ip net.IP) net.IP { - n := len(ip) - r := make(net.IP, n) - for i := 0; i != n; i++ { - r[i] = ip[n-i-1] - } - return r -} - -// Convert reversed ARPA address to a normal IP address -func dnsUnreverseAddr(s string) net.IP { - const arpaV4 = ".in-addr.arpa" - const arpaV6 = ".ip6.arpa" - - if strings.HasSuffix(s, arpaV4) { - ip := strings.TrimSuffix(s, arpaV4) - ip4 := net.ParseIP(ip).To4() - if ip4 == nil { - return nil - } - - return ipReverse(ip4) - - } else if strings.HasSuffix(s, arpaV6) { - ip := strings.TrimSuffix(s, arpaV6) - return ipParseArpa6(ip) - } - - return nil // unknown suffix -} - // ProcessReverse - process PTR request // Return "" if not found or an error occurred func (a *AutoHosts) ProcessReverse(addr string, qtype uint16) string { @@ -367,7 +303,7 @@ func (a *AutoHosts) ProcessReverse(addr string, qtype uint16) string { return "" } - ipReal := dnsUnreverseAddr(addr) + ipReal := DNSUnreverseAddr(addr) if ipReal == nil { return "" // invalid IP in question } diff --git a/util/auto_hosts_test.go b/util/auto_hosts_test.go index 322e7e9c..ea2e43ad 100644 --- a/util/auto_hosts_test.go +++ b/util/auto_hosts_test.go @@ -104,11 +104,13 @@ func TestAutoHostsFSNotify(t *testing.T) { } func TestIP(t *testing.T) { - assert.True(t, dnsUnreverseAddr("1.0.0.127.in-addr.arpa").Equal(net.ParseIP("127.0.0.1").To4())) - assert.True(t, dnsUnreverseAddr("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").Equal(net.ParseIP("::abcd:1234"))) + assert.Equal(t, "127.0.0.1", DNSUnreverseAddr("1.0.0.127.in-addr.arpa").String()) + assert.Equal(t, "::abcd:1234", DNSUnreverseAddr("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").String()) + assert.Equal(t, "::abcd:1234", DNSUnreverseAddr("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").String()) - assert.True(t, dnsUnreverseAddr("1.0.0.127.in-addr.arpa.") == nil) - assert.True(t, dnsUnreverseAddr(".0.0.127.in-addr.arpa") == nil) - assert.True(t, dnsUnreverseAddr(".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") == nil) - assert.True(t, dnsUnreverseAddr("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") == nil) + assert.Nil(t, DNSUnreverseAddr("1.0.0.127.in-addr.arpa.")) + assert.Nil(t, DNSUnreverseAddr(".0.0.127.in-addr.arpa")) + assert.Nil(t, DNSUnreverseAddr(".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")) + assert.Nil(t, DNSUnreverseAddr("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")) + assert.Nil(t, DNSUnreverseAddr("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")) } diff --git a/util/dns.go b/util/dns.go new file mode 100644 index 00000000..aaf51d4d --- /dev/null +++ b/util/dns.go @@ -0,0 +1,70 @@ +package util + +import ( + "net" + "strings" +) + +// convert character to hex number +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 +} + +// parse IPv6 reverse address +func ipParseArpa6(s string) 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 - reverse IP address: 1.0.0.127 -> 127.0.0.1 +func ipReverse(ip net.IP) net.IP { + n := len(ip) + r := make(net.IP, n) + for i := 0; i != n; i++ { + r[i] = ip[n-i-1] + } + return r +} + +// DNSUnreverseAddr - convert reversed ARPA address to a normal IP address +func DNSUnreverseAddr(s string) net.IP { + const arpaV4 = ".in-addr.arpa" + const arpaV6 = ".ip6.arpa" + + if strings.HasSuffix(s, arpaV4) { + ip := strings.TrimSuffix(s, arpaV4) + ip4 := net.ParseIP(ip).To4() + if ip4 == nil { + return nil + } + + return ipReverse(ip4) + + } else if strings.HasSuffix(s, arpaV6) { + ip := strings.TrimSuffix(s, arpaV6) + return ipParseArpa6(ip) + } + + return nil // unknown suffix +} From 0ee3505e1f0cc3df78651f2f9cb393c5ff3df26e Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Tue, 23 Jun 2020 12:39:19 +0300 Subject: [PATCH 23/38] * SB/PC: limit the number of hashes in request to 4 --- dnsfilter/dnsfilter_test.go | 6 ++++++ dnsfilter/security.go | 13 +++++++++++++ 2 files changed, 19 insertions(+) diff --git a/dnsfilter/dnsfilter_test.go b/dnsfilter/dnsfilter_test.go index 6515b53d..f0dff6ec 100644 --- a/dnsfilter/dnsfilter_test.go +++ b/dnsfilter/dnsfilter_test.go @@ -146,6 +146,12 @@ func TestEtcHostsMatching(t *testing.T) { // SAFE BROWSING +func TestSafeBrowsingHash(t *testing.T) { + q, hashes := hostnameToHashParam("1.2.3.4.5.6") + assert.Equal(t, "0132d0fa.b5413b4e.5fa067c1.e7f6c011.", q) + assert.Equal(t, 4, len(hashes)) +} + func TestSafeBrowsing(t *testing.T) { d := NewForTest(&Config{SafeBrowsingEnabled: true}, nil) defer d.Close() diff --git a/dnsfilter/security.go b/dnsfilter/security.go index 7f2b397a..9de23add 100644 --- a/dnsfilter/security.go +++ b/dnsfilter/security.go @@ -157,6 +157,7 @@ func (d *Dnsfilter) checkSafeSearch(host string) (Result, error) { } // for each dot, hash it and add it to string +// The maximum is 4 components: "a.b.c.d" func hostnameToHashParam(host string) (string, map[string]bool) { var hashparam bytes.Buffer hashes := map[string]bool{} @@ -166,6 +167,18 @@ func hostnameToHashParam(host string) (string, map[string]bool) { tld = "" } curhost := host + + nDots := 0 + for i := len(curhost) - 1; i >= 0; i-- { + if curhost[i] == '.' { + nDots++ + if nDots == 4 { + curhost = curhost[i+1:] // "xxx.a.b.c.d" -> "a.b.c.d" + break + } + } + } + for { if curhost == "" { // we've reached end of string From 890876cb0539d4916a21c0e0771a9d4e8322b9be Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Tue, 23 Jun 2020 14:36:26 +0300 Subject: [PATCH 24/38] + pass client Name and IP to dnsfilter * use urlfilter v0.11.0 --- dnsfilter/dnsfilter.go | 24 +++++++++++++++++------- dnsforward/access.go | 2 +- go.mod | 2 +- go.sum | 5 +++-- home/dns.go | 2 ++ 5 files changed, 24 insertions(+), 11 deletions(-) diff --git a/dnsfilter/dnsfilter.go b/dnsfilter/dnsfilter.go index bcd597d8..1014c462 100644 --- a/dnsfilter/dnsfilter.go +++ b/dnsfilter/dnsfilter.go @@ -33,8 +33,12 @@ type RequestFilteringSettings struct { SafeSearchEnabled bool SafeBrowsingEnabled bool ParentalEnabled bool - ClientTags []string - ServicesRules []ServiceEntry + + ClientName string + ClientIP string + ClientTags []string + + ServicesRules []ServiceEntry } // Config allows you to configure DNS filtering with New() or just change variables directly. @@ -297,7 +301,7 @@ func (d *Dnsfilter) CheckHostRules(host string, qtype uint16, setts *RequestFilt return Result{}, nil } - return d.matchHost(host, qtype, setts.ClientTags) + return d.matchHost(host, qtype, *setts) } // CheckHost tries to match the host against filtering rules, @@ -335,7 +339,7 @@ func (d *Dnsfilter) CheckHost(host string, qtype uint16, setts *RequestFiltering // try filter lists first if setts.FilteringEnabled { - result, err = d.matchHost(host, qtype, setts.ClientTags) + result, err = d.matchHost(host, qtype, *setts) if err != nil { return result, err } @@ -545,14 +549,20 @@ func (d *Dnsfilter) initFiltering(allowFilters, blockFilters []Filter) error { } // matchHost is a low-level way to check only if hostname is filtered by rules, skipping expensive safebrowsing and parental lookups -func (d *Dnsfilter) matchHost(host string, qtype uint16, ctags []string) (Result, error) { +func (d *Dnsfilter) matchHost(host string, qtype uint16, setts RequestFilteringSettings) (Result, error) { d.engineLock.RLock() // Keep in mind that this lock must be held no just when calling Match() // but also while using the rules returned by it. defer d.engineLock.RUnlock() + ureq := urlfilter.DNSRequest{} + ureq.Hostname = host + ureq.ClientIP = setts.ClientIP + ureq.ClientName = setts.ClientName + ureq.SortedClientTags = setts.ClientTags + if d.filteringEngineWhite != nil { - rr, ok := d.filteringEngineWhite.Match(host, ctags) + rr, ok := d.filteringEngineWhite.MatchRequest(ureq) if ok { var rule rules.Rule if rr.NetworkRule != nil { @@ -574,7 +584,7 @@ func (d *Dnsfilter) matchHost(host string, qtype uint16, ctags []string) (Result return Result{}, nil } - rr, ok := d.filteringEngine.Match(host, ctags) + rr, ok := d.filteringEngine.MatchRequest(ureq) if !ok { return Result{}, nil } diff --git a/dnsforward/access.go b/dnsforward/access.go index 6eed4337..eadd1141 100644 --- a/dnsforward/access.go +++ b/dnsforward/access.go @@ -122,7 +122,7 @@ func (a *accessCtx) IsBlockedIP(ip string) bool { // IsBlockedDomain - return TRUE if this domain should be blocked func (a *accessCtx) IsBlockedDomain(host string) bool { a.lock.Lock() - _, ok := a.blockedHostsEngine.Match(host, nil) + _, ok := a.blockedHostsEngine.Match(host) a.lock.Unlock() return ok } diff --git a/go.mod b/go.mod index a67e8747..3dfd6d97 100644 --- a/go.mod +++ b/go.mod @@ -5,7 +5,7 @@ go 1.14 require ( github.com/AdguardTeam/dnsproxy v0.29.0 github.com/AdguardTeam/golibs v0.4.2 - github.com/AdguardTeam/urlfilter v0.10.1 + github.com/AdguardTeam/urlfilter v0.11.0 github.com/NYTimes/gziphandler v1.1.1 github.com/fsnotify/fsnotify v1.4.7 github.com/gobuffalo/packr v1.30.1 diff --git a/go.sum b/go.sum index 38971352..ed9051b0 100644 --- a/go.sum +++ b/go.sum @@ -5,8 +5,9 @@ github.com/AdguardTeam/golibs v0.4.0/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKU github.com/AdguardTeam/golibs v0.4.2 h1:7M28oTZFoFwNmp8eGPb3ImmYbxGaJLyQXeIFVHjME0o= github.com/AdguardTeam/golibs v0.4.2/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4= github.com/AdguardTeam/gomitmproxy v0.2.0/go.mod h1:Qdv0Mktnzer5zpdpi5rAwixNJzW2FN91LjKJCkVbYGU= -github.com/AdguardTeam/urlfilter v0.10.1 h1:ECago6OvZjOTKlOqxU39C+V/ecAslaCDYcf5s+/hwaY= -github.com/AdguardTeam/urlfilter v0.10.1/go.mod h1:aMuejlNxpWppOVjiEV87X6z0eMf7wsXHTAIWQuylfZY= +github.com/AdguardTeam/urlfilter v0.11.0 h1:tgZss6uZs1UZAaxpovD/QuX+VVIQLDOlKc7rdF8dwNw= +github.com/AdguardTeam/urlfilter v0.11.0/go.mod h1:aMuejlNxpWppOVjiEV87X6z0eMf7wsXHTAIWQuylfZY= +github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/NYTimes/gziphandler v1.1.1 h1:ZUDjpQae29j0ryrS0u/B8HZfJBtBQHjqw2rQ2cqUQ3I= github.com/NYTimes/gziphandler v1.1.1/go.mod h1:n/CVRwUEOgIxrgPvAQhUUr9oeUtvrhMomdKFjzJNB0c= diff --git a/home/dns.go b/home/dns.go index a5547627..6d7f4cf6 100644 --- a/home/dns.go +++ b/home/dns.go @@ -235,6 +235,7 @@ func applyAdditionalFiltering(clientAddr string, setts *dnsfilter.RequestFilteri if len(clientAddr) == 0 { return } + setts.ClientIP = clientAddr c, ok := Context.clients.Find(clientAddr) if !ok { @@ -247,6 +248,7 @@ func applyAdditionalFiltering(clientAddr string, setts *dnsfilter.RequestFilteri Context.dnsFilter.ApplyBlockedServices(setts, c.BlockedServices, false) } + setts.ClientName = c.Name setts.ClientTags = c.Tags if !c.UseOwnSettings { From b43223d30226f70b4616c71429f93a38e89cb163 Mon Sep 17 00:00:00 2001 From: Andrey Meshkov Date: Tue, 23 Jun 2020 18:02:28 +0300 Subject: [PATCH 25/38] *(home): do not require root privileges on the first run Instead of requiring root privileges, we now check if AdGuard Home can bind to privileged ports. If it cannot, we suggest either running it with root privileges or grant CAP_NET_BIND_SERVICE capability. Please note, that on Windows we still require root access. Closes: #1699 --- home/home.go | 70 +++++++++++++++++++++++++++++++--------------------- util/net.go | 21 ++++++++++++++++ 2 files changed, 63 insertions(+), 28 deletions(-) create mode 100644 util/net.go diff --git a/home/home.go b/home/home.go index e93daa60..f73064c7 100644 --- a/home/home.go +++ b/home/home.go @@ -1,23 +1,19 @@ package home import ( - "bufio" "context" "crypto/tls" "crypto/x509" "fmt" - "io" "io/ioutil" "net" "net/http" "net/url" "os" - "os/exec" "os/signal" "path/filepath" "runtime" "strconv" - "strings" "sync" "syscall" "time" @@ -172,7 +168,7 @@ func run(args options) { Context.firstRun = detectFirstRun() if Context.firstRun { log.Info("This is the first time AdGuard Home is launched") - requireAdminRights() + checkPermissions() } initConfig() @@ -334,36 +330,54 @@ func StartMods() error { // Check if the current user has root (administrator) rights // and if not, ask and try to run as root -func requireAdminRights() { - admin, _ := util.HaveAdminRights() - if //noinspection ALL - admin || isdelve.Enabled { - // Don't forget that for this to work you need to add "delve" tag explicitly - // https://stackoverflow.com/questions/47879070/how-can-i-see-if-the-goland-debugger-is-running-in-the-program +func checkPermissions() { + log.Info("Checking if AdGuard Home has necessary permissions") + + if runtime.GOOS == "windows" { + // On Windows we need to have admin rights to run properly + + admin, _ := util.HaveAdminRights() + if //noinspection ALL + admin || isdelve.Enabled { + // Don't forget that for this to work you need to add "delve" tag explicitly + // https://stackoverflow.com/questions/47879070/how-can-i-see-if-the-goland-debugger-is-running-in-the-program + return + } + + log.Fatal("This is the first launch of AdGuard Home. You must run it as Administrator.") + } + + // We should check if AdGuard Home is able to bind to port 53 + ok, err := util.CanBindPort(53) + + if ok { + log.Info("AdGuard Home can bind to port 53") return } - if runtime.GOOS == "windows" { - log.Fatal("This is the first launch of AdGuard Home. You must run it as Administrator.") + if opErr, ok := err.(*net.OpError); ok { + if sysErr, ok := opErr.Err.(*os.SyscallError); ok { + if errno, ok := sysErr.Err.(syscall.Errno); ok && errno == syscall.EACCES { + msg := `Permission check failed. - } else { - log.Error("This is the first launch of AdGuard Home. You must run it as root.") +AdGuard Home is not allowed to bind to privileged ports (for instance, port 53). +Please note, that this is crucial for a server to be able to use privileged ports. - _, _ = io.WriteString(os.Stdout, "Do you want to start AdGuard Home as root user? [y/n] ") - stdin := bufio.NewReader(os.Stdin) - buf, _ := stdin.ReadString('\n') - buf = strings.TrimSpace(buf) - if buf != "y" { - os.Exit(1) +You have two options: +1. Run AdGuard Home with root privileges +2. On Linux you can grant the CAP_NET_BIND_SERVICE capability: +https://github.com/AdguardTeam/AdGuardHome/wiki/Getting-Started#running-without-superuser` + + log.Fatal(msg) + } } - - cmd := exec.Command("sudo", os.Args...) - cmd.Stdin = os.Stdin - cmd.Stdout = os.Stdout - cmd.Stderr = os.Stderr - _ = cmd.Run() - os.Exit(1) } + + msg := fmt.Sprintf(`AdGuard failed to bind to port 53 due to %v + +Please note, that this is crucial for a DNS server to be able to use that port.`, err) + + log.Info(msg) } // Write PID to a file diff --git a/util/net.go b/util/net.go new file mode 100644 index 00000000..e6d4d58e --- /dev/null +++ b/util/net.go @@ -0,0 +1,21 @@ +package util + +import ( + "fmt" + "net" +) + +// CanBindPort - checks if we can bind to this port or not +func CanBindPort(port int) (bool, error) { + addr, err := net.ResolveTCPAddr("tcp", fmt.Sprintf("127.0.0.1:%d", port)) + if err != nil { + return false, err + } + + l, err := net.ListenTCP("tcp", addr) + if err != nil { + return false, err + } + _ = l.Close() + return true, nil +} From 7b2cc51e35bfb725f02e91cb991ddd099b81ee0c Mon Sep 17 00:00:00 2001 From: Andrey Meshkov Date: Tue, 23 Jun 2020 18:04:26 +0300 Subject: [PATCH 26/38] fix function comment --- home/home.go | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/home/home.go b/home/home.go index f73064c7..f5b9375f 100644 --- a/home/home.go +++ b/home/home.go @@ -328,8 +328,7 @@ func StartMods() error { return nil } -// Check if the current user has root (administrator) rights -// and if not, ask and try to run as root +// Check if the current user permissions are enough to run AdGuard Home func checkPermissions() { log.Info("Checking if AdGuard Home has necessary permissions") From e38a1a583346f377d352148ec0f26c00be6f302e Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Mon, 29 Jun 2020 14:03:12 +0300 Subject: [PATCH 27/38] * use dnsproxy v0.29.1 Close #1777 Squashed commit of the following: commit 5aab12162e9366ccf37bfe662f22bee59b8f98f5 Author: Simon Zolin Date: Mon Jun 29 12:07:34 2020 +0300 * use dnsproxy v0.29.1 --- go.mod | 2 +- go.sum | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/go.mod b/go.mod index 3dfd6d97..eb03f550 100644 --- a/go.mod +++ b/go.mod @@ -3,7 +3,7 @@ module github.com/AdguardTeam/AdGuardHome go 1.14 require ( - github.com/AdguardTeam/dnsproxy v0.29.0 + github.com/AdguardTeam/dnsproxy v0.29.1 github.com/AdguardTeam/golibs v0.4.2 github.com/AdguardTeam/urlfilter v0.11.0 github.com/NYTimes/gziphandler v1.1.1 diff --git a/go.sum b/go.sum index ed9051b0..6d05c0a3 100644 --- a/go.sum +++ b/go.sum @@ -1,5 +1,5 @@ -github.com/AdguardTeam/dnsproxy v0.29.0 h1:cHurldpiipPBAH+kgytcg9pkeYjG43KWiVYPbN3rAw4= -github.com/AdguardTeam/dnsproxy v0.29.0/go.mod h1:hOYFV9TW+pd5XKYz7KZf2FFD8SvSPqjyGTxUae86s58= +github.com/AdguardTeam/dnsproxy v0.29.1 h1:Stc+JLh67C9K38vbrH2920+3FnbXKkFzYQqRiu5auUo= +github.com/AdguardTeam/dnsproxy v0.29.1/go.mod h1:hOYFV9TW+pd5XKYz7KZf2FFD8SvSPqjyGTxUae86s58= github.com/AdguardTeam/golibs v0.4.0 h1:4VX6LoOqFe9p9Gf55BeD8BvJD6M6RDYmgEiHrENE9KU= github.com/AdguardTeam/golibs v0.4.0/go.mod h1:skKsDKIBB7kkFflLJBpfGX+G8QFTx0WKUzB6TIgtUj4= github.com/AdguardTeam/golibs v0.4.2 h1:7M28oTZFoFwNmp8eGPb3ImmYbxGaJLyQXeIFVHjME0o= From 4b2c33d12e6bcc2dddc2ceccb38c0bc9c2fcaa3c Mon Sep 17 00:00:00 2001 From: Andrey Meshkov Date: Mon, 29 Jun 2020 17:24:16 +0300 Subject: [PATCH 28/38] Update translations --- client/src/__locales/bg.json | 6 +++++ client/src/__locales/cs.json | 11 ++++++++- client/src/__locales/da.json | 9 +++++++- client/src/__locales/de.json | 10 +++++++- client/src/__locales/en.json | 6 ++--- client/src/__locales/es.json | 29 ++++++++++++++--------- client/src/__locales/fa.json | 1 - client/src/__locales/fr.json | 3 ++- client/src/__locales/hr.json | 11 ++++++++- client/src/__locales/id.json | 23 +++++++++++++++++- client/src/__locales/it.json | 4 +++- client/src/__locales/ja.json | 6 ++++- client/src/__locales/ko.json | 11 ++++++++- client/src/__locales/nl.json | 8 ++++++- client/src/__locales/pl.json | 9 +++++++- client/src/__locales/pt-br.json | 8 ++++++- client/src/__locales/ro.json | 13 +++++++++-- client/src/__locales/ru.json | 37 ++++++++++++++++++++++++++++- client/src/__locales/sk.json | 11 ++++++++- client/src/__locales/sl.json | 6 ++++- client/src/__locales/tr.json | 11 +++++++++ client/src/__locales/vi.json | 15 ++++++++++++ client/src/__locales/zh-cn.json | 41 ++++++++++++++++++++++++++++++--- client/src/__locales/zh-tw.json | 11 ++++++++- 24 files changed, 264 insertions(+), 36 deletions(-) diff --git a/client/src/__locales/bg.json b/client/src/__locales/bg.json index fa930888..7078011c 100644 --- a/client/src/__locales/bg.json +++ b/client/src/__locales/bg.json @@ -29,6 +29,8 @@ "dhcp_table_expires": "История", "dhcp_warning": "Ако искате да използвате вградения DHCP сървър, трябва да няма друг активен DHCP в мрежата Ви!", "city": "Град", + "response_details": "Подробности за отговора", + "request_details": "Поискайте подробности", "back": "Назад", "dashboard": "Табло", "settings": "Настройки", @@ -37,6 +39,7 @@ "faq": "ЧЗВ", "version": "версия", "address": "Адрес", + "protocol": "Протокол", "on": "ВКЛЮЧЕНО", "off": "ИЗКЛЮЧЕНО", "copyright": "Авторско право", @@ -98,6 +101,7 @@ "filters_and_hosts_hint": "AdGuard Home разбира adblock и host синтаксис.", "cancel_btn": "Откажи", "enter_name_hint": "Въведи име", + "check_updates_btn": "Провери за актуализация", "custom_filter_rules": "Местни правила за филтриране", "custom_filter_rules_hint": "Въвеждайте всяко правило на нов ред. Може да използвате adblock или hosts файлов синтаксис.", "examples_title": "Примери", @@ -137,6 +141,7 @@ "updated_custom_filtering_toast": "Обновени местни правила за филтриране", "rule_removed_from_custom_filtering_toast": "Премахнато от местни правила за филтриране", "rule_added_to_custom_filtering_toast": "Добавено до местни правила за филтриране", + "plain_dns": "Обикновен DNS", "source_label": "Източник", "found_in_known_domain_db": "Намерен в списъците с домейни.", "category_label": "Категория", @@ -230,5 +235,6 @@ "form_error_password": "Паролата не съвпада", "reset_settings": "Изтрий всички настройки", "update_announcement": "Има нова AdGuard Home {{version}}! <0>Цъкни тук за повече информация.", + "disable_ipv6": "Изключете IPv6 протокола", "show_blocked_responses": "Блокирано" } \ No newline at end of file diff --git a/client/src/__locales/cs.json b/client/src/__locales/cs.json index dd5488e6..2f02414b 100644 --- a/client/src/__locales/cs.json +++ b/client/src/__locales/cs.json @@ -3,6 +3,8 @@ "example_upstream_reserved": "Můžete zadat DNS upstream <0>pro konkrétní doménu(y)", "upstream_parallel": "Použijte paralelní požadavky na urychlení řešení simultánním dotazováním na všechny navazující servery", "parallel_requests": "Paralelní požadavky", + "load_balancing": "Optimalizace vytížení", + "load_balancing_desc": "Optimalizovaný dotaz na server. AdGuard Home použije vážený náhodný algoritmus k výběru serveru, takže nejrychlejší server bude používán častěji.", "bootstrap_dns": "Bootstrap DNS servery", "bootstrap_dns_desc": "Servery Bootstrap DNS se používají k řešení IP adres DoH/DoT, které zadáváte jako upstreamy.", "check_dhcp_servers": "Zkontrolovat DHCP servery", @@ -65,7 +67,8 @@ "filters": "Filtry", "filter": "Filtr", "query_log": "Protokol dotazů", - "empty_log": "Záznam dotazů je prázdný", + "compact": "Kompaktní", + "nothing_found": "Nic nebylo nalezeno", "faq": "FAQ", "version": "Verze", "address": "Adresa", @@ -190,6 +193,7 @@ "domain_or_client": "Doména nebo klient", "type_table_header": "Typ", "response_table_header": "Odezva", + "response_code": "Kód odezvy", "client_table_header": "Klient", "empty_response_status": "Prázdná", "show_all_filter_type": "Zobrazit vše", @@ -208,6 +212,7 @@ "query_log_filtered": "Filtrováno pomocí {{filter}}", "query_log_confirm_clear": "Opravdu chcete vymazat celý protokol dotazů?", "query_log_cleared": "Protokol dotazů byl úspěšně vymazán", + "query_log_updated": "Protokol dotazů byl úspěšně aktualizován", "query_log_clear": "Vymazat protokoly dotazů", "query_log_retention": "Uchování protokolů dotazů", "query_log_enable": "Povolit protokol", @@ -225,6 +230,8 @@ "custom_ip": "Vlastní IP", "blocking_ipv4": "Blokování IPv4", "blocking_ipv6": "Blokování IPv6", + "dns_over_https": "DNS přes HTTPS", + "dns_over_tls": "DNS přes TLS", "plain_dns": "Čisté DNS", "form_enter_rate_limit": "Zadejte rychlostní limit", "rate_limit": "Rychlostní limit", @@ -238,6 +245,7 @@ "blocking_mode_null_ip": "Nulová IP: Odezva s nulovou IP adresou (0.0.0.0 pro A; :: pro AAAA)", "blocking_mode_custom_ip": "Vlastní IP. odezva s ručně nastavenou IP adresou", "upstream_dns_client_desc": "Pokud toto pole ponecháte prázdné, AdGuard Home použije servery nakonfigurované v<0>DNS nastavení.", + "tracker_source": "Zdroj slídiče", "source_label": "Zdroj", "found_in_known_domain_db": "Nalezeno v databázi známých domén", "category_label": "Kategorie", @@ -512,6 +520,7 @@ "show_all_responses": "Všechny odpovědi", "show_blocked_responses": "Zablokované", "show_whitelisted_responses": "Povolené", + "show_processed_responses": "Zpracovaný", "blocked_safebrowsing": "Blokované bezpečné prohlížení", "blocked_adult_websites": "Blokované stránky pro dospělé", "blocked_threats": "Blokované hrozby", diff --git a/client/src/__locales/da.json b/client/src/__locales/da.json index 7f50a4c7..9941ac52 100644 --- a/client/src/__locales/da.json +++ b/client/src/__locales/da.json @@ -53,9 +53,11 @@ "dhcp_add_static_lease": "Tilføj static lease", "dhcp_reset": "Er du sikker på, at du vil nulstille DHCP-konfigurationen?", "country": "Land", + "city": "By", "delete_confirm": "Er du sikker på, at du vil slette \"{{key}}\"?", "form_enter_hostname": "Indtast værtsnavn", "error_details": "Fejloplysninger", + "response_details": "Svardetaljer", "request_details": "Anmod om detaljer", "client_details": "Klientoplysninger", "details": "Detaljer", @@ -65,7 +67,8 @@ "filters": "Filtre", "filter": "Filter", "query_log": "Forespørgselslog", - "empty_log": "Forespørgselsloggen er tom", + "compact": "Kompakt", + "nothing_found": "Intet blev fundet", "faq": "FAQ", "version": "Version", "address": "Adresse", @@ -190,6 +193,7 @@ "domain_or_client": "Domæne eller klient", "type_table_header": "Type", "response_table_header": "Svar", + "response_code": "Responskode", "client_table_header": "Klient", "empty_response_status": "Tom", "show_all_filter_type": "Vis alle", @@ -208,6 +212,7 @@ "query_log_filtered": "Filtreret af {{filter}}", "query_log_confirm_clear": "Er du sikker på, at du vil rydde hele forespørgselsloggen?", "query_log_cleared": "Forespørgselsloggen er blevet ryddet", + "query_log_updated": "Forespørgselsloggen er blevet opdateret", "query_log_clear": "Ryd forespørgselslogfiler", "query_log_retention": "Opbevaring af forespørgselslogfiler", "query_log_enable": "Aktivér log", @@ -227,6 +232,7 @@ "blocking_ipv6": "IPv6-blokering", "dns_over_https": "DNS-over-HTTPS", "dns_over_tls": "DNS-over-TLS", + "plain_dns": "Almindelig DNS", "form_enter_rate_limit": "Indtast hyppighedsgrænse", "rate_limit": "Hyppighedsgrænse", "edns_enable": "Aktiver EDNS Client Subnet", @@ -239,6 +245,7 @@ "blocking_mode_null_ip": "Null IP: Svar med nul IP-adresse (0.0.0.0 for A; :: for AAAA)", "blocking_mode_custom_ip": "Brugerdefineret IP: Svar med en manuelt indstillet IP-adresse", "upstream_dns_client_desc": "Hvis du lader dette felt være tomt, vil AdGuard Home bruge de servere, der er konfigureret i <0>DNS-indstillingerne.", + "tracker_source": "Tracker-kilde", "source_label": "Kilde", "found_in_known_domain_db": "Fundet i databasen med kendte domæner.", "category_label": "Kategori", diff --git a/client/src/__locales/de.json b/client/src/__locales/de.json index ddf15657..233ca87a 100644 --- a/client/src/__locales/de.json +++ b/client/src/__locales/de.json @@ -57,6 +57,8 @@ "delete_confirm": "Möchten Sie „{{key}}” wirklich löschen?", "form_enter_hostname": "Gerätenamen eingeben", "error_details": "Fehlerdetails", + "response_details": "Einzelheiten der Antwort", + "request_details": "Einzelheiten der Anfrage", "client_details": "Einzelheiten des Clients", "details": "Details", "back": "Zurück", @@ -65,7 +67,8 @@ "filters": "Filter", "filter": "Filter", "query_log": "Anfragenprotokoll", - "empty_log": "Abfrageprotokoll ist leer", + "compact": "Kompakt", + "nothing_found": "Nichts gefunden\n", "faq": "FAQ", "version": "Version", "address": "Adresse", @@ -182,6 +185,7 @@ "updated_upstream_dns_toast": "Upstream-DNS-Server wurden aktualisiert", "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", + "unblock": "Entsperren", "block": "Blockieren", "time_table_header": "Zeit", "date": "Datum", @@ -189,6 +193,7 @@ "domain_or_client": "Domain oder Client", "type_table_header": "Typ", "response_table_header": "Antwort", + "response_code": "Antwortcode", "client_table_header": "Client", "empty_response_status": "Leer", "show_all_filter_type": "Alle anzeigen", @@ -207,6 +212,7 @@ "query_log_filtered": "Gefiltert nach {{filter}}", "query_log_confirm_clear": "Möchten Sie wirklich das Abfrageprotokoll vollständig löschen?", "query_log_cleared": "Das Abfrageprotokoll wurde erfolgreich gelöscht", + "query_log_updated": "Das Abfrageprotokoll wurde erfolgreich aktualisiert", "query_log_clear": "Abfrageprotokolle leeren", "query_log_retention": "Abfrageprotokolle aufbewahren", "query_log_enable": "Protokoll aktivieren", @@ -226,6 +232,7 @@ "blocking_ipv6": "IPv6-Sperren", "dns_over_https": "DNS-over-HTTPS (DNS-Abrage über HTTPS)", "dns_over_tls": "DNS-over-TLS (DNS-Abrage über TLS)", + "plain_dns": "Einfaches DNS", "form_enter_rate_limit": "Begrenzungswert eingeben", "rate_limit": "Begrenzungswert", "edns_enable": "EDNS Client Subnetz aktivieren", @@ -238,6 +245,7 @@ "blocking_mode_null_ip": "Null-IP: Antworten mit Null-IP-Adresse (0.0.0.0.0 für A; :: für AAAA)", "blocking_mode_custom_ip": "Benutzerdefinierte IP: Mit einer manuell eingestellten IP-Adresse antworten", "upstream_dns_client_desc": "Wenn Sie dieses Feld leer lassen, verwendet AdGuard Home die Server, die in den <0>DNS-Einstellungen konfiguriert sind.", + "tracker_source": "Tracker-Quelle", "source_label": "Quelle", "found_in_known_domain_db": "In der Datenbank der bekannten Domains gefunden.", "category_label": "Kategorie", diff --git a/client/src/__locales/en.json b/client/src/__locales/en.json index 3f638b81..18eabbce 100644 --- a/client/src/__locales/en.json +++ b/client/src/__locales/en.json @@ -68,7 +68,7 @@ "filter": "Filter", "query_log": "Query Log", "compact": "Compact", - "nothing_found": "Nothing is found", + "nothing_found": "Nothing found", "faq": "FAQ", "version": "Version", "address": "Address", @@ -521,7 +521,7 @@ "show_blocked_responses": "Blocked", "show_whitelisted_responses": "Whitelisted", "show_processed_responses": "Processed", - "blocked_safebrowsing": "Blocked Safebrowsing", + "blocked_safebrowsing": "Blocked by Safebrowsing", "blocked_adult_websites": "Blocked Adult Websites", "blocked_threats": "Blocked Threats", "allowed": "Allowed", @@ -530,4 +530,4 @@ "safe_search": "Safe search", "blocklist": "Blocklist", "milliseconds_abbreviation": "ms" -} +} \ No newline at end of file diff --git a/client/src/__locales/es.json b/client/src/__locales/es.json index bb22c1c6..492d5fc7 100644 --- a/client/src/__locales/es.json +++ b/client/src/__locales/es.json @@ -12,7 +12,7 @@ "enabled_dhcp": "Servidor DHCP habilitado", "disabled_dhcp": "Servidor DHCP deshabilitado", "dhcp_title": "Servidor DHCP (experimental)", - "dhcp_description": "Si tu router no proporciona la configuración DHCP, puede utilizar el propio servidor DHCP incorporado de AdGuard.", + "dhcp_description": "Si tu router no proporciona la configuración DHCP, puedes utilizar el propio servidor DHCP incorporado de AdGuard.", "dhcp_enable": "Habilitar servidor DHCP", "dhcp_disable": "Deshabilitar servidor DHCP", "dhcp_not_found": "Es seguro habilitar el servidor DHCP incorporado. No se ha encontrado ningún servidor DHCP activo en la red, sin embargo le recomendamos que lo vuelva a comprobar manualmente, ya que nuestra prueba automática no ofrece actualmente una garantía del 100 %.", @@ -42,10 +42,10 @@ "ip": "IP", "dhcp_table_hostname": "Nombre del host", "dhcp_table_expires": "Expira", - "dhcp_warning": "Si de todos modos desea habilitar el servidor DHCP, asegúrese de que no hay otro servidor DHCP activo en tu red. ¡De lo contrario, puede dejar sin Internet a los dispositivos conectados!", + "dhcp_warning": "Si de todos modos deseas habilitar el servidor DHCP, asegúrate de que no hay otro servidor DHCP activo en tu red. ¡De lo contrario, puedes dejar sin Internet a los dispositivos conectados!", "dhcp_error": "No pudimos determinar si hay otro servidor DHCP en la red.", "dhcp_static_ip_error": "Para poder utilizar el servidor DHCP se debe establecer una dirección IP estática. No hemos podido determinar si esta interfaz de red está configurada utilizando una dirección IP estática. Por favor establezca una dirección IP estática manualmente.", - "dhcp_dynamic_ip_found": "Tu sistema utiliza la configuración de dirección IP dinámica para la interfaz <0>{{interfaceName}}. Para poder utilizar el servidor DHCP se debe establecer una dirección IP estática. Tu dirección IP actual es <0>{{ipAddress}}. Si presiona el botón Habilitar servidor DHCP, estableceremos automáticamente esta dirección IP como estática.", + "dhcp_dynamic_ip_found": "Tu sistema utiliza la configuración de dirección IP dinámica para la interfaz <0>{{interfaceName}}. Para poder utilizar el servidor DHCP se debe establecer una dirección IP estática. Tu dirección IP actual es <0>{{ipAddress}}. Si presionas el botón Habilitar servidor DHCP, estableceremos automáticamente esta dirección IP como estática.", "dhcp_lease_added": "Asignación estática \"{{key}}\" añadido correctamente", "dhcp_lease_deleted": "Asignación estática \"{{key}}\" eliminado correctamente", "dhcp_new_static_lease": "Nueva asignación estática", @@ -53,9 +53,11 @@ "dhcp_add_static_lease": "Añadir asignación estática", "dhcp_reset": "¿Está seguro de que desea restablecer la configuración DHCP?", "country": "País", + "city": "Ciudad", "delete_confirm": "¿Está seguro de que desea eliminar \"{{key}}\"?", "form_enter_hostname": "Ingresa el nombre del host", "error_details": "Detalles del error", + "response_details": "Detalles de la respuesta", "request_details": "Detalles de la petición", "client_details": "Detalles del cliente", "details": "Detalles", @@ -65,7 +67,8 @@ "filters": "Filtros", "filter": "Filtro", "query_log": "Registro de consultas", - "empty_log": "El registro de consultas está vacío", + "compact": "Compacto", + "nothing_found": "No se ha encontrado nada", "faq": "Preguntas frecuentes", "version": "Versión", "address": "Dirección", @@ -106,7 +109,7 @@ "average_processing_time": "Tiempo promedio de procesamiento", "average_processing_time_hint": "Tiempo promedio en milisegundos al procesar una petición DNS", "block_domain_use_filters_and_hosts": "Bloquear dominios usando filtros y archivos hosts", - "filters_block_toggle_hint": "Puede configurar las reglas de bloqueo en la configuración de filtros.", + "filters_block_toggle_hint": "Puedes configurar las reglas de bloqueo en la configuración de filtros.", "use_adguard_browsing_sec": "Usar el servicio web de seguridad de navegación de AdGuard", "use_adguard_browsing_sec_hint": "AdGuard Home comprobará si el dominio está en la lista negra del servicio web de seguridad de navegación. Utilizará la API de búsqueda amigable con la privacidad para realizar la comprobación: solo se envía al servidor un prefijo corto del nombre de dominio con hash SHA256.", "use_adguard_parental": "Usar el control parental de AdGuard", @@ -181,7 +184,7 @@ "all_lists_up_to_date_toast": "Todas las listas ya están actualizadas", "updated_upstream_dns_toast": "Servidores DNS de subida actualizados", "dns_test_ok_toast": "Los servidores DNS especificados funcionan correctamente", - "dns_test_not_ok_toast": "Servidor \"{{key}}\": no se puede utilizar, por favor revise si lo ha escrito correctamente", + "dns_test_not_ok_toast": "Servidor \"{{key}}\": no se puede utilizar, por favor revisa si lo has escrito correctamente", "unblock": "Desbloquear", "block": "Bloquear", "time_table_header": "Hora", @@ -190,6 +193,7 @@ "domain_or_client": "Dominio o cliente", "type_table_header": "Tipo", "response_table_header": "Respuesta", + "response_code": "Código de respuesta", "client_table_header": "Cliente", "empty_response_status": "Vacío", "show_all_filter_type": "Mostrar todo", @@ -208,6 +212,7 @@ "query_log_filtered": "Filtrado por {{filter}}", "query_log_confirm_clear": "¿Está seguro de que desea borrar todo el registro de consultas?", "query_log_cleared": "El registro de consultas se ha borrado correctamente", + "query_log_updated": "El registro de consultas se ha actualizado correctamente", "query_log_clear": "Borrar registros de consultas", "query_log_retention": "Retención de registros de consultas", "query_log_enable": "Habilitar registro", @@ -227,6 +232,7 @@ "blocking_ipv6": "Bloqueo de IPv6", "dns_over_https": "DNS mediante HTTPS", "dns_over_tls": "DNS mediante TLS", + "plain_dns": "DNS simple", "form_enter_rate_limit": "Ingresa el límite de cantidad", "rate_limit": "Límite de cantidad", "edns_enable": "Habilitar subred de cliente EDNS", @@ -239,6 +245,7 @@ "blocking_mode_null_ip": "IP nulo: Responde con dirección IP cero (0.0.0.0 para A; :: para AAAA)", "blocking_mode_custom_ip": "IP personalizada: Responde con una dirección IP establecida manualmente", "upstream_dns_client_desc": "Si se mantiene este campo vacío, AdGuard Home utilizará los servidores configurados en la <0>configuración del DNS.", + "tracker_source": "Fuente del rastreador", "source_label": "Fuente", "found_in_known_domain_db": "Encontrado en la base de datos de dominios conocidos.", "category_label": "Categoría", @@ -374,7 +381,7 @@ "auto_clients_title": "Clientes (activos)", "auto_clients_desc": "Datos de los clientes que utilizan AdGuard Home, pero no se almacenan en la configuración", "access_title": "Configuración de acceso", - "access_desc": "Aquí puede configurar las reglas de acceso para el servidor DNS de AdGuard Home.", + "access_desc": "Aquí puedes configurar las reglas de acceso para el servidor DNS de AdGuard Home.", "access_allowed_title": "Clientes permitidos", "access_allowed_desc": "Lista de CIDR o direcciones IP. Si está configurado, AdGuard Home solo aceptará peticiones de estas direcciones IP.", "access_disallowed_title": "Clientes no permitidos", @@ -400,7 +407,7 @@ "setup_dns_privacy_other_3": "<0>dnscrypt-proxy soporta <1>DNS mediante HTTPS.", "setup_dns_privacy_other_4": "<0>Mozilla Firefox soporta <1>DNS mediante HTTPS.", "setup_dns_privacy_other_5": "Encontrará más implementaciones <0>aquí y <1>aquí.", - "setup_dns_notice": "Para utilizar <1>DNS mediante HTTPS o <1>DNS mediante TLS, debe <0>configurar el cifrado en la configuración de AdGuard Home.", + "setup_dns_notice": "Para utilizar <1>DNS mediante HTTPS o <1>DNS mediante TLS, debes <0>configurar el cifrado en la configuración de AdGuard Home.", "rewrite_added": "Reescritura DNS para \"{{key}}\" añadido correctamente", "rewrite_deleted": "Reescritura DNS para \"{{key}}\" eliminado correctamente", "rewrite_add": "Añadir reescritura DNS", @@ -480,7 +487,7 @@ "autofix_warning_list": "Realizará estas tareas: <0>Deshabilitar el sistema DNSStubListener <0>Establecer la dirección del servidor DNS en 127.0.0.1 <0>Reemplazar el destino del enlace simbólico de /etc/resolv.conf por /run/systemd/resolve/resolv.conf <0>Detener DNSStubListener (recargar el servicio systemd-resolved)", "autofix_warning_result": "Como resultado, todas las peticiones DNS de tu sistema serán procesadas por AdGuard Home de manera predeterminada.", "tags_title": "Etiquetas", - "tags_desc": "Puede seleccionar las etiquetas que correspondan al cliente. Las etiquetas pueden ser incluidas en las reglas de filtrado y te permiten aplicarlas con mayor precisión. <0>Más información", + "tags_desc": "Puedes seleccionar las etiquetas que correspondan al cliente. Las etiquetas pueden ser incluidas en las reglas de filtrado y te permiten aplicarlas con mayor precisión. <0>Más información", "form_select_tags": "Seleccione las etiquetas del cliente", "check_title": "Comprobar filtrado", "check_desc": "Comprueba si el nombre del host está siendo filtrado", @@ -502,8 +509,8 @@ "static_ip_desc": "AdGuard Home es un servidor, por lo que necesita una dirección IP estática para funcionar correctamente. De lo contrario, en algún momento tu router puede asignar una dirección IP diferente a este dispositivo.", "set_static_ip": "Establecer una dirección IP estática", "install_static_ok": "¡Buenas noticias! La dirección IP estática ya está configurada", - "install_static_error": "AdGuard Home no puede configurarlo automáticamente para esta interfaz de red. Busque instrucciones sobre cómo hacer esto manualmente.", - "install_static_configure": "Hemos detectado que utiliza una dirección IP dinámica: <0>{{ip}}. ¿Deseas usarla como tu dirección estática?", + "install_static_error": "AdGuard Home no puede configurarlo automáticamente para esta interfaz de red. Busca instrucciones sobre cómo hacer esto manualmente.", + "install_static_configure": "Hemos detectado que utilizas una dirección IP dinámica: <0>{{ip}}. ¿Deseas usarla como tu dirección estática?", "confirm_static_ip": "AdGuard Home configurará {{ip}} para ser tu dirección IP estática. ¿Desea continuar?", "list_updated": "{{count}} lista actualizada", "list_updated_plural": "{{count}} listas actualizadas", diff --git a/client/src/__locales/fa.json b/client/src/__locales/fa.json index 5e198b75..cca1665f 100644 --- a/client/src/__locales/fa.json +++ b/client/src/__locales/fa.json @@ -65,7 +65,6 @@ "filters": "فيلترها", "filter": "فیلتر", "query_log": "جستار وقایع", - "empty_log": "وقایع جستار خالی است", "faq": "پرسش و پاسخ", "version": "نسخه", "address": "آدرس", diff --git a/client/src/__locales/fr.json b/client/src/__locales/fr.json index 82ce9940..cecb3842 100644 --- a/client/src/__locales/fr.json +++ b/client/src/__locales/fr.json @@ -57,6 +57,7 @@ "delete_confirm": "Voulez-vous vraiment supprimer \"{{key}}\" ?", "form_enter_hostname": "Saisissez un nom d'hôte", "error_details": "Détails des erreurs", + "response_details": "Détails de la réponse", "request_details": "Demander des détails", "client_details": "Détails du client", "details": "Détails", @@ -66,7 +67,6 @@ "filters": "Filtres", "filter": "Filtre", "query_log": "Journal des requêtes", - "empty_log": "Le journal des requêtes est vide", "faq": "FAQ", "version": "version", "address": "Addresse", @@ -228,6 +228,7 @@ "blocking_ipv6": "Blocage IPv6", "dns_over_https": "DNS-over-HTTPS", "dns_over_tls": "DNS-over-TLS", + "plain_dns": "DNS brut", "form_enter_rate_limit": "Entrez la limite de taux", "rate_limit": "Limite de taux", "edns_enable": "Activer le sous-réseau du client EDNS", diff --git a/client/src/__locales/hr.json b/client/src/__locales/hr.json index a0fbbecd..b1482a06 100644 --- a/client/src/__locales/hr.json +++ b/client/src/__locales/hr.json @@ -3,6 +3,8 @@ "example_upstream_reserved": "VI možete odrediti DNS upstream-ove <0>za određene domene", "upstream_parallel": "Koristi paralelne upite kako bi ubrzali rješavanje istovremenim ispitavanjem svih upstream poslužitelja", "parallel_requests": "Paralelni zahtjevi", + "load_balancing": "Load-balancing", + "load_balancing_desc": "Šaljite upite po jednom poslužitelju u isto vrijeme. AdGuard Home će koristiti ponderirani slučajni algoritam za odabir poslužitelja, tako da će se najbrži poslužitelj češće koristiti.", "bootstrap_dns": "Bootstrap DNS poslužitelji", "bootstrap_dns_desc": "Bootstrap DNS poslužitelji koriste se za rezolvanje IP adresa DoH/DoT rezolvera koje navedete kao upstreams.", "check_dhcp_servers": "Provjera DHCP poslužitelja", @@ -51,9 +53,11 @@ "dhcp_add_static_lease": "Dodaj static lease", "dhcp_reset": "Jeste li sigurni da želite poništiti DHCP postavke?", "country": "Država", + "city": "Grad", "delete_confirm": "Jeste li sigurni da želite ukloniti \"{{key}}\"?", "form_enter_hostname": "Unesite naziv računala", "error_details": "Detalji o pogrešci", + "response_details": "Detalji odgovora", "request_details": "Detalji zahtjeva", "client_details": "Detalji o klijentu", "details": "Detalji", @@ -63,7 +67,8 @@ "filters": "Filtri", "filter": "Filtar", "query_log": "Zapisnik upita", - "empty_log": "Zapisik upita je prazan", + "compact": "Kompaktno", + "nothing_found": "Nema rezultata", "faq": "ČPP", "version": "Verzija", "address": "Adresa", @@ -188,6 +193,7 @@ "domain_or_client": "Domena ili klijent", "type_table_header": "Vrsta", "response_table_header": "Odgovor", + "response_code": "Responzivni kod", "client_table_header": "Klijent", "empty_response_status": "Prazno", "show_all_filter_type": "Prikaži sve", @@ -206,6 +212,7 @@ "query_log_filtered": "Filtrirao {{filter}}", "query_log_confirm_clear": "Jeste li sigurni da želite ukloniti zapise upita?", "query_log_cleared": "Zapisnik upita je uspješno uklonjen", + "query_log_updated": "Zapisnik upita je uspješno ažuriran", "query_log_clear": "Očisti zapisnik upita", "query_log_retention": "Spremanje zapisnika upita", "query_log_enable": "Omogući zapise", @@ -225,6 +232,7 @@ "blocking_ipv6": "Blokiranje IPv6", "dns_over_https": "DNS-over-HTTPS", "dns_over_tls": "DNS-over-TLS", + "plain_dns": "Obični DNS", "form_enter_rate_limit": "Unesite ograničenje", "rate_limit": "Ograničenje", "edns_enable": "Omogući EDNS Client Subnet", @@ -237,6 +245,7 @@ "blocking_mode_null_ip": "Nuliran IP: Odgovor s nuliranom IP adresom (0.0.0.0 za A; :: za AAAA)", "blocking_mode_custom_ip": "Prilagođeni IP: Odgovor s ručno postavljenom IP adresom", "upstream_dns_client_desc": "Ako ovo polje ostane prazno, AdGuard Home će upotrijebiti poslužitelje postavljene u <0>DNS postavkama.", + "tracker_source": "Izvor pratitelja", "source_label": "Izvor", "found_in_known_domain_db": "Pronađeno u bazi poznatih domena.", "category_label": "Kategorija", diff --git a/client/src/__locales/id.json b/client/src/__locales/id.json index 512879f5..43e359c3 100644 --- a/client/src/__locales/id.json +++ b/client/src/__locales/id.json @@ -37,6 +37,7 @@ "dhcp_interface_select": "Pilih antarmuka DHCP", "dhcp_hardware_address": "Alamat perangkat keras", "dhcp_ip_addresses": "Alamat IP", + "ip": "IP", "dhcp_table_hostname": "Nama host", "dhcp_table_expires": "Kadaluwarsa", "dhcp_warning": "Jika anda ingin mengaktifkan server DHCP bawaan, pastikan tidak ada server DHCP lain yang aktif. Jika tidak, akan memutus koneksi internet pada perangkat yang telah terhubung!", @@ -49,14 +50,18 @@ "dhcp_static_leases_not_found": "DHCP static lease tidak ditemukan", "dhcp_add_static_lease": "Tambah static lease", "dhcp_reset": "Apakah anda yakin ingin mengatur ulang konfigurasi DHCP anda?", + "country": "Negara", "delete_confirm": "Apakah anda yakin ingin menghapus \"{{key}}\"?", "form_enter_hostname": "Masukkan hostname", "error_details": "Detail kesalahan", "request_details": "Detai permintaan", + "client_details": "Detail klien", + "details": "Detail", "back": "Kembali", "dashboard": "Beranda", "settings": "Pengaturan", "filters": "Penyaring", + "filter": "Filter", "query_log": "Catatan Kueri", "faq": "Tanya Jawab", "version": "versi", @@ -129,8 +134,10 @@ "rules_count_table_header": "Jumlah Aturan", "last_time_updated_table_header": "Terakhir diperbaharui", "actions_table_header": "Aksi", + "request_table_header": "Permintaan", "edit_table_action": "Ubah", "delete_table_action": "Hapus", + "elapsed": "Berlalu", "filters_and_hosts_hint": "AdGuard Home memahami aturan dasar adblock dan sintak file hosts.", "cancel_btn": "Batal", "enter_name_hint": "Masukkan nama", @@ -160,6 +167,7 @@ "time_table_header": "Waktu", "date": "Tanggal", "domain_name_table_header": "Nama domain", + "domain_or_client": "Domain atau klien", "type_table_header": "Tipe", "response_table_header": "Respon", "client_table_header": "Klien", @@ -191,6 +199,8 @@ "default": "Standar", "blocking_ipv4": "Blokiran IPv4", "blocking_ipv6": "Blokiran IPv6", + "dns_over_https": "DNS-over-HTTPS", + "dns_over_tls": "DNS-over-TLS", "edns_cs_desc": "Apabila dinyalakan, AdGuard Home akan mengirim subnet klien ke server-server DNS.", "rate_limit_desc": "Jumlah permintaan per detik yang diperbolehkan untuk satu klien (0: tidak terbatas)", "blocking_mode_custom_ip": "IP kustom: respon dengan alamat IP yang diset secara manual", @@ -199,6 +209,7 @@ "category_label": "Kategori", "rule_label": "Aturan", "unknown_filter": "Penyaringan {{filterId}} tidak dikenal", + "known_tracker": "Pelacak yang dikenal", "install_welcome_title": "Selamat datang di AdGuard Home!", "install_welcome_desc": "AdGuard Home adalah sebuah server DNS pemblokiran iklan dan pelacak di jaringan. Tujuannya adalah memungkinkan anda mengkontrol seluruh jaringan dan semua perangkat anda, dan ini tidak membutuhkan aplikasi tambahan di klien", "install_settings_title": "Antarmuka Halaman Admin", @@ -314,6 +325,7 @@ "form_enter_ip": "Masukkan IP", "form_enter_mac": "Masukkan MAC", "form_client_name": "Masukkan nama klien", + "name": "Nama", "client_global_settings": "Gunakan pengaturan global", "client_deleted": "Klien \"{{key}}\" berhasil dihapus", "client_added": "Klien \"{{key}}\" berhasil ditambahkan", @@ -411,6 +423,7 @@ "location": "Lokasi", "orgname": "Nama organisasi", "netname": "Nama jaringan", + "network": "Jaringan", "descr": "Deskripsi", "whois": "Whois", "filtering_rules_learn_more": "<0>Pelajari lebih lanjut tentang membuat daftar hitam host Anda sendiri.", @@ -432,5 +445,13 @@ "client_confirm_unblock": "Apa anda yakin ingin meng-unblock klien ini \"{{ip}}\"?", "client_blocked": "Klien \"{{ip}}\" sukses di blokir", "client_unblocked": "Klien \"{{ip}}\" sukses di unblock", - "static_ip": "Alamat IP statis" + "static_ip": "Alamat IP statis", + "validated_with_dnssec": "Tervalidasi dengan DNSSEC", + "show_all_responses": "Semua respon", + "show_blocked_responses": "Diblokir", + "show_whitelisted_responses": "Dalam Daftar Putih", + "show_processed_responses": "Terproses", + "safe_search": "Pencarian aman", + "blocklist": "Daftar blokir", + "milliseconds_abbreviation": "ms" } \ No newline at end of file diff --git a/client/src/__locales/it.json b/client/src/__locales/it.json index d317a081..044af3c5 100644 --- a/client/src/__locales/it.json +++ b/client/src/__locales/it.json @@ -53,9 +53,11 @@ "dhcp_add_static_lease": "Aggiungi lease statico", "dhcp_reset": "Sei sicuro di voler ripristinare la configurazione DHCP?", "country": "Regione", + "city": "Città", "delete_confirm": "Sei sicuro di voler cancellare \"{{key}}\"?", "form_enter_hostname": "Inserisci hostname", "error_details": "Dettagli errore", + "response_details": "Dettagli di Risposta", "request_details": "Dettagli della richiesta", "client_details": "Dettagli client", "details": "Dettagli", @@ -65,7 +67,6 @@ "filters": "Filtri", "filter": "Filtro", "query_log": "Query Log", - "empty_log": "Il log query è vuoto", "faq": "FAQ", "version": "versione", "address": "Indirizzo", @@ -227,6 +228,7 @@ "blocking_ipv6": "Blocca IPv6", "dns_over_https": "DNS-over-HTTPS", "dns_over_tls": "DNS-over-TLS", + "plain_dns": "DNS semplice", "form_enter_rate_limit": "Imposta limite delle richieste", "rate_limit": "Limite delle richieste", "edns_enable": "Abilita client di sottorete EDNS", diff --git a/client/src/__locales/ja.json b/client/src/__locales/ja.json index d88fc067..8a3cc3b6 100644 --- a/client/src/__locales/ja.json +++ b/client/src/__locales/ja.json @@ -67,7 +67,8 @@ "filters": "フィルタ", "filter": "フィルタ", "query_log": "クエリ・ログ", - "empty_log": "クエリ・ログは空です", + "compact": "コンパクト", + "nothing_found": "何も見つかりません", "faq": "よくある質問", "version": "バージョン", "address": "アドレス", @@ -192,6 +193,7 @@ "domain_or_client": "ドメインまたはクライアント", "type_table_header": "種類", "response_table_header": "応答", + "response_code": "応答コード", "client_table_header": "クライアント", "empty_response_status": "未定義", "show_all_filter_type": "すべて表示", @@ -210,6 +212,7 @@ "query_log_filtered": "{{filter}}によるフィルタ", "query_log_confirm_clear": "クエリ・ログ全体を消去してもよろしいですか?", "query_log_cleared": "クエリ・ログの消去に成功しました", + "query_log_updated": "クエリ・ログの更新が成功しました", "query_log_clear": "クエリ・ログを消去する", "query_log_retention": "クエリ・ログの保持", "query_log_enable": "ログを有効にする", @@ -242,6 +245,7 @@ "blocking_mode_null_ip": "Null IP:ゼロのIPアドレスで応答します(Aの場合は0.0.0.0; AAAAの場合は::)", "blocking_mode_custom_ip": "カスタムIP:手動で設定されたIPアドレスで応答します", "upstream_dns_client_desc": "このフィールドを未入力のままにすると、AdGuard Homeは<0>DNS設定で構成されたサーバを使用します。", + "tracker_source": "追跡元", "source_label": "ソース", "found_in_known_domain_db": "既知のドメインデータベースに見つかりました。", "category_label": "カテゴリ", diff --git a/client/src/__locales/ko.json b/client/src/__locales/ko.json index bc6f4e3d..9e363e13 100644 --- a/client/src/__locales/ko.json +++ b/client/src/__locales/ko.json @@ -3,6 +3,8 @@ "example_upstream_reserved": "<0>특정 도메인에 대한 DNS 업스트림을 지정할 수 있습니다.", "upstream_parallel": "쿼리 처리 속도를 높이려면 모든 업스트림 서버에서 동시에 병렬 쿼리를 사용해주세요.", "parallel_requests": "병렬 처리 요청", + "load_balancing": "로드 밸런싱", + "load_balancing_desc": "한 번에 하나의 서버씩 질의합니다. AdGuard Home은 가중 랜덤 알고리즘를 사용해서 가장 빠른 서버가 자주 사용되도록 서버를 선택합니다.", "bootstrap_dns": "부트스트랩 DNS 서버", "bootstrap_dns_desc": "부트스트랩 DNS 서버는 업스트림으로 지정한 DoH/DoT 서버의 IP 주소를 확인하는 데 사용합니다.", "check_dhcp_servers": "DHCP 서버 체크", @@ -51,9 +53,11 @@ "dhcp_add_static_lease": "고정 임대 추가", "dhcp_reset": "정말로 DHCP 설정을 초기화할까요?", "country": "지역", + "city": "도시", "delete_confirm": "\"{{key}}\"을 삭제하시겠습니까?", "form_enter_hostname": "호스트 이름을 입력해주세요", "error_details": "오류 상세 정보", + "response_details": "응답 정보", "request_details": "요청 세부 사항", "client_details": "클라이언트 정보", "details": "정보", @@ -63,7 +67,8 @@ "filters": "필터", "filter": "필터", "query_log": "쿼리 로그", - "empty_log": "질의 로그가 비어있음", + "compact": "콤팩트", + "nothing_found": "아무것도 찾을 수 없습니다", "faq": "자주 묻는 질문", "version": "버전", "address": "주소", @@ -188,6 +193,7 @@ "domain_or_client": "도메인 또는 클라이언트", "type_table_header": "유형", "response_table_header": "응답", + "response_code": "응답 코드", "client_table_header": "클라이언트", "empty_response_status": "비어있음", "show_all_filter_type": "모두 표시", @@ -206,6 +212,7 @@ "query_log_filtered": "필터: {{filter}}", "query_log_confirm_clear": "정말로 모든 쿼리 로그를 비우시겠습니까?", "query_log_cleared": "쿼리 로그를 성공적으로 초기화했습니다", + "query_log_updated": "질의 로그가 성공적으로 업데이트되었습니다", "query_log_clear": "쿼리 로그 비우기", "query_log_retention": "쿼리 로그 저장 기간", "query_log_enable": "로그 활성화", @@ -225,6 +232,7 @@ "blocking_ipv6": "IPv6 차단", "dns_over_https": "DNS-over-HTTPS", "dns_over_tls": "DNS-over-TLS", + "plain_dns": "평문 DNS", "form_enter_rate_limit": "한도 제한 입력하기", "rate_limit": "한도 제한", "edns_enable": "EDNS 클라이언트 서브넷 활성화", @@ -237,6 +245,7 @@ "blocking_mode_null_ip": "Null IP: 제로 IP 주소 (A는 0.0.0.0; AAAA는 ::) 로 응답합니다", "blocking_mode_custom_ip": "커스텀 IP: 직접 설정한 IP 주소로 응답합니다", "upstream_dns_client_desc": "이 값을 비워둔다면 AdGuard Home은 <0>DNS 설정에 설정되어 있는 값을 사용합니다.", + "tracker_source": "추적기 소스", "source_label": "소스", "found_in_known_domain_db": "알려진 도메인 데이터베이스에서 발견됨.", "category_label": "카테고리", diff --git a/client/src/__locales/nl.json b/client/src/__locales/nl.json index 5b6bbf38..05b3f7d4 100644 --- a/client/src/__locales/nl.json +++ b/client/src/__locales/nl.json @@ -66,7 +66,8 @@ "filters": "Filters", "filter": "Filter", "query_log": "Query log", - "empty_log": "Logboek leeg", + "compact": "Compact", + "nothing_found": "Niets gevonden", "faq": "Veel gestelde vragen", "version": "Versie", "address": "Adres", @@ -191,6 +192,7 @@ "domain_or_client": "Domein of cliënt", "type_table_header": "Type", "response_table_header": "Antwoord", + "response_code": "Reactie code", "client_table_header": "Gebruiker", "empty_response_status": "Leeg", "show_all_filter_type": "Toon alles", @@ -209,6 +211,7 @@ "query_log_filtered": "Gefilterd door {{filter}}", "query_log_confirm_clear": "Weet u zeker dat u het hele query logboek wilt legen?", "query_log_cleared": "Het query logboek is succesvol geleegd", + "query_log_updated": "Het query logboek is succesvol bijgewerkt", "query_log_clear": "Leeg query logs", "query_log_retention": "Query logs bewaartermijn", "query_log_enable": "Log bestanden inschakelen", @@ -222,6 +225,8 @@ "custom_ip": "Aangepast IP", "dns_over_https": "DNS-via-HTTPS", "dns_over_tls": "DNS-via-TLS", + "plain_dns": "Gewone DNS", + "tracker_source": "Bron volger", "source_label": "Bron", "found_in_known_domain_db": "Gevonden in de bekende domeingegevensbank.", "category_label": "Categorie", @@ -474,6 +479,7 @@ "show_blocked_responses": "Geblokkeerd", "show_whitelisted_responses": "Op toestemmingslijst", "show_processed_responses": "Verwerkt", + "blocked_safebrowsing": "Geblokkeerd door Veilig Browsen", "blocked_adult_websites": "Geblokkeerde 18+ websites", "blocked_threats": "Geblokkeerde bedreigingen", "allowed": "Toegestaan", diff --git a/client/src/__locales/pl.json b/client/src/__locales/pl.json index db23df06..1744d8dc 100644 --- a/client/src/__locales/pl.json +++ b/client/src/__locales/pl.json @@ -3,6 +3,8 @@ "example_upstream_reserved": "możesz określić serwer DNS <0>dla konkretnych domen", "upstream_parallel": "Używaj równoległych żądań, aby przyspieszyć rozwiązywanie adresów domen, jednocześnie wysyłając zapytania do wszystkich głównych serwerów DNS", "parallel_requests": "Równoległe żądania", + "load_balancing": "Równoważenie obciążenia", + "load_balancing_desc": "Zapytaj jeden serwer na raz. AdGuard Home wykorzysta losowy algorytm, aby użyć najczęściej najszybszego serwera.", "bootstrap_dns": "Serwery DNS Bootstrap", "bootstrap_dns_desc": "Serwery DNS Bootstrap są używane do ustalenia adresu IP serwerów DoH/DoT, które oznaczysz jako główne serwery DNS.", "check_dhcp_servers": "Sprawdź serwery DHCP", @@ -55,6 +57,8 @@ "delete_confirm": "Czy na pewno chcesz usunąć \"{{key}}\"?", "form_enter_hostname": "Wpisz nazwę hosta", "error_details": "Szczegóły błędu", + "response_details": "Szczegóły odpowiedzi", + "request_details": "Szczegóły żądania", "client_details": "Szczegóły klienta", "details": "Szczegóły", "back": "Wróć", @@ -63,10 +67,11 @@ "filters": "Filtry", "filter": "Filtr", "query_log": "Dziennik zapytań", - "empty_log": "Dziennik zapytań jest pusty", + "nothing_found": "Nic nie znaleziono", "faq": "FAQ", "version": "wersja", "address": "Adres", + "protocol": "Protokół", "on": "WŁĄCZONY", "off": "WYŁĄCZONY", "copyright": "Prawo autorskie", @@ -187,6 +192,7 @@ "domain_or_client": "Domena lub klient", "type_table_header": "Typ", "response_table_header": "Odpowiedź ", + "response_code": "Kod odpowiedzi", "client_table_header": "Klient", "empty_response_status": "Pusty", "show_all_filter_type": "Pokaż wszystko", @@ -224,6 +230,7 @@ "blocking_ipv6": "Blokowanie IPv6", "dns_over_https": "DNS-over-HTTPS", "dns_over_tls": "DNS-over-TLS", + "plain_dns": "Zwykły DNS", "form_enter_rate_limit": "Wpisz limit ilościowy", "rate_limit": "Limit ilościowy", "edns_enable": "Włącz podsieć klienta EDNS", diff --git a/client/src/__locales/pt-br.json b/client/src/__locales/pt-br.json index 86c9dd7c..dc813864 100644 --- a/client/src/__locales/pt-br.json +++ b/client/src/__locales/pt-br.json @@ -3,6 +3,8 @@ "example_upstream_reserved": "Você pode especificar o DNS upstream <0>para o domínio(s) especifico", "upstream_parallel": "Usar consultas paralelas para acelerar a resolução consultando simultaneamente todos os servidores upstream", "parallel_requests": "Solicitações paralelas", + "load_balancing": "Balanceamento de carga", + "load_balancing_desc": "Consulta um servidor de cada vez. O AdGuard Home usará o algoritmo aleatório ponderado para escolher o servidor, para que o servidor mais rápido seja usado com mais frequência.", "bootstrap_dns": "Servidores DNS de inicialização", "bootstrap_dns_desc": "Servidores DNS de inicialização são usados para resolver endereços IP dos resolvedores DoH/DoT que você especifica como upstreams.", "check_dhcp_servers": "Verificar por servidores DHCP", @@ -51,9 +53,12 @@ "dhcp_add_static_lease": "Adicionar nova concessão estática", "dhcp_reset": "Você tem certeza de que deseja redefinir a configuração DHCP?", "country": "País", + "city": "Cidade", "delete_confirm": "Você tem certeza de que deseja excluir \"{{key}}\"?", "form_enter_hostname": "Digite o hostname", "error_details": "Detalhes do erro", + "response_details": "Detalhes da resposta", + "request_details": "Detalhes da solicitação", "client_details": "Detalhes do cliente", "details": "Detalhes", "back": "Voltar", @@ -62,10 +67,10 @@ "filters": "Filtros", "filter": "Filtro", "query_log": "Registro de consultas", - "empty_log": "O registro de consulta está vazio", "faq": "FAQ", "version": "Versão", "address": "Endereço", + "protocol": "Protocolo", "on": "Ligado", "off": "Desligado", "copyright": "Copyright", @@ -223,6 +228,7 @@ "blocking_ipv6": "Bloqueando IPv6", "dns_over_https": "DNS-sobre-HTTPS", "dns_over_tls": "DNS-sobre-TLS", + "plain_dns": "DNS simples", "form_enter_rate_limit": "Insira a taxa limite", "rate_limit": "Taxa limite", "edns_enable": "Ativar a sub-rede do cliente EDNS", diff --git a/client/src/__locales/ro.json b/client/src/__locales/ro.json index 747f9c04..39d62d6c 100644 --- a/client/src/__locales/ro.json +++ b/client/src/__locales/ro.json @@ -53,9 +53,12 @@ "dhcp_add_static_lease": "Adăugați închiriere statică", "dhcp_reset": "Sunteți sigur că doriți să resetați configurația DHCP?", "country": "Țara", + "city": "Oraș", "delete_confirm": "Sunteți sigur că doriți să ștergeți \"{{key}}\"?", "form_enter_hostname": "Intrați hostname", "error_details": "Detalii eroare", + "response_details": "Detalii răspuns", + "request_details": "Detalii solicitare", "client_details": "Detalii client", "details": "Detalii", "back": "Înapoi", @@ -64,10 +67,12 @@ "filters": "Filtre", "filter": "Filtru", "query_log": "Jurnal interogări", - "empty_log": "Jurnal de interogări gol", + "compact": "Compact", + "nothing_found": "Nu s-a găsit nimic", "faq": "FAQ", "version": "Versiune", "address": "Adresă", + "protocol": "Protocol", "on": "ON", "off": "OFF", "copyright": "Copyright", @@ -188,6 +193,7 @@ "domain_or_client": "Domeniu sau client", "type_table_header": "Tip", "response_table_header": "Răspuns", + "response_code": "Cod de răspuns", "client_table_header": "Client", "empty_response_status": "Gol", "show_all_filter_type": "Arată tot", @@ -206,6 +212,7 @@ "query_log_filtered": "Filtrat de {{filter}}", "query_log_confirm_clear": "Sunteți sigur că doriți să ștergeți întregul jurnal de interogări?", "query_log_cleared": "Jurnalul de interogare a fost șters cu succes", + "query_log_updated": "Jurnalul de solicitări a fost actualizat cu succes", "query_log_clear": "Curăță jurnalele", "query_log_retention": "Retenție jurnale interogare", "query_log_enable": "Activați jurnal", @@ -225,6 +232,7 @@ "blocking_ipv6": "Blocarea IPv6", "dns_over_https": "DNS-over-HTTPS", "dns_over_tls": "DNS-over-TLS", + "plain_dns": "DNS simplu", "form_enter_rate_limit": "Intrați limita ratei", "rate_limit": "Limita ratei", "edns_enable": "Activați clientul subnet EDNS", @@ -237,6 +245,7 @@ "blocking_mode_null_ip": "IP nul: răspunde cu o adresă IP zero (0.0.0.0 pentru A; :: pentru AAAA)", "blocking_mode_custom_ip": "IP personalizat: răspunde cu o adresă IP setată manual", "upstream_dns_client_desc": "Dacă mențineți acest câmp gol, AdGuard Home va folosi serverele configurate în <0>setările DNS.", + "tracker_source": "Sursă tracker", "source_label": "Sursă", "found_in_known_domain_db": "Găsit în baza de date de domenii cunoscută.", "category_label": "Categorie", @@ -272,7 +281,7 @@ "install_devices_router_list_1": "Deschideți preferințele pentru routerul dvs. De obicei, îl puteți accesa din browserul dvs. printr-o adresă URL (cum ar fi http://192.168.0.1/ sau http://192.168.1.1/). Vi se poate cere să intrați parola. Dacă nu v-o amintiți, puteți reseta adesea parola apăsând un buton de pe routerul propriu-zis. Unele routere necesită o aplicație specifică, care în acest caz ar trebui să fie deja instalată pe computerul/telefonul dvs.", "install_devices_router_list_2": "Găsiți setările DHCP/DNS. Căutați literele DNS lângă un câmp care să permită două sau trei seturi de numere, fiecare împărțit în patru grupuri de una până la trei cifre.", "install_devices_router_list_3": "Intrați adresele serverului dvs. AdGuard Home aici.", - "install_devices_router_list_4": "Unele routere nu permit setarea unui server DNS personalizat. În acest caz, vă poate ajuta dacă configurați AdGuard Home ca <0>server DHCP. Dacă nu, trebuie căutat manualul modelului dvs. de router ca să aflați cum se pot personaliza serverele DNS.", + "install_devices_router_list_4": "Unele routere nu permit setarea unui server DNS personalizat. În acest caz, vă poate ajuta dacă ați configura AdGuard Home ca <0>server DHCP. Dacă nu, trebuie căutat manualul modelului dvs. de router ca să aflați cum se pot personaliza serverele DNS.", "install_devices_windows_list_1": "Deschideți panoul de control prin meniul Start sau căutare Windows.", "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.", diff --git a/client/src/__locales/ru.json b/client/src/__locales/ru.json index d0f3d1cf..2d247261 100644 --- a/client/src/__locales/ru.json +++ b/client/src/__locales/ru.json @@ -3,6 +3,8 @@ "example_upstream_reserved": "Вы можете указать DNS-сервер <0>для конкретного домена(-ов)", "upstream_parallel": "Использовать параллельные запросы ко всем серверам одновременно для ускорения обработки запроса", "parallel_requests": "Параллельные запросы", + "load_balancing": "Распределение нагрузки\n", + "load_balancing_desc": "Запрашивайте по одному серверу за раз. AdGuard Home будет использовать случайный алгоритм для выбора сервера, так что самый быстрый сервер будет использоваться чаще.", "bootstrap_dns": "Bootstrap DNS-серверы", "bootstrap_dns_desc": "Bootstrap DNS-серверы используются для поиска IP-адресов DoH/DoT серверов, которые вы указали.", "check_dhcp_servers": "Проверить DHCP-серверы", @@ -37,6 +39,7 @@ "dhcp_interface_select": "Выбрать интерфейс DHCP", "dhcp_hardware_address": "Аппаратный адрес", "dhcp_ip_addresses": "IP-адреса", + "ip": "IP-адрес", "dhcp_table_hostname": "Имя хоста", "dhcp_table_expires": "Истекает", "dhcp_warning": "Если вы все равно хотите включить DHCP-сервер, убедитесь, что в сети больше нет активных DHCP-серверов. Иначе это может сломать доступ в сеть для подключенных устройств!", @@ -49,17 +52,27 @@ "dhcp_static_leases_not_found": "Не найдено статических аренд DHCP", "dhcp_add_static_lease": "Добавить статическую аренду", "dhcp_reset": "Вы уверены, что хотите сбросить настройки DHCP?", + "country": "Страна", + "city": "Город", "delete_confirm": "Are you sure you want to delete \"{{key}}\"?", "form_enter_hostname": "Введите имя хоста", "error_details": "Детализация ошибки", + "response_details": "Детали ответа", + "request_details": "Детали запроса", + "client_details": "Информация о клиенте", + "details": "Детали", "back": "Назад", "dashboard": "Панель управления", "settings": "Настройки", "filters": "Фильтры", + "filter": "Фильтр", "query_log": "Журнал", + "compact": "Компактный", + "nothing_found": "Ничего не найдено", "faq": "FAQ", "version": "версия", "address": "Адрес", + "protocol": "Протокол", "on": "Вкл", "off": "Выкл", "copyright": "Все права защищены", @@ -132,8 +145,10 @@ "rules_count_table_header": "Количество правил:", "last_time_updated_table_header": "Последнее обновление", "actions_table_header": "Действия", + "request_table_header": "Запрос", "edit_table_action": "Редактировать", "delete_table_action": "Удалить", + "elapsed": "Затрачено", "filters_and_hosts_hint": "AdGuard Home распознает базовые правила блокировки и синтаксис файлов hosts.", "no_blocklist_added": "Черные списки не добавлены", "no_whitelist_added": "Белые списки не добавлены", @@ -175,8 +190,10 @@ "time_table_header": "Время", "date": "Дата", "domain_name_table_header": "Домен", + "domain_or_client": "Домен или клиент", "type_table_header": "Тип", "response_table_header": "Ответ", + "response_code": "Код ответа", "client_table_header": "Клиент", "empty_response_status": "Пусто", "show_all_filter_type": "Показать все", @@ -195,6 +212,7 @@ "query_log_filtered": "Отфильтровано с помощью {{filter}}", "query_log_confirm_clear": "Вы уверены, что хотите очистить весь журнал запросов?", "query_log_cleared": "Журнал запросов успешно очищен", + "query_log_updated": "Журнал запросов успешно обновлен", "query_log_clear": "Очистить журнал запросов", "query_log_retention": "Сохранение журнала запросов", "query_log_enable": "Включить журнал", @@ -212,6 +230,9 @@ "custom_ip": "Свой IP", "blocking_ipv4": "Блокировка IPv4", "blocking_ipv6": "Блокировка IPv6", + "dns_over_https": "DNS-over-HTTPS", + "dns_over_tls": "DNS-over-TLS", + "plain_dns": "Нешифрованный DNS", "form_enter_rate_limit": "Введите rate limit", "rate_limit": "Rate limit", "edns_enable": "Включить отправку EDNS Client Subnet", @@ -224,12 +245,14 @@ "blocking_mode_null_ip": "Нулевой IP: Отвечает с нулевым IP-адресом (0.0.0.0 для A; :: для AAAA)", "blocking_mode_custom_ip": "Пользовательский IP: Отвечает с вручную настроенным IP-адресом", "upstream_dns_client_desc": "Если оставить поле пустым, AdGuard Home будет обращаться к серверам, указанным в <0>настройках DNS.", + "tracker_source": "Источник трекинга", "source_label": "Источник", "found_in_known_domain_db": "Найден в базе известных доменов.", "category_label": "Категория", "rule_label": "Правило", "list_label": "Список", "unknown_filter": "Неизвестный фильтр {{filterId}}", + "known_tracker": "Известный трекер", "install_welcome_title": "Добро пожаловать в AdGuard Home!", "install_welcome_desc": "AdGuard Home – это DNS-сервер, блокирующий рекламу и трекинг. Его цель – дать вам возможность контролировать всю вашу сеть и все подключенные устройства. Он не требует установки клиентских программ.", "install_settings_title": "Веб-интерфейс администрирования", @@ -347,6 +370,7 @@ "form_enter_id": "Введите идентификатор", "form_add_id": "Добавить идентификатор", "form_client_name": "Введите имя клиента", + "name": "Имя", "client_global_settings": "Использовать глобальные настройки", "client_deleted": "Клиент \"{{key}}\" успешно удален", "client_added": "Клиент \"{{key}}\" успешно добавлен", @@ -446,6 +470,7 @@ "location": "Местоположение", "orgname": "Название организации", "netname": "Название сети", + "network": "Сеть", "descr": "Описание", "whois": "Whois", "filtering_rules_learn_more": "<0>Узнайте больше о создании собственных списков блокировки хостов.", @@ -491,8 +516,18 @@ "list_updated_plural": "Обновлено списков: {{count}}", "dnssec_enable": "Включить DNSSEC", "dnssec_enable_desc": "Установите флаг DNSSEC в исходящих DNS-запросах и проверьте результат (требуется резолвер с поддержкой DNSSEC)", + "validated_with_dnssec": "Подтверждено с помощью DNSSEC", + "show_all_responses": "Все ответы", "show_blocked_responses": "Blocked", + "show_whitelisted_responses": "В белом списке", + "show_processed_responses": "Обработан", + "blocked_safebrowsing": "Заблокировано согласно базе данных Safebrowsing", "blocked_adult_websites": "Заблокированные \"взрослые\" сайты", "blocked_threats": "Заблокировано угроз", - "blocklist": "Черный список" + "allowed": "Разрешенные", + "filtered": "Отфильтрованные", + "rewritten": "Переписанные", + "safe_search": "Безопасный поиск", + "blocklist": "Черный список", + "milliseconds_abbreviation": "мс" } \ No newline at end of file diff --git a/client/src/__locales/sk.json b/client/src/__locales/sk.json index 7d956d0f..8a31d5fa 100644 --- a/client/src/__locales/sk.json +++ b/client/src/__locales/sk.json @@ -53,9 +53,12 @@ "dhcp_add_static_lease": "Pridať statický prenájom", "dhcp_reset": "Naozaj chcete obnoviť konfiguráciu DHCP?", "country": "Krajina", + "city": "Mesto", "delete_confirm": "Naozaj chcete vymazať \"{{key}}\"?", "form_enter_hostname": "Zadajte meno hostiteľa", "error_details": "Podrobnosti chyby", + "response_details": "Podrobnosti odpovede", + "request_details": "Podrobnosti požiadavky", "client_details": "Podrobnosti klienta", "details": "Podrobnosti", "back": "Naspäť", @@ -64,10 +67,12 @@ "filters": "Filtre", "filter": "Filter", "query_log": "Denník dopytov", - "empty_log": "Denník dopytov je prázdny", + "compact": "Kompaktný", + "nothing_found": "Nič sa nenašlo", "faq": "FAQ", "version": "Verzia", "address": "Adresa", + "protocol": "Protokol", "on": "ZAP.", "off": "VYP.", "copyright": "Copyright", @@ -188,6 +193,7 @@ "domain_or_client": "Doména alebo klient", "type_table_header": "Typ", "response_table_header": "Odozva", + "response_code": "Kód odozvy", "client_table_header": "Klient", "empty_response_status": "Vyčistiť", "show_all_filter_type": "Zobraziť všetko", @@ -206,6 +212,7 @@ "query_log_filtered": "Vyfiltrované pomocou {{filter}}", "query_log_confirm_clear": "Naozaj chcete vymazať celý denník dopytov?", "query_log_cleared": "Denník dopytov bol úspešne vymazaný", + "query_log_updated": "Denník dopytov bol úspešne aktualizovaný", "query_log_clear": "Vymazať denníky dopytov", "query_log_retention": "Obdobie záznamu denníka dopytov", "query_log_enable": "Zapnúť denník", @@ -225,6 +232,7 @@ "blocking_ipv6": "Blokovanie IPv6", "dns_over_https": "DNS-over-HTTPS", "dns_over_tls": "DNS-over-TLS", + "plain_dns": "Obyčajné DNS", "form_enter_rate_limit": "Zadajte rýchlostný limit", "rate_limit": "Rýchlostný limit", "edns_enable": "Povoliť klientsku podsiete EDNS", @@ -237,6 +245,7 @@ "blocking_mode_null_ip": "Null IP: Odpoveď s nulovou IP adresou (0.0.0.0 pre A; :: pre AAAA)", "blocking_mode_custom_ip": "Vlastná IP adresa: Odpovedzte s manuálne nastavenou IP adresou", "upstream_dns_client_desc": "Ak ponecháte toto pole prázdne, AdGuard Home použije servery nakonfigurované v <0>nastaveniach DNS.", + "tracker_source": "Zdroj sledovania", "source_label": "Zdroj", "found_in_known_domain_db": "Nájdené v databáze známych domén.", "category_label": "Kategória", diff --git a/client/src/__locales/sl.json b/client/src/__locales/sl.json index 51a8e1c1..f82bdf44 100644 --- a/client/src/__locales/sl.json +++ b/client/src/__locales/sl.json @@ -53,9 +53,12 @@ "dhcp_add_static_lease": "Dodaj statičen najem", "dhcp_reset": "Ali ste prepričani, da želite ponastaviti konfiguracijo DHCP?", "country": "Dežela", + "city": "Mesto", "delete_confirm": "Ali ste prepričani, da želite izbrisati \"{{key}}\"?", "form_enter_hostname": "Vnesite ime gostitelja", "error_details": "Podrobnosti o napaki", + "response_details": "Podrobnosti o odzivu", + "request_details": "Podrobnosti o zahtevi", "client_details": "Podatki o odjemalcu", "details": "Podrobnosti", "back": "Nazaj", @@ -64,10 +67,10 @@ "filters": "Filtri", "filter": "Filtriraj", "query_log": "Dnevnik poizvedb", - "empty_log": "Dnevnik poizvedb je prazen", "faq": "Pogosta vprašanja in odgovori (FAQ)", "version": "različica", "address": "Naslov", + "protocol": "Protokol", "on": "VKL", "off": "IZK", "copyright": "Avtorske pravice", @@ -225,6 +228,7 @@ "blocking_ipv6": "Onemogočanje IPv6", "dns_over_https": "DNS-prek-HTTPS", "dns_over_tls": "DNS-prek-TLS", + "plain_dns": "Navadni DNS", "form_enter_rate_limit": "Vnesite omejitev hitrosti", "rate_limit": "Omejitev hitrosti", "edns_enable": "Omogoči podmrežje odjemalcev EDNS", diff --git a/client/src/__locales/tr.json b/client/src/__locales/tr.json index a1cee624..358b5fac 100644 --- a/client/src/__locales/tr.json +++ b/client/src/__locales/tr.json @@ -37,6 +37,7 @@ "dhcp_interface_select": "DHCP arayüzünü seç", "dhcp_hardware_address": "Donanım adresi", "dhcp_ip_addresses": "IP adresleri", + "ip": "IP Adresi", "dhcp_table_hostname": "Bilgisayar Adı", "dhcp_table_expires": "Geçerlilik Tarihi", "dhcp_warning": "Dahili DHCP sunucusunu etkinleştirmek istiyorsanız başka aktif DHCP sunucusu olmadığından emin olun. Aksi takdirde cihazlar internete bağlanamayabilir.", @@ -49,13 +50,17 @@ "dhcp_static_leases_not_found": "Sabit DHCP kiralaması bulunamadı", "dhcp_add_static_lease": "Sabit kiralama ekle", "dhcp_reset": "DHCP yapılandırmasını sıfırlamak istediğinizden emin misiniz?", + "country": "Ülke", "delete_confirm": "\"{{key}}\" silmek istediğinizden emin misiniz?", "form_enter_hostname": "Cihaz ismi girin", "error_details": "Hata detayları", + "client_details": "İstemci detayları", + "details": "Detaylar", "back": "Geri", "dashboard": "Pano", "settings": "Ayarlar", "filters": "Filtreler", + "filter": "Filtre", "query_log": "Sorgu Günlüğü", "faq": "SSS", "version": "Sürüm", @@ -132,8 +137,10 @@ "rules_count_table_header": "Kural sayısı", "last_time_updated_table_header": "Son güncelleme", "actions_table_header": "Eylemler", + "request_table_header": "İstek", "edit_table_action": "Düzenle", "delete_table_action": "Sil", + "elapsed": "Geçen zaman", "filters_and_hosts_hint": "AdGuard Home temel reklam engelleme kurallarını ve hosts dosyalarının söz dizim kurallarını anlamaktadır.", "no_blocklist_added": "Hiçbir blok listesi eklenmedi", "no_whitelist_added": "Hiçbir izin listesi eklenmedi", @@ -175,6 +182,7 @@ "time_table_header": "Saat", "date": "Tarih", "domain_name_table_header": "Alan adı", + "domain_or_client": "Alan adı veya istemci", "type_table_header": "Tür", "response_table_header": "Yanıt", "client_table_header": "İstemci", @@ -212,6 +220,7 @@ "custom_ip": "Özel IP", "blocking_ipv4": "IPv4 engelleme", "blocking_ipv6": "IPv6 engelleme", + "dns_over_https": "DNS üzerinden HTTPS", "form_enter_rate_limit": "Sıklık limitini girin", "rate_limit": "Sıklık limiti", "edns_enable": "EDNS İstemci Alt Ağını Etkinleştir", @@ -492,7 +501,9 @@ "dnssec_enable": "DNSSEC'i etkinleştir", "dnssec_enable_desc": "DNSSEC'i giden DNS sorguları için etkinleştir ve sonucu kontrol et (DNSSEC-etkin sorgulama gerekli)", "show_blocked_responses": "Engellendi", + "show_whitelisted_responses": "Beyazlisteye eklendi", "blocked_adult_websites": "Yetişkin içerikli site engellendi", "blocked_threats": "Engellenen Tehditler", + "allowed": "İzin verildi", "blocklist": "Engellenen listesi" } \ No newline at end of file diff --git a/client/src/__locales/vi.json b/client/src/__locales/vi.json index 5faabe28..b878837a 100644 --- a/client/src/__locales/vi.json +++ b/client/src/__locales/vi.json @@ -199,10 +199,12 @@ "edns_cs_desc": "Nếu được bật, AdGuard Home sẽ gửi các mạng con của khách hàng đến các máy chủ DNS.", "rate_limit_desc": "Số lượng yêu cầu mỗi giây mà một khách hàng được phép thực hiện (0: không giới hạn)", "blocking_ipv4_desc": "Địa chỉ IP được trả lại cho một yêu cầu A bị chặn", + "blocking_mode_default": "Mặc định: Trả lời với NXDOMAIN khi bị chặn bởi quy tắc kiểu Adblock; phản hồi với địa chỉ IP được chỉ định trong quy tắc khi bị chặn bởi quy tắc / etc / hosts-style", "source_label": "Nguồn", "found_in_known_domain_db": "Tìm thấy trong cơ sở dữ liệu tên miền", "category_label": "Thể loại", "rule_label": "Quy tắc", + "list_label": "Danh sách", "unknown_filter": "Bộ lọc không rõ {{filterId}}", "install_welcome_title": "Chào mừng bạn đến với AdGuard Home!", "install_welcome_desc": "AdGuard Home là một máy chủ DNS chặn quảng cáo và theo dõi trên toàn mạng. Mục đích của nó là cho phép bạn kiểm soát toàn bộ mạng và tất cả các thiết bị của mình và không yêu cầu sử dụng chương trình phía máy khách.", @@ -421,6 +423,19 @@ "filtering_rules_learn_more": "<0>Tìm hiểu thêm về việc tạo danh sách chặn máy chủ của riêng bạn.", "blocked_by_response": "Chặn bởi CNAME hoặc địa IP ở phản hồi", "try_again": "Hãy thử lại", + "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_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.", + "tags_title": "Thẻ", + "tags_desc": "Bạn có thể chọn các thẻ tương ứng với khách hàng. Thẻ có thể được bao gồm trong các quy tắc lọc và cho phép bạn áp dụng chúng chính xác hơn. <0>Tìm hiểu thêm", + "form_select_tags": "Chọn thẻ khách hàng", + "check_title": "Kiểm tra bộ lọc", + "check_desc": "Kiểm tra xem tên máy chủ có được lọc không", + "check": "Kiểm tra", + "check_ip": "Địa chỉ IP: {{ip}}", + "check_rule": "Quy tắc: {{rule}}", + "check_not_found": "Không tìm thấy trong danh sách bộ lọc của bạn", + "static_ip": "Địa chỉ IP tĩnh", "dnssec_enable": "Bật DNSSEC", "dnssec_enable_desc": "Cắm mốc DNSSEC trong các truy vấn DNS sắp tới và kiểm tra kết quả (buộc phải có trình sửa lỗi hỗ trợ DNSSEC)", "show_blocked_responses": "Bị chặn", diff --git a/client/src/__locales/zh-cn.json b/client/src/__locales/zh-cn.json index 6ac4faae..8fd0c171 100644 --- a/client/src/__locales/zh-cn.json +++ b/client/src/__locales/zh-cn.json @@ -3,6 +3,8 @@ "example_upstream_reserved": "您可以将上游DNS 服务器<0>指定为特定域名", "upstream_parallel": "通过同时查询所有上游服务器,使用并行请求以加速解析", "parallel_requests": "并行请求", + "load_balancing": "负载均衡", + "load_balancing_desc": "一次查询一台服务器。 AdGuard Home将使用加权随机算法来选择服务器,以便更频繁地使用最快的服务器。", "bootstrap_dns": "Bootstrap DNS 服务器", "bootstrap_dns_desc": "Bootstrap DNS 服务器用于解析您指定为上游的 DoH / DoT 解析器的 IP 地址。", "check_dhcp_servers": "检查 DHCP 服务器", @@ -37,6 +39,7 @@ "dhcp_interface_select": "选择 DHCP 接口", "dhcp_hardware_address": "硬件地址", "dhcp_ip_addresses": "IP 地址", + "ip": "IP地址", "dhcp_table_hostname": "主机名", "dhcp_table_expires": "到期", "dhcp_warning": "如果你想要启用内置的 DHCP 服务器,请确保在当前网络中没有其它起作用的 DHCP 服务器。否则,此操作可能会破坏已连接设备的网络连接!", @@ -49,17 +52,27 @@ "dhcp_static_leases_not_found": "未找到 DHCP 静态租约", "dhcp_add_static_lease": "添加静态租约", "dhcp_reset": "您确定要重置DHCP设定么?", + "country": "国家", + "city": "城市", "delete_confirm": "您确定要删除 \"{{key}}\"?", "form_enter_hostname": "输入主机名称", "error_details": "详细错误信息", + "response_details": "响应细节", + "request_details": "请求详情", + "client_details": "客户端详情", + "details": "详细信息", "back": "返回", "dashboard": "仪表盘", "settings": "设置", "filters": "过滤器", + "filter": "过滤器", "query_log": "查询日志", + "compact": "紧凑", + "nothing_found": "没找到", "faq": "常见问题", "version": "版本", "address": "地址", + "protocol": "协议", "on": "启用中", "off": "禁用中", "copyright": "版权", @@ -114,7 +127,7 @@ "encryption_settings": "加密设置", "dhcp_settings": "DHCP 设置", "upstream_dns": "上游 DNS 服务器", - "upstream_dns_hint": "如果此处留空,AdGuard Home 将会使用 Cloudflare DNS 作为上游 DNS。如果想要使用 DNS over TLS,请以 tls:// 为开头。", + "upstream_dns_hint": "如果此处留空,AdGuard Home 将会使用 Quad9 作为上游。", "test_upstream_btn": "测试上游 DNS", "upstreams": "上游服务器", "apply_btn": "应用", @@ -132,8 +145,10 @@ "rules_count_table_header": "规则数", "last_time_updated_table_header": "上次更新时间", "actions_table_header": "活跃状态", + "request_table_header": "请求", "edit_table_action": "编辑", "delete_table_action": "删除", + "elapsed": "耗时", "filters_and_hosts_hint": "AdGuard Home 可以解析基础的 adblock 规则和 Hosts 语法。", "no_blocklist_added": "未添加阻止列表", "no_whitelist_added": "未添加允许列表", @@ -175,8 +190,10 @@ "time_table_header": "时间", "date": "日起", "domain_name_table_header": "域名", + "domain_or_client": "域名或客户端", "type_table_header": "类型", "response_table_header": "响应", + "response_code": "响应代码", "client_table_header": "客户端", "empty_response_status": "空", "show_all_filter_type": "显示所有", @@ -195,6 +212,7 @@ "query_log_filtered": "被 {{filter}} 过滤", "query_log_confirm_clear": "你确定想要清除全部查询日志吗?", "query_log_cleared": "查询日志已成功清除", + "query_log_updated": "已成功更新查询日志", "query_log_clear": "清除查询日志", "query_log_retention": "查询记录保留时间", "query_log_enable": "启用日志", @@ -212,6 +230,9 @@ "custom_ip": "自定义 IP", "blocking_ipv4": "拦截 IPv4", "blocking_ipv6": "拦截 IPv6", + "dns_over_https": "DNS-over-HTTPS", + "dns_over_tls": "DNS-over-TLS", + "plain_dns": "无加密DNS", "form_enter_rate_limit": "输入限制速率", "rate_limit": "速度限制", "edns_enable": "使用客户端的子网地址(EDNS)", @@ -224,12 +245,14 @@ "blocking_mode_null_ip": "空IP:以零IP地址响应(A记录 0.0.0.0;AAAA记录 ::)", "blocking_mode_custom_ip": "自定IP:以手动设置的IP地址响应", "upstream_dns_client_desc": "如果将此字段留空,AdGuard Home 将使用在<0>DNS设置中配置的服务器。", + "tracker_source": "追踪器来源", "source_label": "源", "found_in_known_domain_db": "成功在已知域名数据库中查询到", "category_label": "类别", "rule_label": "规则", "list_label": "列表", "unknown_filter": "未知过滤器 {{filterId}}", + "known_tracker": "已知跟踪器", "install_welcome_title": "欢迎使用 AdGuard Home!", "install_welcome_desc": "AdGuard Home 是一个可在特定网络范围内拦截所有广告和跟踪器的 DNS 服务器。它的目的是让您控制整个网络和您的所有设备,且不需要使用任何客户端程序。", "install_settings_title": "网页管理界面", @@ -347,6 +370,7 @@ "form_enter_id": "输入标识符", "form_add_id": "添加标识符", "form_client_name": "输入客户端名称", + "name": "名称", "client_global_settings": "使用全局设置", "client_deleted": "客户端 \"{{key}}\" 删除成功", "client_added": "客户端 \"{{key}}\" 添加成功", @@ -446,6 +470,7 @@ "location": "地址", "orgname": "机构名称", "netname": "网络名称", + "network": "网络", "descr": "描述", "whois": "Whois", "filtering_rules_learn_more": "<0>了解更多关于创建自己的hosts清单。", @@ -457,6 +482,7 @@ "disable_ipv6": "禁用 IPv6", "disable_ipv6_desc": "启用后,所有IPv6地址 (type AAAA) 的DNS查询都会被丢弃。", "fastest_addr": "最快的 IP 地址", + "fastest_addr_desc": "查询所有DNS服务器并返回所有响应中速度最快的IP地址。因必须等待全部DNS服务器均有所回应,因而会降低DNS查询的速度,但同时此举将会改善总体的连接。", "autofix_warning_text": "若您单击“修复”,AdGuardHome将会配置您的系统以使用AdGuardHome的DNS服务器", "autofix_warning_list": "其将会进行如下工作:<0>停用系统DNSStubListener<0>设置DNS服务器地址为127.0.0.1<0>将/etc/resolv.conf的符号链接目标替换为/run/systemd/resolv/resolv.conf<0>停止DNSStubListener(重新加载系统解析服务)", "autofix_warning_result": "因此,默认情况下所有来自系统的DNS请求都将由AdGuardHome处理。", @@ -490,9 +516,18 @@ "list_updated_plural": "{{count}} 条列表已更新", "dnssec_enable": "启用DNSSEC", "dnssec_enable_desc": "在发出DNS查询中设置DNSSEC标志并检查结果(需要启用DNSSEC的解析器)", + "validated_with_dnssec": "通过DNSSEC验证", + "show_all_responses": "所有响应", "show_blocked_responses": "已拦截", - "blocked_safebrowsing": "安全浏览阻止项目", + "show_whitelisted_responses": "已列入白名单", + "show_processed_responses": "已处理", + "blocked_safebrowsing": "被安全浏览阻止", "blocked_adult_websites": "拦截的成人网站", "blocked_threats": "拦截的威胁", - "blocklist": "拦截列表" + "allowed": "允许项", + "filtered": "已过滤", + "rewritten": "重写项", + "safe_search": "安全搜索", + "blocklist": "拦截列表", + "milliseconds_abbreviation": "毫秒" } \ No newline at end of file diff --git a/client/src/__locales/zh-tw.json b/client/src/__locales/zh-tw.json index 8d8994a6..400e278e 100644 --- a/client/src/__locales/zh-tw.json +++ b/client/src/__locales/zh-tw.json @@ -53,9 +53,12 @@ "dhcp_add_static_lease": "增加靜態租約", "dhcp_reset": "您確定您想要重置動態主機設定協定(DHCP)配置嗎?", "country": "國家", + "city": "城市", "delete_confirm": "您確定您想要刪除 \"{{key}}\" 嗎?", "form_enter_hostname": "輸入主機名稱", "error_details": "錯誤細節", + "response_details": "回應細節", + "request_details": "請求細節", "client_details": "用戶端細節", "details": "細節", "back": "返回", @@ -64,10 +67,12 @@ "filters": "過濾器", "filter": "過濾器", "query_log": "查詢記錄", - "empty_log": "查詢記錄為空", + "compact": "精簡的", + "nothing_found": "無什麼被找到", "faq": "常見問答集", "version": "版本", "address": "位址", + "protocol": "協定", "on": "開著", "off": "關著", "copyright": "版權", @@ -188,6 +193,7 @@ "domain_or_client": "網域或用戶端", "type_table_header": "類型", "response_table_header": "回應", + "response_code": "回應碼", "client_table_header": "用戶端", "empty_response_status": "空無的", "show_all_filter_type": "顯示全部", @@ -206,6 +212,7 @@ "query_log_filtered": "被 {{filter}} 過濾", "query_log_confirm_clear": "您確定您想要清除整個查詢記錄嗎?", "query_log_cleared": "該查詢記錄已被成功地清除", + "query_log_updated": "該查詢記錄已被成功地更新", "query_log_clear": "清除查詢記錄", "query_log_retention": "查詢記錄保留", "query_log_enable": "啟用記錄", @@ -225,6 +232,7 @@ "blocking_ipv6": "封鎖 IPv6", "dns_over_https": "DNS-over-HTTPS", "dns_over_tls": "DNS-over-TLS", + "plain_dns": "一般的 DNS", "form_enter_rate_limit": "輸入速率限制", "rate_limit": "速率限制", "edns_enable": "啟用對於 DNS 的擴充機制(EDNS)用戶端子網路", @@ -237,6 +245,7 @@ "blocking_mode_null_ip": "無效的 IP:以零值 IP 位址(0.0.0.0 供 A;:: 供 AAAA)回覆", "blocking_mode_custom_ip": "自訂的 IP:以一組手動地被設定的 IP 位址回覆", "upstream_dns_client_desc": "如果您將該欄位留空,AdGuard Home 將使用在 <0>DNS 設定中被配置的伺服器。", + "tracker_source": "追蹤器來源", "source_label": "來源", "found_in_known_domain_db": "在已知的域名資料庫中被發現。", "category_label": "類別", From da5467903e4523006afd4824afcf22be3a5764ad Mon Sep 17 00:00:00 2001 From: Andrey Meshkov Date: Mon, 29 Jun 2020 17:46:58 +0300 Subject: [PATCH 29/38] Fix #1433 --- README.md | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index f1de0ad2..73db929b 100644 --- a/README.md +++ b/README.md @@ -132,7 +132,20 @@ AdGuard Home provides a lot of features out-of-the-box with no need to install a It depends. -"DNS sinkholing" is capable of blocking a big percentage of ads, but it lacks flexibility and power of traditional ad blockers. You can get a good impression about the difference between these methods by reading [this article](https://adguard.com/en/blog/adguard-vs-adaway-dns66/). It compares AdGuard for Android (a traditional ad blocker) to hosts-level ad blockers (which are almost identical to DNS-based blockers in their capabilities). However, this level of protection is enough for some users. Additionally, using a DNS-based blocker can help to block ads, tracking and analytics requests on other types of devices, such as SmartTVs, smart speakers or other kinds of IoT devices (on which you can't install tradtional ad blockers). +"DNS sinkholing" is capable of blocking a big percentage of ads, but it lacks flexibility and power of traditional ad blockers. You can get a good impression about the difference between these methods by reading [this article](https://adguard.com/en/blog/adguard-vs-adaway-dns66/). It compares AdGuard for Android (a traditional ad blocker) to hosts-level ad blockers (which are almost identical to DNS-based blockers in their capabilities). + +However, this level of protection is enough for some users. Additionally, using a DNS-based blocker can help to block ads, tracking and analytics requests on other types of devices, such as SmartTVs, smart speakers or other kinds of IoT devices (on which you can't install tradtional ad blockers). + +**Known limitations** + +Here are some examples of what cannot be blocked by a DNS-level blocker: + +* YouTube, Twitch ads +* Facebook, Twitter, Instagram sponsored posts + +Essentially, any advertising that shares a domain with content cannot be blocked by a DNS-level blocker. + +Is there a chance to handle this in the future? DNS will never be enough to do this. Our only option is to use a content blocking proxy like what we do in the standalone AdGuard applications. We're [going to bring](https://github.com/AdguardTeam/AdGuardHome/issues/1228) this feature support to AdGuard Home in the future. Unfortunately, even in this case, there still will be cases when this won't be enough or would require quite complicated configuration. ## How to build from source From 25a14e98abb5427f25af57bbc61277bd992ba600 Mon Sep 17 00:00:00 2001 From: Andrey Meshkov Date: Mon, 29 Jun 2020 20:34:26 +0300 Subject: [PATCH 30/38] add dns to docker run --- build_snap.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/build_snap.sh b/build_snap.sh index 13dae65f..c324fc5a 100755 --- a/build_snap.sh +++ b/build_snap.sh @@ -122,6 +122,7 @@ build_snap_docker() { prepare docker run ${INTERACTIVE} --rm \ + --dns 8.8.8.8 \ -v $(pwd):/build \ -v $(pwd)/launchpad_credentials:/root/${LAUNCHPAD_CREDENTIALS_DIR}/credentials:ro \ ${BUILDER_IMAGE} \ @@ -182,6 +183,7 @@ publish_snap_docker() { # Login and publish the snap docker run ${INTERACTIVE} --rm \ + --dns 8.8.8.8 \ -v $(pwd):/build \ ${BUILDER_IMAGE} \ sh -c "snapcraft login --with=/build/snapcraft_login && snapcraft push --release=${CHANNEL} /build/${snapFile}" From da6cd575870e970ab5787e9082531123be6ed8e3 Mon Sep 17 00:00:00 2001 From: Andrey Meshkov Date: Mon, 29 Jun 2020 20:37:25 +0300 Subject: [PATCH 31/38] rollback dns --- build_snap.sh | 2 -- 1 file changed, 2 deletions(-) diff --git a/build_snap.sh b/build_snap.sh index c324fc5a..13dae65f 100755 --- a/build_snap.sh +++ b/build_snap.sh @@ -122,7 +122,6 @@ build_snap_docker() { prepare docker run ${INTERACTIVE} --rm \ - --dns 8.8.8.8 \ -v $(pwd):/build \ -v $(pwd)/launchpad_credentials:/root/${LAUNCHPAD_CREDENTIALS_DIR}/credentials:ro \ ${BUILDER_IMAGE} \ @@ -183,7 +182,6 @@ publish_snap_docker() { # Login and publish the snap docker run ${INTERACTIVE} --rm \ - --dns 8.8.8.8 \ -v $(pwd):/build \ ${BUILDER_IMAGE} \ sh -c "snapcraft login --with=/build/snapcraft_login && snapcraft push --release=${CHANNEL} /build/${snapFile}" From 250b254c334bc72f7d36b650b70812e99a40b4aa Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Thu, 2 Jul 2020 14:42:39 +0300 Subject: [PATCH 32/38] - home: when printing HTTP addresses to console, use all IP addresses Close #1856 Squashed commit of the following: commit 47ff99f147216bf28f1395847148f084b9dd4deb Author: Simon Zolin Date: Thu Jul 2 14:27:03 2020 +0300 - home: when printing HTTP addresses to console, use all IP addresses --- home/home.go | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/home/home.go b/home/home.go index f5b9375f..e1338038 100644 --- a/home/home.go +++ b/home/home.go @@ -645,8 +645,10 @@ func printHTTPAddresses(proto string) { } for _, iface := range ifaces { - address = net.JoinHostPort(iface.Addresses[0], port) - log.Printf("Go to %s://%s", proto, address) + for _, addr := range iface.Addresses { + address = net.JoinHostPort(addr, strconv.Itoa(config.BindPort)) + log.Printf("Go to %s://%s", proto, address) + } } } else { address = net.JoinHostPort(config.BindHost, port) From 72ce5f57c1e1417ee98f74ec66a5dec08878d8c2 Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Thu, 2 Jul 2020 16:52:29 +0300 Subject: [PATCH 33/38] - auth: show detailed error message if Bolt couldn't initialize its DB Close #1846 Squashed commit of the following: commit 34c612852b784d78191b37577324adeb0149e789 Author: Simon Zolin Date: Thu Jul 2 16:43:27 2020 +0300 - auth: show detailed error message if Bolt couldn't initialize its DB --- home/auth.go | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/home/auth.go b/home/auth.go index a2d6d5f2..3b524d29 100644 --- a/home/auth.go +++ b/home/auth.go @@ -80,7 +80,10 @@ func InitAuth(dbFilename string, users []User, sessionTTL uint32) *Auth { var err error a.db, err = bbolt.Open(dbFilename, 0644, nil) if err != nil { - log.Error("Auth: bbolt.Open: %s", err) + log.Error("Auth: open DB: %s: %s", dbFilename, err) + if err.Error() == "invalid argument" { + log.Error("AdGuard Home cannot be initialized due to an incompatible file system.\nPlease read the explanation here: https://github.com/AdguardTeam/AdGuardHome/wiki/Getting-Started#limitations") + } return nil } a.loadSessions() From 205680b71b10dd618c5a45a98f56f951db7a59f6 Mon Sep 17 00:00:00 2001 From: Artem Baskal Date: Fri, 3 Jul 2020 11:14:54 +0300 Subject: [PATCH 34/38] - client: Make language tag in HTML same as setting language Close #1797 Squashed commit of the following: commit b822a83cb05cc5ba92000cdb7d1c12629471bc57 Merge: e2fa24fb 72ce5f57 Author: ArtemBaskal Date: Fri Jul 3 11:02:56 2020 +0300 Merge branch 'master' into fix/1797 commit e2fa24fb9fa0c15f8411e186e90e0ffb1c705fb2 Author: ArtemBaskal Date: Thu Jul 2 18:21:30 2020 +0300 Extract helper commit ba8473e7b16ab8b1abbee4b42a4ef2b0de8c136b Author: ArtemBaskal Date: Thu Jul 2 15:31:42 2020 +0300 - client: Make language tag in HTML same as setting language --- client/src/actions/index.js | 40 ++++++--- client/src/components/App/index.js | 2 + client/src/components/ui/Footer.js | 127 +++++++++++++++-------------- client/src/helpers/helpers.js | 7 ++ client/src/i18n.js | 5 +- 5 files changed, 106 insertions(+), 75 deletions(-) diff --git a/client/src/actions/index.js b/client/src/actions/index.js index 550c304f..478a3021 100644 --- a/client/src/actions/index.js +++ b/client/src/actions/index.js @@ -70,9 +70,18 @@ export const initSettings = (settingsList) => async (dispatch) => { safesearch, } = settingsList; const newSettingsList = { - safebrowsing: { ...safebrowsing, enabled: safebrowsingStatus.enabled }, - parental: { ...parental, enabled: parentalStatus.enabled }, - safesearch: { ...safesearch, enabled: safesearchStatus.enabled }, + safebrowsing: { + ...safebrowsing, + enabled: safebrowsingStatus.enabled, + }, + parental: { + ...parental, + enabled: parentalStatus.enabled, + }, + safesearch: { + ...safesearch, + enabled: safesearchStatus.enabled, + }, }; dispatch(initSettingsSuccess({ settingsList: newSettingsList })); } catch (error) { @@ -274,13 +283,14 @@ export const testUpstream = (config) => async (dispatch) => { values.upstream_dns = normalizeTextarea(values.upstream_dns); const upstreamResponse = await apiClient.testUpstream(values); - const testMessages = Object.keys(upstreamResponse).map((key) => { - const message = upstreamResponse[key]; - if (message !== 'OK') { - dispatch(addErrorToast({ error: i18next.t('dns_test_not_ok_toast', { key }) })); - } - return message; - }); + const testMessages = Object.keys(upstreamResponse) + .map((key) => { + const message = upstreamResponse[key]; + if (message !== 'OK') { + dispatch(addErrorToast({ error: i18next.t('dns_test_not_ok_toast', { key }) })); + } + return message; + }); if (testMessages.every((message) => message === 'OK')) { dispatch(addSuccessToast('dns_test_ok_toast')); @@ -393,11 +403,17 @@ export const toggleDhcpSuccess = createAction('TOGGLE_DHCP_SUCCESS'); export const toggleDhcp = (values) => async (dispatch) => { dispatch(toggleDhcpRequest()); - let config = { ...values, enabled: false }; + let config = { + ...values, + enabled: false, + }; let successMessage = 'disabled_dhcp'; if (!values.enabled) { - config = { ...values, enabled: true }; + config = { + ...values, + enabled: true, + }; successMessage = 'enabled_dhcp'; dispatch(findActiveDhcp(values.interface_name)); } diff --git a/client/src/components/App/index.js b/client/src/components/App/index.js index 2318c7a9..afbd3888 100644 --- a/client/src/components/App/index.js +++ b/client/src/components/App/index.js @@ -36,6 +36,7 @@ import i18n from '../../i18n'; import Loading from '../ui/Loading'; import { FILTERS_URLS, MENU_URLS, SETTINGS_URLS } from '../../helpers/constants'; import Services from '../Filters/Services'; +import { setHtmlLangAttr } from '../../helpers/helpers'; class App extends Component { componentDidMount() { @@ -62,6 +63,7 @@ class App extends Component { if (!processing) { if (language) { i18n.changeLanguage(language); + setHtmlLangAttr(language); } } diff --git a/client/src/components/ui/Footer.js b/client/src/components/ui/Footer.js index 14f37637..482573d6 100644 --- a/client/src/components/ui/Footer.js +++ b/client/src/components/ui/Footer.js @@ -1,6 +1,6 @@ -import React, { Component, Fragment } from 'react'; +import React from 'react'; import PropTypes from 'prop-types'; -import { Trans, withTranslation } from 'react-i18next'; +import { useTranslation } from 'react-i18next'; import classNames from 'classnames'; import { REPOSITORY, PRIVACY_POLICY_LINK } from '../../helpers/constants'; @@ -10,6 +10,7 @@ import i18n from '../../i18n'; import Version from './Version'; import './Footer.css'; import './Select.css'; +import { setHtmlLangAttr } from '../../helpers/helpers'; const linksData = [ { @@ -27,83 +28,85 @@ const linksData = [ }, ]; -class Footer extends Component { - getYear = () => { +const Footer = (props) => { + const { t } = useTranslation(); + + const getYear = () => { const today = new Date(); return today.getFullYear(); }; - changeLanguage = (event) => { - i18n.changeLanguage(event.target.value); + const changeLanguage = (event) => { + const { value } = event.target; + i18n.changeLanguage(value); + setHtmlLangAttr(value); }; - renderCopyright = () =>
    + const renderCopyright = () =>
    - copyright © {this.getYear()}{' '} + {t('copyright')} © {getYear()}{' '} AdGuard
    ; - renderLinks = (linksData) => linksData.map(({ name, href, className = '' }) => - {name} - ); + const renderLinks = (linksData) => linksData.map(({ name, href, className = '' }) => + {t(name)} + ); - render() { - const { - dnsVersion, processingVersion, getVersion, checkUpdateFlag, - } = this.props; + const { + dnsVersion, processingVersion, getVersion, checkUpdateFlag, + } = props; - return ( - -
    -
    -
    -
    - {this.renderLinks(linksData)} -
    -
    - -
    + return ( + <> +
    +
    +
    +
    + {renderLinks(linksData)}
    -
    -
    -
    -
    -
    - {this.renderCopyright()} -
    - -
    +
    +
    - - ); - } -} +
    +
    +
    +
    + {renderCopyright()} +
    + +
    +
    +
    +
    + + ); +}; Footer.propTypes = { dnsVersion: PropTypes.string, @@ -112,4 +115,4 @@ Footer.propTypes = { checkUpdateFlag: PropTypes.bool, }; -export default withTranslation()(Footer); +export default Footer; diff --git a/client/src/helpers/helpers.js b/client/src/helpers/helpers.js index 253a0506..8b3308c3 100644 --- a/client/src/helpers/helpers.js +++ b/client/src/helpers/helpers.js @@ -588,3 +588,10 @@ export const formatElapsedMs = (elapsedMs, t) => { .toFixed(2); return `${formattedElapsedMs} ${t('milliseconds_abbreviation')}`; }; + +/** + * @param language {string} + */ +export const setHtmlLangAttr = (language) => { + window.document.documentElement.lang = language; +}; diff --git a/client/src/i18n.js b/client/src/i18n.js index 699e59dc..ee776147 100644 --- a/client/src/i18n.js +++ b/client/src/i18n.js @@ -33,6 +33,7 @@ import hr from './__locales/hr.json'; import fa from './__locales/fa.json'; import th from './__locales/th.json'; import ro from './__locales/ro.json'; +import { setHtmlLangAttr } from './helpers/helpers'; const resources = { en: { @@ -143,10 +144,12 @@ i18n wait: true, }, whitelist: availableLanguages, - }, () => { + }, + () => { if (!availableLanguages.includes(i18n.language)) { i18n.changeLanguage(BASE_LOCALE); } + setHtmlLangAttr(i18n.language); }); export default i18n; From f5a1f311033c38272c8c017271a1832709c46ed3 Mon Sep 17 00:00:00 2001 From: Artem Baskal Date: Fri, 3 Jul 2020 11:21:23 +0300 Subject: [PATCH 35/38] - client: Display DomainCell popover Close #1817 Squashed commit of the following: commit 203d52e9b23013cb516765c3d41c288f8ce9d90c Merge: 5c78d918 205680b7 Author: ArtemBaskal Date: Fri Jul 3 11:15:28 2020 +0300 Merge branch 'master' into fix/1817 commit 5c78d918ee2901ff138d5d06046e74ed00dc230d Author: ArtemBaskal Date: Thu Jul 2 17:50:59 2020 +0300 - client: Display DomainCell popover --- client/src/components/Logs/Logs.css | 4 ++++ client/src/components/ui/Popover.js | 19 ++++++++++++++++--- client/src/components/ui/ReactTable.css | 4 ++++ 3 files changed, 24 insertions(+), 3 deletions(-) diff --git a/client/src/components/Logs/Logs.css b/client/src/components/Logs/Logs.css index abdf9611..0a5939c1 100644 --- a/client/src/components/Logs/Logs.css +++ b/client/src/components/Logs/Logs.css @@ -12,6 +12,10 @@ text-overflow: ellipsis; } +.card-table .logs__row { + overflow: visible; +} + .logs__row--center { justify-content: center; } diff --git a/client/src/components/ui/Popover.js b/client/src/components/ui/Popover.js index bc58ac17..7ab6b5ac 100644 --- a/client/src/components/ui/Popover.js +++ b/client/src/components/ui/Popover.js @@ -14,13 +14,21 @@ class Popover extends Component { const source = (
    - source_label: {sourceData.name} + source_label: + {sourceData.name} +
    ); const tracker = (
    - name_table_header: {data.name} + name_table_header: + {data.name} +
    ); @@ -29,7 +37,12 @@ class Popover extends Component { return (
    - + + + +
    diff --git a/client/src/components/ui/ReactTable.css b/client/src/components/ui/ReactTable.css index 42da9557..4595212d 100644 --- a/client/src/components/ui/ReactTable.css +++ b/client/src/components/ui/ReactTable.css @@ -5,6 +5,10 @@ text-overflow: ellipsis; } +.card-table .ReactTable .rt-td { + overflow: visible; +} + .ReactTable .rt-tbody { overflow: visible; } From 9640752d20666373165d1f8bb3f3ddb8378353c3 Mon Sep 17 00:00:00 2001 From: Artem Baskal Date: Fri, 3 Jul 2020 11:45:56 +0300 Subject: [PATCH 36/38] - client: Don't normalise disallowed domains Close #1820 Squashed commit of the following: commit 0c758ddcd738136b92e6f947a8068ecc59f7ec25 Merge: 15650db3 f5a1f311 Author: ArtemBaskal Date: Fri Jul 3 11:22:00 2020 +0300 Merge branch 'master' into fix/1820 commit 15650db35323009001fd427a74a312705b54ac86 Author: ArtemBaskal Date: Mon Jun 29 12:01:51 2020 +0300 '- client: Don't normalise disallowed domains' --- client/src/components/Header/Menu.js | 2 +- client/src/components/Settings/Dns/Access/Form.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/client/src/components/Header/Menu.js b/client/src/components/Header/Menu.js index e65faf2d..5e5e449d 100644 --- a/client/src/components/Header/Menu.js +++ b/client/src/components/Header/Menu.js @@ -37,8 +37,8 @@ const FILTERS_ITEMS = [ { route: FILTERS_URLS.dns_blocklists, text: 'dns_blocklists' }, { route: FILTERS_URLS.dns_allowlists, text: 'dns_allowlists' }, { route: FILTERS_URLS.dns_rewrites, text: 'dns_rewrites' }, - { route: FILTERS_URLS.custom_rules, text: 'custom_filtering_rules' }, { route: FILTERS_URLS.blocked_services, text: 'blocked_services' }, + { route: FILTERS_URLS.custom_rules, text: 'custom_filtering_rules' }, ]; class Menu extends Component { diff --git a/client/src/components/Settings/Dns/Access/Form.js b/client/src/components/Settings/Dns/Access/Form.js index bd7ca897..8edc3189 100644 --- a/client/src/components/Settings/Dns/Access/Form.js +++ b/client/src/components/Settings/Dns/Access/Form.js @@ -46,7 +46,7 @@ const Form = (props) => { type="text" className="form-control form-control--textarea font-monospace" disabled={disabled} - normalizeOnBlur={normalizeMultiline} + normalizeOnBlur={id === 'disallowed_clients' ? normalizeMultiline : undefined} />
    ; From 9df7aba9e187ff272445cfd248aa3bf70e580c63 Mon Sep 17 00:00:00 2001 From: Artem Baskal Date: Fri, 3 Jul 2020 12:01:03 +0300 Subject: [PATCH 37/38] - client: Fix client tracker source links Close #1813 Squashed commit of the following: commit 7f2286cb6e36f90ca19f2830b341d34af513c9a3 Merge: e9f2e08b 9640752d Author: ArtemBaskal Date: Fri Jul 3 11:55:46 2020 +0300 Merge branch 'master' into fix/1813 commit e9f2e08b608ad14e5b327ab86d8faa66784bae44 Merge: ecee0977 f5a1f311 Author: ArtemBaskal Date: Fri Jul 3 11:49:52 2020 +0300 Merge branch 'master' into fix/1813 commit ecee0977ab5439d3be2a99447a771871f0340a2e Author: ArtemBaskal Date: Fri Jul 3 11:35:10 2020 +0300 Capitalize category names commit b4b47ce0177369fb4da5ad2e10a78b2d96bd81c6 Author: ArtemBaskal Date: Thu Jul 2 18:11:40 2020 +0300 - client: Fix client tracker source links --- .../components/Logs/Cells/getDomainCell.js | 16 ++++++++------ client/src/components/Logs/Table.js | 21 +++++++++++-------- 2 files changed, 22 insertions(+), 15 deletions(-) diff --git a/client/src/components/Logs/Cells/getDomainCell.js b/client/src/components/Logs/Cells/getDomainCell.js index d0a44cff..0d460190 100644 --- a/client/src/components/Logs/Cells/getDomainCell.js +++ b/client/src/components/Logs/Cells/getDomainCell.js @@ -7,7 +7,8 @@ import { LONG_TIME_FORMAT, SCHEME_TO_PROTOCOL_MAP, } from '../../../helpers/constants'; -import { formatDateTime, formatTime } from '../../../helpers/helpers'; +import { captitalizeWords, formatDateTime, formatTime } from '../../../helpers/helpers'; +import { getSourceData } from '../../../helpers/trackers/trackers'; const getDomainCell = (props) => { const { @@ -20,8 +21,6 @@ const getDomainCell = (props) => { const hasTracker = !!tracker; - const source = tracker && tracker.sourceData && tracker.sourceData.name; - const lockIconClass = classNames('icons', 'icon--small', 'd-none', 'd-sm-block', 'cursor--pointer', { 'icon--active': answer_dnssec, 'icon--disabled': !answer_dnssec, @@ -55,10 +54,14 @@ const getDomainCell = (props) => { protocol, }; + const sourceData = getSourceData(tracker); + const knownTrackerDataObj = { name_table_header: tracker && tracker.name, - category_label: tracker && tracker.category, - source_label: source && {source}, + category_label: tracker && captitalizeWords(tracker.category), + source_label: sourceData + && {sourceData.name}, }; const renderGrid = (content, idx) => { @@ -71,7 +74,8 @@ const getDomainCell = (props) => { const getGrid = (contentObj, title, className) => [
    {t(title)}
    , -
    {React.Children.map(Object.entries(contentObj), renderGrid)}
    , +
    {React.Children.map(Object.entries(contentObj), renderGrid)}
    , ]; const requestDetails = getGrid(requestDetailsObj, 'request_details'); diff --git a/client/src/components/Logs/Table.js b/client/src/components/Logs/Table.js index 586fca12..ccab98bb 100644 --- a/client/src/components/Logs/Table.js +++ b/client/src/components/Logs/Table.js @@ -19,6 +19,7 @@ import getClientCell from './Cells/getClientCell'; import getResponseCell from './Cells/getResponseCell'; import { + captitalizeWords, checkFiltered, formatDateTime, formatElapsedMs, @@ -26,6 +27,7 @@ import { } from '../../helpers/helpers'; import Loading from '../ui/Loading'; +import { getSourceData } from '../../helpers/trackers/trackers'; const Table = (props) => { const { @@ -300,15 +302,14 @@ const Table = (props) => { toggleBlocking(buttonType, domain); }; - const tracker_source = tracker && tracker.sourceData - && tracker.sourceData.name; - const status = t((FILTERED_STATUS_TO_META_MAP[reason] && FILTERED_STATUS_TO_META_MAP[reason].label) || reason); const statusBlocked =
    {status}
    ; const protocol = t(SCHEME_TO_PROTOCOL_MAP[client_proto]) || ''; + const sourceData = getSourceData(tracker); + const detailedData = { time_table_header: formatTime(time, LONG_TIME_FORMAT), date: formatDateTime(time, DEFAULT_SHORT_DATE_FORMAT_OPTIONS), @@ -318,9 +319,10 @@ const Table = (props) => { protocol, known_tracker: hasTracker && 'title', table_name: hasTracker && tracker.name, - category_label: hasTracker && tracker.category, - tracker_source: hasTracker && tracker_source && {tracker_source}, + category_label: hasTracker && captitalizeWords(tracker.category), + tracker_source: hasTracker && sourceData + && {sourceData.name}, response_details: 'title', install_settings_dns: upstream, elapsed: formattedElapsedMs, @@ -346,9 +348,10 @@ const Table = (props) => { protocol, known_tracker: 'title', table_name: hasTracker && tracker.name, - category_label: hasTracker && tracker.category, - source_label: hasTracker && source - && {source}, + category_label: hasTracker && captitalizeWords(tracker.category), + source_label: hasTracker && sourceData + && {sourceData.name}, response_details: 'title', install_settings_dns: upstream, elapsed: formattedElapsedMs, From 21dfb5ffe8352c55bdb2899c5885dae4fd2e61b0 Mon Sep 17 00:00:00 2001 From: Simon Zolin Date: Fri, 3 Jul 2020 12:21:09 +0300 Subject: [PATCH 38/38] * querylog: case-insensitive search by domain name Close #1828 Squashed commit of the following: commit 347aff1f8c5293bd06ecc0693970fe447b6e2c75 Merge: f07c8dc0 9df7aba9 Author: Simon Zolin Date: Fri Jul 3 12:10:02 2020 +0300 Merge remote-tracking branch 'origin/master' into 1828-qlog-case-insens commit f07c8dc0665585ce00c415293c47c5a8c9724881 Author: Simon Zolin Date: Fri Jul 3 12:09:49 2020 +0300 minor commit 512c7acd48f649a0d11b4fef66a1351fcd19635b Author: Simon Zolin Date: Thu Jul 2 19:01:43 2020 +0300 minor commit 9f5700af56340c38a2d892101e32959702816205 Author: Simon Zolin Date: Thu Jul 2 16:53:56 2020 +0300 * querylog: case-insensitive search by domain name --- querylog/qlog_test.go | 4 ++-- querylog/search_criteria.go | 12 ++++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/querylog/qlog_test.go b/querylog/qlog_test.go index c087fa4d..c4f34e75 100644 --- a/querylog/qlog_test.go +++ b/querylog/qlog_test.go @@ -59,7 +59,7 @@ func TestQueryLog(t *testing.T) { params.searchCriteria = append(params.searchCriteria, searchCriteria{ criteriaType: ctDomainOrClient, strict: true, - value: "test.example.org", + value: "TEST.example.org", }) entries, _ = l.search(params) assert.Equal(t, 1, len(entries)) @@ -70,7 +70,7 @@ func TestQueryLog(t *testing.T) { params.searchCriteria = append(params.searchCriteria, searchCriteria{ criteriaType: ctDomainOrClient, strict: false, - value: "example.org", + value: "example.ORG", }) entries, _ = l.search(params) assert.Equal(t, 3, len(entries)) diff --git a/querylog/search_criteria.go b/querylog/search_criteria.go index 3c1ee0de..382cd9bc 100644 --- a/querylog/search_criteria.go +++ b/querylog/search_criteria.go @@ -62,11 +62,13 @@ func (c *searchCriteria) quickMatchJSONValue(line string, propertyName string) b if len(val) == 0 { return false } + val = strings.ToLower(val) + searchVal := strings.ToLower(c.value) - if c.strict && c.value == val { + if c.strict && searchVal == val { return true } - if !c.strict && strings.Contains(val, c.value) { + if !c.strict && strings.Contains(val, searchVal) { return true } @@ -78,10 +80,12 @@ func (c *searchCriteria) quickMatchJSONValue(line string, propertyName string) b func (c *searchCriteria) match(entry *logEntry) bool { switch c.criteriaType { case ctDomainOrClient: - if c.strict && entry.QHost == c.value { + qhost := strings.ToLower(entry.QHost) + searchVal := strings.ToLower(c.value) + if c.strict && qhost == searchVal { return true } - if !c.strict && strings.Contains(entry.QHost, c.value) { + if !c.strict && strings.Contains(qhost, searchVal) { return true }