mirror of
https://github.com/syncthing/syncthing.git
synced 2026-01-07 13:29:11 -05:00
Compare commits
137 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8fd2937a58 | ||
|
|
cce634f340 | ||
|
|
47429d01e8 | ||
|
|
445c4edeca | ||
|
|
c005b8dcb0 | ||
|
|
b9ed6c4c2c | ||
|
|
3153e36a3d | ||
|
|
60bceb0f09 | ||
|
|
257c3f5e82 | ||
|
|
7d0723da68 | ||
|
|
205426a9c6 | ||
|
|
bd12e38b56 | ||
|
|
95a65bf0d0 | ||
|
|
429b3a0429 | ||
|
|
cc14563b62 | ||
|
|
99b00b6a5e | ||
|
|
b2af8f135b | ||
|
|
67c39b2512 | ||
|
|
ce29d3a574 | ||
|
|
1e9769cdd7 | ||
|
|
6daa766fde | ||
|
|
ed95e80088 | ||
|
|
0dd7934405 | ||
|
|
8606b4dd8d | ||
|
|
4922b46fbd | ||
|
|
b99e92bad7 | ||
|
|
a17d953334 | ||
|
|
7817d092cb | ||
|
|
075a699aae | ||
|
|
44a542391e | ||
|
|
e589e6c19d | ||
|
|
0a50f374db | ||
|
|
4a58196959 | ||
|
|
4949721c0b | ||
|
|
0901350087 | ||
|
|
8078babf0a | ||
|
|
00ce889a8b | ||
|
|
7279644372 | ||
|
|
cd29e3c524 | ||
|
|
3312a29dde | ||
|
|
72d645865e | ||
|
|
9471b9f6af | ||
|
|
0518a92cdb | ||
|
|
6cf01c1d30 | ||
|
|
5f4ed66aa1 | ||
|
|
ee5d0dd43f | ||
|
|
7ebf58f1bc | ||
|
|
aecd7c64ce | ||
|
|
783dd612f7 | ||
|
|
4efff736b3 | ||
|
|
fa12a18190 | ||
|
|
2b65e1062e | ||
|
|
80031c59da | ||
|
|
6e35592e9e | ||
|
|
9e11d7b201 | ||
|
|
fd5f9f8968 | ||
|
|
d8a0a477ca | ||
|
|
6dd6ecde95 | ||
|
|
6e148e20cd | ||
|
|
72c5f2e5c6 | ||
|
|
d7d45d8092 | ||
|
|
57d5dfa80c | ||
|
|
c080f677cb | ||
|
|
ec4c3bae0d | ||
|
|
386cb274bd | ||
|
|
a9d422e008 | ||
|
|
75f64733f9 | ||
|
|
40c952c0ae | ||
|
|
0ee1146e1c | ||
|
|
88180904f2 | ||
|
|
f6ea2a7f8e | ||
|
|
c5f90d64bc | ||
|
|
941c9f1531 | ||
|
|
62a4106a79 | ||
|
|
9c855ab22e | ||
|
|
166273b357 | ||
|
|
d304498027 | ||
|
|
7cbd92e1b1 | ||
|
|
9245d22f16 | ||
|
|
3f85f719de | ||
|
|
7ba05c18ee | ||
|
|
617bf173a4 | ||
|
|
5f8c0ca932 | ||
|
|
93a66deb7e | ||
|
|
997bed569e | ||
|
|
b999b58049 | ||
|
|
2953fe40d1 | ||
|
|
4b69d0e093 | ||
|
|
ff0a83fe5b | ||
|
|
9c60bb8336 | ||
|
|
9ecf9a3f48 | ||
|
|
7ba9e7c322 | ||
|
|
dc42db444b | ||
|
|
a9c221189b | ||
|
|
b2966957e0 | ||
|
|
0d30166357 | ||
|
|
d65f1fb08a | ||
|
|
622b614f31 | ||
|
|
b1ade6d0c0 | ||
|
|
46becc5338 | ||
|
|
20fac4bb80 | ||
|
|
d84b6bb822 | ||
|
|
55b63941b8 | ||
|
|
e70003737b | ||
|
|
f98c21b68e | ||
|
|
c704ba9ef9 | ||
|
|
dfad6a2aa9 | ||
|
|
fb7264a663 | ||
|
|
889814a1af | ||
|
|
694a7de59d | ||
|
|
059185b325 | ||
|
|
1e9e9cbebb | ||
|
|
cdbb32d0f0 | ||
|
|
becbb3b123 | ||
|
|
06da67e6fc | ||
|
|
2f08f8021f | ||
|
|
9d3f3847ed | ||
|
|
74c8d34805 | ||
|
|
5ec1490be0 | ||
|
|
2760d032ca | ||
|
|
813e6ddf83 | ||
|
|
6ffb95f6c8 | ||
|
|
0b5c11bf93 | ||
|
|
5aade9a4a5 | ||
|
|
9717c3d292 | ||
|
|
a365ae51c4 | ||
|
|
97222797a0 | ||
|
|
e588bb29b9 | ||
|
|
2dd9450793 | ||
|
|
3ee12464b4 | ||
|
|
59ebcea356 | ||
|
|
27d4896a13 | ||
|
|
1088eb12ea | ||
|
|
f40d219370 | ||
|
|
429cc20eb7 | ||
|
|
e85ce7c94e | ||
|
|
283c8d95e2 |
8
AUTHORS
8
AUTHORS
@@ -3,7 +3,9 @@
|
||||
#
|
||||
# Name Name Name (nickname) <email1@example.com> <email2@example.com>
|
||||
#
|
||||
# The NICKS list is auto generated from this file.
|
||||
# After changing this list, run "go run script/authors.go" to sort and update
|
||||
# the GUI HTML.
|
||||
#
|
||||
|
||||
Aaron Bieber (qbit) <qbit@deftly.net>
|
||||
Adam Piggott (ProactiveServices) <aD@simplypeachy.co.uk> <simplypeachy@users.noreply.github.com> <ProactiveServices@users.noreply.github.com>
|
||||
@@ -41,6 +43,7 @@ Darshil Chanpura (dtchanpura) <dtchanpura@gmail.com> <dcprime314@gmail.com>
|
||||
David Rimmer (dinosore) <dinosore@dbrsoftware.co.uk>
|
||||
Denis A. (dva) <denisva@gmail.com>
|
||||
Dennis Wilson (snnd) <dw@risu.io>
|
||||
Dmitry Saveliev (dsaveliev) <d.e.saveliev@gmail.com>
|
||||
Dominik Heidler (asdil12) <dominik@heidler.eu>
|
||||
Elias Jarlebring (jarlebring) <jarlebring@gmail.com>
|
||||
Emil Hessman (ceh) <emil@hessman.se>
|
||||
@@ -89,6 +92,7 @@ Michael Tilli (pyfisch) <pyfisch@gmail.com>
|
||||
Nate Morrison (nrm21) <natemorrison@gmail.com>
|
||||
Niels Peter Roest (Niller303) <nielsproest@hotmail.com> <seje.niels@hotmail.com>
|
||||
Pascal Jungblut (pascalj) <github@pascalj.com> <mail@pascal-jungblut.com>
|
||||
Pawel Palenica (qepasa) <pawelpalenica11@gmail.com>
|
||||
Peter Hoeg (peterhoeg) <peter@speartail.com>
|
||||
Philippe Schommers (filoozoom) <philippe@schommers.be>
|
||||
Phill Luby (pluby) <phill.luby@newredo.com>
|
||||
@@ -104,9 +108,11 @@ Simon Frei (imsodin) <freisim93@gmail.com>
|
||||
Stefan Kuntz (Stefan-Code) <stefan.github@gmail.com> <Stefan.github@gmail.com>
|
||||
Stefan Tatschner (rumpelsepp) <stefan@sevenbyte.org> <rumpelsepp@sevenbyte.org>
|
||||
Suhas Gundimeda (snugghash) <suhas.gundimeda@gmail.com> <snugghash@gmail.com>
|
||||
Taylor Khan (nelsonkhan) <nelsonkhan@gmail.com>
|
||||
Tim Abell (timabell) <tim@timwise.co.uk>
|
||||
Tim Howes (timhowes) <timhowes@berkeley.edu>
|
||||
Tobias Nygren (tnn2) <tnn@nygren.pp.se>
|
||||
Tobias Tom (tobiastom) <t.tom@succont.de>
|
||||
Tomas Cerveny (kozec) <kozec@kozec.com>
|
||||
Tully Robinson (tojrobinson) <tully@tojr.org>
|
||||
Tyler Brazier (tylerbrazier) <tyler@tylerbrazier.com>
|
||||
|
||||
@@ -1,11 +1,17 @@
|
||||
Do not report security issues in this bug tracker. Instead, contact
|
||||
security@syncthing.net directly - see https://syncthing.net/security.html
|
||||
for more information.
|
||||
### DO NOT REPORT SECURITY ISSUES IN THIS ISSUE TRACKER
|
||||
|
||||
If your issue is a support request ("How do I get my devices to connect?"
|
||||
or similar), please use the support forum at https://forum.syncthing.net/
|
||||
where a large number of helpful people hang out. This issue tracker is for
|
||||
reporting bugs or feature requests directly to the developers.
|
||||
Instead, contact security@syncthing.net directly - see
|
||||
https://syncthing.net/security.html for more information.
|
||||
|
||||
### DO NOT POST SUPPORT REQUESTS OR GENERAL QUESTIONS IN THIS ISSUE TRACKER
|
||||
|
||||
Please use the forum at https://forum.syncthing.net/ where a large number of
|
||||
helpful people hang out. This issue tracker is for reporting bugs or feature
|
||||
requests directly to the developers. Worst case you might get a short
|
||||
"that's a bug, please report it on GitHub" response on the forum, in which
|
||||
case we thank you for your patience and following our advice. :)
|
||||
|
||||
### Please do post actual bug reports and feature requests.
|
||||
|
||||
If your issue is a bug report, replace this boilerplate with a description
|
||||
of the problem, being sure to include at least:
|
||||
|
||||
149
NICKS
149
NICKS
@@ -1,149 +0,0 @@
|
||||
# This file maps email addresses used in commits to nicks used the changelog.
|
||||
# It is auto generated from the AUTHORS file by script/authors.go.
|
||||
|
||||
0x010C <antoine.lamielle@0x010c.fr>
|
||||
0x010C <gh@0x010c.fr>
|
||||
acogdev <jake@acogdev.com>
|
||||
adelq <aqalieh95@gmail.com>
|
||||
adelq <adelq@users.noreply.github.com>
|
||||
alessandro.g89 <alessandro.g89@gmail.com>
|
||||
alex2108 <register-github@alex-graf.de>
|
||||
andersonvom <andersonvom@gmail.com>
|
||||
andrew-d <andrew@du.nham.ca>
|
||||
asdil12 <dominik@heidler.eu>
|
||||
AudriusButkevicius <audrius.butkevicius@gmail.com>
|
||||
aviau <alexandre@alexandreviau.net>
|
||||
aviau <aviau@debian.org>
|
||||
bencurthoys <ben@bencurthoys.com>
|
||||
benshep <bjashepherd@gmail.com>
|
||||
bigbear2nd <bigbear2nd@gmail.com>
|
||||
brbecker <brbecker@gmail.com>
|
||||
brendanlong <self@brendanlong.com>
|
||||
brgmnn <dan.arne.bergmann@gmail.com>
|
||||
brgmnn <brgmnn@users.noreply.github.com>
|
||||
bsidhom <bsidhom@gmail.com>
|
||||
buinsky <vix_booja@tut.by>
|
||||
burkemw3 <mburke@amplify.com>
|
||||
burkemw3 <burkemw3@gmail.com>
|
||||
calmh <jakob@nym.se>
|
||||
calmh <jakob@kastelo.net>
|
||||
canton7 <antony.male@gmail.com>
|
||||
Cathryne <cathryne.linenweaver@gmail.com>
|
||||
Cathryne <Cathryne@users.noreply.github.com>
|
||||
cdata <chris@scriptolo.gy>
|
||||
cdhowie <me@chrishowie.com>
|
||||
ceh <emil@hessman.se>
|
||||
cqcallaw <enlightened.despot@gmail.com>
|
||||
damajor <damajor@gmail.com>
|
||||
dinosore <dinosore@dbrsoftware.co.uk>
|
||||
dtchanpura <dtchanpura@gmail.com>
|
||||
dtchanpura <dcprime314@gmail.com>
|
||||
dva <denisva@gmail.com>
|
||||
dzarda <dzardacz@gmail.com>
|
||||
eipiminus1 <eipiminusone+github@gmail.com>
|
||||
eipiminus1 <eipiminus1@users.noreply.github.com>
|
||||
elopio <yo@elopio.net>
|
||||
facastagnini <federico.castagnini@gmail.com>
|
||||
filoozoom <philippe@schommers.be>
|
||||
frioux <frew@afoolishmanifesto.com>
|
||||
frioux <frioux@gmail.com>
|
||||
fti7 <frank@isemann.name>
|
||||
gillisig <gilli@vx.is>
|
||||
hadogenes <szafar@linux.pl>
|
||||
imsodin <freisim93@gmail.com>
|
||||
ironmig <kma1660@gmail.com>
|
||||
jarlebring <jarlebring@gmail.com>
|
||||
jayachithra <s.k.jayachithra@gmail.com>
|
||||
jedie <github.com@jensdiemer.de>
|
||||
jedie <git@jensdiemer.de>
|
||||
jgke <jgke@jgke.fi>
|
||||
jmdaweb <jmdaweb@hotmail.com>
|
||||
jmdaweb <jmdaweb@users.noreply.github.com>
|
||||
jpjp <jamespatterson@operamail.com>
|
||||
jpjp <jpjp@users.noreply.github.com>
|
||||
kamadak <kamada@nanohz.org>
|
||||
KayoticSully <kayoticsully@gmail.com>
|
||||
kc1212 <kc04bc@gmx.com>
|
||||
kc1212 <kc1212@users.noreply.github.com>
|
||||
kilburn <kilburn@la3.org>
|
||||
kluppy <kluppy@going2blue.com>
|
||||
kozec <kozec@kozec.com>
|
||||
kralo <max.schulze@online.de>
|
||||
kralo <kralo@users.noreply.github.com>
|
||||
krozycki <rozycki.karol@gmail.com>
|
||||
Kudalufi <kurt@va1der.ca>
|
||||
Kudalufi <kurt.fitzner@gmail.com>
|
||||
kwhite17 <kevinwhite1710@gmail.com>
|
||||
letiemble <laurent.etiemble@gmail.com>
|
||||
letiemble <laurent.etiemble@monobjc.net>
|
||||
liusy182 <liusy182@gmail.com>
|
||||
liusy182 <liusy182@hotmail.com>
|
||||
lkwg82 <lkwg82@gmx.de>
|
||||
LordLandon <lordlandon@gmail.com>
|
||||
majedev <majed.alhajry@gmail.com>
|
||||
marcindziadus <dziadus.marcin@gmail.com>
|
||||
marclaporte <marc@marclaporte.com>
|
||||
marclaporte <marc@laporte.name>
|
||||
mateon1 <matin1111@wp.pl>
|
||||
mogwa1 <devriesb@gmail.com>
|
||||
moshen <moshen.colin@gmail.com>
|
||||
Moter8 <moter8@gmail.com>
|
||||
mpx <mark@kyne.com.au>
|
||||
mvdan <mvdan@mvdan.cc>
|
||||
Niller303 <nielsproest@hotmail.com>
|
||||
Niller303 <seje.niels@hotmail.com>
|
||||
norgeous <daniel@harte.me>
|
||||
norgeous <daniel@danielharte.co.uk>
|
||||
norgeous <norgeous@users.noreply.github.com>
|
||||
nov1n <robert@carosi.nl>
|
||||
nrm21 <natemorrison@gmail.com>
|
||||
Nutomic <me@nutomic.com>
|
||||
pascalj <github@pascalj.com>
|
||||
pascalj <mail@pascal-jungblut.com>
|
||||
peterhoeg <peter@speartail.com>
|
||||
philips <brandon@ifup.org>
|
||||
piobpl <piotrb10@gmail.com>
|
||||
plouj <ploujj@gmail.com>
|
||||
pluby <phill.luby@newredo.com>
|
||||
ProactiveServices <aD@simplypeachy.co.uk>
|
||||
ProactiveServices <simplypeachy@users.noreply.github.com>
|
||||
ProactiveServices <ProactiveServices@users.noreply.github.com>
|
||||
pyfisch <pyfisch@gmail.com>
|
||||
qbit <qbit@deftly.net>
|
||||
ralder <ralder@yandex.ru>
|
||||
rasa <ross@smithii.com>
|
||||
Rewt0r <rewt0r@gmx.com>
|
||||
Rewt0r <Rewt0r@users.noreply.github.com>
|
||||
rumpelsepp <stefan@sevenbyte.org>
|
||||
rumpelsepp <rumpelsepp@sevenbyte.org>
|
||||
sacheendra <sacheendra.t@gmail.com>
|
||||
scienmind <scintertech@cryptolab.net>
|
||||
sciurius <jvromans@squirrel.nl>
|
||||
seehuhn <voss@seehuhn.de>
|
||||
Smiley73 <heiko@zuerker.org>
|
||||
snnd <dw@risu.io>
|
||||
snugghash <suhas.gundimeda@gmail.com>
|
||||
snugghash <snugghash@gmail.com>
|
||||
Stefan-Code <stefan.github@gmail.com>
|
||||
Stefan-Code <Stefan.github@gmail.com>
|
||||
timabell <tim@timwise.co.uk>
|
||||
timhowes <timhowes@berkeley.edu>
|
||||
tnn2 <tnn@nygren.pp.se>
|
||||
tojrobinson <tully@tojr.org>
|
||||
tpng <benny.tpng@gmail.com>
|
||||
tylerbrazier <tyler@tylerbrazier.com>
|
||||
Unrud <unrud@openaliasbox.org>
|
||||
Unrud <Unrud@users.noreply.github.com>
|
||||
uok <ueomkail@gmail.com>
|
||||
uok <uok@users.noreply.github.com>
|
||||
veeti <veeti.paananen@rojekti.fi>
|
||||
Vilbrekin <vilbrekin@gmail.com>
|
||||
wkennington <william@wkennington.com>
|
||||
WSGCSysadmin <e.meitner@willystreet.coop>
|
||||
wweich <wweich@users.noreply.github.com>
|
||||
wweich <wweich@gmx.de>
|
||||
wweich <wulf@weich-kr.de>
|
||||
xduugu <cedric@gmx.ca>
|
||||
zaynetro <romanznet@gmail.com>
|
||||
Zillode <zillode@zillode.be>
|
||||
zukoo <fxgsell@gmail.com>
|
||||
14
README.md
14
README.md
@@ -20,36 +20,36 @@ commentary, see the full [Goals document][13].
|
||||
|
||||
Syncthing should be:
|
||||
|
||||
1. Safe From Data Loss
|
||||
1. **Safe From Data Loss**
|
||||
|
||||
Protecting the user's data is paramount. We take every reasonable
|
||||
precaution to avoid corrupting the user's files.
|
||||
|
||||
2. Secure Against Attackers
|
||||
2. **Secure Against Attackers**
|
||||
|
||||
Again, protecting the user's data is paramount. Regardless of our other
|
||||
goals we must never allow the user's data to be susceptible to
|
||||
eavesdropping or modification by unauthorized parties.
|
||||
|
||||
3. Easy to Use
|
||||
3. **Easy to Use**
|
||||
|
||||
Syncthing should be approachable, understandable and inclusive.
|
||||
|
||||
4. Automatic
|
||||
4. **Automatic**
|
||||
|
||||
User interaction should be required only when absolutely necessary.
|
||||
|
||||
5. Universally Available
|
||||
5. **Universally Available**
|
||||
|
||||
Syncthing should run on every common computer. We are mindful that the
|
||||
latest technology is not always available to any given individual.
|
||||
|
||||
6. For Individuals
|
||||
6. **For Individuals**
|
||||
|
||||
Syncthing is primarily about empowering the individual user with safe,
|
||||
secure and easy to use file synchronization.
|
||||
|
||||
7. Everything Else
|
||||
7. **Everything Else**
|
||||
|
||||
There are many things we care about that don't make it on to the list. It
|
||||
is fine to optimize for these values, as long as they are not in conflict
|
||||
|
||||
71
build.go
71
build.go
@@ -45,6 +45,7 @@ var (
|
||||
noBuildGopath bool
|
||||
extraTags string
|
||||
installSuffix string
|
||||
pkgdir string
|
||||
)
|
||||
|
||||
type target struct {
|
||||
@@ -203,7 +204,7 @@ func main() {
|
||||
}()
|
||||
}
|
||||
|
||||
if gopath() == "" {
|
||||
if gopath := gopath(); gopath == "" {
|
||||
gopath, err := temporaryBuildDir()
|
||||
if err != nil {
|
||||
log.Fatal(err)
|
||||
@@ -216,6 +217,20 @@ func main() {
|
||||
}
|
||||
os.Setenv("GOPATH", gopath)
|
||||
log.Println("GOPATH is", gopath)
|
||||
} else {
|
||||
inside := false
|
||||
wd, _ := os.Getwd()
|
||||
wd, _ = filepath.EvalSymlinks(wd)
|
||||
for _, p := range filepath.SplitList(gopath) {
|
||||
p, _ = filepath.EvalSymlinks(p)
|
||||
if filepath.Join(p, "src/github.com/syncthing/syncthing") == wd {
|
||||
inside = true
|
||||
break
|
||||
}
|
||||
}
|
||||
if !inside {
|
||||
fmt.Println("You seem to have GOPATH set but the Syncthing source not placed correctly within it, which may cause problems.")
|
||||
}
|
||||
}
|
||||
|
||||
// Set path to $GOPATH/bin:$PATH so that we can for sure find tools we
|
||||
@@ -342,6 +357,7 @@ func parseFlags() {
|
||||
flag.BoolVar(&noBuildGopath, "no-build-gopath", noBuildGopath, "Don't build GOPATH, assume it's OK")
|
||||
flag.StringVar(&extraTags, "tags", extraTags, "Extra tags, space separated")
|
||||
flag.StringVar(&installSuffix, "installsuffix", installSuffix, "Install suffix, optional")
|
||||
flag.StringVar(&pkgdir, "pkgdir", "", "Set -pkgdir parameter for `go build`")
|
||||
flag.Parse()
|
||||
}
|
||||
|
||||
@@ -359,9 +375,9 @@ func setup() {
|
||||
"github.com/tsenart/deadcode",
|
||||
"golang.org/x/net/html",
|
||||
"golang.org/x/tools/cmd/cover",
|
||||
"honnef.co/go/simple/cmd/gosimple",
|
||||
"honnef.co/go/staticcheck/cmd/staticcheck",
|
||||
"honnef.co/go/unused/cmd/unused",
|
||||
"honnef.co/go/tools/cmd/gosimple",
|
||||
"honnef.co/go/tools/cmd/staticcheck",
|
||||
"honnef.co/go/tools/cmd/unused",
|
||||
}
|
||||
for _, pkg := range packages {
|
||||
fmt.Println(pkg)
|
||||
@@ -404,6 +420,9 @@ func install(target target, tags []string) {
|
||||
}
|
||||
os.Setenv("GOBIN", filepath.Join(cwd, "bin"))
|
||||
args := []string{"install", "-v", "-ldflags", ldflags()}
|
||||
if pkgdir != "" {
|
||||
args = append(args, "-pkgdir", pkgdir)
|
||||
}
|
||||
if len(tags) > 0 {
|
||||
args = append(args, "-tags", strings.Join(tags, " "))
|
||||
}
|
||||
@@ -427,6 +446,9 @@ func build(target target, tags []string) {
|
||||
|
||||
rmr(target.BinaryName())
|
||||
args := []string{"build", "-i", "-v", "-ldflags", ldflags()}
|
||||
if pkgdir != "" {
|
||||
args = append(args, "-pkgdir", pkgdir)
|
||||
}
|
||||
if len(tags) > 0 {
|
||||
args = append(args, "-tags", strings.Join(tags, " "))
|
||||
}
|
||||
@@ -481,6 +503,10 @@ func buildZip(target target) {
|
||||
|
||||
build(target, tags)
|
||||
|
||||
if goos == "windows" {
|
||||
windowsCodesign(target.BinaryName())
|
||||
}
|
||||
|
||||
for i := range target.archiveFiles {
|
||||
target.archiveFiles[i].src = strings.Replace(target.archiveFiles[i].src, "{{binary}}", target.BinaryName(), 1)
|
||||
target.archiveFiles[i].dst = strings.Replace(target.archiveFiles[i].dst, "{{binary}}", target.BinaryName(), 1)
|
||||
@@ -1070,6 +1096,43 @@ func macosCodesign(file string) {
|
||||
}
|
||||
}
|
||||
|
||||
func windowsCodesign(file string) {
|
||||
st := "signtool.exe"
|
||||
|
||||
if path := os.Getenv("CODESIGN_SIGNTOOL"); path != "" {
|
||||
st = path
|
||||
}
|
||||
|
||||
for i, algo := range []string{"sha1", "sha256"} {
|
||||
args := []string{"sign", "/fd", algo}
|
||||
if f := os.Getenv("CODESIGN_CERTIFICATE_FILE"); f != "" {
|
||||
args = append(args, "/f", f)
|
||||
}
|
||||
if p := os.Getenv("CODESIGN_CERTIFICATE_PASSWORD"); p != "" {
|
||||
args = append(args, "/p", p)
|
||||
}
|
||||
if tr := os.Getenv("CODESIGN_TIMESTAMP_SERVER"); tr != "" {
|
||||
switch algo {
|
||||
case "sha256":
|
||||
args = append(args, "/tr", tr, "/td", algo)
|
||||
default:
|
||||
args = append(args, "/t", tr)
|
||||
}
|
||||
}
|
||||
if i > 0 {
|
||||
args = append(args, "/as")
|
||||
}
|
||||
args = append(args, file)
|
||||
|
||||
bs, err := runError(st, args...)
|
||||
if err != nil {
|
||||
log.Println("Codesign: signing failed:", string(bs))
|
||||
return
|
||||
}
|
||||
log.Println("Codesign: successfully signed", file, "using", algo)
|
||||
}
|
||||
}
|
||||
|
||||
func metalint() {
|
||||
lazyRebuildAssets()
|
||||
runPrint("go", "test", "-run", "Metalint", "./meta")
|
||||
|
||||
@@ -92,7 +92,7 @@ loop:
|
||||
return t1.Sub(t0)
|
||||
}
|
||||
|
||||
// report stops the given process and reports on it's resource usage in two
|
||||
// report stops the given process and reports on its resource usage in two
|
||||
// ways: human readable to stderr, and CSV to stdout.
|
||||
func report(p *rc.Process, wallTime time.Duration) {
|
||||
sv, err := p.SystemVersion()
|
||||
|
||||
@@ -189,7 +189,7 @@ done:
|
||||
// We can end up here in 3 cases:
|
||||
// 1. Timeout joining, in which case there are potentially entries in pendingSessions
|
||||
// 2. General session end/timeout, in which case there are entries in activeSessions
|
||||
// 3. Protocol handler calls dropSession as one of it's clients disconnects.
|
||||
// 3. Protocol handler calls dropSession as one of its clients disconnects.
|
||||
|
||||
sessionMut.Lock()
|
||||
delete(pendingSessions, string(s.serverkey))
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
"regexp"
|
||||
"runtime"
|
||||
"runtime/pprof"
|
||||
"sort"
|
||||
@@ -25,6 +26,7 @@ import (
|
||||
|
||||
"github.com/rcrowley/go-metrics"
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/connections"
|
||||
"github.com/syncthing/syncthing/lib/db"
|
||||
"github.com/syncthing/syncthing/lib/discover"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
@@ -43,6 +45,9 @@ import (
|
||||
|
||||
var (
|
||||
startTime = time.Now()
|
||||
|
||||
// matches a bcrypt hash and not too much else
|
||||
bcryptExpr = regexp.MustCompile(`^\$2[aby]\$\d+\$.{50,}`)
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -94,24 +99,25 @@ type modelIntf interface {
|
||||
ScanFolders() map[string]error
|
||||
ScanFolderSubdirs(folder string, subs []string) error
|
||||
BringToFront(folder, file string)
|
||||
ConnectedTo(deviceID protocol.DeviceID) bool
|
||||
Connection(deviceID protocol.DeviceID) (connections.Connection, bool)
|
||||
GlobalSize(folder string) db.Counts
|
||||
LocalSize(folder string) db.Counts
|
||||
CurrentSequence(folder string) (int64, bool)
|
||||
RemoteSequence(folder string) (int64, bool)
|
||||
State(folder string) (string, time.Time, error)
|
||||
UsageReportingStats(version int, preview bool) map[string]interface{}
|
||||
}
|
||||
|
||||
type configIntf interface {
|
||||
GUI() config.GUIConfiguration
|
||||
RawCopy() config.Configuration
|
||||
Options() config.OptionsConfiguration
|
||||
Replace(cfg config.Configuration) error
|
||||
Replace(cfg config.Configuration) (config.Waiter, error)
|
||||
Subscribe(c config.Committer)
|
||||
Folders() map[string]config.FolderConfiguration
|
||||
Devices() map[protocol.DeviceID]config.DeviceConfiguration
|
||||
SetDevice(config.DeviceConfiguration) error
|
||||
SetDevices([]config.DeviceConfiguration) error
|
||||
SetDevice(config.DeviceConfiguration) (config.Waiter, error)
|
||||
SetDevices([]config.DeviceConfiguration) (config.Waiter, error)
|
||||
Save() error
|
||||
ListenAddresses() []string
|
||||
RequiresRestart() bool
|
||||
@@ -119,6 +125,7 @@ type configIntf interface {
|
||||
|
||||
type connectionsIntf interface {
|
||||
Status() map[string]interface{}
|
||||
NATType() string
|
||||
}
|
||||
|
||||
type rater interface {
|
||||
@@ -332,7 +339,7 @@ func (s *apiService) Serve() {
|
||||
}
|
||||
|
||||
// Add the CORS handling
|
||||
handler = corsMiddleware(handler)
|
||||
handler = corsMiddleware(handler, guiCfg.InsecureAllowFrameLoading)
|
||||
|
||||
if addressIsLocalhost(guiCfg.Address()) && !guiCfg.InsecureSkipHostCheck {
|
||||
// Verify source host
|
||||
@@ -459,7 +466,7 @@ func debugMiddleware(h http.Handler) http.Handler {
|
||||
})
|
||||
}
|
||||
|
||||
func corsMiddleware(next http.Handler) http.Handler {
|
||||
func corsMiddleware(next http.Handler, allowFrameLoading bool) http.Handler {
|
||||
// Handle CORS headers and CORS OPTIONS request.
|
||||
// CORS OPTIONS request are typically sent by browser during AJAX preflight
|
||||
// when the browser initiate a POST request.
|
||||
@@ -486,6 +493,27 @@ func corsMiddleware(next http.Handler) http.Handler {
|
||||
return
|
||||
}
|
||||
|
||||
// Other security related headers that should be present.
|
||||
// https://www.owasp.org/index.php/Security_Headers
|
||||
|
||||
if !allowFrameLoading {
|
||||
// We don't want to be rendered in an <iframe>,
|
||||
// <frame> or <object>. (Unless we do it ourselves.
|
||||
// This is also an escape hatch for people who serve
|
||||
// Syncthing GUI as part of their own website
|
||||
// through a proxy, so they don't need to set the
|
||||
// allowFrameLoading bool.)
|
||||
w.Header().Set("X-Frame-Options", "SAMEORIGIN")
|
||||
}
|
||||
|
||||
// If the browser senses an XSS attack it's allowed to take
|
||||
// action. (How this would not always be the default I
|
||||
// don't fully understand.)
|
||||
w.Header().Set("X-XSS-Protection", "1; mode=block")
|
||||
|
||||
// Our content type headers are correct. Don't guess.
|
||||
w.Header().Set("X-Content-Type-Options", "nosniff")
|
||||
|
||||
// For everything else, pass to the next handler
|
||||
next.ServeHTTP(w, r)
|
||||
return
|
||||
@@ -767,7 +795,7 @@ func (s *apiService) postSystemConfig(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
|
||||
if to.GUI.Password != s.cfg.GUI().Password {
|
||||
if to.GUI.Password != "" {
|
||||
if to.GUI.Password != "" && !bcryptExpr.MatchString(to.GUI.Password) {
|
||||
hash, err := bcrypt.GenerateFromPassword([]byte(to.GUI.Password), 0)
|
||||
if err != nil {
|
||||
l.Warnln("bcrypting password:", err)
|
||||
@@ -779,21 +807,9 @@ func (s *apiService) postSystemConfig(w http.ResponseWriter, r *http.Request) {
|
||||
}
|
||||
}
|
||||
|
||||
// Fixup usage reporting settings
|
||||
|
||||
if curAcc := s.cfg.Options().URAccepted; to.Options.URAccepted > curAcc {
|
||||
// UR was enabled
|
||||
to.Options.URAccepted = usageReportVersion
|
||||
to.Options.URUniqueID = rand.String(8)
|
||||
} else if to.Options.URAccepted < curAcc {
|
||||
// UR was disabled
|
||||
to.Options.URAccepted = -1
|
||||
to.Options.URUniqueID = ""
|
||||
}
|
||||
|
||||
// Activate and save
|
||||
|
||||
if err := s.cfg.Replace(to); err != nil {
|
||||
if _, err := s.cfg.Replace(to); err != nil {
|
||||
l.Warnln("Replacing config:", err)
|
||||
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||
return
|
||||
@@ -882,6 +898,7 @@ func (s *apiService) getSystemStatus(w http.ResponseWriter, r *http.Request) {
|
||||
// gives us percent
|
||||
res["cpuPercent"] = s.cpu.Rate() / 10 / float64(runtime.NumCPU())
|
||||
res["pathSeparator"] = string(filepath.Separator)
|
||||
res["urVersionMax"] = usageReportVersion
|
||||
res["uptime"] = int(time.Since(startTime).Seconds())
|
||||
res["startTime"] = startTime
|
||||
|
||||
@@ -960,7 +977,11 @@ func (s *apiService) getSystemDiscovery(w http.ResponseWriter, r *http.Request)
|
||||
}
|
||||
|
||||
func (s *apiService) getReport(w http.ResponseWriter, r *http.Request) {
|
||||
sendJSON(w, reportData(s.cfg, s.model))
|
||||
version := usageReportVersion
|
||||
if val, _ := strconv.Atoi(r.URL.Query().Get("version")); val > 0 {
|
||||
version = val
|
||||
}
|
||||
sendJSON(w, reportData(s.cfg, s.model, s.connectionsService, version, true))
|
||||
}
|
||||
|
||||
func (s *apiService) getRandomString(w http.ResponseWriter, r *http.Request) {
|
||||
@@ -1180,7 +1201,7 @@ func (s *apiService) makeDevicePauseHandler(paused bool) http.HandlerFunc {
|
||||
cfgs = append(cfgs, cfg)
|
||||
}
|
||||
|
||||
if err := s.cfg.SetDevices(cfgs); err != nil {
|
||||
if _, err := s.cfg.SetDevices(cfgs); err != nil {
|
||||
http.Error(w, err.Error(), 500)
|
||||
}
|
||||
}
|
||||
@@ -1239,7 +1260,7 @@ func (s *apiService) getPeerCompletion(w http.ResponseWriter, r *http.Request) {
|
||||
for _, folder := range s.cfg.Folders() {
|
||||
for _, device := range folder.DeviceIDs() {
|
||||
deviceStr := device.String()
|
||||
if s.model.ConnectedTo(device) {
|
||||
if _, ok := s.model.Connection(device); ok {
|
||||
tot[deviceStr] += s.model.Completion(device, folder.ID).CompletionPct
|
||||
} else {
|
||||
tot[deviceStr] = 0
|
||||
|
||||
@@ -141,17 +141,17 @@ func (s *staticsServer) serveThemes(w http.ResponseWriter, r *http.Request) {
|
||||
func (s *staticsServer) mimeTypeForFile(file string) string {
|
||||
// We use a built in table of the common types since the system
|
||||
// TypeByExtension might be unreliable. But if we don't know, we delegate
|
||||
// to the system.
|
||||
// to the system. All our files are UTF-8.
|
||||
ext := filepath.Ext(file)
|
||||
switch ext {
|
||||
case ".htm", ".html":
|
||||
return "text/html"
|
||||
return "text/html; charset=utf-8"
|
||||
case ".css":
|
||||
return "text/css"
|
||||
return "text/css; charset=utf-8"
|
||||
case ".js":
|
||||
return "application/javascript"
|
||||
return "application/javascript; charset=utf-8"
|
||||
case ".json":
|
||||
return "application/json"
|
||||
return "application/json; charset=utf-8"
|
||||
case ".png":
|
||||
return "image/png"
|
||||
case ".ttf":
|
||||
@@ -159,7 +159,7 @@ func (s *staticsServer) mimeTypeForFile(file string) string {
|
||||
case ".woff":
|
||||
return "application/x-font-woff"
|
||||
case ".svg":
|
||||
return "image/svg+xml"
|
||||
return "image/svg+xml; charset=utf-8"
|
||||
default:
|
||||
return mime.TypeByExtension(ext)
|
||||
}
|
||||
|
||||
@@ -87,13 +87,6 @@ const (
|
||||
maxSystemLog = 250
|
||||
)
|
||||
|
||||
// The discovery results are sorted by their source priority.
|
||||
const (
|
||||
ipv6LocalDiscoveryPriority = iota
|
||||
ipv4LocalDiscoveryPriority
|
||||
globalDiscoveryPriority
|
||||
)
|
||||
|
||||
func init() {
|
||||
if Version != "unknown-dev" {
|
||||
// If not a generic dev build, version string should come from git describe
|
||||
@@ -236,6 +229,7 @@ type RuntimeOptions struct {
|
||||
resetDeltaIdxs bool
|
||||
showVersion bool
|
||||
showPaths bool
|
||||
showDeviceId bool
|
||||
doUpgrade bool
|
||||
doUpgradeCheck bool
|
||||
upgradeTo string
|
||||
@@ -301,6 +295,7 @@ func parseCommandLineOptions() RuntimeOptions {
|
||||
flag.BoolVar(&options.doUpgradeCheck, "upgrade-check", false, "Check for available upgrade")
|
||||
flag.BoolVar(&options.showVersion, "version", false, "Show version")
|
||||
flag.BoolVar(&options.showPaths, "paths", false, "Show configuration paths")
|
||||
flag.BoolVar(&options.showDeviceId, "device-id", false, "Show the device ID")
|
||||
flag.StringVar(&options.upgradeTo, "upgrade-to", options.upgradeTo, "Force upgrade directly from specified URL")
|
||||
flag.BoolVar(&options.auditEnabled, "audit", false, "Write events to audit file")
|
||||
flag.BoolVar(&options.verbose, "verbose", false, "Print verbose log output")
|
||||
@@ -390,6 +385,17 @@ func main() {
|
||||
return
|
||||
}
|
||||
|
||||
if options.showDeviceId {
|
||||
cert, err := tls.LoadX509KeyPair(locations[locCertFile], locations[locKeyFile])
|
||||
if err != nil {
|
||||
l.Fatalln("Error reading device ID:", err)
|
||||
}
|
||||
|
||||
myID = protocol.NewDeviceID(cert.Certificate[0])
|
||||
fmt.Println(myID)
|
||||
return
|
||||
}
|
||||
|
||||
if options.browserOnly {
|
||||
openGUI()
|
||||
return
|
||||
@@ -436,7 +442,7 @@ func main() {
|
||||
}
|
||||
|
||||
func openGUI() {
|
||||
cfg, _ := loadConfig()
|
||||
cfg, _ := loadOrDefaultConfig()
|
||||
if cfg.GUI().Enabled {
|
||||
openURL(cfg.GUI().URL())
|
||||
} else {
|
||||
@@ -475,9 +481,7 @@ func generate(generateDir string) {
|
||||
l.Warnln("Config exists; will not overwrite.")
|
||||
return
|
||||
}
|
||||
var myName, _ = os.Hostname()
|
||||
var newCfg = defaultConfig(myName)
|
||||
var cfg = config.Wrap(cfgFile, newCfg)
|
||||
var cfg = defaultConfig(cfgFile)
|
||||
err = cfg.Save()
|
||||
if err != nil {
|
||||
l.Warnln("Failed to save config", err)
|
||||
@@ -507,7 +511,7 @@ func debugFacilities() string {
|
||||
}
|
||||
|
||||
func checkUpgrade() upgrade.Release {
|
||||
cfg, _ := loadConfig()
|
||||
cfg, _ := loadOrDefaultConfig()
|
||||
opts := cfg.Options()
|
||||
release, err := upgrade.LatestRelease(opts.ReleasesURL, Version, opts.UpgradeToPreReleases)
|
||||
if err != nil {
|
||||
@@ -545,7 +549,7 @@ func performUpgrade(release upgrade.Release) {
|
||||
}
|
||||
|
||||
func upgradeViaRest() error {
|
||||
cfg, _ := loadConfig()
|
||||
cfg, _ := loadOrDefaultConfig()
|
||||
u, err := url.Parse(cfg.GUI().URL())
|
||||
if err != nil {
|
||||
return err
|
||||
@@ -650,7 +654,7 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
||||
"myID": myID.String(),
|
||||
})
|
||||
|
||||
cfg := loadOrCreateConfig()
|
||||
cfg := loadConfigAtStartup()
|
||||
|
||||
if err := checkShortIDs(cfg); err != nil {
|
||||
l.Fatalln("Short device IDs are in conflict. Unlucky!\n Regenerate the device ID of one of the following:\n ", err)
|
||||
@@ -691,9 +695,7 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
||||
},
|
||||
}
|
||||
|
||||
opts := cfg.Options()
|
||||
|
||||
if opts.WeakHashSelectionMethod == config.WeakHashAuto {
|
||||
if opts := cfg.Options(); opts.WeakHashSelectionMethod == config.WeakHashAuto {
|
||||
perfWithWeakHash := cpuBench(3, 150*time.Millisecond, true)
|
||||
l.Infof("Hashing performance with weak hash is %.02f MB/s", perfWithWeakHash)
|
||||
perfWithoutWeakHash := cpuBench(3, 150*time.Millisecond, false)
|
||||
@@ -714,24 +716,6 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
||||
weakhash.Enabled = true
|
||||
}
|
||||
|
||||
if (opts.MaxRecvKbps > 0 || opts.MaxSendKbps > 0) && !opts.LimitBandwidthInLan {
|
||||
lans, _ = osutil.GetLans()
|
||||
for _, lan := range opts.AlwaysLocalNets {
|
||||
_, ipnet, err := net.ParseCIDR(lan)
|
||||
if err != nil {
|
||||
l.Infoln("Network", lan, "is malformed:", err)
|
||||
continue
|
||||
}
|
||||
lans = append(lans, ipnet)
|
||||
}
|
||||
|
||||
networks := make([]string, len(lans))
|
||||
for i, lan := range lans {
|
||||
networks[i] = lan.String()
|
||||
}
|
||||
l.Infoln("Local networks:", strings.Join(networks, ", "))
|
||||
}
|
||||
|
||||
dbFile := locations[locDatabase]
|
||||
ldb, err := db.Open(dbFile)
|
||||
|
||||
@@ -770,6 +754,17 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
||||
// Converts old symlink types to new in the entire database.
|
||||
ldb.ConvertSymlinkTypes()
|
||||
}
|
||||
if cfg.RawCopy().OriginalVersion < 26 {
|
||||
// Adds invalid (ignored) files to global list of files
|
||||
changed := 0
|
||||
for folderID, folderCfg := range folders {
|
||||
changed += ldb.AddInvalidToGlobal([]byte(folderID), protocol.LocalDeviceID[:])
|
||||
for _, deviceCfg := range folderCfg.Devices {
|
||||
changed += ldb.AddInvalidToGlobal([]byte(folderID), deviceCfg.DeviceID[:])
|
||||
}
|
||||
}
|
||||
l.Infof("Database update: Added %d ignored files to the global list", changed)
|
||||
}
|
||||
|
||||
m := model.NewModel(cfg, myID, "syncthing", Version, ldb, protectedFiles)
|
||||
|
||||
@@ -807,7 +802,7 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
||||
|
||||
// Start connection management
|
||||
|
||||
connectionsService := connections.NewService(cfg, myID, m, tlsCfg, cachedDiscovery, bepProtocolName, tlsDefaultCommonName, lans)
|
||||
connectionsService := connections.NewService(cfg, myID, m, tlsCfg, cachedDiscovery, bepProtocolName, tlsDefaultCommonName)
|
||||
mainService.Add(connectionsService)
|
||||
|
||||
if cfg.Options().GlobalAnnEnabled {
|
||||
@@ -822,7 +817,7 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
||||
// Each global discovery server gets its results cached for five
|
||||
// minutes, and is not asked again for a minute when it's returned
|
||||
// unsuccessfully.
|
||||
cachedDiscovery.Add(gd, 5*time.Minute, time.Minute, globalDiscoveryPriority)
|
||||
cachedDiscovery.Add(gd, 5*time.Minute, time.Minute)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -832,14 +827,14 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
||||
if err != nil {
|
||||
l.Warnln("IPv4 local discovery:", err)
|
||||
} else {
|
||||
cachedDiscovery.Add(bcd, 0, 0, ipv4LocalDiscoveryPriority)
|
||||
cachedDiscovery.Add(bcd, 0, 0)
|
||||
}
|
||||
// v6 multicasts
|
||||
mcd, err := discover.NewLocal(myID, cfg.Options().LocalAnnMCAddr, connectionsService)
|
||||
if err != nil {
|
||||
l.Warnln("IPv6 local discovery:", err)
|
||||
} else {
|
||||
cachedDiscovery.Add(mcd, 0, 0, ipv6LocalDiscoveryPriority)
|
||||
cachedDiscovery.Add(mcd, 0, 0)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -863,32 +858,24 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
||||
|
||||
// Candidate builds always run with usage reporting.
|
||||
|
||||
if IsCandidate {
|
||||
if opts := cfg.Options(); IsCandidate {
|
||||
l.Infoln("Anonymous usage reporting is always enabled for candidate releases.")
|
||||
opts.URAccepted = usageReportVersion
|
||||
cfg.SetOptions(opts)
|
||||
cfg.Save()
|
||||
// Unique ID will be set and config saved below if necessary.
|
||||
}
|
||||
|
||||
if opts.URAccepted > 0 && opts.URAccepted < usageReportVersion {
|
||||
l.Infoln("Anonymous usage report has changed; revoking acceptance")
|
||||
opts.URAccepted = 0
|
||||
opts.URUniqueID = ""
|
||||
cfg.SetOptions(opts)
|
||||
}
|
||||
|
||||
if opts.URAccepted >= usageReportVersion && opts.URUniqueID == "" {
|
||||
// Generate and save a new unique ID if it is missing.
|
||||
if opts := cfg.Options(); opts.URUniqueID == "" {
|
||||
opts.URUniqueID = rand.String(8)
|
||||
cfg.SetOptions(opts)
|
||||
cfg.Save()
|
||||
}
|
||||
|
||||
// The usageReportingManager registers itself to listen to configuration
|
||||
// changes, and there's nothing more we need to tell it from the outside.
|
||||
// Hence we don't keep the returned pointer.
|
||||
newUsageReportingManager(cfg, m)
|
||||
usageReportingSvc := newUsageReportingService(cfg, m, connectionsService)
|
||||
mainService.Add(usageReportingSvc)
|
||||
|
||||
if opts.RestartOnWakeup {
|
||||
if opts := cfg.Options(); opts.RestartOnWakeup {
|
||||
go standbyMonitor()
|
||||
}
|
||||
|
||||
@@ -898,7 +885,7 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
||||
|
||||
if IsCandidate && !upgrade.DisabledByCompilation && !noUpgradeFromEnv {
|
||||
l.Infoln("Automatic upgrade is always enabled for candidate releases.")
|
||||
if opts.AutoUpgradeIntervalH == 0 || opts.AutoUpgradeIntervalH > 24 {
|
||||
if opts := cfg.Options(); opts.AutoUpgradeIntervalH == 0 || opts.AutoUpgradeIntervalH > 24 {
|
||||
opts.AutoUpgradeIntervalH = 12
|
||||
// Set the option into the config as well, as the auto upgrade
|
||||
// loop expects to read a valid interval from there.
|
||||
@@ -909,7 +896,7 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
|
||||
// not, as otherwise they cannot step off the candidate channel.
|
||||
}
|
||||
|
||||
if opts.AutoUpgradeIntervalH > 0 {
|
||||
if opts := cfg.Options(); opts.AutoUpgradeIntervalH > 0 {
|
||||
if noUpgradeFromEnv {
|
||||
l.Infof("No automatic upgrades; STNOUPGRADE environment variable defined.")
|
||||
} else {
|
||||
@@ -962,26 +949,28 @@ func setupSignalHandling() {
|
||||
}()
|
||||
}
|
||||
|
||||
func loadConfig() (*config.Wrapper, error) {
|
||||
func loadOrDefaultConfig() (*config.Wrapper, error) {
|
||||
cfgFile := locations[locConfigFile]
|
||||
cfg, err := config.Load(cfgFile, myID)
|
||||
|
||||
if err != nil {
|
||||
myName, _ := os.Hostname()
|
||||
newCfg := defaultConfig(myName)
|
||||
cfg = config.Wrap(cfgFile, newCfg)
|
||||
cfg = defaultConfig(cfgFile)
|
||||
}
|
||||
|
||||
return cfg, err
|
||||
}
|
||||
|
||||
func loadOrCreateConfig() *config.Wrapper {
|
||||
cfg, err := loadConfig()
|
||||
func loadConfigAtStartup() *config.Wrapper {
|
||||
cfgFile := locations[locConfigFile]
|
||||
cfg, err := config.Load(cfgFile, myID)
|
||||
if os.IsNotExist(err) {
|
||||
cfg = defaultConfig(cfgFile)
|
||||
cfg.Save()
|
||||
l.Infof("Defaults saved. Edit %s to taste or use the GUI\n", cfg.ConfigPath())
|
||||
l.Infof("Default config saved. Edit %s to taste or use the GUI\n", cfg.ConfigPath())
|
||||
} else if err == io.EOF {
|
||||
l.Fatalln("Failed to load config: unexpected end of file. Truncated or empty configuration?")
|
||||
} else if err != nil {
|
||||
l.Fatalln("Config:", err)
|
||||
l.Fatalln("Failed to load config:", err)
|
||||
}
|
||||
|
||||
if cfg.RawCopy().OriginalVersion != config.CurrentVersion {
|
||||
@@ -1084,18 +1073,14 @@ func setupGUI(mainService *suture.Supervisor, cfg *config.Wrapper, m *model.Mode
|
||||
}
|
||||
}
|
||||
|
||||
func defaultConfig(myName string) config.Configuration {
|
||||
func defaultConfig(cfgFile string) *config.Wrapper {
|
||||
myName, _ := os.Hostname()
|
||||
|
||||
var defaultFolder config.FolderConfiguration
|
||||
|
||||
if !noDefaultFolder {
|
||||
l.Infoln("Default folder created and/or linked to new config")
|
||||
defaultFolder = config.NewFolderConfiguration("default", fs.FilesystemTypeBasic, locations[locDefFolder])
|
||||
defaultFolder.Label = "Default Folder"
|
||||
defaultFolder.RescanIntervalS = 60
|
||||
defaultFolder.MinDiskFree = config.Size{Value: 1, Unit: "%"}
|
||||
defaultFolder.Devices = []config.FolderDeviceConfiguration{{DeviceID: myID}}
|
||||
defaultFolder.AutoNormalize = true
|
||||
defaultFolder.MaxConflicts = -1
|
||||
defaultFolder = config.NewFolderConfiguration(myID, "default", "Default Folder", fs.FilesystemTypeBasic, locations[locDefFolder])
|
||||
} else {
|
||||
l.Infoln("We will skip creation of a default folder on first start since the proper envvar is set")
|
||||
}
|
||||
@@ -1128,7 +1113,7 @@ func defaultConfig(myName string) config.Configuration {
|
||||
}
|
||||
}
|
||||
|
||||
return newCfg
|
||||
return config.Wrap(cfgFile, newCfg)
|
||||
}
|
||||
|
||||
func resetDB() error {
|
||||
@@ -1339,7 +1324,7 @@ func setPauseState(cfg *config.Wrapper, paused bool) {
|
||||
for i := range raw.Folders {
|
||||
raw.Folders[i].Paused = paused
|
||||
}
|
||||
if err := cfg.Replace(raw); err != nil {
|
||||
if _, err := cfg.Replace(raw); err != nil {
|
||||
l.Fatalln("Cannot adjust paused state:", err)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,8 +34,8 @@ func (c *mockedConfig) Options() config.OptionsConfiguration {
|
||||
return config.OptionsConfiguration{}
|
||||
}
|
||||
|
||||
func (c *mockedConfig) Replace(cfg config.Configuration) error {
|
||||
return nil
|
||||
func (c *mockedConfig) Replace(cfg config.Configuration) (config.Waiter, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (c *mockedConfig) Subscribe(cm config.Committer) {}
|
||||
@@ -48,12 +48,12 @@ func (c *mockedConfig) Devices() map[protocol.DeviceID]config.DeviceConfiguratio
|
||||
return nil
|
||||
}
|
||||
|
||||
func (c *mockedConfig) SetDevice(config.DeviceConfiguration) error {
|
||||
return nil
|
||||
func (c *mockedConfig) SetDevice(config.DeviceConfiguration) (config.Waiter, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (c *mockedConfig) SetDevices([]config.DeviceConfiguration) error {
|
||||
return nil
|
||||
func (c *mockedConfig) SetDevices([]config.DeviceConfiguration) (config.Waiter, error) {
|
||||
return nil, nil
|
||||
}
|
||||
|
||||
func (c *mockedConfig) Save() error {
|
||||
|
||||
@@ -11,3 +11,7 @@ type mockedConnections struct{}
|
||||
func (m *mockedConnections) Status() map[string]interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *mockedConnections) NATType() string {
|
||||
return ""
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ func (m *mockedCachingMux) Cache() map[protocol.DeviceID]discover.CacheEntry {
|
||||
|
||||
// from events.CachingMux
|
||||
|
||||
func (m *mockedCachingMux) Add(finder discover.Finder, cacheTime, negCacheTime time.Duration, priority int) {
|
||||
func (m *mockedCachingMux) Add(finder discover.Finder, cacheTime, negCacheTime time.Duration) {
|
||||
}
|
||||
|
||||
func (m *mockedCachingMux) ChildErrors() map[string]error {
|
||||
|
||||
@@ -9,6 +9,7 @@ package main
|
||||
import (
|
||||
"time"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/connections"
|
||||
"github.com/syncthing/syncthing/lib/db"
|
||||
"github.com/syncthing/syncthing/lib/model"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
@@ -91,8 +92,8 @@ func (m *mockedModel) ScanFolderSubdirs(folder string, subs []string) error {
|
||||
|
||||
func (m *mockedModel) BringToFront(folder, file string) {}
|
||||
|
||||
func (m *mockedModel) ConnectedTo(deviceID protocol.DeviceID) bool {
|
||||
return false
|
||||
func (m *mockedModel) Connection(deviceID protocol.DeviceID) (connections.Connection, bool) {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
func (m *mockedModel) GlobalSize(folder string) db.Counts {
|
||||
@@ -114,3 +115,7 @@ func (m *mockedModel) RemoteSequence(folder string) (int64, bool) {
|
||||
func (m *mockedModel) State(folder string) (string, time.Time, error) {
|
||||
return "", time.Time{}, nil
|
||||
}
|
||||
|
||||
func (m *mockedModel) UsageReportingStats(version int, preview bool) map[string]interface{} {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -198,7 +198,7 @@ func (c *folderSummaryService) sendSummary(folder string) {
|
||||
// We already know about ourselves.
|
||||
continue
|
||||
}
|
||||
if !c.model.ConnectedTo(devCfg.DeviceID) {
|
||||
if _, ok := c.model.Connection(devCfg.DeviceID); !ok {
|
||||
// We're not interested in disconnected devices.
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -12,7 +12,7 @@ import (
|
||||
"crypto/rand"
|
||||
"crypto/tls"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
"runtime"
|
||||
"sort"
|
||||
@@ -20,71 +20,26 @@ import (
|
||||
"time"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/connections"
|
||||
"github.com/syncthing/syncthing/lib/dialer"
|
||||
"github.com/syncthing/syncthing/lib/model"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
"github.com/syncthing/syncthing/lib/scanner"
|
||||
"github.com/syncthing/syncthing/lib/upgrade"
|
||||
"github.com/thejerf/suture"
|
||||
"github.com/syncthing/syncthing/lib/weakhash"
|
||||
)
|
||||
|
||||
// Current version number of the usage report, for acceptance purposes. If
|
||||
// fields are added or changed this integer must be incremented so that users
|
||||
// are prompted for acceptance of the new report.
|
||||
const usageReportVersion = 2
|
||||
|
||||
type usageReportingManager struct {
|
||||
cfg *config.Wrapper
|
||||
model *model.Model
|
||||
sup *suture.Supervisor
|
||||
}
|
||||
|
||||
func newUsageReportingManager(cfg *config.Wrapper, m *model.Model) *usageReportingManager {
|
||||
mgr := &usageReportingManager{
|
||||
cfg: cfg,
|
||||
model: m,
|
||||
}
|
||||
|
||||
// Start UR if it's enabled.
|
||||
mgr.CommitConfiguration(config.Configuration{}, cfg.RawCopy())
|
||||
|
||||
// Listen to future config changes so that we can start and stop as
|
||||
// appropriate.
|
||||
cfg.Subscribe(mgr)
|
||||
|
||||
return mgr
|
||||
}
|
||||
|
||||
func (m *usageReportingManager) VerifyConfiguration(from, to config.Configuration) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *usageReportingManager) CommitConfiguration(from, to config.Configuration) bool {
|
||||
if to.Options.URAccepted >= usageReportVersion && m.sup == nil {
|
||||
// Usage reporting was turned on; lets start it.
|
||||
service := newUsageReportingService(m.cfg, m.model)
|
||||
m.sup = suture.NewSimple("usageReporting")
|
||||
m.sup.Add(service)
|
||||
m.sup.ServeBackground()
|
||||
} else if to.Options.URAccepted < usageReportVersion && m.sup != nil {
|
||||
// Usage reporting was turned off
|
||||
m.sup.Stop()
|
||||
m.sup = nil
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func (m *usageReportingManager) String() string {
|
||||
return fmt.Sprintf("usageReportingManager@%p", m)
|
||||
}
|
||||
const usageReportVersion = 3
|
||||
|
||||
// reportData returns the data to be sent in a usage report. It's used in
|
||||
// various places, so not part of the usageReportingManager object.
|
||||
func reportData(cfg configIntf, m modelIntf) map[string]interface{} {
|
||||
func reportData(cfg configIntf, m modelIntf, connectionsService connectionsIntf, version int, preview bool) map[string]interface{} {
|
||||
opts := cfg.Options()
|
||||
res := make(map[string]interface{})
|
||||
res["urVersion"] = usageReportVersion
|
||||
res["urVersion"] = version
|
||||
res["uniqueID"] = opts.URUniqueID
|
||||
res["version"] = Version
|
||||
res["longVersion"] = LongVersion
|
||||
@@ -227,25 +182,163 @@ func reportData(cfg configIntf, m modelIntf) map[string]interface{} {
|
||||
res["upgradeAllowedAuto"] = !(upgrade.DisabledByCompilation || noUpgradeFromEnv) && opts.AutoUpgradeIntervalH > 0
|
||||
res["upgradeAllowedPre"] = !(upgrade.DisabledByCompilation || noUpgradeFromEnv) && opts.AutoUpgradeIntervalH > 0 && opts.UpgradeToPreReleases
|
||||
|
||||
if version >= 3 {
|
||||
res["uptime"] = int(time.Now().Sub(startTime).Seconds())
|
||||
res["natType"] = connectionsService.NATType()
|
||||
res["alwaysLocalNets"] = len(opts.AlwaysLocalNets) > 0
|
||||
res["cacheIgnoredFiles"] = opts.CacheIgnoredFiles
|
||||
res["overwriteRemoteDeviceNames"] = opts.OverwriteRemoteDevNames
|
||||
res["progressEmitterEnabled"] = opts.ProgressUpdateIntervalS > -1
|
||||
res["customDefaultFolderPath"] = opts.DefaultFolderPath != "~"
|
||||
res["weakHashSelection"] = opts.WeakHashSelectionMethod.String()
|
||||
res["weakHashEnabled"] = weakhash.Enabled
|
||||
res["customTrafficClass"] = opts.TrafficClass != 0
|
||||
res["customTempIndexMinBlocks"] = opts.TempIndexMinBlocks != 10
|
||||
res["temporariesDisabled"] = opts.KeepTemporariesH == 0
|
||||
res["temporariesCustom"] = opts.KeepTemporariesH != 24
|
||||
res["limitBandwidthInLan"] = opts.LimitBandwidthInLan
|
||||
res["customReleaseURL"] = opts.ReleasesURL != "https://upgrades.syncthing.net/meta.json"
|
||||
res["restartOnWakeup"] = opts.RestartOnWakeup
|
||||
res["customStunServers"] = len(opts.StunServers) == 0 || opts.StunServers[0] != "default" || len(opts.StunServers) > 1
|
||||
|
||||
folderUsesV3 := map[string]int{
|
||||
"scanProgressDisabled": 0,
|
||||
"conflictsDisabled": 0,
|
||||
"conflictsUnlimited": 0,
|
||||
"conflictsOther": 0,
|
||||
"disableSparseFiles": 0,
|
||||
"disableTempIndexes": 0,
|
||||
"alwaysWeakHash": 0,
|
||||
"customWeakHashThreshold": 0,
|
||||
"fsWatcherEnabled": 0,
|
||||
}
|
||||
pullOrder := make(map[string]int)
|
||||
filesystemType := make(map[string]int)
|
||||
var fsWatcherDelays []int
|
||||
for _, cfg := range cfg.Folders() {
|
||||
if cfg.ScanProgressIntervalS < 0 {
|
||||
folderUsesV3["scanProgressDisabled"]++
|
||||
}
|
||||
if cfg.MaxConflicts == 0 {
|
||||
folderUsesV3["conflictsDisabled"]++
|
||||
} else if cfg.MaxConflicts < 0 {
|
||||
folderUsesV3["conflictsUnlimited"]++
|
||||
} else {
|
||||
folderUsesV3["conflictsOther"]++
|
||||
}
|
||||
if cfg.DisableSparseFiles {
|
||||
folderUsesV3["disableSparseFiles"]++
|
||||
}
|
||||
if cfg.DisableTempIndexes {
|
||||
folderUsesV3["disableTempIndexes"]++
|
||||
}
|
||||
if cfg.WeakHashThresholdPct < 0 {
|
||||
folderUsesV3["alwaysWeakHash"]++
|
||||
} else if cfg.WeakHashThresholdPct != 25 {
|
||||
folderUsesV3["customWeakHashThreshold"]++
|
||||
}
|
||||
if cfg.FSWatcherEnabled {
|
||||
folderUsesV3["fsWatcherEnabled"]++
|
||||
}
|
||||
pullOrder[cfg.Order.String()]++
|
||||
filesystemType[cfg.FilesystemType.String()]++
|
||||
fsWatcherDelays = append(fsWatcherDelays, cfg.FSWatcherDelayS)
|
||||
}
|
||||
sort.Ints(fsWatcherDelays)
|
||||
folderUsesV3Interface := map[string]interface{}{
|
||||
"pullOrder": pullOrder,
|
||||
"filesystemType": filesystemType,
|
||||
"fsWatcherDelays": fsWatcherDelays,
|
||||
}
|
||||
for key, value := range folderUsesV3 {
|
||||
folderUsesV3Interface[key] = value
|
||||
}
|
||||
res["folderUsesV3"] = folderUsesV3Interface
|
||||
|
||||
guiCfg := cfg.GUI()
|
||||
// Anticipate multiple GUI configs in the future, hence store counts.
|
||||
guiStats := map[string]int{
|
||||
"enabled": 0,
|
||||
"useTLS": 0,
|
||||
"useAuth": 0,
|
||||
"insecureAdminAccess": 0,
|
||||
"debugging": 0,
|
||||
"insecureSkipHostCheck": 0,
|
||||
"insecureAllowFrameLoading": 0,
|
||||
"listenLocal": 0,
|
||||
"listenUnspecified": 0,
|
||||
}
|
||||
theme := make(map[string]int)
|
||||
if guiCfg.Enabled {
|
||||
guiStats["enabled"]++
|
||||
if guiCfg.UseTLS() {
|
||||
guiStats["useTLS"]++
|
||||
}
|
||||
if len(guiCfg.User) > 0 && len(guiCfg.Password) > 0 {
|
||||
guiStats["useAuth"]++
|
||||
}
|
||||
if guiCfg.InsecureAdminAccess {
|
||||
guiStats["insecureAdminAccess"]++
|
||||
}
|
||||
if guiCfg.Debugging {
|
||||
guiStats["debugging"]++
|
||||
}
|
||||
if guiCfg.InsecureSkipHostCheck {
|
||||
guiStats["insecureSkipHostCheck"]++
|
||||
}
|
||||
if guiCfg.InsecureAllowFrameLoading {
|
||||
guiStats["insecureAllowFrameLoading"]++
|
||||
}
|
||||
|
||||
addr, err := net.ResolveTCPAddr("tcp", guiCfg.Address())
|
||||
if err == nil {
|
||||
if addr.IP.IsLoopback() {
|
||||
guiStats["listenLocal"]++
|
||||
} else if addr.IP.IsUnspecified() {
|
||||
guiStats["listenUnspecified"]++
|
||||
}
|
||||
}
|
||||
|
||||
theme[guiCfg.Theme]++
|
||||
}
|
||||
guiStatsInterface := map[string]interface{}{
|
||||
"theme": theme,
|
||||
}
|
||||
for key, value := range guiStats {
|
||||
guiStatsInterface[key] = value
|
||||
}
|
||||
res["guiStats"] = guiStatsInterface
|
||||
}
|
||||
|
||||
for key, value := range m.UsageReportingStats(version, preview) {
|
||||
res[key] = value
|
||||
}
|
||||
|
||||
return res
|
||||
}
|
||||
|
||||
type usageReportingService struct {
|
||||
cfg *config.Wrapper
|
||||
model *model.Model
|
||||
stop chan struct{}
|
||||
cfg *config.Wrapper
|
||||
model *model.Model
|
||||
connectionsService *connections.Service
|
||||
forceRun chan struct{}
|
||||
stop chan struct{}
|
||||
}
|
||||
|
||||
func newUsageReportingService(cfg *config.Wrapper, model *model.Model) *usageReportingService {
|
||||
return &usageReportingService{
|
||||
cfg: cfg,
|
||||
model: model,
|
||||
stop: make(chan struct{}),
|
||||
func newUsageReportingService(cfg *config.Wrapper, model *model.Model, connectionsService *connections.Service) *usageReportingService {
|
||||
svc := &usageReportingService{
|
||||
cfg: cfg,
|
||||
model: model,
|
||||
connectionsService: connectionsService,
|
||||
forceRun: make(chan struct{}),
|
||||
stop: make(chan struct{}),
|
||||
}
|
||||
cfg.Subscribe(svc)
|
||||
return svc
|
||||
}
|
||||
|
||||
func (s *usageReportingService) sendUsageReport() error {
|
||||
d := reportData(s.cfg, s.model)
|
||||
d := reportData(s.cfg, s.model, s.connectionsService, s.cfg.Options().URAccepted, false)
|
||||
var b bytes.Buffer
|
||||
json.NewEncoder(&b).Encode(d)
|
||||
|
||||
@@ -264,27 +357,45 @@ func (s *usageReportingService) sendUsageReport() error {
|
||||
|
||||
func (s *usageReportingService) Serve() {
|
||||
s.stop = make(chan struct{})
|
||||
|
||||
l.Infoln("Starting usage reporting")
|
||||
defer l.Infoln("Stopping usage reporting")
|
||||
|
||||
t := time.NewTimer(time.Duration(s.cfg.Options().URInitialDelayS) * time.Second) // time to initial report at start
|
||||
t := time.NewTimer(time.Duration(s.cfg.Options().URInitialDelayS) * time.Second)
|
||||
for {
|
||||
select {
|
||||
case <-s.stop:
|
||||
return
|
||||
case <-s.forceRun:
|
||||
t.Reset(0)
|
||||
case <-t.C:
|
||||
err := s.sendUsageReport()
|
||||
if err != nil {
|
||||
l.Infoln("Usage report:", err)
|
||||
if s.cfg.Options().URAccepted >= 2 {
|
||||
err := s.sendUsageReport()
|
||||
if err != nil {
|
||||
l.Infoln("Usage report:", err)
|
||||
} else {
|
||||
l.Infof("Sent usage report (version %d)", s.cfg.Options().URAccepted)
|
||||
}
|
||||
}
|
||||
t.Reset(24 * time.Hour) // next report tomorrow
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (s *usageReportingService) VerifyConfiguration(from, to config.Configuration) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *usageReportingService) CommitConfiguration(from, to config.Configuration) bool {
|
||||
if from.Options.URAccepted != to.Options.URAccepted || from.Options.URUniqueID != to.Options.URUniqueID || from.Options.URURL != to.Options.URURL {
|
||||
s.forceRun <- struct{}{}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (s *usageReportingService) Stop() {
|
||||
close(s.stop)
|
||||
close(s.forceRun)
|
||||
}
|
||||
|
||||
func (usageReportingService) String() string {
|
||||
return "usageReportingService"
|
||||
}
|
||||
|
||||
// cpuBench returns CPU performance as a measure of single threaded SHA-256 MiB/s
|
||||
|
||||
16
etc/freebsd-rc/README.md
Normal file
16
etc/freebsd-rc/README.md
Normal file
@@ -0,0 +1,16 @@
|
||||
This directory contains an example for running Syncthing with a `rc.d` script in FreeBSD.
|
||||
|
||||
* Install `syncthing` in `/usr/local/bin/syncthing`.
|
||||
* Copy the `syncthing` rc.d script in `/usr/local/etc/rc.d/syncthing`.
|
||||
* To automatically start `syncthing` at boot time, add the following line to `/etc/rc.conf`:
|
||||
```
|
||||
syncthing_enable=YES
|
||||
```
|
||||
* Optional configuration options are:
|
||||
```
|
||||
syncthing_home=</path/to/syncthing/config/dir>
|
||||
syncthing_log_file=</path/to/syncthing/log/file>
|
||||
syncthing_user=<syncthing_user>
|
||||
syncthing_group=<syncthing_group>
|
||||
```
|
||||
See the rc.d script for more informations.
|
||||
54
etc/freebsd-rc/syncthing
Normal file
54
etc/freebsd-rc/syncthing
Normal file
@@ -0,0 +1,54 @@
|
||||
#!/bin/sh
|
||||
#
|
||||
#
|
||||
# PROVIDE: syncthing
|
||||
# REQUIRE: DAEMON
|
||||
# KEYWORD: shutdown
|
||||
#
|
||||
# Add the following lines to /etc/rc.conf to enable this service:
|
||||
#
|
||||
# syncthing_enable: Set to NO by default. Set it to YES to enable it.
|
||||
# syncthing_home: Directory where syncthing configuration
|
||||
# data is stored.
|
||||
# Default: /usr/local/etc/syncthing
|
||||
# syncthing_log_file: Syncthing log file
|
||||
# Default: /var/log/syncthing.log
|
||||
# syncthing_user: The user account syncthing daemon runs as what
|
||||
# you want it to be.
|
||||
# Default: syncthing
|
||||
# syncthing_group: The group account syncthing daemon runs as what
|
||||
# you want it to be.
|
||||
# Default: syncthing
|
||||
|
||||
. /etc/rc.subr
|
||||
|
||||
name=syncthing
|
||||
rcvar=syncthing_enable
|
||||
|
||||
start_cmd="${name}_start"
|
||||
|
||||
load_rc_config $name
|
||||
|
||||
: ${syncthing_enable:=NO}
|
||||
: ${syncthing_home=/usr/local/etc/syncthing}
|
||||
: ${syncthing_log_file=/var/log/syncthing.log}
|
||||
: ${syncthing_user:=syncthing}
|
||||
syncthing_group=${syncthing_group:-$syncthing_user}
|
||||
|
||||
|
||||
command=/usr/local/bin/syncthing
|
||||
pidfile=/var/run/syncthing.pid
|
||||
syncthing_flags="${syncthing_home:+-home=${syncthing_home}} ${syncthing_log_file:+-logfile=${syncthing_log_file}}"
|
||||
|
||||
syncthing_start() {
|
||||
echo "Starting syncthing"
|
||||
touch ${pidfile} && chown ${syncthing_user} ${pidfile}
|
||||
touch ${syncthing_log_file} && chown ${syncthing_user} ${syncthing_log_file}
|
||||
/usr/sbin/daemon -cf -p ${pidfile} -u ${syncthing_user} ${command} ${syncthing_flags}
|
||||
}
|
||||
|
||||
syncthing_cleanup() {
|
||||
[ -f ${pidfile} ] && rm ${pidfile}
|
||||
}
|
||||
|
||||
run_rc_command $1
|
||||
@@ -367,3 +367,7 @@ ul.three-columns li, ul.two-columns li {
|
||||
width: 100%;
|
||||
}
|
||||
}
|
||||
|
||||
.tab-content {
|
||||
padding-top: 10px;
|
||||
}
|
||||
|
||||
@@ -24,7 +24,10 @@
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "Друга команда се занимава с версиите. Тази команда трябва да премахне файла от синхронизираната папка.",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "Друга команда се занимава с версиите. Тази команда трябва да премахни файла от синхронизираната папка.",
|
||||
"Anonymous Usage Reporting": "Анонимен доклад",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "Форматът на анонимния доклад е променен. Желаете ли да преминете към новия формат?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "Устройства настроени да представят други устройства също ще бъдат добавени към това устройство.",
|
||||
"Are you sure you want to remove device {%name%}?": "Сигурни ли сте, че искате да премахнете устройство {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Сигурни ли сте, че искате да премахнете папка {{label}}?",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Автоматичното обновяване вече предлага избор между стабилни версии и кандидат версии.",
|
||||
"Automatic upgrades": "Автоматично обновяване",
|
||||
"Be careful!": "Внимание!",
|
||||
@@ -53,6 +56,7 @@
|
||||
"Device Identification": "Идентификатор на устройство",
|
||||
"Device Name": "Име на устройството",
|
||||
"Devices": "Устройства",
|
||||
"Disabled": "Деактивирано",
|
||||
"Disconnected": "Не е свързано",
|
||||
"Discovered": "Открит",
|
||||
"Discovery": "Откриване",
|
||||
@@ -84,6 +88,7 @@
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Когато syncthing замени или изтрие файл той се премества в .stversions и преименува с набавени дата и час.",
|
||||
"Files are moved to date stamped versions in a .stversions folder 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.": "Защитава файловете от промени направени на други устройства, но промените направени на това устройство ще бъдат синхронизирани с останалите устройства.",
|
||||
"Filesystem Notifications": "Известия на системата",
|
||||
"Folder": "Папка",
|
||||
"Folder ID": "Идентификатор на папката",
|
||||
"Folder Label": "Етикет на папката",
|
||||
@@ -136,6 +141,7 @@
|
||||
"Newest First": "Първо най-новите",
|
||||
"No": "Не",
|
||||
"No File Versioning": "Без версии",
|
||||
"No files will be deleted as a result of this operation.": "Няма да бъдат изтрити файлове като резултат от тази операция.",
|
||||
"No upgrades": "Няма обновления",
|
||||
"Normal": "Нормален",
|
||||
"Notice": "Известие",
|
||||
@@ -165,11 +171,14 @@
|
||||
"Quick guide to supported patterns": "Бърз наръчник към поддържаните шаблони",
|
||||
"RAM Utilization": "Използван RAM",
|
||||
"Random": "Произволен",
|
||||
"Recent Changes": "Последни промени",
|
||||
"Reduced by ignore patterns": "Намалено посредством шаблон за игнориране",
|
||||
"Release Notes": "Бележки по обновяването",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Кандидат версиите съдържат най-новата функционалност и поправки. Те са близки до традиционните дву-седмични Synchthing обновления.",
|
||||
"Remote Devices": "Чужди устройства",
|
||||
"Remove": "Премахни",
|
||||
"Remove Device": "Премахване на устройство",
|
||||
"Remove Folder": "Премахване на папка",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "Задължителен идентификатор за тази папка. Трябва да бъде един и същ на всички устройства.",
|
||||
"Rescan": "Сканирай",
|
||||
"Rescan All": "Обнови всички",
|
||||
@@ -184,6 +193,8 @@
|
||||
"Scan Time Remaining": "Оставащо време за сканиране",
|
||||
"Scanning": "Сканиране",
|
||||
"See external versioner help for supported templated command line parameters.": "Прегледайте документацията на външното приложение за версии и поддържаните от него командни параметри. ",
|
||||
"See external versioning help for supported templated command line parameters.": "Прегледайте външната документацията за поддържаните командни параметри. ",
|
||||
"Select a version": "Изберте версия",
|
||||
"Select the devices to share this folder with.": "Изберете устройствата, с които да споделите папката.",
|
||||
"Select the folders to share with this device.": "Изберете папките за споделяне с това устройство.",
|
||||
"Send & Receive": "Изпращане & получаване",
|
||||
@@ -197,6 +208,7 @@
|
||||
"Shared With": "Споделена с",
|
||||
"Show ID": "Покажи идентификатора",
|
||||
"Show QR": "Покажи QR",
|
||||
"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": "Спри програмата",
|
||||
@@ -252,6 +264,7 @@
|
||||
"Time": "Време",
|
||||
"Trash Can File Versioning": "Само на файловете в кошчето",
|
||||
"Type": "Тип",
|
||||
"Undecided (will prompt)": "Неизбрано (ще попита)",
|
||||
"Unknown": "Неясно",
|
||||
"Unshared": "Несподелена",
|
||||
"Unused": "Неизползван",
|
||||
|
||||
@@ -24,7 +24,10 @@
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "Un command extern maneja les versions. Té que eliminar el fitxer de la carpeta compartida.",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "Un comando extern controla el versionat. És necessari eliminar el fitxer de la carpeta sincronitzada.",
|
||||
"Anonymous Usage Reporting": "Informe d'ús anònim",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "Anonymous usage report format has changed. Would you like to move to the new format?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "Tots els dispositius configurats en un dispositiu presentador seràn afegits també a aquest dispositiu.",
|
||||
"Are you sure you want to remove device {%name%}?": "Are you sure you want to remove device {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Are you sure you want to remove folder {{label}}?",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "L'actualització automàtica ara ofereix l'elecció entre les versions estables i les versions candidates.",
|
||||
"Automatic upgrades": "Actualitzacions automàtiques",
|
||||
"Be careful!": "Tin precaució!",
|
||||
@@ -53,6 +56,7 @@
|
||||
"Device Identification": "Identificació del dispositiu",
|
||||
"Device Name": "Nom del dispositiu",
|
||||
"Devices": "Dispositius",
|
||||
"Disabled": "Disabled",
|
||||
"Disconnected": "Desconnectat",
|
||||
"Discovered": "Descobert",
|
||||
"Discovery": "Descobriment",
|
||||
@@ -84,6 +88,7 @@
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Els arxius seran moguts a un directori .stversions a versions amb control de la data quan siguen reemplaçats o esborrats per Syncthing.",
|
||||
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Els fitxers són canviats a versions amb indicació de data en una carpeta \".stversions\" quant són reemplaçats o esborrats per Syncthing.",
|
||||
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Els fitxers són protegits dels canvis fets en altres dispositius, però els canvis fets en aquest dispositiu seràn enviats a la resta del grup (cluster).",
|
||||
"Filesystem Notifications": "Filesystem Notifications",
|
||||
"Folder": "Carpeta",
|
||||
"Folder ID": "ID de carpeta",
|
||||
"Folder Label": "Etiqueta de la Carpeta",
|
||||
@@ -136,6 +141,7 @@
|
||||
"Newest First": "El més nou primer",
|
||||
"No": "No",
|
||||
"No File Versioning": "Sense versionat de fitxer",
|
||||
"No files will be deleted as a result of this operation.": "No files will be deleted as a result of this operation.",
|
||||
"No upgrades": "Sense actualitzacions",
|
||||
"Normal": "Normal",
|
||||
"Notice": "Avís",
|
||||
@@ -165,11 +171,14 @@
|
||||
"Quick guide to supported patterns": "Guía ràpida de patrons suportats",
|
||||
"RAM Utilization": "Utilització de la RAM",
|
||||
"Random": "Aleatori",
|
||||
"Recent Changes": "Recent Changes",
|
||||
"Reduced by ignore patterns": "Reduït ignorant patrons",
|
||||
"Release Notes": "Notes de la versió",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Les versions candidates (Release Candidates) contenen les darreres característiques i arreglos. Són paregudes a les versions tradicionals bi-semanals de Syncthing. ",
|
||||
"Remote Devices": "Dispositius Remots",
|
||||
"Remove": "Eliminar",
|
||||
"Remove Device": "Remove Device",
|
||||
"Remove Folder": "Remove Folder",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "Identificador necessari per la carpeta. Deu ser el mateix en tots els dispositius del cluster.",
|
||||
"Rescan": "Tornar a buscar",
|
||||
"Rescan All": "Tornar a buscar tot",
|
||||
@@ -184,6 +193,8 @@
|
||||
"Scan Time Remaining": "Temps d'escaneig restant",
|
||||
"Scanning": "Rastrejant",
|
||||
"See external versioner help for supported templated command line parameters.": "See external versioner help for supported templated command line parameters.",
|
||||
"See external versioning help for supported templated command line parameters.": "See external versioning help for supported templated command line parameters.",
|
||||
"Select a version": "Select a version",
|
||||
"Select the devices to share this folder with.": "Selecciona els dispositius amb els que compartir aquesta carpeta.",
|
||||
"Select the folders to share with this device.": "Selecciona les carpetes per a compartir amb aquest dispositiu.",
|
||||
"Send & Receive": "Enviar i Rebre",
|
||||
@@ -197,6 +208,7 @@
|
||||
"Shared With": "Compartit amb",
|
||||
"Show ID": "Mostrar ID",
|
||||
"Show QR": "Mostrar QR",
|
||||
"Show diff with previous version": "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.": "Mostrat en lloc de l'ID del dispositiu en l'estat del grup (cluster). S'anunciarà als altres dispositius com el nom opcional per defecte.",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Mostrat en lloc de l'ID del dispositiu en l'estat del grup (cluster). S'actualitzarà al nom que el dispositiu anuncia si es deixa buit.",
|
||||
"Shutdown": "Apagar",
|
||||
@@ -252,6 +264,7 @@
|
||||
"Time": "Temps",
|
||||
"Trash Can File Versioning": "Versionat d'arxius de la paperera",
|
||||
"Type": "Tipus",
|
||||
"Undecided (will prompt)": "Undecided (will prompt)",
|
||||
"Unknown": "Desconegut",
|
||||
"Unshared": "No compartit",
|
||||
"Unused": "No utilitzat",
|
||||
|
||||
@@ -21,10 +21,13 @@
|
||||
"Allow Anonymous Usage Reporting?": "Povolit anonymní hlášení o používání?",
|
||||
"Allowed Networks": "Povolené sítě",
|
||||
"Alphabetic": "Abecedně",
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "O verzování se stará externí příkaz. To on musí smazat soubor ze sdíleného adresáře.",
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "Verzování obstarává externí příkaz. Musí odstranit soubor ze sdíleného adresáře.",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "Verzování obstarává externí příkaz. Musí odstranit soubor ze sdíleného adresáře.",
|
||||
"Anonymous Usage Reporting": "Anonymní hlášení o používání",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "Formát anonymního hlášení o používání byl změněn. Chcete přejít na nový formát?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "Jakékoliv přístroje nakonfigurované na zavaděči budou přidány také na tento přístroj.",
|
||||
"Are you sure you want to remove device {%name%}?": "Are you sure you want to remove device {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Are you sure you want to remove folder {{label}}?",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Automatická aktualizace nyní nabízí volbu mezi stabilními vydáními a kandidáty na vydání.",
|
||||
"Automatic upgrades": "Automatické aktualizace",
|
||||
"Be careful!": "Pozor!",
|
||||
@@ -53,6 +56,7 @@
|
||||
"Device Identification": "Identifikace přístroje",
|
||||
"Device Name": "Jméno přístroje",
|
||||
"Devices": "Přístroje",
|
||||
"Disabled": "Vypnuto",
|
||||
"Disconnected": "Odpojen",
|
||||
"Discovered": "Nalezeno",
|
||||
"Discovery": "Oznamování",
|
||||
@@ -84,6 +88,7 @@
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Po nahrazení nebo smazání aplikací Syncthing jsou soubory přesunuty do verzí označených daty v adresáři .stversions.",
|
||||
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Po nahrazení nebo smazání aplikací Syncthing jsou soubory přesunuty do verzí označených daty ve složce .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.": "Soubory jsou chráněny před změnami na ostatních přístrojích, ale změny provedené z tohoto přístroje budou rozeslány na zbytek clusteru.",
|
||||
"Filesystem Notifications": "Oznámení souborového systému",
|
||||
"Folder": "Adresář",
|
||||
"Folder ID": "ID adresáře",
|
||||
"Folder Label": "Jmenovka adresáře",
|
||||
@@ -136,6 +141,7 @@
|
||||
"Newest First": "Od nejnovějšího",
|
||||
"No": "Ne",
|
||||
"No File Versioning": "Bez verzování souborů",
|
||||
"No files will be deleted as a result of this operation.": "No files will be deleted as a result of this operation.",
|
||||
"No upgrades": "Žádné aktualizace",
|
||||
"Normal": "Normální",
|
||||
"Notice": "Oznámení",
|
||||
@@ -158,18 +164,21 @@
|
||||
"Please consult the release notes before performing a major upgrade.": "Před spuštěním důležité aktualizace 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.": "Zadejte prosím přihlašovací jméno a heslo pro GUI v dialogu nastavení.",
|
||||
"Please wait": "Chvíli strpení",
|
||||
"Prefix indicating that the file can be deleted if preventing directory removal": "Prefix indicating that the file can be deleted if preventing directory removal",
|
||||
"Prefix indicating that the pattern should be matched without case sensitivity": "Prefix indicating that the pattern should be matched without case sensitivity",
|
||||
"Prefix indicating that the file can be deleted if preventing directory removal": "Předpona značící možnost smazání souboru, pokud brání odebrání složky",
|
||||
"Prefix indicating that the pattern should be matched without case sensitivity": "Předpona značící ignorování velkých/malých písmen při hledání řetězce",
|
||||
"Preview": "Náhled",
|
||||
"Preview Usage Report": "Náhled záznamu o využítí",
|
||||
"Quick guide to supported patterns": "Rychlá nápověda k podporovaným vzorům",
|
||||
"RAM Utilization": "Využití RAM",
|
||||
"Random": "Náhodně",
|
||||
"Recent Changes": "Nedávné změny",
|
||||
"Reduced by ignore patterns": "Redukováno o ignorované vzory",
|
||||
"Release Notes": "Poznámky k vydání",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Kandidáti na vydání obsahují nejnovější změny a opravy. Podobají se tradičním dvoutýdenním vydáním Syncthing.",
|
||||
"Remote Devices": "Vzdálená zařízení",
|
||||
"Remove": "Odstranit",
|
||||
"Remove Device": "Remove Device",
|
||||
"Remove Folder": "Remove Folder",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "Požadovaný identifikátor adresáře. Musí být stejný na všech zařízeních.",
|
||||
"Rescan": "Opakovat skenování",
|
||||
"Rescan All": "Opakovat skenování všech",
|
||||
@@ -183,7 +192,9 @@
|
||||
"Save": "Uložit",
|
||||
"Scan Time Remaining": "Zbývající čas skenování",
|
||||
"Scanning": "Skenování",
|
||||
"See external versioner help for supported templated command line parameters.": "See external versioner help for supported templated command line parameters.",
|
||||
"See external versioner help for supported templated command line parameters.": "Pro upřesnění požadovaných parametrů příkazu navštivte nápovědu pro externí verzování.",
|
||||
"See external versioning help for supported templated command line parameters.": "Podporované šablonové parametry příkazové řádky jsou dostupné v nápovědě k externímu verzování.",
|
||||
"Select a version": "Vyberte verzi",
|
||||
"Select the devices to share this folder with.": "Vybrat přístroje, se kterými sdílet tento adresář.",
|
||||
"Select the folders to share with this device.": "Vybrat adresáře sdílené s tímto přístrojem.",
|
||||
"Send & Receive": "Odeslat a přijmout",
|
||||
@@ -197,6 +208,7 @@
|
||||
"Shared With": "Sdíleno s",
|
||||
"Show ID": "Zobrazit ID",
|
||||
"Show QR": "Zobrazit QR",
|
||||
"Show diff with previous version": "Ukázat rozdíl oproti předchozí verzi",
|
||||
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Zobrazeno místo ID přístroje na náhledu stavu clusteru. Bude odesíláno ostatním přístrojům jako výchozí jméno přístroje.",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Zobrazeno místo ID přístroje na náhledu stavu clusteru. Pokud nebude vyplněno, bude nastaveno na jméno, které přístroj odesílá.",
|
||||
"Shutdown": "Vypnout",
|
||||
@@ -239,7 +251,7 @@
|
||||
"The minimum free disk space percentage must be a non-negative number between 0 and 100 (inclusive).": "Procentuální údaj minimální velikosti volného místa na disku musí být číslo mezi 0 až 100 (včetně).",
|
||||
"The number of days must be a number and cannot be blank.": "Počet dní musí být číslo a nesmí být prázdný.",
|
||||
"The number of days to keep files in the trash can. Zero means forever.": "Počet dní, po který budou soubory uchovány v koši. Nula znamená navždy.",
|
||||
"The number of old versions to keep, per file.": "Počet starších verzí k zachování pro každý soubor.",
|
||||
"The number of old versions to keep, per file.": "Počet udržovaných starších verzí souboru.",
|
||||
"The number of versions must be a number and cannot be blank.": "Počet verzí musí být číslo a nemůže být prázdné.",
|
||||
"The path cannot be blank.": "Cesta nesmí být prázdná.",
|
||||
"The rate limit must be a non-negative number (0: no limit)": "Limit rychlosti musí být nezáporné číslo (0: bez limitu)",
|
||||
@@ -248,10 +260,11 @@
|
||||
"This Device": "Toto zařízení",
|
||||
"This can easily give hackers access to read and change any files on your computer.": "To může útočníkům jednoduše povolit čtení a úpravy souborů na vašem přístroji. ",
|
||||
"This is a major version upgrade.": "Toto je důležitá aktualizace.",
|
||||
"This setting controls the free space required on the home (i.e., index database) disk.": "This setting controls the free space required on the home (i.e., index database) disk.",
|
||||
"This setting controls the free space required on the home (i.e., index database) disk.": "Toto nastavení ovládá velikost volného prostoru na hlavním disku (ten, na kterém je databáze indexu).",
|
||||
"Time": "Čas",
|
||||
"Trash Can File Versioning": "Verzování souborů v koši",
|
||||
"Type": "Typ",
|
||||
"Undecided (will prompt)": "Nerozhodnuto (zeptá se)",
|
||||
"Unknown": "Neznámý",
|
||||
"Unshared": "Nesdílený",
|
||||
"Unused": "Nepoužitý",
|
||||
|
||||
@@ -24,7 +24,10 @@
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "En ekstern kommando styrer versioneringen. Den skal fjerne filen fra den delte mappe.",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": " ",
|
||||
"Anonymous Usage Reporting": "Anonym brugerstatistik",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "Anonymous usage report format has changed. Would you like to move to the new format?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "Alle enheder som er konfigueret som en introducerende enhed, vil også blive tilføjet til denne enhed.",
|
||||
"Are you sure you want to remove device {%name%}?": "Are you sure you want to remove device {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Are you sure you want to remove folder {{label}}?",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Den automatiske opdatering tilbyder nu valget mellem stabile - og udgivelses kandidater.",
|
||||
"Automatic upgrades": "Automatisk opdatering",
|
||||
"Be careful!": "Vær forsigtig!",
|
||||
@@ -53,6 +56,7 @@
|
||||
"Device Identification": "Enhedsidentifikation",
|
||||
"Device Name": "Enhedsnavn",
|
||||
"Devices": "Enheder",
|
||||
"Disabled": "Disabled",
|
||||
"Disconnected": "Ikke tilsluttet",
|
||||
"Discovered": "Opdaget",
|
||||
"Discovery": "Opslag",
|
||||
@@ -84,6 +88,7 @@
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Filer er flyttet til datostemplet versioner i en .stversions mappe når de bliver erstattet eller slettet af Syncthing.",
|
||||
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Filer flyttes til data-stemplede versioner i en .stversions mappe når de erstattes eller slettes af Syncthing.",
|
||||
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Filer er beskyttet fra ændringer foretaget på andre enheder, men ændringerne på denne enhed vil blive sendt til alle andre tilknyttede enheder.",
|
||||
"Filesystem Notifications": "Filesystem Notifications",
|
||||
"Folder": "Mappe",
|
||||
"Folder ID": "Mappe-ID",
|
||||
"Folder Label": "Mappelabel",
|
||||
@@ -136,6 +141,7 @@
|
||||
"Newest First": "Nyeste først",
|
||||
"No": "Nej",
|
||||
"No File Versioning": "Ingen filversion",
|
||||
"No files will be deleted as a result of this operation.": "No files will be deleted as a result of this operation.",
|
||||
"No upgrades": "Ingen opgraderinger",
|
||||
"Normal": "Normal",
|
||||
"Notice": "OBS",
|
||||
@@ -165,11 +171,14 @@
|
||||
"Quick guide to supported patterns": "Hurtig guide til supporteret mønstre",
|
||||
"RAM Utilization": "RAM-forbrug",
|
||||
"Random": "Tilfældig",
|
||||
"Recent Changes": "Recent Changes",
|
||||
"Reduced by ignore patterns": "Reduceret af ignorerings mønsteret. ",
|
||||
"Release Notes": "Udgivelsesnoter",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Udgivelseskandidater indeholder alle de nyeste funktioner og rettelser. De er ens med de traditionelle 2 ugers Syncthing udgivelser.",
|
||||
"Remote Devices": "Fjernenheder ",
|
||||
"Remove": "Fjern",
|
||||
"Remove Device": "Remove Device",
|
||||
"Remove Folder": "Remove Folder",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "Nødvendig identifikation af mappen. Dette skal være det samme på alle enheder.",
|
||||
"Rescan": "Skan igen",
|
||||
"Rescan All": "Skan alt igen",
|
||||
@@ -184,6 +193,8 @@
|
||||
"Scan Time Remaining": "Tid tilbage af skanningen",
|
||||
"Scanning": "Opdaterer",
|
||||
"See external versioner help for supported templated command line parameters.": "See external versioner help for supported templated command line parameters.",
|
||||
"See external versioning help for supported templated command line parameters.": "See external versioning help for supported templated command line parameters.",
|
||||
"Select a version": "Select a version",
|
||||
"Select the devices to share this folder with.": "Vælg hvilke enheder du vil dele denne mappe med",
|
||||
"Select the folders to share with this device.": "Vælg hvilke mapper du vil dele med denne enhed.",
|
||||
"Send & Receive": "Send & Modtag",
|
||||
@@ -197,6 +208,7 @@
|
||||
"Shared With": "Delt med",
|
||||
"Show ID": "Vis ID",
|
||||
"Show QR": "Vis QR",
|
||||
"Show diff with previous version": "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.": "Vist istedet for Enheds ID i klynge status. Vil blive vist på andre enheder som valgfrit standard navn.",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Vist istedet for Enheds ID i klynge status. Vil blive opdateret til det navn som enheden viser, hvis det ikke er udfyldt.",
|
||||
"Shutdown": "Luk ned",
|
||||
@@ -252,6 +264,7 @@
|
||||
"Time": "Tid",
|
||||
"Trash Can File Versioning": "Skraldespand fil versioner",
|
||||
"Type": "Type",
|
||||
"Undecided (will prompt)": "Undecided (will prompt)",
|
||||
"Unknown": "Ukendt",
|
||||
"Unshared": "Ikke delt",
|
||||
"Unused": "Ubrugt",
|
||||
|
||||
@@ -24,7 +24,10 @@
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "Ein externer Befehl führt die Versionierung durch. Er muss die Datei aus dem geteilten Ordner entfernen.",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "Ein externer Programmaufruf handhabt die Versionierung. Es muss die Datei aus dem zu synchronisierendem Ordner entfernen.",
|
||||
"Anonymous Usage Reporting": "Anonymer Nutzungsbericht",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "Das Format der anonymen Nutzungsberichte wurde geändert. Möchten Sie auf das neue Format umsteigen?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "Alle Geräte, die beim Verteilergerät eingetragen sind, werden auch bei diesem Gerät hinzugefügt.",
|
||||
"Are you sure you want to remove device {%name%}?": "Are you sure you want to remove device {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Are you sure you want to remove folder {{label}}?",
|
||||
"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 Updates aktivieren",
|
||||
"Be careful!": "Vorsicht!",
|
||||
@@ -53,6 +56,7 @@
|
||||
"Device Identification": "Geräteidentifikation",
|
||||
"Device Name": "Gerätename",
|
||||
"Devices": "Geräte",
|
||||
"Disabled": "Deaktiviert",
|
||||
"Disconnected": "Getrennt",
|
||||
"Discovered": "Ermittelt",
|
||||
"Discovery": "Gerätesuche",
|
||||
@@ -84,6 +88,7 @@
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Dateien werden mit Datumsstempel versioniert und in den .stversions Ordner verschoben, wenn sie von Syncthing ersetzt oder gelöscht werden.",
|
||||
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Dateien werden mit Datumsstempel versioniert und in den .stversions Ordner verschoben, wenn sie von Syncthing ersetzt oder gelöscht werden.",
|
||||
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Dateien sind auf diesem Gerät schreibgeschützt. Auf diesem Gerät durchgeführte Veränderungen werden aber auf den Rest des Verbunds übertragen.",
|
||||
"Filesystem Notifications": "Dateisystembenachrichtigungen",
|
||||
"Folder": "Ordner",
|
||||
"Folder ID": "Ordnerkennung",
|
||||
"Folder Label": "Ordnerbezeichnung",
|
||||
@@ -136,6 +141,7 @@
|
||||
"Newest First": "Neueste zuerst",
|
||||
"No": "Nein",
|
||||
"No File Versioning": "Keine Dateiversionierung",
|
||||
"No files will be deleted as a result of this operation.": "No files will be deleted as a result of this operation.",
|
||||
"No upgrades": "Keine Updates",
|
||||
"Normal": "Normal",
|
||||
"Notice": "Hinweis",
|
||||
@@ -165,11 +171,14 @@
|
||||
"Quick guide to supported patterns": "Schnellanleitung zu den unterstützten Mustern",
|
||||
"RAM Utilization": "RAM Auslastung",
|
||||
"Random": "Zufall",
|
||||
"Recent Changes": "Letzte Änderungen",
|
||||
"Reduced by ignore patterns": "Durch Ignoriermuster reduziert",
|
||||
"Release Notes": "Veröffentlichungsnotizen",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Veröffentlichungskandidaten enthalten die neuesten Funktionen und Verbesserungen. Sie gleichen den üblichen zweiwöchentlichen Syncthing-Veröffentlichungen.",
|
||||
"Remote Devices": "Fern-Geräte",
|
||||
"Remove": "Entfernen",
|
||||
"Remove Device": "Remove Device",
|
||||
"Remove Folder": "Remove Folder",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "Erforderlicher Bezeichner für den Ordner. Muss auf allen Verbund-Geräten gleich sein.",
|
||||
"Rescan": "Neu scannen",
|
||||
"Rescan All": "Alle neu scannen",
|
||||
@@ -183,7 +192,9 @@
|
||||
"Save": "Speichern",
|
||||
"Scan Time Remaining": "Zeit für Scan verbleibend",
|
||||
"Scanning": "Scannen",
|
||||
"See external versioner help for supported templated command line parameters.": "See external versioner help for supported templated command line parameters.",
|
||||
"See external versioner help for supported templated command line parameters.": "Siehe externe Versionshilfe für unterstützte Befehlszeilenparameter.",
|
||||
"See external versioning help for supported templated command line parameters.": "Siehe Hilfe zur externen Versionierung für unterstützte Befehlszeilenparameter.",
|
||||
"Select a version": "Wähle eine Version",
|
||||
"Select the devices to share this folder with.": "Wähle die Geräte aus, mit denen Du diesen Ordner teilen willst.",
|
||||
"Select the folders to share with this device.": "Wähle die Ordner aus, die Du mit diesem Gerät teilen möchtest",
|
||||
"Send & Receive": "Senden & empfangen",
|
||||
@@ -197,6 +208,7 @@
|
||||
"Shared With": "Geteilt mit",
|
||||
"Show ID": "Eigene Kennung",
|
||||
"Show QR": "Zeige QR Code",
|
||||
"Show diff with previous version": "Zeige den Unterschied zur vorigen Version",
|
||||
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Wird anstatt der Gerätekennung im Verbund-Status angezeigt. Wird als optionaler Standardname an andere Geräte bekannt gegeben.",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Wird auf diesem Gerät als Gerätename angezeigt und an die anderen Geräte im Geräte-Verbund weitergegeben. Wenn kein Gerätename anegegeben wird, wird der Name des entfernten Gerätes genommen.",
|
||||
"Shutdown": "Herunterfahren",
|
||||
@@ -252,6 +264,7 @@
|
||||
"Time": "Zeit",
|
||||
"Trash Can File Versioning": "Papierkorb Dateiversionierung",
|
||||
"Type": "Typ",
|
||||
"Undecided (will prompt)": "Unentschieden (wird nachgefragt werden)",
|
||||
"Unknown": "Unbekannt",
|
||||
"Unshared": "Ungeteilt",
|
||||
"Unused": "Ungenutzt",
|
||||
|
||||
@@ -24,7 +24,10 @@
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "Μια εξωτερική εντολή χειρίζεται την τήρηση εκδόσεων και αναλαμβάνει να αφαιρέσει το αρχείο από τον συγχρονισμένο φάκελο.",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "Μια εξωτερική εντολή χειρίζεται την διαχείριση εκδόσεων. Χρειάζεται να αφαιρέσει το αρχείο από το φάκελο συγχρονισμένων.",
|
||||
"Anonymous Usage Reporting": "Ανώνυμα στοιχεία χρήσης",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "Η μορφή της αναφοράς ανώνυμων στοιχείων χρήσης έχει αλλάξει. Επιθυμείτε να μεταβείτε στη νέα μορφή;",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "Αν δηλωθεί σαν «βασικός κόμβος», τότε όλες οι συσκευές που είναι δηλωμένες εκεί θα υπάρχουν και στον τοπικό κόμβο.",
|
||||
"Are you sure you want to remove device {%name%}?": "Σίγουρα επιθυμείτε να αφαιρέσετε τη συσκευή {{name}};",
|
||||
"Are you sure you want to remove folder {%label%}?": "Σίγουρα επιθυμείτε να αφαιρέσετε τον φάκελο {{label}};",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Για τις αυτόματες αναβαθμίσεις μπορείτε πλέον να επιλέξετε μεταξύ σταθερών εκδόσεων και υποψήφιων εκδόσεων.",
|
||||
"Automatic upgrades": "Αυτόματη αναβάθμιση",
|
||||
"Be careful!": "Με προσοχή!",
|
||||
@@ -53,7 +56,8 @@
|
||||
"Device Identification": "Ταυτότητα συσκευής",
|
||||
"Device Name": "Όνομα συσκευής",
|
||||
"Devices": "Συσκευές",
|
||||
"Disconnected": "Αποσυνδεδεμένος",
|
||||
"Disabled": "Απενεργοποιημένη",
|
||||
"Disconnected": "Αποσυνδεδεμένη",
|
||||
"Discovered": "Βάσει ανεύρεσης",
|
||||
"Discovery": "Ανεύρεση συσκευών",
|
||||
"Discovery Failures": "Αποτυχίες ανεύρεσης συσκευών",
|
||||
@@ -84,6 +88,7 @@
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Τα αρχεία που σβήνονται ή αντικαθίστανται από το Syncthing μετακινούνται στον κατάλογο .stversions με χρονοσήμανση.",
|
||||
"Files are moved to date stamped versions in a .stversions folder 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.": "Τα αρχεία προστατεύονται από αλλαγές που γίνονται σε άλλες συσκευές, αλλά όποιες αλλαγές γίνουν σε αυτή τη συσκευή θα αποσταλούν σε όλη τη συστάδα συσκευών.",
|
||||
"Filesystem Notifications": "Ειδοποιήσεις συστήματος αρχείων",
|
||||
"Folder": "Φάκελος",
|
||||
"Folder ID": "Ταυτότητα φακέλου",
|
||||
"Folder Label": "Ετικέτα φακέλου",
|
||||
@@ -136,6 +141,7 @@
|
||||
"Newest First": "Το νεότερο πρώτα",
|
||||
"No": "Όχι",
|
||||
"No File Versioning": "Να μην τηρούνται εκδόσεις",
|
||||
"No files will be deleted as a result of this operation.": "Δεν πρόκειται να διαγραφούν αρχεία με αυτή την ενέργεια.",
|
||||
"No upgrades": "Απενεργοποιημένες",
|
||||
"Normal": "Κανονικός",
|
||||
"Notice": "Σημείωση",
|
||||
@@ -165,11 +171,14 @@
|
||||
"Quick guide to supported patterns": "Σύντομη βοήθεια σχετικά με τα πρότυπα αναζήτησης που υποστηρίζονται",
|
||||
"RAM Utilization": "Επιβάρυνση RAM",
|
||||
"Random": "Τυχαία",
|
||||
"Recent Changes": "Πρόσφατες αλλαγές",
|
||||
"Reduced by ignore patterns": "Περιορισμένα λόγω προτύπων αγνόησης",
|
||||
"Release Notes": "Σημείωμα έκδοσης",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Οι υποψήφιες εκδόσεις περιέχουν τις νεότερες λειτουργίες και επιδιορθώσεις σφαλμάτων, όπως και οι παραδοσιακές δισεβδομαδιαίες εκδόσεις του Syncthing.",
|
||||
"Remote Devices": "Απομακρυσμένες συσκευές",
|
||||
"Remove": "Αφαίρεση",
|
||||
"Remove Device": "Αφαίρεση συσκευής",
|
||||
"Remove Folder": "Αφαίρεση φακέλου",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "Απαραίτητο αναγνωριστικό για τον φάκελο. Πρέπει να είναι το ίδιο σε όλες τις συσκευές με τις οποίες διαμοιράζεται ο φάκελος αυτός.",
|
||||
"Rescan": "Έλεγξε για αλλαγές",
|
||||
"Rescan All": "Έλεγξέ τα όλα για αλλαγές",
|
||||
@@ -184,6 +193,8 @@
|
||||
"Scan Time Remaining": "Εναπομείναντας χρόνος για τον έλεγχο ",
|
||||
"Scanning": "Έλεγχος για αλλαγές",
|
||||
"See external versioner help for supported templated command line parameters.": "Ανατρέξτε στην τεκμηρίωση της εξωτερικής τήρησης εκδόσεων για πληροφορίες σχετικά με τις υποστηριζόμενες παραμέτρους της γραμμής εντολών.",
|
||||
"See external versioning help for supported templated command line parameters.": "Ανατρέξτε στην τεκμηρίωση της εξωτερικής τήρησης εκδόσεων για πληροφορίες σχετικά με τις υποστηριζόμενες παραμέτρους της γραμμής εντολών.",
|
||||
"Select a version": "Επιλογή έκδοσης",
|
||||
"Select the devices to share this folder with.": "Διάλεξε τις συσκευές προς τις οποίες θα διαμοιράζεται αυτός ο φάκελος.",
|
||||
"Select the folders to share with this device.": "Διάλεξε ποιοι φάκελοι θα διαμοιράζονται προς αυτή τη συσκευή.",
|
||||
"Send & Receive": "Αποστολή και λήψη",
|
||||
@@ -197,6 +208,7 @@
|
||||
"Shared With": "Διαμοιράζεται με",
|
||||
"Show ID": "Εμφάνιση ταυτότητας",
|
||||
"Show QR": "Δείξε τον κωδικό QR",
|
||||
"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": "Απενεργοποίηση",
|
||||
@@ -252,6 +264,7 @@
|
||||
"Time": "Χρόνος",
|
||||
"Trash Can File Versioning": "Τήρηση εκδόσεων κάδου ανακύκλωσης",
|
||||
"Type": "Τύπος",
|
||||
"Undecided (will prompt)": "Μη καθορισμένη (θα γίνει ερώτηση)",
|
||||
"Unknown": "Άγνωστο",
|
||||
"Unshared": "Δε μοιράζεται",
|
||||
"Unused": "Δε χρησιμοποιείται",
|
||||
|
||||
@@ -24,7 +24,10 @@
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "An external command handles the versioning. It has to remove the file from the shared folder.",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "An external command handles the versioning. It has to remove the file from the synced folder.",
|
||||
"Anonymous Usage Reporting": "Anonymous Usage Reporting",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "Anonymous usage report format has changed. Would you like to move to the new format?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "Any devices configured on an introducer device will be added to this device as well.",
|
||||
"Are you sure you want to remove device {%name%}?": "Are you sure you want to remove device {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Are you sure you want to remove folder {{label}}?",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Automatic upgrade now offers the choice between stable releases and release candidates.",
|
||||
"Automatic upgrades": "Automatic upgrades",
|
||||
"Be careful!": "Be careful!",
|
||||
@@ -53,6 +56,7 @@
|
||||
"Device Identification": "Device Identification",
|
||||
"Device Name": "Device Name",
|
||||
"Devices": "Devices",
|
||||
"Disabled": "Disabled",
|
||||
"Disconnected": "Disconnected",
|
||||
"Discovered": "Discovered",
|
||||
"Discovery": "Discovery",
|
||||
@@ -84,6 +88,7 @@
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.",
|
||||
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.",
|
||||
"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 protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.",
|
||||
"Filesystem Notifications": "Filesystem Notifications",
|
||||
"Folder": "Folder",
|
||||
"Folder ID": "Folder ID",
|
||||
"Folder Label": "Folder Label",
|
||||
@@ -136,6 +141,7 @@
|
||||
"Newest First": "Newest First",
|
||||
"No": "No",
|
||||
"No File Versioning": "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 upgrades": "No upgrades",
|
||||
"Normal": "Normal",
|
||||
"Notice": "Notice",
|
||||
@@ -165,11 +171,14 @@
|
||||
"Quick guide to supported patterns": "Quick guide to supported patterns",
|
||||
"RAM Utilization": "RAM Utilisation",
|
||||
"Random": "Random",
|
||||
"Recent Changes": "Recent Changes",
|
||||
"Reduced by ignore patterns": "Reduced by ignore patterns",
|
||||
"Release Notes": "Release Notes",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Release candidates contain the latest features and fixes. They are similar to the traditional fortnightly Syncthing releases.",
|
||||
"Remote Devices": "Remote Devices",
|
||||
"Remove": "Remove",
|
||||
"Remove Device": "Remove Device",
|
||||
"Remove Folder": "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",
|
||||
"Rescan All": "Rescan All",
|
||||
@@ -184,6 +193,8 @@
|
||||
"Scan Time Remaining": "Scan Time Remaining",
|
||||
"Scanning": "Scanning",
|
||||
"See external versioner help for supported templated command line parameters.": "See external versioner help for supported templated command line parameters.",
|
||||
"See external versioning help for supported templated command line parameters.": "See external versioning help for supported templated command line parameters.",
|
||||
"Select a version": "Select a version",
|
||||
"Select the devices to share this folder with.": "Select the devices to share this folder with.",
|
||||
"Select the folders to share with this device.": "Select the folders to share with this device.",
|
||||
"Send & Receive": "Send & Receive",
|
||||
@@ -197,6 +208,7 @@
|
||||
"Shared With": "Shared With",
|
||||
"Show ID": "Show ID",
|
||||
"Show QR": "Show QR",
|
||||
"Show diff with previous version": "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 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.": "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.",
|
||||
"Shutdown": "Shutdown",
|
||||
@@ -252,6 +264,7 @@
|
||||
"Time": "Time",
|
||||
"Trash Can File Versioning": "Rubbish Bin File Versioning",
|
||||
"Type": "Type",
|
||||
"Undecided (will prompt)": "Undecided (will prompt)",
|
||||
"Unknown": "Unknown",
|
||||
"Unshared": "Unshared",
|
||||
"Unused": "Unused",
|
||||
|
||||
@@ -24,9 +24,14 @@
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "An external command handles the versioning. It has to remove the file from the shared folder.",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "An external command handles the versioning. It has to remove the file from the synced folder.",
|
||||
"Anonymous Usage Reporting": "Anonymous Usage Reporting",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "Anonymous usage report format has changed. Would you like to move to the new format?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "Any devices configured on an introducer device will be added to this device as well.",
|
||||
"Are you sure you want to remove device {%name%}?": "Are you sure you want to remove device {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Are you sure you want to remove folder {{label}}?",
|
||||
"Auto Accept": "Auto Accept",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Automatic upgrade now offers the choice between stable releases and release candidates.",
|
||||
"Automatic upgrades": "Automatic upgrades",
|
||||
"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.",
|
||||
"Be careful!": "Be careful!",
|
||||
"Bugs": "Bugs",
|
||||
"CPU Utilization": "CPU Utilization",
|
||||
@@ -40,12 +45,14 @@
|
||||
"Configured": "Configured",
|
||||
"Connection Error": "Connection Error",
|
||||
"Connection Type": "Connection Type",
|
||||
"Connections": "Connections",
|
||||
"Copied from elsewhere": "Copied from elsewhere",
|
||||
"Copied from original": "Copied from original",
|
||||
"Copyright © 2014-2016 the following Contributors:": "Copyright © 2014-2016 the following Contributors:",
|
||||
"Copyright © 2014-2017 the following Contributors:": "Copyright © 2014-2017 the following Contributors:",
|
||||
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Creating ignore patterns, overwriting an existing file at {{path}}.",
|
||||
"Danger!": "Danger!",
|
||||
"Default Folder Path": "Default Folder Path",
|
||||
"Deleted": "Deleted",
|
||||
"Device": "Device",
|
||||
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "Device \"{{name}}\" ({{device}} at {{address}}) wants to connect. Add new device?",
|
||||
@@ -53,6 +60,7 @@
|
||||
"Device Identification": "Device Identification",
|
||||
"Device Name": "Device Name",
|
||||
"Devices": "Devices",
|
||||
"Disabled": "Disabled",
|
||||
"Disconnected": "Disconnected",
|
||||
"Discovered": "Discovered",
|
||||
"Discovery": "Discovery",
|
||||
@@ -84,6 +92,7 @@
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.",
|
||||
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.",
|
||||
"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 protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.",
|
||||
"Filesystem Notifications": "Filesystem Notifications",
|
||||
"Folder": "Folder",
|
||||
"Folder ID": "Folder ID",
|
||||
"Folder Label": "Folder Label",
|
||||
@@ -96,6 +105,7 @@
|
||||
"GUI Listen Address": "GUI Listen Address",
|
||||
"GUI Listen Addresses": "GUI Listen Addresses",
|
||||
"GUI Theme": "GUI Theme",
|
||||
"General": "General",
|
||||
"Generate": "Generate",
|
||||
"Global Changes": "Global Changes",
|
||||
"Global Discovery": "Global Discovery",
|
||||
@@ -136,6 +146,7 @@
|
||||
"Newest First": "Newest First",
|
||||
"No": "No",
|
||||
"No File Versioning": "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 upgrades": "No upgrades",
|
||||
"Normal": "Normal",
|
||||
"Notice": "Notice",
|
||||
@@ -150,6 +161,7 @@
|
||||
"Override Changes": "Override Changes",
|
||||
"Path": "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 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 new auto accepted folders will be created, as well as the default suggested path when adding new folders via the UI. Tilde character (~) expands to {%tilde%}.": "Path where new auto accepted folders will be created, as well as the default suggested path when adding new folders via the UI. Tilde character (~) expands to {{tilde}}.",
|
||||
"Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).": "Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).",
|
||||
"Path where versions should be stored (leave empty for the default .stversions folder in the folder).": "Path where versions should be stored (leave empty for the default .stversions folder in the folder).",
|
||||
"Pause": "Pause",
|
||||
@@ -165,11 +177,14 @@
|
||||
"Quick guide to supported patterns": "Quick guide to supported patterns",
|
||||
"RAM Utilization": "RAM Utilization",
|
||||
"Random": "Random",
|
||||
"Recent Changes": "Recent Changes",
|
||||
"Reduced by ignore patterns": "Reduced by ignore patterns",
|
||||
"Release Notes": "Release Notes",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.",
|
||||
"Remote Devices": "Remote Devices",
|
||||
"Remove": "Remove",
|
||||
"Remove Device": "Remove Device",
|
||||
"Remove Folder": "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",
|
||||
"Rescan All": "Rescan All",
|
||||
@@ -184,6 +199,8 @@
|
||||
"Scan Time Remaining": "Scan Time Remaining",
|
||||
"Scanning": "Scanning",
|
||||
"See external versioner help for supported templated command line parameters.": "See external versioner help for supported templated command line parameters.",
|
||||
"See external versioning help for supported templated command line parameters.": "See external versioning help for supported templated command line parameters.",
|
||||
"Select a version": "Select a version",
|
||||
"Select the devices to share this folder with.": "Select the devices to share this folder with.",
|
||||
"Select the folders to share with this device.": "Select the folders to share with this device.",
|
||||
"Send \u0026 Receive": "Send \u0026 Receive",
|
||||
@@ -197,6 +214,7 @@
|
||||
"Shared With": "Shared With",
|
||||
"Show ID": "Show ID",
|
||||
"Show QR": "Show QR",
|
||||
"Show diff with previous version": "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 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.": "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.",
|
||||
"Shutdown": "Shutdown",
|
||||
@@ -252,6 +270,9 @@
|
||||
"Time": "Time",
|
||||
"Trash Can File Versioning": "Trash Can File Versioning",
|
||||
"Type": "Type",
|
||||
"Unavailable": "Unavailable",
|
||||
"Unavailable/Disabled by administrator or maintainer": "Unavailable/Disabled by administrator or maintainer",
|
||||
"Undecided (will prompt)": "Undecided (will prompt)",
|
||||
"Unknown": "Unknown",
|
||||
"Unshared": "Unshared",
|
||||
"Unused": "Unused",
|
||||
|
||||
@@ -24,7 +24,10 @@
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "Ekstera komando manipulas la version. Ĝi devas forigi la dosieron el la partigita dosierujo.",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "Ekstera komando manipulas la version. Ĝi devas forigi la dosieron el la sinkronigita dosierujo.",
|
||||
"Anonymous Usage Reporting": "Anonima Raporto de Uzado",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "Anonymous usage report format has changed. Would you like to move to the new format?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "Ajna aparatoj agorditaj sur enkondukanto aparato estos ankaŭ aldonita al ĉi tiu aparato.",
|
||||
"Are you sure you want to remove device {%name%}?": "Are you sure you want to remove device {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Are you sure you want to remove folder {{label}}?",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Aŭtomata ĝisdatigo nun proponas la elekton inter stabilaj eldonoj kaj kandidataj eldonoj.",
|
||||
"Automatic upgrades": "Aŭtomataj ĝisdatigoj",
|
||||
"Be careful!": "Atentu!",
|
||||
@@ -53,6 +56,7 @@
|
||||
"Device Identification": "Identigo de Aparato",
|
||||
"Device Name": "Nomo de Aparato",
|
||||
"Devices": "Aparatoj",
|
||||
"Disabled": "Disabled",
|
||||
"Disconnected": "Malkonektita",
|
||||
"Discovered": "Malkovrita",
|
||||
"Discovery": "Malkovro",
|
||||
@@ -84,6 +88,7 @@
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Dosieroj estas movigitaj al date stampitaj versioj en .stversiaj dosierujo kiam ili estas anstataŭigitaj aŭ forigitaj en Syncthing.",
|
||||
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Dosieroj estas movigitaj al datostampitaj versioj en .stversions dosierujoj kiam ili estas anstataŭigitaj aŭ forigitaj en Syncthing.",
|
||||
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Dosieroj estas protektataj kontraŭ ŝanĝoj faritaj en aliaj aparatoj, sed ŝanĝoj faritaj en ĉi tiu aparato estos senditaj al cetera parto de la grupo.",
|
||||
"Filesystem Notifications": "Filesystem Notifications",
|
||||
"Folder": "Dosierujo",
|
||||
"Folder ID": "Dosieruja ID",
|
||||
"Folder Label": "Dosieruja Etikedo",
|
||||
@@ -136,6 +141,7 @@
|
||||
"Newest First": "Plejnova Unue",
|
||||
"No": "Ne",
|
||||
"No File Versioning": "Sen Dosiera Versionado",
|
||||
"No files will be deleted as a result of this operation.": "No files will be deleted as a result of this operation.",
|
||||
"No upgrades": "Sen ĝisdatigoj",
|
||||
"Normal": "Normala",
|
||||
"Notice": "Avizo",
|
||||
@@ -165,11 +171,14 @@
|
||||
"Quick guide to supported patterns": "Rapida gvidisto al subtenata ŝablonoj",
|
||||
"RAM Utilization": "RAM Utiligado",
|
||||
"Random": "Hazarda",
|
||||
"Recent Changes": "Recent Changes",
|
||||
"Reduced by ignore patterns": "Reduktita per ignorado de la ŝablonoj",
|
||||
"Release Notes": "Eldonitaj Notoj",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Kandidataj eldonoj enhavas la lastajn trajtojn kaj korektojn. Ili estas similaj al la tradiciaj dusemajnaj Syncthing ĵetoj.",
|
||||
"Remote Devices": "Foraj Aparatoj",
|
||||
"Remove": "Forigu",
|
||||
"Remove Device": "Remove Device",
|
||||
"Remove Folder": "Remove Folder",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "Nepra identigilo por la dosierujo. Devas esti la sama en ĉiuj aparatoj de la grupo.",
|
||||
"Rescan": "Reskanu",
|
||||
"Rescan All": "Reskanu Ĉion",
|
||||
@@ -184,6 +193,8 @@
|
||||
"Scan Time Remaining": "Skanada Restanta Tempo",
|
||||
"Scanning": "Skanado",
|
||||
"See external versioner help for supported templated command line parameters.": "See external versioner help for supported templated command line parameters.",
|
||||
"See external versioning help for supported templated command line parameters.": "See external versioning help for supported templated command line parameters.",
|
||||
"Select a version": "Select a version",
|
||||
"Select the devices to share this folder with.": "Elekti la aparatojn por komunigi ĉi tiun dosierujon.",
|
||||
"Select the folders to share with this device.": "Elekti la dosierujojn por komunigi kun ĉi tiu aparato.",
|
||||
"Send & Receive": "Sendi kaj Ricevi",
|
||||
@@ -197,6 +208,7 @@
|
||||
"Shared With": "Komunigita Kun",
|
||||
"Show ID": "Montru ID",
|
||||
"Show QR": "Montru QR",
|
||||
"Show diff with previous version": "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.": "Montrita anstataŭ ID de Aparato en la statuso de la grupo. Estos anoncita al aliaj aparatoj kiel laŭvola defaŭlta nomo.",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Montri anstataŭ ID de Aparato en la statuso de la grupo. Estos ĝisdatigita al la nomo de la aparato sciigante se ĝi estas lasita malplena.",
|
||||
"Shutdown": "Sistemfermu",
|
||||
@@ -252,6 +264,7 @@
|
||||
"Time": "Tempo",
|
||||
"Trash Can File Versioning": "Rubujo ebligas Dosieran Versionadon",
|
||||
"Type": "Tipo",
|
||||
"Undecided (will prompt)": "Undecided (will prompt)",
|
||||
"Unknown": "Nekonata",
|
||||
"Unshared": "Nekomunigita",
|
||||
"Unused": "Neuzita",
|
||||
|
||||
@@ -24,7 +24,10 @@
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "Un comando externo gestiona las versiones. Tiene que eliminar el fichero de la carpeta compartida.",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "Un comando externo controla la versión. El fichero debe ser eliminado de la carpeta sincronizada.",
|
||||
"Anonymous Usage Reporting": "Informe anónimo de uso",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "Anonymous usage report format has changed. Would you like to move to the new format?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "Cualquier dispositivo configurado en un dispositivo de introducción será añadido también.",
|
||||
"Are you sure you want to remove device {%name%}?": "Are you sure you want to remove device {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Are you sure you want to remove folder {{label}}?",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Ahora la actualización automática permite elegir entre versiones estables o versiones candidatas.",
|
||||
"Automatic upgrades": "Actualizaciones automáticas",
|
||||
"Be careful!": "¡Ten cuidado!",
|
||||
@@ -53,6 +56,7 @@
|
||||
"Device Identification": "Identificación del Dispositivo",
|
||||
"Device Name": "Nombre del Dispositivo",
|
||||
"Devices": "Dispositivos",
|
||||
"Disabled": "Disabled",
|
||||
"Disconnected": "Desconectado",
|
||||
"Discovered": "Descubierto",
|
||||
"Discovery": "Descubrimiento",
|
||||
@@ -84,6 +88,7 @@
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Los ficheros son movidos a una carpeta .stversions a versiones con control de fecha cuando son reemplazados o borrados por Syncthing.",
|
||||
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Los ficheros son cambiados a versiones con indicación de fecha en una carpeta \".stversions\" cuando son reemplazados o borrados por Syncthing.",
|
||||
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Los ficheros son protegidos por los cambios hechos en otros dispositivos, pero los cambios hechos en este dispositivo serán enviados al resto del grupo (cluster).",
|
||||
"Filesystem Notifications": "Filesystem Notifications",
|
||||
"Folder": "Carpeta",
|
||||
"Folder ID": "ID de carpeta",
|
||||
"Folder Label": "Etiqueta de la Carpeta",
|
||||
@@ -136,6 +141,7 @@
|
||||
"Newest First": "El más nuevo primero",
|
||||
"No": "No",
|
||||
"No File Versioning": "Sin versionado de fichero",
|
||||
"No files will be deleted as a result of this operation.": "No files will be deleted as a result of this operation.",
|
||||
"No upgrades": "Sin actualizaciones",
|
||||
"Normal": "Normal",
|
||||
"Notice": "Aviso",
|
||||
@@ -165,11 +171,14 @@
|
||||
"Quick guide to supported patterns": "Guía rápida de patrones soportados",
|
||||
"RAM Utilization": "Uso de RAM",
|
||||
"Random": "Aleatorio",
|
||||
"Recent Changes": "Recent Changes",
|
||||
"Reduced by ignore patterns": "Reducido por patrones de ignorar",
|
||||
"Release Notes": "Notas de la versión",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Las versiones candidatas contienen las últimas funcionalidades y correcciones. Son similares a las tradicionales versiones bisemanales de Syncthing.",
|
||||
"Remote Devices": "Otros dispositivos",
|
||||
"Remove": "Eliminar",
|
||||
"Remove Device": "Remove Device",
|
||||
"Remove Folder": "Remove Folder",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "Identificador requerido para la carpeta. Debe ser el mismo en todos los dispositivos del clúster.",
|
||||
"Rescan": "Volver a analizar",
|
||||
"Rescan All": "Volver a analizar Todo",
|
||||
@@ -184,6 +193,8 @@
|
||||
"Scan Time Remaining": "Tiempo Restante de Escaneo",
|
||||
"Scanning": "Analizando",
|
||||
"See external versioner help for supported templated command line parameters.": "See external versioner help for supported templated command line parameters.",
|
||||
"See external versioning help for supported templated command line parameters.": "See external versioning help for supported templated command line parameters.",
|
||||
"Select a version": "Select a version",
|
||||
"Select the devices to share this folder with.": "Selecciona los dispositivos con los que compartir esta carpeta.",
|
||||
"Select the folders to share with this device.": "Selecciona las carpetas para compartir con este dispositivo.",
|
||||
"Send & Receive": "Enviar y Recibir",
|
||||
@@ -197,6 +208,7 @@
|
||||
"Shared With": "Compartir con",
|
||||
"Show ID": "Mostrar ID",
|
||||
"Show QR": "Mostrar QR",
|
||||
"Show diff with previous version": "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.": "Se muestra en lugar del ID del dispositivo en el estado del grupo (cluster). Se notificará a los otros dispositivos como nombre opcional por defecto.",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Se muestra en lugar del ID del dispositivo en el estado del grupo (cluster). Se actualizará al nombre que el dispositivo anuncia si se deja vacío.",
|
||||
"Shutdown": "Apagar",
|
||||
@@ -252,6 +264,7 @@
|
||||
"Time": "Hora",
|
||||
"Trash Can File Versioning": "Versionado de archivos de la papelera",
|
||||
"Type": "Tipo",
|
||||
"Undecided (will prompt)": "Undecided (will prompt)",
|
||||
"Unknown": "Desconocido",
|
||||
"Unshared": "No compartido",
|
||||
"Unused": "No usado",
|
||||
|
||||
@@ -24,7 +24,10 @@
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "Un comando externo gestiona las versiones. Tiene que eliminar el fichero de la carpeta compartida.",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "Un comando externo controla la versión. El fichero debe ser eliminado de la carpeta sincronizada.",
|
||||
"Anonymous Usage Reporting": "Informe anónimo de uso",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "Anonymous usage report format has changed. Would you like to move to the new format?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "Cualquier dispositivo configurado en un dispositivo de introducción será añadido también.",
|
||||
"Are you sure you want to remove device {%name%}?": "Are you sure you want to remove device {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Are you sure you want to remove folder {{label}}?",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Ahora la actualización automática permite elegir entre versiones estables o versiones candidatas.",
|
||||
"Automatic upgrades": "Actualizaciones automáticas",
|
||||
"Be careful!": "¡Ten cuidado!",
|
||||
@@ -53,6 +56,7 @@
|
||||
"Device Identification": "Identificación del Dispositivo",
|
||||
"Device Name": "Nombre del Dispositivo",
|
||||
"Devices": "Dispositivos",
|
||||
"Disabled": "Disabled",
|
||||
"Disconnected": "Desconectado",
|
||||
"Discovered": "Descubierto",
|
||||
"Discovery": "Descubrimiento",
|
||||
@@ -84,6 +88,7 @@
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Los ficheros son movidos a una carpeta .stversions a versiones con control de fecha cuando son reemplazados o borrados por Syncthing.",
|
||||
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Los ficheros son cambiados a versiones con indicación de fecha en una carpeta \".stversions\" cuando son reemplazados o borrados por Syncthing.",
|
||||
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Los ficheros son protegidos por los cambios hechos en otros dispositivos, pero los cambios hechos en este dispositivo serán enviados al resto del grupo (cluster).",
|
||||
"Filesystem Notifications": "Filesystem Notifications",
|
||||
"Folder": "Carpeta",
|
||||
"Folder ID": "ID de carpeta",
|
||||
"Folder Label": "Etiqueta de la Carpeta",
|
||||
@@ -136,6 +141,7 @@
|
||||
"Newest First": "El más nuevo primero",
|
||||
"No": "No",
|
||||
"No File Versioning": "Sin versionado de fichero",
|
||||
"No files will be deleted as a result of this operation.": "No files will be deleted as a result of this operation.",
|
||||
"No upgrades": "Sin actualizaciones",
|
||||
"Normal": "Normal",
|
||||
"Notice": "Aviso",
|
||||
@@ -165,11 +171,14 @@
|
||||
"Quick guide to supported patterns": "Guía rápida de patrones soportados",
|
||||
"RAM Utilization": "Uso de RAM",
|
||||
"Random": "Aleatorio",
|
||||
"Recent Changes": "Recent Changes",
|
||||
"Reduced by ignore patterns": "Reducido por patrones de ignorar",
|
||||
"Release Notes": "Notas de la versión",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Las versiones candidatas contienen las últimas funcionalidades y correcciones. Son similares a las tradicionales versiones bisemanales de Syncthing.",
|
||||
"Remote Devices": "Otros dispositivos",
|
||||
"Remove": "Eliminar",
|
||||
"Remove Device": "Remove Device",
|
||||
"Remove Folder": "Remove Folder",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "Identificador requerido para la carpeta. Debe ser el mismo en todos los dispositivos del clúster.",
|
||||
"Rescan": "Volver a analizar",
|
||||
"Rescan All": "Volver a analizar Todo",
|
||||
@@ -184,6 +193,8 @@
|
||||
"Scan Time Remaining": "Tiempo Restante de Escaneo",
|
||||
"Scanning": "Analizando",
|
||||
"See external versioner help for supported templated command line parameters.": "See external versioner help for supported templated command line parameters.",
|
||||
"See external versioning help for supported templated command line parameters.": "See external versioning help for supported templated command line parameters.",
|
||||
"Select a version": "Select a version",
|
||||
"Select the devices to share this folder with.": "Selecciona los dispositivos con los que compartir esta carpeta.",
|
||||
"Select the folders to share with this device.": "Selecciona las carpetas para compartir con este dispositivo.",
|
||||
"Send & Receive": "Enviar y Recibir",
|
||||
@@ -197,6 +208,7 @@
|
||||
"Shared With": "Compartir con",
|
||||
"Show ID": "Mostrar ID",
|
||||
"Show QR": "Mostrar QR",
|
||||
"Show diff with previous version": "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.": "Se muestra en lugar del ID del dispositivo en el estado del grupo (cluster). Se notificará a los otros dispositivos como nombre opcional por defecto.",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Se muestra en lugar del ID del dispositivo en el estado del grupo (cluster). Se actualizará al nombre que el dispositivo anuncia si se deja vacío.",
|
||||
"Shutdown": "Apagar",
|
||||
@@ -252,6 +264,7 @@
|
||||
"Time": "Hora",
|
||||
"Trash Can File Versioning": "Versionado de archivos de la papelera",
|
||||
"Type": "Tipo",
|
||||
"Undecided (will prompt)": "Undecided (will prompt)",
|
||||
"Unknown": "Desconocido",
|
||||
"Unshared": "No compartido",
|
||||
"Unused": "No usado",
|
||||
|
||||
@@ -24,7 +24,10 @@
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "Kanpoko kontrolagailu batek fitxategien bertsioak kudeatzen ditu. Fitxategiak kendu behar ditu errepertorio sinkronizatuan.",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "Kanpoko kontrolagailu batek fitxeroen bertsioak erabiltzen ditu. Fitxeroak errepertorio sinkronizatutik desagertaraztea berari doakio.",
|
||||
"Anonymous Usage Reporting": "Izenik gabeko erabiltze erreportak",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "Anonymous usage report format has changed. Would you like to move to the new format?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "Sarrarazle deitzen duzun tresna batean gehitua izanen den edozein tresna, zurean ere gehitua izanen da.",
|
||||
"Are you sure you want to remove device {%name%}?": "Are you sure you want to remove device {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Are you sure you want to remove folder {{label}}?",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Eguneratze automatiko sistemak iraunkor bertsioen eta aitzineko bertsioen artean hautatzea proposatzen du",
|
||||
"Automatic upgrades": "Eguneratze automatikoak",
|
||||
"Be careful!": "Kasu emazu!",
|
||||
@@ -53,6 +56,7 @@
|
||||
"Device Identification": "Tresnaren identifikazioa",
|
||||
"Device Name": "Tresnaren izena",
|
||||
"Devices": "Tresnak",
|
||||
"Disabled": "Disabled",
|
||||
"Disconnected": "Deskonektatua",
|
||||
"Discovered": "Agertua",
|
||||
"Discovery": "Agertzea",
|
||||
@@ -84,6 +88,7 @@
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Syncthing-ek aldatzen edo kentzen dituelarik, fitxeroak \".stbertsioak\" peko-errepertoriorat lekutuak dira, jatorrizkoaren berdin berdina den zuhaitz-formako batean",
|
||||
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": ".stbersioak azpi karpetan lekutuko eta ordu-markatuko dira fitxeroak, egitura errelatibo berdin batean, Syncthing-ek aldatu edo ezeztatuko dituelarik.",
|
||||
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Beste tresnetan eginak izanen diren aldaketetatik zainduak izanen dira fitxeroak; haatik, tresna huntan egindako aldaketak besteeri hedatuak izanen dira.",
|
||||
"Filesystem Notifications": "Filesystem Notifications",
|
||||
"Folder": "Partekatze",
|
||||
"Folder ID": "ID partekatze",
|
||||
"Folder Label": "Partekatzearen izena",
|
||||
@@ -136,6 +141,7 @@
|
||||
"Newest First": "Berrienak lehenik",
|
||||
"No": "Ez",
|
||||
"No File Versioning": "Fitxategi bersioen kontrolik ez",
|
||||
"No files will be deleted as a result of this operation.": "No files will be deleted as a result of this operation.",
|
||||
"No upgrades": "Eguneratzerik ez",
|
||||
"Normal": "Normala",
|
||||
"Notice": "Jakinaraztea",
|
||||
@@ -165,11 +171,14 @@
|
||||
"Quick guide to supported patterns": "Eredu konpatibleen gidaliburuxka",
|
||||
"RAM Utilization": "RAM aren erabiltzea",
|
||||
"Random": "Aleatorioa",
|
||||
"Recent Changes": "Recent Changes",
|
||||
"Reduced by ignore patterns": "Baztertze eredu batzuk mugatuak",
|
||||
"Release Notes": "Bertsioen notak",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Azken zuzenketak eta funtzionalitateak edukitzen dituzte aitzin-bertsioek. Bi hilabete guziz egiten diren eguneratzeen berdinak dira.",
|
||||
"Remote Devices": "Beste tresnak",
|
||||
"Remove": "Kendu",
|
||||
"Remove Device": "Remove Device",
|
||||
"Remove Folder": "Remove Folder",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "Partekatzearen erabilzaile izena. Dauden tresna guzietan berdin berdina izan behar du",
|
||||
"Rescan": "Berriz eskaneatu",
|
||||
"Rescan All": "Dena berriz eskaneatu",
|
||||
@@ -184,6 +193,8 @@
|
||||
"Scan Time Remaining": "Gelditzen den azterketa denbora",
|
||||
"Scanning": "Azterketa martxan",
|
||||
"See external versioner help for supported templated command line parameters.": "See external versioner help for supported templated command line parameters.",
|
||||
"See external versioning help for supported templated command line parameters.": "See external versioning help for supported templated command line parameters.",
|
||||
"Select a version": "Select a version",
|
||||
"Select the devices to share this folder with.": " Tresnak hauta itzazu partekatze honekin sinkronizatzeko ",
|
||||
"Select the folders to share with this device.": "Tresna honek erabiltzen dituen partekatzeak hauta itzazu",
|
||||
"Send & Receive": "Igorri eta errezibitu",
|
||||
@@ -197,6 +208,7 @@
|
||||
"Shared With": "...ekin partekatua",
|
||||
"Show ID": "Erakutsi ene ID-a",
|
||||
"Show QR": "Erakutsi QR-a",
|
||||
"Show diff with previous version": "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.": "Tresnaren ID-aren ordez erakutsia, taldearen egoeran. Beste tresneri erakutsia izanen da, izen erabilgarri bat bezala",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Tresnaren ID-aren ordez erakutsia, taldearen egoeran. Hutsa utzia balin bada, urrun den tresnak proposatu izenarekin aktualizatua izanen da",
|
||||
"Shutdown": "Geldi",
|
||||
@@ -252,6 +264,7 @@
|
||||
"Time": "Ordua",
|
||||
"Trash Can File Versioning": "Zakarrontzia",
|
||||
"Type": "Mota",
|
||||
"Undecided (will prompt)": "Undecided (will prompt)",
|
||||
"Unknown": "Ezezaguna",
|
||||
"Unshared": "Partekatua ez dena",
|
||||
"Unused": "Ez baliatua",
|
||||
|
||||
@@ -24,7 +24,10 @@
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "An external command handles the versioning. It has to remove the file from the shared folder.",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "Ulkoinen komento hallitsee versionnin. Sen täytyy poistaa tiedosto synkronoidusta kansiosta.",
|
||||
"Anonymous Usage Reporting": "Anonyymi käyttöraportointi",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "Anonymous usage report format has changed. Would you like to move to the new format?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "Kaikki esittelijäksi määritetyn laitteen tuntemat laitteet lisätään myös tähän laitteeseen.",
|
||||
"Are you sure you want to remove device {%name%}?": "Are you sure you want to remove device {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Are you sure you want to remove folder {{label}}?",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Automatic upgrade now offers the choice between stable releases and release candidates.",
|
||||
"Automatic upgrades": "Automaattiset päivitykset",
|
||||
"Be careful!": "Ole varovainen!",
|
||||
@@ -53,6 +56,7 @@
|
||||
"Device Identification": "Laitteen tunniste",
|
||||
"Device Name": "Laitteen nimi",
|
||||
"Devices": "Laitteet",
|
||||
"Disabled": "Disabled",
|
||||
"Disconnected": "Yhteys katkaistu",
|
||||
"Discovered": "Löydetty",
|
||||
"Discovery": "Etsintä",
|
||||
@@ -84,6 +88,7 @@
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.",
|
||||
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Tiedostot siirretään päivämäärällä merkityiksi versioiksi .stversions-kansioon, kun Syncthing korvaa tai poistaa ne.",
|
||||
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Tiedostot on suojattu muilla laitteilla tehdyiltä muutoksilta, mutta tällä laitteella tehdyt muutokset lähetetään muuhun ryhmään.",
|
||||
"Filesystem Notifications": "Filesystem Notifications",
|
||||
"Folder": "Kansio",
|
||||
"Folder ID": "Kansion ID",
|
||||
"Folder Label": "Kansion nimi",
|
||||
@@ -136,6 +141,7 @@
|
||||
"Newest First": "Uusin ensin",
|
||||
"No": "Ei",
|
||||
"No File Versioning": "Ei tiedostoversiointia",
|
||||
"No files will be deleted as a result of this operation.": "No files will be deleted as a result of this operation.",
|
||||
"No upgrades": "Ei päivityksiä",
|
||||
"Normal": "Normaali kansio",
|
||||
"Notice": "Huomautus",
|
||||
@@ -165,11 +171,14 @@
|
||||
"Quick guide to supported patterns": "Tuettujen lausekkeiden pikaohje",
|
||||
"RAM Utilization": "RAM:n käyttö",
|
||||
"Random": "Satunnainen",
|
||||
"Recent Changes": "Recent Changes",
|
||||
"Reduced by ignore patterns": "Vähennetty ohituslausekkeiden perusteella",
|
||||
"Release Notes": "Julkaisutiedot",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.",
|
||||
"Remote Devices": "Laitteet",
|
||||
"Remove": "Poista",
|
||||
"Remove Device": "Remove Device",
|
||||
"Remove Folder": "Remove Folder",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "Pakollinen tunniste kansiolle, jonka täytyy olla sama kaikilla laitteilla.",
|
||||
"Rescan": "Skannaa uudelleen",
|
||||
"Rescan All": "Skannaa kaikki uudelleen",
|
||||
@@ -184,6 +193,8 @@
|
||||
"Scan Time Remaining": "Skannausaikaa jäljellä",
|
||||
"Scanning": "Skannataan",
|
||||
"See external versioner help for supported templated command line parameters.": "See external versioner help for supported templated command line parameters.",
|
||||
"See external versioning help for supported templated command line parameters.": "See external versioning help for supported templated command line parameters.",
|
||||
"Select a version": "Select a version",
|
||||
"Select the devices to share this folder with.": "Valitse laitteet, joiden kanssa tämä kansio jaetaan.",
|
||||
"Select the folders to share with this device.": "Valitse kansiot jaettavaksi tämän laitteen kanssa.",
|
||||
"Send & Receive": "Lähetä & vastaanota",
|
||||
@@ -197,6 +208,7 @@
|
||||
"Shared With": "Jaettu seuraavien kanssa",
|
||||
"Show ID": "Näytä ID",
|
||||
"Show QR": "Näytä QR-koodi",
|
||||
"Show diff with previous version": "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.": "Näytetään ryhmän tiedoissa laitteen ID:n sijaan. Ilmoitetaan muille laitteille vaihtoehtoisena oletusnimenä.",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Näytetään ryhmän tiedoissa laitteen ID:n sijaan. Tyhjä nimi päivitetään laitteen ilmoittamaksi nimeksi.",
|
||||
"Shutdown": "Sammuta",
|
||||
@@ -252,6 +264,7 @@
|
||||
"Time": "Aika",
|
||||
"Trash Can File Versioning": "Roskakorin tiedostoversiointi",
|
||||
"Type": "Tyyppi",
|
||||
"Undecided (will prompt)": "Undecided (will prompt)",
|
||||
"Unknown": "Tuntematon",
|
||||
"Unshared": "Jakamaton",
|
||||
"Unused": "Käyttämätön",
|
||||
|
||||
@@ -24,7 +24,10 @@
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "Une commande externe gère les versions de fichiers. Il lui incombe de supprimer les fichiers dans le répertoire synchronisé.",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "Une commande externe gère les versions de fichiers. Il lui incombe de supprimer les fichiers dans le répertoire synchronisé.",
|
||||
"Anonymous Usage Reporting": "Rapport anonyme de statistiques d'utilisation",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "Anonymous usage report format has changed. Would you like to move to the new format?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "Lui permettre d'ajouter et enlever des membres à toutes mes listes de membres de partages dont il fait partie (ceci permet de créer toutes les liaisons point à point possibles en complétant mes listes par les siennes, meilleur débit de réception par cumul des débits d'envoi, indépendance vis à vis de l'introducteur, etc).",
|
||||
"Are you sure you want to remove device {%name%}?": "Are you sure you want to remove device {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Are you sure you want to remove folder {{label}}?",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Le système de mise à jour automatique propose le choix entre versions stables et versions préliminaires.",
|
||||
"Automatic upgrades": "Mises à jour automatiques",
|
||||
"Be careful!": "Faites attention !",
|
||||
@@ -53,6 +56,7 @@
|
||||
"Device Identification": "Identifiant de l'appareil",
|
||||
"Device Name": "Nom de l'appareil",
|
||||
"Devices": "Appareil",
|
||||
"Disabled": "Disabled",
|
||||
"Disconnected": "Déconnecté",
|
||||
"Discovered": "Découvert",
|
||||
"Discovery": "Découverte",
|
||||
@@ -84,6 +88,7 @@
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Quand ils sont remplacés ou supprimés par Syncthing, les fichiers sont déplacés et horodatés vers le sous-répertoire .stversions dans une arborescence relative identique à celle de l'original.",
|
||||
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Quand ils sont remplacés ou supprimés par Syncthing, les fichiers sont déplacés et horodatés vers le sous-répertoire .stversions dans une arborescence relative identique à celle de l'original.",
|
||||
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Les fichiers sont protégés des changements réalisés sur les autres appareils, mais les changements réalisés sur celui-ci seront transférés aux autres.",
|
||||
"Filesystem Notifications": "Filesystem Notifications",
|
||||
"Folder": "Partage",
|
||||
"Folder ID": "ID du partage",
|
||||
"Folder Label": "Nom du partage",
|
||||
@@ -136,6 +141,7 @@
|
||||
"Newest First": "Les plus récents en premier",
|
||||
"No": "Non",
|
||||
"No File Versioning": "Pas de préservation",
|
||||
"No files will be deleted as a result of this operation.": "No files will be deleted as a result of this operation.",
|
||||
"No upgrades": "Pas de mises à jour",
|
||||
"Normal": "Normal",
|
||||
"Notice": "Notification",
|
||||
@@ -165,11 +171,14 @@
|
||||
"Quick guide to supported patterns": "Guide rapide des masques compatibles ci-dessous",
|
||||
"RAM Utilization": "Utilisation de la RAM",
|
||||
"Random": "Aléatoire",
|
||||
"Recent Changes": "Recent Changes",
|
||||
"Reduced by ignore patterns": "(Limité par des masques d'exclusion)",
|
||||
"Release Notes": "Notes de version",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Les versions préliminaires contiennent les dernières fonctionnalités et derniers correctifs. Elles sont identiques aux traditionnelles mises à jour bimensuelles.",
|
||||
"Remote Devices": "Autres appareils",
|
||||
"Remove": "Enlever",
|
||||
"Remove Device": "Remove Device",
|
||||
"Remove Folder": "Remove Folder",
|
||||
"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.",
|
||||
"Rescan": "Réanalyser",
|
||||
"Rescan All": "Tout réanalyser",
|
||||
@@ -184,6 +193,8 @@
|
||||
"Scan Time Remaining": "Temps d'analyse restant",
|
||||
"Scanning": "Analyse en cours",
|
||||
"See external versioner help for supported templated command line parameters.": "See external versioner help for supported templated command line parameters.",
|
||||
"See external versioning help for supported templated command line parameters.": "See external versioning help for supported templated command line parameters.",
|
||||
"Select a version": "Select a version",
|
||||
"Select the devices to share this folder with.": "Synchroniser avec :",
|
||||
"Select the folders to share with this device.": "Sélectionner les partages auxquels participe cet appareil.",
|
||||
"Send & Receive": "Envoi & réception",
|
||||
@@ -197,6 +208,7 @@
|
||||
"Shared With": "Synchronisé avec",
|
||||
"Show ID": "Afficher mon ID",
|
||||
"Show QR": "Afficher l'image QR",
|
||||
"Show diff with previous version": "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.": "Affiché à la place de l'ID de l'appareil dans l'état du groupe. Sera diffusé aux autres appareils comme nom convivial optionnel par défaut.",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Affiché à la place de l'ID de l'appareil dans l'état du groupe. Si laissé vide, il sera renseigné par le nom convivial proposé par l'appareil distant.",
|
||||
"Shutdown": "Arrêter",
|
||||
@@ -252,6 +264,7 @@
|
||||
"Time": "Heure",
|
||||
"Trash Can File Versioning": "Style poubelle",
|
||||
"Type": "Type",
|
||||
"Undecided (will prompt)": "Undecided (will prompt)",
|
||||
"Unknown": "Inconnu",
|
||||
"Unshared": "Non partagé",
|
||||
"Unused": "Non utilisé",
|
||||
|
||||
@@ -24,7 +24,10 @@
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "Une commande externe gère les versions de fichiers. Il lui incombe de supprimer les fichiers dans le répertoire synchronisé.",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "Une commande externe gère les versions de fichiers. Il lui incombe de supprimer les fichiers dans le répertoire synchronisé.",
|
||||
"Anonymous Usage Reporting": "Rapport anonyme de statistiques d'utilisation",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "Le format du rapport anonyme d'utilisation a changé. Voulez-vous passer au nouveau format ?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "Lui permettre d'ajouter et enlever des membres à toutes mes listes de membres des partages dont il fait (ou fera !) partie (ceci permet de créer toutes les liaisons point à point possibles en complétant mes listes par les siennes, meilleur débit de réception par cumul des débits d'envoi, indépendance vis à vis de l'introducteur, etc).",
|
||||
"Are you sure you want to remove device {%name%}?": "Êtes-vous sûr de vouloir enlever l'appareil {{name}} ?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Êtes-vous sûr de vouloir enlever le partage {{label}} ?",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Le système de mise à jour automatique propose le choix entre versions stables et versions préliminaires.",
|
||||
"Automatic upgrades": "Mises à jour automatiques",
|
||||
"Be careful!": "Faites attention !",
|
||||
@@ -51,8 +54,9 @@
|
||||
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "\"{{name}}\" ({{device}}), appareil actuellement à {{address}}, demande à se connecter.\nAcceptez-vous de l'ajouter à votre liste d'appareils connus ?",
|
||||
"Device ID": "ID de l'appareil",
|
||||
"Device Identification": "Identifiant de l'appareil",
|
||||
"Device Name": "Nom de l'appareil",
|
||||
"Device Name": "Nom convivial local de l'appareil",
|
||||
"Devices": "Appareils",
|
||||
"Disabled": "Désactivé",
|
||||
"Disconnected": "Déconnecté",
|
||||
"Discovered": "Découvert",
|
||||
"Discovery": "Découverte",
|
||||
@@ -84,6 +88,7 @@
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Quand ils sont remplacés ou supprimés par Syncthing, les fichiers sont déplacés et horodatés vers le sous-répertoire .stversions dans une arborescence relative identique à celle de l'original.",
|
||||
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Quand ils sont remplacés ou supprimés par Syncthing, les fichiers sont déplacés et horodatés vers le sous-répertoire .stversions dans une arborescence relative identique à celle de l'original.",
|
||||
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Les fichiers sont protégés des changements réalisés sur les autres appareils, mais les changements réalisés sur celui-ci seront transférés aux autres.",
|
||||
"Filesystem Notifications": "Notifications du système de fichiers",
|
||||
"Folder": "Partage",
|
||||
"Folder ID": "ID du partage",
|
||||
"Folder Label": "Nom du partage",
|
||||
@@ -136,13 +141,14 @@
|
||||
"Newest First": "Les plus récents en premier",
|
||||
"No": "Non",
|
||||
"No File Versioning": "Pas de préservation",
|
||||
"No files will be deleted as a result of this operation.": "Aucun fichier ne sera supprimé à la suite de cette opération.",
|
||||
"No upgrades": "Pas de mises à jour",
|
||||
"Normal": "Normal",
|
||||
"Notice": "Notification",
|
||||
"OK": "OK",
|
||||
"Off": "Désactivé(e)",
|
||||
"Oldest First": "Les plus anciens en premier",
|
||||
"Optional descriptive label for the folder. Can be different on each device.": "Nom convivial et optionnel du partage, à votre guise. il peut être différent sur chaque appareil.",
|
||||
"Optional descriptive label for the folder. Can be different on each device.": "Nom local, convivial et optionnel du partage, à votre guise. il peut être différent sur chaque appareil. Par notification initiale, il sera proposé tel quel aux nouveaux participants.\nAstuce : comme il est modifiable ultérieurement, pensez à indiquer un nom parlant pour les invités, puis renommez-le quand ils l'auront accepté (exemple d'un partage à deux membres où l'initiateur commence par donner son propre nom au partage, puis le renomme plus tard au nom du partenaire quand celui-ci l'a enregistré). Évitez les erreurs d'orthographe car ce nom servira aussi de base au chemin proposé en création (local et distant) et ce chemin est difficilement modifiable.",
|
||||
"Options": "Options",
|
||||
"Out of Sync": "Désynchronisé",
|
||||
"Out of Sync Items": "Éléments non synchronisés",
|
||||
@@ -165,12 +171,15 @@
|
||||
"Quick guide to supported patterns": "Guide rapide des masques compatibles ci-dessous",
|
||||
"RAM Utilization": "Utilisation de la RAM",
|
||||
"Random": "Aléatoire",
|
||||
"Recent Changes": "Changements récents",
|
||||
"Reduced by ignore patterns": "(Limité par des masques d'exclusion)",
|
||||
"Release Notes": "Notes de version",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Les versions préliminaires contiennent les dernières fonctionnalités et derniers correctifs. Elles sont identiques aux traditionnelles mises à jour bimensuelles.",
|
||||
"Remote Devices": "Autres appareils",
|
||||
"Remove": "Supprimer",
|
||||
"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.",
|
||||
"Remove Device": "Enlever l'appareil",
|
||||
"Remove Folder": "Enlever 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).",
|
||||
"Rescan": "Réanalyser",
|
||||
"Rescan All": "Tout réanalyser",
|
||||
"Rescan Interval": "Intervalle d'analyse",
|
||||
@@ -184,8 +193,10 @@
|
||||
"Scan Time Remaining": "Temps d'analyse restant",
|
||||
"Scanning": "Analyse en cours",
|
||||
"See external versioner help for supported templated command line parameters.": "Voir l'aide sur la préservation externe des fichiers pour les paramètres supportés en lignes de commande dans les modèles.",
|
||||
"See external versioning help for supported templated command line parameters.": "Consulter l'aide à la gestion externe des versions pour voir les paramètres de ligne de commande supportés.",
|
||||
"Select a version": "Choisissez une version",
|
||||
"Select the devices to share this folder with.": "Synchroniser avec :",
|
||||
"Select the folders to share with this device.": "Sélectionner les partages auxquels cet appareil doit participer :",
|
||||
"Select the folders to share with this device.": "Choisir les partages auxquels cet appareil doit participer :",
|
||||
"Send & Receive": "Envoi & réception",
|
||||
"Send Only": "Envoi (lecture seule)",
|
||||
"Settings": "Configuration",
|
||||
@@ -197,8 +208,9 @@
|
||||
"Shared With": "Synchronisé avec",
|
||||
"Show ID": "Afficher mon ID",
|
||||
"Show QR": "Afficher le QR",
|
||||
"Show diff with previous version": "Afficher les différences avec la version précédente",
|
||||
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Affiché à la place de l'ID de l'appareil dans l'état du groupe. Sera diffusé aux autres appareils comme nom convivial optionnel par défaut.",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Affiché à la place de l'ID de l'appareil dans l'état du groupe. Si laissé vide, il sera renseigné par le nom convivial proposé par l'appareil distant.",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Nom convivial local affiché à la place de l'ID de l'appareil dans la plupart des écrans. Si laissé vide, c'est le nom convivial local de l'appareil distant qui sera utilisé. (Modifiable ultérieurement).",
|
||||
"Shutdown": "Arrêter",
|
||||
"Shutdown Complete": "Arrêté !",
|
||||
"Simple File Versioning": "Suivi simplifié des versions",
|
||||
@@ -252,6 +264,7 @@
|
||||
"Time": "Heure",
|
||||
"Trash Can File Versioning": "Style poubelle",
|
||||
"Type": "Type",
|
||||
"Undecided (will prompt)": "Choix différé (Une question sera affichée plus tard)",
|
||||
"Unknown": "Inconnu",
|
||||
"Unshared": "Non partagé",
|
||||
"Unused": "Non utilisé",
|
||||
|
||||
@@ -24,7 +24,10 @@
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "In ekstern kommando soarget foar it ferzjebehear. It moat de triem út de dielde map fuortsmite.",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "In ekstern kommando soarget foar it ferzjebehear. It moat de triem út de syngronisearre map fuortsmite.",
|
||||
"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?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "Alle apparaten die op in 'yntrodusearjend apparaat' ynstelt binne, wurde ek op dit apparaat taheakke.",
|
||||
"Are you sure you want to remove device {%name%}?": "Are you sure you want to remove device {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Are you sure you want to remove folder {{label}}?",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Automatyske fernijing biedt no de kar tusken stabyle ferzjes en ferzje kandidaten",
|
||||
"Automatic upgrades": "Automatyske fernijings",
|
||||
"Be careful!": "Tink derom!",
|
||||
@@ -53,6 +56,7 @@
|
||||
"Device Identification": "Apparaatidentifikaasje",
|
||||
"Device Name": "Apparaatnamme",
|
||||
"Devices": "Apparaten",
|
||||
"Disabled": "Utskeakele",
|
||||
"Disconnected": "Ferbining ferbrutsen",
|
||||
"Discovered": "Untdekt",
|
||||
"Discovery": "Untdekking",
|
||||
@@ -84,6 +88,7 @@
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Triemen wurde ferset nei mei datum stimpele ferzjes yn in .stversions map wannear troch Syncthing ferfangen of fuortsmiten.",
|
||||
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Triemen wurde ferset nei in mei datum stimpele ferzjes yn in .stversions map wannear troch Syncthing ferfangen of fuortsmiten.",
|
||||
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Triemen binne ymmún foar feroarings makke troch oare apparaten, mar feroarings makke op dit apparaat wurde nei de rest fan 'e bondel ferstjoerd.",
|
||||
"Filesystem Notifications": "Meldingen fan Triemsysteem",
|
||||
"Folder": "Map",
|
||||
"Folder ID": "Map-ID",
|
||||
"Folder Label": "Map-opskrift",
|
||||
@@ -136,6 +141,7 @@
|
||||
"Newest First": "Nijste earst",
|
||||
"No": "Nee",
|
||||
"No File Versioning": "Gjin triemferzjebehear",
|
||||
"No files will be deleted as a result of this operation.": "No files will be deleted as a result of this operation.",
|
||||
"No upgrades": "Gjin fernijings",
|
||||
"Normal": "Normaal",
|
||||
"Notice": "Notysje",
|
||||
@@ -165,11 +171,14 @@
|
||||
"Quick guide to supported patterns": "Fluch-paadwizer foar stipe patroanen",
|
||||
"RAM Utilization": "RAM-brûken",
|
||||
"Random": "Willekeurich",
|
||||
"Recent Changes": "Resinte Feroarings",
|
||||
"Reduced by ignore patterns": "Ferlytse troch negear-patroanen",
|
||||
"Release Notes": "Utjeftenotysjes",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Ferzje kandidaten hawwe de lêste mooglikheden en ferbetterings. Se binne allyksa de tradisjonele twa-wyklikse Syncthing ferzjes.",
|
||||
"Remote Devices": "Apparaten op Ofstân",
|
||||
"Remove": "Fuortsmite",
|
||||
"Remove Device": "Remove Device",
|
||||
"Remove Folder": "Remove Folder",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "Ferplicht ID foar de map. Moat op alle bondelapparaten itselde wêze.",
|
||||
"Rescan": "Sken opnij",
|
||||
"Rescan All": "Sken alles opnij",
|
||||
@@ -184,6 +193,8 @@
|
||||
"Scan Time Remaining": "Oerbleaune skentiid",
|
||||
"Scanning": "Oan it skennen",
|
||||
"See external versioner help for supported templated command line parameters.": "Sjoch de eksterne help fan fersjebehearder foar stipe foarbylden fan kommando-rige-parameters.",
|
||||
"See external versioning help for supported templated command line parameters.": "Sjoch de eksterne help fan fersjebehearder foar stipe foarbylden fan kommando-rige-parameters.",
|
||||
"Select a version": "Kies in ferzje",
|
||||
"Select the devices to share this folder with.": "Sykje de apparaten út om dizze map mei te dielen.",
|
||||
"Select the folders to share with this device.": "Sykje de mappen út om mei dit apparaat te dielen.",
|
||||
"Send & Receive": "Stjoere & Untfange",
|
||||
@@ -197,6 +208,7 @@
|
||||
"Shared With": "Dielt mei",
|
||||
"Show ID": "ID sjen litte",
|
||||
"Show QR": "QR sjen litte",
|
||||
"Show diff with previous version": "Ferskil (diff) mei de foarige ferzje sjen litte",
|
||||
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Wurd ynstee fan apparaat-ID sjen litten by de bondeltastân. Wurd nei oare apparaten advertearre as in mooglike standertnamme.",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Wurd yn de bondeltastân sjen litten ynstee fan apparaat-ID. Wannear't leech litten wurd, wurd it fernijt nei de namme die it apparaat útstjoert.",
|
||||
"Shutdown": "Ofslute",
|
||||
@@ -252,6 +264,7 @@
|
||||
"Time": "Tiid",
|
||||
"Trash Can File Versioning": "Jiskefet-triemferzjebehear",
|
||||
"Type": "Type",
|
||||
"Undecided (will prompt)": "Noch net beslist (wurd noch frege)",
|
||||
"Unknown": "Unbekend",
|
||||
"Unshared": "Net dielt",
|
||||
"Unused": "Net brûkt",
|
||||
|
||||
@@ -24,7 +24,10 @@
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "Külső program kezeli a fájlverzió-követést. Az távolítja el a fájlt a megosztott mappából.",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "Külső program kezeli a fájlverzió-követést. Az távolítja el a fájlt a szinkronizált mappából.",
|
||||
"Anonymous Usage Reporting": "Névtelen felhasználási adatok küldése",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "A névtelen használati jelentés formátuma megváltozott. Szeretnél áttérni az új formátumra?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "A bevezető eszközön beállított minden eszköz hozzá lesz adva ehhez az eszközhöz is.",
|
||||
"Are you sure you want to remove device {%name%}?": "Biztos, hogy el akarod távolítani az eszközt: {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Biztos, hogy el akarod távolítani a mappát: {{label}}?",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Az automatikus frissítés most lehetőséget kínál a stabil és az előzetes kiadások közötti választásra.",
|
||||
"Automatic upgrades": "Automatikus frissítések",
|
||||
"Be careful!": "Óvatosan!",
|
||||
@@ -53,6 +56,7 @@
|
||||
"Device Identification": "Eszközazonosító",
|
||||
"Device Name": "Eszköz neve",
|
||||
"Devices": "Eszközök",
|
||||
"Disabled": "Letiltva",
|
||||
"Disconnected": "Kapcsolat bontva",
|
||||
"Discovered": "Felfedezett",
|
||||
"Discovery": "Felfedezés",
|
||||
@@ -84,6 +88,7 @@
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Ha a Syncthing felülírja vagy törli a fájlokat, akkor azok a .stversions könyvtárba lesznek áthelyezve, időbélyegzővel ellátva.",
|
||||
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Ha a Syncthing felülírja vagy törli a fájlokat, akkor azok a .stversions mappába lesznek áthelyezve, időbélyegzővel ellátva.",
|
||||
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "A fájlok védve vannak a más eszközökön történt változásokkal szemben, de az ezen az eszközön történt változások érvényesek lesznek a többire.",
|
||||
"Filesystem Notifications": "Fájlrendszer értesítések",
|
||||
"Folder": "Mappa",
|
||||
"Folder ID": "Mappaazonosító",
|
||||
"Folder Label": "Mappacímke",
|
||||
@@ -136,6 +141,7 @@
|
||||
"Newest First": "Újabb először",
|
||||
"No": "Nem",
|
||||
"No File Versioning": "Nincs fájlverzió-követés",
|
||||
"No files will be deleted as a result of this operation.": "A művelet eredményeként egyetlen fájl sem lesz törölve.",
|
||||
"No upgrades": "Nincsenek frissítések",
|
||||
"Normal": "Normál",
|
||||
"Notice": "Megjegyzés",
|
||||
@@ -165,11 +171,14 @@
|
||||
"Quick guide to supported patterns": "Rövid útmutató a használható mintákról",
|
||||
"RAM Utilization": "Memóriahasználat",
|
||||
"Random": "Véletlenszerű",
|
||||
"Recent Changes": "Utolsó módosítások",
|
||||
"Reduced by ignore patterns": "Kihagyási mintákkal csökkentve",
|
||||
"Release Notes": "Kiadási megjegyzések",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Az előzetes kiadások tartalmazzák a legújabb fejlesztéseket és javításokat. Ezek hasonlóak a hagyományos, kétheti Syncthing kiadásokhoz.",
|
||||
"Remote Devices": "Távoli eszközök",
|
||||
"Remove": "Eltávolítás",
|
||||
"Remove Device": "Eszköz eltávolítás",
|
||||
"Remove Folder": "Mappa eltávolítás",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "A mappa szükséges azonosítója. Minden fürtözött eszközön azonosnak kell lennie.",
|
||||
"Rescan": "Átnézés",
|
||||
"Rescan All": "Összes átnézése",
|
||||
@@ -184,6 +193,8 @@
|
||||
"Scan Time Remaining": "Fennmaradó átnézési idő",
|
||||
"Scanning": "Átnézés",
|
||||
"See external versioner help for supported templated command line parameters.": "A támogatott parancssori paraméter sablonokat a külső verziókezelő súgójában találod.",
|
||||
"See external versioning help for supported templated command line parameters.": "A támogatott parancssori paraméter sablonokat a külső verziókezelő súgójában találod.",
|
||||
"Select a version": "Válassz egy verziót",
|
||||
"Select the devices to share this folder with.": "Eszközök, amelyekkel megosztandó a mappa",
|
||||
"Select the folders to share with this device.": "Mappák, amelyek megosztandók ezzel az eszközzel.",
|
||||
"Send & Receive": "Küldés és fogadás",
|
||||
@@ -197,6 +208,7 @@
|
||||
"Shared With": "Megosztva ezekkel:",
|
||||
"Show ID": "Azonosító mutatása",
|
||||
"Show QR": "QR-kód mutatása",
|
||||
"Show diff with previous version": "Előző verzió eltérésének megjelenítése",
|
||||
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Az eszközazonosító helyett jelenik meg. A többi eszközön alapértelmezett névként használható. ",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Az eszközazonosító helyett jelenik meg. Üresen hagyva az eszköz saját neve lesz alkalmazva.",
|
||||
"Shutdown": "Leállítás",
|
||||
@@ -252,6 +264,7 @@
|
||||
"Time": "Idő",
|
||||
"Trash Can File Versioning": "Szemetes fájlverzió-követés",
|
||||
"Type": "Típus",
|
||||
"Undecided (will prompt)": "Bizonytalan (kérdezni fogja)",
|
||||
"Unknown": "Ismeretlen",
|
||||
"Unshared": "Nincs megosztva",
|
||||
"Unused": "Nincs használatban",
|
||||
|
||||
@@ -24,7 +24,10 @@
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "Il controllo versione è gestito da un comando esterno. Quest'ultimo deve rimuovere il file dalla cartella condivisa.",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "Il controllo versione è gestito da un comando esterno. Quest'ultimo deve rimuovere il file dalla cartella sincronizzata.",
|
||||
"Anonymous Usage Reporting": "Statistiche Anonime di Utilizzo",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "Il formato delle statistiche anonime di utilizzo è cambiato. Vuoi passare al nuovo formato?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "Qualsiasi dispositivo configurato in un introduttore verrà aggiunto anche a questo dispositivo.",
|
||||
"Are you sure you want to remove device {%name%}?": "Are you sure you want to remove device {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Are you sure you want to remove folder {{label}}?",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Aggiornamenti automatici offrono la scelta tra rilasci stabili e candidati di rilascio.",
|
||||
"Automatic upgrades": "Aggiornamenti automatici",
|
||||
"Be careful!": "Fai attenzione!",
|
||||
@@ -53,6 +56,7 @@
|
||||
"Device Identification": "Identificazione Dispositivo",
|
||||
"Device Name": "Nome Dispositivo",
|
||||
"Devices": "Dispositivi",
|
||||
"Disabled": "Disabilitato",
|
||||
"Disconnected": "Disconnesso",
|
||||
"Discovered": "Individuato",
|
||||
"Discovery": "Individuazione",
|
||||
@@ -84,6 +88,7 @@
|
||||
"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 moved to date stamped versions in a .stversions folder 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.",
|
||||
"Filesystem Notifications": "Notifiche del filesystem",
|
||||
"Folder": "Cartella",
|
||||
"Folder ID": "ID Cartella",
|
||||
"Folder Label": "Etichetta per la Cartella",
|
||||
@@ -136,6 +141,7 @@
|
||||
"Newest First": "Prima il più recente",
|
||||
"No": "No",
|
||||
"No File Versioning": "Nessun Controllo Versione",
|
||||
"No files will be deleted as a result of this operation.": "No files will be deleted as a result of this operation.",
|
||||
"No upgrades": "Senza aggiornamenti",
|
||||
"Normal": "Normale",
|
||||
"Notice": "Avviso",
|
||||
@@ -165,11 +171,14 @@
|
||||
"Quick guide to supported patterns": "Guida veloce agli schemi supportati",
|
||||
"RAM Utilization": "Utilizzo RAM",
|
||||
"Random": "Casuale",
|
||||
"Recent Changes": "Recent Changes",
|
||||
"Reduced by ignore patterns": "Ridotto da schemi di esclusione",
|
||||
"Release Notes": "Note di Rilascio",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Candidati di rilascio contengono le ultime funzionalita e aggiustamenti. Sono simili ai rilasci bisettimanali di Syncthing.",
|
||||
"Remote Devices": "Dispositivi Remoti",
|
||||
"Remove": "Rimuovi",
|
||||
"Remove Device": "Remove Device",
|
||||
"Remove Folder": "Remove Folder",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "Identificatore obbligatorio della cartella. Deve essere lo stesso su tutti i dispositivi del cluster.",
|
||||
"Rescan": "Riscansiona",
|
||||
"Rescan All": "Riscansiona Tutto",
|
||||
@@ -184,6 +193,8 @@
|
||||
"Scan Time Remaining": "Tempo di Scansione Rimanente",
|
||||
"Scanning": "Scansione in corso",
|
||||
"See external versioner help for supported templated command line parameters.": "Consultare la guida al controllo di versione per i modelli dei parametri di riga di comando supportati.",
|
||||
"See external versioning help for supported templated command line parameters.": "Consultare la guida al controllo di versione per i modelli dei parametri di riga di comando supportati.",
|
||||
"Select a version": "Seleziona una versione",
|
||||
"Select the devices to share this folder with.": "Seleziona i dispositivi con i quali condividere questa cartella.",
|
||||
"Select the folders to share with this device.": "Seleziona le cartelle da condividere con questo dispositivo.",
|
||||
"Send & Receive": "Invia & Ricevi",
|
||||
@@ -197,6 +208,7 @@
|
||||
"Shared With": "Condiviso Con",
|
||||
"Show ID": "Mostra ID",
|
||||
"Show QR": "Mostra QR",
|
||||
"Show diff with previous version": "Mostra le differenze con la versione precedente",
|
||||
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Visibile al posto dell'ID Dispositivo nello stato del cluster. Negli altri dispositivi verrà presentato come nome predefinito opzionale.",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Visibile al posto dell'ID Dispositivo nello stato del cluster. Se viene lasciato vuoto, verrà utilizzato il nome proposto dal dispositivo.",
|
||||
"Shutdown": "Arresta",
|
||||
@@ -252,6 +264,7 @@
|
||||
"Time": "Tempo",
|
||||
"Trash Can File Versioning": "Controllo Versione con Cestino",
|
||||
"Type": "Tipo",
|
||||
"Undecided (will prompt)": "Non deciso (verrà richiesto)",
|
||||
"Unknown": "Sconosciuto",
|
||||
"Unshared": "Non Condiviso",
|
||||
"Unused": "Non Utilizzato",
|
||||
|
||||
@@ -21,10 +21,13 @@
|
||||
"Allow Anonymous Usage Reporting?": "匿名で使用状況をレポートすることを許可しますか?",
|
||||
"Allowed Networks": "許可されているネットワーク",
|
||||
"Alphabetic": "アルファベット順",
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "外部コマンドにバージョン管理を任せます。ここで指定するコマンドは、共有フォルダーからファイルを削除するものでなくてはなりません。",
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "外部コマンドでバージョン管理を行います。ここで指定するコマンドは、共有フォルダーからファイルを削除するものでなくてはなりません。",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "外部コマンドにバージョンを管理させます。ここで指定するコマンドは、同期フォルダーからファイルを削除するものでなくてはなりません。",
|
||||
"Anonymous Usage Reporting": "匿名での使用状況レポート",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "匿名での使用状況レポートのフォーマットが変わりました。新形式でのレポートに移行しますか?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "紹介者デバイス上で設定されたデバイスは、このデバイス上にも追加されます。",
|
||||
"Are you sure you want to remove device {%name%}?": "Are you sure you want to remove device {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Are you sure you want to remove folder {{label}}?",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "自動アップグレードは、安定版とリリース候補版のいずれかを選べるようになりました。",
|
||||
"Automatic upgrades": "自動アップグレード",
|
||||
"Be careful!": "注意!",
|
||||
@@ -53,6 +56,7 @@
|
||||
"Device Identification": "デバイスID",
|
||||
"Device Name": "デバイス名",
|
||||
"Devices": "デバイス",
|
||||
"Disabled": "無効",
|
||||
"Disconnected": "切断中",
|
||||
"Discovered": "探索結果",
|
||||
"Discovery": "探索サーバー",
|
||||
@@ -84,6 +88,7 @@
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Syncthingによって置き換えられたり削除されたファイルは、タイムスタンプ付きのファイル名で .stversions ディレクトリに移動します。",
|
||||
"Files are moved to date stamped versions in a .stversions folder 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.": "ファイルを他のデバイスによる変更から保護します。一方、このデバイスでの変更は他のデバイスに送信されます。",
|
||||
"Filesystem Notifications": "Filesystem Notifications",
|
||||
"Folder": "フォルダー",
|
||||
"Folder ID": "フォルダーID",
|
||||
"Folder Label": "フォルダー名",
|
||||
@@ -136,6 +141,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 upgrades": "アップグレードしない",
|
||||
"Normal": "通常",
|
||||
"Notice": "通知",
|
||||
@@ -149,7 +155,7 @@
|
||||
"Outgoing Rate Limit (KiB/s)": "上り帯域制限 (KiB/s)",
|
||||
"Override Changes": "他のデバイスの変更を上書きする",
|
||||
"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 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 ディレクトリ)",
|
||||
"Path where versions should be stored (leave empty for the default .stversions folder in the folder).": "古いバージョンを保存するパス (空欄の場合、デフォルトでフォルダー内の .stversions フォルダー)",
|
||||
"Pause": "一時停止",
|
||||
@@ -165,11 +171,14 @@
|
||||
"Quick guide to supported patterns": "サポートされているパターンのクイックガイド",
|
||||
"RAM Utilization": "メモリ使用量",
|
||||
"Random": "ランダム",
|
||||
"Recent Changes": "Recent Changes",
|
||||
"Reduced by ignore patterns": "無視パターン該当分を除く",
|
||||
"Release Notes": "リリースノート",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "リリース候補版には最新の機能と修正が含まれます。これは従来の隔週リリースに近いものです。",
|
||||
"Remote Devices": "接続先デバイス",
|
||||
"Remove": "除去",
|
||||
"Remove Device": "Remove Device",
|
||||
"Remove Folder": "Remove Folder",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "フォルダーの識別子で、必須です。このフォルダーを共有する全てのデバイス上で同一でなくてはなりません。",
|
||||
"Rescan": "再スキャン",
|
||||
"Rescan All": "すべて再スキャン",
|
||||
@@ -184,6 +193,8 @@
|
||||
"Scan Time Remaining": "スキャン残り時間",
|
||||
"Scanning": "スキャン中",
|
||||
"See external versioner help for supported templated command line parameters.": "See external versioner help for supported templated command line parameters.",
|
||||
"See external versioning help for supported templated command line parameters.": "使用可能なコマンドラインパラメータについてはヘルプの外部バージョン管理の項目を参照してください。",
|
||||
"Select a version": "バージョンを選択してください",
|
||||
"Select the devices to share this folder with.": "このフォルダーを共有するデバイスを選択してください。",
|
||||
"Select the folders to share with this device.": "このデバイスと共有するフォルダーを選択してください。",
|
||||
"Send & Receive": "送受信",
|
||||
@@ -197,6 +208,7 @@
|
||||
"Shared With": "共有中のデバイス",
|
||||
"Show ID": "IDを表示",
|
||||
"Show QR": "QRコードを表示",
|
||||
"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.": "ステータス画面でデバイスIDの代わりに表示されます。他のデバイスに対してもデフォルトの名前として通知されます。",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "ステータス画面でデバイスIDの代わりに表示されます。空欄にすると相手側デバイスが通知してきた名前で更新されます。",
|
||||
"Shutdown": "シャットダウン",
|
||||
@@ -222,7 +234,7 @@
|
||||
"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を再起動してください。",
|
||||
"The Syncthing admin interface is configured to allow remote access without a password.": "Syncthingの管理画面が、パスワードなしで外部からアクセスできるように設定されています。",
|
||||
"The aggregated statistics are publicly available at the URL below.": "集計結果は次のURLで公開されています。",
|
||||
"The aggregated statistics are publicly available at the URL below.": "集計結果は以下のURLで公開されています。",
|
||||
"The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.": "設定が保存されましたが、まだ有効になっていません。新しい設定を有効にするにはSyncthingを再起動してください。",
|
||||
"The device ID cannot be blank.": "デバイスIDを入力してください。",
|
||||
"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).": "ここに入力するデバイスIDは、接続したい相手側デバイスの [メニュー]→[IDを表示] で確認できます。スペースとハイフンは入力しなくてもかまいません。",
|
||||
@@ -252,6 +264,7 @@
|
||||
"Time": "日時",
|
||||
"Trash Can File Versioning": "ゴミ箱によるバージョン管理",
|
||||
"Type": "タイプ",
|
||||
"Undecided (will prompt)": "未決定(再確認する)",
|
||||
"Unknown": "不明",
|
||||
"Unshared": "非共有",
|
||||
"Unused": "未使用",
|
||||
|
||||
@@ -24,7 +24,10 @@
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "외부 커맨드가 파일 버전을 관리합니다. 공유된 폴더에서 파일을 삭제해야 합니다.",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "외부 커맨드가 파일 버전을 관리합니다. 동기화된 폴더에서 파일을 삭제해야 합니다.",
|
||||
"Anonymous Usage Reporting": "익명 사용 보고서",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "익명 사용 리포트의 형식이 변경되었습니다. 새 형식으로 이동 하시겠습니까?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "유도 장치에 추가된 기기들은 이 기기에도 동시에 추가됩니다.",
|
||||
"Are you sure you want to remove device {%name%}?": "Are you sure you want to remove device {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Are you sure you want to remove folder {{label}}?",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "자동 업데이트를 이제 안정 버전과 출시 후보 사이에 선택 할 수 있게 됩니다.",
|
||||
"Automatic upgrades": "자동 업데이트",
|
||||
"Be careful!": "주의!",
|
||||
@@ -53,6 +56,7 @@
|
||||
"Device Identification": "기기 식별자",
|
||||
"Device Name": "기기 이름",
|
||||
"Devices": "기기",
|
||||
"Disabled": "비활성화",
|
||||
"Disconnected": "연결 끊김",
|
||||
"Discovered": "탐색됨",
|
||||
"Discovery": "탐색",
|
||||
@@ -84,6 +88,7 @@
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "파일이 Syncthing에 의해서 교체되거나 삭제되면 .stversions 폴더에 있는 날짜가 바뀐 버전으로 이동됩니다.",
|
||||
"Files are moved to date stamped versions in a .stversions folder 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.": "다른 장치가 파일을 편집할 수 없으며 반드시 이 장치의 내용을 기준으로 동기화합니다.",
|
||||
"Filesystem Notifications": "파일시스템 알림",
|
||||
"Folder": "폴더",
|
||||
"Folder ID": "폴더 ID",
|
||||
"Folder Label": "폴더 라벨",
|
||||
@@ -136,6 +141,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 upgrades": "업데이트 안함",
|
||||
"Normal": "일반",
|
||||
"Notice": "공지",
|
||||
@@ -165,11 +171,14 @@
|
||||
"Quick guide to supported patterns": "지원하는 패턴에 대한 빠른 도움말",
|
||||
"RAM Utilization": "RAM 사용량",
|
||||
"Random": "무작위",
|
||||
"Recent Changes": "Recent Changes",
|
||||
"Reduced by ignore patterns": "무시 패턴으로 축소",
|
||||
"Release Notes": "릴리즈 노트",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "출시 후보는 최신 기능과 버그 픽스를 포함 하고 있습니다. 이 버전은 예전 방식인 2주 주기 Syncthing 출시와 비슷합니다.",
|
||||
"Remote Devices": "원격 기기",
|
||||
"Remove": "삭제",
|
||||
"Remove Device": "Remove Device",
|
||||
"Remove Folder": "Remove Folder",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "폴더 식별자가 필요합니다. 모든 장치에서 동일해야 합니다.",
|
||||
"Rescan": "재탐색",
|
||||
"Rescan All": "전체 재탐색",
|
||||
@@ -183,7 +192,9 @@
|
||||
"Save": "저장",
|
||||
"Scan Time Remaining": "탐색 남은 시간",
|
||||
"Scanning": "탐색중",
|
||||
"See external versioner help for supported templated command line parameters.": "See external versioner help for supported templated command line parameters.",
|
||||
"See external versioner help for supported templated command line parameters.": "지원되는 템플릿 명령 행 매개 변수에 대해서는 외부 버전 도움말을 참조하십시오.",
|
||||
"See external versioning help for supported templated command line parameters.": "지원되는 템플릿 명령 행 매개 변수에 대해서는 외부 버전 도움말을 참조하십시오.",
|
||||
"Select a version": "버전 선택",
|
||||
"Select the devices to share this folder with.": "이 폴더를 공유할 장치를 선택합니다.",
|
||||
"Select the folders to share with this device.": "이 장치와 공유할 폴더를 선택합니다.",
|
||||
"Send & Receive": "송신 & 수신",
|
||||
@@ -197,6 +208,7 @@
|
||||
"Shared With": "~와 공유",
|
||||
"Show ID": "내 기기 ID",
|
||||
"Show QR": "QR 코드 보기",
|
||||
"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": "종료",
|
||||
@@ -252,6 +264,7 @@
|
||||
"Time": "시간",
|
||||
"Trash Can File Versioning": "휴지통을 통한 파일 버전 관리",
|
||||
"Type": "종류",
|
||||
"Undecided (will prompt)": "Undecided (will prompt)",
|
||||
"Unknown": "알 수 없음",
|
||||
"Unshared": "공유되지 않음",
|
||||
"Unused": "사용되지 않음",
|
||||
|
||||
@@ -24,7 +24,10 @@
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "Išorinė komanda apdoroja versijų valdymą. Ji turi pašalinti failą iš bendrinamo aplanko.",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "Išorinė komanda apdoroja versijų valdymą. Ji turi pašalinti failą iš sinchronizuoto aplanko.",
|
||||
"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?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "Visi supažindintojo įrenginiai bus pridėti prie jūsų įrenginių sąrašo.",
|
||||
"Are you sure you want to remove device {%name%}?": "Ar tikrai norite pašalinti įrenginį {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Ar tikrai norite pašalinti aplanką {{label}}?",
|
||||
"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",
|
||||
"Be careful!": "Būkite atsargūs!",
|
||||
@@ -53,6 +56,7 @@
|
||||
"Device Identification": "Įrenginio identifikacija",
|
||||
"Device Name": "Įrenginio pavadinimas",
|
||||
"Devices": "Įrenginiai",
|
||||
"Disabled": "Išjungta",
|
||||
"Disconnected": "Atsijungęs",
|
||||
"Discovered": "Atrastas",
|
||||
"Discovery": "Lokacija",
|
||||
@@ -84,6 +88,7 @@
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Programai Syncthing pakeičiant ar ištrinant failus, jie yra perkeliami į datomis pažymėtas versijas, kataloge .stversions.",
|
||||
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Programai Syncthing pakeičiant ar ištrinant failus, jie yra perkeliami į datomis pažymėtas versijas, aplanke .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.": "Failai yra apsaugoti nuo kituose įrenginiuose atliktų pakeitimų, bet pakeitimai šiame įrenginyje bus nusiųsti kitiems įrenginiams.",
|
||||
"Filesystem Notifications": "Failų sistemos pranešimai",
|
||||
"Folder": "Aplankas",
|
||||
"Folder ID": "Aplanko ID",
|
||||
"Folder Label": "Aplanko etiketė",
|
||||
@@ -136,6 +141,7 @@
|
||||
"Newest First": "Naujausi pirmiau",
|
||||
"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ų",
|
||||
"Normal": "Normalus",
|
||||
"Notice": "Įspėjimas",
|
||||
@@ -165,11 +171,14 @@
|
||||
"Quick guide to supported patterns": "Trumpas leistinų šablonų vadovas",
|
||||
"RAM Utilization": "Atminties naudojimas",
|
||||
"Random": "Atsitiktinė",
|
||||
"Recent Changes": "Paskiausi keitimai",
|
||||
"Reduced by ignore patterns": "Sumažinta pagal nepaisomus šablonus",
|
||||
"Release Notes": "Laidos Informacija",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Kandidatinėse versijose yra naujausios ypatybės ir pataisymai. Šios versijos yra panašios į tradicines, du kartus per mėnesį išleidžiamas Syncthing versijas.",
|
||||
"Remote Devices": "Nuotoliniai įrenginiai",
|
||||
"Remove": "Pašalinti",
|
||||
"Remove Device": "Šalinti įrenginį",
|
||||
"Remove Folder": "Šalinti aplanką",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "Reikalaujamas aplanko identifikatorius. Privalo būti toks pats visuose įrenginiuose.",
|
||||
"Rescan": "Nuskaityti iš naujo",
|
||||
"Rescan All": "Nuskaityti visus aplankus",
|
||||
@@ -183,7 +192,9 @@
|
||||
"Save": "Išsaugoti",
|
||||
"Scan Time Remaining": "Likęs nuskaitymo laikas",
|
||||
"Scanning": "Skenuojama",
|
||||
"See external versioner help for supported templated command line parameters.": "Palaikomiems šabloniniams komandų eilutės parametrams, žiūrėkite išorinį versijų valdymo žinyną.",
|
||||
"See external versioner help for supported templated command line parameters.": "Palaikomiems šabloniniams komandų eilutės parametrams, žiūrėkite išorinį versijų valdymo programos žinyną.",
|
||||
"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 a version": "Pasirinkti versiją",
|
||||
"Select the devices to share this folder with.": "Pasirinkite įrenginius, su kuriais dalinsitės šį aplanką.",
|
||||
"Select the folders to share with this device.": "Pasirinkite aplankus kuriais norite dalintis su šiuo įrenginiu.",
|
||||
"Send & Receive": "Siųsti ir gauti",
|
||||
@@ -197,6 +208,7 @@
|
||||
"Shared With": "Dalinamasi su",
|
||||
"Show ID": "Rodyti ID",
|
||||
"Show QR": "Rodyti QR",
|
||||
"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.",
|
||||
"Shutdown": "Išjungti",
|
||||
@@ -248,10 +260,11 @@
|
||||
"This Device": "Šis įrenginys",
|
||||
"This can easily give hackers access to read and change any files on your computer.": "Tai gali suteikti programišiams lengvą prieigą skaityti ir keisti bet kokius failus jūsų kompiuteryje.",
|
||||
"This is a major version upgrade.": "Tai yra stambus atnaujinimas.",
|
||||
"This setting controls the free space required on the home (i.e., index database) disk.": "Šis nustatymas valdo laisvą vietą, kuri yra reikalinga namų (t.y., rodyklės duomenų bazės) diske.",
|
||||
"This setting controls the free space required on the home (i.e., index database) disk.": "Šis nustatymas valdo laisvą vietą, kuri yra reikalinga namų (duomenų bazės) diske.",
|
||||
"Time": "Laikas",
|
||||
"Trash Can File Versioning": "Šiukšliadėžės versijų valdymas",
|
||||
"Type": "Tipas",
|
||||
"Undecided (will prompt)": "Nenuspręsta (bus klausiama)",
|
||||
"Unknown": "Nežinoma",
|
||||
"Unshared": "Nesidalinama",
|
||||
"Unused": "Nenaudojamas",
|
||||
|
||||
@@ -24,7 +24,10 @@
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "En ekstern kommando håndterer versjonkontrollen. Den må fjerne filen fra den delte mappa.",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "En ekstern kommando håndterer versjonkontrollen. Den må fjerne filen fra den synkroniserte mappa.",
|
||||
"Anonymous Usage Reporting": "Anonym innsamling av brukerdata",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "Det anonyme bruksrapportformatet har endret seg. Ønsker du å gå over til det nye formatet?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "Enheter satt opp på en introduksjonsenhet vil også bli lagt til denne enheten.",
|
||||
"Are you sure you want to remove device {%name%}?": "Er du sikker på at du ønsker å fjerne enheten {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Er du sikker på at du ønsker å fjerne mappen {{label}}?",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Automatisk oppgradering lar deg nå få valget mellom ferdige utgaver og utgivelseskandidater.",
|
||||
"Automatic upgrades": "Automatiske oppdateringer",
|
||||
"Be careful!": "Vær forsiktig!",
|
||||
@@ -53,6 +56,7 @@
|
||||
"Device Identification": "Enhetskjennemerke",
|
||||
"Device Name": "Navn på enhet",
|
||||
"Devices": "Enheter",
|
||||
"Disabled": "Avskrudd",
|
||||
"Disconnected": "Frakoblet",
|
||||
"Discovered": "Oppdaget",
|
||||
"Discovery": "Oppslag",
|
||||
@@ -84,6 +88,7 @@
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Filer flyttes til en datostemplet versjon i .stversions-mappa når den oppdateres eller slettes av Syncthing.",
|
||||
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Filer flyttes til en datostemplet versjon i .stversions-mappa når den oppdateres eller slettes av Syncthing.",
|
||||
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Filer er beskyttet mot endringer som er gjort på andre enheter, men endringer som er gjort på denne enheten blir sendt til resten av gruppen.",
|
||||
"Filesystem Notifications": "Filsystemvarsler ",
|
||||
"Folder": "Mappe",
|
||||
"Folder ID": "Mappe-ID",
|
||||
"Folder Label": "Merkelapp for mappe",
|
||||
@@ -110,7 +115,7 @@
|
||||
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Feilaktige innstillinger kan skade innholdet i dine delte mapper og hindre Syncthing i å fungere.",
|
||||
"Introduced By": "Introdusert av",
|
||||
"Introducer": "Introduktør",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "Invers av den gitte tilstanden (t.d. ikke ekskluder)",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "Invers av den gitte tilstanden (dvs. ekskluder ikke)",
|
||||
"Keep Versions": "Behold versjoner",
|
||||
"Largest First": "Største fil først",
|
||||
"Last File Received": "Sist mottatte fil",
|
||||
@@ -136,6 +141,7 @@
|
||||
"Newest First": "Den nyeste først",
|
||||
"No": "Nei",
|
||||
"No File Versioning": "Ingen versjonskontroll",
|
||||
"No files will be deleted as a result of this operation.": "Ingen filer vil bli slettet som følge av denne operasjonen.",
|
||||
"No upgrades": "Ingen oppgraderinger",
|
||||
"Normal": "Normal",
|
||||
"Notice": "Merknader",
|
||||
@@ -162,14 +168,17 @@
|
||||
"Prefix indicating that the pattern should be matched without case sensitivity": "Prefiks som indikerer at mønsteret skal samsvare uten versalsensitivitet",
|
||||
"Preview": "Forhåndsvisning",
|
||||
"Preview Usage Report": "Forhåndsvisning av datainnsamling",
|
||||
"Quick guide to supported patterns": "Kjapp innføring i godkjente mønster",
|
||||
"Quick guide to supported patterns": "Kjapp innføring i godkjente mønstre",
|
||||
"RAM Utilization": "RAM-utnyttelse",
|
||||
"Random": "Tilfeldig",
|
||||
"Recent Changes": "Nylige endringer",
|
||||
"Reduced by ignore patterns": "Reduser med utelatelsesmønster",
|
||||
"Release Notes": "Utgivelsesnotat",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Utgivelseskandidater inneholder de seneste problemfiksene og funksjonene. De ligner på de tradisjonelle Syncthing-utgivelsene som kom hver andre uke.",
|
||||
"Remote Devices": "Andre enheter",
|
||||
"Remove": "Fjern",
|
||||
"Remove Device": "Fjern enhet",
|
||||
"Remove Folder": "Fjern mappe",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "Påkrevd identifikator for mappa. Denne må være lik på alle enheter i samme klynge.",
|
||||
"Rescan": "Gjennomsøk på nytt",
|
||||
"Rescan All": "Gjennomsøk alt på nytt",
|
||||
@@ -184,6 +193,8 @@
|
||||
"Scan Time Remaining": "Gjenstående tid for gjennomsøking",
|
||||
"Scanning": "Gjennomsøker",
|
||||
"See external versioner help for supported templated command line parameters.": "Se ekstern versjoneringshjelp for støttede mal-baserte kommandolinjeparameter.",
|
||||
"See external versioning help for supported templated command line parameters.": "Se ekstern versjoneringshjelp for støttede mal-baserte kommandolinjeparameter.",
|
||||
"Select a version": "Velg en versjon",
|
||||
"Select the devices to share this folder with.": "Velg enhetene du vil dele denne mappen med.",
|
||||
"Select the folders to share with this device.": "Velg hvilke mapper som skal deles med denne enheten.",
|
||||
"Send & Receive": "Sende og motta",
|
||||
@@ -197,6 +208,7 @@
|
||||
"Shared With": "Delt med",
|
||||
"Show ID": "Vis ID",
|
||||
"Show QR": "Vis QR-kode",
|
||||
"Show diff with previous version": "Vis diff med forrige version",
|
||||
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Vis i stedet for enhets-ID i gruppestatus. Vil bli kringkastet til andre enheter som et valgfritt forvalgsnavn.",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Vist i stedet for mappe-ID i gruppestatus. Vil bli oppdatert til navnet enheten kringkaster dersom tomt.",
|
||||
"Shutdown": "Avslutt",
|
||||
@@ -252,6 +264,7 @@
|
||||
"Time": "Klokkeslett",
|
||||
"Trash Can File Versioning": "Papirkurv versjonskontroll",
|
||||
"Type": "Type",
|
||||
"Undecided (will prompt)": "Ikke bestemt (vil spørre)",
|
||||
"Unknown": "Ukjent",
|
||||
"Unshared": "Ikke delt",
|
||||
"Unused": "Ikke i bruk",
|
||||
|
||||
@@ -24,7 +24,10 @@
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "Een extern commando regelt het versiebeheer. Dit moet het bestand verwijderen van de gedeelde map.",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "Een extern commando regelt het versiebeheer. Dit moet het bestand verwijderen van de gesynchroniseerde map.",
|
||||
"Anonymous Usage Reporting": "Anonieme gebruikersstatistieken",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "Het formaat voor anonieme gebruikersrapporten is gewijzigd. Wil je naar het nieuwe formaat overschakelen?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "Apparaten die geconfigureerd worden op een introductieapparaat zullen ook aan dit apparaat worden toegevoegd.",
|
||||
"Are you sure you want to remove device {%name%}?": "Weet je zeker dat je apparaat {{name}} wil verwijderen?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Weet je zeker dat je map {{label}} wil verwijderen?",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Automatisch bijwerken biedt nu de keuze tussen stabiele uitgaven en uitgavekandidaten.",
|
||||
"Automatic upgrades": "Automatische upgrades",
|
||||
"Be careful!": "Wees voorzichtig!",
|
||||
@@ -43,7 +46,7 @@
|
||||
"Copied from elsewhere": "Gekopieerd vanaf elders",
|
||||
"Copied from original": "Gekopieerd van het origineel",
|
||||
"Copyright © 2014-2016 the following Contributors:": "Copyright © 2014-2016 voor de volgende bijdragers:",
|
||||
"Copyright © 2014-2017 the following Contributors:": "Copyright © 2014-2017 de volgende bijdragers:",
|
||||
"Copyright © 2014-2017 the following Contributors:": "Copyright © 2014-2017 voor de volgende bijdragers:",
|
||||
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Negeerpatronen worden aangemaakt, bestaand bestand wordt overschreven op {{path}}.",
|
||||
"Danger!": "Let op!",
|
||||
"Deleted": "Verwijderd",
|
||||
@@ -53,6 +56,7 @@
|
||||
"Device Identification": "Apparaat-identificatie",
|
||||
"Device Name": "Naam apparaat",
|
||||
"Devices": "Apparaten",
|
||||
"Disabled": "Uitgeschakeld",
|
||||
"Disconnected": "Niet verbonden",
|
||||
"Discovered": "Ontdekt",
|
||||
"Discovery": "Ontdekken",
|
||||
@@ -84,6 +88,7 @@
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Bestanden worden niet door Syncthing vervangen of verwijderd, maar verplaatst naar de map .stversions.",
|
||||
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Bestanden worden niet door Syncthing vervangen of verwijderd, maar verplaatst naar de map .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.": "Bestanden zijn beschermt tegen aanpassingen die gemaakt zijn door andere apparaten, maar aanpassingen op dit apparaat worden doorgestuurd naar de rest van het cluster.",
|
||||
"Filesystem Notifications": "Bestandssysteemmeldingen",
|
||||
"Folder": "Map",
|
||||
"Folder ID": "Map-ID",
|
||||
"Folder Label": "Map label",
|
||||
@@ -136,6 +141,7 @@
|
||||
"Newest First": "Nieuwste eerst",
|
||||
"No": "Nee",
|
||||
"No File Versioning": "Geen versiebeheer",
|
||||
"No files will be deleted as a result of this operation.": "Deze handeling zal geen bestanden verwijderen.",
|
||||
"No upgrades": "Geen upgrades",
|
||||
"Normal": "Normaal",
|
||||
"Notice": "Mededeling",
|
||||
@@ -165,11 +171,14 @@
|
||||
"Quick guide to supported patterns": "Snelgids voor ondersteunde patronen",
|
||||
"RAM Utilization": "Geheugengebruik",
|
||||
"Random": "Willekeurig",
|
||||
"Recent Changes": "Recente wijzigingen",
|
||||
"Reduced by ignore patterns": "Verminderd door negeerpatronen",
|
||||
"Release Notes": "Release notes",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Uitgavekandidaten bevatten de laatste nieuwe functionaliteit en oplossingen voor problemen. Ze lijken op de traditionele, tweemaal per week, Syncthing-uitgaven.",
|
||||
"Remote Devices": "Externe apparaten",
|
||||
"Remove": "Verwijderen",
|
||||
"Remove Device": "Apparaat verwijderen",
|
||||
"Remove Folder": "Map verwijderen",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "De identifier voor de map is verplicht. Dit moet hetzelfde zijn op alle apparaten in het cluster. ",
|
||||
"Rescan": "Opnieuw scannen",
|
||||
"Rescan All": "Scan alles opnieuw",
|
||||
@@ -183,7 +192,9 @@
|
||||
"Save": "Bewaar",
|
||||
"Scan Time Remaining": "Resterende scantijd",
|
||||
"Scanning": "Aan het zoeken",
|
||||
"See external versioner help for supported templated command line parameters.": "See external versioner help for supported templated command line parameters.",
|
||||
"See external versioner help for supported templated command line parameters.": "Zie de documentatie van de externe versie voor ondersteunde command line parameters.",
|
||||
"See external versioning help for supported templated command line parameters.": "Bekijk de documentatie van het extern versiebeheer voor ondersteunde opdrachtregelparameters.",
|
||||
"Select a version": "Selecteer een versie",
|
||||
"Select the devices to share this folder with.": "Selecteer de apparaten om deze map mee te delen.",
|
||||
"Select the folders to share with this device.": "Selecteer de mappen om met dit apparaat te delen.",
|
||||
"Send & Receive": "Verzenden & Ontvangen",
|
||||
@@ -197,6 +208,7 @@
|
||||
"Shared With": "Gedeeld met",
|
||||
"Show ID": "Toon ID",
|
||||
"Show QR": "QR tonen",
|
||||
"Show diff with previous version": "Verschil met vorige versie tonen",
|
||||
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Wordt i.p.v. het apparaat-ID getoond in de clusterstatus. Deze naam wordt aan andere apparaten voorgesteld als optionele standaard naam.",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Wordt in plaats van het apparaat-ID in de cluster status getoond. Zal geupdate worden naar de naam die het apparaat uitzend. ",
|
||||
"Shutdown": "Sluit af",
|
||||
@@ -252,6 +264,7 @@
|
||||
"Time": "Tijd",
|
||||
"Trash Can File Versioning": "Versiebeheer bestanden prullenbak",
|
||||
"Type": "Type",
|
||||
"Undecided (will prompt)": "Onbeslist (bevestiging vragen)",
|
||||
"Unknown": "Onbekend",
|
||||
"Unshared": "Niet gedeeld",
|
||||
"Unused": "Ongebruikt",
|
||||
|
||||
@@ -24,7 +24,10 @@
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "An external command handles the versioning. It has to remove the file from the shared folder.",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "Ein ekstern kommando handterer filutgåver. Den må sørga for at fila blir fjerna frå den synkroniserte mappa.",
|
||||
"Anonymous Usage Reporting": "Anonymisert bruksrapportering",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "Anonymous usage report format has changed. Would you like to move to the new format?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "Einingar konfigurert på ei introduksjonseining vil òg verta lagt til denne eininga.",
|
||||
"Are you sure you want to remove device {%name%}?": "Are you sure you want to remove device {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Are you sure you want to remove folder {{label}}?",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Automatic upgrade now offers the choice between stable releases and release candidates.",
|
||||
"Automatic upgrades": "Automatiske oppdateringar",
|
||||
"Be careful!": "Ver varsam!",
|
||||
@@ -53,6 +56,7 @@
|
||||
"Device Identification": "Einingskjennemerke",
|
||||
"Device Name": "Namn På Eining",
|
||||
"Devices": "Einingar",
|
||||
"Disabled": "Disabled",
|
||||
"Disconnected": "Fråkopla",
|
||||
"Discovered": "Oppdaga",
|
||||
"Discovery": "Oppdaging",
|
||||
@@ -84,6 +88,7 @@
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.",
|
||||
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Filer som Syncthing oppdaterer eller slettar vert flytta til ein datostempla versjon i .stversions-katalogen.",
|
||||
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Filer er beskytta mot endringar gjort på andre einingar, men endringar gjort på denne eininga vert sende til resten av klyngja.",
|
||||
"Filesystem Notifications": "Filesystem Notifications",
|
||||
"Folder": "Mappe",
|
||||
"Folder ID": "Mappe ID",
|
||||
"Folder Label": "Merkelapp for mappa",
|
||||
@@ -136,6 +141,7 @@
|
||||
"Newest First": "Nyaste fyrst",
|
||||
"No": "Nei",
|
||||
"No File Versioning": "Inga filutgåvehandtering",
|
||||
"No files will be deleted as a result of this operation.": "No files will be deleted as a result of this operation.",
|
||||
"No upgrades": "No upgrades",
|
||||
"Normal": "Normal",
|
||||
"Notice": "Merknad",
|
||||
@@ -165,11 +171,14 @@
|
||||
"Quick guide to supported patterns": "Kjapp innføring i godkjente mønster",
|
||||
"RAM Utilization": "Minnebruk",
|
||||
"Random": "Tilfeldig",
|
||||
"Recent Changes": "Recent Changes",
|
||||
"Reduced by ignore patterns": "Reduser med utelatelsesmønster",
|
||||
"Release Notes": "Utgjevingsnotat",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.",
|
||||
"Remote Devices": "Eksterne einingar",
|
||||
"Remove": "Fjern",
|
||||
"Remove Device": "Remove Device",
|
||||
"Remove Folder": "Remove Folder",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "Påkravd identifikator for katalogen. Denne må vera lik på alle einingane i same klynge.",
|
||||
"Rescan": "Skann På Ny",
|
||||
"Rescan All": "Skann alle på nytt",
|
||||
@@ -184,6 +193,8 @@
|
||||
"Scan Time Remaining": "Gjenståande skannetid",
|
||||
"Scanning": "Skannar",
|
||||
"See external versioner help for supported templated command line parameters.": "See external versioner help for supported templated command line parameters.",
|
||||
"See external versioning help for supported templated command line parameters.": "See external versioning help for supported templated command line parameters.",
|
||||
"Select a version": "Select a version",
|
||||
"Select the devices to share this folder with.": "Vel einingane du vil dela denne mappa med.",
|
||||
"Select the folders to share with this device.": "Vel mappene du vil dela med denne eininga.",
|
||||
"Send & Receive": "Sende og motta",
|
||||
@@ -197,6 +208,7 @@
|
||||
"Shared With": "Delt Med",
|
||||
"Show ID": "Vis ID",
|
||||
"Show QR": "Vis QR",
|
||||
"Show diff with previous version": "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.": "Vist i staden for einings-ID-en i klyngjestatusen. Vil verta kringkasta til dei andre einingane som eit valfritt standardnamn.",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Vist i staden for mappe-ID-en i klyngjestatuses. Vil verta oppdatert til namnet eininga kringkastar dersom tomt.",
|
||||
"Shutdown": "Slå Av",
|
||||
@@ -252,6 +264,7 @@
|
||||
"Time": "Time",
|
||||
"Trash Can File Versioning": "Papirkorg-filutgåvehandtering",
|
||||
"Type": "Type",
|
||||
"Undecided (will prompt)": "Undecided (will prompt)",
|
||||
"Unknown": "Ukjent",
|
||||
"Unshared": "Ikkje delt",
|
||||
"Unused": "Ubrukt",
|
||||
|
||||
@@ -24,7 +24,10 @@
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "Zewnętrzna komenda odpowiedzialna za wersjonowanie. Musi usunąć plik ze współdzielonego folderu.",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "Zewnętrzna komenda odpowiedzialna za wersjonowanie. Musi usuwać ten plik z synchronizowanego folderu.",
|
||||
"Anonymous Usage Reporting": "Anonimowe statystyki użycia",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "Format anonimowego raportu zużycia uległ zmianie.\nCzy chcesz przejść na nowy format?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "Wszystkie urządzenia skonfigurowane na urządzeniu wprowadzającym zostaną dodane także do tego urządzenia.",
|
||||
"Are you sure you want to remove device {%name%}?": "Are you sure you want to remove device {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Are you sure you want to remove folder {{label}}?",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Automatyczne aktualizacje pozwalają teraz wybrać pomiędzy wydaniami stabilnymi a wersjami kandydującymi.",
|
||||
"Automatic upgrades": "Automatyczne aktualizacje",
|
||||
"Be careful!": "Uważaj!",
|
||||
@@ -53,6 +56,7 @@
|
||||
"Device Identification": "Identyfikator urządzenia",
|
||||
"Device Name": "Nazwa urządzenia",
|
||||
"Devices": "Urządzenia",
|
||||
"Disabled": "Wyłączone",
|
||||
"Disconnected": "Rozłączony",
|
||||
"Discovered": "Odkryte",
|
||||
"Discovery": "Odnajdywanie",
|
||||
@@ -84,6 +88,7 @@
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Pliki są datowane i przenoszone do folderu .stversions przez Syncthing, kiedy zostaną zmienione lub usunięte.",
|
||||
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Pliki przenoszone są do wersji oznaczonych datą w folderze .stversions kiedy są zastępowane bądź usuwane przez Syncthing",
|
||||
"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 na innym urządzeniu, jednak zmiany w tym urządzeniu będą wysłane do reszty.",
|
||||
"Filesystem Notifications": "Powiadomienia systemowe",
|
||||
"Folder": "Folder",
|
||||
"Folder ID": "ID folderu",
|
||||
"Folder Label": "Etykieta folderu",
|
||||
@@ -136,6 +141,7 @@
|
||||
"Newest First": "Najnowsze na początku",
|
||||
"No": "Nie",
|
||||
"No File Versioning": "Bez wersjonowania pliku",
|
||||
"No files will be deleted as a result of this operation.": "No files will be deleted as a result of this operation.",
|
||||
"No upgrades": "Brak aktualizacji",
|
||||
"Normal": "Zwykły",
|
||||
"Notice": "Wskazówka",
|
||||
@@ -165,11 +171,14 @@
|
||||
"Quick guide to supported patterns": "Krótki przewodnik po obsługiwanych wzorcach",
|
||||
"RAM Utilization": "Użycie pamięci RAM",
|
||||
"Random": "Losowo",
|
||||
"Recent Changes": "Ostatnie zmiany",
|
||||
"Reduced by ignore patterns": "Ograniczono przez wzorce ignorowania",
|
||||
"Release Notes": "Informacje o wydaniu",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Wydania kandydujące zawierają najnowsze funkcje oraz poprawki błędów. Są one podobne do tradycyjnych co dwutygodniowych wydań Syncthing.",
|
||||
"Remote Devices": "Urządzenia zdalne",
|
||||
"Remove": "Usuń",
|
||||
"Remove Device": "Remove Device",
|
||||
"Remove Folder": "Remove Folder",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "Wymagany identyfikator dla folderu. Musi być taki sam na wszystkich urządzeniach.",
|
||||
"Rescan": "Skanuj ponownie",
|
||||
"Rescan All": "Skanuj wszystko ponownie",
|
||||
@@ -183,7 +192,9 @@
|
||||
"Save": "Zapisz",
|
||||
"Scan Time Remaining": "Pozostały czas skanowania",
|
||||
"Scanning": "Skanowanie",
|
||||
"See external versioner help for supported templated command line parameters.": "See external versioner help for supported templated command line parameters.",
|
||||
"See external versioner help for supported templated command line parameters.": "Dostępne zmienne dla polecenia opisane są w dokumentacji w sekcji Zewnętrzne wersjonowanie plików.",
|
||||
"See external versioning help for supported templated command line parameters.": "Dostępne zmienne dla polecenia opisane są w dokumentacji w sekcji Zewnętrzne wersjonowanie plików.",
|
||||
"Select a version": "Wybierz wersję",
|
||||
"Select the devices to share this folder with.": "Wybierz urządzenie, któremu udostępnić folder.",
|
||||
"Select the folders to share with this device.": "Wybierz foldery do współdzielenia z tym urządzeniem.",
|
||||
"Send & Receive": "Wyślij i odbierz",
|
||||
@@ -197,6 +208,7 @@
|
||||
"Shared With": "Współdzielony z",
|
||||
"Show ID": "Pokaż ID",
|
||||
"Show QR": "Pokaż kod QR",
|
||||
"Show diff with previous version": "Pokaż różnice z poprzednią wersją",
|
||||
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Pokazane w statusie zamiast ID urządzenia.Zostanie wysłane do innych urządzeń jako opcjonalna domyślna nazwa.",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Pokazane w statusie zamiast ID urządzenia. Zostanie zaktualizowane do nazwy urządzenia jeżeli pozostanie puste.",
|
||||
"Shutdown": "Wyłącz",
|
||||
@@ -252,6 +264,7 @@
|
||||
"Time": "Czas",
|
||||
"Trash Can File Versioning": "Kontrola werjsi plików w koszu",
|
||||
"Type": "Typ",
|
||||
"Undecided (will prompt)": "Jeszcze nie zdecydowałem (przypomnij później)",
|
||||
"Unknown": "Nieznany",
|
||||
"Unshared": "Nieudostępnione",
|
||||
"Unused": "Nieużywane",
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"A device with that ID is already added.": "Um dispositivo com este ID já foi adicionado.",
|
||||
"A device with that ID is already added.": "Um dispositivo com esta ID já foi adicionado.",
|
||||
"A negative number of days doesn't make sense.": "Um número negativo de dias não faz sentido.",
|
||||
"A new major version may not be compatible with previous versions.": "Uma nova versão principal pode não ser compatível com versões anteriores.",
|
||||
"API Key": "Chave da API",
|
||||
@@ -24,7 +24,10 @@
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "Um comando externo cuida do versionamento. Ele tem que remover o arquivo da pasta compartilhada.",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "Um programa externo controla o versionamento. Ele tem que remover o arquivo da pasta sincronizada.",
|
||||
"Anonymous Usage Reporting": "Relatórios anônimos de uso",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "O formato do relatório anônimo de uso mudou. Gostaria de usar o formato novo?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "Quaisquer dispositivos configurados em um apresentador também serão adicionados a este dispositivo.",
|
||||
"Are you sure you want to remove device {%name%}?": "Are you sure you want to remove device {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Are you sure you want to remove folder {{label}}?",
|
||||
"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 ao lançamento.",
|
||||
"Automatic upgrades": "Atualizações automáticas",
|
||||
"Be careful!": "Tenha cuidado!",
|
||||
@@ -53,6 +56,7 @@
|
||||
"Device Identification": "Identificação do dispositivo",
|
||||
"Device Name": "Nome do dispositivo",
|
||||
"Devices": "Dispositivos",
|
||||
"Disabled": "Desabilitado",
|
||||
"Disconnected": "Desconectado",
|
||||
"Discovered": "Descoberto",
|
||||
"Discovery": "Descoberta",
|
||||
@@ -84,6 +88,7 @@
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Os arquivos são renomeados com suas datas e movidos para o diretório .stversions quando substituídos ou apagados pelo Syncthing.",
|
||||
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Os arquivos são renomeados com suas datas na pasta .stversions quando substituídos ou removidos pelo Syncthing.",
|
||||
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Os arquivos estão protegidos contra alterações feitas em outros dispositivos, mas alterações feitas neste dispositivo serão enviadas ao resto dos dispositivos.",
|
||||
"Filesystem Notifications": "Notificação do Sistema de Arquivos",
|
||||
"Folder": "Pasta",
|
||||
"Folder ID": "ID da pasta",
|
||||
"Folder Label": "Rótulo da pasta",
|
||||
@@ -136,6 +141,7 @@
|
||||
"Newest First": "Mais novo primeiro",
|
||||
"No": "Não",
|
||||
"No File Versioning": "Desligado",
|
||||
"No files will be deleted as a result of this operation.": "No files will be deleted as a result of this operation.",
|
||||
"No upgrades": "Sem atualizações",
|
||||
"Normal": "Normal",
|
||||
"Notice": "Aviso",
|
||||
@@ -158,18 +164,21 @@
|
||||
"Please consult the release notes before performing a major upgrade.": "Por favor, consulte as notas de lançamento antes de atualizar para uma versão \"major\".",
|
||||
"Please set a GUI Authentication User and Password in the Settings dialog.": "Por favor, defina um nome de usuário e senha para acesso à interface web, nas configurações.",
|
||||
"Please wait": "Aguarde",
|
||||
"Prefix indicating that the file can be deleted if preventing directory removal": "Prefix indicating that the file can be deleted if preventing directory removal",
|
||||
"Prefix indicating that the pattern should be matched without case sensitivity": "Prefix indicating that the pattern should be matched without case sensitivity",
|
||||
"Prefix indicating that the file can be deleted if preventing directory removal": "Prefixo indicando que o arquivo pode ser removido caso esteja impedindo a remoção do seu diretório",
|
||||
"Prefix indicating that the pattern should be matched without case sensitivity": "Prefixo indicando que o filtro deve ser igualado sem distinção entre maiúsculas e minúsculas",
|
||||
"Preview": "Visualizar",
|
||||
"Preview Usage Report": "Visualizar relatório de uso",
|
||||
"Quick guide to supported patterns": "Guia rápido dos padrões suportados",
|
||||
"RAM Utilization": "Uso de RAM",
|
||||
"Random": "Aleatória",
|
||||
"Recent Changes": "Mudanças Recentes",
|
||||
"Reduced by ignore patterns": "Reduzido por filtros",
|
||||
"Release Notes": "Notas de lançamento",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Versões candidatas ao lançamento possuem os recursos e correções mais recentes. Elas são similares às tradicionais versões quinzenais.",
|
||||
"Remote Devices": "Dispositivos remotos",
|
||||
"Remove": "Remover",
|
||||
"Remove Device": "Remove Device",
|
||||
"Remove Folder": "Remover pasta",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "Identificador obrigatório da pasta. Deve ser igual em todos os dispositivos do grupo.",
|
||||
"Rescan": "Verificar agora",
|
||||
"Rescan All": "Verificar todas",
|
||||
@@ -183,7 +192,9 @@
|
||||
"Save": "Salvar",
|
||||
"Scan Time Remaining": "Tempo de verificação restante",
|
||||
"Scanning": "Verificando",
|
||||
"See external versioner help for supported templated command line parameters.": "See external versioner help for supported templated command line parameters.",
|
||||
"See external versioner help for supported templated command line parameters.": "Consulte a ajuda sobre versionamento externo para modelos de parâmetros de linha de comando aceitos.",
|
||||
"See external versioning help for supported templated command line parameters.": "Consulte a ajuda sobre versionamento externo para modelos de parâmetros de linha de comando aceitos.",
|
||||
"Select a version": "Selecione uma versão",
|
||||
"Select the devices to share this folder with.": "Selecione os dispositivos com os quais esta pasta será compartilhada.",
|
||||
"Select the folders to share with this device.": "Selecione as pastas a serem compartilhadas com este dispositivo.",
|
||||
"Send & Receive": "Envia e recebe",
|
||||
@@ -197,6 +208,7 @@
|
||||
"Shared With": "Compartilhada com",
|
||||
"Show ID": "Mostrar ID",
|
||||
"Show QR": "Mostrar QR Code",
|
||||
"Show diff with previous version": "Mostrar diferenças da versão anterior",
|
||||
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Mostrado no lugar do ID do dispositivo no indicador de estado do grupo. Será divulgado aos outros dispositivos como um nome opcional e pré-definido.",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Mostrado no lugar do ID do dispositivo no indicador de estado do grupo. Será atualizado para o nome que o dispositivo divulga, caso seja deixado em branco.",
|
||||
"Shutdown": "Desligar",
|
||||
@@ -248,10 +260,11 @@
|
||||
"This Device": "Este dispositivo",
|
||||
"This can easily give hackers access to read and change any files on your computer.": "Isto pode dar a hackers poder de leitura e escrita de qualquer arquivo em seu dispositivo.",
|
||||
"This is a major version upgrade.": "Esta é uma atualização para uma versão \"major\".",
|
||||
"This setting controls the free space required on the home (i.e., index database) disk.": "This setting controls the free space required on the home (i.e., index database) disk.",
|
||||
"This setting controls the free space required on the home (i.e., index database) disk.": "Este ajuste controla o espaço livre necessário no disco que contém o banco de dados do Syncthing.",
|
||||
"Time": "Hora",
|
||||
"Trash Can File Versioning": "Lixeira",
|
||||
"Type": "Tipo",
|
||||
"Undecided (will prompt)": "Não tenho certeza (perguntar sempre)",
|
||||
"Unknown": "Desconhecida",
|
||||
"Unshared": "Não compartilhada",
|
||||
"Unused": "Não utilizado",
|
||||
|
||||
@@ -24,7 +24,10 @@
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "Um comando externo controla as versões. Esse comando tem que remover o ficheiro da pasta partilhada.",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "Um comando externo trata do controle de versões. Esse comando tem que remover o ficheiro da pasta sincronizada.",
|
||||
"Anonymous Usage Reporting": "Enviar relatórios anónimos de utilização",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "O formato do relatório anónimo de utilização foi alterado. Gostaria de mudar para o novo formato?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "Quaisquer dispositivos configurados num dispositivo apresentador serão também adicionados a este dispositivo.",
|
||||
"Are you sure you want to remove device {%name%}?": "Tem a certeza que quer remover o dispositivo {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Tem a certeza que quer remover a pasta {{label}}?",
|
||||
"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",
|
||||
"Be careful!": "Tenha cuidado!",
|
||||
@@ -53,6 +56,7 @@
|
||||
"Device Identification": "Identificação do dispositivo",
|
||||
"Device Name": "Nome do dispositivo",
|
||||
"Devices": "Dispositivos",
|
||||
"Disabled": "Desactivado",
|
||||
"Disconnected": "Desconectado",
|
||||
"Discovered": "Descoberto",
|
||||
"Discovery": "Pesquisa",
|
||||
@@ -84,6 +88,7 @@
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Os ficheiros são movidos para versões marcadas com data e hora numa pasta .stversions, ao serem substituídos ou eliminados pelo Syncthing.",
|
||||
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Os ficheiros são movidos para versões carimbadas com o tempo numa pasta .stversions, ao serem substituídos ou apagados pelo Syncthing.",
|
||||
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Os ficheiros estão protegidos contra alterações feitas noutros dispositivos, mas alterações feitas neste dispositivo serão enviadas ao resto do grupo.",
|
||||
"Filesystem Notifications": "Notificações do sistema de ficheiros",
|
||||
"Folder": "Pasta",
|
||||
"Folder ID": "ID da pasta",
|
||||
"Folder Label": "Etiqueta da pasta",
|
||||
@@ -136,6 +141,7 @@
|
||||
"Newest First": "Primeiro os mais recentes",
|
||||
"No": "Não",
|
||||
"No File Versioning": "Nenhuma",
|
||||
"No files will be deleted as a result of this operation.": "Nenhum ficheiro será eliminado como resultado desta operação.",
|
||||
"No upgrades": "Sem actualizações",
|
||||
"Normal": "Normal",
|
||||
"Notice": "Avisos",
|
||||
@@ -165,11 +171,14 @@
|
||||
"Quick guide to supported patterns": "Guia rápido dos padrões suportados",
|
||||
"RAM Utilization": "Utilização da RAM",
|
||||
"Random": "Aleatória",
|
||||
"Recent Changes": "Alterações recentes",
|
||||
"Reduced by ignore patterns": "Reduzido por padrões de exclusão",
|
||||
"Release Notes": "Notas de lançamento",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Versões candidatas a lançamento contêm as funcionalidades e as correcções mais recentes. São semelhantes aos tradicionais lançamentos bi-semanais do Syncthing.",
|
||||
"Remote Devices": "Dispositivos remotos",
|
||||
"Remove": "Remover",
|
||||
"Remove Device": "Remover dispositivo",
|
||||
"Remove Folder": "Remover pasta",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "Identificador obrigatório para a pasta. Tem que ser igual em todos os dispositivos do grupo.",
|
||||
"Rescan": "Verificar agora",
|
||||
"Rescan All": "Verificar todas agora",
|
||||
@@ -184,6 +193,8 @@
|
||||
"Scan Time Remaining": "Tempo restante da verificação",
|
||||
"Scanning": "Verificando",
|
||||
"See external versioner help for supported templated command line parameters.": "Veja a ajuda do gestor de versões externo para saber que parâmetros da linha de comandos são suportados.",
|
||||
"See external versioning help for supported templated command line parameters.": "Veja a ajuda externa sobre gestão de versões para ver os modelos suportados de parâmetros para a linha de comandos.",
|
||||
"Select a version": "Seleccione uma versão",
|
||||
"Select the devices to share this folder with.": "Seleccione os dispositivos com os quais vai partilhar esta pasta.",
|
||||
"Select the folders to share with this device.": "Seleccione as pastas a partilhar com este dispositivo.",
|
||||
"Send & Receive": "Envia e recebe",
|
||||
@@ -197,6 +208,7 @@
|
||||
"Shared With": "Partilhada com",
|
||||
"Show ID": "Mostrar ID",
|
||||
"Show QR": "Mostrar QR",
|
||||
"Show diff with previous version": "Mostrar diferenças em relação à versão anterior",
|
||||
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Apresentado ao invés do ID do dispositivo no indicador de estado do grupo. Será divulgado aos outros dispositivos como um nome predefinido opcional.",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Apresentado ao invés do ID do dispositivo no indicador de estado do grupo. Será actualizado para o nome que o dispositivo divulga, se for deixado em branco.",
|
||||
"Shutdown": "Desligar",
|
||||
@@ -252,6 +264,7 @@
|
||||
"Time": "Quando",
|
||||
"Trash Can File Versioning": "Reciclagem",
|
||||
"Type": "Tipo",
|
||||
"Undecided (will prompt)": "Não definido (será inquirido na altura)",
|
||||
"Unknown": "Desconhecido",
|
||||
"Unshared": "Não partilhada",
|
||||
"Unused": "Não utilizado",
|
||||
|
||||
@@ -24,7 +24,10 @@
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "Для версионирования используется внешняя программа. Ей нужно удалить файл из общей папки.",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "Внешний процесс управляет версиями файлов. Процесс удалит файл из синхронизируемой папки.",
|
||||
"Anonymous Usage Reporting": "Анонимный отчет об использовании",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "Формат анонимных отчётов изменился. Вы хотите переключиться на новый формат?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "Все устройства, подключённые к устройству-рекомендателю, будут добавлены к текущему устройству.",
|
||||
"Are you sure you want to remove device {%name%}?": "Are you sure you want to remove device {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Are you sure you want to remove folder {{label}}?",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Автоматическое обновление теперь предлагает выбор между стабильными выпусками и кандидатами в релизы.",
|
||||
"Automatic upgrades": "Автообновление",
|
||||
"Be careful!": "Будьте осторожны!",
|
||||
@@ -32,7 +35,7 @@
|
||||
"CPU Utilization": "Загрузка ЦП",
|
||||
"Changelog": "Журнал изменений",
|
||||
"Clean out after": "Очистить после",
|
||||
"Click to see discovery failures": "Click to see discovery failures",
|
||||
"Click to see discovery failures": "Щёлкните, чтобы посмотреть ошибки",
|
||||
"Close": "Закрыть",
|
||||
"Command": "Команда",
|
||||
"Comment, when used at the start of a line": "Комментарий, если используется в начале строки",
|
||||
@@ -53,6 +56,7 @@
|
||||
"Device Identification": "Идентификация устройства",
|
||||
"Device Name": "Имя устройства",
|
||||
"Devices": "Устройства",
|
||||
"Disabled": "Отключено",
|
||||
"Disconnected": "Нет соединения",
|
||||
"Discovered": "Обнаружено",
|
||||
"Discovery": "Обнаружение",
|
||||
@@ -84,6 +88,7 @@
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Когда Syncthing изменяет или удаляет файлы, их версии с таймштампами помещаются в папку .stversions",
|
||||
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Файлы с временнОй меткой версии помещаются в папку .stversions при их замене или удалении Syncthing.",
|
||||
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Файлы защищены от изменений сделанных на других устройствах, но изменения сделанные на этом устройстве будут отправлены всему кластеру.",
|
||||
"Filesystem Notifications": "Уведомления файловой системы",
|
||||
"Folder": "Папка",
|
||||
"Folder ID": "ID папки",
|
||||
"Folder Label": "Ярлык папки",
|
||||
@@ -136,6 +141,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 upgrades": "Нет обновлений",
|
||||
"Normal": "Нормально",
|
||||
"Notice": "Внимание",
|
||||
@@ -165,11 +171,14 @@
|
||||
"Quick guide to supported patterns": "Краткое руководство по поддерживаемым шаблонам",
|
||||
"RAM Utilization": "Использование памяти",
|
||||
"Random": "Случайно",
|
||||
"Recent Changes": "Recent Changes",
|
||||
"Reduced by ignore patterns": "Уменьшено шаблонами игнорирования",
|
||||
"Release Notes": "Примечания к выпуску",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Кандидаты в релизы содержат последние улучшения и исправления. Они похожи на традиционные двухнедельные выпуски Syncthing.",
|
||||
"Remote Devices": "Удалённые устройства",
|
||||
"Remove": "Удалить",
|
||||
"Remove Device": "Remove Device",
|
||||
"Remove Folder": "Remove Folder",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "Обязательный идентификатор папки. Должен быть одним и тем же на всех устройствах кластера.",
|
||||
"Rescan": "Пересканировать",
|
||||
"Rescan All": "Пересканировать все",
|
||||
@@ -184,6 +193,8 @@
|
||||
"Scan Time Remaining": "Оставшееся время сканирования",
|
||||
"Scanning": "Сканирование",
|
||||
"See external versioner help for supported templated command line parameters.": "See external versioner help for supported templated command line parameters.",
|
||||
"See external versioning help for supported templated command line parameters.": "See external versioning help for supported templated command line parameters.",
|
||||
"Select a version": "Выберите версию",
|
||||
"Select the devices to share this folder with.": "Выберите устройства, для которых будет доступна эта папка.",
|
||||
"Select the folders to share with this device.": "Выберите папки, которые будут доступны этому устройству.",
|
||||
"Send & Receive": "Отправить и получить",
|
||||
@@ -197,6 +208,7 @@
|
||||
"Shared With": "Доступ предоставлен",
|
||||
"Show ID": "Показать ID",
|
||||
"Show QR": "Показать QR-код",
|
||||
"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.": "Отображается вместо ID устройства в статусе группы. Будет разослан другим устройствам в качестве имени по умолчанию.",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Отображается вместо ID устройства в статусе группы. Если поле не заполнено, то будет установлено имя, передаваемое этим устройством.",
|
||||
"Shutdown": "Выключить",
|
||||
@@ -252,6 +264,7 @@
|
||||
"Time": "Время",
|
||||
"Trash Can File Versioning": "Использовать версионность для файлов в Корзине",
|
||||
"Type": "Тип",
|
||||
"Undecided (will prompt)": "Undecided (will prompt)",
|
||||
"Unknown": "Неизвестно",
|
||||
"Unshared": "Необщедоступно",
|
||||
"Unused": "Не используется",
|
||||
|
||||
@@ -24,7 +24,10 @@
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "Externý príkaz obstaráva verzie. Musí odstrániť ",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "Verzie spravuje externý príkaz. Musí odstrániť súbor zo synchronizovaného adresára.",
|
||||
"Anonymous Usage Reporting": "Anonymné hlásenie o používaní",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "Anonymous usage report format has changed. Would you like to move to the new format?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "Všetky zariadenia nakonfigurované na uvádzači budú tiež pridané na tomto zariadení.",
|
||||
"Are you sure you want to remove device {%name%}?": "Are you sure you want to remove device {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Are you sure you want to remove folder {{label}}?",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Automatická aktualizácia teraz ponúka voľbu medzi stabilnými vydaniami a kandidátmi na vydanie.",
|
||||
"Automatic upgrades": "Automatické aktualizácie",
|
||||
"Be careful!": "Buď opatrný!",
|
||||
@@ -53,6 +56,7 @@
|
||||
"Device Identification": "Identifikácia zariadenia",
|
||||
"Device Name": "Názov zariadenia",
|
||||
"Devices": "Zariadenia",
|
||||
"Disabled": "Disabled",
|
||||
"Disconnected": "Odpojené",
|
||||
"Discovered": "Zistené",
|
||||
"Discovery": "Zisťovanie",
|
||||
@@ -84,6 +88,7 @@
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Súbory premiestnené alebo zmazané aplikáciou Sycthing sú presunuté do verzií označených dátumov v adresári .stversions.",
|
||||
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Súbory premiestnené alebo zmazané aplikáciou Syncthing sú premenované na verziu s dátumom a presunuté do adresára .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.": "Soubory sú chránené pred zmenami na ostatních zariadeniach, ale zmeny provedené z tohto zariadenia budú rozoslané na zvyšok klastra.",
|
||||
"Filesystem Notifications": "Filesystem Notifications",
|
||||
"Folder": "Adresár",
|
||||
"Folder ID": "ID adresára",
|
||||
"Folder Label": "Označenie adresára",
|
||||
@@ -136,6 +141,7 @@
|
||||
"Newest First": "Najnovší najprv",
|
||||
"No": "Nie",
|
||||
"No File Versioning": "Bez verzií súbor",
|
||||
"No files will be deleted as a result of this operation.": "No files will be deleted as a result of this operation.",
|
||||
"No upgrades": "Bez aktualizácií",
|
||||
"Normal": "Normalny",
|
||||
"Notice": "Oznámenie",
|
||||
@@ -165,11 +171,14 @@
|
||||
"Quick guide to supported patterns": "Rýchly sprievodca podporovanými vzormi",
|
||||
"RAM Utilization": "Využitie RAM",
|
||||
"Random": "Náhodne",
|
||||
"Recent Changes": "Recent Changes",
|
||||
"Reduced by ignore patterns": "Znížené o ignorované vzory",
|
||||
"Release Notes": "Poznámky k vydaniu",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Kandidáti na vydanie obsahujú najnovšie vlastnosti a opravy. Sú podobné tradičným dvojtýždenným vydaniam programu Syncthing.",
|
||||
"Remote Devices": "Vzdialené zariadenia",
|
||||
"Remove": "Odstrániť",
|
||||
"Remove Device": "Remove Device",
|
||||
"Remove Folder": "Remove Folder",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "Potrebný identifikátor pre adresár. Musí byť rovnaký na všetkých zariadeniach v skupine.",
|
||||
"Rescan": "Opakovať skenovanie",
|
||||
"Rescan All": "Opakovať skenovanie všetkých",
|
||||
@@ -184,6 +193,8 @@
|
||||
"Scan Time Remaining": "Zostávajúci čas skenovania",
|
||||
"Scanning": "Skenovanie",
|
||||
"See external versioner help for supported templated command line parameters.": "See external versioner help for supported templated command line parameters.",
|
||||
"See external versioning help for supported templated command line parameters.": "See external versioning help for supported templated command line parameters.",
|
||||
"Select a version": "Select a version",
|
||||
"Select the devices to share this folder with.": "Vyberte zariadenia s ktorými chcete zdieľať tento adresár.",
|
||||
"Select the folders to share with this device.": "Vyberte adresáre ktoré chcete zdieľať s týmto zariadením.",
|
||||
"Send & Receive": "Prijímať a odosielať",
|
||||
@@ -197,6 +208,7 @@
|
||||
"Shared With": "Zdieľané s",
|
||||
"Show ID": "Zobraziť ID",
|
||||
"Show QR": "Zobraziť QR",
|
||||
"Show diff with previous version": "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.": "Zobrazované namiesto ID zariadenia v štatúte klastra. Toto pomenovanie bude oznamovať ostatným zariadeniam ako voliteľné predvolené pomenovanie.",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Zobrazované namiesto ID zariadenia v klastri. Ak je ponechané prázdne, bude nahradené pomenovaním, ktoré oznamuje zariadenie.",
|
||||
"Shutdown": "Vypnutie",
|
||||
@@ -252,6 +264,7 @@
|
||||
"Time": "Čas",
|
||||
"Trash Can File Versioning": "Verzie súborov v koši",
|
||||
"Type": "Typ",
|
||||
"Undecided (will prompt)": "Undecided (will prompt)",
|
||||
"Unknown": "Neznáme",
|
||||
"Unshared": "Nezdieľané",
|
||||
"Unused": "Nepoužité",
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
"API Key": "API-nyckel",
|
||||
"About": "Om",
|
||||
"Action": "Åtgärd",
|
||||
"Actions": "Funktioner",
|
||||
"Actions": "Åtgärder",
|
||||
"Add": "Lägg till",
|
||||
"Add Device": "Lägg till enhet",
|
||||
"Add Folder": "Lägg till mapp",
|
||||
@@ -24,7 +24,10 @@
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "Ett externt kommando hanterar versionshanteringen. Det måste ta bort filen från den delade mappen.",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "Ett externt kommando sköter versionshanteringen. Den behöver ta bort filen från den synkroniserade mappen.",
|
||||
"Anonymous Usage Reporting": "Anonym användarstatistiksrapportering",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "Anonymt användningsrapportformat har ändrats. Vill du flytta till det nya formatet?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "Alla enheter konfigurerade på en introduktör enhet kommer också att läggas till den här enheten.",
|
||||
"Are you sure you want to remove device {%name%}?": "Är du säker på att du vill ta bort enheten {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Är du säker på att du vill ta bort mappen {{label}}?",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Automatisk uppgradering erbjuder nu valet mellan stabila utgåvor och utgåvskandidater.",
|
||||
"Automatic upgrades": "Automatiska uppgraderingar",
|
||||
"Be careful!": "Var aktsam!",
|
||||
@@ -42,8 +45,8 @@
|
||||
"Connection Type": "Anslutningstyp",
|
||||
"Copied from elsewhere": "Kopierat från annanstans",
|
||||
"Copied from original": "Kopierat från original",
|
||||
"Copyright © 2014-2016 the following Contributors:": "Upphovsrätt © 2014-2016 följande bidragare:",
|
||||
"Copyright © 2014-2017 the following Contributors:": "Upphovsrätt © 2014-2017 följande bidragande:",
|
||||
"Copyright © 2014-2016 the following Contributors:": "Copyright © 2014-2016 följande bidragare:",
|
||||
"Copyright © 2014-2017 the following Contributors:": "Copyright © 2014-2017 följande bidragande:",
|
||||
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Skapa ignorera mönster, skriver över en existerande fil på {{path}}.",
|
||||
"Danger!": "Fara!",
|
||||
"Deleted": "Tog bort",
|
||||
@@ -53,6 +56,7 @@
|
||||
"Device Identification": "Enhetsidentifikation",
|
||||
"Device Name": "Enhetsnamn",
|
||||
"Devices": "Enheter",
|
||||
"Disabled": "Inaktiverad",
|
||||
"Disconnected": "Frånkopplad",
|
||||
"Discovered": "Upptäckt",
|
||||
"Discovery": "Annonsering",
|
||||
@@ -84,23 +88,24 @@
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Filer flyttas till datumstämplade versioner i en .stversions-mapp när de ersätts eller tas bort av Syncthing.",
|
||||
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Filer flyttas till datummärkta versioner i en .stversions mapp när de ersätts eller tas bort av Syncthing.",
|
||||
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Filer skyddas från ändringar gjorda på andra enheter, men ändringar som görs på den här noden skickas till de andra klustermedlemmarna.",
|
||||
"Filesystem Notifications": "filsystemsnotifieringar",
|
||||
"Folder": "Mapp",
|
||||
"Folder ID": "Mapp-ID",
|
||||
"Folder Label": "Mapp-etikett",
|
||||
"Folder Path": "Mappsökväg",
|
||||
"Folder Type": "Mapp-typ",
|
||||
"Folder Type": "Mapptyp",
|
||||
"Folders": "Mappar",
|
||||
"GUI": "Grafiskt gränssnitt",
|
||||
"GUI Authentication Password": "GUI autentiseringslösenord",
|
||||
"GUI Authentication User": "GUI autentiseringsanvändare",
|
||||
"GUI Listen Address": "GUI lyssnaradresser",
|
||||
"GUI Listen Addresses": "GUI lyssnaradresser",
|
||||
"GUI Theme": "GUI tema",
|
||||
"GUI Authentication Password": "GUI-autentiseringslösenord",
|
||||
"GUI Authentication User": "GUI-autentiseringsanvändare",
|
||||
"GUI Listen Address": "GUI-lyssnaradress",
|
||||
"GUI Listen Addresses": "GUI-lyssnaradresser",
|
||||
"GUI Theme": "GUI-tema",
|
||||
"Generate": "Generera",
|
||||
"Global Changes": "Globala ändringar",
|
||||
"Global Discovery": "Global annonsering",
|
||||
"Global Discovery Servers": "Globala annonseringsservrar",
|
||||
"Global State": "Global status",
|
||||
"Global State": "Globalt tillstånd",
|
||||
"Help": "Hjälp",
|
||||
"Home page": "Hemsida",
|
||||
"Ignore": "Ignorera",
|
||||
@@ -121,8 +126,8 @@
|
||||
"Learn more": "Ta reda på mer",
|
||||
"Listeners": "Lyssnare",
|
||||
"Local Discovery": "Lokal annonsering",
|
||||
"Local State": "Lokal status",
|
||||
"Local State (Total)": "Lokal status (totalt)",
|
||||
"Local State": "Lokalt tillstånd",
|
||||
"Local State (Total)": "Lokalt tillstånd (totalt)",
|
||||
"Major Upgrade": "Större uppgradering",
|
||||
"Master": "Huvud",
|
||||
"Maximum Age": "Maximum ålder",
|
||||
@@ -136,6 +141,7 @@
|
||||
"Newest First": "Nyast först",
|
||||
"No": "Nej",
|
||||
"No File Versioning": "Ingen filversionshantering",
|
||||
"No files will be deleted as a result of this operation.": "Inga filer kommer att tas bort till följd av denna operation.",
|
||||
"No upgrades": "Inga uppgraderingar",
|
||||
"Normal": "Normal",
|
||||
"Notice": "Observera",
|
||||
@@ -165,11 +171,14 @@
|
||||
"Quick guide to supported patterns": "Snabb handledning till mönster som stöds",
|
||||
"RAM Utilization": "RAM användning",
|
||||
"Random": "Slumpmässig",
|
||||
"Recent Changes": "Senaste ändringar",
|
||||
"Reduced by ignore patterns": "Minskas med ignorera mönster",
|
||||
"Release Notes": "Versionsanteckningar",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Utgåvskandidater innehåller de senaste funktionerna och korrigeringarna. De är lika de traditionella Syncthing-utgåvorna som kommer ut varannan vecka.",
|
||||
"Remote Devices": "Fjärrenheter",
|
||||
"Remove": "Ta bort",
|
||||
"Remove Device": "Ta bort enhet",
|
||||
"Remove Folder": "Ta bort mapp",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "Krävs identifierare för mappen. Måste vara densamma på alla kluster enheter.",
|
||||
"Rescan": "Skanna om",
|
||||
"Rescan All": "Skanna om alla",
|
||||
@@ -183,7 +192,9 @@
|
||||
"Save": "Spara",
|
||||
"Scan Time Remaining": "Återstående skanningstid",
|
||||
"Scanning": "Skannar",
|
||||
"See external versioner help for supported templated command line parameters.": "See external versioner help for supported templated command line parameters.",
|
||||
"See external versioner help for supported templated command line parameters.": "Se hjälp för extern version för stödda mallade kommandoradsparametrar.",
|
||||
"See external versioning help for supported templated command line parameters.": "Se hjälp för extern version för stödda mallade kommandoradsparametrar.",
|
||||
"Select a version": "Välj en version",
|
||||
"Select the devices to share this folder with.": "Ange enheterna som den här mappen ska delas med.",
|
||||
"Select the folders to share with this device.": "Välj mapparna som ska delas med den här enheten.",
|
||||
"Send & Receive": "Skicka & ta emot",
|
||||
@@ -197,6 +208,7 @@
|
||||
"Shared With": "Delad med",
|
||||
"Show ID": "Visa ID",
|
||||
"Show QR": "Visa QR",
|
||||
"Show diff with previous version": "Visa skillnad med tidigare version",
|
||||
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Visas istället för enhet-ID i klusterstatusen. Skickas till andra enheter som ett alternativt förvalt namn.",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Visas i stället för enhet-ID i klusterstatusen. Kommer att uppdateras till namnet enheten annonserar om det lämnas tomt.",
|
||||
"Shutdown": "Stäng av",
|
||||
@@ -224,13 +236,13 @@
|
||||
"The Syncthing admin interface is configured to allow remote access without a password.": "Syncthing administratör gränssnittet är konfigurerat för att tillåta fjärrtillträde utan ett lösenord.",
|
||||
"The aggregated statistics are publicly available at the URL below.": "Den aggregerade statistiken är offentligt tillgänglig på webbadressen nedan.",
|
||||
"The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.": "Konfigurationen har sparats men inte aktiverats. Syncthing måste startas om för att aktivera den nya konfigurationen.",
|
||||
"The device ID cannot be blank.": "Enhet-ID kan inte vara tomt.",
|
||||
"The device ID cannot be blank.": "Enhetens ID kan inte vara tomt.",
|
||||
"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).": "Enhet-ID som behövs här kan du hitta i \"Åtgärder > Visa ID\"-dialogrutan på den andra enheten. Mellanrum och bindestreck är valfria (ignoreras).",
|
||||
"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.": "Den krypterade användarstatistiken skickas dagligen. Den används för att spåra vanliga plattformar, mappstorlekar och versioner. Om datat som rapporteras ändras så kommer du att bli tillfrågad igen.",
|
||||
"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.": "Det inmatade enhet-ID verkar inte vara korrekt. Det ska vara en 52 eller 56 teckensträng bestående av siffror och bokstäver, eventuellt med mellanrum och bindestreck.",
|
||||
"The first command line parameter is the folder path and the second parameter is the relative path in the folder.": "Den första kommandoparametern är sökvägen till mappen och den andra parametern är den relativa sökvägen i katalogen.",
|
||||
"The folder ID cannot be blank.": "Mapp-ID får inte vara tomt.",
|
||||
"The folder ID must be unique.": "Mapp-ID måste vara unikt.",
|
||||
"The folder ID cannot be blank.": "Mapp-ID:t får inte vara tomt.",
|
||||
"The folder ID must be unique.": "Mapp-ID:t måste vara unikt.",
|
||||
"The folder path cannot be blank.": "Mapp-sökvägen kan inte vara tom.",
|
||||
"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.": "De följande intervallen används: varje 30 sekunder under den första timmen; varje timme under den första dagen; varje dag för de första 30 dagarna; varje vecka tills den maximala åldersgränsen uppnås.",
|
||||
"The following items could not be synchronized.": "Följande objekt kunde inte synkroniseras.",
|
||||
@@ -252,6 +264,7 @@
|
||||
"Time": "Tid",
|
||||
"Trash Can File Versioning": "Papperskorgs filversionshantering",
|
||||
"Type": "Typ",
|
||||
"Undecided (will prompt)": "Obeslutad (kommer att skriva)",
|
||||
"Unknown": "Okänd",
|
||||
"Unshared": "Inte delad",
|
||||
"Unused": "Oanvänd",
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"A device with that ID is already added.": "Bu ID'yi taşıyan aygıt zaten eklendi.",
|
||||
"A negative number of days doesn't make sense.": "Eksi gün sayısı mantıklı bir ifade değil.",
|
||||
"A new major version may not be compatible with previous versions.": "Yeni ana sürüm önceki sürümlerle uyumlu olmayabilir.",
|
||||
"A new major version may not be compatible with previous versions.": "Yeni ana sürüm, önceki sürümlerle uyumlu olmayabilir.",
|
||||
"API Key": "API Anahtarı",
|
||||
"About": "Hakkında",
|
||||
"Action": "Eylem",
|
||||
@@ -24,7 +24,10 @@
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "An external command handles the versioning. It has to remove the file from the shared folder.",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "Sürümleme işlemini harici bir komut yürütüyor. Dosyayı eşzamanlama klasöründen kaldırmak zorunda.",
|
||||
"Anonymous Usage Reporting": "Anonim Kullanım Raporlaması",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "Anonymous usage report format has changed. Would you like to move to the new format?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "Tanıtıcı bir cihaz üzerinde yapılandırılan cihazlar bu cihaza da eklenecektir.",
|
||||
"Are you sure you want to remove device {%name%}?": "Are you sure you want to remove device {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Are you sure you want to remove folder {{label}}?",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Kendiliğinden yükseltme artık kararlı dağıtımlar ve sürüm adayları arasında seçim yapmayı sağlıyor.",
|
||||
"Automatic upgrades": "Kendiliğinden yükseltmeler",
|
||||
"Be careful!": "Dikkatli ol!",
|
||||
@@ -53,6 +56,7 @@
|
||||
"Device Identification": "Aygıt Kimliği",
|
||||
"Device Name": "Aygıt Adı",
|
||||
"Devices": "Aygıtlar",
|
||||
"Disabled": "Disabled",
|
||||
"Disconnected": "Bağlantı Kesik",
|
||||
"Discovered": "Keşfedildi",
|
||||
"Discovery": "Keşif",
|
||||
@@ -84,6 +88,7 @@
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.",
|
||||
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Dosyalar Syncthing tarafından yeri değiştirildiğinde ya da silindiğinde, tarih damgalı sürümleri .stversions klasörüne taşınır.",
|
||||
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Dosyalar diğer aygıtlarda yapılan değişikliklerden korunur, ancak bu aygıttaki değişiklikler kümedeki diğer aygıtlara gönderilir.",
|
||||
"Filesystem Notifications": "Filesystem Notifications",
|
||||
"Folder": "Klasör",
|
||||
"Folder ID": "Klasör ID",
|
||||
"Folder Label": "Klasör Etiketi",
|
||||
@@ -136,6 +141,7 @@
|
||||
"Newest First": "En yeni olan önce",
|
||||
"No": "Hayır",
|
||||
"No File Versioning": "Dosya Sürümleme İşlemi Yok",
|
||||
"No files will be deleted as a result of this operation.": "No files will be deleted as a result of this operation.",
|
||||
"No upgrades": "Yükseltme yok",
|
||||
"Normal": "Olağan",
|
||||
"Notice": "Uyarı",
|
||||
@@ -165,11 +171,14 @@
|
||||
"Quick guide to supported patterns": "Desteklenen kalıp dizileri için hızlı rehber",
|
||||
"RAM Utilization": "RAM Kullanımı",
|
||||
"Random": "Rastgele",
|
||||
"Recent Changes": "Recent Changes",
|
||||
"Reduced by ignore patterns": "Gözardı edilen kalıp dizileri tarafından daraltıldı",
|
||||
"Release Notes": "Sürüm Notları",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Sürüm adayları en son özellikleri ve hata düzeltmelerini içerir. Bunlar, geleneksel olarak iki haftada bir yayımlanan Syncthing dağıtımlarına benzer.",
|
||||
"Remote Devices": "Uzak Aygıtlar",
|
||||
"Remove": "Kaldır",
|
||||
"Remove Device": "Remove Device",
|
||||
"Remove Folder": "Remove Folder",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "Klasör için tanımlayıcı gereklidir. Tüm küme cihazlarda aynı olmalıdır.",
|
||||
"Rescan": "Tekrar Tara",
|
||||
"Rescan All": "Tümünü Tekrar Tara",
|
||||
@@ -184,6 +193,8 @@
|
||||
"Scan Time Remaining": "Kalan Tarama Zamanı",
|
||||
"Scanning": "Taranıyor",
|
||||
"See external versioner help for supported templated command line parameters.": "See external versioner help for supported templated command line parameters.",
|
||||
"See external versioning help for supported templated command line parameters.": "See external versioning help for supported templated command line parameters.",
|
||||
"Select a version": "Select a version",
|
||||
"Select the devices to share this folder with.": "Bu klasörü paylaşacağın aygıtları seç.",
|
||||
"Select the folders to share with this device.": "Bu aygıtla paylaşılacak klasörleri seç.",
|
||||
"Send & Receive": "Gönder & Al",
|
||||
@@ -197,6 +208,7 @@
|
||||
"Shared With": "Paylaşılan düğümler",
|
||||
"Show ID": "ID Göster",
|
||||
"Show QR": "QR Göster",
|
||||
"Show diff with previous version": "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.": "Küme durumunda Aygıt ID yerine bunu göster. Varsayılan ad isteğe bağlı olarak diğer aygıtlara ilan edilecektir.",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Küme durumunda Aygıt ID yerine bunu göster. Eğer düğüm adı boş bırakılırsa düğüm adı güncellenip ilan edilecektir.",
|
||||
"Shutdown": "Kapat",
|
||||
@@ -252,6 +264,7 @@
|
||||
"Time": "Zaman",
|
||||
"Trash Can File Versioning": "Çöp Kutusu Dosya Sürümleme İşlemi",
|
||||
"Type": "Tür",
|
||||
"Undecided (will prompt)": "Undecided (will prompt)",
|
||||
"Unknown": "Bilinmiyor",
|
||||
"Unshared": "Paylaşılmayan",
|
||||
"Unused": "Kullanılmayan",
|
||||
|
||||
@@ -24,7 +24,10 @@
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "Зовнішня команда керування версіями. Вона має видалити файл із спільної директорії.",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "Зовнішня команда керування версіями. Вона має видалити файл із директорії, що синхронізується.",
|
||||
"Anonymous Usage Reporting": "Анонімна статистика використання",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "Змінився формат анонімного звіту про користування. Бажаєте перейти на новий формат?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "Усі пристрої, налаштовані на пристрої-рекомендувачі, будуть додані до поточного пристрою.",
|
||||
"Are you sure you want to remove device {%name%}?": "Are you sure you want to remove device {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Are you sure you want to remove folder {{label}}?",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Автоматиче оновлення зараз дозволяє обирати між стабільними випусками та реліз-кандидатами.",
|
||||
"Automatic upgrades": "Автоматичні оновлення",
|
||||
"Be careful!": "Будьте обережні!",
|
||||
@@ -44,7 +47,7 @@
|
||||
"Copied from original": "Скопійовано з оригіналу",
|
||||
"Copyright © 2014-2016 the following Contributors:": "© 2014-2016 Всі права застережено, вклад внесли:",
|
||||
"Copyright © 2014-2017 the following Contributors:": "© 2014-2017 Всі права застережено, вклад внесли:",
|
||||
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Creating ignore patterns, overwriting an existing file at {{path}}.",
|
||||
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Створення шаблонів винятків з перезаписом існуючого файлу {{path}}.",
|
||||
"Danger!": "Небезпечно!",
|
||||
"Deleted": "Видалене",
|
||||
"Device": "Пристрій",
|
||||
@@ -53,6 +56,7 @@
|
||||
"Device Identification": "Ідентифікатор пристрою",
|
||||
"Device Name": "Назва пристрою",
|
||||
"Devices": "Пристрої",
|
||||
"Disabled": "Вимкнено",
|
||||
"Disconnected": "З’єднання відсутнє",
|
||||
"Discovered": "Виявлено",
|
||||
"Discovery": "Сервери координації NAT",
|
||||
@@ -84,6 +88,7 @@
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Файли будуть поміщатися у директорію .stversions із відповідною позначкою часу, коли вони будуть замінятися або видалятися програмою.",
|
||||
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by 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.": "Вміст папки захищено від змін, зроблених на інших пристроях, але зміни зроблені на цьому пристрої можна розіслати решті пристроїв кластеру.",
|
||||
"Filesystem Notifications": "Повідомлення файлової системи",
|
||||
"Folder": "Директорія",
|
||||
"Folder ID": "ID директорії",
|
||||
"Folder Label": "Мітка директорії",
|
||||
@@ -136,6 +141,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 upgrades": "Немає оновлень",
|
||||
"Normal": "Нормальний",
|
||||
"Notice": "Повідомлення",
|
||||
@@ -165,11 +171,14 @@
|
||||
"Quick guide to supported patterns": "Швидкий посібник по шаблонам, що підтримуються",
|
||||
"RAM Utilization": "Використання RAM",
|
||||
"Random": "Випадково",
|
||||
"Recent Changes": "Останні зміни",
|
||||
"Reduced by ignore patterns": "Зменшено шаблонами ігнорування",
|
||||
"Release Notes": "Примітки до випуску",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Реліз-кандидати містять найостанніші функції та виправлення. Вони схожі на традиційні щодвотижневі випуски Syncthing.",
|
||||
"Remote Devices": "Віддалені пристрої",
|
||||
"Remove": "Видалити",
|
||||
"Remove Device": "Remove Device",
|
||||
"Remove Folder": "Remove Folder",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "Обов'язковий унікальний ідентифікатор директорії. Має бути однаковим на усіх пристроях кластеру.",
|
||||
"Rescan": "Пересканувати",
|
||||
"Rescan All": "Пересканувати усе",
|
||||
@@ -183,7 +192,9 @@
|
||||
"Save": "Зберегти",
|
||||
"Scan Time Remaining": "Час до кінця сканування",
|
||||
"Scanning": "Сканування",
|
||||
"See external versioner help for supported templated command line parameters.": "See external versioner help for supported templated command line parameters.",
|
||||
"See external versioner help for supported templated command line parameters.": "Переглянути допомогу по зовнішньому версіонуванню для підтримуваних шаблонних параметрів командного рядка.",
|
||||
"See external versioning help for supported templated command line parameters.": "Переглянути допомогу по зовнішньому версіонуванню для підтримуваних шаблонних параметрів командного рядка.",
|
||||
"Select a version": "Обрати версію",
|
||||
"Select the devices to share this folder with.": "Оберіть пристрої, які матимуть доступ до цієї директорії.",
|
||||
"Select the folders to share with this device.": "Оберіть директорії до яких матиме доступ цей пристрій.",
|
||||
"Send & Receive": "Відправити та отримати",
|
||||
@@ -197,6 +208,7 @@
|
||||
"Shared With": "Доступно для",
|
||||
"Show ID": "Показати ID",
|
||||
"Show QR": "Показати QR-код",
|
||||
"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.": "Показується замість ID пристрою в статусі кластера. Буде розголошено іншим вузлам як опціональне типове ім’я.",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Показується замість ID пристрою в статусі кластера. Буде оновлено ім’ям, яке розголошене пристроєм, якщо залишити порожнім.",
|
||||
"Shutdown": "Вимкнути",
|
||||
@@ -252,6 +264,7 @@
|
||||
"Time": "Час",
|
||||
"Trash Can File Versioning": "Версіонування файлів у кошику ",
|
||||
"Type": "Тип",
|
||||
"Undecided (will prompt)": "Невизначено (буде запитано)",
|
||||
"Unknown": "Невідомо",
|
||||
"Unshared": "Не розповсюджується",
|
||||
"Unused": "Не використовується",
|
||||
|
||||
@@ -1,288 +0,0 @@
|
||||
{
|
||||
"A device with that ID is already added.": "Đã có một thiết bị trùng ID.",
|
||||
"A negative number of days doesn't make sense.": "Số ngày không được âm.",
|
||||
"A new major version may not be compatible with previous versions.": "Phiên bản quan trọng mới có thể sẽ không tương thích với các bản cũ.",
|
||||
"API Key": "Khoá API",
|
||||
"About": "Thông tin về",
|
||||
"Action": "Action",
|
||||
"Actions": "Thao tác",
|
||||
"Add": "Thêm",
|
||||
"Add Device": "Thêm thiết bị",
|
||||
"Add Folder": "Thêm thư mục",
|
||||
"Add Remote Device": "Thêm thiết bị từ xa",
|
||||
"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 new folder?": "Thêm thư mục mới?",
|
||||
"Address": "Địa chỉ",
|
||||
"Addresses": "Các địa chỉ",
|
||||
"Advanced": "Nâng cao",
|
||||
"Advanced Configuration": "Cấu hình nâng cao",
|
||||
"Advanced settings": "Cài đặt nâng cao",
|
||||
"All Data": "Tất cả dữ liệu",
|
||||
"Allow Anonymous Usage Reporting?": "Cho phép báo cáo sử dụng ẩn danh?",
|
||||
"Allowed Networks": "Allowed Networks",
|
||||
"Alphabetic": "A-Z",
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "An external command handles the versioning. It has to remove the file from the shared folder.",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "Một lệnh ngoại vi chịu trách nhiệm phiên bản hoá. Nó sẽ xoá tập tin khỏi thư mục đã đồng bộ.",
|
||||
"Anonymous Usage Reporting": "Báo cáo sử dụng ẩn danh",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "Bất kỳ thiết bị nào liên kết với thiết bị giới thiệu cũng sẽ được thêm vào.",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Automatic upgrade now offers the choice between stable releases and release candidates.",
|
||||
"Automatic upgrades": "Cập nhật tự động",
|
||||
"Be careful!": "Cẩn thận!",
|
||||
"Bugs": "Lỗi",
|
||||
"CPU Utilization": "Mức s.dụng CPU",
|
||||
"Changelog": "Lịch sử thay đổi",
|
||||
"Clean out after": "Dọn dẹp sau",
|
||||
"Click to see discovery failures": "Click to see discovery failures",
|
||||
"Close": "Đóng",
|
||||
"Command": "Lệnh",
|
||||
"Comment, when used at the start of a line": "Bình luận, khi dùng trước đầu dòng",
|
||||
"Compression": "Nén",
|
||||
"Configured": "Configured",
|
||||
"Connection Error": "Lỗi kết nối",
|
||||
"Connection Type": "Connection Type",
|
||||
"Copied from elsewhere": "Đã sao chép từ nơi khác",
|
||||
"Copied from original": "Đã sao chép từ nguồn",
|
||||
"Copyright © 2014-2016 the following Contributors:": "Bản quyền © 2014-2016 thuộc về các nhà cộng tác sau:",
|
||||
"Copyright © 2014-2017 the following Contributors:": "Copyright © 2014-2017 the following Contributors:",
|
||||
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Creating ignore patterns, overwriting an existing file at {{path}}.",
|
||||
"Danger!": "Nguy hiểm!",
|
||||
"Deleted": "Đã xoá",
|
||||
"Device": "Device",
|
||||
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "Thiết bị \"{{name}}\" ({{device}} tại {{address}}) muốn kết nối. Thêm thiết bị mới?",
|
||||
"Device ID": "ID thiết bị",
|
||||
"Device Identification": "Danh tính thiết bị",
|
||||
"Device Name": "Tên thiết bị",
|
||||
"Devices": "Các thiết bị",
|
||||
"Disconnected": "Đã ngắt kết nối",
|
||||
"Discovered": "Discovered",
|
||||
"Discovery": "Tìm thấy",
|
||||
"Discovery Failures": "Discovery Failures",
|
||||
"Documentation": "Tài liệu",
|
||||
"Download Rate": "Tốc độ tải xuống",
|
||||
"Downloaded": "Đã tải xuống",
|
||||
"Downloading": "Đang tải xuống",
|
||||
"Edit": "Chỉnh sửa",
|
||||
"Edit Device": "Edit Device",
|
||||
"Edit Folder": "Edit Folder",
|
||||
"Editing": "Đang ch.sửa",
|
||||
"Editing {%path%}.": "Editing {{path}}.",
|
||||
"Enable NAT traversal": "Enable NAT traversal",
|
||||
"Enable Relaying": "Bật chế độ ch.tiếp",
|
||||
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.",
|
||||
"Enter a non-privileged port number (1024 - 65535).": "Enter a non-privileged port number (1024 - 65535).",
|
||||
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Nhập các địa chỉ ngăn cách bởi dấu phẩy (\"tcp://ip:port\", \"tcp://host:port\") hoặc \"dynamic\" để tiến hành dò tìm địa chỉ tự động.",
|
||||
"Enter ignore patterns, one per line.": "Nhập các quy luật bỏ qua, từng dòng một.",
|
||||
"Error": "Lỗi",
|
||||
"External File Versioning": "Kiểu ngoại vi",
|
||||
"Failed Items": "Các n.dung bị lỗi",
|
||||
"Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.": "Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.",
|
||||
"File Pull Order": "Thứ tự pull tập tin",
|
||||
"File Versioning": "Ph.bản hoá tập tin",
|
||||
"File permission bits are ignored when looking for changes. Use on FAT file systems.": "Các ph.tử g.phép tập tin sẽ được bỏ qua khi t.kiếm th.đổi. Dùng trên h.thống tập tin FAT.",
|
||||
"Files are moved to .stversions directory when replaced or deleted by Syncthing.": "Files are moved to .stversions directory when replaced or deleted by Syncthing.",
|
||||
"Files are moved to .stversions folder when replaced or deleted by Syncthing.": "Các t.tin sẽ được chuyển tới th.mục .stversions khi bị th.thế hoặc xoá bởi Syncthing.",
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.",
|
||||
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Các t.tin sẽ được chuyển tới các ph.bản được đ.dấu ng.tháng trong th.mục .stversions khi bị th.thế hoặc xoá bởi Syncthing.",
|
||||
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Các t.tin được b.vệ khỏi những th.đổi trên các th.bị khác, nhưng những th.đổi trên th.bị này sẽ được chuyển tới các máy cụm còn lại.",
|
||||
"Folder": "Thư mục",
|
||||
"Folder ID": "ID thư mục",
|
||||
"Folder Label": "Nhãn thư mục",
|
||||
"Folder Path": "Đ.dẫn đến th.mục",
|
||||
"Folder Type": "Folder Type",
|
||||
"Folders": "Các th.mục",
|
||||
"GUI": "GUI",
|
||||
"GUI Authentication Password": "Mật khẩu xác minh GUI",
|
||||
"GUI Authentication User": "Người dùng xác minh GUI",
|
||||
"GUI Listen Address": "GUI Listen Address",
|
||||
"GUI Listen Addresses": "Các đ.chỉ lắng nghe GUI",
|
||||
"GUI Theme": "GUI Theme",
|
||||
"Generate": "Tạo mới",
|
||||
"Global Changes": "Global Changes",
|
||||
"Global Discovery": "Dò tìm toàn cầu",
|
||||
"Global Discovery Servers": "Các m.chủ dò tìm toàn cầu",
|
||||
"Global State": "Tr.thái toàn cầu",
|
||||
"Help": "Trợ giúp",
|
||||
"Home page": "Trang chủ",
|
||||
"Ignore": "Bỏ qua",
|
||||
"Ignore Patterns": "Bỏ qua các quy luật",
|
||||
"Ignore Permissions": "Bỏ qua các giấy phép",
|
||||
"Incoming Rate Limit (KiB/s)": "Giới hạn t.độ đầu vào (KiB/s)",
|
||||
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Cấu hình không đúng có thể làm mất mát dữ liệu và khiến Syncthing ngừng hoạt động.",
|
||||
"Introduced By": "Introduced By",
|
||||
"Introducer": "Th.bị giới thiệu",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "Đảo ngược điều kiện cho trước (VD: không được loại trừ)",
|
||||
"Keep Versions": "Giữ các ph.bản",
|
||||
"Largest First": "Lớn nhất đầu tiên",
|
||||
"Last File Received": "T.tin nhận được gần đây",
|
||||
"Last Scan": "Last Scan",
|
||||
"Last seen": "Thấy lần cuối",
|
||||
"Later": "Để sau",
|
||||
"Latest Change": "Latest Change",
|
||||
"Learn more": "Learn more",
|
||||
"Listeners": "Listeners",
|
||||
"Local Discovery": "Dò tìm cục bộ",
|
||||
"Local State": "Tr.thái cục bộ",
|
||||
"Local State (Total)": "Tr.thái cục bộ (Tổng)",
|
||||
"Major Upgrade": "Bản n.cấp q.trọng",
|
||||
"Master": "Master",
|
||||
"Maximum Age": "Thời hạn tối đa",
|
||||
"Metadata Only": "Chỉ siêu dữ liệu",
|
||||
"Minimum Free Disk Space": "Dung lượng đĩa trống tối thiểu",
|
||||
"Move to top of queue": "Chuyển đến đầu hàng chờ",
|
||||
"Multi level wildcard (matches multiple directory levels)": "Ký tự thay thế đa cấp (phù hợp với đa cấp độ thư mục)",
|
||||
"Never": "Chưa từng",
|
||||
"New Device": "Thiết bị mới",
|
||||
"New Folder": "Thư mục mới",
|
||||
"Newest First": "Mới nhất đầu tiên",
|
||||
"No": "Không",
|
||||
"No File Versioning": "Không dùng",
|
||||
"No upgrades": "No upgrades",
|
||||
"Normal": "Normal",
|
||||
"Notice": "Chú ý",
|
||||
"OK": "OK",
|
||||
"Off": "Tắt",
|
||||
"Oldest First": "Cũ nhất đầu tiên",
|
||||
"Optional descriptive label for the folder. Can be different on each device.": "Nhãn mô tả tuỳ chọn cho thư mục. Có thể khác nhau trên từng thiết bị.",
|
||||
"Options": "Tuỳ chọn",
|
||||
"Out of Sync": "Mất đồng bộ",
|
||||
"Out of Sync Items": "Các n.dung mất đ.bộ",
|
||||
"Outgoing Rate Limit (KiB/s)": "Giới hạn t.độ đầu ra (KiB/s)",
|
||||
"Override Changes": "Ghi đè các th.đổi",
|
||||
"Path": "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": "Đường dẫn đến thư mục trên máy cục bộ. Sẽ tạo mới nếu chưa hiện hữu. Dấu ngã (~) có thể được dùng làm lối tắt cho",
|
||||
"Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).": "Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).",
|
||||
"Path where versions should be stored (leave empty for the default .stversions folder in the folder).": "Đường dẫn nơi các phiên bản được lưu trữ (nếu để trống, thư mục mặc định sẽ là .stversions).",
|
||||
"Pause": "Tạm dừng",
|
||||
"Pause All": "Pause All",
|
||||
"Paused": "Đã t.dừng",
|
||||
"Please consult the release notes before performing a major upgrade.": "Hãy xem kỹ lịch sử phát hành trước khi tiến hành bản cập nhật q.trọng.",
|
||||
"Please set a GUI Authentication User and Password in the Settings dialog.": "Hãy thiết lập tên ng.dùng và mật khẩu xác minh GUI trong hộp thoại Cài đặt.",
|
||||
"Please wait": "Xin chờ",
|
||||
"Prefix indicating that the file can be deleted if preventing directory removal": "Prefix indicating that the file can be deleted if preventing directory removal",
|
||||
"Prefix indicating that the pattern should be matched without case sensitivity": "Prefix indicating that the pattern should be matched without case sensitivity",
|
||||
"Preview": "Xem trước",
|
||||
"Preview Usage Report": "Xem trước báo cáo s.dụng",
|
||||
"Quick guide to supported patterns": "H.dẫn sơ lược về các q.luật được hỗ trợ",
|
||||
"RAM Utilization": "Mức s.dụng RAM",
|
||||
"Random": "Ngẫu nhiên",
|
||||
"Reduced by ignore patterns": "Reduced by ignore patterns",
|
||||
"Release Notes": "Lịch sử phát hành",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.",
|
||||
"Remote Devices": "Các thiết bị từ xa",
|
||||
"Remove": "Xoá",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "Tên tắt bắt buộc cho thư mục. Phải trùng khớp trên tất cả thiết bị trong cụm.",
|
||||
"Rescan": "Quét lại",
|
||||
"Rescan All": "Quét lại t.cả",
|
||||
"Rescan Interval": "Kh.cách th.gian quét lại",
|
||||
"Restart": "Kh.động lại",
|
||||
"Restart Needed": "Cần kh.động lại",
|
||||
"Restarting": "Đang kh.động lại",
|
||||
"Resume": "Tiếp tục",
|
||||
"Resume All": "Resume All",
|
||||
"Reused": "Đã s.dụng lại",
|
||||
"Save": "Lưu",
|
||||
"Scan Time Remaining": "Thời gian quét còn lại",
|
||||
"Scanning": "Đang quét",
|
||||
"See external versioner help for supported templated command line parameters.": "See external versioner help for supported templated command line parameters.",
|
||||
"Select the devices to share this folder with.": "Chọn các thiết bị để chia sẻ thư mục này.",
|
||||
"Select the folders to share with this device.": "Chọn các thư mục để chia sẻ với thiết bị này.",
|
||||
"Send & Receive": "Send & Receive",
|
||||
"Send Only": "Send Only",
|
||||
"Settings": "Cài đặt",
|
||||
"Share": "Chia sẻ",
|
||||
"Share Folder": "Chia sẻ th.mục",
|
||||
"Share Folders With Device": "Chia sẻ các th.mục với th.bị",
|
||||
"Share With Devices": "Chia sẻ với các th.bị",
|
||||
"Share this folder?": "Chia sẻ th.mục này?",
|
||||
"Shared With": "Đã ch.sẻ với",
|
||||
"Show ID": "Hiển thị ID",
|
||||
"Show QR": "Hiển thị QR",
|
||||
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Hiển thị thay cho ID th.bị trong trạng thái cụm. Sẽ được giới thiệu đến các th.bị khác như tên mặc định tuỳ chọn.",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Hiển thị thay cho ID thiết bị trong trạng thái cụm. Nếu để trống sẽ được cập nhật thành tên mà thiết bị giới thiệu.",
|
||||
"Shutdown": "Tắt",
|
||||
"Shutdown Complete": "Tắt hoàn tất",
|
||||
"Simple File Versioning": "Kiểu đơn giản",
|
||||
"Single level wildcard (matches within a directory only)": "Ký tự thay thế đơn cấp (phù hợp với chỉ một thư mục)",
|
||||
"Smallest First": "Nhỏ nhất đầu tiên",
|
||||
"Source Code": "Mã nguồn",
|
||||
"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 are delayed by about two weeks. During this time they go through testing as release candidates.",
|
||||
"Stable releases only": "Stable releases only",
|
||||
"Staggered File Versioning": "Theo thời gian",
|
||||
"Start Browser": "Mở trình duyệt",
|
||||
"Statistics": "Thống kê",
|
||||
"Stopped": "Đã dừng",
|
||||
"Support": "Hỗ trợ",
|
||||
"Sync Protocol Listen Addresses": "Đồng bộ các đ.chỉ l.nghe giao thức",
|
||||
"Syncing": "Đang đ.bộ",
|
||||
"Syncthing has been shut down.": "Đã tắt Syncthing.",
|
||||
"Syncthing includes the following software or portions thereof:": "Syncthing bao gồm các ph.mềm hoặc ph.tử của các ph.mềm sau:",
|
||||
"Syncthing is restarting.": "Syncthing đang kh.động lại.",
|
||||
"Syncthing is upgrading.": "Syncthing đang n.cấp.",
|
||||
"Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…": "Có vẻ như Syncthing đang bị nghẽn hoặc là mạng của bạn có vấn đề. Đang thử lại...",
|
||||
"Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.": "Có vẻ như Syncthing đang gặp phải v.đề khi x.lý yêu cầu của bạn. Xin làm mới trang hoặc kh.động lại Syncthing nếu v.đề vẫn còn tiếp diễn.",
|
||||
"The Syncthing admin interface is configured to allow remote access without a password.": "Giao diện q.trị của Syncthing được c.hình nhằm cho phép tr.cập từ xa không cần mật khẩu.",
|
||||
"The aggregated statistics are publicly available at the URL below.": "The aggregated statistics are publicly available at the URL below.",
|
||||
"The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.": "Cấu hình đã được lưu nhưng chưa được kích hoạt. Syncthing phải khởi động lại để kích hoạt cấu hình mới. ",
|
||||
"The device ID cannot be blank.": "Không được để trống ID thiết bị.",
|
||||
"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).": "ID thiết bị cần nhập có thể được tìm thấy trong hộp thoại \"Thao tác > Hiển thị ID\" trên thiết bị kia. Khoảng trắng và gạch ngang là tuỳ chọn (bỏ qua).",
|
||||
"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.": "Báo cáo s.dụng đã mã hoá sẽ được gửi đi hằng ngày. Nó được dùng để t.thập s.liệu về các HĐH phổ biến, kích cỡ th.mục và ph.bản ứng dụng. Nếu bộ d.liệu báo cáo có th.đổi, bạn sẽ được nhắc thông qua h.thoại này.",
|
||||
"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.": "ID thiết bị đã nhập không hợp lệ. Nó phải là một chuỗi từ 52 đến 56 ký tự, bao gồm chữ cái và các con số, với khoảng trắng và gạch ngang là tuỳ chọn.",
|
||||
"The first command line parameter is the folder path and the second parameter is the relative path in the folder.": "Tham số dòng lệnh đầu tiên là đường dẫn thư mục và tham số thứ hai là đường dẫn tương đối trong thư mục.",
|
||||
"The folder ID cannot be blank.": "Không được để trống ID thư mục.",
|
||||
"The folder ID must be unique.": "ID thư mục phải là duy nhất.",
|
||||
"The folder path cannot be blank.": "Không được để trống đ.dẫn đến th.mục.",
|
||||
"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.": "Các khoảng th.gian sau đây sẽ được s.dụng: một phiên bản, trong giờ đầu tiên, được giữ lại mỗi 30 giây, trong ngày đầu tiên là mỗi giờ, trong 30 ngày đầu tiên là mỗi ngày, cho đến khi th.hạn tối đa mỗi ph.bản được giữ lại là mỗi tuần. ",
|
||||
"The following items could not be synchronized.": "Không thể đồng bộ những nội dung sau.",
|
||||
"The maximum age must be a number and cannot be blank.": "Thời hạn tối đa phải là một con số và không được để trống.",
|
||||
"The maximum time to keep a version (in days, set to 0 to keep versions forever).": "Th.gian t.đa một ph.bản được giữ lại (tính bằng ngày, nhập 0 để giữ tập tin mãi mãi).",
|
||||
"The minimum free disk space percentage must be a non-negative number between 0 and 100 (inclusive).": "Phần trăm dung lượng đĩa trống tối thiểu phải là một số không âm (nằm trong khoảng) từ 0 đến 100.",
|
||||
"The number of days must be a number and cannot be blank.": "Số ngày phải là một con số và không được để trống.",
|
||||
"The number of days to keep files in the trash can. Zero means forever.": "Số ngày tập tin được giữ trong thùng rác. 0 nghĩa là mãi mãi.",
|
||||
"The number of old versions to keep, per file.": "Số phiên bản cũ cần giữ lại với mỗi tập tin.",
|
||||
"The number of versions must be a number and cannot be blank.": "Số phiên bản phải là một con số và không được để trống.",
|
||||
"The path cannot be blank.": "Không được để trống đường dẫn.",
|
||||
"The rate limit must be a non-negative number (0: no limit)": "Giới hạn tốc độ phải là một số không âm (0: không giới hạn)",
|
||||
"The rescan interval must be a non-negative number of seconds.": "Khoảng thời gian quét lại phải là một số giây không âm.",
|
||||
"They are retried automatically and will be synced when the error is resolved.": "Chúng sẽ được tự động thử lại và đồng bộ khi lỗi được khắc phục.",
|
||||
"This Device": "Thiết bị này",
|
||||
"This can easily give hackers access to read and change any files on your computer.": "Th.tác này có thể khiến tin tặc dễ dàng tr.cập để đọc và th.đổi bất kỳ t.tin nào trên máy của bạn.",
|
||||
"This is a major version upgrade.": "Đây là bản nâng cấp quan trọng.",
|
||||
"This setting controls the free space required on the home (i.e., index database) disk.": "This setting controls the free space required on the home (i.e., index database) disk.",
|
||||
"Time": "Time",
|
||||
"Trash Can File Versioning": "Kiểu thùng rác",
|
||||
"Type": "Type",
|
||||
"Unknown": "Không biết",
|
||||
"Unshared": "Chưa chia sẻ",
|
||||
"Unused": "Chưa sử dụng",
|
||||
"Up to Date": "Đã đồng bộ",
|
||||
"Updated": "Đã cập nhật",
|
||||
"Upgrade": "Nâng cấp",
|
||||
"Upgrade To {%version%}": "Nâng cấp lên {{version}}",
|
||||
"Upgrading": "Đang nâng cấp",
|
||||
"Upload Rate": "Tốc độ tải lên",
|
||||
"Uptime": "Th.gian h.động",
|
||||
"Usage reporting is always enabled for candidate releases.": "Usage reporting is always enabled for candidate releases.",
|
||||
"Use HTTPS for GUI": "Sử dụng HTTPS cho GUI",
|
||||
"Version": "Phiên bản",
|
||||
"Versions Path": "Đ.dẫn đến các ph.bản",
|
||||
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Các phiên bản sẽ tự động được xoá nếu chúng cũ hơn thời hạn tối đa hoặc vượt quá số tập tin cho phép trong một khoảng thời gian.",
|
||||
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Warning, this path is a parent directory of an existing folder \"{{otherFolder}}\".",
|
||||
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Warning, this path is a parent directory of an existing folder \"{{otherFolderLabel}}\" ({{otherFolder}}).",
|
||||
"Warning, this path is a subdirectory of an existing folder \"{%otherFolder%}\".": "Cảnh báo, đường dẫn này là thư mục con của thư mục hiện hữu \"{{otherFolder}}\".",
|
||||
"Warning, this path is a subdirectory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Warning, this path is a subdirectory of an existing folder \"{{otherFolderLabel}}\" ({{otherFolder}}).",
|
||||
"When adding a new device, keep in mind that this device must be added on the other side too.": "Khi thêm một thiết bị mới, hãy nhớ rằng thiết bị này cũng phải được thêm vào máy kia.",
|
||||
"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.": "Khi thêm một thư mục mới, hãy nhớ rằng ID thư mục được dùng để gắn kết thư mục giữa các thiết bị với nhau. Chúng phải chính xác từng chữ, cả viết hoa và thường giữa tất cả thiết bị.",
|
||||
"Yes": "Phải",
|
||||
"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 change your choice at any time in the Settings dialog.",
|
||||
"You can read more about the two release channels at the link below.": "You can read more about the two release channels at the link below.",
|
||||
"You must keep at least one version.": "Bạn phải giữ ít nhất một phiên bản.",
|
||||
"days": "ngày",
|
||||
"directories": "directories",
|
||||
"files": "files",
|
||||
"full documentation": "tài liệu đầy đủ",
|
||||
"items": "nội dung",
|
||||
"{%device%} wants to share folder \"{%folder%}\".": "{{device}} muốn chia sẻ thư mục \"{{folder}}\".",
|
||||
"{%device%} wants to share folder \"{%folderlabel%}\" ({%folder%}).": "{{device}} wants to share folder \"{{folderlabel}}\" ({{folder}})."
|
||||
}
|
||||
@@ -24,7 +24,10 @@
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "使用外部命令接管版本控制。该命令必须自行从共享文件夹中删除该文件。",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "使用外部命令接管版本控制。该命令必须自行从同步文件夹中删除该文件。",
|
||||
"Anonymous Usage Reporting": "匿名使用报告",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "匿名使用情况的报告格式已经变更。是否要迁移到新的格式?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "在中介设备上添加的任何“远程设备”,也会被自动添加到本机的“远程设备”列表。",
|
||||
"Are you sure you want to remove device {%name%}?": "Are you sure you want to remove device {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Are you sure you want to remove folder {{label}}?",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "自动升级现提供了稳定版本和发布候选版之间的选择。",
|
||||
"Automatic upgrades": "自动升级",
|
||||
"Be careful!": "小心!",
|
||||
@@ -53,6 +56,7 @@
|
||||
"Device Identification": "设备标识",
|
||||
"Device Name": "设备名",
|
||||
"Devices": "设备",
|
||||
"Disabled": "已禁用",
|
||||
"Disconnected": "连接已断开",
|
||||
"Discovered": "已发现",
|
||||
"Discovery": "设备发现",
|
||||
@@ -84,6 +88,7 @@
|
||||
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "当某个文件在其他设备被替换或删除时,本设备将在 .stversions 目录中保留该文件的备份,并在文件名中加入时间戳信息。",
|
||||
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by 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.": "在其它设备中对该文件夹内文件的修改并不会被同步到本机,但是在本机上对其的修改,则会被同步到其它设备中。",
|
||||
"Filesystem Notifications": "文件系统通知",
|
||||
"Folder": "文件夹",
|
||||
"Folder ID": "文件夹 ID",
|
||||
"Folder Label": "文件夹标签",
|
||||
@@ -136,6 +141,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 upgrades": "无更新",
|
||||
"Normal": "普通",
|
||||
"Notice": "提示",
|
||||
@@ -165,11 +171,14 @@
|
||||
"Quick guide to supported patterns": "支持的通配符的简单教程:",
|
||||
"RAM Utilization": "内存使用量",
|
||||
"Random": "随机顺序",
|
||||
"Recent Changes": "最近更改",
|
||||
"Reduced by ignore patterns": "已由忽略列表缩减",
|
||||
"Release Notes": "发布说明",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "发布候选版包含最新的特性和修复。它们跟传统的 Syncthing 双周发布版类似。",
|
||||
"Remote Devices": "远程设备",
|
||||
"Remove": "移除",
|
||||
"Remove Device": "Remove Device",
|
||||
"Remove Folder": "Remove Folder",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "需要给文件夹设置标识。在所有丛设备上必须一致。",
|
||||
"Rescan": "重新扫描",
|
||||
"Rescan All": "全部重新扫描",
|
||||
@@ -183,7 +192,9 @@
|
||||
"Save": "保存",
|
||||
"Scan Time Remaining": "扫描剩余时间",
|
||||
"Scanning": "扫描中",
|
||||
"See external versioner help for supported templated command line parameters.": "See external versioner help for supported templated command line parameters.",
|
||||
"See external versioner help for supported templated command line parameters.": "有关支持的命令行参数模板,请参阅外部的版本控制器帮助。",
|
||||
"See external versioning help for supported templated command line parameters.": "有关受支持的模板命令行参数,请参阅外部版本控制帮助。",
|
||||
"Select a version": "选择版本",
|
||||
"Select the devices to share this folder with.": "选择将本文件夹共享给哪些设备。",
|
||||
"Select the folders to share with this device.": "选择与该设备共享的文件夹。",
|
||||
"Send & Receive": "发送与接收",
|
||||
@@ -197,6 +208,7 @@
|
||||
"Shared With": "共享给",
|
||||
"Show ID": "显示 ID",
|
||||
"Show QR": "显示 QR 码",
|
||||
"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.": "在设备丛中,显示该名称,而不是设备 ID。亦会作为一个可选的默认名称被发送到其他设备。",
|
||||
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "在设备丛中,将会显示本名称,而不是设备 ID。如果设置为空,则会使用目标设备提供的默认名称。",
|
||||
"Shutdown": "关闭 Syncthing",
|
||||
@@ -252,6 +264,7 @@
|
||||
"Time": "时间",
|
||||
"Trash Can File Versioning": "回收站式版本控制",
|
||||
"Type": "类型",
|
||||
"Undecided (will prompt)": "待定(将提示)",
|
||||
"Unknown": "未知",
|
||||
"Unshared": "未共享",
|
||||
"Unused": "未使用",
|
||||
|
||||
301
gui/default/assets/lang/lang-zh-TW.json
Normal file
301
gui/default/assets/lang/lang-zh-TW.json
Normal file
@@ -0,0 +1,301 @@
|
||||
{
|
||||
"A device with that ID is already added.": "該裝置識別碼已被新增。",
|
||||
"A negative number of days doesn't make sense.": "一個負的天數並不合理。",
|
||||
"A new major version may not be compatible with previous versions.": "新的主要版本可能與以前的版本不相容。",
|
||||
"API Key": "API 金鑰",
|
||||
"About": "關於",
|
||||
"Action": "動作",
|
||||
"Actions": "操作",
|
||||
"Add": "增加",
|
||||
"Add Device": "增加裝置",
|
||||
"Add Folder": "增加資料夾",
|
||||
"Add Remote Device": "新增遠端裝置",
|
||||
"Add devices from the introducer to our device list, for mutually shared folders.": "對於共用的資料夾,匯入引入者的裝置清單。",
|
||||
"Add new folder?": "新增資料夾?",
|
||||
"Address": "位址",
|
||||
"Addresses": "位址",
|
||||
"Advanced": "進階",
|
||||
"Advanced Configuration": "進階配置",
|
||||
"Advanced settings": "進階設定",
|
||||
"All Data": "全部資料",
|
||||
"Allow Anonymous Usage Reporting?": "允許匿名的使用資訊回報?",
|
||||
"Allowed Networks": "允許的網路",
|
||||
"Alphabetic": "字母順序",
|
||||
"An external command handles the versioning. It has to remove the file from the shared folder.": "處理版本的外部指令。其必須從資料夾中刪除檔案。",
|
||||
"An external command handles the versioning. It has to remove the file from the synced folder.": "處理版本的外部指令。其必須從資料夾中刪除檔案。",
|
||||
"Anonymous Usage Reporting": "匿名的使用資訊回報",
|
||||
"Anonymous usage report format has changed. Would you like to move to the new format?": "匿名的使用資訊回報格式已經改變,你想要移至新格式嗎?",
|
||||
"Any devices configured on an introducer device will be added to this device as well.": "任何在引入者裝置所設置的裝置將會一併新增至此裝置",
|
||||
"Are you sure you want to remove device {%name%}?": "Are you sure you want to remove device {{name}}?",
|
||||
"Are you sure you want to remove folder {%label%}?": "Are you sure you want to remove folder {{label}}?",
|
||||
"Automatic upgrade now offers the choice between stable releases and release candidates.": "自動更新目前有穩定發行版及發行候選版可供選擇。",
|
||||
"Automatic upgrades": "自動升級",
|
||||
"Be careful!": "請小心!",
|
||||
"Bugs": "程式錯誤",
|
||||
"CPU Utilization": "CPU 使用",
|
||||
"Changelog": "更新日誌",
|
||||
"Clean out after": "於之後清空",
|
||||
"Click to see discovery failures": "點擊以查閱失敗的探索",
|
||||
"Close": "關閉",
|
||||
"Command": "指令",
|
||||
"Comment, when used at the start of a line": "註解,當輸入在一行的開頭時",
|
||||
"Compression": "壓縮",
|
||||
"Configured": "已設定",
|
||||
"Connection Error": "連線錯誤",
|
||||
"Connection Type": "連接類型",
|
||||
"Copied from elsewhere": "從別處複製",
|
||||
"Copied from original": "從原處複製",
|
||||
"Copyright © 2014-2016 the following Contributors:": "Copyright © 2014-2016 下列貢獻者:",
|
||||
"Copyright © 2014-2017 the following Contributors:": "Copyright © 2014-2017 下列貢獻者:",
|
||||
"Creating ignore patterns, overwriting an existing file at {%path%}.": "建立忽略樣式,覆蓋已存在的 {{path}}。",
|
||||
"Danger!": "危險!",
|
||||
"Deleted": "已刪除",
|
||||
"Device": "裝置",
|
||||
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "裝置 \"{{name}}\" ({{device}} 位於 {{address}}) 想要連線。 要增加新裝置嗎?",
|
||||
"Device ID": "裝置識別碼",
|
||||
"Device Identification": "裝置識別",
|
||||
"Device Name": "裝置名稱",
|
||||
"Devices": "裝置",
|
||||
"Disabled": "關閉",
|
||||
"Disconnected": "斷線",
|
||||
"Discovered": "已發現",
|
||||
"Discovery": "探索",
|
||||
"Discovery Failures": "探索失敗",
|
||||
"Documentation": "說明文件",
|
||||
"Download Rate": "下載速率",
|
||||
"Downloaded": "已下載",
|
||||
"Downloading": "正在下載",
|
||||
"Edit": "編輯",
|
||||
"Edit Device": "編輯裝置",
|
||||
"Edit Folder": "編輯資料夾",
|
||||
"Editing": "正在編輯",
|
||||
"Editing {%path%}.": "正在編輯 {{path}} 。",
|
||||
"Enable NAT traversal": "啟用 NAT 穿透",
|
||||
"Enable Relaying": "啟用中繼",
|
||||
"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:port\", \"tcp://host:port\"),或輸入 \"dynamic\" 以進行位址的自動探索",
|
||||
"Enter ignore patterns, one per line.": "輸入忽略樣式,每行一種。",
|
||||
"Error": "錯誤",
|
||||
"External File Versioning": "外部檔案版本控制",
|
||||
"Failed Items": "失敗的項目",
|
||||
"Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.": "若未配置 IPv6,則無法連接 IPv6 伺服器係屬正常。",
|
||||
"File Pull Order": "提取檔案的順序",
|
||||
"File Versioning": "檔案版本控制",
|
||||
"File permission bits are ignored when looking for changes. Use on FAT file systems.": "當改變時,檔案權限位元 File permission bits 會被忽略。用於 FAT 檔案系統上。",
|
||||
"Files are moved to .stversions directory when replaced or deleted by Syncthing.": "當檔案被 Syncthing 取代或刪除時,它們將被移至 .stversions 資料夾。",
|
||||
"Files are moved to .stversions folder 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 date stamped versions in a .stversions folder 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.": "其他裝置做的改變不會影響到此裝置的檔案,但在此裝置上的變化將被發送到叢集中的其他部分。",
|
||||
"Filesystem Notifications": "檔案系統通知",
|
||||
"Folder": "資料夾",
|
||||
"Folder ID": "資料夾識別碼",
|
||||
"Folder Label": "資料夾標籤",
|
||||
"Folder Path": "資料夾路徑",
|
||||
"Folder Type": "資料夾類型",
|
||||
"Folders": "資料夾",
|
||||
"GUI": "GUI",
|
||||
"GUI Authentication Password": "GUI 認證密碼",
|
||||
"GUI Authentication User": "GUI 使用者認證名稱",
|
||||
"GUI Listen Address": "GUI 監聽位址",
|
||||
"GUI Listen Addresses": "GUI 監聽位址",
|
||||
"GUI Theme": "主題",
|
||||
"Generate": "產生",
|
||||
"Global Changes": "全域變動",
|
||||
"Global Discovery": "全域探索",
|
||||
"Global Discovery Servers": "全域探索伺服器",
|
||||
"Global State": "全域狀態",
|
||||
"Help": "說明",
|
||||
"Home page": "首頁",
|
||||
"Ignore": "忽略",
|
||||
"Ignore Patterns": "忽略樣式",
|
||||
"Ignore Permissions": "忽略權限",
|
||||
"Incoming Rate Limit (KiB/s)": "傳入速率限制 (KiB/s)",
|
||||
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "不正確的設定可能會損壞您的資料夾內容,並導致 Syncthing 不正常運作。",
|
||||
"Introduced By": "引入自",
|
||||
"Introducer": "引入者",
|
||||
"Inversion of the given condition (i.e. do not exclude)": "反轉給定條件 (即:不要排除)",
|
||||
"Keep Versions": "保留歷史版本數",
|
||||
"Largest First": "最大的優先",
|
||||
"Last File Received": "最後接收的檔案",
|
||||
"Last Scan": "最後掃描",
|
||||
"Last seen": "最後發現時間",
|
||||
"Later": "稍後",
|
||||
"Latest Change": "最近變動",
|
||||
"Learn more": "瞭解更多",
|
||||
"Listeners": "監聽者",
|
||||
"Local Discovery": "本機探索",
|
||||
"Local State": "本機狀態",
|
||||
"Local State (Total)": "本機狀態 (總結)",
|
||||
"Major Upgrade": "重大更新",
|
||||
"Master": "主要的",
|
||||
"Maximum Age": "最長保留時間",
|
||||
"Metadata Only": "僅中繼資料",
|
||||
"Minimum Free Disk Space": "最少閒置磁碟空間",
|
||||
"Move to top of queue": "移到隊列頂端",
|
||||
"Multi level wildcard (matches multiple directory levels)": "多階層萬用字元 (可比對多層資料夾)",
|
||||
"Never": "從未",
|
||||
"New Device": "新裝置",
|
||||
"New Folder": "新資料夾",
|
||||
"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 upgrades": "不更新",
|
||||
"Normal": "正常的",
|
||||
"Notice": "注意",
|
||||
"OK": "確定",
|
||||
"Off": "關閉",
|
||||
"Oldest First": "最舊的優先",
|
||||
"Optional descriptive label for the folder. Can be different on each device.": "資料夾的說明標籤(選擇性)。在不同裝置上可不一致。",
|
||||
"Options": "選項",
|
||||
"Out of Sync": "不同步",
|
||||
"Out of Sync Items": "不同步物件",
|
||||
"Outgoing Rate Limit (KiB/s)": "連出速率限制 (KiB/s)",
|
||||
"Override Changes": "置換改變",
|
||||
"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 資料夾)。",
|
||||
"Path where versions should be stored (leave empty for the default .stversions folder in the folder).": "儲存歷史版本的路徑 (若為空,則預設使用資料夾中的 .stversions 資料夾)。",
|
||||
"Pause": "暫停",
|
||||
"Pause All": "全部暫停",
|
||||
"Paused": "暫停",
|
||||
"Please consult the release notes before performing a major upgrade.": "執行重大升級前請先參閱版本資訊。",
|
||||
"Please set a GUI Authentication User and Password in the Settings dialog.": "請在設定對話方塊內設置 GUI 使用者認證名稱及密碼。",
|
||||
"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": "前綴表示此樣式不區分大小寫",
|
||||
"Preview": "預覽",
|
||||
"Preview Usage Report": "預覽使用資訊報告",
|
||||
"Quick guide to supported patterns": "可支援樣式的快速指南",
|
||||
"RAM Utilization": "記憶體使用",
|
||||
"Random": "隨機",
|
||||
"Recent Changes": "Recent Changes",
|
||||
"Reduced by ignore patterns": "已由忽略樣式縮減",
|
||||
"Release Notes": "版本資訊",
|
||||
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "發行候選版包含最新的功能及修補。與傳統 Syncthing 雙週發行版相似。",
|
||||
"Remote Devices": "遠端裝置",
|
||||
"Remove": "移除",
|
||||
"Remove Device": "Remove Device",
|
||||
"Remove Folder": "Remove Folder",
|
||||
"Required identifier for the folder. Must be the same on all cluster devices.": "資料夾的識別字。必須在叢集內所有的裝置上皆相同。",
|
||||
"Rescan": "重新掃描",
|
||||
"Rescan All": "全部重新掃描",
|
||||
"Rescan Interval": "重新掃描間隔",
|
||||
"Restart": "重新啟動",
|
||||
"Restart Needed": "需要重新啟動",
|
||||
"Restarting": "正在重新啟動",
|
||||
"Resume": "繼續",
|
||||
"Resume All": "全部繼續",
|
||||
"Reused": "重用",
|
||||
"Save": "儲存",
|
||||
"Scan Time Remaining": "剩餘掃描時間",
|
||||
"Scanning": "正在掃描",
|
||||
"See external versioner help for supported templated command line parameters.": "關於命令列模板參數請參閱外部版本管理說明。",
|
||||
"See external versioning help for supported templated command line parameters.": "查看關於命令列模板參數請參閱外部版本管理說明。",
|
||||
"Select a version": "選擇一個版本",
|
||||
"Select the devices to share this folder with.": "選擇要共享這個資料夾的裝置。",
|
||||
"Select the folders to share with this device.": "選擇要共享這個資料夾的裝置。",
|
||||
"Send & Receive": "傳送及接收",
|
||||
"Send Only": "僅傳送",
|
||||
"Settings": "設定",
|
||||
"Share": "分享",
|
||||
"Share Folder": "分享資料夾",
|
||||
"Share Folders With Device": "與裝置共享資料夾",
|
||||
"Share With Devices": "與這些裝置共享",
|
||||
"Share this folder?": "分享此資料夾?",
|
||||
"Shared With": "與誰共享",
|
||||
"Show ID": "顯示識別碼",
|
||||
"Show QR": "顯示 QR 碼",
|
||||
"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 File Versioning": "簡單檔案版本控制",
|
||||
"Single level wildcard (matches within a directory only)": "單階層萬用字元 (只在單個資料夾階層內比對)",
|
||||
"Smallest First": "最小的優先",
|
||||
"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 File Versioning": "變動式檔案版本控制",
|
||||
"Start Browser": "啟動瀏覽器",
|
||||
"Statistics": "統計",
|
||||
"Stopped": "已停止",
|
||||
"Support": "支援",
|
||||
"Sync Protocol Listen Addresses": "同步通訊協定監聽位址",
|
||||
"Syncing": "正在同步",
|
||||
"Syncthing has been shut down.": "Syncthing 已經關閉。",
|
||||
"Syncthing includes the following software or portions thereof:": "Syncthing 包括以下軟體或其中的一部分:",
|
||||
"Syncthing is restarting.": "Syncthing 正在重新啟動。",
|
||||
"Syncthing is upgrading.": "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。",
|
||||
"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 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 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 first command line parameter is the folder path and the second parameter is the relative path in the folder.": "第一個命令列參數是資料夾路徑,第二個參數是在資料夾中的相對路徑。",
|
||||
"The folder ID cannot be blank.": "資料夾識別碼不能為空白。",
|
||||
"The folder ID must be unique.": "資料夾識別碼必須為獨一無二的。",
|
||||
"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 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 minimum free disk space percentage must be a non-negative number between 0 and 100 (inclusive).": "最少閒置磁碟空間的百分比必須是介於 0 到 100 (包含)的非負數。",
|
||||
"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 must be a non-negative number (0: no limit)": "限制速率必須為非負的數字 (0: 不設限制)",
|
||||
"The rescan interval must be a non-negative number of seconds.": "重新掃描間隔必須為一個非負數的秒數。",
|
||||
"They are retried automatically and will be synced when the error is resolved.": "解決間題後,將會自動重試和同步。",
|
||||
"This Device": "本機",
|
||||
"This can easily give hackers access to read and change any files on your computer.": "這能給駭客輕易的來讀取、變更電腦中的任何檔案。",
|
||||
"This is a major version upgrade.": "這是一個主要版本更新。",
|
||||
"This setting controls the free space required on the home (i.e., index database) disk.": "此設定控制家目錄(即:索引資料庫)的必須可用空間。",
|
||||
"Time": "時間",
|
||||
"Trash Can File Versioning": "垃圾筒式檔案版本控制",
|
||||
"Type": "類型",
|
||||
"Undecided (will prompt)": "未定的(將會提示)",
|
||||
"Unknown": "未知",
|
||||
"Unshared": "未共享",
|
||||
"Unused": "未使用",
|
||||
"Up to Date": "最新",
|
||||
"Updated": "已更新",
|
||||
"Upgrade": "升級",
|
||||
"Upgrade To {%version%}": "升級至 {{version}}",
|
||||
"Upgrading": "正在升級",
|
||||
"Upload Rate": "上載速率",
|
||||
"Uptime": "上線時間",
|
||||
"Usage reporting is always enabled for candidate releases.": "發行候選版永遠回報使用數據",
|
||||
"Use HTTPS for GUI": "為 GUI 使用 HTTPS",
|
||||
"Version": "版本",
|
||||
"Versions Path": "歷史版本路徑",
|
||||
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "當檔案歷史版本的存留時間大於設定的最大值,或是其數量在一段時間內超出允許值時,則會被刪除。",
|
||||
"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}}\" 的下級目錄。",
|
||||
"Warning, this path is a subdirectory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "警告,此路徑是現存資料夾 \"{{otherFolderLabel}}\" ({{otherFolder}}) 的下級目錄。",
|
||||
"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.": "當新增一個資料夾時,請記住,資料夾識別碼是用來將裝置之間的資料夾綁定在一起的。它們有區分大小寫,且必須在所有裝置之間完全相同。",
|
||||
"Yes": "是",
|
||||
"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 must keep at least one version.": "您必須保留至少一個版本。",
|
||||
"days": "日",
|
||||
"directories": "個目錄",
|
||||
"files": "個檔案",
|
||||
"full documentation": "完整說明文件",
|
||||
"items": "個項目",
|
||||
"{%device%} wants to share folder \"{%folder%}\".": "{{device}} 想要分享資料夾 \"{{folder}}\"。",
|
||||
"{%device%} wants to share folder \"{%folderlabel%}\" ({%folder%}).": "{{device}} 想要分享資料夾 \"{{folderlabel}}\" ({{folder}})。"
|
||||
}
|
||||
@@ -1 +1 @@
|
||||
var langPrettyprint = {"bg":"Bulgarian","ca@valencia":"Catalan (Valencian)","cs":"Czech","da":"Danish","de":"German","el":"Greek","en":"English","en-GB":"English (United Kingdom)","eo":"Esperanto","es":"Spanish","es-ES":"Spanish (Spain)","eu":"Basque","fi":"Finnish","fr":"French","fr-CA":"French (Canada)","fy":"Western Frisian","hu":"Hungarian","it":"Italian","ja":"Japanese","ko-KR":"Korean (Korea)","lt":"Lithuanian","nb":"Norwegian Bokmål","nl":"Dutch","nn":"Norwegian Nynorsk","pl":"Polish","pt-BR":"Portuguese (Brazil)","pt-PT":"Portuguese (Portugal)","ru":"Russian","sk":"Slovak","sv":"Swedish","tr":"Turkish","uk":"Ukrainian","vi":"Vietnamese","zh-CN":"Chinese (China)"}
|
||||
var langPrettyprint = {"bg":"Bulgarian","ca@valencia":"Catalan (Valencian)","cs":"Czech","da":"Danish","de":"German","el":"Greek","en":"English","en-GB":"English (United Kingdom)","eo":"Esperanto","es":"Spanish","es-ES":"Spanish (Spain)","eu":"Basque","fi":"Finnish","fr":"French","fr-CA":"French (Canada)","fy":"Western Frisian","hu":"Hungarian","it":"Italian","ja":"Japanese","ko-KR":"Korean (Korea)","lt":"Lithuanian","nb":"Norwegian Bokmål","nl":"Dutch","nn":"Norwegian Nynorsk","pl":"Polish","pt-BR":"Portuguese (Brazil)","pt-PT":"Portuguese (Portugal)","ru":"Russian","sk":"Slovak","sv":"Swedish","tr":"Turkish","uk":"Ukrainian","zh-CN":"Chinese (China)","zh-TW":"Chinese (Taiwan)"}
|
||||
|
||||
@@ -1 +1 @@
|
||||
var validLangs = ["bg","ca@valencia","cs","da","de","el","en","en-GB","eo","es","es-ES","eu","fi","fr","fr-CA","fy","hu","it","ja","ko-KR","lt","nb","nl","nn","pl","pt-BR","pt-PT","ru","sk","sv","tr","uk","vi","zh-CN"]
|
||||
var validLangs = ["bg","ca@valencia","cs","da","de","el","en","en-GB","eo","es","es-ES","eu","fi","fr","fr-CA","fy","hu","it","ja","ko-KR","lt","nb","nl","nn","pl","pt-BR","pt-PT","ru","sk","sv","tr","uk","zh-CN","zh-TW"]
|
||||
|
||||
@@ -368,7 +368,13 @@
|
||||
<span translate>Yes</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-if="folder.rescanIntervalS != 60">
|
||||
<tr ng-if="folder.fsNotifications">
|
||||
<th><span class="fa fa-fw fa-bolt"></span> <span translate>Filesystem Notifications</span></th>
|
||||
<td class="text-right">
|
||||
<span translate>Yes</span>
|
||||
</td>
|
||||
</tr>
|
||||
<tr ng-if="(folder.rescanIntervalS != 60 && !folder.fsNotifications) || (folder.rescanIntervalS != 3600 && folder.fsNotifications)">
|
||||
<th><span class="fa fa-fw fa-refresh"></span> <span translate>Rescan Interval</span></th>
|
||||
<td class="text-right">{{folder.rescanIntervalS}} s</td>
|
||||
</tr>
|
||||
@@ -394,9 +400,9 @@
|
||||
</tr>
|
||||
<tr>
|
||||
<th><span class="fa fa-fw fa-share-alt"></span> <span translate>Shared With</span></th>
|
||||
<td class="text-right" title="{{sharesFolder(folder)}}">{{sharesFolder(folder)}}</td>
|
||||
<td class="text-right" ng-attr-title="{{sharesFolder(folder)}}">{{sharesFolder(folder)}}</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<tr ng-if="folderStats[folder.id].lastScan">
|
||||
<th><span class="fa fa-fw fa-clock-o"></span> <span translate>Last Scan</span></th>
|
||||
<td translate ng-if="folderStats[folder.id].lastScanDays >= 365" class="text-right">Never</td>
|
||||
<td ng-if="folderStats[folder.id].lastScanDays < 365" class="text-right">
|
||||
@@ -645,7 +651,7 @@
|
||||
</tr>
|
||||
<tr ng-if="deviceFolders(deviceCfg).length > 0">
|
||||
<th><span class="fa fa-fw fa-folder"></span> <span translate>Folders</span></th>
|
||||
<td class="text-right" title="{{deviceFolders(deviceCfg).map(folderLabel).join(', ')}}">{{deviceFolders(deviceCfg).map(folderLabel).join(", ")}}</td>
|
||||
<td class="text-right" ng-attr-title="{{deviceFolders(deviceCfg).map(folderLabel).join(', ')}}">{{deviceFolders(deviceCfg).map(folderLabel).join(", ")}}</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
@@ -670,7 +676,7 @@
|
||||
<div class="form-group">
|
||||
<span class="pull-right">
|
||||
<button type="button" class="btn btn-sm btn-default" ng-click="globalChanges()">
|
||||
<span class="fa fa-fw fa-history"></span> <span translate>Global Changes</span>
|
||||
<span class="fa fa-fw fa-info-circle"></span> <span translate>Recent Changes</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-sm btn-default" ng-click="addDevice()">
|
||||
<span class="fa fa-plus"></span> <span translate>Add Remote Device</span>
|
||||
@@ -719,6 +725,8 @@
|
||||
<ng-include src="'syncthing/core/majorUpgradeModalView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/core/aboutModalView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/core/discoveryFailuresModalView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/folder/removeFolderDialogView.html'"></ng-include>
|
||||
<ng-include src="'syncthing/device/removeDeviceDialogView.html'"></ng-include>
|
||||
|
||||
<!-- vendor scripts -->
|
||||
<script type="text/javascript" src="vendor/jquery/jquery-2.2.2.js"></script>
|
||||
@@ -750,6 +758,7 @@
|
||||
<script type="text/javascript" src="syncthing/core/selectOnClickDirective.js"></script>
|
||||
<script type="text/javascript" src="syncthing/core/syncthingController.js"></script>
|
||||
<script type="text/javascript" src="syncthing/core/tooltipDirective.js"></script>
|
||||
<script type="text/javascript" src="syncthing/core/uncamelFilter.js"></script>
|
||||
<script type="text/javascript" src="syncthing/core/uniqueFolderDirective.js"></script>
|
||||
<script type="text/javascript" src="syncthing/core/validDeviceidDirective.js"></script>
|
||||
<script type="text/javascript" src="assets/lang/valid-langs.js"></script>
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<p translate>Copyright © 2014-2017 the following Contributors:</p>
|
||||
<div class="row">
|
||||
<div class="col-md-12" id="contributor-list">
|
||||
Jakob Borg, Audrius Butkevicius, Alexander Graf, Anderson Mesquita, Antony Male, Ben Schulz, Caleb Callaway, Daniel Harte, Lars K.W. Gohlke, Lode Hoste, Michael Ploujnikov, Nate Morrison, Philippe Schommers, Ryan Sullivan, Sergey Mishin, Simon Frei, Stefan Tatschner, Aaron Bieber, Adam Piggott, Adel Qalieh, Alessandro G., Alexandre Viau, Andrew Dunham, Andrey D, Antoine Lamielle, Arthur Axel fREW Schmidt, Bart De Vries, Ben Curthoys, Ben Shepherd, Ben Sidhom, Benny Ng, Brandon Philips, Brendan Long, Brian R. Becker, Carsten Hagemann, Cathryne Linenweaver, Cedric Staniewski, Chris Howie, Chris Joel, Colin Kennedy, Daniel Bergmann, Daniel Martí, Darshil Chanpura, David Rimmer, Denis A., Dennis Wilson, Dominik Heidler, Elias Jarlebring, Emil Hessman, Erik Meitner, Federico Castagnini, Felix Ableitner, Felix Unterpaintner, Francois-Xavier Gsell, Frank Isemann, Gilli Sigurdsson, Heiko Zuerker, Jaakko Hannikainen, Jacek Szafarkiewicz, Jake Peterson, James Patterson, Jaroslav Malec, Jaya Chithra, Jens Diemer, Jochen Voss, Johan Vromans, Jose Manuel Delicado, Karol Różycki, Kelong Cong, Ken'ichi Kamada, Kevin Allen, Kevin White, Jr., Kurt Fitzner, Laurent Etiemble, Leo Arias, Liu Siyuan, Lord Landon Agahnim, Majed Abdulaziz, Marc Laporte, Marc Pujol, Marcin Dziadus, Mark Pulford, Mateusz Naściszewski, Matt Burke, Max Schulze, Michael Jephcote, Michael Tilli, Niels Peter Roest, Pascal Jungblut, Peter Hoeg, Phill Luby, Piotr Bejda, Robert Carosi, Roman Zaynetdinov, Ross Smith II, Sacheendra Talluri, Scott Klupfel, Stefan Kuntz, Suhas Gundimeda, Tim Abell, Tim Howes, Tobias Nygren, Tomas Cerveny, Tully Robinson, Tyler Brazier, Unrud, Veeti Paananen, Victor Buinsky, Vil Brekin, William A. Kennington III, Wulf Weich, Xavier O., Yannic A.
|
||||
Jakob Borg, Audrius Butkevicius, Alexander Graf, Anderson Mesquita, Antony Male, Ben Schulz, Caleb Callaway, Daniel Harte, Lars K.W. Gohlke, Lode Hoste, Michael Ploujnikov, Nate Morrison, Philippe Schommers, Ryan Sullivan, Sergey Mishin, Simon Frei, Stefan Tatschner, Aaron Bieber, Adam Piggott, Adel Qalieh, Alessandro G., Alexandre Viau, Andrew Dunham, Andrey D, Antoine Lamielle, Arthur Axel fREW Schmidt, Bart De Vries, Ben Curthoys, Ben Shepherd, Ben Sidhom, Benny Ng, Brandon Philips, Brendan Long, Brian R. Becker, Carsten Hagemann, Cathryne Linenweaver, Cedric Staniewski, Chris Howie, Chris Joel, Colin Kennedy, Daniel Bergmann, Daniel Martí, Darshil Chanpura, David Rimmer, Denis A., Dennis Wilson, Dmitry Saveliev, Dominik Heidler, Elias Jarlebring, Emil Hessman, Erik Meitner, Federico Castagnini, Felix Ableitner, Felix Unterpaintner, Francois-Xavier Gsell, Frank Isemann, Gilli Sigurdsson, Heiko Zuerker, Jaakko Hannikainen, Jacek Szafarkiewicz, Jake Peterson, James Patterson, Jaroslav Malec, Jaya Chithra, Jens Diemer, Jochen Voss, Johan Vromans, Jose Manuel Delicado, Karol Różycki, Kelong Cong, Ken'ichi Kamada, Kevin Allen, Kevin White, Jr., Kurt Fitzner, Laurent Etiemble, Leo Arias, Liu Siyuan, Lord Landon Agahnim, Majed Abdulaziz, Marc Laporte, Marc Pujol, Marcin Dziadus, Mark Pulford, Mateusz Naściszewski, Matt Burke, Max Schulze, Michael Jephcote, Michael Tilli, Niels Peter Roest, Pascal Jungblut, Pawel Palenica, Peter Hoeg, Phill Luby, Piotr Bejda, Robert Carosi, Roman Zaynetdinov, Ross Smith II, Sacheendra Talluri, Scott Klupfel, Stefan Kuntz, Suhas Gundimeda, Taylor Khan, Tim Abell, Tim Howes, Tobias Nygren, Tobias Tom, Tomas Cerveny, Tully Robinson, Tyler Brazier, Unrud, Veeti Paananen, Victor Buinsky, Vil Brekin, William A. Kennington III, Wulf Weich, Xavier O., Yannic A.
|
||||
</div>
|
||||
</div>
|
||||
<hr/>
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
angular.module('syncthing.core')
|
||||
.directive('modal', function () {
|
||||
return {
|
||||
// If you ever change any of the petroglyphs below, please search for $parent.$parent,
|
||||
// as some templates rely on the way scope is composed in this case.
|
||||
restrict: 'E',
|
||||
templateUrl: 'modal.html',
|
||||
replace: true,
|
||||
|
||||
@@ -2,7 +2,7 @@ angular.module('syncthing.core')
|
||||
.config(function($locationProvider) {
|
||||
$locationProvider.html5Mode({enabled: true, requireBase: false}).hashPrefix('!');
|
||||
})
|
||||
.controller('SyncthingController', function ($scope, $http, $location, LocaleService, Events, $filter) {
|
||||
.controller('SyncthingController', function ($scope, $http, $location, LocaleService, Events, $filter, $q) {
|
||||
'use strict';
|
||||
|
||||
// private/helper definitions
|
||||
@@ -33,6 +33,9 @@ angular.module('syncthing.core')
|
||||
$scope.folderRejections = {};
|
||||
$scope.protocolChanged = false;
|
||||
$scope.reportData = {};
|
||||
$scope.reportDataPreview = '';
|
||||
$scope.reportDataPreviewVersion = '';
|
||||
$scope.reportDataPreviewDiff = false;
|
||||
$scope.reportPreview = false;
|
||||
$scope.folders = {};
|
||||
$scope.seenError = '';
|
||||
@@ -47,7 +50,6 @@ angular.module('syncthing.core')
|
||||
$scope.neededPageSize = 10;
|
||||
$scope.failed = {};
|
||||
$scope.failedCurrentPage = 1;
|
||||
$scope.failedCurrentFolder = undefined;
|
||||
$scope.failedPageSize = 10;
|
||||
$scope.scanProgress = {};
|
||||
$scope.themes = [];
|
||||
@@ -63,6 +65,7 @@ angular.module('syncthing.core')
|
||||
selectedDevices: {},
|
||||
type: "readwrite",
|
||||
rescanIntervalS: 60,
|
||||
fsWatcherDelayS: 10,
|
||||
minDiskFree: {value: 1, unit: "%"},
|
||||
maxConflicts: 10,
|
||||
fsync: true,
|
||||
@@ -134,6 +137,10 @@ angular.module('syncthing.core')
|
||||
|
||||
$http.get(urlbase + '/svc/report').success(function (data) {
|
||||
$scope.reportData = data;
|
||||
if ($scope.system && $scope.config.options.urAccepted > -1 && $scope.config.options.urSeen < $scope.system.urVersionMax && $scope.config.options.urAccepted < $scope.system.urVersionMax) {
|
||||
// Usage reporting format has changed, prompt the user to re-accept.
|
||||
$('#ur').modal();
|
||||
}
|
||||
}).error($scope.emitHTTPError);
|
||||
|
||||
$http.get(urlbase + '/system/upgrade').success(function (data) {
|
||||
@@ -376,6 +383,7 @@ angular.module('syncthing.core')
|
||||
$scope.config = config;
|
||||
$scope.config.options._listenAddressesStr = $scope.config.options.listenAddresses.join(', ');
|
||||
$scope.config.options._globalAnnounceServersStr = $scope.config.options.globalAnnounceServers.join(', ');
|
||||
$scope.config.options._urAcceptedStr = "" + $scope.config.options.urAccepted;
|
||||
|
||||
$scope.devices = $scope.config.devices;
|
||||
$scope.devices.forEach(function (deviceCfg) {
|
||||
@@ -412,6 +420,10 @@ angular.module('syncthing.core')
|
||||
$scope.myID = data.myID;
|
||||
$scope.system = data;
|
||||
|
||||
if ($scope.reportDataPreviewVersion === '') {
|
||||
$scope.reportDataPreviewVersion = $scope.system.urVersionMax;
|
||||
}
|
||||
|
||||
var listenersFailed = [];
|
||||
for (var address in data.connectionServiceStatus) {
|
||||
if (data.connectionServiceStatus[address].error) {
|
||||
@@ -1058,7 +1070,6 @@ angular.module('syncthing.core')
|
||||
$scope.editSettings = function () {
|
||||
// Make a working copy
|
||||
$scope.tmpOptions = angular.copy($scope.config.options);
|
||||
$scope.tmpOptions.urEnabled = ($scope.tmpOptions.urAccepted > 0);
|
||||
$scope.tmpOptions.deviceName = $scope.thisDevice().name;
|
||||
$scope.tmpOptions.upgrades = "none";
|
||||
if ($scope.tmpOptions.autoUpgradeIntervalH > 0) {
|
||||
@@ -1088,18 +1099,31 @@ angular.module('syncthing.core')
|
||||
}).error($scope.emitHTTPError);
|
||||
};
|
||||
|
||||
$scope.urVersions = function() {
|
||||
var result = [];
|
||||
if ($scope.system) {
|
||||
for (var i = $scope.system.urVersionMax; i >= 2; i--) {
|
||||
result.push("" + i);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
$scope.saveSettings = function () {
|
||||
// Make sure something changed
|
||||
var changed = !angular.equals($scope.config.options, $scope.tmpOptions) || !angular.equals($scope.config.gui, $scope.tmpGUI);
|
||||
var themeChanged = $scope.config.gui.theme !== $scope.tmpGUI.theme;
|
||||
if (changed) {
|
||||
// Angular has issues with selects with numeric values, so we handle strings here.
|
||||
$scope.tmpOptions.urAccepted = parseInt($scope.tmpOptions._urAcceptedStr);
|
||||
// Check if auto-upgrade has been enabled or disabled. This
|
||||
// also has an effect on usage reporting, so do the check
|
||||
// for that later.
|
||||
if ($scope.tmpOptions.upgrades == "candidate") {
|
||||
$scope.tmpOptions.autoUpgradeIntervalH = $scope.tmpOptions.autoUpgradeIntervalH || 12;
|
||||
$scope.tmpOptions.upgradeToPreReleases = true;
|
||||
$scope.tmpOptions.urEnabled = true;
|
||||
$scope.tmpOptions.urAccepted = $scope.system.urVersionMax;
|
||||
$scope.tmpOptions.urSeen = $scope.system.urVersionMax;
|
||||
} else if ($scope.tmpOptions.upgrades == "stable") {
|
||||
$scope.tmpOptions.autoUpgradeIntervalH = $scope.tmpOptions.autoUpgradeIntervalH || 12;
|
||||
$scope.tmpOptions.upgradeToPreReleases = false;
|
||||
@@ -1107,13 +1131,6 @@ angular.module('syncthing.core')
|
||||
$scope.tmpOptions.autoUpgradeIntervalH = 0;
|
||||
}
|
||||
|
||||
// Check if usage reporting has been enabled or disabled
|
||||
if ($scope.tmpOptions.urEnabled && $scope.tmpOptions.urAccepted <= 0) {
|
||||
$scope.tmpOptions.urAccepted = 1000;
|
||||
} else if (!$scope.tmpOptions.urEnabled && $scope.tmpOptions.urAccepted > 0) {
|
||||
$scope.tmpOptions.urAccepted = -1;
|
||||
}
|
||||
|
||||
// Check if protocol will need to be changed on restart
|
||||
if ($scope.config.gui.useTLS !== $scope.tmpGUI.useTLS) {
|
||||
$scope.protocolChanged = true;
|
||||
@@ -1691,13 +1708,17 @@ angular.module('syncthing.core')
|
||||
};
|
||||
|
||||
$scope.acceptUR = function () {
|
||||
$scope.config.options.urAccepted = 1000; // Larger than the largest existing report version
|
||||
$scope.config.options.urAccepted = $scope.system.urVersionMax;
|
||||
$scope.config.options.urSeen = $scope.system.urVersionMax;
|
||||
$scope.saveConfig();
|
||||
$('#ur').modal('hide');
|
||||
};
|
||||
|
||||
$scope.declineUR = function () {
|
||||
$scope.config.options.urAccepted = -1;
|
||||
if ($scope.config.options.urAccepted === 0) {
|
||||
$scope.config.options.urAccepted = -1;
|
||||
}
|
||||
$scope.config.options.urSeen = $scope.system.urVersionMax;
|
||||
$scope.saveConfig();
|
||||
$('#ur').modal('hide');
|
||||
};
|
||||
@@ -1747,6 +1768,31 @@ angular.module('syncthing.core')
|
||||
$scope.reportPreview = true;
|
||||
};
|
||||
|
||||
$scope.refreshReportDataPreview = function () {
|
||||
$scope.reportDataPreview = '';
|
||||
if (!$scope.reportDataPreviewVersion) {
|
||||
return;
|
||||
}
|
||||
var version = parseInt($scope.reportDataPreviewVersion);
|
||||
if ($scope.reportDataPreviewDiff && version > 2) {
|
||||
$q.all([
|
||||
$http.get(urlbase + '/svc/report?version=' + version),
|
||||
$http.get(urlbase + '/svc/report?version=' + (version-1)),
|
||||
]).then(function (responses) {
|
||||
var newReport = responses[0].data;
|
||||
var oldReport = responses[1].data;
|
||||
angular.forEach(oldReport, function(_, key) {
|
||||
delete newReport[key];
|
||||
});
|
||||
$scope.reportDataPreview = newReport;
|
||||
});
|
||||
} else {
|
||||
$http.get(urlbase + '/svc/report?version=' + version).success(function (data) {
|
||||
$scope.reportDataPreview = data;
|
||||
}).error($scope.emitHTTPError);
|
||||
}
|
||||
};
|
||||
|
||||
$scope.rescanAllFolders = function () {
|
||||
$http.post(urlbase + "/db/scan");
|
||||
};
|
||||
|
||||
27
gui/default/syncthing/core/uncamelFilter.js
Normal file
27
gui/default/syncthing/core/uncamelFilter.js
Normal file
@@ -0,0 +1,27 @@
|
||||
angular.module('syncthing.core')
|
||||
.filter('uncamel', function () {
|
||||
return function (input) {
|
||||
input = input.replace(/(.)([A-Z][a-z]+)/g, '$1 $2').replace(/([a-z0-9])([A-Z])/g, '$1 $2');
|
||||
var parts = input.split(' ');
|
||||
var lastPart = parts.splice(-1)[0];
|
||||
switch (lastPart) {
|
||||
case "S":
|
||||
parts.push('(seconds)');
|
||||
break;
|
||||
case "M":
|
||||
parts.push('(minutes)');
|
||||
break;
|
||||
case "H":
|
||||
parts.push('(hours)');
|
||||
break;
|
||||
case "Ms":
|
||||
parts.push('(milliseconds)');
|
||||
break;
|
||||
default:
|
||||
parts.push(lastPart);
|
||||
break;
|
||||
}
|
||||
input = parts.join(' ');
|
||||
return input.charAt(0).toUpperCase() + input.slice(1);
|
||||
};
|
||||
});
|
||||
@@ -24,31 +24,59 @@
|
||||
</div>
|
||||
<div ng-if="editingExisting" class="well well-sm text-monospace" select-on-click>{{currentDevice.deviceID}}</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label translate for="name">Device Name</label>
|
||||
<input id="name" class="form-control" type="text" ng-model="currentDevice.name" />
|
||||
<p translate ng-if="currentDevice.deviceID == myID" class="help-block">Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.</p>
|
||||
<p translate ng-if="currentDevice.deviceID != myID" class="help-block">Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.</p>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label translate for="name">Device Name</label>
|
||||
<input id="name" class="form-control" type="text" ng-model="currentDevice.name" />
|
||||
<p translate ng-if="currentDevice.deviceID == myID" class="help-block">Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.</p>
|
||||
<p translate ng-if="currentDevice.deviceID != myID" class="help-block">Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label translate for="addresses">Addresses</label>
|
||||
<input ng-disabled="currentDevice.deviceID == myID" id="addresses" class="form-control" type="text" ng-model="currentDevice._addressesStr"></input>
|
||||
<p translate class="help-block">Enter comma separated ("tcp://ip:port", "tcp://host:port") addresses or "dynamic" to perform automatic discovery of the address.</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label translate for="addresses">Addresses</label>
|
||||
<input ng-disabled="currentDevice.deviceID == myID" id="addresses" class="form-control" type="text" ng-model="currentDevice._addressesStr"></input>
|
||||
<p translate class="help-block">Enter comma separated ("tcp://ip:port", "tcp://host:port") addresses or "dynamic" to perform automatic discovery of the address.</p>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label translate>Compression</label>
|
||||
<select class="form-control" ng-model="currentDevice.compression">
|
||||
<option value="always" translate>All Data</option>
|
||||
<option value="metadata" translate>Metadata Only</option>
|
||||
<option value="never" translate>Off</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label translate>Compression</label>
|
||||
<select class="form-control" ng-model="currentDevice.compression">
|
||||
<option value="always" translate>All Data</option>
|
||||
<option value="metadata" translate>Metadata Only</option>
|
||||
<option value="never" translate>Off</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="currentDevice.introducer"> <span translate>Introducer</span>
|
||||
</label>
|
||||
<p translate class="help-block">Add devices from the introducer to our device list, for mutually shared folders.</p>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="currentDevice.introducer">
|
||||
<span translate>Introducer</span>
|
||||
<p translate class="help-block">Add devices from the introducer to our device list, for mutually shared folders.</p>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="currentDevice.autoAcceptFolders">
|
||||
<span translate>Auto Accept</span>
|
||||
<p translate class="help-block">Automatically create or share folders that this device advertises at the default path.</p>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
@@ -87,7 +115,7 @@
|
||||
<button type="button" class="btn btn-warning btn-sm disabled" ng-if="willBeReintroducedBy" tooltip data-original-title="This device will be reintroduced by {{ willBeReintroducedBy }}">
|
||||
<span class="fa fa-minus-circle"></span> <span translate>Remove</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-warning btn-sm" ng-click="deleteDevice()" ng-if="!willBeReintroducedBy">
|
||||
<button type="button" class="btn btn-warning btn-sm" data-toggle="modal" data-target="#remove-device-confirmation" ng-if="!willBeReintroducedBy">
|
||||
<span class="fa fa-minus-circle"></span> <span translate>Remove</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<style> th, td { padding: 6px; } </style>
|
||||
<modal id="globalChanges" status="default" icon="{{'history'}}" heading="{{'Global Changes' | translate}}" large="yes" closeable="yes">
|
||||
<modal id="globalChanges" status="default" icon="{{'info-circle'}}" heading="{{'Recent Changes' | translate}}" large="yes" closeable="yes">
|
||||
<div class="modal-body">
|
||||
<table>
|
||||
<thead>
|
||||
|
||||
15
gui/default/syncthing/device/removeDeviceDialogView.html
Normal file
15
gui/default/syncthing/device/removeDeviceDialogView.html
Normal file
@@ -0,0 +1,15 @@
|
||||
<modal id="remove-device-confirmation" status="warning" icon="exclamation-circle" heading="{{'Remove Device' | translate}}" large="no" closeable="yes">
|
||||
<div class="modal-body">
|
||||
<p ng-model="currentDevice.name" style=" overflow : hidden; text-overflow: ellipsis; white-space: nowrap;">
|
||||
<span translate translate-value-name="{{currentDevice.name}}">Are you sure you want to remove device {%name%}?</span>
|
||||
</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-warning pull-left btn-sm" data-dismiss="modal" ng-click="deleteDevice()">
|
||||
<span class="fa fa-minus-circle"></span> <span translate>Yes</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-default btn-sm" data-dismiss="modal">
|
||||
<span class="fa fa-times"></span> <span translate>No</span>
|
||||
</button>
|
||||
</div>
|
||||
</modal>
|
||||
@@ -180,7 +180,7 @@
|
||||
<label translate for="externalCommand">Command</label>
|
||||
<input name="externalCommand" id="externalCommand" class="form-control" type="text" ng-model="currentFolder.externalCommand" required="" aria-required="true" />
|
||||
<p class="help-block">
|
||||
<span translate ng-if="folderEditor.externalCommand.$valid || folderEditor.externalCommand.$pristine">See external versioner help for supported templated command line parameters.</span>
|
||||
<span translate ng-if="folderEditor.externalCommand.$valid || folderEditor.externalCommand.$pristine">See external versioning help for supported templated command line parameters.</span>
|
||||
<span translate ng-if="folderEditor.externalCommand.$error.required && folderEditor.externalCommand.$dirty">The path cannot be blank.</span>
|
||||
</p>
|
||||
</div>
|
||||
@@ -199,7 +199,7 @@
|
||||
<button type="button" class="btn btn-default btn-sm" data-dismiss="modal">
|
||||
<span class="fa fa-times"></span> <span translate>Close</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-warning pull-left btn-sm" ng-click="deleteFolder(currentFolder.id)" ng-if="editingExisting">
|
||||
<button type="button" class="btn btn-warning pull-left btn-sm" data-toggle="modal" data-target="#remove-folder-confirmation" ng-if="editingExisting">
|
||||
<span class="fa fa-minus-circle"></span> <span translate>Remove</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
18
gui/default/syncthing/folder/removeFolderDialogView.html
Normal file
18
gui/default/syncthing/folder/removeFolderDialogView.html
Normal file
@@ -0,0 +1,18 @@
|
||||
<modal id="remove-folder-confirmation" status="warning" icon="exclamation-circle" heading="{{'Remove Folder' | translate}}" large="no" closeable="yes">
|
||||
<div class="modal-body">
|
||||
<p ng-model="currentFolder.label" style=" overflow : hidden; text-overflow: ellipsis; white-space: nowrap;">
|
||||
<span translate translate-value-label="{{currentFolder.label}}">Are you sure you want to remove folder {%label%}?</span>
|
||||
</p>
|
||||
<p translate>
|
||||
No files will be deleted as a result of this operation.
|
||||
</p>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-warning pull-left btn-sm" data-dismiss="modal" ng-click="deleteFolder(currentFolder.id)">
|
||||
<span class="fa fa-minus-circle"></span> <span translate>Yes</span>
|
||||
</button>
|
||||
<button type="button" class="btn btn-default btn-sm" data-dismiss="modal">
|
||||
<span class="fa fa-times"></span> <span translate>No</span>
|
||||
</button>
|
||||
</div>
|
||||
</modal>
|
||||
@@ -16,7 +16,7 @@
|
||||
<div class="panel-body">
|
||||
<form class="form-horizontal" role="form">
|
||||
<div ng-repeat="(key, value) in advancedConfig.gui" ng-init="type = inputTypeFor(key, value)" ng-if="type != 'skip'" class="form-group">
|
||||
<label for="guiInput{{$index}}" class="col-sm-4 control-label">{{key}}</label>
|
||||
<label for="guiInput{{$index}}" class="col-sm-4 control-label">{{key | uncamel}}</label>
|
||||
<div class="col-sm-8">
|
||||
<input ng-if="inputTypeFor(key, value) == 'list'" id="optionsInput{{$index}}" class="form-control" type="text" ng-model="advancedConfig.gui[key]" ng-list/>
|
||||
<input ng-if="inputTypeFor(key, value) != 'list'" id="optionsInput{{$index}}" class="form-control" type="{{inputTypeFor(key, value)}}" ng-model="advancedConfig.gui[key]" />
|
||||
@@ -35,7 +35,7 @@
|
||||
<div class="panel-body">
|
||||
<form class="form-horizontal" role="form">
|
||||
<div ng-repeat="(key, value) in advancedConfig.options" ng-if="inputTypeFor(key, value) != 'skip'" class="form-group">
|
||||
<label for="optionsInput{{$index}}" class="col-sm-4 control-label">{{key}}</label>
|
||||
<label for="optionsInput{{$index}}" class="col-sm-4 control-label">{{key | uncamel}}</label>
|
||||
<div class="col-sm-8">
|
||||
<input ng-if="inputTypeFor(key, value) == 'list'" id="optionsInput{{$index}}" class="form-control" type="text" ng-model="advancedConfig.options[key]" ng-list/>
|
||||
<input ng-if="inputTypeFor(key, value) != 'list'" id="optionsInput{{$index}}" class="form-control" type="{{inputTypeFor(key, value)}}" ng-model="advancedConfig.options[key]" />
|
||||
@@ -59,7 +59,7 @@
|
||||
<div class="panel-body">
|
||||
<form class="form-horizontal" role="form">
|
||||
<div ng-repeat="(key, value) in folder" ng-if="inputTypeFor(key, value) != 'skip'" class="form-group">
|
||||
<label for="folder{{$index}}Input{{$index}}" class="col-sm-4 control-label">{{key}}</label>
|
||||
<label for="folder{{$index}}Input{{$index}}" class="col-sm-4 control-label">{{key | uncamel}}</label>
|
||||
<div class="col-sm-8">
|
||||
<input ng-if="inputTypeFor(key, value) == 'list'" id="optionsInput{{$index}}" class="form-control" type="text" ng-model="folder[key]" ng-list/>
|
||||
<input ng-if="inputTypeFor(key, value) != 'list'" id="optionsInput{{$index}}" class="form-control" type="{{inputTypeFor(key, value)}}" ng-model="folder[key]" />
|
||||
@@ -80,7 +80,7 @@
|
||||
<div class="panel-body">
|
||||
<form class="form-horizontal" role="form">
|
||||
<div ng-repeat="(key, value) in device" ng-if="inputTypeFor(key, value) != 'skip'" class="form-group">
|
||||
<label for="device{{$index}}Input{{$index}}" class="col-sm-4 control-label">{{key}}</label>
|
||||
<label for="device{{$index}}Input{{$index}}" class="col-sm-4 control-label">{{key | uncamel}}</label>
|
||||
<div class="col-sm-8">
|
||||
<input ng-if="inputTypeFor(key, value) == 'list'" id="optionsInput{{$index}}" class="form-control" type="text" ng-model="device[key]" ng-list/>
|
||||
<input ng-if="inputTypeFor(key, value) != 'list'" id="optionsInput{{$index}}" class="form-control" type="{{inputTypeFor(key, value)}}" ng-model="device[key]" />
|
||||
|
||||
@@ -1,36 +1,180 @@
|
||||
<modal id="settings" status="default" icon="cog" heading="{{'Settings' | translate}}" large="yes" closeable="yes">
|
||||
<div class="modal-body">
|
||||
<form role="form" name="settingsEditor">
|
||||
<div class="row">
|
||||
|
||||
<div class="col-md-6">
|
||||
<ul class="nav nav-tabs">
|
||||
<li class="active"><a data-toggle="tab" href="#settings-general" translate>General</a></li>
|
||||
<li><a data-toggle="tab" href="#settings-gui" translate>GUI</a></li>
|
||||
<li><a data-toggle="tab" href="#settings-connections" translate>Connections</a></li>
|
||||
</ul>
|
||||
<div class="tab-content">
|
||||
<div id="settings-general" class="tab-pane in active">
|
||||
<div class="form-group">
|
||||
<label translate for="DeviceName">Device Name</label>
|
||||
<input id="DeviceName" class="form-control" type="text" ng-model="tmpOptions.deviceName"/>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-horizontal">
|
||||
<div class="form-group" ng-class="{'has-error': settingsEditor.minHomeDiskFree.$invalid && settingsEditor.minHomeDiskFree.$dirty}">
|
||||
<label class="col-xs-12" for="minHomeDiskFree"><span translate>Minimum Free Disk Space</span></label><br/>
|
||||
<div class="col-xs-9"><input name="minHomeDiskFree" id="minHomeDiskFree" class="form-control" type="number" ng-model="tmpOptions.minHomeDiskFree.value" required="" aria-required="true" min="0" step="0.01"/></div>
|
||||
<div class="col-xs-3"><select class="col-sm-3 form-control" ng-model="tmpOptions.minHomeDiskFree.unit">
|
||||
<option value="%">%</option>
|
||||
<option value="kB">kB</option>
|
||||
<option value="MB">MB</option>
|
||||
<option value="GB">GB</option>
|
||||
<option value="TB">TB</option>
|
||||
</select></div>
|
||||
<p class="col-xs-12 help-block">
|
||||
<span translate ng-show="settingsEditor.minHomeDiskFree.$invalid">Enter a non-negative number (e.g., "2.35") and select a unit. Percentages are as part of the total disk size.</span>
|
||||
<span translate ng-hide="settingsEditor.minHomeDiskFree.$invalid">This setting controls the free space required on the home (i.e., index database) disk.</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label translate>API Key</label>
|
||||
<div class="input-group">
|
||||
<input type="text" readonly class="text-monospace form-control" value="{{tmpGUI.apiKey || '-'}}"/>
|
||||
<span class="input-group-btn">
|
||||
<button type="button" class="btn btn-default btn-secondary" ng-click="setAPIKey(tmpGUI)">
|
||||
<span class="fa fa-repeat"></span> <span translate>Generate</span>
|
||||
</button>
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<div ng-if="tmpOptions.upgrades != 'candidate'">
|
||||
<label translate for="urVersion">Anonymous Usage Reporting</label> (<a href="" translate data-toggle="modal" data-target="#urPreview">Preview</a>)
|
||||
<select class="form-control" id="urVersion" ng-model="tmpOptions._urAcceptedStr">
|
||||
<option ng-repeat="n in urVersions()" value="{{n}}">{{'Version' | translate}} {{n}}</option>
|
||||
<!-- 1 does not exist, as we did not support incremental formats back then. -->
|
||||
<option value="0" translate>Undecided (will prompt)</option>
|
||||
<option value="-1" translate>Disabled</option>
|
||||
</select>
|
||||
</div>
|
||||
<p class="help-block" ng-if="tmpOptions.upgrades == 'candidate'">
|
||||
<span translate>Usage reporting is always enabled for candidate releases.</span> (<a href="" translate data-toggle="modal" data-target="#urPreview">Preview</a>)
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label translate>Automatic upgrades</label> <a href="https://docs.syncthing.net/users/releases.html" target="_blank"><span class="fa fa-fw fa-book"></span> <span translate>Help</span></a>
|
||||
<select class="form-control" ng-model="tmpOptions.upgrades" ng-if="upgradeInfo">
|
||||
<option value="none" translate>No upgrades</option>
|
||||
<option value="stable" translate>Stable releases only</option>
|
||||
<option value="candidate" translate>Stable releases and release candidates</option>
|
||||
</select>
|
||||
<p class="help-block" ng-if="!upgradeInfo">
|
||||
<span translate>Unavailable/Disabled by administrator or maintainer</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label translate for="urVersion">Default Folder Path</label>
|
||||
<input id="DefaultFolderPath" class="form-control" type="text" ng-model="tmpOptions.defaultFolderPath"/>
|
||||
<p class="help-block">
|
||||
<span translate translate-value-tilde="{{system.tilde}}">
|
||||
Path where new auto accepted folders will be created, as well as the default suggested path when adding new folders via the UI. Tilde character (~) expands to {%tilde%}.
|
||||
</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="settings-gui" class="tab-pane">
|
||||
<div class="form-group" ng-class="{'has-error': settingsEditor.Address.$invalid && settingsEditor.Address.$dirty}">
|
||||
<label translate for="Address">GUI Listen Address</label> <a href="https://docs.syncthing.net/users/guilisten.html" target="_blank"><span class="fa fa-fw fa-book"></span> <span translate>Help</span></a>
|
||||
<input id="Address" name="Address" class="form-control" type="text" ng-model="tmpGUI.address" ng-pattern="/.*:0*((102[4-9])|(10[3-9][0-9])|(1[1-9][0-9][0-9])|([2-9][0-9][0-9][0-9])|([1-6]\d{4}))$/"/>
|
||||
<p class="help-block" ng-show="settingsEditor.Address.$invalid" translate>
|
||||
Enter a non-privileged port number (1024 - 65535).
|
||||
</p>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label translate for="User">GUI Authentication User</label>
|
||||
<input id="User" class="form-control" type="text" ng-model="tmpGUI.user"/>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label translate for="Password">GUI Authentication Password</label>
|
||||
<input id="Password" class="form-control" type="password" ng-model="tmpGUI.password" ng-trim="false"/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input id="UseTLS" type="checkbox" ng-model="tmpGUI.useTLS"/> <span translate>Use HTTPS for GUI</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input id="StartBrowser" type="checkbox" ng-model="tmpOptions.startBrowser"/> <span translate>Start Browser</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label translate>GUI Theme</label>
|
||||
<select class="form-control" ng-model="tmpGUI.theme" ng-if="themes.length > 1">
|
||||
<option ng-repeat="theme in themes.sort()" value="{{ theme }}">
|
||||
{{ themeName(theme) }}
|
||||
</option>
|
||||
</select>
|
||||
<p class="help-block" ng-if="themes.length < 2">
|
||||
<span translate>Unavailable</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div id="settings-connections" class="tab-pane">
|
||||
<div class="form-group">
|
||||
<label translate for="ListenAddressesStr">Sync Protocol Listen Addresses</label> <a href="https://docs.syncthing.net/users/config.html#listen-addresses" target="_blank"><span class="fa fa-fw fa-book"></span> <span translate>Help</span></a>
|
||||
|
||||
<input id="ListenAddressesStr" class="form-control" type="text" ng-model="tmpOptions._listenAddressesStr"/>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{'has-error': settingsEditor.MaxRecvKbps.$invalid && settingsEditor.MaxRecvKbps.$dirty}">
|
||||
<label translate for="MaxRecvKbps">Incoming Rate Limit (KiB/s)</label>
|
||||
<input id="MaxRecvKbps" name="MaxRecvKbps" class="form-control" type="number" ng-model="tmpOptions.maxRecvKbps" min="0"/>
|
||||
<p class="help-block">
|
||||
<span translate ng-if="settingsEditor.MaxRecvKbps.$error.min && settingsEditor.MaxRecvKbps.$dirty">The rate limit must be a non-negative number (0: no limit)</span>
|
||||
</p>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group" ng-class="{'has-error': settingsEditor.MaxRecvKbps.$invalid && settingsEditor.MaxRecvKbps.$dirty}">
|
||||
<label translate for="MaxRecvKbps">Incoming Rate Limit (KiB/s)</label>
|
||||
<input id="MaxRecvKbps" name="MaxRecvKbps" class="form-control" type="number" ng-model="tmpOptions.maxRecvKbps" min="0"/>
|
||||
<p class="help-block">
|
||||
<span translate ng-if="settingsEditor.MaxRecvKbps.$error.min && settingsEditor.MaxRecvKbps.$dirty">The rate limit must be a non-negative number (0: no limit)</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-6">
|
||||
<div class="form-group" ng-class="{'has-error': settingsEditor.MaxSendKbps.$invalid && settingsEditor.MaxSendKbps.$dirty}">
|
||||
<label translate for="MaxSendKbps">Outgoing Rate Limit (KiB/s)</label>
|
||||
<input id="MaxSendKbps" name="MaxSendKbps" class="form-control" type="number" ng-model="tmpOptions.maxSendKbps" min="0"/>
|
||||
<p class="help-block">
|
||||
<span translate ng-if="settingsEditor.MaxSendKbps.$error.min && settingsEditor.MaxSendKbps.$dirty">The rate limit must be a non-negative number (0: no limit)</span>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-class="{'has-error': settingsEditor.MaxSendKbps.$invalid && settingsEditor.MaxSendKbps.$dirty}">
|
||||
<label translate for="MaxSendKbps">Outgoing Rate Limit (KiB/s)</label>
|
||||
<input id="MaxSendKbps" name="MaxSendKbps" class="form-control" type="number" ng-model="tmpOptions.maxSendKbps" min="0"/>
|
||||
<p class="help-block">
|
||||
<span translate ng-if="settingsEditor.MaxSendKbps.$error.min && settingsEditor.MaxSendKbps.$dirty">The rate limit must be a non-negative number (0: no limit)</span>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
@@ -51,7 +195,6 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
@@ -72,102 +215,16 @@
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="clearfix"></div>
|
||||
<div class="form-group">
|
||||
<label translate for="GlobalAnnServersStr">Global Discovery Servers</label>
|
||||
<input ng-disabled="!tmpOptions.globalAnnounceEnabled" id="GlobalAnnServersStr" class="form-control" type="text" ng-model="tmpOptions._globalAnnounceServersStr"/>
|
||||
</div>
|
||||
|
||||
<div class="form-horizontal">
|
||||
<div class="form-group" ng-class="{'has-error': settingsEditor.minHomeDiskFree.$invalid && settingsEditor.minHomeDiskFree.$dirty}">
|
||||
<label class="col-xs-12" for="minHomeDiskFree"><span translate>Minimum Free Disk Space</span></label><br/>
|
||||
<div class="col-xs-9"><input name="minHomeDiskFree" id="minHomeDiskFree" class="form-control" type="number" ng-model="tmpOptions.minHomeDiskFree.value" required="" aria-required="true" min="0" step="0.01"/></div>
|
||||
<div class="col-xs-3"><select class="col-sm-3 form-control" ng-model="tmpOptions.minHomeDiskFree.unit">
|
||||
<option value="%">%</option>
|
||||
<option value="kB">kB</option>
|
||||
<option value="MB">MB</option>
|
||||
<option value="GB">GB</option>
|
||||
<option value="TB">TB</option>
|
||||
</select></div>
|
||||
<p class="col-xs-12 help-block">
|
||||
<span translate ng-show="settingsEditor.minHomeDiskFree.$invalid">Enter a non-negative number (e.g., "2.35") and select a unit. Percentages are as part of the total disk size.</span>
|
||||
<span translate ng-hide="settingsEditor.minHomeDiskFree.$invalid">This setting controls the free space required on the home (i.e., index database) disk.</span>
|
||||
</p>
|
||||
<div class="row">
|
||||
<div class="col-md-6">
|
||||
<div class="form-group">
|
||||
<label translate for="GlobalAnnServersStr">Global Discovery Servers</label>
|
||||
<input ng-disabled="!tmpOptions.globalAnnounceEnabled" id="GlobalAnnServersStr" class="form-control" type="text" ng-model="tmpOptions._globalAnnounceServersStr"/>
|
||||
</div>
|
||||
<div>
|
||||
<div class="col-md-6">
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<div class="col-md-6">
|
||||
<div class="form-group" ng-class="{'has-error': settingsEditor.Address.$invalid && settingsEditor.Address.$dirty}">
|
||||
<label translate for="Address">GUI Listen Address</label> <a href="https://docs.syncthing.net/users/guilisten.html" target="_blank"><span class="fa fa-fw fa-book"></span> <span translate>Help</span></a>
|
||||
<input id="Address" name="Address" class="form-control" type="text" ng-model="tmpGUI.address" ng-pattern="/.*:0*((102[4-9])|(10[3-9][0-9])|(1[1-9][0-9][0-9])|([2-9][0-9][0-9][0-9])|([1-6]\d{4}))$/"/>
|
||||
<p class="help-block" ng-show="settingsEditor.Address.$invalid" translate>
|
||||
Enter a non-privileged port number (1024 - 65535).
|
||||
</p>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label translate for="User">GUI Authentication User</label>
|
||||
<input id="User" class="form-control" type="text" ng-model="tmpGUI.user"/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label translate for="Password">GUI Authentication Password</label>
|
||||
<input id="Password" class="form-control" type="password" ng-model="tmpGUI.password" ng-trim="false"/>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input id="UseTLS" type="checkbox" ng-model="tmpGUI.useTLS"/> <span translate>Use HTTPS for GUI</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="checkbox">
|
||||
<label>
|
||||
<input id="StartBrowser" type="checkbox" ng-model="tmpOptions.startBrowser"/> <span translate>Start Browser</span>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group" ng-if="upgradeInfo">
|
||||
<label translate>Automatic upgrades</label> <a href="https://docs.syncthing.net/users/releases.html" target="_blank"><span class="fa fa-fw fa-book"></span> <span translate>Help</span></a>
|
||||
<select class="form-control" ng-model="tmpOptions.upgrades">
|
||||
<option value="none" translate>No upgrades</option>
|
||||
<option value="stable" translate>Stable releases only</option>
|
||||
<option value="candidate" translate>Stable releases and release candidates</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="checkbox" ng-if="tmpOptions.upgrades != 'candidate'">
|
||||
<label>
|
||||
<input id="UREnabled" type="checkbox" ng-model="tmpOptions.urEnabled"/> <span translate>Anonymous Usage Reporting</span> (<a href="" translate data-toggle="modal" data-target="#urPreview">Preview</a>)
|
||||
</label>
|
||||
</div>
|
||||
<p class="help-block" ng-if="tmpOptions.upgrades == 'candidate'">
|
||||
<span translate>Usage reporting is always enabled for candidate releases.</span> (<a href="" translate data-toggle="modal" data-target="#urPreview">Preview</a>)
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<hr />
|
||||
|
||||
<div class="form-group">
|
||||
<label translate>API Key</label>
|
||||
<div class="well well-sm text-monospace" select-on-click>{{tmpGUI.apiKey || "-"}}</div>
|
||||
<button type="button" class="btn btn-sm btn-default" ng-click="setAPIKey(tmpGUI)">
|
||||
<span class="fa fa-repeat"></span> <span translate>Generate</span>
|
||||
</button>
|
||||
</div>
|
||||
|
||||
<div class="form-group" ng-if="themes.length > 1">
|
||||
<label translate>GUI Theme</label>
|
||||
<select class="form-control" ng-model="tmpGUI.theme">
|
||||
<option ng-repeat="theme in themes.sort()" value="{{ theme }}">
|
||||
{{ themeName(theme) }}
|
||||
</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -1,8 +1,13 @@
|
||||
<modal id="ur" status="info" icon="bar-chart" heading="{{'Allow Anonymous Usage Reporting?' | translate}}" large="yes" closeable="no">
|
||||
<div class="modal-body">
|
||||
<p translate>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.</p>
|
||||
<p translate>The aggregated statistics are publicly available at the URL below.</p>
|
||||
<p><a href="https://data.syncthing.net/" target="_blank">https://data.syncthing.net/</a></p>
|
||||
<div ng-if="config.options.urAccepted > 0 && config.options.urAccepted < system.urVersionMax">
|
||||
<p translate>Anonymous usage report format has changed. Would you like to move to the new format?</p>
|
||||
</div>
|
||||
<div ng-if="!(config.options.urAccepted > 0 && config.options.urAccepted < system.urVersionMax)">
|
||||
<p translate>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.</p>
|
||||
<p translate>The aggregated statistics are publicly available at the URL below.</p>
|
||||
<p><a href="https://data.syncthing.net/" target="_blank">https://data.syncthing.net/</a></p>
|
||||
</div>
|
||||
<button type="button" class="btn btn-default btn-sm" ng-click="showReportPreview()" ng-show="!reportPreview">
|
||||
<span class="fa fa-file-text-o"></span> <span translate>Preview Usage Report</span>
|
||||
</button>
|
||||
|
||||
@@ -5,8 +5,20 @@
|
||||
</p>
|
||||
<p translate>The aggregated statistics are publicly available at the URL below.</p>
|
||||
<p><a href="https://data.syncthing.net/" target="_blank">https://data.syncthing.net/</a></p>
|
||||
<label translate>Version</label>
|
||||
<select id="urPreviewVersion" class="form-control" ng-model="$parent.$parent.reportDataPreviewVersion" ng-change="refreshReportDataPreview()" >
|
||||
<option selected value translate>Select a version</option>
|
||||
<option ng-repeat="n in urVersions()" value="{{n}}">{{'Version' | translate}} {{n}}</option>
|
||||
</select>
|
||||
<div class="checkbox" ng-if="$parent.$parent.reportDataPreviewVersion > 2">
|
||||
<label>
|
||||
<input type="checkbox" ng-model="$parent.$parent.$parent.reportDataPreviewDiff" ng-change="refreshReportDataPreview()"/>
|
||||
<span translate>Show diff with previous version</span>
|
||||
</label>
|
||||
</div>
|
||||
<hr>
|
||||
<form>
|
||||
<textarea class="form-control" rows="20">{{reportData | json}}</textarea>
|
||||
<textarea class="form-control" rows="20" ng-if="reportDataPreview">{{reportDataPreview | json}}</textarea>
|
||||
</form>
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
# Copyright (C) 2016 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/.
|
||||
|
||||
# This script should be run by Jenkins as './src/github.com/syncthing/syncthing/jenkins/build-linux.bash',
|
||||
# that is, it should be run from $GOPATH.
|
||||
|
||||
. src/github.com/syncthing/syncthing/jenkins/common.bash
|
||||
|
||||
init
|
||||
|
||||
# after init we are in the source directory
|
||||
|
||||
clean
|
||||
fetchExtra
|
||||
buildSource
|
||||
build
|
||||
test
|
||||
testWithCoverage
|
||||
|
||||
platforms=(
|
||||
dragonfly-amd64
|
||||
freebsd-amd64 freebsd-386
|
||||
linux-amd64 linux-386 linux-arm linux-arm64 linux-ppc64 linux-ppc64le linux-mips linux-mipsle
|
||||
netbsd-amd64 netbsd-386
|
||||
openbsd-amd64 openbsd-386
|
||||
)
|
||||
|
||||
echo Building
|
||||
for plat in "${platforms[@]}"; do
|
||||
echo Building "$plat"
|
||||
|
||||
goos="${plat%-*}"
|
||||
goarch="${plat#*-}"
|
||||
go run build.go -goos "$goos" -goarch "$goarch" tar
|
||||
mv *.tar.gz "$WORKSPACE"
|
||||
echo
|
||||
done
|
||||
|
||||
export BUILD_USER=deb
|
||||
go run build.go -goarch amd64 deb
|
||||
go run build.go -goarch i386 deb
|
||||
go run build.go -goarch armel deb
|
||||
go run build.go -goarch armhf deb
|
||||
go run build.go -goarch arm64 deb
|
||||
|
||||
mv *.deb "$WORKSPACE"
|
||||
|
||||
export BUILD_USER=snap
|
||||
go run build.go -goarch amd64 snap
|
||||
go run build.go -goarch armhf snap
|
||||
go run build.go -goarch arm64 snap
|
||||
|
||||
mv *.snap "$WORKSPACE"
|
||||
|
||||
if [[ -d /usr/local/oldgo ]]; then
|
||||
echo
|
||||
echo Building with minimum supported Go version
|
||||
export GOROOT=/usr/local/oldgo
|
||||
export PATH="$GOROOT/bin:$PATH"
|
||||
go version
|
||||
echo
|
||||
|
||||
rm -rf "$GOPATH/pkg"
|
||||
go run build.go install all # only compile, don't run lints and stuff
|
||||
fi
|
||||
@@ -1,37 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
# Copyright (C) 2016 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/.
|
||||
|
||||
# This script should be run by Jenkins as './src/github.com/syncthing/syncthing/jenkins/build-macos.bash',
|
||||
# that is, it should be run from $GOPATH.
|
||||
|
||||
. src/github.com/syncthing/syncthing/jenkins/common.bash
|
||||
|
||||
init
|
||||
|
||||
# after init we are in the source directory
|
||||
|
||||
clean
|
||||
fetchExtra
|
||||
build
|
||||
test
|
||||
|
||||
platforms=(
|
||||
darwin-amd64 darwin-386
|
||||
)
|
||||
|
||||
echo Building
|
||||
for plat in "${platforms[@]}"; do
|
||||
echo Building "$plat"
|
||||
|
||||
goos="${plat%-*}"
|
||||
goarch="${plat#*-}"
|
||||
go run build.go -goos "$goos" -goarch "$goarch" tar
|
||||
mv *.tar.gz "$WORKSPACE"
|
||||
echo
|
||||
done
|
||||
@@ -1,38 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
# Copyright (C) 2017 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/.
|
||||
|
||||
# This script should be run by Jenkins as './src/github.com/syncthing/syncthing/jenkins/build-macos.bash',
|
||||
# that is, it should be run from $GOPATH.
|
||||
|
||||
. src/github.com/syncthing/syncthing/jenkins/common.bash
|
||||
|
||||
init
|
||||
|
||||
# after init we are in the source directory
|
||||
|
||||
clean
|
||||
fetchExtra
|
||||
|
||||
# Solaris always uses cgo, as opposed to our regular cross builds
|
||||
export CGO_ENABLED=1
|
||||
|
||||
# Quick build, generate assets
|
||||
go run build.go build syncthing
|
||||
|
||||
# Test the stuff we are going to build only, as discosrv etc fails.
|
||||
# -race is not supported on Solaris.
|
||||
echo Testing
|
||||
go test ./lib/... ./cmd/syncthing
|
||||
echo
|
||||
|
||||
# Specifically set "syncthing" target as discosrv currently doesn't build
|
||||
echo Building
|
||||
go run build.go tar syncthing
|
||||
mv *.tar.gz "$WORKSPACE"
|
||||
echo
|
||||
@@ -1,55 +0,0 @@
|
||||
@echo off
|
||||
|
||||
rem Copyright (C) 2016 The Syncthing Authors.
|
||||
rem
|
||||
rem This Source Code Form is subject to the terms of the Mozilla Public
|
||||
rem License, v. 2.0. If a copy of the MPL was not distributed with this file,
|
||||
rem You can obtain one at https://mozilla.org/MPL/2.0/.
|
||||
|
||||
rem This batch file should be run from the GOPATH.
|
||||
rem It expects to run on amd64, for windows-amd64 Go to be installed in C:\go
|
||||
rem and for windows-386 Go to be installed in C:\go-386.
|
||||
|
||||
rem cURL should be installed in C:\Program Files\cURL.
|
||||
|
||||
set ORIGPATH="C:\Program Files\cURL\bin";%PATH%
|
||||
set PATH=c:\go\bin;%ORIGPATH%
|
||||
set GOROOT=c:\go
|
||||
|
||||
cd >gopath
|
||||
set /p GOPATH= <gopath
|
||||
|
||||
cd src\github.com\syncthing\syncthing
|
||||
|
||||
echo Initializing ^& cleaning
|
||||
go version
|
||||
git clean -fxd || goto error
|
||||
go run build.go version
|
||||
echo.
|
||||
|
||||
echo Fetching extras
|
||||
mkdir extra
|
||||
curl -s -L -o extra/Getting-Started.pdf https://docs.syncthing.net/pdf/Getting-Started.pdf || goto :error
|
||||
curl -s -L -o extra/FAQ.pdf https://docs.syncthing.net/pdf/FAQ.pdf || goto :error
|
||||
echo.
|
||||
|
||||
echo Testing
|
||||
go run build.go test || goto :error
|
||||
echo.
|
||||
|
||||
echo Building (amd64)
|
||||
go run build.go zip || goto :error
|
||||
echo.
|
||||
|
||||
set PATH=c:\go-386\bin;%ORIGPATH%
|
||||
set GOROOT=c:\go-386
|
||||
|
||||
echo building (386)
|
||||
go run build.go zip || goto :error
|
||||
echo.
|
||||
|
||||
goto :EOF
|
||||
|
||||
:error
|
||||
echo code #%errorlevel%.
|
||||
exit /b %errorlevel%
|
||||
@@ -1,110 +0,0 @@
|
||||
#!/bin/bash
|
||||
set -euo pipefail
|
||||
|
||||
# Copyright (C) 2016 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/.
|
||||
|
||||
ulimit -t 600 || true
|
||||
ulimit -d 1024000 || true
|
||||
ulimit -m 1024000 || true
|
||||
|
||||
export CGO_ENABLED=0
|
||||
export GO386=387
|
||||
export GOARM=5
|
||||
|
||||
function init {
|
||||
echo Initializing
|
||||
export GOPATH=$(pwd)
|
||||
export WORKSPACE="${WORKSPACE:-$GOPATH}"
|
||||
go version
|
||||
rm -f *.tar.gz *.zip *.deb *.snap
|
||||
cd src/github.com/syncthing/syncthing
|
||||
|
||||
version=$(go run build.go version)
|
||||
echo "Building $version"
|
||||
echo
|
||||
}
|
||||
|
||||
function clean {
|
||||
echo Cleaning
|
||||
rm -rf "$GOPATH/pkg"
|
||||
git clean -fxd
|
||||
rm -rf parts # created by snapcraft, contains git repo so not cleaned by git above
|
||||
echo
|
||||
}
|
||||
|
||||
function fetchExtra {
|
||||
echo Fetching extra resources
|
||||
mkdir extra
|
||||
curl -s -o extra/Getting-Started.pdf https://docs.syncthing.net/pdf/Getting-Started.pdf
|
||||
curl -s -o extra/FAQ.pdf https://docs.syncthing.net/pdf/FAQ.pdf
|
||||
echo
|
||||
}
|
||||
|
||||
function checkAuthorsCopyright {
|
||||
echo Basic metadata checks
|
||||
go run script/check-authors.go
|
||||
go run script/check-copyright.go lib/ cmd/ script/
|
||||
echo
|
||||
}
|
||||
|
||||
function build {
|
||||
echo Build
|
||||
go run build.go
|
||||
echo
|
||||
}
|
||||
|
||||
function test {
|
||||
echo Test with race
|
||||
CGO_ENABLED=1 go run build.go -race test
|
||||
echo
|
||||
}
|
||||
|
||||
function testWithCoverage {
|
||||
echo Test with coverage
|
||||
CGO_ENABLED=1
|
||||
|
||||
echo "mode: set" > coverage.out
|
||||
fail=0
|
||||
|
||||
# For every package in the repo
|
||||
for dir in $(go list ./lib/... ./cmd/...) ; do
|
||||
# run the tests
|
||||
GOPATH="$(pwd)/Godeps/_workspace:$GOPATH" go test -coverprofile=profile.out $dir
|
||||
if [ -f profile.out ] ; then
|
||||
# and if there was test output, append it to coverage.out
|
||||
grep -v "mode: " profile.out >> coverage.out
|
||||
rm profile.out
|
||||
fi
|
||||
done
|
||||
|
||||
gocov convert coverage.out | gocov-xml > coverage.xml
|
||||
|
||||
# This is usually run from within Jenkins. If it is, we need to
|
||||
# tweak the paths in coverage.xml so cobertura finds the
|
||||
# source.
|
||||
if [[ "${WORKSPACE:-default}" != "default" ]] ; then
|
||||
sed "s#$WORKSPACE##g" < coverage.xml > coverage.xml.new && mv coverage.xml.new coverage.xml
|
||||
fi
|
||||
|
||||
notCovered=$(egrep -c '\s0$' coverage.out)
|
||||
total=$(wc -l coverage.out | awk '{print $1}')
|
||||
coverPct=$(awk "BEGIN{print (1 - $notCovered / $total) * 100}")
|
||||
echo "$coverPct" > "coverage.txt"
|
||||
echo "Test coverage is $coverPct%%"
|
||||
echo
|
||||
|
||||
CGO_ENABLED=0 # reset to before
|
||||
}
|
||||
|
||||
function buildSource {
|
||||
echo Archiving source
|
||||
echo "$version" > RELEASE
|
||||
pushd .. >/dev/null
|
||||
tar c -z -f "$WORKSPACE/syncthing-source-$version.tar.gz" --exclude .git syncthing
|
||||
popd >/dev/null
|
||||
echo
|
||||
}
|
||||
@@ -137,17 +137,11 @@ func (w *broadcastWriter) Serve() {
|
||||
return
|
||||
}
|
||||
|
||||
if err, ok := err.(net.Error); ok && err.Temporary() {
|
||||
// A transient error. Lets hope for better luck in the future.
|
||||
l.Debugln(err)
|
||||
continue
|
||||
}
|
||||
|
||||
if err != nil {
|
||||
// Some other error that we don't expect. Bail and retry.
|
||||
// Some other error that we don't expect. Debug and continue.
|
||||
l.Debugln(err)
|
||||
w.setError(err)
|
||||
return
|
||||
continue
|
||||
}
|
||||
|
||||
l.Debugf("sent %d bytes to %s", len(bs), dst)
|
||||
|
||||
@@ -52,7 +52,7 @@ func TestReplaceCommit(t *testing.T) {
|
||||
// Replace config. We should get back a clean response and the config
|
||||
// should change.
|
||||
|
||||
err := w.Replace(Configuration{Version: 1})
|
||||
_, err := w.Replace(Configuration{Version: 1})
|
||||
if err != nil {
|
||||
t.Fatal("Should not have a validation error:", err)
|
||||
}
|
||||
@@ -69,7 +69,7 @@ func TestReplaceCommit(t *testing.T) {
|
||||
sub0 := requiresRestart{committed: make(chan struct{}, 1)}
|
||||
w.Subscribe(sub0)
|
||||
|
||||
err = w.Replace(Configuration{Version: 2})
|
||||
_, err = w.Replace(Configuration{Version: 2})
|
||||
if err != nil {
|
||||
t.Fatal("Should not have a validation error:", err)
|
||||
}
|
||||
@@ -87,7 +87,7 @@ func TestReplaceCommit(t *testing.T) {
|
||||
|
||||
w.Subscribe(validationError{})
|
||||
|
||||
err = w.Replace(Configuration{Version: 3})
|
||||
_, err = w.Replace(Configuration{Version: 3})
|
||||
if err == nil {
|
||||
t.Fatal("Should have a validation error")
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ import (
|
||||
|
||||
const (
|
||||
OldestHandledVersion = 10
|
||||
CurrentVersion = 23
|
||||
CurrentVersion = 26
|
||||
MaxRescanIntervalS = 365 * 24 * 60 * 60
|
||||
)
|
||||
|
||||
@@ -48,11 +48,8 @@ var (
|
||||
DefaultListenAddresses = []string{
|
||||
util.Address("tcp", net.JoinHostPort("0.0.0.0", strconv.Itoa(DefaultTCPPort))),
|
||||
"dynamic+https://relays.syncthing.net/endpoint",
|
||||
util.Address("kcp", net.JoinHostPort("0.0.0.0", strconv.Itoa(DefaultKCPPort))),
|
||||
}
|
||||
// DefaultKCPListenAddress gets added to the default listen address set
|
||||
// when the appropriate feature flag is set. Feature flag stuff to be
|
||||
// removed later.
|
||||
DefaultKCPListenAddress = util.Address("kcp", net.JoinHostPort("0.0.0.0", strconv.Itoa(DefaultKCPPort)))
|
||||
// DefaultDiscoveryServersV4 should be substituted when the configuration
|
||||
// contains <globalAnnounceServer>default-v4</globalAnnounceServer>.
|
||||
DefaultDiscoveryServersV4 = []string{
|
||||
@@ -326,6 +323,15 @@ func (cfg *Configuration) clean() error {
|
||||
if cfg.Version == 22 {
|
||||
convertV22V23(cfg)
|
||||
}
|
||||
if cfg.Version == 23 {
|
||||
convertV23V24(cfg)
|
||||
}
|
||||
if cfg.Version == 24 {
|
||||
convertV24V25(cfg)
|
||||
}
|
||||
if cfg.Version == 25 {
|
||||
convertV25V26(cfg)
|
||||
}
|
||||
|
||||
// Build a list of available devices
|
||||
existingDevices := make(map[protocol.DeviceID]bool)
|
||||
@@ -375,6 +381,25 @@ func (cfg *Configuration) clean() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
func convertV25V26(cfg *Configuration) {
|
||||
// triggers database update
|
||||
cfg.Version = 26
|
||||
}
|
||||
|
||||
func convertV24V25(cfg *Configuration) {
|
||||
for i := range cfg.Folders {
|
||||
cfg.Folders[i].FSWatcherDelayS = 10
|
||||
}
|
||||
|
||||
cfg.Version = 25
|
||||
}
|
||||
|
||||
func convertV23V24(cfg *Configuration) {
|
||||
cfg.Options.URSeen = 2
|
||||
|
||||
cfg.Version = 24
|
||||
}
|
||||
|
||||
func convertV22V23(cfg *Configuration) {
|
||||
permBits := fs.FileMode(0777)
|
||||
if runtime.GOOS == "windows" {
|
||||
@@ -382,19 +407,24 @@ func convertV22V23(cfg *Configuration) {
|
||||
// begin with.
|
||||
permBits = 0700
|
||||
}
|
||||
|
||||
// Upgrade code remains hardcoded for .stfolder despite configurable
|
||||
// marker name in later versions.
|
||||
|
||||
for i := range cfg.Folders {
|
||||
fs := cfg.Folders[i].Filesystem()
|
||||
// Invalid config posted, or tests.
|
||||
if fs == nil {
|
||||
continue
|
||||
}
|
||||
if stat, err := fs.Stat(".stfolder"); err == nil && !stat.IsDir() {
|
||||
err = fs.Remove(".stfolder")
|
||||
if stat, err := fs.Stat(DefaultMarkerName); err == nil && !stat.IsDir() {
|
||||
err = fs.Remove(DefaultMarkerName)
|
||||
if err == nil {
|
||||
err = fs.Mkdir(".stfolder", permBits)
|
||||
err = fs.Mkdir(DefaultMarkerName, permBits)
|
||||
fs.Hide(DefaultMarkerName) // ignore error
|
||||
}
|
||||
if err != nil {
|
||||
l.Fatalln("failed to upgrade folder marker:", err)
|
||||
l.Infoln("Failed to upgrade folder marker:", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ import (
|
||||
"bytes"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"reflect"
|
||||
@@ -20,6 +21,7 @@ import (
|
||||
|
||||
"github.com/d4l3k/messagediff"
|
||||
"github.com/syncthing/syncthing/lib/fs"
|
||||
"github.com/syncthing/syncthing/lib/osutil"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
)
|
||||
|
||||
@@ -68,7 +70,6 @@ func TestDefaultValues(t *testing.T) {
|
||||
WeakHashSelectionMethod: WeakHashAuto,
|
||||
StunKeepaliveS: 24,
|
||||
StunServers: []string{"default"},
|
||||
DefaultKCPEnabled: false,
|
||||
KCPCongestionControl: true,
|
||||
KCPReceiveWindowSize: 128,
|
||||
KCPSendWindowSize: 128,
|
||||
@@ -86,13 +87,13 @@ func TestDefaultValues(t *testing.T) {
|
||||
|
||||
func TestDeviceConfig(t *testing.T) {
|
||||
for i := OldestHandledVersion; i <= CurrentVersion; i++ {
|
||||
os.RemoveAll("testdata/.stfolder")
|
||||
os.RemoveAll(filepath.Join("testdata", DefaultMarkerName))
|
||||
wr, err := Load(fmt.Sprintf("testdata/v%d.xml", i), device1)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
_, err = os.Stat("testdata/.stfolder")
|
||||
_, err = os.Stat(filepath.Join("testdata", DefaultMarkerName))
|
||||
if i < 6 && err != nil {
|
||||
t.Fatal(err)
|
||||
} else if i >= 6 && err == nil {
|
||||
@@ -103,22 +104,25 @@ func TestDeviceConfig(t *testing.T) {
|
||||
|
||||
expectedFolders := []FolderConfiguration{
|
||||
{
|
||||
ID: "test",
|
||||
FilesystemType: fs.FilesystemTypeBasic,
|
||||
Path: "testdata",
|
||||
Devices: []FolderDeviceConfiguration{{DeviceID: device1}, {DeviceID: device4}},
|
||||
Type: FolderTypeSendOnly,
|
||||
RescanIntervalS: 600,
|
||||
Copiers: 0,
|
||||
Pullers: 0,
|
||||
Hashers: 0,
|
||||
AutoNormalize: true,
|
||||
MinDiskFree: Size{1, "%"},
|
||||
MaxConflicts: -1,
|
||||
ID: "test",
|
||||
FilesystemType: fs.FilesystemTypeBasic,
|
||||
Path: "testdata",
|
||||
Devices: []FolderDeviceConfiguration{{DeviceID: device1}, {DeviceID: device4}},
|
||||
Type: FolderTypeSendOnly,
|
||||
RescanIntervalS: 600,
|
||||
FSWatcherEnabled: false,
|
||||
FSWatcherDelayS: 10,
|
||||
Copiers: 0,
|
||||
Pullers: 0,
|
||||
Hashers: 0,
|
||||
AutoNormalize: true,
|
||||
MinDiskFree: Size{1, "%"},
|
||||
MaxConflicts: -1,
|
||||
Versioning: VersioningConfiguration{
|
||||
Params: map[string]string{},
|
||||
},
|
||||
WeakHashThresholdPct: 25,
|
||||
MarkerName: DefaultMarkerName,
|
||||
},
|
||||
}
|
||||
|
||||
@@ -200,6 +204,7 @@ func TestOverriddenValues(t *testing.T) {
|
||||
ProgressUpdateIntervalS: 10,
|
||||
LimitBandwidthInLan: true,
|
||||
MinHomeDiskFree: Size{5.2, "%"},
|
||||
URSeen: 2,
|
||||
URURL: "https://localhost/newdata",
|
||||
URInitialDelayS: 800,
|
||||
URPostInsecurely: true,
|
||||
@@ -213,7 +218,6 @@ func TestOverriddenValues(t *testing.T) {
|
||||
WeakHashSelectionMethod: WeakHashNever,
|
||||
StunKeepaliveS: 10,
|
||||
StunServers: []string{"a.stun.com", "b.stun.com"},
|
||||
DefaultKCPEnabled: true,
|
||||
KCPCongestionControl: false,
|
||||
KCPReceiveWindowSize: 1280,
|
||||
KCPSendWindowSize: 1280,
|
||||
@@ -428,6 +432,62 @@ func TestFolderPath(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestFolderCheckPath(t *testing.T) {
|
||||
n, err := ioutil.TempDir("", "")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
err = os.MkdirAll(filepath.Join(n, "dir", ".stfolder"), os.FileMode(0777))
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
testcases := []struct {
|
||||
path string
|
||||
err error
|
||||
}{
|
||||
{
|
||||
path: "",
|
||||
err: errMarkerMissing,
|
||||
},
|
||||
{
|
||||
path: "does not exist",
|
||||
err: errPathMissing,
|
||||
},
|
||||
{
|
||||
path: "dir",
|
||||
err: nil,
|
||||
},
|
||||
}
|
||||
|
||||
err = osutil.DebugSymlinkForTestsOnly(filepath.Join(n, "dir"), filepath.Join(n, "link"))
|
||||
if err == nil {
|
||||
t.Log("running with symlink check")
|
||||
testcases = append(testcases, struct {
|
||||
path string
|
||||
err error
|
||||
}{
|
||||
path: "link",
|
||||
err: nil,
|
||||
})
|
||||
} else if runtime.GOOS != "windows" {
|
||||
t.Log("running without symlink check")
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
for _, testcase := range testcases {
|
||||
cfg := FolderConfiguration{
|
||||
Path: filepath.Join(n, testcase.path),
|
||||
MarkerName: DefaultMarkerName,
|
||||
}
|
||||
|
||||
if err := cfg.CheckPath(); testcase.err != err {
|
||||
t.Errorf("unexpected error in case %s: %s != %s", testcase.path, err, testcase.err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestNewSaveLoad(t *testing.T) {
|
||||
path := "testdata/temp.xml"
|
||||
os.Remove(path)
|
||||
@@ -766,7 +826,7 @@ func TestSharesRemovedOnDeviceRemoval(t *testing.T) {
|
||||
t.Error("Should have less devices")
|
||||
}
|
||||
|
||||
err = wrapper.Replace(raw)
|
||||
_, err = wrapper.Replace(raw)
|
||||
if err != nil {
|
||||
t.Errorf("Failed: %s", err)
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ type DeviceConfiguration struct {
|
||||
IntroducedBy protocol.DeviceID `xml:"introducedBy,attr" json:"introducedBy"`
|
||||
Paused bool `xml:"paused" json:"paused"`
|
||||
AllowedNetworks []string `xml:"allowedNetwork,omitempty" json:"allowedNetworks"`
|
||||
AutoAcceptFolders bool `xml:"autoAcceptFolders" json:"autoAcceptFolders"`
|
||||
}
|
||||
|
||||
func NewDeviceConfiguration(id protocol.DeviceID, name string) DeviceConfiguration {
|
||||
|
||||
@@ -7,21 +7,33 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"runtime"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/fs"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
"github.com/syncthing/syncthing/lib/util"
|
||||
)
|
||||
|
||||
var (
|
||||
errPathNotDirectory = errors.New("folder path not a directory")
|
||||
errPathMissing = errors.New("folder path missing")
|
||||
errMarkerMissing = errors.New("folder marker missing")
|
||||
)
|
||||
|
||||
const DefaultMarkerName = ".stfolder"
|
||||
|
||||
type FolderConfiguration struct {
|
||||
ID string `xml:"id,attr" json:"id"`
|
||||
Label string `xml:"label,attr" json:"label"`
|
||||
Label string `xml:"label,attr" json:"label" restart:"false"`
|
||||
FilesystemType fs.FilesystemType `xml:"filesystemType" json:"filesystemType"`
|
||||
Path string `xml:"path,attr" json:"path"`
|
||||
Type FolderType `xml:"type,attr" json:"type"`
|
||||
Devices []FolderDeviceConfiguration `xml:"device" json:"devices"`
|
||||
RescanIntervalS int `xml:"rescanIntervalS,attr" json:"rescanIntervalS"`
|
||||
FSWatcherEnabled bool `xml:"fsWatcherEnabled,attr" json:"fsWatcherEnabled"`
|
||||
FSWatcherDelayS int `xml:"fsWatcherDelayS,attr" json:"fsWatcherDelayS"`
|
||||
IgnorePerms bool `xml:"ignorePerms,attr" json:"ignorePerms"`
|
||||
AutoNormalize bool `xml:"autoNormalize,attr" json:"autoNormalize"`
|
||||
MinDiskFree Size `xml:"minDiskFree" json:"minDiskFree"`
|
||||
@@ -32,13 +44,13 @@ type FolderConfiguration struct {
|
||||
Order PullOrder `xml:"order" json:"order"`
|
||||
IgnoreDelete bool `xml:"ignoreDelete" json:"ignoreDelete"`
|
||||
ScanProgressIntervalS int `xml:"scanProgressIntervalS" json:"scanProgressIntervalS"` // Set to a negative value to disable. Value of 0 will get replaced with value of 2 (default value)
|
||||
PullerSleepS int `xml:"pullerSleepS" json:"pullerSleepS"`
|
||||
PullerPauseS int `xml:"pullerPauseS" json:"pullerPauseS"`
|
||||
MaxConflicts int `xml:"maxConflicts" json:"maxConflicts"`
|
||||
DisableSparseFiles bool `xml:"disableSparseFiles" json:"disableSparseFiles"`
|
||||
DisableTempIndexes bool `xml:"disableTempIndexes" json:"disableTempIndexes"`
|
||||
Paused bool `xml:"paused" json:"paused"`
|
||||
WeakHashThresholdPct int `xml:"weakHashThresholdPct" json:"weakHashThresholdPct"` // Use weak hash if more than X percent of the file has changed. Set to -1 to always use weak hash.
|
||||
MarkerName string `xml:"markerName" json:"markerName"`
|
||||
|
||||
cachedFilesystem fs.Filesystem
|
||||
|
||||
@@ -51,11 +63,18 @@ type FolderDeviceConfiguration struct {
|
||||
IntroducedBy protocol.DeviceID `xml:"introducedBy,attr" json:"introducedBy"`
|
||||
}
|
||||
|
||||
func NewFolderConfiguration(id string, fsType fs.FilesystemType, path string) FolderConfiguration {
|
||||
func NewFolderConfiguration(myID protocol.DeviceID, id, label string, fsType fs.FilesystemType, path string) FolderConfiguration {
|
||||
f := FolderConfiguration{
|
||||
ID: id,
|
||||
FilesystemType: fsType,
|
||||
Path: path,
|
||||
ID: id,
|
||||
Label: label,
|
||||
RescanIntervalS: 60,
|
||||
FSWatcherDelayS: 10,
|
||||
MinDiskFree: Size{Value: 1, Unit: "%"},
|
||||
Devices: []FolderDeviceConfiguration{{DeviceID: myID}},
|
||||
AutoNormalize: true,
|
||||
MaxConflicts: -1,
|
||||
FilesystemType: fsType,
|
||||
Path: path,
|
||||
}
|
||||
f.prepare()
|
||||
return f
|
||||
@@ -80,34 +99,66 @@ func (f FolderConfiguration) Filesystem() fs.Filesystem {
|
||||
}
|
||||
|
||||
func (f *FolderConfiguration) CreateMarker() error {
|
||||
if !f.HasMarker() {
|
||||
permBits := fs.FileMode(0777)
|
||||
if runtime.GOOS == "windows" {
|
||||
// Windows has no umask so we must chose a safer set of bits to
|
||||
// begin with.
|
||||
permBits = 0700
|
||||
}
|
||||
fs := f.Filesystem()
|
||||
err := fs.Mkdir(".stfolder", permBits)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if dir, err := fs.Open("."); err == nil {
|
||||
if serr := dir.Sync(); err != nil {
|
||||
l.Infof("fsync %q failed: %v", ".", serr)
|
||||
}
|
||||
} else {
|
||||
l.Infof("fsync %q failed: %v", ".", err)
|
||||
}
|
||||
fs.Hide(".stfolder")
|
||||
if err := f.CheckPath(); err != errMarkerMissing {
|
||||
return err
|
||||
}
|
||||
if f.MarkerName != DefaultMarkerName {
|
||||
// Folder uses a non-default marker so we shouldn't mess with it.
|
||||
// Pretend we created it and let the subsequent health checks sort
|
||||
// out the actual situation.
|
||||
return nil
|
||||
}
|
||||
|
||||
permBits := fs.FileMode(0777)
|
||||
if runtime.GOOS == "windows" {
|
||||
// Windows has no umask so we must chose a safer set of bits to
|
||||
// begin with.
|
||||
permBits = 0700
|
||||
}
|
||||
fs := f.Filesystem()
|
||||
err := fs.Mkdir(DefaultMarkerName, permBits)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if dir, err := fs.Open("."); err != nil {
|
||||
l.Debugln("folder marker: open . failed:", err)
|
||||
} else if err := dir.Sync(); err != nil {
|
||||
l.Debugln("folder marker: fsync . failed:", err)
|
||||
}
|
||||
fs.Hide(DefaultMarkerName)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *FolderConfiguration) HasMarker() bool {
|
||||
_, err := f.Filesystem().Stat(".stfolder")
|
||||
return err == nil
|
||||
// CheckPath returns nil if the folder root exists and contains the marker file
|
||||
func (f *FolderConfiguration) CheckPath() error {
|
||||
fi, err := f.Filesystem().Stat(".")
|
||||
if err != nil {
|
||||
if !fs.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
return errPathMissing
|
||||
}
|
||||
|
||||
// Users might have the root directory as a symlink or reparse point.
|
||||
// Furthermore, OneDrive bullcrap uses a magic reparse point to the cloudz...
|
||||
// Yet it's impossible for this to happen, as filesystem adds a trailing
|
||||
// path separator to the root, so even if you point the filesystem at a file
|
||||
// Stat ends up calling stat on C:\dir\file\ which, fails with "is not a directory"
|
||||
// in the error check above, and we don't even get to here.
|
||||
if !fi.IsDir() && !fi.IsSymlink() {
|
||||
return errPathNotDirectory
|
||||
}
|
||||
|
||||
_, err = f.Filesystem().Stat(f.MarkerName)
|
||||
if err != nil {
|
||||
if !fs.IsNotExist(err) {
|
||||
return err
|
||||
}
|
||||
return errMarkerMissing
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *FolderConfiguration) CreateRoot() (err error) {
|
||||
@@ -157,6 +208,11 @@ func (f *FolderConfiguration) prepare() {
|
||||
f.RescanIntervalS = 0
|
||||
}
|
||||
|
||||
if f.FSWatcherDelayS <= 0 {
|
||||
f.FSWatcherEnabled = false
|
||||
f.FSWatcherDelayS = 10
|
||||
}
|
||||
|
||||
if f.Versioning.Params == nil {
|
||||
f.Versioning.Params = make(map[string]string)
|
||||
}
|
||||
@@ -164,6 +220,29 @@ func (f *FolderConfiguration) prepare() {
|
||||
if f.WeakHashThresholdPct == 0 {
|
||||
f.WeakHashThresholdPct = 25
|
||||
}
|
||||
|
||||
if f.MarkerName == "" {
|
||||
f.MarkerName = DefaultMarkerName
|
||||
}
|
||||
}
|
||||
|
||||
// RequiresRestartOnly returns a copy with only the attributes that require
|
||||
// restart on change.
|
||||
func (f FolderConfiguration) RequiresRestartOnly() FolderConfiguration {
|
||||
copy := f
|
||||
|
||||
// Manual handling for things that are not taken care of by the tag
|
||||
// copier, yet should not cause a restart.
|
||||
copy.cachedFilesystem = nil
|
||||
|
||||
blank := FolderConfiguration{}
|
||||
util.CopyMatchingTag(&blank, ©, "restart", func(v string) bool {
|
||||
if len(v) > 0 && v != "false" {
|
||||
panic(fmt.Sprintf(`unexpected tag value: %s. expected untagged or "false"`, v))
|
||||
}
|
||||
return v == "false"
|
||||
})
|
||||
return copy
|
||||
}
|
||||
|
||||
type FolderDeviceConfigurationList []FolderDeviceConfiguration
|
||||
@@ -179,3 +258,7 @@ func (l FolderDeviceConfigurationList) Swap(a, b int) {
|
||||
func (l FolderDeviceConfigurationList) Len() int {
|
||||
return len(l)
|
||||
}
|
||||
|
||||
func (f *FolderConfiguration) CheckFreeSpace() (err error) {
|
||||
return checkFreeSpace(f.MinDiskFree, f.Filesystem())
|
||||
}
|
||||
|
||||
@@ -13,16 +13,17 @@ import (
|
||||
)
|
||||
|
||||
type GUIConfiguration struct {
|
||||
Enabled bool `xml:"enabled,attr" json:"enabled" default:"true"`
|
||||
RawAddress string `xml:"address" json:"address" default:"127.0.0.1:8384"`
|
||||
User string `xml:"user,omitempty" json:"user"`
|
||||
Password string `xml:"password,omitempty" json:"password"`
|
||||
RawUseTLS bool `xml:"tls,attr" json:"useTLS"`
|
||||
APIKey string `xml:"apikey,omitempty" json:"apiKey"`
|
||||
InsecureAdminAccess bool `xml:"insecureAdminAccess,omitempty" json:"insecureAdminAccess"`
|
||||
Theme string `xml:"theme" json:"theme" default:"default"`
|
||||
Debugging bool `xml:"debugging,attr" json:"debugging"`
|
||||
InsecureSkipHostCheck bool `xml:"insecureSkipHostcheck,omitempty" json:"insecureSkipHostcheck"`
|
||||
Enabled bool `xml:"enabled,attr" json:"enabled" default:"true"`
|
||||
RawAddress string `xml:"address" json:"address" default:"127.0.0.1:8384"`
|
||||
User string `xml:"user,omitempty" json:"user"`
|
||||
Password string `xml:"password,omitempty" json:"password"`
|
||||
RawUseTLS bool `xml:"tls,attr" json:"useTLS"`
|
||||
APIKey string `xml:"apikey,omitempty" json:"apiKey"`
|
||||
InsecureAdminAccess bool `xml:"insecureAdminAccess,omitempty" json:"insecureAdminAccess"`
|
||||
Theme string `xml:"theme" json:"theme" default:"default"`
|
||||
Debugging bool `xml:"debugging,attr" json:"debugging"`
|
||||
InsecureSkipHostCheck bool `xml:"insecureSkipHostcheck,omitempty" json:"insecureSkipHostcheck"`
|
||||
InsecureAllowFrameLoading bool `xml:"insecureAllowFrameLoading,omitempty" json:"insecureAllowFrameLoading"`
|
||||
}
|
||||
|
||||
func (c GUIConfiguration) Address() string {
|
||||
|
||||
@@ -10,6 +10,8 @@ import (
|
||||
"encoding/json"
|
||||
"encoding/xml"
|
||||
"fmt"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/util"
|
||||
)
|
||||
|
||||
type WeakHashSelectionMethod int
|
||||
@@ -96,11 +98,11 @@ func (WeakHashSelectionMethod) ParseDefault(value string) (interface{}, error) {
|
||||
|
||||
type OptionsConfiguration struct {
|
||||
ListenAddresses []string `xml:"listenAddress" json:"listenAddresses" default:"default"`
|
||||
GlobalAnnServers []string `xml:"globalAnnounceServer" json:"globalAnnounceServers" json:"globalAnnounceServer" default:"default"`
|
||||
GlobalAnnEnabled bool `xml:"globalAnnounceEnabled" json:"globalAnnounceEnabled" default:"true"`
|
||||
LocalAnnEnabled bool `xml:"localAnnounceEnabled" json:"localAnnounceEnabled" default:"true"`
|
||||
LocalAnnPort int `xml:"localAnnouncePort" json:"localAnnouncePort" default:"21027"`
|
||||
LocalAnnMCAddr string `xml:"localAnnounceMCAddr" json:"localAnnounceMCAddr" default:"[ff12::8384]:21027"`
|
||||
GlobalAnnServers []string `xml:"globalAnnounceServer" json:"globalAnnounceServers" json:"globalAnnounceServer" default:"default" restart:"true"`
|
||||
GlobalAnnEnabled bool `xml:"globalAnnounceEnabled" json:"globalAnnounceEnabled" default:"true" restart:"true"`
|
||||
LocalAnnEnabled bool `xml:"localAnnounceEnabled" json:"localAnnounceEnabled" default:"true" restart:"true"`
|
||||
LocalAnnPort int `xml:"localAnnouncePort" json:"localAnnouncePort" default:"21027" restart:"true"`
|
||||
LocalAnnMCAddr string `xml:"localAnnounceMCAddr" json:"localAnnounceMCAddr" default:"[ff12::8384]:21027" restart:"true"`
|
||||
MaxSendKbps int `xml:"maxSendKbps" json:"maxSendKbps"`
|
||||
MaxRecvKbps int `xml:"maxRecvKbps" json:"maxRecvKbps"`
|
||||
ReconnectIntervalS int `xml:"reconnectionIntervalS" json:"reconnectionIntervalS" default:"60"`
|
||||
@@ -112,28 +114,28 @@ type OptionsConfiguration struct {
|
||||
NATRenewalM int `xml:"natRenewalMinutes" json:"natRenewalMinutes" default:"30"`
|
||||
NATTimeoutS int `xml:"natTimeoutSeconds" json:"natTimeoutSeconds" default:"10"`
|
||||
URAccepted int `xml:"urAccepted" json:"urAccepted"` // Accepted usage reporting version; 0 for off (undecided), -1 for off (permanently)
|
||||
URSeen int `xml:"urSeen" json:"urSeen"` // Report which the user has been prompted for.
|
||||
URUniqueID string `xml:"urUniqueID" json:"urUniqueId"` // Unique ID for reporting purposes, regenerated when UR is turned on.
|
||||
URURL string `xml:"urURL" json:"urURL" default:"https://data.syncthing.net/newdata"`
|
||||
URPostInsecurely bool `xml:"urPostInsecurely" json:"urPostInsecurely" default:"false"` // For testing
|
||||
URInitialDelayS int `xml:"urInitialDelayS" json:"urInitialDelayS" default:"1800"`
|
||||
RestartOnWakeup bool `xml:"restartOnWakeup" json:"restartOnWakeup" default:"true"`
|
||||
AutoUpgradeIntervalH int `xml:"autoUpgradeIntervalH" json:"autoUpgradeIntervalH" default:"12"` // 0 for off
|
||||
UpgradeToPreReleases bool `xml:"upgradeToPreReleases" json:"upgradeToPreReleases"` // when auto upgrades are enabled
|
||||
KeepTemporariesH int `xml:"keepTemporariesH" json:"keepTemporariesH" default:"24"` // 0 for off
|
||||
CacheIgnoredFiles bool `xml:"cacheIgnoredFiles" json:"cacheIgnoredFiles" default:"false"`
|
||||
RestartOnWakeup bool `xml:"restartOnWakeup" json:"restartOnWakeup" default:"true" restart:"true"`
|
||||
AutoUpgradeIntervalH int `xml:"autoUpgradeIntervalH" json:"autoUpgradeIntervalH" default:"12" restart:"true"` // 0 for off
|
||||
UpgradeToPreReleases bool `xml:"upgradeToPreReleases" json:"upgradeToPreReleases" restart:"true"` // when auto upgrades are enabled
|
||||
KeepTemporariesH int `xml:"keepTemporariesH" json:"keepTemporariesH" default:"24"` // 0 for off
|
||||
CacheIgnoredFiles bool `xml:"cacheIgnoredFiles" json:"cacheIgnoredFiles" default:"false" restart:"true"`
|
||||
ProgressUpdateIntervalS int `xml:"progressUpdateIntervalS" json:"progressUpdateIntervalS" default:"5"`
|
||||
LimitBandwidthInLan bool `xml:"limitBandwidthInLan" json:"limitBandwidthInLan" default:"false"`
|
||||
MinHomeDiskFree Size `xml:"minHomeDiskFree" json:"minHomeDiskFree" default:"1 %"`
|
||||
ReleasesURL string `xml:"releasesURL" json:"releasesURL" default:"https://upgrades.syncthing.net/meta.json"`
|
||||
ReleasesURL string `xml:"releasesURL" json:"releasesURL" default:"https://upgrades.syncthing.net/meta.json" restart:"true"`
|
||||
AlwaysLocalNets []string `xml:"alwaysLocalNet" json:"alwaysLocalNets"`
|
||||
OverwriteRemoteDevNames bool `xml:"overwriteRemoteDeviceNamesOnConnect" json:"overwriteRemoteDeviceNamesOnConnect" default:"false"`
|
||||
TempIndexMinBlocks int `xml:"tempIndexMinBlocks" json:"tempIndexMinBlocks" default:"10"`
|
||||
UnackedNotificationIDs []string `xml:"unackedNotificationID" json:"unackedNotificationIDs"`
|
||||
TrafficClass int `xml:"trafficClass" json:"trafficClass"`
|
||||
WeakHashSelectionMethod WeakHashSelectionMethod `xml:"weakHashSelectionMethod" json:"weakHashSelectionMethod"`
|
||||
WeakHashSelectionMethod WeakHashSelectionMethod `xml:"weakHashSelectionMethod" json:"weakHashSelectionMethod" restart:"true"`
|
||||
StunServers []string `xml:"stunServer" json:"stunServers" default:"default"`
|
||||
StunKeepaliveS int `xml:"stunKeepaliveSeconds" json:"stunKeepaliveSeconds" default:"24"`
|
||||
DefaultKCPEnabled bool `xml:"defaultKCPEnabled" json:"defaultKCPEnabled" default:"false"`
|
||||
KCPNoDelay bool `xml:"kcpNoDelay" json:"kcpNoDelay" default:"false"`
|
||||
KCPUpdateIntervalMs int `xml:"kcpUpdateIntervalMs" json:"kcpUpdateIntervalMs" default:"25"`
|
||||
KCPFastResend bool `xml:"kcpFastResend" json:"kcpFastResend" default:"false"`
|
||||
@@ -162,3 +164,17 @@ func (orig OptionsConfiguration) Copy() OptionsConfiguration {
|
||||
copy(c.UnackedNotificationIDs, orig.UnackedNotificationIDs)
|
||||
return c
|
||||
}
|
||||
|
||||
// RequiresRestartOnly returns a copy with only the attributes that require
|
||||
// restart on change.
|
||||
func (orig OptionsConfiguration) RequiresRestartOnly() OptionsConfiguration {
|
||||
copy := orig
|
||||
blank := OptionsConfiguration{}
|
||||
util.CopyMatchingTag(&blank, ©, "restart", func(v string) bool {
|
||||
if len(v) > 0 && v != "true" {
|
||||
panic(fmt.Sprintf(`unexpected tag value: %s. expected untagged or "true"`, v))
|
||||
}
|
||||
return v != "true"
|
||||
})
|
||||
return copy
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/fs"
|
||||
)
|
||||
|
||||
type Size struct {
|
||||
@@ -73,3 +75,24 @@ func (s Size) String() string {
|
||||
func (Size) ParseDefault(s string) (interface{}, error) {
|
||||
return ParseSize(s)
|
||||
}
|
||||
|
||||
func checkFreeSpace(req Size, fs fs.Filesystem) error {
|
||||
val := req.BaseValue()
|
||||
if val <= 0 {
|
||||
return nil
|
||||
}
|
||||
|
||||
usage, err := fs.Usage(".")
|
||||
if req.Percentage() {
|
||||
freePct := (float64(usage.Free) / float64(usage.Total)) * 100
|
||||
if err == nil && freePct < val {
|
||||
return fmt.Errorf("insufficient space in %v %v: %f %% < %v", fs.Type(), fs.URI(), freePct, req)
|
||||
}
|
||||
} else {
|
||||
if err == nil && float64(usage.Free) < val {
|
||||
return fmt.Errorf("insufficient space in %v %v: %v < %v", fs.Type(), fs.URI(), usage.Free, req)
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
1
lib/config/testdata/overridenvalues.xml
vendored
1
lib/config/testdata/overridenvalues.xml
vendored
@@ -38,7 +38,6 @@
|
||||
<stunKeepaliveSeconds>10</stunKeepaliveSeconds>
|
||||
<stunServer>a.stun.com</stunServer>
|
||||
<stunServer>b.stun.com</stunServer>
|
||||
<defaultKCPEnabled>true</defaultKCPEnabled>
|
||||
<kcpCongestionControl>false</kcpCongestionControl>
|
||||
<kcpReceiveWindowSize>1280</kcpReceiveWindowSize>
|
||||
<kcpSendWindowSize>1280</kcpSendWindowSize>
|
||||
|
||||
16
lib/config/testdata/v24.xml
vendored
Normal file
16
lib/config/testdata/v24.xml
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<configuration version="22">
|
||||
<folder id="test" path="testdata" type="readonly" ignorePerms="false" rescanIntervalS="600" autoNormalize="true">
|
||||
<filesystemType>basic</filesystemType>
|
||||
<device id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR"></device>
|
||||
<device id="P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2"></device>
|
||||
<minDiskFree unit="%">1</minDiskFree>
|
||||
<maxConflicts>-1</maxConflicts>
|
||||
<fsync>true</fsync>
|
||||
</folder>
|
||||
<device id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR" name="node one" compression="metadata">
|
||||
<address>tcp://a</address>
|
||||
</device>
|
||||
<device id="P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2" name="node two" compression="metadata">
|
||||
<address>tcp://b</address>
|
||||
</device>
|
||||
</configuration>
|
||||
16
lib/config/testdata/v25.xml
vendored
Normal file
16
lib/config/testdata/v25.xml
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<configuration version="25">
|
||||
<folder id="test" path="testdata" type="readonly" ignorePerms="false" rescanIntervalS="600" fsNotifications="false" notifyDelayS="10" autoNormalize="true">
|
||||
<filesystemType>basic</filesystemType>
|
||||
<device id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR"></device>
|
||||
<device id="P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2"></device>
|
||||
<minDiskFree unit="%">1</minDiskFree>
|
||||
<maxConflicts>-1</maxConflicts>
|
||||
<fsync>true</fsync>
|
||||
</folder>
|
||||
<device id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR" name="node one" compression="metadata">
|
||||
<address>tcp://a</address>
|
||||
</device>
|
||||
<device id="P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2" name="node two" compression="metadata">
|
||||
<address>tcp://b</address>
|
||||
</device>
|
||||
</configuration>
|
||||
16
lib/config/testdata/v26.xml
vendored
Normal file
16
lib/config/testdata/v26.xml
vendored
Normal file
@@ -0,0 +1,16 @@
|
||||
<configuration version="26">
|
||||
<folder id="test" path="testdata" type="readonly" ignorePerms="false" rescanIntervalS="600" fsNotifications="false" notifyDelayS="10" autoNormalize="true">
|
||||
<filesystemType>basic</filesystemType>
|
||||
<device id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR"></device>
|
||||
<device id="P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2"></device>
|
||||
<minDiskFree unit="%">1</minDiskFree>
|
||||
<maxConflicts>-1</maxConflicts>
|
||||
<fsync>true</fsync>
|
||||
</folder>
|
||||
<device id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR" name="node one" compression="metadata">
|
||||
<address>tcp://a</address>
|
||||
</device>
|
||||
<device id="P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2" name="node two" compression="metadata">
|
||||
<address>tcp://b</address>
|
||||
</device>
|
||||
</configuration>
|
||||
@@ -8,9 +8,11 @@ package config
|
||||
|
||||
import (
|
||||
"os"
|
||||
"path/filepath"
|
||||
"sync/atomic"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/fs"
|
||||
"github.com/syncthing/syncthing/lib/osutil"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
"github.com/syncthing/syncthing/lib/rand"
|
||||
@@ -43,6 +45,15 @@ type Committer interface {
|
||||
String() string
|
||||
}
|
||||
|
||||
// Waiter allows to wait for the given config operation to complete.
|
||||
type Waiter interface {
|
||||
Wait()
|
||||
}
|
||||
|
||||
type noopWaiter struct{}
|
||||
|
||||
func (noopWaiter) Wait() {}
|
||||
|
||||
// A wrapper around a Configuration that manages loads, saves and published
|
||||
// notifications of changes to registered Handlers
|
||||
|
||||
@@ -129,25 +140,24 @@ func (w *Wrapper) RawCopy() Configuration {
|
||||
}
|
||||
|
||||
// Replace swaps the current configuration object for the given one.
|
||||
func (w *Wrapper) Replace(cfg Configuration) error {
|
||||
func (w *Wrapper) Replace(cfg Configuration) (Waiter, error) {
|
||||
w.mut.Lock()
|
||||
defer w.mut.Unlock()
|
||||
|
||||
return w.replaceLocked(cfg)
|
||||
}
|
||||
|
||||
func (w *Wrapper) replaceLocked(to Configuration) error {
|
||||
func (w *Wrapper) replaceLocked(to Configuration) (Waiter, error) {
|
||||
from := w.cfg
|
||||
|
||||
if err := to.clean(); err != nil {
|
||||
return err
|
||||
return noopWaiter{}, err
|
||||
}
|
||||
|
||||
for _, sub := range w.subs {
|
||||
l.Debugln(sub, "verifying configuration")
|
||||
if err := sub.VerifyConfiguration(from, to); err != nil {
|
||||
l.Debugln(sub, "rejected config:", err)
|
||||
return err
|
||||
return noopWaiter{}, err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,15 +165,19 @@ func (w *Wrapper) replaceLocked(to Configuration) error {
|
||||
w.deviceMap = nil
|
||||
w.folderMap = nil
|
||||
|
||||
w.notifyListeners(from, to)
|
||||
|
||||
return nil
|
||||
return w.notifyListeners(from, to), nil
|
||||
}
|
||||
|
||||
func (w *Wrapper) notifyListeners(from, to Configuration) {
|
||||
func (w *Wrapper) notifyListeners(from, to Configuration) Waiter {
|
||||
wg := sync.NewWaitGroup()
|
||||
wg.Add(len(w.subs))
|
||||
for _, sub := range w.subs {
|
||||
go w.notifyListener(sub, from.Copy(), to.Copy())
|
||||
go func(commiter Committer) {
|
||||
w.notifyListener(commiter, from.Copy(), to.Copy())
|
||||
wg.Done()
|
||||
}(sub)
|
||||
}
|
||||
return wg
|
||||
}
|
||||
|
||||
func (w *Wrapper) notifyListener(sub Committer, from, to Configuration) {
|
||||
@@ -190,7 +204,7 @@ func (w *Wrapper) Devices() map[protocol.DeviceID]DeviceConfiguration {
|
||||
|
||||
// SetDevices adds new devices to the configuration, or overwrites existing
|
||||
// devices with the same ID.
|
||||
func (w *Wrapper) SetDevices(devs []DeviceConfiguration) error {
|
||||
func (w *Wrapper) SetDevices(devs []DeviceConfiguration) (Waiter, error) {
|
||||
w.mut.Lock()
|
||||
defer w.mut.Unlock()
|
||||
|
||||
@@ -215,12 +229,12 @@ func (w *Wrapper) SetDevices(devs []DeviceConfiguration) error {
|
||||
|
||||
// SetDevice adds a new device to the configuration, or overwrites an existing
|
||||
// device with the same ID.
|
||||
func (w *Wrapper) SetDevice(dev DeviceConfiguration) error {
|
||||
func (w *Wrapper) SetDevice(dev DeviceConfiguration) (Waiter, error) {
|
||||
return w.SetDevices([]DeviceConfiguration{dev})
|
||||
}
|
||||
|
||||
// RemoveDevice removes the device from the configuration
|
||||
func (w *Wrapper) RemoveDevice(id protocol.DeviceID) error {
|
||||
func (w *Wrapper) RemoveDevice(id protocol.DeviceID) (Waiter, error) {
|
||||
w.mut.Lock()
|
||||
defer w.mut.Unlock()
|
||||
|
||||
@@ -234,7 +248,7 @@ func (w *Wrapper) RemoveDevice(id protocol.DeviceID) error {
|
||||
}
|
||||
}
|
||||
if !removed {
|
||||
return nil
|
||||
return noopWaiter{}, nil
|
||||
}
|
||||
|
||||
return w.replaceLocked(newCfg)
|
||||
@@ -256,7 +270,7 @@ func (w *Wrapper) Folders() map[string]FolderConfiguration {
|
||||
|
||||
// SetFolder adds a new folder to the configuration, or overwrites an existing
|
||||
// folder with the same ID.
|
||||
func (w *Wrapper) SetFolder(fld FolderConfiguration) error {
|
||||
func (w *Wrapper) SetFolder(fld FolderConfiguration) (Waiter, error) {
|
||||
w.mut.Lock()
|
||||
defer w.mut.Unlock()
|
||||
|
||||
@@ -284,7 +298,7 @@ func (w *Wrapper) Options() OptionsConfiguration {
|
||||
}
|
||||
|
||||
// SetOptions replaces the current options configuration object.
|
||||
func (w *Wrapper) SetOptions(opts OptionsConfiguration) error {
|
||||
func (w *Wrapper) SetOptions(opts OptionsConfiguration) (Waiter, error) {
|
||||
w.mut.Lock()
|
||||
defer w.mut.Unlock()
|
||||
newCfg := w.cfg.Copy()
|
||||
@@ -300,7 +314,7 @@ func (w *Wrapper) GUI() GUIConfiguration {
|
||||
}
|
||||
|
||||
// SetGUI replaces the current GUI configuration object.
|
||||
func (w *Wrapper) SetGUI(gui GUIConfiguration) error {
|
||||
func (w *Wrapper) SetGUI(gui GUIConfiguration) (Waiter, error) {
|
||||
w.mut.Lock()
|
||||
defer w.mut.Unlock()
|
||||
newCfg := w.cfg.Copy()
|
||||
@@ -404,9 +418,6 @@ func (w *Wrapper) ListenAddresses() []string {
|
||||
switch addr {
|
||||
case "default":
|
||||
addresses = append(addresses, DefaultListenAddresses...)
|
||||
if w.cfg.Options.DefaultKCPEnabled { // temporary feature flag
|
||||
addresses = append(addresses, DefaultKCPListenAddress)
|
||||
}
|
||||
default:
|
||||
addresses = append(addresses, addr)
|
||||
}
|
||||
@@ -452,3 +463,9 @@ func (w *Wrapper) MyName() string {
|
||||
cfg, _ := w.Device(myID)
|
||||
return cfg.Name
|
||||
}
|
||||
|
||||
// CheckHomeFreeSpace returns nil if the home disk has the required amount of
|
||||
// free space, or if home disk free space checking is disabled.
|
||||
func (w *Wrapper) CheckHomeFreeSpace() error {
|
||||
return checkFreeSpace(w.Options().MinHomeDiskFree, fs.NewFilesystem(fs.FilesystemTypeBasic, filepath.Dir(w.ConfigPath())))
|
||||
}
|
||||
|
||||
@@ -44,7 +44,6 @@ func (d *kcpDialer) Dial(id protocol.DeviceID, uri *url.URL) (internalConn, erro
|
||||
conn, err = kcp.DialWithOptions(uri.Host, nil, 0, 0)
|
||||
}
|
||||
if err != nil {
|
||||
l.Debugln(err)
|
||||
conn.Close()
|
||||
return internalConn{}, err
|
||||
}
|
||||
@@ -101,6 +100,10 @@ func (kcpDialerFactory) Priority() int {
|
||||
return kcpPriority
|
||||
}
|
||||
|
||||
func (kcpDialerFactory) AlwaysWAN() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (kcpDialerFactory) Enabled(cfg config.Configuration) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -12,16 +12,20 @@ import (
|
||||
"net/url"
|
||||
"strings"
|
||||
"sync"
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/AudriusButkevicius/kcp-go"
|
||||
"github.com/AudriusButkevicius/pfilter"
|
||||
"github.com/ccding/go-stun/stun"
|
||||
"github.com/xtaci/smux"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/nat"
|
||||
"github.com/xtaci/smux"
|
||||
)
|
||||
|
||||
const stunRetryInterval = 5 * time.Minute
|
||||
|
||||
func init() {
|
||||
factory := &kcpListenerFactory{}
|
||||
for _, scheme := range []string{"kcp", "kcp4", "kcp6"} {
|
||||
@@ -38,6 +42,7 @@ type kcpListener struct {
|
||||
stop chan struct{}
|
||||
conns chan internalConn
|
||||
factory listenerFactory
|
||||
nat atomic.Value
|
||||
|
||||
address *url.URL
|
||||
err error
|
||||
@@ -56,7 +61,7 @@ func (t *kcpListener) Serve() {
|
||||
t.mut.Lock()
|
||||
t.err = err
|
||||
t.mut.Unlock()
|
||||
l.Infoln("listen (BEP/kcp):", err)
|
||||
l.Infoln("Listen (BEP/kcp):", err)
|
||||
return
|
||||
}
|
||||
filterConn := pfilter.NewPacketFilter(packetConn)
|
||||
@@ -73,7 +78,7 @@ func (t *kcpListener) Serve() {
|
||||
t.mut.Lock()
|
||||
t.err = err
|
||||
t.mut.Unlock()
|
||||
l.Infoln("listen (BEP/kcp):", err)
|
||||
l.Infoln("Listen (BEP/kcp):", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -102,7 +107,7 @@ func (t *kcpListener) Serve() {
|
||||
}
|
||||
if err != nil {
|
||||
if err, ok := err.(net.Error); !ok || !err.Timeout() {
|
||||
l.Warnln("Accepting connection (BEP/kcp):", err)
|
||||
l.Warnln("Listen (BEP/kcp): Accepting connection:", err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
@@ -183,12 +188,21 @@ func (t *kcpListener) Factory() listenerFactory {
|
||||
return t.factory
|
||||
}
|
||||
|
||||
func (t *kcpListener) NATType() string {
|
||||
v := t.nat.Load().(stun.NATType)
|
||||
if v == stun.NATUnknown || v == stun.NATError {
|
||||
return "unknown"
|
||||
}
|
||||
return v.String()
|
||||
}
|
||||
|
||||
func (t *kcpListener) stunRenewal(listener net.PacketConn) {
|
||||
client := stun.NewClientWithConnection(listener)
|
||||
client.SetSoftwareName("syncthing")
|
||||
|
||||
var natType stun.NATType
|
||||
var extAddr *stun.Host
|
||||
var udpAddr *net.UDPAddr
|
||||
var err error
|
||||
|
||||
oldType := stun.NATUnknown
|
||||
@@ -199,6 +213,7 @@ func (t *kcpListener) stunRenewal(listener net.PacketConn) {
|
||||
if t.cfg.Options().StunKeepaliveS < 1 {
|
||||
time.Sleep(time.Second)
|
||||
oldType = stun.NATUnknown
|
||||
t.nat.Store(stun.NATUnknown)
|
||||
t.mut.Lock()
|
||||
t.address = nil
|
||||
t.mut.Unlock()
|
||||
@@ -206,7 +221,17 @@ func (t *kcpListener) stunRenewal(listener net.PacketConn) {
|
||||
}
|
||||
|
||||
for _, addr := range t.cfg.StunServers() {
|
||||
client.SetServerAddr(addr)
|
||||
// Resolve the address, so that in case the server advertises two
|
||||
// IPs, we always hit the same one, as otherwise, the mapping might
|
||||
// expire as we hit the other address, and cause us to flip flop
|
||||
// between servers/external addresses, as a result flooding discovery
|
||||
// servers.
|
||||
udpAddr, err = net.ResolveUDPAddr("udp", addr)
|
||||
if err != nil {
|
||||
l.Debugf("%s stun addr resolution on %s: %s", t.uri, addr, err)
|
||||
continue
|
||||
}
|
||||
client.SetServerAddr(udpAddr.String())
|
||||
|
||||
natType, extAddr, err = client.Discover()
|
||||
if err != nil || extAddr == nil {
|
||||
@@ -222,6 +247,14 @@ func (t *kcpListener) stunRenewal(listener net.PacketConn) {
|
||||
|
||||
if oldType != natType {
|
||||
l.Infof("%s detected NAT type: %s", t.uri, natType)
|
||||
t.nat.Store(natType)
|
||||
oldType = natType
|
||||
}
|
||||
|
||||
// We can't punch through this one, so no point doing keepalives
|
||||
// and such, just try again in a minute and hope that the NAT type changes.
|
||||
if !isPunchable(natType) {
|
||||
break
|
||||
}
|
||||
|
||||
for {
|
||||
@@ -261,19 +294,18 @@ func (t *kcpListener) stunRenewal(listener net.PacketConn) {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
oldType = natType
|
||||
}
|
||||
|
||||
// We failed to contact all provided stun servers, chillout for a while.
|
||||
time.Sleep(time.Minute)
|
||||
// We failed to contact all provided stun servers or the nat is not punchable.
|
||||
// Chillout for a while.
|
||||
time.Sleep(stunRetryInterval)
|
||||
}
|
||||
}
|
||||
|
||||
type kcpListenerFactory struct{}
|
||||
|
||||
func (f *kcpListenerFactory) New(uri *url.URL, cfg *config.Wrapper, tlsCfg *tls.Config, conns chan internalConn, natService *nat.Service) genericListener {
|
||||
return &kcpListener{
|
||||
l := &kcpListener{
|
||||
uri: fixupPort(uri, config.DefaultKCPPort),
|
||||
cfg: cfg,
|
||||
tlsCfg: tlsCfg,
|
||||
@@ -281,8 +313,14 @@ func (f *kcpListenerFactory) New(uri *url.URL, cfg *config.Wrapper, tlsCfg *tls.
|
||||
stop: make(chan struct{}),
|
||||
factory: f,
|
||||
}
|
||||
l.nat.Store(stun.NATUnknown)
|
||||
return l
|
||||
}
|
||||
|
||||
func (kcpListenerFactory) Enabled(cfg config.Configuration) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func isPunchable(natType stun.NATType) bool {
|
||||
return natType == stun.NATNone || natType == stun.NATPortRestricted || natType == stun.NATRestricted || natType == stun.NATFull
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"sync/atomic"
|
||||
"time"
|
||||
|
||||
"github.com/AudriusButkevicius/kcp-go"
|
||||
"github.com/AudriusButkevicius/pfilter"
|
||||
"github.com/xtaci/smux"
|
||||
)
|
||||
@@ -24,6 +25,10 @@ var (
|
||||
filters filterList
|
||||
)
|
||||
|
||||
func init() {
|
||||
kcp.BlacklistDuration = 10 * time.Minute
|
||||
}
|
||||
|
||||
type filterList []*pfilter.PacketFilter
|
||||
|
||||
// Sort connections by whether they are unspecified or not, as connections
|
||||
|
||||
47
lib/connections/lan_test.go
Normal file
47
lib/connections/lan_test.go
Normal file
@@ -0,0 +1,47 @@
|
||||
// Copyright (C) 2017 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 connections
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
)
|
||||
|
||||
func TestIsLANHost(t *testing.T) {
|
||||
cases := []struct {
|
||||
addr string
|
||||
lan bool
|
||||
}{
|
||||
// loopback
|
||||
{"127.0.0.1:22000", true},
|
||||
{"127.0.0.1", true},
|
||||
// local nets
|
||||
{"10.20.30.40:22000", true},
|
||||
{"10.20.30.40", true},
|
||||
// neither
|
||||
{"192.0.2.1:22000", false},
|
||||
{"192.0.2.1", false},
|
||||
// doesn't resolve
|
||||
{"[banana::phone]:hello", false},
|
||||
{"„‹›fl´fi·‰ˇ¨Á˝", false},
|
||||
}
|
||||
|
||||
cfg := config.Wrap("/dev/null", config.Configuration{
|
||||
Options: config.OptionsConfiguration{
|
||||
AlwaysLocalNets: []string{"10.20.30.0/24"},
|
||||
},
|
||||
})
|
||||
s := &Service{cfg: cfg}
|
||||
|
||||
for _, tc := range cases {
|
||||
res := s.isLANHost(tc.addr)
|
||||
if res != tc.lan {
|
||||
t.Errorf("isLANHost(%q) => %v, expected %v", tc.addr, res, tc.lan)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -45,7 +45,7 @@ func (d *relayDialer) Dial(id protocol.DeviceID, uri *url.URL) (internalConn, er
|
||||
|
||||
err = dialer.SetTrafficClass(conn, d.cfg.Options().TrafficClass)
|
||||
if err != nil {
|
||||
l.Debugf("failed to set traffic class: %s", err)
|
||||
l.Debugln("Dial (BEP/relay): setting traffic class:", err)
|
||||
}
|
||||
|
||||
var tc *tls.Conn
|
||||
@@ -64,10 +64,6 @@ func (d *relayDialer) Dial(id protocol.DeviceID, uri *url.URL) (internalConn, er
|
||||
return internalConn{tc, connTypeRelayClient, relayPriority}, nil
|
||||
}
|
||||
|
||||
func (relayDialer) Priority() int {
|
||||
return relayPriority
|
||||
}
|
||||
|
||||
func (d *relayDialer) RedialFrequency() time.Duration {
|
||||
return time.Duration(d.cfg.Options().RelayReconnectIntervalM) * time.Minute
|
||||
}
|
||||
@@ -85,6 +81,10 @@ func (relayDialerFactory) Priority() int {
|
||||
return relayPriority
|
||||
}
|
||||
|
||||
func (relayDialerFactory) AlwaysWAN() bool {
|
||||
return true
|
||||
}
|
||||
|
||||
func (relayDialerFactory) Enabled(cfg config.Configuration) bool {
|
||||
return cfg.Options.RelaysEnabled
|
||||
}
|
||||
|
||||
@@ -50,7 +50,7 @@ func (t *relayListener) Serve() {
|
||||
t.mut.Lock()
|
||||
t.err = err
|
||||
t.mut.Unlock()
|
||||
l.Warnln("listen (BEP/relay):", err)
|
||||
l.Warnln("Listen (BEP/relay):", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -62,6 +62,9 @@ func (t *relayListener) Serve() {
|
||||
|
||||
oldURI := clnt.URI()
|
||||
|
||||
l.Infof("Relay listener (%v) starting", t)
|
||||
defer l.Infof("Relay listener (%v) shutting down", t)
|
||||
|
||||
for {
|
||||
select {
|
||||
case inv, ok := <-invitations:
|
||||
@@ -71,18 +74,18 @@ func (t *relayListener) Serve() {
|
||||
|
||||
conn, err := client.JoinSession(inv)
|
||||
if err != nil {
|
||||
l.Infoln("Joining relay session (BEP/relay):", err)
|
||||
l.Infoln("Listen (BEP/relay): joining session:", err)
|
||||
continue
|
||||
}
|
||||
|
||||
err = dialer.SetTCPOptions(conn)
|
||||
if err != nil {
|
||||
l.Infoln(err)
|
||||
l.Debugln("Listen (BEP/relay): setting tcp options:", err)
|
||||
}
|
||||
|
||||
err = dialer.SetTrafficClass(conn, t.cfg.Options().TrafficClass)
|
||||
if err != nil {
|
||||
l.Debugf("failed to set traffic class: %s", err)
|
||||
l.Debugln("Listen (BEP/relay): setting traffic class:", err)
|
||||
}
|
||||
|
||||
var tc *tls.Conn
|
||||
@@ -95,7 +98,7 @@ func (t *relayListener) Serve() {
|
||||
err = tlsTimedHandshake(tc)
|
||||
if err != nil {
|
||||
tc.Close()
|
||||
l.Infoln("TLS handshake (BEP/relay):", err)
|
||||
l.Infoln("Listen (BEP/relay): TLS handshake:", err)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -171,6 +174,10 @@ func (t *relayListener) String() string {
|
||||
return t.uri.String()
|
||||
}
|
||||
|
||||
func (t *relayListener) NATType() string {
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
type relayListenerFactory struct{}
|
||||
|
||||
func (f *relayListenerFactory) New(uri *url.URL, cfg *config.Wrapper, tlsCfg *tls.Config, conns chan internalConn, natService *nat.Service) genericListener {
|
||||
|
||||
@@ -12,13 +12,16 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/url"
|
||||
"sort"
|
||||
"strings"
|
||||
stdsync "sync"
|
||||
"time"
|
||||
|
||||
"github.com/syncthing/syncthing/lib/config"
|
||||
"github.com/syncthing/syncthing/lib/discover"
|
||||
"github.com/syncthing/syncthing/lib/events"
|
||||
"github.com/syncthing/syncthing/lib/nat"
|
||||
"github.com/syncthing/syncthing/lib/osutil"
|
||||
"github.com/syncthing/syncthing/lib/protocol"
|
||||
"github.com/syncthing/syncthing/lib/sync"
|
||||
"github.com/syncthing/syncthing/lib/util"
|
||||
@@ -79,7 +82,6 @@ type Service struct {
|
||||
conns chan internalConn
|
||||
bepProtocolName string
|
||||
tlsDefaultCommonName string
|
||||
lans []*net.IPNet
|
||||
limiter *limiter
|
||||
natService *nat.Service
|
||||
natServiceToken *suture.ServiceToken
|
||||
@@ -88,13 +90,10 @@ type Service struct {
|
||||
listeners map[string]genericListener
|
||||
listenerTokens map[string]suture.ServiceToken
|
||||
listenerSupervisor *suture.Supervisor
|
||||
|
||||
curConMut sync.Mutex
|
||||
currentConnection map[protocol.DeviceID]completeConn
|
||||
}
|
||||
|
||||
func NewService(cfg *config.Wrapper, myID protocol.DeviceID, mdl Model, tlsCfg *tls.Config, discoverer discover.Finder,
|
||||
bepProtocolName string, tlsDefaultCommonName string, lans []*net.IPNet) *Service {
|
||||
bepProtocolName string, tlsDefaultCommonName string) *Service {
|
||||
|
||||
service := &Service{
|
||||
Supervisor: suture.New("connections.Service", suture.Spec{
|
||||
@@ -110,7 +109,6 @@ func NewService(cfg *config.Wrapper, myID protocol.DeviceID, mdl Model, tlsCfg *
|
||||
conns: make(chan internalConn),
|
||||
bepProtocolName: bepProtocolName,
|
||||
tlsDefaultCommonName: tlsDefaultCommonName,
|
||||
lans: lans,
|
||||
limiter: newLimiter(cfg),
|
||||
natService: nat.NewService(myID, cfg),
|
||||
|
||||
@@ -129,12 +127,15 @@ func NewService(cfg *config.Wrapper, myID protocol.DeviceID, mdl Model, tlsCfg *
|
||||
FailureThreshold: 2,
|
||||
FailureBackoff: 600 * time.Second,
|
||||
}),
|
||||
|
||||
curConMut: sync.NewMutex(),
|
||||
currentConnection: make(map[protocol.DeviceID]completeConn),
|
||||
}
|
||||
cfg.Subscribe(service)
|
||||
|
||||
raw := cfg.RawCopy()
|
||||
// Actually starts the listeners and NAT service
|
||||
// Need to start this before service.connect so that any dials that
|
||||
// try punch through already have a listener to cling on.
|
||||
service.CommitConfiguration(raw, raw)
|
||||
|
||||
// There are several moving parts here; one routine per listening address
|
||||
// (handled in configuration changing) to handle incoming connections,
|
||||
// one routine to periodically attempt outgoing connections, one routine to
|
||||
@@ -145,10 +146,6 @@ func NewService(cfg *config.Wrapper, myID protocol.DeviceID, mdl Model, tlsCfg *
|
||||
service.Add(serviceFunc(service.handle))
|
||||
service.Add(service.listenerSupervisor)
|
||||
|
||||
raw := cfg.RawCopy()
|
||||
// Actually starts the listeners and NAT service
|
||||
service.CommitConfiguration(raw, raw)
|
||||
|
||||
return service
|
||||
}
|
||||
|
||||
@@ -225,16 +222,12 @@ next:
|
||||
}
|
||||
|
||||
// If we have a relay connection, and the new incoming connection is
|
||||
// not a relay connection, we should drop that, and prefer the this one.
|
||||
connected := s.model.ConnectedTo(remoteID)
|
||||
s.curConMut.Lock()
|
||||
ct, ok := s.currentConnection[remoteID]
|
||||
s.curConMut.Unlock()
|
||||
priorityKnown := ok && connected
|
||||
// not a relay connection, we should drop that, and prefer this one.
|
||||
ct, connected := s.model.Connection(remoteID)
|
||||
|
||||
// Lower priority is better, just like nice etc.
|
||||
if priorityKnown && ct.internalConn.priority > c.priority {
|
||||
l.Debugln("Switching connections", remoteID)
|
||||
if connected && ct.Priority() > c.priority {
|
||||
l.Debugf("Switching connections %s (existing: %s new: %s)", remoteID, ct, c)
|
||||
} else if connected {
|
||||
// We should not already be connected to the other party. TODO: This
|
||||
// could use some better handling. If the old connection is dead but
|
||||
@@ -242,7 +235,7 @@ next:
|
||||
// this one. But in case we are two devices connecting to each other
|
||||
// in parallel we don't want to do that or we end up with no
|
||||
// connections still established...
|
||||
l.Infof("Connected to already connected device (%s)", remoteID)
|
||||
l.Infof("Connected to already connected device %s (existing: %s new: %s)", remoteID, ct, c)
|
||||
c.Close()
|
||||
continue
|
||||
}
|
||||
@@ -282,9 +275,6 @@ next:
|
||||
l.Infof("Established secure connection to %s at %s (%s)", remoteID, name, tlsCipherSuiteNames[c.ConnectionState().CipherSuite])
|
||||
|
||||
s.model.AddConnection(modelConn, hello)
|
||||
s.curConMut.Lock()
|
||||
s.currentConnection[remoteID] = modelConn
|
||||
s.curConMut.Unlock()
|
||||
continue next
|
||||
}
|
||||
}
|
||||
@@ -317,7 +307,6 @@ func (s *Service) connect() {
|
||||
now := time.Now()
|
||||
var seen []string
|
||||
|
||||
nextDevice:
|
||||
for _, deviceCfg := range cfg.Devices {
|
||||
deviceID := deviceCfg.DeviceID
|
||||
if deviceID == s.myID {
|
||||
@@ -328,19 +317,13 @@ func (s *Service) connect() {
|
||||
continue
|
||||
}
|
||||
|
||||
connected := s.model.ConnectedTo(deviceID)
|
||||
s.curConMut.Lock()
|
||||
ct, ok := s.currentConnection[deviceID]
|
||||
s.curConMut.Unlock()
|
||||
priorityKnown := ok && connected
|
||||
ct, connected := s.model.Connection(deviceID)
|
||||
|
||||
if priorityKnown && ct.internalConn.priority == bestDialerPrio {
|
||||
if connected && ct.Priority() == bestDialerPrio {
|
||||
// Things are already as good as they can get.
|
||||
continue
|
||||
}
|
||||
|
||||
l.Debugln("Reconnect loop for", deviceID)
|
||||
|
||||
var addrs []string
|
||||
for _, addr := range deviceCfg.Addresses {
|
||||
if addr == "dynamic" {
|
||||
@@ -354,8 +337,14 @@ func (s *Service) connect() {
|
||||
}
|
||||
}
|
||||
|
||||
addrs = util.UniqueStrings(addrs)
|
||||
|
||||
l.Debugln("Reconnect loop for", deviceID, addrs)
|
||||
|
||||
seen = append(seen, addrs...)
|
||||
|
||||
dialTargets := make([]dialTarget, 0)
|
||||
|
||||
for _, addr := range addrs {
|
||||
nextDialAt, ok := nextDial[addr]
|
||||
if ok && initialRampup >= sleep && nextDialAt.After(now) {
|
||||
@@ -368,7 +357,7 @@ func (s *Service) connect() {
|
||||
|
||||
uri, err := url.Parse(addr)
|
||||
if err != nil {
|
||||
l.Infof("Dialer for %s: %v", addr, err)
|
||||
l.Infof("Parsing dialer address %s: %v", addr, err)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -381,31 +370,44 @@ func (s *Service) connect() {
|
||||
|
||||
dialerFactory, err := s.getDialerFactory(cfg, uri)
|
||||
if err == errDisabled {
|
||||
l.Debugln("Dialer for", uri, "is disabled")
|
||||
l.Debugln(dialerFactory, "for", uri, "is disabled")
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
l.Infof("Dialer for %v: %v", uri, err)
|
||||
l.Infof("%v for %v: %v", dialerFactory, uri, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if priorityKnown && dialerFactory.Priority() >= ct.internalConn.priority {
|
||||
l.Debugf("Not dialing using %s as priority is less than current connection (%d >= %d)", dialerFactory, dialerFactory.Priority(), ct.internalConn.priority)
|
||||
priority := dialerFactory.Priority()
|
||||
|
||||
if connected && priority >= ct.Priority() {
|
||||
l.Debugf("Not dialing using %s as priority is less than current connection (%d >= %d)", dialerFactory, dialerFactory.Priority(), ct.Priority())
|
||||
continue
|
||||
}
|
||||
|
||||
dialer := dialerFactory.New(s.cfg, s.tlsCfg)
|
||||
l.Debugln("dial", deviceCfg.DeviceID, uri)
|
||||
nextDial[addr] = now.Add(dialer.RedialFrequency())
|
||||
|
||||
conn, err := dialer.Dial(deviceID, uri)
|
||||
if err != nil {
|
||||
l.Debugln("dial failed", deviceCfg.DeviceID, uri, err)
|
||||
continue
|
||||
// For LAN addresses, increase the priority so that we
|
||||
// try these first.
|
||||
switch {
|
||||
case dialerFactory.AlwaysWAN():
|
||||
// Do nothing.
|
||||
case s.isLANHost(uri.Host):
|
||||
priority -= 1
|
||||
}
|
||||
|
||||
dialTargets = append(dialTargets, dialTarget{
|
||||
dialer: dialer,
|
||||
priority: priority,
|
||||
deviceID: deviceID,
|
||||
uri: uri,
|
||||
})
|
||||
}
|
||||
|
||||
conn, ok := dialParallel(deviceCfg.DeviceID, dialTargets)
|
||||
if ok {
|
||||
s.conns <- conn
|
||||
continue nextDevice
|
||||
}
|
||||
}
|
||||
|
||||
@@ -422,17 +424,59 @@ func (s *Service) connect() {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Service) isLANHost(host string) bool {
|
||||
// Probably we are called with an ip:port combo which we can resolve as
|
||||
// a TCP address.
|
||||
if addr, err := net.ResolveTCPAddr("tcp", host); err == nil {
|
||||
return s.isLAN(addr)
|
||||
}
|
||||
// ... but this function looks general enough that someone might try
|
||||
// with just an IP as well in the future so lets allow that.
|
||||
if addr, err := net.ResolveIPAddr("ip", host); err == nil {
|
||||
return s.isLAN(addr)
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *Service) isLAN(addr net.Addr) bool {
|
||||
tcpaddr, ok := addr.(*net.TCPAddr)
|
||||
if !ok {
|
||||
var ip net.IP
|
||||
|
||||
switch addr := addr.(type) {
|
||||
case *net.IPAddr:
|
||||
ip = addr.IP
|
||||
case *net.TCPAddr:
|
||||
ip = addr.IP
|
||||
case *net.UDPAddr:
|
||||
ip = addr.IP
|
||||
default:
|
||||
// From the standard library, just Unix sockets.
|
||||
// If you invent your own, handle it.
|
||||
return false
|
||||
}
|
||||
for _, lan := range s.lans {
|
||||
if lan.Contains(tcpaddr.IP) {
|
||||
|
||||
if ip.IsLoopback() {
|
||||
return true
|
||||
}
|
||||
|
||||
for _, lan := range s.cfg.Options().AlwaysLocalNets {
|
||||
_, ipnet, err := net.ParseCIDR(lan)
|
||||
if err != nil {
|
||||
l.Debugln("Network", lan, "is malformed:", err)
|
||||
continue
|
||||
}
|
||||
if ipnet.Contains(ip) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return tcpaddr.IP.IsLoopback()
|
||||
|
||||
lans, _ := osutil.GetLans()
|
||||
for _, lan := range lans {
|
||||
if lan.Contains(ip) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *Service) createListener(factory listenerFactory, uri *url.URL) bool {
|
||||
@@ -467,9 +511,6 @@ func (s *Service) CommitConfiguration(from, to config.Configuration) bool {
|
||||
|
||||
for _, dev := range from.Devices {
|
||||
if !newDevices[dev.DeviceID] {
|
||||
s.curConMut.Lock()
|
||||
delete(s.currentConnection, dev.DeviceID)
|
||||
s.curConMut.Unlock()
|
||||
warningLimitersMut.Lock()
|
||||
delete(warningLimiters, dev.DeviceID)
|
||||
warningLimitersMut.Unlock()
|
||||
@@ -479,6 +520,13 @@ func (s *Service) CommitConfiguration(from, to config.Configuration) bool {
|
||||
s.listenersMut.Lock()
|
||||
seen := make(map[string]struct{})
|
||||
for _, addr := range config.Wrap("", to).ListenAddresses() {
|
||||
if addr == "" {
|
||||
// We can get an empty address if there is an empty listener
|
||||
// element in the config, indicating no listeners should be
|
||||
// used. This is not an error.
|
||||
continue
|
||||
}
|
||||
|
||||
if _, ok := s.listeners[addr]; ok {
|
||||
seen[addr] = struct{}{}
|
||||
continue
|
||||
@@ -486,7 +534,7 @@ func (s *Service) CommitConfiguration(from, to config.Configuration) bool {
|
||||
|
||||
uri, err := url.Parse(addr)
|
||||
if err != nil {
|
||||
l.Infof("Listener for %s: %v", addr, err)
|
||||
l.Infof("Parsing listener address %s: %v", addr, err)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -496,7 +544,7 @@ func (s *Service) CommitConfiguration(from, to config.Configuration) bool {
|
||||
continue
|
||||
}
|
||||
if err != nil {
|
||||
l.Infof("Listener for %v: %v", uri, err)
|
||||
l.Infof("Getting listener factory for %v: %v", uri, err)
|
||||
continue
|
||||
}
|
||||
|
||||
@@ -574,6 +622,18 @@ func (s *Service) Status() map[string]interface{} {
|
||||
return result
|
||||
}
|
||||
|
||||
func (s *Service) NATType() string {
|
||||
s.listenersMut.RLock()
|
||||
defer s.listenersMut.RUnlock()
|
||||
for _, listener := range s.listeners {
|
||||
natType := listener.NATType()
|
||||
if natType != "unknown" {
|
||||
return natType
|
||||
}
|
||||
}
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
func (s *Service) getDialerFactory(cfg config.Configuration, uri *url.URL) (dialerFactory, error) {
|
||||
dialerFactory, ok := dialers[uri.Scheme]
|
||||
if !ok {
|
||||
@@ -679,3 +739,64 @@ func IsAllowedNetwork(host string, allowed []string) bool {
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
func dialParallel(deviceID protocol.DeviceID, dialTargets []dialTarget) (internalConn, bool) {
|
||||
// Group targets into buckets by priority
|
||||
dialTargetBuckets := make(map[int][]dialTarget, len(dialTargets))
|
||||
for _, tgt := range dialTargets {
|
||||
dialTargetBuckets[tgt.priority] = append(dialTargetBuckets[tgt.priority], tgt)
|
||||
}
|
||||
|
||||
// Get all available priorities
|
||||
priorities := make([]int, 0, len(dialTargetBuckets))
|
||||
for prio := range dialTargetBuckets {
|
||||
priorities = append(priorities, prio)
|
||||
}
|
||||
|
||||
// Sort the priorities so that we dial lowest first (which means highest...)
|
||||
sort.Ints(priorities)
|
||||
|
||||
for _, prio := range priorities {
|
||||
tgts := dialTargetBuckets[prio]
|
||||
res := make(chan internalConn, len(tgts))
|
||||
wg := stdsync.WaitGroup{}
|
||||
for _, tgt := range tgts {
|
||||
wg.Add(1)
|
||||
go func(tgt dialTarget) {
|
||||
conn, err := tgt.Dial()
|
||||
if err == nil {
|
||||
res <- conn
|
||||
}
|
||||
wg.Done()
|
||||
}(tgt)
|
||||
}
|
||||
|
||||
// Spawn a routine which will unblock main routine in case we fail
|
||||
// to connect to anyone.
|
||||
go func() {
|
||||
wg.Wait()
|
||||
close(res)
|
||||
}()
|
||||
|
||||
// Wait for the first connection, or for channel closure.
|
||||
conn, ok := <-res
|
||||
|
||||
// Got a connection, means more might come back, hence spawn a
|
||||
// routine that will do the discarding.
|
||||
if ok {
|
||||
l.Debugln("connected to", deviceID, prio, "using", conn, conn.priority)
|
||||
go func(deviceID protocol.DeviceID, prio int) {
|
||||
wg.Wait()
|
||||
l.Debugln("discarding", len(res), "connections while connecting to", deviceID, prio)
|
||||
for conn := range res {
|
||||
conn.Close()
|
||||
}
|
||||
}(deviceID, prio)
|
||||
return conn, ok
|
||||
} else {
|
||||
// Failed to connect, report that fact.
|
||||
l.Debugln("failed to connect to", deviceID, prio)
|
||||
}
|
||||
}
|
||||
return internalConn{}, false
|
||||
}
|
||||
|
||||
@@ -25,7 +25,9 @@ type Connection interface {
|
||||
protocol.Connection
|
||||
io.Closer
|
||||
Type() string
|
||||
Transport() string
|
||||
RemoteAddr() net.Addr
|
||||
Priority() int
|
||||
}
|
||||
|
||||
// completeConn is the aggregation of an internalConn and the
|
||||
@@ -74,10 +76,43 @@ func (t connType) String() string {
|
||||
}
|
||||
}
|
||||
|
||||
func (t connType) Transport() string {
|
||||
switch t {
|
||||
case connTypeRelayClient, connTypeRelayServer:
|
||||
return "relay"
|
||||
case connTypeTCPClient, connTypeTCPServer:
|
||||
return "tcp"
|
||||
case connTypeKCPClient, connTypeKCPServer:
|
||||
return "kcp"
|
||||
default:
|
||||
return "unknown"
|
||||
}
|
||||
}
|
||||
|
||||
func (c internalConn) Type() string {
|
||||
return c.connType.String()
|
||||
}
|
||||
|
||||
func (c internalConn) Priority() int {
|
||||
return c.priority
|
||||
}
|
||||
|
||||
func (c internalConn) Transport() string {
|
||||
transport := c.connType.Transport()
|
||||
host, _, err := net.SplitHostPort(c.LocalAddr().String())
|
||||
if err != nil {
|
||||
return transport
|
||||
}
|
||||
ip := net.ParseIP(host)
|
||||
if ip == nil {
|
||||
return transport
|
||||
}
|
||||
if ip.To4() != nil {
|
||||
return transport + "4"
|
||||
}
|
||||
return transport + "6"
|
||||
}
|
||||
|
||||
func (c internalConn) String() string {
|
||||
return fmt.Sprintf("%s-%s/%s", c.LocalAddr(), c.RemoteAddr(), c.connType.String())
|
||||
}
|
||||
@@ -85,6 +120,7 @@ func (c internalConn) String() string {
|
||||
type dialerFactory interface {
|
||||
New(*config.Wrapper, *tls.Config) genericDialer
|
||||
Priority() int
|
||||
AlwaysWAN() bool
|
||||
Enabled(config.Configuration) bool
|
||||
String() string
|
||||
}
|
||||
@@ -116,12 +152,13 @@ type genericListener interface {
|
||||
OnAddressesChanged(func(genericListener))
|
||||
String() string
|
||||
Factory() listenerFactory
|
||||
NATType() string
|
||||
}
|
||||
|
||||
type Model interface {
|
||||
protocol.Model
|
||||
AddConnection(conn Connection, hello protocol.HelloResult)
|
||||
ConnectedTo(remoteID protocol.DeviceID) bool
|
||||
Connection(remoteID protocol.DeviceID) (Connection, bool)
|
||||
OnHello(protocol.DeviceID, net.Addr, protocol.HelloResult) error
|
||||
GetHello(protocol.DeviceID) protocol.HelloIntf
|
||||
}
|
||||
@@ -146,3 +183,21 @@ func (o *onAddressesChangedNotifier) notifyAddressesChanged(l genericListener) {
|
||||
callback(l)
|
||||
}
|
||||
}
|
||||
|
||||
type dialTarget struct {
|
||||
dialer genericDialer
|
||||
priority int
|
||||
uri *url.URL
|
||||
deviceID protocol.DeviceID
|
||||
}
|
||||
|
||||
func (t dialTarget) Dial() (internalConn, error) {
|
||||
l.Debugln("dialing", t.deviceID, t.uri, "prio", t.priority)
|
||||
conn, err := t.dialer.Dial(t.deviceID, t.uri)
|
||||
if err != nil {
|
||||
l.Debugln("dialing", t.deviceID, t.uri, "error:", err)
|
||||
} else {
|
||||
l.Debugln("dialing", t.deviceID, t.uri, "success:", conn)
|
||||
}
|
||||
return conn, err
|
||||
}
|
||||
|
||||
@@ -33,18 +33,17 @@ func (d *tcpDialer) Dial(id protocol.DeviceID, uri *url.URL) (internalConn, erro
|
||||
|
||||
conn, err := dialer.DialTimeout(uri.Scheme, uri.Host, 10*time.Second)
|
||||
if err != nil {
|
||||
l.Debugln(err)
|
||||
return internalConn{}, err
|
||||
}
|
||||
|
||||
err = dialer.SetTCPOptions(conn)
|
||||
if err != nil {
|
||||
l.Infoln(err)
|
||||
l.Debugln("Dial (BEP/tcp): setting tcp options:", err)
|
||||
}
|
||||
|
||||
err = dialer.SetTrafficClass(conn, d.cfg.Options().TrafficClass)
|
||||
if err != nil {
|
||||
l.Debugf("failed to set traffic class: %s", err)
|
||||
l.Debugln("Dial (BEP/tcp): setting traffic class:", err)
|
||||
}
|
||||
|
||||
tc := tls.Client(conn, d.tlsCfg)
|
||||
@@ -74,6 +73,10 @@ func (tcpDialerFactory) Priority() int {
|
||||
return tcpPriority
|
||||
}
|
||||
|
||||
func (tcpDialerFactory) AlwaysWAN() bool {
|
||||
return false
|
||||
}
|
||||
|
||||
func (tcpDialerFactory) Enabled(cfg config.Configuration) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
@@ -52,7 +52,7 @@ func (t *tcpListener) Serve() {
|
||||
t.mut.Lock()
|
||||
t.err = err
|
||||
t.mut.Unlock()
|
||||
l.Infoln("listen (BEP/tcp):", err)
|
||||
l.Infoln("Listen (BEP/tcp):", err)
|
||||
return
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ func (t *tcpListener) Serve() {
|
||||
t.mut.Lock()
|
||||
t.err = err
|
||||
t.mut.Unlock()
|
||||
l.Infoln("listen (BEP/tcp):", err)
|
||||
l.Infoln("Listen (BEP/tcp):", err)
|
||||
return
|
||||
}
|
||||
defer listener.Close()
|
||||
@@ -95,27 +95,26 @@ func (t *tcpListener) Serve() {
|
||||
}
|
||||
if err != nil {
|
||||
if err, ok := err.(*net.OpError); !ok || !err.Timeout() {
|
||||
l.Warnln("Accepting connection (BEP/tcp):", err)
|
||||
l.Warnln("Listen (BEP/tcp): Accepting connection:", err)
|
||||
}
|
||||
continue
|
||||
}
|
||||
|
||||
l.Debugln("connect from", conn.RemoteAddr())
|
||||
l.Debugln("Listen (BEP/tcp): connect from", conn.RemoteAddr())
|
||||
|
||||
err = dialer.SetTCPOptions(conn)
|
||||
if err != nil {
|
||||
l.Infoln(err)
|
||||
if err := dialer.SetTCPOptions(conn); err != nil {
|
||||
l.Debugln("Listen (BEP/tcp): setting tcp options:", err)
|
||||
}
|
||||
|
||||
err = dialer.SetTrafficClass(conn, t.cfg.Options().TrafficClass)
|
||||
if err != nil {
|
||||
l.Debugf("failed to set traffic class: %s", err)
|
||||
if tc := t.cfg.Options().TrafficClass; tc != 0 {
|
||||
if err := dialer.SetTrafficClass(conn, tc); err != nil {
|
||||
l.Debugln("Listen (BEP/tcp): setting traffic class:", err)
|
||||
}
|
||||
}
|
||||
|
||||
tc := tls.Server(conn, t.tlsCfg)
|
||||
err = tlsTimedHandshake(tc)
|
||||
if err != nil {
|
||||
l.Infoln("TLS handshake (BEP/tcp):", err)
|
||||
if err := tlsTimedHandshake(tc); err != nil {
|
||||
l.Infoln("Listen (BEP/tcp): TLS handshake:", err)
|
||||
tc.Close()
|
||||
continue
|
||||
}
|
||||
@@ -176,6 +175,10 @@ func (t *tcpListener) Factory() listenerFactory {
|
||||
return t.factory
|
||||
}
|
||||
|
||||
func (t *tcpListener) NATType() string {
|
||||
return "unknown"
|
||||
}
|
||||
|
||||
type tcpListenerFactory struct{}
|
||||
|
||||
func (f *tcpListenerFactory) New(uri *url.URL, cfg *config.Wrapper, tlsCfg *tls.Config, conns chan internalConn, natService *nat.Service) genericListener {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user