mirror of
https://github.com/syncthing/syncthing.git
synced 2026-01-03 11:29:10 -05:00
Compare commits
63 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bdfd0f0548 | ||
|
|
5d27185083 | ||
|
|
4dfb9d7c83 | ||
|
|
2f15670094 | ||
|
|
b49137ce36 | ||
|
|
7e4e65ebf5 | ||
|
|
8c8167a4ab | ||
|
|
73cc5553b6 | ||
|
|
2ab2488274 | ||
|
|
eb9cd363d0 | ||
|
|
7fe3906534 | ||
|
|
5fdab1bf11 | ||
|
|
13a6d43f0b | ||
|
|
ac942e2481 | ||
|
|
bbd2a7fbc5 | ||
|
|
07a9fa2dbd | ||
|
|
aa559bf496 | ||
|
|
2d968d46b7 | ||
|
|
86c4cafc96 | ||
|
|
c4dfb66d84 | ||
|
|
f4d160684b | ||
|
|
b76e6ce70d | ||
|
|
6b4028eede | ||
|
|
ad81ac8da7 | ||
|
|
7ebeaefe77 | ||
|
|
e1dd36561d | ||
|
|
96c30f8387 | ||
|
|
fc8b353011 | ||
|
|
416b9e8924 | ||
|
|
9f6d732587 | ||
|
|
f2f5786b33 | ||
|
|
eb617865d2 | ||
|
|
a49e318d25 | ||
|
|
e74674a019 | ||
|
|
d98fa474ae | ||
|
|
f16817632f | ||
|
|
bda4016109 | ||
|
|
8f5d07bd09 | ||
|
|
302b352d78 | ||
|
|
45beb28fa5 | ||
|
|
ee9b20e47a | ||
|
|
0f55d5fc3e | ||
|
|
35e153625c | ||
|
|
d5e1b99e6c | ||
|
|
3297624037 | ||
|
|
445e8cc532 | ||
|
|
e041877488 | ||
|
|
36e08f8eee | ||
|
|
8b321387c0 | ||
|
|
8edd67a569 | ||
|
|
e829a63295 | ||
|
|
6881a6897a | ||
|
|
9387e107b3 | ||
|
|
aa901790b9 | ||
|
|
17df4b8634 | ||
|
|
34ef30dd5c | ||
|
|
fc1c7a3c49 | ||
|
|
2abfefc18c | ||
|
|
86a08eb87d | ||
|
|
d330d65859 | ||
|
|
4e1831fa3a | ||
|
|
2f3eacdb6c | ||
|
|
1ce2af1238 |
13
.github/ISSUE_TEMPLATE/01-feature.md
vendored
13
.github/ISSUE_TEMPLATE/01-feature.md
vendored
@@ -1,13 +0,0 @@
|
||||
---
|
||||
name: Feature request
|
||||
about: If you're just not sure how to do something, see "ask a question".
|
||||
labels: enhancement, needs-triage
|
||||
---
|
||||
|
||||
### Include required information
|
||||
|
||||
Please be sure to include at least:
|
||||
|
||||
- what problem your new feature would solve
|
||||
- how or why you think it is generally useful (i.e., not just for you)
|
||||
- what alternatives or workarounds you considered
|
||||
28
.github/ISSUE_TEMPLATE/01-feature.yml
vendored
Normal file
28
.github/ISSUE_TEMPLATE/01-feature.yml
vendored
Normal file
@@ -0,0 +1,28 @@
|
||||
name: Feature request
|
||||
description: File a new feature request
|
||||
labels: ["enhancement", "needs-triage"]
|
||||
body:
|
||||
|
||||
- type: textarea
|
||||
id: feature
|
||||
attributes:
|
||||
label: Feature description
|
||||
description: Please describe the behavior you'd like to see.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: problem-usecase
|
||||
attributes:
|
||||
label: Problem or use case
|
||||
description: Please explain which problem this would solve, or what the use case is for the feature. Keep in mind that it's more likely to be implemented if it's generally useful for a larger number of users.
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: textarea
|
||||
id: alternatives
|
||||
attributes:
|
||||
label: Alternatives or workarounds
|
||||
description: Please describe any alternatives or workarounds you have considered and, possibly, rejected.
|
||||
validations:
|
||||
required: true
|
||||
23
.github/ISSUE_TEMPLATE/02-bug.md
vendored
23
.github/ISSUE_TEMPLATE/02-bug.md
vendored
@@ -1,23 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: If you're actually looking for support, see "ask a question".
|
||||
labels: bug, needs-triage
|
||||
---
|
||||
|
||||
### Does your log mention database corruption?
|
||||
|
||||
If your Syncthing log reports panics because of database corruption it is
|
||||
most likely a fault with your system's storage or memory. Affected log
|
||||
entries will contain lines starting with `panic: leveldb`. You will need to
|
||||
delete the index database to clear this, by running `syncthing
|
||||
-reset-database`.
|
||||
|
||||
### Include required information
|
||||
|
||||
Please be sure to include at least:
|
||||
|
||||
- which version of Syncthing and what operating system you are using
|
||||
- browser and version, if applicable
|
||||
- what happened,
|
||||
- what you expected to happen instead, and
|
||||
- any steps to reproduce the problem.
|
||||
51
.github/ISSUE_TEMPLATE/02-bug.yml
vendored
Normal file
51
.github/ISSUE_TEMPLATE/02-bug.yml
vendored
Normal file
@@ -0,0 +1,51 @@
|
||||
name: Bug report
|
||||
description: If you're actually looking for support instead, see "I need help / I have a question".
|
||||
labels: ["bug", "needs-triage"]
|
||||
body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
:no_entry_sign: If you want to report a security issue, please see [our Security Policy](https://syncthing.net/security/) and do not report the issue here.
|
||||
|
||||
:interrobang: If you are not sure if there is a bug, but something isn't working right and you need help, please [use the forum](https://forum.syncthing.net/).
|
||||
|
||||
- type: textarea
|
||||
id: what-happened
|
||||
attributes:
|
||||
label: What happened?
|
||||
description: Also tell us, what did you expect to happen, and any steps we might use to reproduce the problem.
|
||||
placeholder: Tell us what you see!
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: version
|
||||
attributes:
|
||||
label: Syncthing version
|
||||
description: What version of Syncthing are you running?
|
||||
placeholder: v1.27.4
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: platform
|
||||
attributes:
|
||||
label: Platform & operating system
|
||||
description: On what platform(s) are you seeing the problem?
|
||||
placeholder: Linux arm64
|
||||
validations:
|
||||
required: true
|
||||
|
||||
- type: input
|
||||
id: browser
|
||||
attributes:
|
||||
label: Browser version
|
||||
description: If the problem is related to the GUI, describe your browser and version.
|
||||
placeholder: Safari 17.3.1
|
||||
|
||||
- type: textarea
|
||||
id: logs
|
||||
attributes:
|
||||
label: Relevant log output
|
||||
description: Please copy and paste any relevant log output or crash backtrace. This will be automatically formatted into code, so no need for backticks.
|
||||
render: shell
|
||||
17
.github/workflows/build-infra-dockers.yaml
vendored
17
.github/workflows/build-infra-dockers.yaml
vendored
@@ -4,9 +4,10 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- infrastructure
|
||||
- infra-*
|
||||
|
||||
env:
|
||||
GO_VERSION: "~1.21.5"
|
||||
GO_VERSION: "~1.22.0"
|
||||
CGO_ENABLED: "0"
|
||||
BUILD_USER: docker
|
||||
BUILD_HOST: github.syncthing.net
|
||||
@@ -14,6 +15,7 @@ env:
|
||||
jobs:
|
||||
docker-syncthing:
|
||||
name: Build and push Docker images
|
||||
if: github.repository == 'syncthing/syncthing'
|
||||
runs-on: ubuntu-latest
|
||||
environment: docker
|
||||
strategy:
|
||||
@@ -49,6 +51,17 @@ jobs:
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
|
||||
- name: Set Docker tags (all branches)
|
||||
run: |
|
||||
tags=syncthing/${{ matrix.pkg }}:${{ github.sha }}
|
||||
echo "TAGS=$tags" >> $GITHUB_ENV
|
||||
|
||||
- name: Set Docker tags (latest)
|
||||
if: github.ref == 'refs/heads/infrastructure'
|
||||
run: |
|
||||
tags=syncthing/${{ matrix.pkg }}:latest,${{ env.TAGS }}
|
||||
echo "TAGS=$tags" >> $GITHUB_ENV
|
||||
|
||||
- name: Build and push
|
||||
uses: docker/build-push-action@v5
|
||||
with:
|
||||
@@ -56,6 +69,6 @@ jobs:
|
||||
file: ./Dockerfile.${{ matrix.pkg }}
|
||||
platforms: linux/amd64,linux/arm64
|
||||
push: true
|
||||
tags: syncthing/${{ matrix.pkg }}:latest,syncthing/${{ matrix.pkg }}:${{ github.sha }}
|
||||
tags: ${{ env.TAGS }}
|
||||
labels: |
|
||||
org.opencontainers.image.revision=${{ github.sha }}
|
||||
|
||||
58
.github/workflows/build-syncthing.yaml
vendored
58
.github/workflows/build-syncthing.yaml
vendored
@@ -12,7 +12,7 @@ env:
|
||||
# The go version to use for builds. We set check-latest to true when
|
||||
# installing, so we get the latest patch version that matches the
|
||||
# expression.
|
||||
GO_VERSION: "~1.21.5"
|
||||
GO_VERSION: "~1.22.0"
|
||||
|
||||
# Optimize compatibility on the slow archictures.
|
||||
GO386: softfloat
|
||||
@@ -48,7 +48,7 @@ jobs:
|
||||
runner: ["windows-latest", "ubuntu-latest", "macos-latest"]
|
||||
# The oldest version in this list should match what we have in our go.mod.
|
||||
# Variables don't seem to be supported here, or we could have done something nice.
|
||||
go: ["~1.20.12", "~1.21.5"]
|
||||
go: ["~1.21.7", "~1.22.0"]
|
||||
runs-on: ${{ matrix.runner }}
|
||||
steps:
|
||||
- name: Set git to use LF
|
||||
@@ -165,7 +165,7 @@ jobs:
|
||||
go version
|
||||
echo "GO_VERSION=$(go version | sed 's#^.*go##;s# .*##')" >> $GITHUB_ENV
|
||||
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~\AppData\Local\go-build
|
||||
@@ -190,7 +190,7 @@ jobs:
|
||||
CODESIGN_TIMESTAMP_SERVER: ${{ secrets.CODESIGN_TIMESTAMP_SERVER }}
|
||||
|
||||
- name: Archive artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: packages-windows
|
||||
path: syncthing-windows-*.zip
|
||||
@@ -218,7 +218,7 @@ jobs:
|
||||
go version
|
||||
echo "GO_VERSION=$(go version | sed 's#^.*go##;s# .*##')" >> $GITHUB_ENV
|
||||
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cache/go-build
|
||||
@@ -235,7 +235,7 @@ jobs:
|
||||
CGO_ENABLED: "0"
|
||||
|
||||
- name: Archive artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: packages-linux
|
||||
path: syncthing-linux-*.tar.gz
|
||||
@@ -265,7 +265,7 @@ jobs:
|
||||
go version
|
||||
echo "GO_VERSION=$(go version | sed 's#^.*go##;s# .*##')" >> $GITHUB_ENV
|
||||
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cache/go-build
|
||||
@@ -334,7 +334,7 @@ jobs:
|
||||
zip -r "../$universal.zip" "$universal"
|
||||
|
||||
- name: Archive artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: packages-macos
|
||||
path: syncthing-*.zip
|
||||
@@ -349,7 +349,7 @@ jobs:
|
||||
runs-on: macos-latest
|
||||
steps:
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: packages-macos
|
||||
|
||||
@@ -392,7 +392,7 @@ jobs:
|
||||
go version
|
||||
echo "GO_VERSION=$(go version | sed 's#^.*go##;s# .*##')" >> $GITHUB_ENV
|
||||
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cache/go-build
|
||||
@@ -431,7 +431,7 @@ jobs:
|
||||
CGO_ENABLED: "0"
|
||||
|
||||
- name: Archive artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: packages-other
|
||||
path: syncthing-*.tar.gz
|
||||
@@ -471,7 +471,7 @@ jobs:
|
||||
mv "syncthing-source-$version.tar.gz" syncthing
|
||||
|
||||
- name: Archive artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: packages-source
|
||||
path: syncthing-source-*.tar.gz
|
||||
@@ -504,7 +504,13 @@ jobs:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@v4
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
cache: false
|
||||
check-latest: true
|
||||
|
||||
- name: Install signing tool
|
||||
run: |
|
||||
@@ -543,7 +549,7 @@ jobs:
|
||||
GNUPG_SIGNING_KEY_BASE64: ${{ secrets.GNUPG_SIGNING_KEY_BASE64 }}
|
||||
|
||||
- name: Archive artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: packages-signed
|
||||
path: packages/*
|
||||
@@ -579,7 +585,7 @@ jobs:
|
||||
run: |
|
||||
gem install fpm
|
||||
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cache/go-build
|
||||
@@ -595,7 +601,7 @@ jobs:
|
||||
BUILD_USER: debian
|
||||
|
||||
- name: Archive artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: debian-packages
|
||||
path: "*.deb"
|
||||
@@ -620,11 +626,17 @@ jobs:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Download artifacts
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: packages-signed
|
||||
path: packages
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
cache: false
|
||||
check-latest: true
|
||||
|
||||
- name: Create release json
|
||||
run: |
|
||||
cd packages
|
||||
@@ -662,17 +674,23 @@ jobs:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Download signed packages
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: packages-signed
|
||||
path: packages
|
||||
|
||||
- name: Download debian packages
|
||||
uses: actions/download-artifact@v3
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: debian-packages
|
||||
path: packages
|
||||
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
cache: false
|
||||
check-latest: true
|
||||
|
||||
- name: Set version
|
||||
run: |
|
||||
version=$(go run build.go version)
|
||||
@@ -743,7 +761,7 @@ jobs:
|
||||
go version
|
||||
echo "GO_VERSION=$(go version | sed 's#^.*go##;s# .*##')" >> $GITHUB_ENV
|
||||
|
||||
- uses: actions/cache@v3
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/.cache/go-build
|
||||
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
token: ${{ secrets.ACTIONS_GITHUB_TOKEN }}
|
||||
- uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ^1.19.6
|
||||
go-version: stable
|
||||
- run: |
|
||||
set -euo pipefail
|
||||
git config --global user.name 'Syncthing Release Automation'
|
||||
|
||||
13
AUTHORS
13
AUTHORS
@@ -51,6 +51,7 @@ Audrius Butkevicius (AudriusButkevicius) <audrius.butkevicius@gmail.com> <github
|
||||
Aurélien Rainone <476650+arl@users.noreply.github.com>
|
||||
BAHADIR YILMAZ <bahadiryilmaz32@gmail.com>
|
||||
Bart De Vries (mogwa1) <devriesb@gmail.com>
|
||||
Beat Reichenbach <44111292+beatreichenbach@users.noreply.github.com>
|
||||
Ben Curthoys (bencurthoys) <ben@bencurthoys.com>
|
||||
Ben Schulz (uok) <ueomkail@gmail.com> <uok@users.noreply.github.com>
|
||||
Ben Shepherd (benshep) <bjashepherd@gmail.com>
|
||||
@@ -93,6 +94,7 @@ Daniel Barczyk <46358936+DanielBarczyk@users.noreply.github.com>
|
||||
Daniel Bergmann (brgmnn) <dan.arne.bergmann@gmail.com> <brgmnn@users.noreply.github.com>
|
||||
Daniel Harte (norgeous) <daniel@harte.me> <daniel@danielharte.co.uk> <norgeous@users.noreply.github.com>
|
||||
Daniel Martí (mvdan) <mvdan@mvdan.cc>
|
||||
Daniel Padrta <64928366+danpadcz@users.noreply.github.com>
|
||||
Darshil Chanpura (dtchanpura) <dtchanpura@gmail.com> <dcprime314@gmail.com>
|
||||
David Rimmer (dinosore) <dinosore@dbrsoftware.co.uk>
|
||||
deepsource-autofix[bot] <62050782+deepsource-autofix[bot]@users.noreply.github.com>
|
||||
@@ -105,6 +107,7 @@ derekriemer <derek.riemer@colorado.edu>
|
||||
DerRockWolf <50499906+DerRockWolf@users.noreply.github.com>
|
||||
desbma <desbma@users.noreply.github.com>
|
||||
Devon G. Redekopp <devon@redekopp.com>
|
||||
diemade <spamkill@posteo.ch>
|
||||
digital <didev@dinid.net>
|
||||
Dimitri Papadopoulos Orfanos <3234522+DimitriPapadopoulos@users.noreply.github.com>
|
||||
Dmitry Saveliev (dsaveliev) <d.e.saveliev@gmail.com>
|
||||
@@ -154,13 +157,14 @@ Jacek Szafarkiewicz (hadogenes) <szafar@linux.pl>
|
||||
Jack Croft <jccroft1@users.noreply.github.com>
|
||||
Jacob <jyundt@gmail.com>
|
||||
Jake Peterson (acogdev) <jake@acogdev.com>
|
||||
Jakob Borg (calmh) <jakob@nym.se> <jakob@kastelo.net>
|
||||
Jakob Borg (calmh) <jakob@nym.se> <jakob@kastelo.net> <jborg@coreweave.com>
|
||||
James O'Beirne <wild-github@au92.org>
|
||||
James Patterson (jpjp) <jamespatterson@operamail.com> <jpjp@users.noreply.github.com>
|
||||
janost <janost@tuta.io>
|
||||
Jaroslav Lichtblau <svetlemodry@users.noreply.github.com>
|
||||
Jaroslav Malec (dzarda) <dzardacz@gmail.com>
|
||||
jaseg <githubaccount@jaseg.net>
|
||||
Jaspitta <ste.scarpitta@gmail.com>
|
||||
Jauder Ho <jauderho@users.noreply.github.com>
|
||||
Jaya Chithra (jayachithra) <s.k.jayachithra@gmail.com>
|
||||
Jaya Kumar <jaya.kumar@ict.nl>
|
||||
@@ -179,6 +183,7 @@ Jonathan Cross <jcross@gmail.com>
|
||||
Jonta <359397+Jonta@users.noreply.github.com>
|
||||
Jose Manuel Delicado (jmdaweb) <jmdaweb@hotmail.com> <jmdaweb@users.noreply.github.com>
|
||||
jtagcat <git-514635f7@jtag.cat> <git-12dbd862@jtag.cat>
|
||||
Julian Lehrhuber <jul13579@users.noreply.github.com>
|
||||
Jörg Thalheim <Mic92@users.noreply.github.com>
|
||||
Jędrzej Kula <kula.jedrek@gmail.com>
|
||||
K.B.Dharun Krishna <kbdharunkrishna@gmail.com>
|
||||
@@ -194,6 +199,7 @@ Kevin Bushiri (keevBush) <keevbush@gmail.com> <36192217+keevBush@users.noreply.g
|
||||
Kevin White, Jr. (kwhite17) <kevinwhite1710@gmail.com>
|
||||
klemens <ka7@github.com>
|
||||
Kurt Fitzner (Kudalufi) <kurt@va1der.ca> <kurt.fitzner@gmail.com>
|
||||
kylosus <33132401+kylosus@users.noreply.github.com>
|
||||
Lars K.W. Gohlke (lkwg82) <lkwg82@gmx.de>
|
||||
Lars Lehtonen <lars.lehtonen@gmail.com>
|
||||
Laurent Arnoud <laurent@spkdev.net>
|
||||
@@ -204,6 +210,7 @@ Lode Hoste (Zillode) <zillode@zillode.be>
|
||||
Lord Landon Agahnim (LordLandon) <lordlandon@gmail.com>
|
||||
LSmithx2 <42276854+lsmithx2@users.noreply.github.com>
|
||||
Lukas Lihotzki <lukas@lihotzki.de>
|
||||
Luke Hamburg <1992842+luckman212@users.noreply.github.com>
|
||||
luzpaz <luzpaz@users.noreply.github.com>
|
||||
Majed Abdulaziz (majedev) <majed.alhajry@gmail.com>
|
||||
Marc Laporte (marclaporte) <marc@marclaporte.com> <marc@laporte.name>
|
||||
@@ -241,6 +248,7 @@ Mingxuan Lin <gdlmx@users.noreply.github.com>
|
||||
mv1005 <49659413+mv1005@users.noreply.github.com>
|
||||
Nate Morrison (nrm21) <natemorrison@gmail.com>
|
||||
Naveen <172697+naveensrinivasan@users.noreply.github.com>
|
||||
nf <nf@wh3rd.net>
|
||||
Nicholas Rishel (PrototypeNM1) <rishel.nick@gmail.com> <PrototypeNM1@users.noreply.github.com>
|
||||
Nick Busey <NickBusey@users.noreply.github.com>
|
||||
Nico Stapelbroek <3368018+nstapelbroek@users.noreply.github.com>
|
||||
@@ -300,12 +308,15 @@ Stefan Kuntz (Stefan-Code) <stefan.github@gmail.com> <Stefan.github@gmail.com>
|
||||
Stefan Tatschner (rumpelsepp) <stefan@sevenbyte.org> <rumpelsepp@sevenbyte.org> <stefan@rumpelsepp.org>
|
||||
Steven Eckhoff <steven.eckhoff.opensource@gmail.com>
|
||||
Suhas Gundimeda (snugghash) <suhas.gundimeda@gmail.com> <snugghash@gmail.com>
|
||||
Sven Bachmann <dev@mcbachmann.de>
|
||||
Syncthing Automation <automation@syncthing.net>
|
||||
Syncthing Release Automation <release@syncthing.net>
|
||||
Taylor Khan (nelsonkhan) <nelsonkhan@gmail.com>
|
||||
Thomas <9749173+uhthomas@users.noreply.github.com>
|
||||
Thomas Hipp <thomashipp@gmail.com>
|
||||
Tim Abell (timabell) <tim@timwise.co.uk>
|
||||
Tim Howes (timhowes) <timhowes@berkeley.edu>
|
||||
Tim Nordenfur <tim@gurka.se>
|
||||
Tobias Klauser <tobias.klauser@gmail.com>
|
||||
Tobias Nygren (tnn2) <tnn@nygren.pp.se>
|
||||
Tobias Tom (tobiastom) <t.tom@succont.de>
|
||||
|
||||
@@ -15,6 +15,9 @@ To grant Syncthing additional capabilities without running as root, use the
|
||||
`PCAP` environment variable with the same syntax as that for `setcap(8)`.
|
||||
For example, `PCAP=cap_chown,cap_fowner+ep`.
|
||||
|
||||
To set a different umask value, use the `UMASK` environment variable. For
|
||||
example `UMASK=002`.
|
||||
|
||||
## Example Usage
|
||||
|
||||
**Docker cli**
|
||||
|
||||
@@ -63,12 +63,6 @@ implementations][11] for Windows, Mac, and Linux.
|
||||
|
||||
To run Syncthing in Docker, see [the Docker README][16].
|
||||
|
||||
## Vote on features/bugs
|
||||
|
||||
We'd like to encourage you to [vote][12] on issues that matter to you.
|
||||
This helps the team understand what are the biggest pain points for our
|
||||
users, and could potentially influence what is being worked on next.
|
||||
|
||||
## Getting in Touch
|
||||
|
||||
The first and best point of contact is the [Forum][8].
|
||||
@@ -89,7 +83,7 @@ build process.
|
||||
## Signed Releases
|
||||
|
||||
As of v0.10.15 and onwards, release binaries are GPG signed with the key
|
||||
D26E6ED000654A3E, available from https://syncthing.net/security.html and
|
||||
D26E6ED000654A3E, available from https://syncthing.net/security/ and
|
||||
most key servers.
|
||||
|
||||
There is also a built-in automatic upgrade mechanism (disabled in some
|
||||
@@ -111,7 +105,6 @@ All code is licensed under the [MPLv2 License][7].
|
||||
[8]: https://forum.syncthing.net/
|
||||
[10]: https://github.com/syncthing/syncthing/issues
|
||||
[11]: https://docs.syncthing.net/users/contrib.html#gui-wrappers
|
||||
[12]: https://www.bountysource.com/teams/syncthing/issues
|
||||
[13]: https://github.com/syncthing/syncthing/blob/main/GOALS.md
|
||||
[14]: assets/logo-text-128.png
|
||||
[15]: https://syncthing.net/
|
||||
|
||||
1
build.go
1
build.go
@@ -33,6 +33,7 @@ import (
|
||||
"text/template"
|
||||
"time"
|
||||
|
||||
_ "github.com/syncthing/syncthing/lib/automaxprocs"
|
||||
buildpkg "github.com/syncthing/syncthing/lib/build"
|
||||
)
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
_ "github.com/syncthing/syncthing/lib/automaxprocs"
|
||||
"github.com/syncthing/syncthing/lib/sha256"
|
||||
)
|
||||
|
||||
|
||||
@@ -23,11 +23,11 @@ import (
|
||||
"path/filepath"
|
||||
|
||||
"github.com/alecthomas/kong"
|
||||
raven "github.com/getsentry/raven-go"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
_ "github.com/syncthing/syncthing/lib/automaxprocs"
|
||||
"github.com/syncthing/syncthing/lib/sha256"
|
||||
"github.com/syncthing/syncthing/lib/ur"
|
||||
|
||||
raven "github.com/getsentry/raven-go"
|
||||
)
|
||||
|
||||
const maxRequestSize = 1 << 20 // 1 MiB
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
_ "github.com/syncthing/syncthing/lib/automaxprocs"
|
||||
"github.com/syncthing/syncthing/lib/beacon"
|
||||
"github.com/syncthing/syncthing/lib/discover"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
_ "github.com/syncthing/syncthing/lib/automaxprocs"
|
||||
"github.com/syncthing/syncthing/lib/build"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
"github.com/syncthing/syncthing/lib/tlsutil"
|
||||
|
||||
@@ -14,6 +14,8 @@ import (
|
||||
"net/http"
|
||||
"os"
|
||||
"time"
|
||||
|
||||
_ "github.com/syncthing/syncthing/lib/automaxprocs"
|
||||
)
|
||||
|
||||
type event struct {
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
||||
_ "github.com/syncthing/syncthing/lib/automaxprocs"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
"github.com/syncthing/syncthing/lib/scanner"
|
||||
)
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"os"
|
||||
"time"
|
||||
|
||||
_ "github.com/syncthing/syncthing/lib/automaxprocs"
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/discover"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"fmt"
|
||||
"os"
|
||||
|
||||
_ "github.com/syncthing/syncthing/lib/automaxprocs"
|
||||
"github.com/syncthing/syncthing/lib/fs"
|
||||
"github.com/syncthing/syncthing/lib/ignore"
|
||||
)
|
||||
|
||||
@@ -15,6 +15,8 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
_ "github.com/syncthing/syncthing/lib/automaxprocs"
|
||||
)
|
||||
|
||||
func main() {
|
||||
@@ -43,7 +45,7 @@ func generateFiles(dir string, files, maxexp int, srcname string) error {
|
||||
}
|
||||
|
||||
p0 := filepath.Join(dir, string(n[0]), n[0:2])
|
||||
err = os.MkdirAll(p0, 0755)
|
||||
err = os.MkdirAll(p0, 0o755)
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
@@ -82,7 +84,7 @@ func generateOneFile(fd io.ReadSeeker, p1 string, s int64) error {
|
||||
return err
|
||||
}
|
||||
|
||||
os.Chmod(p1, os.FileMode(rand.Intn(0777)|0400))
|
||||
os.Chmod(p1, os.FileMode(rand.Intn(0o777)|0o400))
|
||||
|
||||
t := time.Now().Add(-time.Duration(rand.Intn(30*86400)) * time.Second)
|
||||
return os.Chtimes(p1, t, t)
|
||||
|
||||
@@ -21,14 +21,14 @@ import (
|
||||
"time"
|
||||
|
||||
lru "github.com/hashicorp/golang-lru/v2"
|
||||
"github.com/syncthing/syncthing/lib/httpcache"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
|
||||
"github.com/oschwald/geoip2-golang"
|
||||
"github.com/prometheus/client_golang/prometheus"
|
||||
"github.com/prometheus/client_golang/prometheus/promhttp"
|
||||
"github.com/syncthing/syncthing/cmd/strelaypoolsrv/auto"
|
||||
"github.com/syncthing/syncthing/lib/assets"
|
||||
_ "github.com/syncthing/syncthing/lib/automaxprocs"
|
||||
"github.com/syncthing/syncthing/lib/httpcache"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
"github.com/syncthing/syncthing/lib/rand"
|
||||
"github.com/syncthing/syncthing/lib/relay/client"
|
||||
"github.com/syncthing/syncthing/lib/sync"
|
||||
|
||||
@@ -19,19 +19,18 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
_ "github.com/syncthing/syncthing/lib/automaxprocs"
|
||||
"github.com/syncthing/syncthing/lib/build"
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/nat"
|
||||
"github.com/syncthing/syncthing/lib/osutil"
|
||||
_ "github.com/syncthing/syncthing/lib/pmp"
|
||||
syncthingprotocol "github.com/syncthing/syncthing/lib/protocol"
|
||||
"github.com/syncthing/syncthing/lib/relay/protocol"
|
||||
"github.com/syncthing/syncthing/lib/tlsutil"
|
||||
"golang.org/x/time/rate"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/nat"
|
||||
_ "github.com/syncthing/syncthing/lib/pmp"
|
||||
_ "github.com/syncthing/syncthing/lib/upnp"
|
||||
|
||||
syncthingprotocol "github.com/syncthing/syncthing/lib/protocol"
|
||||
"golang.org/x/time/rate"
|
||||
)
|
||||
|
||||
var (
|
||||
|
||||
@@ -14,6 +14,7 @@ import (
|
||||
"path/filepath"
|
||||
"time"
|
||||
|
||||
_ "github.com/syncthing/syncthing/lib/automaxprocs"
|
||||
syncthingprotocol "github.com/syncthing/syncthing/lib/protocol"
|
||||
"github.com/syncthing/syncthing/lib/relay/client"
|
||||
"github.com/syncthing/syncthing/lib/relay/protocol"
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"log"
|
||||
"os"
|
||||
|
||||
_ "github.com/syncthing/syncthing/lib/automaxprocs"
|
||||
"github.com/syncthing/syncthing/lib/signature"
|
||||
"github.com/syncthing/syncthing/lib/upgrade"
|
||||
)
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/alecthomas/kong"
|
||||
_ "github.com/syncthing/syncthing/lib/automaxprocs"
|
||||
"github.com/syncthing/syncthing/lib/httpcache"
|
||||
"github.com/syncthing/syncthing/lib/upgrade"
|
||||
)
|
||||
|
||||
@@ -26,6 +26,7 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
_ "github.com/syncthing/syncthing/lib/automaxprocs"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
)
|
||||
|
||||
@@ -157,7 +158,7 @@ func saveCert(priv interface{}, derBytes []byte) {
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0600)
|
||||
keyOut, err := os.OpenFile("key.pem", os.O_WRONLY|os.O_CREATE|os.O_TRUNC, 0o600)
|
||||
if err != nil {
|
||||
fmt.Println(err)
|
||||
os.Exit(1)
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"os"
|
||||
"time"
|
||||
|
||||
_ "github.com/syncthing/syncthing/lib/automaxprocs"
|
||||
"github.com/syncthing/syncthing/lib/sha256"
|
||||
)
|
||||
|
||||
|
||||
@@ -22,7 +22,6 @@ import (
|
||||
"path"
|
||||
"path/filepath"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"runtime/pprof"
|
||||
"sort"
|
||||
"strconv"
|
||||
@@ -31,7 +30,9 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/alecthomas/kong"
|
||||
_ "github.com/syncthing/syncthing/lib/automaxprocs"
|
||||
"github.com/thejerf/suture/v4"
|
||||
"github.com/willabides/kongplete"
|
||||
|
||||
"github.com/syncthing/syncthing/cmd/syncthing/cli"
|
||||
"github.com/syncthing/syncthing/cmd/syncthing/cmdutil"
|
||||
@@ -133,10 +134,11 @@ var (
|
||||
// commands and options here are top level commands to syncthing.
|
||||
// Cli is just a placeholder for the help text (see main).
|
||||
var entrypoint struct {
|
||||
Serve serveOptions `cmd:"" help:"Run Syncthing"`
|
||||
Generate generate.CLI `cmd:"" help:"Generate key and config, then exit"`
|
||||
Decrypt decrypt.CLI `cmd:"" help:"Decrypt or verify an encrypted folder"`
|
||||
Cli cli.CLI `cmd:"" help:"Command line interface for Syncthing"`
|
||||
Serve serveOptions `cmd:"" help:"Run Syncthing"`
|
||||
Generate generate.CLI `cmd:"" help:"Generate key and config, then exit"`
|
||||
Decrypt decrypt.CLI `cmd:"" help:"Decrypt or verify an encrypted folder"`
|
||||
Cli cli.CLI `cmd:"" help:"Command line interface for Syncthing"`
|
||||
InstallCompletions kongplete.InstallCompletions `cmd:"" help:"Print commands to install shell completions"`
|
||||
}
|
||||
|
||||
// serveOptions are the options for the `syncthing serve` command.
|
||||
@@ -247,6 +249,7 @@ func main() {
|
||||
log.Fatal(err)
|
||||
}
|
||||
|
||||
kongplete.Complete(parser)
|
||||
ctx, err := parser.Parse(args)
|
||||
parser.FatalIfErrorf(err)
|
||||
ctx.BindTo(l, (*logger.Logger)(nil)) // main logger available to subcommands
|
||||
@@ -648,10 +651,6 @@ func syncthingMain(options serveOptions) {
|
||||
|
||||
setupSignalHandling(app)
|
||||
|
||||
if os.Getenv("GOMAXPROCS") == "" {
|
||||
runtime.GOMAXPROCS(runtime.NumCPU())
|
||||
}
|
||||
|
||||
if options.DebugProfileCPU {
|
||||
f, err := os.Create(fmt.Sprintf("cpu-%d.pprof", os.Getpid()))
|
||||
if err != nil {
|
||||
@@ -862,6 +861,7 @@ func cleanConfigDirectory() {
|
||||
"backup-of-v0.8": 30 * 24 * time.Hour, // these neither
|
||||
"tmp-index-sorter.*": time.Minute, // these should never exist on startup
|
||||
"support-bundle-*": 30 * 24 * time.Hour, // keep old support bundle zip or folder for a month
|
||||
"csrftokens.txt": 0, // deprecated, remove immediately
|
||||
}
|
||||
|
||||
for pat, dur := range patterns {
|
||||
|
||||
@@ -13,6 +13,7 @@ import (
|
||||
"github.com/alecthomas/kong"
|
||||
"github.com/syncthing/syncthing/cmd/ursrv/aggregate"
|
||||
"github.com/syncthing/syncthing/cmd/ursrv/serve"
|
||||
_ "github.com/syncthing/syncthing/lib/automaxprocs"
|
||||
)
|
||||
|
||||
type CLI struct {
|
||||
|
||||
@@ -71,10 +71,12 @@ var (
|
||||
{regexp.MustCompile(`\sandroid-.*vagrant@basebox-stretch64`), "F-Droid"},
|
||||
{regexp.MustCompile(`\svagrant@bullseye`), "F-Droid"},
|
||||
{regexp.MustCompile(`\sbuilduser@(archlinux|svetlemodry)`), "Arch (3rd party)"},
|
||||
{regexp.MustCompile(`\ssyncthing@archlinux`), "Arch (3rd party)"},
|
||||
{regexp.MustCompile(`@debian`), "Debian (3rd party)"},
|
||||
{regexp.MustCompile(`@fedora`), "Fedora (3rd party)"},
|
||||
{regexp.MustCompile(`\sbrew@`), "Homebrew (3rd party)"},
|
||||
{regexp.MustCompile(`\sroot@buildkitsandbox`), "LinuxServer.io (3rd party)"},
|
||||
{regexp.MustCompile(`\sports@freebsd`), "FreeBSD (3rd party)"},
|
||||
{regexp.MustCompile(`.`), "Others"},
|
||||
}
|
||||
)
|
||||
|
||||
82
go.mod
82
go.mod
@@ -1,78 +1,94 @@
|
||||
module github.com/syncthing/syncthing
|
||||
|
||||
go 1.20
|
||||
go 1.21.0
|
||||
|
||||
require (
|
||||
github.com/AudriusButkevicius/recli v0.0.7-0.20220911121932-d000ce8fbf0f
|
||||
github.com/alecthomas/kong v0.8.1
|
||||
github.com/calmh/incontainer v0.0.0-20221224152218-b3e71b103d7a
|
||||
github.com/calmh/incontainer v1.0.0
|
||||
github.com/calmh/xdr v1.1.0
|
||||
github.com/ccding/go-stun v0.1.4
|
||||
github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/chmduquesne/rollinghash v4.0.0+incompatible
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
|
||||
github.com/d4l3k/messagediff v1.2.1
|
||||
github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568
|
||||
github.com/getsentry/raven-go v0.2.0
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect
|
||||
github.com/go-ldap/ldap/v3 v3.4.6
|
||||
github.com/gobwas/glob v0.2.3
|
||||
github.com/gogo/protobuf v1.3.2
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/greatroar/blobloom v0.7.2
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7
|
||||
github.com/jackpal/gateway v1.0.10
|
||||
github.com/jackpal/gateway v1.0.13
|
||||
github.com/jackpal/go-nat-pmp v1.0.2
|
||||
github.com/julienschmidt/httprouter v1.3.0
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51
|
||||
github.com/klauspost/cpuid/v2 v2.2.6 // indirect
|
||||
github.com/lib/pq v1.10.9
|
||||
github.com/maruel/panicparse/v2 v2.3.1
|
||||
github.com/maxbrunsfeld/counterfeiter/v6 v6.5.0
|
||||
github.com/maxbrunsfeld/counterfeiter/v6 v6.8.1
|
||||
github.com/minio/sha256-simd v1.0.1
|
||||
github.com/miscreant/miscreant.go v0.0.0-20200214223636-26d376326b75
|
||||
github.com/oschwald/geoip2-golang v1.9.0
|
||||
github.com/pierrec/lz4/v4 v4.1.18
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/prometheus/client_golang v1.17.0
|
||||
github.com/prometheus/common v0.45.0 // indirect
|
||||
github.com/prometheus/procfs v0.12.0 // indirect
|
||||
github.com/quic-go/quic-go v0.40.1
|
||||
github.com/pierrec/lz4/v4 v4.1.21
|
||||
github.com/prometheus/client_golang v1.19.0
|
||||
github.com/quic-go/quic-go v0.41.0
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475
|
||||
github.com/shirou/gopsutil/v3 v3.23.11
|
||||
github.com/shirou/gopsutil/v3 v3.24.2
|
||||
github.com/syncthing/notify v0.0.0-20210616190510-c6b7342338d2
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d
|
||||
github.com/thejerf/suture/v4 v4.0.2
|
||||
github.com/urfave/cli v1.22.14
|
||||
github.com/vitrun/qart v0.0.0-20160531060029-bf64b92db6b0
|
||||
golang.org/x/crypto v0.16.0
|
||||
golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb
|
||||
golang.org/x/mod v0.14.0 // indirect
|
||||
golang.org/x/net v0.19.0
|
||||
golang.org/x/sys v0.15.0
|
||||
github.com/willabides/kongplete v0.4.0
|
||||
go.uber.org/automaxprocs v1.5.3
|
||||
golang.org/x/crypto v0.21.0
|
||||
golang.org/x/net v0.21.0
|
||||
golang.org/x/sys v0.18.0
|
||||
golang.org/x/text v0.14.0
|
||||
golang.org/x/time v0.5.0
|
||||
golang.org/x/tools v0.16.1
|
||||
google.golang.org/protobuf v1.31.0
|
||||
golang.org/x/tools v0.18.0
|
||||
google.golang.org/protobuf v1.32.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
|
||||
github.com/alecthomas/assert/v2 v2.5.0 // indirect
|
||||
github.com/alecthomas/repr v0.3.0 // indirect
|
||||
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/certifi/gocertifi v0.0.0-20210507211836-431795d63e8d // indirect
|
||||
github.com/cespare/xxhash/v2 v2.2.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.3 // indirect
|
||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.5 // indirect
|
||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||
github.com/go-task/slim-sprig v0.0.0-20230315185526-52ccab3ef572 // indirect
|
||||
github.com/google/pprof v0.0.0-20231212022811-ec68065c825e // indirect
|
||||
github.com/google/uuid v1.4.0 // indirect
|
||||
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.13.2 // indirect
|
||||
github.com/golang/snappy v0.0.4 // indirect
|
||||
github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 // indirect
|
||||
github.com/kr/text v0.2.0 // indirect
|
||||
github.com/nxadm/tail v1.4.11 // indirect
|
||||
github.com/onsi/ginkgo/v2 v2.16.0 // indirect
|
||||
github.com/onsi/gomega v1.31.1 // indirect
|
||||
github.com/oschwald/maxminddb-golang v1.12.0 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect
|
||||
github.com/prometheus/client_model v0.5.0 // indirect
|
||||
github.com/quic-go/qtls-go1-20 v0.4.1 // indirect
|
||||
github.com/pkg/errors v0.9.1 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||
github.com/posener/complete v1.2.3 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
|
||||
github.com/prometheus/client_model v0.6.0 // indirect
|
||||
github.com/prometheus/common v0.49.0 // indirect
|
||||
github.com/prometheus/procfs v0.12.0 // indirect
|
||||
github.com/riywo/loginshell v0.0.0-20200815045211-7d26008be1ab // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.3 // indirect
|
||||
go.uber.org/mock v0.3.0 // indirect
|
||||
github.com/stretchr/objx v0.5.2 // indirect
|
||||
github.com/stretchr/testify v1.9.0 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||
go.uber.org/mock v0.4.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 // indirect
|
||||
golang.org/x/mod v0.16.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
// https://github.com/gobwas/glob/pull/55
|
||||
|
||||
157
go.sum
157
go.sum
@@ -3,18 +3,21 @@ github.com/AudriusButkevicius/recli v0.0.7-0.20220911121932-d000ce8fbf0f/go.mod
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 h1:mFRzDkZVAjdal+s7s0MwaRv9igoPqLRdzOLzw/8Xvq8=
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358/go.mod h1:chxPXzSsl7ZWRAuOIE23GDNzjWuZquvFlgA8xmpunjU=
|
||||
github.com/BurntSushi/toml v1.3.2/go.mod h1:CxXYINrC8qIiEnFrOxCa7Jy5BFHlXnUU2pbicEuybxQ=
|
||||
github.com/alecthomas/assert/v2 v2.1.0 h1:tbredtNcQnoSd3QBhQWI7QZ3XHOVkw1Moklp2ojoH/0=
|
||||
github.com/alecthomas/assert/v2 v2.5.0 h1:OJKYg53BQx06/bMRBSPDCO49CbCDNiUQXwdoNrt6x5w=
|
||||
github.com/alecthomas/assert/v2 v2.5.0/go.mod h1:fw5suVxB+wfYJ3291t0hRTqtGzFYdSwstnRQdaQx2DM=
|
||||
github.com/alecthomas/kong v0.8.1 h1:acZdn3m4lLRobeh3Zi2S2EpnXTd1mOL6U7xVml+vfkY=
|
||||
github.com/alecthomas/kong v0.8.1/go.mod h1:n1iCIO2xS46oE8ZfYCNDqdR0b0wZNrXAIAqro/2132U=
|
||||
github.com/alecthomas/repr v0.1.0 h1:ENn2e1+J3k09gyj2shc0dHr/yjaWSHRlrJ4DPMevDqE=
|
||||
github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74 h1:Kk6a4nehpJ3UuJRqlA3JxYxBZEqCeOmATOvrbT4p9RA=
|
||||
github.com/alecthomas/repr v0.3.0 h1:NeYzUPfjjlqHY4KtzgKJiWd6sVq2eNUPTi34PiFGjY8=
|
||||
github.com/alecthomas/repr v0.3.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
|
||||
github.com/alexbrainman/sspi v0.0.0-20210105120005-909beea2cc74/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
|
||||
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa h1:LHTHcTQiSGT7VVbI0o4wBRNQIgn917usHWOd6VAffYI=
|
||||
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/calmh/glob v0.0.0-20220615080505-1d823af5017b h1:Fjm4GuJ+TGMgqfGHN42IQArJb77CfD/mAwLbDUoJe6g=
|
||||
github.com/calmh/glob v0.0.0-20220615080505-1d823af5017b/go.mod h1:91K7jfEsgJSyfSrX+gmrRfZMtntx6JsHolWubGXDopg=
|
||||
github.com/calmh/incontainer v0.0.0-20221224152218-b3e71b103d7a h1:CjrQbpvnV4BMzPHf0r8p2FAvzEp/bp761CmBBeNIHXI=
|
||||
github.com/calmh/incontainer v0.0.0-20221224152218-b3e71b103d7a/go.mod h1:eOhqnw15c9X+4RNBe0W3HlUZFfX16O0EDsCOInTndHY=
|
||||
github.com/calmh/incontainer v1.0.0 h1:g2cTUtZuFGmMGX8GoykPkN1Judj2uw8/3/aEtq4Z/rg=
|
||||
github.com/calmh/incontainer v1.0.0/go.mod h1:eOhqnw15c9X+4RNBe0W3HlUZFfX16O0EDsCOInTndHY=
|
||||
github.com/calmh/xdr v1.1.0 h1:U/Dd4CXNLoo8EiQ4ulJUXkgO1/EyQLgDKLgpY1SOoJE=
|
||||
github.com/calmh/xdr v1.1.0/go.mod h1:E8sz2ByAdXC8MbANf1LCRYzedSnnc+/sXXJs/PVqoeg=
|
||||
github.com/ccding/go-stun v0.1.4 h1:lC0co3Q3vjAuu2Jz098WivVPBPbemYFqbwE1syoka4M=
|
||||
@@ -31,6 +34,7 @@ github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMn
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.2/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||
github.com/d4l3k/messagediff v1.2.1 h1:ZcAIMYsUg0EAp9X+tt8/enBE/Q8Yd5kzPynLyKptt9U=
|
||||
github.com/d4l3k/messagediff v1.2.1/go.mod h1:Oozbb1TVXFac9FtSIxHBMnBCq2qeH/2KkEQxENCrlLo=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
@@ -40,15 +44,18 @@ github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568 h1:BMXYYRWT
|
||||
github.com/flynn-archive/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:rZfgFAXFS/z/lEd6LJmf9HVZ1LkgYiHx5pHhV5DR16M=
|
||||
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
|
||||
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
|
||||
github.com/fsnotify/fsnotify v1.5.4 h1:jRbGcIw6P2Meqdwuo0H1p6JVLbL5DHKAKlYndzMwVZI=
|
||||
github.com/fsnotify/fsnotify v1.5.4/go.mod h1:OVB6XrOHzAwXMpEM7uPOzcehqUV2UqJxmVXmkdnm1bU=
|
||||
github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw=
|
||||
github.com/fsnotify/fsnotify v1.7.0 h1:8JEhPFa5W2WU7YfeZzPNqzMP6Lwt7L2715Ggo0nosvA=
|
||||
github.com/fsnotify/fsnotify v1.7.0/go.mod h1:40Bi/Hjc2AVfZrqy+aj+yEI+/bRxZnMJyTJwOpGvigM=
|
||||
github.com/getsentry/raven-go v0.2.0 h1:no+xWJRb5ZI7eE8TWgIq1jLulQiIoLG0IfYxv5JYMGs=
|
||||
github.com/getsentry/raven-go v0.2.0/go.mod h1:KungGk8q33+aIAZUIVWZDr2OfAEBsO49PX4NzFV5kcQ=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.5 h1:MNHlNMBDgEKD4TcKr36vQN68BA00aDfjIt3/bD50WnA=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/go-ldap/ldap/v3 v3.4.6 h1:ert95MdbiG7aWo/oPYp9btL3KJlMPKnP58r09rI8T+A=
|
||||
github.com/go-ldap/ldap/v3 v3.4.6/go.mod h1:IGMQANNtxpsOzj7uUAMjpGBaOVTC4DYyIy8VsTdxmtc=
|
||||
github.com/go-logr/logr v1.3.0 h1:2y3SDp0ZXuc6/cjLSZ+Q3ir+QB9T/iG5yYRXqsagWSY=
|
||||
github.com/go-logr/logr v1.4.1 h1:pKouT5E8xu9zeFC39JXRDukb6JFQPXM5p5I91188VAQ=
|
||||
github.com/go-logr/logr v1.4.1/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
|
||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
||||
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
||||
@@ -67,6 +74,7 @@ github.com/golang/protobuf v1.4.2/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
|
||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||
github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
|
||||
@@ -79,20 +87,27 @@ github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeN
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/pprof v0.0.0-20210407192527-94a9f03dee38/go.mod h1:kpwsk12EmLew5upagYY7GY0pfYCcupk39gWOCRROcvE=
|
||||
github.com/google/pprof v0.0.0-20231212022811-ec68065c825e h1:bwOy7hAFd0C91URzMIEBfr6BAz29yk7Qj0cy6S7DJlU=
|
||||
github.com/google/pprof v0.0.0-20231212022811-ec68065c825e/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||
github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7 h1:y3N7Bm7Y9/CtpiVkw/ZWj6lSlDF3F74SfKwfTCer72Q=
|
||||
github.com/google/pprof v0.0.0-20240227163752-401108e1b7e7/go.mod h1:czg5+yv1E0ZGTi6S6vVK1mke0fV+FaUhNGcd6VRS9Ik=
|
||||
github.com/google/uuid v1.3.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.4.0 h1:MtMxsa51/r9yyhkyLsVeVt0B+BGQZzpQiTQ4eHZ8bc4=
|
||||
github.com/google/uuid v1.4.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/greatroar/blobloom v0.7.2 h1:F30MGLHOcb4zr0pwCPTcKdlTM70rEgkf+LzdUPc5ss8=
|
||||
github.com/greatroar/blobloom v0.7.2/go.mod h1:mjMJ1hh1wjGVfr93QIHJ6FfDNVrA0IELv8OvMHJxHKs=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/errwrap v1.1.0 h1:OxrOeh75EUXMY8TBjag2fzXGZ40LB6IKw45YeGUDY2I=
|
||||
github.com/hashicorp/errwrap v1.1.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
github.com/hashicorp/go-multierror v1.0.0/go.mod h1:dHtQlpGsu+cZNNAkkCN/P3hoUDHhCYQXV3UM06sGGrk=
|
||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7 h1:a+bsQ5rvGLjzHuww6tVxozPZFVghXaHOwFs4luLUK2k=
|
||||
github.com/hashicorp/golang-lru/v2 v2.0.7/go.mod h1:QeFd9opnmA6QUJc5vARoKUSoFhyfM2/ZepoAG6RGpeM=
|
||||
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
|
||||
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/ianlancetaylor/demangle v0.0.0-20200824232613-28f6c0f3b639/go.mod h1:aSSvb/t6k1mPoxDqO4vJh6VOCGPwU4O0C2/Eqndh1Sc=
|
||||
github.com/jackpal/gateway v1.0.10 h1:7g3fDo4Cd3RnTu6PzAfw6poO4Y81uNxrxFQFsBFSzJM=
|
||||
github.com/jackpal/gateway v1.0.10/go.mod h1:+uPBgIllrbkwYCAoDkGSZbjvpre/bGYAFCYIcrH+LHs=
|
||||
github.com/jackpal/gateway v1.0.13 h1:fJccMvawxx0k7S1q7Fy/SXFE0R3hMXkMuw8y9SofWAk=
|
||||
github.com/jackpal/gateway v1.0.13/go.mod h1:6c8LjW+FVESFmwxaXySkt7fU98Yv806ADS3OY6Cvh2U=
|
||||
github.com/jackpal/go-nat-pmp v1.0.2 h1:KzKSgb7qkJvOUTqYl9/Hg/me3pWgBmERKrTGD7BdWus=
|
||||
github.com/jackpal/go-nat-pmp v1.0.2/go.mod h1:QPH045xvCAeXUZOxsnwmrtiCoxIr9eob+4orBN1SBKc=
|
||||
github.com/julienschmidt/httprouter v1.3.0 h1:U0609e9tgbseu3rBINet9P48AI/D3oJs4dN7jwJOQ1U=
|
||||
@@ -101,8 +116,12 @@ github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51 h1:Z9n2FFNU
|
||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
|
||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
|
||||
github.com/klauspost/cpuid/v2 v2.2.6 h1:ndNyv040zDGIDh8thGkXYjnFtiN02M1PVVF+JE/48xc=
|
||||
github.com/klauspost/cpuid/v2 v2.2.6/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7 h1:ZWSB3igEs+d0qvnxR/ZBzXVmxkgt8DdzP6m9pfuVLDM=
|
||||
github.com/klauspost/cpuid/v2 v2.2.7/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||
@@ -110,76 +129,87 @@ github.com/maruel/panicparse/v2 v2.3.1 h1:NtJavmbMn0DyzmmSStE8yUsmPZrZmudPH7kplx
|
||||
github.com/maruel/panicparse/v2 v2.3.1/go.mod h1:s3UmQB9Fm/n7n/prcD2xBGDkwXD6y2LeZnhbEXvs9Dg=
|
||||
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0 h1:jWpvCLoY8Z/e3VKvlsiIGKtc+UG6U5vzxaoagmhXfyg=
|
||||
github.com/matttproud/golang_protobuf_extensions/v2 v2.0.0/go.mod h1:QUyp042oQthUoa9bqDv0ER0wrtXnBruoNd7aNjkbP+k=
|
||||
github.com/maxbrunsfeld/counterfeiter/v6 v6.5.0 h1:rBhB9Rls+yb8kA4x5a/cWxOufWfXt24E+kq4YlbGj3g=
|
||||
github.com/maxbrunsfeld/counterfeiter/v6 v6.5.0/go.mod h1:fJ0UAZc1fx3xZhU4eSHQDJ1ApFmTVhp5VTpV9tm2ogg=
|
||||
github.com/maxbrunsfeld/counterfeiter/v6 v6.8.1 h1:NicmruxkeqHjDv03SfSxqmaLuisddudfP3h5wdXFbhM=
|
||||
github.com/maxbrunsfeld/counterfeiter/v6 v6.8.1/go.mod h1:eyp4DdUJAKkr9tvxR3jWhw2mDK7CWABMG5r9uyaKC7I=
|
||||
github.com/mgutz/ansi v0.0.0-20200706080929-d51e80ef957d/go.mod h1:01TrycV0kFyexm33Z7vhZRXopbI8J3TDReVlkTgMUxE=
|
||||
github.com/minio/sha256-simd v1.0.1 h1:6kaan5IFmwTNynnKKpDHe6FWHohJOHhCPchzK49dzMM=
|
||||
github.com/minio/sha256-simd v1.0.1/go.mod h1:Pz6AKMiUdngCLpeTL/RJY1M9rUuPMYujV5xJjtbRSN8=
|
||||
github.com/miscreant/miscreant.go v0.0.0-20200214223636-26d376326b75 h1:cUVxyR+UfmdEAZGJ8IiKld1O0dbGotEnkMolG5hfMSY=
|
||||
github.com/miscreant/miscreant.go v0.0.0-20200214223636-26d376326b75/go.mod h1:pBbZyGwC5i16IBkjVKoy/sznA8jPD/K9iedwe1ESE6w=
|
||||
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
|
||||
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
|
||||
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
|
||||
github.com/nxadm/tail v1.4.11 h1:8feyoE3OzPrcshW5/MJ4sGESc5cqmGkGCWlco4l0bqY=
|
||||
github.com/nxadm/tail v1.4.11/go.mod h1:OTaG3NK980DZzxbRq6lEuzgU+mug70nY11sMd4JXXHc=
|
||||
github.com/onsi/ginkgo v1.6.0/go.mod h1:lLunBs/Ym6LB5Z9jYTR76FiuTmxDTDusOGeTQH+WWjE=
|
||||
github.com/onsi/ginkgo v1.12.1/go.mod h1:zj2OWP4+oCPe1qIXoGWkgMRwljMUYCdkwsT2108oapk=
|
||||
github.com/onsi/ginkgo v1.16.4/go.mod h1:dX+/inL/fNMqNlz0e9LfyB9TswhZpCVdJM/Z6Vvnwo0=
|
||||
github.com/onsi/ginkgo v1.16.5 h1:8xi0RTUf59SOSfEtZMvwTvXYMzG4gV23XVHOZiXNtnE=
|
||||
github.com/onsi/ginkgo v1.16.5/go.mod h1:+E8gABHa3K6zRBolWtd+ROzc/U5bkGt0FwiG042wbpU=
|
||||
github.com/onsi/ginkgo/v2 v2.1.3/go.mod h1:vw5CSIxN1JObi/U8gcbwft7ZxR2dgaR70JSE3/PpL4c=
|
||||
github.com/onsi/ginkgo/v2 v2.13.2 h1:Bi2gGVkfn6gQcjNjZJVO8Gf0FHzMPf2phUei9tejVMs=
|
||||
github.com/onsi/ginkgo/v2 v2.13.2/go.mod h1:XStQ8QcGwLyF4HdfcZB8SFOS/MWCgDuXMSBe6zrvLgM=
|
||||
github.com/onsi/ginkgo/v2 v2.16.0 h1:7q1w9frJDzninhXxjZd+Y/x54XNjG/UlRLIYPZafsPM=
|
||||
github.com/onsi/ginkgo/v2 v2.16.0/go.mod h1:llBI3WDLL9Z6taip6f33H76YcWtJv+7R3HigUjbIBOs=
|
||||
github.com/onsi/gomega v1.7.1/go.mod h1:XdKZgCCFLUoM/7CFJVPcG8C1xQ1AJ0vpAezJrB7JYyY=
|
||||
github.com/onsi/gomega v1.10.1/go.mod h1:iN09h71vgCQne3DLsj+A5owkum+a2tYe+TOCB1ybHNo=
|
||||
github.com/onsi/gomega v1.17.0/go.mod h1:HnhC7FXeEQY45zxNK3PPoIUhzk/80Xly9PcubAlGdZY=
|
||||
github.com/onsi/gomega v1.19.0/go.mod h1:LY+I3pBVzYsTBU1AnDwOSxaYi9WoWiqgwooUqq9yPro=
|
||||
github.com/onsi/gomega v1.29.0 h1:KIA/t2t5UBzoirT4H9tsML45GEbo3ouUnBHsCfD2tVg=
|
||||
github.com/onsi/gomega v1.31.1 h1:KYppCUK+bUgAZwHOu7EXVBKyQA6ILvOESHkn/tgoqvo=
|
||||
github.com/onsi/gomega v1.31.1/go.mod h1:y40C95dwAD1Nz36SsEnxvfFe8FFfNxzI5eJ0EYGyAy0=
|
||||
github.com/oschwald/geoip2-golang v1.9.0 h1:uvD3O6fXAXs+usU+UGExshpdP13GAqp4GBrzN7IgKZc=
|
||||
github.com/oschwald/geoip2-golang v1.9.0/go.mod h1:BHK6TvDyATVQhKNbQBdrj9eAvuwOMi2zSFXizL3K81Y=
|
||||
github.com/oschwald/maxminddb-golang v1.12.0 h1:9FnTOD0YOhP7DGxGsq4glzpGy5+w7pq50AS6wALUMYs=
|
||||
github.com/oschwald/maxminddb-golang v1.12.0/go.mod h1:q0Nob5lTCqyQ8WT6FYgS1L7PXKVVbgiymefNwIjPzgY=
|
||||
github.com/pierrec/lz4/v4 v4.1.18 h1:xaKrnTkyoqfh1YItXl56+6KJNVYWlEEPuAQW9xsplYQ=
|
||||
github.com/pierrec/lz4/v4 v4.1.18/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pierrec/lz4/v4 v4.1.21 h1:yOVMLb6qSIDP67pl/5F7RepeKYu/VmTyEXvuMI5d9mQ=
|
||||
github.com/pierrec/lz4/v4 v4.1.21/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/posener/complete v1.2.3 h1:NP0eAhjcjImqslEwo/1hq7gpajME0fTLTezBKDqfXqo=
|
||||
github.com/posener/complete v1.2.3/go.mod h1:WZIdtGGp+qx0sLrYKtIRAruyNpv6hFCicSgv7Sy7s/s=
|
||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b h1:0LFwY6Q3gMACTjAbMZBjXAqTOzOwFaj2Ld6cjeQ7Rig=
|
||||
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/prometheus/client_golang v1.17.0 h1:rl2sfwZMtSthVU752MqfjQozy7blglC+1SOtjMAMh+Q=
|
||||
github.com/prometheus/client_golang v1.17.0/go.mod h1:VeL+gMmOAxkS2IqfCq0ZmHSL+LjWfWDUmp1mBz9JgUY=
|
||||
github.com/prometheus/client_model v0.5.0 h1:VQw1hfvPvk3Uv6Qf29VrPF32JB6rtbgI6cYPYQjL0Qw=
|
||||
github.com/prometheus/client_model v0.5.0/go.mod h1:dTiFglRmd66nLR9Pv9f0mZi7B7fk5Pm3gvsjB5tr+kI=
|
||||
github.com/prometheus/common v0.45.0 h1:2BGz0eBc2hdMDLnO/8n0jeB3oPrt2D08CekT0lneoxM=
|
||||
github.com/prometheus/common v0.45.0/go.mod h1:YJmSTw9BoKxJplESWWxlbyttQR4uaEcGyv9MZjVOJsY=
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 h1:o4JXh1EVt9k/+g42oCprj/FisM4qX9L3sZB3upGN2ZU=
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
|
||||
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
|
||||
github.com/prometheus/client_golang v1.19.0 h1:ygXvpU1AoN1MhdzckN+PyD9QJOSD4x7kmXYlnfbA6JU=
|
||||
github.com/prometheus/client_golang v1.19.0/go.mod h1:ZRM9uEAypZakd+q/x7+gmsvXdURP+DABIEIjnmDdp+k=
|
||||
github.com/prometheus/client_model v0.6.0 h1:k1v3CzpSRUTrKMppY35TLwPvxHqBu0bYgxZzqGIgaos=
|
||||
github.com/prometheus/client_model v0.6.0/go.mod h1:NTQHnmxFpouOD0DpvP4XujX3CdOAGQPoaGhyTchlyt8=
|
||||
github.com/prometheus/common v0.49.0 h1:ToNTdK4zSnPVJmh698mGFkDor9wBI/iGaJy5dbH1EgI=
|
||||
github.com/prometheus/common v0.49.0/go.mod h1:Kxm+EULxRbUkjGU6WFsQqo3ORzB4tyKvlWFOE9mB2sE=
|
||||
github.com/prometheus/procfs v0.12.0 h1:jluTpSng7V9hY0O2R9DzzJHYb2xULk9VTR1V1R/k6Bo=
|
||||
github.com/prometheus/procfs v0.12.0/go.mod h1:pcuDEFsWDnvcgNzo4EEweacyhjeA9Zk3cnaOZAZEfOo=
|
||||
github.com/quic-go/qtls-go1-20 v0.4.1 h1:D33340mCNDAIKBqXuAvexTNMUByrYmFYVfKfDN5nfFs=
|
||||
github.com/quic-go/qtls-go1-20 v0.4.1/go.mod h1:X9Nh97ZL80Z+bX/gUXMbipO6OxdiDi58b/fMC9mAL+k=
|
||||
github.com/quic-go/quic-go v0.40.1 h1:X3AGzUNFs0jVuO3esAGnTfvdgvL4fq655WaOi1snv1Q=
|
||||
github.com/quic-go/quic-go v0.40.1/go.mod h1:PeN7kuVJ4xZbxSv/4OX6S1USOX8MJvydwpTx31vx60c=
|
||||
github.com/quic-go/quic-go v0.41.0 h1:aD8MmHfgqTURWNJy48IYFg2OnxwHT3JL7ahGs73lb4k=
|
||||
github.com/quic-go/quic-go v0.41.0/go.mod h1:qCkNjqczPEvgsOnxZ0eCD14lv+B2LHlFAB++CNOh9hA=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475 h1:N/ElC8H3+5XpJzTSTfLsJV/mx9Q9g7kxmchpfZyxgzM=
|
||||
github.com/rcrowley/go-metrics v0.0.0-20201227073835-cf1acfcdf475/go.mod h1:bCqnVzQkZxMG4s8nGwiZ5l3QUCyqpo9Y+/ZMZ9VjZe4=
|
||||
github.com/riywo/loginshell v0.0.0-20200815045211-7d26008be1ab h1:ZjX6I48eZSFetPb41dHudEyVr5v953N15TsNZXlkcWY=
|
||||
github.com/riywo/loginshell v0.0.0-20200815045211-7d26008be1ab/go.mod h1:/PfPXh0EntGc3QAAyUaviy4S9tzy4Zp0e2ilq4voC6E=
|
||||
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
|
||||
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sclevine/spec v1.4.0 h1:z/Q9idDcay5m5irkZ28M7PtQM4aOISzOpj4bUPkDee8=
|
||||
github.com/shirou/gopsutil/v3 v3.23.11 h1:i3jP9NjCPUz7FiZKxlMnODZkdSIp2gnzfrvsu9CuWEQ=
|
||||
github.com/shirou/gopsutil/v3 v3.23.11/go.mod h1:1FrWgea594Jp7qmjHUUPlJDTPgcsb9mGnXDxavtikzM=
|
||||
github.com/sclevine/spec v1.4.0/go.mod h1:LvpgJaFyvQzRvc1kaDs0bulYwzC70PbiYjC4QnFHkOM=
|
||||
github.com/shirou/gopsutil/v3 v3.24.2 h1:kcR0erMbLg5/3LcInpw0X/rrPSqq4CDPyI6A6ZRC18Y=
|
||||
github.com/shirou/gopsutil/v3 v3.24.2/go.mod h1:tSg/594BcA+8UdQU2XcW803GWYgdtauFFPgJCJKZlVk=
|
||||
github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg9SUEw2VQ=
|
||||
github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
|
||||
github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
|
||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
|
||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||
github.com/stretchr/testify v1.7.2/go.mod h1:R6va5+xMeoiuVRoj+gSkQ7d3FALtqAAGI1FQKckRals=
|
||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk=
|
||||
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/syncthing/notify v0.0.0-20210616190510-c6b7342338d2 h1:F4snRP//nIuTTW9LYEzVH4HVwDG9T3M4t8y/2nqMbiY=
|
||||
github.com/syncthing/notify v0.0.0-20210616190510-c6b7342338d2/go.mod h1:J0q59IWjLtpRIJulohwqEZvjzwOfTEPp8SVhDJl+y0Y=
|
||||
github.com/syndtr/goleveldb v1.0.1-0.20220721030215-126854af5e6d h1:vfofYNRScrDdvS342BElfbETmL1Aiz3i2t0zfRj16Hs=
|
||||
@@ -193,28 +223,32 @@ github.com/urfave/cli v1.22.14 h1:ebbhrRiGK2i4naQJr+1Xj92HXZCrK7MsyTS/ob3HnAk=
|
||||
github.com/urfave/cli v1.22.14/go.mod h1:X0eDS6pD6Exaclxm99NJ3FiCDRED7vIHpx2mDOHLvkA=
|
||||
github.com/vitrun/qart v0.0.0-20160531060029-bf64b92db6b0 h1:okhMind4q9H1OxF44gNegWkiP4H/gsTFLalHFa4OOUI=
|
||||
github.com/vitrun/qart v0.0.0-20160531060029-bf64b92db6b0/go.mod h1:TTbGUfE+cXXceWtbTHq6lqcTvYPBKLNejBEbnUsQJtU=
|
||||
github.com/willabides/kongplete v0.4.0 h1:eivXxkp5ud5+4+NVN9e4goxC5mSh3n1RHov+gsblM2g=
|
||||
github.com/willabides/kongplete v0.4.0/go.mod h1:0P0jtWD9aTsqPSUAl4de35DLghrr57XcayPyvqSi2X8=
|
||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yusufpapurcu/wmi v1.2.3 h1:E1ctvB7uKFMOJw3fdOW32DwGE9I7t++CRUEMKvFoFiw=
|
||||
github.com/yusufpapurcu/wmi v1.2.3/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
go.uber.org/mock v0.3.0 h1:3mUxI1No2/60yUYax92Pt8eNOEecx2D3lcXZh2NEZJo=
|
||||
go.uber.org/mock v0.3.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
||||
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
||||
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
go.uber.org/automaxprocs v1.5.3 h1:kWazyxZUrS3Gs4qUpbwo5kEIMGe/DAvi5Z4tl2NW4j8=
|
||||
go.uber.org/automaxprocs v1.5.3/go.mod h1:eRbA25aqJrxAbsLO0xy5jVwPt7FQnRgjW+efnwa1WM0=
|
||||
go.uber.org/mock v0.4.0 h1:VcM4ZOtdbR4f6VXfiOpwpVJDL6lCReaZ6mw31wqh7KU=
|
||||
go.uber.org/mock v0.4.0/go.mod h1:a6FSlNadKUHUa9IP5Vyt1zh4fC7uAwxMutEAscFbkZc=
|
||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||
golang.org/x/crypto v0.16.0 h1:mMMrFzRSCF0GvB7Ne27XVtVAaXLrPmgPC7/v0tkwHaY=
|
||||
golang.org/x/crypto v0.16.0/go.mod h1:gCAAfMLgwOJRpTjQ2zCCt2OcSfYMTeZVSRtQlPC7Nq4=
|
||||
golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb h1:c0vyKkb6yr3KR7jEfJaOSv4lG7xPkbN6r52aJz1d8a8=
|
||||
golang.org/x/exp v0.0.0-20231206192017-f3f8817b8deb/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI=
|
||||
golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA=
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225 h1:LfspQV/FYTatPTr/3HzIcmiUFH7PGP+OQ6mgDYo3yuQ=
|
||||
golang.org/x/exp v0.0.0-20240222234643-814bf88cf225/go.mod h1:CxmFvTBINI24O/j8iY7H1xHzx2i4OsyguNBmN/uPtqc=
|
||||
golang.org/x/mod v0.2.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
|
||||
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.16.0 h1:QX4fJ0Rr5cPQCF7O9lh9Se4pmwfwskqZfq5moyldzic=
|
||||
golang.org/x/mod v0.16.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
@@ -228,15 +262,16 @@ golang.org/x/net v0.0.0-20220607020251-c690dde0001d/go.mod h1:XRhObCWvk6IyKnWLug
|
||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.19.0 h1:zTwKpTd2XuCqf8huc7Fo2iSy+4RHPd10s4KzeTnVr1c=
|
||||
golang.org/x/net v0.19.0/go.mod h1:CfAk/cbD4CthTvqiEl8NpboMuiuOYsAr/7NOjZJtv1U=
|
||||
golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.5.0 h1:60k92dhOjHxJkrqnwsfl8KuaHbn/5dl0lUPUklKo3qE=
|
||||
golang.org/x/sync v0.6.0 h1:5BMeUDZ7vkXGfEr1x9B4bRcTH4lpkTkpdh0T/J+qjbQ=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20180926160741-c2ed4eda69e7/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
@@ -260,13 +295,15 @@ golang.org/x/sys v0.0.0-20220408201424-a24fb2fb8a0f/go.mod h1:oPkhp1MJrh7nUepCBc
|
||||
golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.15.0 h1:h48lPFYpsTvQJZF4EKyI4aLHaev3CxivZmv7yZig9pc=
|
||||
golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4=
|
||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
@@ -290,8 +327,8 @@ golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4f
|
||||
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.16.1 h1:TLyB3WofjdOEepBHAU20JdNC1Zbg87elYofWYAY5oZA=
|
||||
golang.org/x/tools v0.16.1/go.mod h1:kYVVN6I1mBNoB1OX+noeBjbRk4IUEPa7JJ+TJMEooJ0=
|
||||
golang.org/x/tools v0.18.0 h1:k8NLag8AGHnn+PHbl7g43CtqZAwG60vZkLqgyZgIHgQ=
|
||||
golang.org/x/tools v0.18.0/go.mod h1:GL7B4CwcLLeo59yx/9UWWuNOW1n3VZ4f5axWfML7Lcg=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
@@ -305,9 +342,11 @@ google.golang.org/protobuf v1.21.0/go.mod h1:47Nbq4nVaFHyn7ilMalzfO3qCViNmqZ2kzi
|
||||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||
google.golang.org/protobuf v1.31.0 h1:g0LDEJHgrBl9N9r17Ru3sqWhkIx2NB67okBHPwC7hs8=
|
||||
google.golang.org/protobuf v1.31.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||
google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I=
|
||||
google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 h1:uRGJdciOHaEIrze2W8Q3AKkepLTh2hOroT7a+7czfdQ=
|
||||
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7/go.mod h1:dt/ZhP58zS4L8KSrWDmTeBkI65Dw0HsyUHuEVlX15mw=
|
||||
|
||||
@@ -189,6 +189,13 @@ input[type="checkbox"].extended-attributes-filter-rule-checkbox {
|
||||
word-break: break-all;
|
||||
}
|
||||
|
||||
/* Break up long words in paragraphs only if necessary to prevent text overflow. */
|
||||
.overflow-break-word {
|
||||
overflow-wrap: break-word;
|
||||
/* Legacy name alias */
|
||||
word-wrap: break-word;
|
||||
}
|
||||
|
||||
.folder-advanced {
|
||||
padding: 1rem;
|
||||
margin-bottom: 15px;
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
"Add Device": "إضافة جهاز",
|
||||
"Add Folder": "إضافة مجلد",
|
||||
"Add Remote Device": "إضافة جهاز بعيد",
|
||||
"Add devices from the introducer to our device list, for mutually shared folders.": "اضف أجهزة من المعرف/المقدم إلى قائمة الأجهزة الخاصة بنا، للمجلدات المشتركة بشكل متبادل.",
|
||||
"Add devices from the introducer to our device list, for mutually shared folders.": "أضف أجهزة من الوسيط إلى قائمة الأجهزة الخاصة بنا، للمجلدات المشتركة بشكل متبادل.",
|
||||
"Add filter entry": "إضافة عامل التصفية",
|
||||
"Add ignore patterns": "أضف أنماط التجاهل",
|
||||
"Add new folder?": "إضافة مجلد جديد؟",
|
||||
@@ -34,7 +34,7 @@
|
||||
"Apply": "تقدم",
|
||||
"Are you sure you want to override all remote changes?": "هل أنت متأكد أنك تريد تجاوز كافة التغييرات عن بُعد؟",
|
||||
"Are you sure you want to permanently delete all these files?": "هل أنت متأكد أنك تريد حذف كل هذه الملفات بشكل دائم؟",
|
||||
"Are you sure you want to remove device {%name%}?": " هل انت متاكد من حذف الجهاز {{name}}? ",
|
||||
"Are you sure you want to remove device {%name%}?": "هل أنت متيقِّن من حذف هذا الجهاز {{name}}؟",
|
||||
"Are you sure you want to remove folder {%label%}?": "هل انت متاكد من حذف المجلد {{label}}؟",
|
||||
"Are you sure you want to restore {%count%} files?": "هل انت متاكد من استعادة {{count}} ملف؟",
|
||||
"Are you sure you want to revert all local changes?": "هل أنت متأكد أنك تريد التراجع عن كافة التغييرات المحلية؟",
|
||||
@@ -45,8 +45,8 @@
|
||||
"Automatic Crash Reporting": "التبليغ التلقائي للاخطاء",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "توفر الترقية التلقائية الاختيار بين النسخ الثابتة أو النسخ المرشحة.",
|
||||
"Automatic upgrades": "تحديث تلقائي",
|
||||
"Automatic upgrades are always enabled for candidate releases.": "الترقية التلقائية مفعلة دائمًا للنسخ المرشحة. ",
|
||||
"Automatically create or share folders that this device advertises at the default path.": "تلقائيا أنشئ وشارك المجلدات الموجودة في المسار الافتراضي.",
|
||||
"Automatic upgrades are always enabled for candidate releases.": "الترقية التلقائية مفعلة دائمًا للنسخ المرشحة.",
|
||||
"Automatically create or share folders that this device advertises at the default path.": "أنشئ وشارك المجلدات الموجودة في المسار الافتراضي تلقائيا.",
|
||||
"Available debug logging facilities:": "خدمات سجلات تدقيق البرمجيات المتوفرة:",
|
||||
"Be careful!": "احذر!",
|
||||
"Body:": "جسم:",
|
||||
@@ -70,10 +70,10 @@
|
||||
"Connection Type": "نوع الاتصال",
|
||||
"Connections": "اتصالات",
|
||||
"Connections via relays might be rate limited by the relay": "قد يكون معدل التوصيلات عبر المرحلات محدودًا بواسطة المرحل",
|
||||
"Continuously watching for changes is now available within Syncthing. This will detect changes on disk and issue a scan on only the modified paths. The benefits are that changes are propagated quicker and that less full scans are required.": "مراقبة الملفات بشكل مستمر متوفر في Syncthing. يتم فحص الملفات التي تم تغييرها في المسار فقط. هذا يساعد على تجنب فحص كامل المسار لأداء اسرع. ",
|
||||
"Continuously watching for changes is now available within Syncthing. This will detect changes on disk and issue a scan on only the modified paths. The benefits are that changes are propagated quicker and that less full scans are required.": "مراقبة الملفات بشكل مستمر متوفر في Syncthing. يتم فحص الملفات التي تم تغييرها في المسار فقط. هذا يساعد على تجنب فحص كامل المسار لأداء اسرع.",
|
||||
"Copied from elsewhere": "منسوخ من مكان أخر",
|
||||
"Copied from original": "منسوخ من الأصل",
|
||||
"Copied!": "تم النسخ",
|
||||
"Copied!": "تم النسخ!",
|
||||
"Copy": "نسخ",
|
||||
"Copy failed! Try to select and copy manually.": "فشل النسخ! حاول التحديد والنسخ يدويًا.",
|
||||
"Currently Shared With Devices": "حاليًا تم مشاركته مع الأجهزة",
|
||||
@@ -94,15 +94,15 @@
|
||||
"Deselect devices to stop sharing this folder with.": "قم بإلغاء تحديد الأجهزة لإيقاف مشاركة هذا المجلد معها.",
|
||||
"Deselect folders to stop sharing with this device.": "قم بإلغاء تحديد المجلدات لإيقاف المشاركة مع هذا الجهاز.",
|
||||
"Device": "جهاز",
|
||||
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "الجهاز \"{{الاسم}}\" ({{الجهاز}} في {{العنوان}}) يرغب في الاتصال، إضافة جهاز جديد؟",
|
||||
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "الجهاز \"{{name}}\" ({{device}} في {{address}}) يرغب في الاتصال، إضافة جهاز جديد؟",
|
||||
"Device Certificate": "شهادة الجهاز",
|
||||
"Device ID": "هوية الجهاز",
|
||||
"Device Identification": "هوية الجهاز",
|
||||
"Device Name": "أسم الجهاز",
|
||||
"Device ID": "معرف الجهاز",
|
||||
"Device Identification": "معرف الجهاز",
|
||||
"Device Name": "اسم الجهاز",
|
||||
"Device Status": "حالة الجهاز",
|
||||
"Device is untrusted, enter encryption password": "الجهاز غير موثوق به، أدخل كلمة مرور التشفير",
|
||||
"Device rate limits": "حدود معدل نقل البيانات",
|
||||
"Device that last modified the item": "اخر جهاز جهاز عدل على العنصر",
|
||||
"Device that last modified the item": "آخر من عدل على العنصر",
|
||||
"Devices": "الأجهزة",
|
||||
"Disable Crash Reporting": "تعطيل ميزة التبليغ عن الأخطاء",
|
||||
"Disabled": "معطل",
|
||||
@@ -163,10 +163,10 @@
|
||||
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "الملفات محمية من التغييرات التي تم إجراؤها على الأجهزة الأخرى ، ولكن سيتم إرسال التغييرات التي تم إجراؤها على هذا الجهاز إلى بقية الأجهزة.",
|
||||
"Files are synchronized from the cluster, but any changes made locally will not be sent to other devices.": "تُزامَنُ الملفات من العنقود، لكن التغيرات المحلية على هذا الجهاز لاتُطَبَّقُ على غيره من الأجهزة.",
|
||||
"Filesystem Watcher Errors": "أخطاء مراقب نظام الملفات",
|
||||
"Filter by date": "فلتره بالتاريخ ",
|
||||
"Filter by date": "فلترة بالتاريخ",
|
||||
"Filter by name": "فلتر باستخدام الاسم",
|
||||
"Folder": "مجلد",
|
||||
"Folder ID": "هوية المجلد",
|
||||
"Folder ID": "مُعرِّف المجلد",
|
||||
"Folder Label": "تسمية المجلد",
|
||||
"Folder Path": "مسار المجلد",
|
||||
"Folder Status": "حالة المجلد",
|
||||
@@ -176,25 +176,25 @@
|
||||
"Folders": "المجلدات",
|
||||
"For the following folders an error occurred while starting to watch for changes. It will be retried every minute, so the errors might go away soon. If they persist, try to fix the underlying issue and ask for help if you can't.": "للمجلدات التالية، حدث خطأ قبل بدء مشاهدة التغييرات. ستتم إعادة المحاولة كل دقيقة، نظرًا لذلك قد تختفي الأخطاء قريبًا. لكن إذا استمرت، فحاول حل المشكلة واطلب المساعدة إذا لم تستطع حل المشكلة.",
|
||||
"Forever": "للأبد",
|
||||
"Full Rescan Interval (s)": "مدة أعاده الفحص الكامل (ثانية)",
|
||||
"Full Rescan Interval (s)": "مدة إعادة الفحص الكامل (ثانية)",
|
||||
"GUI": "واجهة المستخدم الرسومية",
|
||||
"GUI / API HTTPS Certificate": "الواجهة / API وثيقة HTTPS",
|
||||
"GUI Authentication Password": "كلمة السر لتوثيق الواجهة",
|
||||
"GUI Authentication User": "أسم المستخدم لدخول واجهة الرسومية",
|
||||
"GUI Authentication User": "اسم المستخدم لدخول واجهة الرسومية",
|
||||
"GUI Authentication: Set User and Password": "توثيق الواجهة: أنشئ كلمة مرور للمستخدم",
|
||||
"GUI Listen Address": "واجهة الرسومية الاستماع الى العنوان",
|
||||
"GUI Override Directory": "مجلد إحلال الواجهة",
|
||||
"GUI Theme": "شكل الواجه",
|
||||
"GUI Theme": "شكل الواجهة",
|
||||
"General": "عام",
|
||||
"Generate": "توليد",
|
||||
"Global Discovery": "الاكتشاف العالمي",
|
||||
"Global Discovery Servers": "الاكتشاف العالمي",
|
||||
"Global State": "الحالة العامة ",
|
||||
"Global State": "الحالة العامة",
|
||||
"Help": "مساعدة",
|
||||
"Hint: only deny-rules detected while the default is deny. Consider adding \"permit any\" as last rule.": "ملحوظة: إذا كان الإعداد الافتراضي هو الرفض، وحدها قواعد الرفض تُرصد. جرب إضافة \"السماح للكل\" كخيار أخير.",
|
||||
"Home page": "الصفحة الرئيسية",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "ومع ذلك، تشير إعداداتك الحالية إلى أنك قد لا ترغب في تمكينه. لذلك تم تعطيل الإبلاغ التلقائي عن الأعطال.",
|
||||
"Identification": "التعرف",
|
||||
"Identification": "المُعرِّف",
|
||||
"If untrusted, enter encryption password": "في حالة الرِّيبة، أدخل كلمة سر التشفير",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "إذا أردت منع المستخدمين الآخرين على هذا الحاسب من الوصول لملفاتك من خلال Syncthing، يُنصَح بإعداد وثائق الملكية.",
|
||||
"Ignore": "تجاهل",
|
||||
@@ -206,11 +206,11 @@
|
||||
"Ignored at": "تجاهل عند",
|
||||
"Included Software": "البرامج المُضمَّنة",
|
||||
"Incoming Rate Limit (KiB/s)": "الحد الأقصى البيانات الواردة (KiB/s)",
|
||||
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "الإعدادات الغير صحيحه قد تدمر بيانات المجلد وتجعل المزامنة غير صالحه للعمل",
|
||||
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "الإعدادات الغير صحيحة قد تدمر بيانات المجلد وتُفْشِلُ المزامنة.",
|
||||
"Incorrect user name or password.": "رُصِدَ خطأ في اسم المستخدم أو كلمة المرور.",
|
||||
"Internally used paths:": "المسار المستخدم محليّا:",
|
||||
"Introduced By": "عرف بواسطة",
|
||||
"Introducer": "المعرف",
|
||||
"Introducer": "الوسيط",
|
||||
"Introduction": "تقديم",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "عكس الحالة المذكورة (مثلا: لا تستثنِ)",
|
||||
"Keep Versions": "احتفظ بالاصدارات",
|
||||
@@ -219,10 +219,10 @@
|
||||
"Last 30 Days": "الثلاثون يومًا السابقة",
|
||||
"Last 7 Days": "الأيام السبعة السابقة",
|
||||
"Last Month": "الشهر الماضي",
|
||||
"Last Scan": "اخر فحص",
|
||||
"Last Scan": "آخر فحص",
|
||||
"Last seen": "اخر ظهور",
|
||||
"Latest Change": "اخر التغييرات",
|
||||
"Learn more": "اعرف اكثر ",
|
||||
"Learn more": "اعرف أكثر",
|
||||
"Learn more at {%url%}": "اطلع على المزيد في {{url}}",
|
||||
"Limit": "الحد",
|
||||
"Listener Failures": "فشل المستمع",
|
||||
@@ -264,7 +264,7 @@
|
||||
"Newest First": "الأحدث أولا",
|
||||
"No": "لا",
|
||||
"No File Versioning": "لا تقسيم لإصدارات الملفات",
|
||||
"No files will be deleted as a result of this operation.": "لن يتم حذف اي ملفات بسبب هذا العملية",
|
||||
"No files will be deleted as a result of this operation.": "لن يتم حذف أي ملفات بسبب هذا العملية.",
|
||||
"No rules set": "لم تحدد قواعد",
|
||||
"No upgrades": "لا يوجد ترقيات",
|
||||
"Not shared": "لم يُشارَك",
|
||||
@@ -273,7 +273,7 @@
|
||||
"OK": "موافق",
|
||||
"Off": "اطفئ",
|
||||
"Oldest First": "الأقدم أولا",
|
||||
"Optional descriptive label for the folder. Can be different on each device.": "تسمية وصفية اختيارية للمجلد . يمكن أن تكون مختلفة على كل جهاز. ",
|
||||
"Optional descriptive label for the folder. Can be different on each device.": "تسمية وصفية اختيارية للمجلد. يمكن أن تكون مختلفة على كل جهاز.",
|
||||
"Options": "خيارات",
|
||||
"Out of Sync": "خارج التزامن",
|
||||
"Out of Sync Items": "عناصر خارج التزامن",
|
||||
@@ -287,13 +287,13 @@
|
||||
"Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).": "المسار حيث تخزن الإصدارات (يترك فارغًا لدليل .vversions الافتراضي في المجلد المشترك).",
|
||||
"Paths": "المسارات",
|
||||
"Pause": "إيقاف",
|
||||
"Pause All": "أيقاف الكل ",
|
||||
"Pause All": "إيقاف الكل",
|
||||
"Paused": "توقف",
|
||||
"Paused (Unused)": "متوقف (مهمل)",
|
||||
"Pending changes": "التغييرات المعلقة",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "المسح الدوري خلال فترة زمنية معينة وتعطيل مشاهدة التغييرات.",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "المسح الدوري خلال فترة زمنية معينة وتفعيل مشاهدة التغييرات.",
|
||||
"Periodic scanning at given interval and failed setting up watching for changes, retrying every 1m:": "المسح الدوري خلال فترة زمنية معينة وفشل اعداد مشاهدة التغييرات، اعادة المحاولة كل 1 دقيقة.",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "الفحص الدوري خلال فترة زمنية معينة وتعطيل تَرقُّب التغييرات",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "المسح الدوري خلال فترة زمنية معينة وتفعيل تَرقُّب التغييرات",
|
||||
"Periodic scanning at given interval and failed setting up watching for changes, retrying every 1m:": "المسح الدوري خلال فترة زمنية معينة وفشل إعداد تَرقُّب التغييرات، إعادة المحاولة كل 1 دقيقة:",
|
||||
"Permanently add it to the ignore list, suppressing further notifications.": "أدرجها أبداً على قائمة التجاهل، اكتم الإشعارات مستقبلا.",
|
||||
"Please consult the release notes before performing a major upgrade.": "يرجى العودة إلى ملاحظات الإصدار قبل تنفيذ ترقية رئيسية.",
|
||||
"Please set a GUI Authentication User and Password in the Settings dialog.": "تفضل بإنشاء مستخدما موثقا للواجهة وكلمة مرور من خلال قائمة الإعدادات.",
|
||||
@@ -306,13 +306,13 @@
|
||||
"QR code": "الصورة المشفرة (QR)",
|
||||
"QUIC LAN": "اتصال QUIC للشبكة المحلية (LAN)",
|
||||
"QUIC WAN": "QUIC الشبكة العامة",
|
||||
"Quick guide to supported patterns": "الدليل مختصر للأنماط المدعومة ",
|
||||
"Quick guide to supported patterns": "دليل مختصر للأنماط المدعومة",
|
||||
"Random": "عشوائي",
|
||||
"Receive Encrypted": "استلام المشفَّر",
|
||||
"Receive Only": "استقبال فقط",
|
||||
"Received data is already encrypted": "البيانات المستوردة مشفرة بالفعل",
|
||||
"Recent Changes": "اخر التغييرات",
|
||||
"Reduced by ignore patterns": "تقليص بواسطة تجاهل الأنماط. ",
|
||||
"Reduced by ignore patterns": "تقليص بواسطة تجاهل الأنماط",
|
||||
"Relay LAN": "ترحيل الشبكة المحلية (LAN)",
|
||||
"Relay WAN": "ترحيل الشبكة العامة (WAN)",
|
||||
"Release Notes": "ملاحظات الإصدار",
|
||||
@@ -322,32 +322,32 @@
|
||||
"Remove": "إزالة",
|
||||
"Remove Device": "حذف جهاز",
|
||||
"Remove Folder": "حذف مجلد",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "يتطلب معرفًا للمجلد. يجب أن يستخدم نفس المعرف لبقية الأجهزة. ",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "يتطلب معرفًا للمجلد. يجب أن يستخدم نفس المعرف لبقية الأجهزة.",
|
||||
"Rescan": "إعادة فحص",
|
||||
"Rescan All": "أعادة فحص الكل",
|
||||
"Rescan All": "إعادة فحص الكل",
|
||||
"Rescans": "يعيد الفحص",
|
||||
"Restart": "إعادة تشغيل",
|
||||
"Restart Needed": "مطلوب أعادة تشغيل",
|
||||
"Restarting": "يتم إعادة التشغيل",
|
||||
"Restore": "استعادة",
|
||||
"Restore Versions": "استعادة أصدارات ",
|
||||
"Restore Versions": "استعادة إصدارات",
|
||||
"Resume": "استرد",
|
||||
"Resume All": "استعادة الكل ",
|
||||
"Reused": "إعادة الاستخدام",
|
||||
"Resume All": "استئناف الجميع",
|
||||
"Reused": "مُعادة الاستخدام",
|
||||
"Revert": "الرجوع عن التغيير",
|
||||
"Revert Local Changes": "التراجع عن التغييرات",
|
||||
"Save": "حفظ",
|
||||
"Saving changes": "تُحفَظ التعديلات",
|
||||
"Scan Time Remaining": "فحص الوقت المتبقي",
|
||||
"Scanning": "يتم الفحص",
|
||||
"See external versioning help for supported templated command line parameters.": "راجع تعليمات الإصدارات الخارجية لمعرفة القيم المدعومة في سطر الأوامر. ",
|
||||
"See external versioning help for supported templated command line parameters.": "راجع تعليمات الإصدارات الخارجية لمعرفة القيم المدعومة في سطر الأوامر.",
|
||||
"Select All": "تحديد الكل",
|
||||
"Select a version": "اختار أصدار ",
|
||||
"Select a version": "اختر إصداراً",
|
||||
"Select additional devices to share this folder with.": "اختيار المزيد من الأجهزة التي ترغب في مشاركة هذا المجلد معها.",
|
||||
"Select additional folders to share with this device.": "اختيار المزيد من المجلدات لمشاركتها مع هذا الجهاز.",
|
||||
"Select latest version": "اختار اخر أصدار ",
|
||||
"Select latest version": "اختر آخر إصدار",
|
||||
"Select oldest version": "اختيار أقدم إصدار",
|
||||
"Send & Receive": "إرسال واستقبال ",
|
||||
"Send & Receive": "إرسال واستقبال",
|
||||
"Send Extended Attributes": "أرسل البيانات الثانوية",
|
||||
"Send Only": "إرسال فقط",
|
||||
"Send Ownership": "أرسل الملكية",
|
||||
@@ -361,13 +361,13 @@
|
||||
"Shared Folders": "المجلدات المُشارَكة",
|
||||
"Shared With": "مشاركة مع",
|
||||
"Sharing": "مشاركه",
|
||||
"Show ID": "عرض الهوية",
|
||||
"Show ID": "عرض المُعرِّف",
|
||||
"Show QR": "اظهار QR",
|
||||
"Show detailed discovery status": "اعرض حالة الاكتشاف تفصيليا",
|
||||
"Show detailed listener status": "اعرض حالة الاستماع تفصيليا",
|
||||
"Show diff with previous version": "اظهر الفرق مع النسخة السابقة ",
|
||||
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "يُعرَض بدلا من الهوية في حالة العنقود. سيُروَّج للأجهزة الأخرى على انه اسم اساسي محتمل.",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "يُعرَض بدلا من الهوية في حالة العنقود. إذا تُرك فارغا، سيُحدَّث إلى الاسم المختار من قِبَل الجهاز.",
|
||||
"Show diff with previous version": "أظهر الفرق مقارنةً بالنسخة السابقة",
|
||||
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "يُعرَض بدلا من المُعرِّف ضمن العناقيد. سيُروَّج للأجهزة الأخرى على أنه اسم أساسي محتمل.",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "يُعرَض بدلا من المُعرِّف ضمن العناقيد. إذا تُرك فارغا، سيُحدَّث إلى الاسم المختار من قِبَل الجهاز.",
|
||||
"Shutdown": "إغلاق",
|
||||
"Shutdown Complete": "تم الإغلاق",
|
||||
"Simple": "بسيط",
|
||||
@@ -379,13 +379,14 @@
|
||||
"Some items could not be restored:": "بعض العناصر لا يمكن استرجاعها:",
|
||||
"Some listening addresses could not be enabled to accept connections:": "بعض عناوين الاستماع لا يمكن تفعيلها لقبول الاتصالات:",
|
||||
"Source Code": "مصدر الشفرة",
|
||||
"Stable releases and release candidates": "الإصدارات المستقرة والإصدارات المرشحة.",
|
||||
"Stable releases and release candidates": "الإصدارات المستقرة والإصدارات المرشحة",
|
||||
"Stable releases are delayed by about two weeks. During this time they go through testing as release candidates.": "الإصدارات المستقرة تأخرت بنحو أسبوعين. خلال هذه الفترة يتم إجراء الاختبارات كإصدارات مرشحة.",
|
||||
"Stable releases only": "الإصدارات المستقرة فقط",
|
||||
"Staggered": "مترنِّح",
|
||||
"Staggered File Versioning": "تقسمات إصدارات الملف مهترئة",
|
||||
"Start Browser": "تشغيل المتصفح",
|
||||
"Statistics": "إحصائيات",
|
||||
"Stay logged in": "ابقِ مُسجل الدخول",
|
||||
"Stopped": "متوقف",
|
||||
"Stores and syncs only encrypted data. Folders on all connected devices need to be set up with the same password or be of type \"{%receiveEncrypted%}\" too.": "يُزامن ويخزن البيانات المشفرة فقط. يجب أن تكون المجلدات على جميع الأجهزة مُجهزَّة بكلمة المرور نفسها، أو أن تكون من نوع \"{{receiveEncrypted}}\".",
|
||||
"Subject:": "الموضوع:",
|
||||
@@ -396,7 +397,7 @@
|
||||
"Sync Protocol Listen Addresses": "عناوين بروتوكول استقبال المزامنة",
|
||||
"Sync Status": "وضع المزامنة",
|
||||
"Syncing": "يتم التزامن",
|
||||
"Syncthing device ID for \"{%devicename%}\"": "هوية Syncthing الجهاز لـ {{devicename}}",
|
||||
"Syncthing device ID for \"{%devicename%}\"": "مُعرِّف Syncthing للجهاز {{devicename}}",
|
||||
"Syncthing has been shut down.": "تم إيقاف Syncthing.",
|
||||
"Syncthing includes the following software or portions thereof:": "المزامنة تتضمن البرامج التالية أو أجزائها:",
|
||||
"Syncthing is Free and Open Source Software licensed as MPL v2.0.": "Syncthing هو برنامج حر مفتوح المصدر تحت ترخيص MPL v2.0 (ترخيص موزيلا العام النسخة الثانية).",
|
||||
@@ -418,18 +419,18 @@
|
||||
"The aggregated statistics are publicly available at the URL below.": "الإحصاءات المجمعة متاحة للجميع على العنوان التالي.",
|
||||
"The cleanup interval cannot be blank.": "المدة بين عمليات التنظيف لا يمكن تركها فارغة.",
|
||||
"The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.": "تم حفظ الإعدادات ولكن لم يتم تفعيلها بعد. يجب أعادة تشغيل Syncthing حتى تم تفعيل الإعدادات.",
|
||||
"The device ID cannot be blank.": "هوية الجهاز لا يمكن أن تكون فارغة.",
|
||||
"The device ID to enter here can be found in the \"Actions > Show ID\" dialog on the other device. Spaces and dashes are optional (ignored).": "يمكنك أن تجد هوية الجهاز الذي ينبغي استخدامه هنا في قائمة \"الإجراءات > عرض الهوية\" على الجهاز الآخر. المسافات والخطوط الاعتراضية تُتجاهَل.",
|
||||
"The device ID cannot be blank.": "مُعرِّف الجهاز لا يمكن أن يكون فارغاً.",
|
||||
"The device ID to enter here can be found in the \"Actions > Show ID\" dialog on the other device. Spaces and dashes are optional (ignored).": "يمكنك أن تجد مُعرِّف الجهاز الذي ينبغي استخدامه هنا في قائمة \"الإجراءات > عرض المُعرِّف\" على الجهاز الآخر. المسافات والخطوط الاعتراضية تُتجاهَل.",
|
||||
"The encrypted usage report is sent daily. It is used to track common platforms, folder sizes, and app versions. If the reported data set is changed you will be prompted with this dialog again.": "تقارير الاستخدام المشفرة ترسل يوميا. تُستخدم هذه التقارير لتتبع المنصات الشائعة، أحجام المجلدات، إصدارات التطبيق. إذا تغيرت بنود هذا التقرير، ستواجَهُ بهذه النافذة مرة أخرى.",
|
||||
"The entered device ID does not look valid. It should be a 52 or 56 character string consisting of letters and numbers, with spaces and dashes being optional.": "الهوية المُقَدَّمَة ناقصة على ما يبدو. الهوية مكوَّنة من 52 أو 56 رمزا بين حروف وأرقام، مع تجاهل المسافات الفارغة وخطوط الاعتراض.",
|
||||
"The folder ID cannot be blank.": "هوية المجلد لا يمكن أن تكون فارغة.",
|
||||
"The folder ID must be unique.": "يجب أن يكون عنوان المجلد فريد ",
|
||||
"The entered device ID does not look valid. It should be a 52 or 56 character string consisting of letters and numbers, with spaces and dashes being optional.": "المُعرِّف المُقَدَّم ناقص على ما يبدو. المُعرِّف مكوَّن من 52 أو 56 رمزاً بين حروف وأرقام، مع تجاهل المسافات الفارغة والخطوط الفاصلة.",
|
||||
"The folder ID cannot be blank.": "معرف المجلد لا يمكن أن يكون فارغاً.",
|
||||
"The folder ID must be unique.": "يجب أن يكون عنوان المجلد فريداً.",
|
||||
"The folder content on other devices will be overwritten to become identical with this device. Files not present here will be deleted on other devices.": "ستحل محتويات هذا المجلد محل محتويات مجلدات الأجهزة الأخرى. الملفات التي ليس لها وجود هنا ستحذف عن الأجهزة الأخرى.",
|
||||
"The folder content on this device will be overwritten to become identical with other devices. Files newly added here will be deleted.": "ستحل البيانات في الأجهزة الأخرى محل البيانات في هذا المجلد. ستحذف الملفات التي ستُنشأ هنا.",
|
||||
"The folder path cannot be blank.": "مسار المجلد لا يمكن أن يكون فارغ",
|
||||
"The folder path cannot be blank.": "مسار المجلد لا يمكن أن يكون فارغاً.",
|
||||
"The following intervals are used: for the first hour a version is kept every 30 seconds, for the first day a version is kept every hour, for the first 30 days a version is kept every day, until the maximum age a version is kept every week.": "المُدَد التالية مُستخدَمة: تُحفظ نسخة كل 30 ثانية في الساعة الأولى، ونسخة كل ساعة لبقية اليوم الأول، ونسخة يومية لأول ثلاثين يوما، ونسخة أسبوعية للأمد.",
|
||||
"The following items could not be synchronized.": "فشل مزامنة العناصر التالية",
|
||||
"The following items were changed locally.": "تم تغيير العناصر التالية محليا",
|
||||
"The following items could not be synchronized.": "فشلت مزامنة العناصر التالية.",
|
||||
"The following items were changed locally.": "غُيِّرت العناصر التالية محليا.",
|
||||
"The following methods are used to discover other devices on the network and announce this device to be found by others:": "الطرق التالية مستخدمة للإعلان عن هذا الجهاز، وإيجاد الأجهزة الأخرى أيضا:",
|
||||
"The following text will automatically be inserted into a new message.": "النص التالي سيُضمَّن تلقائيا في رسالة جديدة.",
|
||||
"The following unexpected items were found.": "عُثِر على المحتوى غير المتوقع التالي.",
|
||||
@@ -440,7 +441,7 @@
|
||||
"The number of connections must be a non-negative number.": "عدد الاتصالات يجب ألا يكون سالبا.",
|
||||
"The number of days must be a number and cannot be blank.": "حقل عدد الأيام يجب أن يكون رقم ولا يمكن تركه فارغ.",
|
||||
"The number of days to keep files in the trash can. Zero means forever.": "عدد أيام حفظ الملفات في سلة المهملات. الصفر يعني إلى الأبد.",
|
||||
"The number of old versions to keep, per file.": "عدد النسخ القديمة المحفوظة، لكل ملف. ",
|
||||
"The number of old versions to keep, per file.": "عدد النسخ القديمة المحفوظة، لكل ملف.",
|
||||
"The number of versions must be a number and cannot be blank.": "حقل عدد النسخ يجب أن يكون رقم ولا يمكن أن تركة فارغا.",
|
||||
"The path cannot be blank.": "المسار لا يمكن أن يكون فارغ.",
|
||||
"The rate limit is applied to the accumulated traffic of all connections to this device.": "السرعة القصوى المختارة لنقل البيانات المتراكمة من جميع الاتصالات على هذا الجهاز.",
|
||||
@@ -456,7 +457,7 @@
|
||||
"This Month": "هذا الشهر",
|
||||
"This can easily give hackers access to read and change any files on your computer.": "هذا قد يسبب في اختراق جهازك.",
|
||||
"This device cannot automatically discover other devices or announce its own address to be found by others. Only devices with statically configured addresses can connect.": "لا يمكن لهذا الجهاز أن يرصد الأجهزة الأخرى تلقائيا، ولا أن يعلن عنوانه ليمكن الأجهزة الأخرى من إيجاده. الأجهزة ثابتة العناوين فقط يمكن أن تتصل.",
|
||||
"This is a major version upgrade.": "ترقية أساسية ",
|
||||
"This is a major version upgrade.": "ترقية أساسية.",
|
||||
"This setting controls the free space required on the home (i.e., index database) disk.": "هذا الخيار يتحكم في المساحة الفارغة المطلوبة من القرص الرئيسي.",
|
||||
"Time": "الوقت",
|
||||
"Time the item was last modified": "توقيت اخر تعديل للعنصر",
|
||||
@@ -478,16 +479,16 @@
|
||||
"Unshared Devices": "الأجهزة غير المُشَارَكة",
|
||||
"Unshared Folders": "المجلدات غير المُشارَكة",
|
||||
"Untrusted": "غير موثوق",
|
||||
"Up to Date": "اخز أصدار ",
|
||||
"Up to Date": "مُزَامَن",
|
||||
"Updated {%file%}": "مُحَدَّث {{file}}",
|
||||
"Upgrade": "ترقية",
|
||||
"Upgrade To {%version%}": "ترقية الى {{version}} ",
|
||||
"Upgrade To {%version%}": "ترقية إلى النسخة {{version}}",
|
||||
"Upgrading": "جاري الترقية",
|
||||
"Upload Rate": "معدل الرفع",
|
||||
"Uptime": "وقت التشغيل",
|
||||
"Usage reporting is always enabled for candidate releases.": "تقارير الاستخدام مفعلة دائمًا للنسخ المرشحة.",
|
||||
"Use HTTPS for GUI": "استخدام HTTPS مع الواجه الرسومية ",
|
||||
"Use notifications from the filesystem to detect changed items.": "استخدم أشغارات نظام الملفات لمعرفة الملفات المتغيرة",
|
||||
"Use HTTPS for GUI": "استخدم HTTPS لتأمين واجهة المستخدم",
|
||||
"Use notifications from the filesystem to detect changed items.": "استخدم إشعارات نظام الملفات لمعرفة الملفات المتغيرة.",
|
||||
"User": "مستخدِم",
|
||||
"User Home": "منزل المستخدم",
|
||||
"Username/Password has not been set for the GUI authentication. Please consider setting it up.": "اسم المستخدم/كلمة المرور لم يُنشَآ لتوثيق الواجهة. يُرجى إنشاؤهما من فضلك.",
|
||||
@@ -511,19 +512,19 @@
|
||||
"Watch for Changes": "راقب التغييرات",
|
||||
"Watching for Changes": "جاري مراقبة التغيرات",
|
||||
"Watching for changes discovers most changes without periodic scanning.": "مراقبة التغييرات تكشف معظم التغييرات دون إجراء المسح الدوري.",
|
||||
"When adding a new device, keep in mind that this device must be added on the other side too.": "يجب أضافه الأجهزة الجديدة في الطرفين",
|
||||
"When adding a new device, keep in mind that this device must be added on the other side too.": "يجب إضافة الأجهزة الجديدة في الطرفين.",
|
||||
"When adding a new folder, keep in mind that the Folder ID is used to tie folders together between devices. They are case sensitive and must match exactly between all devices.": "عند إضافة مجلد جديد ، ضع في الاعتبار أن معرف المجلد يُستخدم لربط المجلدات معًا بين الأجهزة المختلفة. وهي حساسة لحالة الأحرف لذا يجب أن تتطابق تمامًا بين جميع الأجهزة.",
|
||||
"When set to more than one on both devices, Syncthing will attempt to establish multiple concurrent connections. If the values differ, the highest will be used. Set to zero to let Syncthing decide.": "إذا عُرفَّ Syncthing بأنه أكثر من واحد على كلا الجهازين، فإنه سيحاول إقامة عدة اتصالات متوازية. إذا اختلفت القِيَم، أعلاها ستُستخدَم. صَفِّرها لتترك القرار لـ Syncthing.",
|
||||
"Yes": "نعم",
|
||||
"Yesterday": "أمس",
|
||||
"You can also copy and paste the text into a new message manually.": "يكنك نسخ النص لتدرجه في رسالة جديدة بنفسك.",
|
||||
"You can also select one of these nearby devices:": "يمكنك أيضا اختيار واحد من الأجهزة القريبة ",
|
||||
"You can also select one of these nearby devices:": "يمكنك أيضا اختيار واحدة من الأجهزة القريبة:",
|
||||
"You can change your choice at any time in the Settings dialog.": "يمكنك تغيير اختيارك في أي وقت بواسطة الاعدادات.",
|
||||
"You can read more about the two release channels at the link below.": "يمكنك قراءة المزيد عن إصداريّ القناتين عبر الرابط بالأسفل.",
|
||||
"You have no ignored devices.": "لا يوجد أجهزة في قائمة التجاهل ",
|
||||
"You have no ignored folders.": "لا يوجد مجلدات في قائمه التجاهل ",
|
||||
"You have unsaved changes. Do you really want to discard them?": "الإعدادات لم تحفظ. هل انت متأكد من الإلغاء؟ ",
|
||||
"You must keep at least one version.": "يجب الاحتفاظ بنسخة واحده على الاقل",
|
||||
"You have no ignored devices.": "لا أجهزة مُتجاهَلَةٌ.",
|
||||
"You have no ignored folders.": "لا مجلدات مُتجاهَلَةٌ.",
|
||||
"You have unsaved changes. Do you really want to discard them?": "الإعدادات لم تُحفظ. هل أنت متأكد من الإلغاء؟",
|
||||
"You must keep at least one version.": "يجب الاحتفاظ بنسخة واحدة على الأقل.",
|
||||
"You should never add or change anything locally in a \"{%receiveEncrypted%}\" folder.": "ينبغي ألا تغير شيئا في المجلد المحلي في حالة كان \"{{receiveEncrypted}}\".",
|
||||
"Your SMS app should open to let you choose the recipient and send it from your own number.": "ينبغي أن يسمح تطبيق SMS لديك بأن تختار مستلما ويرسلها من رقمك.",
|
||||
"Your email app should open to let you choose the recipient and send it from your own address.": "ينبغي أن يسمح تطبيق البريد الإلكتروني الخاص بك باختيار مستلم و أن يرسلها من عنوانك.",
|
||||
@@ -544,11 +545,11 @@
|
||||
"black": "أسوَد",
|
||||
"dark": "داكن",
|
||||
"default": "افتراضي",
|
||||
"light": "خفيف"
|
||||
"light": "أبيض"
|
||||
}
|
||||
},
|
||||
"unknown device": "جهاز مجهول",
|
||||
"{%device%} wants to share folder \"{%folder%}\".": "{{device}} يريد مشاركة مجلد \"{{folder}}\". ",
|
||||
"{%device%} wants to share folder \"{%folderlabel%}\" ({%folder%}).": "{{device}} يريد مشاركة مجلد \"{{folderlabel}}\" ({{folder}}). ",
|
||||
"{%device%} wants to share folder \"{%folder%}\".": "{{device}} يريد مشاركة هذا المجلد \"{{folder}}\".",
|
||||
"{%device%} wants to share folder \"{%folderlabel%}\" ({%folder%}).": "{{device}} يريد مشاركة هذا المجلد \"{{folderlabel}}\" ({{folder}}).",
|
||||
"{%reintroducer%} might reintroduce this device.": "{{reintroducer}} يمكن أن يعيد تقديم هذا الجهاز."
|
||||
}
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
"Are you sure you want to restore {%count%} files?": "Вы сапраўды жадаеце аднавіць {{count}} файл(ы)?",
|
||||
"Are you sure you want to revert all local changes?": "Вы сапраўды жадаеце адмяніць усе лакальныя змены?",
|
||||
"Are you sure you want to upgrade?": "Вы сапраўды жадаеце абнавіць?",
|
||||
"Authentication Required": "Патрабуецца Аутэнтыфікацыя",
|
||||
"Authors": "Аўтары",
|
||||
"Auto Accept": "Прынімаць Аўтаматычна",
|
||||
"Automatic Crash Reporting": "Аўтаматычныя Спрадвыздачы Пра Памылкі",
|
||||
|
||||
@@ -97,7 +97,7 @@
|
||||
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "Устройство \"{{name}}\" ({{device}}) с адрес {{address}} желае да се свърже. Да бъде ли добавено?",
|
||||
"Device Certificate": "Сертификат на устройството",
|
||||
"Device ID": "Идентификатор на устройство",
|
||||
"Device Identification": "Идентификация на устройство",
|
||||
"Device Identification": "Идентификатор на устройство",
|
||||
"Device Name": "Име на устройството",
|
||||
"Device Status": "Състояние на устройството",
|
||||
"Device is untrusted, enter encryption password": "Устройството е недоверено, въведете парола за шифроване",
|
||||
@@ -189,12 +189,12 @@
|
||||
"Generate": "Подновяване",
|
||||
"Global Discovery": "Глобално откриване",
|
||||
"Global Discovery Servers": "Сървъри за глобално откриване",
|
||||
"Global State": "Глобално състояние",
|
||||
"Global State": "Общо състояние",
|
||||
"Help": "Помощ",
|
||||
"Hint: only deny-rules detected while the default is deny. Consider adding \"permit any\" as last rule.": "Подсказка: има само забрабяващи правила, а по подразбиране е „забранено“. Помислете дали да не добавите „permit any“ като последно правило.",
|
||||
"Home page": "Страница",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "Текущите настройки обаче показват, че може би не искате да бъде включена. За това автоматичното докладване на сривове е изключено.",
|
||||
"Identification": "Идентификация",
|
||||
"Identification": "Идентифициране",
|
||||
"If untrusted, enter encryption password": "При недоверено задайте парола за шифроване",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "Ако желаете да предотвратите достъпа на другите потребители на устройството до Syncthing, а чрез него и до файловете ви, помислете за удостоверяване на графичния интерфейс.",
|
||||
"Ignore": "Пренебрегване",
|
||||
@@ -386,6 +386,7 @@
|
||||
"Staggered File Versioning": "Разпределени версии",
|
||||
"Start Browser": "Отваряне в мрежов четец",
|
||||
"Statistics": "Статистика",
|
||||
"Stay logged in": "Оставане в системата",
|
||||
"Stopped": "Спряна",
|
||||
"Stores and syncs only encrypted data. Folders on all connected devices need to be set up with the same password or be of type \"{%receiveEncrypted%}\" too.": "Съхранява и синхронизира само шифровани данни. Папките на всички свързани устройства трябва да бъдат настроени със същата парола или също да са от вида „{{receiveEncrypted}}“.",
|
||||
"Subject:": "Относно:",
|
||||
@@ -419,9 +420,9 @@
|
||||
"The cleanup interval cannot be blank.": "Интервалът на почистване не може да бъде празен.",
|
||||
"The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.": "Настройките са запазени, но не са приложени. За да влязат в сила Syncthing трябва да се рестартира.",
|
||||
"The device ID cannot be blank.": "Полето идентификатор на устройство не може да бъде празно.",
|
||||
"The device ID to enter here can be found in the \"Actions > Show ID\" dialog on the other device. Spaces and dashes are optional (ignored).": "Идентификаторът на устройството, който да въведете се намира в „Действия > Идентификатор“. Интервалите и дефисите са незадължителни.",
|
||||
"The device ID to enter here can be found in the \"Actions > Show ID\" dialog on the other device. Spaces and dashes are optional (ignored).": "Идентификаторът на устройството, който трябва да въведете се намира в „Действия > Идентификатор“. Интервалите и дефисите са незадължителни.",
|
||||
"The encrypted usage report is sent daily. It is used to track common platforms, folder sizes, and app versions. If the reported data set is changed you will be prompted with this dialog again.": "Шифрованият отчет за употреба се изпраща ежедневно. Използва се за отчитане на най-често срещаните платформи, размери на папки и издания на приложението. При промяна в събираните данни отново ще бъде поискано вашето съгласие.",
|
||||
"The entered device ID does not look valid. It should be a 52 or 56 character string consisting of letters and numbers, with spaces and dashes being optional.": "Въведеният идентификатор на устройство не е валиден. Трябва да бъде 52 или 56 символа и да се състои от букви и цифри, като интервалите и дефисите са незадължителни.",
|
||||
"The entered device ID does not look valid. It should be a 52 or 56 character string consisting of letters and numbers, with spaces and dashes being optional.": "Въведеният идентификатор на устройство не е приемлив. Трябва да бъде 52 или 56 символа и да се състои от букви и цифри, като интервалите и дефисите са незадължителни.",
|
||||
"The folder ID cannot be blank.": "Полето идентификатор на папка не може да бъде празно.",
|
||||
"The folder ID must be unique.": "Идентификаторът на папката трябва да бъде уникален.",
|
||||
"The folder content on other devices will be overwritten to become identical with this device. Files not present here will be deleted on other devices.": "Съдържанието на папката в другите устройства ще бъде презаписано, за да стане еднакво със съдържанието на това устройство. Файловете, които ги няма тук, но съществуват на другите устройства ще бъдат премахнати.",
|
||||
|
||||
@@ -282,7 +282,7 @@
|
||||
"Pending changes": "Čekající změny",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Periodické skenování podle zadaného intervalu; sledování změn vypnuto",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Periodické skenování podle zadaného intervalu; sledování změn zapnuto",
|
||||
"Periodic scanning at given interval and failed setting up watching for changes, retrying every 1m:": "Periodické skenování podle zadaného intervalu; nastavení sledování změn se nezdařilo, opětovný pokus každou 1 min: ",
|
||||
"Periodic scanning at given interval and failed setting up watching for changes, retrying every 1m:": "Periodické skenování podle zadaného intervalu; nastavení sledování změn se nezdařilo, opětovný pokus každou 1 min:",
|
||||
"Permanently add it to the ignore list, suppressing further notifications.": "Natrvalo ignorovat, takže oznámení již nebudou přicházet.",
|
||||
"Please consult the release notes before performing a major upgrade.": "Před přechodem na novější hlavní verzi si nejdříve přečtěte poznámky k vydání nové verze.",
|
||||
"Please set a GUI Authentication User and Password in the Settings dialog.": "V dialogu Nastavení zadejte uživatelské jméno a heslo pro ověření se v GUI.",
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
"Are you sure you want to upgrade?": "Sind Sie sicher, dass Sie ein Upgrade durchführen möchten?",
|
||||
"Authentication Required": "Authentifizierung erforderlich",
|
||||
"Authors": "Autoren",
|
||||
"Auto Accept": "Automatische Annahme",
|
||||
"Auto Accept": "Automatisch annehmen",
|
||||
"Automatic Crash Reporting": "Automatische Absturzmeldung",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Die automatische Aktualisierung bietet jetzt die Wahl zwischen stabilen Veröffentlichungen und Veröffentlichungskandidaten.",
|
||||
"Automatic upgrades": "Automatische Aktualisierungen aktivieren",
|
||||
@@ -99,6 +99,7 @@
|
||||
"Device ID": "Gerätekennung",
|
||||
"Device Identification": "Geräteidentifikation",
|
||||
"Device Name": "Gerätename",
|
||||
"Device Status": "Gerätestatus",
|
||||
"Device is untrusted, enter encryption password": "Gerät wird nicht vertraut, Verschlüsselungspasswort eingeben",
|
||||
"Device rate limits": "Datenratenbegrenzungen fürs Gerät",
|
||||
"Device that last modified the item": "Gerät, das das Element zuletzt geändert hat",
|
||||
@@ -168,6 +169,7 @@
|
||||
"Folder ID": "Ordnerkennung",
|
||||
"Folder Label": "Ordnerbezeichnung",
|
||||
"Folder Path": "Ordnerpfad",
|
||||
"Folder Status": "Ordnerstatus",
|
||||
"Folder Type": "Ordnertyp",
|
||||
"Folder type \"{%receiveEncrypted%}\" can only be set when adding a new folder.": "Ordnertyp „{{receiveEncrypted}}“ kann nur beim Hinzufügen eines neuen Ordners festgelegt werden.",
|
||||
"Folder type \"{%receiveEncrypted%}\" cannot be changed after adding the folder. You need to remove the folder, delete or decrypt the data on disk, and add the folder again.": "Der Ordnertyp „{{receiveEncrypted}}“ kann nach dem Hinzufügen nicht geändert werden. Sie müssen den Ordner entfernen, die Daten auf dem Speichermedium löschen oder entschlüsseln und anschließend den Ordner wieder neu hinzufügen.",
|
||||
@@ -384,6 +386,7 @@
|
||||
"Staggered File Versioning": "Stufenweise Dateiversionierung",
|
||||
"Start Browser": "Browser starten",
|
||||
"Statistics": "Statistiken",
|
||||
"Stay logged in": "Angemeldet bleiben",
|
||||
"Stopped": "Gestoppt",
|
||||
"Stores and syncs only encrypted data. Folders on all connected devices need to be set up with the same password or be of type \"{%receiveEncrypted%}\" too.": "Speichert und synchronisiert nur verschlüsselte Daten. Ordner auf allen verbundenen Geräten müssen mit dem selben Passwort eingerichtet werden oder vom Typ „{{receiveEncrypted}}“ sein.",
|
||||
"Subject:": "Betreff:",
|
||||
|
||||
@@ -6,11 +6,14 @@
|
||||
"About": "Σχετικά με το Syncthing",
|
||||
"Action": "Ενέργεια",
|
||||
"Actions": "Ενέργειες",
|
||||
"Active filter rules": "Ενεργοί κανόνες φίλτρου",
|
||||
"Add": "Προσθήκη",
|
||||
"Add Device": "Προσθήκη συσκευής",
|
||||
"Add Folder": "Προσθήκη φακέλου",
|
||||
"Add Remote Device": "Προσθήκη Απομακρυσμένης Συσκευής",
|
||||
"Add devices from the introducer to our device list, for mutually shared folders.": "Προσθήκη συσκευών από το Βασικό κόμβο στη λίστα συσκευών μας, για όσους κοινούς φακέλους υπάρχουν μεταξύ τους.",
|
||||
"Add filter entry": "Προσθήκη καταχώρισης φίλτρου",
|
||||
"Add ignore patterns": "Προσθήκη μοτίβων παράβλεψης",
|
||||
"Add new folder?": "Προσθήκη νέου φακέλου;",
|
||||
"Additionally the full rescan interval will be increased (times 60, i.e. new default of 1h). You can also configure it manually for every folder later after choosing No.": "Θα αυξηθεί επίσης το διάστημα επανασαρώσεων στο 60-πλάσιο (νέα προεπιλεγμένη τιμή: 1 ώρα). Μπορείτε να το προσαρμόσετε για κάθε φάκελο αφού επιλέξετε «Όχι».",
|
||||
"Address": "Διεύθυνση",
|
||||
@@ -18,16 +21,26 @@
|
||||
"Advanced": "Προχωρημένες",
|
||||
"Advanced Configuration": "Προχωρημένες ρυθμίσεις",
|
||||
"All Data": "Όλα τα δεδομένα",
|
||||
"All Time": "Συνεχώς",
|
||||
"All folders shared with this device must be protected by a password, such that all sent data is unreadable without the given password.": "Όλοι οι φάκελοι που μοιράζονται με αυτήν τη συσκευή πρέπει να προστατεύονται με κωδικό πρόσβασης, έτσι ώστε όλα τα δεδομένα που αποστέλλονται να μην είναι αναγνώσιμα χωρίς τον συγκεκριμένο κωδικό πρόσβασης.",
|
||||
"Allow Anonymous Usage Reporting?": "Να επιτρέπεται η αποστολή ανώνυμων στοιχείων χρήσης;",
|
||||
"Allowed Networks": "Επιτρεπόμενα δίκτυα",
|
||||
"Alphabetic": "Αλφαβητικά",
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder. If the path to the application contains spaces, it should be quoted.": "Μια εξωτερική εντολή χειρίζεται την τήρηση εκδόσεων και αναλαμβάνει να αφαιρέσει το αρχείο από τον συγχρονισμένο φάκελο. Αν η διαδρομή προς την εφαρμογή περιέχει διαστήματα, πρέπει να εσωκλείεται σε εισαγωγικά. ",
|
||||
"Altered by ignoring deletes.": "Τροποποιήθηκε με παράβλεψη διαγραφών.",
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder. If the path to the application contains spaces, it should be quoted.": "Μια εξωτερική εντολή χειρίζεται την τήρηση εκδόσεων και αναλαμβάνει να αφαιρέσει το αρχείο από τον συγχρονισμένο φάκελο. Αν η διαδρομή προς την εφαρμογή περιέχει διαστήματα, πρέπει να εσωκλείεται σε εισαγωγικά.",
|
||||
"Anonymous Usage Reporting": "Ανώνυμα στοιχεία χρήσης",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "Η μορφή της αναφοράς ανώνυμων στοιχείων χρήσης έχει αλλάξει. Επιθυμείτε να μεταβείτε στη νέα μορφή;",
|
||||
"Applied to LAN": "Εφαρμόστηκε σε LAN",
|
||||
"Apply": "Εφαρμογή",
|
||||
"Are you sure you want to override all remote changes?": "Είστε βέβαιοι ότι θέλετε να παρακάμψετε όλες τις απομακρυσμένες αλλαγές;",
|
||||
"Are you sure you want to permanently delete all these files?": "Είστε βέβαιοι ότι θέλετε να διαγράψετε οριστικά όλα αυτά τα αρχεία;",
|
||||
"Are you sure you want to remove device {%name%}?": "Σίγουρα επιθυμείτε να αφαιρέσετε τη συσκευή {{name}};",
|
||||
"Are you sure you want to remove folder {%label%}?": "Σίγουρα επιθυμείτε να αφαιρέσετε τον φάκελο {{label}};",
|
||||
"Are you sure you want to restore {%count%} files?": "Σίγουρα επιθυμείτε να επαναφέρετε {{count}} αρχεία;",
|
||||
"Are you sure you want to revert all local changes?": "Είστε βέβαιοι ότι θέλετε να επαναφέρετε όλες τις τοπικές αλλαγές;",
|
||||
"Are you sure you want to upgrade?": "Σίγουρα επιθυμείτε να αναβαθμίσετε;",
|
||||
"Authentication Required": "Απαιτείται έλεγχος ταυτότητας",
|
||||
"Authors": "Συγγραφείς",
|
||||
"Auto Accept": "Αυτόματη αποδοχή",
|
||||
"Automatic Crash Reporting": "Αυτόματη αναφορά σφαλμάτων",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Για τις αυτόματες αναβαθμίσεις μπορείτε πλέον να επιλέξετε μεταξύ σταθερών εκδόσεων και υποψήφιων εκδόσεων.",
|
||||
@@ -36,32 +49,58 @@
|
||||
"Automatically create or share folders that this device advertises at the default path.": "Αυτόματη δημιουργία ή κοινή χρήση φακέλων τους οποίους ανακοινώνει αυτή η συσκευή στην προκαθορισμένη διαδρομή.",
|
||||
"Available debug logging facilities:": "Διαθέσιμες επιλογές μηνυμάτων αποσφαλμάτωσης:",
|
||||
"Be careful!": "Με προσοχή!",
|
||||
"Body:": "Περιεχόμενο:",
|
||||
"Bugs": "Bugs",
|
||||
"Cancel": "Ματαίωση",
|
||||
"Changelog": "Πληροφορίες εκδόσεων",
|
||||
"Clean out after": "Εκκαθάριση μετά από",
|
||||
"Cleaning Versions": "Καθαρισμός Εκδόσεων",
|
||||
"Cleanup Interval": "Διάστημα καθαρισμού",
|
||||
"Click to see full identification string and QR code.": "Κάντε κλικ για να δείτε την πλήρη συμβολοσειρά αναγνώρισης και τον κωδικό QR.",
|
||||
"Close": "Τέλος",
|
||||
"Command": "Εντολή",
|
||||
"Comment, when used at the start of a line": "Σχόλιο, όταν χρησιμοποιείται στην αρχή μιας γραμμής",
|
||||
"Compression": "Συμπίεση",
|
||||
"Configuration Directory": "Κατάλογος διαμόρφωσης",
|
||||
"Configuration File": "Αρχείο Διαμόρφωσης",
|
||||
"Configured": "Βάσει ρύθμισης",
|
||||
"Connected (Unused)": "Συνδεδεμένη (εκτός χρήσης)",
|
||||
"Connection Error": "Σφάλμα σύνδεσης",
|
||||
"Connection Management": "Διαχείριση Συνδέσεων",
|
||||
"Connection Type": "Τύπος Σύνδεσης",
|
||||
"Connections": "Συνδέσεις",
|
||||
"Connections via relays might be rate limited by the relay": "Οι συνδέσεις μέσω αναμεταδοτών ενδέχεται να περιορίζονται από τον αναμεταδότη",
|
||||
"Continuously watching for changes is now available within Syncthing. This will detect changes on disk and issue a scan on only the modified paths. The benefits are that changes are propagated quicker and that less full scans are required.": "Το Syncthing πλέον υποστηρίζει τη συνεχή επιτήρηση αλλαγών. Αυτή ανιχνεύει τις αλλαγές στον δίσκο και πραγματοποιεί σάρωση μόνο στα τροποποιημένα μονοπάτια. Χάρις σε αυτήν, οι αλλαγές διαδίδονται ταχύτερα και απαιτούνται λιγότερες πλήρεις σαρώσεις.",
|
||||
"Copied from elsewhere": "Έχει αντιγραφεί από κάπου αλλού",
|
||||
"Copied from original": "Έχει αντιγραφεί από το πρωτότυπο",
|
||||
"Copied!": "Αντιγράφηκε!",
|
||||
"Copy": "Αντιγραφή",
|
||||
"Copy failed! Try to select and copy manually.": "Η αντιγραφή απέτυχε! Προσπαθήστε να επιλέξετε και να αντιγράψετε χειροκίνητα.",
|
||||
"Currently Shared With Devices": "Διαμοιράζεται με αυτές τις συσκευές",
|
||||
"Custom Range": "Προσαρμοσμένο εύρος",
|
||||
"Danger!": "Προσοχή!",
|
||||
"Database Location": "Τοποθεσία βάσης δεδομένων",
|
||||
"Debugging Facilities": "Εργαλεία αποσφαλμάτωσης",
|
||||
"Default": "Προκαθορισμένο",
|
||||
"Default Configuration": "Προκαθορισμένη διαμόρφωση",
|
||||
"Default Device": "Προεπιλεγμένη συσκευή",
|
||||
"Default Folder": "Προεπιλεγμένος φάκελος",
|
||||
"Default Ignore Patterns": "Προεπιλεγμένα μοτίβα παράβλεψης",
|
||||
"Defaults": "Προεπιλογές",
|
||||
"Delete": "Διαγραφή",
|
||||
"Delete Unexpected Items": "Διαγραφή μη αναμενόμενων στοιχείων",
|
||||
"Deleted {%file%}": "Διαγράφηκε το {{file}}",
|
||||
"Deselect All": "Αποεπιλογή όλων",
|
||||
"Deselect devices to stop sharing this folder with.": "Αποεπιλέξτε συσκευές για να σταματήσει ο διαμοιρασμός του φακέλου με αυτές.",
|
||||
"Deselect folders to stop sharing with this device.": "Καταργήστε την επιλογή φακέλων για να διακόψετε την κοινή χρήση με αυτήν τη συσκευή.",
|
||||
"Device": "Συσκευή",
|
||||
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "Η συσκευή \"{{name}}\" ({{device}} στη διεύθυνση {{address}}) επιθυμεί να συνδεθεί. Προσθήκη της νέας συσκευής;",
|
||||
"Device Certificate": "Πιστοποιητικό συσκευής",
|
||||
"Device ID": "Ταυτότητα συσκευής",
|
||||
"Device Identification": "Ταυτότητα συσκευής",
|
||||
"Device Name": "Όνομα συσκευής",
|
||||
"Device Status": "Κατάσταση συσκευής",
|
||||
"Device is untrusted, enter encryption password": "Η συσκευή δεν είναι αξιόπιστη, εισαγάγετε τον κωδικό κρυπτογράφησης",
|
||||
"Device rate limits": "Όρια ταχύτητας συσκευών",
|
||||
"Device that last modified the item": "Συσκευή από την οποία πραγματοποιήθηκε η τελευταία τροποποίηση του στοιχείου",
|
||||
"Devices": "Συσκευές",
|
||||
@@ -70,12 +109,17 @@
|
||||
"Disabled periodic scanning and disabled watching for changes": "Έχουν απενεργοποιηθεί η τακτική σάρωση και η επιτήρηση αλλαγών",
|
||||
"Disabled periodic scanning and enabled watching for changes": "Έχει απενεργοποιηθεί η τακτική σάρωση και ενεργοποιηθεί η επιτήρηση αλλαγών",
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Έχει απενεργοποιηθεί η τακτική σάρωση και απέτυχε η ενεργοποίηση επιτήρησης αλλαγών. Γίνεται νέα προσπάθεια κάθε 1m:",
|
||||
"Disables comparing and syncing file permissions. Useful on systems with nonexistent or custom permissions (e.g. FAT, exFAT, Synology, Android).": "Απενεργοποιεί τη σύγκριση και τον συγχρονισμό των δικαιωμάτων αρχείων. Χρήσιμο σε συστήματα με ανύπαρκτα ή προσαρμοσμένα δικαιώματα (π.χ. FAT, exFAT, Synology, Android).",
|
||||
"Discard": "Απόρριψη",
|
||||
"Disconnected": "Αποσυνδεδεμένη",
|
||||
"Disconnected (Inactive)": "Αποσυνδεδεμένο (Ανενεργό)",
|
||||
"Disconnected (Unused)": "Αποσυνδεδεμένη (εκτός χρήσης)",
|
||||
"Discovered": "Βάσει ανεύρεσης",
|
||||
"Discovery": "Ανεύρεση συσκευών",
|
||||
"Discovery Failures": "Αποτυχίες ανεύρεσης συσκευών",
|
||||
"Discovery Status": "Κατάσταση Ανακάλυψης",
|
||||
"Dismiss": "Απόρριψη",
|
||||
"Do not add it to the ignore list, so this notification may recur.": "Να μην προστεθεί στη λίστα παράβλεψης, οπότε αυτή η ειδοποίηση ενδέχεται να επαναληφθεί.",
|
||||
"Do not restore": "Να μη γίνει επαναφορά",
|
||||
"Do not restore all": "Να μη γίνει επαναφορά όλων",
|
||||
"Do you want to enable watching for changes for all your folders?": "Επιθυμείτε να ενεργοποιήσετε την επιτήρηση για όλους τους φακέλους σας;",
|
||||
@@ -85,20 +129,31 @@
|
||||
"Downloading": "Λήψη",
|
||||
"Edit": "Επεξεργασία",
|
||||
"Edit Device": "Επεξεργασία συσκευής",
|
||||
"Edit Device Defaults": "Επεξεργασία προεπιλογών συσκευής",
|
||||
"Edit Folder": "Επεξεργασία φακέλου",
|
||||
"Edit Folder Defaults": "Επεξεργασία προεπιλογών φακέλου",
|
||||
"Editing {%path%}.": "Επεξεργασία του {{path}}.",
|
||||
"Enable Crash Reporting": "Ενεργοποίηση αναφοράς σφαλμάτων",
|
||||
"Enable NAT traversal": "Ενεργοποίηση διάσχισης NAT",
|
||||
"Enable Relaying": "Ενεργοποίηση αναμετάδοσης",
|
||||
"Enabled": "Ενεργοποιημένη",
|
||||
"Enables sending extended attributes to other devices, and applying incoming extended attributes. May require running with elevated privileges.": "Επιτρέπει την αποστολή εκτεταμένων χαρακτηριστικών σε άλλες συσκευές και την εφαρμογή εισερχόμενων εκτεταμένων χαρακτηριστικών. Μπορεί να απαιτεί εκτέλεση με αυξημένα δικαιώματα.",
|
||||
"Enables sending extended attributes to other devices, but not applying incoming extended attributes. This can have a significant performance impact. Always enabled when \"Sync Extended Attributes\" is enabled.": "Επιτρέπει την αποστολή εκτεταμένων χαρακτηριστικών σε άλλες συσκευές, αλλά όχι την εφαρμογή εισερχόμενων εκτεταμένων χαρακτηριστικών. Αυτό μπορεί να έχει σημαντικό αντίκτυπο στην απόδοση. Πάντα ενεργοποιημένο όταν είναι ενεργοποιημένο το \"Συγχρονισμός εκτεταμένων χαρακτηριστικών\".",
|
||||
"Enables sending ownership information to other devices, and applying incoming ownership information. Typically requires running with elevated privileges.": "Επιτρέπει την αποστολή πληροφοριών ιδιοκτησίας σε άλλες συσκευές και την εφαρμογή εισερχόμενων πληροφοριών ιδιοκτησίας. Συνήθως απαιτεί εκτέλεση με αυξημένα δικαιώματα.",
|
||||
"Enables sending ownership information to other devices, but not applying incoming ownership information. This can have a significant performance impact. Always enabled when \"Sync Ownership\" is enabled.": "Επιτρέπει την αποστολή πληροφοριών ιδιοκτησίας σε άλλες συσκευές, αλλά όχι την εφαρμογή εισερχόμενων πληροφοριών ιδιοκτησίας. Αυτό μπορεί να έχει σημαντικό αντίκτυπο στην απόδοση. Ενεργοποιείται πάντα όταν είναι ενεργοποιημένη η \"Συγχρονισμός ιδιοκτησίας\".",
|
||||
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Εισάγετε έναν μη αρνητικό αριθμό (π.χ. «2.35») και επιλέξτε μια μονάδα μέτρησης. Τα ποσοστά ισχύουν ως προς το συνολικό μέγεθος του δίσκου.",
|
||||
"Enter a non-privileged port number (1024 - 65535).": "Εισάγετε τον αριθμό μιας μη δεσμευμένης θύρας (1024 - 65535).",
|
||||
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Εισάγετε τις διευθύνσεις χωρισμένες με κόμμα (\"tcp://ip:θύρα\", \"tcp://όνομα:θύρα\") ή γράψτε \"dynamic\" για την αυτόματη ανεύρεση τους.",
|
||||
"Enter ignore patterns, one per line.": "Δώσε τα πρότυπα που θα αγνοηθούν, ένα σε κάθε γραμμή.",
|
||||
"Enter up to three octal digits.": "Εισάγετε έως τρία οκταδικά ψηφία.",
|
||||
"Error": "Σφάλμα",
|
||||
"Extended Attributes": "Εκτεταμένα χαρακτηριστικά",
|
||||
"Extended Attributes Filter": "Εκτεταμένο φίλτρο χαρακτηριστικών",
|
||||
"External": "Εξωτερική",
|
||||
"External File Versioning": "Εξωτερική τήρηση εκδόσεων",
|
||||
"Failed Items": "Αρχεία που απέτυχαν",
|
||||
"Failed to load file versions.": "Η φόρτωση των εκδόσεων αρχείων απέτυχε.",
|
||||
"Failed to load ignore patterns.": "Αποτυχία φόρτωσης μοτίβων παράβλεψης.",
|
||||
"Failed to setup, retrying": "Αποτυχία ενεργοποίησης, γίνεται νέα προσπάθεια",
|
||||
"Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.": "Είναι φυσιολογική η αποτυχία σύνδεσης σε εξυπηρετητές IPv6 όταν δεν υπάρχει συνδεσιμότητα IPv6.",
|
||||
"File Pull Order": "Σειρά με την οποία θα κατεβαίνουν τα αρχεία",
|
||||
@@ -114,14 +169,21 @@
|
||||
"Folder ID": "Ταυτότητα φακέλου",
|
||||
"Folder Label": "Ετικέτα φακέλου",
|
||||
"Folder Path": "Μονοπάτι φακέλου",
|
||||
"Folder Status": "Κατάσταση φακέλου",
|
||||
"Folder Type": "Τύπος φακέλου",
|
||||
"Folder type \"{%receiveEncrypted%}\" can only be set when adding a new folder.": "Ο τύπος φακέλου \"{{receiveEncrypted}}\" μπορεί να οριστεί μόνο κατά την προσθήκη νέου φακέλου.",
|
||||
"Folder type \"{%receiveEncrypted%}\" cannot be changed after adding the folder. You need to remove the folder, delete or decrypt the data on disk, and add the folder again.": "Ο τύπος φακέλου \"{{receiveEncrypted}}\" δεν μπορεί να αλλάξει μετά την προσθήκη του φακέλου. Πρέπει να αφαιρέσετε το φάκελο, να διαγράψετε ή να αποκρυπτογραφήσετε τα δεδομένα στο δίσκο και να προσθέσετε ξανά το φάκελο.",
|
||||
"Folders": "Φάκελοι",
|
||||
"For the following folders an error occurred while starting to watch for changes. It will be retried every minute, so the errors might go away soon. If they persist, try to fix the underlying issue and ask for help if you can't.": "Στους παρακάτω φακέλους εμφανίστηκε σφάλμα κατά την ενεργοποίηση της επιτήρησης αλλαγών. Καθώς θα γίνεται νέα προσπάθεια κάθε λεπτό, ενδέχεται αυτά τα σφάλματα να διορθωθούν από μόνα τους. Αν παραμείνουν, προσπαθήστε να επιλύσετε το βασικό αίτιο ή ζητήστε βοήθεια αν δεν μπορείτε.",
|
||||
"Forever": "Για πάντα",
|
||||
"Full Rescan Interval (s)": "Διάστημα πλήρων επανασαρώσεων (s)",
|
||||
"GUI": "Γραφικό περιβάλλον",
|
||||
"GUI / API HTTPS Certificate": "Πιστοποιητικό HTTPS για το GUI / API",
|
||||
"GUI Authentication Password": "Κωδικός για την πρόσβαση στη διεπαφή",
|
||||
"GUI Authentication User": "Χρηστώνυμο για την πρόσβαση στη διεπαφή",
|
||||
"GUI Authentication: Set User and Password": "Έλεγχος ταυτότητας GUI: Ορισμός χρήστη και κωδικού πρόσβασης",
|
||||
"GUI Listen Address": "Διεύθυνση ακρόασης γραφικού περιβάλλοντος (GUI)",
|
||||
"GUI Override Directory": "Κατάλογος παράκαμψης GUI",
|
||||
"GUI Theme": "Θέμα GUI",
|
||||
"General": "Γενικά",
|
||||
"Generate": "Δημιουργία",
|
||||
@@ -129,27 +191,42 @@
|
||||
"Global Discovery Servers": "Διακομιστές καθολικής ανεύρεσης κόμβων",
|
||||
"Global State": "Καθολική κατάσταση",
|
||||
"Help": "Βοήθεια",
|
||||
"Hint: only deny-rules detected while the default is deny. Consider adding \"permit any\" as last rule.": "Συμβουλή: εντοπίζονται μόνο κανόνες άρνησης ενώ η προεπιλογή είναι η άρνηση. Εξετάστε το ενδεχόμενο να προσθέσετε \"επιτρέπονται όλοι\" ως τελευταίο κανόνα.",
|
||||
"Home page": "Αρχική σελίδα",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "Ωστόσο, σύμφωνα με τις τρέχουσες ρυθμίσεις σας, μάλλον δεν επιθυμείτε αυτή τη λειτουργία. Οι αναφορές σφαλμάτων απενεργοποιήθηκαν.",
|
||||
"Identification": "Ταυτοποίηση",
|
||||
"If untrusted, enter encryption password": "Εάν δεν είναι αξιόπιστοι, εισαγάγετε έναν κωδικό πρόσβασης κρυπτογράφησης",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "Εάν θέλετε να εμποδίσετε άλλους χρήστες σε αυτόν τον υπολογιστή να έχουν πρόσβαση στο Syncthing και μέσω αυτού στα αρχεία σας, εξετάστε το ενδεχόμενο να ρυθμίσετε τον έλεγχο ταυτότητας.",
|
||||
"Ignore": "Αγνόησε",
|
||||
"Ignore Patterns": "Πρότυπο για αγνόηση",
|
||||
"Ignore Permissions": "Αγνόησε τα δικαιώματα",
|
||||
"Ignore patterns can only be added after the folder is created. If checked, an input field to enter ignore patterns will be presented after saving.": "Τα μοτίβα παράβλεψης μπορούν να προστεθούν μόνο μετά τη δημιουργία του φακέλου. Εάν είναι επιλεγμένο, θα εμφανιστεί ένα πεδίο εισαγωγής για την εισαγωγή μοτίβων παράβλεψης μετά την αποθήκευση.",
|
||||
"Ignored Devices": "Αγνοηθείσες συσκευές",
|
||||
"Ignored Folders": "Αγνοηθέντες φάκελοι",
|
||||
"Ignored at": "Αγνοήθηκε στην",
|
||||
"Included Software": "Συμπεριλαμβανόμενο Λογισμικό",
|
||||
"Incoming Rate Limit (KiB/s)": "Περιορισμός ταχύτητας λήψης (KiB/s)",
|
||||
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Με μια εσφαλμένη ρύθμιση μπορεί να προκληθεί ζημιά στα περιεχόμενα των φακέλων και το Syncthing να σταματήσει να λειτουργεί.",
|
||||
"Incorrect user name or password.": "Λανθασμένο όνομα χρήστη ή κωδικός πρόσβασης.",
|
||||
"Internally used paths:": "Διαδρομές που χρησιμοποιούνται εσωτερικά:",
|
||||
"Introduced By": "Προτάθηκε από",
|
||||
"Introducer": "Βασικός κόμβος",
|
||||
"Introduction": "Εισαγωγή",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "Αντιστροφή της δοσμένης συνθήκης (π.χ. να μην εξαιρείς) ",
|
||||
"Keep Versions": "Διατήρηση εκδόσεων",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "Το μεγαλύτερο πρώτα",
|
||||
"Last 30 Days": "Τελευταίες 30 ημέρες",
|
||||
"Last 7 Days": "Τελευταίες 7 ημέρες",
|
||||
"Last Month": "Τον προηγούμενο μήνα",
|
||||
"Last Scan": "Τελευταία Σάρωση",
|
||||
"Last seen": "Τελευταία σύνδεση",
|
||||
"Latest Change": "Τελευταία αλλαγή",
|
||||
"Learn more": "Μάθετε περισσότερα",
|
||||
"Learn more at {%url%}": "Μάθετε περισσότερα στο {{url}}",
|
||||
"Limit": "Όριο",
|
||||
"Listener Failures": "Αποτυχίες ακροατή",
|
||||
"Listener Status": "Κατάσταση ακροατή",
|
||||
"Listeners": "Ακροατές",
|
||||
"Loading data...": "Φόρτωση δεδομένων...",
|
||||
"Loading...": "Φόρτωση...",
|
||||
@@ -159,15 +236,26 @@
|
||||
"Local State (Total)": "Τοπική κατάσταση (συνολικά)",
|
||||
"Locally Changed Items": "Τοπικές αλλαγές",
|
||||
"Log": "Αρχείο καταγραφής",
|
||||
"Log File": "Αρχείο καταγραφής",
|
||||
"Log In": "Σύνδεση",
|
||||
"Log Out": "Αποσύνδεση",
|
||||
"Log in to see paths information.": "Συνδεθείτε για να δείτε πληροφορίες για τις διαδρομές.",
|
||||
"Log in to see version information.": "Συνδεθείτε για να δείτε πληροφορίες έκδοσης.",
|
||||
"Log tailing paused. Scroll to the bottom to continue.": "Η αυτόματη παρακολούθηση του αρχείου καταγραφής είναι σε παύση. Κυλίστε στο τέλος της οθόνης για να συνεχίσετε.",
|
||||
"Login failed, see Syncthing logs for details.": "Η σύνδεση απέτυχε, ανατρέξτε στην ενότητα Syncthing αρχείων καταγραφής για λεπτομέρειες.",
|
||||
"Logs": "Αρχεία καταγραφής",
|
||||
"Major Upgrade": "Σημαντική αναβάθμιση",
|
||||
"Mass actions": "Μαζικές ενέργειες",
|
||||
"Maximum Age": "Μέγιστη ηλικία",
|
||||
"Maximum single entry size": "Μέγιστο μέγεθος μιας εισόδου",
|
||||
"Maximum total size": "Μέγιστο συνολικό μέγεθος",
|
||||
"Metadata Only": "Μόνο μεταδεδομένα",
|
||||
"Minimum Free Disk Space": "Ελάχιστος ελεύθερος αποθηκευτικός χώρος",
|
||||
"Mod. Device": "Συσκευή τροποποίησης",
|
||||
"Mod. Time": "Ώρα τροποποίησης",
|
||||
"More than a month ago": "Πάνω από ένα μήνα πριν",
|
||||
"More than a week ago": "Πάνω από μια εβδομάδα πριν",
|
||||
"More than a year ago": "Πάνω από ένα χρόνο πριν",
|
||||
"Move to top of queue": "Μεταφορά στην αρχή της λίστας",
|
||||
"Multi level wildcard (matches multiple directory levels)": "Τελεστής μπαλαντέρ (*) για πολλά επίπεδα (χρησιμοποιείται για εμφωλευμένους φακέλους)",
|
||||
"Never": "Ποτέ",
|
||||
@@ -177,8 +265,11 @@
|
||||
"No": "Όχι",
|
||||
"No File Versioning": "Να μην τηρούνται εκδόσεις",
|
||||
"No files will be deleted as a result of this operation.": "Δεν πρόκειται να διαγραφούν αρχεία με αυτή την ενέργεια.",
|
||||
"No rules set": "Δεν υπάρχουν κανόνες",
|
||||
"No upgrades": "Απενεργοποιημένες",
|
||||
"Not shared": "Δεν μοιράζεται",
|
||||
"Notice": "Σημείωση",
|
||||
"Number of Connections": "Αριθμός Συνδέσεων",
|
||||
"OK": "OK",
|
||||
"Off": "Απενεργοποιημένο",
|
||||
"Oldest First": "Το παλιότερο πρώτα",
|
||||
@@ -187,10 +278,14 @@
|
||||
"Out of Sync": "Μη συγχρονισμένα",
|
||||
"Out of Sync Items": "Μη συγχρονισμένα αντικείμενα",
|
||||
"Outgoing Rate Limit (KiB/s)": "Περιορισμός ταχύτητας αποστολής (KiB/s)",
|
||||
"Override": "Παράκαμψη",
|
||||
"Override Changes": "Να αντικατασταθούν οι αλλαγές",
|
||||
"Ownership": "Ιδιοκτησία",
|
||||
"Password": "Κωδικός πρόσβασης",
|
||||
"Path": "Μονοπάτι",
|
||||
"Path to the folder on the local computer. Will be created if it does not exist. The tilde character (~) can be used as a shortcut for": "Μονοπάτι του φακέλου σε αυτόν τον υπολογιστή. Αν δεν υπάρχει θα δημιουργηθεί. Η περισπωμένη (~) μπορεί να μπει σαν συντόμευση για το",
|
||||
"Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).": "Ο κατάλογος στον οποίο θα αποθηκεύονται οι εκδόσεις των αρχείων (αν δεν οριστεί, θα αποθηκεύονται στον υποκατάλογο .stversions)",
|
||||
"Paths": "Διαδρομές",
|
||||
"Pause": "Παύση",
|
||||
"Pause All": "Παύση όλων",
|
||||
"Paused": "Σε παύση",
|
||||
@@ -199,6 +294,7 @@
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Τακτική σάρωση ανά καθορισμένο διάστημα και απενεργοποίηση επιτήρησης αλλαγών",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Τακτική σάρωση ανά καθορισμένο διάστημα και ενεργοποίηση επιτήρησης αλλαγών",
|
||||
"Periodic scanning at given interval and failed setting up watching for changes, retrying every 1m:": "Τακτική σάρωση ανά καθορισμένο διάστημα και αποτυχία ενεργοποίησης επιτήρησης αλλαγών. Γίνεται νέα προσπάθεια κάθε 1m:",
|
||||
"Permanently add it to the ignore list, suppressing further notifications.": "Προσθέστε το μόνιμα στη λίστα παράβλεψης, καταργώντας περαιτέρω ειδοποιήσεις.",
|
||||
"Please consult the release notes before performing a major upgrade.": "Παρακαλούμε, πριν από την εκτέλεση μιας σημαντικής αναβάθμισης, να συμβουλευτείς το σημείωμα που τη συνοδεύει.",
|
||||
"Please set a GUI Authentication User and Password in the Settings dialog.": "Παρακαλώ όρισε στις ρυθμίσεις έναν χρήστη και έναν κωδικό πρόσβασης για τη διεπαφή.",
|
||||
"Please wait": "Παρακαλώ περιμένετε",
|
||||
@@ -207,14 +303,22 @@
|
||||
"Preparing to Sync": "Προετοιμασία συγχρονισμού",
|
||||
"Preview": "Προεπισκόπηση",
|
||||
"Preview Usage Report": "Προεπισκόπηση αναφοράς χρήσης",
|
||||
"QR code": "Κωδικός QR",
|
||||
"QUIC LAN": "QUIC LAN",
|
||||
"QUIC WAN": "QUIC WAN",
|
||||
"Quick guide to supported patterns": "Σύντομη βοήθεια σχετικά με τα πρότυπα αναζήτησης που υποστηρίζονται",
|
||||
"Random": "Τυχαία",
|
||||
"Receive Encrypted": "Λήψη κρυπτογραφημένων",
|
||||
"Receive Only": "Μόνο λήψη",
|
||||
"Received data is already encrypted": "Τα ληφθέντα δεδομένα είναι ήδη κρυπτογραφημένα",
|
||||
"Recent Changes": "Πρόσφατες αλλαγές",
|
||||
"Reduced by ignore patterns": "Περιορισμένα λόγω προτύπων αγνόησης",
|
||||
"Relay LAN": "Αναμεταδότης LAN",
|
||||
"Relay WAN": "Αναμεταδότης WAN",
|
||||
"Release Notes": "Σημείωμα έκδοσης",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Οι υποψήφιες εκδόσεις περιέχουν τις νεότερες λειτουργίες και επιδιορθώσεις σφαλμάτων, όπως και οι παραδοσιακές δισεβδομαδιαίες εκδόσεις του Syncthing.",
|
||||
"Remote Devices": "Απομακρυσμένες συσκευές",
|
||||
"Remote GUI": "Απομακρυσμένο GUI",
|
||||
"Remove": "Αφαίρεση",
|
||||
"Remove Device": "Αφαίρεση συσκευής",
|
||||
"Remove Folder": "Αφαίρεση φακέλου",
|
||||
@@ -230,61 +334,90 @@
|
||||
"Resume": "Συνέχεια",
|
||||
"Resume All": "Συνέχιση όλων",
|
||||
"Reused": "Χρησιμοποιήθηκε ξανά",
|
||||
"Revert": "Επαναφορά",
|
||||
"Revert Local Changes": "Αναίρεση τοπικών αλλαγών",
|
||||
"Save": "Αποθήκευση",
|
||||
"Saving changes": "Αποθήκευση αλλαγών",
|
||||
"Scan Time Remaining": "Εναπομείναντας χρόνος για τον έλεγχο ",
|
||||
"Scanning": "Έλεγχος για αλλαγές",
|
||||
"See external versioning help for supported templated command line parameters.": "Ανατρέξτε στην τεκμηρίωση της εξωτερικής τήρησης εκδόσεων για πληροφορίες σχετικά με τις υποστηριζόμενες παραμέτρους της γραμμής εντολών.",
|
||||
"Select All": "Επιλογή όλων",
|
||||
"Select a version": "Επιλογή έκδοσης",
|
||||
"Select additional devices to share this folder with.": "Επιλέξτε επιπλέον συσκευές με τις οποίες θα διαμοιράζεται αυτός ο φάκελος.",
|
||||
"Select additional folders to share with this device.": "Επιλέξτε επιπλέον φακέλους για κοινή χρήση με αυτήν τη συσκευή.",
|
||||
"Select latest version": "Επιλογή τελευταίας έκδοσης",
|
||||
"Select oldest version": "Επιλογή παλαιότερης έκδοσης",
|
||||
"Send & Receive": "Αποστολή και λήψη",
|
||||
"Send Extended Attributes": "Αποστολή εκτεταμένων χαρακτηριστικών",
|
||||
"Send Only": "Μόνο αποστολή",
|
||||
"Send Ownership": "Αποστολή ιδιοκτησίας",
|
||||
"Set Ignores on Added Folder": "Ορίστε τα αγνοούμενα στον προστιθέμενο φάκελο",
|
||||
"Settings": "Ρυθμίσεις",
|
||||
"Share": "Διαμοίραση",
|
||||
"Share Folder": "Διαμοίραση φακέλου",
|
||||
"Share by Email": "Κοινή χρήση μέσω email",
|
||||
"Share by SMS": "Κοινή χρήση μέσω SMS",
|
||||
"Share this folder?": "Να διαμοιραστεί αυτός ο φάκελος;",
|
||||
"Shared Folders": "Κοινόχρηστοι φάκελοι",
|
||||
"Shared With": "Διαμοιράζεται με",
|
||||
"Sharing": "Διαμοιρασμός",
|
||||
"Show ID": "Εμφάνιση ταυτότητας",
|
||||
"Show QR": "Δείξε τον κωδικό QR",
|
||||
"Show detailed discovery status": "Εμφάνιση λεπτομερούς κατάστασης ανακάλυψης",
|
||||
"Show detailed listener status": "Εμφάνιση λεπτομερούς κατάστασης ακροατή",
|
||||
"Show diff with previous version": "Εμφάνιση διαφορών με προηγούμενη έκδοση",
|
||||
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Θα φαίνεται αντί για την ταυτότητα της συσκευής στην προβολή της κατάστασης ολόκληρης της συστάδας. Θα γνωστοποιείται σαν το προαιρετικό όνομα της συσκευής.",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Θα φαίνεται αντί για την ταυτότητα της συσκευής στην προβολή της κατάστασης ολόκληρης της συστάδας. Θα ενημερώνεται αυτόματα αν αλλάξει το όνομα της συσκευής.",
|
||||
"Shutdown": "Απενεργοποίηση",
|
||||
"Shutdown Complete": "Πλήρης απενεργοποίηση",
|
||||
"Simple": "Απλό",
|
||||
"Simple File Versioning": "Απλή τήρηση εκδόσεων",
|
||||
"Single level wildcard (matches within a directory only)": "Τελεστής μπαλαντέρ (*) για ένα επίπεδο (χρησιμοποιείται για έναν φάκελο μόνο)",
|
||||
"Size": "Μέγεθος",
|
||||
"Smallest First": "Το μικρότερο πρώτα",
|
||||
"Some discovery methods could not be established for finding other devices or announcing this device:": "Δεν ήταν δυνατή η καθιέρωση ορισμένων μεθόδων ανακάλυψης για την εύρεση άλλων συσκευών ή την ανακοίνωση αυτής της συσκευής:",
|
||||
"Some items could not be restored:": "Κάποια στοιχεία δεν μπόρεσαν να επαναφερθούν:",
|
||||
"Some listening addresses could not be enabled to accept connections:": "Δεν ήταν δυνατή η ενεργοποίηση ορισμένων διευθύνσεων ακρόασης για αποδοχή συνδέσεων:",
|
||||
"Source Code": "Πηγαίος κώδικας",
|
||||
"Stable releases and release candidates": "Σταθερές εκδόσεις και υποψήφιες εκδόσεις.",
|
||||
"Stable releases are delayed by about two weeks. During this time they go through testing as release candidates.": "Οι σταθερές εκδόσεις βγαίνουν με καθυστέρηση περίπου δύο εβδομάδων. Σε αυτό το διάστημα δοκιμάζονται ως υποψήφιες εκδόσεις.",
|
||||
"Stable releases only": "Μόνο σταθερές εκδόσεις",
|
||||
"Staggered": "Κλιμακωμένος",
|
||||
"Staggered File Versioning": "Να τηρούνται κλιμακούμενες εκδόσεις",
|
||||
"Start Browser": "Εκκίνηση προγράμματος περιήγησης",
|
||||
"Statistics": "Στατιστικά",
|
||||
"Stay logged in": "Παραμείνετε συνδεδεμένοι",
|
||||
"Stopped": "Απενεργοποιημένο",
|
||||
"Stores and syncs only encrypted data. Folders on all connected devices need to be set up with the same password or be of type \"{%receiveEncrypted%}\" too.": "Αποθηκεύει και συγχρονίζει μόνο κρυπτογραφημένα δεδομένα. Οι φάκελοι σε όλες τις συνδεδεμένες συσκευές πρέπει να ρυθμιστούν με τον ίδιο κωδικό πρόσβασης ή να είναι επίσης του τύπου \"{{receiveEncrypted}}\".",
|
||||
"Subject:": "Θέμα:",
|
||||
"Support": "Υποστήριξη",
|
||||
"Support Bundle": "Πακέτο υποστήριξης",
|
||||
"Sync Extended Attributes": "Συγχρονισμός εκτεταμένων χαρακτηριστικών",
|
||||
"Sync Ownership": "Συγχρονισμός ιδιοκτησίας",
|
||||
"Sync Protocol Listen Addresses": "Διευθύνσεις για το πρωτόκολλο συγχρονισμού",
|
||||
"Sync Status": "Κατάσταση συγχρονισμού",
|
||||
"Syncing": "Συγχρονίζω",
|
||||
"Syncthing device ID for \"{%devicename%}\"": "Συγχρονισμός αναγνωριστικού συσκευής για \"{{devicename}}\"",
|
||||
"Syncthing has been shut down.": "Το Syncthing έχει απενεργοποιηθεί.",
|
||||
"Syncthing includes the following software or portions thereof:": "Το Syncthing περιλαμβάνει τα παρακάτω λογισμικά ή μέρη αυτών:",
|
||||
"Syncthing is Free and Open Source Software licensed as MPL v2.0.": "Το Syncthing είναι ελεύθερο λογισμικό και ανοικτού κώδικα, με άδεια MPL v2.0.",
|
||||
"Syncthing is a continuous file synchronization program. It synchronizes files between two or more computers in real time, safely protected from prying eyes. Your data is your data alone and you deserve to choose where it is stored, whether it is shared with some third party, and how it's transmitted over the internet.": "Το Syncthing είναι ένα πρόγραμμα συνεχούς συγχρονισμού αρχείων. Συγχρονίζει αρχεία μεταξύ δύο ή περισσότερων υπολογιστών σε πραγματικό χρόνο, με ασφάλεια από τα αδιάκριτα βλέμματα. Τα δεδομένα σας είναι μόνο τα δεδομένα σας και σας αξίζει να επιλέξετε πού θα αποθηκευτούν, αν θα κοινοποιηθούν σε τρίτους και πώς θα μεταδοθούν μέσω του Διαδικτύου.",
|
||||
"Syncthing is listening on the following network addresses for connection attempts from other devices:": "Το Syncthing ακούει στις ακόλουθες διευθύνσεις δικτύου για προσπάθειες σύνδεσης από άλλες συσκευές:",
|
||||
"Syncthing is not listening for connection attempts from other devices on any address. Only outgoing connections from this device may work.": "Το Syncthing δεν ακούει για προσπάθειες σύνδεσης από άλλες συσκευές σε οποιαδήποτε διεύθυνση. Μόνο οι εξερχόμενες συνδέσεις από αυτήν τη συσκευή ενδέχεται να λειτουργούν.",
|
||||
"Syncthing is restarting.": "Το Syncthing επανεκκινείται.",
|
||||
"Syncthing is saving changes.": "Το Syncthing αποθηκεύει τις αλλαγές.",
|
||||
"Syncthing is upgrading.": "Το Syncthing αναβαθμίζεται.",
|
||||
"Syncthing now supports automatically reporting crashes to the developers. This feature is enabled by default.": "Το Syncthing επιτρέπει την αυτόματη υποβολή αναφορών σφαλμάτων στους προγραμματιστές. Η προεπιλεγμένη ρύθμιση είναι να αποστέλλονται οι αναφορές.",
|
||||
"Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…": "Το Syncthing φαίνεται πως είναι απενεργοποιημένο ή υπάρχει πρόβλημα στη σύνδεσή σου στο διαδίκτυο. Προσπαθώ πάλι…",
|
||||
"Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.": "Το Syncthing φαίνεται να αντιμετωπίζει ένα πρόβλημα με την επεξεργασία του αιτήματός σου. Παρακαλούμε, αν το πρόβλημα συνεχίζει, ανανέωσε την σελίδα ή επανεκκίνησε το Syncthing.",
|
||||
"TCP LAN": "TCP LAN",
|
||||
"TCP WAN": "TCP WAN",
|
||||
"Take me back": "Επιστροφή",
|
||||
"The GUI address is overridden by startup options. Changes here will not take effect while the override is in place.": "Η διεύθυνση του GUI έχει τροποποιηθεί μέσω παραμέτρων εκκίνησης. Οι αλλαγές εδώ δεν θα ισχύσουν όσο είναι ενεργές αυτές οι παράμετροι.",
|
||||
"The Syncthing Authors": "Οι δημιουργοί του Syncthing",
|
||||
"The Syncthing admin interface is configured to allow remote access without a password.": "Η διεπαφή διαχείρισης του Syncthing είναι ρυθμισμένη να επιτρέπει την πρόσβαση χωρίς κωδικό.",
|
||||
"The aggregated statistics are publicly available at the URL below.": "Τα στατιστικά που έχουν συλλεγεί είναι δημόσια διαθέσιμα στη παρακάτω διεύθυνση.",
|
||||
"The cleanup interval cannot be blank.": "Το διάστημα καθαρισμού δεν μπορεί να είναι κενό.",
|
||||
"The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.": "Οι ρυθμίσεις έχουν αποθηκευτεί αλλά δεν έχουν ενεργοποιηθεί. Πρέπει να επανεκκινήσεις το Syncthing για να ισχύσουν οι νέες ρυθμίσεις.",
|
||||
"The device ID cannot be blank.": "Η ταυτότητα της συσκευής δεν μπορεί να είναι κενή",
|
||||
"The device ID to enter here can be found in the \"Actions > Show ID\" dialog on the other device. Spaces and dashes are optional (ignored).": "Η ταυτότητα της συσκευής που θα μπει εδώ βρίσκεται στο μενού «Ενέργειες > Εμφάνιση ταυτότητας» στην άλλη συσκευή. Κενοί χαρακτήρες και παύλες είναι προαιρετικοί (θα αγνοηθούν).",
|
||||
@@ -292,38 +425,62 @@
|
||||
"The entered device ID does not look valid. It should be a 52 or 56 character string consisting of letters and numbers, with spaces and dashes being optional.": "Η ταυτότητα συσκευής που έδωσες δε φαίνεται έγκυρη. Θα πρέπει να είναι μια σειρά από 52 ή 56 χαρακτήρες (γράμματα και αριθμοί). Τα κενά και οι παύλες είναι προαιρετικά (αδιάφορα).",
|
||||
"The folder ID cannot be blank.": "Η ταυτότητα του φακέλου δεν μπορεί να είναι κενή.",
|
||||
"The folder ID must be unique.": "Η ταυτότητα του φακέλου πρέπει να είναι μοναδική.",
|
||||
"The folder content on other devices will be overwritten to become identical with this device. Files not present here will be deleted on other devices.": "Το περιεχόμενο του φακέλου σε άλλες συσκευές θα αντικατασταθεί για να γίνει πανομοιότυπο με αυτήν τη συσκευή. Τα αρχεία που δεν υπάρχουν εδώ θα διαγραφούν σε άλλες συσκευές.",
|
||||
"The folder content on this device will be overwritten to become identical with other devices. Files newly added here will be deleted.": "Το περιεχόμενο του φακέλου σε αυτήν τη συσκευή θα αντικατασταθεί για να γίνει πανομοιότυπο με άλλες συσκευές. Τα αρχεία που προστέθηκαν πρόσφατα εδώ θα διαγραφούν.",
|
||||
"The folder path cannot be blank.": "Το μονοπάτι του φακέλου δεν μπορεί να είναι κενό.",
|
||||
"The following intervals are used: for the first hour a version is kept every 30 seconds, for the first day a version is kept every hour, for the first 30 days a version is kept every day, until the maximum age a version is kept every week.": "Θα χρησιμοποιούνται τα εξής διαστήματα: Την πρώτη ώρα θα τηρείται μια έκδοση κάθε 30 δευτερόλεπτα. Την πρώτη ημέρα, μια έκδοση κάθε μια ώρα. Τις πρώτες 30 ημέρες, μία έκδοση κάθε ημέρα. Από εκεί και έπειτα μέχρι τη μέγιστη ηλικία, θα τηρείται μια έκδοση κάθε εβδομάδα.",
|
||||
"The following items could not be synchronized.": "Δεν ήταν δυνατόν να συγχρονιστούν τα παρακάτω αρχεία.",
|
||||
"The following items were changed locally.": "Τα παρακάτω στοιχεία τροποποιήθηκαν τοπικά.",
|
||||
"The following methods are used to discover other devices on the network and announce this device to be found by others:": "Οι ακόλουθες μέθοδοι χρησιμοποιούνται για τον εντοπισμό άλλων συσκευών στο δίκτυο και την αναγγελία της εύρεσης αυτής της συσκευής από άλλους:",
|
||||
"The following text will automatically be inserted into a new message.": "Το παρακάτω κείμενο θα εισαχθεί αυτόματα σε ένα νέο μήνυμα.",
|
||||
"The following unexpected items were found.": "Βρέθηκαν τα ακόλουθα απροσδόκητα στοιχεία.",
|
||||
"The interval must be a positive number of seconds.": "Το διάστημα πρέπει να είναι θετικός αριθμός δευτερολέπτων.",
|
||||
"The interval, in seconds, for running cleanup in the versions directory. Zero to disable periodic cleaning.": "Το διάστημα, σε δευτερόλεπτα, για την εκτέλεση εκκαθάρισης στον κατάλογο εκδόσεων. Μηδέν για να απενεργοποιήσετε τον περιοδικό καθαρισμό.",
|
||||
"The maximum age must be a number and cannot be blank.": "Η μέγιστη ηλικία πρέπει να είναι αριθμός και σίγουρα όχι κενό.",
|
||||
"The maximum time to keep a version (in days, set to 0 to keep versions forever).": "Η μέγιστη ηλικία παλιότερων εκδόσεων (σε ημέρες, αν δώσεις 0 οι παλιότερες εκδόσεις θα διατηρούνται για πάντα).",
|
||||
"The number of connections must be a non-negative number.": "Ο αριθμός των συνδέσεων πρέπει να είναι μη αρνητικός αριθμός.",
|
||||
"The number of days must be a number and cannot be blank.": "Ο αριθμός ημερών πρέπει να είναι αριθμός και σίγουρα όχι κενό.",
|
||||
"The number of days to keep files in the trash can. Zero means forever.": "Ο αριθμός ημερών που θα διατηρούνται τα αρχεία στον κάδο. Μηδέν σημαίνει διατήρηση για πάντα.",
|
||||
"The number of old versions to keep, per file.": "Πόσες παλιότερες εκδόσεις θα διατηρούνται, ανά αρχείο.",
|
||||
"The number of versions must be a number and cannot be blank.": "Ο αριθμός εκδόσεων πρέπει να είναι αριθμός και σίγουρα όχι κενό.",
|
||||
"The path cannot be blank.": "Το μονοπάτι δεν μπορεί να είναι κενό.",
|
||||
"The rate limit is applied to the accumulated traffic of all connections to this device.": "Το όριο ρυθμού εφαρμόζεται στη συσσωρευμένη κίνηση όλων των συνδέσεων σε αυτήν τη συσκευή.",
|
||||
"The rate limit must be a non-negative number (0: no limit)": "Το όριο ταχύτητας πρέπει να είναι ένας μη-αρνητικός αριθμός (0: χωρίς όριο)",
|
||||
"The remote device has not accepted sharing this folder.": "Η απομακρυσμένη συσκευή δεν έχει αποδεχτεί την κοινή χρήση αυτού του φακέλου.",
|
||||
"The remote device has paused this folder.": "Η απομακρυσμένη συσκευή έχει θέσει σε παύση αυτόν τον φάκελο.",
|
||||
"The rescan interval must be a non-negative number of seconds.": "Ο χρόνος επανελέγχου για αλλαγές είναι σε δευτερόλεπτα (δηλ. θετικός αριθμός).",
|
||||
"There are no devices to share this folder with.": "Δεν υπάρχουν συσκευές με τις οποίες διαμοιράζεται αυτός ο φάκελος.",
|
||||
"There are no file versions to restore.": "Δεν υπάρχουν εκδόσεις αρχείων για επαναφορά.",
|
||||
"There are no folders to share with this device.": "Δεν υπάρχουν φάκελοι για κοινή χρήση με αυτήν τη συσκευή.",
|
||||
"They are retried automatically and will be synced when the error is resolved.": "Όταν επιλυθεί το σφάλμα θα κατεβούν και θα συχρονιστούν αυτόματα.",
|
||||
"This Device": "Αυτή η συσκευή",
|
||||
"This Month": "Αυτο το μηνα",
|
||||
"This can easily give hackers access to read and change any files on your computer.": "Αυτό μπορεί εύκολα να δώσει πρόσβαση ανάγνωσης και επεξεργασίας αρχείων του υπολογιστή σας σε χάκερς.",
|
||||
"This device cannot automatically discover other devices or announce its own address to be found by others. Only devices with statically configured addresses can connect.": "Αυτή η συσκευή δεν μπορεί να ανακαλύψει αυτόματα άλλες συσκευές ή να ανακοινώσει τη δική της διεύθυνση που θα βρεθεί από άλλους. Μόνο συσκευές με στατικά διαμορφωμένες διευθύνσεις μπορούν να συνδεθούν.",
|
||||
"This is a major version upgrade.": "Αυτή είναι μια σημαντική αναβάθμιση.",
|
||||
"This setting controls the free space required on the home (i.e., index database) disk.": "Αυτή η επιλογή καθορίζει τον ελεύθερο χώρο που θα παραμένει ελεύθερος στον δίσκο όπου βρίσκεται ο κατάλογος της εφαρμογής (και συνεπώς η βάση δεδομένων ευρετηρίων).",
|
||||
"Time": "Χρόνος",
|
||||
"Time the item was last modified": "Ώρα τελευταίας τροποποίησης του στοιχείου",
|
||||
"To connect with the Syncthing device named \"{%devicename%}\", add a new remote device on your end with this ID:": "Για να συνδεθείτε με τη συσκευή συγχρονισμού με το όνομα \"{{devicename}}\", προσθέστε μια νέα απομακρυσμένη συσκευή στο άκρο σας με αυτό το αναγνωριστικό:",
|
||||
"To permit a rule, have the checkbox checked. To deny a rule, leave it unchecked.": "Για να επιτρέψετε έναν κανόνα, επιλέξτε το πλαίσιο ελέγχου. Για να αρνηθείτε έναν κανόνα, αφήστε τον ανεξέλεγκτο.",
|
||||
"Today": "Σήμερα",
|
||||
"Trash Can": "Κάδος απορριμμάτων",
|
||||
"Trash Can File Versioning": "Τήρηση εκδόσεων κάδου ανακύκλωσης",
|
||||
"Type": "Τύπος",
|
||||
"UNIX Permissions": "Άδειες αρχείων UNIX",
|
||||
"Unavailable": "Μη διαθέσιμο",
|
||||
"Unavailable/Disabled by administrator or maintainer": "Μη διαθέσιμο/απενεργοποιημένο από τον διαχειριστή ή υπεύθυνο διανομής",
|
||||
"Undecided (will prompt)": "Μη καθορισμένη (θα γίνει ερώτηση)",
|
||||
"Unexpected Items": "Απροσδόκητα στοιχεία",
|
||||
"Unexpected items have been found in this folder.": "Βρέθηκαν μη αναμενόμενα στοιχεία σε αυτόν τον φάκελο.",
|
||||
"Unignore": "Αναίρεση αγνόησης",
|
||||
"Unknown": "Άγνωστο",
|
||||
"Unshared": "Δε μοιράζεται",
|
||||
"Unshared Devices": "Συσκευές χωρίς διαμοιρασμό",
|
||||
"Unshared Folders": "Μη κοινόχρηστοι φάκελοι",
|
||||
"Untrusted": "Αναξιόπιστος",
|
||||
"Up to Date": "Ενημερωμένη",
|
||||
"Updated {%file%}": "Ενημερωμένο {{file}}",
|
||||
"Upgrade": "Αναβάθμιση",
|
||||
"Upgrade To {%version%}": "Αναβάθμιση στην έκδοση {{version}}",
|
||||
"Upgrading": "Αναβάθμιση",
|
||||
@@ -332,6 +489,13 @@
|
||||
"Usage reporting is always enabled for candidate releases.": "Η αποστολή αναφορών χρήσης είναι πάντα ενεργοποιημένη στις υποψήφιες εκδόσεις.",
|
||||
"Use HTTPS for GUI": "Χρήση HTTPS για τη διεπαφή",
|
||||
"Use notifications from the filesystem to detect changed items.": "Χρήση ειδοποιήσεων από το σύστημα αρχείων για την ανίχνευση αλλαγών.",
|
||||
"User": "Χρήστης",
|
||||
"User Home": "Αρχική σελίδα χρήστη",
|
||||
"Username/Password has not been set for the GUI authentication. Please consider setting it up.": "Όνομα χρήστη/Κωδικός πρόσβασης δεν έχει οριστεί για τον έλεγχο ταυτότητας GUI. Παρακαλώ σκεφτείτε να το ρυθμίσετε.",
|
||||
"Using a QUIC connection over LAN": "Χρήση σύνδεσης QUIC μέσω LAN",
|
||||
"Using a QUIC connection over WAN": "Χρήση σύνδεσης QUIC μέσω WAN",
|
||||
"Using a direct TCP connection over LAN": "Χρήση απευθείας σύνδεσης TCP μέσω LAN",
|
||||
"Using a direct TCP connection over WAN": "Χρήση απευθείας σύνδεσης TCP μέσω WAN",
|
||||
"Version": "Έκδοση",
|
||||
"Versions": "Εκδόσεις",
|
||||
"Versions Path": "Φάκελος τήρησης εκδόσεων",
|
||||
@@ -339,6 +503,7 @@
|
||||
"Waiting to Clean": "Αναμονή εκκαθάρισης",
|
||||
"Waiting to Scan": "Αναμονή σάρωσης",
|
||||
"Waiting to Sync": "Αναμονή συγχρονισμού",
|
||||
"Warning": "Προειδοποίηση",
|
||||
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Προσοχή, αυτό το μονοπάτι είναι γονικός φάκελος ενός υπάρχοντος φακέλου \"{{otherFolder}}\".",
|
||||
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Προσοχή, αυτό το μονοπάτι είναι γονικός φάκελος ενός υπάρχοντος φακέλου \"{{otherFolderLabel}}\" ({{otherFolder}}).",
|
||||
"Warning, this path is a subdirectory of an existing folder \"{%otherFolder%}\".": "Προσοχή, αυτό το μονοπάτι είναι υποφάκελος του υπάρχοντος φακέλου \"{{otherFolder}}\".",
|
||||
@@ -349,7 +514,10 @@
|
||||
"Watching for changes discovers most changes without periodic scanning.": "Με την επιτήρηση αλλαγών ανιχνεύονται οι περισσότερες αλλαγές χωρίς τακτικές σαρώσεις.",
|
||||
"When adding a new device, keep in mind that this device must be added on the other side too.": "Θυμήσου πως όταν προσθέτεις μια νέα συσκευή, ετούτη η συσκευή θα πρέπει να προστεθεί και στην άλλη πλευρά.",
|
||||
"When adding a new folder, keep in mind that the Folder ID is used to tie folders together between devices. They are case sensitive and must match exactly between all devices.": "Όταν προσθέτεις έναν νέο φάκελο, θυμήσου πως η ταυτότητα ενός φακέλου χρησιμοποιείται για να να συσχετίσει φακέλους μεταξύ συσκευών. Η ταυτότητα του φακέλου θα πρέπει να είναι η ίδια σε όλες τις συσκευές και έχουν σημασία τα πεζά ή κεφαλαία γράμματα.",
|
||||
"When set to more than one on both devices, Syncthing will attempt to establish multiple concurrent connections. If the values differ, the highest will be used. Set to zero to let Syncthing decide.": "Όταν οριστεί σε περισσότερες από μία και στις δύο συσκευές, το Syncthing θα επιχειρήσει να δημιουργήσει πολλές ταυτόχρονες συνδέσεις. Εάν οι τιμές διαφέρουν, θα χρησιμοποιηθεί η υψηλότερη. Ορίστε στο μηδέν για να αποφασίσει το Syncthing.",
|
||||
"Yes": "Ναι",
|
||||
"Yesterday": "Εχθές",
|
||||
"You can also copy and paste the text into a new message manually.": "Μπορείτε επίσης να αντιγράψετε και να επικολλήσετε το κείμενο σε ένα νέο μήνυμα με μη αυτόματο τρόπο.",
|
||||
"You can also select one of these nearby devices:": "Μπορείτε επίσης να επιλέξετε μια από αυτές τις γειτονικές συσκευές:",
|
||||
"You can change your choice at any time in the Settings dialog.": "Μπορείτε να αλλάξετε τη ρύθμιση αυτή ανά πάσα στιγμή στο παράθυρο «Ρυθμίσεις».",
|
||||
"You can read more about the two release channels at the link below.": "Μπορείτε να διαβάσετε περισσότερα για τα δύο κανάλια εκδόσεων στον παρακάτω σύνδεσμο.",
|
||||
@@ -357,12 +525,31 @@
|
||||
"You have no ignored folders.": "Δεν έχετε αγνοηθέντες φακέλους.",
|
||||
"You have unsaved changes. Do you really want to discard them?": "Έχετε μη αποθηκευμένες αλλαγές. Σίγουρα επιθυμείτε να τις απορρίψετε;",
|
||||
"You must keep at least one version.": "Πρέπει να τηρήσεις τουλάχιστον μια έκδοση.",
|
||||
"You should never add or change anything locally in a \"{%receiveEncrypted%}\" folder.": "Δεν πρέπει ποτέ να προσθέσετε ή να αλλάξετε οτιδήποτε τοπικά σε έναν φάκελο \"{{receiveEncrypted}}\".",
|
||||
"Your SMS app should open to let you choose the recipient and send it from your own number.": "Η εφαρμογή SMS θα πρέπει να ανοίξει για να σας επιτρέψει να επιλέξετε τον παραλήπτη και να τον στείλετε από τον δικό σας αριθμό.",
|
||||
"Your email app should open to let you choose the recipient and send it from your own address.": "Η εφαρμογή email σας θα πρέπει να ανοίξει για να σας επιτρέψει να επιλέξετε τον παραλήπτη και να τον στείλετε από τη δική σας διεύθυνση.",
|
||||
"days": "Μέρες",
|
||||
"deleted": "διαγράφηκε",
|
||||
"deny": "άρνηση",
|
||||
"directories": "κατάλογοι",
|
||||
"file": "αρχείο",
|
||||
"files": "αρχεία",
|
||||
"folder": "φάκελος",
|
||||
"full documentation": "πλήρης τεκμηρίωση",
|
||||
"items": "εγγραφές",
|
||||
"modified": "τροποποιήθηκε",
|
||||
"permit": "επιτρέπετε",
|
||||
"seconds": "δευτερόλεπτα",
|
||||
"theme": {
|
||||
"name": {
|
||||
"black": "Μαύρο",
|
||||
"dark": "Σκοτεινό",
|
||||
"default": "Προκαθορισμένο",
|
||||
"light": "Φωτεινό"
|
||||
}
|
||||
},
|
||||
"unknown device": "άγνωστη συσκευή",
|
||||
"{%device%} wants to share folder \"{%folder%}\".": "Η συσκευή {{device}} θέλει να μοιράσει τον φάκελο «{{folder}}».",
|
||||
"{%device%} wants to share folder \"{%folderlabel%}\" ({%folder%}).": "Η συσκευή {{device}} επιθυμεί να διαμοιράσει τον φάκελο \"{{folderlabel}}\" ({{folder}})."
|
||||
"{%device%} wants to share folder \"{%folderlabel%}\" ({%folder%}).": "Η συσκευή {{device}} επιθυμεί να διαμοιράσει τον φάκελο \"{{folderlabel}}\" ({{folder}}).",
|
||||
"{%reintroducer%} might reintroduce this device.": "Ο χρήστης {{reintroducer}} ενδέχεται να επαναφέρει αυτήν τη συσκευή."
|
||||
}
|
||||
|
||||
@@ -99,6 +99,7 @@
|
||||
"Device ID": "Device ID",
|
||||
"Device Identification": "Device Identification",
|
||||
"Device Name": "Device Name",
|
||||
"Device Status": "Device Status",
|
||||
"Device is untrusted, enter encryption password": "Device is untrusted, enter encryption password",
|
||||
"Device rate limits": "Device rate limits",
|
||||
"Device that last modified the item": "Device that last modified the item",
|
||||
@@ -168,6 +169,7 @@
|
||||
"Folder ID": "Folder ID",
|
||||
"Folder Label": "Folder Label",
|
||||
"Folder Path": "Folder Path",
|
||||
"Folder Status": "Folder Status",
|
||||
"Folder Type": "Folder Type",
|
||||
"Folder type \"{%receiveEncrypted%}\" can only be set when adding a new folder.": "Folder type \"{{receiveEncrypted}}\" can only be set when adding a new folder.",
|
||||
"Folder type \"{%receiveEncrypted%}\" cannot be changed after adding the folder. You need to remove the folder, delete or decrypt the data on disk, and add the folder again.": "Folder type \"{{receiveEncrypted}}\" cannot be changed after adding the folder. You need to remove the folder, delete or decrypt the data on disk, and add the folder again.",
|
||||
@@ -384,6 +386,7 @@
|
||||
"Staggered File Versioning": "Staggered File Versioning",
|
||||
"Start Browser": "Start Browser",
|
||||
"Statistics": "Statistics",
|
||||
"Stay logged in": "Stay logged in",
|
||||
"Stopped": "Stopped",
|
||||
"Stores and syncs only encrypted data. Folders on all connected devices need to be set up with the same password or be of type \"{%receiveEncrypted%}\" too.": "Stores and syncs only encrypted data. Folders on all connected devices need to be set up with the same password or be of type \"{{receiveEncrypted}}\" too.",
|
||||
"Subject:": "Subject:",
|
||||
|
||||
@@ -386,6 +386,7 @@
|
||||
"Staggered File Versioning": "Staggered File Versioning",
|
||||
"Start Browser": "Start Browser",
|
||||
"Statistics": "Statistics",
|
||||
"Stay logged in": "Stay logged in",
|
||||
"Stopped": "Stopped",
|
||||
"Stores and syncs only encrypted data. Folders on all connected devices need to be set up with the same password or be of type \"{%receiveEncrypted%}\" too.": "Stores and syncs only encrypted data. Folders on all connected devices need to be set up with the same password or be of type \"{{receiveEncrypted}}\" too.",
|
||||
"Subject:": "Subject:",
|
||||
|
||||
@@ -192,7 +192,7 @@
|
||||
"Options": "Opcioj",
|
||||
"Out of Sync": "Elsinkronigita",
|
||||
"Out of Sync Items": "Elsinkronigitaj Eroj",
|
||||
"Outgoing Rate Limit (KiB/s)": " Eliranta Rapideco Limo (KiB/s)",
|
||||
"Outgoing Rate Limit (KiB/s)": "Eliranta Rapideco Limo (KiB/s)",
|
||||
"Override Changes": "Transpasi Ŝanĝojn",
|
||||
"Path": "Vojo",
|
||||
"Path to the folder on the local computer. Will be created if it does not exist. The tilde character (~) can be used as a shortcut for": "Vojo de la dosierujo en la loka komputilo. Kreiĝos se ne ekzistas. La tilda signo (~) povas esti uzata kiel mallongigilo por",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"A device with that ID is already added.": "Ya se ha agregado un dispositivo con ese ID.",
|
||||
"A negative number of days doesn't make sense.": "Un número negativo de días no tiene sentido.",
|
||||
"A new major version may not be compatible with previous versions.": "Una nueva versión principal puede no ser compatible con las versiones anteriores.",
|
||||
"A new major version may not be compatible with previous versions.": "Una nueva versión principal podría no ser compatible con las versiones anteriores.",
|
||||
"API Key": "Clave del API",
|
||||
"About": "Acerca de",
|
||||
"Action": "Acción",
|
||||
@@ -10,7 +10,7 @@
|
||||
"Add": "Agregar",
|
||||
"Add Device": "Agregar el dispositivo",
|
||||
"Add Folder": "Agregar Carpeta",
|
||||
"Add Remote Device": "Añadir un dispositivo",
|
||||
"Add Remote Device": "Añadir un dispositivo remoto",
|
||||
"Add devices from the introducer to our device list, for mutually shared folders.": "Añadir dispositivos desde el introductor a nuestra lista de dispositivos, para las carpetas compartidas mutuamente.",
|
||||
"Add filter entry": "Añadir una entrada al filtro",
|
||||
"Add ignore patterns": "Agregar patrones a ignorar",
|
||||
@@ -26,14 +26,14 @@
|
||||
"Allow Anonymous Usage Reporting?": "¿Deseas permitir el envío anónimo de informes de uso?",
|
||||
"Allowed Networks": "Redes permitidas",
|
||||
"Alphabetic": "Alfabético",
|
||||
"Altered by ignoring deletes.": "Alterado al ignorar eliminaciones.",
|
||||
"Altered by ignoring deletes.": "Alterado ignorando eliminaciones.",
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder. If the path to the application contains spaces, it should be quoted.": "Un comando externo maneja las versiones. Tienes que eliminar el archivo de la carpeta compartida. Si la ruta a la aplicación contiene espacios, ésta debe estar entre comillas.",
|
||||
"Anonymous Usage Reporting": "Informe anónimo de uso",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "El formato del informe de uso anónimo a cambiado. ¿Desearía usar el nuevo formato?",
|
||||
"Applied to LAN": "Aplicado a la LAN",
|
||||
"Apply": "Solicitar",
|
||||
"Are you sure you want to override all remote changes?": "¿Está seguro(a) de que desea sobreescribir todos los cambios remotos?",
|
||||
"Are you sure you want to permanently delete all these files?": "¿Está seguro de que desea eliminar permanente todos estos archivos?",
|
||||
"Are you sure you want to permanently delete all these files?": "¿Está seguro de que desea eliminar permanentemente todos estos archivos?",
|
||||
"Are you sure you want to remove device {%name%}?": "¿Está seguro que desea eliminar el dispositivo {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "¿Está seguro que desea eliminar la carpeta {{label}}?",
|
||||
"Are you sure you want to restore {%count%} files?": "¿Está seguro que desea restaurar {{count}} archivos?",
|
||||
@@ -271,7 +271,7 @@
|
||||
"Notice": "Aviso",
|
||||
"Number of Connections": "Número de las conexiones",
|
||||
"OK": "De acuerdo",
|
||||
"Off": "Desconectar",
|
||||
"Off": "Desactivado",
|
||||
"Oldest First": "El más antiguo primero",
|
||||
"Optional descriptive label for the folder. Can be different on each device.": "Etiqueta descriptiva opcional para la carpeta. Puede ser diferente en cada dispositivo.",
|
||||
"Options": "Opciones",
|
||||
@@ -386,6 +386,7 @@
|
||||
"Staggered File Versioning": "Versionado escalonado de fichero",
|
||||
"Start Browser": "Iniciar el navegador",
|
||||
"Statistics": "Estadísticas",
|
||||
"Stay logged in": "Permanecer conectado",
|
||||
"Stopped": "Detenido",
|
||||
"Stores and syncs only encrypted data. Folders on all connected devices need to be set up with the same password or be of type \"{%receiveEncrypted%}\" too.": "Almacena y sincroniza sólo los datos cifrados. Las carpetas de todos los dispositivos conectados deben estar configuradas con la misma contraseña o ser también del tipo \"{{receiveEncrypted}}\".",
|
||||
"Subject:": "Asunto:",
|
||||
|
||||
@@ -289,7 +289,7 @@
|
||||
"See external versioning help for supported templated command line parameters.": "Ikusi kanpoko bertsioen kudeatzailearen laguntza txantiloi bat erabiltzen duten komandoen lerro-parametroetarako.",
|
||||
"Select All": "Hautatu guztia",
|
||||
"Select a version": "Bertsio bat aukeratu",
|
||||
"Select additional devices to share this folder with.": " Tresna gehigarriak hauta itzazu partekatze honekin sinkronizatzeko ",
|
||||
"Select additional devices to share this folder with.": "Tresna gehigarriak hauta itzazu partekatze honekin sinkronizatzeko",
|
||||
"Select additional folders to share with this device.": "Aukeratu karpeta osagarriak gailu honekin partekatzeko.",
|
||||
"Select latest version": "Aukeratu azken bertsioa",
|
||||
"Select oldest version": "Aukeratu bertsio zaharrena",
|
||||
@@ -316,7 +316,7 @@
|
||||
"Size": "Tamaina",
|
||||
"Smallest First": "Ttipienak lehenik",
|
||||
"Some discovery methods could not be established for finding other devices or announcing this device:": "Aurkikuntza-metodo batzuk ezin izan dira ezarri beste gailu batzuk aurkitzeko edo gailu honen berri emateko:",
|
||||
"Some items could not be restored:": "Zenbat fitxategi ezin izan dira berreskuratu",
|
||||
"Some items could not be restored:": "Zenbat fitxategi ezin izan dira berreskuratu:",
|
||||
"Some listening addresses could not be enabled to accept connections:": "Entzuteko helbide batzuek ezin dituzte konexioak onartu:",
|
||||
"Source Code": "Iturri kodea",
|
||||
"Stable releases and release candidates": "iraunkor eta aintzin-bertsioak",
|
||||
|
||||
@@ -26,11 +26,14 @@
|
||||
"Anonymous Usage Reporting": "Anonyymi käyttöraportointi",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "Anonyymi käyttöraportti on muuttunut. Haluatko vaihtaa uuteen muotoon?",
|
||||
"Apply": "Käytä",
|
||||
"Are you sure you want to override all remote changes?": "Haluatko varmasti ylikirjoittaa kaikki etämuutokset?",
|
||||
"Are you sure you want to permanently delete all these files?": "Oletko varma että haluat poistaa lopullisesti kaikki nämä tiedostot?",
|
||||
"Are you sure you want to remove device {%name%}?": "Oletko varma, että haluat postaa laitteen {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Oletko varma, että haluat poistaa kansion {{label}}?",
|
||||
"Are you sure you want to restore {%count%} files?": "Haluatko varmasti palauttaa {{count}} tiedostoa?",
|
||||
"Are you sure you want to upgrade?": "Oletko varma että haluat päivittää?",
|
||||
"Authentication Required": "Tunnistautuminen vaaditaan",
|
||||
"Authors": "Tekijät",
|
||||
"Auto Accept": "Hyväksy automaattisesti",
|
||||
"Automatic Crash Reporting": "Kaatumisen automaattinen raportointi",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Automaattinen päivitys sallii valita vakaiden- ja kehitysversioiden välillä.",
|
||||
@@ -43,6 +46,8 @@
|
||||
"Changelog": "Muutoshistoria",
|
||||
"Clean out after": "Puhdista seuraavan ajan kuluttua",
|
||||
"Cleaning Versions": "Puhdistetaan Versioita",
|
||||
"Cleanup Interval": "Puhdistusväli",
|
||||
"Click to see full identification string and QR code.": "Napsauta nähdäksesi koko tunnistemerkkijonon ja QR-koodin.",
|
||||
"Close": "Sulje",
|
||||
"Command": "Komento",
|
||||
"Comment, when used at the start of a line": "Kommentti, käytettäessä rivin alussa",
|
||||
@@ -76,6 +81,7 @@
|
||||
"Device ID": "Laitteen ID",
|
||||
"Device Identification": "Laitteen tunniste",
|
||||
"Device Name": "Laitteen nimi",
|
||||
"Device Status": "Laitteen tila",
|
||||
"Device rate limits": "Laitteen siirtonopeuden rajoitus",
|
||||
"Device that last modified the item": "Laite, joka viimeisimmäksi muokkasi kohdetta",
|
||||
"Devices": "Laitteet",
|
||||
@@ -131,6 +137,7 @@
|
||||
"Folder ID": "Kansion ID",
|
||||
"Folder Label": "Kansion nimi",
|
||||
"Folder Path": "Kansion polku",
|
||||
"Folder Status": "Kansion tila",
|
||||
"Folder Type": "Kansion tyyppi",
|
||||
"Folders": "Kansiot",
|
||||
"For the following folders an error occurred while starting to watch for changes. It will be retried every minute, so the errors might go away soon. If they persist, try to fix the underlying issue and ask for help if you can't.": "Seuraavien kansioiden valvonnan aloitus epäonnistui. Yritetään uudelleen minuutin välein, joten virhe saattaa poistua pian. Mikäli virheet jäävät pysyviksi, yritä korjata taustaongelma tai kysy apua foorumilta, mikäli et onnistu.",
|
||||
@@ -176,6 +183,8 @@
|
||||
"Local State (Total)": "Paikallinen tila (Yhteensä)",
|
||||
"Locally Changed Items": "Paikallisesti muuttuneet tiedot",
|
||||
"Log": "Loki",
|
||||
"Log In": "Kirjaudu sisään",
|
||||
"Log Out": "Kirjaudu ulos",
|
||||
"Log tailing paused. Scroll to the bottom to continue.": "Login seuraaminen pysäytetty. Jatka vierittämällä alas.",
|
||||
"Logs": "Lokit",
|
||||
"Major Upgrade": "Pääversion päivitys.",
|
||||
@@ -185,6 +194,9 @@
|
||||
"Minimum Free Disk Space": "Vapaan levytilan vähimmäismäärä",
|
||||
"Mod. Device": "Muokannut laite",
|
||||
"Mod. Time": "Muokkausaika",
|
||||
"More than a month ago": "Yli kuukausi sitten",
|
||||
"More than a week ago": "Yli viikko sitten",
|
||||
"More than a year ago": "Yli vuosi sitten",
|
||||
"Move to top of queue": "Siirrä jonon alkuun",
|
||||
"Multi level wildcard (matches multiple directory levels)": "Monitasoinen jokerimerkki (vaikuttaa useassa kansiotasossa)",
|
||||
"Never": "Ei koskaan",
|
||||
@@ -206,12 +218,14 @@
|
||||
"Out of Sync Items": "Kohteet, jotka eivät ole ajan tasalla",
|
||||
"Outgoing Rate Limit (KiB/s)": "Uloslähtevän liikenteen rajoitus (KiB/s)",
|
||||
"Override Changes": "Ohita muutokset",
|
||||
"Password": "Salasana",
|
||||
"Path": "Polku",
|
||||
"Path to the folder on the local computer. Will be created if it does not exist. The tilde character (~) can be used as a shortcut for": "Polku kansioon paikallisella tietokoneella. Kansio luodaan, ellei sitä ole olemassa. Tilde-merkkiä (~) voidaan käyttää oikotienä polulle",
|
||||
"Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).": "Polku, mihin versiot tallennetaan. (Jätä tyhjäksi, jolloin tiedostot tallennetaan .stversions-kansioon jaetun kansion sisällä.)",
|
||||
"Pause": "Keskeytä",
|
||||
"Pause All": "Keskeytä kaikki",
|
||||
"Paused": "Keskeytetty",
|
||||
"Paused (Unused)": "Keskeytetty (käyttämätön)",
|
||||
"Pending changes": "Odottavia muutoksia",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Ajoitettu skannaus päällä. Muutosten seuranta pois päältä",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Ajoitettu skannaus ja muutosten seuranta päällä",
|
||||
@@ -224,6 +238,7 @@
|
||||
"Preparing to Sync": "Valmistellaan synkronointia",
|
||||
"Preview": "Esikatselu",
|
||||
"Preview Usage Report": "Esikatsele käyttöraportti",
|
||||
"QR code": "QR koodi",
|
||||
"Quick guide to supported patterns": "Tuettujen lausekkeiden pikaohje",
|
||||
"Random": "Satunnainen",
|
||||
"Receive Only": "Vain vastaanotto",
|
||||
@@ -249,6 +264,7 @@
|
||||
"Reused": "Uudelleenkäytetty",
|
||||
"Revert Local Changes": "Palauta paikalliset muutokset",
|
||||
"Save": "Tallenna",
|
||||
"Saving changes": "Tallennetaan muutoksia",
|
||||
"Scan Time Remaining": "Skannausaikaa jäljellä",
|
||||
"Scanning": "Skannataan",
|
||||
"See external versioning help for supported templated command line parameters.": "Katso ulkopuolisen versiohallinnan tukisivu komentoriviparametreistä.",
|
||||
@@ -295,6 +311,7 @@
|
||||
"Syncthing includes the following software or portions thereof:": "Syncthing sisältää seuraavat ohjelmistot tai sen osat:",
|
||||
"Syncthing is Free and Open Source Software licensed as MPL v2.0.": "Syncthing on avointa lähdekoodia, joka on lisensöity MPL v2.0 lisenssillä.",
|
||||
"Syncthing is restarting.": "Syncthing käynnistyy uudelleen.",
|
||||
"Syncthing is saving changes.": "Syncthing tallentaa muutoksia.",
|
||||
"Syncthing is upgrading.": "Syncthing päivittyy.",
|
||||
"Syncthing now supports automatically reporting crashes to the developers. This feature is enabled by default.": "Synthing tukee automaattista kaatumisraportointia. Tämä ominaisuus on oletuksena käytössä.",
|
||||
"Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…": "Syncthing näyttää olevan alhaalla tai internetyhteydessä on ongelma. Yritetään uudelleen...",
|
||||
@@ -303,6 +320,7 @@
|
||||
"The GUI address is overridden by startup options. Changes here will not take effect while the override is in place.": "Käyttöliittymän osoite on asetettu käynnistysparametreillä. Muutokset täällä tulevat voimaan vasta, kun käynnistysparametrejä ei käytetä.",
|
||||
"The Syncthing admin interface is configured to allow remote access without a password.": "Syncthingin hallintakäyttöliittymä on asetettu sallimaan ulkoiset yhteydet ilman salasanaa.",
|
||||
"The aggregated statistics are publicly available at the URL below.": "Koostetut tilastot ovat julkisesti saatavilla alla olevassa osoitteessa.",
|
||||
"The cleanup interval cannot be blank.": "Puhdistusväli ei voi olla tyhjä.",
|
||||
"The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.": "Asetukset on tallennettu, mutta niitä ei ole otettu käyttöön. Syncthingin täytyy käynnistyä uudelleen, jotta uudet asetukset saadaan käyttöön.",
|
||||
"The device ID cannot be blank.": "Laitteen ID ei voi olla tyhjä.",
|
||||
"The device ID to enter here can be found in the \"Actions > Show ID\" dialog on the other device. Spaces and dashes are optional (ignored).": "Tähän kohtaan syötettävän ID:n löytää \"Muokkaa > Näytä ID\" -valikosta toiselta laitteelta. Välit ja viivat ovat valinnaisia (jätetään huomiotta).",
|
||||
@@ -313,6 +331,7 @@
|
||||
"The folder path cannot be blank.": "Kansion polku ei voi olla tyhjä.",
|
||||
"The following intervals are used: for the first hour a version is kept every 30 seconds, for the first day a version is kept every hour, for the first 30 days a version is kept every day, until the maximum age a version is kept every week.": "Seuraavat aikavälit ovat käytössä: ensimmäisen tunnin ajalta uusi versio säilytetään joka 30 sekunti, ensimmäisen päivän ajalta uusi versio säilytetään tunneittain ja ensimmäisen 30 päivän aikana uusi versio säilytetään päivittäin. Lopulta uusi versio säilytetään viikoittain, kunnes maksimi-ikä saavutetaan.",
|
||||
"The following items could not be synchronized.": "Seuraavia nimikkeitä ei voitu synkronoida.",
|
||||
"The interval, in seconds, for running cleanup in the versions directory. Zero to disable periodic cleaning.": "Aikaväli sekunteina versiohakemiston puhdistamisen suorittamiseen. Nolla poistaaksesi säännöllisen puhdistuksen käytöstä.",
|
||||
"The maximum age must be a number and cannot be blank.": "Maksimi-iän tulee olla numero, eikä se voi olla tyhjä.",
|
||||
"The maximum time to keep a version (in days, set to 0 to keep versions forever).": "Maksimiaika versioiden säilytykseen (päivissä, aseta 0 säilyttääksesi versiot ikuisesti).",
|
||||
"The number of days must be a number and cannot be blank.": "Päivien määrän tulee olla numero, eikä se voi olla tyhjä.",
|
||||
@@ -321,14 +340,23 @@
|
||||
"The number of versions must be a number and cannot be blank.": "Versioiden määrän rulee olla numero, eikä se voi olla tyhjä.",
|
||||
"The path cannot be blank.": "Polku ei voi olla tyhjä.",
|
||||
"The rate limit must be a non-negative number (0: no limit)": "Nopeusrajan tulee olla positiivinen luku tai nolla. (0: ei rajaa)",
|
||||
"The remote device has not accepted sharing this folder.": "Etälaite ei ole hyväksynyt tämän kansion jakamista.",
|
||||
"The remote device has paused this folder.": "Etälaite on keskeyttänyt tämän kansion.",
|
||||
"The rescan interval must be a non-negative number of seconds.": "Uudelleenskannauksen aikavälin tulee olla ei-negatiivinen numero sekunteja.",
|
||||
"There are no devices to share this folder with.": "Ei ole laitteita, joille tämä kansio jaetaan.",
|
||||
"There are no file versions to restore.": "Palautettavaa tiedostoversiota ei ole.",
|
||||
"There are no folders to share with this device.": "Tämän laitteen kanssa jaettavia kansioita ei ole.",
|
||||
"They are retried automatically and will be synced when the error is resolved.": "Niiden synkronointia yritetään uudelleen automaattisesti.",
|
||||
"This Device": "Tämä laite",
|
||||
"This Month": "Tässä kuussa",
|
||||
"This can easily give hackers access to read and change any files on your computer.": "Tämä voi helposti sallia vihamielisille tahoille pääsyn lukea ja muokata kaikkia tiedostojasi",
|
||||
"This is a major version upgrade.": "Tämä on pääversion päivitys.",
|
||||
"This setting controls the free space required on the home (i.e., index database) disk.": "Tämä asetus määrittää vaaditun vapaan levytilan kotikansiossa (se missä index-tietokanta on).",
|
||||
"Time": "Aika",
|
||||
"Time the item was last modified": "Aika jolloin kohdetta viimeksi muokattiin",
|
||||
"To permit a rule, have the checkbox checked. To deny a rule, leave it unchecked.": "Jos haluat sallia säännön, valitse valintaruutu. Jos haluat hylätä säännön, jätä se valitsematta.",
|
||||
"Today": "Tänään",
|
||||
"Trash Can": "Roskakori",
|
||||
"Trash Can File Versioning": "Roskakorin tiedostoversiointi",
|
||||
"Type": "Tyyppi",
|
||||
"Unavailable": "Ei saatavilla",
|
||||
@@ -340,6 +368,7 @@
|
||||
"Unshared Devices": "Jakamattomat laitteet",
|
||||
"Unshared Folders": "Jakamattomat kansiot",
|
||||
"Up to Date": "Ajan tasalla",
|
||||
"Updated {%file%}": "Päivitetty {{file}}",
|
||||
"Upgrade": "Päivitys",
|
||||
"Upgrade To {%version%}": "Päivitä versioon {{version}}",
|
||||
"Upgrading": "Päivitetään",
|
||||
@@ -347,10 +376,13 @@
|
||||
"Uptime": "Päälläoloaika",
|
||||
"Usage reporting is always enabled for candidate releases.": "Käytön raportointi on aina käytössä testiversioissa.",
|
||||
"Use HTTPS for GUI": "Käytä HTTPS:ää GUI:n kanssa",
|
||||
"Use notifications from the filesystem to detect changed items.": "Käytä tiedostojärjestelmän ilmoituksia havaitaksesi muuttuneet kohteet.",
|
||||
"User": "Käyttäjä",
|
||||
"Version": "Versio",
|
||||
"Versions": "Versiot",
|
||||
"Versions Path": "Versioiden polku",
|
||||
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Versiot poistetaan automaattisesti mikäli ne ovat vanhempia kuin maksimi-ikä tai niiden määrä ylittää sallitun määrän tietyllä aikavälillä.",
|
||||
"Waiting to Sync": "Odotetaan synkronointia",
|
||||
"Warning": "Varoitus",
|
||||
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Varoitus: tämä polku on olemassa olevan kansion \"{{otherFolder}}\" yläkansio.",
|
||||
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Varoitus: Tämä kansio on jo olemassa olevan kansion yläkansio \"{{otherFolderLabel}}\" ({{otherFolder}}).",
|
||||
@@ -372,10 +404,15 @@
|
||||
"You have unsaved changes. Do you really want to discard them?": "Sinulla on tallentamattomia muutoksia. Tahdotko hylätä ne?",
|
||||
"You must keep at least one version.": "Sinun tulee säilyttää ainakin yksi versio.",
|
||||
"days": "päivää",
|
||||
"deleted": "poistettu",
|
||||
"directories": "kansiot",
|
||||
"file": "tiedosto",
|
||||
"files": "tiedostot",
|
||||
"folder": "kansio",
|
||||
"full documentation": "täysi dokumentaatio",
|
||||
"items": "kohteet",
|
||||
"modified": "muokattu",
|
||||
"seconds": "sekuntia",
|
||||
"theme": {
|
||||
"name": {
|
||||
"black": "Musta",
|
||||
@@ -384,6 +421,7 @@
|
||||
"light": "Vaalea"
|
||||
}
|
||||
},
|
||||
"unknown device": "tuntematon laite",
|
||||
"{%device%} wants to share folder \"{%folder%}\".": "{{device}} haluaa jakaa kansion \"{{folder}}\".",
|
||||
"{%device%} wants to share folder \"{%folderlabel%}\" ({%folder%}).": "{{device}} haluaa jakaa kansion \"{{folderlabel}}\" ({{folder}})."
|
||||
}
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
"Automatic upgrades": "Mises à jour automatiques",
|
||||
"Be careful!": "Faites attention !",
|
||||
"Changelog": "Historique des versions",
|
||||
"Clean out after": "Purger après :",
|
||||
"Clean out after": "Purger après",
|
||||
"Close": "Fermer",
|
||||
"Command": "Commande",
|
||||
"Comment, when used at the start of a line": "Commentaire lorsque utilisé en début de ligne",
|
||||
|
||||
@@ -99,6 +99,7 @@
|
||||
"Device ID": "ID de l'appareil",
|
||||
"Device Identification": "Identifiant de l'appareil",
|
||||
"Device Name": "Nom convivial local de l'appareil",
|
||||
"Device Status": "État de l'appareil",
|
||||
"Device is untrusted, enter encryption password": "Confiance retirée, entrez un mot de passe de chiffrement",
|
||||
"Device rate limits": "Limitations de débit",
|
||||
"Device that last modified the item": "Dernier appareil modificateur",
|
||||
@@ -168,6 +169,7 @@
|
||||
"Folder ID": "ID du partage",
|
||||
"Folder Label": "Nom du partage",
|
||||
"Folder Path": "Chemin racine du partage",
|
||||
"Folder Status": "État du partage",
|
||||
"Folder Type": "Type de partage",
|
||||
"Folder type \"{%receiveEncrypted%}\" can only be set when adding a new folder.": "Le type de partage \"{{receiveEncrypted}}\" ne peut être défini qu'à la création.",
|
||||
"Folder type \"{%receiveEncrypted%}\" cannot be changed after adding the folder. You need to remove the folder, delete or decrypt the data on disk, and add the folder again.": "Un partage de type \"{{receiveEncrypted}}\" ne peut pas être modifié après sa création. Il vous faut l'enlever, supprimer ou déchiffrer les données du disque, puis recréer le partage.",
|
||||
@@ -320,7 +322,7 @@
|
||||
"Remove": "Supprimer",
|
||||
"Remove Device": "Supprimer l'appareil",
|
||||
"Remove Folder": "Supprimer le partage",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "Identifiant du partage. Doit être le même sur tous les appareils concernés (généré aléatoirement, mais modifiable à la création, par exemple pour faire entrer un appareil dans un partage pré-existant actuellement non connecté mais dont on connais déjà l'ID, ou s'il n'y a personne à l'autre bout pour vous inviter à y participer).",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "Identifiant du partage. Doit être le même sur tous les appareils concernés (généré aléatoirement, mais modifiable à la création, par exemple pour faire entrer un appareil dans un partage pré-existant actuellement non connecté mais dont on connaît déjà l'ID, ou s'il n'y a personne à l'autre bout pour vous inviter à y participer).",
|
||||
"Rescan": "Réanalyser",
|
||||
"Rescan All": "Tout réanalyser",
|
||||
"Rescans": "Réanalyses/Surveillance",
|
||||
@@ -347,7 +349,7 @@
|
||||
"Select oldest version": "Restaurer la plus ancienne version",
|
||||
"Send & Receive": "Envoi & réception",
|
||||
"Send Extended Attributes": "Envoyer les attributs étendus",
|
||||
"Send Only": "Envoi (lecture seule)",
|
||||
"Send Only": "Envoi seulement",
|
||||
"Send Ownership": "Envoyer l'appartenance",
|
||||
"Set Ignores on Added Folder": "Définir des exclusions pour le nouveau partage",
|
||||
"Settings": "Configuration",
|
||||
@@ -384,6 +386,7 @@
|
||||
"Staggered File Versioning": "Versions échelonnées des fichiers",
|
||||
"Start Browser": "Lancer le navigateur web",
|
||||
"Statistics": "Statistiques",
|
||||
"Stay logged in": "Rester connecté",
|
||||
"Stopped": "Arrêté",
|
||||
"Stores and syncs only encrypted data. Folders on all connected devices need to be set up with the same password or be of type \"{%receiveEncrypted%}\" too.": "Récupère seulement des données chiffrées. Ce partage sur tous les autres appareils doit aussi être du type \"{{receiveEncrypted}}\" ou bien être défini avec le même mot de passe.",
|
||||
"Subject:": "Objet :",
|
||||
@@ -545,6 +548,7 @@
|
||||
"light": "Clair"
|
||||
}
|
||||
},
|
||||
"unknown device": "appareil inconnu",
|
||||
"{%device%} wants to share folder \"{%folder%}\".": "{{device}} vous invite au partage \"{{folder}}\".",
|
||||
"{%device%} wants to share folder \"{%folderlabel%}\" ({%folder%}).": "{{device}} vous invite au partage \"{{folderlabel}}\" ({{folder}}).",
|
||||
"{%reintroducer%} might reintroduce this device.": "{{reintroducer}} pourrait ré-enrôler cet appareil."
|
||||
|
||||
@@ -6,11 +6,13 @@
|
||||
"About": "Oer",
|
||||
"Action": "Aksje",
|
||||
"Actions": "Aksjes",
|
||||
"Active filter rules": "Aktive filterregels",
|
||||
"Add": "Taheakje",
|
||||
"Add Device": "Apparaat taheakje",
|
||||
"Add Folder": "Map taheakje",
|
||||
"Add Remote Device": "Apparaat op Ofstân Taheakje",
|
||||
"Add devices from the introducer to our device list, for mutually shared folders.": "Heakje apparaten fan de yntrodusearders ta oan ús apparatenlyst, foar mei-inoar dielde mappen.",
|
||||
"Add filter entry": "Filter-item tafoegje",
|
||||
"Add ignore patterns": "Foech nije negear-patroanen ta",
|
||||
"Add new folder?": "Nije map taheakje?",
|
||||
"Additionally the full rescan interval will be increased (times 60, i.e. new default of 1h). You can also configure it manually for every folder later after choosing No.": "Boppedat wurd it ynterfal foar in folledige wer-sken omheech brocht (kear 60 minuten, dit is in nije standert fan 1 oere). Jo kinne dit ek letter foar elke map hânmjittich ynstelle nei it kiezen fan Nee.",
|
||||
@@ -28,6 +30,7 @@
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder. If the path to the application contains spaces, it should be quoted.": "In ekstern kommando soarget foar it ferzjebehear. It moat de triem út de dielde map fuortsmite. As it paad nei de applikaasje romtes hat, moat it tusken oanheltekens sette wurden.",
|
||||
"Anonymous Usage Reporting": "Anonym brûkensrapportaazje",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "It formaat fan de rapportaazje fan anonime gebrûksynformaasje is feroare. Wolle jo op dit nije formaat oerstappe?",
|
||||
"Applied to LAN": "Tapast op LAN",
|
||||
"Apply": "Tapasse",
|
||||
"Are you sure you want to override all remote changes?": "Binne jo der wis fan dat jo alle wizigingen op ôfstân oerskriuwe wolle?",
|
||||
"Are you sure you want to permanently delete all these files?": "Binne jo der wis fan dat jo al dizze bestannen permanint wiskje wolle?",
|
||||
@@ -36,6 +39,7 @@
|
||||
"Are you sure you want to restore {%count%} files?": "Bist der wis fan datsto {{count}} triemen weromsette wolst?",
|
||||
"Are you sure you want to revert all local changes?": "Binne jo der wis fan dat jo alle lokale wizigingen oerskriuwe wolle?",
|
||||
"Are you sure you want to upgrade?": "Bist der wis fan datsto upwardearre wolst?",
|
||||
"Authentication Required": "Autentikeren Ferplicht",
|
||||
"Authors": "Auteurs",
|
||||
"Auto Accept": "Auto-akseptaasje",
|
||||
"Automatic Crash Reporting": "Automatyske Rapportaazje fan Fêstrinners",
|
||||
@@ -62,6 +66,7 @@
|
||||
"Configured": "Konfigureart",
|
||||
"Connected (Unused)": "Ferbûn (Net Brûkt)",
|
||||
"Connection Error": "Ferbiningsflater",
|
||||
"Connection Management": "Ferbiningsbeliid",
|
||||
"Connection Type": "Ferbiningstype",
|
||||
"Connections": "Ferbinings",
|
||||
"Connections via relays might be rate limited by the relay": "Ferbinings fia relays kinne yn harren rate beheind wurde troch it relay.",
|
||||
@@ -76,22 +81,25 @@
|
||||
"Danger!": "Gefaar!",
|
||||
"Database Location": "Database lokaasje",
|
||||
"Debugging Facilities": "Debug-foarsjennings",
|
||||
"Default": "Standert",
|
||||
"Default Configuration": "Standertkonfiguraasje",
|
||||
"Default Device": "Standertapparaat",
|
||||
"Default Folder": "Standertmap",
|
||||
"Default Ignore Patterns": "Standert Negearpatroanen",
|
||||
"Defaults": "Standertwearden",
|
||||
"Delete": "Fuortsmite",
|
||||
"Delete Unexpected Items": " Unferwachte items wiskje",
|
||||
"Delete Unexpected Items": "Unferwachte items wiskje",
|
||||
"Deleted {%file%}": "{{file}} is fuortsmiten",
|
||||
"Deselect All": "Alles Deselektearje",
|
||||
"Deselect devices to stop sharing this folder with.": "Kies de apparaten om dizze map net langer mei te dielen.",
|
||||
"Deselect folders to stop sharing with this device.": "Deselektearje mappen om it dielen mei dit apparaat te stopjen.",
|
||||
"Device": "Apparaat",
|
||||
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "Apparaat \"{{name}}\" {{device}} op ({{address}}) wol ferbining meitsje. Nij apparaat taheakje?",
|
||||
"Device Certificate": "Apparaatsertifikaat",
|
||||
"Device ID": "Apparaat-ID",
|
||||
"Device Identification": "Apparaatidentifikaasje",
|
||||
"Device Name": "Apparaatnamme",
|
||||
"Device Status": "Apparaattastân",
|
||||
"Device is untrusted, enter encryption password": "Apparaat is net fertroud, fier fersiferingswachtwurd yn",
|
||||
"Device rate limits": "Apparaatfluggenslimiet",
|
||||
"Device that last modified the item": "Apparaat dat dit item it lêst oanpast hat",
|
||||
@@ -104,10 +112,14 @@
|
||||
"Disables comparing and syncing file permissions. Useful on systems with nonexistent or custom permissions (e.g. FAT, exFAT, Synology, Android).": "Skakelt fergelykjen en syngronisearjen fan bestânrjochten út. Nuttich op systemen mei net-besteande as oanpaste tagongsrjochten (bgl. FAT, exFAT, Synology, Android).",
|
||||
"Discard": "Fuortsmite\n",
|
||||
"Disconnected": "Ferbining ferbrutsen",
|
||||
"Disconnected (Inactive)": "Ferbining ferbrutsen (net aktief)",
|
||||
"Disconnected (Unused)": "Ferbining ferbrutsen (Net Brûkt)",
|
||||
"Discovered": "Untdekt",
|
||||
"Discovery": "Untdekking",
|
||||
"Discovery Failures": "Untdekkingsflaters",
|
||||
"Discovery Status": "Untdekkingstastân",
|
||||
"Dismiss": "Fuortsmite",
|
||||
"Do not add it to the ignore list, so this notification may recur.": "Net oan negearlyst taheakken, sadat dit berjocht opnij komme kin.",
|
||||
"Do not restore": "Net tebeksette",
|
||||
"Do not restore all": "Hielendal net tebeksette",
|
||||
"Do you want to enable watching for changes for all your folders?": "Wolle jo it konstant byhâlden fan feroarings foar al jo mappen oansette?",
|
||||
@@ -125,6 +137,7 @@
|
||||
"Enable NAT traversal": "NAT-trochkruse ynskeakelje",
|
||||
"Enable Relaying": "Trochjaan tastean",
|
||||
"Enabled": "Ynskeakele",
|
||||
"Enables sending extended attributes to other devices, and applying incoming extended attributes. May require running with elevated privileges.": "Makket mooglik dat wiidweidige attributen ferstjoert wurde kinne nei oare apparaten, en dat ynkommende wiidweidige attributen tapast wurde kinne. Ferhege privileezjes binne mooglik nedich.",
|
||||
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Fier in net-negatyf nûmer yn (bygelyks \"2.35\") en selektearje in ienheid. Percentages stean foar it part fan de totale skiifromte.",
|
||||
"Enter a non-privileged port number (1024 - 65535).": "Fier in net-befoarrjochte poart-nûmer yn (1024 - 65535).",
|
||||
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Fier troch komma's skieden (\"tcp://ip:port\", \"tcp://host:port\") adressen yn of \"dynamic\" om automatyske ûntdekking fan it adres út te fieren.",
|
||||
@@ -170,7 +183,7 @@
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "Lykwols, jo aktuele ynstellings litte sjen dat jo it miskien net oan sette wol. Wy hawwe automatysk rapportearjen fan fêstrinnen foar jo útsetten.",
|
||||
"Identification": "Identifikaasje",
|
||||
"If untrusted, enter encryption password": "As net fertroud, fier dan fersiferingswachtwurd yn",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "As jo wolle foarkomme dat oare brûkers op dizze kompjûter tagong krije ta Syncthing en dêrtroch jo bestannen, oerweeg dan it ynstellen fan ferifikaasje.",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "As jo wolle foarkomme dat oare brûkers op dizze kompjûter tagong krije ta Syncthing en dêrtroch jo bestannen, oerweeg dan it ynstellen fan ferifikaasje.",
|
||||
"Ignore": "Negearje",
|
||||
"Ignore Patterns": "Negear-patroanen",
|
||||
"Ignore Permissions": "Negear-rjochten",
|
||||
@@ -305,7 +318,7 @@
|
||||
"Single level wildcard (matches within a directory only)": "Inkel-nivo jokerteken (wildcard) (fergeliket allinnich binnen in map)",
|
||||
"Size": "Grutte",
|
||||
"Smallest First": "Lytste earst",
|
||||
"Some items could not be restored:": "Guon uûnderdielen koenen net tebeksetten wurde.",
|
||||
"Some items could not be restored:": "Guon uûnderdielen koenen net tebeksetten wurde:",
|
||||
"Source Code": "Boarnekoade",
|
||||
"Stable releases and release candidates": "Stabyle ferzjes en ferzje kanditaten",
|
||||
"Stable releases are delayed by about two weeks. During this time they go through testing as release candidates.": "Stabyle ferzjes wurde likernôch twa wiken útstelt. Yn die tiid wurde se testen as ferzje kandidaten.",
|
||||
|
||||
@@ -193,7 +193,7 @@
|
||||
"Ignore patterns can only be added after the folder is created. If checked, an input field to enter ignore patterns will be presented after saving.": "Mellőzési minták csak a mappa létrehozása után adhatók hozzá. Bejelölve egy beviteli mező fog megjelenni mentés után a mellőzési minták számára.",
|
||||
"Ignored Devices": "Mellőzött eszközök",
|
||||
"Ignored Folders": "Mellőzött mappák",
|
||||
"Ignored at": "Mellőzve:",
|
||||
"Ignored at": "Mellőzve",
|
||||
"Included Software": "Felhasznált szoftver",
|
||||
"Incoming Rate Limit (KiB/s)": "Bejövő sebességkorlát (KiB/s)",
|
||||
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Helytelen konfiguráció esetén károsodhat a mappák tartalma és működésképtelenné válhat a Syncthing.",
|
||||
|
||||
@@ -99,6 +99,7 @@
|
||||
"Device ID": "ID Dispositivo",
|
||||
"Device Identification": "Identificazione Dispositivo",
|
||||
"Device Name": "Nome Dispositivo",
|
||||
"Device Status": "Stato Dispositivo",
|
||||
"Device is untrusted, enter encryption password": "Il dispositivo non è attendibile, inserisci la password di crittografia",
|
||||
"Device rate limits": "Limiti di velocità del dispositivo",
|
||||
"Device that last modified the item": "Dispositivo che ha modificato l'elemento per ultimo",
|
||||
@@ -157,7 +158,7 @@
|
||||
"Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.": "La connessione a server IPv6 fallisce se non c'è connettività IPv6.",
|
||||
"File Pull Order": "Ordine Prelievo File",
|
||||
"File Versioning": "Controllo Versione File",
|
||||
"Files are moved to .stversions directory when replaced or deleted by Syncthing.": "I file sono spostati nella certella .stversions quando vengono sostituiti o cancellati da Syncthing.",
|
||||
"Files are moved to .stversions directory when replaced or deleted by Syncthing.": "I file sono spostati nella cartella .stversions quando vengono sostituiti o cancellati da Syncthing.",
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "I file sostituiti o eliminati da Syncthing vengono datati e spostati in una cartella .stversions.",
|
||||
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "I file sono protetti dalle modifiche effettuate negli altri dispositivi, ma le modifiche effettuate in questo dispositivo verranno inviate anche al resto del cluster.",
|
||||
"Files are synchronized from the cluster, but any changes made locally will not be sent to other devices.": "I file sono sincronizzati dal cluster, ma eventuali modifiche apportate localmente non verranno inviate ad altri dispositivi.",
|
||||
@@ -168,6 +169,7 @@
|
||||
"Folder ID": "ID Cartella",
|
||||
"Folder Label": "Etichetta per la Cartella",
|
||||
"Folder Path": "Percorso Cartella",
|
||||
"Folder Status": "Stato Cartella",
|
||||
"Folder Type": "Tipo di Cartella",
|
||||
"Folder type \"{%receiveEncrypted%}\" can only be set when adding a new folder.": "Il tipo di cartella \"{{receiveEncrypted}}\" può essere impostata solo quando si aggiunge una nuova cartella.",
|
||||
"Folder type \"{%receiveEncrypted%}\" cannot be changed after adding the folder. You need to remove the folder, delete or decrypt the data on disk, and add the folder again.": "Il tipo di cartella \"{{receiveEncrypted}}\" non può essere modificato dopo aver aggiunto la cartella. È necessario rimuovere la cartella, eliminare o decrittografare i dati sul disco e aggiungere nuovamente la cartella.",
|
||||
@@ -236,6 +238,7 @@
|
||||
"Log": "Log",
|
||||
"Log File": "File Log",
|
||||
"Log In": "Login",
|
||||
"Log Out": "Disconnetti",
|
||||
"Log in to see paths information.": "Accedere per visualizzare le informazioni sui percorsi.",
|
||||
"Log in to see version information.": "Accedere per visualizzare le informazioni sulla versione.",
|
||||
"Log tailing paused. Scroll to the bottom to continue.": "Visualizzazione log in pausa. Scorri fino in fondo per continuare.",
|
||||
@@ -383,6 +386,7 @@
|
||||
"Staggered File Versioning": "Controllo Versione Cadenzato",
|
||||
"Start Browser": "Avvia Browser",
|
||||
"Statistics": "Statistiche",
|
||||
"Stay logged in": "Resta connesso",
|
||||
"Stopped": "Fermato",
|
||||
"Stores and syncs only encrypted data. Folders on all connected devices need to be set up with the same password or be of type \"{%receiveEncrypted%}\" too.": "Memorizza e sincronizza solo i dati crittografati. Le cartelle su tutti i dispositivi collegati devono essere configurate con la stessa password o essere del tipo \"{{receiveEncrypted}}\".",
|
||||
"Subject:": "Oggetto:",
|
||||
@@ -544,6 +548,7 @@
|
||||
"light": "Chiaro"
|
||||
}
|
||||
},
|
||||
"unknown device": "dispositivo sconosciuto",
|
||||
"{%device%} wants to share folder \"{%folder%}\".": "{{device}} vuole condividere la cartella \"{{folder}}\".",
|
||||
"{%device%} wants to share folder \"{%folderlabel%}\" ({%folder%}).": "{{device}} vuole condividere la cartella \"{{folderlabel}}\" ({{folder}}).",
|
||||
"{%reintroducer%} might reintroduce this device.": "{{reintroducer}} potrebbe reintrodurre questo dispositivo."
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"A device with that ID is already added.": "이 식별자를 가진 기기가 이미 추가되어 있습니다.",
|
||||
"A negative number of days doesn't make sense.": "일수를 음수로 입력하는 것은 말이 되지 않습니다.",
|
||||
"A negative number of days doesn't make sense.": "일수를 음수로 입력하는 것은 올바르지 않습니다.",
|
||||
"A new major version may not be compatible with previous versions.": "새로운 주요 버전이 이전 버전들과 호환되지 않을 수 있습니다.",
|
||||
"API Key": "API 키",
|
||||
"About": "정보",
|
||||
@@ -386,6 +386,7 @@
|
||||
"Staggered File Versioning": "시차제 파일 버전 관리",
|
||||
"Start Browser": "브라우저 열기",
|
||||
"Statistics": "통계",
|
||||
"Stay logged in": "로그인 상태 유지",
|
||||
"Stopped": "중지됨",
|
||||
"Stores and syncs only encrypted data. Folders on all connected devices need to be set up with the same password or be of type \"{%receiveEncrypted%}\" too.": "암호화된 데이터만이 보관되어 동기화됩니다. 모든 공유된 기기의 폴더가 동일한 비밀번호를 설정하거나 동일한 \"{{receiveEncrypted}}\" 유형이어야 합니다.",
|
||||
"Subject:": "제목:",
|
||||
|
||||
@@ -26,6 +26,7 @@
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder. If the path to the application contains spaces, it should be quoted.": "Išorinė komanda apdoroja versijų valdymą. Ji turi pašalinti failą iš bendrinamo aplanko. Jei kelyje į programą yra tarpų, jie turėtų būti imami į kabutes.",
|
||||
"Anonymous Usage Reporting": "Anoniminė naudojimo ataskaita",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "Anoniminės naudojimo ataskaitos formatas pasikeitė. Ar norėtumėte pereiti prie naujojo formato?",
|
||||
"Applied to LAN": "Pritaikyta vietiniam tinklui (LAN)",
|
||||
"Apply": "Taikyti",
|
||||
"Are you sure you want to override all remote changes?": "Ar tikrai norite nustelbti visus nuotolinius pakeitimus?",
|
||||
"Are you sure you want to permanently delete all these files?": "Ar tikrai norite visam laikui ištrinti visus šiuos failus?",
|
||||
@@ -34,30 +35,32 @@
|
||||
"Are you sure you want to restore {%count%} files?": "Ar tikrai norite atkurti {{count}} failų(-us)?",
|
||||
"Are you sure you want to revert all local changes?": "Ar tikrai norite sugrąžinti visus vietinius pakeitimus?",
|
||||
"Are you sure you want to upgrade?": "Ar tikrai norite naujinti?",
|
||||
"Authentication Required": "Reikia nustatyti tapatybę",
|
||||
"Authors": "Autoriai",
|
||||
"Auto Accept": "Automatiškai priimti",
|
||||
"Automatic Crash Reporting": "Automatinės ataskaitos apie strigtis",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Automatiniai atnaujinimai dabar siūlo pasirinkimą tarp stabilių versijų ir kandidatinių versijų.",
|
||||
"Automatic upgrades": "Automatiniai atnaujinimai",
|
||||
"Automatic upgrades are always enabled for candidate releases.": "Automatiniai naujinimai kandidatinėms versijoms visada yra įjungti.",
|
||||
"Automatically create or share folders that this device advertises at the default path.": "Automatiškai sukurti ar dalintis aplankais, kuriuos šis įrenginys skelbia numatytajame kelyje.",
|
||||
"Automatically create or share folders that this device advertises at the default path.": "Automatiškai sukurti ar bendrinti aplankus, kuriuos šis įrenginys skelbia numatytajame kelyje.",
|
||||
"Available debug logging facilities:": "Prieinamos derinimo registravimo priemonės:",
|
||||
"Be careful!": "Būkite atsargūs!",
|
||||
"Bugs": "Klaidos",
|
||||
"Cancel": "Atsisakyti",
|
||||
"Changelog": "Pasikeitimai",
|
||||
"Changelog": "Keitinių žurnalas",
|
||||
"Clean out after": "Išvalyti po",
|
||||
"Cleanup Interval": "Išvalymo intervalas",
|
||||
"Click to see full identification string and QR code.": "Spustelėkite norint pamatyti visą identifikavimo eilutę ir QR kodą.",
|
||||
"Click to see full identification string and QR code.": "Spustelėkite, kad pamatytumėte visą identifikavimo eilutę ir QR kodą.",
|
||||
"Close": "Užverti",
|
||||
"Command": "Komanda",
|
||||
"Comment, when used at the start of a line": "Komentaras naudojamas naujoje eilutėje",
|
||||
"Compression": "Kompresija",
|
||||
"Compression": "Glaudinimas",
|
||||
"Configuration Directory": "Konfigūracijos katalogas",
|
||||
"Configuration File": "Konfigūracijos failas",
|
||||
"Configured": "Sukonfigūruotas",
|
||||
"Connected (Unused)": "Prisijungęs (Nenaudojamas)",
|
||||
"Connection Error": "Susijungimo klaida",
|
||||
"Connection Error": "Ryšio klaida",
|
||||
"Connection Management": "Ryšių valdymas",
|
||||
"Connection Type": "Ryšio tipas",
|
||||
"Connections": "Ryšiai",
|
||||
"Continuously watching for changes is now available within Syncthing. This will detect changes on disk and issue a scan on only the modified paths. The benefits are that changes are propagated quicker and that less full scans are required.": "Pastoviai stebėti pakeitimus dabar galima Syncthing viduje. Tai aptiks pakeitimus jūsų diske ir paleis nuskaitymą tik modifikuotuose keliuose. Pranašumas yra tas, kad pakeitimai sklis greičiau ir reikės mažiau pilnų nuskaitymų.",
|
||||
@@ -67,6 +70,7 @@
|
||||
"Copy": "Kopijuoti",
|
||||
"Copy failed! Try to select and copy manually.": "Nepavyko nukopijuoti! Pabandykite pažymėti ir nukopijuoti rankiniu būdu.",
|
||||
"Currently Shared With Devices": "Šiuo metu bendrinama su įrenginiais",
|
||||
"Custom Range": "Tinkintas rėžis",
|
||||
"Danger!": "Pavojus!",
|
||||
"Database Location": "Duomenų bazės vieta",
|
||||
"Debugging Facilities": "Derinimo priemonės",
|
||||
@@ -78,13 +82,15 @@
|
||||
"Delete Unexpected Items": "Ištrinti netikėtus elementus",
|
||||
"Deleted {%file%}": "Ištrintas {{file}}",
|
||||
"Deselect All": "Nuimti žymėjimą nuo visų",
|
||||
"Deselect devices to stop sharing this folder with.": "Panaikinti įrenginių pasirinkimą, kad su jais būtų nustota bendrinti šį aplanką. ",
|
||||
"Deselect devices to stop sharing this folder with.": "Nuimkite žymėjimą nuo įrenginių norėdami nustoti su jais bendrinti šį aplanką.",
|
||||
"Deselect folders to stop sharing with this device.": "Nuimkite žymėjimą nuo aplankų norėdami nustoti juos bendinti su šiuo įrenginiu.",
|
||||
"Device": "Įrenginys",
|
||||
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "Įrenginys \"{{name}}\" ({{device}} {{address}}) nori prisijungti. Pridėti naują įrenginį?",
|
||||
"Device Certificate": "Įrenginio liudijimas",
|
||||
"Device ID": "Įrenginio ID",
|
||||
"Device Identification": "Įrenginio identifikacija",
|
||||
"Device Identification": "Įrenginio identifikavimas",
|
||||
"Device Name": "Įrenginio pavadinimas",
|
||||
"Device Status": "Įrenginio būsena",
|
||||
"Device is untrusted, enter encryption password": "Įrenginys yra nepatikimas, įveskite šifravimo slaptažodį",
|
||||
"Device rate limits": "Įrenginio spartos apribojimai",
|
||||
"Device that last modified the item": "Įrenginys, kuris paskutinis modifikavo elementą",
|
||||
@@ -97,19 +103,21 @@
|
||||
"Disables comparing and syncing file permissions. Useful on systems with nonexistent or custom permissions (e.g. FAT, exFAT, Synology, Android).": "Išjungia palyginimą bei failų leidimų sinchronizavimą. Naudinga sistemose, kuriose nėra leidimų, arba jie yra tinkinti (pvz., FAT, exFAT, Synology, Android).",
|
||||
"Discard": "Atmesti",
|
||||
"Disconnected": "Atsijungęs",
|
||||
"Disconnected (Inactive)": "Atsijungęs (Pasyvus)",
|
||||
"Disconnected (Unused)": "Atsijungęs (Nenaudojamas)",
|
||||
"Discovered": "Atrastas",
|
||||
"Discovery": "Lokacija",
|
||||
"Discovery Failures": "Matomumo nesėkmės",
|
||||
"Discovery": "Atradimas",
|
||||
"Discovery Failures": "Atradimo nesėkmės",
|
||||
"Discovery Status": "Atradimo būsena",
|
||||
"Dismiss": "Atmesti",
|
||||
"Do not restore": "Neatkurti",
|
||||
"Do not restore all": "Neatkurti visus",
|
||||
"Do you want to enable watching for changes for all your folders?": "Ar norite įjungti pakeitimų stebėjimą visiems savo aplankams?",
|
||||
"Documentation": "Aprašymas",
|
||||
"Download Rate": "Parsisiuntimo greitis",
|
||||
"Downloaded": "Parsisiųstas",
|
||||
"Downloading": "Siunčiama",
|
||||
"Edit": "Redaguoti",
|
||||
"Download Rate": "Atsiuntimo greitis",
|
||||
"Downloaded": "Atsiųsta",
|
||||
"Downloading": "Atsiunčiama",
|
||||
"Edit": "Taisyti",
|
||||
"Edit Device": "Taisyti įrenginį",
|
||||
"Edit Device Defaults": "Taisyti įrenginio numatytąsias reikšmes",
|
||||
"Edit Folder": "Taisyti aplanką",
|
||||
@@ -121,13 +129,16 @@
|
||||
"Enabled": "Įjungta",
|
||||
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Įveskite neneigiamąjį skaičių (pvz., \"2.35\") ir pasirinkite įtaisą. Procentai yra skaičiuojami kaip viso disko dydžio dalis.",
|
||||
"Enter a non-privileged port number (1024 - 65535).": "Įveskite neprivilegijuoto prievado numerį (1024 - 65535).",
|
||||
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Įveskite kableliais atskirtus (\"tcp://ip:prievadas\", \"tcp://serveris:prievadas\") adresus arba \"dynamic\", kad atliktumėte automatinį adresų atlikimą.",
|
||||
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Įveskite kableliais atskirtus („tcp://ip:prievadas“, „tcp://serveris:prievadas“) adresus arba „dynamic“, kad atliktumėte automatinį adresų atradimą.",
|
||||
"Enter ignore patterns, one per line.": "Suveskite nepaisomus šablonus, kiekvieną naujoje eilutėje.",
|
||||
"Enter up to three octal digits.": "Įveskite iki trijų aštuntainių skaitmenų.",
|
||||
"Error": "Klaida",
|
||||
"Extended Attributes": "Išplėstiniai požymiai",
|
||||
"Extended Attributes Filter": "Išplėstinių požymių filtras",
|
||||
"External File Versioning": "Išorinis versijų valdymas",
|
||||
"Failed Items": "Nepavykę siuntimai",
|
||||
"Failed to load file versions.": "Nepavyko įkelti failo versijų.",
|
||||
"Failed to load ignore patterns.": "Nepavyko įkelti nepaisymo šablonų.",
|
||||
"Failed to setup, retrying": "Nepavyko nustatyti, bandoma iš naujo",
|
||||
"Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.": "Nesėkmė prisijungti prie IPv6 serverių yra tikėtina, jei nėra IPv6 ryšio.",
|
||||
"File Pull Order": "Failų siuntimo tvarka",
|
||||
@@ -143,26 +154,32 @@
|
||||
"Folder ID": "Aplanko ID",
|
||||
"Folder Label": "Aplanko etiketė",
|
||||
"Folder Path": "Kelias iki aplanko",
|
||||
"Folder Status": "Aplanko būsena",
|
||||
"Folder Type": "Aplanko tipas",
|
||||
"Folder type \"{%receiveEncrypted%}\" can only be set when adding a new folder.": "Aplanko tipas „{{receiveEncrypted}}“ gali būti nustatytas tik pridedant naują aplanką.",
|
||||
"Folder type \"{%receiveEncrypted%}\" cannot be changed after adding the folder. You need to remove the folder, delete or decrypt the data on disk, and add the folder again.": "Aplanko tipas „{{receiveEncrypted}}“ negali būti pakeistas po to, kai aplankas pridėtas. Turite pašalinti aplanką, ištrinti arba iššifruoti diske esančius duomenis ir vėl pridėti aplanką.",
|
||||
"Folders": "Aplankai",
|
||||
"For the following folders an error occurred while starting to watch for changes. It will be retried every minute, so the errors might go away soon. If they persist, try to fix the underlying issue and ask for help if you can't.": "Pradėjus stebėti pakeitimus, šiuose aplankuose atsirado klaidų. Kiekvieną minutę bus bandoma iš naujo, taigi, klaidos gali išnykti. Jeigu jos neišnyks, pabandykite išspręsti slypinčią problemą, o jeigu neįstengiate, paprašykite pagalbos.",
|
||||
"Forever": "Amžinai",
|
||||
"Full Rescan Interval (s)": "Pilno nuskaitymo iš naujo intervalas (s)",
|
||||
"GUI": "Valdymo skydelis",
|
||||
"GUI / API HTTPS Certificate": "",
|
||||
"GUI Authentication Password": "Valdymo skydelio slaptažodis",
|
||||
"GUI Authentication User": "Valdymo skydelio vartotojo vardas",
|
||||
"GUI Authentication: Set User and Password": "Valdymo skydelio tapatybės nustatymas: Nustatyti vartotoją ir slaptažodį",
|
||||
"GUI Authentication User": "Valdymo skydelio naudotojo vardas",
|
||||
"GUI Authentication: Set User and Password": "Valdymo skydelio tapatybės nustatymas: Nustatyti naudotoją ir slaptažodį",
|
||||
"GUI Listen Address": "Valdymo skydelio adresas",
|
||||
"GUI Theme": "Valdymo skydelio apipavidalinimas",
|
||||
"General": "Bendra",
|
||||
"Generate": "Sukurti",
|
||||
"Global Discovery": "Visuotinis matomumas",
|
||||
"Global Discovery Servers": "Visuotinio matomumo serveriai",
|
||||
"Global Discovery": "Visuotinis atradimas",
|
||||
"Global Discovery Servers": "Visuotinio atradimo serveriai",
|
||||
"Global State": "Visuotinė būsena",
|
||||
"Help": "Pagalba",
|
||||
"Home page": "Pagrindinis puslapis",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "Vis dėlto, jūsų esami nustatymai nurodo, kad jūs, greičiausiai, nenorite turėti jas įjungtas. Mes jums išjungėme automatines ataskaitas apie strigtis.",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "Jei norite neleisti kitiems šio kompiuterio vartotojams gauti prieigą prie Syncthing, o per ją, prieigą prie jūsų failų, tuomet apsvarstykite galimybę nusistatyti tapatybės nustatymą.",
|
||||
"Identification": "Identifikavimas",
|
||||
"If untrusted, enter encryption password": "Jei nepatikimas, įveskite šifravimo slaptažodį",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "Jei norite neleisti kitiems šio kompiuterio naudotojams gauti prieigą prie Syncthing, o per ją, prieigą prie jūsų failų, tuomet apsvarstykite galimybę nusistatyti tapatybės nustatymą.",
|
||||
"Ignore": "Nepaisyti",
|
||||
"Ignore Patterns": "Nepaisyti šablonų",
|
||||
"Ignore Permissions": "Nepaisyti failų prieigos leidimų",
|
||||
@@ -172,12 +189,13 @@
|
||||
"Included Software": "Įtraukta programinė įranga",
|
||||
"Incoming Rate Limit (KiB/s)": "Atsiunčiamo srauto maksimalus greitis (KiB/s)",
|
||||
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Neteisinga konfigūracija gali pažeisti jūsų aplankų turinį ir padaryti Syncthing neoperuotina.",
|
||||
"Incorrect user name or password.": "Neteisingas naudotojo vardas ar slaptažodis.",
|
||||
"Introduced By": "Supažindė",
|
||||
"Introducer": "Supažindintojas",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "Apversti sąlygas (pvz.: nenustoti naudoti)",
|
||||
"Keep Versions": "Saugojamų versijų kiekis",
|
||||
"LDAP": "LDAP",
|
||||
"Largest First": "Didžiausi pirmiau",
|
||||
"Largest First": "Pirma didžiausi",
|
||||
"Last Scan": "Paskutinis nuskaitymas",
|
||||
"Last seen": "Paskutinį kartą matytas",
|
||||
"Latest Change": "Paskutinis pakeitimas",
|
||||
@@ -188,17 +206,23 @@
|
||||
"Loading data...": "Įkeliami duomenys...",
|
||||
"Loading...": "Įkeliama...",
|
||||
"Local Additions": "Vietiniai pridėjimai",
|
||||
"Local Discovery": "Vietinis matomumas",
|
||||
"Local Discovery": "Vietinis atradimas",
|
||||
"Local State": "Vietinė būsena",
|
||||
"Local State (Total)": "Vietinė būsena (Bendrai)",
|
||||
"Locally Changed Items": "Vietoje pakeisti elementai",
|
||||
"Log": "Žurnalas",
|
||||
"Log File": "Žurnalo failas",
|
||||
"Log In": "Prisijungti",
|
||||
"Log Out": "Atsijungti",
|
||||
"Log in to see paths information.": "Prisijunkite norėdami matyti informaciją apie kelius.",
|
||||
"Log in to see version information.": "Prisijunkite norėdami matyti informaciją apie versijas.",
|
||||
"Log tailing paused. Scroll to the bottom to continue.": "Žurnalo galas pristabdytas. Slinkite į apačią, norėdami tęsti.",
|
||||
"Login failed, see Syncthing logs for details.": "Nepavyko prisijungti, išsamesnei informacijai žiūrėkite Syncthing žurnalus.",
|
||||
"Logs": "Žurnalai",
|
||||
"Major Upgrade": "Stambus atnaujinimas",
|
||||
"Mass actions": "Masiniai veiksmai",
|
||||
"Maximum Age": "Maksimalus amžius",
|
||||
"Metadata Only": "Metaduomenims",
|
||||
"Metadata Only": "Tik metaduomenys",
|
||||
"Minimum Free Disk Space": "Minimum laisvos vietos diske",
|
||||
"Mod. Device": "Mod. įrenginys",
|
||||
"Mod. Time": "Mod. laikas",
|
||||
@@ -210,15 +234,17 @@
|
||||
"Never": "Niekada",
|
||||
"New Device": "Naujas įrenginys",
|
||||
"New Folder": "Naujas aplankas",
|
||||
"Newest First": "Naujausi pirmiau",
|
||||
"Newest First": "Pirma naujausi",
|
||||
"No": "Ne",
|
||||
"No File Versioning": "Nėra versijų valdymo",
|
||||
"No files will be deleted as a result of this operation.": "Šios operacijos rezultate nebus pašalinti jokie failai.",
|
||||
"No upgrades": "Be atnaujinimų",
|
||||
"Not shared": "Nebendrinama",
|
||||
"Notice": "Įspėjimas",
|
||||
"Number of Connections": "Ryšių skaičius",
|
||||
"OK": "Gerai",
|
||||
"Off": "Netaikoma",
|
||||
"Oldest First": "Seniausi pirmiau",
|
||||
"Oldest First": "Pirma seniausi",
|
||||
"Optional descriptive label for the folder. Can be different on each device.": "Nebūtina aprašomoji aplanko etiketė. Kiekviename įrenginyje gali būti skirtinga.",
|
||||
"Options": "Parametrai",
|
||||
"Out of Sync": "Išsisinchronizavę",
|
||||
@@ -226,9 +252,10 @@
|
||||
"Outgoing Rate Limit (KiB/s)": "Išsiunčiamo srauto maksimalus greitis (KiB/s)",
|
||||
"Override": "Nustelbti",
|
||||
"Override Changes": "Perrašyti pakeitimus",
|
||||
"Password": "Slaptažodis",
|
||||
"Path": "Kelias",
|
||||
"Path to the folder on the local computer. Will be created if it does not exist. The tilde character (~) can be used as a shortcut for": "Kelias iki aplanko šiame kompiuteryje. Bus sukurtas, jei neegzistuoja. Tildės simbolis (~) gali būti naudojamas kaip trumpinys",
|
||||
"Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).": "Kelias, kur bus saugomos versijos (palikite tuščią numatytajam .stversions katalogui bendrinamame aplanke).",
|
||||
"Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).": "Kelias, kuriame bus saugomos versijos (palikite tuščią numatytajam .stversions katalogui bendrinamame aplanke).",
|
||||
"Paths": "Keliai",
|
||||
"Pause": "Pristabdyti",
|
||||
"Pause All": "Pristabdyti visus",
|
||||
@@ -239,7 +266,7 @@
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Periodinis nuskaitymas nurodytu intervalu ir įjungtas pakeitimų stebėjimas",
|
||||
"Periodic scanning at given interval and failed setting up watching for changes, retrying every 1m:": "Periodinis nuskaitymas nurodytu intervalu ir nepavykęs nustatyti pakeitimų stebėjimas, bandoma iš naujo kas 1 min.:",
|
||||
"Please consult the release notes before performing a major upgrade.": "Peržvelkite laidos informaciją prieš atlikdami stambų atnaujinimą.",
|
||||
"Please set a GUI Authentication User and Password in the Settings dialog.": "Prašome nustatymų dialoge nustatyti valdymo skydelio vartotojo vardą ir slaptažodį.",
|
||||
"Please set a GUI Authentication User and Password in the Settings dialog.": "Prašome nustatymų dialoge nustatyti valdymo skydelio naudotojo vardą ir slaptažodį.",
|
||||
"Please wait": "Prašome palaukti",
|
||||
"Prefix indicating that the file can be deleted if preventing directory removal": "Priešdelis, nurodantis, kad failas gali būti ištrintas tuo atveju, jei neleidžia šalinti katalogo",
|
||||
"Prefix indicating that the pattern should be matched without case sensitivity": "Priešdelis, nurodantis, kad šablonas turėtų būti atitiktas neskiriant raidžių dydžio",
|
||||
@@ -251,6 +278,7 @@
|
||||
"QUIC WAN": "QUIC WAN (platusis tinklas)",
|
||||
"Quick guide to supported patterns": "Trumpas leistinų šablonų vadovas",
|
||||
"Random": "Atsitiktinė",
|
||||
"Receive Encrypted": "Gauti šifruotą",
|
||||
"Receive Only": "Tik gauti",
|
||||
"Received data is already encrypted": "Gauti duomenys jau yra šifruoti",
|
||||
"Recent Changes": "Paskiausi keitimai",
|
||||
@@ -265,7 +293,7 @@
|
||||
"Rescan": "Nuskaityti iš naujo",
|
||||
"Rescan All": "Nuskaityti visus aplankus",
|
||||
"Rescans": "Nuskaitymai",
|
||||
"Restart": "Perleisti",
|
||||
"Restart": "Paleisti iš naujo",
|
||||
"Restart Needed": "Reikalingas perleidimas",
|
||||
"Restarting": "Persileidžia",
|
||||
"Restore": "Atkurti",
|
||||
@@ -276,15 +304,18 @@
|
||||
"Revert": "Sugrąžinti",
|
||||
"Revert Local Changes": "Sugrąžinti vietinius pakeitimus",
|
||||
"Save": "Išsaugoti",
|
||||
"Saving changes": "Įrašomi pakeitimai",
|
||||
"Scan Time Remaining": "Likęs nuskaitymo laikas",
|
||||
"Scanning": "Skenuojama",
|
||||
"See external versioning help for supported templated command line parameters.": "Palaikomiems šabloniniams komandų eilutės parametrams, žiūrėkite išorinį versijų valdymo žinyną.",
|
||||
"Select All": "Žymėti visus",
|
||||
"Select a version": "Pasirinkti versiją",
|
||||
"Select additional devices to share this folder with.": "Pasirinkti papildomus įrenginius, su kuriais bendrinti šį aplanką.",
|
||||
"Select additional devices to share this folder with.": "Pažymėkite papildomus įrenginius, su kuriais bendrinti šį aplanką.",
|
||||
"Select additional folders to share with this device.": "Pažymėkite papildomus aplankus, kuriuos bendrinti su šiuo įrenginiu.",
|
||||
"Select latest version": "Pasirinkti paskiausią versiją",
|
||||
"Select oldest version": "Pasirinkti seniausią versiją",
|
||||
"Send & Receive": "Siųsti ir gauti",
|
||||
"Send Extended Attributes": "Siųsti išplėstinius požymius",
|
||||
"Send Only": "Tik siųsti",
|
||||
"Settings": "Nustatymai",
|
||||
"Share": "Bendrinti",
|
||||
@@ -294,9 +325,10 @@
|
||||
"Share this folder?": "Bendrinti šį aplanką?",
|
||||
"Shared Folders": "Bendrinami aplankai",
|
||||
"Shared With": "Bendrinama su",
|
||||
"Sharing": "Dalinamasis",
|
||||
"Sharing": "Bendrinimas",
|
||||
"Show ID": "Rodyti ID",
|
||||
"Show QR": "Rodyti QR",
|
||||
"Show detailed discovery status": "Rodyti išsamią atradimo būseną",
|
||||
"Show diff with previous version": "Rodyti skirtumus su ankstesne versija",
|
||||
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Grupės būsenoje rodomas vietoje įrenginio vardo. Kiti įrenginiai matys kaip pasirinktinį vardą.",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Grupės būsenoje rodomas vietoje įrenginio vardo. Bus atnaujintas į įrenginio vardą jei nieko neįrašysite.",
|
||||
@@ -305,19 +337,23 @@
|
||||
"Simple File Versioning": "Supaprastintas versijų valdymas",
|
||||
"Single level wildcard (matches within a directory only)": "Vieno lygio pakaitos simbolis (atitinka tik vieną katalogo lygį)",
|
||||
"Size": "Dydis",
|
||||
"Smallest First": "Mažiausi pirmiau",
|
||||
"Smallest First": "Pirma mažiausi",
|
||||
"Some items could not be restored:": "Kai kurių elementų atkurti nepavyko:",
|
||||
"Source Code": "Išeities kodas",
|
||||
"Stable releases and release candidates": "Stabilios versijos ir kandidatinės versijos",
|
||||
"Stable releases are delayed by about two weeks. During this time they go through testing as release candidates.": "Stabilios versijos pasirodo maždaug dvi savaites vėliau. Per tą laiką, jos pereina testavimą kaip kandidatinės versijos.",
|
||||
"Stable releases are delayed by about two weeks. During this time they go through testing as release candidates.": "Stabilios versijos pasirodo maždaug dvi savaites vėliau. Per tą laiką jos yra testuojamos kaip kandidatinės versijos.",
|
||||
"Stable releases only": "Tik stabilios versijos",
|
||||
"Staggered File Versioning": "Pakopinis versijų valdymas",
|
||||
"Start Browser": "Paleisti naršyklę",
|
||||
"Statistics": "Statistika",
|
||||
"Stay logged in": "Išlikti prisijungus",
|
||||
"Stopped": "Sustabdyta",
|
||||
"Stores and syncs only encrypted data. Folders on all connected devices need to be set up with the same password or be of type \"{%receiveEncrypted%}\" too.": "Saugo ir sinchronizuoja tik šifruotus duomenis. Aplankui visuose prijungtuose įrenginiuose turi būti nustatytas tas pats slaptažodis arba aplankas irgi turi būti „{{receiveEncrypted}}“ tipo.",
|
||||
"Support": "Pagalba",
|
||||
"Support Bundle": "Palaikymo paketas",
|
||||
"Sync Extended Attributes": "Sinchronizuoti išplėstinius požymius",
|
||||
"Sync Protocol Listen Addresses": "Sutapatinimo taisyklių adresas",
|
||||
"Sync Status": "Sinchronizavimo būsena",
|
||||
"Syncing": "Sutapatinama",
|
||||
"Syncthing device ID for \"{%devicename%}\"": "Syncthing įrenginio ID, skirtas „{{devicename}}“",
|
||||
"Syncthing has been shut down.": "Syncthing išjungtas",
|
||||
@@ -325,9 +361,10 @@
|
||||
"Syncthing is Free and Open Source Software licensed as MPL v2.0.": "Syncthing yra laisva ir atvirojo kodo programinė įranga, licencijuota pagal MPL v2.0.",
|
||||
"Syncthing is a continuous file synchronization program. It synchronizes files between two or more computers in real time, safely protected from prying eyes. Your data is your data alone and you deserve to choose where it is stored, whether it is shared with some third party, and how it's transmitted over the internet.": "Syncthing yra pastovaus failų sinchronizavimo programa. Ji realiu laiku sinchronizuoja failus tarp dviejų ar daugiau kompiuterių, saugiai apsaugodama juos nuo smalsių akių. Jūsų duomenys yra tik jūsų duomenys ir jūs turite teisę rinktis, kur juos laikyti, su kuo juos bendrinti ir kaip juos persiuntinėti.",
|
||||
"Syncthing is restarting.": "Syncthing perleidžiamas",
|
||||
"Syncthing is saving changes.": "Syncthing įrašo pakeitimus.",
|
||||
"Syncthing is upgrading.": "Syncthing atsinaujina.",
|
||||
"Syncthing now supports automatically reporting crashes to the developers. This feature is enabled by default.": "Dabar, Syncthing palaiko ir automatiškai plėtotojams siunčia ataskaitas apie strigtis. Pagal numatymą, ši ypatybė yra įjungta.",
|
||||
"Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…": "Syncthing išjungta arba problemos su Interneto ryšių. Bandoma iš naujo…",
|
||||
"Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…": "Atrodo, kad Syncthing išjungta arba yra problemų su interneto ryšiu. Bandoma iš naujo…",
|
||||
"Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.": "Atrodo, kad Syncthing, vykdydamas jūsų užklausą, susidūrė su problemomis. Prašome iš naujo įkelti puslapį, arba jei problema išlieka, iš naujo paleisti Syncthing.",
|
||||
"TCP LAN": "TCP LAN (vietinis tinklas)",
|
||||
"TCP WAN": "TCP WAN (platusis tinklas)",
|
||||
@@ -337,15 +374,15 @@
|
||||
"The Syncthing admin interface is configured to allow remote access without a password.": "Syncthing administratoriaus sąsaja yra sukonfigūruota taip, kad be slaptažodžio leistų nuotolinę prieigą.",
|
||||
"The aggregated statistics are publicly available at the URL below.": "Naudojimosi ataskaitą galite peržiūrėti žemiau nurodytu URL adresu.",
|
||||
"The cleanup interval cannot be blank.": "Išvalymo intervalas negali būti tuščias.",
|
||||
"The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.": "Nauji nustatymai išsaugoti, bet neaktyvuoti. Perleiskite Syncthing programą iš naujo norėdami įgalinti naujus nustatymus.",
|
||||
"The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.": "Konfigūracija įrašyta, bet neaktyvuota. Syncthing privalo būti paleista iš naujo, kad aktyvuotų naują konfigūraciją.",
|
||||
"The device ID cannot be blank.": "Įrenginio ID negali būti tuščias.",
|
||||
"The device ID to enter here can be found in the \"Actions > Show ID\" dialog on the other device. Spaces and dashes are optional (ignored).": "Įrenginio ID, kurį čia reikia įvesti, galite rasti „Veiksmai > Rodyti ID“ dialoge kitame įrenginyje. Tarpai ir brūkšneliai nebūtini (ignoruojami).",
|
||||
"The encrypted usage report is sent daily. It is used to track common platforms, folder sizes, and app versions. If the reported data set is changed you will be prompted with this dialog again.": "Kas dieną siunčiama šifruota naudojimo ataskaita. Ji naudojama sekti, kokios platformos naudojamos, aplankų dydžius ir programų versijas. Jei siunčiamų duomenų turinys pasikeis, šis dialogas bus parodytas iš naujo.",
|
||||
"The entered device ID does not look valid. It should be a 52 or 56 character string consisting of letters and numbers, with spaces and dashes being optional.": "Įvestas neteisingas įrenginio ID. Turi būti 52 ar 56 simbolių eilutė su raidėmis ir skaičiais kuriuos galima atskirti tarpu arba brūkšneliu.",
|
||||
"The folder ID cannot be blank.": "Aplanko ID negali būti tuščias.",
|
||||
"The folder ID must be unique.": "Aplanko ID turi būti unikalus.",
|
||||
"The folder content on other devices will be overwritten to become identical with this device. Files not present here will be deleted on other devices.": "Aplanko turinys kituose įrenginiuose bus perrašytas taip, kad būtų toks pats, kaip šiame įrenginyje. Failai, kurių nėra šiame aplanke, bus ištrinti kituose įrenginiuose.",
|
||||
"The folder content on this device will be overwritten to become identical with other devices. Files newly added here will be deleted.": "Aplanko turinys šiame įrenginyje bus perrašytas taip, kad būtų toks pats, kaip kituose įrenginiuose. Į šią vietą naujai pridėti failai, bus ištrinti.",
|
||||
"The folder content on other devices will be overwritten to become identical with this device. Files not present here will be deleted on other devices.": "Aplanko turinys kituose įrenginiuose bus perrašytas taip, kad būtų toks pats, kaip šiame įrenginyje. Failai, kurių nėra šiame aplanke, kituose įrenginiuose bus ištrinti.",
|
||||
"The folder content on this device will be overwritten to become identical with other devices. Files newly added here will be deleted.": "Aplanko turinys šiame įrenginyje bus perrašytas taip, kad būtų toks pats, kaip kituose įrenginiuose. Į šią vietą naujai pridėti failai bus ištrinti.",
|
||||
"The folder path cannot be blank.": "Kelias iki aplanko negali būti tuščias.",
|
||||
"The following intervals are used: for the first hour a version is kept every 30 seconds, for the first day a version is kept every hour, for the first 30 days a version is kept every day, until the maximum age a version is kept every week.": "Šie pertraukų nustatymai naudojami: pirmą valandą versijos laikomos 30 sekundžių, pirmą dieną versijos laikomos valandą, pirmas 30 dienų versijos laikomos parą, kol nebus viršytas nustatytas maksimalus amžius.",
|
||||
"The following items could not be synchronized.": "Nepavyko parsiųsti šių failų.",
|
||||
@@ -356,11 +393,12 @@
|
||||
"The maximum age must be a number and cannot be blank.": "Maksimalus amžius turi būti skaitmuo ir negali būti tuščias laukelis.",
|
||||
"The maximum time to keep a version (in days, set to 0 to keep versions forever).": "Maksimalus laikas kurį bus saugojama versija (dienomis, nustatykite 0 norėdami saugoti amžinai).",
|
||||
"The number of days must be a number and cannot be blank.": "Dienų skaičius turi būti teigiamas skaičius.",
|
||||
"The number of days to keep files in the trash can. Zero means forever.": "Kiek dienų laikyti failus šiukšliadėžėje. Nulis reiškia amžinai.",
|
||||
"The number of days to keep files in the trash can. Zero means forever.": "Kiek dienų laikyti failus šiukšlinėje. Nulis reiškia amžinai.",
|
||||
"The number of old versions to keep, per file.": "Kiek failo versijų saugoti.",
|
||||
"The number of versions must be a number and cannot be blank.": "Versijų skaičius turi būti skaitmuo ir negali būti tuščias laukelis.",
|
||||
"The path cannot be blank.": "Kelias negali būti tuščias.",
|
||||
"The rate limit must be a non-negative number (0: no limit)": "Srauto maksimalus greitis privalo būti ne neigiamas skaičius (0: nėra apribojimo)",
|
||||
"The remote device has not accepted sharing this folder.": "Nuotolinis įrenginys nepriėmė šio aplanko bendrinimo.",
|
||||
"The remote device has paused this folder.": "Nuotolinis įrenginys pristabdė šį aplanką.",
|
||||
"The rescan interval must be a non-negative number of seconds.": "Nuskaitymo dažnis negali būti neigiamas skaičius.",
|
||||
"There are no devices to share this folder with.": "Nėra įrenginių su kuriais bendrinti šį aplanką.",
|
||||
@@ -375,7 +413,7 @@
|
||||
"Time the item was last modified": "Laikas, kai elementas buvo paskutinį kartą modifikuotas",
|
||||
"Today": "Šiandien",
|
||||
"Trash Can": "Šiukšlinė",
|
||||
"Trash Can File Versioning": "Šiukšliadėžės versijų valdymas",
|
||||
"Trash Can File Versioning": "Šiukšlinės versijų valdymas",
|
||||
"Type": "Tipas",
|
||||
"UNIX Permissions": "UNIX leidimai",
|
||||
"Unavailable": "Neprieinama",
|
||||
@@ -386,8 +424,9 @@
|
||||
"Unignore": "Nustoti nepaisyti",
|
||||
"Unknown": "Nežinoma",
|
||||
"Unshared": "Nebendrinama",
|
||||
"Unshared Devices": "Nebedrinami įrenginiai",
|
||||
"Unshared Devices": "Įrenginiai, su kuriais nebendrinama",
|
||||
"Unshared Folders": "Nebendrinami aplankai",
|
||||
"Untrusted": "Nepatikimas",
|
||||
"Up to Date": "Atnaujinta",
|
||||
"Updated {%file%}": "Atnaujintas {{file}}",
|
||||
"Upgrade": "Atnaujinimas",
|
||||
@@ -398,7 +437,12 @@
|
||||
"Usage reporting is always enabled for candidate releases.": "Naudojimo ataskaita kandidatinėms versijoms visada yra įjungta.",
|
||||
"Use HTTPS for GUI": "Valdymo skydeliui naudoti saugų ryšį ",
|
||||
"Use notifications from the filesystem to detect changed items.": "Naudoti pranešimus iš failų sistemos, norint aptikti pakeistus elementus.",
|
||||
"Username/Password has not been set for the GUI authentication. Please consider setting it up.": "Valdymo skydelio tapatybės nustatymui nebuvo nustatytas vartotojo vardas/slaptažodis. Apsvarstykite galimybę jį nusistatyti.",
|
||||
"User": "Naudotojas",
|
||||
"Username/Password has not been set for the GUI authentication. Please consider setting it up.": "Valdymo skydelio tapatybės nustatymui nebuvo nustatytas naudotojo vardas/slaptažodis. Apsvarstykite galimybę jį nusistatyti.",
|
||||
"Using a QUIC connection over LAN": "Naudoja QUIC ryšį per vietinį tinklą (LAN)",
|
||||
"Using a QUIC connection over WAN": "Naudoja QUIC ryšį per platųjį tinklą (WAN)",
|
||||
"Using a direct TCP connection over LAN": "Naudoja tiesioginį TCP ryšį per vietinį tinklą (LAN)",
|
||||
"Using a direct TCP connection over WAN": "Naudoja tiesioginį TCP ryšį per platųjį tinklą (WAN)",
|
||||
"Version": "Versija",
|
||||
"Versions": "Versijos",
|
||||
"Versions Path": "Kelias iki versijos",
|
||||
@@ -427,6 +471,8 @@
|
||||
"You have no ignored folders.": "Jūs neturite jokių nepaisomų aplankų.",
|
||||
"You have unsaved changes. Do you really want to discard them?": "Turite neįrašytų pakeitimų. Ar tikrai norite juos atmesti?",
|
||||
"You must keep at least one version.": "Būtina saugoti bent vieną versiją.",
|
||||
"Your SMS app should open to let you choose the recipient and send it from your own number.": "Turi atsiverti SMS programėlė ir leisti jums pasirinkti gavėją bei išsiųsti žinutę iš nuosavo numerio.",
|
||||
"Your email app should open to let you choose the recipient and send it from your own address.": "Turi atsiverti el. pašto programėlė ir leisti jums pasirinkti gavėją bei išsiųsti el. laišką iš nuosavo adreso.",
|
||||
"days": "dienos",
|
||||
"deleted": "ištrintas",
|
||||
"directories": "katalogai",
|
||||
@@ -437,6 +483,15 @@
|
||||
"items": "įrašai",
|
||||
"modified": "modifikuotas",
|
||||
"seconds": "sek.",
|
||||
"theme": {
|
||||
"name": {
|
||||
"black": "Juodas",
|
||||
"dark": "Tamsus",
|
||||
"default": "Numatytasis",
|
||||
"light": "Šviesus"
|
||||
}
|
||||
},
|
||||
"unknown device": "nežinomas įrenginys",
|
||||
"{%device%} wants to share folder \"{%folder%}\".": "{{device}} nori bendrinti aplanką „{{folder}}“.",
|
||||
"{%device%} wants to share folder \"{%folderlabel%}\" ({%folder%}).": "{{device}} nori bendrinti aplanką „{{folderlabel}}“ ({{folder}})."
|
||||
}
|
||||
|
||||
@@ -158,8 +158,8 @@
|
||||
"Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.": "Błąd połączenia do serwerów IPv6 może wystąpić, gdy w ogóle nie ma połączenia po IPv6.",
|
||||
"File Pull Order": "Kolejność pobierania plików",
|
||||
"File Versioning": "Wersjonowanie plików",
|
||||
"Files are moved to .stversions directory when replaced or deleted by Syncthing.": "Pliki zmienione lub usunięte przez Syncthing są przenoszone do katalogu .stversions.",
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Pliki zmienione lub usunięte przez Syncthing są datowane i przenoszone do katalogu .stversions.",
|
||||
"Files are moved to .stversions directory when replaced or deleted by Syncthing.": "Pliki zastąpione lub usunięte przez Syncthing są przenoszone do katalogu .stversions.",
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Pliki zastąpione lub usunięte przez Syncthing są datowane i przenoszone do katalogu .stversions.",
|
||||
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Pliki są zabezpieczone przed zmianami dokonanymi na innych urządzeniach, ale zmiany dokonane na tym urządzeniu będą wysyłane do pozostałych urządzeń.",
|
||||
"Files are synchronized from the cluster, but any changes made locally will not be sent to other devices.": "Pliki są synchronizowane z pozostałych urządzeń, ale wszelkie zmiany dokonane lokalnie nie będą wysyłanie do innych urządzeń.",
|
||||
"Filesystem Watcher Errors": "Błędy obserwatora plików",
|
||||
@@ -196,7 +196,7 @@
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "Niemniej jednak, obecne ustawienia wskazują, że możesz nie chcieć włączać tej funkcji. Automatyczne zgłaszanie awarii zostało więc wyłączone na tym urządzeniu.",
|
||||
"Identification": "Identyfikator",
|
||||
"If untrusted, enter encryption password": "Jeżeli folder jest niezaufany, wprowadź szyfrujące hasło",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "Jeżeli chcesz zakazać innym użytkownikom tego komputera dostępu do programu Syncthing, a przez niego do swoich plików, zastanów się nad ustawieniem uwierzytelniania.",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "Jeżeli chcesz zakazać innym użytkownikom tego komputera dostępu do programu Syncthing, a przez niego do swoich plików, zastanów się nad włączeniem uwierzytelniania.",
|
||||
"Ignore": "Ignoruj",
|
||||
"Ignore Patterns": "Wzorce ignorowania",
|
||||
"Ignore Permissions": "Ignorowanie uprawnień",
|
||||
@@ -206,7 +206,7 @@
|
||||
"Ignored at": "Ignorowane od",
|
||||
"Included Software": "Zawarte oprogramowanie",
|
||||
"Incoming Rate Limit (KiB/s)": "Ograniczenie prędkości pobierania (KiB/s)",
|
||||
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Niepoprawne ustawienia mogą uszkodzić zawartość folderów oraz uczynić Syncthing niesprawnym.",
|
||||
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Niepoprawne ustawienia mogą uszkodzić zawartość folderów oraz sprawić, że Syncthing przestanie działać.",
|
||||
"Incorrect user name or password.": "Nieprawidłowa nazwa użytkownika lub hasło.",
|
||||
"Internally used paths:": "Ścieżki używane wewnętrznie:",
|
||||
"Introduced By": "Wprowadzony przez",
|
||||
@@ -242,7 +242,7 @@
|
||||
"Log in to see paths information.": "Zaloguj się, aby zobaczyć informacje o ścieżkach.",
|
||||
"Log in to see version information.": "Zaloguj się, aby zobaczyć informacje o wersji.",
|
||||
"Log tailing paused. Scroll to the bottom to continue.": "Zatrzymano wypisywanie logów. Przewiń w dół, aby je wznowić.",
|
||||
"Login failed, see Syncthing logs for details.": "Logowanie nie powiodło się. Aby uzyskać szczegółowe informacje, zobacz dziennik zdarzeń programu Syncthing.",
|
||||
"Login failed, see Syncthing logs for details.": "Logowanie nie powiodło się. Sprawdź szczegóły w dzienniku zdarzeń programu.",
|
||||
"Logs": "Dziennik zdarzeń",
|
||||
"Major Upgrade": "Duża aktualizacja",
|
||||
"Mass actions": "Działania masowe",
|
||||
@@ -386,6 +386,7 @@
|
||||
"Staggered File Versioning": "Rozbudowane wersjonowanie plików",
|
||||
"Start Browser": "Uruchom przeglądarkę",
|
||||
"Statistics": "Statystyki",
|
||||
"Stay logged in": "Pozostań zalogowany",
|
||||
"Stopped": "Zatrzymany",
|
||||
"Stores and syncs only encrypted data. Folders on all connected devices need to be set up with the same password or be of type \"{%receiveEncrypted%}\" too.": "Przechowuje i synchronizuje tylko zaszyfrowane dane. Foldery na wszystkich połączonych urządzeniach muszą używać tego samego hasła bądź też być rodzaju \"{{receiveEncrypted}}\".",
|
||||
"Subject:": "Tytuł:",
|
||||
@@ -396,7 +397,7 @@
|
||||
"Sync Protocol Listen Addresses": "Adres nasłuchu protokołu synchronizacji",
|
||||
"Sync Status": "Stan synchronizacji",
|
||||
"Syncing": "Synchronizowanie",
|
||||
"Syncthing device ID for \"{%devicename%}\"": "Identyfikator Syncthing dla urządzenia \"{{devicename}}\"",
|
||||
"Syncthing device ID for \"{%devicename%}\"": "Identyfikator programu Syncthing dla urządzenia \"{{devicename}}\"",
|
||||
"Syncthing has been shut down.": "Syncthing został wyłączony.",
|
||||
"Syncthing includes the following software or portions thereof:": "Syncthing zawiera następujące oprogramowanie lub ich części:",
|
||||
"Syncthing is Free and Open Source Software licensed as MPL v2.0.": "Syncthing to wolne i otwarte oprogramowanie na licencji MPL 2.0.",
|
||||
@@ -406,15 +407,15 @@
|
||||
"Syncthing is restarting.": "Syncthing jest uruchamiany ponownie.",
|
||||
"Syncthing is saving changes.": "Syncthing zapisuje zmiany.",
|
||||
"Syncthing is upgrading.": "Syncthing jest aktualizowany.",
|
||||
"Syncthing now supports automatically reporting crashes to the developers. This feature is enabled by default.": "Syncthing zawiera teraz automatyczne zgłaszanie awarii do autorów. Ta funkcja jest domyślnie włączona.",
|
||||
"Syncthing now supports automatically reporting crashes to the developers. This feature is enabled by default.": "Syncthing obsługuje od teraz automatyczne zgłaszanie awarii do twórców programu. Ta funkcja jest domyślnie włączona.",
|
||||
"Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…": "Syncthing wydaje się być wyłączony lub wystąpił problem z połączeniem internetowym. Próbuję ponownie…",
|
||||
"Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.": "Syncthing wydaje się mieć trudności z przetworzeniem tego zapytania. Odśwież stronę lub uruchom Syncthing ponownie, jeżeli problem nie ustąpi.",
|
||||
"Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.": "Syncthing wydaje się mieć trudności z przetworzeniem tego zapytania. Jeżeli problem nie ustąpi, odśwież stronę lub uruchom Syncthing ponownie.",
|
||||
"TCP LAN": "TCP LAN",
|
||||
"TCP WAN": "TCP WAN",
|
||||
"Take me back": "Powrót",
|
||||
"The GUI address is overridden by startup options. Changes here will not take effect while the override is in place.": "Adres GUI jest nadpisywany przez opcje uruchamiania. Zmiany dokonane tutaj nie będą obowiązywać, dopóki nadpisywanie jest w użyciu.",
|
||||
"The Syncthing Authors": "Twórcy Syncthing",
|
||||
"The Syncthing admin interface is configured to allow remote access without a password.": "Ustawienia interfejsu administracyjnego aplikacji Syncthing zezwalają na zdalny dostęp bez hasła.",
|
||||
"The Syncthing admin interface is configured to allow remote access without a password.": "Ustawienia interfejsu administracyjnego programu Syncthing zezwalają na dostęp zdalny bez hasła.",
|
||||
"The aggregated statistics are publicly available at the URL below.": "Zebrane statystyki są publicznie dostępne pod poniższym adresem.",
|
||||
"The cleanup interval cannot be blank.": "Przedział czasowy czyszczenia nie może być pusty.",
|
||||
"The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.": "Ustawienia zostały zapisane, ale nie są jeszcze aktywne. Syncthing musi zostać uruchomiony ponownie, aby aktywować nowe ustawienia.",
|
||||
@@ -460,7 +461,7 @@
|
||||
"This setting controls the free space required on the home (i.e., index database) disk.": "To ustawienie kontroluje ilość wolnej przestrzeni na dysku domowym (np. do indeksowania bazy danych).",
|
||||
"Time": "Czas",
|
||||
"Time the item was last modified": "Czas ostatniej modyfikacji elementu",
|
||||
"To connect with the Syncthing device named \"{%devicename%}\", add a new remote device on your end with this ID:": "Aby nawiązać połączenie z urządzeniem \"{{devicename}}\", dodaj nowe urządzenie po swojej stronie używając poniższego identyfikatora.",
|
||||
"To connect with the Syncthing device named \"{%devicename%}\", add a new remote device on your end with this ID:": "Aby nawiązać połączenie z urządzeniem \"{{devicename}}\", dodaj nowe urządzenie po swojej stronie używając identyfikatora:",
|
||||
"To permit a rule, have the checkbox checked. To deny a rule, leave it unchecked.": "Aby zezwolić na regułę, zaznacz pole wyboru. Aby zablokować regułę, pozostaw je niezaznaczone.",
|
||||
"Today": "Dzisiaj",
|
||||
"Trash Can": "Kosz",
|
||||
@@ -507,7 +508,7 @@
|
||||
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Uwaga: ta ścieżka to nadkatalog istniejącego folderu \"{{otherFolderLabel}}\" ({{otherFolder}}).",
|
||||
"Warning, this path is a subdirectory of an existing folder \"{%otherFolder%}\".": "Uwaga: ta ścieżka to podkatalog istniejącego folderu \"{{otherFolder}}\".",
|
||||
"Warning, this path is a subdirectory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Uwaga: ten folder to podkatalog istniejącego folderu \"{{otherFolderLabel}}\" ({{otherFolder}}).",
|
||||
"Warning: If you are using an external watcher like {%syncthingInotify%}, you should make sure it is deactivated.": "Uwaga: jeżeli korzystasz z zewnętrznego obserwatora, takiego jak {{syncthingInotify}}, upewnij się, że ta opcja jest wyłączona.",
|
||||
"Warning: If you are using an external watcher like {%syncthingInotify%}, you should make sure it is deactivated.": "Uwaga: jeżeli korzystasz z zewnętrznego obserwatora, np. {{syncthingInotify}}, upewnij się, że to ustawienie jest wyłączone.",
|
||||
"Watch for Changes": "Obserwuj zmiany",
|
||||
"Watching for Changes": "Obserwowanie zmian",
|
||||
"Watching for changes discovers most changes without periodic scanning.": "Obserwowanie wykrywa większość zmian bez potrzeby okresowego skanowania.",
|
||||
|
||||
@@ -38,14 +38,14 @@
|
||||
"Are you sure you want to remove folder {%label%}?": "Tem a certeza que quer remover a pasta {{label}}?",
|
||||
"Are you sure you want to restore {%count%} files?": "Tem a certeza que quer restaurar {{count}} ficheiros?",
|
||||
"Are you sure you want to revert all local changes?": "Tem a certeza que quer reverter todas as alterações locais?",
|
||||
"Are you sure you want to upgrade?": "Tem a certeza que quer actualizar?",
|
||||
"Are you sure you want to upgrade?": "Tem a certeza que quer atualizar?",
|
||||
"Authentication Required": "É necessária autenticação",
|
||||
"Authors": "Autores",
|
||||
"Auto Accept": "Aceitar automaticamente",
|
||||
"Automatic Crash Reporting": "Relatório Automático de Estouro",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "A actualização automática agora oferece a escolha entre versões estáveis e candidatas a lançamento.",
|
||||
"Automatic upgrades": "Actualizações automáticas",
|
||||
"Automatic upgrades are always enabled for candidate releases.": "As actualizações automáticas estão sempre activadas nas versões candidatas a lançamento.",
|
||||
"Automatic Crash Reporting": "Relatório Automático de Falhas",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "A atualização automática agora oferece a escolha entre versões estáveis e candidatas a lançamento.",
|
||||
"Automatic upgrades": "Atualizações automáticas",
|
||||
"Automatic upgrades are always enabled for candidate releases.": "As atualizações automáticas estão sempre ativadas nas versões candidatas a lançamento.",
|
||||
"Automatically create or share folders that this device advertises at the default path.": "Criar ou partilhar, de forma automática e no caminho predefinido, pastas que este dispositivo publicita.",
|
||||
"Available debug logging facilities:": "Recursos de registo de depuração disponíveis:",
|
||||
"Be careful!": "Tenha cuidado!",
|
||||
@@ -70,12 +70,12 @@
|
||||
"Connection Type": "Tipo de ligação",
|
||||
"Connections": "Ligações",
|
||||
"Connections via relays might be rate limited by the relay": "Ligações via retransmissores podem ter a velocidade limitada pelo retransmissor",
|
||||
"Continuously watching for changes is now available within Syncthing. This will detect changes on disk and issue a scan on only the modified paths. The benefits are that changes are propagated quicker and that less full scans are required.": "A vigilância de alterações contínua está agora disponível dentro do Syncthing. Este sistema irá detectar alterações no disco e efectuar uma verificação apenas nas pastas modificadas. Os benefícios são que as alterações são propagadas mais depressa e são necessárias menos verificações completas.",
|
||||
"Continuously watching for changes is now available within Syncthing. This will detect changes on disk and issue a scan on only the modified paths. The benefits are that changes are propagated quicker and that less full scans are required.": "A vigilância de alterações contínua está agora disponível dentro do Syncthing. Este sistema irá detetar alterações no disco e efetuar uma verificação apenas nas pastas modificadas. Os benefícios são que as alterações são propagadas mais depressa e são necessárias menos verificações completas.",
|
||||
"Copied from elsewhere": "Copiado doutro sítio",
|
||||
"Copied from original": "Copiado do original",
|
||||
"Copied!": "Copiado!",
|
||||
"Copy": "Copiar",
|
||||
"Copy failed! Try to select and copy manually.": "A cópia falhou! Tente seleccionar e copiar manualmente.",
|
||||
"Copy failed! Try to select and copy manually.": "A cópia falhou! Tente selecionar e copiar manualmente.",
|
||||
"Currently Shared With Devices": "Dispositivos com os quais está partilhada",
|
||||
"Custom Range": "Intervalo personalizado",
|
||||
"Danger!": "Perigo!",
|
||||
@@ -90,9 +90,9 @@
|
||||
"Delete": "Eliminar",
|
||||
"Delete Unexpected Items": "Eliminar itens inesperados",
|
||||
"Deleted {%file%}": "{{file}} eliminado",
|
||||
"Deselect All": "Retirar todas as selecções",
|
||||
"Deselect devices to stop sharing this folder with.": "Retire a selecção para deixar de partilhar a pasta com esses dispositivos.",
|
||||
"Deselect folders to stop sharing with this device.": "Retire a selecção das pastas para deixar de as partilhar com este dispositivo.",
|
||||
"Deselect All": "Retirar todas as seleções",
|
||||
"Deselect devices to stop sharing this folder with.": "Retire a seleção para deixar de partilhar a pasta com esses dispositivos.",
|
||||
"Deselect folders to stop sharing with this device.": "Retire a seleção das pastas para deixar de as partilhar com este dispositivo.",
|
||||
"Device": "Dispositivo",
|
||||
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "O dispositivo \"{{name}}\" ({{device}} em {{address}}) quer conectar-se. Adiciono este novo dispositivo?",
|
||||
"Device Certificate": "Certificado do dispositivo",
|
||||
@@ -104,12 +104,12 @@
|
||||
"Device rate limits": "Limites de velocidade do dispositivo",
|
||||
"Device that last modified the item": "Último dispositivo a modificar o item",
|
||||
"Devices": "Dispositivos",
|
||||
"Disable Crash Reporting": "Desactivar Relatório de Estouro",
|
||||
"Disabled": "Desactivada",
|
||||
"Disabled periodic scanning and disabled watching for changes": "Desactivada a verificação periódica e desactivada a vigilância de alterações",
|
||||
"Disabled periodic scanning and enabled watching for changes": "Desactivada a verificação periódica e desactivada a vigilância de alterações",
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Desactivada a verificação periódica e falha ao preparar a vigilância de alterações, tentando novamente a cada minuto:",
|
||||
"Disables comparing and syncing file permissions. Useful on systems with nonexistent or custom permissions (e.g. FAT, exFAT, Synology, Android).": "Desactiva a comparação e a sincronização das permissões dos ficheiros. É útil em sistemas onde as permissões não existem ou são personalizadas (ex.: FAT, exFAT, Synology, Android).",
|
||||
"Disable Crash Reporting": "Desativar Relatório de Falhas",
|
||||
"Disabled": "Desativada",
|
||||
"Disabled periodic scanning and disabled watching for changes": "Desativada a verificação periódica e desativada a vigilância de alterações",
|
||||
"Disabled periodic scanning and enabled watching for changes": "Desativada a verificação periódica e ativada a vigilância de alterações",
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Desativada a verificação periódica e falha ao preparar a vigilância de alterações, tentando novamente a cada minuto:",
|
||||
"Disables comparing and syncing file permissions. Useful on systems with nonexistent or custom permissions (e.g. FAT, exFAT, Synology, Android).": "Desativa a comparação e a sincronização das permissões dos ficheiros. É útil em sistemas onde as permissões não existem ou são personalizadas (ex.: FAT, exFAT, Synology, Android).",
|
||||
"Discard": "Descartar",
|
||||
"Disconnected": "Desconectado",
|
||||
"Disconnected (Inactive)": "Desconectado (inactivo)",
|
||||
@@ -122,39 +122,39 @@
|
||||
"Do not add it to the ignore list, so this notification may recur.": "Não adicionar à lista dos ignorados, para que esta notificação volte a aparecer.",
|
||||
"Do not restore": "Não restaurar",
|
||||
"Do not restore all": "Não restaurar nenhum",
|
||||
"Do you want to enable watching for changes for all your folders?": "Quer activar a vigilância de alterações para todas as suas pastas?",
|
||||
"Do you want to enable watching for changes for all your folders?": "Quer ativar a vigilância de alterações para todas as suas pastas?",
|
||||
"Documentation": "Documentação",
|
||||
"Download Rate": "Velocidade de recepção",
|
||||
"Downloaded": "Recebido",
|
||||
"Downloading": "Recebendo",
|
||||
"Downloading": "A Receber",
|
||||
"Edit": "Editar",
|
||||
"Edit Device": "Editar dispositivo",
|
||||
"Edit Device Defaults": "Editar as predefinições do dispositivo",
|
||||
"Edit Folder": "Editar pasta",
|
||||
"Edit Folder Defaults": "Editar as predefinições da pasta",
|
||||
"Editing {%path%}.": "Editando {{path}}.",
|
||||
"Enable Crash Reporting": "Activar Relatório de Estouro",
|
||||
"Enable NAT traversal": "Activar travessia de NAT",
|
||||
"Editing {%path%}.": "A editar {{path}}.",
|
||||
"Enable Crash Reporting": "Ativar Relatório de Falhas",
|
||||
"Enable NAT traversal": "Ativar travessia de NAT",
|
||||
"Enable Relaying": "Permitir retransmissão",
|
||||
"Enabled": "Activada",
|
||||
"Enables sending extended attributes to other devices, and applying incoming extended attributes. May require running with elevated privileges.": "Habilita o envio de atributos estendidos para os outros dispositivos e a aplicação dos atributos estendidos recebidos. Pode exigir que se corra com privilégios elevados.",
|
||||
"Enables sending extended attributes to other devices, but not applying incoming extended attributes. This can have a significant performance impact. Always enabled when \"Sync Extended Attributes\" is enabled.": "Habilita o envio de atributos estendidos para outros dispositivos, mas não a aplicação dos atributos estendidos recebidos. Isto pode ter um impacto de desempenho significativo. Fica sempre habilitado quando \"Sincronizar atributos estendidos\" é habilitado.",
|
||||
"Enables sending ownership information to other devices, and applying incoming ownership information. Typically requires running with elevated privileges.": "Habilita o envio de informação sobre propriedade para os outros dispositivos e a aplicação da informação recebida sobre propriedade. Requer, tipicamente, que se execute com privilégios elevados.",
|
||||
"Enables sending ownership information to other devices, but not applying incoming ownership information. This can have a significant performance impact. Always enabled when \"Sync Ownership\" is enabled.": "Habilita o envio da informação de propriedade para outros dispositivos, mas não a aplicação da informação de propriedade recebida. Pode ter um impacto significativo no desempenho. Fica sempre habilitado quando \"Sincronizar a propriedade\" é habilitada.",
|
||||
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Escreva um número positivo (ex.: \"2.35\") e seleccione uma unidade. Percentagens são relativas ao tamanho total do disco.",
|
||||
"Enter a non-privileged port number (1024 - 65535).": "Escreva um número de porto não-privilegiado (1024-65535).",
|
||||
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Introduza endereços separados por vírgulas (\"tcp://ip:porto\", \"tcp://máquina:porto\") ou \"dynamic\" para descobrir automaticamente os endereços.",
|
||||
"Enabled": "Ativada",
|
||||
"Enables sending extended attributes to other devices, and applying incoming extended attributes. May require running with elevated privileges.": "Permite o envio de atributos estendidos para outros dispositivos, e a aplicação de atributos estendidos recebidos. Pode ser necessário executar com privilégios elevados.",
|
||||
"Enables sending extended attributes to other devices, but not applying incoming extended attributes. This can have a significant performance impact. Always enabled when \"Sync Extended Attributes\" is enabled.": "Permite o envio de atributos estendidos para outros dispositivos, mas não a aplicação dos atributos estendidos recebidos. Isto pode ter um impacto de desempenho significativo. Sempre ativo quando \"Sincronizar atributos estendidos\" está ativado.",
|
||||
"Enables sending ownership information to other devices, and applying incoming ownership information. Typically requires running with elevated privileges.": "Permite o envio de informação sobre propriedade para outros dispositivos, e a aplicação da informação recebida sobre propriedade. Requer, tipicamente, que se execute com privilégios elevados.",
|
||||
"Enables sending ownership information to other devices, but not applying incoming ownership information. This can have a significant performance impact. Always enabled when \"Sync Ownership\" is enabled.": "Permite o envio da informação de propriedade para outros dispositivos, mas não a aplicação da informação de propriedade recebida. Pode ter um impacto significativo no desempenho. Sempre ativo quando \"Sincronizar a propriedade\" está ativado.",
|
||||
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Escreva um número positivo (ex.: \"2.35\") e selecione uma unidade. Percentagens são relativas ao tamanho total do disco.",
|
||||
"Enter a non-privileged port number (1024 - 65535).": "Escreva um número de porta não privilegiado (1024-65535).",
|
||||
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Introduza endereços separados por vírgulas (\"tcp://ip:porta\", \"tcp://máquina:porta\") ou \"dynamic\" para descobrir automaticamente os endereços.",
|
||||
"Enter ignore patterns, one per line.": "Escreva os padrões de exclusão, um por linha.",
|
||||
"Enter up to three octal digits.": "Insira de um a três dígitos em octal.",
|
||||
"Error": "Erro",
|
||||
"Extended Attributes": "Atributos estendidos",
|
||||
"Extended Attributes Filter": "Filtro de atributos extendidos",
|
||||
"External": "Externa",
|
||||
"External File Versioning": "Externa",
|
||||
"External File Versioning": "Gestão de Versões de Ficheiros Externa",
|
||||
"Failed Items": "Itens que falharam",
|
||||
"Failed to load file versions.": "Falhou ao carregar as versões do ficheiro.",
|
||||
"Failed to load ignore patterns.": "Falhou o carregamento dos padrões de exclusão.",
|
||||
"Failed to setup, retrying": "A preparação falhou, tentando novamente",
|
||||
"Failed to load file versions.": "Falha ao carregar as versões do ficheiro.",
|
||||
"Failed to load ignore patterns.": "Falha ao carregar os padrões de exclusão.",
|
||||
"Failed to setup, retrying": "A preparação falhou, a tentar novamente",
|
||||
"Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.": "São esperadas falhas na ligação a servidores IPv6 se não existir conectividade IPv6.",
|
||||
"File Pull Order": "Ordem de obtenção de ficheiros",
|
||||
"File Versioning": "Gestão de versões de ficheiros",
|
||||
@@ -192,8 +192,8 @@
|
||||
"Global State": "Estado global",
|
||||
"Help": "Ajuda",
|
||||
"Hint: only deny-rules detected while the default is deny. Consider adding \"permit any\" as last rule.": "Dica: quando a predefinição é \"negar\", apenas as regras de negação são encontradas. Considere adicionar \"permitir tudo\" como última regra.",
|
||||
"Home page": "Página do projecto",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "Contudo, a sua configuração actual indica que pode não a querer activada. Nós desactivámos automaticamente o relatório de estouro para si.",
|
||||
"Home page": "Inicio",
|
||||
"However, your current settings indicate you might not want it enabled. We have disabled automatic crash reporting for you.": "Contudo, a sua configuração atual indica que pode não a querer ativada. Nós desativámos automaticamente o relatório de falhas para si.",
|
||||
"Identification": "Identificação",
|
||||
"If untrusted, enter encryption password": "Se não for fiável, insira uma senha de encriptação",
|
||||
"If you want to prevent other users on this computer from accessing Syncthing and through it your files, consider setting up authentication.": "Se quiser evitar que outros utilizadores neste computador acedam ao Syncthing e, através dele, aos seus ficheiros, considere configurar a autenticação.",
|
||||
@@ -206,7 +206,7 @@
|
||||
"Ignored at": "Ignorado em",
|
||||
"Included Software": "Software incluído",
|
||||
"Incoming Rate Limit (KiB/s)": "Limite de velocidade de recepção (KiB/s)",
|
||||
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Uma configuração incorrecta pode danificar o conteúdo da pasta e tornar o Syncthing inoperacional.",
|
||||
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Uma configuração incorreta pode danificar o conteúdo da pasta e tornar o Syncthing inoperacional.",
|
||||
"Incorrect user name or password.": "Nome de utilizador ou senha errados.",
|
||||
"Internally used paths:": "Caminhos usados internamente:",
|
||||
"Introduced By": "Introduzido por",
|
||||
@@ -244,7 +244,7 @@
|
||||
"Log tailing paused. Scroll to the bottom to continue.": "O acompanhamento do final do registo está em pausa. Desloque para o final para continuar.",
|
||||
"Login failed, see Syncthing logs for details.": "O início da sessão falhou. Veja os registos do Syncthing para mais detalhes.",
|
||||
"Logs": "Registos",
|
||||
"Major Upgrade": "Actualização importante",
|
||||
"Major Upgrade": "Atualização importante",
|
||||
"Mass actions": "Operações em massa",
|
||||
"Maximum Age": "Idade máxima",
|
||||
"Maximum single entry size": "Tamanho máximo das entradas únicas",
|
||||
@@ -291,8 +291,8 @@
|
||||
"Paused": "Em pausa",
|
||||
"Paused (Unused)": "Em pausa (não usado)",
|
||||
"Pending changes": "Alterações pendentes",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Verificação periódica no intervalo dado e desactivada a vigilância de alterações",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Verificação periódica no intervalo dado e activada a vigilância de alterações",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Verificação periódica no intervalo dado e desativada a vigilância de alterações",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Verificação periódica no intervalo dado e ativada a vigilância de alterações",
|
||||
"Periodic scanning at given interval and failed setting up watching for changes, retrying every 1m:": "Verificação periódica no intervalo dado e falha ao preparar a vigilância de alterações, tentando novamente a cada minuto:",
|
||||
"Permanently add it to the ignore list, suppressing further notifications.": "Adicionar permanentemente à lista de ignorados, inibindo novas notificações.",
|
||||
"Please consult the release notes before performing a major upgrade.": "Consulte as notas de lançamento antes de fazer uma actualização importante.",
|
||||
@@ -337,16 +337,16 @@
|
||||
"Revert": "Reverter",
|
||||
"Revert Local Changes": "Reverter alterações locais",
|
||||
"Save": "Gravar",
|
||||
"Saving changes": "Guardando modificações",
|
||||
"Saving changes": "A guardar modificações",
|
||||
"Scan Time Remaining": "Tempo restante da verificação",
|
||||
"Scanning": "Verificação de alterações",
|
||||
"See external versioning help for supported templated command line parameters.": "Veja a ajuda sobre a gestão de versões externa para ver os modelos suportados de parâmetros para a linha de comandos.",
|
||||
"Select All": "Seleccionar tudo",
|
||||
"Select a version": "Seleccione uma versão",
|
||||
"Select additional devices to share this folder with.": "Seleccione outros dispositivos com os quais também pretende partilhar a pasta.",
|
||||
"Select additional folders to share with this device.": "Seleccione pastas adicionais para partilhar com este dispositivo.",
|
||||
"Select latest version": "Seleccionar a última versão",
|
||||
"Select oldest version": "Seleccionar a versão mais antiga",
|
||||
"Select additional devices to share this folder with.": "Selecione outros dispositivos com os quais também pretende partilhar a pasta.",
|
||||
"Select additional folders to share with this device.": "Selecione pastas adicionais para partilhar com este dispositivo.",
|
||||
"Select latest version": "Selecionar a última versão",
|
||||
"Select oldest version": "Selecionar a versão mais antiga",
|
||||
"Send & Receive": "envia e recebe",
|
||||
"Send Extended Attributes": "Enviar atributos estendidos",
|
||||
"Send Only": "envia apenas",
|
||||
@@ -377,7 +377,7 @@
|
||||
"Smallest First": "Primeiro os menores",
|
||||
"Some discovery methods could not be established for finding other devices or announcing this device:": "Não foi possível estabelecer alguns dos métodos de descoberta para encontrar outros dispositivos ou anunciar este dispositivo:",
|
||||
"Some items could not be restored:": "Não foi possível restaurar alguns dos itens:",
|
||||
"Some listening addresses could not be enabled to accept connections:": "Alguns endereços de escuta não puderam ser activados para aceitar ligações:",
|
||||
"Some listening addresses could not be enabled to accept connections:": "Alguns endereços de escuta não puderam ser ativados para aceitar ligações:",
|
||||
"Source Code": "Código fonte",
|
||||
"Stable releases and release candidates": "Versões estáveis e versões candidatas a lançamento",
|
||||
"Stable releases are delayed by about two weeks. During this time they go through testing as release candidates.": "Versões estáveis são adiadas por cerca de duas semanas. Durante esse período são submetidas a testes sob a forma de versões candidatas a lançamento.",
|
||||
@@ -386,6 +386,7 @@
|
||||
"Staggered File Versioning": "Escalonada",
|
||||
"Start Browser": "Iniciar navegador",
|
||||
"Statistics": "Estatísticas",
|
||||
"Stay logged in": "Continuar conectado",
|
||||
"Stopped": "Parado",
|
||||
"Stores and syncs only encrypted data. Folders on all connected devices need to be set up with the same password or be of type \"{%receiveEncrypted%}\" too.": "Armazena e sincroniza apenas dados encriptados. As pastas em todos os dispositivos conectados têm de ser configuradas com a mesma senha ou ser também do tipo \"{{receiveEncrypted}}\".",
|
||||
"Subject:": "Assunto:",
|
||||
@@ -412,12 +413,12 @@
|
||||
"TCP LAN": "TCP LAN",
|
||||
"TCP WAN": "TCP WAN",
|
||||
"Take me back": "Voltar atrás",
|
||||
"The GUI address is overridden by startup options. Changes here will not take effect while the override is in place.": "O endereço da interface gráfica é substituído pelas opções de arranque. Alterações feitas aqui não terão efeito enquanto a substituição estiver activa.",
|
||||
"The GUI address is overridden by startup options. Changes here will not take effect while the override is in place.": "O endereço da interface gráfica é substituído pelas opções de arranque. Alterações feitas aqui não terão efeito enquanto a substituição estiver ativa.",
|
||||
"The Syncthing Authors": "Os autores do Syncthing",
|
||||
"The Syncthing admin interface is configured to allow remote access without a password.": "A interface de administração do Syncthing está configurada para permitir o acesso remoto sem pedir senha.",
|
||||
"The aggregated statistics are publicly available at the URL below.": "As estatísticas agregadas estão publicamente disponíveis no URL abaixo.",
|
||||
"The cleanup interval cannot be blank.": "O intervalo entre limpezas não pode estar vazio.",
|
||||
"The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.": "A configuração foi gravada mas não activada. O Syncthing tem que reiniciar para activar a nova configuração.",
|
||||
"The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.": "A configuração foi gravada mas não ativada. O Syncthing tem que reiniciar para ativar a nova configuração.",
|
||||
"The device ID cannot be blank.": "O ID do dispositivo não pode estar vazio.",
|
||||
"The device ID to enter here can be found in the \"Actions > Show ID\" dialog on the other device. Spaces and dashes are optional (ignored).": "O ID do dispositivo a colocar aqui pode ser obtido no menu \"Operações > Mostrar ID\" do outro dispositivo. Espaços e hífenes são opcionais (ignorados).",
|
||||
"The encrypted usage report is sent daily. It is used to track common platforms, folder sizes, and app versions. If the reported data set is changed you will be prompted with this dialog again.": "O relatório de utilização cifrado é enviado diariamente. É utilizado para rastrear plataformas comuns, tamanhos de pastas e versões da aplicação. Se o tipo de dados do relatório for alterado, será notificado novamente através desta janela.",
|
||||
@@ -434,7 +435,7 @@
|
||||
"The following text will automatically be inserted into a new message.": "O texto seguinte será inserido automaticamente numa nova mensagem.",
|
||||
"The following unexpected items were found.": "Foram encontrados os seguinte itens inesperados.",
|
||||
"The interval must be a positive number of seconds.": "O intervalo tem que ser um número positivo de segundos.",
|
||||
"The interval, in seconds, for running cleanup in the versions directory. Zero to disable periodic cleaning.": "O intervalo, em segundos, para executar limpezas na pasta das versões. Coloque zero para desactivar a limpeza periódica.",
|
||||
"The interval, in seconds, for running cleanup in the versions directory. Zero to disable periodic cleaning.": "O intervalo, em segundos, para executar limpezas na pasta das versões. Coloque zero para desativar a limpeza periódica.",
|
||||
"The maximum age must be a number and cannot be blank.": "A idade máxima tem que ser um número e não pode estar vazia.",
|
||||
"The maximum time to keep a version (in days, set to 0 to keep versions forever).": "Tempo máximo, em dias, para manter uma versão (use 0 para manter a versão para sempre).",
|
||||
"The number of connections must be a non-negative number.": "O número de ligações tem que ser um número não negativo.",
|
||||
@@ -456,7 +457,7 @@
|
||||
"This Month": "Este mês",
|
||||
"This can easily give hackers access to read and change any files on your computer.": "Isso facilmente dará acesso aos piratas informáticos para lerem e modificarem quaisquer ficheiros no seu computador.",
|
||||
"This device cannot automatically discover other devices or announce its own address to be found by others. Only devices with statically configured addresses can connect.": "Este dispositivo não pode descobrir automaticamente outros dispositivos ou anunciar o seu próprio endereço para que seja encontrado pelos outros. Apenas dispositivos com endereços configurados estaticamente podem estabelecer ligação.",
|
||||
"This is a major version upgrade.": "Esta é uma actualização para uma versão importante.",
|
||||
"This is a major version upgrade.": "Esta é uma atualização para uma versão importante.",
|
||||
"This setting controls the free space required on the home (i.e., index database) disk.": "Este parâmetro controla o espaço livre necessário no disco base (ou seja, o disco da base de dados do índice).",
|
||||
"Time": "Quando",
|
||||
"Time the item was last modified": "Quando o item foi modificado pela última vez",
|
||||
@@ -499,17 +500,17 @@
|
||||
"Versions": "Versões",
|
||||
"Versions Path": "Caminho das versões",
|
||||
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "As versões são eliminadas automaticamente se forem mais antigas do que a idade máxima ou excederem o número máximo de ficheiros permitido num intervalo.",
|
||||
"Waiting to Clean": "Aguardando a limpeza",
|
||||
"Waiting to Scan": "Aguardando a verificação",
|
||||
"Waiting to Sync": "Aguardando a sincronização",
|
||||
"Waiting to Clean": "A aguardar a Limpeza",
|
||||
"Waiting to Scan": "A aguardar a Verificação",
|
||||
"Waiting to Sync": "A aguardar a Sincronização",
|
||||
"Warning": "Aviso",
|
||||
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Aviso: Este caminho é uma pasta mãe duma pasta \"{{otherFolder}}\" já existente.",
|
||||
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Aviso: Este caminho é uma pasta mãe duma pasta \"{{otherFolderLabel}}\" ({{otherFolder}}) já existente.",
|
||||
"Warning, this path is a subdirectory of an existing folder \"{%otherFolder%}\".": "Aviso: Este caminho é uma subpasta da pasta \"{{otherFolder}}\" já existente.",
|
||||
"Warning, this path is a subdirectory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Aviso: Este caminho é uma subpasta da pasta \"{{otherFolderLabel}}\" ({{otherFolder}}) já existente.",
|
||||
"Warning: If you are using an external watcher like {%syncthingInotify%}, you should make sure it is deactivated.": "Aviso: Se estiver a usar um verificador externo, tal como o {{syncthingInotify}}, deve certificar-se que está desactivado.",
|
||||
"Warning: If you are using an external watcher like {%syncthingInotify%}, you should make sure it is deactivated.": "Aviso: Se estiver a usar um verificador externo, tal como o {{syncthingInotify}}, deve certificar-se que está desativado.",
|
||||
"Watch for Changes": "Vigiar alterações",
|
||||
"Watching for Changes": "Vigilância de alterações",
|
||||
"Watching for Changes": "A vigiar Alterações",
|
||||
"Watching for changes discovers most changes without periodic scanning.": "A vigilância de alterações descobre a maior parte das alterações sem a necessidade de fazer uma verificação periódica.",
|
||||
"When adding a new device, keep in mind that this device must be added on the other side too.": "Quando adicionar um novo dispositivo, lembre-se que este dispositivo tem que ser adicionado do outro lado também.",
|
||||
"When adding a new folder, keep in mind that the Folder ID is used to tie folders together between devices. They are case sensitive and must match exactly between all devices.": "Quando adicionar uma nova pasta, lembre-se que o ID da pasta é utilizado para ligar as pastas entre dispositivos. É sensível às diferenças entre maiúsculas e minúsculas e tem que ter uma correspondência perfeita entre todos os dispositivos.",
|
||||
|
||||
@@ -4,92 +4,119 @@
|
||||
"A new major version may not be compatible with previous versions.": "Este posibil ca o nouă versiune majoră să nu fie compatibilă cu versiunile anterioare.",
|
||||
"API Key": "Cheie API",
|
||||
"About": "Despre",
|
||||
"Action": "Acționează",
|
||||
"Action": "Acțiune",
|
||||
"Actions": "Acțiuni",
|
||||
"Active filter rules": "Reguli de filtrare active",
|
||||
"Add": "Adaugă",
|
||||
"Add Device": "Adaugă Dispozitiv",
|
||||
"Add Folder": "Adaugă Mapă",
|
||||
"Add Remote Device": "Adaugă dispozitiv la distanță",
|
||||
"Add devices from the introducer to our device list, for mutually shared folders.": "Adăugați dispozitive de la introductor la lista dispozitivelor noastre, pentru folderele partajate reciproc.",
|
||||
"Add new folder?": "Adauga o mapă nouă?",
|
||||
"Additionally the full rescan interval will be increased (times 60, i.e. new default of 1h). You can also configure it manually for every folder later after choosing No.": "În plus, intervalul complet de rescanare va fi mărit (de 60 de ori, adică noul implict de 1 oră). Puteți, de asemenea, să o configurați manual pentru fiecare dosar mai târziu după alegerea nr.",
|
||||
"Add devices from the introducer to our device list, for mutually shared folders.": "Adăugați dispozitive de la introductor la lista dispozitivelor noastre, pentru mapele partajate reciproc.",
|
||||
"Add filter entry": "Adaugă regulă de filtrare",
|
||||
"Add ignore patterns": "Adaugă modele de ignorat",
|
||||
"Add new folder?": "Adaugă o mapă nouă?",
|
||||
"Additionally the full rescan interval will be increased (times 60, i.e. new default of 1h). You can also configure it manually for every folder later after choosing No.": "În plus, intervalul complet de rescanare va fi mărit (de 60 de ori, adică noul implict de 1 oră). Puteți, de asemenea, să o configurați manual pentru fiecare mapă mai târziu după alegerea nr.",
|
||||
"Address": "Adresă",
|
||||
"Addresses": "Adrese",
|
||||
"Advanced": "Avansat",
|
||||
"Advanced Configuration": "Configurari avansate",
|
||||
"All Data": "Toate Datele",
|
||||
"All folders shared with this device must be protected by a password, such that all sent data is unreadable without the given password.": "Toate folderele partajate cu acest dispozitiv trebuie protejate printr-o parolă, astfel încât toate datele trimise să nu poată fi citite fără parola dată.",
|
||||
"All Time": "Toți timpii",
|
||||
"All folders shared with this device must be protected by a password, such that all sent data is unreadable without the given password.": "Toate mapele partajate cu acest dispozitiv trebuie protejate printr-o parolă, astfel încât toate datele trimise să nu poată fi citite fără parola dată.",
|
||||
"Allow Anonymous Usage Reporting?": "Permiteţi raportarea anonimă de folosire a aplicaţiei?",
|
||||
"Allowed Networks": "Rețele permise",
|
||||
"Alphabetic": "Alfabetic",
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder. If the path to the application contains spaces, it should be quoted.": "O comandă externă gestionează versiunea. Trebuie să elimine fișierul din folderul partajat. Dacă calea către aplicație conține spații, ar trebui să fie pusă între ghilimele.",
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder. If the path to the application contains spaces, it should be quoted.": "O comandă externă gestionează versiunea. Trebuie să elimine fișierul din mapa partajat. Dacă calea către aplicație conține spații, ar trebui să fie pusă între ghilimele.",
|
||||
"Anonymous Usage Reporting": "Raport Anonim despre Folosirea Aplicației",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "Formatul raportului de utilizare anonim s-a schimbat. Doriți să vă mutați în noul format?",
|
||||
"Applied to LAN": "Aplicat pentru LAN",
|
||||
"Apply": "Aplică",
|
||||
"Are you sure you want to override all remote changes?": "Sunteți sigur că doriți să suprascrieți toate schimbările remote?",
|
||||
"Are you sure you want to permanently delete all these files?": "Sigur doriți să ștergeți definitiv toate aceste fișiere?",
|
||||
"Are you sure you want to remove device {%name%}?": "Sigur doriți să eliminați dispozitivul {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Sigur doriți să eliminați dosarul {{label}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Sigur doriți să eliminați mapa {{label}}?",
|
||||
"Are you sure you want to restore {%count%} files?": "Sigur doriți să restaurați {{count}} fișiere?",
|
||||
"Are you sure you want to upgrade?": "Sigur doriți să faceți upgrade?",
|
||||
"Are you sure you want to revert all local changes?": "Sunteți sigur că doriți să anulați toate schimbările locale?",
|
||||
"Are you sure you want to upgrade?": "Sigur doriți să actualizați?",
|
||||
"Authentication Required": "Este necesară autentificarea",
|
||||
"Authors": "Autori",
|
||||
"Auto Accept": "Acceptare automată",
|
||||
"Automatic Crash Reporting": "Raportarea automată a problemelor întâmpinate",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Actualizarea automată oferă acum posibilitatea de a alege între versiuni stabile și candidați la versiuni.",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Actualizarea automată oferă acum posibilitatea de a alege între lansări stabile și candidați la lansare.",
|
||||
"Automatic upgrades": "Actualizare automată",
|
||||
"Automatic upgrades are always enabled for candidate releases.": "Automatic upgrades are always enabled for candidate releases.",
|
||||
"Automatically create or share folders that this device advertises at the default path.": "Automatically create or share folders that this device advertises at the default path.",
|
||||
"Available debug logging facilities:": "Available debug logging facilities:",
|
||||
"Automatic upgrades are always enabled for candidate releases.": "Actualizările automate sunt mereu active petru candidați la lansare.",
|
||||
"Automatically create or share folders that this device advertises at the default path.": "Crează sau partajează automat mapele anunțate de acest dispozitiv la calea implicită.",
|
||||
"Available debug logging facilities:": "Facilități disponibile pentru registrul de depanare:",
|
||||
"Be careful!": "Fii atent!",
|
||||
"Body:": "Corp:",
|
||||
"Bugs": "Bug-uri",
|
||||
"Cancel": "Renunță",
|
||||
"Changelog": "Noutăți",
|
||||
"Clean out after": "Clean out after",
|
||||
"Cleaning Versions": "Cleaning Versions",
|
||||
"Cleanup Interval": "Cleanup Interval",
|
||||
"Clean out after": "Curăță după",
|
||||
"Cleaning Versions": "Curățare versiuni",
|
||||
"Cleanup Interval": "Interval de curățare",
|
||||
"Click to see full identification string and QR code.": "Click to see full identification string and QR code.",
|
||||
"Close": "Închide",
|
||||
"Command": "Comandă",
|
||||
"Comment, when used at the start of a line": "Comentariu, când este folosit la începutul unei linii",
|
||||
"Compression": "Compresie",
|
||||
"Configured": "Configured",
|
||||
"Connected (Unused)": "Connected (Unused)",
|
||||
"Configuration Directory": "Director de configurare",
|
||||
"Configuration File": "Fișier de configurare",
|
||||
"Configured": "Configurat",
|
||||
"Connected (Unused)": "Conectat (Nefolosit)",
|
||||
"Connection Error": "Eroare de conexiune",
|
||||
"Connection Type": "Connection Type",
|
||||
"Connections": "Connections",
|
||||
"Connection Management": "Managementul conexiunilor",
|
||||
"Connection Type": "Tip de conexiune",
|
||||
"Connections": "Conexiuni",
|
||||
"Connections via relays might be rate limited by the relay": "Conexiunile prin relee pot fi limitate de viteza releului",
|
||||
"Continuously watching for changes is now available within Syncthing. This will detect changes on disk and issue a scan on only the modified paths. The benefits are that changes are propagated quicker and that less full scans are required.": "Continuously watching for changes is now available within Syncthing. This will detect changes on disk and issue a scan on only the modified paths. The benefits are that changes are propagated quicker and that less full scans are required.",
|
||||
"Copied from elsewhere": "Copiat din altă parte",
|
||||
"Copied from original": "Copiat din original",
|
||||
"Currently Shared With Devices": "Currently Shared With Devices",
|
||||
"Danger!": "Danger!",
|
||||
"Debugging Facilities": "Debugging Facilities",
|
||||
"Default Configuration": "Default Configuration",
|
||||
"Default Device": "Default Device",
|
||||
"Default Folder": "Default Folder",
|
||||
"Defaults": "Defaults",
|
||||
"Copied!": "Copiat!",
|
||||
"Copy": "Copie",
|
||||
"Copy failed! Try to select and copy manually.": "Copierea a eșuat!Încearcă să selectezi și să copii manual.",
|
||||
"Currently Shared With Devices": "La Moment Partajat cu Dispozitive",
|
||||
"Custom Range": "Interval Personalizat",
|
||||
"Danger!": "Pericol!",
|
||||
"Database Location": "Locația Bazei de Date",
|
||||
"Debugging Facilities": "Facilități de Depanare",
|
||||
"Default": "Implicit",
|
||||
"Default Configuration": "Configurare implicită",
|
||||
"Default Device": "Dispozitiv implicit",
|
||||
"Default Folder": "Mapă implicită",
|
||||
"Defaults": "Valori implicite",
|
||||
"Delete": "Şterge",
|
||||
"Delete Unexpected Items": "Delete Unexpected Items",
|
||||
"Deselect All": "Deselect All",
|
||||
"Deselect devices to stop sharing this folder with.": "Deselect devices to stop sharing this folder with.",
|
||||
"Deselect folders to stop sharing with this device.": "Deselect folders to stop sharing with this device.",
|
||||
"Device": "Device",
|
||||
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "Device \"{{name}}\" ({{device}} at {{address}}) wants to connect. Add new device?",
|
||||
"Delete Unexpected Items": "Șterge itemii neașteptați",
|
||||
"Deleted {%file%}": "{{file}} șters",
|
||||
"Deselect All": "Deselectează totul",
|
||||
"Deselect devices to stop sharing this folder with.": "Deselecteați dispozitivele cu care doriți să încetați partajarea mapei date.",
|
||||
"Deselect folders to stop sharing with this device.": "Deselectați mapele pentru a întrerupe partajarea lor cu acest dispozitiv.",
|
||||
"Device": "Dispozitiv",
|
||||
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "Dispozitivul \"{{name}}\" ({{device}} la {{address}}) vrea să se conecteze. Adaugă un dispozitiv nou?",
|
||||
"Device Certificate": "Certificatul dispozitivului",
|
||||
"Device ID": "ID Dispozitiv",
|
||||
"Device Identification": "Identificare Dispozitiv",
|
||||
"Device Name": "Nume Dispozitiv",
|
||||
"Device is untrusted, enter encryption password": "Device is untrusted, enter encryption password",
|
||||
"Device rate limits": "Device rate limits",
|
||||
"Device that last modified the item": "Device that last modified the item",
|
||||
"Device Status": "Statut Dispozitiv",
|
||||
"Device is untrusted, enter encryption password": "Dispozitivul nu este de încredere, introduceți parola de criptare.",
|
||||
"Device rate limits": "Rata de limită a dispozitivului",
|
||||
"Device that last modified the item": "Ultimul dispozitiv ce a modificat itemul",
|
||||
"Devices": "Dispozitiv",
|
||||
"Disable Crash Reporting": "Disable Crash Reporting",
|
||||
"Disabled": "Disabled",
|
||||
"Disabled periodic scanning and disabled watching for changes": "Disabled periodic scanning and disabled watching for changes",
|
||||
"Disabled periodic scanning and enabled watching for changes": "Disabled periodic scanning and enabled watching for changes",
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:",
|
||||
"Disables comparing and syncing file permissions. Useful on systems with nonexistent or custom permissions (e.g. FAT, exFAT, Synology, Android).": "Disables comparing and syncing file permissions. Useful on systems with nonexistent or custom permissions (e.g. FAT, exFAT, Synology, Android).",
|
||||
"Discard": "Discard",
|
||||
"Disabled": "Deactivat",
|
||||
"Disabled periodic scanning and disabled watching for changes": "Scanarea periodică și urmărirea schimbărilor dezactivate",
|
||||
"Disabled periodic scanning and enabled watching for changes": "Scanare periodică dezactivată și urmărirea schimbărilor activată",
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Scanare periodică dezactivată și setarea urmăririi schimbărilor eșuată, se va reîncerca la fiecare 1 minut:",
|
||||
"Disables comparing and syncing file permissions. Useful on systems with nonexistent or custom permissions (e.g. FAT, exFAT, Synology, Android).": "Dezactivează compararea și sincronizarea permisiunilor fișierului. Util pentru sisteme ce nu permit permisiuni personalizate (ex: FAT, exFAT, Synology, Android).",
|
||||
"Discard": "Renunță",
|
||||
"Disconnected": "Deconectat",
|
||||
"Disconnected (Unused)": "Disconnected (Unused)",
|
||||
"Discovered": "Discovered",
|
||||
"Discovery": "Discovery",
|
||||
"Discovery Failures": "Discovery Failures",
|
||||
"Dismiss": "Dismiss",
|
||||
"Disconnected (Inactive)": "Deconectat (inactiv)",
|
||||
"Disconnected (Unused)": "Deconectat (neutilizat)",
|
||||
"Discovered": "Descoperit",
|
||||
"Discovery": "Descoperire",
|
||||
"Discovery Failures": "Eșec de descoperire",
|
||||
"Discovery Status": "Statut de descoperire",
|
||||
"Dismiss": "Înlătură",
|
||||
"Do not add it to the ignore list, so this notification may recur.": "Do not add it to the ignore list, so this notification may recur.",
|
||||
"Do not restore": "Do not restore",
|
||||
"Do not restore all": "Do not restore all",
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
"Add filter entry": "Добавить правило фильтрации",
|
||||
"Add ignore patterns": "Добавить шаблоны для игнорирования",
|
||||
"Add new folder?": "Добавить новую папку?",
|
||||
"Additionally the full rescan interval will be increased (times 60, i.e. new default of 1h). You can also configure it manually for every folder later after choosing No.": "Также будет увеличен интервал полного сканирования (в 60 раз, т. е. новое значение — 1 час). Вы можете вручную настроить интервал для каждой папки, выбрав \"Нет\".",
|
||||
"Additionally the full rescan interval will be increased (times 60, i.e. new default of 1h). You can also configure it manually for every folder later after choosing No.": "Также будет увеличен интервал полного сканирования (в 60 раз, т. е. новое значение — 1 час). Вы можете вручную настроить интервал для каждой папки, выбрав «Нет».",
|
||||
"Address": "Адрес",
|
||||
"Addresses": "Адреса",
|
||||
"Advanced": "Дополнительно",
|
||||
@@ -38,7 +38,7 @@
|
||||
"Are you sure you want to remove folder {%label%}?": "Уверены, что хотите удалить папку {{label}}?",
|
||||
"Are you sure you want to restore {%count%} files?": "Уверены, что хотите восстановить {{count}} файлов?",
|
||||
"Are you sure you want to revert all local changes?": "Уверены, что хотите отменить все локальные изменения?",
|
||||
"Are you sure you want to upgrade?": "Уверены, что хотите обновить?",
|
||||
"Are you sure you want to upgrade?": "Уверены, что хотите обновить версию приложения?",
|
||||
"Authentication Required": "Требуется Аутентификация",
|
||||
"Authors": "Авторы",
|
||||
"Auto Accept": "Автопринятие",
|
||||
@@ -81,14 +81,14 @@
|
||||
"Danger!": "Опасно!",
|
||||
"Database Location": "Расположение базы данных",
|
||||
"Debugging Facilities": "Средства отладки",
|
||||
"Default": "По-умолчанию",
|
||||
"Default": "По умолчанию",
|
||||
"Default Configuration": "Настройки по умолчанию",
|
||||
"Default Device": "Стандартное Устройство",
|
||||
"Default Device": "Стандартное устройство",
|
||||
"Default Folder": "Стандартная папка",
|
||||
"Default Ignore Patterns": "Шаблон игнорирования по умолчанию",
|
||||
"Defaults": "Стандартные параметры",
|
||||
"Delete": "Удалить",
|
||||
"Delete Unexpected Items": "Удалить неожиданные элементы",
|
||||
"Delete Unexpected Items": "Удалить неожиданные объекты",
|
||||
"Deleted {%file%}": "{{file}} удалён",
|
||||
"Deselect All": "Снять выделение",
|
||||
"Deselect devices to stop sharing this folder with.": "Отмените выбор устройств, чтобы прекратить совместное использование этой папки.",
|
||||
@@ -99,6 +99,7 @@
|
||||
"Device ID": "ID устройства",
|
||||
"Device Identification": "Идентификация устройства",
|
||||
"Device Name": "Имя устройства",
|
||||
"Device Status": "Статус устройства",
|
||||
"Device is untrusted, enter encryption password": "Устройство ненадёжно, укажите пароль шифрования",
|
||||
"Device rate limits": "Ограничения скорости для устройства",
|
||||
"Device that last modified the item": "Устройство, последним изменившее объект",
|
||||
@@ -107,7 +108,7 @@
|
||||
"Disabled": "Отключено",
|
||||
"Disabled periodic scanning and disabled watching for changes": "Периодическое сканирование и отслеживание изменений отключено",
|
||||
"Disabled periodic scanning and enabled watching for changes": "Периодическое сканирование и отслеживание изменений отключено",
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Периодическое сканирование отключено, не удалось включить отслеживание изменений, повторная попытка каждую минуту.",
|
||||
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Периодическое сканирование отключено, не удалось включить отслеживание изменений, повторная попытка каждую минуту:",
|
||||
"Disables comparing and syncing file permissions. Useful on systems with nonexistent or custom permissions (e.g. FAT, exFAT, Synology, Android).": "Отключает сравнение и синхронизацию разрешений файлов. Полезно для систем с несуществующими или настраиваемыми разрешениями (например, FAT, exFAT, Synology, Android).",
|
||||
"Discard": "Отменить",
|
||||
"Disconnected": "Нет соединения",
|
||||
@@ -133,8 +134,8 @@
|
||||
"Edit Folder Defaults": "Изменить умолчания папки",
|
||||
"Editing {%path%}.": "Правка {{path}}.",
|
||||
"Enable Crash Reporting": "Включить отчёты о сбоях",
|
||||
"Enable NAT traversal": "Включить NAT traversal",
|
||||
"Enable Relaying": "Включить релеи",
|
||||
"Enable NAT traversal": "Использовать обход NAT",
|
||||
"Enable Relaying": "Использовать ретрансляторы",
|
||||
"Enabled": "Включено",
|
||||
"Enables sending extended attributes to other devices, and applying incoming extended attributes. May require running with elevated privileges.": "Включает отправку расширенных атрибутов на другие устройства и применение расширенных атрибутов локально. Может потребовать запуска с повышенными правами.",
|
||||
"Enables sending extended attributes to other devices, but not applying incoming extended attributes. This can have a significant performance impact. Always enabled when \"Sync Extended Attributes\" is enabled.": "Включает отправку расширенных атрибутов на другие устройства, но не применение расширенных атрибутов с других устройств. Это может значительно повлиять на производительность. Всегда активно, если включено «Синхронизировать расширенные атрибуты».",
|
||||
@@ -150,15 +151,15 @@
|
||||
"Extended Attributes Filter": "Фильтр расширенных атрибутов",
|
||||
"External": "Внешний",
|
||||
"External File Versioning": "Внешний контроль версий файлов",
|
||||
"Failed Items": "Сбои",
|
||||
"Failed Items": "Сбойные объекты",
|
||||
"Failed to load file versions.": "Не удалось загрузить версии файлов.",
|
||||
"Failed to load ignore patterns.": "Не удалось загрузить шаблоны игнорирования.",
|
||||
"Failed to setup, retrying": "Не удалось настроить, пробуем ещё",
|
||||
"Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.": "Если нет IPv6-соединений, при подключении к IPv6-серверам произойдёт ошибка.",
|
||||
"File Pull Order": "Порядок получения файлов",
|
||||
"File Versioning": "Управление версиями",
|
||||
"Files are moved to .stversions directory when replaced or deleted by Syncthing.": "Когда Syncthing изменяет или удаляет файлы, они помещаются в папку .stversions",
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Когда Syncthing изменяет или удаляет файлы, их версии с отметками времени помещаются в папку .stversions",
|
||||
"Files are moved to .stversions directory when replaced or deleted by Syncthing.": "Когда Syncthing изменяет или удаляет файлы, они помещаются в папку .stversions.",
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Когда Syncthing изменяет или удаляет файлы, их версии с отметками времени помещаются в папку .stversions.",
|
||||
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Файлы защищены от изменений сделанных на других устройствах, но изменения сделанные на этом устройстве будут отправлены всему кластеру.",
|
||||
"Files are synchronized from the cluster, but any changes made locally will not be sent to other devices.": "Файлы синхронизируются из группы, но изменения, сделанные на этом устройстве, не будут отправлены на другие устройства группы.",
|
||||
"Filesystem Watcher Errors": "Ошибки отслеживания файловой системы",
|
||||
@@ -168,6 +169,7 @@
|
||||
"Folder ID": "ID папки",
|
||||
"Folder Label": "Ярлык папки",
|
||||
"Folder Path": "Путь к папке",
|
||||
"Folder Status": "Статус папки",
|
||||
"Folder Type": "Тип папки",
|
||||
"Folder type \"{%receiveEncrypted%}\" can only be set when adding a new folder.": "Тип папки «{{receiveEncrypted}}» может быть указан только при создании новой папки.",
|
||||
"Folder type \"{%receiveEncrypted%}\" cannot be changed after adding the folder. You need to remove the folder, delete or decrypt the data on disk, and add the folder again.": "Тип папки «{{receiveEncrypted}}» не может быть изменён после добавления. Вам необходимо убрать папку, удалить или дешифровать данные на диске, а затем снова добавить папку.",
|
||||
@@ -226,8 +228,8 @@
|
||||
"Listener Failures": "Ошибки прослушивателя",
|
||||
"Listener Status": "Статус прослушивателя",
|
||||
"Listeners": "Прослушиватель",
|
||||
"Loading data...": "Загрузка данных...",
|
||||
"Loading...": "Загрузка...",
|
||||
"Loading data...": "Загрузка данных…",
|
||||
"Loading...": "Загрузка…",
|
||||
"Local Additions": "Локальные дополнения",
|
||||
"Local Discovery": "Локальное обнаружение",
|
||||
"Local State": "Локальное состояние",
|
||||
@@ -240,7 +242,7 @@
|
||||
"Log in to see paths information.": "Войдите, чтобы увидеть информацию о путях.",
|
||||
"Log in to see version information.": "Войдите, чтобы просмотреть информацию о версии.",
|
||||
"Log tailing paused. Scroll to the bottom to continue.": "Вывод журнала приостановлен. Прокрутите вниз, чтобы продолжить.",
|
||||
"Login failed, see Syncthing logs for details.": "Не удалось войти в систему. Посмотреть подробности можно в журнале Syncthing",
|
||||
"Login failed, see Syncthing logs for details.": "Не удалось войти в систему. Посмотреть подробности можно в журнале Syncthing.",
|
||||
"Logs": "Журналы",
|
||||
"Major Upgrade": "Обновление основной версии",
|
||||
"Mass actions": "Массовые действия",
|
||||
@@ -262,10 +264,10 @@
|
||||
"Newest First": "Сначала новые",
|
||||
"No": "Нет",
|
||||
"No File Versioning": "Без управления версиями файлов",
|
||||
"No files will be deleted as a result of this operation.": "В результате этой операции никакие файлы не будут удалены",
|
||||
"No files will be deleted as a result of this operation.": "В результате этой операции никакие файлы не будут удалены.",
|
||||
"No rules set": "Правила не заданы",
|
||||
"No upgrades": "Нет обновлений",
|
||||
"Not shared": "Не зашаренный",
|
||||
"Not shared": "Нет общего доступа",
|
||||
"Notice": "Внимание",
|
||||
"Number of Connections": "Количество подключений",
|
||||
"OK": "ОК",
|
||||
@@ -291,10 +293,10 @@
|
||||
"Pending changes": "Несохранённые изменения",
|
||||
"Periodic scanning at given interval and disabled watching for changes": "Периодическое сканирование с заданным интервалом, отслеживание изменений отключено",
|
||||
"Periodic scanning at given interval and enabled watching for changes": "Периодическое сканирование с заданным интервалом и включено отслеживание изменений",
|
||||
"Periodic scanning at given interval and failed setting up watching for changes, retrying every 1m:": "Периодическое сканирование с заданным интервалом, неудачная настройка отслеживания изменений, повторная попытка каждую минуту.",
|
||||
"Periodic scanning at given interval and failed setting up watching for changes, retrying every 1m:": "Периодическое сканирование с заданным интервалом, неудачная настройка отслеживания изменений, повторная попытка каждую минуту:",
|
||||
"Permanently add it to the ignore list, suppressing further notifications.": "Добавление в список игнорирования навсегда с подавлением будущих уведомлений.",
|
||||
"Please consult the release notes before performing a major upgrade.": "Перед проведением обновления основной версии ознакомьтесь, пожалуйста, с замечаниями к версии",
|
||||
"Please set a GUI Authentication User and Password in the Settings dialog.": "Установите имя пользователя и пароль для интерфейса в настройках",
|
||||
"Please consult the release notes before performing a major upgrade.": "Перед проведением обновления основной версии ознакомьтесь, пожалуйста, с замечаниями к версии.",
|
||||
"Please set a GUI Authentication User and Password in the Settings dialog.": "Установите имя пользователя и пароль для интерфейса в настройках.",
|
||||
"Please wait": "Пожалуйста, подождите",
|
||||
"Prefix indicating that the file can be deleted if preventing directory removal": "Префикс, указывающий что файл может быть удалён, если он мешает удалить папку",
|
||||
"Prefix indicating that the pattern should be matched without case sensitivity": "Префикс, указывающий что шаблон должен сопоставляться без учёта регистра",
|
||||
@@ -338,7 +340,7 @@
|
||||
"Saving changes": "Изменения сохраняются",
|
||||
"Scan Time Remaining": "Оставшееся время сканирования",
|
||||
"Scanning": "Сканирование",
|
||||
"See external versioning help for supported templated command line parameters.": "Поддерживаемые шаблонные параметры командной строки см. в документации сторонней программы контроля версий",
|
||||
"See external versioning help for supported templated command line parameters.": "Поддерживаемые шаблонные параметры командной строки см. в документации сторонней программы контроля версий.",
|
||||
"Select All": "Выбрать все",
|
||||
"Select a version": "Выберите версию",
|
||||
"Select additional devices to share this folder with.": "Выберите дополнительные устройства, для которых будет доступна эта папка.",
|
||||
@@ -384,6 +386,7 @@
|
||||
"Staggered File Versioning": "Ступенчатое управление версиями файлов",
|
||||
"Start Browser": "Запускать браузер",
|
||||
"Statistics": "Статистика",
|
||||
"Stay logged in": "Оставаться в системе",
|
||||
"Stopped": "Остановлено",
|
||||
"Stores and syncs only encrypted data. Folders on all connected devices need to be set up with the same password or be of type \"{%receiveEncrypted%}\" too.": "Хранит и синхронизирует только зашифрованные данные. Папки на всех подключённых устройствах должны быть настроены под один и тот же пароль или иметь тип «{{receiveEncrypted}}».",
|
||||
"Subject:": "Субьект:",
|
||||
@@ -405,7 +408,7 @@
|
||||
"Syncthing is saving changes.": "Синхронизация это сохранение изменений.",
|
||||
"Syncthing is upgrading.": "Обновление Syncthing.",
|
||||
"Syncthing now supports automatically reporting crashes to the developers. This feature is enabled by default.": "Syncthing теперь поддерживает автоматическую отправку отчетов о сбоях разработчикам. Эта функция включена по умолчанию.",
|
||||
"Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…": "Кажется, Syncthing не запущен или есть проблемы с подключением к Интернету. Переподключаюсь...",
|
||||
"Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…": "Кажется, Syncthing не запущен или есть проблемы с подключением к Интернету. Переподключаюсь…",
|
||||
"Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.": "Syncthing столкнулся с проблемой при обработке Вашего запроса. Пожалуйста, обновите страницу или перезапустите Syncthing если проблема повторится.",
|
||||
"TCP LAN": "TCP LAN",
|
||||
"TCP WAN": "TCP WAN",
|
||||
@@ -425,24 +428,24 @@
|
||||
"The folder content on other devices will be overwritten to become identical with this device. Files not present here will be deleted on other devices.": "Содержание папки на других устройствах будет перезаписано и станет идентично этому устройству. Файлы, отсутствующие здесь, будут удалены на других устройствах.",
|
||||
"The folder content on this device will be overwritten to become identical with other devices. Files newly added here will be deleted.": "Содержание папки на этом устройстве будет перезаписано и станет идентично другим устройствам. Новые файлы на этом устройстве будут удалены.",
|
||||
"The folder path cannot be blank.": "Путь к папке не должен быть пустым.",
|
||||
"The following intervals are used: for the first hour a version is kept every 30 seconds, for the first day a version is kept every hour, for the first 30 days a version is kept every day, until the maximum age a version is kept every week.": "Используются следующие интервалы: в первый час версия меняется каждые 30 секунд, в первый день - каждый час, первые 30 дней - каждый день, после, до максимального срока - каждую неделю.",
|
||||
"The following items could not be synchronized.": "Невозможно синхронизировать следующие объекты",
|
||||
"The following items were changed locally.": "Следующие объекты были изменены локально",
|
||||
"The following intervals are used: for the first hour a version is kept every 30 seconds, for the first day a version is kept every hour, for the first 30 days a version is kept every day, until the maximum age a version is kept every week.": "Используются следующие интервалы: в первый час версия меняется каждые 30 секунд, в первый день — каждый час, первые 30 дней — каждый день, после, до максимального срока — каждую неделю.",
|
||||
"The following items could not be synchronized.": "Невозможно синхронизировать следующие объекты.",
|
||||
"The following items were changed locally.": "Следующие объекты были изменены локально.",
|
||||
"The following methods are used to discover other devices on the network and announce this device to be found by others:": "Для обнаружения других устройств в сети и анонсирования этого устройства используются следующие методы:",
|
||||
"The following text will automatically be inserted into a new message.": "Следующий текст будет автоматически вставлен в новое сообщение.",
|
||||
"The following unexpected items were found.": "Были найдены следующие объекты.",
|
||||
"The interval must be a positive number of seconds.": "Интервал секунд должен быть положительным.",
|
||||
"The interval, in seconds, for running cleanup in the versions directory. Zero to disable periodic cleaning.": "Интервал в секундах для запуска очистки в каталоге версий. Ноль, чтобы отключить периодическую очистку.",
|
||||
"The maximum age must be a number and cannot be blank.": "Максимальный срок должен быть числом и не может быть пустым.",
|
||||
"The maximum time to keep a version (in days, set to 0 to keep versions forever).": "Максимальный срок хранения версии (в днях, 0 значит вечное хранение).",
|
||||
"The maximum time to keep a version (in days, set to 0 to keep versions forever).": "Максимальный срок хранения версии в днях (0 — бесконечно).",
|
||||
"The number of connections must be a non-negative number.": "Количество соединений должно быть неотрицательным.",
|
||||
"The number of days must be a number and cannot be blank.": "Количество дней должно быть числом и не может быть пустым.",
|
||||
"The number of days to keep files in the trash can. Zero means forever.": "Количество дней хранения файлов в корзине. Ноль значит навсегда.",
|
||||
"The number of days to keep files in the trash can. Zero means forever.": "Количество дней хранения файлов в корзине (0 — бесконечно).",
|
||||
"The number of old versions to keep, per file.": "Количество хранимых версий файла.",
|
||||
"The number of versions must be a number and cannot be blank.": "Количество версий должно быть числом и не может быть пустым.",
|
||||
"The path cannot be blank.": "Путь не может быть пустым.",
|
||||
"The rate limit is applied to the accumulated traffic of all connections to this device.": "Ограничение скорости применяется к накопленному трафику всех подключений к этому устройству.",
|
||||
"The rate limit must be a non-negative number (0: no limit)": "Скорость должна быть неотрицательным числом (0: нет ограничения)",
|
||||
"The rate limit must be a non-negative number (0: no limit)": "Скорость должна быть неотрицательным числом (0 — без ограничений)",
|
||||
"The remote device has not accepted sharing this folder.": "Удаленное устройство не разрешило общий доступ к этой папке.",
|
||||
"The remote device has paused this folder.": "Удаленное устройство приостановило эту папку.",
|
||||
"The rescan interval must be a non-negative number of seconds.": "Интервал пересканирования должен быть неотрицательным количеством секунд.",
|
||||
@@ -468,8 +471,8 @@
|
||||
"Unavailable": "Недоступно",
|
||||
"Unavailable/Disabled by administrator or maintainer": "Недоступно или отключено администратором",
|
||||
"Undecided (will prompt)": "Не определено (запрашивать каждый раз)",
|
||||
"Unexpected Items": "Неожиданные элементы",
|
||||
"Unexpected items have been found in this folder.": "В папке найдены неожиданные элементы.",
|
||||
"Unexpected Items": "Неожиданные объекты",
|
||||
"Unexpected items have been found in this folder.": "В папке найдены неожиданные объекты.",
|
||||
"Unignore": "Не игнорировать",
|
||||
"Unknown": "Неизвестно",
|
||||
"Unshared": "Не общедоступно",
|
||||
@@ -489,10 +492,10 @@
|
||||
"User": "Пользователь",
|
||||
"User Home": "Папка пользователя",
|
||||
"Username/Password has not been set for the GUI authentication. Please consider setting it up.": "Имя пользователя/пароль не был установлен для GUI-аутентификации. Настройте его.",
|
||||
"Using a QUIC connection over LAN": "Использование QUIC-соединения по локальной сети",
|
||||
"Using a QUIC connection over WAN": "Использование QUIC-соединения по всеобщей сети",
|
||||
"Using a direct TCP connection over LAN": "Использование прямого TCP-соединения через LAN",
|
||||
"Using a direct TCP connection over WAN": "Использование прямого TCP-соединения через WAN",
|
||||
"Using a QUIC connection over LAN": "Использовать QUIC-соединения в LAN",
|
||||
"Using a QUIC connection over WAN": "Использовать QUIC-соединения в WAN",
|
||||
"Using a direct TCP connection over LAN": "Использовать прямые TCP-соединения в LAN",
|
||||
"Using a direct TCP connection over WAN": "Использовать прямые TCP-соединения в WAN",
|
||||
"Version": "Версия",
|
||||
"Versions": "Версии",
|
||||
"Versions Path": "Путь к версиям",
|
||||
@@ -533,7 +536,7 @@
|
||||
"files": "файлов",
|
||||
"folder": "папка",
|
||||
"full documentation": "полная документация",
|
||||
"items": "элементы",
|
||||
"items": "объекты",
|
||||
"modified": "изменено",
|
||||
"permit": "разрешить",
|
||||
"seconds": "сек.",
|
||||
|
||||
@@ -386,6 +386,7 @@
|
||||
"Staggered File Versioning": "Filversionshantering i intervall",
|
||||
"Start Browser": "Starta webbläsaren",
|
||||
"Statistics": "Statistik",
|
||||
"Stay logged in": "Förbli inloggad",
|
||||
"Stopped": "Stoppad",
|
||||
"Stores and syncs only encrypted data. Folders on all connected devices need to be set up with the same password or be of type \"{%receiveEncrypted%}\" too.": "Lagrar och synkroniserar endast krypterade data. Mappar på alla anslutna enheter måste ställas in med samma lösenord eller också vara av typen \"{{receiveEncrypted}}\".",
|
||||
"Subject:": "Ämne:",
|
||||
|
||||
@@ -386,6 +386,7 @@
|
||||
"Staggered File Versioning": "Aşamalı Dosya Sürümlendirme",
|
||||
"Start Browser": "Tarayıcıyı başlat",
|
||||
"Statistics": "İstatistikler",
|
||||
"Stay logged in": "Oturum açık kal",
|
||||
"Stopped": "Durduruldu",
|
||||
"Stores and syncs only encrypted data. Folders on all connected devices need to be set up with the same password or be of type \"{%receiveEncrypted%}\" too.": "Yalnızca şifrelenmiş verileri depolar ve eşitler. Tüm bağlı cihazlardaki klasörlerin de aynı parola ile ayarlanması veya \"{{receiveEncrypted}}\" türünde olması gerekir.",
|
||||
"Subject:": "Konu:",
|
||||
|
||||
@@ -386,6 +386,7 @@
|
||||
"Staggered File Versioning": "阶段版本控制",
|
||||
"Start Browser": "启动浏览器",
|
||||
"Statistics": "统计",
|
||||
"Stay logged in": "保持登录",
|
||||
"Stopped": "已停止",
|
||||
"Stores and syncs only encrypted data. Folders on all connected devices need to be set up with the same password or be of type \"{%receiveEncrypted%}\" too.": "仅存储和同步加密的数据。所有连接的设备上的文件夹也需要使用相同的密码设置,或者也必须设置为“ {{receiveEncrypted}}”类型。",
|
||||
"Subject:": "主题:",
|
||||
|
||||
@@ -177,6 +177,7 @@
|
||||
"Ignore": "忽略",
|
||||
"Ignore Patterns": "忽略樣式",
|
||||
"Ignore Permissions": "忽略權限",
|
||||
"Ignore patterns can only be added after the folder is created. If checked, an input field to enter ignore patterns will be presented after saving.": "忽略模式只能在建立資料夾之後新增。如果選取這個項目,會在儲存後顯示一個設定忽略模式的欄位。",
|
||||
"Ignored Devices": "已忽略的裝置",
|
||||
"Ignored Folders": "已忽略的資料夾",
|
||||
"Ignored at": "忽略時間",
|
||||
|
||||
@@ -1 +1 @@
|
||||
var langPrettyprint = {"ar":"Arabic","bg":"Bulgarian","ca":"Catalan","ca@valencia":"Valencian","cs":"Czech","da":"Danish","de":"German","en":"English","en-GB":"English (United Kingdom)","es":"Spanish","eu":"Basque","fr":"French","fy":"Frisian","hu":"Hungarian","id":"Indonesian","it":"Italian","ja":"Japanese","ko-KR":"Korean","lt":"Lithuanian","nl":"Dutch","pl":"Polish","pt-BR":"Portuguese (Brazil)","pt-PT":"Portuguese (Portugal)","ro-RO":"Romanian","ru":"Russian","sk":"Slovak","sl":"Slovenian","sv":"Swedish","tr":"Turkish","uk":"Ukrainian","zh-CN":"Chinese (Simplified)","zh-HK":"Chinese (Traditional, Hong Kong)","zh-TW":"Chinese (Traditional)"}
|
||||
var langPrettyprint = {"ar":"Arabic","bg":"Bulgarian","ca":"Catalan","ca@valencia":"Valencian","cs":"Czech","da":"Danish","de":"German","el":"Greek","en":"English","en-GB":"English (United Kingdom)","es":"Spanish","eu":"Basque","fr":"French","fy":"Frisian","hu":"Hungarian","id":"Indonesian","it":"Italian","ja":"Japanese","ko-KR":"Korean","lt":"Lithuanian","nl":"Dutch","pl":"Polish","pt-BR":"Portuguese (Brazil)","pt-PT":"Portuguese (Portugal)","ro-RO":"Romanian","ru":"Russian","sk":"Slovak","sl":"Slovenian","sv":"Swedish","tr":"Turkish","uk":"Ukrainian","zh-CN":"Chinese (Simplified)","zh-HK":"Chinese (Traditional, Hong Kong)","zh-TW":"Chinese (Traditional)"}
|
||||
|
||||
@@ -1 +1 @@
|
||||
var validLangs = ["ar","bg","ca","ca@valencia","cs","da","de","en","en-GB","es","eu","fr","fy","hu","id","it","ja","ko-KR","lt","nl","pl","pt-BR","pt-PT","ro-RO","ru","sk","sl","sv","tr","uk","zh-CN","zh-HK","zh-TW"]
|
||||
var validLangs = ["ar","bg","ca","ca@valencia","cs","da","de","el","en","en-GB","es","eu","fr","fy","hu","id","it","ja","ko-KR","lt","nl","pl","pt-BR","pt-PT","ro-RO","ru","sk","sl","sv","tr","uk","zh-CN","zh-HK","zh-TW"]
|
||||
|
||||
@@ -359,6 +359,12 @@
|
||||
<input id="password" class="form-control" type="password" name="password" ng-model="login.password" ng-trim="false" autocomplete="current-password" />
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="login.stayLoggedIn" > <span translate>Stay logged in</span>
|
||||
</label>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-9 login-form-messages">
|
||||
<p ng-if="login.errors.badLogin" class="text-danger" translate>
|
||||
@@ -398,9 +404,9 @@
|
||||
<span class="hidden-xs">{{folderStatusText(folder)}}</span>
|
||||
<span ng-switch-when="scanning" ng-if="scanPercentage(folder.id) != undefined">({{scanPercentage(folder.id) | percent}})</span>
|
||||
<span ng-switch-when="syncing">({{syncPercentage(folder.id) | percent}}, {{model[folder.id].needBytes | binary}}B)</span>
|
||||
<span class="inline-icon">
|
||||
<span class="inline-icon">
|
||||
<span class="visible-xs fa fa-fw {{folderStatusIcon(folder)}}" aria-label="{{folderStatusText(folder)}}"></span>
|
||||
</span>
|
||||
</span>
|
||||
</div>
|
||||
<div class="panel-title-text">
|
||||
<span tooltip data-original-title="{{folder.label.length != 0 ? folder.id : ''}}">{{folder.label.length != 0 ? folder.label : folder.id}}</span>
|
||||
@@ -555,7 +561,7 @@
|
||||
<span ng-switch-when="trashcan" translate>Trash Can</span>
|
||||
<span ng-switch-when="simple" translate>Simple</span>
|
||||
<span ng-switch-when="staggered" translate>Staggered</span>
|
||||
<span ng-switch-when="external" tooltip data-original-title="<span class='text-monospace'>{{folder.versioning.params.command}}</span>" translate>External</span>
|
||||
<span ng-switch-when="external" tooltip data-original-title="{{folder.versioning.params.command}}" translate>External</span>
|
||||
</span>
|
||||
<span ng-if="folder.versioning.type != 'external'">
|
||||
<span ng-if="(folder.versioning.type == 'trashcan' || folder.versioning.type == 'simple')" tooltip data-original-title="{{'Clean out after' | translate}}">
|
||||
@@ -579,12 +585,16 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<th><span class="fas fa-fw fa-share-alt"></span> <span translate>Shared With</span></th>
|
||||
<td class="text-right no-overflow-ellipse word-break-all">
|
||||
<td class="text-right no-overflow-ellipse overflow-break-word">
|
||||
<span ng-repeat="device in otherDevices(folder.devices)">
|
||||
<span ng-switch="completion[device.deviceID][folder.id].remoteState">
|
||||
<span ng-switch-when="notSharing" data-original-title="{{'The remote device has not accepted sharing this folder.' | translate}}" tooltip>{{deviceName(devices[device.deviceID])}}<sup>1</sup><span ng-if="!$last">,</span></span>
|
||||
<span ng-switch-when="paused" data-original-title="{{'The remote device has paused this folder.' | translate}}" tooltip>{{deviceName(devices[device.deviceID])}}<sup>2</sup><span ng-if="!$last">,</span></span>
|
||||
<span ng-switch-default>{{deviceName(devices[device.deviceID])}}<span ng-if="!$last">,</span></span>
|
||||
<span ng-if="folder.type !== 'receiveencrypted' && device.encryptionPassword" class="text-nowrap">
|
||||
<span class="fa fa-lock"></span> <!-- Avoid stray space...
|
||||
--></span><!-- Avoid stray space...
|
||||
--><span ng-switch="completion[device.deviceID][folder.id].remoteState"><!-- Avoid stray space...
|
||||
--><span ng-switch-when="notSharing" data-original-title="{{'The remote device has not accepted sharing this folder.' | translate}}" tooltip>{{deviceName(devices[device.deviceID])}}<sup>1</sup></span><!-- Avoid stray space...
|
||||
--><span ng-switch-when="paused" data-original-title="{{'The remote device has paused this folder.' | translate}}" tooltip>{{deviceName(devices[device.deviceID])}}<sup>2</sup></span><!-- Avoid stray space...
|
||||
--><span ng-switch-default><a href="" ng-click="editDeviceExisting(devices[device.deviceID])">{{deviceName(devices[device.deviceID])}}</a></span><!-- Avoid stray space...
|
||||
--><span ng-if="!$last">,</span>
|
||||
</span>
|
||||
</span>
|
||||
</td>
|
||||
@@ -910,7 +920,7 @@
|
||||
</tr>
|
||||
<tr ng-if="deviceCfg.introducedBy">
|
||||
<th><span class="far fa-fw fa-handshake-o"></span> <span translate>Introduced By</span></th>
|
||||
<td class="text-right">{{ deviceName(devices[deviceCfg.introducedBy]) || deviceCfg.introducedBy.substring(0, 5) }}</td>
|
||||
<td class="text-right">{{ deviceName(devices[deviceCfg.introducedBy]) || deviceShortID(deviceCfg.introducedBy) }}</td>
|
||||
</tr>
|
||||
<tr ng-if="deviceCfg.autoAcceptFolders">
|
||||
<th><span class="fa fa-fw fa-level-down"></span> <span translate>Auto Accept</span></th>
|
||||
@@ -934,12 +944,16 @@
|
||||
</tr>
|
||||
<tr ng-if="deviceFolders(deviceCfg).length > 0">
|
||||
<th><span class="fas fa-fw fa-folder"></span> <span translate>Folders</span></th>
|
||||
<td class="text-right no-overflow-ellipse word-break-all">
|
||||
<td class="text-right no-overflow-ellipse overflow-break-word">
|
||||
<span ng-repeat="folderID in deviceFolders(deviceCfg)">
|
||||
<span ng-switch="completion[deviceCfg.deviceID][folderID].remoteState">
|
||||
<span ng-switch-when="notSharing" data-original-title="{{'The remote device has not accepted sharing this folder.' | translate}}" tooltip>{{folderLabel(folderID)}}<sup>1</sup><span ng-if="!$last">,</span></span>
|
||||
<span ng-switch-when="paused" data-original-title="{{'The remote device has paused this folder.' | translate}}" tooltip>{{folderLabel(folderID)}}<sup>2</sup><span ng-if="!$last">,</span></span>
|
||||
<span ng-switch-default>{{folderLabel(folderID)}}<span ng-if="!$last">,</span></span>
|
||||
<span ng-if="folderIsSharedEncrypted(folderID, deviceCfg.deviceID)" class="text-nowrap">
|
||||
<span class="fa fa-lock"></span> <!-- Avoid stray space...
|
||||
--></span><!-- Avoid stray space...
|
||||
--><span ng-switch="completion[deviceCfg.deviceID][folderID].remoteState"><!-- Avoid stray space...
|
||||
--><span ng-switch-when="notSharing" data-original-title="{{'The remote device has not accepted sharing this folder.' | translate}}" tooltip>{{folderLabel(folderID)}}<sup>1</sup></span><!-- Avoid stray space...
|
||||
--><span ng-switch-when="paused" data-original-title="{{'The remote device has paused this folder.' | translate}}" tooltip>{{folderLabel(folderID)}}<sup>2</sup></span><!-- Avoid stray space...
|
||||
--><span ng-switch-default>{{folderLabel(folderID)}}</span><!-- Avoid stray space...
|
||||
--><span ng-if="!$last">,</span>
|
||||
</span>
|
||||
</span>
|
||||
</td>
|
||||
|
||||
@@ -18,6 +18,9 @@ var syncthing = angular.module('syncthing', [
|
||||
var urlbase = 'rest';
|
||||
var authUrlbase = urlbase + '/noauth/auth';
|
||||
|
||||
// keep consistent with ShortIDStringLength in lib/protocol/deviceid.go
|
||||
var shortIDStringLength = 7;
|
||||
|
||||
syncthing.config(function ($httpProvider, $translateProvider, LocaleServiceProvider) {
|
||||
// language and localisation
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@
|
||||
<h4 class="text-center" translate>The Syncthing Authors</h4>
|
||||
<div class="row">
|
||||
<div class="col-md-12" id="contributor-list">
|
||||
Jakob Borg, Audrius Butkevicius, Jesse Lucas, Simon Frei, Tomasz Wilczyński, Alexander Graf, Alexandre Viau, Anderson Mesquita, André Colomb, Antony Male, Ben Schulz, Caleb Callaway, Daniel Harte, Eric P, Evgeny Kuznetsov, Lars K.W. Gohlke, Lode Hoste, Michael Ploujnikov, Nate Morrison, Philippe Schommers, Ryan Sullivan, Sergey Mishin, Stefan Tatschner, Wulf Weich, bt90, greatroar, Aaron Bieber, Adam Piggott, Adel Qalieh, Alan Pope, Alberto Donato, Aleksey Vasenev, Alessandro G., Alex Lindeman, Alex Xu, Alexander Seiler, Alexandre Alves, Aman Gupta, Anatoli Babenia, Andreas Sommer, Andrew Dunham, Andrew Meyer, Andrew Rabert, Andrey D, Anjan Momi, Anthony Goeckner, Antoine Lamielle, Anur, Aranjedeath, Arkadiusz Tymiński, Aroun, Arthur Axel fREW Schmidt, Artur Zubilewicz, Aurélien Rainone, BAHADIR YILMAZ, Bart De Vries, Ben Curthoys, Ben Shepherd, Ben Sidhom, Benedikt Heine, Benedikt Morbach, Benjamin Nater, Benno Fünfstück, Benny Ng, Boqin Qin, Boris Rybalkin, Brandon Philips, Brendan Long, Brian R. Becker, Carsten Hagemann, Catfriend1, Cathryne Linenweaver, Cedric Staniewski, Chih-Hsuan Yen, Choongkyu, Chris Howie, Chris Joel, Chris Tonkinson, Christian Kujau, Christian Prescott, Colin Kennedy, Cromefire_, Cyprien Devillez, Dale Visser, Dan, Daniel Barczyk, Daniel Bergmann, Daniel Martí, Darshil Chanpura, David Rimmer, DeflateAwning, Denis A., Dennis Wilson, DerRockWolf, Devon G. Redekopp, Dimitri Papadopoulos Orfanos, Dmitry Saveliev, Domenic Horner, Dominik Heidler, Elias Jarlebring, Elliot Huffman, Emil Hessman, Emil Lundberg, Eng Zer Jun, Eric Lesiuta, Erik Meitner, Evan Spensley, Federico Castagnini, Felix, Felix Ableitner, Felix Lampe, Felix Unterpaintner, Francois-Xavier Gsell, Frank Isemann, Gahl Saraf, Gilli Sigurdsson, Gleb Sinyavskiy, Graham Miln, Greg, Han Boetes, HansK-p, Harrison Jones, Heiko Zuerker, Hugo Locurcio, Iain Barnett, Ian Johnson, Ikko Ashimine, Ilya Brin, Iskander Sharipov, Jaakko Hannikainen, Jacek Szafarkiewicz, Jack Croft, Jacob, Jake Peterson, James O'Beirne, James Patterson, Jaroslav Lichtblau, Jaroslav Malec, Jauder Ho, Jaya Chithra, Jaya Kumar, Jeffery To, Jens Diemer, Jerry Jacobs, Jochen Voss, Johan Andersson, Johan Vromans, John Rinehart, Jonas Thelemann, Jonathan, Jonathan Cross, Jonta, Jose Manuel Delicado, Jörg Thalheim, Jędrzej Kula, K.B.Dharun Krishna, Kalle Laine, Karol Różycki, Kebin Liu, Keith Harrison, Keith Turner, Kelong Cong, Ken'ichi Kamada, Kevin Allen, Kevin Bushiri, Kevin White, Jr., Kurt Fitzner, LSmithx2, Lars Lehtonen, Laurent Arnoud, Laurent Etiemble, Leo Arias, Liu Siyuan, Lord Landon Agahnim, Lukas Lihotzki, Majed Abdulaziz, Marc Laporte, Marc Pujol, Marcin Dziadus, Marcus Legendre, Mario Majila, Mark Pulford, Martchus, Martin Polehla, Mateusz Naściszewski, Mateusz Ż, Matic Potočnik, Matt Burke, Matt Robenolt, Matteo Ruina, Maurizio Tomasi, Max, Max Schulze, MaximAL, Maxime Thirouin, Maximilian, MichaIng, Michael Jephcote, Michael Rienstra, Michael Tilli, Migelo, Mike Boone, MikeLund, MikolajTwarog, Mingxuan Lin, Naveen, Nicholas Rishel, Nick Busey, Nico Stapelbroek, Nicolas Braud-Santoni, Nicolas Perraut, Niels Peter Roest, Nils Jakobi, NinoM4ster, Nitroretro, NoLooseEnds, Oliver Freyermuth, Otiel, Oyebanji Jacob Mayowa, Pablo, Pascal Jungblut, Paul Brit, Pawel Palenica, Paweł Rozlach, Peter Badida, Peter Dave Hello, Peter Hoeg, Peter Marquardt, Phani Rithvij, Phil Davis, Phill Luby, Pier Paolo Ramon, Piotr Bejda, Pramodh KP, Quentin Hibon, Rahmi Pruitt, Richard Hartmann, Robert Carosi, Roberto Santalla, Robin Schoonover, Roman Zaynetdinov, Ross Smith II, Ruslan Yevdokymov, Ryan Qian, Sacheendra Talluri, Scott Klupfel, Sertonix, Shaarad Dalvi, Simon Mwepu, Sly_tom_cat, Stefan Kuntz, Steven Eckhoff, Suhas Gundimeda, Taylor Khan, Thomas Hipp, Tim Abell, Tim Howes, Tobias Klauser, Tobias Nygren, Tobias Tom, Tom Jakubowski, Tommy Thorn, Tully Robinson, Tyler Brazier, Tyler Kropp, Unrud, Veeti Paananen, Victor Buinsky, Vik, Vil Brekin, Vladimir Rusinov, Will Rouesnel, William A. Kennington III, Xavier O., Yannic A., andresvia, andyleap, boomsquared, chenrui, chucic, cjc7373, cui fliter, d-volution, derekriemer, desbma, digital, entity0xfe, georgespatton, ghjklw, guangwu, gudvinr, ignacy123, janost, jaseg, jelle van der Waa, jtagcat, klemens, luzpaz, marco-m, mclang, mv1005, orangekame3, otbutz, overkill, perewa, red_led, rubenbe, sec65, vapatel2, villekalliomaki, wangguoliang, wouter bolsterlee, xarx00, xjtdy888, 佛跳墙, 落心
|
||||
Jakob Borg, Audrius Butkevicius, Jesse Lucas, Simon Frei, Tomasz Wilczyński, Alexander Graf, Alexandre Viau, Anderson Mesquita, André Colomb, Antony Male, Ben Schulz, Caleb Callaway, Daniel Harte, Eric P, Evgeny Kuznetsov, Lars K.W. Gohlke, Lode Hoste, Michael Ploujnikov, Nate Morrison, Philippe Schommers, Ryan Sullivan, Sergey Mishin, Stefan Tatschner, Wulf Weich, bt90, greatroar, Aaron Bieber, Adam Piggott, Adel Qalieh, Alan Pope, Alberto Donato, Aleksey Vasenev, Alessandro G., Alex Lindeman, Alex Xu, Alexander Seiler, Alexandre Alves, Aman Gupta, Anatoli Babenia, Andreas Sommer, Andrew Dunham, Andrew Meyer, Andrew Rabert, Andrey D, Anjan Momi, Anthony Goeckner, Antoine Lamielle, Anur, Aranjedeath, Arkadiusz Tymiński, Aroun, Arthur Axel fREW Schmidt, Artur Zubilewicz, Aurélien Rainone, BAHADIR YILMAZ, Bart De Vries, Beat Reichenbach, Ben Curthoys, Ben Shepherd, Ben Sidhom, Benedikt Heine, Benedikt Morbach, Benjamin Nater, Benno Fünfstück, Benny Ng, Boqin Qin, Boris Rybalkin, Brandon Philips, Brendan Long, Brian R. Becker, Carsten Hagemann, Catfriend1, Cathryne Linenweaver, Cedric Staniewski, Chih-Hsuan Yen, Choongkyu, Chris Howie, Chris Joel, Chris Tonkinson, Christian Kujau, Christian Prescott, Colin Kennedy, Cromefire_, Cyprien Devillez, Dale Visser, Dan, Daniel Barczyk, Daniel Bergmann, Daniel Martí, Daniel Padrta, Darshil Chanpura, David Rimmer, DeflateAwning, Denis A., Dennis Wilson, DerRockWolf, Devon G. Redekopp, Dimitri Papadopoulos Orfanos, Dmitry Saveliev, Domenic Horner, Dominik Heidler, Elias Jarlebring, Elliot Huffman, Emil Hessman, Emil Lundberg, Eng Zer Jun, Eric Lesiuta, Erik Meitner, Evan Spensley, Federico Castagnini, Felix, Felix Ableitner, Felix Lampe, Felix Unterpaintner, Francois-Xavier Gsell, Frank Isemann, Gahl Saraf, Gilli Sigurdsson, Gleb Sinyavskiy, Graham Miln, Greg, Han Boetes, HansK-p, Harrison Jones, Heiko Zuerker, Hugo Locurcio, Iain Barnett, Ian Johnson, Ikko Ashimine, Ilya Brin, Iskander Sharipov, Jaakko Hannikainen, Jacek Szafarkiewicz, Jack Croft, Jacob, Jake Peterson, James O'Beirne, James Patterson, Jaroslav Lichtblau, Jaroslav Malec, Jaspitta, Jauder Ho, Jaya Chithra, Jaya Kumar, Jeffery To, Jens Diemer, Jerry Jacobs, Jochen Voss, Johan Andersson, Johan Vromans, John Rinehart, Jonas Thelemann, Jonathan, Jonathan Cross, Jonta, Jose Manuel Delicado, Julian Lehrhuber, Jörg Thalheim, Jędrzej Kula, K.B.Dharun Krishna, Kalle Laine, Karol Różycki, Kebin Liu, Keith Harrison, Keith Turner, Kelong Cong, Ken'ichi Kamada, Kevin Allen, Kevin Bushiri, Kevin White, Jr., Kurt Fitzner, LSmithx2, Lars Lehtonen, Laurent Arnoud, Laurent Etiemble, Leo Arias, Liu Siyuan, Lord Landon Agahnim, Lukas Lihotzki, Luke Hamburg, Majed Abdulaziz, Marc Laporte, Marc Pujol, Marcin Dziadus, Marcus Legendre, Mario Majila, Mark Pulford, Martchus, Martin Polehla, Mateusz Naściszewski, Mateusz Ż, Matic Potočnik, Matt Burke, Matt Robenolt, Matteo Ruina, Maurizio Tomasi, Max, Max Schulze, MaximAL, Maxime Thirouin, Maximilian, MichaIng, Michael Jephcote, Michael Rienstra, Michael Tilli, Migelo, Mike Boone, MikeLund, MikolajTwarog, Mingxuan Lin, Naveen, Nicholas Rishel, Nick Busey, Nico Stapelbroek, Nicolas Braud-Santoni, Nicolas Perraut, Niels Peter Roest, Nils Jakobi, NinoM4ster, Nitroretro, NoLooseEnds, Oliver Freyermuth, Otiel, Oyebanji Jacob Mayowa, Pablo, Pascal Jungblut, Paul Brit, Pawel Palenica, Paweł Rozlach, Peter Badida, Peter Dave Hello, Peter Hoeg, Peter Marquardt, Phani Rithvij, Phil Davis, Phill Luby, Pier Paolo Ramon, Piotr Bejda, Pramodh KP, Quentin Hibon, Rahmi Pruitt, Richard Hartmann, Robert Carosi, Roberto Santalla, Robin Schoonover, Roman Zaynetdinov, Ross Smith II, Ruslan Yevdokymov, Ryan Qian, Sacheendra Talluri, Scott Klupfel, Sertonix, Shaarad Dalvi, Simon Mwepu, Sly_tom_cat, Stefan Kuntz, Steven Eckhoff, Suhas Gundimeda, Sven Bachmann, Taylor Khan, Thomas, Thomas Hipp, Tim Abell, Tim Howes, Tim Nordenfur, Tobias Klauser, Tobias Nygren, Tobias Tom, Tom Jakubowski, Tommy Thorn, Tully Robinson, Tyler Brazier, Tyler Kropp, Unrud, Veeti Paananen, Victor Buinsky, Vik, Vil Brekin, Vladimir Rusinov, Will Rouesnel, William A. Kennington III, Xavier O., Yannic A., andresvia, andyleap, boomsquared, chenrui, chucic, cjc7373, cui fliter, d-volution, derekriemer, desbma, diemade, digital, entity0xfe, georgespatton, ghjklw, guangwu, gudvinr, ignacy123, janost, jaseg, jelle van der Waa, jtagcat, klemens, kylosus, luzpaz, marco-m, mclang, mv1005, nf, orangekame3, otbutz, overkill, perewa, red_led, rubenbe, sec65, vapatel2, villekalliomaki, wangguoliang, wouter bolsterlee, xarx00, xjtdy888, 佛跳墙, 落心
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -103,6 +103,7 @@ angular.module('syncthing.core')
|
||||
$http.post(authUrlbase + '/password', {
|
||||
username: $scope.login.username,
|
||||
password: $scope.login.password,
|
||||
stayLoggedIn: $scope.login.stayLoggedIn,
|
||||
}).then(function () {
|
||||
location.reload();
|
||||
}).catch(function (response) {
|
||||
@@ -1039,18 +1040,29 @@ angular.module('syncthing.core')
|
||||
// Do the same thing in case we only have zero byte files to sync.
|
||||
return 95;
|
||||
}
|
||||
var pct = 100 * $scope.model[folder].inSyncBytes / $scope.model[folder].globalBytes;
|
||||
return Math.floor(pct);
|
||||
return progressIntegerPercentage($scope.model[folder].inSyncBytes, $scope.model[folder].globalBytes);
|
||||
};
|
||||
|
||||
$scope.scanPercentage = function (folder) {
|
||||
if (!$scope.scanProgress[folder]) {
|
||||
return undefined;
|
||||
}
|
||||
var pct = 100 * $scope.scanProgress[folder].current / $scope.scanProgress[folder].total;
|
||||
return Math.floor(pct);
|
||||
return progressIntegerPercentage($scope.scanProgress[folder].current, $scope.scanProgress[folder].total);
|
||||
};
|
||||
|
||||
function progressIntegerPercentage(current, total) {
|
||||
// Even after whatever is being tracked (e.g. hashed or synced
|
||||
// bytes) is completed, there's likely some more work to be done to
|
||||
// fully finish the process (db updates, ...). Users apparently
|
||||
// don't like seeing 100%, so give them 99% to indicate "about to be
|
||||
// finished".
|
||||
if (current === total) {
|
||||
return 99;
|
||||
}
|
||||
var pct = 100 * current / total;
|
||||
return Math.floor(pct);
|
||||
}
|
||||
|
||||
$scope.scanRate = function (folder) {
|
||||
if (!$scope.scanProgress[folder]) {
|
||||
return 0;
|
||||
@@ -1449,7 +1461,7 @@ angular.module('syncthing.core')
|
||||
|
||||
$scope.friendlyNameFromShort = function (shortID) {
|
||||
var matches = Object.keys($scope.devices).filter(function (id) {
|
||||
return id.substr(0, 7) === shortID;
|
||||
return id.substr(0, shortIDStringLength) === shortID;
|
||||
});
|
||||
if (matches.length !== 1) {
|
||||
return shortID;
|
||||
@@ -1462,7 +1474,7 @@ angular.module('syncthing.core')
|
||||
if (match) {
|
||||
return $scope.deviceName(match);
|
||||
}
|
||||
return deviceID.substr(0, 6);
|
||||
return deviceID.substr(0, shortIDStringLength);
|
||||
};
|
||||
|
||||
$scope.deviceName = function (deviceCfg) {
|
||||
@@ -1479,7 +1491,7 @@ angular.module('syncthing.core')
|
||||
if (typeof deviceID === 'undefined') {
|
||||
return "";
|
||||
}
|
||||
return deviceID.substr(0, 6);
|
||||
return deviceID.substr(0, shortIDStringLength);
|
||||
};
|
||||
|
||||
$scope.thisDeviceName = function () {
|
||||
@@ -1490,7 +1502,7 @@ angular.module('syncthing.core')
|
||||
if (device.name) {
|
||||
return device.name;
|
||||
}
|
||||
return device.deviceID.substr(0, 6);
|
||||
return device.deviceID.substr(0, shortIDStringLength);
|
||||
};
|
||||
|
||||
$scope.showDeviceIdentification = function (deviceCfg) {
|
||||
@@ -2650,6 +2662,15 @@ angular.module('syncthing.core')
|
||||
+ '&device=' + encodeURIComponent(deviceID));
|
||||
};
|
||||
|
||||
$scope.folderIsSharedEncrypted = function (folderID, deviceID) {
|
||||
var folderCfg = $scope.folders[folderID];
|
||||
if (!folderCfg || folderCfg.type === 'receiveencrypted') return false;
|
||||
|
||||
return folderCfg.devices.some(function (device) {
|
||||
return device.deviceID === deviceID && device.encryptionPassword !== '';
|
||||
});
|
||||
};
|
||||
|
||||
$scope.folderHasUnacceptedDevices = function (folderCfg) {
|
||||
for (var deviceID in $scope.completion) {
|
||||
if (deviceID in $scope.devices
|
||||
@@ -3591,7 +3612,7 @@ angular.module('syncthing.core')
|
||||
return n.match !== "";
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
// The showModal and hideModal functions are a bandaid for a Bootstrap
|
||||
// bug (see https://github.com/twbs/bootstrap/issues/3902) that causes
|
||||
// multiple consecutively shown or hidden modals to overlap which leads
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
<modal id="restoreVersions" status="default" icon="fas fa-undo" heading="{{'Restore Versions' | translate}} ({{folderLabel(restoreVersions.folder)}})" large="yes" closeable="yes">
|
||||
<div class="modal-body">
|
||||
<!--
|
||||
Inform the user about loading data even before the tree is initialised
|
||||
to avoid confusion where nothing is displayed on the screen for a while.
|
||||
Ref: https://forum.syncthing.net/t/reversed-date-in-search-filter/21369/3
|
||||
-->
|
||||
<div ng-if="!restoreVersions.versions" translate>Loading data...</div>
|
||||
<div ng-if="restoreVersions.versions && !restoreVersions.errors">
|
||||
<div id="restoreTree-container">
|
||||
<table id="restoreTree">
|
||||
|
||||
1
lib/api/.gitignore
vendored
1
lib/api/.gitignore
vendored
@@ -1 +0,0 @@
|
||||
/testdata/config/csrftokens.txt
|
||||
@@ -91,6 +91,7 @@ type service struct {
|
||||
startupErr error
|
||||
listenerAddr net.Addr
|
||||
exitChan chan *svcutil.FatalErr
|
||||
miscDB *db.NamespacedKV
|
||||
|
||||
guiErrors logger.Recorder
|
||||
systemLog logger.Recorder
|
||||
@@ -104,7 +105,7 @@ type Service interface {
|
||||
WaitForStart() error
|
||||
}
|
||||
|
||||
func New(id protocol.DeviceID, cfg config.Wrapper, assetDir, tlsDefaultCommonName string, m model.Model, defaultSub, diskSub events.BufferedSubscription, evLogger events.Logger, discoverer discover.Manager, connectionsService connections.Service, urService *ur.Service, fss model.FolderSummaryService, errors, systemLog logger.Recorder, noUpgrade bool) Service {
|
||||
func New(id protocol.DeviceID, cfg config.Wrapper, assetDir, tlsDefaultCommonName string, m model.Model, defaultSub, diskSub events.BufferedSubscription, evLogger events.Logger, discoverer discover.Manager, connectionsService connections.Service, urService *ur.Service, fss model.FolderSummaryService, errors, systemLog logger.Recorder, noUpgrade bool, miscDB *db.NamespacedKV) Service {
|
||||
return &service{
|
||||
id: id,
|
||||
cfg: cfg,
|
||||
@@ -127,6 +128,7 @@ func New(id protocol.DeviceID, cfg config.Wrapper, assetDir, tlsDefaultCommonNam
|
||||
configChanged: make(chan struct{}),
|
||||
startedOnce: make(chan struct{}),
|
||||
exitChan: make(chan *svcutil.FatalErr, 1),
|
||||
miscDB: miscDB,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -353,31 +355,27 @@ func (s *service) Serve(ctx context.Context) error {
|
||||
|
||||
// Handle Prometheus metrics
|
||||
promHttpHandler := promhttp.Handler()
|
||||
mux.HandleFunc("/metrics", func(w http.ResponseWriter, req *http.Request) {
|
||||
// fetching metrics counts as an event, for the purpose of whether
|
||||
// we should prepare folder summaries etc.
|
||||
s.fss.OnEventRequest()
|
||||
promHttpHandler.ServeHTTP(w, req)
|
||||
})
|
||||
mux.Handle("/metrics", promHttpHandler)
|
||||
|
||||
guiCfg := s.cfg.GUI()
|
||||
|
||||
// Wrap everything in CSRF protection. The /rest prefix should be
|
||||
// protected, other requests will grant cookies.
|
||||
var handler http.Handler = newCsrfManager(s.id.Short().String(), "/rest", guiCfg, mux, locations.Get(locations.CsrfTokens))
|
||||
var handler http.Handler = newCsrfManager(s.id.Short().String(), "/rest", guiCfg, mux, s.miscDB)
|
||||
|
||||
// Add our version and ID as a header to responses
|
||||
handler = withDetailsMiddleware(s.id, handler)
|
||||
|
||||
// Wrap everything in basic auth, if user/password is set.
|
||||
if guiCfg.IsAuthEnabled() {
|
||||
sessionCookieName := "sessionid-" + s.id.Short().String()
|
||||
handler = basicAuthAndSessionMiddleware(sessionCookieName, s.id.Short().String(), guiCfg, s.cfg.LDAP(), handler, s.evLogger)
|
||||
handlePasswordAuth := passwordAuthHandler(sessionCookieName, guiCfg, s.cfg.LDAP(), s.evLogger)
|
||||
restMux.Handler(http.MethodPost, "/rest/noauth/auth/password", handlePasswordAuth)
|
||||
tokenCookieManager := newTokenCookieManager(s.id.Short().String(), guiCfg, s.evLogger, s.miscDB)
|
||||
authMW := newBasicAuthAndSessionMiddleware(tokenCookieManager, guiCfg, s.cfg.LDAP(), handler, s.evLogger)
|
||||
handler = authMW
|
||||
|
||||
restMux.Handler(http.MethodPost, "/rest/noauth/auth/password", http.HandlerFunc(authMW.passwordAuthHandler))
|
||||
|
||||
// Logout is a no-op without a valid session cookie, so /noauth/ is fine here
|
||||
restMux.Handler(http.MethodPost, "/rest/noauth/auth/logout", handleLogout(sessionCookieName))
|
||||
restMux.Handler(http.MethodPost, "/rest/noauth/auth/logout", http.HandlerFunc(authMW.handleLogout))
|
||||
}
|
||||
|
||||
// Redirect to HTTPS if we are supposed to
|
||||
@@ -979,6 +977,7 @@ func (s *service) getDBFile(w http.ResponseWriter, r *http.Request) {
|
||||
av, err := s.model.Availability(folder, gf, protocol.BlockInfo{})
|
||||
if err != nil {
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
}
|
||||
mtimeMapping, mtimeErr := s.model.GetMtimeMapping(folder, file)
|
||||
|
||||
@@ -1392,11 +1391,7 @@ func (s *service) getDiskEvents(w http.ResponseWriter, r *http.Request) {
|
||||
s.getEvents(w, r, sub)
|
||||
}
|
||||
|
||||
func (s *service) getEvents(w http.ResponseWriter, r *http.Request, eventSub events.BufferedSubscription) {
|
||||
if eventSub.Mask()&(events.FolderSummary|events.FolderCompletion) != 0 {
|
||||
s.fss.OnEventRequest()
|
||||
}
|
||||
|
||||
func (*service) getEvents(w http.ResponseWriter, r *http.Request, eventSub events.BufferedSubscription) {
|
||||
qs := r.URL.Query()
|
||||
sinceStr := qs.Get("since")
|
||||
limitStr := qs.Get("limit")
|
||||
|
||||
@@ -11,6 +11,7 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
@@ -18,13 +19,12 @@ import (
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/rand"
|
||||
"github.com/syncthing/syncthing/lib/sync"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
var (
|
||||
sessions = make(map[string]bool)
|
||||
sessionsMut = sync.NewMutex()
|
||||
const (
|
||||
maxSessionLifetime = 7 * 24 * time.Hour
|
||||
maxActiveSessions = 25
|
||||
randomTokenLength = 64
|
||||
)
|
||||
|
||||
func emitLoginAttempt(success bool, username, address string, evLogger events.Logger) {
|
||||
@@ -78,75 +78,79 @@ func isNoAuthPath(path string) bool {
|
||||
})
|
||||
}
|
||||
|
||||
func basicAuthAndSessionMiddleware(cookieName, shortID string, guiCfg config.GUIConfiguration, ldapCfg config.LDAPConfiguration, next http.Handler, evLogger events.Logger) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
if hasValidAPIKeyHeader(r, guiCfg) {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
for _, cookie := range r.Cookies() {
|
||||
// We iterate here since there may, historically, be multiple
|
||||
// cookies with the same name but different path. Any "old" ones
|
||||
// won't match an existing session and will be ignored, then
|
||||
// later removed on logout or when timing out.
|
||||
if cookie.Name == cookieName {
|
||||
sessionsMut.Lock()
|
||||
_, ok := sessions[cookie.Value]
|
||||
sessionsMut.Unlock()
|
||||
if ok {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fall back to Basic auth if provided
|
||||
if username, ok := attemptBasicAuth(r, guiCfg, ldapCfg, evLogger); ok {
|
||||
createSession(cookieName, username, guiCfg, evLogger, w, r)
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// Exception for static assets and REST calls that don't require authentication.
|
||||
if isNoAuthPath(r.URL.Path) {
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// Some browsers don't send the Authorization request header unless prompted by a 401 response.
|
||||
// This enables https://user:pass@localhost style URLs to keep working.
|
||||
if guiCfg.SendBasicAuthPrompt {
|
||||
unauthorized(w, shortID)
|
||||
return
|
||||
}
|
||||
|
||||
forbidden(w)
|
||||
})
|
||||
type basicAuthAndSessionMiddleware struct {
|
||||
tokenCookieManager *tokenCookieManager
|
||||
guiCfg config.GUIConfiguration
|
||||
ldapCfg config.LDAPConfiguration
|
||||
next http.Handler
|
||||
evLogger events.Logger
|
||||
}
|
||||
|
||||
func passwordAuthHandler(cookieName string, guiCfg config.GUIConfiguration, ldapCfg config.LDAPConfiguration, evLogger events.Logger) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
var req struct {
|
||||
Username string
|
||||
Password string
|
||||
}
|
||||
if err := unmarshalTo(r.Body, &req); err != nil {
|
||||
l.Debugln("Failed to parse username and password:", err)
|
||||
http.Error(w, "Failed to parse username and password.", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
func newBasicAuthAndSessionMiddleware(tokenCookieManager *tokenCookieManager, guiCfg config.GUIConfiguration, ldapCfg config.LDAPConfiguration, next http.Handler, evLogger events.Logger) *basicAuthAndSessionMiddleware {
|
||||
return &basicAuthAndSessionMiddleware{
|
||||
tokenCookieManager: tokenCookieManager,
|
||||
guiCfg: guiCfg,
|
||||
ldapCfg: ldapCfg,
|
||||
next: next,
|
||||
evLogger: evLogger,
|
||||
}
|
||||
}
|
||||
|
||||
if auth(req.Username, req.Password, guiCfg, ldapCfg) {
|
||||
createSession(cookieName, req.Username, guiCfg, evLogger, w, r)
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
return
|
||||
}
|
||||
func (m *basicAuthAndSessionMiddleware) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
if hasValidAPIKeyHeader(r, m.guiCfg) {
|
||||
m.next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
emitLoginAttempt(false, req.Username, r.RemoteAddr, evLogger)
|
||||
antiBruteForceSleep()
|
||||
forbidden(w)
|
||||
})
|
||||
if m.tokenCookieManager.hasValidSession(r) {
|
||||
m.next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// Fall back to Basic auth if provided
|
||||
if username, ok := attemptBasicAuth(r, m.guiCfg, m.ldapCfg, m.evLogger); ok {
|
||||
m.tokenCookieManager.createSession(username, false, w, r)
|
||||
m.next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// Exception for static assets and REST calls that don't require authentication.
|
||||
if isNoAuthPath(r.URL.Path) {
|
||||
m.next.ServeHTTP(w, r)
|
||||
return
|
||||
}
|
||||
|
||||
// Some browsers don't send the Authorization request header unless prompted by a 401 response.
|
||||
// This enables https://user:pass@localhost style URLs to keep working.
|
||||
if m.guiCfg.SendBasicAuthPrompt {
|
||||
unauthorized(w, m.tokenCookieManager.shortID)
|
||||
return
|
||||
}
|
||||
|
||||
forbidden(w)
|
||||
}
|
||||
|
||||
func (m *basicAuthAndSessionMiddleware) passwordAuthHandler(w http.ResponseWriter, r *http.Request) {
|
||||
var req struct {
|
||||
Username string
|
||||
Password string
|
||||
StayLoggedIn bool
|
||||
}
|
||||
if err := unmarshalTo(r.Body, &req); err != nil {
|
||||
l.Debugln("Failed to parse username and password:", err)
|
||||
http.Error(w, "Failed to parse username and password.", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
||||
if auth(req.Username, req.Password, m.guiCfg, m.ldapCfg) {
|
||||
m.tokenCookieManager.createSession(req.Username, req.StayLoggedIn, w, r)
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
return
|
||||
}
|
||||
|
||||
emitLoginAttempt(false, req.Username, r.RemoteAddr, m.evLogger)
|
||||
antiBruteForceSleep()
|
||||
forbidden(w)
|
||||
}
|
||||
|
||||
func attemptBasicAuth(r *http.Request, guiCfg config.GUIConfiguration, ldapCfg config.LDAPConfiguration, evLogger events.Logger) (string, bool) {
|
||||
@@ -172,59 +176,9 @@ func attemptBasicAuth(r *http.Request, guiCfg config.GUIConfiguration, ldapCfg c
|
||||
return "", false
|
||||
}
|
||||
|
||||
func createSession(cookieName string, username string, guiCfg config.GUIConfiguration, evLogger events.Logger, w http.ResponseWriter, r *http.Request) {
|
||||
sessionid := rand.String(32)
|
||||
sessionsMut.Lock()
|
||||
sessions[sessionid] = true
|
||||
sessionsMut.Unlock()
|
||||
|
||||
// Best effort detection of whether the connection is HTTPS --
|
||||
// either directly to us, or as used by the client towards a reverse
|
||||
// proxy who sends us headers.
|
||||
connectionIsHTTPS := r.TLS != nil ||
|
||||
strings.ToLower(r.Header.Get("x-forwarded-proto")) == "https" ||
|
||||
strings.Contains(strings.ToLower(r.Header.Get("forwarded")), "proto=https")
|
||||
// If the connection is HTTPS, or *should* be HTTPS, set the Secure
|
||||
// bit in cookies.
|
||||
useSecureCookie := connectionIsHTTPS || guiCfg.UseTLS()
|
||||
|
||||
http.SetCookie(w, &http.Cookie{
|
||||
Name: cookieName,
|
||||
Value: sessionid,
|
||||
// In HTTP spec Max-Age <= 0 means delete immediately,
|
||||
// but in http.Cookie MaxAge = 0 means unspecified (session) and MaxAge < 0 means delete immediately
|
||||
MaxAge: 0,
|
||||
Secure: useSecureCookie,
|
||||
Path: "/",
|
||||
})
|
||||
|
||||
emitLoginAttempt(true, username, r.RemoteAddr, evLogger)
|
||||
}
|
||||
|
||||
func handleLogout(cookieName string) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
for _, cookie := range r.Cookies() {
|
||||
// We iterate here since there may, historically, be multiple
|
||||
// cookies with the same name but different path. We drop them
|
||||
// all.
|
||||
if cookie.Name == cookieName {
|
||||
sessionsMut.Lock()
|
||||
delete(sessions, cookie.Value)
|
||||
sessionsMut.Unlock()
|
||||
|
||||
// Delete the cookie
|
||||
http.SetCookie(w, &http.Cookie{
|
||||
Name: cookieName,
|
||||
Value: "",
|
||||
MaxAge: -1,
|
||||
Secure: cookie.Secure,
|
||||
Path: cookie.Path,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
})
|
||||
func (m *basicAuthAndSessionMiddleware) handleLogout(w http.ResponseWriter, r *http.Request) {
|
||||
m.tokenCookieManager.destroySession(w, r)
|
||||
w.WriteHeader(http.StatusNoContent)
|
||||
}
|
||||
|
||||
func auth(username string, password string, guiCfg config.GUIConfiguration, ldapCfg config.LDAPConfiguration) bool {
|
||||
|
||||
@@ -8,8 +8,12 @@ package api
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/db"
|
||||
"github.com/syncthing/syncthing/lib/db/backend"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
)
|
||||
|
||||
var guiCfg config.GUIConfiguration
|
||||
@@ -110,3 +114,76 @@ func TestEscapeForLDAPDN(t *testing.T) {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
type mockClock struct {
|
||||
now time.Time
|
||||
}
|
||||
|
||||
func (c *mockClock) Now() time.Time {
|
||||
c.now = c.now.Add(1) // time always ticks by at least 1 ns
|
||||
return c.now
|
||||
}
|
||||
|
||||
func (c *mockClock) wind(t time.Duration) {
|
||||
c.now = c.now.Add(t)
|
||||
}
|
||||
|
||||
func TestTokenManager(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
mdb, _ := db.NewLowlevel(backend.OpenMemory(), events.NoopLogger)
|
||||
kdb := db.NewNamespacedKV(mdb, "test")
|
||||
clock := &mockClock{now: time.Now()}
|
||||
|
||||
// Token manager keeps up to three tokens with a validity time of 24 hours.
|
||||
tm := newTokenManager("testTokens", kdb, 24*time.Hour, 3)
|
||||
tm.timeNow = clock.Now
|
||||
|
||||
// Create three tokens
|
||||
t0 := tm.New()
|
||||
t1 := tm.New()
|
||||
t2 := tm.New()
|
||||
|
||||
// Check that the tokens are valid
|
||||
if !tm.Check(t0) {
|
||||
t.Errorf("token %q should be valid", t0)
|
||||
}
|
||||
if !tm.Check(t1) {
|
||||
t.Errorf("token %q should be valid", t1)
|
||||
}
|
||||
if !tm.Check(t2) {
|
||||
t.Errorf("token %q should be valid", t2)
|
||||
}
|
||||
|
||||
// Create a fourth token
|
||||
t3 := tm.New()
|
||||
// It should be valid
|
||||
if !tm.Check(t3) {
|
||||
t.Errorf("token %q should be valid", t3)
|
||||
}
|
||||
// But the first token should have been removed
|
||||
if tm.Check(t0) {
|
||||
t.Errorf("token %q should be invalid", t0)
|
||||
}
|
||||
|
||||
// Wind the clock by 12 hours
|
||||
clock.wind(12 * time.Hour)
|
||||
// The second token should still be valid (and checking it will give it more life)
|
||||
if !tm.Check(t1) {
|
||||
t.Errorf("token %q should be valid", t1)
|
||||
}
|
||||
|
||||
// Wind the clock by 12 hours
|
||||
clock.wind(12 * time.Hour)
|
||||
// The second token should still be valid
|
||||
if !tm.Check(t1) {
|
||||
t.Errorf("token %q should be valid", t1)
|
||||
}
|
||||
// But the third and fourth tokens should have expired
|
||||
if tm.Check(t2) {
|
||||
t.Errorf("token %q should be invalid", t2)
|
||||
}
|
||||
if tm.Check(t3) {
|
||||
t.Errorf("token %q should be invalid", t3)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,33 +7,24 @@
|
||||
package api
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/osutil"
|
||||
"github.com/syncthing/syncthing/lib/rand"
|
||||
"github.com/syncthing/syncthing/lib/sync"
|
||||
"github.com/syncthing/syncthing/lib/db"
|
||||
)
|
||||
|
||||
const maxCsrfTokens = 25
|
||||
const (
|
||||
maxCSRFTokenLifetime = time.Hour
|
||||
maxActiveCSRFTokens = 25
|
||||
)
|
||||
|
||||
type csrfManager struct {
|
||||
// tokens is a list of valid tokens. It is sorted so that the most
|
||||
// recently used token is first in the list. New tokens are added to the front
|
||||
// of the list (as it is the most recently used at that time). The list is
|
||||
// pruned to a maximum of maxCsrfTokens, throwing away the least recently used
|
||||
// tokens.
|
||||
tokens []string
|
||||
tokensMut sync.Mutex
|
||||
|
||||
unique string
|
||||
prefix string
|
||||
apiKeyValidator apiKeyValidator
|
||||
next http.Handler
|
||||
saveLocation string
|
||||
tokens *tokenManager
|
||||
}
|
||||
|
||||
type apiKeyValidator interface {
|
||||
@@ -43,17 +34,14 @@ type apiKeyValidator interface {
|
||||
// Check for CSRF token on /rest/ URLs. If a correct one is not given, reject
|
||||
// the request with 403. For / and /index.html, set a new CSRF cookie if none
|
||||
// is currently set.
|
||||
func newCsrfManager(unique string, prefix string, apiKeyValidator apiKeyValidator, next http.Handler, saveLocation string) *csrfManager {
|
||||
func newCsrfManager(unique string, prefix string, apiKeyValidator apiKeyValidator, next http.Handler, miscDB *db.NamespacedKV) *csrfManager {
|
||||
m := &csrfManager{
|
||||
tokensMut: sync.NewMutex(),
|
||||
tokens: make([]string, 0, maxCsrfTokens),
|
||||
unique: unique,
|
||||
prefix: prefix,
|
||||
apiKeyValidator: apiKeyValidator,
|
||||
next: next,
|
||||
saveLocation: saveLocation,
|
||||
tokens: newTokenManager("csrfTokens", miscDB, maxCSRFTokenLifetime, maxActiveCSRFTokens),
|
||||
}
|
||||
m.load()
|
||||
return m
|
||||
}
|
||||
|
||||
@@ -78,11 +66,11 @@ func (m *csrfManager) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
// and set a CSRF cookie if there isn't already a valid one.
|
||||
if !strings.HasPrefix(r.URL.Path, m.prefix) {
|
||||
cookie, err := r.Cookie("CSRF-Token-" + m.unique)
|
||||
if err != nil || !m.validToken(cookie.Value) {
|
||||
if err != nil || !m.tokens.Check(cookie.Value) {
|
||||
l.Debugln("new CSRF cookie in response to request for", r.URL)
|
||||
cookie = &http.Cookie{
|
||||
Name: "CSRF-Token-" + m.unique,
|
||||
Value: m.newToken(),
|
||||
Value: m.tokens.New(),
|
||||
}
|
||||
http.SetCookie(w, cookie)
|
||||
}
|
||||
@@ -99,7 +87,7 @@ func (m *csrfManager) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
|
||||
// Verify the CSRF token
|
||||
token := r.Header.Get("X-CSRF-Token-" + m.unique)
|
||||
if !m.validToken(token) {
|
||||
if !m.tokens.Check(token) {
|
||||
http.Error(w, "CSRF Error", http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
@@ -107,78 +95,6 @@ func (m *csrfManager) ServeHTTP(w http.ResponseWriter, r *http.Request) {
|
||||
m.next.ServeHTTP(w, r)
|
||||
}
|
||||
|
||||
func (m *csrfManager) validToken(token string) bool {
|
||||
m.tokensMut.Lock()
|
||||
defer m.tokensMut.Unlock()
|
||||
for i, t := range m.tokens {
|
||||
if t == token {
|
||||
if i > 0 {
|
||||
// Move this token to the head of the list. Copy the tokens at
|
||||
// the front one step to the right and then replace the token
|
||||
// at the head.
|
||||
copy(m.tokens[1:], m.tokens[:i])
|
||||
m.tokens[0] = token
|
||||
}
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *csrfManager) newToken() string {
|
||||
token := rand.String(32)
|
||||
|
||||
m.tokensMut.Lock()
|
||||
defer m.tokensMut.Unlock()
|
||||
|
||||
if len(m.tokens) < maxCsrfTokens {
|
||||
m.tokens = append(m.tokens, "")
|
||||
}
|
||||
copy(m.tokens[1:], m.tokens)
|
||||
m.tokens[0] = token
|
||||
|
||||
m.save()
|
||||
|
||||
return token
|
||||
}
|
||||
|
||||
func (m *csrfManager) save() {
|
||||
// We're ignoring errors in here. It's not super critical and there's
|
||||
// nothing relevant we can do about them anyway...
|
||||
|
||||
if m.saveLocation == "" {
|
||||
return
|
||||
}
|
||||
|
||||
f, err := osutil.CreateAtomic(m.saveLocation)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
for _, t := range m.tokens {
|
||||
fmt.Fprintln(f, t)
|
||||
}
|
||||
|
||||
f.Close()
|
||||
}
|
||||
|
||||
func (m *csrfManager) load() {
|
||||
if m.saveLocation == "" {
|
||||
return
|
||||
}
|
||||
|
||||
f, err := os.Open(m.saveLocation)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
defer f.Close()
|
||||
|
||||
s := bufio.NewScanner(f)
|
||||
for s.Scan() {
|
||||
m.tokens = append(m.tokens, s.Text())
|
||||
}
|
||||
}
|
||||
|
||||
func hasValidAPIKeyHeader(r *http.Request, validator apiKeyValidator) bool {
|
||||
if key := r.Header.Get("X-API-Key"); validator.IsValidAPIKey(key) {
|
||||
return true
|
||||
|
||||
@@ -18,7 +18,7 @@ import (
|
||||
"net/http/httptest"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"slices"
|
||||
"strconv"
|
||||
"strings"
|
||||
"testing"
|
||||
@@ -29,6 +29,8 @@ import (
|
||||
"github.com/syncthing/syncthing/lib/build"
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
connmocks "github.com/syncthing/syncthing/lib/connections/mocks"
|
||||
"github.com/syncthing/syncthing/lib/db"
|
||||
"github.com/syncthing/syncthing/lib/db/backend"
|
||||
discovermocks "github.com/syncthing/syncthing/lib/discover/mocks"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
eventmocks "github.com/syncthing/syncthing/lib/events/mocks"
|
||||
@@ -45,12 +47,10 @@ import (
|
||||
"github.com/syncthing/syncthing/lib/tlsutil"
|
||||
"github.com/syncthing/syncthing/lib/ur"
|
||||
"github.com/thejerf/suture/v4"
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
var (
|
||||
confDir = filepath.Join("testdata", "config")
|
||||
token = filepath.Join(confDir, "csrftokens.txt")
|
||||
dev1 protocol.DeviceID
|
||||
apiCfg = newMockedConfig()
|
||||
testAPIKey = "foobarbaz"
|
||||
@@ -72,71 +72,6 @@ func TestMain(m *testing.M) {
|
||||
os.Exit(exitCode)
|
||||
}
|
||||
|
||||
func TestCSRFToken(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
max := 10 * maxCsrfTokens
|
||||
int := 5
|
||||
if testing.Short() {
|
||||
max = 1 + maxCsrfTokens
|
||||
int = 2
|
||||
}
|
||||
|
||||
m := newCsrfManager("unique", "prefix", config.GUIConfiguration{}, nil, "")
|
||||
|
||||
t1 := m.newToken()
|
||||
t2 := m.newToken()
|
||||
|
||||
t3 := m.newToken()
|
||||
if !m.validToken(t3) {
|
||||
t.Fatal("t3 should be valid")
|
||||
}
|
||||
|
||||
valid := make(map[string]struct{}, maxCsrfTokens)
|
||||
for _, token := range m.tokens {
|
||||
valid[token] = struct{}{}
|
||||
}
|
||||
|
||||
for i := 0; i < max; i++ {
|
||||
if i%int == 0 {
|
||||
// t1 and t2 should remain valid by virtue of us checking them now
|
||||
// and then.
|
||||
if !m.validToken(t1) {
|
||||
t.Fatal("t1 should be valid at iteration", i)
|
||||
}
|
||||
if !m.validToken(t2) {
|
||||
t.Fatal("t2 should be valid at iteration", i)
|
||||
}
|
||||
}
|
||||
|
||||
if len(m.tokens) == maxCsrfTokens {
|
||||
// We're about to add a token, which will remove the last token
|
||||
// from m.tokens.
|
||||
delete(valid, m.tokens[len(m.tokens)-1])
|
||||
}
|
||||
|
||||
// The newly generated token is always valid
|
||||
t4 := m.newToken()
|
||||
if !m.validToken(t4) {
|
||||
t.Fatal("t4 should be valid at iteration", i)
|
||||
}
|
||||
valid[t4] = struct{}{}
|
||||
|
||||
v := make(map[string]struct{}, maxCsrfTokens)
|
||||
for _, token := range m.tokens {
|
||||
v[token] = struct{}{}
|
||||
}
|
||||
|
||||
if !reflect.DeepEqual(v, valid) {
|
||||
t.Fatalf("want valid tokens %v, got %v", valid, v)
|
||||
}
|
||||
}
|
||||
|
||||
if m.validToken(t3) {
|
||||
t.Fatal("t3 should have expired by now")
|
||||
}
|
||||
}
|
||||
|
||||
func TestStopAfterBrokenConfig(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
@@ -148,8 +83,9 @@ func TestStopAfterBrokenConfig(t *testing.T) {
|
||||
}
|
||||
w := config.Wrap("/dev/null", cfg, protocol.LocalDeviceID, events.NoopLogger)
|
||||
|
||||
srv := New(protocol.LocalDeviceID, w, "", "syncthing", nil, nil, nil, events.NoopLogger, nil, nil, nil, nil, nil, nil, false).(*service)
|
||||
defer os.Remove(token)
|
||||
mdb, _ := db.NewLowlevel(backend.OpenMemory(), events.NoopLogger)
|
||||
kdb := db.NewMiscDataNamespace(mdb)
|
||||
srv := New(protocol.LocalDeviceID, w, "", "syncthing", nil, nil, nil, events.NoopLogger, nil, nil, nil, nil, nil, nil, false, kdb).(*service)
|
||||
|
||||
srv.started = make(chan string)
|
||||
|
||||
@@ -289,10 +225,11 @@ func TestAPIServiceRequests(t *testing.T) {
|
||||
cases := []httpTestCase{
|
||||
// /rest/db
|
||||
{
|
||||
URL: "/rest/db/completion?device=" + protocol.LocalDeviceID.String() + "&folder=default",
|
||||
Code: 200,
|
||||
Type: "application/json",
|
||||
Prefix: "{",
|
||||
URL: "/rest/db/completion?device=" + protocol.LocalDeviceID.String() + "&folder=default",
|
||||
Code: 200,
|
||||
Type: "application/json",
|
||||
Prefix: "{",
|
||||
Timeout: 15 * time.Second,
|
||||
},
|
||||
{
|
||||
URL: "/rest/db/file?folder=default&file=something",
|
||||
@@ -497,7 +434,7 @@ func TestAPIServiceRequests(t *testing.T) {
|
||||
|
||||
for _, tc := range cases {
|
||||
tc := tc
|
||||
t.Run(cases[0].URL, func(t *testing.T) {
|
||||
t.Run(tc.URL, func(t *testing.T) {
|
||||
t.Parallel()
|
||||
testHTTPRequest(t, baseURL, tc, testAPIKey)
|
||||
})
|
||||
@@ -507,8 +444,6 @@ func TestAPIServiceRequests(t *testing.T) {
|
||||
// testHTTPRequest tries the given test case, comparing the result code,
|
||||
// content type, and result prefix.
|
||||
func testHTTPRequest(t *testing.T, baseURL string, tc httpTestCase, apikey string) {
|
||||
// Should not be parallelized, as that just causes timeouts eventually with more test-cases
|
||||
|
||||
timeout := time.Second
|
||||
if tc.Timeout > 0 {
|
||||
timeout = tc.Timeout
|
||||
@@ -563,6 +498,15 @@ func hasSessionCookie(cookies []*http.Cookie) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func hasDeleteSessionCookie(cookies []*http.Cookie) bool {
|
||||
for _, cookie := range cookies {
|
||||
if cookie.MaxAge < 0 && strings.HasPrefix(cookie.Name, "sessionid") {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func httpGet(url string, basicAuthUsername string, basicAuthPassword string, xapikeyHeader string, authorizationBearer string, cookies []*http.Cookie, t *testing.T) *http.Response {
|
||||
req, err := http.NewRequest("GET", url, nil)
|
||||
for _, cookie := range cookies {
|
||||
@@ -592,7 +536,7 @@ func httpGet(url string, basicAuthUsername string, basicAuthPassword string, xap
|
||||
return resp
|
||||
}
|
||||
|
||||
func httpPost(url string, body map[string]string, t *testing.T) *http.Response {
|
||||
func httpPost(url string, body map[string]string, cookies []*http.Cookie, t *testing.T) *http.Response {
|
||||
bodyBytes, err := json.Marshal(body)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -603,6 +547,10 @@ func httpPost(url string, body map[string]string, t *testing.T) *http.Response {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for _, cookie := range cookies {
|
||||
req.AddCookie(cookie)
|
||||
}
|
||||
|
||||
resp, err := http.DefaultClient.Do(req)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
@@ -687,6 +635,43 @@ func TestHTTPLogin(t *testing.T) {
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Logout removes the session cookie", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
resp := httpGetBasicAuth(url, "üser", "räksmörgås") // string literals in Go source code are in UTF-8
|
||||
if resp.StatusCode != expectedOkStatus {
|
||||
t.Errorf("Unexpected non-%d return code %d for authed request (UTF-8)", expectedOkStatus, resp.StatusCode)
|
||||
}
|
||||
if !hasSessionCookie(resp.Cookies()) {
|
||||
t.Errorf("Expected session cookie for authed request (UTF-8)")
|
||||
}
|
||||
logoutResp := httpPost(baseURL+"/rest/noauth/auth/logout", nil, resp.Cookies(), t)
|
||||
if !hasDeleteSessionCookie(logoutResp.Cookies()) {
|
||||
t.Errorf("Expected session cookie to be deleted for logout request")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Session cookie is invalid after logout", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
loginResp := httpGetBasicAuth(url, "üser", "räksmörgås") // string literals in Go source code are in UTF-8
|
||||
if loginResp.StatusCode != expectedOkStatus {
|
||||
t.Errorf("Unexpected non-%d return code %d for authed request (UTF-8)", expectedOkStatus, loginResp.StatusCode)
|
||||
}
|
||||
if !hasSessionCookie(loginResp.Cookies()) {
|
||||
t.Errorf("Expected session cookie for authed request (UTF-8)")
|
||||
}
|
||||
|
||||
resp := httpGet(url, "", "", "", "", loginResp.Cookies(), t)
|
||||
if resp.StatusCode != expectedOkStatus {
|
||||
t.Errorf("Unexpected non-%d return code %d for cookie-authed request (UTF-8)", expectedOkStatus, resp.StatusCode)
|
||||
}
|
||||
|
||||
httpPost(baseURL+"/rest/noauth/auth/logout", nil, loginResp.Cookies(), t)
|
||||
resp = httpGet(url, "", "", "", "", loginResp.Cookies(), t)
|
||||
if resp.StatusCode != expectedFailStatus {
|
||||
t.Errorf("Expected session to be invalid (status %d) after logout, got status: %d", expectedFailStatus, resp.StatusCode)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("ISO-8859-1 auth works", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
resp := httpGetBasicAuth(url, "\xfcser", "r\xe4ksm\xf6rg\xe5s") // escaped ISO-8859-1
|
||||
@@ -773,7 +758,7 @@ func TestHtmlFormLogin(t *testing.T) {
|
||||
resourceUrl404 := baseURL + "/any-path/that/does/nooooooot/match-any/noauth-pattern"
|
||||
|
||||
performLogin := func(username string, password string) *http.Response {
|
||||
return httpPost(loginUrl, map[string]string{"username": username, "password": password}, t)
|
||||
return httpPost(loginUrl, map[string]string{"username": username, "password": password}, nil, t)
|
||||
}
|
||||
|
||||
performResourceRequest := func(url string, cookies []*http.Cookie) *http.Response {
|
||||
@@ -838,9 +823,40 @@ func TestHtmlFormLogin(t *testing.T) {
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Logout removes the session cookie", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
// JSON is always UTF-8, so ISO-8859-1 case is not applicable
|
||||
resp := performLogin("üser", "räksmörgås") // string literals in Go source code are in UTF-8
|
||||
if resp.StatusCode != http.StatusNoContent {
|
||||
t.Errorf("Unexpected non-204 return code %d for authed request (UTF-8)", resp.StatusCode)
|
||||
}
|
||||
logoutResp := httpPost(baseURL+"/rest/noauth/auth/logout", nil, resp.Cookies(), t)
|
||||
if !hasDeleteSessionCookie(logoutResp.Cookies()) {
|
||||
t.Errorf("Expected session cookie to be deleted for logout request")
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("Session cookie is invalid after logout", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
// JSON is always UTF-8, so ISO-8859-1 case is not applicable
|
||||
loginResp := performLogin("üser", "räksmörgås") // string literals in Go source code are in UTF-8
|
||||
if loginResp.StatusCode != http.StatusNoContent {
|
||||
t.Errorf("Unexpected non-204 return code %d for authed request (UTF-8)", loginResp.StatusCode)
|
||||
}
|
||||
resp := performResourceRequest(resourceUrl, loginResp.Cookies())
|
||||
if resp.StatusCode != http.StatusOK {
|
||||
t.Errorf("Unexpected non-200 return code %d for authed request (UTF-8)", resp.StatusCode)
|
||||
}
|
||||
httpPost(baseURL+"/rest/noauth/auth/logout", nil, loginResp.Cookies(), t)
|
||||
resp = performResourceRequest(resourceUrl, loginResp.Cookies())
|
||||
if resp.StatusCode != http.StatusForbidden {
|
||||
t.Errorf("Expected session to be invalid (status 403) after logout, got status: %d", resp.StatusCode)
|
||||
}
|
||||
})
|
||||
|
||||
t.Run("form login is not applicable to other URLs", func(t *testing.T) {
|
||||
t.Parallel()
|
||||
resp := httpPost(baseURL+"/meta.js", map[string]string{"username": "üser", "password": "räksmörgås"}, t)
|
||||
resp := httpPost(baseURL+"/meta.js", map[string]string{"username": "üser", "password": "räksmörgås"}, nil, t)
|
||||
if resp.StatusCode != http.StatusForbidden {
|
||||
t.Errorf("Unexpected non-403 return code %d for incorrect form login URL", resp.StatusCode)
|
||||
}
|
||||
@@ -926,8 +942,9 @@ func startHTTP(cfg config.Wrapper) (string, context.CancelFunc, error) {
|
||||
|
||||
// Instantiate the API service
|
||||
urService := ur.New(cfg, m, connections, false)
|
||||
svc := New(protocol.LocalDeviceID, cfg, assetDir, "syncthing", m, eventSub, diskEventSub, events.NoopLogger, discoverer, connections, urService, mockedSummary, errorLog, systemLog, false).(*service)
|
||||
defer os.Remove(token)
|
||||
mdb, _ := db.NewLowlevel(backend.OpenMemory(), events.NoopLogger)
|
||||
kdb := db.NewMiscDataNamespace(mdb)
|
||||
svc := New(protocol.LocalDeviceID, cfg, assetDir, "syncthing", m, eventSub, diskEventSub, events.NoopLogger, discoverer, connections, urService, mockedSummary, errorLog, systemLog, false, kdb).(*service)
|
||||
svc.started = addrChan
|
||||
|
||||
// Actually start the API service
|
||||
@@ -1467,8 +1484,9 @@ func TestEventMasks(t *testing.T) {
|
||||
cfg := newMockedConfig()
|
||||
defSub := new(eventmocks.BufferedSubscription)
|
||||
diskSub := new(eventmocks.BufferedSubscription)
|
||||
svc := New(protocol.LocalDeviceID, cfg, "", "syncthing", nil, defSub, diskSub, events.NoopLogger, nil, nil, nil, nil, nil, nil, false).(*service)
|
||||
defer os.Remove(token)
|
||||
mdb, _ := db.NewLowlevel(backend.OpenMemory(), events.NoopLogger)
|
||||
kdb := db.NewMiscDataNamespace(mdb)
|
||||
svc := New(protocol.LocalDeviceID, cfg, "", "syncthing", nil, defSub, diskSub, events.NoopLogger, nil, nil, nil, nil, nil, nil, false, kdb).(*service)
|
||||
|
||||
if mask := svc.getEventMask(""); mask != DefaultEventMask {
|
||||
t.Errorf("incorrect default mask %x != %x", int64(mask), int64(DefaultEventMask))
|
||||
|
||||
@@ -10,18 +10,8 @@ import (
|
||||
"github.com/syncthing/syncthing/lib/logger"
|
||||
)
|
||||
|
||||
var (
|
||||
l = logger.DefaultLogger.NewFacility("api", "REST API")
|
||||
)
|
||||
var l = logger.DefaultLogger.NewFacility("api", "REST API")
|
||||
|
||||
func shouldDebugHTTP() bool {
|
||||
return l.ShouldDebug("api")
|
||||
}
|
||||
|
||||
func init() {
|
||||
// The debug facility was originally named "http", changed in:
|
||||
// https://github.com/syncthing/syncthing/pull/5548
|
||||
if l.IsTraced("http") {
|
||||
l.SetDebug("api", true)
|
||||
}
|
||||
}
|
||||
|
||||
224
lib/api/tokenmanager.go
Normal file
224
lib/api/tokenmanager.go
Normal file
@@ -0,0 +1,224 @@
|
||||
// Copyright (C) 2024 The Syncthing Authors.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
"net/http"
|
||||
"slices"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/db"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/rand"
|
||||
"github.com/syncthing/syncthing/lib/sync"
|
||||
)
|
||||
|
||||
type tokenManager struct {
|
||||
key string
|
||||
miscDB *db.NamespacedKV
|
||||
lifetime time.Duration
|
||||
maxItems int
|
||||
|
||||
timeNow func() time.Time // can be overridden for testing
|
||||
|
||||
mut sync.Mutex
|
||||
tokens *TokenSet
|
||||
saveTimer *time.Timer
|
||||
}
|
||||
|
||||
func newTokenManager(key string, miscDB *db.NamespacedKV, lifetime time.Duration, maxItems int) *tokenManager {
|
||||
tokens := &TokenSet{
|
||||
Tokens: make(map[string]int64),
|
||||
}
|
||||
if bs, ok, _ := miscDB.Bytes(key); ok {
|
||||
_ = tokens.Unmarshal(bs) // best effort
|
||||
}
|
||||
return &tokenManager{
|
||||
key: key,
|
||||
miscDB: miscDB,
|
||||
lifetime: lifetime,
|
||||
maxItems: maxItems,
|
||||
timeNow: time.Now,
|
||||
mut: sync.NewMutex(),
|
||||
tokens: tokens,
|
||||
}
|
||||
}
|
||||
|
||||
// Check returns true if the token is valid, and updates the token's expiry
|
||||
// time. The token is removed if it is expired.
|
||||
func (m *tokenManager) Check(token string) bool {
|
||||
m.mut.Lock()
|
||||
defer m.mut.Unlock()
|
||||
|
||||
expires, ok := m.tokens.Tokens[token]
|
||||
if ok {
|
||||
if expires < m.timeNow().UnixNano() {
|
||||
// The token is expired.
|
||||
m.saveLocked() // removes expired tokens
|
||||
return false
|
||||
}
|
||||
|
||||
// Give the token further life.
|
||||
m.tokens.Tokens[token] = m.timeNow().Add(m.lifetime).UnixNano()
|
||||
m.saveLocked()
|
||||
}
|
||||
return ok
|
||||
}
|
||||
|
||||
// New creates a new token and returns it.
|
||||
func (m *tokenManager) New() string {
|
||||
token := rand.String(randomTokenLength)
|
||||
|
||||
m.mut.Lock()
|
||||
defer m.mut.Unlock()
|
||||
|
||||
m.tokens.Tokens[token] = m.timeNow().Add(m.lifetime).UnixNano()
|
||||
m.saveLocked()
|
||||
|
||||
return token
|
||||
}
|
||||
|
||||
// Delete removes a token.
|
||||
func (m *tokenManager) Delete(token string) {
|
||||
m.mut.Lock()
|
||||
defer m.mut.Unlock()
|
||||
|
||||
delete(m.tokens.Tokens, token)
|
||||
m.saveLocked()
|
||||
}
|
||||
|
||||
func (m *tokenManager) saveLocked() {
|
||||
// Remove expired tokens.
|
||||
now := m.timeNow().UnixNano()
|
||||
for token, expiry := range m.tokens.Tokens {
|
||||
if expiry < now {
|
||||
delete(m.tokens.Tokens, token)
|
||||
}
|
||||
}
|
||||
|
||||
// If we have a limit on the number of tokens, remove the oldest ones.
|
||||
if m.maxItems > 0 && len(m.tokens.Tokens) > m.maxItems {
|
||||
// Sort the tokens by expiry time, oldest first.
|
||||
type tokenExpiry struct {
|
||||
token string
|
||||
expiry int64
|
||||
}
|
||||
var tokens []tokenExpiry
|
||||
for token, expiry := range m.tokens.Tokens {
|
||||
tokens = append(tokens, tokenExpiry{token, expiry})
|
||||
}
|
||||
slices.SortFunc(tokens, func(i, j tokenExpiry) int {
|
||||
return int(i.expiry - j.expiry)
|
||||
})
|
||||
// Remove the oldest tokens.
|
||||
for _, token := range tokens[:len(tokens)-m.maxItems] {
|
||||
delete(m.tokens.Tokens, token.token)
|
||||
}
|
||||
}
|
||||
|
||||
// Postpone saving until one second of inactivity.
|
||||
if m.saveTimer == nil {
|
||||
m.saveTimer = time.AfterFunc(time.Second, m.scheduledSave)
|
||||
} else {
|
||||
m.saveTimer.Reset(time.Second)
|
||||
}
|
||||
}
|
||||
|
||||
func (m *tokenManager) scheduledSave() {
|
||||
m.mut.Lock()
|
||||
defer m.mut.Unlock()
|
||||
|
||||
m.saveTimer = nil
|
||||
|
||||
bs, _ := m.tokens.Marshal() // can't fail
|
||||
_ = m.miscDB.PutBytes(m.key, bs) // can fail, but what are we going to do?
|
||||
}
|
||||
|
||||
type tokenCookieManager struct {
|
||||
cookieName string
|
||||
shortID string
|
||||
guiCfg config.GUIConfiguration
|
||||
evLogger events.Logger
|
||||
tokens *tokenManager
|
||||
}
|
||||
|
||||
func newTokenCookieManager(shortID string, guiCfg config.GUIConfiguration, evLogger events.Logger, miscDB *db.NamespacedKV) *tokenCookieManager {
|
||||
return &tokenCookieManager{
|
||||
cookieName: "sessionid-" + shortID,
|
||||
shortID: shortID,
|
||||
guiCfg: guiCfg,
|
||||
evLogger: evLogger,
|
||||
tokens: newTokenManager("sessions", miscDB, maxSessionLifetime, maxActiveSessions),
|
||||
}
|
||||
}
|
||||
|
||||
func (m *tokenCookieManager) createSession(username string, persistent bool, w http.ResponseWriter, r *http.Request) {
|
||||
sessionid := m.tokens.New()
|
||||
|
||||
// Best effort detection of whether the connection is HTTPS --
|
||||
// either directly to us, or as used by the client towards a reverse
|
||||
// proxy who sends us headers.
|
||||
connectionIsHTTPS := r.TLS != nil ||
|
||||
strings.ToLower(r.Header.Get("x-forwarded-proto")) == "https" ||
|
||||
strings.Contains(strings.ToLower(r.Header.Get("forwarded")), "proto=https")
|
||||
// If the connection is HTTPS, or *should* be HTTPS, set the Secure
|
||||
// bit in cookies.
|
||||
useSecureCookie := connectionIsHTTPS || m.guiCfg.UseTLS()
|
||||
|
||||
maxAge := 0
|
||||
if persistent {
|
||||
maxAge = int(maxSessionLifetime.Seconds())
|
||||
}
|
||||
http.SetCookie(w, &http.Cookie{
|
||||
Name: m.cookieName,
|
||||
Value: sessionid,
|
||||
// In HTTP spec Max-Age <= 0 means delete immediately,
|
||||
// but in http.Cookie MaxAge = 0 means unspecified (session) and MaxAge < 0 means delete immediately
|
||||
MaxAge: maxAge,
|
||||
Secure: useSecureCookie,
|
||||
Path: "/",
|
||||
})
|
||||
|
||||
emitLoginAttempt(true, username, r.RemoteAddr, m.evLogger)
|
||||
}
|
||||
|
||||
func (m *tokenCookieManager) hasValidSession(r *http.Request) bool {
|
||||
for _, cookie := range r.Cookies() {
|
||||
// We iterate here since there may, historically, be multiple
|
||||
// cookies with the same name but different path. Any "old" ones
|
||||
// won't match an existing session and will be ignored, then
|
||||
// later removed on logout or when timing out.
|
||||
if cookie.Name == m.cookieName {
|
||||
if m.tokens.Check(cookie.Value) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *tokenCookieManager) destroySession(w http.ResponseWriter, r *http.Request) {
|
||||
for _, cookie := range r.Cookies() {
|
||||
// We iterate here since there may, historically, be multiple
|
||||
// cookies with the same name but different path. We drop them
|
||||
// all.
|
||||
if cookie.Name == m.cookieName {
|
||||
m.tokens.Delete(cookie.Value)
|
||||
|
||||
// Create a cookie deletion command
|
||||
http.SetCookie(w, &http.Cookie{
|
||||
Name: m.cookieName,
|
||||
Value: "",
|
||||
MaxAge: -1,
|
||||
Secure: cookie.Secure,
|
||||
Path: cookie.Path,
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
411
lib/api/tokenset.pb.go
Normal file
411
lib/api/tokenset.pb.go
Normal file
@@ -0,0 +1,411 @@
|
||||
// Code generated by protoc-gen-gogo. DO NOT EDIT.
|
||||
// source: lib/api/tokenset.proto
|
||||
|
||||
package api
|
||||
|
||||
import (
|
||||
fmt "fmt"
|
||||
proto "github.com/gogo/protobuf/proto"
|
||||
io "io"
|
||||
math "math"
|
||||
math_bits "math/bits"
|
||||
)
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
var _ = proto.Marshal
|
||||
var _ = fmt.Errorf
|
||||
var _ = math.Inf
|
||||
|
||||
// This is a compile-time assertion to ensure that this generated file
|
||||
// is compatible with the proto package it is being compiled against.
|
||||
// A compilation error at this line likely means your copy of the
|
||||
// proto package needs to be updated.
|
||||
const _ = proto.GoGoProtoPackageIsVersion3 // please upgrade the proto package
|
||||
|
||||
type TokenSet struct {
|
||||
// token -> expiry time (epoch nanoseconds)
|
||||
Tokens map[string]int64 `protobuf:"bytes,1,rep,name=tokens,proto3" json:"tokens" xml:"token" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"varint,2,opt,name=value,proto3"`
|
||||
}
|
||||
|
||||
func (m *TokenSet) Reset() { *m = TokenSet{} }
|
||||
func (m *TokenSet) String() string { return proto.CompactTextString(m) }
|
||||
func (*TokenSet) ProtoMessage() {}
|
||||
func (*TokenSet) Descriptor() ([]byte, []int) {
|
||||
return fileDescriptor_9ea8707737c33b38, []int{0}
|
||||
}
|
||||
func (m *TokenSet) XXX_Unmarshal(b []byte) error {
|
||||
return m.Unmarshal(b)
|
||||
}
|
||||
func (m *TokenSet) XXX_Marshal(b []byte, deterministic bool) ([]byte, error) {
|
||||
if deterministic {
|
||||
return xxx_messageInfo_TokenSet.Marshal(b, m, deterministic)
|
||||
} else {
|
||||
b = b[:cap(b)]
|
||||
n, err := m.MarshalToSizedBuffer(b)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return b[:n], nil
|
||||
}
|
||||
}
|
||||
func (m *TokenSet) XXX_Merge(src proto.Message) {
|
||||
xxx_messageInfo_TokenSet.Merge(m, src)
|
||||
}
|
||||
func (m *TokenSet) XXX_Size() int {
|
||||
return m.ProtoSize()
|
||||
}
|
||||
func (m *TokenSet) XXX_DiscardUnknown() {
|
||||
xxx_messageInfo_TokenSet.DiscardUnknown(m)
|
||||
}
|
||||
|
||||
var xxx_messageInfo_TokenSet proto.InternalMessageInfo
|
||||
|
||||
func init() {
|
||||
proto.RegisterType((*TokenSet)(nil), "api.TokenSet")
|
||||
proto.RegisterMapType((map[string]int64)(nil), "api.TokenSet.TokensEntry")
|
||||
}
|
||||
|
||||
func init() { proto.RegisterFile("lib/api/tokenset.proto", fileDescriptor_9ea8707737c33b38) }
|
||||
|
||||
var fileDescriptor_9ea8707737c33b38 = []byte{
|
||||
// 260 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0x12, 0xcb, 0xc9, 0x4c, 0xd2,
|
||||
0x4f, 0x2c, 0xc8, 0xd4, 0x2f, 0xc9, 0xcf, 0x4e, 0xcd, 0x2b, 0x4e, 0x2d, 0xd1, 0x2b, 0x28, 0xca,
|
||||
0x2f, 0xc9, 0x17, 0x62, 0x4e, 0x2c, 0xc8, 0x54, 0x3a, 0xce, 0xc8, 0xc5, 0x11, 0x02, 0x12, 0x0f,
|
||||
0x4e, 0x2d, 0x11, 0x0a, 0xe0, 0x62, 0x83, 0xa8, 0x91, 0x60, 0x54, 0x60, 0xd6, 0xe0, 0x36, 0x92,
|
||||
0xd4, 0x4b, 0x2c, 0xc8, 0xd4, 0x83, 0x49, 0x43, 0x18, 0xc5, 0xae, 0x79, 0x25, 0x45, 0x95, 0x4e,
|
||||
0xb2, 0x27, 0xee, 0xc9, 0x33, 0xbc, 0xba, 0x27, 0x0f, 0xd5, 0xf0, 0xe9, 0x9e, 0x3c, 0x77, 0x45,
|
||||
0x6e, 0x8e, 0x95, 0x12, 0x98, 0xab, 0x14, 0x04, 0x15, 0x96, 0xca, 0xe4, 0xe2, 0x46, 0xd2, 0x25,
|
||||
0xa4, 0xc6, 0xc5, 0x9c, 0x9d, 0x5a, 0x29, 0xc1, 0xa8, 0xc0, 0xa8, 0xc1, 0xe9, 0x24, 0xf2, 0xea,
|
||||
0x9e, 0x3c, 0x88, 0xfb, 0xe9, 0x9e, 0x3c, 0x27, 0x58, 0x6f, 0x76, 0x6a, 0xa5, 0x52, 0x10, 0x48,
|
||||
0x44, 0x48, 0x8f, 0x8b, 0xb5, 0x2c, 0x31, 0xa7, 0x34, 0x55, 0x82, 0x49, 0x81, 0x51, 0x83, 0xd9,
|
||||
0x49, 0xe2, 0xd5, 0x3d, 0x79, 0x88, 0x00, 0xdc, 0x1e, 0x30, 0x4f, 0x29, 0x08, 0x22, 0x6a, 0xc5,
|
||||
0x64, 0xc1, 0xe8, 0xe4, 0x71, 0xe2, 0xa1, 0x1c, 0xc3, 0x85, 0x87, 0x72, 0x0c, 0x27, 0x1e, 0xc9,
|
||||
0x31, 0x5e, 0x78, 0x24, 0xc7, 0x38, 0xe1, 0xb1, 0x1c, 0xc3, 0x82, 0xc7, 0x72, 0x8c, 0x17, 0x1e,
|
||||
0xcb, 0x31, 0xdc, 0x78, 0x2c, 0xc7, 0x10, 0xa5, 0x96, 0x9e, 0x59, 0x92, 0x51, 0x9a, 0xa4, 0x97,
|
||||
0x9c, 0x9f, 0xab, 0x5f, 0x5c, 0x99, 0x97, 0x5c, 0x92, 0x91, 0x99, 0x97, 0x8e, 0xc4, 0x82, 0x86,
|
||||
0x53, 0x12, 0x1b, 0x38, 0x7c, 0x8c, 0x01, 0x01, 0x00, 0x00, 0xff, 0xff, 0xfe, 0x25, 0x31, 0x49,
|
||||
0x39, 0x01, 0x00, 0x00,
|
||||
}
|
||||
|
||||
func (m *TokenSet) Marshal() (dAtA []byte, err error) {
|
||||
size := m.ProtoSize()
|
||||
dAtA = make([]byte, size)
|
||||
n, err := m.MarshalToSizedBuffer(dAtA[:size])
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return dAtA[:n], nil
|
||||
}
|
||||
|
||||
func (m *TokenSet) MarshalTo(dAtA []byte) (int, error) {
|
||||
size := m.ProtoSize()
|
||||
return m.MarshalToSizedBuffer(dAtA[:size])
|
||||
}
|
||||
|
||||
func (m *TokenSet) MarshalToSizedBuffer(dAtA []byte) (int, error) {
|
||||
i := len(dAtA)
|
||||
_ = i
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Tokens) > 0 {
|
||||
for k := range m.Tokens {
|
||||
v := m.Tokens[k]
|
||||
baseI := i
|
||||
i = encodeVarintTokenset(dAtA, i, uint64(v))
|
||||
i--
|
||||
dAtA[i] = 0x10
|
||||
i -= len(k)
|
||||
copy(dAtA[i:], k)
|
||||
i = encodeVarintTokenset(dAtA, i, uint64(len(k)))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
i = encodeVarintTokenset(dAtA, i, uint64(baseI-i))
|
||||
i--
|
||||
dAtA[i] = 0xa
|
||||
}
|
||||
}
|
||||
return len(dAtA) - i, nil
|
||||
}
|
||||
|
||||
func encodeVarintTokenset(dAtA []byte, offset int, v uint64) int {
|
||||
offset -= sovTokenset(v)
|
||||
base := offset
|
||||
for v >= 1<<7 {
|
||||
dAtA[offset] = uint8(v&0x7f | 0x80)
|
||||
v >>= 7
|
||||
offset++
|
||||
}
|
||||
dAtA[offset] = uint8(v)
|
||||
return base
|
||||
}
|
||||
func (m *TokenSet) ProtoSize() (n int) {
|
||||
if m == nil {
|
||||
return 0
|
||||
}
|
||||
var l int
|
||||
_ = l
|
||||
if len(m.Tokens) > 0 {
|
||||
for k, v := range m.Tokens {
|
||||
_ = k
|
||||
_ = v
|
||||
mapEntrySize := 1 + len(k) + sovTokenset(uint64(len(k))) + 1 + sovTokenset(uint64(v))
|
||||
n += mapEntrySize + 1 + sovTokenset(uint64(mapEntrySize))
|
||||
}
|
||||
}
|
||||
return n
|
||||
}
|
||||
|
||||
func sovTokenset(x uint64) (n int) {
|
||||
return (math_bits.Len64(x|1) + 6) / 7
|
||||
}
|
||||
func sozTokenset(x uint64) (n int) {
|
||||
return sovTokenset(uint64((x << 1) ^ uint64((int64(x) >> 63))))
|
||||
}
|
||||
func (m *TokenSet) Unmarshal(dAtA []byte) error {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
for iNdEx < l {
|
||||
preIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTokenset
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
wireType := int(wire & 0x7)
|
||||
if wireType == 4 {
|
||||
return fmt.Errorf("proto: TokenSet: wiretype end group for non-group")
|
||||
}
|
||||
if fieldNum <= 0 {
|
||||
return fmt.Errorf("proto: TokenSet: illegal tag %d (wire type %d)", fieldNum, wire)
|
||||
}
|
||||
switch fieldNum {
|
||||
case 1:
|
||||
if wireType != 2 {
|
||||
return fmt.Errorf("proto: wrong wireType = %d for field Tokens", wireType)
|
||||
}
|
||||
var msglen int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTokenset
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
msglen |= int(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if msglen < 0 {
|
||||
return ErrInvalidLengthTokenset
|
||||
}
|
||||
postIndex := iNdEx + msglen
|
||||
if postIndex < 0 {
|
||||
return ErrInvalidLengthTokenset
|
||||
}
|
||||
if postIndex > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
if m.Tokens == nil {
|
||||
m.Tokens = make(map[string]int64)
|
||||
}
|
||||
var mapkey string
|
||||
var mapvalue int64
|
||||
for iNdEx < postIndex {
|
||||
entryPreIndex := iNdEx
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTokenset
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
fieldNum := int32(wire >> 3)
|
||||
if fieldNum == 1 {
|
||||
var stringLenmapkey uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTokenset
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
stringLenmapkey |= uint64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
intStringLenmapkey := int(stringLenmapkey)
|
||||
if intStringLenmapkey < 0 {
|
||||
return ErrInvalidLengthTokenset
|
||||
}
|
||||
postStringIndexmapkey := iNdEx + intStringLenmapkey
|
||||
if postStringIndexmapkey < 0 {
|
||||
return ErrInvalidLengthTokenset
|
||||
}
|
||||
if postStringIndexmapkey > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
mapkey = string(dAtA[iNdEx:postStringIndexmapkey])
|
||||
iNdEx = postStringIndexmapkey
|
||||
} else if fieldNum == 2 {
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return ErrIntOverflowTokenset
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
mapvalue |= int64(b&0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
} else {
|
||||
iNdEx = entryPreIndex
|
||||
skippy, err := skipTokenset(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthTokenset
|
||||
}
|
||||
if (iNdEx + skippy) > postIndex {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
m.Tokens[mapkey] = mapvalue
|
||||
iNdEx = postIndex
|
||||
default:
|
||||
iNdEx = preIndex
|
||||
skippy, err := skipTokenset(dAtA[iNdEx:])
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if (skippy < 0) || (iNdEx+skippy) < 0 {
|
||||
return ErrInvalidLengthTokenset
|
||||
}
|
||||
if (iNdEx + skippy) > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx += skippy
|
||||
}
|
||||
}
|
||||
|
||||
if iNdEx > l {
|
||||
return io.ErrUnexpectedEOF
|
||||
}
|
||||
return nil
|
||||
}
|
||||
func skipTokenset(dAtA []byte) (n int, err error) {
|
||||
l := len(dAtA)
|
||||
iNdEx := 0
|
||||
depth := 0
|
||||
for iNdEx < l {
|
||||
var wire uint64
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowTokenset
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
wire |= (uint64(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
wireType := int(wire & 0x7)
|
||||
switch wireType {
|
||||
case 0:
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowTokenset
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
iNdEx++
|
||||
if dAtA[iNdEx-1] < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
case 1:
|
||||
iNdEx += 8
|
||||
case 2:
|
||||
var length int
|
||||
for shift := uint(0); ; shift += 7 {
|
||||
if shift >= 64 {
|
||||
return 0, ErrIntOverflowTokenset
|
||||
}
|
||||
if iNdEx >= l {
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
b := dAtA[iNdEx]
|
||||
iNdEx++
|
||||
length |= (int(b) & 0x7F) << shift
|
||||
if b < 0x80 {
|
||||
break
|
||||
}
|
||||
}
|
||||
if length < 0 {
|
||||
return 0, ErrInvalidLengthTokenset
|
||||
}
|
||||
iNdEx += length
|
||||
case 3:
|
||||
depth++
|
||||
case 4:
|
||||
if depth == 0 {
|
||||
return 0, ErrUnexpectedEndOfGroupTokenset
|
||||
}
|
||||
depth--
|
||||
case 5:
|
||||
iNdEx += 4
|
||||
default:
|
||||
return 0, fmt.Errorf("proto: illegal wireType %d", wireType)
|
||||
}
|
||||
if iNdEx < 0 {
|
||||
return 0, ErrInvalidLengthTokenset
|
||||
}
|
||||
if depth == 0 {
|
||||
return iNdEx, nil
|
||||
}
|
||||
}
|
||||
return 0, io.ErrUnexpectedEOF
|
||||
}
|
||||
|
||||
var (
|
||||
ErrInvalidLengthTokenset = fmt.Errorf("proto: negative length found during unmarshaling")
|
||||
ErrIntOverflowTokenset = fmt.Errorf("proto: integer overflow")
|
||||
ErrUnexpectedEndOfGroupTokenset = fmt.Errorf("proto: unexpected end of group")
|
||||
)
|
||||
15
lib/automaxprocs/automaxprocs.go
Normal file
15
lib/automaxprocs/automaxprocs.go
Normal file
@@ -0,0 +1,15 @@
|
||||
// Copyright (C) 2024 The Syncthing Authors.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
package automaxprocs
|
||||
|
||||
import (
|
||||
"go.uber.org/automaxprocs/maxprocs"
|
||||
)
|
||||
|
||||
func init() {
|
||||
maxprocs.Set()
|
||||
}
|
||||
@@ -36,7 +36,7 @@ var (
|
||||
LongVersion string
|
||||
Extra string
|
||||
|
||||
allowedVersionExp = regexp.MustCompile(`^v\d+\.\d+\.\d+(-[a-z0-9]+)*(\.\d+)*(\+\d+-g[0-9a-f]+)?(-[^\s]+)?$`)
|
||||
allowedVersionExp = regexp.MustCompile(`^v\d+\.\d+\.\d+(-[a-z0-9]+)*(\.\d+)*(\+\d+-g[0-9a-f]+|\+[0-9a-z]+)?(-[^\s]+)?$`)
|
||||
|
||||
envTags = []string{
|
||||
"STGUIASSETS",
|
||||
|
||||
@@ -27,6 +27,11 @@ func TestAllowedVersions(t *testing.T) {
|
||||
{"v0.13.0-some-weird-but-allowed-tag", true},
|
||||
{"v0.13.0-allowed.to.do.this", true},
|
||||
{"v0.13.0+not.allowed.to.do.this", false},
|
||||
{"v1.27.0+xyz", true},
|
||||
{"v1.27.0-abc.1+xyz", true},
|
||||
{"v1.0.0+45", true},
|
||||
{"v1.0.0-noupgrade", true},
|
||||
{"v1.0.0+noupgrade", true},
|
||||
}
|
||||
|
||||
for i, c := range testcases {
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
//go:build go1.15 && !noquic
|
||||
// +build go1.15,!noquic
|
||||
//go:build !noquic
|
||||
// +build !noquic
|
||||
|
||||
package connections
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
//go:build go1.15 && !noquic
|
||||
// +build go1.15,!noquic
|
||||
//go:build !noquic
|
||||
// +build !noquic
|
||||
|
||||
package connections
|
||||
|
||||
|
||||
@@ -4,8 +4,8 @@
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at http://mozilla.org/MPL/2.0/.
|
||||
|
||||
//go:build noquic || !go1.15
|
||||
// +build noquic !go1.15
|
||||
//go:build noquic
|
||||
// +build noquic
|
||||
|
||||
package connections
|
||||
|
||||
|
||||
@@ -22,14 +22,12 @@ import (
|
||||
"math"
|
||||
"net"
|
||||
"net/url"
|
||||
"slices"
|
||||
"sort"
|
||||
"strings"
|
||||
stdsync "sync"
|
||||
"time"
|
||||
|
||||
"golang.org/x/exp/constraints"
|
||||
"golang.org/x/exp/slices"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/build"
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/connections/registry"
|
||||
@@ -1468,20 +1466,3 @@ func newConnectionID(t0, t1 int64) string {
|
||||
// from the random. We want the timestamp part deterministic.
|
||||
return enc.EncodeToString(buf[:8]) + enc.EncodeToString(buf[8:])
|
||||
}
|
||||
|
||||
// temporary implementations of min and max, to be removed once we can use
|
||||
// Go 1.21 builtins. :)
|
||||
|
||||
func min[T constraints.Ordered](a, b T) T {
|
||||
if a < b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
func max[T constraints.Ordered](a, b T) T {
|
||||
if a > b {
|
||||
return a
|
||||
}
|
||||
return b
|
||||
}
|
||||
|
||||
@@ -338,17 +338,22 @@ func (s *Snapshot) Sequence(device protocol.DeviceID) int64 {
|
||||
return s.meta.Counts(device, 0).Sequence
|
||||
}
|
||||
|
||||
// RemoteSequence returns the change version for the given folder, as
|
||||
// sent by remote peers. This is guaranteed to increment if the contents of
|
||||
// the remote or global folder has changed.
|
||||
func (s *Snapshot) RemoteSequence() int64 {
|
||||
var ver int64
|
||||
|
||||
// RemoteSequences returns a map of the sequence numbers seen for each
|
||||
// remote device sharing this folder.
|
||||
func (s *Snapshot) RemoteSequences() map[protocol.DeviceID]int64 {
|
||||
res := make(map[protocol.DeviceID]int64)
|
||||
for _, device := range s.meta.devices() {
|
||||
ver += s.Sequence(device)
|
||||
switch device {
|
||||
case protocol.EmptyDeviceID, protocol.LocalDeviceID, protocol.GlobalDeviceID:
|
||||
continue
|
||||
default:
|
||||
if seq := s.Sequence(device); seq > 0 {
|
||||
res[device] = seq
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return ver
|
||||
return res
|
||||
}
|
||||
|
||||
func (s *Snapshot) LocalSize() Counts {
|
||||
|
||||
@@ -22,11 +22,10 @@ type FileInfoBatch struct {
|
||||
flushFn func([]protocol.FileInfo) error
|
||||
}
|
||||
|
||||
// NewFileInfoBatch returns a new FileInfoBatch that calls fn when it's time
|
||||
// to flush.
|
||||
func NewFileInfoBatch(fn func([]protocol.FileInfo) error) *FileInfoBatch {
|
||||
return &FileInfoBatch{
|
||||
infos: make([]protocol.FileInfo, 0, MaxBatchSizeFiles),
|
||||
flushFn: fn,
|
||||
}
|
||||
return &FileInfoBatch{flushFn: fn}
|
||||
}
|
||||
|
||||
func (b *FileInfoBatch) SetFlushFunc(fn func([]protocol.FileInfo) error) {
|
||||
@@ -34,6 +33,9 @@ func (b *FileInfoBatch) SetFlushFunc(fn func([]protocol.FileInfo) error) {
|
||||
}
|
||||
|
||||
func (b *FileInfoBatch) Append(f protocol.FileInfo) {
|
||||
if b.infos == nil {
|
||||
b.infos = make([]protocol.FileInfo, 0, MaxBatchSizeFiles)
|
||||
}
|
||||
b.infos = append(b.infos, f)
|
||||
b.size += f.ProtoSize()
|
||||
}
|
||||
@@ -61,7 +63,7 @@ func (b *FileInfoBatch) Flush() error {
|
||||
}
|
||||
|
||||
func (b *FileInfoBatch) Reset() {
|
||||
b.infos = b.infos[:0]
|
||||
b.infos = nil
|
||||
b.size = 0
|
||||
}
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@ package fs
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"unicode/utf8"
|
||||
|
||||
"github.com/syncthing/notify"
|
||||
)
|
||||
@@ -37,18 +38,18 @@ func (f *BasicFilesystem) Watch(name string, ignore Matcher, ctx context.Context
|
||||
eventMask |= permEventMask
|
||||
}
|
||||
|
||||
if ignore.SkipIgnoredDirs() {
|
||||
absShouldIgnore := func(absPath string) bool {
|
||||
rel, err := f.unrootedChecked(absPath, roots)
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
return ignore.ShouldIgnore(rel)
|
||||
absShouldIgnore := func(absPath string) bool {
|
||||
if !utf8.ValidString(absPath) {
|
||||
return true
|
||||
}
|
||||
err = notify.WatchWithFilter(watchPath, backendChan, absShouldIgnore, eventMask)
|
||||
} else {
|
||||
err = notify.Watch(watchPath, backendChan, eventMask)
|
||||
|
||||
rel, err := f.unrootedChecked(absPath, roots)
|
||||
if err != nil {
|
||||
return true
|
||||
}
|
||||
return ignore.Match(rel).CanSkipDir()
|
||||
}
|
||||
err = notify.WatchWithFilter(watchPath, backendChan, absShouldIgnore, eventMask)
|
||||
if err != nil {
|
||||
notify.Stop(backendChan)
|
||||
if reachedMaxUserWatches(err) {
|
||||
@@ -82,7 +83,14 @@ func (f *BasicFilesystem) watchLoop(ctx context.Context, name string, roots []st
|
||||
|
||||
select {
|
||||
case ev := <-backendChan:
|
||||
relPath, err := f.unrootedChecked(ev.Path(), roots)
|
||||
evPath := ev.Path()
|
||||
|
||||
if !utf8.ValidString(evPath) {
|
||||
l.Debugln(f.Type(), f.URI(), "Watch: Ignoring invalid UTF-8")
|
||||
continue
|
||||
}
|
||||
|
||||
relPath, err := f.unrootedChecked(evPath, roots)
|
||||
if err != nil {
|
||||
select {
|
||||
case errChan <- err:
|
||||
@@ -94,7 +102,7 @@ func (f *BasicFilesystem) watchLoop(ctx context.Context, name string, roots []st
|
||||
return
|
||||
}
|
||||
|
||||
if ignore.ShouldIgnore(relPath) {
|
||||
if ignore.Match(relPath).IsIgnored() {
|
||||
l.Debugln(f.Type(), f.URI(), "Watch: Ignoring", relPath)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -23,6 +23,7 @@ import (
|
||||
|
||||
"github.com/syncthing/notify"
|
||||
"github.com/syncthing/syncthing/lib/build"
|
||||
"github.com/syncthing/syncthing/lib/ignore/ignoreresult"
|
||||
)
|
||||
|
||||
func TestMain(m *testing.M) {
|
||||
@@ -99,7 +100,7 @@ func TestWatchInclude(t *testing.T) {
|
||||
|
||||
file := "file"
|
||||
ignored := "ignored"
|
||||
testFs.MkdirAll(filepath.Join(name, ignored), 0777)
|
||||
testFs.MkdirAll(filepath.Join(name, ignored), 0o777)
|
||||
included := filepath.Join(ignored, "included")
|
||||
|
||||
testCase := func() {
|
||||
@@ -317,12 +318,12 @@ func TestWatchErrorLinuxInterpretation(t *testing.T) {
|
||||
t.Skip("testing of linux specific error codes")
|
||||
}
|
||||
|
||||
var errTooManyFiles = &os.PathError{
|
||||
errTooManyFiles := &os.PathError{
|
||||
Op: "error while traversing",
|
||||
Path: "foo",
|
||||
Err: syscall.Errno(24),
|
||||
}
|
||||
var errNoSpace = &os.PathError{
|
||||
errNoSpace := &os.PathError{
|
||||
Op: "error while traversing",
|
||||
Path: "bar",
|
||||
Err: syscall.Errno(28),
|
||||
@@ -346,13 +347,13 @@ func TestWatchSymlinkedRoot(t *testing.T) {
|
||||
}
|
||||
|
||||
name := "symlinkedRoot"
|
||||
if err := testFs.MkdirAll(name, 0755); err != nil {
|
||||
if err := testFs.MkdirAll(name, 0o755); err != nil {
|
||||
panic(fmt.Sprintf("Failed to create directory %s: %s", name, err))
|
||||
}
|
||||
defer testFs.RemoveAll(name)
|
||||
|
||||
root := filepath.Join(name, "root")
|
||||
if err := testFs.MkdirAll(root, 0777); err != nil {
|
||||
if err := testFs.MkdirAll(root, 0o777); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
link := filepath.Join(name, "link")
|
||||
@@ -369,7 +370,7 @@ func TestWatchSymlinkedRoot(t *testing.T) {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
if err := linkedFs.MkdirAll("foo", 0777); err != nil {
|
||||
if err := linkedFs.MkdirAll("foo", 0o777); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
@@ -507,7 +508,7 @@ func TestTruncateFileOnly(t *testing.T) {
|
||||
// path relative to folder root, also creates parent dirs if necessary
|
||||
func createTestFile(name string, file string) string {
|
||||
joined := filepath.Join(name, file)
|
||||
if err := testFs.MkdirAll(filepath.Dir(joined), 0755); err != nil {
|
||||
if err := testFs.MkdirAll(filepath.Dir(joined), 0o755); err != nil {
|
||||
panic(fmt.Sprintf("Failed to create parent directory for %s: %s", joined, err))
|
||||
}
|
||||
handle, err := testFs.Create(joined)
|
||||
@@ -529,7 +530,7 @@ func renameTestFile(name string, old string, new string) {
|
||||
func modifyTestFile(name string, file string, content string) {
|
||||
joined := filepath.Join(testDirAbs, name, file)
|
||||
|
||||
err := os.WriteFile(joined, []byte(content), 0755)
|
||||
err := os.WriteFile(joined, []byte(content), 0o755)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("Failed to modify test file %s: %s", joined, err))
|
||||
}
|
||||
@@ -540,7 +541,7 @@ func sleepMs(ms int) {
|
||||
}
|
||||
|
||||
func testScenario(t *testing.T, name string, testCase func(), expectedEvents, allowedEvents []Event, fm fakeMatcher, ignorePerms bool) {
|
||||
if err := testFs.MkdirAll(name, 0755); err != nil {
|
||||
if err := testFs.MkdirAll(name, 0o755); err != nil {
|
||||
panic(fmt.Sprintf("Failed to create directory %s: %s", name, err))
|
||||
}
|
||||
defer testFs.RemoveAll(name)
|
||||
@@ -567,7 +568,7 @@ func testScenario(t *testing.T, name string, testCase func(), expectedEvents, al
|
||||
}
|
||||
|
||||
func testWatchOutput(t *testing.T, name string, in <-chan Event, expectedEvents, allowedEvents []Event, ctx context.Context, cancel context.CancelFunc) {
|
||||
var expected = make(map[Event]struct{})
|
||||
expected := make(map[Event]struct{})
|
||||
for _, ev := range expectedEvents {
|
||||
ev.Name = filepath.Join(name, ev.Name)
|
||||
expected[ev] = struct{}{}
|
||||
@@ -613,8 +614,11 @@ type fakeMatcher struct {
|
||||
skipIgnoredDirs bool
|
||||
}
|
||||
|
||||
func (fm fakeMatcher) ShouldIgnore(name string) bool {
|
||||
return name != fm.include && name == fm.ignore
|
||||
func (fm fakeMatcher) Match(name string) ignoreresult.R {
|
||||
if name != fm.include && name == fm.ignore {
|
||||
return ignoreresult.Ignored
|
||||
}
|
||||
return ignoreresult.NotIgnored
|
||||
}
|
||||
|
||||
func (fm fakeMatcher) SkipIgnoredDirs() bool {
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/ignore/ignoreresult"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
)
|
||||
|
||||
@@ -127,12 +128,7 @@ type Usage struct {
|
||||
}
|
||||
|
||||
type Matcher interface {
|
||||
ShouldIgnore(name string) bool
|
||||
SkipIgnoredDirs() bool
|
||||
}
|
||||
|
||||
type MatchResult interface {
|
||||
IsIgnored() bool
|
||||
Match(name string) ignoreresult.R
|
||||
}
|
||||
|
||||
type Event struct {
|
||||
|
||||
@@ -6,7 +6,11 @@
|
||||
|
||||
package ignore
|
||||
|
||||
import "time"
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/ignore/ignoreresult"
|
||||
)
|
||||
|
||||
type nower interface {
|
||||
Now() time.Time
|
||||
@@ -20,7 +24,7 @@ type cache struct {
|
||||
}
|
||||
|
||||
type cacheEntry struct {
|
||||
result Result
|
||||
result ignoreresult.R
|
||||
access int64 // Unix nanosecond count. Sufficient until the year 2262.
|
||||
}
|
||||
|
||||
@@ -39,7 +43,7 @@ func (c *cache) clean(d time.Duration) {
|
||||
}
|
||||
}
|
||||
|
||||
func (c *cache) get(key string) (Result, bool) {
|
||||
func (c *cache) get(key string) (ignoreresult.R, bool) {
|
||||
entry, ok := c.entries[key]
|
||||
if ok {
|
||||
entry.access = clock.Now().UnixNano()
|
||||
@@ -48,7 +52,7 @@ func (c *cache) get(key string) (Result, bool) {
|
||||
return entry.result, ok
|
||||
}
|
||||
|
||||
func (c *cache) set(key string, result Result) {
|
||||
func (c *cache) set(key string, result ignoreresult.R) {
|
||||
c.entries[key] = cacheEntry{result, time.Now().UnixNano()}
|
||||
}
|
||||
|
||||
|
||||
@@ -9,6 +9,8 @@ package ignore
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/ignore/ignoreresult"
|
||||
)
|
||||
|
||||
func TestCache(t *testing.T) {
|
||||
@@ -28,7 +30,7 @@ func TestCache(t *testing.T) {
|
||||
|
||||
// Set and check some items
|
||||
|
||||
c.set("true", resultInclude|resultDeletable)
|
||||
c.set("true", ignoreresult.IgnoredDeletable)
|
||||
c.set("false", 0)
|
||||
|
||||
res, ok = c.get("true")
|
||||
|
||||
@@ -18,28 +18,13 @@ import (
|
||||
|
||||
"github.com/gobwas/glob"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/build"
|
||||
"github.com/syncthing/syncthing/lib/fs"
|
||||
"github.com/syncthing/syncthing/lib/ignore/ignoreresult"
|
||||
"github.com/syncthing/syncthing/lib/osutil"
|
||||
"github.com/syncthing/syncthing/lib/sha256"
|
||||
"github.com/syncthing/syncthing/lib/sync"
|
||||
)
|
||||
|
||||
const (
|
||||
resultNotMatched Result = 0
|
||||
resultInclude Result = 1 << iota
|
||||
resultDeletable = 1 << iota
|
||||
resultFoldCase = 1 << iota
|
||||
)
|
||||
|
||||
var defaultResult Result = resultInclude
|
||||
|
||||
func init() {
|
||||
if build.IsDarwin || build.IsWindows {
|
||||
defaultResult |= resultFoldCase
|
||||
}
|
||||
}
|
||||
|
||||
// A ParseError signifies an error with contents of an ignore file,
|
||||
// including I/O errors on included files. An I/O error on the root level
|
||||
// ignore file is not a ParseError.
|
||||
@@ -70,18 +55,18 @@ func parseError(err error) error {
|
||||
type Pattern struct {
|
||||
pattern string
|
||||
match glob.Glob
|
||||
result Result
|
||||
result ignoreresult.R
|
||||
}
|
||||
|
||||
func (p Pattern) String() string {
|
||||
ret := p.pattern
|
||||
if p.result&resultInclude != resultInclude {
|
||||
if !p.result.IsIgnored() {
|
||||
ret = "!" + ret
|
||||
}
|
||||
if p.result&resultFoldCase == resultFoldCase {
|
||||
if p.result.IsCaseFolded() {
|
||||
ret = "(?i)" + ret
|
||||
}
|
||||
if p.result&resultDeletable == resultDeletable {
|
||||
if p.result.IsDeletable() {
|
||||
ret = "(?d)" + ret
|
||||
}
|
||||
return ret
|
||||
@@ -94,25 +79,17 @@ func (p Pattern) allowsSkippingIgnoredDirs() bool {
|
||||
if p.pattern[0] != '/' {
|
||||
return false
|
||||
}
|
||||
if strings.Contains(p.pattern[1:], "/") {
|
||||
// A "/**" at the end is allowed and doesn't have any bearing on the
|
||||
// below checks; remove it before checking.
|
||||
pattern := strings.TrimSuffix(p.pattern, "/**")
|
||||
if len(pattern) == 0 {
|
||||
return true
|
||||
}
|
||||
if strings.Contains(pattern[1:], "/") {
|
||||
return false
|
||||
}
|
||||
// Double asterisk everywhere in the path except at the end is bad
|
||||
return !strings.Contains(strings.TrimSuffix(p.pattern, "**"), "**")
|
||||
}
|
||||
|
||||
type Result uint8
|
||||
|
||||
func (r Result) IsIgnored() bool {
|
||||
return r&resultInclude == resultInclude
|
||||
}
|
||||
|
||||
func (r Result) IsDeletable() bool {
|
||||
return r.IsIgnored() && r&resultDeletable == resultDeletable
|
||||
}
|
||||
|
||||
func (r Result) IsCaseFolded() bool {
|
||||
return r&resultFoldCase == resultFoldCase
|
||||
return !strings.Contains(strings.TrimSuffix(pattern, "**"), "**")
|
||||
}
|
||||
|
||||
// The ChangeDetector is responsible for determining if files have changed
|
||||
@@ -128,16 +105,15 @@ type ChangeDetector interface {
|
||||
}
|
||||
|
||||
type Matcher struct {
|
||||
fs fs.Filesystem
|
||||
lines []string // exact lines read from .stignore
|
||||
patterns []Pattern // patterns including those from included files
|
||||
withCache bool
|
||||
matches *cache
|
||||
curHash string
|
||||
stop chan struct{}
|
||||
changeDetector ChangeDetector
|
||||
skipIgnoredDirs bool
|
||||
mut sync.Mutex
|
||||
fs fs.Filesystem
|
||||
lines []string // exact lines read from .stignore
|
||||
patterns []Pattern // patterns including those from included files
|
||||
withCache bool
|
||||
matches *cache
|
||||
curHash string
|
||||
stop chan struct{}
|
||||
changeDetector ChangeDetector
|
||||
mut sync.Mutex
|
||||
}
|
||||
|
||||
// An Option can be passed to New()
|
||||
@@ -160,10 +136,9 @@ func WithChangeDetector(cd ChangeDetector) Option {
|
||||
|
||||
func New(fs fs.Filesystem, opts ...Option) *Matcher {
|
||||
m := &Matcher{
|
||||
fs: fs,
|
||||
stop: make(chan struct{}),
|
||||
mut: sync.NewMutex(),
|
||||
skipIgnoredDirs: true,
|
||||
fs: fs,
|
||||
stop: make(chan struct{}),
|
||||
mut: sync.NewMutex(),
|
||||
}
|
||||
for _, opt := range opts {
|
||||
opt(m)
|
||||
@@ -227,23 +202,6 @@ func (m *Matcher) parseLocked(r io.Reader, file string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
m.skipIgnoredDirs = true
|
||||
var previous string
|
||||
for _, p := range patterns {
|
||||
// We automatically add patterns with a /** suffix, which normally
|
||||
// means that we cannot skip directories. However if the same
|
||||
// pattern without the /** already exists (which is true for
|
||||
// automatically added patterns) we can skip.
|
||||
if l := len(p.pattern); l > 3 && p.pattern[:len(p.pattern)-3] == previous {
|
||||
continue
|
||||
}
|
||||
if !p.allowsSkippingIgnoredDirs() {
|
||||
m.skipIgnoredDirs = false
|
||||
break
|
||||
}
|
||||
previous = p.pattern
|
||||
}
|
||||
|
||||
m.curHash = newHash
|
||||
m.patterns = patterns
|
||||
if m.withCache {
|
||||
@@ -253,16 +211,24 @@ func (m *Matcher) parseLocked(r io.Reader, file string) error {
|
||||
return err
|
||||
}
|
||||
|
||||
func (m *Matcher) Match(file string) (result Result) {
|
||||
if file == "." {
|
||||
return resultNotMatched
|
||||
// Match matches the patterns plus temporary and internal files.
|
||||
func (m *Matcher) Match(file string) (result ignoreresult.R) {
|
||||
switch {
|
||||
case fs.IsTemporary(file):
|
||||
return ignoreresult.IgnoreAndSkip
|
||||
|
||||
case fs.IsInternal(file):
|
||||
return ignoreresult.IgnoreAndSkip
|
||||
|
||||
case file == ".":
|
||||
return ignoreresult.NotIgnored
|
||||
}
|
||||
|
||||
m.mut.Lock()
|
||||
defer m.mut.Unlock()
|
||||
|
||||
if len(m.patterns) == 0 {
|
||||
return resultNotMatched
|
||||
return ignoreresult.NotIgnored
|
||||
}
|
||||
|
||||
if m.matches != nil {
|
||||
@@ -278,24 +244,36 @@ func (m *Matcher) Match(file string) (result Result) {
|
||||
}()
|
||||
}
|
||||
|
||||
// Check all the patterns for a match.
|
||||
// Check all the patterns for a match. Track whether the patterns so far
|
||||
// allow skipping matched directories or not. As soon as we hit an
|
||||
// exclude pattern (with some exceptions), we can't skip directories
|
||||
// anymore.
|
||||
file = filepath.ToSlash(file)
|
||||
var lowercaseFile string
|
||||
canSkipDir := true
|
||||
for _, pattern := range m.patterns {
|
||||
if canSkipDir && !pattern.allowsSkippingIgnoredDirs() {
|
||||
canSkipDir = false
|
||||
}
|
||||
|
||||
res := pattern.result
|
||||
if canSkipDir {
|
||||
res = res.WithSkipDir()
|
||||
}
|
||||
if pattern.result.IsCaseFolded() {
|
||||
if lowercaseFile == "" {
|
||||
lowercaseFile = strings.ToLower(file)
|
||||
}
|
||||
if pattern.match.Match(lowercaseFile) {
|
||||
return pattern.result
|
||||
return res
|
||||
}
|
||||
} else if pattern.match.Match(file) {
|
||||
return pattern.result
|
||||
return res
|
||||
}
|
||||
}
|
||||
|
||||
// Default to not matching.
|
||||
return resultNotMatched
|
||||
return ignoreresult.NotIgnored
|
||||
}
|
||||
|
||||
// Lines return a list of the unprocessed lines in .stignore at last load
|
||||
@@ -348,28 +326,6 @@ func (m *Matcher) clean(d time.Duration) {
|
||||
}
|
||||
}
|
||||
|
||||
// ShouldIgnore returns true when a file is temporary, internal or ignored
|
||||
func (m *Matcher) ShouldIgnore(filename string) bool {
|
||||
switch {
|
||||
case fs.IsTemporary(filename):
|
||||
return true
|
||||
|
||||
case fs.IsInternal(filename):
|
||||
return true
|
||||
|
||||
case m.Match(filename).IsIgnored():
|
||||
return true
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (m *Matcher) SkipIgnoredDirs() bool {
|
||||
m.mut.Lock()
|
||||
defer m.mut.Unlock()
|
||||
return m.skipIgnoredDirs
|
||||
}
|
||||
|
||||
func hashPatterns(patterns []Pattern) string {
|
||||
h := sha256.New()
|
||||
for _, pat := range patterns {
|
||||
@@ -414,7 +370,7 @@ func loadParseIncludeFile(filesystem fs.Filesystem, file string, cd ChangeDetect
|
||||
// isNotExist is considered "ok" in a sense of that a folder doesn't have to act
|
||||
// upon it. This is because it is allowed for .stignore to not exist. However,
|
||||
// included ignore files are not allowed to be missing and these errors should be
|
||||
// acted upon on. So we don't perserve the error chain here and manually set an
|
||||
// acted upon on. So we don't preserve the error chain here and manually set an
|
||||
// error instead, if the file is missing.
|
||||
if fs.IsNotExist(err) {
|
||||
err = errors.New("file not found")
|
||||
@@ -431,7 +387,7 @@ func loadParseIncludeFile(filesystem fs.Filesystem, file string, cd ChangeDetect
|
||||
|
||||
func parseLine(line string) ([]Pattern, error) {
|
||||
pattern := Pattern{
|
||||
result: defaultResult,
|
||||
result: ignoreresult.Ignored,
|
||||
}
|
||||
|
||||
// Allow prefixes to be specified in any order, but only once.
|
||||
@@ -441,14 +397,14 @@ func parseLine(line string) ([]Pattern, error) {
|
||||
if strings.HasPrefix(line, "!") && !seenPrefix[0] {
|
||||
seenPrefix[0] = true
|
||||
line = line[1:]
|
||||
pattern.result ^= resultInclude
|
||||
pattern.result = pattern.result.ToggleIgnored()
|
||||
} else if strings.HasPrefix(line, "(?i)") && !seenPrefix[1] {
|
||||
seenPrefix[1] = true
|
||||
pattern.result |= resultFoldCase
|
||||
pattern.result = pattern.result.WithFoldCase()
|
||||
line = line[4:]
|
||||
} else if strings.HasPrefix(line, "(?d)") && !seenPrefix[2] {
|
||||
seenPrefix[2] = true
|
||||
pattern.result |= resultDeletable
|
||||
pattern.result = pattern.result.WithDeletable()
|
||||
line = line[4:]
|
||||
} else {
|
||||
break
|
||||
|
||||
@@ -17,6 +17,7 @@ import (
|
||||
|
||||
"github.com/syncthing/syncthing/lib/build"
|
||||
"github.com/syncthing/syncthing/lib/fs"
|
||||
"github.com/syncthing/syncthing/lib/ignore/ignoreresult"
|
||||
"github.com/syncthing/syncthing/lib/osutil"
|
||||
"github.com/syncthing/syncthing/lib/rand"
|
||||
)
|
||||
@@ -415,7 +416,7 @@ func TestCommentsAndBlankLines(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
var result Result
|
||||
var result ignoreresult.R
|
||||
|
||||
func BenchmarkMatch(b *testing.B) {
|
||||
testFs := newTestFS()
|
||||
@@ -1121,8 +1122,8 @@ func TestIssue5009(t *testing.T) {
|
||||
if err := pats.Parse(bytes.NewBufferString(stignore), ".stignore"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !pats.skipIgnoredDirs {
|
||||
t.Error("skipIgnoredDirs should be true without includes")
|
||||
if m := pats.Match("ign2"); !m.CanSkipDir() {
|
||||
t.Error("CanSkipDir should be true without excludes")
|
||||
}
|
||||
|
||||
stignore = `
|
||||
@@ -1137,8 +1138,8 @@ func TestIssue5009(t *testing.T) {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
if pats.skipIgnoredDirs {
|
||||
t.Error("skipIgnoredDirs should not be true with includes")
|
||||
if m := pats.Match("ign2"); m.CanSkipDir() {
|
||||
t.Error("CanSkipDir should not be true with excludes")
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1271,8 +1272,8 @@ func TestSkipIgnoredDirs(t *testing.T) {
|
||||
if err := pats.Parse(bytes.NewBufferString(stignore), ".stignore"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if !pats.SkipIgnoredDirs() {
|
||||
t.Error("SkipIgnoredDirs should be true")
|
||||
if m := pats.Match("whatever"); !m.CanSkipDir() {
|
||||
t.Error("CanSkipDir should be true")
|
||||
}
|
||||
|
||||
stignore = `
|
||||
@@ -1282,8 +1283,8 @@ func TestSkipIgnoredDirs(t *testing.T) {
|
||||
if err := pats.Parse(bytes.NewBufferString(stignore), ".stignore"); err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
if pats.SkipIgnoredDirs() {
|
||||
t.Error("SkipIgnoredDirs should be false")
|
||||
if m := pats.Match("whatever"); m.CanSkipDir() {
|
||||
t.Error("CanSkipDir should be false")
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
96
lib/ignore/ignoreresult/ignoreresult.go
Normal file
96
lib/ignore/ignoreresult/ignoreresult.go
Normal file
@@ -0,0 +1,96 @@
|
||||
// Copyright (C) 2024 The Syncthing Authors.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
// Package result provides the result type for ignore matching. This is a
|
||||
// separate package in order to break import cycles.
|
||||
package ignoreresult
|
||||
|
||||
const (
|
||||
NotIgnored R = 0
|
||||
// `Ignored` is defined in platform specific files
|
||||
IgnoredDeletable = Ignored | deletableBit
|
||||
IgnoreAndSkip = Ignored | canSkipDirBit
|
||||
)
|
||||
|
||||
const (
|
||||
// Private definitions of the bits that make up the result value
|
||||
ignoreBit R = 1 << iota
|
||||
deletableBit
|
||||
foldCaseBit
|
||||
canSkipDirBit
|
||||
)
|
||||
|
||||
type R uint8
|
||||
|
||||
// IsIgnored returns true if the result is ignored.
|
||||
func (r R) IsIgnored() bool {
|
||||
return r&ignoreBit != 0
|
||||
}
|
||||
|
||||
// IsDeletable returns true if the result is ignored and deletable.
|
||||
func (r R) IsDeletable() bool {
|
||||
return r.IsIgnored() && r&deletableBit != 0
|
||||
}
|
||||
|
||||
// IsCaseFolded returns true if the result was a case-insensitive match.
|
||||
func (r R) IsCaseFolded() bool {
|
||||
return r&foldCaseBit != 0
|
||||
}
|
||||
|
||||
// CanSkipDir returns true if the result is ignored and the directory can be
|
||||
// skipped (no need to recurse deeper). Note that ignore matches are textual
|
||||
// and based on the name only -- this being true does not mean that the
|
||||
// matched item is a directory, merely that *if* it is a directory, it can
|
||||
// be skipped.
|
||||
func (r R) CanSkipDir() bool {
|
||||
return r.IsIgnored() && r&canSkipDirBit != 0
|
||||
}
|
||||
|
||||
// ToggleIgnored returns a copy of the result with the ignored bit toggled.
|
||||
func (r R) ToggleIgnored() R {
|
||||
return r ^ ignoreBit
|
||||
}
|
||||
|
||||
// WithDeletable returns a copy of the result with the deletable bit set.
|
||||
func (r R) WithDeletable() R {
|
||||
return r | deletableBit
|
||||
}
|
||||
|
||||
// WithFoldCase returns a copy of the result with the fold case bit set.
|
||||
func (r R) WithFoldCase() R {
|
||||
return r | foldCaseBit
|
||||
}
|
||||
|
||||
// WithSkipDir returns a copy of the result with the skip dir bit set.
|
||||
func (r R) WithSkipDir() R {
|
||||
return r | canSkipDirBit
|
||||
}
|
||||
|
||||
// String returns a human readable representation of the result flags.
|
||||
func (r R) String() string {
|
||||
var s string
|
||||
if r&ignoreBit != 0 {
|
||||
s += "i"
|
||||
} else {
|
||||
s += "-"
|
||||
}
|
||||
if r&deletableBit != 0 {
|
||||
s += "d"
|
||||
} else {
|
||||
s += "-"
|
||||
}
|
||||
if r&foldCaseBit != 0 {
|
||||
s += "f"
|
||||
} else {
|
||||
s += "-"
|
||||
}
|
||||
if r&canSkipDirBit != 0 {
|
||||
s += "s"
|
||||
} else {
|
||||
s += "-"
|
||||
}
|
||||
return s
|
||||
}
|
||||
11
lib/ignore/ignoreresult/ignoreresult_foldcase.go
Normal file
11
lib/ignore/ignoreresult/ignoreresult_foldcase.go
Normal file
@@ -0,0 +1,11 @@
|
||||
// Copyright (C) 2024 The Syncthing Authors.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
//go:build windows || darwin
|
||||
|
||||
package ignoreresult
|
||||
|
||||
const Ignored = ignoreBit | foldCaseBit
|
||||
11
lib/ignore/ignoreresult/ignoreresult_nofoldcase.go
Normal file
11
lib/ignore/ignoreresult/ignoreresult_nofoldcase.go
Normal file
@@ -0,0 +1,11 @@
|
||||
// Copyright (C) 2024 The Syncthing Authors.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
//go:build !windows && !darwin
|
||||
|
||||
package ignoreresult
|
||||
|
||||
const Ignored = ignoreBit
|
||||
38
lib/ignore/ignoreresult/ignoreresult_test.go
Normal file
38
lib/ignore/ignoreresult/ignoreresult_test.go
Normal file
@@ -0,0 +1,38 @@
|
||||
// Copyright (C) 2024 The Syncthing Authors.
|
||||
//
|
||||
// This Source Code Form is subject to the terms of the Mozilla Public
|
||||
// License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
// You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
package ignoreresult_test
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/ignore/ignoreresult"
|
||||
)
|
||||
|
||||
func TestFlagCanSkipDir(t *testing.T) {
|
||||
// Verify that CanSkipDir() means that something is both ignored and can
|
||||
// be skipped as a directory, so that it's legitimate to say
|
||||
// Match(...).CanSkipDir() instead of having to create a temporary
|
||||
// variable and check both Match(...).IsIgnored() and
|
||||
// Match(...).CanSkipDir().
|
||||
|
||||
cases := []struct {
|
||||
res ignoreresult.R
|
||||
canSkipDir bool
|
||||
}{
|
||||
{0, false},
|
||||
{ignoreresult.NotIgnored, false},
|
||||
{ignoreresult.NotIgnored.WithSkipDir(), false},
|
||||
{ignoreresult.Ignored, false},
|
||||
{ignoreresult.IgnoreAndSkip, true},
|
||||
}
|
||||
|
||||
for _, tc := range cases {
|
||||
if tc.res.CanSkipDir() != tc.canSkipDir {
|
||||
t.Errorf("%v.CanSkipDir() != %v", tc.res, tc.canSkipDir)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,6 @@ const (
|
||||
HTTPSKeyFile LocationEnum = "httpsKeyFile"
|
||||
Database LocationEnum = "database"
|
||||
LogFile LocationEnum = "logFile"
|
||||
CsrfTokens LocationEnum = "csrfTokens"
|
||||
PanicLog LocationEnum = "panicLog"
|
||||
AuditLog LocationEnum = "auditLog"
|
||||
GUIAssets LocationEnum = "guiAssets"
|
||||
@@ -121,7 +120,6 @@ var locationTemplates = map[LocationEnum]string{
|
||||
HTTPSKeyFile: "${config}/https-key.pem",
|
||||
Database: "${data}/" + LevelDBDir,
|
||||
LogFile: "${data}/syncthing.log", // --logfile on Windows
|
||||
CsrfTokens: "${data}/csrftokens.txt",
|
||||
PanicLog: "${data}/panic-%{timestamp}.log",
|
||||
AuditLog: "${data}/audit-%{timestamp}.log",
|
||||
GUIAssets: "${config}/gui",
|
||||
@@ -170,7 +168,6 @@ func PrettyPaths() string {
|
||||
fmt.Fprintf(&b, "Database location:\n\t%s\n\n", Get(Database))
|
||||
fmt.Fprintf(&b, "Log file:\n\t%s\n\n", Get(LogFile))
|
||||
fmt.Fprintf(&b, "GUI override directory:\n\t%s\n\n", Get(GUIAssets))
|
||||
fmt.Fprintf(&b, "CSRF tokens file:\n\t%s\n\n", Get(CsrfTokens))
|
||||
fmt.Fprintf(&b, "Default sync folder directory:\n\t%s\n\n", Get(DefFolder))
|
||||
return b.String()
|
||||
}
|
||||
|
||||
@@ -10,10 +10,9 @@ package locations
|
||||
|
||||
import (
|
||||
"path/filepath"
|
||||
"slices"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"golang.org/x/exp/slices"
|
||||
)
|
||||
|
||||
func TestUnixConfigDir(t *testing.T) {
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"io"
|
||||
"log"
|
||||
"os"
|
||||
"slices"
|
||||
"strings"
|
||||
"sync"
|
||||
"time"
|
||||
@@ -52,7 +53,6 @@ type Logger interface {
|
||||
Warnf(format string, vals ...interface{})
|
||||
ShouldDebug(facility string) bool
|
||||
SetDebug(facility string, enabled bool)
|
||||
IsTraced(facility string) bool
|
||||
Facilities() map[string]string
|
||||
FacilityDebugging() []string
|
||||
NewFacility(facility, description string) Logger
|
||||
@@ -63,7 +63,7 @@ type logger struct {
|
||||
handlers [NumLevels][]MessageHandler
|
||||
facilities map[string]string // facility name => description
|
||||
debug map[string]struct{} // only facility names with debugging enabled
|
||||
traces string
|
||||
traces []string
|
||||
mut sync.Mutex
|
||||
}
|
||||
|
||||
@@ -80,9 +80,21 @@ func New() Logger {
|
||||
}
|
||||
|
||||
func newLogger(w io.Writer) Logger {
|
||||
traces := strings.FieldsFunc(os.Getenv("STTRACE"), func(r rune) bool {
|
||||
return strings.ContainsRune(",; ", r)
|
||||
})
|
||||
|
||||
if len(traces) > 0 {
|
||||
if slices.Contains(traces, "all") {
|
||||
traces = []string{"all"}
|
||||
} else {
|
||||
slices.Sort(traces)
|
||||
}
|
||||
}
|
||||
|
||||
return &logger{
|
||||
logger: log.New(w, "", DefaultFlags),
|
||||
traces: os.Getenv("STTRACE"),
|
||||
traces: traces,
|
||||
facilities: make(map[string]string),
|
||||
debug: make(map[string]struct{}),
|
||||
}
|
||||
@@ -118,6 +130,7 @@ func (l *logger) callHandlers(level LogLevel, s string) {
|
||||
func (l *logger) Debugln(vals ...interface{}) {
|
||||
l.debugln(3, vals...)
|
||||
}
|
||||
|
||||
func (l *logger) debugln(level int, vals ...interface{}) {
|
||||
s := fmt.Sprintln(vals...)
|
||||
l.mut.Lock()
|
||||
@@ -130,6 +143,7 @@ func (l *logger) debugln(level int, vals ...interface{}) {
|
||||
func (l *logger) Debugf(format string, vals ...interface{}) {
|
||||
l.debugf(3, format, vals...)
|
||||
}
|
||||
|
||||
func (l *logger) debugf(level int, format string, vals ...interface{}) {
|
||||
s := fmt.Sprintf(format, vals...)
|
||||
l.mut.Lock()
|
||||
@@ -215,9 +229,18 @@ func (l *logger) SetDebug(facility string, enabled bool) {
|
||||
}
|
||||
}
|
||||
|
||||
// IsTraced returns whether the facility name is contained in STTRACE.
|
||||
func (l *logger) IsTraced(facility string) bool {
|
||||
return strings.Contains(l.traces, facility) || l.traces == "all"
|
||||
// isTraced returns whether the facility name is contained in STTRACE.
|
||||
func (l *logger) isTraced(facility string) bool {
|
||||
if len(l.traces) > 0 {
|
||||
if l.traces[0] == "all" {
|
||||
return true
|
||||
}
|
||||
|
||||
_, found := slices.BinarySearch(l.traces, facility)
|
||||
return found
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
// FacilityDebugging returns the set of facilities that have debugging
|
||||
@@ -246,7 +269,7 @@ func (l *logger) Facilities() map[string]string {
|
||||
|
||||
// NewFacility returns a new logger bound to the named facility.
|
||||
func (l *logger) NewFacility(facility, description string) Logger {
|
||||
l.SetDebug(facility, l.IsTraced(facility))
|
||||
l.SetDebug(facility, l.isTraced(facility))
|
||||
|
||||
l.mut.Lock()
|
||||
l.facilities[facility] = description
|
||||
|
||||
@@ -160,7 +160,7 @@ func (f *fakeConnection) sendIndexUpdate() {
|
||||
for i := range f.files {
|
||||
toSend[i] = prepareFileInfoForIndex(f.files[i])
|
||||
}
|
||||
f.model.IndexUpdate(f, f.folder, toSend)
|
||||
f.model.IndexUpdate(f, &protocol.IndexUpdate{Folder: f.folder, Files: toSend})
|
||||
}
|
||||
|
||||
func addFakeConn(m *testModel, dev protocol.DeviceID, folderID string) *fakeConnection {
|
||||
@@ -168,7 +168,7 @@ func addFakeConn(m *testModel, dev protocol.DeviceID, folderID string) *fakeConn
|
||||
fc.folder = folderID
|
||||
m.AddConnection(fc, protocol.Hello{})
|
||||
|
||||
m.ClusterConfig(fc, protocol.ClusterConfig{
|
||||
m.ClusterConfig(fc, &protocol.ClusterConfig{
|
||||
Folders: []protocol.Folder{
|
||||
{
|
||||
ID: folderID,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user