Compare commits

...

108 Commits

Author SHA1 Message Date
Jakob Borg
f1b253fc00 lib/db: Don't whack blocks when putting truncated file (#6434)
As of the latest database checker we are again putting files without
blocks. I'm not 100% convinced that's a great idea, but we also do it
for ignored files apparently so it looks like we probably should support
it. This adds an escape hatch that must be manually enabled...
2020-03-20 12:07:29 +01:00
Simon Frei
b33d5e57c6 lib/db, lib/syncthing: Repair db once on upgrade (ref #6425, #6427) (#6429) 2020-03-19 16:00:05 +01:00
Simon Frei
0060840249 lib/db: Fix removeFromGlobal and no filenames in error (fixes #6427) (#6428) 2020-03-19 16:00:05 +01:00
Simon Frei
71faae67f2 lib/db: Remove emptied global list in checkGlobals (fixes #6425) (#6426) 2020-03-19 15:59:49 +01:00
Simon Frei
00b2340f9a lib/db: Checkpoint during schema updates (fixes #6422) (#6424) 2020-03-18 20:33:43 +01:00
Simon Frei
cc2a55892f lib: Repair sequence inconsistencies (#6367) 2020-03-18 17:34:46 +01:00
Jakob Borg
80107d5f5e lib/config: Correct spelling of address in LDAP config (#6420)
Literally noone uses this so I don't see a need to call this out or
trigger a 1.5 release for it.
2020-03-18 10:44:00 +00:00
Mario Majila
f10e85d0c2 gui: Display folder name in modal (fixes #5380) (#6407) 2020-03-18 11:13:58 +01:00
Kevin Bushiri
f4a6e4439a gui: Add folder name for restore version modal (fixes #5380) (#6418) 2020-03-18 11:11:40 +01:00
Jakob Borg
2ae3ea0d52 gui, man, authors: Update docs, translations, and contributors 2020-03-18 07:45:30 +01:00
Alex Xu
1e68ab3f90 lib/beacon: Only send to appropriately flagged interfaces (ref #5957) (#6404)
saves some traffic (potential mobile wakeups), may help with #5957.
2020-03-17 09:40:37 +01:00
Simon Mwepu
f08d09f607 gui: Display device name in modal (fixes #5380) (#6405) 2020-03-17 08:23:45 +01:00
Jakob Borg
e053db6a5e lib/protocol: Zero pad index ID strings 2020-03-17 07:40:52 +01:00
Simon Frei
1bd4ea0cbb lib/db: Don't ignore failures unmarshaling version lists (#6411) 2020-03-16 10:09:27 +01:00
Simon Frei
a1cb1d70c4 lib/db: Use need func in withNeed and simplify (#6412) 2020-03-16 08:45:45 +01:00
Simon Frei
c101a04179 cmd/syncthing: Do auto-upgrade before startup (fixes #6384) (#6385) 2020-03-16 08:12:32 +01:00
Simon Frei
16698b12b1 lib/db: Extend set test with second remote (#6402) 2020-03-11 08:15:45 +01:00
Jakob Borg
0bc571b2fd gui, man, authors: Update docs, translations, and contributors 2020-03-11 07:45:28 +01:00
Jakob Borg
20aaa5927b lib/protocol: Use BlocksHash to compare block lists when available (#6401)
This is an optimization for faster equal checks on block lists.
2020-03-10 14:46:49 +01:00
Jakob Borg
d612c35290 lib/api: Ignore that one file that always shows up in git status 2020-03-07 11:46:54 +01:00
Jakob Borg
5ab257fb60 Merge branch 'release'
* release:
  lib/db: Be more lenient during migration (fixes #6397) (#6398)
2020-03-06 20:53:55 +01:00
Jakob Borg
db02545ef3 lib/db: Be more lenient during migration (fixes #6397) (#6398) 2020-03-06 20:52:22 +01:00
Jakob Borg
2faa1ad360 lib/db: Be more lenient during migration (fixes #6397) (#6398) 2020-03-06 20:50:55 +01:00
Jakob Borg
860ae7f395 cmd/ursrv: Analytics for Synology dist 2020-03-06 07:46:11 +01:00
Jakob Borg
135c71ca87 build: Build image should use Go 1.13 for now 2020-03-05 11:53:07 +01:00
Jakob Borg
c7d6a6d780 gui, lib/api: Remove CPU & RAM measurements (fixes #6249) (#6393) 2020-03-04 20:27:48 +01:00
Jakob Borg
92533dd9f0 gui, man, authors: Update docs, translations, and contributors 2020-03-04 07:45:31 +01:00
Jakob Borg
dd92b2b8f4 all: Tweak error creation (#6391)
- In the few places where we wrap errors, use the new Go 1.13 "%w"
  construction instead of %s or %v.

- Where we create errors with constant strings, consistently use
  errors.New and not fmt.Errorf.

- Remove capitalization from errors in the few places where we had that.
2020-03-03 22:40:00 +01:00
Jakob Borg
eddc8d3ff2 authors: Cleanup on request 2020-03-02 16:31:29 +01:00
Jakob Borg
dfdd5af7a6 build: We can now use Go 1.13 2020-03-01 12:59:49 +01:00
Jakob Borg
6b5c281dd5 Merge branch 'release'
* release:
  lib/db: Prevent GC concurrently with migration (fixes #6389) (#6390)
  build: Fix syso creation (fixes #6386) (#6387)
2020-02-29 19:58:49 +01:00
Jakob Borg
52e72e0122 lib/db: Prevent GC concurrently with migration (fixes #6389) (#6390) 2020-02-29 19:51:48 +01:00
Jakob Borg
c08e253e7c lib/db: Prevent GC concurrently with migration (fixes #6389) (#6390) 2020-02-29 19:51:32 +01:00
Evgeny Kuznetsov
d1e0a38c04 build: Fix syso creation (fixes #6386) (#6387) 2020-02-29 19:48:42 +01:00
Evgeny Kuznetsov
ac19cdb2cd build: Fix syso creation (fixes #6386) (#6387) 2020-02-28 20:40:14 +01:00
Jakob Borg
58607486af Merge branch 'release'
* release:
  lib/db: Correct metadata recalculation (fixes #6381) (#6382)
2020-02-28 11:21:51 +01:00
Jakob Borg
0b610017ea lib/db: Correct metadata recalculation (fixes #6381) (#6382)
If we decide to recalculate the metadata we shouldn't start from
whatever we loaded from the database, as that data is wrong. We should
start from a clean slate.
2020-02-28 11:17:02 +01:00
Jakob Borg
5de6f6d349 lib/db: Correct metadata recalculation (fixes #6381) (#6382)
If we decide to recalculate the metadata we shouldn't start from
whatever we loaded from the database, as that data is wrong. We should
start from a clean slate.
2020-02-28 11:16:33 +01:00
Jakob Borg
daf05c6509 Merge branch 'release'
* release:
  lib/db: Remove reference to env var that never existed
  lib/db: Slightly improve indirection (ref #6372) (#6373)
2020-02-27 11:24:18 +01:00
Jakob Borg
9a1df97c69 lib/db: Remove reference to env var that never existed 2020-02-27 11:22:09 +01:00
Jakob Borg
ee61da5b6a lib/db: Slightly improve indirection (ref #6372) (#6373)
I was working on indirecting version vectors, and that resulted in some
refactoring and improving the existing block indirection stuff. We may
or may not end up doing the version vector indirection, but I think
these changes are reasonable anyhow and will simplify the diff
significantly if we do go there. The main points are:

- A bunch of renaming to make the indirection and GC not about "blocks"
  but about "indirection".

- Adding a cutoff so that we don't actually indirect for small block
  lists. This gets us better performance when handling small files as it
  cuts out the indirection for quite small loss in space efficiency.

- Being paranoid and always recalculating the hash on put. This costs
  some CPU, but the consequences if a buggy or malicious implementation
  silently substituted the block list by lying about the hash would be bad.
2020-02-27 11:22:01 +01:00
Jakob Borg
883497966e lib/db: Remove reference to env var that never existed 2020-02-27 11:21:35 +01:00
Jakob Borg
4f7a77597e lib/db: Slightly improve indirection (ref #6372) (#6373)
I was working on indirecting version vectors, and that resulted in some
refactoring and improving the existing block indirection stuff. We may
or may not end up doing the version vector indirection, but I think
these changes are reasonable anyhow and will simplify the diff
significantly if we do go there. The main points are:

- A bunch of renaming to make the indirection and GC not about "blocks"
  but about "indirection".

- Adding a cutoff so that we don't actually indirect for small block
  lists. This gets us better performance when handling small files as it
  cuts out the indirection for quite small loss in space efficiency.

- Being paranoid and always recalculating the hash on put. This costs
  some CPU, but the consequences if a buggy or malicious implementation
  silently substituted the block list by lying about the hash would be bad.
2020-02-27 11:19:21 +01:00
Jakob Borg
c4b9046eaa build: Forked github.com/spaolacci/murmur3 for unsafe (ref #6371) 2020-02-26 20:25:24 +01:00
Simon Frei
299a80d328 cmd/syncthing: Do not truncate/rotate logs at start (#6359) 2020-02-26 13:49:03 +01:00
Jakob Borg
4e4b9a872a lib/dialer: Preserve nilness in error handling (fixes #6368) (#6369)
Also the call site where it shouldn't anyway be looking at the conn when
the err is non-nil.
2020-02-26 13:16:18 +01:00
Simon Frei
cb624dbf5d cmd/syncthing: Add indication that reset db happened (#6364) 2020-02-26 12:38:43 +01:00
Audrius Butkevicius
71aecc5cd4 lib/dialer: Bring back address faking connection (fixes #6289) (#6363) 2020-02-26 12:37:23 +01:00
Jakob Borg
10af09e4b4 gui, man, authors: Update docs, translations, and contributors 2020-02-26 07:45:29 +01:00
Simon Frei
680b0b14db lib/connections: Refactor status for testing (ref #6361) (#6362) 2020-02-25 21:18:31 +01:00
Jakob Borg
55238e3b5b lib/connections: Actually record connection errors (#6361) 2020-02-25 16:56:24 +01:00
Simon Frei
f0e33d052a lib: More contextification (#6343) 2020-02-24 21:57:15 +01:00
Jakob Borg
7b8622c2e9 build: Simplify build image for snaps 2020-02-23 08:40:42 +01:00
Jakob Borg
40e1835927 Merge branch 'release'
* release:
  lib/db: Allow put partial FileInfo without blocks (ref #6353)
  lib/db: Don't panic on incorrect BlocksHash (fixes #6353) (#6355)
2020-02-22 19:17:38 +01:00
Jakob Borg
a5e12a0a3d lib/db: Allow put partial FileInfo without blocks (ref #6353) 2020-02-22 17:49:23 +01:00
Jakob Borg
10cb14fcb8 lib/db: Allow put partial FileInfo without blocks (ref #6353) 2020-02-22 17:44:34 +01:00
Simon Frei
4f29180e7c lib/db: Don't panic on incorrect BlocksHash (fixes #6353) (#6355) 2020-02-22 16:52:34 +01:00
Simon Frei
32e12abb43 lib/db: Don't panic on incorrect BlocksHash (fixes #6353) (#6355) 2020-02-22 16:51:23 +01:00
Jakob Borg
4cc1b7f42c Merge branch 'release'
* release:
  lib/db: Schema update to repair sequence index (ref #6304) (#6350)
  lib: Modify FileInfos consistently (ref #6321) (#6349)
2020-02-22 09:40:27 +01:00
Simon Frei
0fb2cd52ff lib/db: Schema update to repair sequence index (ref #6304) (#6350) 2020-02-22 09:37:21 +01:00
Simon Frei
6489feb1d7 lib/db: Schema update to repair sequence index (ref #6304) (#6350) 2020-02-22 09:36:59 +01:00
Simon Frei
a4bd4d118a lib: Modify FileInfos consistently (ref #6321) (#6349) 2020-02-22 09:31:26 +01:00
Simon Frei
fae7425bbf lib: Modify FileInfos consistently (ref #6321) (#6349) 2020-02-19 16:58:09 +01:00
Jakob Borg
7b5551248a gui, man, authors: Update docs, translations, and contributors 2020-02-19 07:45:29 +01:00
Tyler Kropp
4026625c2d lib/config, gui: Set unix socket permissions for GUI listen address (fixes #5979) (#6310) 2020-02-18 08:52:12 +01:00
Jakob Borg
3e0241ea31 build: Dockerfile for the builder image 2020-02-14 10:44:31 +01:00
Jakob Borg
bb375b1aff lib/model: Stop summary sender faster (ref #6319) (#6341)
One of the causes of "panic: database is closed" is that we try to send
summaries after it's been closed. Calculating summaries can take a long
time and if we have a lot of folders it's not unreasonable to think
that we might be stopped in this loop, so prepare to bail here.

* push
2020-02-14 08:11:54 +01:00
Simon Frei
05e23f1991 lib/db: Don't call backend.Commit twice (ref #6337) (#6342) 2020-02-14 08:11:24 +01:00
Jakob Borg
71de6fe290 lib/upnp: Exit quicker (#6339)
During NAT discovery we block for 10s (NatTimeoutS) before returning.
This is mostly noticeable when Ctrl-C:ing a Syncthing directly after
startup as we wait for those ten seconds before shutting down. This
makes it check the context a little bit more frequently.
2020-02-13 15:39:36 +01:00
Jakob Borg
6a840a040b lib/db: Keep metadata better in sync (ref #6335) (#6337)
This adds metadata updates to the same write batch as the underlying
file change. The odds of a metadata update going missing is greatly
reduced.

Bonus change: actually commit the transaction in recalcMeta.
2020-02-13 15:23:08 +01:00
Simon Frei
c3637f2191 lib: Faster termination on exit (ref #6319) (#6329) 2020-02-13 14:43:00 +01:00
Simon Frei
ca90f4e6af lib/db: Use flags from arg not LocalFlags() updating meta (#6333) 2020-02-13 14:02:30 +01:00
Jakob Borg
51fa36d61f lib/db: Recover sequence number and metadata on startup (fixes #6335) (#6336)
lib/db: Recover sequence number and metadata on startup (fixes #6335)

If we crashed after writing new file entries but before updating
metadata in the database the sequence number and metadata will be wrong.
This fixes that.
2020-02-13 13:05:26 +01:00
Jakob Borg
d95a087829 lib/db: Don't leak snapshot when closing (#6331)
We could potentially get a snapshot and then fail to get a releaser,
leaking the snapshot. This takes the releaser first and makes sure to
release it on snapshot error.
2020-02-12 12:00:17 +01:00
Jakob Borg
a728743c86 lib/db: Use Commit() instead of commit() (#6330)
The readWriteTransaction offered both commit() (the one to use) and
Commit() (via embedding) where the latter didn't close the read
transaction. This removes the lower cased variant in order to prevent
the mistake.

The only place where the mistake was made was the new gc runner, where
it would leave a read snapshot open forever.
2020-02-12 11:59:55 +01:00
Simon Frei
ce27780a4c lib/model: Return empty summary on paused folders (ref #6272) (#6326) 2020-02-12 11:59:12 +01:00
Jakob Borg
0df39ddc72 lib/fs, lib/model: Rewrite RecvOnly tests (#6318)
During some other work I discovered these tests weren't great, so I've
rewritten them to be a little better. The real changes here are:

- Don't play games with not starting the folder and such, and don't
  construct a fake folder instance -- just use the one the model has. The
  folder starts and scans but the folder contents are empty at this point
  so that's fine.

- Use a fakefs instead of a temp dir.

- To support the above, implement a fakefs option `?content=true` to
  make the fakefs actually retain written content. Use sparingly,
  obviously, but it means the fakefs can usually be used instead of an
  on disk real directory.
2020-02-12 07:47:05 +01:00
Jakob Borg
b84aa114be gui, man, authors: Update docs, translations, and contributors 2020-02-12 07:45:30 +01:00
Simon Frei
a596e5e2f0 lib/model: Consistent error return values for folder methods on model (#6325) 2020-02-12 07:35:24 +01:00
Jakob Borg
04e648fee6 lib/db: Handle missing block lists as missing file (ref #6321) (#6322)
Also explicitly handle non-nil but empty block lists (if they should
ever pop up as an effect of unmarshalling changes or whatnot).
2020-02-11 15:37:22 +01:00
Simon Frei
29736b1e33 lib/db: Add closeWaitGroup to allow async operation (#6317) 2020-02-11 14:31:43 +01:00
Jakob Borg
b61da487e4 all: Update metadata modtime on delete (ref #6284) (#6315)
This records the time a file was marked as deleted. It will, in the
future, aid in garbage collecting old files.
2020-02-10 10:48:30 +01:00
Jakob Borg
b4064e07dc build: Minor tidy 2020-02-07 16:21:01 +01:00
Jakob Borg
b4dc15bc06 gui, man, authors: Update docs, translations, and contributors 2020-02-05 07:45:30 +01:00
Anjan Momi
3304e0f832 etc/linux-runit: Add excecute permission (#6306) 2020-02-03 11:50:44 +01:00
Jakob Borg
b8a5e1a244 cmd/stindex: Print missing sequence ranges concisely 2020-02-03 09:18:21 +01:00
Jakob Borg
5823e7a5ce lib/model: Sort and group model initialization better (ref #6303) 2020-02-01 08:12:25 +01:00
Jakob Borg
55937b61ca lib/model: Add global request limiter (fixes #6302) (#6303)
This adds a new config with the simple and concise name
maxConcurrentIncomingRequestKiB. This limits how many bytes we have "in
the air" in the form of response data being read and processed.

After some testing I think that not having this limiter is seldom a
great idea and thus I propose a default value of 256 MiB for this new
setting.

I also refactored the folder IO limiter to be a model/folder attribute
instead of a package global.
2020-02-01 08:02:18 +01:00
Jakob Borg
9cef283151 cmd/stindex: Teach it about new key types 2020-01-31 08:27:20 +01:00
Jakob Borg
e0d4cdc9a3 lib/ignore: Don't crash on empty patterns (fixes #6300) (#6301)
Instead of panicking when we try to look closer at the empty pattern,
return something like `invalid pattern "(?d)" in ignore file: missing
pattern`.
2020-01-30 09:58:44 +01:00
Jakob Borg
ac3879e2b0 gui, man, authors: Update docs, translations, and contributors 2020-01-29 07:45:31 +01:00
Jakob Borg
d91c4b010b lib/config, lib/model: Limit concurrent pulls (fixes #5914) (#6290)
Adds a new folder state "Waiting to Sync" in the same vein as the
existing "Waiting to Scan". This vastly improves performances in the
rare cases when there are lots and lots of folders operating.
2020-01-27 17:31:17 +01:00
Jakob Borg
84920bff63 lib/db: Fixup last commit with better key name 2020-01-26 15:22:21 +01:00
Jakob Borg
bf4c8439e8 lib/db: Configurable block GC time (#6295)
Also retain the interval over restarts by storing last GC time in the
database. This to make sure that GC eventually happens even if the
interval is configured to a long time (say, a month).
2020-01-26 15:13:28 +01:00
Jakob Borg
8fc2dfad0c lib/db: Deduplicate block lists in database (fixes #5898) (#6283)
* lib/db: Deduplicate block lists in database (fixes #5898)

This moves the block list in the database out from being just a field on
the FileInfo to being an object of its own. When putting a FileInfo we
marshal the block list separately and store it keyed by the sha256 of
the marshalled block list. When getting, if we are not doing a
"truncated" get, we do an extra read and unmarshal for the block list.

Old block lists are cleared out by a periodic GC sweep. The alternative
would be to use refcounting, but:

- There is a larger risk of getting that wrong and either dropping a
  block list in error or keeping them around forever.

- It's tricky with our current database, as we don't have dirty reads.
  This means that if we update two FileInfos with identical block lists in
  the same transaction we can't just do read/modify/write for the ref
  counters as we wouldn't see our own first update. See above about
  tracking this and risks about getting it wrong.

GC uses a bloom filter for keys to avoid heavy RAM usage. GC can't run
concurrently with FileInfo updates so there is a new lock around those
operation at the lowlevel.

The end result is a much more compact database, especially for setups
with many peers where files get duplicated many times.

This is per-key-class stats for a large database I'm currently working
with, under the current schema:

```
 0x00:  9138161 items, 870876 KB keys + 7397482 KB data, 95 B +  809 B avg, 1637651 B max
 0x01:   185656 items,  10388 KB keys + 1790909 KB data, 55 B + 9646 B avg,  924525 B max
 0x02:   916890 items,  84795 KB keys +    3667 KB data, 92 B +    4 B avg,     192 B max
 0x03:      384 items,     27 KB keys +       5 KB data, 72 B +   15 B avg,      87 B max
 0x04:     1109 items,     17 KB keys +      17 KB data, 15 B +   15 B avg,      69 B max
 0x06:      383 items,      3 KB keys +       0 KB data,  9 B +    2 B avg,      18 B max
 0x07:      510 items,      4 KB keys +      12 KB data,  9 B +   24 B avg,      41 B max
 0x08:     1349 items,     12 KB keys +      10 KB data,  9 B +    8 B avg,      17 B max
 0x09:      194 items,      0 KB keys +     123 KB data,  5 B +  634 B avg,   11484 B max
 0x0a:        3 items,      0 KB keys +       0 KB data, 14 B +    7 B avg,      30 B max
 0x0b:   181836 items,   2363 KB keys +   10694 KB data, 13 B +   58 B avg,     173 B max
 Total 10426475 items, 968490 KB keys + 9202925 KB data.
```

Note 7.4 GB of data in class 00, total size 9.2 GB. After running the
migration we get this instead:

```
 0x00:  9138161 items, 870876 KB keys + 2611392 KB data, 95 B +  285 B avg,    4788 B max
 0x01:   185656 items,  10388 KB keys + 1790909 KB data, 55 B + 9646 B avg,  924525 B max
 0x02:   916890 items,  84795 KB keys +    3667 KB data, 92 B +    4 B avg,     192 B max
 0x03:      384 items,     27 KB keys +       5 KB data, 72 B +   15 B avg,      87 B max
 0x04:     1109 items,     17 KB keys +      17 KB data, 15 B +   15 B avg,      69 B max
 0x06:      383 items,      3 KB keys +       0 KB data,  9 B +    2 B avg,      18 B max
 0x07:      510 items,      4 KB keys +      12 KB data,  9 B +   24 B avg,      41 B max
 0x09:      194 items,      0 KB keys +     123 KB data,  5 B +  634 B avg,   11484 B max
 0x0a:        3 items,      0 KB keys +       0 KB data, 14 B +   17 B avg,      51 B max
 0x0b:   181836 items,   2363 KB keys +   10694 KB data, 13 B +   58 B avg,     173 B max
 0x0d:    44282 items,   1461 KB keys +   61081 KB data, 33 B + 1379 B avg, 1637399 B max
 Total 10469408 items, 969939 KB keys + 4477905 KB data.
```

Class 00 is now down to 2.6 GB, with just 61 MB added in class 0d.

There will be some additional reads in some cases which theoretically
hurts performance, but this will be more than compensated for by smaller
writes and better compaction.

On my own home setup which just has three devices and a handful of
folders the difference is smaller in absolute numbers of course, but
still less than half the old size:

```
 0x00:  297122 items,  20894 KB keys + 306860 KB data, 70 B + 1032 B avg, 103237 B max
 0x01:  115299 items,   7738 KB keys +  17542 KB data, 67 B +  152 B avg,    419 B max
 0x02: 1430537 items, 121223 KB keys +   5722 KB data, 84 B +    4 B avg,    253 B max
 ...
 Total 1947412 items, 151268 KB keys + 337485 KB data.
```

to:

```
 0x00:  297122 items,  20894 KB keys +  37038 KB data, 70 B +  124 B avg,    520 B max
 0x01:  115299 items,   7738 KB keys +  17542 KB data, 67 B +  152 B avg,    419 B max
 0x02: 1430537 items, 121223 KB keys +   5722 KB data, 84 B +    4 B avg,    253 B max
 ...
 0x0d:   18041 items,    595 KB keys +  71964 KB data, 33 B + 3988 B avg, 101109 B max
 Total 1965447 items, 151863 KB keys + 139628 KB data.
```

* wip

* wip

* wip

* wip
2020-01-24 08:35:44 +01:00
Audrius Butkevicius
17b441c993 lib/relays: Fix incorrect timeout, bring back logging (ref #6289) (#6291)
* lib/relays: Fix incorrect timeout, bring back logging (ref #6289)

* Fix format strings
2020-01-23 21:37:35 +00:00
Jakob Borg
b9879e2013 gui, man, authors: Update docs, translations, and contributors 2020-01-22 07:45:33 +01:00
Simon Frei
08f0e125ef all: Transactionalize db.FileSet (fixes #5952) (#6239) 2020-01-21 18:23:08 +01:00
Jakob Borg
d62a0cf692 lib/model: Handle progress emitter zero interval (fixes #6281) (#6282)
Makes the logic a bit clearer and safer. This also sneakily redefines
the 0 interval to also mean disabled, whereas it previously meant ...
sometimes default to 1s, sometimes just spin.
2020-01-20 21:14:29 +01:00
dependabot-preview[bot]
ddd26f5c42 build(deps): bump github.com/pkg/errors from 0.9.0 to 0.9.1 (#6279)
Bumps [github.com/pkg/errors](https://github.com/pkg/errors) from 0.9.0 to 0.9.1.
- [Release notes](https://github.com/pkg/errors/releases)
- [Commits](https://github.com/pkg/errors/compare/v0.9.0...v0.9.1)

Signed-off-by: dependabot-preview[bot] <support@dependabot.com>
2020-01-20 20:05:19 +01:00
Simon Frei
69da11a263 cmd/syncthing: Always use monitor process (fixes #4774, fixes #5786) (#6278) 2020-01-20 09:07:46 +01:00
Simon Frei
879d757850 lib/syncthing: Wait for actual termination on Stop() (#6277) 2020-01-20 08:40:15 +01:00
Jakob Borg
6c8e8f0391 lib/model: Remove legacy handling of symlinks (#6276)
This hardly seams relevant any more; 0.14.14 is dead since a long time.
2020-01-19 12:02:20 +01:00
Simon Frei
39891cdf42 lib/model: Return paused summary instead of error on paused folders (#6272) 2020-01-17 09:30:00 +01:00
Simon Frei
e782bab9fc lib/config: Add some info to the folder marker missing (ref #5207) (#6270) 2020-01-16 15:30:29 +01:00
Tomasz Wilczyński
9cc49aea77 assets, gui: Losslessly compress all JPG, PNG, and PDF images (#6265)
Use FileOptimizer (https://nikkhokkho.sourceforge.io/static.php?page=FileOptimizer)
to losslessly compress all JPG, PNG, and PDF images without reducing their
quality.

Signed-off-by: Tomasz Wilczyński <twilczynski@naver.com>
2020-01-16 13:52:43 +01:00
Jakob Borg
29690502f0 cmd/strelaypoolsrv: Serve gzip compressed responses 2020-01-15 10:36:21 +01:00
Jakob Borg
d323e9c106 gui, man, authors: Update docs, translations, and contributors 2020-01-15 07:46:01 +01:00
213 changed files with 4725 additions and 2645 deletions

View File

@@ -18,6 +18,7 @@ Adam Piggott (ProactiveServices) <aD@simplypeachy.co.uk> <simplypeachy@users.nor
Adel Qalieh (adelq) <aqalieh95@gmail.com> <adelq@users.noreply.github.com>
Alan Pope <alan@popey.com>
Alessandro G. (alessandro.g89) <alessandro.g89@gmail.com>
Alex Xu <alex.hello71@gmail.com>
Alexander Graf (alex2108) <register-github@alex-graf.de>
Alexandre Viau (aviau) <alexandre@alexandreviau.net> <aviau@debian.org>
Aman Gupta <aman@tmm1.net>
@@ -28,6 +29,7 @@ Andrew Rabert (nvllsvm) <ar@nullsum.net> <6550543+nvllsvm@users.noreply.github.c
Andrey D (scienmind) <scintertech@cryptolab.net> <scienmind@users.noreply.github.com>
André Colomb (acolomb) <src@andre.colomb.de> <github.com@andre.colomb.de>
andyleap <andyleap@gmail.com>
Anjan Momi <anjan@momi.ca>
Antoine Lamielle (0x010C) <antoine.lamielle@0x010c.fr> <gh@0x010c.fr>
Antony Male (canton7) <antony.male@gmail.com>
Aranjedeath <Aranjedeath@users.noreply.github.com>
@@ -202,6 +204,7 @@ Sacheendra Talluri (sacheendra) <sacheendra.t@gmail.com>
Scott Klupfel (kluppy) <kluppy@going2blue.com>
Sergey Mishin (ralder) <ralder@yandex.ru>
Simon Frei (imsodin) <freisim93@gmail.com>
Simon Mwepu <simonmwepu@gmail.com>
Sly_tom_cat <slytomcat@mail.ru>
Stefan Kuntz (Stefan-Code) <stefan.github@gmail.com> <Stefan.github@gmail.com>
Stefan Tatschner (rumpelsepp) <stefan@sevenbyte.org> <rumpelsepp@sevenbyte.org> <stefan@rumpelsepp.org>
@@ -213,10 +216,11 @@ Tim Howes (timhowes) <timhowes@berkeley.edu>
Tobias Nygren (tnn2) <tnn@nygren.pp.se>
Tobias Tom (tobiastom) <t.tom@succont.de>
Tom Jakubowski <tom@crystae.net>
Tomas Cerveny (kozec) <kozec@kozec.com>
Tomasz Wilczyński <5626656+tomasz1986@users.noreply.github.com>
Tommy Thorn <tommy-github-email@thorn.ws>
Tully Robinson (tojrobinson) <tully@tojr.org>
Tyler Brazier (tylerbrazier) <tyler@tylerbrazier.com>
Tyler Kropp <kropptyler@gmail.com>
Unrud (Unrud) <unrud@openaliasbox.org> <Unrud@users.noreply.github.com>
Veeti Paananen (veeti) <veeti.paananen@rojekti.fi>
Victor Buinsky (buinsky) <vix_booja@tut.by>

17
Dockerfile.builder Normal file
View File

@@ -0,0 +1,17 @@
# We will grab the Go compiler from the latest Go image.
FROM golang:1.13 as go
# Otherwise we base on the snapcraft container as that is by far the
# most complex and tricky thing to get installed and working...
FROM snapcore/snapcraft
# Go
COPY --from=go /usr/local/go /usr/local/go
ENV PATH="/usr/local/go/bin:$PATH"
# FPM to build Debian packages
RUN apt-get update && apt-get install -y --no-install-recommends \
locales rubygems ruby-dev build-essential git \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/* \
&& gem install --no-ri --no-rdoc fpm

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

After

Width:  |  Height:  |  Size: 19 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 40 KiB

After

Width:  |  Height:  |  Size: 38 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 19 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 38 KiB

After

Width:  |  Height:  |  Size: 36 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 8.2 KiB

After

Width:  |  Height:  |  Size: 8.1 KiB

View File

Binary file not shown.

View File

@@ -15,6 +15,7 @@ import (
"compress/flate"
"compress/gzip"
"crypto/sha256"
"encoding/json"
"errors"
"flag"
"fmt"
@@ -41,7 +42,6 @@ var (
noupgrade bool
version string
goCmd string
goVersion float64
race bool
debug = os.Getenv("BUILDDEBUG") != ""
extraTags string
@@ -630,31 +630,35 @@ func buildSnap(target target) {
}
func shouldBuildSyso(dir string) (string, error) {
type M map[string]interface{}
major, minor, patch, build := semanticVersion()
bs, err := json.Marshal(M{
"FixedFileInfo": M{
"FileVersion": M{
"Major": major,
"Minor": minor,
"Patch": patch,
"Build": build,
},
},
"StringFileInfo": M{
"FileDescription": "Open Source Continuous File Synchronization",
"LegalCopyright": "The Syncthing Authors",
"ProductVersion": getVersion(),
"ProductName": "Syncthing",
},
"IconPath": "assets/logo.ico",
})
if err != nil {
return "", err
}
jsonPath := filepath.Join(dir, "versioninfo.json")
file, err := os.Create(filepath.Join(dir, "versioninfo.json"))
err = ioutil.WriteFile(jsonPath, bs, 0644)
if err != nil {
return "", errors.New("failed to create " + jsonPath + ": " + err.Error())
}
major, minor, patch, build := semanticVersion()
fmt.Fprintf(file, `{
"FixedFileInfo": {
"FileVersion": {
"Major": %s,
"Minor": %s,
"Patch": %s,
"Build": %s
}
},
"StringFileInfo": {
"FileDescription": "Open Source Continuous File Synchronization",
"LegalCopyright": "The Syncthing Authors",
"ProductVersion": "%s",
"ProductName": "Syncthing"
},
"IconPath": "assets/logo.ico"
}`, major, minor, patch, build, getVersion())
file.Close()
defer func() {
if err := os.Remove(jsonPath); err != nil {
log.Printf("Warning: unable to remove generated %s: %v. Please remove it manually.", jsonPath, err)
@@ -800,18 +804,13 @@ func transifex() {
}
func ldflags(program string) string {
sep := '='
if goVersion > 0 && goVersion < 1.5 {
sep = ' '
}
b := new(bytes.Buffer)
b := new(strings.Builder)
b.WriteString("-w")
fmt.Fprintf(b, " -X github.com/syncthing/syncthing/lib/build.Version%c%s", sep, version)
fmt.Fprintf(b, " -X github.com/syncthing/syncthing/lib/build.Stamp%c%d", sep, buildStamp())
fmt.Fprintf(b, " -X github.com/syncthing/syncthing/lib/build.User%c%s", sep, buildUser())
fmt.Fprintf(b, " -X github.com/syncthing/syncthing/lib/build.Host%c%s", sep, buildHost())
fmt.Fprintf(b, " -X github.com/syncthing/syncthing/lib/build.Program%c%s", sep, program)
fmt.Fprintf(b, " -X github.com/syncthing/syncthing/lib/build.Version=%s", version)
fmt.Fprintf(b, " -X github.com/syncthing/syncthing/lib/build.Stamp=%d", buildStamp())
fmt.Fprintf(b, " -X github.com/syncthing/syncthing/lib/build.User=%s", buildUser())
fmt.Fprintf(b, " -X github.com/syncthing/syncthing/lib/build.Host=%s", buildHost())
fmt.Fprintf(b, " -X github.com/syncthing/syncthing/lib/build.Program=%s", program)
if v := os.Getenv("EXTRA_LDFLAGS"); v != "" {
fmt.Fprintf(b, " %s", v)
}
@@ -828,13 +827,7 @@ func rmr(paths ...string) {
}
func getReleaseVersion() (string, error) {
fd, err := os.Open("RELEASE")
if err != nil {
return "", err
}
defer fd.Close()
bs, err := ioutil.ReadAll(fd)
bs, err := ioutil.ReadFile("RELEASE")
if err != nil {
return "", err
}
@@ -871,13 +864,22 @@ func getVersion() string {
return "unknown-dev"
}
func semanticVersion() (major, minor, patch, build string) {
func semanticVersion() (major, minor, patch, build int) {
r := regexp.MustCompile(`v(?P<Major>\d+)\.(?P<Minor>\d+).(?P<Patch>\d+).*\+(?P<CommitsAhead>\d+)`)
matches := r.FindStringSubmatch(getVersion())
if len(matches) != 5 {
return "0", "0", "0", "0"
return 0, 0, 0, 0
}
return matches[1], matches[2], matches[3], matches[4]
var ints [4]int
for i := 1; i < 5; i++ {
value, err := strconv.Atoi(matches[i])
if err != nil {
return 0, 0, 0, 0
}
ints[i-1] = value
}
return ints[0], ints[1], ints[2], ints[3]
}
func getBranchSuffix() string {

View File

@@ -10,6 +10,7 @@ import (
"bytes"
"context"
"crypto/tls"
"errors"
"fmt"
"net"
"net/http"
@@ -80,16 +81,16 @@ func (c *APIClient) Post(url, body string) (*http.Response, error) {
func checkResponse(response *http.Response) error {
if response.StatusCode == 404 {
return fmt.Errorf("Invalid endpoint or API call")
return errors.New("invalid endpoint or API call")
} else if response.StatusCode == 403 {
return fmt.Errorf("Invalid API key")
return errors.New("invalid API key")
} else if response.StatusCode != 200 {
data, err := responseToBArray(response)
if err != nil {
return err
}
body := strings.TrimSpace(string(data))
return fmt.Errorf("Unexpected HTTP status returned: %s\n%s", response.Status, body)
return fmt.Errorf("unexpected HTTP status returned: %s\n%s", response.Status, body)
}
return nil
}

View File

@@ -7,6 +7,7 @@
package main
import (
"errors"
"fmt"
"strings"
@@ -54,7 +55,7 @@ func errorsPush(c *cli.Context) error {
if body != "" {
errStr += "\nBody: " + body
}
return fmt.Errorf(errStr)
return errors.New(errStr)
}
return nil
}

View File

@@ -60,7 +60,7 @@ func compareDirectories(dirs ...string) error {
} else if res[i].name > res[0].name {
return fmt.Errorf("%s missing %v (present in %s)", dirs[i], res[0], dirs[0])
}
return fmt.Errorf("Mismatch; %v (%s) != %v (%s)", res[i], dirs[i], res[0], dirs[0])
return fmt.Errorf("mismatch; %v (%s) != %v (%s)", res[i], dirs[i], res[0], dirs[0])
}
}

View File

@@ -7,6 +7,7 @@
package main
import (
"context"
"crypto/tls"
"errors"
"flag"
@@ -95,7 +96,7 @@ func checkServer(deviceID protocol.DeviceID, server string) checkResult {
})
go func() {
addresses, err := disco.Lookup(deviceID)
addresses, err := disco.Lookup(context.Background(), deviceID)
res <- checkResult{addresses: addresses, error: err}
}()

58
cmd/stindex/accounting.go Normal file
View File

@@ -0,0 +1,58 @@
// Copyright (C) 2020 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 main
import (
"fmt"
"log"
"os"
"text/tabwriter"
"github.com/syncthing/syncthing/lib/db/backend"
)
// account prints key and data size statistics per class
func account(ldb backend.Backend) {
it, err := ldb.NewPrefixIterator(nil)
if err != nil {
log.Fatal(err)
}
var ksizes [256]int
var dsizes [256]int
var counts [256]int
var max [256]int
for it.Next() {
key := it.Key()
t := key[0]
ds := len(it.Value())
ks := len(key)
s := ks + ds
counts[t]++
ksizes[t] += ks
dsizes[t] += ds
if s > max[t] {
max[t] = s
}
}
tw := tabwriter.NewWriter(os.Stdout, 1, 1, 1, ' ', tabwriter.AlignRight)
toti, totds, totks := 0, 0, 0
for t := range ksizes {
if ksizes[t] > 0 {
// yes metric kilobytes 🤘
fmt.Fprintf(tw, "0x%02x:\t%d items,\t%d KB keys +\t%d KB data,\t%d B +\t%d B avg,\t%d B max\t\n", t, counts[t], ksizes[t]/1000, dsizes[t]/1000, ksizes[t]/counts[t], dsizes[t]/counts[t], max[t])
toti += counts[t]
totds += dsizes[t]
totks += ksizes[t]
}
}
fmt.Fprintf(tw, "Total\t%d items,\t%d KB keys +\t%d KB data.\t\n", toti, totks/1000, totds/1000)
tw.Flush()
}

View File

@@ -80,6 +80,31 @@ func dump(ldb backend.Backend) {
fmt.Printf("[deviceidx] K:%d V:%s\n", key, dev)
}
case db.KeyTypeIndexID:
device := binary.BigEndian.Uint32(it.Key()[1:])
folder := binary.BigEndian.Uint32(it.Key()[5:])
fmt.Printf("[indexid] D:%d F:%d I:%x\n", device, folder, it.Value())
case db.KeyTypeFolderMeta:
folder := binary.BigEndian.Uint32(it.Key()[1:])
fmt.Printf("[foldermeta] F:%d V:%x\n", folder, it.Value())
case db.KeyTypeMiscData:
fmt.Printf("[miscdata] K:%q V:%q\n", it.Key()[1:], it.Value())
case db.KeyTypeSequence:
folder := binary.BigEndian.Uint32(it.Key()[1:])
seq := binary.BigEndian.Uint64(it.Key()[5:])
fmt.Printf("[sequence] F:%d S:%d V:%q\n", folder, seq, it.Value())
case db.KeyTypeNeed:
folder := binary.BigEndian.Uint32(it.Key()[1:])
file := string(it.Key()[5:])
fmt.Printf("[need] F:%d V:%q\n", folder, file)
case db.KeyTypeBlockList:
fmt.Printf("[blocklist] H:%x\n", it.Key()[1:])
default:
fmt.Printf("[???]\n %x\n %x\n", it.Key(), it.Value())
}

View File

@@ -11,6 +11,7 @@ import (
"encoding/binary"
"fmt"
"log"
"sort"
"github.com/syncthing/syncthing/lib/db"
"github.com/syncthing/syncthing/lib/db/backend"
@@ -41,6 +42,8 @@ func idxck(ldb backend.Backend) (success bool) {
globals := make(map[globalKey]db.VersionList)
sequences := make(map[sequenceKey]string)
needs := make(map[globalKey]struct{})
blocklists := make(map[string]struct{})
usedBlocklists := make(map[string]struct{})
var localDeviceKey uint32
success = true
@@ -99,6 +102,10 @@ func idxck(ldb backend.Backend) (success bool) {
folder := binary.BigEndian.Uint32(key[1:])
name := nulString(key[1+4:])
needs[globalKey{folder, name}] = struct{}{}
case db.KeyTypeBlockList:
hash := string(key[1:])
blocklists[hash] = struct{}{}
}
}
@@ -108,6 +115,7 @@ func idxck(ldb backend.Backend) (success bool) {
return
}
var missingSeq []sequenceKey
for fk, fi := range fileInfos {
if fk.name != fi.Name {
fmt.Printf("Mismatching FileInfo name, %q (key) != %q (actual)\n", fk.name, fi.Name)
@@ -126,9 +134,11 @@ func idxck(ldb backend.Backend) (success bool) {
}
if fk.device == localDeviceKey {
name, ok := sequences[sequenceKey{fk.folder, uint64(fi.Sequence)}]
sk := sequenceKey{fk.folder, uint64(fi.Sequence)}
name, ok := sequences[sk]
if !ok {
fmt.Printf("Sequence entry missing for FileInfo %q, folder %q, seq %d\n", fi.Name, folder, fi.Sequence)
missingSeq = append(missingSeq, sk)
success = false
continue
}
@@ -137,6 +147,41 @@ func idxck(ldb backend.Backend) (success bool) {
success = false
}
}
if len(fi.Blocks) == 0 && len(fi.BlocksHash) != 0 {
key := string(fi.BlocksHash)
if _, ok := blocklists[key]; !ok {
fmt.Printf("Missing block list for file %q, block list hash %x\n", fi.Name, fi.BlocksHash)
success = false
} else {
usedBlocklists[key] = struct{}{}
}
}
}
// Aggregate the ranges of missing sequence entries, print them
sort.Slice(missingSeq, func(a, b int) bool {
if missingSeq[a].folder != missingSeq[b].folder {
return missingSeq[a].folder < missingSeq[b].folder
}
return missingSeq[a].sequence < missingSeq[b].sequence
})
var folder uint32
var startSeq, prevSeq uint64
for _, sk := range missingSeq {
if folder != sk.folder || sk.sequence != prevSeq+1 {
if folder != 0 {
fmt.Printf("Folder %d missing %d sequence entries: #%d - #%d\n", folder, prevSeq-startSeq+1, startSeq, prevSeq)
}
startSeq = sk.sequence
folder = sk.folder
}
prevSeq = sk.sequence
}
if folder != 0 {
fmt.Printf("Folder %d missing %d sequence entries: #%d - #%d\n", folder, prevSeq-startSeq+1, startSeq, prevSeq)
}
for gk, vl := range globals {
@@ -229,6 +274,10 @@ func idxck(ldb backend.Backend) (success bool) {
}
}
if d := len(blocklists) - len(usedBlocklists); d > 0 {
fmt.Printf("%d block list entries out of %d needs GC\n", d, len(blocklists))
}
return
}

View File

@@ -35,15 +35,18 @@ func main() {
log.Fatal(err)
}
if mode == "dump" {
switch mode {
case "dump":
dump(ldb)
} else if mode == "dumpsize" {
case "dumpsize":
dumpsize(ldb)
} else if mode == "idxck" {
case "idxck":
if !idxck(ldb) {
os.Exit(1)
}
} else {
case "account":
account(ldb)
default:
fmt.Println("Unknown mode")
}
}

View File

@@ -10,8 +10,10 @@ import (
"context"
"crypto/tls"
"encoding/json"
"errors"
"flag"
"fmt"
"io"
"io/ioutil"
"log"
"mime"
@@ -364,8 +366,8 @@ func handleRequest(w http.ResponseWriter, r *http.Request) {
}
}
func handleGetRequest(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json; charset=utf-8")
func handleGetRequest(rw http.ResponseWriter, r *http.Request) {
rw.Header().Set("Content-Type", "application/json; charset=utf-8")
mut.RLock()
relays := append(permanentRelays, knownRelays...)
mut.RUnlock()
@@ -373,7 +375,15 @@ func handleGetRequest(w http.ResponseWriter, r *http.Request) {
// Shuffle
rand.Shuffle(relays)
json.NewEncoder(w).Encode(map[string][]*relay{
w := io.Writer(rw)
if strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
rw.Header().Set("Content-Encoding", "gzip")
gw := gzip.NewWriter(rw)
defer gw.Close()
w = gw
}
_ = json.NewEncoder(w).Encode(map[string][]*relay{
"relays": relays,
})
}
@@ -485,7 +495,7 @@ func handleRelayTest(request request) {
if debug {
log.Println("Test for relay", request.relay, "failed")
}
request.result <- result{fmt.Errorf("connection test failed"), 0}
request.result <- result{errors.New("connection test failed"), 0}
return
}

View File

@@ -14,6 +14,7 @@ import (
"crypto/x509"
"crypto/x509/pkix"
"encoding/pem"
"errors"
"flag"
"fmt"
"math/big"
@@ -191,7 +192,7 @@ func pemBlockForKey(priv interface{}) (*pem.Block, error) {
}
return &pem.Block{Type: "EC PRIVATE KEY", Bytes: b}, nil
default:
return nil, fmt.Errorf("unknown key type")
return nil, errors.New("unknown key type")
}
}

View File

@@ -47,6 +47,7 @@ import (
const (
tlsDefaultCommonName = "syncthing"
deviceCertLifetimeDays = 20 * 365
sigTerm = syscall.Signal(15)
)
const (
@@ -118,6 +119,10 @@ are mostly useful for developers. Use with care.
"h", "m" and "s" abbreviations for hours minutes and seconds.
Valid values are like "720h", "30s", etc.
STGCINDIRECTEVERY Set to a time interval to override the default database
indirection GC interval of 13 hours. Same format as the
STRECHECKDBEVERY variable.
GOMAXPROCS Set the maximum number of CPU cores to use. Defaults to all
available CPU cores.
@@ -134,10 +139,12 @@ The following are valid values for the STTRACE variable:
%s`
)
// Environment options
var (
// Environment options
innerProcess = os.Getenv("STNORESTART") != "" || os.Getenv("STMONITORED") != ""
noDefaultFolder = os.Getenv("STNODEFAULTFOLDER") != ""
errConcurrentUpgrade = errors.New("upgrade prevented by other running Syncthing instance")
)
type RuntimeOptions struct {
@@ -225,7 +232,7 @@ func parseCommandLineOptions() RuntimeOptions {
flag.BoolVar(&options.Verbose, "verbose", false, "Print verbose log output")
flag.BoolVar(&options.paused, "paused", false, "Start with all devices and folders paused")
flag.BoolVar(&options.unpaused, "unpaused", false, "Start with all devices and folders unpaused")
flag.StringVar(&options.logFile, "logfile", options.logFile, "Log file name (still always logs to stdout). Cannot be used together with -no-restart/STNORESTART environment variable.")
flag.StringVar(&options.logFile, "logfile", options.logFile, "Log file name (still always logs to stdout).")
flag.IntVar(&options.logMaxSize, "log-max-size", options.logMaxSize, "Maximum size of any file (zero to disable log rotation).")
flag.IntVar(&options.logMaxFiles, "log-max-old-files", options.logMaxFiles, "Number of old files to keep (zero to keep only current).")
flag.StringVar(&options.auditFile, "auditfile", options.auditFile, "Specify audit file (use \"-\" for stdout, \"--\" for stderr)")
@@ -260,15 +267,6 @@ func main() {
os.Setenv("STGUIAPIKEY", options.guiAPIKey)
}
// Check for options which are not compatible with each other. We have
// to check logfile before it's set to the default below - we only want
// to complain if they set -logfile explicitly, not if it's set to its
// default location
if options.noRestart && (options.logFile != "" && options.logFile != "-") {
l.Warnln("-logfile may not be used with -no-restart or STNORESTART")
os.Exit(syncthing.ExitError.AsInt())
}
if options.hideConsole {
osutil.HideConsole()
}
@@ -363,14 +361,24 @@ func main() {
}
if options.doUpgradeCheck {
checkUpgrade()
if _, err := checkUpgrade(); err != nil {
l.Warnln("Checking for upgrade:", err)
os.Exit(exitCodeForUpgrade(err))
}
return
}
if options.doUpgrade {
release := checkUpgrade()
performUpgrade(release)
return
release, err := checkUpgrade()
if err == nil {
err = performUpgrade(release)
}
if err != nil {
l.Warnln("Upgrade:", err)
os.Exit(exitCodeForUpgrade(err))
}
l.Infof("Upgraded to %q", release.Tag)
os.Exit(syncthing.ExitUpgrade.AsInt())
}
if options.resetDatabase {
@@ -378,10 +386,11 @@ func main() {
l.Warnln("Resetting database:", err)
os.Exit(syncthing.ExitError.AsInt())
}
l.Infoln("Successfully reset database - it will be rebuilt after next start.")
return
}
if innerProcess || options.noRestart {
if innerProcess {
syncthingMain(options)
} else {
monitorMain(options)
@@ -465,45 +474,47 @@ func debugFacilities() string {
return b.String()
}
func checkUpgrade() upgrade.Release {
type errNoUpgrade struct {
current, latest string
}
func (e errNoUpgrade) Error() string {
return fmt.Sprintf("no upgrade available (current %q >= latest %q).", e.current, e.latest)
}
func checkUpgrade() (upgrade.Release, error) {
cfg, _ := loadOrDefaultConfig(protocol.EmptyDeviceID, events.NoopLogger)
opts := cfg.Options()
release, err := upgrade.LatestRelease(opts.ReleasesURL, build.Version, opts.UpgradeToPreReleases)
if err != nil {
l.Warnln("Upgrade:", err)
os.Exit(syncthing.ExitError.AsInt())
return upgrade.Release{}, err
}
if upgrade.CompareVersions(release.Tag, build.Version) <= 0 {
noUpgradeMessage := "No upgrade available (current %q >= latest %q)."
l.Infof(noUpgradeMessage, build.Version, release.Tag)
os.Exit(syncthing.ExitNoUpgradeAvailable.AsInt())
return upgrade.Release{}, errNoUpgrade{build.Version, release.Tag}
}
l.Infof("Upgrade available (current %q < latest %q)", build.Version, release.Tag)
return release
return release, nil
}
func performUpgrade(release upgrade.Release) {
func performUpgradeDirect(release upgrade.Release) error {
// Use leveldb database locks to protect against concurrent upgrades
_, err := syncthing.OpenDBBackend(locations.Get(locations.Database), config.TuningAuto)
if err == nil {
err = upgrade.To(release)
if err != nil {
l.Warnln("Upgrade:", err)
os.Exit(syncthing.ExitError.AsInt())
}
l.Infof("Upgraded to %q", release.Tag)
} else {
l.Infoln("Attempting upgrade through running Syncthing...")
err = upgradeViaRest()
if err != nil {
l.Warnln("Upgrade:", err)
os.Exit(syncthing.ExitError.AsInt())
}
l.Infoln("Syncthing upgrading")
os.Exit(syncthing.ExitUpgrade.AsInt())
if _, err := syncthing.OpenDBBackend(locations.Get(locations.Database), config.TuningAuto); err != nil {
return errConcurrentUpgrade
}
return upgrade.To(release)
}
func performUpgrade(release upgrade.Release) error {
if err := performUpgradeDirect(release); err != nil {
if err != errConcurrentUpgrade {
return err
}
l.Infoln("Attempting upgrade through running Syncthing...")
return upgradeViaRest()
}
return nil
}
func upgradeViaRest() error {
@@ -571,6 +582,45 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
os.Exit(syncthing.ExitError.AsInt())
}
// Candidate builds should auto upgrade. Make sure the option is set,
// unless we are in a build where it's disabled or the STNOUPGRADE
// environment variable is set.
if build.IsCandidate && !upgrade.DisabledByCompilation && !runtimeOptions.NoUpgrade {
l.Infoln("Automatic upgrade is always enabled for candidate releases.")
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.
cfg.SetOptions(opts)
cfg.Save()
}
// We don't tweak the user's choice of upgrading to pre-releases or
// not, as otherwise they cannot step off the candidate channel.
}
// Check if auto-upgrades should be done and if yes, do an initial
// upgrade immedately. The auto-upgrade routine can only be started
// later after App is initialised.
shouldAutoUpgrade := shouldUpgrade(cfg, runtimeOptions)
if shouldAutoUpgrade {
// Try to do upgrade directly
release, err := checkUpgrade()
if err == nil {
if err = performUpgradeDirect(release); err == nil {
l.Infof("Upgraded to %q, exiting now.", release.Tag)
os.Exit(syncthing.ExitUpgrade.AsInt())
}
}
// Log the error if relevant.
if err != nil {
if _, ok := err.(errNoUpgrade); !ok {
l.Infoln("Initial automatic upgrade:", err)
}
}
}
if runtimeOptions.unpaused {
setPauseState(cfg, false)
} else if runtimeOptions.paused {
@@ -595,6 +645,10 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
app := syncthing.New(cfg, ldb, evLogger, cert, appOpts)
if shouldAutoUpgrade {
go autoUpgrade(cfg, app, evLogger)
}
setupSignalHandling(app)
if len(os.Getenv("GOMAXPROCS")) == 0 {
@@ -617,31 +671,6 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
go standbyMonitor(app)
}
// Candidate builds should auto upgrade. Make sure the option is set,
// unless we are in a build where it's disabled or the STNOUPGRADE
// environment variable is set.
if build.IsCandidate && !upgrade.DisabledByCompilation && !runtimeOptions.NoUpgrade {
l.Infoln("Automatic upgrade is always enabled for candidate releases.")
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.
cfg.SetOptions(opts)
cfg.Save()
}
// We don't tweak the user's choice of upgrading to pre-releases or
// not, as otherwise they cannot step off the candidate channel.
}
if opts := cfg.Options(); opts.AutoUpgradeIntervalH > 0 {
if runtimeOptions.NoUpgrade {
l.Infof("No automatic upgrades; STNOUPGRADE environment variable defined.")
} else {
go autoUpgrade(cfg, app, evLogger)
}
}
if err := app.Start(); err != nil {
os.Exit(syncthing.ExitError.AsInt())
}
@@ -677,7 +706,6 @@ func setupSignalHandling(app *syncthing.App) {
// Exit with "success" code (no restart) on INT/TERM
stopSign := make(chan os.Signal, 1)
sigTerm := syscall.Signal(15)
signal.Notify(stopSign, os.Interrupt, sigTerm)
go func() {
<-stopSign
@@ -775,6 +803,20 @@ func standbyMonitor(app *syncthing.App) {
}
}
func shouldUpgrade(cfg config.Wrapper, runtimeOptions RuntimeOptions) bool {
if upgrade.DisabledByCompilation {
return false
}
if opts := cfg.Options(); opts.AutoUpgradeIntervalH < 0 {
return false
}
if runtimeOptions.NoUpgrade {
l.Infof("No automatic upgrades; STNOUPGRADE environment variable defined.")
return false
}
return true
}
func autoUpgrade(cfg config.Wrapper, app *syncthing.App, evLogger events.Logger) {
timer := time.NewTimer(0)
sub := evLogger.Subscribe(events.DeviceConnected)
@@ -897,3 +939,10 @@ func setPauseState(cfg config.Wrapper, paused bool) {
os.Exit(syncthing.ExitError.AsInt())
}
}
func exitCodeForUpgrade(err error) int {
if _, ok := err.(errNoUpgrade); ok {
return syncthing.ExitNoUpgradeAvailable.AsInt()
}
return syncthing.ExitError.AsInt()
}

View File

@@ -21,6 +21,7 @@ import (
"time"
"github.com/syncthing/syncthing/lib/events"
"github.com/syncthing/syncthing/lib/fs"
"github.com/syncthing/syncthing/lib/locations"
"github.com/syncthing/syncthing/lib/osutil"
"github.com/syncthing/syncthing/lib/protocol"
@@ -50,36 +51,42 @@ func monitorMain(runtimeOptions RuntimeOptions) {
logFile := runtimeOptions.logFile
if logFile != "-" {
if expanded, err := fs.ExpandTilde(logFile); err == nil {
logFile = expanded
}
var fileDst io.Writer
var err error
open := func(name string) (io.WriteCloser, error) {
return newAutoclosedFile(name, logFileAutoCloseDelay, logFileMaxOpenTime)
}
if runtimeOptions.logMaxSize > 0 {
open := func(name string) (io.WriteCloser, error) {
return newAutoclosedFile(name, logFileAutoCloseDelay, logFileMaxOpenTime), nil
}
fileDst = newRotatedFile(logFile, open, int64(runtimeOptions.logMaxSize), runtimeOptions.logMaxFiles)
fileDst, err = newRotatedFile(logFile, open, int64(runtimeOptions.logMaxSize), runtimeOptions.logMaxFiles)
} else {
fileDst = newAutoclosedFile(logFile, logFileAutoCloseDelay, logFileMaxOpenTime)
fileDst, err = open(logFile)
}
if runtime.GOOS == "windows" {
// Translate line breaks to Windows standard
fileDst = osutil.ReplacingWriter{
Writer: fileDst,
From: '\n',
To: []byte{'\r', '\n'},
if err != nil {
l.Warnln("Failed to setup logging to file, proceeding with logging to stdout only:", err)
} else {
if runtime.GOOS == "windows" {
// Translate line breaks to Windows standard
fileDst = osutil.ReplacingWriter{
Writer: fileDst,
From: '\n',
To: []byte{'\r', '\n'},
}
}
// Log to both stdout and file.
dst = io.MultiWriter(dst, fileDst)
l.Infof(`Log output saved to file "%s"`, logFile)
}
// Log to both stdout and file.
dst = io.MultiWriter(dst, fileDst)
l.Infof(`Log output saved to file "%s"`, logFile)
}
args := os.Args
var restarts [countRestarts]time.Time
stopSign := make(chan os.Signal, 1)
sigTerm := syscall.Signal(15)
signal.Notify(stopSign, os.Interrupt, sigTerm)
restartSign := make(chan os.Signal, 1)
sigHup := syscall.Signal(1)
@@ -111,7 +118,7 @@ func monitorMain(runtimeOptions RuntimeOptions) {
panic(err)
}
l.Infoln("Starting syncthing")
l.Debugln("Starting syncthing")
err = cmd.Start()
if err != nil {
l.Warnln("Error starting the main Syncthing process:", err)
@@ -144,12 +151,13 @@ func monitorMain(runtimeOptions RuntimeOptions) {
exit <- cmd.Wait()
}()
stopped := false
select {
case s := <-stopSign:
l.Infof("Signal %d received; exiting", s)
cmd.Process.Signal(sigTerm)
<-exit
return
err = <-exit
stopped = true
case s := <-restartSign:
l.Infof("Signal %d received; restarting", s)
@@ -157,20 +165,31 @@ func monitorMain(runtimeOptions RuntimeOptions) {
err = <-exit
case err = <-exit:
if err == nil {
// Successful exit indicates an intentional shutdown
return
} else if exiterr, ok := err.(*exec.ExitError); ok {
if exiterr.ExitCode() == syncthing.ExitUpgrade.AsInt() {
// Restart the monitor process to release the .old
// binary as part of the upgrade process.
l.Infoln("Restarting monitor...")
if err = restartMonitor(args); err != nil {
l.Warnln("Restart:", err)
}
return
}
}
if err == nil {
// Successful exit indicates an intentional shutdown
os.Exit(syncthing.ExitSuccess.AsInt())
}
if exiterr, ok := err.(*exec.ExitError); ok {
exitCode := exiterr.ExitCode()
if stopped || runtimeOptions.noRestart {
os.Exit(exitCode)
}
if exitCode == syncthing.ExitUpgrade.AsInt() {
// Restart the monitor process to release the .old
// binary as part of the upgrade process.
l.Infoln("Restarting monitor...")
if err = restartMonitor(args); err != nil {
l.Warnln("Restart:", err)
}
os.Exit(exitCode)
}
}
if runtimeOptions.noRestart {
os.Exit(syncthing.ExitError.AsInt())
}
l.Infoln("Syncthing exited:", err)
@@ -338,16 +357,30 @@ type rotatedFile struct {
currentSize int64
}
// the createFn should act equivalently to os.Create
type createFn func(name string) (io.WriteCloser, error)
func newRotatedFile(name string, create createFn, maxSize int64, maxFiles int) *rotatedFile {
return &rotatedFile{
name: name,
create: create,
maxSize: maxSize,
maxFiles: maxFiles,
func newRotatedFile(name string, create createFn, maxSize int64, maxFiles int) (*rotatedFile, error) {
var size int64
if info, err := os.Lstat(name); err != nil {
if !os.IsNotExist(err) {
return nil, err
}
size = 0
} else {
size = info.Size()
}
writer, err := create(name)
if err != nil {
return nil, err
}
return &rotatedFile{
name: name,
create: create,
maxSize: maxSize,
maxFiles: maxFiles,
currentFile: writer,
currentSize: size,
}, nil
}
func (r *rotatedFile) Write(bs []byte) (int, error) {
@@ -355,19 +388,13 @@ func (r *rotatedFile) Write(bs []byte) (int, error) {
// file so we'll start on a new one.
if r.currentSize+int64(len(bs)) > r.maxSize {
r.currentFile.Close()
r.currentFile = nil
r.currentSize = 0
}
// If we have no current log, rotate old files out of the way and create
// a new one.
if r.currentFile == nil {
r.rotate()
fd, err := r.create(r.name)
f, err := r.create(r.name)
if err != nil {
return 0, err
}
r.currentFile = fd
r.currentFile = f
}
n, err := r.currentFile.Write(bs)
@@ -420,7 +447,7 @@ type autoclosedFile struct {
mut sync.Mutex
}
func newAutoclosedFile(name string, closeDelay, maxOpenTime time.Duration) *autoclosedFile {
func newAutoclosedFile(name string, closeDelay, maxOpenTime time.Duration) (*autoclosedFile, error) {
f := &autoclosedFile{
name: name,
closeDelay: closeDelay,
@@ -429,8 +456,13 @@ func newAutoclosedFile(name string, closeDelay, maxOpenTime time.Duration) *auto
closed: make(chan struct{}),
closeTimer: time.NewTimer(time.Minute),
}
f.mut.Lock()
defer f.mut.Unlock()
if err := f.ensureOpenLocked(); err != nil {
return nil, err
}
go f.closerLoop()
return f
return f, nil
}
func (f *autoclosedFile) Write(bs []byte) (int, error) {
@@ -438,7 +470,7 @@ func (f *autoclosedFile) Write(bs []byte) (int, error) {
defer f.mut.Unlock()
// Make sure the file is open for appending
if err := f.ensureOpen(); err != nil {
if err := f.ensureOpenLocked(); err != nil {
return 0, err
}
@@ -468,22 +500,14 @@ func (f *autoclosedFile) Close() error {
}
// Must be called with f.mut held!
func (f *autoclosedFile) ensureOpen() error {
func (f *autoclosedFile) ensureOpenLocked() error {
if f.fd != nil {
// File is already open
return nil
}
// We open the file for write only, and create it if it doesn't exist.
flags := os.O_WRONLY | os.O_CREATE
if f.opened.IsZero() {
// This is the first time we are opening the file. We should truncate
// it to better emulate an os.Create() call.
flags |= os.O_TRUNC
} else {
// The file was already opened once, so we should append to it.
flags |= os.O_APPEND
}
flags := os.O_WRONLY | os.O_CREATE | os.O_APPEND
fd, err := os.OpenFile(f.name, flags, 0644)
if err != nil {

View File

@@ -33,7 +33,10 @@ func TestRotatedFile(t *testing.T) {
maxSize := int64(len(testData) + len(testData)/2)
// We allow the log file plus two rotated copies.
rf := newRotatedFile(logName, open, maxSize, 2)
rf, err := newRotatedFile(logName, open, maxSize, 2)
if err != nil {
t.Fatal(err)
}
// Write some bytes.
if _, err := rf.Write(testData); err != nil {
@@ -140,7 +143,10 @@ func TestAutoClosedFile(t *testing.T) {
data := []byte("hello, world\n")
// An autoclosed file that closes very quickly
ac := newAutoclosedFile(file, time.Millisecond, time.Millisecond)
ac, err := newAutoclosedFile(file, time.Millisecond, time.Millisecond)
if err != nil {
t.Fatal(err)
}
// Write some data.
if _, err := ac.Write(data); err != nil {
@@ -182,21 +188,23 @@ func TestAutoClosedFile(t *testing.T) {
}
// Open the file again.
ac = newAutoclosedFile(file, time.Second, time.Second)
ac, err = newAutoclosedFile(file, time.Second, time.Second)
if err != nil {
t.Fatal(err)
}
// Write something
if _, err := ac.Write(data); err != nil {
t.Fatal(err)
}
// It should now contain only one write, because the first open
// should be a truncate.
// It should now contain three writes, as the file is always opened for appending
bs, err = ioutil.ReadFile(file)
if err != nil {
t.Fatal(err)
}
if len(bs) != len(data) {
t.Fatalf("Write failed, expected %d bytes, not %d", len(data), len(bs))
if len(bs) != 3*len(data) {
t.Fatalf("Write failed, expected %d bytes, not %d", 3*len(data), len(bs))
}
// Close.

View File

@@ -56,6 +56,7 @@ var (
{regexp.MustCompile("snap@build.syncthing.net"), "Snapcraft"},
{regexp.MustCompile("android-.*vagrant@basebox-stretch64"), "F-Droid"},
{regexp.MustCompile("builduser@svetlemodry"), "Arch (3rd party)"},
{regexp.MustCompile("synology@kastelo.net"), "Synology (Kastelo)"},
{regexp.MustCompile("@debian"), "Debian (3rd party)"},
{regexp.MustCompile("@fedora"), "Fedora (3rd party)"},
{regexp.MustCompile(`\bbrew@`), "Homebrew (3rd party)"},
@@ -266,10 +267,10 @@ type report struct {
func (r *report) Validate() error {
if r.UniqueID == "" || r.Version == "" || r.Platform == "" {
return fmt.Errorf("missing required field")
return errors.New("missing required field")
}
if len(r.Date) != 8 {
return fmt.Errorf("date not initialized")
return errors.New("date not initialized")
}
// Some fields may not be null.
@@ -1419,7 +1420,7 @@ func getReport(db *sql.DB) map[string]interface{} {
r["platforms"] = group(byPlatform, analyticsFor(platforms, 2000), 10)
r["compilers"] = group(byCompiler, analyticsFor(compilers, 2000), 5)
r["builders"] = analyticsFor(builders, 12)
r["distributions"] = analyticsFor(distributions, 10)
r["distributions"] = analyticsFor(distributions, len(knownDistributions))
r["featureOrder"] = featureOrder
r["locations"] = locations
r["contries"] = countryList

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 6.4 KiB

After

Width:  |  Height:  |  Size: 4.8 KiB

View File

@@ -2,7 +2,7 @@
Name=Start Syncthing
GenericName=File synchronization
Comment=Starts the main syncthing process in the background.
Exec=/usr/bin/syncthing -no-browser
Exec=/usr/bin/syncthing -no-browser -logfile=~/.config/syncthing/syncthing.log
Icon=syncthing
Terminal=false
Type=Application

0
etc/linux-runit/run Normal file → Executable file
View File

10
go.mod
View File

@@ -30,16 +30,19 @@ require (
github.com/onsi/gomega v1.6.0 // indirect
github.com/oschwald/geoip2-golang v1.4.0
github.com/petermattis/goid v0.0.0-20180202154549-b0b1615b78e5 // indirect
github.com/pkg/errors v0.9.0
github.com/pkg/errors v0.9.1
github.com/prometheus/client_golang v1.2.1
github.com/rcrowley/go-metrics v0.0.0-20190826022208-cac0b30c2563
github.com/sasha-s/go-deadlock v0.2.0
github.com/shirou/gopsutil v0.0.0-20190714054239-47ef3260b6bf
github.com/spaolacci/murmur3 v1.1.0 // indirect
github.com/syncthing/notify v0.0.0-20190709140112-69c7a957d3e2
github.com/syndtr/goleveldb v1.0.1-0.20190923125748-758128399b1d
github.com/thejerf/suture v3.0.2+incompatible
github.com/urfave/cli v1.22.2
github.com/vitrun/qart v0.0.0-20160531060029-bf64b92db6b0
github.com/willf/bitset v1.1.10 // indirect
github.com/willf/bloom v2.0.3+incompatible
golang.org/x/crypto v0.0.0-20190829043050-9756ffdc2472
golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297
golang.org/x/text v0.3.2
@@ -49,4 +52,7 @@ require (
gopkg.in/ldap.v2 v2.5.1
)
go 1.12
go 1.13
// https://github.com/spaolacci/murmur3/pull/30
replace github.com/spaolacci/murmur3 v1.1.0 => github.com/calmh/murmur3 v1.1.1-0.20200226160057-74e9af8f47ac

14
go.sum
View File

@@ -8,8 +8,10 @@ github.com/StackExchange/wmi v0.0.0-20180116203802-5d049714c4a6/go.mod h1:3eOhrU
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d h1:G0m3OIz70MZUWq3EgK3CesDbo8upS2Vm9/P3FtgI+Jk=
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4 h1:Hs82Z41s6SdL1CELW+XaDYmOH4hkBN4/N9og/AsOv7E=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973 h1:xJ4a3vCFaGF/jqvzLMYoU8P317H5OQ+Via4RmuPwCS0=
github.com/beorn7/perks v0.0.0-20180321164747-3a771d992973/go.mod h1:Dwedo/Wpr24TaqPxmxbtue+5NUziq4I4S80YR8gNf3Q=
@@ -19,6 +21,8 @@ github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
github.com/bkaradzic/go-lz4 v0.0.0-20160924222819-7224d8d8f27e h1:2augTYh6E+XoNrrivZJBadpThP/dsvYKj0nzqfQ8tM4=
github.com/bkaradzic/go-lz4 v0.0.0-20160924222819-7224d8d8f27e/go.mod h1:0YdlkowM3VswSROI7qDxhRvJ3sLhlFrRRwjwegp5jy4=
github.com/calmh/murmur3 v1.1.1-0.20200226160057-74e9af8f47ac h1:mc24tiVsBenJuhJFQzgvTo1ECJxCGXUgNktcfEhJHHo=
github.com/calmh/murmur3 v1.1.1-0.20200226160057-74e9af8f47ac/go.mod h1:nZyyz8Qrw2g3CakiZkVTsiwKlCgQSCf2ZCAFB3DHbaI=
github.com/calmh/xdr v1.1.0 h1:U/Dd4CXNLoo8EiQ4ulJUXkgO1/EyQLgDKLgpY1SOoJE=
github.com/calmh/xdr v1.1.0/go.mod h1:E8sz2ByAdXC8MbANf1LCRYzedSnnc+/sXXJs/PVqoeg=
github.com/ccding/go-stun v0.0.0-20180726100737-be486d185f3d h1:As4937T5NVbJ/DmZT9z33pyLEprMd6CUSfhbmMY57Io=
@@ -143,6 +147,8 @@ github.com/pkg/errors v0.8.1 h1:iURUrRGxPUNPdy5/HRSm+Yj6okJ6UtLINN0Q9M4+h3I=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.0 h1:J8lpUdobwIeCI7OiSxHqEwJUKvJwicL5+3v1oe2Yb4k=
github.com/pkg/errors v0.9.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
@@ -176,7 +182,10 @@ github.com/shirou/w32 v0.0.0-20160930032740-bb4de0191aa4/go.mod h1:qsXQc7+bwAM3Q
github.com/shurcooL/sanitized_anchor_name v1.0.0 h1:PdmoCO6wvbs+7yrJyMORt4/BmY5IYyJwS/kOiWx8mHo=
github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc=
github.com/sirupsen/logrus v1.2.0/go.mod h1:LxeOpSwHxABJmUn/MG1IvRgCAasNZTLOkJPxbbu5VWo=
github.com/sirupsen/logrus v1.4.2 h1:SPIRibHv4MatM3XXNO2BJeFLZwZ2LvZgfQ5+UNI2im4=
github.com/sirupsen/logrus v1.4.2/go.mod h1:tLMulIdttU9McNUspp0xgXVQah82FyeX6MwdIuYE2rE=
github.com/spaolacci/murmur3 v1.1.0 h1:7c1g84S4BPRrfL5Xrdp6fOJ206sU9y293DDHaoy0bLI=
github.com/spaolacci/murmur3 v1.1.0/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
github.com/stretchr/testify v1.2.2 h1:bSDNvY7ZPG5RlJ8otE/7V6gMiyenm9RtJ7IUVIAoJ1w=
@@ -197,6 +206,10 @@ github.com/urfave/cli v1.22.2 h1:gsqYFH8bb9ekPA12kRo0hfjngWQjkJPlN9R0N78BoUo=
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/vitrun/qart v0.0.0-20160531060029-bf64b92db6b0 h1:okhMind4q9H1OxF44gNegWkiP4H/gsTFLalHFa4OOUI=
github.com/vitrun/qart v0.0.0-20160531060029-bf64b92db6b0/go.mod h1:TTbGUfE+cXXceWtbTHq6lqcTvYPBKLNejBEbnUsQJtU=
github.com/willf/bitset v1.1.10 h1:NotGKqX0KwQ72NUzqrjZq5ipPNDQex9lo3WpaS8L2sc=
github.com/willf/bitset v1.1.10/go.mod h1:RjeCKbqT1RxIR/KWY6phxZiaY1IyutSBfGjNPySAYV4=
github.com/willf/bloom v2.0.3+incompatible h1:QDacWdqcAUI1MPOwIQZRy9kOR7yxfyEmxX8Wdm2/JPA=
github.com/willf/bloom v2.0.3+incompatible/go.mod h1:MmAltL9pDMNTrvUkxdg0k0q5I0suxmuwp3KbyrZLOZ8=
golang.org/x/crypto v0.0.0-20180904163835-0709b304e793/go.mod h1:6SG95UA2DQfeDnfUPMdvaQW0Q7yPrPDi9nlGo2tz2b4=
golang.org/x/crypto v0.0.0-20190228161510-8dd112bcdc25/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2 h1:VklqNMn3ovrHsnt90PveolxSbWFaJdECFbxSq0Mqo2M=
@@ -244,6 +257,7 @@ golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGm
golang.org/x/tools v0.0.0-20181030221726-6c7e314b6563/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
google.golang.org/genproto v0.0.0-20180831171423-11092d34479b/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6 h1:jMFz6MfLP0/4fUyZle81rXUoxOBFi19VUFKVDOQfozc=
gopkg.in/alecthomas/kingpin.v2 v2.2.6/go.mod h1:FMv+mEhP44yOT+4EoQTLFTRgOQ1FBLkstjWtayDeSgw=
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d h1:TxyelI5cVkbREznMhfzycHdkp5cLA7DpE+GKjSslYhM=
gopkg.in/asn1-ber.v1 v1.0.0-20181015200546-f715ec2f112d/go.mod h1:cuepJuh7vyXfUyUwEgHQXw849cJrilpS5NeIjOWESAw=

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.4 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.5 KiB

After

Width:  |  Height:  |  Size: 3.5 KiB

View File

Binary file not shown.

Before

Width:  |  Height:  |  Size: 4.0 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

@@ -106,6 +106,7 @@
"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 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.": "Добавете шаблони за игнориране, по един на ред.",
"Enter up to three octal digits.": "Enter up to three octal digits.",
"Error": "Грешка",
"External File Versioning": "Външно управление на версиите",
"Failed Items": "Неуспешни",
@@ -348,6 +349,7 @@
"Time the item was last modified": "Часът на последна промяна на елемента",
"Trash Can File Versioning": "Само на файловете в кошчето",
"Type": "Тип",
"UNIX Permissions": "UNIX Permissions",
"Unavailable": "Не е на разположение",
"Unavailable/Disabled by administrator or maintainer": "Не е на разположение/Деактивриан от администраторът или поддръжника",
"Undecided (will prompt)": "Неизбрано (ще попита)",
@@ -372,6 +374,8 @@
"Versions": "Версии",
"Versions Path": "Път до версиите",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Версиите биват изтривани автоматично, когато са по-стари от максималната възраст или надминават броя версии разрешени в даден интервал.",
"Waiting to Scan": "Waiting to Scan",
"Waiting to Sync": "Waiting to Sync",
"Waiting to scan": "Waiting to scan",
"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}}).",

View File

@@ -106,6 +106,7 @@
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Introdueix adreces separades per coma (\"tcp://ip:port\", \"tcp://host:port\") o \"dynamic\" per a realitzar el descobriment automàtic de l'adreça.",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Introduïr adreces separades per coma (\"tcp://ip:port\", \"tcp://host:port\") o dinàmiques per al descobriment automàtic de l'adreça.",
"Enter ignore patterns, one per line.": "Introduïr patrons a ignorar, un per línia.",
"Enter up to three octal digits.": "Enter up to three octal digits.",
"Error": "Error",
"External File Versioning": "Versionat extern de fitxers",
"Failed Items": "Objectes fallits",
@@ -348,6 +349,7 @@
"Time the item was last modified": "Hora a la que l'ítem fou modificat per última vegada",
"Trash Can File Versioning": "Versionat d'arxius de la paperera",
"Type": "Tipus",
"UNIX Permissions": "UNIX Permissions",
"Unavailable": "No disponible",
"Unavailable/Disabled by administrator or maintainer": "No disponible/Desactivar per l'administrador o mantenedor",
"Undecided (will prompt)": "No decidit (es preguntarà)",
@@ -372,6 +374,8 @@
"Versions": "Versions",
"Versions Path": "Ruta de les versions",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Les versions s'esborren automàticament si són més antigues que l'edat màxima o excedixen el nombre de fitxer permesos en un interval.",
"Waiting to Scan": "Waiting to Scan",
"Waiting to Sync": "Waiting to Sync",
"Waiting to scan": "Esperant per a escanetjar",
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Perill! Esta ruta és un directori pare d'una carpeta ja existent \"{{otherFolder}}\".",
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Perill! Esta ruta és un directori pare d'una carpeta existent \"{{otherFolderLabel}}\" ({{otherFolder}}).",

View File

@@ -31,7 +31,7 @@
"Are you sure you want to remove device {%name%}?": "Opravdu chcete odebrat zařízení {{name}}?",
"Are you sure you want to remove folder {%label%}?": "Opravdu chcete odebrat složku {{label}}?",
"Are you sure you want to restore {%count%} files?": "Opravdu chcete obnovit {{count}} souborů?",
"Are you sure you want to upgrade?": "Are you sure you want to upgrade?",
"Are you sure you want to upgrade?": "Skutečně chcete provést aktualizaci?",
"Auto Accept": "Přijmout automaticky",
"Automatic Crash Reporting": "Automatické hlášení pádů",
"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 ně.",
@@ -60,13 +60,13 @@
"Copyright © 2014-2017 the following Contributors:": "Copyright © 2014-2017 následující přispěvatelé:",
"Copyright © 2014-2019 the following Contributors:": "Copyright © 2014-2019 následující přispěvatelé:",
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Vytvářejí se vzory ignorovaného a přepisuje se jimi existující soubor v {{path}}.",
"Currently Shared With Devices": "Currently Shared With Devices",
"Currently Shared With Devices": "Aktuálně sdíleno se zařízeními",
"Danger!": "Nebezpečí!",
"Debugging Facilities": "Nástroje pro ladění",
"Default Folder Path": "Popis umístění výchozí složky",
"Deleted": "Smazáno",
"Deselect All": "Zrušit výběr všeho",
"Deselect devices to stop sharing this folder with.": "Deselect devices to stop sharing this folder with.",
"Deselect devices to stop sharing this folder with.": "Zrušte výběr zařízení, se kterými již nemá být tato složka sdílena.",
"Device": "Zařízení",
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "Zařízení „{{name}}“ ({{device}} na {{address}}) se chce připojit. Přidat nové zařízení?",
"Device ID": "Identifikátor zařízení",
@@ -106,6 +106,7 @@
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Zadejte adresy oddělené čárkou („tcp://ip:port“, „tcp://host:port“) nebo „dynamic“ pro automatické zjišťování adres.",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Zadejte adresy oddělené čárkami („tcp://ip:port“, „tcp://host:port“) nebo „dynamic“ pro automatické zjištění adresy.",
"Enter ignore patterns, one per line.": "Zadejte vzory toho, co ignorovat každý na zvlášť řádek.",
"Enter up to three octal digits.": "Zadejte nanejvýš tři osmičkové číslice.",
"Error": "Chyba",
"External File Versioning": "Externí správa verzí souborů",
"Failed Items": "Nezdařené položky",
@@ -171,7 +172,7 @@
"Listeners": "Naslouchající",
"Loading data...": "Načítání dat…",
"Loading...": "Načítání…",
"Local Additions": "Local Additions",
"Local Additions": "Místní příbytky",
"Local Discovery": "Místní oznamování",
"Local State": "Místní status",
"Local State (Total)": "Místní status (Celkem)",
@@ -228,7 +229,7 @@
"Please wait": "Chvíli strpení",
"Prefix indicating that the file can be deleted if preventing directory removal": "Tato předpona značí, že pokud soubor brání odebrání složky, je možné ho smazat",
"Prefix indicating that the pattern should be matched without case sensitivity": "Tato předpona značí, že při porovnávání se vzorem nemají být rozlišována malá/velká písmena",
"Preparing to Sync": "Preparing to Sync",
"Preparing to Sync": "Probíhá příprava k synchronizaci",
"Preview": "Náhled",
"Preview Usage Report": "Náhled hlášení o využívání",
"Quick guide to supported patterns": "Rychlá nápověda k podporovaným vzorům",
@@ -265,7 +266,7 @@
"See external versioning help for supported templated command line parameters.": "Podporované šablonové parametry příkazové řádky jsou dostupné v nápovědě k externí správě verzí.",
"Select All": "Vybrat vše",
"Select a version": "Vyberte verzi",
"Select additional devices to share this folder with.": "Select additional devices to share this folder with.",
"Select additional devices to share this folder with.": "Vyberte další zařízení pro sdílení s touto složkou.",
"Select latest version": "Vybrat nejnovější verzi",
"Select oldest version": "Vybrat nejstarší verzi",
"Select the devices to share this folder with.": "Vybrat zařízení, se kterými sdílet tuto složku.",
@@ -338,7 +339,7 @@
"The path cannot be blank.": "Popis umístění nemůže zůstat nevyplněný.",
"The rate limit must be a non-negative number (0: no limit)": "Je třeba, aby limit rychlosti bylo kladné číslo (0: bez limitu)",
"The rescan interval must be a non-negative number of seconds.": "Je třeba, aby interval opakování skenování bylo kladné číslo.",
"There are no devices to share this folder with.": "There are no devices to share this folder with.",
"There are no devices to share this folder with.": "Nejsou žádná zařízení, se kterými lze sdílet tuto složku.",
"They are retried automatically and will be synced when the error is resolved.": "Nové pokusy o synchronizaci budou probíhat automaticky a položky budou synchronizovány jakmile bude chyba odstraněna.",
"This Device": "Toto zařízení",
"This can easily give hackers access to read and change any files on your computer.": "Toto může útočníkům jednoduše umožnit čtení a úpravy souborů na vašem počítači. ",
@@ -348,13 +349,14 @@
"Time the item was last modified": "Čas poslední modifikace položky",
"Trash Can File Versioning": "Ponechávat jednu předchozí verzi (jako Koš) ",
"Type": "Typ",
"UNIX Permissions": "UNIX oprávnění",
"Unavailable": "Nedostupné",
"Unavailable/Disabled by administrator or maintainer": "Není k dispozici / vypnuto správcem systému či balíčku",
"Undecided (will prompt)": "Nerozhodnuto (zeptá se)",
"Unignore": "Přestat ignorovat",
"Unknown": "Neznámý",
"Unshared": "Nesdílený",
"Unshared Devices": "Unshared Devices",
"Unshared Devices": "Nesdílená zařízení",
"Unused": "Nepoužitý",
"Up to Date": "Aktuální",
"Updated": "Aktualizováno",
@@ -372,6 +374,8 @@
"Versions": "Verze",
"Versions Path": "Popis umístění verzí",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Verze jsou automaticky smazány, pokud jsou starší než maximální časový limit nebo překročí počet souborů povolených pro interval.",
"Waiting to Scan": "Čekání na skenování",
"Waiting to Sync": "Čekání na synchronizaci",
"Waiting to scan": "Čekání na skenování",
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Varování, tento popis umístění je nadřazenou složkou existující „{{otherFolder}}“.",
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Varování, tento popis umístění je nadřazenou složkou existující „{{otherFolderLabel}}“ ({{otherFolder}}).",

View File

@@ -106,6 +106,7 @@
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Angiv kommaseparerede adresser (“tcp://ip:port”, “tcp://host:port”) eller “dynamic” for at benytte automatisk opdagelse af adressen.",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Angiv en kommaadskilt adresseliste (\"tcp://ip:port\", \"tcp://host:port\")  eller \"dynamic\" for automatisk at opdage adressen.",
"Enter ignore patterns, one per line.": "Indtast ignoreringsmønstre, ét per linje.",
"Enter up to three octal digits.": "Enter up to three octal digits.",
"Error": "Fejl",
"External File Versioning": "Ekstern filversionering",
"Failed Items": "Mislykkede filer",
@@ -348,6 +349,7 @@
"Time the item was last modified": "Tidspunkt for seneste ændring af filen",
"Trash Can File Versioning": "Versionering med papirkurv",
"Type": "Type",
"UNIX Permissions": "UNIX Permissions",
"Unavailable": "Ikke tilgængelig",
"Unavailable/Disabled by administrator or maintainer": "Ikke tilgængelig / deaktiveret af administrator eller vedligeholder",
"Undecided (will prompt)": "Ubestemt (du bliver spurgt)",
@@ -372,6 +374,8 @@
"Versions": "Versioner",
"Versions Path": "Versionssti",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Versioner slettes automatisk, hvis de er ældre end den givne maksimum alder eller overstiger det tilladte antal filer i et interval.",
"Waiting to Scan": "Waiting to Scan",
"Waiting to Sync": "Waiting to Sync",
"Waiting to scan": "Venter på at skanne",
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Advarsel: Denne sti er en forældermappe til den eksisterende mappe “{{otherFolder}}”.",
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Advarsel: Denne sti er en forældermappe til den eksisterende mappe “{{otherFolderLabel}}” ({{otherFolder}}).",

View File

@@ -60,13 +60,13 @@
"Copyright © 2014-2017 the following Contributors:": "Copyright © 2014-2017 der folgenden Unterstützer:",
"Copyright © 2014-2019 the following Contributors:": "Copyright © 2014-2019 folgende Mitwirkende:",
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Erstelle Ignoriermuster, welche die existierende Datei {{path}} überschreiben.",
"Currently Shared With Devices": "Currently Shared With Devices",
"Currently Shared With Devices": "Derzeit mit Geräten geteilt",
"Danger!": "Achtung!",
"Debugging Facilities": "Debugging-Möglichkeiten",
"Default Folder Path": "Standardmäßiger Ordnerpfad",
"Deleted": "Gelöscht",
"Deselect All": "Alle abwählen",
"Deselect devices to stop sharing this folder with.": "Deselect devices to stop sharing this folder with.",
"Deselect devices to stop sharing this folder with.": "Wähle die Geräte ab, für die dieser Ordner nicht mehr freigegeben werden soll.",
"Device": "Gerät",
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "Gerät \"{{name}}\" ({{device}} {{address}}) möchte sich verbinden. Gerät hinzufügen?",
"Device ID": "Gerätekennung",
@@ -106,6 +106,7 @@
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Kommagetrennte Adressen (\"tcp://ip:port\", \"tcp://host:port\") oder \"dynamic\" eingeben, um die Adresse automatisch zu ermitteln.",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Kommagetrennte Adressen (\"tcp://ip:port\", \"tcp://host:port\") oder \"dynamic\" eingeben, um die Adresse automatisch zu ermitteln.",
"Enter ignore patterns, one per line.": "Geben Sie Ignoriermuster ein, eines pro Zeile.",
"Enter up to three octal digits.": "Enter up to three octal digits.",
"Error": "Fehler",
"External File Versioning": "Externe Dateiversionierung",
"Failed Items": "Fehlgeschlagene Elemente",
@@ -228,7 +229,7 @@
"Please wait": "Bitte warten",
"Prefix indicating that the file can be deleted if preventing directory removal": "Präfix, das anzeigt, dass die Datei gelöscht werden kann, wenn sie die Entfernung des Ordners verhindert",
"Prefix indicating that the pattern should be matched without case sensitivity": "Präfix, das anzeigt, dass das Muster ohne Beachtung der Groß-/Kleinschreibung übereinstimmen soll",
"Preparing to Sync": "Preparing to Sync",
"Preparing to Sync": "Vorbereiten auf die Synchronisation",
"Preview": "Vorschau",
"Preview Usage Report": "Vorschau des Nutzungsberichts",
"Quick guide to supported patterns": "Schnellanleitung zu den unterstützten Mustern",
@@ -265,7 +266,7 @@
"See external versioning help for supported templated command line parameters.": "Siehe Hilfe zur externen Versionierung für unterstützte Befehlszeilenparameter.",
"Select All": "Alle auswählen",
"Select a version": "Wählen Sie eine Version",
"Select additional devices to share this folder with.": "Select additional devices to share this folder with.",
"Select additional devices to share this folder with.": "Wähle weitere Geräte aus, für die dieser Ordner geteilt werden soll.",
"Select latest version": "Letzte Version auswählen",
"Select oldest version": "Älteste Version auswählen",
"Select the devices to share this folder with.": "Wähle die Geräte aus, mit denen Sie diesen Ordner teilen wollen.",
@@ -338,7 +339,7 @@
"The path cannot be blank.": "Der Pfad darf nicht leer sein.",
"The rate limit must be a non-negative number (0: no limit)": "Das Datenratelimit muss eine nicht negative Zahl sein (0 = kein Limit).",
"The rescan interval must be a non-negative number of seconds.": "Das Scanintervall muss eine nicht negative Anzahl (in Sekunden) sein.",
"There are no devices to share this folder with.": "There are no devices to share this folder with.",
"There are no devices to share this folder with.": "Es gibt keine Geräte, mit denen dieser Ordner geteilt werden kann.",
"They are retried automatically and will be synced when the error is resolved.": "Sie werden automatisch heruntergeladen und werden synchronisiert, wenn der Fehler behoben wurde.",
"This Device": "Dieses Gerät",
"This can easily give hackers access to read and change any files on your computer.": "Dies kann dazu führen, dass Unberechtigte relativ einfach auf Ihre Dateien zugreifen und diese ändern können.",
@@ -348,13 +349,14 @@
"Time the item was last modified": "Zeit der letzten Änderung des Elements",
"Trash Can File Versioning": "Papierkorb Dateiversionierung",
"Type": "Typ",
"UNIX Permissions": "UNIX-Berechtigungen",
"Unavailable": " Nicht verfügbar",
"Unavailable/Disabled by administrator or maintainer": "Nicht verfügbar/durch Administrator oder Betreuer deaktiviert",
"Undecided (will prompt)": "Unentschlossen (wird nachgefragt)",
"Unignore": "Beachten",
"Unknown": "Unbekannt",
"Unshared": "Ungeteilt",
"Unshared Devices": "Unshared Devices",
"Unshared Devices": "Ungeteilte Geräte",
"Unused": "Ungenutzt",
"Up to Date": "Aktuell",
"Updated": "Aktualisiert",
@@ -372,6 +374,8 @@
"Versions": "Versionen",
"Versions Path": "Versionierungspfad",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Alte Dateiversionen werden automatisch gelöscht, wenn sie älter als das angegebene Höchstalter sind oder die angegebene Höchstzahl an Dateien erreicht ist.",
"Waiting to Scan": "Waiting to Scan",
"Waiting to Sync": "Warten auf die Synchronisation",
"Waiting to scan": "Warten auf Scan",
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Warnung, dieser Pfad ist ein übergeordneter Ordner eines existierenden Ordners \"{{otherFolder}}\".",
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Warnung, dieser Pfad ist ein übergeordneter Ordner eines existierenden Ordners \"{{otherFolderLabel}}\" ({{otherFolder}}).",

View File

@@ -106,6 +106,7 @@
"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 comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.",
"Enter ignore patterns, one per line.": "Δώσε τα πρότυπα που θα αγνοηθούν, ένα σε κάθε γραμμή.",
"Enter up to three octal digits.": "Enter up to three octal digits.",
"Error": "Σφάλμα",
"External File Versioning": "Εξωτερική τήρηση εκδόσεων",
"Failed Items": "Αρχεία που απέτυχαν",
@@ -348,6 +349,7 @@
"Time the item was last modified": "Ώρα τελευταίας τροποποίησης του στοιχείου",
"Trash Can File Versioning": "Τήρηση εκδόσεων κάδου ανακύκλωσης",
"Type": "Τύπος",
"UNIX Permissions": "UNIX Permissions",
"Unavailable": "Μη διαθέσιμο",
"Unavailable/Disabled by administrator or maintainer": "Μη διαθέσιμο/απενεργοποιημένο από τον διαχειριστή ή υπεύθυνο διανομής",
"Undecided (will prompt)": "Μη καθορισμένη (θα γίνει ερώτηση)",
@@ -372,6 +374,8 @@
"Versions": "Εκδόσεις",
"Versions Path": "Φάκελος τήρησης εκδόσεων",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Οι παλιές εκδόσεις θα σβήνονται αυτόματα όταν ξεπεράσουν τη μέγιστη ηλικία ή όταν ξεπεραστεί ο μέγιστος αριθμός αρχείων ανά περίοδο.",
"Waiting to Scan": "Waiting to Scan",
"Waiting to Sync": "Waiting to Sync",
"Waiting to scan": "Waiting to scan",
"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}}).",

View File

@@ -106,6 +106,7 @@
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.",
"Enter ignore patterns, one per line.": "Enter ignore patterns, one per line.",
"Enter up to three octal digits.": "Enter up to three octal digits.",
"Error": "Error",
"External File Versioning": "External File Versioning",
"Failed Items": "Failed Items",
@@ -348,6 +349,7 @@
"Time the item was last modified": "Time the item was last modified",
"Trash Can File Versioning": "Rubbish Bin File Versioning",
"Type": "Type",
"UNIX Permissions": "UNIX Permissions",
"Unavailable": "Unavailable",
"Unavailable/Disabled by administrator or maintainer": "Unavailable/Disabled by administrator or maintainer",
"Undecided (will prompt)": "Undecided (will prompt)",
@@ -372,6 +374,8 @@
"Versions": "Versions",
"Versions Path": "Versions Path",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.",
"Waiting to Scan": "Waiting to Scan",
"Waiting to Sync": "Waiting to Sync",
"Waiting to scan": "Waiting to scan",
"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}}).",

View File

@@ -106,6 +106,7 @@
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.",
"Enter ignore patterns, one per line.": "Enter ignore patterns, one per line.",
"Enter up to three octal digits.": "Enter up to three octal digits.",
"Error": "Error",
"External File Versioning": "External File Versioning",
"Failed Items": "Failed Items",
@@ -348,6 +349,7 @@
"Time the item was last modified": "Time the item was last modified",
"Trash Can File Versioning": "Trash Can File Versioning",
"Type": "Type",
"UNIX Permissions": "UNIX Permissions",
"Unavailable": "Unavailable",
"Unavailable/Disabled by administrator or maintainer": "Unavailable/Disabled by administrator or maintainer",
"Undecided (will prompt)": "Undecided (will prompt)",
@@ -372,6 +374,8 @@
"Versions": "Versions",
"Versions Path": "Versions Path",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.",
"Waiting to Scan": "Waiting to Scan",
"Waiting to Sync": "Waiting to Sync",
"Waiting to scan": "Waiting to scan",
"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}}).",

View File

@@ -2,16 +2,16 @@
"A device with that ID is already added.": "Aparato kun samtia ID estis jam aldonita.",
"A negative number of days doesn't make sense.": "Negativa numero de tagoj ne havas sencon.",
"A new major version may not be compatible with previous versions.": "Nova ĉefa versio eble ne kongruanta kun antaŭaj versioj.",
"API Key": "API Ŝlosilo",
"API Key": "Ŝlosilo API",
"About": "Pri",
"Action": "Ago",
"Actions": "Agoj",
"Add": "Aldoni",
"Add Device": "Aldoni Aparaton",
"Add Folder": "Aldoni Dosierujon",
"Add Remote Device": "Aldoni Foran Aparaton",
"Add Device": "Aldoni aparaton",
"Add Folder": "Aldoni dosierujon",
"Add Remote Device": "Aldoni foran aparaton",
"Add devices from the introducer to our device list, for mutually shared folders.": "Aldoni aparatojn de la enkondukanto ĝis nia aparatlisto, por reciproke komunigitaj dosierujoj.",
"Add new folder?": "Aldoni novan dosierujon?",
"Add new folder?": "Ĉu aldoni novan dosierujon?",
"Additionally the full rescan interval will be increased (times 60, i.e. new default of 1h). You can also configure it manually for every folder later after choosing No.": "Aldone, plena reskana intervalo estos pliigita (60-oble, t.e. nova defaŭlto estas 1h). Vi povas ankaŭ agordi ĝin permane por ĉiu dosierujo poste post elekto de Ne.",
"Address": "Adreso",
"Addresses": "Adresoj",
@@ -31,9 +31,9 @@
"Are you sure you want to remove device {%name%}?": "Ĉu vi certas, ke vi volas forigi aparaton {{name}}?",
"Are you sure you want to remove folder {%label%}?": "Ĉu vi certas, ke vi volas forigi dosierujon {{label}}?",
"Are you sure you want to restore {%count%} files?": "Ĉu vi certas, ke vi volas restarigi {{count}} dosierojn?",
"Are you sure you want to upgrade?": "Are you sure you want to upgrade?",
"Are you sure you want to upgrade?": "Ĉu vi certe volas plinovigi?",
"Auto Accept": "Akcepti Aŭtomate",
"Automatic Crash Reporting": "Automatic Crash Reporting",
"Automatic Crash Reporting": "Aŭtomata raportado de kraŝoj",
"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",
"Automatic upgrades are always enabled for candidate releases.": "Aŭtomataj ĝisdatigoj ĉiam ŝaltitaj por kandidataj eldonoj.",
@@ -60,13 +60,13 @@
"Copyright © 2014-2017 the following Contributors:": "Kopirajto © 2014-2017 por la sekvantaj Kontribuantoj:",
"Copyright © 2014-2019 the following Contributors:": "Kopirajto © 2014-2019 por la sekvantaj Kontribuantoj:",
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Kreante ignorantajn ŝablonojn, anstataŭige ekzistantan dosieron ĉe {{path}}.",
"Currently Shared With Devices": "Currently Shared With Devices",
"Currently Shared With Devices": "Nune komunigita kun aparatoj",
"Danger!": "Danĝero!",
"Debugging Facilities": "Elpurigadiloj",
"Default Folder Path": "Defaŭlta Dosieruja Vojo",
"Deleted": "Forigita",
"Deselect All": "Malelekti Ĉiujn",
"Deselect devices to stop sharing this folder with.": "Deselect devices to stop sharing this folder with.",
"Deselect devices to stop sharing this folder with.": "Malelekti aparatojn por ĉesi komunigi tiun ĉi dosierujon kun ili.",
"Device": "Aparato",
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "Aparato \"{{name}}\" ({{device}} ĉe {{address}}) volas konekti. Aldoni la novan aparaton?",
"Device ID": "Aparato ID",
@@ -75,7 +75,7 @@
"Device rate limits": "Limoj de rapideco de aparato",
"Device that last modified the item": "Aparato kiu laste modifis la eron",
"Devices": "Aparatoj",
"Disable Crash Reporting": "Disable Crash Reporting",
"Disable Crash Reporting": "Malŝalti raportadon de kraŝoj",
"Disabled": "Malebligita",
"Disabled periodic scanning and disabled watching for changes": "Malebligita perioda skanado kaj malebligita rigardado je ŝanĝoj",
"Disabled periodic scanning and enabled watching for changes": "Malebligita perioda skanado kaj ebligita rigardado je ŝanĝoj",
@@ -97,7 +97,7 @@
"Edit Folder": "Redakti Dosierujon",
"Editing": "Redaktado",
"Editing {%path%}.": "Redaktado de {{path}}.",
"Enable Crash Reporting": "Enable Crash Reporting",
"Enable Crash Reporting": "Ŝalti raportadon de kraŝoj",
"Enable NAT traversal": "Ŝaltu trairan NAT",
"Enable Relaying": "Ŝaltu Relajsadon",
"Enabled": "Ebligita",
@@ -106,6 +106,7 @@
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Enigu adresojn dividitajn per komoj (\"tcp://ip:port\", \"tcp://host:port\") aŭ \"dynamic\" por elfari aŭtomatan malkovradon de la adreso.",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Enigu adresojn dividitajn per komoj (\"tcp://ip:port\", \"tcp://host:port\") aŭ \"dynamic\" por elfari aŭtomatan malkovradon de la adreso.",
"Enter ignore patterns, one per line.": "Enigu ignorantajn ŝablonojn, unu po linio.",
"Enter up to three octal digits.": "Entajpu ĝis tri okumajn ciferojn.",
"Error": "Eraro",
"External File Versioning": "Ekstera Versionado de Dosiero",
"Failed Items": "Malsukcesaj Eroj",
@@ -171,7 +172,7 @@
"Listeners": "Aŭskultantoj",
"Loading data...": "Ŝarĝas datumojn...",
"Loading...": "Ŝarĝas...",
"Local Additions": "Local Additions",
"Local Additions": "Lokaj aldonoj",
"Local Discovery": "Loka Malkovro",
"Local State": "Loka Stato",
"Local State (Total)": "Loka Stato (Tuta)",
@@ -228,7 +229,7 @@
"Please wait": "Bonvolu atendi",
"Prefix indicating that the file can be deleted if preventing directory removal": "Prefikso indikanta, ke la dosiero povas esti forigita, se ĝi malhelpas forigi dosierujon",
"Prefix indicating that the pattern should be matched without case sensitivity": "Prefikso indikanta, ke la ŝablono devus esti egalita usklecoblinde.",
"Preparing to Sync": "Preparing to Sync",
"Preparing to Sync": "Pretigante sinkronigadon",
"Preview": "Antaŭrigardo",
"Preview Usage Report": "Antaŭrigardo Uzada Raporto",
"Quick guide to supported patterns": "Rapida gvidilo pri subtenata ŝablonoj",
@@ -265,7 +266,7 @@
"See external versioning help for supported templated command line parameters.": "Vidu informlibron de ekstera versionado por subtenata ŝablona parametroj de komandlinio.",
"Select All": "Elekti Ĉiujn",
"Select a version": "Elekti version",
"Select additional devices to share this folder with.": "Select additional devices to share this folder with.",
"Select additional devices to share this folder with.": "Elektu pliajn aparatojn por komunigi tiun ĉi dosierujon kun ili.",
"Select latest version": "Elekti plej novan version",
"Select oldest version": "Elekti plej malnovan version",
"Select the devices to share this folder with.": "Elekti la aparatojn por komunigi ĉi tiun dosierujon.",
@@ -338,7 +339,7 @@
"The path cannot be blank.": "La vojo ne povas esti malplena.",
"The rate limit must be a non-negative number (0: no limit)": "La rapideca limo devas esti pozitiva nombro (0: senlimo)",
"The rescan interval must be a non-negative number of seconds.": "La intervalo de reskano devas esti pozitiva nombro da sekundoj.",
"There are no devices to share this folder with.": "There are no devices to share this folder with.",
"There are no devices to share this folder with.": "Estas neniu aparato kun kiu komunigi tiun ĉi dosierujon.",
"They are retried automatically and will be synced when the error is resolved.": "Ili estas reprovitaj aŭtomate kaj estos sinkronigitaj kiam la eraro estas solvita.",
"This Device": "Ĉi Tiu Aparato",
"This can easily give hackers access to read and change any files on your computer.": "Ĉi tio povas facile doni al kodumuloj atingon por legi kaj ŝanĝi ajnajn dosierojn en via komputilo.",
@@ -348,13 +349,14 @@
"Time the item was last modified": "Tempo de lasta modifo de la ero",
"Trash Can File Versioning": "Rubuja Dosiera Versionado",
"Type": "Tipo",
"UNIX Permissions": "Permesoj UNIX",
"Unavailable": "Ne disponebla",
"Unavailable/Disabled by administrator or maintainer": "Ne disponebla/Malebligita de administranto aŭ subtenanto",
"Undecided (will prompt)": "Hezitema (demandos)",
"Unignore": "Malignoru",
"Unknown": "Nekonata",
"Unshared": "Nekomunigita",
"Unshared Devices": "Unshared Devices",
"Unshared Devices": "Malkomunigitaj aparatoj",
"Unused": "Neuzita",
"Up to Date": "Ĝisdata",
"Updated": "Ĝisdatigita",
@@ -372,6 +374,8 @@
"Versions": "Versioj",
"Versions Path": "Vojo de Versioj",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Versioj estas aŭtomate forigita se ili estas pli malnovaj ol la maksimuma aĝo aŭ superas la nombron da dosieroj permesita en intervalo.",
"Waiting to Scan": "Atendante skanadon",
"Waiting to Sync": "Atendante sinkronigadon",
"Waiting to scan": "Atendante scanadon",
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Averto, ĉi tiu vojo estas parenta dosierujo de ekzistanta dosierujo \"{{otherFolder}}\".",
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Averto, ĉi tiu vojo estas parenta dosierujo de ekzistanta dosierujo \"{{otherFolderLabel}}\" ({{otherFolder}}).",

View File

@@ -106,6 +106,7 @@
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Introduzca las direcciones, separadas por comas (\"tcp://ip:port\", \"tcp://host:port\"), o \"dynamic\" para llevar a cabo el descubrimiento automático de la dirección.",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Introducir direcciones separadas por coma (\"tcp://ip:port\", \"tcp://host:port\") o dinámicas para realizar el descubrimiento automático de la dirección.",
"Enter ignore patterns, one per line.": "Introducir patrones a ignorar, uno por línea.",
"Enter up to three octal digits.": "Enter up to three octal digits.",
"Error": "Error",
"External File Versioning": "Versionado externo de fichero",
"Failed Items": "Elementos fallidos",
@@ -348,6 +349,7 @@
"Time the item was last modified": "Tiempo en el que se modificó el ítem por última vez",
"Trash Can File Versioning": "Versionado de archivos de la papelera",
"Type": "Tipo",
"UNIX Permissions": "UNIX Permissions",
"Unavailable": "No disponible",
"Unavailable/Disabled by administrator or maintainer": "No disponible/Desactivado por el administrador o el mantenedor",
"Undecided (will prompt)": "Aún no decidido (se preguntará al usuario)",
@@ -372,6 +374,8 @@
"Versions": "Versiones",
"Versions Path": "Ruta de las versiones",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Las versiones se borran automáticamente si son más antiguas que la edad máxima o exceden el número de ficheros permitidos en un intervalo.",
"Waiting to Scan": "Waiting to Scan",
"Waiting to Sync": "Waiting to Sync",
"Waiting to scan": "Esperando para escanear",
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "¡Peligro! Esta ruta es un directorio principal de la carpeta ya existente \"{{otherFolder}}\".",
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "'Peligro! Esta ruta es un subdirectorio de la carpeta ya existente \"{{otherFolderLabel}}\" ({{otherFolder}}).",

View File

@@ -106,6 +106,7 @@
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Introduzca las direcciones, separadas por comas (\"tcp://ip:port\", \"tcp://host:port\"), o \"dynamic\" para llevar a cabo el descubrimiento automático de la dirección.",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.",
"Enter ignore patterns, one per line.": "Introducir patrones a ignorar, uno por línea.",
"Enter up to three octal digits.": "Enter up to three octal digits.",
"Error": "Error",
"External File Versioning": "Versionado externo de fichero",
"Failed Items": "Elementos fallidos",
@@ -348,6 +349,7 @@
"Time the item was last modified": "Hora en que el ítem fue modificado por última vez",
"Trash Can File Versioning": "Versionado de archivos de la papelera",
"Type": "Tipo",
"UNIX Permissions": "UNIX Permissions",
"Unavailable": "No disponible",
"Unavailable/Disabled by administrator or maintainer": "No disponible/Deshabilitado por el administrador o mantenedor",
"Undecided (will prompt)": "No decidido (se preguntará)",
@@ -372,6 +374,8 @@
"Versions": "Versiones",
"Versions Path": "Ruta de las versiones",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Las versiones se borran automáticamente si son más antiguas que la edad máxima o exceden el número de ficheros permitidos en un intervalo.",
"Waiting to Scan": "Waiting to Scan",
"Waiting to Sync": "Waiting to Sync",
"Waiting to scan": "Waiting to scan",
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "¡Peligro! Esta ruta es un directorio principal de la carpeta ya existente \"{{otherFolder}}\".",
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "'Peligro! Esta ruta es un subdirectorio de la carpeta ya existente \"{{otherFolderLabel}}\" ({{otherFolder}}).",

View File

@@ -106,6 +106,7 @@
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Syötä osoitteet pilkuilla erotettuina (\"tcp://ip:portti, tcp://nimi:portti\") tai \"dynamic\" käyttääksesi osoitteen automaattista selvitystä.",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.",
"Enter ignore patterns, one per line.": "Syötä ohituslausekkeet, yksi riviä kohden.",
"Enter up to three octal digits.": "Enter up to three octal digits.",
"Error": "Virhe",
"External File Versioning": "Ulkoinen tiedostoversionti",
"Failed Items": "Epäonnistuneet kohteet",
@@ -348,6 +349,7 @@
"Time the item was last modified": "Aika jolloin kohdetta viimeksi muokattiin",
"Trash Can File Versioning": "Roskakorin tiedostoversiointi",
"Type": "Tyyppi",
"UNIX Permissions": "UNIX Permissions",
"Unavailable": "Ei saatavilla",
"Unavailable/Disabled by administrator or maintainer": "Ei saatavilla / ylläpitäjän estämä.",
"Undecided (will prompt)": "Ei päätetty (kysytään myöhemmin)",
@@ -372,6 +374,8 @@
"Versions": "Versiot",
"Versions Path": "Versioiden polku",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Versiot poistetaan automaattisesti mikäli ne ovat vanhempia kuin maksimi-ikä tai niiden määrä ylittää sallitun määrän tietyllä aikavälillä.",
"Waiting to Scan": "Waiting to Scan",
"Waiting to Sync": "Waiting to Sync",
"Waiting to scan": "Odotetaan skannausta",
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Varoitus: tämä polku on olemassa olevan kansion \"{{otherFolder}}\" yläkansio.",
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Varoitus: Tämä kansio on jo olemassa olevan kansion yläkansio \"{{otherFolderLabel}}\" ({{otherFolder}}).",

View File

@@ -106,6 +106,7 @@
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Entrer les adresses (\"tcp://ip:port\" ou \"tcp://hôte:port\") séparées par une virgule, ou \"dynamic\" afin d'activer la recherche automatique de l'adresse.",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Entrer les adresses (\"tcp://ip:port\" ou \"tcp://hôte:port\") séparées par une virgule, ou \"dynamic\" afin d'activer la recherche automatique de l'adresse.",
"Enter ignore patterns, one per line.": "Entrez les masques d'exclusion, un par ligne.",
"Enter up to three octal digits.": "Entrez jusqu'à 3 chiffres octaux",
"Error": "Erreur",
"External File Versioning": "Gestion externe des versions de fichiers",
"Failed Items": "Éléments en échec",
@@ -348,6 +349,7 @@
"Time the item was last modified": "Dernière modification de l'élément",
"Trash Can File Versioning": "Style poubelle",
"Type": "Type",
"UNIX Permissions": "Permissions UNIX",
"Unavailable": "Indisponible",
"Unavailable/Disabled by administrator or maintainer": "Indisponible/Désactivé par l'administrateur ou le mainteneur",
"Undecided (will prompt)": "Non défini (Choisir plus tard)",
@@ -372,6 +374,8 @@
"Versions": "Restauration...",
"Versions Path": "Emplacement des versions",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Les plus anciennes versions seront supprimées automatiquement quand elles dépassent la durée maximum de conservation ou si leur nombre (par fichier) est supérieur à la limite prédéfinie pour l'intervalle.",
"Waiting to Scan": "En attente d'analyse",
"Waiting to Sync": "En attente de synchronisation",
"Waiting to scan": "En attente d'analyse",
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Attention, ce chemin est un répertoire parent d'au moins un partage existant (par exemple \"{{otherFolder}}\"). Si c'est bien ce que vous souhaitez, vous devriez créer un nouveau sous-répertoire, sinon ceci peut causer des problèmes tels que duplications et/ou suppressions intempestives de fichiers.",
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Attention, ce chemin est un répertoire parent d'au moins un partage existant (par exemple \"{{otherFolderLabel}}\" ({{otherFolder}})). Si vous continuez, vous devriez créer un nouveau sous-répertoire, sinon ceci peut causer des problèmes tels que duplications et/ou suppressions intempestives de fichiers.",

View File

@@ -106,6 +106,7 @@
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Fier troch komma's skieden (\"tcp://ip:port\", \"tcp://host:port\") adressen yn of \"dynamic\" om automatyske ûntdekking fan it adres út te fieren.",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Fier troch komma's skieden (\"tcp://ip:port\", \"tcp://host:port\") adressen yn of \"dynamic\" om automatyske ûntdekking fan it adres út te fieren.",
"Enter ignore patterns, one per line.": "Fier negearpatroanen yn, ien per rigel.",
"Enter up to three octal digits.": "Enter up to three octal digits.",
"Error": "Flater",
"External File Versioning": "Ekstern ferzjebehear foar triemen",
"Failed Items": "Mislearre items",
@@ -348,6 +349,7 @@
"Time the item was last modified": "Tiidstip dat it ûnderdiel foar it lest oanpast waard.",
"Trash Can File Versioning": "Jiskefet-triemferzjebehear",
"Type": "Type",
"UNIX Permissions": "UNIX Permissions",
"Unavailable": "Net beskikber",
"Unavailable/Disabled by administrator or maintainer": "Net beskikber/Utsetten troch administrator of ûnderhâlder",
"Undecided (will prompt)": "Noch net beslist (wurd noch frege)",
@@ -372,6 +374,8 @@
"Versions": "Ferzjes",
"Versions Path": "Ferzjes-paad",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Ferzjes wurde automatysk fuortsmiten wannear't se âlder binne dan de maksimale âldens of wannear it tal fan triemen yn in ynterval grutter is dan tastean.",
"Waiting to Scan": "Waiting to Scan",
"Waiting to Sync": "Waiting to Sync",
"Waiting to scan": "Wachtet om te skennen",
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Warskôging, dit paad is in boppelizzende triemtafel fan in besteande map \"{{otherFolder}}\".",
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Warskôging, dit paad is in boppelizzende triemtafel fan in besteande map \"{{otherFolderLabel}}\" ({{otherFolder}}).",

View File

@@ -60,13 +60,13 @@
"Copyright © 2014-2017 the following Contributors:": "Szerzői jog © 2014-2017 az alábbi közreműködők:",
"Copyright © 2014-2019 the following Contributors:": "Szerzői jog © 2014-2019 az alábbi közreműködők:",
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Mellőzési minták létrehozása, egy létező fájl felülírása itt: {{path}}.",
"Currently Shared With Devices": "Currently Shared With Devices",
"Currently Shared With Devices": "Eszközök, melyekkel jelenleg meg van osztva",
"Danger!": "Veszély!",
"Debugging Facilities": "Hibakeresési képességek",
"Default Folder Path": "Alapértelmezett mappa útvonala",
"Deleted": "Törölve",
"Deselect All": "Kijelölés megszüntetése",
"Deselect devices to stop sharing this folder with.": "Deselect devices to stop sharing this folder with.",
"Deselect devices to stop sharing this folder with.": "Azon eszközök kijelölésének törlése, amelyekkel e mappa megosztása leállítandó.",
"Device": "Eszköz",
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "\"{{name}}\" eszköz ({{device}} @ {{address}}) szeretne csatlakozni. Hozzáadható az új eszköz?",
"Device ID": "Eszközazonosító",
@@ -106,6 +106,7 @@
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Vesszővel elválasztva több cím is megadható (\"tcp://ip:port\", \"tcp://host:port\"), az automatikus felfedezéshez a 'dynamic' kulcsszó használatos. ",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Vesszővel elválasztva több cím is megadható („tcp://ip:port”, „tcp://kiszolgáló:port”), az automatikus felfedezéshez a „dynamic” kulcsszó használatos. ",
"Enter ignore patterns, one per line.": "A mellőzési mintákból soronként egyet kell megadni.",
"Enter up to three octal digits.": "Adjon meg legfeljebb három oktális számjegyet.",
"Error": "Hiba",
"External File Versioning": "Külső fájlverzió-követés",
"Failed Items": "Hibás elemek",
@@ -171,7 +172,7 @@
"Listeners": "Kapcsolatok",
"Loading data...": "Adatok betöltése...",
"Loading...": "Betöltés...",
"Local Additions": "Local Additions",
"Local Additions": "Helyi hozzáadások",
"Local Discovery": "Helyi felfedezés",
"Local State": "Helyi állapot",
"Local State (Total)": "Helyi állapot (teljes)",
@@ -228,7 +229,7 @@
"Please wait": "Türelem",
"Prefix indicating that the file can be deleted if preventing directory removal": "Előtag, amely jelzi, hogy a fájl törölhető, ha tiltva van a mappák eltávolítása",
"Prefix indicating that the pattern should be matched without case sensitivity": "Előtag, amely jelzi, hogy a mintát nagy- ill. kisbetűérzékenység nélkül kell illeszteni.",
"Preparing to Sync": "Preparing to Sync",
"Preparing to Sync": "Szinkronizálás előkészítése",
"Preview": "Előnézet",
"Preview Usage Report": "Használati jelentés áttekintése",
"Quick guide to supported patterns": "Rövid útmutató a használható mintákról",
@@ -265,7 +266,7 @@
"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 All": "Mindent kijelöl",
"Select a version": "Válassz egy verziót",
"Select additional devices to share this folder with.": "Select additional devices to share this folder with.",
"Select additional devices to share this folder with.": "További eszközök, amelyekkel megosztandó a mappa.",
"Select latest version": "Legfrissebb verzió kijelölése",
"Select oldest version": "Legrégebbi verzió kijelölése",
"Select the devices to share this folder with.": "Eszközök, amelyekkel megosztandó a mappa",
@@ -338,7 +339,7 @@
"The path cannot be blank.": "Az elérési útvonal nem lehet üres.",
"The rate limit must be a non-negative number (0: no limit)": "A sebességlimitnek pozitív számnak kell lennie (0: nincs limit)",
"The rescan interval must be a non-negative number of seconds.": "Az átnézési intervallum nullánál nagyobb másodperc érték kell legyen.",
"There are no devices to share this folder with.": "There are no devices to share this folder with.",
"There are no devices to share this folder with.": "Nincsenek eszközök, amelyekkel megosztható lenne a mappa.",
"They are retried automatically and will be synced when the error is resolved.": "A hiba javítása után automatikusan újra megpróbálja a szinkronizálást.",
"This Device": "Ez az eszköz",
"This can easily give hackers access to read and change any files on your computer.": "Így a hekkerek könnyedén hozzáférést szerezhetnek a gépen tárolt fájlok olvasásához és módosításához.",
@@ -348,13 +349,14 @@
"Time the item was last modified": "Az idő, amikor utoljára módosítva lett az elem",
"Trash Can File Versioning": "Szemetes fájlverzió-követés",
"Type": "Típus",
"UNIX Permissions": "UNIX jogosultságok",
"Unavailable": "Nem elérhető",
"Unavailable/Disabled by administrator or maintainer": "Nem elérhető/letiltva egy adminisztrátor vagy karbantartó által",
"Undecided (will prompt)": "Bizonytalan (kérdezni fogja)",
"Unignore": "Mellőzés visszavonása",
"Unknown": "Ismeretlen",
"Unshared": "Nincs megosztva",
"Unshared Devices": "Unshared Devices",
"Unshared Devices": "Nem megosztott eszközök",
"Unused": "Nincs használatban",
"Up to Date": "Friss",
"Updated": "Frissítve",
@@ -372,6 +374,8 @@
"Versions": "Verziók",
"Versions Path": "Verziók útvonala",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "A régi verziók automatikusan törlődnek, amennyiben öregebbek, mint a maximum kor, vagy már több van belőlük, mint az adott időszakban megtartható maximum.",
"Waiting to Scan": "Várakozás átnézésre",
"Waiting to Sync": "Várakozás a szinkronizálásra",
"Waiting to scan": "Várakozás átnézésre",
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Figyelem, ez az útvonal a meglévő „{{otherFolder}}” mappa szülőmappája.",
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Figyelem, ez az útvonal a meglévő „{{otherFolderLabel}}” ({{otherFolder}}) mappa szülőmappája.",

View File

@@ -106,6 +106,7 @@
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Inserisci indirizzi separati da virgola (\"tcp://ip:porta\", \"tcp://host:porta\") oppure \"dynamic\" per effettuare il rilevamento automatico dell'indirizzo.",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Inserire gli indirizzi separati da virgola (\"tcp://ip:porta\", \"tcp://host:porta\") o \"dynamic\" per eseguire il rilevamento automatico dell'indirizzo.",
"Enter ignore patterns, one per line.": "Inserisci gli schemi di esclusione, uno per riga.",
"Enter up to three octal digits.": "Enter up to three octal digits.",
"Error": "Errore",
"External File Versioning": "Controllo Versione Esterno",
"Failed Items": "Elementi Errati",
@@ -348,6 +349,7 @@
"Time the item was last modified": "Ora dell'ultima modifica degli elementi",
"Trash Can File Versioning": "Controllo Versione con Cestino",
"Type": "Tipo",
"UNIX Permissions": "UNIX Permissions",
"Unavailable": "Non disponibile",
"Unavailable/Disabled by administrator or maintainer": "Non disponibile/Disabilitato dall'amministratore o dal manutentore",
"Undecided (will prompt)": "Non deciso (verrà richiesto)",
@@ -372,6 +374,8 @@
"Versions": "Versioni",
"Versions Path": "Percorso Cartella Versioni",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Le versioni vengono eliminate automaticamente se superano la durata massima o il numero di file permessi in un determinato intervallo temporale.",
"Waiting to Scan": "In attesa di Scansione",
"Waiting to Sync": "In attesa di Sincronizzazione",
"Waiting to scan": "In attesa di scansione",
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Attenzione, questo percorso è una cartella superiore di una cartella esistente \"{{otherFolder}}\".",
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Attenzione, questo percorso è una cartella superiore di una cartella esistente \"{{otherFolderLabel}}\" ({{otherFolder}}).",

View File

@@ -31,7 +31,7 @@
"Are you sure you want to remove device {%name%}?": "デバイス {{name}} を削除してよろしいですか?",
"Are you sure you want to remove folder {%label%}?": "フォルダー {{label}} を削除してよろしいですか?",
"Are you sure you want to restore {%count%} files?": "Are you sure you want to restore {{count}} files?",
"Are you sure you want to upgrade?": "Are you sure you want to upgrade?",
"Are you sure you want to upgrade?": "アップグレードしてよろしいですか?",
"Auto Accept": "自動承諾",
"Automatic Crash Reporting": "Automatic Crash Reporting",
"Automatic upgrade now offers the choice between stable releases and release candidates.": "自動アップグレードは、安定版とリリース候補版のいずれかを選べるようになりました。",
@@ -106,6 +106,7 @@
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "アドレスを指定する場合は「tcp://IPアドレス:ポート, tcp://ホスト名:ポート」のようにコンマで区切って入力してください。自動探索を行う場合は「dynamic」と入力してください。",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.",
"Enter ignore patterns, one per line.": "無視するファイル名のパターンを、一行につき一条件で入力してください。",
"Enter up to three octal digits.": "Enter up to three octal digits.",
"Error": "エラー",
"External File Versioning": "外部バージョン管理",
"Failed Items": "失敗した項目",
@@ -167,7 +168,7 @@
"Later": "後で設定",
"Latest Change": "最終変更内容",
"Learn more": "詳細を確認する",
"Limit": "Limit",
"Limit": "制限",
"Listeners": "待ち受けポート",
"Loading data...": "データの読み込み中...",
"Loading...": "読み込み中...",
@@ -266,8 +267,8 @@
"Select All": "すべて選択",
"Select a version": "バージョンを選択してください",
"Select additional devices to share this folder with.": "このフォルダの共有に追加したいデバイスがある場合は、当該デバイスを選択してください。",
"Select latest version": "Select latest version",
"Select oldest version": "Select oldest version",
"Select latest version": "最も新しいバージョンを選択",
"Select oldest version": "最も古いバージョンを選択",
"Select the devices to share this folder with.": "このフォルダーを共有するデバイスを選択してください。",
"Select the folders to share with this device.": "このデバイスと共有するフォルダーを選択してください。",
"Send & Receive": "送受信",
@@ -348,6 +349,7 @@
"Time the item was last modified": "Time the item was last modified",
"Trash Can File Versioning": "ゴミ箱によるバージョン管理",
"Type": "タイプ",
"UNIX Permissions": "UNIX Permissions",
"Unavailable": "Unavailable",
"Unavailable/Disabled by administrator or maintainer": "Unavailable/Disabled by administrator or maintainer",
"Undecided (will prompt)": "未決定(再確認する)",
@@ -372,7 +374,9 @@
"Versions": "バージョン",
"Versions Path": "古いバージョンを保存するパス",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "古いバージョンは、最大保存日数もしくは期間ごとの最大保存数を超えた場合、自動的に削除されます。",
"Waiting to scan": "Waiting to scan",
"Waiting to Scan": "スキャンの待機中",
"Waiting to Sync": "同期の待機中",
"Waiting to scan": "スキャンの待機中",
"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}}」のサブディレクトリです。",

View File

@@ -106,6 +106,7 @@
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "주소 자동 검색을 하기 위해서는 \"ip:port\" 형식의 주소들을 쉼표로 구분해서 입력하거나 \"dynamic\"을 입력하세요.",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.",
"Enter ignore patterns, one per line.": "무시할 패턴을 한 줄에 하나씩 입력하세요.",
"Enter up to three octal digits.": "Enter up to three octal digits.",
"Error": "오류",
"External File Versioning": "외부 파일 버전 관리",
"Failed Items": "실패한 항목",
@@ -348,6 +349,7 @@
"Time the item was last modified": "항목이 마지막으로 수정 된 시간",
"Trash Can File Versioning": "휴지통을 통한 파일 버전 관리",
"Type": "종류",
"UNIX Permissions": "UNIX Permissions",
"Unavailable": "불가능",
"Unavailable/Disabled by administrator or maintainer": "운영자 또는 관리자에 의해 불가능/비활성화 됨",
"Undecided (will prompt)": "Undecided (will prompt)",
@@ -372,6 +374,8 @@
"Versions": "버전",
"Versions Path": "버전 저장 경로",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "최대 보존 기간보다 오래되었거나 지정한 개수를 넘긴 버전은 자동으로 삭제됩니다.",
"Waiting to Scan": "Waiting to Scan",
"Waiting to Sync": "Waiting to Sync",
"Waiting to scan": "Waiting to scan",
"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}}) 의 상위 폴더 입니다.",

View File

@@ -66,7 +66,7 @@
"Default Folder Path": "Numatytojo aplanko kelias",
"Deleted": "Ištrinta",
"Deselect All": "Nuimti žymėjimą nuo visų",
"Deselect devices to stop sharing this folder with.": "Deselect devices to stop sharing this folder with.",
"Deselect devices to stop sharing this folder with.": "Panaikinti įrenginių pasirinkimą, kad su jais būtų nustota bendrinti šį aplanką. ",
"Device": "Įrenginys",
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "Įrenginys \"{{name}}\" ({{device}} {{address}}) nori prisijungti. Pridėti naują įrenginį?",
"Device ID": "Įrenginio ID",
@@ -106,6 +106,7 @@
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Įveskite kableliais atskirtus (\"tcp://ip:prievadas\", \"tcp://serveris:prievadas\") adresus arba \"dynamic\", kad atliktumėte automatinį adresų aptikimą.",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Įveskite kableliais atskirtus (\"tcp://ip:prievadas\", \"tcp://serveris:prievadas\") adresus arba \"dynamic\", kad atliktumėte automatinį adresų atlikimą.",
"Enter ignore patterns, one per line.": "Suveskite nepaisomus šablonus, kiekvieną naujoje eilutėje.",
"Enter up to three octal digits.": "Įveskite iki trijų aštuntainių skaitmenų.",
"Error": "Klaida",
"External File Versioning": "Išorinis versijų valdymas",
"Failed Items": "Nepavykę siuntimai",
@@ -265,7 +266,7 @@
"See external versioning help for supported templated command line parameters.": "Palaikomiems šabloniniams komandų eilutės parametrams, žiūrėkite išorinį versijų valdymo žinyną.",
"Select All": "Žymėti visus",
"Select a version": "Pasirinkti versiją",
"Select additional devices to share this folder with.": "Select additional devices to share this folder with.",
"Select additional devices to share this folder with.": "Pasirinkti papildomus įrenginius, su kuriais bendrinti šį aplanką.",
"Select latest version": "Pasirinkti paskiausią versiją",
"Select oldest version": "Pasirinkti seniausią versiją",
"Select the devices to share this folder with.": "Pasirinkite įrenginius, su kuriais dalinsitės šį aplanką.",
@@ -348,13 +349,14 @@
"Time the item was last modified": "Laikas, kai elementas buvo paskutinį kartą modifikuotas",
"Trash Can File Versioning": "Šiukšliadėžės versijų valdymas",
"Type": "Tipas",
"UNIX Permissions": "UNIX leidimai",
"Unavailable": "Neprieinama",
"Unavailable/Disabled by administrator or maintainer": "Neprieinama/Išjungta administratoriaus ar prižiūrėtojo",
"Undecided (will prompt)": "Nenuspręsta (bus klausiama)",
"Unignore": "Nustoti nepaisyti",
"Unknown": "Nežinoma",
"Unshared": "Nesidalinama",
"Unshared Devices": "Unshared Devices",
"Unshared Devices": "Nebedrinami įrenginiai",
"Unused": "Nenaudojamas",
"Up to Date": "Atnaujinta",
"Updated": "Atnaujinta",
@@ -372,6 +374,8 @@
"Versions": "Versijos",
"Versions Path": "Kelias iki versijos",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Versijos ištrinamos jei senesnės už nustatyta maksimalų amžių arba jei viršytas maksimalus failų skaičius per nustatytą laiko tarpą.",
"Waiting to Scan": "Laukiama nuskaityti",
"Waiting to Sync": "Laukiama sinchronizuoti",
"Waiting to scan": "Laukiama nuskaityti",
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Įspėjimas, šis kelias yra esamo aplanko \"{{otherFolder}}\" virškatalogis.",
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Įspėjimas, šis kelias yra esamo aplanko \"{{otherFolderLabel}}\" ({{otherFolder}}) virškatalogis.",

View File

@@ -106,6 +106,7 @@
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Skriv inn kommaseparerte (\"tcp://ip:port\", \"tcp://host:port\") adresser, eller ordet \"dynamic\" for å gjøre automatisk oppslag i adressen.",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.",
"Enter ignore patterns, one per line.": "Skriv inn mønster som skal utelates, ett per linje.",
"Enter up to three octal digits.": "Enter up to three octal digits.",
"Error": "Feilmelding",
"External File Versioning": "Ekstern versjonskontroll",
"Failed Items": "Elementsynkronisering som har mislyktes",
@@ -348,6 +349,7 @@
"Time the item was last modified": "Tidspunktet elementet sist ble endret",
"Trash Can File Versioning": "Papirkurv versjonskontroll",
"Type": "Type",
"UNIX Permissions": "UNIX Permissions",
"Unavailable": "Utilgjengelig",
"Unavailable/Disabled by administrator or maintainer": "Utilgjengelig/avskrudd av administrator eller vedlikeholder",
"Undecided (will prompt)": "Ikke bestemt (vil spørre)",
@@ -372,6 +374,8 @@
"Versions": "Versjoner",
"Versions Path": "Plassering av versjoner",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Versjoner blir automatisk slettet når maksimal levetid er nådd eller når antall filer er oversteget.",
"Waiting to Scan": "Venter på å starte gjennomsøkning",
"Waiting to Sync": "Waiting to Sync",
"Waiting to scan": "Venter på å starte gjennomsøkning",
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Advarsel, denne stien er en foreldremappe for en eksisterende mappe \"{{otherFolder}}\".",
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Advarsel, denne stien er en foreldremappe for en eksisterende mappe \"{{otherFolderLabel}}\" ({{otherFolder}}).",

View File

@@ -31,7 +31,7 @@
"Are you sure you want to remove device {%name%}?": "Weet u zeker dat u apparaat {{name}} wilt verwijderen?",
"Are you sure you want to remove folder {%label%}?": "Weet u zeker dat u map {{label}} wilt verwijderen?",
"Are you sure you want to restore {%count%} files?": "Weet u zeker dat u {{count}} bestanden wilt herstellen?",
"Are you sure you want to upgrade?": "Weet u zeker dat u wilt upgraden?",
"Are you sure you want to upgrade?": "Weet u zeker dat u wilt bijwerken?",
"Auto Accept": "Automatisch aanvaarden",
"Automatic Crash Reporting": "Automatische crashrapportage",
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Automatisch bijwerken biedt nu de keuze tussen stabiele releases en release canditates.",
@@ -106,6 +106,7 @@
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Voer door komma's gescheiden (\"tcp://ip:port\", \"tcp://host:port\") adressen in of \"dynamic\" om automatische ontdekking van het adres uit te voeren.",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Voer door komma's gescheiden (\"tcp://ip:port\", \"tcp://host:port\") adressen in of \"dynamic\" om automatische ontdekking van het adres uit te voeren.",
"Enter ignore patterns, one per line.": "Negeerpatronen invoeren, één per regel.",
"Enter up to three octal digits.": "Voer tot drie octale cijfers in.",
"Error": "Fout",
"External File Versioning": "Extern versiebeheer",
"Failed Items": "Mislukte items",
@@ -307,7 +308,7 @@
"Syncthing has been shut down.": "Syncthing werd afgesloten.",
"Syncthing includes the following software or portions thereof:": "Syncthing bevat de volgende software of delen daarvan:",
"Syncthing is Free and Open Source Software licensed as MPL v2.0.": "Syncthing is gratis en opensource software onder licentie van MPL v2.0.",
"Syncthing is restarting.": "Syncthing is aan het herstarten.",
"Syncthing is restarting.": "Syncthing wordt opnieuw gestart.",
"Syncthing is upgrading.": "Syncthing is aan het bijwerken.",
"Syncthing now supports automatically reporting crashes to the developers. This feature is enabled by default.": "Syncthing ondersteunt nu automatisch rapporteren van crashes naar de ontwikkelaars. De functie is standaard ingeschakeld.",
"Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…": "Syncthing lijkt gestopt te zijn, of er is een probleem met uw internetverbinding. Opnieuw proberen...",
@@ -348,6 +349,7 @@
"Time the item was last modified": "Tijdstip waarop het item laatst gewijzigd is",
"Trash Can File Versioning": "Versiebeheer prullenbak",
"Type": "Type",
"UNIX Permissions": "UNIX-machtigingen",
"Unavailable": "Niet beschikbaar",
"Unavailable/Disabled by administrator or maintainer": "Niet beschikbaar of uitgeschakeld door administrator of beheerder",
"Undecided (will prompt)": "Onbeslist (zal bevestiging vragen)",
@@ -372,6 +374,8 @@
"Versions": "Versies",
"Versions Path": "Pad voor versies",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Versies worden automatisch verwijderd als deze ouder zijn dan de maximale leeftijd of als ze het maximaal aantal toegestane bestanden in een interval overschrijden.",
"Waiting to Scan": "Wachten om te scannen",
"Waiting to Sync": "Wachten om te synchroniseren",
"Waiting to scan": "Wachten om te scannen",
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Waarschuwing, dit pad is een bovenliggende map van een bestaande map \"{{otherFolder}}\".",
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Waarschuwing, dit pad is een bovenliggende map van een bestaande map \"{{otherFolderLabel}}\" ({{otherFolder}}).",

View File

@@ -106,6 +106,7 @@
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Wpisz oddzielone przecinkiem adresy (\"tcp://ip:port\", \"tcp://host:port\") lub \"dynamic\" by przeprowadzić automatyczne odnalezienie adresu.",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Wprowadź adresy oddzielone przecinkiem (\"tcp://ip:port\", \"tcp://host:port\") lub \"dynamic\" celem automatycznego odkrycia adresu.",
"Enter ignore patterns, one per line.": "Wprowadź wzorce ignorowania, jeden w każdej linii.",
"Enter up to three octal digits.": "Enter up to three octal digits.",
"Error": "Błąd",
"External File Versioning": "Zewnętrzne wersjonowanie pliku",
"Failed Items": "Niepowodzenia",
@@ -348,6 +349,7 @@
"Time the item was last modified": "Czas ostatniej modyfikacji elementu",
"Trash Can File Versioning": "Kontrola werjsi plików w koszu",
"Type": "Typ",
"UNIX Permissions": "UNIX Permissions",
"Unavailable": "Niedostępne",
"Unavailable/Disabled by administrator or maintainer": "Niedostępne/Wyłączone przez administratora lub opiekuna",
"Undecided (will prompt)": "Jeszcze nie zdecydowałem (przypomnij później)",
@@ -372,6 +374,8 @@
"Versions": "Wersje",
"Versions Path": "Ścieżka wersji",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Wersje zostają automatycznie usunięte jeżeli są starsze niż maksymalny wiek lub przekraczają liczbę dopuszczalnych wersji.",
"Waiting to Scan": "Waiting to Scan",
"Waiting to Sync": "Waiting to Sync",
"Waiting to scan": "Oczekiwanie na skanowanie",
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Uwaga, ta ścieżka jest nadrzędnym folderem istniejącego folderu \"{{otherFolder}}\".",
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Uwaga, ten folder jest nadfolderem istniejącego folderu \"{{otherFolderLabel}}\" ({{otherFolder}}).",

View File

@@ -106,6 +106,7 @@
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Insira endereços (\"tcp://ip:porta\", \"tcp://host:porta\") separados por vírgula ou \"dynamic\" para executar a descoberta automática do endereço.",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.",
"Enter ignore patterns, one per line.": "Insira os filtros, um por linha.",
"Enter up to three octal digits.": "Enter up to three octal digits.",
"Error": "Erro",
"External File Versioning": "Externo",
"Failed Items": "Itens com falha",
@@ -348,6 +349,7 @@
"Time the item was last modified": "Momento em que o item foi modificado pela última vez",
"Trash Can File Versioning": "Lixeira",
"Type": "Tipo",
"UNIX Permissions": "UNIX Permissions",
"Unavailable": "Não disponível",
"Unavailable/Disabled by administrator or maintainer": "Não disponível ou desabilitado pelo administrador ou mantenedor",
"Undecided (will prompt)": "Não tenho certeza (perguntar sempre)",
@@ -372,6 +374,8 @@
"Versions": "Versões",
"Versions Path": "Caminho do versionamento",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "As versões são automaticamente apagadas se elas são mais antigas do que a idade máxima ou excederem o número de arquivos permitido em um intervalo.",
"Waiting to Scan": "Waiting to Scan",
"Waiting to Sync": "Waiting to Sync",
"Waiting to scan": "Waiting to scan",
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Aviso: este caminho é o diretório pai da pasta \"{{otherFolder}}\".",
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Aviso: este caminho é o diretório pai da pasta \"{{otherFolderLabel}}\" ({{otherFolder}}).",

View File

@@ -106,6 +106,7 @@
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Introduza endereços separados por vírgulas (\"tcp://ip:porto\", \"tcp://máquina:porto\") ou \"dynamic\" para detectar automaticamente os endereços.",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Introduza endereços separados por vírgulas (\"tcp://ip:porto\", \"tcp://máquina:porto\") ou \"dynamic\" para detectar automaticamente os endereços.",
"Enter ignore patterns, one per line.": "Escreva os padrões de exclusão, um por linha.",
"Enter up to three octal digits.": "Insira de um a três dígitos em octal.",
"Error": "Erro",
"External File Versioning": "Externa",
"Failed Items": "Itens que falharam",
@@ -348,6 +349,7 @@
"Time the item was last modified": "Quando o item foi modificado pela última vez",
"Trash Can File Versioning": "Reciclagem",
"Type": "Tipo",
"UNIX Permissions": "Permissões UNIX",
"Unavailable": "Indisponível",
"Unavailable/Disabled by administrator or maintainer": "Indisponíveis ou desactivadas pelo administrador ou responsável de manutenção",
"Undecided (will prompt)": "Não definido (será inquirido na altura)",
@@ -372,6 +374,8 @@
"Versions": "Versões",
"Versions Path": "Caminho das versões",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "As versões são eliminadas automaticamente se forem mais antigas do que a idade máxima ou excederem o número máximo de ficheiros permitido num intervalo.",
"Waiting to Scan": "À espera para verificar",
"Waiting to Sync": "À espera para sincronizar",
"Waiting to scan": "À espera para verificar",
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Aviso: Este caminho é uma pasta mãe duma pasta \"{{otherFolder}}\" já existente.",
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Aviso: Este caminho é uma pasta mãe duma pasta \"{{otherFolderLabel}}\" ({{otherFolder}}) já existente.",

View File

@@ -106,6 +106,7 @@
"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 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.": "Введите шаблоны игнорирования, по одному на строку.",
"Enter up to three octal digits.": "Enter up to three octal digits.",
"Error": "Ошибка",
"External File Versioning": "Внешний контроль версий файлов",
"Failed Items": "Сбои",
@@ -348,6 +349,7 @@
"Time the item was last modified": "Время последней модификации объекта",
"Trash Can File Versioning": "Использовать версионность для файлов в Корзине",
"Type": "Тип",
"UNIX Permissions": "UNIX Permissions",
"Unavailable": "Недоступно",
"Unavailable/Disabled by administrator or maintainer": "Недоступно или отключено администратором",
"Undecided (will prompt)": "Не определено (запрашивать каждый раз)",
@@ -372,6 +374,8 @@
"Versions": "Версии",
"Versions Path": "Путь к версиям",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Версии удаляются автоматически, если они существуют дольше максимального срока или превышают разрешённое количество файлов за интервал.",
"Waiting to Scan": "Waiting to Scan",
"Waiting to Sync": "Waiting to Sync",
"Waiting to scan": "Ожидание сканирования",
"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}}).",

View File

@@ -106,6 +106,7 @@
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Zadaj čiarkou oddelené (\"tcp://ip:port\", \"tcp://host:port\") adresy alebo \"dynamic\" na automatické zistenie adresy.",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.",
"Enter ignore patterns, one per line.": "Zadaj ignorované vzory, jeden na riadok.",
"Enter up to three octal digits.": "Enter up to three octal digits.",
"Error": "Chyba",
"External File Versioning": "Externé spracovanie verzií súborov",
"Failed Items": "Zlyhané položky",
@@ -348,6 +349,7 @@
"Time the item was last modified": "Čas poslednej zmeny položky",
"Trash Can File Versioning": "Verzie súborov v koši",
"Type": "Typ",
"UNIX Permissions": "UNIX Permissions",
"Unavailable": "Nedostupné",
"Unavailable/Disabled by administrator or maintainer": "Nedostupné/Zakázané administrátorom alebo správcom",
"Undecided (will prompt)": "Undecided (will prompt)",
@@ -372,6 +374,8 @@
"Versions": "Verzie",
"Versions Path": "Cesta k verziám",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Verzie sú automaticky zmazané ak sú staršie ako je maximálny časový limit alebo presiahnu počet súborov povolených v danom intervale.",
"Waiting to Scan": "Waiting to Scan",
"Waiting to Sync": "Waiting to Sync",
"Waiting to scan": "Čaká na sken",
"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}}).",

View File

@@ -12,7 +12,7 @@
"Add Remote Device": "Lägg till fjärrenhet",
"Add devices from the introducer to our device list, for mutually shared folders.": "Lägg enheter från introduktören till vår enhetslista för ömsesidigt delade mappar.",
"Add new folder?": "Lägg till ny mapp?",
"Additionally the full rescan interval will be increased (times 60, i.e. new default of 1h). You can also configure it manually for every folder later after choosing No.": "Dessutom kommer det fullständiga återkommande uppdateringsintervallet att höjas (60 gånger, d.v.s. ny standard på 1h). Du kan också konfigurera det manuellt för varje mapp senare efter att du valt Nej.",
"Additionally the full rescan interval will be increased (times 60, i.e. new default of 1h). You can also configure it manually for every folder later after choosing No.": "Dessutom kommer det fullständiga återkommande skanningsintervallet att höjas (60 gånger, d.v.s. ny standard på 1h). Du kan också konfigurera det manuellt för varje mapp senare efter att du valt Nej.",
"Address": "Adress",
"Addresses": "Adresser",
"Advanced": "Avancerat",
@@ -31,7 +31,7 @@
"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}}?",
"Are you sure you want to restore {%count%} files?": "Är du säker på att du vill återställa {{count}} filer?",
"Are you sure you want to upgrade?": "Are you sure you want to upgrade?",
"Are you sure you want to upgrade?": "Är du säker på att du vill uppgradera?",
"Auto Accept": "Acceptera automatiskt",
"Automatic Crash Reporting": "Automatisk kraschrapportering",
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Automatisk uppgradering erbjuder nu valet mellan stabila utgåvor och utgåvskandidater.",
@@ -53,20 +53,20 @@
"Connection Error": "Anslutningsproblem",
"Connection Type": "Anslutningstyp",
"Connections": "Anslutningar",
"Continuously watching for changes is now available within Syncthing. This will detect changes on disk and issue a scan on only the modified paths. The benefits are that changes are propagated quicker and that less full scans are required.": "Kontinuerligt utkik efter ändringar är nu tillgängligt för Syncthing. Detta kommer att upptäcka ändringar på disken och utfärda en uppdatering på endast de ändrade sökvägarna. Fördelarna är att förändringar sprids snabbare och att mindre fullständiga uppdateringar krävs.",
"Continuously watching for changes is now available within Syncthing. This will detect changes on disk and issue a scan on only the modified paths. The benefits are that changes are propagated quicker and that less full scans are required.": "Kontinuerligt utkik efter ändringar är nu tillgängligt för Syncthing. Detta kommer att upptäcka ändringar på disken och utfärda en skanning på endast de ändrade sökvägarna. Fördelarna är att förändringar sprids snabbare och att mindre fullständiga skanningar krävs.",
"Copied from elsewhere": "Kopierat från annanstans",
"Copied from original": "Kopierat från original",
"Copyright © 2014-2016 the following Contributors:": "Copyright © 2014-2016 följande bidragare:",
"Copyright © 2014-2017 the following Contributors:": "Copyright © 2014-2017 följande bidragsgivare:",
"Copyright © 2014-2019 the following Contributors:": "Copyright © 2014-2019 följande bidragsgivare:",
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Skapa ignorera mönster, skriver över en existerande fil på {{path}}.",
"Currently Shared With Devices": "Currently Shared With Devices",
"Currently Shared With Devices": "För närvarande delas med enheter",
"Danger!": "Fara!",
"Debugging Facilities": "Felsökningsanläggningar",
"Default Folder Path": "Standard mappsökväg",
"Deleted": "Raderade",
"Deselect All": "Avmarkera alla",
"Deselect devices to stop sharing this folder with.": "Deselect devices to stop sharing this folder with.",
"Deselect devices to stop sharing this folder with.": "Avmarkera enheter för att sluta dela den här mappen med.",
"Device": "Enhet",
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "Enhet \"{{name}}\" ({{device}} på {{address}}) vill ansluta. Lägg till ny enhet?",
"Device ID": "Enhets-ID",
@@ -77,9 +77,9 @@
"Devices": "Enheter",
"Disable Crash Reporting": "Inaktivera kraschrapportering",
"Disabled": "Inaktiverad",
"Disabled periodic scanning and disabled watching for changes": "Inaktiverad periodisk uppdatering och inaktiverad spaning efter ändringar",
"Disabled periodic scanning and enabled watching for changes": "Inaktiverad periodisk uppdatering och aktiverad spaning efter ändringar",
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Inaktiverad periodisk uppdatering och misslyckad att ställa in spaning efter ändringar, försök igen varje 1m:",
"Disabled periodic scanning and disabled watching for changes": "Inaktiverad periodisk skanning och inaktiverad övervakning av ändringar",
"Disabled periodic scanning and enabled watching for changes": "Inaktiverad periodisk skanning och aktiverad övervakning av ändringar",
"Disabled periodic scanning and failed setting up watching for changes, retrying every 1m:": "Inaktiverad periodisk skanning och misslyckades att ställa in övervakning av ändringar, försök igen varje 1m:",
"Discard": "Kassera",
"Disconnected": "Frånkopplad",
"Discovered": "Upptäckt",
@@ -106,6 +106,7 @@
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Ange kommaseparerade (\"tcp://ip:port\", \"tcp://host:port\")-adresser eller ordet \"dynamic\" för att använda automatisk uppslagning.",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Ange kommaseparerade adresser (\"tcp://ip:port\", \"tcp://host:port\") eller \"dynamic\" för att utföra automatisk upptäckt av adressen.",
"Enter ignore patterns, one per line.": "Ange mönster att ignorera, en per rad.",
"Enter up to three octal digits.": "Ange upp till tre oktala siffror.",
"Error": "Fel",
"External File Versioning": "Extern filversionshantering",
"Failed Items": "Misslyckade objekt",
@@ -132,7 +133,7 @@
"Folder Type": "Mapptyp",
"Folders": "Mappar",
"For the following folders an error occurred while starting to watch for changes. It will be retried every minute, so the errors might go away soon. If they persist, try to fix the underlying issue and ask for help if you can't.": "För följande mappar uppstod ett fel när du började bevaka ändringar. Det kommer att omförsökas varje minut, så felen kan försvinna snart. Om de fortsätter, försök att åtgärda det underliggande problemet och fråga om hjälp om du inte kan.",
"Full Rescan Interval (s)": "Fullständig(a) återkommande uppdateringsintervall(er)",
"Full Rescan Interval (s)": "Fullständig(a) återkommande skanningsintervall(er)",
"GUI": "Grafiskt gränssnitt",
"GUI Authentication Password": "Gränssnittets autentiseringslösenord",
"GUI Authentication User": "Gränssnittets autentiseringsanvändare",
@@ -162,7 +163,7 @@
"Keep Versions": "Behåll versioner",
"Largest First": "Största först",
"Last File Received": "Senaste fil mottagen",
"Last Scan": "Senaste uppdatering",
"Last Scan": "Senaste skanning",
"Last seen": "Senast sedd",
"Later": "Senare",
"Latest Change": "Senaste ändring",
@@ -171,7 +172,7 @@
"Listeners": "Lyssnare",
"Loading data...": "Laddar data...",
"Loading...": "Laddar...",
"Local Additions": "Local Additions",
"Local Additions": "Lokala tillägg",
"Local Discovery": "Lokal annonsering",
"Local State": "Lokalt tillstånd",
"Local State (Total)": "Lokalt tillstånd (totalt)",
@@ -190,7 +191,7 @@
"Mod. Device": "Enhet som utförde ändring",
"Mod. Time": "Tid för ändring",
"Move to top of queue": "Flytta till överst i kön",
"Multi level wildcard (matches multiple directory levels)": "Jokertecken som representerar noll eller fler godtyckliga tecken, även över kataloggränser.",
"Multi level wildcard (matches multiple directory levels)": "Flernivå jokertecken (matchar flera mappnivåer)",
"Never": "Aldrig",
"New Device": "Ny enhet",
"New Folder": "Ny mapp",
@@ -213,22 +214,22 @@
"Path": "Sökväg",
"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": "Sökväg till mappen på din dator. Kommer att skapas om det inte finns. Tecknet tilde (~) kan användas som en genväg för",
"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%}.": "Sökvägen där nya automatiskt accepterade mappar kommer att skapas, liksom den föreslagna sökvägen när du lägger till nya mappar via gränssnittet. Tecknet tilde (~) expanderar till {{tilde}}.",
"Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).": "Sökväg där versioner ska lagras (lämna tomt för standard .stversions-mappen i den delade katalogen).",
"Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).": "Sökväg där versioner ska lagras (lämna tomt för standard .stversions-mappen i den delade mappen).",
"Path where versions should be stored (leave empty for the default .stversions folder in the folder).": "Sökväg där versioner sparas (lämna tomt för att använda standard .stversions-mappen i mappen).",
"Pause": "Paus",
"Pause": "Pausa",
"Pause All": "Pausa alla",
"Paused": "Pausad",
"Pending changes": "Väntar på ändringar",
"Periodic scanning at given interval and disabled watching for changes": "Periodisk uppdatering i givet intervall och inaktiverad spaning efter ändringar",
"Periodic scanning at given interval and enabled watching for changes": "Periodisk uppdatering i givet intervall och aktiverad spaning efter ändringar",
"Periodic scanning at given interval and failed setting up watching for changes, retrying every 1m:": "Periodisk uppdatering i givet intervall och misslyckades med att ställa in utkik efter ändringar, försök igen var 1m:",
"Periodic scanning at given interval and disabled watching for changes": "Periodisk skanning i givet intervall och inaktiverad övervakning av ändringar",
"Periodic scanning at given interval and enabled watching for changes": "Periodisk skanning i givet intervall och aktiverad övervakning av ändringar",
"Periodic scanning at given interval and failed setting up watching for changes, retrying every 1m:": "Periodisk skanning i givet intervall och misslyckades med att ställa in utkik efter ändringar, försök igen var 1m:",
"Permissions": "Behörigheter",
"Please consult the release notes before performing a major upgrade.": "Läs igenom versionsnyheterna innan den stora uppgraderingen.",
"Please set a GUI Authentication User and Password in the Settings dialog.": "Ställ in ett grafiska gränssnittets användarautentisering och lösenord i inställningsdialogrutan.",
"Please wait": "Var god vänta",
"Prefix indicating that the file can be deleted if preventing directory removal": "Prefix som indikerar att filen kan raderas om det förhindrar radering av katalog",
"Prefix indicating that the file can be deleted if preventing directory removal": "Prefix som indikerar att filen kan tas bort om det förhindrar mappborttagning",
"Prefix indicating that the pattern should be matched without case sensitivity": "Prefix som indikerar att mönstret ska matchas utan skiftlägeskänslighet",
"Preparing to Sync": "Preparing to Sync",
"Preparing to Sync": "Förberedelser för synkronisering",
"Preview": "Förhandsgranska",
"Preview Usage Report": "Förhandsgranska statistik",
"Quick guide to supported patterns": "Snabb handledning till mönster som stöds",
@@ -244,10 +245,10 @@
"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": "Uppdatera igen",
"Rescan All": "Uppdatera alla igen",
"Rescan Interval": "Återkommande uppdateringsintervall",
"Rescans": "Återkommande uppdateringar",
"Rescan": "Skanna igen",
"Rescan All": "Skanna alla igen",
"Rescan Interval": "Återkommande skanningsintervall",
"Rescans": "Återkommande skanningar",
"Restart": "Starta om",
"Restart Needed": "Omstart behövs",
"Restarting": "Startar om",
@@ -259,13 +260,13 @@
"Revert Local Changes": "Återställ lokala ändringar",
"Running": "Körs",
"Save": "Spara",
"Scan Time Remaining": "Återstående uppdateringstid",
"Scanning": "Uppdaterar",
"Scan Time Remaining": "Återstående skanningstid",
"Scanning": "Skannar",
"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 All": "Markera alla",
"Select a version": "Välj en version",
"Select additional devices to share this folder with.": "Select additional devices to share this folder with.",
"Select additional devices to share this folder with.": "Välj ytterligare enheter för att dela den här mappen med.",
"Select latest version": "Välj senaste versionen",
"Select oldest version": "Välj äldsta versionen",
"Select the devices to share this folder with.": "Ange enheterna som den här mappen ska delas med.",
@@ -321,7 +322,7 @@
"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).": "Enhets-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 enhets-ID:t 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 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 mappen.",
"The folder ID cannot be blank.": "Mapp-ID får inte vara tomt.",
"The folder ID must be unique.": "Mapp-ID måste vara unik.",
"The folder path cannot be blank.": "Mappsökvägen kan inte vara tom.",
@@ -338,7 +339,7 @@
"The path cannot be blank.": "Sökvägen kan inte vara tom.",
"The rate limit must be a non-negative number (0: no limit)": "Frekvensgränsen måste vara ett icke-negativt tal (0: ingen gräns)",
"The rescan interval must be a non-negative number of seconds.": "Förnyelseintervallet måste vara ett positivt antal sekunder",
"There are no devices to share this folder with.": "There are no devices to share this folder with.",
"There are no devices to share this folder with.": "Det finns inga enheter att dela den här mappen med.",
"They are retried automatically and will be synced when the error is resolved.": "De omprövas automatiskt och kommer att synkroniseras när felet är löst.",
"This Device": "Denna enhet",
"This can easily give hackers access to read and change any files on your computer.": "Detta kan lätt ge hackare tillgång till att läsa och ändra några filer på datorn.",
@@ -348,13 +349,14 @@
"Time the item was last modified": "Tidpunkten objektet var senast ändrad",
"Trash Can File Versioning": "Papperskorgs filversionshantering",
"Type": "Typ",
"UNIX Permissions": "UNIX-behörigheter",
"Unavailable": "Inte tillgänglig",
"Unavailable/Disabled by administrator or maintainer": "Inte tillgänglig/inaktiverad av administratör eller underhållare",
"Undecided (will prompt)": "Obeslutad (kommer att skriva)",
"Unignore": "Sluta ignorera",
"Unknown": "Okänd",
"Unshared": "Inte delad",
"Unshared Devices": "Unshared Devices",
"Unshared Devices": "Odelade enheter",
"Unused": "Oanvänd",
"Up to Date": "Uppdaterad",
"Updated": "Uppdaterade",
@@ -372,15 +374,17 @@
"Versions": "Versioner",
"Versions Path": "Sökväg för versioner",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Versioner raderas automatiskt när de är äldre än den maximala åldersgränsen eller överstiger frekvensen i intervallet.",
"Waiting to scan": "Väntar på uppdatering",
"Waiting to Scan": "Väntar på att skanna",
"Waiting to Sync": "Väntar på att synkronisera",
"Waiting to scan": "Väntar på att skanna",
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Varning, denna sökväg är en överordnad mapp av en befintlig mapp \"{{otherFolder}}\".",
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Varning, denna sökväg är en överordnad mapp av en befintlig mapp \"{{otherFolderLabel}}\" ({{otherFolder}}).",
"Warning, this path is a subdirectory of an existing folder \"{%otherFolder%}\".": "Varning, denna sökväg är en underkatalog till en befintlig mapp \"{{otherFolder}}\".",
"Warning, this path is a subdirectory of an existing folder \"{%otherFolder%}\".": "Varning, denna sökväg är en undermapp till en befintlig mapp \"{{otherFolder}}\".",
"Warning, this path is a subdirectory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Varning, denna sökväg är en undermapp av en befintlig mapp \"{{otherFolderLabel}}\" ({{otherFolder}}).",
"Warning: If you are using an external watcher like {%syncthingInotify%}, you should make sure it is deactivated.": "Varning: Om du använder en extern bevakare som {{syncthingInotify}}, bör du se till att den är inaktiverad.",
"Watch for Changes": "Håll utkik efter ändringar",
"Watching for Changes": "Håller utkik efter ändringar",
"Watching for changes discovers most changes without periodic scanning.": "Hålla utkik efter ändringar upptäcker de flesta förändringar utan periodisk uppdatering.",
"Watching for changes discovers most changes without periodic scanning.": "Hålla utkik efter ändringar upptäcker de flesta förändringar utan periodisk skanning.",
"When adding a new device, keep in mind that this device must be added on the other side too.": "När du lägger till en ny enhet, kom ihåg att den här enheten måste läggas till på den andra enheten också.",
"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.": "När du lägger till ny mapp, tänk på att mapp-ID knyter ihop mappar mellan olika enheter. De skiftlägeskänsliga och måste matcha precis mellan alla enheter.",
"Yes": "Ja",
@@ -392,7 +396,7 @@
"You have unsaved changes. Do you really want to discard them?": "Du har ändringar som inte sparats. Vill du verkligen kassera dem?",
"You must keep at least one version.": "Du måste behålla åtminstone en version.",
"days": "dagar",
"directories": "kataloger",
"directories": "mappar",
"files": "filer",
"full documentation": "fullständig dokumentation",
"items": "objekt",

View File

@@ -106,6 +106,7 @@
"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 comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.",
"Enter ignore patterns, one per line.": "Введіть шаблони ігнорування, по одному на рядок.",
"Enter up to three octal digits.": "Enter up to three octal digits.",
"Error": "Помилка",
"External File Versioning": "Зовнішне керування версіями",
"Failed Items": "Невдалі",
@@ -348,6 +349,7 @@
"Time the item was last modified": "Час останньої зміни елемента:",
"Trash Can File Versioning": "Версіонування файлів у кошику ",
"Type": "Тип",
"UNIX Permissions": "UNIX Permissions",
"Unavailable": "Недоступно",
"Unavailable/Disabled by administrator or maintainer": "Недоступно/заборонено адміністратором або куратором",
"Undecided (will prompt)": "Невизначено (буде запитано)",
@@ -372,6 +374,8 @@
"Versions": "Версії",
"Versions Path": "Шлях до версій",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Версії автоматично видаляються, якщо вони старше, ніж максимальний вік, або перевищують допустиму кількість файлів за інтервал.",
"Waiting to Scan": "Waiting to Scan",
"Waiting to Sync": "Waiting to Sync",
"Waiting to scan": "Waiting to scan",
"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}}).",

View File

@@ -10,7 +10,7 @@
"Add Device": "添加设备",
"Add Folder": "添加文件夹",
"Add Remote Device": "添加远程设备",
"Add devices from the introducer to our device list, for mutually shared folders.": "将此新设备上拥有的“远程设备”都自动添加到您这边的“远程设备”列表中(如果它们跟您存在相同的文件夹的话)",
"Add devices from the introducer to our device list, for mutually shared folders.": "将这个设备上那些,跟本机有着共同文件夹的“远程设备”,都添加到本机的“远程设备”列表。",
"Add new folder?": "添加新文件夹?",
"Additionally the full rescan interval will be increased (times 60, i.e. new default of 1h). You can also configure it manually for every folder later after choosing No.": "另外,完整重新扫描的间隔将增大(时间 60以新的默认 1 小时为例)。你也可以在选择“否”后手动配置每个文件夹的时间。",
"Address": "地址",
@@ -27,17 +27,17 @@
"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.": "在中介设备上添加的任何“远程设备”,也会被自动添加到本机的“远程设备”列表。",
"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}} 吗?",
"Are you sure you want to restore {%count%} files?": "您确定要恢复这 {{count}} 个文件吗?",
"Are you sure you want to upgrade?": "Are you sure you want to upgrade?",
"Are you sure you want to upgrade?": "你确定要升级吗?",
"Auto Accept": "自动接受",
"Automatic Crash Reporting": "自动发送崩溃报告",
"Automatic upgrade now offers the choice between stable releases and release candidates.": "自动升级现在提供了稳定版本和候选发布版的选项。",
"Automatic upgrades": "自动升级",
"Automatic upgrades are always enabled for candidate releases.": "候选发布版会一直启用自动升级。",
"Automatically create or share folders that this device advertises at the default path.": "自动地创建或共享这个设备在默认路径通告的文件夹。",
"Automatically create or share folders that this device advertises at the default path.": "在本机默认文件夹中,自动地创建或共享这个设备共享出来的所有文件夹。",
"Available debug logging facilities:": "可用的调试日志功能:",
"Be careful!": "小心!",
"Bugs": "问题回报",
@@ -60,13 +60,13 @@
"Copyright © 2014-2017 the following Contributors:": "Copyright © 2014-2017 以下贡献者:",
"Copyright © 2014-2019 the following Contributors:": "版权所有 © 2014-2019 以下贡献者:",
"Creating ignore patterns, overwriting an existing file at {%path%}.": "正在创建忽略模式,覆盖位于 {{path}} 的已有文件。",
"Currently Shared With Devices": "Currently Shared With Devices",
"Currently Shared With Devices": "当前设备已共享",
"Danger!": "危险!",
"Debugging Facilities": "调试功能",
"Default Folder Path": "默认文件夹路径",
"Deleted": "已删除",
"Deselect All": "取消全选",
"Deselect devices to stop sharing this folder with.": "Deselect devices to stop sharing this folder with.",
"Deselect devices to stop sharing this folder with.": "反选设备以停止共享此文件夹",
"Device": "设备",
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "设备 \"{{name}}\"(位于 {{address}} 的 {{device}})请求连接。是否添加新设备?",
"Device ID": "设备 ID",
@@ -106,6 +106,7 @@
"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 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.": "请输入忽略模式,每行一条。",
"Enter up to three octal digits.": "最多输入三个8进制数字",
"Error": "错误",
"External File Versioning": "外部版本控制",
"Failed Items": "失败的项目",
@@ -119,7 +120,7 @@
"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.": "当某个文件在其他设备被替换或删除时,本设备将在 .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.": "在其它设备中对该文件夹内文件的修改并不会被同步到本机,但是在本机上对其的修改,则会被同步到其它设备。",
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "在其它设备中对该文件夹内文件的修改并不会被同步到本机,但是在本机上对其的修改,则会被同步到集群中的其它设备。",
"Files are synchronized from the cluster, but any changes made locally will not be sent to other devices.": "文件将从集群同步,但本地所作的任何更改都不会被发送到其他设备。",
"Filesystem Notifications": "文件系统通知",
"Filesystem Watcher Errors": "文件系统监视器错误",
@@ -171,7 +172,7 @@
"Listeners": "侦听程序",
"Loading data...": "正在载入数据…",
"Loading...": "正在载入…",
"Local Additions": "Local Additions",
"Local Additions": "从本地添加",
"Local Discovery": "本地发现",
"Local State": "本地状态",
"Local State (Total)": "本地状态汇总",
@@ -227,8 +228,8 @@
"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": "表示该模式匹配忽略了大小写差异的前缀",
"Preparing to Sync": "Preparing to Sync",
"Prefix indicating that the pattern should be matched without case sensitivity": "此前缀表示,后面的模式匹配时不区分大小写",
"Preparing to Sync": "准备同步",
"Preview": "预览",
"Preview Usage Report": "预览使用报告",
"Quick guide to supported patterns": "支持的通配符的简单教程:",
@@ -243,7 +244,7 @@
"Remove": "移除",
"Remove Device": "移除设备",
"Remove Folder": "移除文件夹",
"Required identifier for the folder. Must be the same on all cluster devices.": "需要给文件夹设置标识。所有设备上必须一致。",
"Required identifier for the folder. Must be the same on all cluster devices.": "必需的文件夹唯一标识。同一个文件夹在集群中的所有设备上ID必须相同。",
"Rescan": "重新扫描",
"Rescan All": "全部重新扫描",
"Rescan Interval": "扫描间隔",
@@ -265,7 +266,7 @@
"See external versioning help for supported templated command line parameters.": "有关受支持的模板命令行参数,请参阅外部版本控制帮助。",
"Select All": "全选",
"Select a version": "选择版本",
"Select additional devices to share this folder with.": "Select additional devices to share this folder with.",
"Select additional devices to share this folder with.": "选择其他共享此文件夹的设备",
"Select latest version": "选择最新的版本",
"Select oldest version": "选择最旧的版本",
"Select the devices to share this folder with.": "选择将本文件夹共享给哪些设备。",
@@ -283,8 +284,8 @@
"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。如果设置为空则会使用目标设备提供的默认名称。",
"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",
"Shutdown Complete": "关闭完成",
"Simple File Versioning": "简易版本控制",
@@ -338,7 +339,7 @@
"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.": "扫描间隔单位为秒,且不能为负数。",
"There are no devices to share this folder with.": "There are no devices to share this folder with.",
"There are no devices to share this folder with.": "没有设备共享此文件夹",
"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.": "这会让骇客能够轻而易举地访问及修改您的文件。",
@@ -348,13 +349,14 @@
"Time the item was last modified": "该项最近修改的时间",
"Trash Can File Versioning": "回收站式版本控制",
"Type": "类型",
"UNIX Permissions": "UNIX权限",
"Unavailable": "无效",
"Unavailable/Disabled by administrator or maintainer": "无效/禁用(由管理员或维护者)",
"Undecided (will prompt)": "待定(将提示)",
"Unignore": "解除忽略",
"Unknown": "未知",
"Unshared": "未共享",
"Unshared Devices": "Unshared Devices",
"Unshared Devices": "未共享设备",
"Unused": "未使用",
"Up to Date": "同步完成",
"Updated": "已更新",
@@ -372,6 +374,8 @@
"Versions": "历史版本",
"Versions Path": "历史版本路径",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "超过最长保留时间,或者不满足下列条件的历史版本,将会被删除。",
"Waiting to Scan": "等待扫描",
"Waiting to Sync": "等待同步",
"Waiting to scan": "等待扫描",
"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}})的上级目录。",
@@ -381,7 +385,7 @@
"Watch for Changes": "监视更改",
"Watching for Changes": "正在监视更改",
"Watching for changes discovers most changes without periodic scanning.": "对更改的监视无需定期扫描就可以发现大多数更改。",
"When adding a new device, keep in mind that this device must be added on the other side too.": "若您在本机添加新设备,记住您也必须在这个设备上添加本机。",
"When adding a new device, keep in mind that this device must be added on the other side too.": "若您在本机添加新设备,记住您也必须在这个设备上添加本机。",
"When adding a new folder, keep in mind that the Folder ID is used to tie folders together between devices. They are case sensitive and must match exactly between all devices.": "若你添加了新文件夹,记住文件夹 ID 是用以在不同设备间建立联系的。在不同设备间拥有相同 ID 的文件夹将会被同步。且文件夹 ID 区分大小写。",
"Yes": "是",
"You can also select one of these nearby devices:": "您也可以从这些附近的设备中选择:",

View File

@@ -106,6 +106,7 @@
"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 comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.",
"Enter ignore patterns, one per line.": "輸入忽略樣式,每行一種。",
"Enter up to three octal digits.": "Enter up to three octal digits.",
"Error": "錯誤",
"External File Versioning": "外部的檔案版本控制",
"Failed Items": "失敗的項目",
@@ -348,6 +349,7 @@
"Time the item was last modified": "前次修改時間",
"Trash Can File Versioning": "垃圾筒式檔案版本控制",
"Type": "類型",
"UNIX Permissions": "UNIX Permissions",
"Unavailable": "無法使用",
"Unavailable/Disabled by administrator or maintainer": "無法使用 / 被系統管理員或維護者停用",
"Undecided (will prompt)": "未決定(將會提示)",
@@ -372,6 +374,8 @@
"Versions": "版本",
"Versions Path": "歷史版本路徑",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "當檔案歷史版本的存留時間大於設定的最大值,或是其數量在一段時間內超出允許值時,則會被刪除。",
"Waiting to Scan": "Waiting to Scan",
"Waiting to Sync": "Waiting to Sync",
"Waiting to scan": "Waiting to scan",
"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}}) 的上級目錄。",

View File

@@ -313,7 +313,7 @@
<span ng-switch-when="paused"><span class="hidden-xs" translate>Paused</span><span class="visible-xs" aria-label="{{'Paused' | translate}}"><i class="fas fa-fw fa-pause"></i></span></span>
<span ng-switch-when="unknown"><span class="hidden-xs" translate>Unknown</span><span class="visible-xs" aria-label="{{'Unknown' | translate}}"><i class="fas fa-fw fa-question-circle"></i></span></span>
<span ng-switch-when="unshared"><span class="hidden-xs" translate>Unshared</span><span class="visible-xs" aria-label="{{'Unshared' | translate}}"><i class="fas fa-fw fa-unlink"></i></span></span>
<span ng-switch-when="scan-waiting"><span class="hidden-xs" translate>Waiting to scan</span><span class="visible-xs" aria-label="{{'Waiting to scan' | translate}}"><i class="fas fa-fw fa-hourglass-half"></i></span></span>
<span ng-switch-when="scan-waiting"><span class="hidden-xs" translate>Waiting to Scan</span><span class="visible-xs" aria-label="{{'Waiting to Scan' | translate}}"><i class="fas fa-fw fa-hourglass-half"></i></span></span>
<span ng-switch-when="stopped"><span class="hidden-xs" translate>Stopped</span><span class="visible-xs" aria-label="{{'Stopped' | translate}}"><i class="fas fa-fw fa-stop"></i></span></span>
<span ng-switch-when="scanning">
<span class="hidden-xs" translate>Scanning</span>
@@ -324,6 +324,10 @@
</span>
<span ng-switch-when="idle"><span class="hidden-xs" translate>Up to Date</span><span class="visible-xs" aria-label="{{'Up to Date' | translate}}"><i class="fas fa-fw fa-check"></i></span></span>
<span ng-switch-when="localadditions"><span class="hidden-xs" translate>Local Additions</span><span class="visible-xs" aria-label="{{'Local Additions' | translate}}"><i class="fas fa-fw fa-check"></i></span></span>
<span ng-switch-when="sync-waiting">
<span class="hidden-xs" translate>Waiting to Sync</span>
<span class="visible-xs" aria-label="{{'Waiting to Sync' | translate}}"><i class="fas fa-fw fa-hourglass-half"></i></span>
</span>
<span ng-switch-when="sync-preparing">
<span class="hidden-xs" translate>Preparing to Sync</span>
<span class="visible-xs" aria-label="{{'Preparing to Sync' | translate}}"><i class="fas fa-fw fa-hourglass-half"></i></span>
@@ -600,14 +604,6 @@
</span>
</td>
</tr>
<tr>
<th><span class="fas fa-fw fa-microchip"></span>&nbsp;<span translate>RAM Utilization</span></th>
<td class="text-right">{{system.sys | binary}}B</td>
</tr>
<tr>
<th><span class="fas fa-fw fa-tachometer-alt"></span>&nbsp;<span translate>CPU Utilization</span></th>
<td class="text-right">{{system.cpuPercent | alwaysNumber | percent}}</td>
</tr>
<tr>
<th><span class="fas fa-fw fa-sitemap"></span>&nbsp;<span translate>Listeners</span></th>
<td class="text-right">

View File

@@ -14,7 +14,7 @@
<p translate>Copyright &copy; 2014-2019 the following Contributors:</p>
<div class="row">
<div class="col-md-12" id="contributor-list">
Jakob Borg, Audrius Butkevicius, Simon Frei, Alexander Graf, Alexandre Viau, 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, Stefan Tatschner, Wulf Weich, dependabot-preview[bot], Aaron Bieber, Adam Piggott, Adel Qalieh, Alan Pope, Alessandro G., Aman Gupta, Andrew Dunham, Andrew Rabert, Andrey D, André Colomb, Antoine Lamielle, Aranjedeath, Arkadiusz Tymiński, Arthur Axel fREW Schmidt, Artur Zubilewicz, Aurélien Rainone, BAHADIR YILMAZ, Bart De Vries, Ben Curthoys, Ben Shepherd, Ben Sidhom, Benedikt Heine, Benedikt Morbach, Benno Fünfstück, Benny Ng, Boris Rybalkin, Brandon Philips, Brendan Long, Brian R. Becker, Carsten Hagemann, Cathryne Linenweaver, Cedric Staniewski, Chris Howie, Chris Joel, Chris Tonkinson, Colin Kennedy, Cromefire_, Cyprien Devillez, Dale Visser, Dan, Daniel Bergmann, Daniel Martí, Darshil Chanpura, David Rimmer, Denis A., Dennis Wilson, Dmitry Saveliev, Domenic Horner, Dominik Heidler, Elias Jarlebring, Elliot Huffman, Emil Hessman, Erik Meitner, Evgeny Kuznetsov, Federico Castagnini, Felix Ableitner, Felix Unterpaintner, Francois-Xavier Gsell, Frank Isemann, Gilli Sigurdsson, Graham Miln, Han Boetes, Harrison Jones, Heiko Zuerker, Hugo Locurcio, Iain Barnett, Ian Johnson, Ilya Brin, Iskander Sharipov, Jaakko Hannikainen, Jacek Szafarkiewicz, Jacob, Jake Peterson, James Patterson, Jaroslav Malec, Jaya Chithra, Jens Diemer, Jerry Jacobs, Jochen Voss, Johan Andersson, Johan Vromans, John Rinehart, Jonas Thelemann, Jonathan Cross, Jose Manuel Delicado, Jörg Thalheim, Kalle Laine, Karol Różycki, Keith Turner, Kelong Cong, Ken'ichi Kamada, Kevin Allen, Kevin White, Jr., Kurt Fitzner, Laurent Arnoud, Laurent Etiemble, Leo Arias, Liu Siyuan, Lord Landon Agahnim, Lukas Lihotzki, Majed Abdulaziz, Marc Laporte, Marc Pujol, Marcin Dziadus, Marcus Legendre, Mark Pulford, Mateusz Naściszewski, Mateusz Ż, Matic Potočnik, Matt Burke, Matt Robenolt, Matteo Ruina, Maurizio Tomasi, Max Schulze, MaximAL, Maxime Thirouin, Michael Jephcote, Michael Tilli, Mike Boone, MikeLund, Mingxuan Lin, Nicholas Rishel, Nico Stapelbroek, Nicolas Braud-Santoni, Niels Peter Roest, Nils Jakobi, Nitroretro, NoLooseEnds, Oliver Freyermuth, Otiel, Oyebanji Jacob Mayowa, Pablo, Pascal Jungblut, Paul Brit, Pawel Palenica, Paweł Rozlach, Peter Badida, Peter Dave Hello, Peter Hoeg, Peter Marquardt, Phil Davis, Phill Luby, Pier Paolo Ramon, Piotr Bejda, Pramodh KP, Richard Hartmann, Robert Carosi, Robin Schoonover, Roman Zaynetdinov, Ross Smith II, Ruslan Yevdokymov, Sacheendra Talluri, Scott Klupfel, Sly_tom_cat, Stefan Kuntz, Suhas Gundimeda, Taylor Khan, Thomas Hipp, Tim Abell, Tim Howes, Tobias Nygren, Tobias Tom, Tom Jakubowski, Tomas Cerveny, Tommy Thorn, Tully Robinson, Tyler Brazier, Unrud, Veeti Paananen, Victor Buinsky, Vil Brekin, Vladimir Rusinov, William A. Kennington III, Xavier O., Yannic A., andresvia, andyleap, boomsquared, chenrui, chucic, dependabot[bot], derekriemer, desbma, georgespatton, ghjklw, janost, jaseg, jelle van der Waa, klemens, marco-m, otbutz, perewa, rubenbe, wangguoliang, xjtdy888, 佛跳墙
Jakob Borg, Audrius Butkevicius, Simon Frei, Alexander Graf, Alexandre Viau, Anderson Mesquita, Antony Male, Ben Schulz, Caleb Callaway, Daniel Harte, Evgeny Kuznetsov, Lars K.W. Gohlke, Lode Hoste, Michael Ploujnikov, Nate Morrison, Philippe Schommers, Ryan Sullivan, Sergey Mishin, Stefan Tatschner, Wulf Weich, dependabot-preview[bot], Aaron Bieber, Adam Piggott, Adel Qalieh, Alan Pope, Alessandro G., Alex Xu, Aman Gupta, Andrew Dunham, Andrew Rabert, Andrey D, André Colomb, Anjan Momi, Antoine Lamielle, Aranjedeath, Arkadiusz Tymiński, Arthur Axel fREW Schmidt, Artur Zubilewicz, Aurélien Rainone, BAHADIR YILMAZ, Bart De Vries, Ben Curthoys, Ben Shepherd, Ben Sidhom, Benedikt Heine, Benedikt Morbach, Benno Fünfstück, Benny Ng, Boris Rybalkin, Brandon Philips, Brendan Long, Brian R. Becker, Carsten Hagemann, Cathryne Linenweaver, Cedric Staniewski, Chris Howie, Chris Joel, Chris Tonkinson, Colin Kennedy, Cromefire_, Cyprien Devillez, Dale Visser, Dan, Daniel Bergmann, Daniel Martí, Darshil Chanpura, David Rimmer, Denis A., Dennis Wilson, Dmitry Saveliev, Domenic Horner, Dominik Heidler, Elias Jarlebring, Elliot Huffman, Emil Hessman, Erik Meitner, Federico Castagnini, Felix Ableitner, Felix Unterpaintner, Francois-Xavier Gsell, Frank Isemann, Gilli Sigurdsson, Graham Miln, Han Boetes, Harrison Jones, Heiko Zuerker, Hugo Locurcio, Iain Barnett, Ian Johnson, Ilya Brin, Iskander Sharipov, Jaakko Hannikainen, Jacek Szafarkiewicz, Jacob, Jake Peterson, James Patterson, Jaroslav Malec, Jaya Chithra, Jens Diemer, Jerry Jacobs, Jochen Voss, Johan Andersson, Johan Vromans, John Rinehart, Jonas Thelemann, Jonathan Cross, Jose Manuel Delicado, Jörg Thalheim, Kalle Laine, Karol Różycki, Keith Turner, Kelong Cong, Ken'ichi Kamada, Kevin Allen, Kevin White, Jr., Kurt Fitzner, Laurent Arnoud, Laurent Etiemble, Leo Arias, Liu Siyuan, Lord Landon Agahnim, Lukas Lihotzki, Majed Abdulaziz, Marc Laporte, Marc Pujol, Marcin Dziadus, Marcus Legendre, Mark Pulford, Mateusz Naściszewski, Mateusz Ż, Matic Potočnik, Matt Burke, Matt Robenolt, Matteo Ruina, Maurizio Tomasi, Max Schulze, MaximAL, Maxime Thirouin, Michael Jephcote, Michael Tilli, Mike Boone, MikeLund, Mingxuan Lin, Nicholas Rishel, Nico Stapelbroek, Nicolas Braud-Santoni, Niels Peter Roest, Nils Jakobi, Nitroretro, NoLooseEnds, Oliver Freyermuth, Otiel, Oyebanji Jacob Mayowa, Pablo, Pascal Jungblut, Paul Brit, Pawel Palenica, Paweł Rozlach, Peter Badida, Peter Dave Hello, Peter Hoeg, Peter Marquardt, Phil Davis, Phill Luby, Pier Paolo Ramon, Piotr Bejda, Pramodh KP, Richard Hartmann, Robert Carosi, Robin Schoonover, Roman Zaynetdinov, Ross Smith II, Ruslan Yevdokymov, Sacheendra Talluri, Scott Klupfel, Simon Mwepu, Sly_tom_cat, Stefan Kuntz, Suhas Gundimeda, Taylor Khan, Thomas Hipp, Tim Abell, Tim Howes, Tobias Nygren, Tobias Tom, Tom Jakubowski, Tomasz Wilczyński, Tommy Thorn, Tully Robinson, Tyler Brazier, Tyler Kropp, Unrud, Veeti Paananen, Victor Buinsky, Vil Brekin, Vladimir Rusinov, William A. Kennington III, Xavier O., Yannic A., andresvia, andyleap, boomsquared, chenrui, chucic, dependabot[bot], derekriemer, desbma, georgespatton, ghjklw, janost, jaseg, jelle van der Waa, klemens, marco-m, otbutz, perewa, rubenbe, wangguoliang, xjtdy888, 佛跳墙
</div>
</div>
<hr />

View File

@@ -350,6 +350,9 @@ angular.module('syncthing.core')
var debouncedFuncs = {};
function refreshFolder(folder) {
if ($scope.folders[folder].paused) {
return;
}
var key = "refreshFolder" + folder;
if (!debouncedFuncs[key]) {
debouncedFuncs[key] = debounce(function () {
@@ -780,10 +783,6 @@ angular.module('syncthing.core')
};
$scope.folderStatus = function (folderCfg) {
if (typeof $scope.model[folderCfg.id] === 'undefined') {
return 'unknown';
}
if (folderCfg.paused) {
return 'paused';
}
@@ -791,7 +790,7 @@ angular.module('syncthing.core')
var folderInfo = $scope.model[folderCfg.id];
// after restart syncthing process state may be empty
if (!folderInfo.state) {
if (typeof folderInfo === 'undefined' || !folderInfo.state) {
return 'unknown';
}
@@ -838,7 +837,7 @@ angular.module('syncthing.core')
if (status === 'stopped' || status === 'outofsync' || status === 'error' || status === 'faileditems') {
return 'danger';
}
if (status === 'unshared' || status === 'scan-waiting') {
if (status === 'unshared' || status === 'scan-waiting' || status === 'sync-waiting') {
return 'warning';
}
@@ -2492,4 +2491,11 @@ angular.module('syncthing.core')
$scope.config.options.crashReportingEnabled = enabled;
$scope.saveConfig();
};
$scope.isUnixAddress = function (address) {
return address != null &&
(address.startsWith('/') ||
address.startsWith('unix://') ||
address.startsWith('unixs://'));
}
});

View File

@@ -1,4 +1,4 @@
<modal id="editDevice" status="default" icon="{{editingExisting ? 'fas fa-pencil-alt' : 'fas fa-desktop'}}" heading="{{editingExisting ? 'Edit Device' : 'Add Device' | translate}}" large="yes" closeable="yes">
<modal id="editDevice" status="default" icon="{{editingExisting ? 'fas fa-pencil-alt' : 'fas fa-desktop'}}" heading="{{editingExisting ? 'Edit Device' : 'Add Device' | translate}} {{currentDevice.name}}" large="yes" closeable="yes">
<div class="modal-body">
<form role="form" name="deviceEditor">
<ul class="nav nav-tabs" ng-init="loadFormIntoScope(deviceEditor)">

View File

@@ -1,4 +1,4 @@
<modal id="editFolder" status="default" icon="{{editingExisting ? 'fas fa-pencil-alt' : 'fas fa-folder'}}" heading="{{editingExisting ? 'Edit Folder' : 'Add Folder' | translate}}" large="yes" closeable="yes">
<modal id="editFolder" status="default" icon="{{editingExisting ? 'fas fa-pencil-alt' : 'fas fa-folder'}}" heading="{{editingExisting ? 'Edit Folder' : 'Add Folder' | translate}} ({{folderLabel(currentFolder.id)}})" large="yes" closeable="yes">
<div class="modal-body">
<form role="form" name="folderEditor">
<ul class="nav nav-tabs" ng-init="loadFormIntoScope(folderEditor)">

View File

@@ -1,4 +1,4 @@
<modal id="restoreVersions" status="default" icon="fas fa-undo" heading="{{'Restore Versions' | translate}}" large="yes" closeable="yes">
<modal id="restoreVersions" status="default" icon="fas fa-undo" heading="{{'Restore Versions' | translate}} ({{folderLabel(restoreVersions.folder)}})" large="yes" closeable="yes">
<div class="modal-body">
<span translate ng-if="!restoreVersions.versions && !restoreVersions.errors">Loading data...</span>
<div ng-if="restoreVersions.versions">

View File

@@ -172,6 +172,13 @@
</div>
</div>
<div class="col-md-6">
<div ng-if="isUnixAddress(tmpGUI.address)" class="form-group" ng-class="{'has-error': settingsEditor.UnixSocketPermissions.$invalid && settingsEditor.UnixSocketPermissions.$dirty}">
<label translate>UNIX Permissions</label>
<input id="UnixSocketPermissions" name="UnixSocketPermissions" class="form-control" type="text" ng-model="tmpGUI.unixSocketPermissions" ng-pattern="/^0?[0-7]{0,3}$/" />
<p class="help-block" ng-show="settingsEditor.UnixSocketPermissions.$invalid" translate>
Enter up to three octal digits.
</p>
</div>
</div>
</div>
</div>

1
lib/api/.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
/testdata/config/csrftokens.txt

View File

@@ -81,7 +81,6 @@ type service struct {
fss model.FolderSummaryService
urService *ur.Service
systemConfigMut sync.Mutex // serializes posts to /rest/system/config
cpu Rater
contr Controller
noUpgrade bool
tlsDefaultCommonName string
@@ -95,10 +94,6 @@ type service struct {
systemLog logger.Recorder
}
type Rater interface {
Rate() float64
}
type Controller interface {
ExitUpgrading()
Restart()
@@ -111,7 +106,7 @@ type Service interface {
WaitForStart() error
}
func New(id protocol.DeviceID, cfg config.Wrapper, assetDir, tlsDefaultCommonName string, m model.Model, defaultSub, diskSub events.BufferedSubscription, evLogger events.Logger, discoverer discover.CachingMux, connectionsService connections.Service, urService *ur.Service, fss model.FolderSummaryService, errors, systemLog logger.Recorder, cpu Rater, contr Controller, noUpgrade bool) Service {
func New(id protocol.DeviceID, cfg config.Wrapper, assetDir, tlsDefaultCommonName string, m model.Model, defaultSub, diskSub events.BufferedSubscription, evLogger events.Logger, discoverer discover.CachingMux, connectionsService connections.Service, urService *ur.Service, fss model.FolderSummaryService, errors, systemLog logger.Recorder, contr Controller, noUpgrade bool) Service {
s := &service{
id: id,
cfg: cfg,
@@ -130,7 +125,6 @@ func New(id protocol.DeviceID, cfg config.Wrapper, assetDir, tlsDefaultCommonNam
systemConfigMut: sync.NewMutex(),
guiErrors: errors,
systemLog: systemLog,
cpu: cpu,
contr: contr,
noUpgrade: noUpgrade,
tlsDefaultCommonName: tlsDefaultCommonName,
@@ -187,6 +181,15 @@ func (s *service) getListener(guiCfg config.GUIConfiguration) (net.Listener, err
return nil, err
}
if guiCfg.Network() == "unix" && guiCfg.UnixSocketPermissions() != 0 {
// We should error if this fails under the assumption that these permissions are
// required for operation.
err = os.Chmod(guiCfg.Address(), guiCfg.UnixSocketPermissions())
if err != nil {
return nil, err
}
}
listener := &tlsutil.DowngradingListener{
Listener: rawListener,
TLSConfig: tlsCfg,
@@ -743,15 +746,18 @@ func (s *service) getDBRemoteNeed(w http.ResponseWriter, r *http.Request) {
page, perpage := getPagingParams(qs)
if files, err := s.model.RemoteNeedFolderFiles(deviceID, folder, page, perpage); err != nil {
snap, err := s.model.DBSnapshot(folder)
if err != nil {
http.Error(w, err.Error(), http.StatusNotFound)
} else {
sendJSON(w, map[string]interface{}{
"files": toJsonFileInfoSlice(files),
"page": page,
"perpage": perpage,
})
return
}
defer snap.Release()
files := snap.RemoteNeedFolderFiles(deviceID, page, perpage)
sendJSON(w, map[string]interface{}{
"files": toJsonFileInfoSlice(files),
"page": page,
"perpage": perpage,
})
}
func (s *service) getDBLocalChanged(w http.ResponseWriter, r *http.Request) {
@@ -761,7 +767,13 @@ func (s *service) getDBLocalChanged(w http.ResponseWriter, r *http.Request) {
page, perpage := getPagingParams(qs)
files := s.model.LocalChangedFiles(folder, page, perpage)
snap, err := s.model.DBSnapshot(folder)
if err != nil {
http.Error(w, err.Error(), http.StatusNotFound)
return
}
defer snap.Release()
files := snap.LocalChangedFiles(page, perpage)
sendJSON(w, map[string]interface{}{
"files": toJsonFileInfoSlice(files),
@@ -933,9 +945,7 @@ func (s *service) getSystemStatus(w http.ResponseWriter, r *http.Request) {
res["connectionServiceStatus"] = s.connectionsService.ListenerStatus()
res["lastDialStatus"] = s.connectionsService.ConnectionStatus()
// cpuUsage.Rate() is in milliseconds per second, so dividing by ten
// gives us percent
res["cpuPercent"] = s.cpu.Rate() / 10 / float64(runtime.NumCPU())
res["cpuPercent"] = 0 // deprecated from API
res["pathSeparator"] = string(filepath.Separator)
res["urVersionMax"] = ur.Version
res["uptime"] = s.urService.UptimeS()
@@ -1048,7 +1058,7 @@ func (s *service) getSupportBundle(w http.ResponseWriter, r *http.Request) {
}
// Report Data as a JSON
if usageReportingData, err := json.MarshalIndent(s.urService.ReportData(), "", " "); err != nil {
if usageReportingData, err := json.MarshalIndent(s.urService.ReportData(context.TODO()), "", " "); err != nil {
l.Warnln("Support bundle: failed to create versionPlatform.json:", err)
} else {
files = append(files, fileEntry{name: "usage-reporting.json.txt", data: usageReportingData})
@@ -1133,7 +1143,7 @@ func (s *service) getReport(w http.ResponseWriter, r *http.Request) {
if val, _ := strconv.Atoi(r.URL.Query().Get("version")); val > 0 {
version = val
}
sendJSON(w, s.urService.ReportDataPreview(version))
sendJSON(w, s.urService.ReportDataPreview(context.TODO(), version))
}
func (s *service) getRandomString(w http.ResponseWriter, r *http.Request) {

View File

@@ -29,7 +29,6 @@ import (
"github.com/syncthing/syncthing/lib/events"
"github.com/syncthing/syncthing/lib/fs"
"github.com/syncthing/syncthing/lib/locations"
"github.com/syncthing/syncthing/lib/model"
"github.com/syncthing/syncthing/lib/protocol"
"github.com/syncthing/syncthing/lib/sync"
"github.com/syncthing/syncthing/lib/tlsutil"
@@ -108,7 +107,7 @@ func TestStopAfterBrokenConfig(t *testing.T) {
}
w := config.Wrap("/dev/null", cfg, events.NoopLogger)
srv := New(protocol.LocalDeviceID, w, "", "syncthing", nil, nil, nil, events.NoopLogger, nil, nil, nil, nil, nil, nil, nil, nil, false).(*service)
srv := New(protocol.LocalDeviceID, w, "", "syncthing", nil, nil, nil, events.NoopLogger, nil, nil, nil, nil, nil, nil, nil, false).(*service)
defer os.Remove(token)
srv.started = make(chan string)
@@ -523,13 +522,11 @@ func startHTTP(cfg *mockedConfig) (string, *suture.Supervisor, error) {
connections := new(mockedConnections)
errorLog := new(mockedLoggerRecorder)
systemLog := new(mockedLoggerRecorder)
cpu := new(mockedCPUService)
addrChan := make(chan string)
// Instantiate the API service
urService := ur.New(cfg, m, connections, false)
summaryService := model.NewFolderSummaryService(cfg, m, protocol.LocalDeviceID, events.NoopLogger)
svc := New(protocol.LocalDeviceID, cfg, assetDir, "syncthing", m, eventSub, diskEventSub, events.NoopLogger, discoverer, connections, urService, summaryService, errorLog, systemLog, cpu, nil, false).(*service)
svc := New(protocol.LocalDeviceID, cfg, assetDir, "syncthing", m, eventSub, diskEventSub, events.NoopLogger, discoverer, connections, urService, &mockedFolderSummaryService{}, errorLog, systemLog, nil, false).(*service)
defer os.Remove(token)
svc.started = addrChan
@@ -545,7 +542,7 @@ func startHTTP(cfg *mockedConfig) (string, *suture.Supervisor, error) {
tcpAddr, err := net.ResolveTCPAddr("tcp", addr)
if err != nil {
supervisor.Stop()
return "", nil, fmt.Errorf("Weird address from API service: %v", err)
return "", nil, fmt.Errorf("weird address from API service: %w", err)
}
host, _, _ := net.SplitHostPort(cfg.gui.RawAddress)
@@ -1028,7 +1025,7 @@ func TestEventMasks(t *testing.T) {
cfg := new(mockedConfig)
defSub := new(mockedEventSub)
diskSub := new(mockedEventSub)
svc := New(protocol.LocalDeviceID, cfg, "", "syncthing", nil, defSub, diskSub, events.NoopLogger, nil, nil, nil, nil, nil, nil, nil, nil, false).(*service)
svc := New(protocol.LocalDeviceID, cfg, "", "syncthing", nil, defSub, diskSub, events.NoopLogger, nil, nil, nil, nil, nil, nil, nil, false).(*service)
defer os.Remove(token)
if mask := svc.getEventMask(""); mask != DefaultEventMask {

View File

@@ -1,13 +0,0 @@
// 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 api
type mockedCPUService struct{}
func (*mockedCPUService) Rate() float64 {
return 42
}

View File

@@ -7,6 +7,7 @@
package api
import (
"context"
"time"
"github.com/syncthing/syncthing/lib/discover"
@@ -26,7 +27,7 @@ func (m *mockedCachingMux) Stop() {
// from events.Finder
func (m *mockedCachingMux) Lookup(deviceID protocol.DeviceID) (direct []string, err error) {
func (m *mockedCachingMux) Lookup(ctx context.Context, deviceID protocol.DeviceID) (direct []string, err error) {
return nil, nil
}

View File

@@ -36,12 +36,8 @@ func (m *mockedModel) NeedFolderFiles(folder string, page, perpage int) ([]db.Fi
return nil, nil, nil
}
func (m *mockedModel) RemoteNeedFolderFiles(device protocol.DeviceID, folder string, page, perpage int) ([]db.FileInfoTruncated, error) {
return nil, nil
}
func (m *mockedModel) NeedSize(folder string) db.Counts {
return db.Counts{}
func (m *mockedModel) FolderProgressBytesCompleted(_ string) int64 {
return 0
}
func (m *mockedModel) ConnectionStats() map[string]interface{} {
@@ -112,26 +108,6 @@ func (m *mockedModel) Connection(deviceID protocol.DeviceID) (connections.Connec
return nil, false
}
func (m *mockedModel) GlobalSize(folder string) db.Counts {
return db.Counts{}
}
func (m *mockedModel) LocalSize(folder string) db.Counts {
return db.Counts{}
}
func (m *mockedModel) ReceiveOnlyChangedSize(folder string) db.Counts {
return db.Counts{}
}
func (m *mockedModel) CurrentSequence(folder string) (int64, bool) {
return 0, false
}
func (m *mockedModel) RemoteSequence(folder string) (int64, bool) {
return 0, false
}
func (m *mockedModel) State(folder string) (string, time.Time, error) {
return "", time.Time{}, nil
}
@@ -148,10 +124,6 @@ func (m *mockedModel) WatchError(folder string) error {
return nil
}
func (m *mockedModel) LocalChangedFiles(folder string, page, perpage int) []db.FileInfoTruncated {
return nil
}
func (m *mockedModel) Serve() {}
func (m *mockedModel) Stop() {}
@@ -188,3 +160,19 @@ func (m *mockedModel) GetHello(protocol.DeviceID) protocol.HelloIntf {
}
func (m *mockedModel) StartDeadlockDetector(timeout time.Duration) {}
func (m *mockedModel) DBSnapshot(_ string) (*db.Snapshot, error) {
return nil, nil
}
type mockedFolderSummaryService struct{}
func (m *mockedFolderSummaryService) Serve() {}
func (m *mockedFolderSummaryService) Stop() {}
func (m *mockedFolderSummaryService) Summary(folder string) (map[string]interface{}, error) {
return map[string]interface{}{"mocked": true}, nil
}
func (m *mockedFolderSummaryService) OnEventRequest() {}

View File

@@ -44,17 +44,29 @@ func writeBroadcasts(ctx context.Context, inbox <-chan []byte, port int) error {
return nil
}
addrs, err := net.InterfaceAddrs()
intfs, err := net.Interfaces()
if err != nil {
l.Debugln(err)
return err
}
var dsts []net.IP
for _, addr := range addrs {
if iaddr, ok := addr.(*net.IPNet); ok && len(iaddr.IP) >= 4 && iaddr.IP.IsGlobalUnicast() && iaddr.IP.To4() != nil {
baddr := bcast(iaddr)
dsts = append(dsts, baddr.IP)
for _, intf := range intfs {
if intf.Flags&net.FlagBroadcast == 0 {
continue
}
addrs, err := intf.Addrs()
if err != nil {
l.Debugln(err)
return err
}
for _, addr := range addrs {
if iaddr, ok := addr.(*net.IPNet); ok && len(iaddr.IP) >= 4 && iaddr.IP.IsGlobalUnicast() && iaddr.IP.To4() != nil {
baddr := bcast(iaddr)
dsts = append(dsts, baddr.IP)
}
}
}

View File

@@ -67,6 +67,10 @@ func writeMulticasts(ctx context.Context, inbox <-chan []byte, addr string) erro
success := 0
for _, intf := range intfs {
if intf.Flags&net.FlagMulticast == 0 {
continue
}
wcm.IfIndex = intf.Index
pconn.SetWriteDeadline(time.Now().Add(time.Second))
_, err = pconn.WriteTo(bs, wcm, gaddr)

View File

@@ -31,7 +31,7 @@ import (
const (
OldestHandledVersion = 10
CurrentVersion = 29
CurrentVersion = 30
MaxRescanIntervalS = 365 * 24 * 60 * 60
)
@@ -295,11 +295,11 @@ func (cfg *Configuration) clean() error {
}
if folder.Path == "" {
return fmt.Errorf("folder %q: %v", folder.ID, errFolderPathEmpty)
return fmt.Errorf("folder %q: %w", folder.ID, errFolderPathEmpty)
}
if _, ok := existingFolders[folder.ID]; ok {
return fmt.Errorf("folder %q: %v", folder.ID, errFolderIDDuplicate)
return fmt.Errorf("folder %q: %w", folder.ID, errFolderIDDuplicate)
}
existingFolders[folder.ID] = folder

View File

@@ -86,8 +86,13 @@ func TestDefaultValues(t *testing.T) {
func TestDeviceConfig(t *testing.T) {
for i := OldestHandledVersion; i <= CurrentVersion; i++ {
cfgFile := fmt.Sprintf("testdata/v%d.xml", i)
if _, err := os.Stat(cfgFile); os.IsNotExist(err) {
continue
}
os.RemoveAll(filepath.Join("testdata", DefaultMarkerName))
wr, err := load(fmt.Sprintf("testdata/v%d.xml", i), device1)
wr, err := load(cfgFile, device1)
if err != nil {
t.Fatal(err)
}
@@ -1127,6 +1132,27 @@ func TestRemoveDeviceWithEmptyID(t *testing.T) {
}
}
func TestMaxConcurrentFolders(t *testing.T) {
cases := []struct {
input int
output int
}{
{input: -42, output: 0},
{input: -1, output: 0},
{input: 0, output: runtime.GOMAXPROCS(-1)},
{input: 1, output: 1},
{input: 42, output: 42},
}
for _, tc := range cases {
opts := OptionsConfiguration{RawMaxFolderConcurrency: tc.input}
res := opts.MaxFolderConcurrency()
if res != tc.output {
t.Errorf("Wrong MaxFolderConcurrency, %d => %d, expected %d", tc.input, res, tc.output)
}
}
}
// defaultConfigAsMap returns a valid default config as a JSON-decoded
// map[string]interface{}. This is useful to override random elements and
// re-encode into JSON.

View File

@@ -23,7 +23,7 @@ import (
var (
ErrPathNotDirectory = errors.New("folder path not a directory")
ErrPathMissing = errors.New("folder path missing")
ErrMarkerMissing = errors.New("folder marker missing")
ErrMarkerMissing = errors.New("folder marker missing (this indicates potential data loss, search docs/forum to get information about how to proceed)")
)
const DefaultMarkerName = ".stfolder"

View File

@@ -9,12 +9,14 @@ package config
import (
"net/url"
"os"
"strconv"
"strings"
)
type GUIConfiguration struct {
Enabled bool `xml:"enabled,attr" json:"enabled" default:"true"`
RawAddress string `xml:"address" json:"address" default:"127.0.0.1:8384"`
RawUnixSocketPermissions string `xml:"unixSocketPermissions,omitempty" json:"unixSocketPermissions"`
User string `xml:"user,omitempty" json:"user"`
Password string `xml:"password,omitempty" json:"password"`
AuthMode AuthMode `xml:"authMode,omitempty" json:"authMode"`
@@ -59,6 +61,15 @@ func (c GUIConfiguration) Address() string {
return c.RawAddress
}
func (c GUIConfiguration) UnixSocketPermissions() os.FileMode {
perm, err := strconv.ParseUint(c.RawUnixSocketPermissions, 8, 32)
if err != nil {
// ignore incorrectly formatted permissions
return 0
}
return os.FileMode(perm) & os.ModePerm
}
func (c GUIConfiguration) Network() string {
if override := os.Getenv("STGUIADDRESS"); strings.Contains(override, "/") {
url, err := url.Parse(override)

View File

@@ -7,7 +7,7 @@
package config
type LDAPConfiguration struct {
Address string `xml:"address,omitempty" json:"addresd"`
Address string `xml:"address,omitempty" json:"address"`
BindDN string `xml:"bindDN,omitempty" json:"bindDN"`
Transport LDAPTransport `xml:"transport,omitempty" json:"transport"`
InsecureSkipVerify bool `xml:"insecureSkipVerify,omitempty" json:"insecureSkipVerify" default:"false"`

View File

@@ -25,6 +25,7 @@ import (
// update the config version. The order of migrations doesn't matter here,
// put the newest on top for readability.
var migrations = migrationSet{
{30, migrateToConfigV30},
{29, migrateToConfigV29},
{28, migrateToConfigV28},
{27, migrateToConfigV27},
@@ -84,6 +85,13 @@ func (m migration) apply(cfg *Configuration) {
cfg.Version = m.targetVersion
}
func migrateToConfigV30(cfg *Configuration) {
// The "max concurrent scans" option is now spelled "max folder concurrency"
// to be more general.
cfg.Options.RawMaxFolderConcurrency = cfg.Options.DeprecatedMaxConcurrentScans
cfg.Options.DeprecatedMaxConcurrentScans = 0
}
func migrateToConfigV29(cfg *Configuration) {
// The new crash reporting option should follow the state of global
// discovery / usage reporting, and we should display an appropriate

View File

@@ -8,7 +8,9 @@ package config
import (
"fmt"
"runtime"
"github.com/syncthing/syncthing/lib/protocol"
"github.com/syncthing/syncthing/lib/rand"
"github.com/syncthing/syncthing/lib/util"
)
@@ -52,13 +54,14 @@ type OptionsConfiguration struct {
TrafficClass int `xml:"trafficClass" json:"trafficClass"`
DefaultFolderPath string `xml:"defaultFolderPath" json:"defaultFolderPath" default:"~"`
SetLowPriority bool `xml:"setLowPriority" json:"setLowPriority" default:"true"`
MaxConcurrentScans int `xml:"maxConcurrentScans" json:"maxConcurrentScans"`
RawMaxFolderConcurrency int `xml:"maxFolderConcurrency" json:"maxFolderConcurrency"`
CRURL string `xml:"crashReportingURL" json:"crURL" default:"https://crash.syncthing.net/newcrash"` // crash reporting URL
CREnabled bool `xml:"crashReportingEnabled" json:"crashReportingEnabled" default:"true" restart:"true"`
StunKeepaliveStartS int `xml:"stunKeepaliveStartS" json:"stunKeepaliveStartS" default:"180"` // 0 for off
StunKeepaliveMinS int `xml:"stunKeepaliveMinS" json:"stunKeepaliveMinS" default:"20"` // 0 for off
RawStunServers []string `xml:"stunServer" json:"stunServers" default:"default"`
DatabaseTuning Tuning `xml:"databaseTuning" json:"databaseTuning" restart:"true"`
RawMaxCIRequestKiB int `xml:"maxConcurrentIncomingRequestKiB" json:"maxConcurrentIncomingRequestKiB"`
DeprecatedUPnPEnabled bool `xml:"upnpEnabled,omitempty" json:"-"`
DeprecatedUPnPLeaseM int `xml:"upnpLeaseMinutes,omitempty" json:"-"`
@@ -66,6 +69,7 @@ type OptionsConfiguration struct {
DeprecatedUPnPTimeoutS int `xml:"upnpTimeoutSeconds,omitempty" json:"-"`
DeprecatedRelayServers []string `xml:"relayServer,omitempty" json:"-"`
DeprecatedMinHomeDiskFreePct float64 `xml:"minHomeDiskFreePct,omitempty" json:"-"`
DeprecatedMaxConcurrentScans int `xml:"maxConcurrentScans,omitempty" json:"-"`
}
func (opts OptionsConfiguration) Copy() OptionsConfiguration {
@@ -152,3 +156,47 @@ func (opts OptionsConfiguration) GlobalDiscoveryServers() []string {
}
return util.UniqueTrimmedStrings(servers)
}
func (opts OptionsConfiguration) MaxFolderConcurrency() int {
// If a value is set, trust that.
if opts.RawMaxFolderConcurrency > 0 {
return opts.RawMaxFolderConcurrency
}
if opts.RawMaxFolderConcurrency < 0 {
// -1 etc means unlimited, which in the implementation means zero
return 0
}
// Otherwise default to the number of CPU cores in the system as a rough
// approximation of system powerfullness.
if n := runtime.GOMAXPROCS(-1); n > 0 {
return n
}
// We should never get here to begin with, but since we're here let's
// use some sort of reasonable compromise between the old "no limit" and
// getting nothing done... (Median number of folders out there at time
// of writing is two, 95-percentile at 12 folders.)
return 4 // https://xkcd.com/221/
}
func (opts OptionsConfiguration) MaxConcurrentIncomingRequestKiB() int {
// Negative is disabled, which in limiter land is spelled zero
if opts.RawMaxCIRequestKiB < 0 {
return 0
}
if opts.RawMaxFolderConcurrency == 0 {
// The default is 256 MiB
return 256 * 1024 // KiB
}
// We can't really do less than a couple of concurrent blocks or we'll
// pretty much stall completely. Check that an explicit value is large
// enough.
const minAllowed = 2 * protocol.MaxBlockSize / 1024
if opts.RawMaxCIRequestKiB < minAllowed {
return minAllowed
}
// Roll with it.
return opts.RawMaxCIRequestKiB
}

View File

@@ -1,12 +0,0 @@
<configuration version="10">
<folder id="test" path="testdata" ro="true" ignorePerms="false" rescanIntervalS="600" autoNormalize="true">
<device id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR"></device>
<device id="P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2"></device>
</folder>
<device id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR" name="node one" compression="metadata">
<address>a</address>
</device>
<device id="P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2" name="node two" compression="metadata">
<address>b</address>
</device>
</configuration>

View File

@@ -1,13 +0,0 @@
<configuration version="11">
<folder id="test" path="testdata" ro="true" ignorePerms="false" rescanIntervalS="600" autoNormalize="true">
<device id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR"></device>
<device id="P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2"></device>
<minDiskFreePct>1</minDiskFreePct>
</folder>
<device id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR" name="node one" compression="metadata">
<address>a</address>
</device>
<device id="P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2" name="node two" compression="metadata">
<address>b</address>
</device>
</configuration>

View File

@@ -1,14 +0,0 @@
<configuration version="12">
<folder id="test" path="testdata" ro="true" ignorePerms="false" rescanIntervalS="600" autoNormalize="true">
<device id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR"></device>
<device id="P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2"></device>
<minDiskFreePct>1</minDiskFreePct>
<maxConflicts>-1</maxConflicts>
</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>

View File

@@ -1,14 +0,0 @@
<configuration version="13">
<folder id="test" path="testdata" ro="true" ignorePerms="false" rescanIntervalS="600" autoNormalize="true">
<device id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR"></device>
<device id="P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2"></device>
<minDiskFreePct>1</minDiskFreePct>
<maxConflicts>-1</maxConflicts>
</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>

View File

@@ -1,14 +0,0 @@
<configuration version="14">
<folder id="test" path="testdata" type="readonly" ignorePerms="false" rescanIntervalS="600" autoNormalize="true">
<device id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR"></device>
<device id="P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2"></device>
<minDiskFreePct>1</minDiskFreePct>
<maxConflicts>-1</maxConflicts>
</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>

View File

@@ -1,14 +0,0 @@
<configuration version="15">
<folder id="test" path="testdata" type="readonly" ignorePerms="false" rescanIntervalS="600" autoNormalize="true">
<device id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR"></device>
<device id="P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2"></device>
<minDiskFreePct>1</minDiskFreePct>
<maxConflicts>-1</maxConflicts>
</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>

View File

@@ -1,14 +0,0 @@
<configuration version="16">
<folder id="test" path="testdata" type="readonly" ignorePerms="false" rescanIntervalS="600" autoNormalize="true">
<device id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR"></device>
<device id="P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2"></device>
<minDiskFreePct>1</minDiskFreePct>
<maxConflicts>-1</maxConflicts>
</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>

View File

@@ -1,15 +0,0 @@
<configuration version="17">
<folder id="test" path="testdata" type="readonly" ignorePerms="false" rescanIntervalS="600" autoNormalize="true">
<device id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR"></device>
<device id="P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2"></device>
<minDiskFreePct>1</minDiskFreePct>
<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>

View File

@@ -1,15 +0,0 @@
<configuration version="18">
<folder id="test" path="testdata" type="readonly" ignorePerms="false" rescanIntervalS="600" autoNormalize="true">
<device id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR"></device>
<device id="P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2"></device>
<minDiskFreePct>1</minDiskFreePct>
<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>

View File

@@ -1,15 +0,0 @@
<configuration version="19">
<folder id="test" path="testdata" type="readonly" ignorePerms="false" rescanIntervalS="600" autoNormalize="true">
<device id="AIR6LPZ-7K4PTTV-UXQSMUU-CPQ5YWH-OEDFIIQ-JUG777G-2YQXXR5-YD6AWQR"></device>
<device id="P56IOI7-MZJNU2Y-IQGDREY-DM2MGTI-MGL3BXN-PQ6W5BM-TBBZ4TJ-XZWICQ2"></device>
<minDiskFreePct>1</minDiskFreePct>
<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>

View File

@@ -1,15 +0,0 @@
<configuration version="20">
<folder id="test" path="testdata" type="readonly" ignorePerms="false" rescanIntervalS="600" autoNormalize="true">
<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>

View File

@@ -1,15 +0,0 @@
<configuration version="21">
<folder id="test" path="testdata" type="readonly" ignorePerms="false" rescanIntervalS="600" autoNormalize="true">
<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>

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