Compare commits

...

42 Commits

Author SHA1 Message Date
Jakob Borg
8f3f787a34 gui, man: Update docs & translations 2017-05-18 07:47:51 +02:00
Darshil Chanpura
3522d451df gui: Added a CSS rule for out of sync items modal
Removed text decoration on hover which was shown while hovering on span with eject icon.

GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4135
2017-05-16 08:56:54 +00:00
Jakob Borg
cf3114b56d authors: Amend dtchanpura 2017-05-16 10:49:48 +02:00
Jakob Borg
3d95135638 authors: Add dtchanpura 2017-05-16 10:47:29 +02:00
Jakob Borg
4db662e576 gui: Ensure failed items folder path contains separator (fixes #4143)
Windows specific, due to how we handle folder paths.

GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4149
2017-05-15 06:32:16 +00:00
Jakob Borg
1d15b8be9b cmd/syncthing: Warn when running as a super user (fixes #4123)
UID 0 on Unixes, SYSTEM SID on Windows.

GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4148
2017-05-15 05:42:21 +00:00
Jakob Borg
d25b15263a cmd/syncthing: Process handle should be closed 2017-05-14 18:06:27 +02:00
Wulf Weich
7931d956f7 gui: fix path breaking out of global changes modal (fixes #3895)
GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4146
2017-05-13 10:42:37 +00:00
Elliot Huffman
c9afabf09f etc: Update systemd docs URL
Skip-check: authors

GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4145
2017-05-13 08:01:53 +00:00
Jakob Borg
c262f48bfe Merge branch 'release'
* release:
  cmd/syncthing: Fix CPU usage reporting (tick time)
2017-05-06 17:37:16 +02:00
Jakob Borg
8c108b4d20 cmd/syncthing: Fix CPU usage reporting (tick time) 2017-05-06 17:36:12 +02:00
Jakob Borg
ec137c9522 cmd/syncthing: Fix CPU usage reporting (tick time) 2017-05-06 17:35:07 +02:00
Jakob Borg
b17d7d8126 Merge branch 'release'
* release:
  cmd/syncthing: Report correct CPU usage on Windows (fixes #4133)
2017-05-05 16:20:35 +02:00
Jakob Borg
43569d8d36 cmd/syncthing: Report correct CPU usage on Windows (fixes #4133) 2017-05-05 16:16:43 +02:00
Jakob Borg
c4b527e5e9 cmd/syncthing: Report correct CPU usage on Windows (fixes #4133) 2017-05-05 16:12:59 +02:00
Jakob Borg
6386d079b0 gui: Don't reload concurrently with saving config when changing theme (fixes #4127) 2017-05-05 16:12:59 +02:00
Ben S
d2699a20fc gui: Display global changes timestamps in 24h format
GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4130
2017-05-04 10:18:47 +00:00
Simon Frei
0b854dff9d lib/ignore: Don't match root (".")
GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4122
2017-05-01 16:58:08 +00:00
Simon Frei
9de6cdddfd script: Ignore units and allow translated strings as translate-values
GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4120
2017-04-29 15:48:00 +00:00
Jakob Borg
5045842f4f lib/config: Don't XML serialize deprecated minDiskFreePct 2017-04-27 14:46:19 +09:00
Jakob Borg
e0405de5bf lib/protocol: More descriptive errors on device ID parse failures 2017-04-27 14:45:35 +09:00
Jakob Borg
d6fbfc3545 lib/fs, lib/model, lib/scanner: Make scans cancellable (fixes #3965)
The folder already knew how to stop properly, but the fs.Walk() didn't
and can potentially take a very long time. This adds context support to
Walk and the underlying scanning stuff, and passes in an appropriate
context from above. The stop channel in model.folder is replaced with a
context for this purpose.

To test I added an infiniteFS that represents a large amount of data
(not actually infinite, but close) and verify that walking it is
properly stopped. For that to be implemented smoothly I moved out the
Walk function to it's own type, as typically the implementer of a new
filesystem type might not need or want to reimplement Walk.

It's somewhat tricky to test that this actually works properly on the
actual sendReceiveFolder and so on, as those are started from inside the
model and the filesystem isn't easily pluggable etc. Instead I've tested
that part manually by adding a huge folder and verifying that pause,
resume and reconfig do the right things by looking at debug output.

GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4117
2017-04-26 00:15:23 +00:00
Jakob Borg
bdaef44765 gui, man: Update docs & translations 2017-04-26 09:13:12 +09:00
Jakob Borg
488444354b lib/db: Don't panic
So, when first implementing the database layer I added panics on every
unexpected error condition mostly to be sure to flush out bugs and
inconsistencies. Then it became sort of standard, and we don't seem to
have many bugs here any more so the panics are usually caused by things
like checksum errors on read. But it's not an optimal user experience to
crash all the time.

Here I've weeded out most of the panics, while retaining a few "can't
happen" ones like errors on marshalling and write that we really can't
recover from.

For the rest, I'm mostly treating any read error as "entry didn't
exist". This should mean we'll rescan the file and correct the info (if
scanning) or treat it as a new file and do conflict handling (when
pulling). In some cases things like our global stats may be slightly
incorrect until a restart, if a database entry goes suddenly missing
during runtime.

All in all, I think this makes us a bit more robust and friendly without
introducing too many risks for the user. If the database is truly toast,
probably many other things on the system will be toast as well...

GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4118
2017-04-25 22:52:37 +00:00
Jakob Borg
26654df48c gui: Restrict GUI listening ports to >1024, add help (fixes #4020)
This adds a pattern validator to the GUI listen port field that checks
for port numbers 1024 and above. Also adds a help link pointing to the
(new) page talking about GUI listen port numbers. That page has
information on how to work around the restriction, in general terms.

Also changes the header from "GUI Listen Addresses" to the singular
version, because we only support one listen address today.

GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4116
2017-04-24 07:19:28 +00:00
Jakob Borg
7f5e236dd7 gui: Wait for config commit before setting ignores (ref #4095)
Given the saveConfig() is async, it might not have happened before we
try to save the ignores and unpause. Likewise must wait for saving
ignores before unpausing or the scan might start before ignores are on
disk.

Javsacript <3
2017-04-24 08:57:07 +09:00
Simon Frei
914b09fd1f lib/model: Create root directory for paused folders (fixes #4094)
GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4095
2017-04-23 23:50:56 +00:00
Jakob Borg
e9f05d138f lib/db, lib/model: Always use reasonable sized batches (fixes #2250, fixes #4112)
Harmonize how we use batches in the model, using ProtoSize() to judge
the actual weight of the entire batch instead of estimating. Use smaller
batches in the block map - I think we might have though that batch.Len()
in the leveldb was the batch size in bytes, but it's actually number of
operations.

GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4114
2017-04-22 14:23:33 +00:00
Jakob Borg
10894695c6 cmd/syncthing: Use a 10 second EWMA for CPU usage, refactor a little
We have it lying around so might as well use it instead of inventing our
own thing.

GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4111
2017-04-20 08:33:09 +00:00
Simon Frei
6b188ebcf3 lib/model: Mark initial scan as finished even if failed and refactor (fixes #4103)
The mechanism to disallow manual scans before the initial scan completed
(#3996) , had the side effect, that if the initial scan failed, no further
scans are allowed. So this marks the initial scan as finished regardless of
whether it succeeded or not.

There was also redundant code in rofolder and a pointless check for folder
health in scanSubsIfHealthy (happens in internalScanFolderSubdirs as well).
This also moves logging from folder.go to ro/rw-folder.go to include the
information about whether it is send-only or send-receive

GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4104
2017-04-20 00:20:34 +00:00
Jakob Borg
57e3f9e64b vendor: Update golang.org/x/sys/unix 2017-04-15 10:31:55 +02:00
Jakob Borg
b5694ca788 Merge branch 'release' (omitting the revert)
* release:
  Revert "lib/model, gui: Allow creating and editing ignores of paused folders (fixes #3608)"
2017-04-15 09:49:32 +02:00
Jonathan Cross
f689512a3f gui: Reduce height of textarea in ignores modal
Skip-check: authors

GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4102
2017-04-14 20:33:41 +00:00
Jakob Borg
dd1f7a5ab7 lib/connections: Allow negative ACL entries on devices (fixes #4096)
Prefix an entry with "!" to make it a negative entry. First match wins.

GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4097
2017-04-13 17:43:29 +00:00
Jakob Borg
d48e46a29c cmd/syncthing: Allow custom event subscriptions (fixes #1879)
This adds a parameter "events" to the /rest/events endpoint. It should
be a comma separated list of the events the consumer is interested in.
When not given it defaults to the current set of events, so it's
backwards compatible.

The API service then manages subscriptions, creating them as required
for each requested event mask. Old subscriptions are not "garbage
collected" - it's assumed that in normal usage the set of event
subscriptions will be small enough. Possibly lower than before, as we
will not set up the disk event subscription unless it's actually used.

GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4092
2017-04-13 17:14:34 +00:00
Jakob Borg
75460be98d Merge branch 'release'
* release:
  lib/protocol: Accept invalid files without blocks (fixes #4093)
2017-04-12 11:49:11 +02:00
Jakob Borg
e3e028c988 lib/protocol: Accept invalid files without blocks (fixes #4093) 2017-04-12 11:28:12 +02:00
Jakob Borg
da34f27546 gui, lib/config, lib/model: Allow absolute values for minimum disk free space (fixes #3307)
This deprecates the current minDiskFreePct setting and introduces
minDiskFree. The latter is, in it's serialized form, a string with a
unit. We accept percentages ("2.35%") and absolute values ("250 k", "12.5
Gi"). Common suffixes are understood. The config editor lets the user
enter the string, and validates it.

We still default to "1 %", but the user can change that to an absolute
value at will.

GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4087
LGTM: AudriusButkevicius, imsodin
2017-04-12 09:01:19 +00:00
Jakob Borg
c205fdd77e cmd/syncthing: Handle pre-releases with zero auto upgrade interval (fixes #4090) 2017-04-10 15:56:52 +02:00
Jakob Borg
ae4206f362 gui: Add forgotten translation string 2017-04-07 09:16:55 +02:00
Keith Turner
391665e322 readme: Use logo as header
Skip-check: authors

GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4088
2017-04-07 05:21:11 +00:00
Simon Frei
5521759b23 lib/model: TestIgnores: Add ms sleep on all platforms (ref #3986 #3996)
GitHub-Pull-Request: https://github.com/syncthing/syncthing/pull/4083
2017-04-06 09:55:54 +00:00
114 changed files with 2071 additions and 1463 deletions

View File

@@ -37,6 +37,7 @@ Colin Kennedy (moshen) <moshen.colin@gmail.com>
Daniel Bergmann (brgmnn) <dan.arne.bergmann@gmail.com> <brgmnn@users.noreply.github.com>
Daniel Harte (norgeous) <daniel@harte.me> <daniel@danielharte.co.uk> <norgeous@users.noreply.github.com>
Daniel Martí (mvdan) <mvdan@mvdan.cc>
Darshil Chanpura (dtchanpura) <dtchanpura@gmail.com> <dcprime314@gmail.com>
David Rimmer (dinosore) <dinosore@dbrsoftware.co.uk>
Denis A. (dva) <denisva@gmail.com>
Dennis Wilson (snnd) <dw@risu.io>

2
NICKS
View File

@@ -36,6 +36,8 @@ ceh <emil@hessman.se>
cqcallaw <enlightened.despot@gmail.com>
damajor <damajor@gmail.com>
dinosore <dinosore@dbrsoftware.co.uk>
dtchanpura <dtchanpura@gmail.com>
dtchanpura <dcprime314@gmail.com>
dva <denisva@gmail.com>
dzarda <dzardacz@gmail.com>
eipiminus1 <eipiminusone+github@gmail.com>

View File

@@ -1,4 +1,6 @@
# Syncthing
[![Syncthing][14]][15]
---
[![Latest Linux & Cross Build](https://img.shields.io/jenkins/s/http/build.syncthing.net/syncthing.svg?style=flat-square&label=linux+%26+cross)](https://build.syncthing.net/job/syncthing/lastBuild/)
[![Latest Windows Build](https://img.shields.io/jenkins/s/http/build.syncthing.net/syncthing-windows.svg?style=flat-square&label=windows)](https://build.syncthing.net/job/syncthing/lastBuild/)
@@ -108,3 +110,5 @@ All code is licensed under the [MPLv2 License][7].
[11]: https://docs.syncthing.net/users/contrib.html#gui-wrappers
[12]: https://www.bountysource.com/teams/syncthing/issues
[13]: https://github.com/syncthing/syncthing/blob/master/GOALS.md
[14]: assets/logo-text-128.png
[15]: https://syncthing.net/

View File

@@ -7,6 +7,7 @@
package main
import (
"context"
"flag"
"log"
"os"
@@ -70,7 +71,7 @@ func main() {
if *standardBlocks || blockSize < protocol.BlockSize {
blockSize = protocol.BlockSize
}
bs, err := scanner.Blocks(fd, blockSize, fi.Size(), nil, true)
bs, err := scanner.Blocks(context.TODO(), fd, blockSize, fi.Size(), nil, true)
if err != nil {
log.Fatal(err)
}

View File

@@ -59,40 +59,20 @@ type prusage_t struct {
}
func solarisPrusage(pid int, rusage *prusage_t) error {
fd, err := os.Open(fmt.Sprintf("/proc/%d/usage", pid))
var procFile = fmt.Sprintf("/proc/%d/usage", os.Getpid())
func cpuUsage() time.Duration {
fd, err := os.Open(procFile)
if err != nil {
return err
return 0
}
var rusage prusage_t
err = binary.Read(fd, binary.LittleEndian, rusage)
fd.Close()
return err
}
func init() {
go trackCPUUsage()
}
func trackCPUUsage() {
var prevUsage int64
var prevTime = time.Now().UnixNano()
var rusage prusage_t
var pid = os.Getpid()
for range time.NewTicker(time.Second).C {
err := solarisPrusage(pid, &rusage)
if err != nil {
l.Warnln("getting prusage:", err)
continue
}
curTime := time.Now().UnixNano()
timeDiff := curTime - prevTime
curUsage := rusage.Pr_utime.Nano() + rusage.Pr_stime.Nano()
usageDiff := curUsage - prevUsage
cpuUsageLock.Lock()
copy(cpuUsagePercent[1:], cpuUsagePercent[0:])
cpuUsagePercent[0] = 100 * float64(usageDiff) / float64(timeDiff)
cpuUsageLock.Unlock()
prevTime = curTime
prevUsage = curUsage
if err != nil {
return 0
}
return time.Duration(rusage.Pr_utime.Nano() + rusage.Pr_stime.Nano())
}

View File

@@ -0,0 +1,18 @@
// Copyright (C) 2014 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/.
//+build !windows,!solaris
package main
import "syscall"
import "time"
func cpuUsage() time.Duration {
var rusage syscall.Rusage
syscall.Getrusage(syscall.RUSAGE_SELF, &rusage)
return time.Duration(rusage.Utime.Nano() + rusage.Stime.Nano())
}

View File

@@ -0,0 +1,27 @@
// Copyright (C) 2014 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/.
//+build windows
package main
import "syscall"
import "time"
func cpuUsage() time.Duration {
handle, err := syscall.GetCurrentProcess()
if err != nil {
return 0
}
defer syscall.CloseHandle(handle)
var ctime, etime, ktime, utime syscall.Filetime
if err := syscall.GetProcessTimes(handle, &ctime, &etime, &ktime, &utime); err != nil {
return 0
}
return time.Duration(ktime.Nanoseconds() + utime.Nanoseconds())
}

View File

@@ -11,6 +11,7 @@ import (
"encoding/json"
"fmt"
"io/ioutil"
"math"
"net"
"net/http"
"os"
@@ -45,6 +46,12 @@ var (
startTime = time.Now()
)
const (
defaultEventMask = events.AllEvents &^ events.LocalChangeDetected &^ events.RemoteChangeDetected
diskEventMask = events.LocalChangeDetected | events.RemoteChangeDetected
eventSubBufferSize = 1000
)
type apiService struct {
id protocol.DeviceID
cfg configIntf
@@ -52,8 +59,8 @@ type apiService struct {
httpsKeyFile string
statics *staticsServer
model modelIntf
eventSub events.BufferedSubscription
diskEventSub events.BufferedSubscription
eventSubs map[events.EventType]events.BufferedSubscription
eventSubsMut sync.Mutex
discoverer discover.CachingMux
connectionsService connectionsIntf
fss *folderSummaryService
@@ -114,16 +121,19 @@ type connectionsIntf interface {
Status() map[string]interface{}
}
func newAPIService(id protocol.DeviceID, cfg configIntf, httpsCertFile, httpsKeyFile, assetDir string, m modelIntf, eventSub events.BufferedSubscription, diskEventSub events.BufferedSubscription, discoverer discover.CachingMux, connectionsService connectionsIntf, errors, systemLog logger.Recorder) *apiService {
func newAPIService(id protocol.DeviceID, cfg configIntf, httpsCertFile, httpsKeyFile, assetDir string, m modelIntf, defaultSub, diskSub events.BufferedSubscription, discoverer discover.CachingMux, connectionsService connectionsIntf, errors, systemLog logger.Recorder) *apiService {
service := &apiService{
id: id,
cfg: cfg,
httpsCertFile: httpsCertFile,
httpsKeyFile: httpsKeyFile,
statics: newStaticsServer(cfg.GUI().Theme, assetDir),
model: m,
eventSub: eventSub,
diskEventSub: diskEventSub,
id: id,
cfg: cfg,
httpsCertFile: httpsCertFile,
httpsKeyFile: httpsKeyFile,
statics: newStaticsServer(cfg.GUI().Theme, assetDir),
model: m,
eventSubs: map[events.EventType]events.BufferedSubscription{
defaultEventMask: defaultSub,
diskEventMask: diskSub,
},
eventSubsMut: sync.NewMutex(),
discoverer: discoverer,
connectionsService: connectionsService,
systemConfigMut: sync.NewMutex(),
@@ -234,7 +244,7 @@ func (s *apiService) Serve() {
getRestMux.HandleFunc("/rest/db/need", s.getDBNeed) // folder [perpage] [page]
getRestMux.HandleFunc("/rest/db/status", s.getDBStatus) // folder
getRestMux.HandleFunc("/rest/db/browse", s.getDBBrowse) // folder [prefix] [dirsonly] [levels]
getRestMux.HandleFunc("/rest/events", s.getIndexEvents) // [since] [limit] [timeout]
getRestMux.HandleFunc("/rest/events", s.getIndexEvents) // [since] [limit] [timeout] [events]
getRestMux.HandleFunc("/rest/events/disk", s.getDiskEvents) // [since] [limit] [timeout]
getRestMux.HandleFunc("/rest/stats/device", s.getDeviceStats) // -
getRestMux.HandleFunc("/rest/stats/folder", s.getFolderStats) // -
@@ -837,8 +847,29 @@ func (s *apiService) flushResponse(resp string, w http.ResponseWriter) {
f.Flush()
}
var cpuUsagePercent [10]float64 // The last ten seconds
var cpuUsageLock = sync.NewRWMutex()
// 10 second average. Magic alpha value comes from looking at EWMA package
// definitions of EWMA1, EWMA5. The tick rate *must* be five seconds (hard
// coded in the EWMA package).
var cpuTickRate = 5 * time.Second
var cpuAverage = metrics.NewEWMA(1 - math.Exp(-float64(cpuTickRate)/float64(time.Second)/10.0))
func init() {
if !innerProcess {
return
}
go func() {
// Initialize prevUsage to an actual value returned by cpuUsage
// instead of zero, because at least Windows returns a huge negative
// number here that then slowly increments...
prevUsage := cpuUsage()
for range time.NewTicker(cpuTickRate).C {
curUsage := cpuUsage()
cpuAverage.Update(int64((curUsage - prevUsage) / time.Millisecond))
prevUsage = curUsage
cpuAverage.Tick()
}
}()
}
func (s *apiService) getSystemStatus(w http.ResponseWriter, r *http.Request) {
var m runtime.MemStats
@@ -866,14 +897,9 @@ func (s *apiService) getSystemStatus(w http.ResponseWriter, r *http.Request) {
}
res["connectionServiceStatus"] = s.connectionsService.Status()
cpuUsageLock.RLock()
var cpusum float64
for _, p := range cpuUsagePercent {
cpusum += p
}
cpuUsageLock.RUnlock()
res["cpuPercent"] = cpusum / float64(len(cpuUsagePercent)) / float64(runtime.NumCPU())
// cpuUsage.Rate() is in milliseconds per second, so dividing by ten
// gives us percent
res["cpuPercent"] = cpuAverage.Rate() / 10 / float64(runtime.NumCPU())
res["pathSeparator"] = string(filepath.Separator)
res["uptime"] = int(time.Since(startTime).Seconds())
res["startTime"] = startTime
@@ -969,7 +995,9 @@ func (s *apiService) getRandomString(w http.ResponseWriter, r *http.Request) {
func (s *apiService) getDBIgnores(w http.ResponseWriter, r *http.Request) {
qs := r.URL.Query()
ignores, patterns, err := s.model.GetIgnores(qs.Get("folder"))
folder := qs.Get("folder")
ignores, patterns, err := s.model.GetIgnores(folder)
if err != nil {
http.Error(w, err.Error(), 500)
return
@@ -1009,11 +1037,14 @@ func (s *apiService) postDBIgnores(w http.ResponseWriter, r *http.Request) {
func (s *apiService) getIndexEvents(w http.ResponseWriter, r *http.Request) {
s.fss.gotEventRequest()
s.getEvents(w, r, s.eventSub)
mask := s.getEventMask(r.URL.Query().Get("events"))
sub := s.getEventSub(mask)
s.getEvents(w, r, sub)
}
func (s *apiService) getDiskEvents(w http.ResponseWriter, r *http.Request) {
s.getEvents(w, r, s.diskEventSub)
sub := s.getEventSub(diskEventMask)
s.getEvents(w, r, sub)
}
func (s *apiService) getEvents(w http.ResponseWriter, r *http.Request, eventSub events.BufferedSubscription) {
@@ -1045,6 +1076,31 @@ func (s *apiService) getEvents(w http.ResponseWriter, r *http.Request, eventSub
sendJSON(w, evs)
}
func (s *apiService) getEventMask(evs string) events.EventType {
eventMask := defaultEventMask
if evs != "" {
eventList := strings.Split(evs, ",")
eventMask = 0
for _, ev := range eventList {
eventMask |= events.UnmarshalEventType(strings.TrimSpace(ev))
}
}
return eventMask
}
func (s *apiService) getEventSub(mask events.EventType) events.BufferedSubscription {
s.eventSubsMut.Lock()
bufsub, ok := s.eventSubs[mask]
if !ok {
evsub := events.Default.Subscribe(mask)
bufsub = events.NewBufferedSubscription(evsub, eventSubBufferSize)
s.eventSubs[mask] = bufsub
}
s.eventSubsMut.Unlock()
return bufsub
}
func (s *apiService) getSystemUpgrade(w http.ResponseWriter, r *http.Request) {
if noUpgradeFromEnv {
http.Error(w, upgrade.ErrUpgradeUnsupported.Error(), 500)

View File

@@ -23,6 +23,7 @@ import (
"github.com/d4l3k/messagediff"
"github.com/syncthing/syncthing/lib/config"
"github.com/syncthing/syncthing/lib/events"
"github.com/syncthing/syncthing/lib/protocol"
"github.com/syncthing/syncthing/lib/sync"
"github.com/thejerf/suture"
@@ -924,3 +925,34 @@ func TestOptionsRequest(t *testing.T) {
t.Fatal("OPTIONS on /rest/system/status should return a 'Access-Control-Allow-Headers: Content-Type, X-API-KEY' header")
}
}
func TestEventMasks(t *testing.T) {
cfg := new(mockedConfig)
defSub := new(mockedEventSub)
diskSub := new(mockedEventSub)
svc := newAPIService(protocol.LocalDeviceID, cfg, "", "", "", nil, defSub, diskSub, nil, nil, nil, nil)
if mask := svc.getEventMask(""); mask != defaultEventMask {
t.Errorf("incorrect default mask %x != %x", int64(mask), int64(defaultEventMask))
}
expected := events.FolderSummary | events.LocalChangeDetected
if mask := svc.getEventMask("FolderSummary,LocalChangeDetected"); mask != expected {
t.Errorf("incorrect parsed mask %x != %x", int64(mask), int64(expected))
}
expected = 0
if mask := svc.getEventMask("WeirdEvent,something else that doens't exist"); mask != expected {
t.Errorf("incorrect parsed mask %x != %x", int64(mask), int64(expected))
}
if res := svc.getEventSub(defaultEventMask); res != defSub {
t.Errorf("should have returned the given default event sub")
}
if res := svc.getEventSub(diskEventMask); res != diskSub {
t.Errorf("should have returned the given disk event sub")
}
if res := svc.getEventSub(events.LocalIndexUpdated); res == nil || res == defSub || res == diskSub {
t.Errorf("should have returned a valid, non-default event sub")
}
}

View File

@@ -1,37 +0,0 @@
// Copyright (C) 2014 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/.
//+build !windows,!solaris
package main
import (
"syscall"
"time"
)
func init() {
go trackCPUUsage()
}
func trackCPUUsage() {
var prevUsage int64
var prevTime = time.Now().UnixNano()
var rusage syscall.Rusage
for range time.NewTicker(time.Second).C {
syscall.Getrusage(syscall.RUSAGE_SELF, &rusage)
curTime := time.Now().UnixNano()
timeDiff := curTime - prevTime
curUsage := rusage.Utime.Nano() + rusage.Stime.Nano()
usageDiff := curUsage - prevUsage
cpuUsageLock.Lock()
copy(cpuUsagePercent[1:], cpuUsagePercent[0:])
cpuUsagePercent[0] = 100 * float64(usageDiff) / float64(timeDiff)
cpuUsageLock.Unlock()
prevTime = curTime
prevUsage = curUsage
}
}

View File

@@ -1,58 +0,0 @@
// Copyright (C) 2014 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/.
//+build windows
package main
import (
"syscall"
"time"
)
func init() {
go trackCPUUsage()
}
func trackCPUUsage() {
handle, err := syscall.GetCurrentProcess()
if err != nil {
l.Warnln("Cannot track CPU usage:", err)
return
}
var ctime, etime, ktime, utime syscall.Filetime
err = syscall.GetProcessTimes(handle, &ctime, &etime, &ktime, &utime)
if err != nil {
l.Warnln("Cannot track CPU usage:", err)
return
}
prevTime := ctime.Nanoseconds()
prevUsage := ktime.Nanoseconds() + utime.Nanoseconds() // Always overflows
for range time.NewTicker(time.Second).C {
err := syscall.GetProcessTimes(handle, &ctime, &etime, &ktime, &utime)
if err != nil {
continue
}
curTime := time.Now().UnixNano()
timeDiff := curTime - prevTime
// This is sometimes 0, no clue why.
if timeDiff == 0 {
continue
}
curUsage := ktime.Nanoseconds() + utime.Nanoseconds()
usageDiff := curUsage - prevUsage
cpuUsageLock.Lock()
copy(cpuUsagePercent[1:], cpuUsagePercent[0:])
cpuUsagePercent[0] = 100 * float64(usageDiff) / float64(timeDiff)
cpuUsageLock.Unlock()
prevTime = curTime
prevUsage = curUsage
}
}

View File

@@ -637,8 +637,8 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
// Event subscription for the API; must start early to catch the early
// events. The LocalChangeDetected event might overwhelm the event
// receiver in some situations so we will not subscribe to it here.
apiSub := events.NewBufferedSubscription(events.Default.Subscribe(events.AllEvents&^events.LocalChangeDetected&^events.RemoteChangeDetected), 1000)
diskSub := events.NewBufferedSubscription(events.Default.Subscribe(events.LocalChangeDetected|events.RemoteChangeDetected), 1000)
defaultSub := events.NewBufferedSubscription(events.Default.Subscribe(defaultEventMask), eventSubBufferSize)
diskSub := events.NewBufferedSubscription(events.Default.Subscribe(diskEventMask), eventSubBufferSize)
if len(os.Getenv("GOMAXPROCS")) == 0 {
runtime.GOMAXPROCS(runtime.NumCPU())
@@ -815,6 +815,7 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
// Add and start folders
for _, folderCfg := range cfg.Folders() {
if folderCfg.Paused {
folderCfg.CreateRoot()
continue
}
m.AddFolder(folderCfg)
@@ -868,7 +869,7 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
// GUI
setupGUI(mainService, cfg, m, apiSub, diskSub, cachedDiscovery, connectionsService, errors, systemLog, runtimeOptions)
setupGUI(mainService, cfg, m, defaultSub, diskSub, cachedDiscovery, connectionsService, errors, systemLog, runtimeOptions)
if runtimeOptions.cpuProfile {
f, err := os.Create(fmt.Sprintf("cpu-%d.pprof", os.Getpid()))
@@ -923,6 +924,10 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
l.Infoln("Automatic upgrade is always enabled for candidate releases.")
if 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.
@@ -936,6 +941,10 @@ func syncthingMain(runtimeOptions RuntimeOptions) {
}
}
if isSuperUser() {
l.Warnln("Syncthing should not run as a privileged or system user. Please consider using a normal user account.")
}
events.Default.Log(events.StartupComplete, map[string]string{
"myID": myID.String(),
})
@@ -1082,7 +1091,7 @@ func startAuditing(mainService *suture.Supervisor, auditFile string) {
l.Infoln("Audit log in", auditDest)
}
func setupGUI(mainService *suture.Supervisor, cfg *config.Wrapper, m *model.Model, apiSub events.BufferedSubscription, diskSub events.BufferedSubscription, discoverer discover.CachingMux, connectionsService *connections.Service, errors, systemLog logger.Recorder, runtimeOptions RuntimeOptions) {
func setupGUI(mainService *suture.Supervisor, cfg *config.Wrapper, m *model.Model, defaultSub, diskSub events.BufferedSubscription, discoverer discover.CachingMux, connectionsService *connections.Service, errors, systemLog logger.Recorder, runtimeOptions RuntimeOptions) {
guiCfg := cfg.GUI()
if !guiCfg.Enabled {
@@ -1093,7 +1102,7 @@ func setupGUI(mainService *suture.Supervisor, cfg *config.Wrapper, m *model.Mode
l.Warnln("Insecure admin access is enabled.")
}
api := newAPIService(myID, cfg, locations[locHTTPSCertFile], locations[locHTTPSKeyFile], runtimeOptions.assetDir, m, apiSub, diskSub, discoverer, connectionsService, errors, systemLog)
api := newAPIService(myID, cfg, locations[locHTTPSCertFile], locations[locHTTPSKeyFile], runtimeOptions.assetDir, m, defaultSub, diskSub, discoverer, connectionsService, errors, systemLog)
cfg.Subscribe(api)
mainService.Add(api)
@@ -1113,7 +1122,7 @@ func defaultConfig(myName string) config.Configuration {
defaultFolder = config.NewFolderConfiguration("default", locations[locDefFolder])
defaultFolder.Label = "Default Folder"
defaultFolder.RescanIntervalS = 60
defaultFolder.MinDiskFreePct = 1
defaultFolder.MinDiskFree = config.Size{Value: 1, Unit: "%"}
defaultFolder.Devices = []config.FolderDeviceConfiguration{{DeviceID: myID}}
defaultFolder.AutoNormalize = true
defaultFolder.MaxConflicts = -1
@@ -1241,7 +1250,15 @@ func autoUpgrade(cfg *config.Wrapper) {
l.Infof("Connected to device %s with a newer version (current %q < remote %q). Checking for upgrades.", data["id"], Version, data["clientVersion"])
case <-timer.C:
}
opts := cfg.Options()
checkInterval := time.Duration(opts.AutoUpgradeIntervalH) * time.Hour
if checkInterval < time.Hour {
// We shouldn't be here if AutoUpgradeIntervalH < 1, but for
// safety's sake.
checkInterval = time.Hour
}
rel, err := upgrade.LatestRelease(opts.ReleasesURL, Version, opts.UpgradeToPreReleases)
if err == upgrade.ErrUpgradeUnsupported {
events.Default.Unsubscribe(sub)
@@ -1251,13 +1268,13 @@ func autoUpgrade(cfg *config.Wrapper) {
// Don't complain too loudly here; we might simply not have
// internet connectivity, or the upgrade server might be down.
l.Infoln("Automatic upgrade:", err)
timer.Reset(time.Duration(cfg.Options().AutoUpgradeIntervalH) * time.Hour)
timer.Reset(checkInterval)
continue
}
if upgrade.CompareVersions(rel.Tag, Version) != upgrade.Newer {
// Skip equal, older or majorly newer (incompatible) versions
timer.Reset(time.Duration(cfg.Options().AutoUpgradeIntervalH) * time.Hour)
timer.Reset(checkInterval)
continue
}
@@ -1265,7 +1282,7 @@ func autoUpgrade(cfg *config.Wrapper) {
err = upgrade.To(rel)
if err != nil {
l.Warnln("Automatic upgrade:", err)
timer.Reset(time.Duration(cfg.Options().AutoUpgradeIntervalH) * time.Hour)
timer.Reset(checkInterval)
continue
}
events.Default.Unsubscribe(sub)

View File

@@ -0,0 +1,17 @@
// 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/.
// +build !windows
package main
import (
"os"
)
func isSuperUser() bool {
return os.Geteuid() == 0
}

View File

@@ -0,0 +1,41 @@
// 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 main
import "syscall"
// https://msdn.microsoft.com/en-us/library/windows/desktop/aa379649(v=vs.85).aspx
const securityLocalSystemRID = "S-1-5-18"
func isSuperUser() bool {
tok, err := syscall.OpenCurrentProcessToken()
if err != nil {
l.Debugln("OpenCurrentProcessToken:", err)
return false
}
defer tok.Close()
user, err := tok.GetTokenUser()
if err != nil {
l.Debugln("GetTokenUser:", err)
return false
}
if user.User.Sid == nil {
l.Debugln("sid is nil")
return false
}
sid, err := user.User.Sid.String()
if err != nil {
l.Debugln("Sid.String():", err)
return false
}
l.Debugf("SID: %q", sid)
return sid == securityLocalSystemRID
}

View File

@@ -8,6 +8,7 @@ package main
import (
"bytes"
"context"
"crypto/rand"
"crypto/tls"
"encoding/json"
@@ -309,7 +310,7 @@ func cpuBenchOnce(duration time.Duration, useWeakHash bool, bs []byte) float64 {
b := 0
for time.Since(t0) < duration {
r := bytes.NewReader(bs)
blocksResult, _ = scanner.Blocks(r, protocol.BlockSize, int64(len(bs)), nil, useWeakHash)
blocksResult, _ = scanner.Blocks(context.TODO(), r, protocol.BlockSize, int64(len(bs)), nil, useWeakHash)
b += len(bs)
}
d := time.Since(t0)

View File

@@ -5,4 +5,4 @@ This directory contains configuration files for running Syncthing under the
systemd user service. For further documentation take a look at the [systemd
section][1] on https://docs.syncthing.net.
[1]: https://docs.syncthing.net/users/autostart.html#systemd
[1]: https://docs.syncthing.net/users/autostart.html#using-systemd

View File

@@ -100,6 +100,11 @@ ul+h5 {
white-space: nowrap;
}
/* Removing text decoration on anchor link hover pull request: #4135 */
.table td.small-data span a:hover {
text-decoration: none;
}
table.table-condensed {
table-layout: fixed;
}
@@ -266,6 +271,21 @@ ul.three-columns li, ul.two-columns li {
z-index: 980;
}
.globalChanges-path-col {
/* These are technically the same, but use both */
overflow-wrap: break-word;
word-wrap: break-word;
-ms-word-break: break-all;
/* This is the dangerous one in WebKit, as it breaks things wherever */
word-break: break-all;
/* Instead use this non-standard one: */
word-break: break-word;
}
.globalChanges-time-col {
width: 100px;
}
/** Footer nav on small devices **/
@media (max-width: 1199px) {
/* Stay at the end of the page, with space reserved for the footer

View File

@@ -10,6 +10,7 @@
"Add Device": "Добави устройство",
"Add Folder": "Добави папка",
"Add Remote Device": "Добави ново устройство",
"Add devices from the introducer to our device list, for mutually shared folders.": "Добавяне на устройства от списъка на запознаващото устройтво в нашият списък с устройства, за взаимно споделени папки.",
"Add new folder?": "Добави нова папка?",
"Address": "Адрес",
"Addresses": "Адреси",
@@ -67,6 +68,8 @@
"Editing {%path%}.": "Промяна на {{path}}.",
"Enable NAT traversal": "Разреши NAT traversal",
"Enable Relaying": "Разреши препращане",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Въведете не отрицателно число (пр. \"2.35\") и изберете единица.\nПроцентите са като част от размера на цялото дисково пространство.",
"Enter a non-privileged port number (1024 - 65535).": "Въведете непривилегирован номер на порт (1024-65535).",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Въведете адреси разделени със запетая (\"tcp://ip:port\", \"tcp://host:port\") или \"dynamic\", за да автоматично откриване на наличните адреси.",
"Enter ignore patterns, one per line.": "Добави шаблони за игнориране, по един на ред.",
"Error": "Грешка",
@@ -90,6 +93,7 @@
"GUI": "Потребителски интерфейс",
"GUI Authentication Password": "Парола за интерфейса",
"GUI Authentication User": "Потребителско име за интерфейса",
"GUI Listen Address": "Адрес на слушане на GUI-то",
"GUI Listen Addresses": "Адрес за свързване с потребителския интерфейс",
"GUI Theme": "Тема за потребителския интефейс",
"Generate": "Генерирай",
@@ -241,6 +245,7 @@
"This Device": "Вашето устройство",
"This can easily give hackers access to read and change any files on your computer.": "Това дава лесен достъп на хакери да разглеждат и променят всякакви файлове на компютъра Ви.",
"This is a major version upgrade.": "Това е нова основна версия.",
"This setting controls the free space required on the home (i.e., index database) disk.": "Тази настройка контролира нужното свободното място на основния (пр. този с базата данни) диск.",
"Time": "Време",
"Trash Can File Versioning": "Само на файловете в кошчето",
"Type": "Тип",

View File

@@ -1,279 +0,0 @@
{
"A device with that ID is already added.": "Ja s'ha afegit un dispositiu amb aquesta ID.",
"A negative number of days doesn't make sense.": "Un nombre negatiu de dies no té sentit.",
"A new major version may not be compatible with previous versions.": "Una nova versió major pot ser incompatible amb versions anteriors.",
"API Key": "Clau API",
"About": "Sobre",
"Action": "Action",
"Actions": "Accions",
"Add": "Afegir",
"Add Device": "Afegir dispositiu",
"Add Folder": "Afegir carpeta",
"Add Remote Device": "Add Remote Device",
"Add new folder?": "Afegir nova carpeta?",
"Address": "Adreça",
"Addresses": "Adreces",
"Advanced": "Avançat",
"Advanced Configuration": "Configuració Avançada",
"Advanced settings": "Advanced settings",
"All Data": "Totes les dades",
"Allow Anonymous Usage Reporting?": "Permetre l'enviament anònim d'informes d'ús?",
"Allowed Networks": "Allowed Networks",
"Alphabetic": "Alfabètic",
"An external command handles the versioning. It has to remove the file from the shared folder.": "An external command handles the versioning. It has to remove the file from the shared folder.",
"An external command handles the versioning. It has to remove the file from the synced folder.": "Un comando extern s'encarrega del control de versions. Ha d'eliminar l'arxiu de la carpeta sincronitzada.",
"Anonymous Usage Reporting": "Informe anònim d'ús",
"Any devices configured on an introducer device will be added to this device as well.": "Qualsevol dispositiu configurat en un dispositiu introductor també s'afegirà a aquest dispositiu.",
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Automatic upgrade now offers the choice between stable releases and release candidates.",
"Automatic upgrades": "Actualitzacions automàtiques",
"Be careful!": "Ves amb compte!",
"Bugs": "Bugs",
"CPU Utilization": "Utilització del CPU",
"Changelog": "Historial de canvis",
"Clean out after": "Netejar després",
"Click to see discovery failures": "Click to see discovery failures",
"Close": "Tancar",
"Command": "Comando",
"Comment, when used at the start of a line": "Comentari quan és usat al principi d'una línia",
"Compression": "Compressió",
"Configured": "Configured",
"Connection Error": "Error de connexió",
"Connection Type": "Connection Type",
"Copied from elsewhere": "Copiat d'un altre lloc",
"Copied from original": "Copiat de l'original",
"Copyright © 2014-2016 the following Contributors:": "Copyright © 2014-2016 the following Contributors:",
"Copyright © 2014-2017 the following Contributors:": "Copyright © 2014-2017 the following Contributors:",
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Creating ignore patterns, overwriting an existing file at {{path}}.",
"Danger!": "Perill!",
"Deleted": "Esborrat",
"Device": "Device",
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "Device \"{{name}}\" ({{device}} at {{address}}) wants to connect. Add new device?",
"Device ID": "ID del dispositiu",
"Device Identification": "Identificació del dispositiu",
"Device Name": "Nom del dispositiu",
"Devices": "Dispositius",
"Disconnected": "Desconnectat",
"Discovered": "Discovered",
"Discovery": "Descobriment",
"Discovery Failures": "Discovery Failures",
"Documentation": "Documentació",
"Download Rate": "Tasca de descarrega",
"Downloaded": "Descarregat",
"Downloading": "Descarregant",
"Edit": "Editar",
"Edit Device": "Edit Device",
"Edit Folder": "Edit Folder",
"Editing": "Modificant",
"Editing {%path%}.": "Editing {{path}}.",
"Enable NAT traversal": "Enable NAT traversal",
"Enable Relaying": "Enable Relaying",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Introdueix adreces separades per comes (\"tcp://ip:port\", \"tcp://host:port\") o \"dinàmic\" per realitzar descobriments automàtics de l'adreça.",
"Enter ignore patterns, one per line.": "Introduex patrons a ignorar, un per línia.",
"Error": "Error",
"External File Versioning": "Versionat de fitxers extern",
"Failed Items": "Elements fallats",
"Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.": "Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.",
"File Pull Order": "Ordre d'agafar fitxers",
"File Versioning": "Versionat de Fitxers",
"File permission bits are ignored when looking for changes. Use on FAT file systems.": "Els bits de permisos dels fitxers son ignorats quan es cerquen canvis. Utilitzar en sistemes de fitxers FAT.",
"Files are moved to .stversions directory when replaced or deleted by Syncthing.": "Files are moved to .stversions directory when replaced or deleted by Syncthing.",
"Files are moved to .stversions folder when replaced or deleted by Syncthing.": "Els fitxers són moguts a la carpeta .stversions quan són reemplaçats o esborrats per Syncthing.",
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.",
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Els fitxers es mouen amb l'estampat de la data a la carpeta .stversions quan son substituïts o esborrats per syncthing.",
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Els fitxers estan protegits de canvis fets per altres dispositius, però els canvis fets en aquest dispositiu seran enviats a la resta del cluster.",
"Folder": "Carpeta",
"Folder ID": "ID de carpeta",
"Folder Label": "Folder Label",
"Folder Path": "Camí de carpeta",
"Folder Type": "Folder Type",
"Folders": "Carpetes",
"GUI": "GUI",
"GUI Authentication Password": "Contrasenya d'autenticació GUI",
"GUI Authentication User": "Usuari d'autenticació GUI",
"GUI Listen Addresses": "Adreça d'escolta del GUI",
"GUI Theme": "GUI Theme",
"Generate": "Generar",
"Global Changes": "Global Changes",
"Global Discovery": "Descobriment Global",
"Global Discovery Servers": "Global Discovery Servers",
"Global State": "Estat global",
"Help": "Ajuda",
"Home page": "Pàgina d'inici",
"Ignore": "Ignorar",
"Ignore Patterns": "Patrons d'ignoració",
"Ignore Permissions": "Ignora Permisos",
"Incoming Rate Limit (KiB/s)": "Límit de velocitat d'entrada (KiB/s)",
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Una configuració incorrecta pot malmetre els continguts de la teva carpeta i que Syncthing esdevingui inoperatiu.",
"Introduced By": "Introduced By",
"Introducer": "Introductor",
"Inversion of the given condition (i.e. do not exclude)": "Inversió del patrò introduït",
"Keep Versions": "Mantenir Versions",
"Largest First": "Més gran primer",
"Last File Received": "Últim fitxer rebut",
"Last Scan": "Last Scan",
"Last seen": "Vist per última vegada",
"Later": "Després",
"Latest Change": "Latest Change",
"Learn more": "Learn more",
"Listeners": "Listeners",
"Local Discovery": "Descobriment Local",
"Local State": "Estat local",
"Local State (Total)": "Estat local (Total)",
"Major Upgrade": "Actualització major",
"Master": "Master",
"Maximum Age": "Antiguitat Màxima",
"Metadata Only": "Només metadades",
"Minimum Free Disk Space": "Espai de disc lliure mínim",
"Move to top of queue": "Moure al primer de la cua",
"Multi level wildcard (matches multiple directory levels)": "Caràcter comodí de nivell múltiple (aparella en carpetes de nivells múltiples)",
"Never": "Mai",
"New Device": "Nou dispositiu",
"New Folder": "Nova carpeta",
"Newest First": "Més nou primer",
"No": "No",
"No File Versioning": "Sense Versionat de Fitxer",
"No upgrades": "No upgrades",
"Normal": "Normal",
"Notice": "Avís",
"OK": "OK",
"Off": "Desactivar",
"Oldest First": "Més antic primer",
"Optional descriptive label for the folder. Can be different on each device.": "Optional descriptive label for the folder. Can be different on each device.",
"Options": "Opcions",
"Out of Sync": "Fora de sincronia",
"Out of Sync Items": "Arxius encara no sincronitzats",
"Outgoing Rate Limit (KiB/s)": "Límit de velocitat de sortida (KiB/s)",
"Override Changes": "Sobreescriure Canvis",
"Path": "Path",
"Path to the folder on the local computer. Will be created if it does not exist. The tilde character (~) can be used as a shortcut for": "Ruta de la carpeta a l'equip local. Si no existeix serà creada. El caràcter (~) es pot fer servir com a drecera de",
"Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).": "Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).",
"Path where versions should be stored (leave empty for the default .stversions folder in the folder).": "Ruta on les versions s'haurien de guardar (deixa-ho buit per fer servir el directori .stversions per defecte a la carpeta)",
"Pause": "Pausa",
"Pause All": "Pause All",
"Paused": "Pausat",
"Please consult the release notes before performing a major upgrade.": "Si us plau consulta les notes de llançament abans de realitzar una actualització major.",
"Please set a GUI Authentication User and Password in the Settings dialog.": "Si us plau, estableix un usuari i contrasenya al GUI a través del quadre de diàleg de configuració.",
"Please wait": "Si-us-plau espera",
"Preview": "Vista prèvia",
"Preview Usage Report": "Vista Prèvia de l'Informe d'Ús",
"Quick guide to supported patterns": "Guia ràpida per als possibles patrons",
"RAM Utilization": "Utilització de la RAM",
"Random": "Aleatori",
"Reduced by ignore patterns": "Reduced by ignore patterns",
"Release Notes": "Notes de llançament",
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.",
"Remote Devices": "Remote Devices",
"Remove": "Esborrar",
"Required identifier for the folder. Must be the same on all cluster devices.": "Required identifier for the folder. Must be the same on all cluster devices.",
"Rescan": "Re-escanejar",
"Rescan All": "Re-escanejar tot",
"Rescan Interval": "Interval de re-escaneig",
"Restart": "Reiniciar",
"Restart Needed": "És Necessari Reiniciar",
"Restarting": "Reiniciant",
"Resume": "Reprendre",
"Resume All": "Resume All",
"Reused": "Reutilitzat",
"Save": "Guardar",
"Scan Time Remaining": "Temps d'escanejat restant",
"Scanning": "Escanejant",
"Select the devices to share this folder with.": "Selecciona els dispositius en els quals compartir aquesta carpeta.",
"Select the folders to share with this device.": "Selecciona la carpeta per a compartir en aquest dispositiu.",
"Send & Receive": "Send & Receive",
"Send Only": "Send Only",
"Settings": "Preferències",
"Share": "Compartir",
"Share Folder": "Compartir carpeta",
"Share Folders With Device": "Compartir carpetes en dispositiu",
"Share With Devices": "Compartir en dispositius",
"Share this folder?": "Compartir aquesta carpeta?",
"Shared With": "Compartir Amb",
"Show ID": "Mostrar ID",
"Show QR": "Show QR",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Mostrat en comptes del ID del Node en l'estat del cluster. Serà advertit als altres dispositius com un nom opcional per defecte.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Mostrat en comptes del ID del Node en l'estat del cluster. S'actualitzarà al nom del dispositiu si es deixa buit.",
"Shutdown": "Apagar",
"Shutdown Complete": "Apagat complet",
"Simple File Versioning": "Versionat de Fitxers Senzill",
"Single level wildcard (matches within a directory only)": "Caràcter comodí de nivell singular (aparella sóls en una carpeta)",
"Smallest First": "Més petit primer",
"Source Code": "Codi Font",
"Stable releases and release candidates": "Stable releases and release candidates",
"Stable releases are delayed by about two weeks. During this time they go through testing as release candidates.": "Stable releases are delayed by about two weeks. During this time they go through testing as release candidates.",
"Stable releases only": "Stable releases only",
"Staggered File Versioning": "Versionat de Fitxers Esglaonat",
"Start Browser": "Arrancar Navegador",
"Statistics": "Estadístiques",
"Stopped": "Aturat",
"Support": "Suport",
"Sync Protocol Listen Addresses": "Adreça d'escolta del Protocol Sync",
"Syncing": "Synthing",
"Syncthing has been shut down.": "S'ha aturat el synthing.",
"Syncthing includes the following software or portions thereof:": "Syncthing inclou el següent programari o parts dels mateixos:",
"Syncthing is restarting.": "Reiniciant syncthing.",
"Syncthing is upgrading.": "Actualitzant syncthing.",
"Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…": "Synthing sembla parat, o hi ha algun problema amb la connexió a Internet. Reintentant...",
"Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.": "Sembla ser que Syncthing està tinguent problemes per processar la teva petició. Si us plau, refresca la pàgina o reinicia Syncthing si el problema persisteix.",
"The Syncthing admin interface is configured to allow remote access without a password.": "La interfície d'administració de Syncthing està configurada per permetre l'accés remot sense contrasenya.",
"The aggregated statistics are publicly available at the URL below.": "The aggregated statistics are publicly available at the URL below.",
"The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.": "La configuració s'ha guardar però no s'ha activat. S'ha de reiniciar el synthing per activar la nova configuració.",
"The device ID cannot be blank.": "El ID del dispositiu no pot estar en blanc.",
"The device ID to enter here can be found in the \"Actions > Show ID\" dialog on the other device. Spaces and dashes are optional (ignored).": "The device ID to enter here can be found in the \"Actions > Show ID\" dialog on the other device. Spaces and dashes are optional (ignored).",
"The encrypted usage report is sent daily. It is used to track common platforms, folder sizes and app versions. If the reported data set is changed you will be prompted with this dialog again.": "L'informe d'ús encriptat s'envia diàriament. Es fa servir per rastrejar plataformes habituals, mides de carpetes i versions de l'aplicació. Si es canvia el conjunt de dades reportades es demanarà amb aquest diàleg de nou.",
"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.": "El ID del dispositiu introduït no sembla vàlid. Hauria de tenir 52 o 56 caràcters amb lletres i números, els espais i les barres son opcionals.",
"The first command line parameter is the folder path and the second parameter is the relative path in the folder.": "El primer paràmetre de la línia de comandes és el camí a la carpeta i el segon paràmetre és el camí relatiu a la carpeta.",
"The folder ID cannot be blank.": "El ID del dispositiu no pot estar en blanc.",
"The folder ID must be unique.": "El ID de la carpeta ha de ser únic.",
"The folder path cannot be blank.": "El camí a la carpeta no pot estar en blanc.",
"The following intervals are used: for the first hour a version is kept every 30 seconds, for the first day a version is kept every hour, for the first 30 days a version is kept every day, until the maximum age a version is kept every week.": "Es fan servir els següents intervals: per la primera hora es manté una versió cada 30 segons, pel primer dia es manté una versió cada hora, pel primer cada 30 dies es manté una versió cada dia, fins el màxim d'antiguitat es manté una versió cada setmana.",
"The following items could not be synchronized.": "Els següents elements no es poden sincronitzar.",
"The maximum age must be a number and cannot be blank.": "La màxima antiguitat ha de ser un número i no pot estar en blanc.",
"The maximum time to keep a version (in days, set to 0 to keep versions forever).": "Temps màxim en mantenir una versió (en dies, si es deixa en 0 es mantenen les versions per sempre).",
"The minimum free disk space percentage must be a non-negative number between 0 and 100 (inclusive).": "El percentatge d'espai de disc lliure mínim ha de ser un nombre positiu entre 0 i 100 (inclosos).",
"The number of days must be a number and cannot be blank.": "El nombre de dies ha de ser un número i no pot estar en blanc.",
"The number of days to keep files in the trash can. Zero means forever.": "El nombre de dies per guardar els fitxers a la paperera. Zero significa per sempre.",
"The number of old versions to keep, per file.": "El nombre de versions antigues que es mantenen per fitxer.",
"The number of versions must be a number and cannot be blank.": "El nombre de versions ha de ser un número i no es pot deixar en blanc.",
"The path cannot be blank.": "El camí no pot estar en blanc.",
"The rate limit must be a non-negative number (0: no limit)": "El límit de velocitat ha de ser un nombre positiu (0: sense límit)",
"The rescan interval must be a non-negative number of seconds.": "El interval de re-escaneig ha der ser un nombre positiu de segons.",
"They are retried automatically and will be synced when the error is resolved.": "Són reintentats automàticament i seran sincronitzats quan l'error estigui resolt.",
"This Device": "This Device",
"This can easily give hackers access to read and change any files on your computer.": "Això pot donar facilment accés a hackers per llegir i canviar qualsevol fitxer del teu ordinador.",
"This is a major version upgrade.": "Aquesta és una actualització de versió major.",
"Time": "Time",
"Trash Can File Versioning": "Paperera de versionat de fitxers",
"Type": "Type",
"Unknown": "Desconegut",
"Unshared": "No compartit",
"Unused": "No usat",
"Up to Date": "Actualitzat",
"Updated": "Actualitzat",
"Upgrade": "Actualització",
"Upgrade To {%version%}": "Actualitzar a {{version}}",
"Upgrading": "Actualitzant",
"Upload Rate": "Tasca de Pujada",
"Uptime": "Temps funcionant",
"Usage reporting is always enabled for candidate releases.": "Usage reporting is always enabled for candidate releases.",
"Use HTTPS for GUI": "Utilitzar HTTPS pel GUI",
"Version": "Versió",
"Versions Path": "Carpeta 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 son automàticament eliminades si son més antigues que el màxim d'antiguitat o si excedeixen del nombre de fitxers permesos en un interval.",
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Warning, this path is a parent directory of an existing folder \"{{otherFolder}}\".",
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Warning, this path is a parent directory of an existing folder \"{{otherFolderLabel}}\" ({{otherFolder}}).",
"Warning, this path is a subdirectory of an existing folder \"{%otherFolder%}\".": "Warning, this path is a subdirectory of an existing folder \"{{otherFolder}}\".",
"Warning, this path is a subdirectory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Warning, this path is a subdirectory of an existing folder \"{{otherFolderLabel}}\" ({{otherFolder}}).",
"When adding a new device, keep in mind that this device must be added on the other side too.": "Quan s'afegeix un nou dispositiu, recorda que aquest dispositiu tambè s'ha d'afegir a l'altre banda.",
"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.": "Quan s'afegeix una nova carpeta recorda que el ID d'aquesta s'utilitza per lligar repositoris entre els dispositius. Es distingeix entre majúscules i minúscules i ha de ser exactament iguals entre tots els dispositius.",
"Yes": "Si",
"You can change your choice at any time in the Settings dialog.": "You can change your choice at any time in the Settings dialog.",
"You can read more about the two release channels at the link below.": "You can read more about the two release channels at the link below.",
"You must keep at least one version.": "Has de mantenir com a mínim una versió.",
"days": "dies",
"directories": "directories",
"files": "files",
"full documentation": "documentació sencera",
"items": "Elements",
"{%device%} wants to share folder \"{%folder%}\".": "{{device}} vol compartir la carpeta \"{{folder}}\".",
"{%device%} wants to share folder \"{%folderlabel%}\" ({%folder%}).": "{{device}} wants to share folder \"{{folderlabel}}\" ({{folder}})."
}

View File

@@ -4,12 +4,13 @@
"A new major version may not be compatible with previous versions.": "Una nova versión amb canvis importants pot no ser compatible amb versions prèvies.",
"API Key": "Clau API",
"About": "Sobre",
"Action": "Action",
"Action": "Acció",
"Actions": "Accions",
"Add": "Afegir",
"Add Device": "Afegir dispositiu",
"Add Folder": "Afegir carpeta",
"Add Remote Device": "Afegir Dispositiu Remot.",
"Add devices from the introducer to our device list, for mutually shared folders.": "Afegir dispositius des-de l'introductor a la nostra llista de dispositius, per a tindre carpetes compartides mútuament",
"Add new folder?": "Afegir nova carpeta?",
"Address": "Direcció",
"Addresses": "Direccions",
@@ -18,20 +19,20 @@
"Advanced settings": "Ajustos avançats.",
"All Data": "Totes les dades",
"Allow Anonymous Usage Reporting?": "Permetre informes d'ús anònim?",
"Allowed Networks": "Allowed Networks",
"Allowed Networks": "Xarxes permeses",
"Alphabetic": "Alfabètic",
"An external command handles the versioning. It has to remove the file from the shared folder.": "An external command handles the versioning. It has to remove the file from the shared folder.",
"An external command handles the versioning. It has to remove the file from the shared folder.": "Un command extern maneja les versions. Té que eliminar el fitxer de la carpeta compartida.",
"An external command handles the versioning. It has to remove the file from the synced folder.": "Un comando extern controla el versionat. És necessari eliminar el fitxer de la carpeta sincronitzada.",
"Anonymous Usage Reporting": "Informe d'ús anònim",
"Any devices configured on an introducer device will be added to this device as well.": "Tots els dispositius configurats en un dispositiu presentador seràn afegits també a aquest dispositiu.",
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Automatic upgrade now offers the choice between stable releases and release candidates.",
"Automatic upgrade now offers the choice between stable releases and release candidates.": "L'actualització automàtica ara ofereix l'elecció entre les versions estables i les versions candidates.",
"Automatic upgrades": "Actualitzacions automàtiques",
"Be careful!": "Tin precaució!",
"Bugs": "Errors (Bugs)",
"CPU Utilization": "Utilització de la CPU",
"Changelog": "Registre de canvis",
"Clean out after": "Netejar després de",
"Click to see discovery failures": "Click to see discovery failures",
"Click to see discovery failures": "Clica per a vore els fallos en el descobriment",
"Close": "Tancar",
"Command": "Comando",
"Comment, when used at the start of a line": "Comentar, quant s'utilitza al principi d'una línia",
@@ -42,11 +43,11 @@
"Copied from elsewhere": "Copiat de qualsevol lloc",
"Copied from original": "Copiat de l'original",
"Copyright © 2014-2016 the following Contributors:": "Copyright © 2014-2016 els següents Col·laboradors:",
"Copyright © 2014-2017 the following Contributors:": "Copyright © 2014-2017 the following Contributors:",
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Creating ignore patterns, overwriting an existing file at {{path}}.",
"Copyright © 2014-2017 the following Contributors:": "Copyright © 2014-2017 els següents Col·laboradors:",
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Creant patrons a ignorar, sobreescriguent un fitxer que ja existeix a {{path}}.",
"Danger!": "Perill!",
"Deleted": "Esborrat",
"Device": "Device",
"Device": "Dispositiu",
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "Dispositiu \"{{name}}\" ({{device}} a l'adreça {{address}}) vol connectar. Afegir nou dispositiu?",
"Device ID": "ID del dispositiu",
"Device Identification": "Identificació del dispositiu",
@@ -55,7 +56,7 @@
"Disconnected": "Desconnectat",
"Discovered": "Descobert",
"Discovery": "Descobriment",
"Discovery Failures": "Discovery Failures",
"Discovery Failures": "Fallades al Descobriment",
"Documentation": "Documentació",
"Download Rate": "Velocitat de descàrrega",
"Downloaded": "Descarregat",
@@ -64,21 +65,23 @@
"Edit Device": "Editar Dispositiu",
"Edit Folder": "Editar Carpeta",
"Editing": "Editant",
"Editing {%path%}.": "Editing {{path}}.",
"Editing {%path%}.": "Editant {{path}}.",
"Enable NAT traversal": "Permetre NAT transversal",
"Enable Relaying": "Permetre Transmissions",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Introdueix un nombre no negatiu (per exemple, \"2.35\") i selecciona una unitat. Els percentatges són com a part del tamany total del disc.",
"Enter a non-privileged port number (1024 - 65535).": "Introdueix un nombre de port sense privilegis (1024-65535).",
"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 ignore patterns, one per line.": "Introduïr patrons a ignorar, un per línia.",
"Error": "Error",
"External File Versioning": "Versionat extern de fitxers",
"Failed Items": "Objectes fallits",
"Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.": "Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.",
"Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.": "És possible que es produïsca una fallada al connectar als servidors IPv6 si no hi ha connectivitat IPv6.",
"File Pull Order": "Ordre de fitxers del pull",
"File Versioning": "Versionat de fitxer",
"File permission bits are ignored when looking for changes. Use on FAT file systems.": "Els bits de permís del fitxer són ignorats quant es busquen els canvis. Utilitzar en sistemes de fitxers FAT.",
"Files are moved to .stversions directory when replaced or deleted by Syncthing.": "Files are moved to .stversions directory when replaced or deleted by Syncthing.",
"Files are moved to .stversions directory when replaced or deleted by Syncthing.": "Els fitxers seràn moguts al directori .stversions quant siguen reemplaçats o esborrats per Syncthing.",
"Files are moved to .stversions folder when replaced or deleted by Syncthing.": "Els arxius es menejen a la carpeta .stversions quant són substituïts o esborrats per Syncthing.",
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.",
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Els arxius seran moguts a un directori .stversions a versions amb control de la data quan siguen reemplaçats o esborrats per Syncthing.",
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Els fitxers són canviats a versions amb indicació de data en una carpeta \".stversions\" quant són reemplaçats o esborrats per Syncthing.",
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Els fitxers són protegits dels canvis fets en altres dispositius, però els canvis fets en aquest dispositiu seràn enviats a la resta del grup (cluster).",
"Folder": "Carpeta",
@@ -90,10 +93,11 @@
"GUI": "IGU (Interfície Gràfica d'Usuari)",
"GUI Authentication Password": "Password d'autenticació de l'Interfície Gràfica d'Usuari (GUI)",
"GUI Authentication User": "Autenticació de l'usuari de l'Interfície Gràfica d'Usuari (GUI)",
"GUI Listen Address": "Adreça d'Escolta de l'Interfície Gràfica d'Usuari (GUI).",
"GUI Listen Addresses": "Direcció d'escolta de l'Interfície Gràfica d'Usuari (GUI)",
"GUI Theme": "GUI Theme",
"GUI Theme": "Tema de l'Interfície Gràfica d'Usuari (GUI)",
"Generate": "Generar",
"Global Changes": "Global Changes",
"Global Changes": "Canvis Globals",
"Global Discovery": "Descobriment global",
"Global Discovery Servers": "Servidors de Descobriment Global",
"Global State": "Estat global",
@@ -104,7 +108,7 @@
"Ignore Permissions": "Permisos a ignorar",
"Incoming Rate Limit (KiB/s)": "Límit de descàrrega (KiB/s)",
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "La configuración incorrecta pot danyar el contingut de la teua carpeta i deixar Syncthing inoperatiu.",
"Introduced By": "Introduced By",
"Introduced By": "Introduït Per",
"Introducer": "Presentador",
"Inversion of the given condition (i.e. do not exclude)": "Inversió de la condició donada (per exemple no excloure)",
"Keep Versions": "Mantindre versions",
@@ -114,7 +118,7 @@
"Last seen": "Vist per última vegada",
"Later": "Més tard",
"Latest Change": "Últim Canvi",
"Learn more": "Learn more",
"Learn more": "Saber més",
"Listeners": "Escoltants",
"Local Discovery": "Descobriment local",
"Local State": "Estat local",
@@ -132,7 +136,7 @@
"Newest First": "El més nou primer",
"No": "No",
"No File Versioning": "Sense versionat de fitxer",
"No upgrades": "No upgrades",
"No upgrades": "Sense actualitzacions",
"Normal": "Normal",
"Notice": "Avís",
"OK": "OK",
@@ -144,12 +148,12 @@
"Out of Sync Items": "Dispositius sense sincronitzar",
"Outgoing Rate Limit (KiB/s)": "Límit de pujada (KiB/s)",
"Override Changes": "Sobreescriure els canvis",
"Path": "Path",
"Path": "Ruta",
"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": "Ruta a la carpeta local en l'ordinador. Es crearà si no existeix. El caràcter tilde (~) es pot utilitzar com a drecera",
"Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).": "Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).",
"Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).": "La ruta on deuen guardar-se les versions (deixar buit per al directori per defecte .stversions en la carpeta compartida).",
"Path where versions should be stored (leave empty for the default .stversions folder in the folder).": "Ruta on les versions deurien estar emmagatzemades (deixar buit per a la carpeta .stversions en la carpeta).",
"Pause": "Pausa",
"Pause All": "Pause All",
"Pause All": "Pausa Tot",
"Paused": "Pausat",
"Please consult the release notes before performing a major upgrade.": "Per favor, consultar les notes de la versió abans de fer una actualització important.",
"Please set a GUI Authentication User and Password in the Settings dialog.": "Per favor, estableix un usuari i password per a l'Interfície Gràfica d'Usuari en el menú d'Adjustos.",
@@ -161,7 +165,7 @@
"Random": "Aleatori",
"Reduced by ignore patterns": "Reduït ignorant patrons",
"Release Notes": "Notes de la versió",
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.",
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Les versions candidates (Release Candidates) contenen les darreres característiques i arreglos. Són paregudes a les versions tradicionals bi-semanals de Syncthing. ",
"Remote Devices": "Dispositius Remots",
"Remove": "Eliminar",
"Required identifier for the folder. Must be the same on all cluster devices.": "Identificador necessari per la carpeta. Deu ser el mateix en tots els dispositius del cluster.",
@@ -172,7 +176,7 @@
"Restart Needed": "Reinici necesari",
"Restarting": "Reiniciant",
"Resume": "Continuar",
"Resume All": "Resume All",
"Resume All": "Continuar Tot",
"Reused": "Reutilitzat",
"Save": "Gravar",
"Scan Time Remaining": "Temps d'escaneig restant",
@@ -198,9 +202,9 @@
"Single level wildcard (matches within a directory only)": "Comodí de nivell únic (coincideix sols dins d'un directori)",
"Smallest First": "El més xicotet primer",
"Source Code": "Codi font",
"Stable releases and release candidates": "Stable releases and release candidates",
"Stable releases are delayed by about two weeks. During this time they go through testing as release candidates.": "Stable releases are delayed by about two weeks. During this time they go through testing as release candidates.",
"Stable releases only": "Stable releases only",
"Stable releases and release candidates": "Versions estables i versions candidates",
"Stable releases are delayed by about two weeks. During this time they go through testing as release candidates.": "Les versions estables es retrasen sobre dos setmanes. Durant aquest temps es fiquen a prova com versions candidates.",
"Stable releases only": "Solament versions estables",
"Staggered File Versioning": "Versionat de fitxers escalonat",
"Start Browser": "Iniciar navegador",
"Statistics": "Estadístiques",
@@ -241,9 +245,10 @@
"This Device": "Aquest Dispositiu",
"This can easily give hackers access to read and change any files on your computer.": "Açò pot donar accés fàcilment als hackers per a llegir i canviar qualsevol fitxer al teu ordinador.",
"This is a major version upgrade.": "Aquesta és una actualització important de la versió.",
"Time": "Time",
"This setting controls the free space required on the home (i.e., index database) disk.": "Aquest ajust controla l'espai lliure requerit en el disc inicial (per exemple, la base de dades de l'index).",
"Time": "Temps",
"Trash Can File Versioning": "Versionat d'arxius de la paperera",
"Type": "Type",
"Type": "Tipus",
"Unknown": "Desconegut",
"Unshared": "No compartit",
"Unused": "No utilitzat",
@@ -254,20 +259,20 @@
"Upgrading": "Actualitzant",
"Upload Rate": "Velocitat d'actualització",
"Uptime": "Temps de funcionament",
"Usage reporting is always enabled for candidate releases.": "Usage reporting is always enabled for candidate releases.",
"Use HTTPS for GUI": "Utilitzar HTTP per a l'Interfície Gràfica d'Usuari (GUI)",
"Usage reporting is always enabled for candidate releases.": "Els informes d'ús sempre estan activats per a les versions candidates.",
"Use HTTPS for GUI": "Utilitzar HTTPS per a l'Interfície Gràfica d'Usuari (GUI)",
"Version": "Versió",
"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.",
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Warning, this path is a parent directory of an existing folder \"{{otherFolder}}\".",
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Warning, this path is a parent directory of an existing folder \"{{otherFolderLabel}}\" ({{otherFolder}}).",
"Warning, this path is a subdirectory of an existing folder \"{%otherFolder%}\".": "Perill! Aquesta ruta és un subdirectori d'una carpeta que ja existeix nomenada \"{{otherFolder}}\".",
"Warning, this path is a subdirectory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Warning, this path is a subdirectory of an existing folder \"{{otherFolderLabel}}\" ({{otherFolder}}).",
"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}}).",
"Warning, this path is a subdirectory of an existing folder \"{%otherFolder%}\".": "Perill! Esta ruta és un subdirectori d'una carpeta que ja existeix nomenada \"{{otherFolder}}\".",
"Warning, this path is a subdirectory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Perill! Esta ruta és un subdirectori de una carpeta existent \"{{otherFolderLabel}}\" ({{otherFolder}}).",
"When adding a new device, keep in mind that this device must be added on the other side too.": "Quant s'afig un nou dispositiu, hi ha que tindre en compte que aquest dispositiu deu ser afegit també en l'altre costat.",
"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.": "Quant s'afig una nova carpeta, hi ha que tindre en compte que l'ID de la carpeta s'utilitza per a juntar les carpetes entre dispositius. Són sensibles a les majúscules i deuen coincidir exactament entre tots els dispositius.",
"Yes": "Sí",
"You can change your choice at any time in the Settings dialog.": "You can change your choice at any time in the Settings dialog.",
"You can read more about the two release channels at the link below.": "You can read more about the two release channels at the link below.",
"You can change your choice at any time in the Settings dialog.": "Pots canviar la teua elecció en qualsevol moment en el dialog Ajustos",
"You can read more about the two release channels at the link below.": "Pots llegir més sobre els dos canals de versions en l'enllaç de baix.",
"You must keep at least one version.": "Es deu mantindre al menys una versió.",
"days": "dies",
"directories": "directoris",

View File

@@ -10,6 +10,7 @@
"Add Device": "Přidat přístroj",
"Add Folder": "Přidat adresář",
"Add Remote Device": "Přidat vzdálené zařízení",
"Add devices from the introducer to our device list, for mutually shared folders.": "Přidat zařízení ze zavaděče do našeho seznamu zařízení (pro vzájemně sdílené adresáře.)",
"Add new folder?": "Přidat nový adresář?",
"Address": "Adresa",
"Addresses": "Adresy",
@@ -67,6 +68,8 @@
"Editing {%path%}.": "Editace {{path}}.",
"Enable NAT traversal": "Povolit NAT přenos",
"Enable Relaying": "Povolit přenašeče",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Zadajte kladné číslo (např. \"2.35\") a zvolte jednotku. Percenta znamenají část celkové velikosti disku.",
"Enter a non-privileged port number (1024 - 65535).": "Enter a non-privileged port number (1024 - 65535).",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Zadejte adresy oddělené čárkou (\"tcp://ip:port\", \"tcp://host:port\") nebo \"dynamic\" pro automatické zjišťování adres.",
"Enter ignore patterns, one per line.": "Vložit ignorované vzory, jeden na řádek.",
"Error": "Chyba",
@@ -90,6 +93,7 @@
"GUI": "GUI",
"GUI Authentication Password": "Přihlašovací heslo pro GUI",
"GUI Authentication User": "Přihlašovací jméno pro GUI",
"GUI Listen Address": "GUI Listen Address",
"GUI Listen Addresses": "Adresa naslouchání GUI",
"GUI Theme": "Grafické téma",
"Generate": "Generovat",
@@ -241,6 +245,7 @@
"This Device": "Toto zařízení",
"This can easily give hackers access to read and change any files on your computer.": "To může útočníkům jednoduše povolit čtení a úpravy souborů na vašem přístroji. ",
"This is a major version upgrade.": "Toto je důležitá aktualizace.",
"This setting controls the free space required on the home (i.e., index database) disk.": "This setting controls the free space required on the home (i.e., index database) disk.",
"Time": "Čas",
"Trash Can File Versioning": "Verzování souborů v koši",
"Type": "Typ",

View File

@@ -10,6 +10,7 @@
"Add Device": "Tilføj enhed",
"Add Folder": "Tilføj mappe",
"Add Remote Device": "Tilføj fjernenhed",
"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?": "Tilføj ny mappe",
"Address": "Adresse",
"Addresses": "Adresser",
@@ -18,7 +19,7 @@
"Advanced settings": "Avancerede indstillinger",
"All Data": "Alt data",
"Allow Anonymous Usage Reporting?": "Tillad anonym brugerstatistik?",
"Allowed Networks": "Allowed Networks",
"Allowed Networks": "Tilladte netværk",
"Alphabetic": "Alfabetisk",
"An external command handles the versioning. It has to remove the file from the shared folder.": "En ekstern kommando styrer versioneringen. Den skal fjerne filen fra den delte mappe.",
"An external command handles the versioning. It has to remove the file from the synced folder.": " ",
@@ -64,9 +65,11 @@
"Edit Device": "Rediger enhed",
"Edit Folder": "Rediger mappe",
"Editing": "Redigerer",
"Editing {%path%}.": "Editing {{path}}.",
"Editing {%path%}.": "Redigerer {{path}}.",
"Enable NAT traversal": "Aktiver NAT",
"Enable Relaying": "Aktiver Relaying",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.",
"Enter a non-privileged port number (1024 - 65535).": "Enter a non-privileged port number (1024 - 65535).",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Angiv kommaseparerede adresser (\"tcp://ip:port\", \"tcp://host:port\") eller \"dynamic\" for at benytte automatisk opdagelse af adressen.",
"Enter ignore patterns, one per line.": "Vælg ignorer maske, én per linje.",
"Error": "Fejl",
@@ -90,6 +93,7 @@
"GUI": "GUI",
"GUI Authentication Password": "GUI-kodeord",
"GUI Authentication User": "GUI-brugernavn",
"GUI Listen Address": "GUI Listen Address",
"GUI Listen Addresses": "GUI-lytteadresse",
"GUI Theme": "GUI tema",
"Generate": "Opret",
@@ -162,7 +166,7 @@
"Reduced by ignore patterns": "Reduceret af ignorerings mønsteret. ",
"Release Notes": "Udgivelsesnoter",
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Udgivelseskandidater indeholder alle de nyeste funktioner og rettelser. De er ens med de traditionelle 2 ugers Syncthing udgivelser.",
"Remote Devices": "Fjern Enheder ",
"Remote Devices": "Fjernenheder ",
"Remove": "Fjern",
"Required identifier for the folder. Must be the same on all cluster devices.": "Nødvendig identifikation af mappen. Dette skal være det samme på alle enheder.",
"Rescan": "Skan igen",
@@ -241,6 +245,7 @@
"This Device": "Denne Enhed",
"This can easily give hackers access to read and change any files on your computer.": "Dette gør det nemt for hackere at få adgang til at læse og ændre filer på din computer.",
"This is a major version upgrade.": "Dette er en ny version",
"This setting controls the free space required on the home (i.e., index database) disk.": "This setting controls the free space required on the home (i.e., index database) disk.",
"Time": "Tid",
"Trash Can File Versioning": "Skraldespand fil versioner",
"Type": "Type",

View File

@@ -10,6 +10,7 @@
"Add Device": "Gerät hinzufügen",
"Add Folder": "Ordner hinzufügen",
"Add Remote Device": "Gerät hinzufügen",
"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?": "Neuen Ordner hinzufügen?",
"Address": "Adresse",
"Addresses": "Adressen",
@@ -18,7 +19,7 @@
"Advanced settings": "Erweiterte Einstellungen",
"All Data": "Alle Daten",
"Allow Anonymous Usage Reporting?": "Übertragung von anonymen Nutzungsberichten erlauben?",
"Allowed Networks": "Allowed Networks",
"Allowed Networks": "Erlaubte Netzwerke",
"Alphabetic": "Alphabetisch",
"An external command handles the versioning. It has to remove the file from the shared folder.": "Ein externer Befehl führt die Versionierung durch. Dazu muss die Datei aus dem geteilten Ordner entfernt werden.",
"An external command handles the versioning. It has to remove the file from the synced folder.": "Ein externer Programmaufruf handhabt die Versionierung. Es muss die Datei aus dem zu synchronisierendem Ordner entfernen.",
@@ -64,9 +65,11 @@
"Edit Device": "Gerät bearbeiten",
"Edit Folder": "Ordner bearbeiten",
"Editing": "Bearbeitet",
"Editing {%path%}.": "Editing {{path}}.",
"Editing {%path%}.": "{{path}} wird bearbeitet.",
"Enable NAT traversal": "NAT-Durchdringung aktivieren",
"Enable Relaying": "Weiterleitung aktivieren",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.",
"Enter a non-privileged port number (1024 - 65535).": "Enter a non-privileged port number (1024 - 65535).",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "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.",
"Error": "Fehler",
@@ -90,6 +93,7 @@
"GUI": "GUI",
"GUI Authentication Password": "Passwort für Zugang zur Benutzeroberfläche",
"GUI Authentication User": "Nutzername für Zugang zur Benutzeroberfläche",
"GUI Listen Address": "GUI Listen Address",
"GUI Listen Addresses": "Adresse(n) für die Benutzeroberfläche",
"GUI Theme": "GUI-Theme",
"Generate": "Generieren",
@@ -241,6 +245,7 @@
"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.",
"This is a major version upgrade.": "Dies ist eine neue Hauptversion.",
"This setting controls the free space required on the home (i.e., index database) disk.": "This setting controls the free space required on the home (i.e., index database) disk.",
"Time": "Zeit",
"Trash Can File Versioning": "Papierkorb Dateiversionierung",
"Type": "Typ",

View File

@@ -10,6 +10,7 @@
"Add Device": "Προσθήκη συσκευής",
"Add Folder": "Προσθήκη φακέλου",
"Add Remote Device": "Προσθήκη Απομακρυσμένης Συσκευής",
"Add devices from the introducer to our device list, for mutually shared folders.": "Προσθήκη συσκευών από το Βασικό κόμβο στη λίστα συσκευών μας, για όσους κοινούς φακέλους υπάρχουν μεταξύ τους.",
"Add new folder?": "Προσθήκη νέου φακέλου;",
"Address": "Διεύθυνση",
"Addresses": "Διευθύνσεις",
@@ -18,7 +19,7 @@
"Advanced settings": "Προχωρημένες ρυθμίσεις",
"All Data": "Όλα τα δεδομένα",
"Allow Anonymous Usage Reporting?": "Να επιτρέπεται η αποστολή ανώνυμων στοιχείων χρήσης;",
"Allowed Networks": "Allowed Networks",
"Allowed Networks": "Επιτρεπόμενα δίκτυα",
"Alphabetic": "Αλφαβητικά",
"An external command handles the versioning. It has to remove the file from the shared folder.": "Μια εξωτερική εντολή χειρίζεται την τήρηση εκδόσεων και αναλαμβάνει να αφαιρέσει το αρχείο από τον συγχρονισμένο φάκελο.",
"An external command handles the versioning. It has to remove the file from the synced folder.": "Μια εξωτερική εντολή χειρίζεται την διαχείριση εκδόσεων. Χρειάζεται να αφαιρέσει το αρχείο από το φάκελο συγχρονισμένων.",
@@ -31,7 +32,7 @@
"CPU Utilization": "Επιβάρυνση του επεξεργαστή",
"Changelog": "Πληροφορίες εκδόσεων",
"Clean out after": "Εκκαθάριση μετά από",
"Click to see discovery failures": "Click to see discovery failures",
"Click to see discovery failures": "Πατήστε για να δείτε τις αποτυχίες ανεύρεσης συσκευών",
"Close": "Τέλος",
"Command": "Εντολή",
"Comment, when used at the start of a line": "Σχόλιο, όταν χρησιμοποιείται στην αρχή μιας γραμμής",
@@ -43,7 +44,7 @@
"Copied from original": "Έχει αντιγραφεί από το πρωτότυπο",
"Copyright © 2014-2016 the following Contributors:": "Copyright © 2014-2016 για τους παρακάτω συνεισφέροντες:",
"Copyright © 2014-2017 the following Contributors:": "Copyright © 2014-2017 για τους παρακάτω συνεισφέροντες:",
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Creating ignore patterns, overwriting an existing file at {{path}}.",
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Δημιουργία προτύπων αγνόησης, αντικατάσταση του υπάρχοντος αρχείου στο {{path}}.",
"Danger!": "Προσοχή!",
"Deleted": "Διαγραμμένα",
"Device": "Συσκευή",
@@ -64,9 +65,11 @@
"Edit Device": "Επεξεργασία συσκευής",
"Edit Folder": "Επεξεργασία φακέλου",
"Editing": "Επεξεργασία σε εξέλιξη",
"Editing {%path%}.": "Editing {{path}}.",
"Editing {%path%}.": "Επεξεργασία του {{path}}.",
"Enable NAT traversal": "Ενεργοποίηση διάσχισης NAT",
"Enable Relaying": "Ενεργοποίηση αναμετάδοσης",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Εισάγετε έναν μη αρνητικό αριθμό (π.χ. «2.35») και επιλέξτε μια μονάδα μέτρησης. Τα ποσοστά ισχύουν ως προς το συνολικό μέγεθος του δίσκου.",
"Enter a non-privileged port number (1024 - 65535).": "Εισάγετε τον αριθμό μιας μη δεσμευμένης θύρας (1024 - 65535).",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Εισάγετε τις διευθύνσεις χωρισμένες με κόμμα (\"tcp://ip:port\", \"tcp://host:port\") ή γράψτε \"dynamic\" για την αυτόματη ανεύρεση τους.",
"Enter ignore patterns, one per line.": "Δώσε τα πρότυπα που θα αγνοηθούν, ένα σε κάθε γραμμή.",
"Error": "Σφάλμα",
@@ -90,6 +93,7 @@
"GUI": "Γραφικό περιβάλλον",
"GUI Authentication Password": "Κωδικός για την πρόσβαση στη διεπαφή",
"GUI Authentication User": "Χρηστώνυμο για την πρόσβαση στη διεπαφή",
"GUI Listen Address": "Διεύθυνση ακρόασης γραφικού περιβάλλοντος (GUI)",
"GUI Listen Addresses": "Διευθύνσεις από τις οποίες θα είναι προσβάσιμη η διεπαφή",
"GUI Theme": "Θέμα GUI",
"Generate": "Δημιουργία",
@@ -241,6 +245,7 @@
"This Device": "Αυτή η συσκευή",
"This can easily give hackers access to read and change any files on your computer.": "Αυτό μπορεί εύκολα να δώσει πρόσβαση ανάγνωσης και επεξεργασίας αρχείων του υπολογιστή σας σε χάκερς.",
"This is a major version upgrade.": "Αυτή είναι μια σημαντική αναβάθμιση.",
"This setting controls the free space required on the home (i.e., index database) disk.": "Αυτή η επιλογή καθορίζει τον ελεύθερο χώρο που θα παραμένει ελεύθερος στον δίσκο όπου βρίσκεται ο κατάλογος της εφαρμογής (και συνεπώς η βάση δεδομένων ευρετηρίων).",
"Time": "Χρόνος",
"Trash Can File Versioning": "Τήρηση εκδόσεων κάδου ανακύκλωσης",
"Type": "Τύπος",

View File

@@ -10,6 +10,7 @@
"Add Device": "Add Device",
"Add Folder": "Add Folder",
"Add Remote Device": "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?": "Add new folder?",
"Address": "Address",
"Addresses": "Addresses",
@@ -67,6 +68,8 @@
"Editing {%path%}.": "Editing {{path}}.",
"Enable NAT traversal": "Enable NAT traversal",
"Enable Relaying": "Enable Relaying",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.",
"Enter a non-privileged port number (1024 - 65535).": "Enter a non-privileged port number (1024 - 65535).",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "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.",
"Error": "Error",
@@ -90,6 +93,7 @@
"GUI": "GUI",
"GUI Authentication Password": "GUI Authentication Password",
"GUI Authentication User": "GUI Authentication User",
"GUI Listen Address": "GUI Listen Address",
"GUI Listen Addresses": "GUI Listen Addresses",
"GUI Theme": "GUI Theme",
"Generate": "Generate",
@@ -241,6 +245,7 @@
"This Device": "This Device",
"This can easily give hackers access to read and change any files on your computer.": "This can easily give hackers access to read and change any files on your computer.",
"This is a major version upgrade.": "This is a major version upgrade.",
"This setting controls the free space required on the home (i.e., index database) disk.": "This setting controls the free space required on the home (i.e., index database) disk.",
"Time": "Time",
"Trash Can File Versioning": "Rubbish Bin File Versioning",
"Type": "Type",

View File

@@ -10,6 +10,7 @@
"Add Device": "Add Device",
"Add Folder": "Add Folder",
"Add Remote Device": "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?": "Add new folder?",
"Address": "Address",
"Addresses": "Addresses",
@@ -43,6 +44,7 @@
"Copied from original": "Copied from original",
"Copyright © 2014-2016 the following Contributors:": "Copyright © 2014-2016 the following Contributors:",
"Copyright © 2014-2017 the following Contributors:": "Copyright © 2014-2017 the following Contributors:",
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Creating ignore patterns, overwriting an existing file at {{path}}.",
"Danger!": "Danger!",
"Deleted": "Deleted",
"Device": "Device",
@@ -63,8 +65,11 @@
"Edit Device": "Edit Device",
"Edit Folder": "Edit Folder",
"Editing": "Editing",
"Editing {%path%}.": "Editing {{path}}.",
"Enable NAT traversal": "Enable NAT traversal",
"Enable Relaying": "Enable Relaying",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.",
"Enter a non-privileged port number (1024 - 65535).": "Enter a non-privileged port number (1024 - 65535).",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "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.",
"Error": "Error",
@@ -88,6 +93,7 @@
"GUI": "GUI",
"GUI Authentication Password": "GUI Authentication Password",
"GUI Authentication User": "GUI Authentication User",
"GUI Listen Address": "GUI Listen Address",
"GUI Listen Addresses": "GUI Listen Addresses",
"GUI Theme": "GUI Theme",
"Generate": "Generate",
@@ -239,6 +245,7 @@
"This Device": "This Device",
"This can easily give hackers access to read and change any files on your computer.": "This can easily give hackers access to read and change any files on your computer.",
"This is a major version upgrade.": "This is a major version upgrade.",
"This setting controls the free space required on the home (i.e., index database) disk.": "This setting controls the free space required on the home (i.e., index database) disk.",
"Time": "Time",
"Trash Can File Versioning": "Trash Can File Versioning",
"Type": "Type",

View File

@@ -10,6 +10,7 @@
"Add Device": "Aldonu Aparaton",
"Add Folder": "Aldonu Dosierujon",
"Add Remote Device": "Aldonu Foran Aparaton",
"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?": "Aldoni novan dosierujon?",
"Address": "Adreso",
"Addresses": "Adresoj",
@@ -67,6 +68,8 @@
"Editing {%path%}.": "Redaktado {{path}}.",
"Enable NAT traversal": "Ŝaltu trairan NAT",
"Enable Relaying": "Ŝaltu Relajsadon",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.",
"Enter a non-privileged port number (1024 - 65535).": "Enter a non-privileged port number (1024 - 65535).",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Enigi 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.": "Entajpu ignori skemojn, unu po linio.",
"Error": "Eraro",
@@ -90,6 +93,7 @@
"GUI": "Grafika Interfaco",
"GUI Authentication Password": "Pasvorta Aŭtentigo en Grafika Interfaco",
"GUI Authentication User": "Uzanta Aŭtentigo en Grafika Interfaco",
"GUI Listen Address": "GUI Listen Address",
"GUI Listen Addresses": "Aŭskultado de Adresoj en Grafika Interfaco",
"GUI Theme": "Etoso de Grafika Interfaco",
"Generate": "Generi",
@@ -241,6 +245,7 @@
"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.",
"This is a major version upgrade.": "Ĉi tio estas ĉefversio ĝisdatigita.",
"This setting controls the free space required on the home (i.e., index database) disk.": "This setting controls the free space required on the home (i.e., index database) disk.",
"Time": "Tempo",
"Trash Can File Versioning": "Rubujo ebligas Dosieran Versionadon",
"Type": "Tipo",

View File

@@ -10,6 +10,7 @@
"Add Device": "Agregar el dispositivo",
"Add Folder": "Agregar Carpeta",
"Add Remote Device": "Añadir un dispositivo",
"Add devices from the introducer to our device list, for mutually shared folders.": "Añadir dispositivos desde el introductor a nuestra lista de dispositivos, para las carpetas compartidas mutuamente.",
"Add new folder?": "¿Agregar una carpeta nueva?",
"Address": "Dirección",
"Addresses": "Direcciones",
@@ -18,9 +19,9 @@
"Advanced settings": "Ajustes avanzados",
"All Data": "Todos los datos",
"Allow Anonymous Usage Reporting?": "¿Deseas permitir el envío anónimo de informes de uso?",
"Allowed Networks": "Allowed Networks",
"Allowed Networks": "Redes permitidas",
"Alphabetic": "Alfabético",
"An external command handles the versioning. It has to remove the file from the shared folder.": "An external command handles the versioning. It has to remove the file from the shared folder.",
"An external command handles the versioning. It has to remove the file from the shared folder.": "Un comando externo gestiona las versiones. Tiene que eliminar el fichero de la carpeta compartida.",
"An external command handles the versioning. It has to remove the file from the synced folder.": "Un comando externo controla la versión. El fichero debe ser eliminado de la carpeta sincronizada.",
"Anonymous Usage Reporting": "Informe anónimo de uso",
"Any devices configured on an introducer device will be added to this device as well.": "Cualquier dispositivo configurado en un dispositivo de introducción será añadido también.",
@@ -31,7 +32,7 @@
"CPU Utilization": "Uso de CPU",
"Changelog": "Registro de cambios",
"Clean out after": "Limpiar tras",
"Click to see discovery failures": "Click to see discovery failures",
"Click to see discovery failures": "Clica para ver fallos de descubrimiento.",
"Close": "Cerrar",
"Command": "Acción",
"Comment, when used at the start of a line": "Comentar, cuando se usa al comienzo de una línea",
@@ -43,7 +44,7 @@
"Copied from original": "Copiado del original",
"Copyright © 2014-2016 the following Contributors:": "Copyright © 2014-2016 los siguientes Colaboradores:",
"Copyright © 2014-2017 the following Contributors:": "Copyright © 2014-2017 Los siguientes colaboradores:",
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Creating ignore patterns, overwriting an existing file at {{path}}.",
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Crear patrones a ignorar, sobreescribiendo un fichero existente en {{path}}.",
"Danger!": "¡Peligro!",
"Deleted": "Eliminado",
"Device": "Dispositivo",
@@ -55,7 +56,7 @@
"Disconnected": "Desconectado",
"Discovered": "Descubierto",
"Discovery": "Descubrimiento",
"Discovery Failures": "Discovery Failures",
"Discovery Failures": "Fallos de Descubrimiento",
"Documentation": "Documentación",
"Download Rate": "Velocidad de descarga",
"Downloaded": "Descargado",
@@ -64,21 +65,23 @@
"Edit Device": "Editar Dispositivo",
"Edit Folder": "Editar Carpeta",
"Editing": "Editando",
"Editing {%path%}.": "Editing {{path}}.",
"Editing {%path%}.": "Editando {{path}}.",
"Enable NAT traversal": "Permitir NAT transversal",
"Enable Relaying": "Habilitar Retransmisión",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Introduce un número no negativo (por ejemplo, \"2.35\") y selecciona una unidad. Los porcentajes son como parte del tamaño total del disco.",
"Enter a non-privileged port number (1024 - 65535).": "Introduce un puerto sin privilegios (1024 - 65535).",
"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 ignore patterns, one per line.": "Introducir patrones a ignorar, uno por línea.",
"Error": "Error",
"External File Versioning": "Versionado externo de fichero",
"Failed Items": "Elementos fallidos",
"Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.": "Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.",
"Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.": "Se espera un fallo al conectar a los servidores IPv6 si no hay conectividad IPv6.",
"File Pull Order": "Orden de obtención de los ficheros",
"File Versioning": "Versionado de ficheros",
"File permission bits are ignored when looking for changes. Use on FAT file systems.": "Los bits de permiso de ficheros son ignorados cuando se buscan cambios. Utilizar en sistemas de ficheros FAT.",
"Files are moved to .stversions directory when replaced or deleted by Syncthing.": "Files are moved to .stversions directory when replaced or deleted by Syncthing.",
"Files are moved to .stversions directory when replaced or deleted by Syncthing.": "Los ficheros son movidos a la carpeta .stversions cuando son reemplazados o borrados por Syncthing.",
"Files are moved to .stversions folder when replaced or deleted by Syncthing.": "Los archivos serán movidos a la carpeta .stversions cuando sean reemplazados o borrados por Syncthing.",
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.",
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Los ficheros son movidos a una carpeta .stversions a versiones con control de fecha cuando son reemplazados o borrados por Syncthing.",
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Los ficheros son cambiados a versiones con indicación de fecha en una carpeta \".stversions\" cuando son reemplazados o borrados por Syncthing.",
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Los ficheros son protegidos por los cambios hechos en otros dispositivos, pero los cambios hechos en este dispositivo serán enviados al resto del grupo (cluster).",
"Folder": "Carpeta",
@@ -90,6 +93,7 @@
"GUI": "GUI",
"GUI Authentication Password": "Password de la Interfaz Gráfica de Usuario (GUI)",
"GUI Authentication User": "Autentificación de usuario de la Interfaz Gráfica de Usuario (GUI)",
"GUI Listen Address": "Dirección de Escucha del GUI.",
"GUI Listen Addresses": "Direcciones de escucha de la Interfaz Gráfica de Usuario (GUI)",
"GUI Theme": "Tema GUI",
"Generate": "Generar",
@@ -146,7 +150,7 @@
"Override Changes": "Anular cambios",
"Path": "Parche",
"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": "Ruta a la carpeta en la máquina local. Se creará si no existe. El carácter de la tilde (~) puede usarse como atajo.",
"Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).": "Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).",
"Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).": "La ruta donde las versiones deben ser almacenadas (dejar vacío para el directorio .stversions por defecto en la carpeta compartida).",
"Path where versions should be stored (leave empty for the default .stversions folder in the folder).": "Ruta donde se almacenarán las versiones (dejar vacío para usar la carpeta por defecto \".stversions\").",
"Pause": "Pausar",
"Pause All": "Pausar todo",
@@ -241,6 +245,7 @@
"This Device": "Este Dispositivo",
"This can easily give hackers access to read and change any files on your computer.": "Esto podría permitir fácilmente el acceso a hackers para leer y modificar cualquier fichero de tu equipo.",
"This is a major version upgrade.": "Hay una actualización importante.",
"This setting controls the free space required on the home (i.e., index database) disk.": "Este ajuste controla el espacio libre necesario en el disco principal (por ejemplo, el índice de la base de datos).",
"Time": "Hora",
"Trash Can File Versioning": "Versionado de archivos de la papelera",
"Type": "Tipo",

View File

@@ -10,6 +10,7 @@
"Add Device": "Agregar Dispositivo",
"Add Folder": "Agregar Repositorio",
"Add Remote Device": "Agregar Dispositivo Remoto",
"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?": "¿Agregar nueva carpeta?",
"Address": "Dirección",
"Addresses": "Direcciones",
@@ -67,6 +68,8 @@
"Editing {%path%}.": "Editing {{path}}.",
"Enable NAT traversal": "Habilitar NAT trasversal",
"Enable Relaying": "Habilitar Retransmisión",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.",
"Enter a non-privileged port number (1024 - 65535).": "Enter a non-privileged port number (1024 - 65535).",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Introduce las direcciones (\"tcp://ip:puerto\", \"tcp://huésped:puerto\") separadas por comas, o \"dynamic\" para ejecutar un descubrimiento automático de la dirección. ",
"Enter ignore patterns, one per line.": "Añadir patrones de exclusión, uno por línea.",
"Error": "Error",
@@ -90,6 +93,7 @@
"GUI": "GUI",
"GUI Authentication Password": "Contraseña de autenticación de la GUI",
"GUI Authentication User": "Usuario de la GUI",
"GUI Listen Address": "GUI Listen Address",
"GUI Listen Addresses": "Direcciones de escucha para la GUI.",
"GUI Theme": "Apariencia de la GUI",
"Generate": "Generar",
@@ -241,6 +245,7 @@
"This Device": "Este Dispositivo",
"This can easily give hackers access to read and change any files on your computer.": "Esto puede darle permiso a los hackers, podrán acceder a cualquier archivo, pudiéndolos leer y editar.",
"This is a major version upgrade.": "Esta es una actualización de version mayor.",
"This setting controls the free space required on the home (i.e., index database) disk.": "This setting controls the free space required on the home (i.e., index database) disk.",
"Time": "Tiempo",
"Trash Can File Versioning": "Versiones como cubo de basura",
"Type": "Tipo",

View File

@@ -1,15 +1,16 @@
{
"A device with that ID is already added.": "Id hori duen tresna bat jadanik bada",
"A negative number of days doesn't make sense.": "0 edo zenbaki positiboa onartzen da bakarrik",
"A new major version may not be compatible with previous versions.": "Aldaketa garrantzitsuak dituen bertsio berria beharbada ez da bateragarria izango bertsio zaharragoekin.",
"A new major version may not be compatible with previous versions.": "Aldaketa garrantzitsuak dituen bertsio berri bat ez da beharbada bateragarria izanen bertsio zaharragoekin.",
"API Key": "API giltza",
"About": "Honi buruz",
"Action": "Ekintza",
"Action": "Egintza",
"Actions": "Egintzak",
"Add": "Gehitu",
"Add Device": "Tresna gehitu",
"Add Folder": "Karpeta gehitu",
"Add Remote Device": "Urruneko tresna bat gehitu",
"Add devices from the introducer to our device list, for mutually shared folders.": "Gure tresna zerrendan tresnak gehitzea baimendu, partekatzeetan.",
"Add new folder?": "Karpeta berria gehitu?",
"Address": "Helbidea",
"Addresses": "Helbideak",
@@ -18,20 +19,20 @@
"Advanced settings": "Parametro aitzinatuak",
"All Data": "Datu guziak",
"Allow Anonymous Usage Reporting?": "Izenik gabeko erabiltze erreportak baimendu?",
"Allowed Networks": "Allowed Networks",
"Allowed Networks": "Sare baimenduak",
"Alphabetic": "Alfabetikoa",
"An external command handles the versioning. It has to remove the file from the shared folder.": "An external command handles the versioning. It has to remove the file from the shared folder.",
"An external command handles the versioning. It has to remove the file from the shared folder.": "Kanpoko kontrolagailu batek fitxategien bertsioak kudeatzen ditu. Fitxategiak kendu behar ditu errepertorio sinkronizatuan.",
"An external command handles the versioning. It has to remove the file from the synced folder.": "Kanpoko kontrolagailu batek fitxeroen bertsioak erabiltzen ditu. Fitxeroak errepertorio sinkronizatutik desagertaraztea berari doakio.",
"Anonymous Usage Reporting": "Izenik gabeko erabiltze erreportak",
"Any devices configured on an introducer device will be added to this device as well.": "Sarrarazle deitzen duzun tresna batean gehitua izanen den edozein tresna, zurean ere gehitua izanen da.",
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Eguneratze automatiko sistemak iraunkor ala aitzin bertsioen arteko aukera proposatzen du",
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Eguneratze automatiko sistemak iraunkor bertsioen eta aitzineko bertsioen artean hautatzea proposatzen du",
"Automatic upgrades": "Eguneratze automatikoak",
"Be careful!": "Kasu emazu!",
"Bugs": "Akatsak",
"CPU Utilization": "Prozesadorearen erabiltzea",
"Changelog": "Bertsioen historia",
"Clean out after": "Garbi …. epearen ondotik",
"Click to see discovery failures": "Click to see discovery failures",
"Click to see discovery failures": "Klik egin hutsegiteak ikusteko",
"Close": "Hetsi",
"Command": "Kontrolagailua",
"Comment, when used at the start of a line": "Komentarioa, lerro baten hastean delarik",
@@ -43,237 +44,241 @@
"Copied from original": "Jatorrizkotik kopiatua",
"Copyright © 2014-2016 the following Contributors:": "Copyright 2014-2016, ekarle hauk:",
"Copyright © 2014-2017 the following Contributors:": "Copyright 2014-2017, ekarle hauk:",
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Creating ignore patterns, overwriting an existing file at {{path}}.",
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Baztertze modelo batzuen sortzea, den fitxategiari ordaina ezartzea: {{bidea}}",
"Danger!": "Lanjera !",
"Deleted": "Kendua",
"Device": "Tresna",
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "Makina \"{{name}}\" ({{device}} izan {{address}}) konektatu nahi du. Gaineratu berri makina ?",
"Device ID": "Makina ID",
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "Tresna \"{{name}}\" ({{device}}{{address}} era) konektatu nahi du. Onhartzen duzu? ?",
"Device ID": "Tresnaren ID-a",
"Device Identification": "Tresnaren identifikazioa",
"Device Name": "Makina izen",
"Devices": "Makinak",
"Disconnected": "Desloturik",
"Discovered": "Ziloa",
"Device Name": "Tresnaren izena",
"Devices": "Tresnak",
"Disconnected": "Deskonektatua",
"Discovered": "Agertua",
"Discovery": "Aurkikuntza",
"Discovery Failures": "Discovery Failures",
"Documentation": "Dokumentazio",
"Download Rate": "Deskargatze emari",
"Downloaded": "Telekargatua",
"Downloading": "Deskargatze",
"Discovery Failures": "Hutsegiteak",
"Documentation": "Dokumentazioa",
"Download Rate": "Deskargatzearen bit-tasa",
"Downloaded": "Deskargatua",
"Downloading": "Deskargatzea",
"Edit": "Aldatu",
"Edit Device": "Aldaketa tresna",
"Edit Folder": "Aldaketa partekatze",
"Editing": "Aldaketa",
"Editing {%path%}.": "Editing {{path}}.",
"Enable NAT traversal": "Ahalbidetu NAT",
"Enable Relaying": "Ahalbidetu lekua hartu",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": " (\"tcp://ip:port\", \"tcp://nom:port\") zuzenbideak sar, krakotx batez separatuak edo bestenaz \"dynamic\", zuzenbidearen xekatze automatikoa aktibatzeko\nTu peux traduire nom et port mot à mot dans la parenthèse, c'est pas des variables du programme, juste du texte explicatif",
"Edit Device": "Tresna aldatzea",
"Edit Folder": "Partekatze aldatzea",
"Editing": "Aldaketak",
"Editing {%path%}.": "Muntatzea {{bidea}}",
"Enable NAT traversal": "NAT translazioa aktibatu",
"Enable Relaying": "Aldizkatzea posible",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Negatiboa ez den zenbaki bat hauta ezazu (\"2.35\" adib.) eta unitate bat hauta. Disko osoaren espazio ehunekoa",
"Enter a non-privileged port number (1024 - 65535).": "Abantailatua ez den portu zenbalki bat sar ezazu (1024 - 65535)",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": " (\"tcp://ip:ataka\", \"tcp://izena:ataka\") zuzenbideak sar, krakotx batez separatuak edo bestenaz \"dynamic\", zuzenbidearen xekatze automatikoa aktibatzeko\nTu peux traduire nom et port mot à mot dans la parenthèse, c'est pas des variables du programme, juste du texte explicatif",
"Enter ignore patterns, one per line.": "Ezkluzio filtroak sar, lerro batean bakar bat",
"Error": "Huts",
"External File Versioning": "Fitxero bertsioen kanpoko kudeaketa",
"Failed Items": "Fitxategiken huts",
"Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.": "Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.",
"File Pull Order": "Fitxategiak irekitzeko agindua",
"File Versioning": "Artxiboak babesteko metodoa",
"File permission bits are ignored when looking for changes. Use on FAT file systems.": "Aldaketa bilaketetan fitxero baimenen bitak ez dira kontuan hartuko. Fitxero FAT sistimetan erabilia.",
"Files are moved to .stversions directory when replaced or deleted by Syncthing.": "Files are moved to .stversions directory when replaced or deleted by Syncthing.",
"Error": "Hutsa",
"External File Versioning": "Fitxategi bertsioen kanpoko kudeaketa",
"Failed Items": "Huts egin duten fitxategiak",
"Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.": "IPv6 zerbitzariei buruzko konexioak huts eginen du, IPv6 konektibitaterik ez bada",
"File Pull Order": "Fitxategiak berreskuratzeko ordena",
"File Versioning": "Fitxategiak zaintzeko metodoa",
"File permission bits are ignored when looking for changes. Use on FAT file systems.": "Aldaketa bilaketetan, fitxeroen baimen bitak ez dira kontuan hartuko. Fitxero FAT sistimetan erabilia.",
"Files are moved to .stversions directory when replaced or deleted by Syncthing.": "Fitxategiak .stbersioak errepertorioan lekutuak dira, Syncthing-ek ordezkatzen edo kentzen dituelarik",
"Files are moved to .stversions folder when replaced or deleted by Syncthing.": ".stbersioak azpi karpetan lekutuko dira fitxeroak, Syncthing-ek aldatu edo ezeztatuko dituelarik. Beren helbide errelatiboak hor berean berriz sortuak izanen dira, behar balin bada",
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.",
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": ".stbersioak azpi karpetan lekutuko eta ordu-markatuko dira fitxeroak, Syncthing-ek aldatu edo ezeztatuko dituelarik. Beren helbide errelatiboak hor berean berriz sortuak izanen dira, behar balin bada",
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Beste tresnetan eginak izanen diren aldaketetatik zainduak izanen dira fitxeroak; haatik, tresna huntan egindako aldaketak besteeri hedatuak izanen dira",
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": ".stbersioak azpi karpetan lekutuko eta ordu-markatuko dira fitxeroak, egitura errelatibo berdin batean, Syncthing-ek aldatu edo ezeztatuko dituelarik.",
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Beste tresnetan eginak izanen diren aldaketetatik zainduak izanen dira fitxeroak; haatik, tresna huntan egindako aldaketak besteeri hedatuak izanen dira.",
"Folder": "Partekatze",
"Folder ID": "Partekatze ID",
"Folder Label": "Partekatze izengoiti",
"Folder Path": "Partekatze bidexka",
"Folder ID": "ID partekatze",
"Folder Label": "Partekatzearen izena",
"Folder Path": "Partekatzearen sustrai bidea",
"Folder Type": "Partekatze mota",
"Folders": "Partekatzek",
"GUI": "Interfaze grafiko",
"GUI Authentication Password": "Interfaze grafiko pasahitz",
"GUI Authentication User": "Interfaze grafiko erabiltzaile",
"GUI Listen Addresses": "Interfaze grafiko helbide",
"GUI Theme": "GUI Theme",
"Folders": "Partekatzeak",
"GUI": "Interfaze grafikoa",
"GUI Authentication Password": "Interfaze grafiko pasahitza",
"GUI Authentication User": "Interfaze grafiko erabiltzaile baimendua",
"GUI Listen Address": "Interfaze grafiko helbidea",
"GUI Listen Addresses": "Interfaze grafiko helbideak",
"GUI Theme": "Interfaze grafiko tema",
"Generate": "Sortu",
"Global Changes": "Global Changes",
"Global Discovery": "Aurkikuntza oso",
"Global Discovery Servers": "Aurkikuntza oso zerbitzarik",
"Global State": "Oso egoera",
"Help": "Aiuta",
"Home page": "Errezibitze",
"Ignore": "Baztertu",
"Ignore Patterns": "Bazterketak arauk",
"Ignore Permissions": "Baztertu baimenek",
"Incoming Rate Limit (KiB/s)": "Deskargatze emari gehieneko (KiB/s)",
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Langer !!!!",
"Introduced By": "Introduced By",
"Introducer": "Abiarazle",
"Global Changes": "Azken aldaketak",
"Global Discovery": "Aurkikuntza orokorra",
"Global Discovery Servers": "Orokor aurkikuntza zerbitzaria",
"Global State": "Egoera orokorra",
"Help": "Laguntza",
"Home page": "Harrera",
"Ignore": "Kontuan ez hartu",
"Ignore Patterns": "Baztertzeak",
"Ignore Permissions": "Baimenak kontuan ez hartu",
"Incoming Rate Limit (KiB/s)": "Deskargatze emari muga (KiB/s)",
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Behar ez den konfigurazio batek zuen partekatzetan makurrak egin ditzake eta Syncthing ezin erabilia utzi",
"Introduced By": "...k sartua",
"Introducer": "Tresna sarrarazlea",
"Inversion of the given condition (i.e. do not exclude)": "Emana izan den baldintza alderantziz eman (i.e ez baztertu)",
"Keep Versions": "Gorde bertsioak",
"Largest First": "Handienak lehenik",
"Last File Received": " Fitxategi azken eskuratu",
"Last Scan": "Azterketa azken",
"Last File Received": " Azkenik eskuratu fitxategia",
"Last Scan": "Azken azterketa",
"Last seen": "Azken agerraldia",
"Later": "Berantago",
"Latest Change": "Asken aldaketa",
"Learn more": "Learn more",
"Latest Change": "Azken aldaketa",
"Learn more": "Gehiago jakiteko",
"Listeners": "Entzungailuak",
"Local Discovery": "Lekuko aurkikuntza",
"Local State": "Lekuko egoera",
"Local State (Total)": "Lekuko egoera (Oso)",
"Major Upgrade": "Nagusi eguneratu",
"Master": "Nagusi",
"Maximum Age": "Goren adin",
"Local State (Total)": "Lekuko egoera (Osoa)",
"Major Upgrade": "Eguneratze nagusia",
"Master": "Nagusia",
"Maximum Age": "Adin gehiena",
"Metadata Only": "Metadatuak bakarrik",
"Minimum Free Disk Space": "Diskoan leku libre gutxieneko",
"Move to top of queue": "Igurikatze zerrenda bururat lekuz alda",
"Multi level wildcard (matches multiple directory levels)": "Hein askorentzako jokerra (errepertorio eta azpi errepertorioeri dagokiona)",
"Minimum Free Disk Space": "Diskoan gutieneko leku libroa ",
"Move to top of queue": "Lerro bururat lekuz alda",
"Multi level wildcard (matches multiple directory levels)": "Hein anitzerako jokerra (errepertorio eta azpi errepertorioeri dagokiona)",
"Never": "Sekulan",
"New Device": "Berria makina",
"New Folder": "Berri partekatze",
"Newest First": "Gehien gertatu berri lehen",
"New Device": "Tresna berria",
"New Folder": "Partekatze berria",
"Newest First": "Berrienak lehenik",
"No": "Ez",
"No File Versioning": "Ez babestu",
"No upgrades": "No upgrades",
"Normal": "Normal",
"No File Versioning": "Fitxategi bersioen kontrolik ez",
"No upgrades": "Eguneratzerik ez",
"Normal": "Normala",
"Notice": "Jakinaraztea",
"OK": "Ados",
"Off": "Desgaitu",
"Oldest First": "Gehien zahar lehen",
"Optional descriptive label for the folder. Can be different on each device.": "Partikatzearen izen hautuzkoa eta atsegina, zure gisa. Tresna bakotxean desberdina izaiten ahal da.",
"Options": "Hautuk",
"Oldest First": "Zaharrenak lehenik",
"Optional descriptive label for the folder. Can be different on each device.": "Partekatzearen izen hautuzkoa eta atsegina, zure gisa. Tresna bakotxean desberdina izaiten ahal da.",
"Options": "Hautuzkoak",
"Out of Sync": "Ez sinkronizatua",
"Out of Sync Items": "Ez sinkronizatu elementuak",
"Outgoing Rate Limit (KiB/s)": "Bidaltze emari gehieneko (KiB/s)",
"Outgoing Rate Limit (KiB/s)": "Bidaltze emari gehienekoa (KiB/s)",
"Override Changes": "Aldaketak desegin",
"Path": "Bidexka",
"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": "Bertako tresnaren karpetari buruzko bidea. Ez balin bada, asmatu beharko da bat. Vous pouvez entrer un chemin absolu (p.ex \"/home/moi/Sync/Exemple\") ou relatif à celui du programme (p.ex \"..\\Partages\\Exemple\" - utile pour installation portable). Tildea (~, edo ~+Espazioa Windows XP+Azerty-n) erabil litzateke bide motz gisa",
"Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).": "Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).",
"Path where versions should be stored (leave empty for the default .stversions folder in the folder).": "Kopiak kontserbatzeko bidea (hutsa utzezazu, .stversioen karpetaren bide ohituan).",
"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": "Lekuko tresnaren partekatzeari buruzko bidea. Ez balitz, asmatu beharko da bat. Programarenari, baitezpadako bide bat sartzen ahal duzu (adibidez \"/home/ni/Sync/Etsenplua\") edo bestenaz bide errelatibo bat (adibidez \"..\\Partekatzeak\\Etsenplua\" - instalazio mugikor batentzat baliagarria). Tildea (~, edo ~+Espazioa Windows XP+Azerty-n) erabil litzateke laburbide gisa",
"Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).": "Kopiak kontserbatzeko bidea (hutsa utz ezazu, .steversioen ohizko bidearentzat, dosier partekatuan)",
"Path where versions should be stored (leave empty for the default .stversions folder in the folder).": "Kopiak kontserbatzeko bidea (hutsa utz ezazu, .stversioen ohizko dosierarentzat, karpeta partekatuan)",
"Pause": "Pausa",
"Pause All": "Pause All",
"Paused": "Geldirik",
"Pause All": "Geldi dena",
"Paused": "Gelditua",
"Please consult the release notes before performing a major upgrade.": "Aktualizatze garrantzitsu bat egin baino lehen, bertsioaren oharrak begira itzazu.",
"Please set a GUI Authentication User and Password in the Settings dialog.": "Konfigurazio leihoan asma itzazu erabiltzale izen bat eta sartzeko giltza bat",
"Please wait": "Oraino pazientzia pixka bat har ezazu",
"Please set a GUI Authentication User and Password in the Settings dialog.": "Konfigurazio leihoan asma itzazu erabiltzale izen bat eta pasahitz bat",
"Please wait": "Pazientzia pixka bat, otoi",
"Preview": "Aurrebista",
"Preview Usage Report": "Erabiltze aurrebista",
"Quick guide to supported patterns": "Filtro ez onartuen txostena :",
"RAM Utilization": "RAM erabiltze",
"Random": "Aleatorio",
"Reduced by ignore patterns": "(Mugatu baztertzek patroikez)",
"Preview Usage Report": "Erabiltze estatistika txostenaren aurrebista",
"Quick guide to supported patterns": "Eredu konpatibleen gidaliburuxka",
"RAM Utilization": "RAM aren erabiltzea",
"Random": "Aleatorioa",
"Reduced by ignore patterns": "Baztertze eredu batzuk mugatuak",
"Release Notes": "Bertsioen notak",
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.",
"Remote Devices": "Besteak makinak",
"Remote Devices": "Beste tresnak",
"Remove": "Kendu",
"Required identifier for the folder. Must be the same on all cluster devices.": "Partikatzearen erabilzaile izena. Diren tresna guzietan berdin berdina izan behar du",
"Rescan": "Berreskanea",
"Rescan All": "Berreskanea guzia",
"Rescan Interval": "Arte berreskanea",
"Restart": "Berriz abiatu",
"Required identifier for the folder. Must be the same on all cluster devices.": "Partekatzearen erabilzaile izena. Dauden tresna guzietan berdin berdina izan behar du",
"Rescan": "Berriz eskaneatu",
"Rescan All": "Dena berriz eskaneatu",
"Rescan Interval": "Berriz eskaneatzeko tartea",
"Restart": "Berriz piztu",
"Restart Needed": "Berriz piztea beharrezkoa",
"Restarting": "Berriz piztea martxan",
"Resume": "Berriz hasi",
"Resume All": "Resume All",
"Resume": "Berriz hastea",
"Resume All": "Dena berriz hastea",
"Reused": "Berriz erabilia",
"Save": "Begiratu",
"Scan Time Remaining": "Gelditzen den denbora azterketa",
"Scanning": "Etengabeko azterketa",
"Select the devices to share this folder with.": "Honekin sinkronizatua:",
"Select the folders to share with this device.": "Tresna hunek erabiltzen dituen banaketak hauta",
"Send & Receive": "Igorri & Artu",
"Send Only": "Bakarrik igorri",
"Settings": "Egokitzek",
"Share": "Banatu",
"Share Folder": "Banatu",
"Share Folders With Device": "Partekatu makinakekin",
"Share With Devices": "Partekatuekin makinak",
"Share this folder?": "Banatze hau onartzen duzu?",
"Shared With": "Partekatuekin",
"Show ID": "Erakutsi ene ID",
"Show QR": "Erakutsi QR",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Tresnaren ID-aren ordez erakutsia, taldearen egoeran. Beste tresneri erakutsia izanen da, izen erabilgarria bezala",
"Save": "Grabatu",
"Scan Time Remaining": "Gelditzen den azterketa denbora",
"Scanning": "Azterketa martxan",
"Select the devices to share this folder with.": " Tresnak hauta itzazu partekatze honekin sinkronizatzeko ",
"Select the folders to share with this device.": "Tresna honek erabiltzen dituen partekatzeak hauta itzazu",
"Send & Receive": "Igorri eta errezibitu",
"Send Only": "Igorrri bakarrik",
"Settings": "Konfigurazioa",
"Share": "Partekatu",
"Share Folder": "Partekatzea",
"Share Folders With Device": "Tresnarekin partekatzeak",
"Share With Devices": "Tresnekin partekatu",
"Share this folder?": "Partekatze hau onartzen duzu?",
"Shared With": "...ekin partekatua",
"Show ID": "Erakutsi ene ID-a",
"Show QR": "Erakutsi QR-a",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Tresnaren ID-aren ordez erakutsia, taldearen egoeran. Beste tresneri erakutsia izanen da, izen erabilgarri bat bezala",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Tresnaren ID-aren ordez erakutsia, taldearen egoeran. Hutsa utzia balin bada, urrun den tresnak proposatu izenarekin aktualizatua izanen da",
"Shutdown": "Utzi",
"Shutdown": "Geldi",
"Shutdown Complete": "Gelditua!",
"Simple File Versioning": "Bertsioen segitze sinplifikatuak",
"Simple File Versioning": "Bertsioen segitze sinplifikatua",
"Single level wildcard (matches within a directory only)": "Hein bakar bateko jokerra (karpetaren barnean bakarrik dagokiona)",
"Smallest First": "Tipienak lehenik",
"Source Code": "Iturri kode",
"Stable releases and release candidates": "Stable releases and release candidates",
"Stable releases are delayed by about two weeks. During this time they go through testing as release candidates.": "Stable releases are delayed by about two weeks. During this time they go through testing as release candidates.",
"Stable releases only": "Stable releases only",
"Staggered File Versioning": "Bertsio eskaleratuak",
"Start Browser": "Web nabigatzailea pitz",
"Statistics": "Statistikak",
"Smallest First": "Ttipienak lehenik",
"Source Code": "Iturri kodea",
"Stable releases and release candidates": "iraunkor eta aintzin-bertsioak",
"Stable releases are delayed by about two weeks. During this time they go through testing as release candidates.": "Iraunkor bertsioak bi astez (nonbait han) gibelatuak dira. Bitartean, aintzin-bertsio gisa probatuak izanen dira.",
"Stable releases only": "Iraunkor bertsioak bakarrik",
"Staggered File Versioning": "Bertsio mailakatuak",
"Start Browser": "Web nabigatzailea piztu",
"Statistics": "Estatistikak",
"Stopped": "Gelditua!",
"Support": "Foroa",
"Sync Protocol Listen Addresses": "Sinkronizatu protokoloaren entzun zuzenbideak",
"Syncing": "Sinkronizazio joaira",
"Syncing": "Sinkronizazioa martxan",
"Syncthing has been shut down.": "Syncthing gelditua izan da",
"Syncthing includes the following software or portions thereof:": "Syncthing-ek programa hauk integratzen ditu (edo programa hauetatik datozten elementuak):",
"Syncthing is restarting.": "Syncthing berriz pizten ari",
"Syncthing is upgrading.": "Syncthing aktualizatzen ari da",
"Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…": "Iduri luke Syncthing gelditua dela, edo bestenaz arrazo bat bada interneten konekzioarekin. Berriz entsea zaitez…",
"Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.": "Iduri luke Syncthing arazo bat duela zure eskaeraren tratatzeko. Otoi, horria freska ezazu edo bestenaz Syncthing berriz pitz arazoak segitzen badu.",
"The Syncthing admin interface is configured to allow remote access without a password.": "Syncthing administrazio interfazea pentsatua da urrundikako irisbideak sekretu hitz gabe onartzeko !!!",
"The aggregated statistics are publicly available at the URL below.": "Estadistikak zuzen bide honetan publikoki ikusgarri dira",
"The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.": "Konfigurazioa grabatua izan da bainan ez aktibatua. Syncthing berriz piztu behar da konfigurazio berriaren berriz aktibatzeko.",
"Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.": "Iduri luke Syncthing-ek arazo bat duela zure eskaera tratatzeko. Otoi, orrialdea freska ezazu edo bestenaz, arazoak segitzen badu, Syncthing berriz pitz ezazu .",
"The Syncthing admin interface is configured to allow remote access without a password.": "Syncthing-en administrazio interfazea pentsatua da urrundikako helbideak pasahitzik gabe onartzeko !",
"The aggregated statistics are publicly available at the URL below.": "Estadistikak zuzen bide honetan publikoki ikusgarriak dira",
"The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.": "Konfigurazioa grabatua izan da bainan ez aktibatua. Syncthing berriz piztu behar da konfigurazio berria berriz aktibatzeko.",
"The device ID cannot be blank.": "Tresnaren ID-a ez da hutsa izaiten ahal.",
"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).": "Tresnaren ID-a atxemaiten ahal da \"Ekintzak > Tresna urrunduaren \"ID-a erakuts\" menuan. Espazio eta gioiak ez dira beharrezkoak.",
"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.": "Erabileraren zifratu txostena egun guziz igorria da. Erabili diren plataformak, banaketeen neurriak eta aplikazioaren bertsioen zerendatzeko balio du.",
"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.": "Sartu den tresnaren ID-ak iduri du ez duela balio. 52 edo 56-ko ezaugarriko kadena baten itxura behar luke, hizkiak, zifrak eta baita ere tarte edo gioiez egina",
"The first command line parameter is the folder path and the second parameter is the relative path in the folder.": "Agingailu lerroaren lehen parametroa banatua den karpetaren bidea da, eta bigarrena karpetan den errelatibo bidea",
"The folder ID cannot be blank.": "banatzearen ID-a ez da hutsa izaiten ahal",
"The folder ID must be unique.": "Banatzearen ID-ak bakarra izan behar du",
"The folder path cannot be blank.": "Karpetari buruzko bidea ez da hutsa izaiten ahal",
"The following intervals are used: for the first hour a version is kept every 30 seconds, for the first day a version is kept every hour, for the first 30 days a version is kept every day, until the maximum age a version is kept every week.": "Hunako tarteak erabiliak dira: oren bateko denboraldian bertsio bat kontserbatua da 30 segundu guziz. Egun batekoan,bertsio bat egunero. Handik harat, adinaren mugetan egonez, bertsio bat astero.",
"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).": "Sartu behar den tresnaren ID-a atxemaiten ahal da menuan \"Ekintzak > ID-a erakuts\" (tresna urrunduarena). Espazio eta gioiak ez dira beharrezkoak.",
"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.": "Erabileraren zifratu txostena egun guziz igorria da. Erabili diren plataformak, partekatzeen neurriak eta aplikazioaren bertsioen zerendatzeko balio du. Datu orokorrak aldatzen balin badira, mezu honen bidez ontzat emaitea eskatua izanen zaizu.\nErabiltzearen zifratu txostena egun guziz igorria da. Balio du erabiliak izan diren plataformak, partekatzeen izaria eta aplikazioaren bertsioak zerrendatzeko. Datu orokorrek aldatuak izan behar balute, mezu honen bidez ontzat emaitea eskatua izanen zaizu. Zure erabakia aldatzen ahal duzu Ekintzak/Konfigurazioa-ren bidez, baita igortzeen maiztasuna Ekintzak/ aitzinatua/Opzioak -en bidez.",
"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.": "Sartu den tresnaren ID-ak iduri du ez duela balio. 52 edo 56-ko ezaugarriko kadena baten itxura behar luke, hizkiak, zifrak eta baita ere tarte edo gioiez egina.",
"The first command line parameter is the folder path and the second parameter is the relative path in the folder.": "Agingailu lerroaren lehen parametroa partekatzearen bidea da, eta bigarrena partekatzean den bide errelatiboa.",
"The folder ID cannot be blank.": "Partekatzearen ID-a ez da hutsa izaiten ahal",
"The folder ID must be unique.": "Partekatzearen ID-a bakarra izan behar da",
"The folder path cannot be blank.": "Partekatzeari buruzko bidea ez da hutsa izaiten ahal",
"The following intervals are used: for the first hour a version is kept every 30 seconds, for the first day a version is kept every hour, for the first 30 days a version is kept every day, until the maximum age a version is kept every week.": "Hunako tarteak erabiliak dira: lehen orduan bertsio bat kontserbatua da 30 segundu guziz. Lehen egunean, bertsio bat ordu bakoitz, lehen 30 egunetan bertsio bat egunero. Handik harat, adinaren mugetan egonez, bertsio bat astero.",
"The following items could not be synchronized.": "Ondoko fitxero hauk ez dira sinkronizatuak ahal izan",
"The maximum age must be a number and cannot be blank.": "Gehieneko adinak zenbaki bat behar du izan eta ez da hutsa izaiten ahal.",
"The maximum time to keep a version (in days, set to 0 to keep versions forever).": "Bertsio baten kontserbatzeko epe haundiena (egunez behar du izan. Jar ezazu zerotan bertsioak betirako atxikitzeko)",
"The minimum free disk space percentage must be a non-negative number between 0 and 100 (inclusive).": "Diskoaren ehuneko espazioa hutsak zenbaki positibo bat behar du izan, 0 eta 100-en artekoa (100 barne)",
"The number of days must be a number and cannot be blank.": "Egunen kopuruak numerikoa izan behar du eta ez da hutsa izaiten ahal",
"The number of days to keep files in the trash can. Zero means forever.": "Zikin ontziko elgar hizketen kontserbatzeko egun kopurua. Beti 0 erran nahi du.",
"The number of old versions to keep, per file.": "Atxikitzeko diren lehenagoko bertsio kopurua,fitxero bakotxarentzat",
"The number of versions must be a number and cannot be blank.": "Bertsio kopuruak numerikoa behar du izan eta ez da hutsa izaiten ahal",
"The number of days to keep files in the trash can. Zero means forever.": "Zikin ontzian elgar hizketak kontserbatzeko egun kopurua. Zerok \"betirako\" erran nahi du.",
"The number of old versions to keep, per file.": "Atxikitzeko diren lehenagoko bertsioen kopurua, fitxero bakoitzarentzat",
"The number of versions must be a number and cannot be blank.": "Bertsioen kopuruak numerikoa behar du izan eta ez da hutsa izaiten ahal",
"The path cannot be blank.": "Bidea ez da hutsa izaiten ahal",
"The rate limit must be a non-negative number (0: no limit)": "Ixuriaren neurria ez da negatiboa izaiten ahal (0 = mugarik gabekoa)",
"The rescan interval must be a non-negative number of seconds.": "Ikerketaren tartea ez da segundu kopuru negatiboa izaiten ahal",
"They are retried automatically and will be synced when the error is resolved.": "Akatsa zuzendua izanen delarik, automatikoki berriz entseatuak et sinkronizatuak izanen dira",
"This Device": "Makina hau",
"This can easily give hackers access to read and change any files on your computer.": "Hunek errexki irakurtzen eta aldatzen uzten ahal du zure ordenagailuko edozein fitxero, nahiz eta sartu denak ez haizu!",
"The rate limit must be a non-negative number (0: no limit)": "Ixuriaren emaria ez da negatiboa izaiten ahal (0 = mugarik gabekoa)",
"The rescan interval must be a non-negative number of seconds.": "Ikerketaren tartea ez da segundo kopuru negatiboa izaiten ahal",
"They are retried automatically and will be synced when the error is resolved.": "Errorea zuzendua izanen delarik, automatikoki berriz entseatuak et sinkronizatuak izanen dira",
"This Device": "Tresna hau",
"This can easily give hackers access to read and change any files on your computer.": "Hunek errexki irakurtzen eta aldatzen uzten ahal du zure ordenagailuko edozein fitxero, nahiz eta sartu denak ez haizu izan!",
"This is a major version upgrade.": "Aktualizatze garrantzitsu bat da",
"Time": "Denbora",
"This setting controls the free space required on the home (i.e., index database) disk.": "Behar den espazio kontrolatzen du egokitze honek, zure erabiltzale partekatzea geritzatzen duen diskoan (hori da, indexazio datu-basean)",
"Time": "Ordua",
"Trash Can File Versioning": "Zakarrontzia",
"Type": "Mota",
"Unknown": "Ez ezaguna",
"Unshared": "Partekatu ez den",
"Unknown": "Ezezaguna",
"Unshared": "Partekatua ez dena",
"Unused": "Ez baliatua",
"Up to Date": "Egun",
"Updated": "Berritu",
"Up to Date": "Eguneratua",
"Updated": "Berritua",
"Upgrade": "Aktualizatu",
"Upgrade To {%version%}": "Egunetaratzea {{version}}-i buruz",
"Upgrade To {%version%}": "Egunetaratu {{bertsio}}-ari buruz",
"Upgrading": "Syncthing-en egunetaratzea",
"Upload Rate": "Bidaltze emari",
"Uptime": "Denbora ibiltze",
"Usage reporting is always enabled for candidate releases.": "Usage reporting is always enabled for candidate releases.",
"Use HTTPS for GUI": "HTTPS-a erabil GUI-arentzat",
"Version": "Bertsio",
"Versions Path": "Bertsioen egon tokia",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Bertsioak automatikoki ezeztatuak izanen dira, kontserbatzeko iraupen denbora pasatua badute edo bitartean onartua den kopurua gainditua balin bada",
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Warning, this path is a parent directory of an existing folder \"{{otherFolder}}\".",
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Warning, this path is a parent directory of an existing folder \"{{otherFolderLabel}}\" ({{otherFolder}}).",
"Warning, this path is a subdirectory of an existing folder \"{%otherFolder%}\".": "Kasu emazu, \"{{otherFolder}}\" banaketa azpi-karpetaren bidea da. Arazoak emaiten ahal ditu, fitxero batzuen ezeztatze edo duplikatzeak batez ere.",
"Warning, this path is a subdirectory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Kasu emazu, \"{{otherFolderLabel}}\" ({{otherFolder}}) banaketa azpi-karpetaren bidea da. Arazoak emaiten ahal ditu, fitxero batzuen ezeztatze edo duplikatzeak batez ere.",
"Upload Rate": "Igortze emaria",
"Uptime": "Erabiltze denbora",
"Usage reporting is always enabled for candidate releases.": "Erabiltze estatiskitak aintzin-bertsioetan beti igorriak dira",
"Use HTTPS for GUI": "HTTPS-a erabil ezazu GUI-arentzat",
"Version": "Bertsioa",
"Versions Path": "Bertsioen kokalekua",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "Bertsioak automatikoki ezeztatuak izanen dira, kontserbatzeko iraupen denbora pasatua badute edo bitartean onartua den kopurua (fitxategi bakoitzean) gainditua balin bada",
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Kasu, bide hau dagoen partekatze baten karpeta ahaidea da (adibidez, \" {{BestePartekatze}}\"). Segitzen baduzu, azpi-karpeta berri bat sortu behar duzu, bestenaz arazoak sortzen ahal dira, fitxategi kentzeak edo doblatzeak.",
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Kasu, bide hau dagoen partekatze baten karpeta ahaidea da (adibidez, \"{{BestePartekatzeLabela}}\" ({{BestePartekatze}}). ",
"Warning, this path is a subdirectory of an existing folder \"{%otherFolder%}\".": "Kasu, bide hau \"{{BestePartekatze}}\" partekatzearen azpi-karpeta da. Arazoak emaiten ahal ditu, fitxategi kentzeak edo doblatzeak, adibidez.",
"Warning, this path is a subdirectory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Kasu, bide hau \"{{BestePartekatzeLabela}}\" ({{BestePartekatze}}) partekatzearen azpi-karpeta da. Arazoak emaiten ahal ditu, fitxategi kentzeak edo doblatzeak, adibidez.",
"When adding a new device, keep in mind that this device must be added on the other side too.": "Tresna bat gehitzen duzularik, gogoan atxik ezazu zurea bestaldean gehitu behar dela ere",
"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.": "Tresna bat gehitzen delarik, gogoan atxik ezazu bere IDa erabilia dela errepertorioak lotzeko tresnen bitartez. ID-a hautskorra da eta banatze huntan parte hartzen duten tresna guzietan berdina izanen da",
"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.": "Partekatze bat gehitzen delarik, gogoan atxik ezazu bere IDa erabilia dela errepertorioak lotzeko tresnen bitartez. ID-a hautskorra da eta partekatze hontan parte hartzen duten tresna guzietan berdina izan behar du.",
"Yes": "Bai",
"You can change your choice at any time in the Settings dialog.": "You can change your choice at any time in the Settings dialog.",
"You can read more about the two release channels at the link below.": "You can read more about the two release channels at the link below.",
"You can change your choice at any time in the Settings dialog.": "Zure hautua aldatzen ahal duzu \"Konfigurazio\" leihatilan",
"You can read more about the two release channels at the link below.": "Bi banaketa kanal hauen bidez gehiago jakin dezakezu, lokarri honen bidez ",
"You must keep at least one version.": "Bertsio bat bederen behar duzu atxiki",
"days": "Egunak",
"directories": "karpetak",
"files": "fitxategik",
"directories": "Karpetak",
"files": "Fitxategiak",
"full documentation": "Dokumentazio osoa",
"items": "Elementuak",
"{%device%} wants to share folder \"{%folder%}\".": "{{device}} banaketa \"{{folder}}\" gomitatzen zaitu.",
"{%device%} wants to share folder \"{%folderlabel%}\" ({%folder%}).": "{{device}} \"{{folderlabel}}\" ({{folder}}) gomitatzen zaitu."
"{%device%} wants to share folder \"{%folder%}\".": "{{Tresna}}-k \"{{folder}}\" partekatze hontan gomitatzen zaitu.",
"{%device%} wants to share folder \"{%folderlabel%}\" ({%folder%}).": "{{Tresna}}-ak \"{{PartekatzeLabela}}\" ({{Partekatze}}) hontan gomitatzen zaitu."
}

View File

@@ -10,6 +10,7 @@
"Add Device": "Lisää laite",
"Add Folder": "Lisää kansio",
"Add Remote Device": "Lisää laite",
"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?": "Lisää uusi kansio?",
"Address": "Osoite",
"Addresses": "Osoitteet",
@@ -67,6 +68,8 @@
"Editing {%path%}.": "Editing {{path}}.",
"Enable NAT traversal": "Aktivoi osoitteenmuunnoksen kierto",
"Enable Relaying": "Aktivoi yhteyden välitys",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.",
"Enter a non-privileged port number (1024 - 65535).": "Enter a non-privileged port number (1024 - 65535).",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Syötä osoitteet pilkuilla erotettuina (\"tcp://ip:portti, tcp://nimi:portti\") tai \"dynamic\" käyttääksesi osoitteen automaattista selvitystä.",
"Enter ignore patterns, one per line.": "Syötä ohituslausekkeet, yksi riviä kohden.",
"Error": "Virhe",
@@ -90,6 +93,7 @@
"GUI": "GUI",
"GUI Authentication Password": "GUI:n salasana",
"GUI Authentication User": "GUI:n käyttäjätunnus",
"GUI Listen Address": "GUI Listen Address",
"GUI Listen Addresses": "GUI:n kuunteluosoitteet",
"GUI Theme": "GUI Theme",
"Generate": "Generoi",
@@ -241,6 +245,7 @@
"This Device": "Tämä laite",
"This can easily give hackers access to read and change any files on your computer.": "Tämä voi helposti sallia vihamielisille tahoille pääsyn lukea ja muokata kaikkia tiedostojasi",
"This is a major version upgrade.": "Tämä on pääversion päivitys.",
"This setting controls the free space required on the home (i.e., index database) disk.": "This setting controls the free space required on the home (i.e., index database) disk.",
"Time": "Aika",
"Trash Can File Versioning": "Roskakorin tiedostoversiointi",
"Type": "Tyyppi",

View File

@@ -10,6 +10,7 @@
"Add Device": "Ajouter l'appareil",
"Add Folder": "Ajouter un partage",
"Add Remote Device": "Ajouter un appareil",
"Add devices from the introducer to our device list, for mutually shared folders.": "Lui permettre d'ajouter et enlever des membres à toutes mes listes de membres de partages dont il fait partie (ceci permet de créer toutes les liaisons point à point possibles en complétant mes listes par les siennes, meilleur débit de réception par cumul des débits d'envoi, indépendance vis à vis de l'introducteur, etc).",
"Add new folder?": "Ajouter ce partage ?",
"Address": "Adresse",
"Addresses": "Adresses",
@@ -23,7 +24,7 @@
"An external command handles the versioning. It has to remove the file from the shared folder.": "Une commande externe gère les versions de fichiers. Il lui incombe de supprimer les fichiers dans le répertoire synchronisé.",
"An external command handles the versioning. It has to remove the file from the synced folder.": "Une commande externe gère les versions de fichiers. Il lui incombe de supprimer les fichiers dans le répertoire synchronisé.",
"Anonymous Usage Reporting": "Rapport anonyme de statistiques d'utilisation",
"Any devices configured on an introducer device will be added to this device as well.": "Tout appareil ajouté sur un appareil que vous déclarez comme introducteur sera aussi ajouté sur votre propre appareil.",
"Any devices configured on an introducer device will be added to this device as well.": "Lui permettre d'ajouter et enlever des membres à toutes mes listes de membres de partages dont il fait partie (ceci permet de créer toutes les liaisons point à point possibles en complétant mes listes par les siennes, meilleur débit de réception par cumul des débits d'envoi, indépendance vis à vis de l'introducteur, etc).",
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Le système de mise à jour automatique propose le choix entre versions stables et versions préliminaires.",
"Automatic upgrades": "Mises à jour automatiques",
"Be careful!": "Faites attention !",
@@ -43,7 +44,7 @@
"Copied from original": "Copié depuis l'original",
"Copyright © 2014-2016 the following Contributors:": "Copyright © 2014-2016, les contributeurs suivants:",
"Copyright © 2014-2017 the following Contributors:": "Copyright © 2014-2017, les contributeurs suivants :",
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Création de masques d'exclusion, remplacement du fichier existant dans {{path}}.",
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Création de masques d'exclusion, remplacement du fichier existant : {{path}}.",
"Danger!": "Attention !",
"Deleted": "Supprimé",
"Device": "Appareil",
@@ -67,6 +68,8 @@
"Editing {%path%}.": "Modification de {{path}}.",
"Enable NAT traversal": "Activer transfert d'adresses NAT",
"Enable Relaying": "Activer le relayage",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Nombre positif (p.ex, \"2.35\") et unité. Pourcentage de l'espace disque total.",
"Enter a non-privileged port number (1024 - 65535).": "Enter a non-privileged port number (1024 - 65535).",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "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.": "Entrer les masques d'exclusion, un par ligne.",
"Error": "Erreur",
@@ -90,6 +93,7 @@
"GUI": "Interface graphique",
"GUI Authentication Password": "Mot de passe d'authentification GUI",
"GUI Authentication User": "Utilisateur autorisé GUI",
"GUI Listen Address": "GUI Listen Address",
"GUI Listen Addresses": "Adresses de l'interface (GUI)",
"GUI Theme": "Thème graphique",
"Generate": "Générer",
@@ -241,6 +245,7 @@
"This Device": "Cet appareil",
"This can easily give hackers access to read and change any files on your computer.": "Ceci peut aisément permettre à un intrus de lire et modifier n'importe quel fichier de votre ordinateur. ",
"This is a major version upgrade.": "Il s'agit d'une mise à jour majeure.",
"This setting controls the free space required on the home (i.e., index database) disk.": "Ce réglage contrôle l'espace disque requis dans le disque qui abrite votre répertoire utilisateur (pour la base de données d'indexation).",
"Time": "Heure",
"Trash Can File Versioning": "Style poubelle",
"Type": "Type",

View File

@@ -10,6 +10,7 @@
"Add Device": "Ajouter l'appareil",
"Add Folder": "Ajouter un partage",
"Add Remote Device": "Ajouter un appareil",
"Add devices from the introducer to our device list, for mutually shared folders.": "Lui permettre d'ajouter et enlever des membres à toutes mes listes de membres des partages dont il fait (ou fera !) partie (ceci permet de créer toutes les liaisons point à point possibles en complétant mes listes par les siennes, meilleur débit de réception par cumul des débits d'envoi, indépendance vis à vis de l'introducteur, etc).",
"Add new folder?": "Ajouter ce partage ?",
"Address": "Adresse",
"Addresses": "Adresses",
@@ -23,14 +24,14 @@
"An external command handles the versioning. It has to remove the file from the shared folder.": "Une commande externe gère les versions de fichiers. Il lui incombe de supprimer les fichiers dans le répertoire synchronisé.",
"An external command handles the versioning. It has to remove the file from the synced folder.": "Une commande externe gère les versions de fichiers. Il lui incombe de supprimer les fichiers dans le répertoire synchronisé.",
"Anonymous Usage Reporting": "Rapport anonyme de statistiques d'utilisation",
"Any devices configured on an introducer device will be added to this device as well.": "Tout appareil ajouté sur un appareil que vous déclarez comme introducteur sera aussi ajouté sur votre propre appareil.",
"Any devices configured on an introducer device will be added to this device as well.": "Lui permettre d'ajouter et enlever des membres à toutes mes listes de membres des partages dont il fait (ou fera !) partie (ceci permet de créer toutes les liaisons point à point possibles en complétant mes listes par les siennes, meilleur débit de réception par cumul des débits d'envoi, indépendance vis à vis de l'introducteur, etc).",
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Le système de mise à jour automatique propose le choix entre versions stables et versions préliminaires.",
"Automatic upgrades": "Mises à jour automatiques",
"Be careful!": "Faites attention !",
"Bugs": "Bugs",
"CPU Utilization": "Utilisation du CPU",
"Changelog": "Historique des versions",
"Clean out after": "Purger après :",
"Clean out after": "Conserver pendant :",
"Click to see discovery failures": "Voir les échecs de découverte",
"Close": "Fermer",
"Command": "Commande",
@@ -41,9 +42,9 @@
"Connection Type": "Type de connexion",
"Copied from elsewhere": "Copié d'ailleurs",
"Copied from original": "Copié depuis l'original",
"Copyright © 2014-2016 the following Contributors:": "Copyright © 2014-2016, les contributeurs suivants:",
"Copyright © 2014-2017 the following Contributors:": "Copyright © 2014-2017, les contributeurs suivants :",
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Création de masques d'exclusion, remplacement du fichier existant dans {{path}}.",
"Copyright © 2014-2016 the following Contributors:": "Copyright © 2014-2016, les contributeurs sont:",
"Copyright © 2014-2017 the following Contributors:": "Copyright © 2014-2017, les contributeurs sont:",
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Création de masques d'exclusion, remplacement du fichier existant : {{path}}.",
"Danger!": "Attention !",
"Deleted": "Supprimé",
"Device": "Appareil",
@@ -67,6 +68,8 @@
"Editing {%path%}.": "Modification de {{path}}.",
"Enable NAT traversal": "Activer la translation d'adresses (NAT)",
"Enable Relaying": "Relayage possible",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Nombre positif (p.ex, \"2.35\") et unité. Pourcentage de l'espace disque total.",
"Enter a non-privileged port number (1024 - 65535).": "Entrez un n° de port non-privilégié (1024 - 65535)",
"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.",
"Error": "Erreur",
@@ -90,6 +93,7 @@
"GUI": "Interface graphique",
"GUI Authentication Password": "Mot de passe d'authentification GUI",
"GUI Authentication User": "Utilisateur autorisé GUI",
"GUI Listen Address": "Adresse d'écoute du GUI",
"GUI Listen Addresses": "Adresses de l'interface (GUI)",
"GUI Theme": "Thème graphique",
"Generate": "Générer",
@@ -108,7 +112,7 @@
"Introducer": "Appareil introducteur",
"Inversion of the given condition (i.e. do not exclude)": "Inverser la condition donnée (i.e. ne pas exclure)",
"Keep Versions": "Combien de versions conserver",
"Largest First": "Les plus volumineux d'abord",
"Largest First": "Les plus volumineux en premier",
"Last File Received": "Dernier changement",
"Last Scan": "Dernière analyse",
"Last seen": "Dernière apparition",
@@ -178,13 +182,13 @@
"Scan Time Remaining": "Temps d'analyse restant",
"Scanning": "Analyse en cours",
"Select the devices to share this folder with.": "Synchroniser avec :",
"Select the folders to share with this device.": "Sélectionner les partages auxquels participe cet appareil.",
"Select the folders to share with this device.": "Sélectionner les partages auxquels cet appareil doit participer :",
"Send & Receive": "Envoi & réception",
"Send Only": "Envoi (lecture seule)",
"Settings": "Configuration",
"Share": "Partager",
"Share Folder": "Partager",
"Share Folders With Device": "Partages avec cet appareil",
"Share Folders With Device": "Participe à ces partages",
"Share With Devices": "Synchroniser avec des appareils",
"Share this folder?": "Acceptez-vous ce partage ?",
"Shared With": "Synchronisé avec",
@@ -196,7 +200,7 @@
"Shutdown Complete": "Arrêté !",
"Simple File Versioning": "Suivi simplifié des versions",
"Single level wildcard (matches within a directory only)": "Joker à un seul niveau (correspond uniquement à lintérieur du répertoire)",
"Smallest First": "Les plus petits d'abord",
"Smallest First": "Les plus petits en premier",
"Source Code": "Code source",
"Stable releases and release candidates": "Versions stables et préliminaires",
"Stable releases are delayed by about two weeks. During this time they go through testing as release candidates.": "Les versions stables sont reportées d'environ deux semaines. Pendant ce temps elles sont testées en tant que versions préliminaires.",
@@ -231,7 +235,7 @@
"The maximum time to keep a version (in days, set to 0 to keep versions forever).": "Durée maximum de conservation d'une version (en jours, 0 pour conserver les versions indéfiniment)",
"The minimum free disk space percentage must be a non-negative number between 0 and 100 (inclusive).": "Le pourcentage d'espace disque libre doit être un nombre positif compris entre 0 et 100 (inclus).",
"The number of days must be a number and cannot be blank.": "Le nombre de jours doit être numérique et ne peut pas être vide.",
"The number of days to keep files in the trash can. Zero means forever.": "Le nombre de jours de conservation des fichiers dans la poubelle. 0 signifie toujours.",
"The number of days to keep files in the trash can. Zero means forever.": "Nombre de jours de conservation des fichiers dans la poubelle. 0 signifie \"indéfiniment\".",
"The number of old versions to keep, per file.": "Le nombre maximum d'anciennes versions à garder indéfiniment, par fichier.",
"The number of versions must be a number and cannot be blank.": "Le nombre de versions doit être numérique, et ne peut pas être vide.",
"The path cannot be blank.": "Le chemin ne peut pas être vide.",
@@ -241,6 +245,7 @@
"This Device": "Cet appareil",
"This can easily give hackers access to read and change any files on your computer.": "Ceci peut aisément permettre à un intrus de lire et modifier n'importe quel fichier de votre ordinateur.",
"This is a major version upgrade.": "Il s'agit d'une mise à jour majeure.",
"This setting controls the free space required on the home (i.e., index database) disk.": "Ce réglage contrôle l'espace disque requis dans le disque qui abrite votre répertoire utilisateur (pour la base de données d'indexation).",
"Time": "Heure",
"Trash Can File Versioning": "Style poubelle",
"Type": "Type",

View File

@@ -10,6 +10,7 @@
"Add Device": "Apparaat taheakje",
"Add Folder": "Map taheakje",
"Add Remote Device": "Apparaat op Ofstân Taheakje",
"Add devices from the introducer to our device list, for mutually shared folders.": "Heakje apparaten fan de yntrodusearders ta oan ús apparatenlyst, foar mei-inoar dielde mappen.",
"Add new folder?": "Nije map taheakje?",
"Address": "Adres",
"Addresses": "Adressen",
@@ -67,6 +68,8 @@
"Editing {%path%}.": "{{path}} wurd bewurke.",
"Enable NAT traversal": "NAT-trochkruse ynskeakelje",
"Enable Relaying": "Trochjaan tastean",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Fier in net-negatyf nûmer yn (bygelyks \"2.35\") en selektearje in ienheid. Percentages stean foar it part fan de totale skiifromte.",
"Enter a non-privileged port number (1024 - 65535).": "Fier in net-befoarrjochte poart-nûmer yn (1024 - 65535).",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Fier troch komma's skieden (\"tcp://ip:port\", \"tcp://host:port\") adressen yn of \"dynamic\" om automatyske ûntdekking fan it adres út te fieren.",
"Enter ignore patterns, one per line.": "Fier negearpatroanen yn, ien per rigel.",
"Error": "Flater",
@@ -90,6 +93,7 @@
"GUI": "GUI",
"GUI Authentication Password": "Wachtwurd foar ferifikaasje yn GUI",
"GUI Authentication User": "Brûkers-ID foar ferifikaasje yn GUI",
"GUI Listen Address": "GUI-harkadres",
"GUI Listen Addresses": "Harkadres foar GUI",
"GUI Theme": "Ynterfaasjetema",
"Generate": "Generearje",
@@ -241,6 +245,7 @@
"This Device": "Dit Apparaat",
"This can easily give hackers access to read and change any files on your computer.": "Dit kin samar ynkringers (hackers) tagong jaan om elke triem op jo kompjûter te besjen en te feroarjen.",
"This is a major version upgrade.": "Dit is in wichtige ferzjefernijing.",
"This setting controls the free space required on the home (i.e., index database) disk.": "Dizze ynstelling bepaalt de frije romte dy't noadich is op de home-skiif (fan de yndeks-databank).",
"Time": "Tiid",
"Trash Can File Versioning": "Jiskefet-triemferzjebehear",
"Type": "Type",

View File

@@ -10,6 +10,7 @@
"Add Device": "Eszköz hozzáadása",
"Add Folder": "Mappa hozzáadása",
"Add Remote Device": "Távoli eszköz hozzáadása",
"Add devices from the introducer to our device list, for mutually shared folders.": "Eszközök hozzáadása a bevezetőről az eszköz listához, a közösen megosztott mappákhoz.",
"Add new folder?": "Hozzáadható az új mappa?",
"Address": "Cím",
"Addresses": "Címek",
@@ -67,6 +68,8 @@
"Editing {%path%}.": "{{path}} szerkesztése.",
"Enable NAT traversal": "NAT bejárás engedélyezése",
"Enable Relaying": "Közvetítés engedélyezése",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Adj meg egy nem-negatív számot (pl. \"2.35\") és válassz egy mértékegységet. A százalékok a teljes lemezméretre vonatkoznak.",
"Enter a non-privileged port number (1024 - 65535).": "Adj meg egy nem privilegizált port számot (1024 - 65535).",
"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 bevihető (\"tcp://ip:port\", \"tcp://host:port\"), az automatikus felderítéshez a 'dynamic' kulcsszó használatos. ",
"Enter ignore patterns, one per line.": "A kihagyási mintákból soronként egyet kell megadni.",
"Error": "Hiba",
@@ -90,6 +93,7 @@
"GUI": "Grafikus felület",
"GUI Authentication Password": "Grafikus felület jelszava",
"GUI Authentication User": "Grafikus felület felhasználói neve ",
"GUI Listen Address": "Grafikus felület címe",
"GUI Listen Addresses": "Grafikus felület címe",
"GUI Theme": "Grafikus felület témája",
"Generate": "Generálás",
@@ -241,6 +245,7 @@
"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.",
"This is a major version upgrade.": "Ez egy főverzió-frissítés.",
"This setting controls the free space required on the home (i.e., index database) disk.": "Ez e beállítás szabályozza a szükséges szabad helyet a fő (pl: index, adatbázis) lemezen.",
"Time": "Idő",
"Trash Can File Versioning": "Szemetes fájlverzió-követés",
"Type": "Típus",

View File

@@ -10,6 +10,7 @@
"Add Device": "Tambah Perangkat",
"Add Folder": "Tambah Folder",
"Add Remote Device": "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?": "Tambah folder baru",
"Address": "Alamat",
"Addresses": "Alamat",
@@ -67,6 +68,8 @@
"Editing {%path%}.": "Editing {{path}}.",
"Enable NAT traversal": "Enable NAT traversal",
"Enable Relaying": "Aktifkan Relay",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.",
"Enter a non-privileged port number (1024 - 65535).": "Enter a non-privileged port number (1024 - 65535).",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Masukkan alamat, pisahkan dengan koma (\"tcp://ip:port\", \"tcp://host:port\") atau \"dynamic\" untuk menjalankan penemuan otomatis alamat tersebut.",
"Enter ignore patterns, one per line.": "Masukkan pola pengabaian, satu per baris.",
"Error": "Galat",
@@ -90,6 +93,7 @@
"GUI": "GUI",
"GUI Authentication Password": "Sandi Otentikasi GUI",
"GUI Authentication User": "Pengguna Otentikasi GUI",
"GUI Listen Address": "GUI Listen Address",
"GUI Listen Addresses": "Alamat Listen GUI",
"GUI Theme": "GUI Theme",
"Generate": "Buat Baru",
@@ -241,6 +245,7 @@
"This Device": "This Device",
"This can easily give hackers access to read and change any files on your computer.": "This can easily give hackers access to read and change any files on your computer.",
"This is a major version upgrade.": "This is a major version upgrade.",
"This setting controls the free space required on the home (i.e., index database) disk.": "This setting controls the free space required on the home (i.e., index database) disk.",
"Time": "Time",
"Trash Can File Versioning": "Trash Can File Versioning",
"Type": "Type",

View File

@@ -10,6 +10,7 @@
"Add Device": "Aggiungi Dispositivo",
"Add Folder": "Aggiungi Cartella",
"Add Remote Device": "Aggiungi Dispositivo Remoto",
"Add devices from the introducer to our device list, for mutually shared folders.": "Aggiungi dispositivi dall'introduttore al nostro elenco, per le cartelle condivise reciprocamente.",
"Add new folder?": "Aggiungere una nuova cartella?",
"Address": "Indirizzo",
"Addresses": "Indirizzi",
@@ -43,7 +44,7 @@
"Copied from original": "Copiato dall'originale",
"Copyright © 2014-2016 the following Contributors:": "Copyright © 2014-2016 i seguenti Collaboratori:",
"Copyright © 2014-2017 the following Contributors:": "Copyright © 2014-2017 i seguenti Collaboratori:",
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Creating ignore patterns, overwriting an existing file at {{path}}.",
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Creazione di schemi di esclusione, sovrascrivendo un file esistente in {{path}}.",
"Danger!": "Pericolo!",
"Deleted": "Cancellato",
"Device": "Dispositivo",
@@ -64,9 +65,11 @@
"Edit Device": "Modifica Dispositivo",
"Edit Folder": "Modifica Cartella",
"Editing": "Modifica di",
"Editing {%path%}.": "Editing {{path}}.",
"Editing {%path%}.": "Modifica di {{path}}.",
"Enable NAT traversal": "Abilita NAT traversal",
"Enable Relaying": "Abilita Reindirizzamento",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Inserisci un numero non negativo (ad esempio \"2.35\") e seleziona un'unità. Le percentuali sono parte della dimensione totale del disco.",
"Enter a non-privileged port number (1024 - 65535).": "Enter a non-privileged port number (1024 - 65535).",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Inserisci indirizzi separati da virgola (\"tcp://ip:porta\", \"tcp://host:porta\") oppure \"dynamic\" per effettuare il rilevamento automatico dell'indirizzo.",
"Enter ignore patterns, one per line.": "Inserisci gli schemi di esclusione, uno per riga.",
"Error": "Errore",
@@ -90,6 +93,7 @@
"GUI": "Interfaccia Grafica Utente",
"GUI Authentication Password": "Password dell'Interfaccia Grafica",
"GUI Authentication User": "Utente dell'Interfaccia Grafica",
"GUI Listen Address": "GUI Listen Address",
"GUI Listen Addresses": "Indirizzi dell'Interfaccia Grafica",
"GUI Theme": "Tema GUI",
"Generate": "Genera",
@@ -241,6 +245,7 @@
"This Device": "Questo Dispositivo",
"This can easily give hackers access to read and change any files on your computer.": "Ciò potrebbe facilmente permettere agli hackers accesso alla lettura e modifica di qualunque file del tuo computer.",
"This is a major version upgrade.": "Questo è un aggiornamento di versione principale",
"This setting controls the free space required on the home (i.e., index database) disk.": "Questa impostazione controlla lo spazio libero richiesto sul disco home (cioè, database di indice).",
"Time": "Tempo",
"Trash Can File Versioning": "Controllo Versione con Cestino",
"Type": "Tipo",

View File

@@ -10,6 +10,7 @@
"Add Device": "デバイスを追加",
"Add Folder": "フォルダーを追加",
"Add Remote Device": "接続先デバイスを追加",
"Add devices from the introducer to our device list, for mutually shared folders.": "紹介者デバイスから紹介されたデバイスは、相互に共有しているフォルダーがある場合、このデバイス上でも登録されます。",
"Add new folder?": "新しいフォルダーとして追加しますか?",
"Address": "アドレス",
"Addresses": "アドレス",
@@ -67,6 +68,8 @@
"Editing {%path%}.": "{{path}} を編集中。",
"Enable NAT traversal": "NATトラバーサルを有効にする",
"Enable Relaying": "中継サーバー経由の通信を有効にする",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "0以上の数 (例: 2.35) を入力し、単位を選択してください。パーセントはディスク容量全体に対する割合です。",
"Enter a non-privileged port number (1024 - 65535).": "非特権ポート番号 (1024 - 65535) を入力してください。",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "アドレスを指定する場合は「tcp://IPアドレス:ポート」または「tcp://ホスト名:ポート」をコンマで区切って入力してください。自動探索を行う場合は「dynamic」と入力してください。",
"Enter ignore patterns, one per line.": "無視するファイル名のパターンを、一行につき一条件で入力してください。",
"Error": "エラー",
@@ -90,6 +93,7 @@
"GUI": "GUI",
"GUI Authentication Password": "GUI認証パスワード",
"GUI Authentication User": "GUI認証ユーザー名",
"GUI Listen Address": "GUI待ち受けアドレス",
"GUI Listen Addresses": "GUI待ち受けアドレスリスト",
"GUI Theme": "GUIテーマ",
"Generate": "生成",
@@ -241,6 +245,7 @@
"This Device": "このデバイス",
"This can easily give hackers access to read and change any files on your computer.": "この設定のままでは、あなたのコンピューターにある任意のファイルを、他者が簡単に盗み見たり書き換えたりすることができます。",
"This is a major version upgrade.": "メジャーアップグレードです。",
"This setting controls the free space required on the home (i.e., index database) disk.": "この設定は、ホームディスク (インデックスデータベースがあるディスク) で必要な空き容量を管理します。",
"Time": "日時",
"Trash Can File Versioning": "ゴミ箱によるバージョン管理",
"Type": "タイプ",

View File

@@ -10,6 +10,7 @@
"Add Device": "기기 추가",
"Add Folder": "폴더 추가",
"Add Remote Device": "다른 기기 추가",
"Add devices from the introducer to our device list, for mutually shared folders.": "상호 공유 폴더에 대해 유도자의 장치를 장치 목록에 추가합니다.",
"Add new folder?": "새로운 폴더를 추가하시겠습니까?",
"Address": "주소",
"Addresses": "주소",
@@ -67,6 +68,8 @@
"Editing {%path%}.": "{{path}} 수정하기.",
"Enable NAT traversal": "NAT traversal 활성화",
"Enable Relaying": "Relaying 활성화",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "음수가 아닌 수 (예, \"2.35\") 를 입력 후 단위를 선택하세요. 백분율은 총 디스크 크기의 일부입니다.",
"Enter a non-privileged port number (1024 - 65535).": "비 특권 포트 번호를 입력하세요 (1024 - 65535).",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "주소 자동 검색을 하기 위해서는 \"ip:port\" 형식의 주소들을 쉼표로 구분해서 입력하거나 \"dynamic\"을 입력하세요.",
"Enter ignore patterns, one per line.": "무시할 패턴을 한 줄에 하나씩 입력하세요.",
"Error": "오류",
@@ -90,6 +93,7 @@
"GUI": "GUI",
"GUI Authentication Password": "GUI 인증 비밀번호",
"GUI Authentication User": "GUI 인증 사용자",
"GUI Listen Address": "GUI 주소",
"GUI Listen Addresses": "GUI 주소",
"GUI Theme": "GUI 테마",
"Generate": "생성",
@@ -241,6 +245,7 @@
"This Device": "현재 기기",
"This can easily give hackers access to read and change any files on your computer.": "이 설정은 해커가 손쉽게 사용자 컴퓨터의 모든 파일을 읽고 변경할 수 있도록 할 수 있습니다.",
"This is a major version upgrade.": "이 업데이트는 메이저 버전입니다.",
"This setting controls the free space required on the home (i.e., index database) disk.": "이 설정은 홈 디스크에 필요한 여유 공간을 제어합니다. (즉, 인덱스 데이터베이스)",
"Time": "시간",
"Trash Can File Versioning": "휴지통을 통한 파일 버전 관리",
"Type": "종류",

View File

@@ -10,6 +10,7 @@
"Add Device": "Pridėti įrenginį",
"Add Folder": "Pridėti aplanką",
"Add Remote Device": "Pridėti nuotolinį įrenginį",
"Add devices from the introducer to our device list, for mutually shared folders.": "Pridėti įrenginius iš supažindintojo į mūsų įrenginių sąrašą, siekiant abipusiškai bendrinti aplankus.",
"Add new folder?": "Pridėti naują aplanką?",
"Address": "Adresas",
"Addresses": "Adresai",
@@ -67,6 +68,8 @@
"Editing {%path%}.": "Redaguojama {{path}}.",
"Enable NAT traversal": "Leisti kirsti NAT",
"Enable Relaying": "Įjungti retransliavimą",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Įveskite neneigiamąjį skaičių (pvz., \"2.35\") ir pasirinkite įtaisą. Procentai yra skaičiuojami kaip viso disko dydžio dalis.",
"Enter a non-privileged port number (1024 - 65535).": "Įveskite neprivilegijuoto prievado numerį (1024 - 65535).",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Įveskite kableliais atskirtus (\"tcp://ip:prievadas\", \"tcp://serveris:prievadas\") adresus arba \"dynamic\", kad atliktumėte automatinį adresų aptikimą.",
"Enter ignore patterns, one per line.": "Suveskite nepaisomus šablonus, kiekvieną naujoje eilutėje.",
"Error": "Klaida",
@@ -90,6 +93,7 @@
"GUI": "Valdymo skydelis",
"GUI Authentication Password": "Valdymo skydelio slaptažodis",
"GUI Authentication User": "Valdymo skydelio vartotojo vardas",
"GUI Listen Address": "Valdymo skydelio adresas",
"GUI Listen Addresses": "Valdymo skydelio adresas",
"GUI Theme": "Valdymo skydelio tema",
"Generate": "Sukurti",
@@ -125,7 +129,7 @@
"Metadata Only": "Metaduomenims",
"Minimum Free Disk Space": "Minimum laisvos vietos diske",
"Move to top of queue": "Perkelti į eilės priekį",
"Multi level wildcard (matches multiple directory levels)": "Keletos lygių pakaitos (atitinka keletą direktorijų lygių)",
"Multi level wildcard (matches multiple directory levels)": "Keleto lygių pakaitos simbolis (atitinka keletą katalogų lygių)",
"Never": "Niekada",
"New Device": "Naujas įrenginys",
"New Folder": "Naujas aplankas",
@@ -195,7 +199,7 @@
"Shutdown": "Išjungti",
"Shutdown Complete": "Sėkmingai išjungta",
"Simple File Versioning": "Supaprastintas versijų valdymas",
"Single level wildcard (matches within a directory only)": "Vieno lygio pakaitos (atitinka tik vieną direktorijos lygį)",
"Single level wildcard (matches within a directory only)": "Vieno lygio pakaitos simbolis (atitinka tik vieną katalogo lygį)",
"Smallest First": "Mažiausi pirmiau",
"Source Code": "Išeities kodas",
"Stable releases and release candidates": "Stabilios versijos ir kandidatinės versijos",
@@ -226,7 +230,7 @@
"The folder ID must be unique.": "Aplanko ID turi būti unikalus.",
"The folder path cannot be blank.": "Kelias iki aplanko negali būti tuščias.",
"The following intervals are used: for the first hour a version is kept every 30 seconds, for the first day a version is kept every hour, for the first 30 days a version is kept every day, until the maximum age a version is kept every week.": "Šie pertraukų nustatymai naudojami: pirmą valandą versijos laikomos 30 sekundžių, pirmą dieną versijos laikomos valandą, pirmas 30 dienų versijos laikomos parą, kol nebus viršytas nustatytas maksimalus amžius.",
"The following items could not be synchronized.": "Nepavyko parsiųsti šių failų",
"The following items could not be synchronized.": "Nepavyko parsiųsti šių failų.",
"The maximum age must be a number and cannot be blank.": "Maksimalus amžius turi būti skaitmuo ir negali būti tuščias laukelis.",
"The maximum time to keep a version (in days, set to 0 to keep versions forever).": "Maksimalus laikas kurį bus saugojama versija (dienomis, nustatykite 0 norėdami saugoti amžinai).",
"The minimum free disk space percentage must be a non-negative number between 0 and 100 (inclusive).": "Mažiausia laisvos disko vietos procentinė reikšmė privalo būti neneigiamas skaičius tarp 0 ir 100 (imtinai).",
@@ -237,10 +241,11 @@
"The path cannot be blank.": "Kelias negali būti tuščias.",
"The rate limit must be a non-negative number (0: no limit)": "Srauto maksimalus greitis privalo būti ne neigiamas skaičius (0: nėra apribojimo)",
"The rescan interval must be a non-negative number of seconds.": "Nuskaitymo dažnis negali būti neigiamas skaičius.",
"They are retried automatically and will be synced when the error is resolved.": "Failus bus automatiškai bandoma parsiųsti dar kartą kai išspręsite klaidas",
"They are retried automatically and will be synced when the error is resolved.": "Failus bus automatiškai bandoma parsiųsti dar kartą kai išspręsite klaidas.",
"This Device": "Šis įrenginys",
"This can easily give hackers access to read and change any files on your computer.": "Tai gali suteikti programišiams lengvą prieigą skaityti ir keisti bet kokius failus jūsų kompiuteryje.",
"This is a major version upgrade.": "Tai yra stambus atnaujinimas.",
"This setting controls the free space required on the home (i.e., index database) disk.": "Šis nustatymas valdo laisvą vietą, kuri yra reikalinga namų (t.y., rodyklės duomenų bazės) diske.",
"Time": "Laikas",
"Trash Can File Versioning": "Šiukšliadėžės versijų valdymas",
"Type": "Tipas",
@@ -270,7 +275,7 @@
"You can read more about the two release channels at the link below.": "Jūs galite perskaityti daugiau apie šiuos du laidos kanalus, pasinaudodami žemiau esančia nuoroda.",
"You must keep at least one version.": "Būtina saugoti bent vieną versiją.",
"days": "dienos",
"directories": "papkės",
"directories": "katalogai",
"files": "failai",
"full documentation": "pilna dokumentacija",
"items": "įrašai",

View File

@@ -10,6 +10,7 @@
"Add Device": "Legg til enhet",
"Add Folder": "Legg til mappe",
"Add Remote Device": "Legg til ekstern enhet",
"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?": "Legg til ny mappe?",
"Address": "Adresse",
"Addresses": "Adresser",
@@ -67,6 +68,8 @@
"Editing {%path%}.": "Editing {{path}}.",
"Enable NAT traversal": "Slå på NAT-traversering",
"Enable Relaying": "Aktiver reléforsendelse",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.",
"Enter a non-privileged port number (1024 - 65535).": "Enter a non-privileged port number (1024 - 65535).",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Skriv inn kommaseparerte (\"tcp://ip:port\", \"tcp://host:port\") adresser, eller ordet \"dynamic\" for å gjøre automatisk oppslag i adressen.",
"Enter ignore patterns, one per line.": "Skriv inn mønster som skal utelates, ett per linje.",
"Error": "Feilmelding",
@@ -90,6 +93,7 @@
"GUI": "grafisk brukergrensesnitt",
"GUI Authentication Password": "Passord for GUI-autenisering",
"GUI Authentication User": "Bruker for GUI-autenisering",
"GUI Listen Address": "GUI Listen Address",
"GUI Listen Addresses": "GUI-lytteadresse",
"GUI Theme": "GUI-tema",
"Generate": "Generer",
@@ -241,6 +245,7 @@
"This Device": "Denne enheten",
"This can easily give hackers access to read and change any files on your computer.": "Dette kan lett gi hackere tilgang til å lese og endre alle filer på datamaskinen din.",
"This is a major version upgrade.": "Dette er en storoppgradering",
"This setting controls the free space required on the home (i.e., index database) disk.": "This setting controls the free space required on the home (i.e., index database) disk.",
"Time": "Klokkeslett",
"Trash Can File Versioning": "Papirkurv versjonskontroll",
"Type": "Type",

View File

@@ -10,6 +10,7 @@
"Add Device": "Apparaat toevoegen",
"Add Folder": "Map toevoegen",
"Add Remote Device": "Voeg extern apparaat toe",
"Add devices from the introducer to our device list, for mutually shared folders.": "Voeg apparaten van het introductieapparaat toe aan de lijst met apparaten voor gemeenschappelijk gedeelde mappen.",
"Add new folder?": "Nieuwe map toevoegen?",
"Address": "Adres",
"Addresses": "Adressen",
@@ -67,6 +68,8 @@
"Editing {%path%}.": "Bezig met bewerken van {{path}}.",
"Enable NAT traversal": "Activeer NAT traversal",
"Enable Relaying": "Activeer doorsturen",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.",
"Enter a non-privileged port number (1024 - 65535).": "Enter a non-privileged port number (1024 - 65535).",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Voer door komma's gescheiden (\"tcp://ip:port\", \"tcp://host:port\") adressen in of voer \"dynamisch\" in om automatische ontdekking van het adres uit te voeren.",
"Enter ignore patterns, one per line.": "Voer negeerpatronen in, één per regel.",
"Error": "Fout",
@@ -90,6 +93,7 @@
"GUI": "GUI",
"GUI Authentication Password": "GUI-wachtwoord",
"GUI Authentication User": "GUI-gebruikersnaam",
"GUI Listen Address": "GUI Listen Address",
"GUI Listen Addresses": "GUI-adres",
"GUI Theme": "GUI-thema",
"Generate": "Genereer",
@@ -241,6 +245,7 @@
"This Device": "Dit apparaat",
"This can easily give hackers access to read and change any files on your computer.": "Dit kan kwaadwilligen eenvoudig toegang geven tot het lezen en wijzigen van bestanden op jouw computer.",
"This is a major version upgrade.": "Dit is een grote update.",
"This setting controls the free space required on the home (i.e., index database) disk.": "This setting controls the free space required on the home (i.e., index database) disk.",
"Time": "Tijd",
"Trash Can File Versioning": "Versiebeheer bestanden prullenbak",
"Type": "Type",

View File

@@ -10,6 +10,7 @@
"Add Device": "Legg Til Eining",
"Add Folder": "Legg Til Mappe",
"Add Remote Device": "Legg til ekstern eining",
"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?": "Leggja til ny mappe?",
"Address": "Adresse",
"Addresses": "Adresser",
@@ -67,6 +68,8 @@
"Editing {%path%}.": "Editing {{path}}.",
"Enable NAT traversal": "Slå på NAT-gjennomgang",
"Enable Relaying": "Aktiver relé",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.",
"Enter a non-privileged port number (1024 - 65535).": "Enter a non-privileged port number (1024 - 65535).",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Skriv inn adresser med komma mellom kvar adresse («tcp://ip:port», «tcp://host:port»), eller «dynamic» for å automatisk søkja opp adressa.",
"Enter ignore patterns, one per line.": "Skriv inn mønster som skal utelatast, eitt per linje.",
"Error": "Feilmelding",
@@ -90,6 +93,7 @@
"GUI": "grafisk brukargrensesnitt",
"GUI Authentication Password": "GUI Passord",
"GUI Authentication User": "GUI Brukar",
"GUI Listen Address": "GUI Listen Address",
"GUI Listen Addresses": "GUI Lytteadresse",
"GUI Theme": "GUI Theme",
"Generate": "Generer",
@@ -241,6 +245,7 @@
"This Device": "Denne eininga",
"This can easily give hackers access to read and change any files on your computer.": "Dette kan lett gje datasnokar tilgang til å lesa og endra vilkårlege filer på denne maskina.",
"This is a major version upgrade.": "Dette er ei hovudoppgradering",
"This setting controls the free space required on the home (i.e., index database) disk.": "This setting controls the free space required on the home (i.e., index database) disk.",
"Time": "Time",
"Trash Can File Versioning": "Papirkorg-filutgåvehandtering",
"Type": "Type",

View File

@@ -10,6 +10,7 @@
"Add Device": "Dodaj urządzenie",
"Add Folder": "Dodaj folder",
"Add Remote Device": "Dodaj urządzenie zdalne",
"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?": "Dodać nowy folder?",
"Address": "Adres",
"Addresses": "Adresy",
@@ -67,6 +68,8 @@
"Editing {%path%}.": "Editing {{path}}.",
"Enable NAT traversal": "Włącz trawersowanie NAT",
"Enable Relaying": "Włącz przekazywanie",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.",
"Enter a non-privileged port number (1024 - 65535).": "Enter a non-privileged port number (1024 - 65535).",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Wpisz oddzielone przecinkiem adresy (\"tcp://ip:port\", \"tcp://host:port\") lub \"dynamic\" by przeprowadzić automatyczne odnalezienie adresu.",
"Enter ignore patterns, one per line.": "Wprowadź wzorce ignorowania, jeden w każdej linii.",
"Error": "Błąd",
@@ -90,6 +93,7 @@
"GUI": "GUI",
"GUI Authentication Password": "Hasło",
"GUI Authentication User": "Użytkownik",
"GUI Listen Address": "GUI Listen Address",
"GUI Listen Addresses": "Adres nasłuchiwania",
"GUI Theme": "Motyw GUI",
"Generate": "Generuj",
@@ -241,6 +245,7 @@
"This Device": "To urządzenie",
"This can easily give hackers access to read and change any files on your computer.": "Może to umożliwić osobom trzecim dostęp do odczytu i zmian dowolnych plików na urządzeniu.",
"This is a major version upgrade.": "To jest ważna aktualizacja",
"This setting controls the free space required on the home (i.e., index database) disk.": "This setting controls the free space required on the home (i.e., index database) disk.",
"Time": "Czas",
"Trash Can File Versioning": "Kontrola werjsi plików w koszu",
"Type": "Typ",

View File

@@ -10,6 +10,7 @@
"Add Device": "Adicionar dispositivo",
"Add Folder": "Adicionar pasta",
"Add Remote Device": "Adicionar dispositivo remoto",
"Add devices from the introducer to our device list, for mutually shared folders.": "Adicionar dispositivos do introdutor à sua lista de dispositivos para pastas compartilhadas mutualmente.",
"Add new folder?": "Adicionar nova pasta?",
"Address": "Endereço",
"Addresses": "Endereços",
@@ -43,7 +44,7 @@
"Copied from original": "Copiado do original",
"Copyright © 2014-2016 the following Contributors:": "Direitos reservados © 2014-2016 aos seguintes colaboradores:",
"Copyright © 2014-2017 the following Contributors:": "Copyright © 2014-2017 dos seguintes Colaboradores:",
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Creating ignore patterns, overwriting an existing file at {{path}}.",
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Criando filtros, sobrescrevendo o arquivo {{path}}.",
"Danger!": "Perigo!",
"Deleted": "Apagado",
"Device": "Dispositivo",
@@ -67,6 +68,8 @@
"Editing {%path%}.": "Editando {{path}}.",
"Enable NAT traversal": "Habilitar NAT",
"Enable Relaying": "Habilitar retransmissão",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Insira um número não negativo (por exemplo, 2.35) e escolha uma unidade. Porcentagens são como parte do tamanho total do disco.",
"Enter a non-privileged port number (1024 - 65535).": "Insira um número de porta não privilegiada (1024-65535).",
"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 ignore patterns, one per line.": "Insira os filtros, um por linha.",
"Error": "Erro",
@@ -90,6 +93,7 @@
"GUI": "Interface gráfica",
"GUI Authentication Password": "Senha para acesso à interface",
"GUI Authentication User": "Nome de usuário para acesso à interface",
"GUI Listen Address": "Endereço de escuta da interface web",
"GUI Listen Addresses": "Endereços de escuta da interface",
"GUI Theme": "Tema da interface",
"Generate": "Gerar",
@@ -241,6 +245,7 @@
"This Device": "Este dispositivo",
"This can easily give hackers access to read and change any files on your computer.": "Isto pode dar a hackers poder de leitura e escrita de qualquer arquivo em seu dispositivo.",
"This is a major version upgrade.": "Esta é uma atualização para uma versão \"major\".",
"This setting controls the free space required on the home (i.e., index database) disk.": "This setting controls the free space required on the home (i.e., index database) disk.",
"Time": "Hora",
"Trash Can File Versioning": "Lixeira",
"Type": "Tipo",

View File

@@ -10,6 +10,7 @@
"Add Device": "Adicionar dispositivo",
"Add Folder": "Adicionar pasta",
"Add Remote Device": "Adicionar dispositivo remoto",
"Add devices from the introducer to our device list, for mutually shared folders.": "Adicione dispositivos do apresentador à nossa lista de dispositivos para ter pastas mutuamente partilhadas.",
"Add new folder?": "Adicionar nova pasta?",
"Address": "Endereço",
"Addresses": "Endereços",
@@ -67,6 +68,8 @@
"Editing {%path%}.": "Editando {{path}}.",
"Enable NAT traversal": "Activar travessia de NAT",
"Enable Relaying": "Permitir retransmissão",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Escreva um número positivo (ex.: \"2.35\") e seleccione uma unidade. Percentagens são relativas ao tamanho total do disco.",
"Enter a non-privileged port number (1024 - 65535).": "Escreva um número de porto não-privilegiado (1024-65535).",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Introduza endereços separados por vírgulas (\"tcp://ip:porto\", \"tcp://máquina:porto\") ou \"dynamic\" para detectar automaticamente os endereços.",
"Enter ignore patterns, one per line.": "Escreva os padrões de exclusão, um por linha.",
"Error": "Erro",
@@ -90,6 +93,7 @@
"GUI": "Interface gráfica",
"GUI Authentication Password": "Senha da autenticação na interface gráfica",
"GUI Authentication User": "Utilizador da autenticação na interface gráfica",
"GUI Listen Address": "Endereço de escuta da interface gráfica",
"GUI Listen Addresses": "Endereço de escuta da interface gráfica",
"GUI Theme": "Tema gráfico",
"Generate": "Gerar",
@@ -241,6 +245,7 @@
"This Device": "Este dispositivo",
"This can easily give hackers access to read and change any files on your computer.": "Isso facilmente dará acesso aos piratas informáticos para lerem e modificarem quaisquer ficheiros no seu computador.",
"This is a major version upgrade.": "Esta é uma actualização para uma versão importante.",
"This setting controls the free space required on the home (i.e., index database) disk.": "Este parâmetro controla o espaço livre necessário no disco base (ou seja, o disco da base de dados do índice).",
"Time": "Quando",
"Trash Can File Versioning": "Reciclagem",
"Type": "Tipo",

View File

@@ -10,6 +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?": "Добавить новую папку?",
"Address": "Адрес",
"Addresses": "Адреса",
@@ -67,6 +68,8 @@
"Editing {%path%}.": "Editing {{path}}.",
"Enable NAT traversal": "Включить NAT traversal",
"Enable Relaying": "Включить релеи",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.",
"Enter a non-privileged port number (1024 - 65535).": "Enter a non-privileged port number (1024 - 65535).",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Введите через запятую («tcp://ip:port», «tcp://host:port») адреса, либо «dynamic», чтобы выполнить автоматическое обнаружение адреса.",
"Enter ignore patterns, one per line.": "Введите шаблоны игнорирования, по одному на строку.",
"Error": "Ошибка",
@@ -90,6 +93,7 @@
"GUI": "Интерфейс",
"GUI Authentication Password": "Пароль для доступа к панели управления",
"GUI Authentication User": "Имя пользователя для доступа к панели управления",
"GUI Listen Address": "GUI Listen Address",
"GUI Listen Addresses": "Адрес панели управления",
"GUI Theme": "Тема оформления",
"Generate": "Сгенерировать",
@@ -241,6 +245,7 @@
"This Device": "Это устройство",
"This can easily give hackers access to read and change any files on your computer.": "Это может дать доступ хакерам для чтения и изменения любых файлов на вашем компьютере.",
"This is a major version upgrade.": "Это обновление основной версии продукта.",
"This setting controls the free space required on the home (i.e., index database) disk.": "This setting controls the free space required on the home (i.e., index database) disk.",
"Time": "Время",
"Trash Can File Versioning": "Использовать версионность для файлов в Корзине",
"Type": "Тип",

View File

@@ -0,0 +1,284 @@
{
"A device with that ID is already added.": "Prístroj s týmto ID je už pridaný.",
"A negative number of days doesn't make sense.": "Záporný počet dní nedáva zmysel.",
"A new major version may not be compatible with previous versions.": "Nová hlavná verzia nemusí byť kompatibilná s predchádzajúcimi verziami.",
"API Key": "API kľúč",
"About": "O aplikácii",
"Action": "Akcia",
"Actions": "Akcie",
"Add": "Pridať",
"Add Device": "Pridať zariadenie",
"Add Folder": "Pridať adresár",
"Add Remote Device": "Pridať vzdialené zariadenie",
"Add devices from the introducer to our device list, for mutually shared folders.": "Pre vzájomne zdielané adresáre pridaj zariadenie od zavádzača do svojho zoznamu zariadení.",
"Add new folder?": "Pridať nový adresár?",
"Address": "Adresa",
"Addresses": "Adresy",
"Advanced": "Pokročilé",
"Advanced Configuration": "Pokročilá konfigurácia",
"Advanced settings": "Pokročilé nastavenia",
"All Data": "Všetky dáta",
"Allow Anonymous Usage Reporting?": "Povoliť anoynmné hlásenie o použivaní?",
"Allowed Networks": "Povolené siete",
"Alphabetic": "Abecedne",
"An external command handles the versioning. It has to remove the file from the shared folder.": "Externý príkaz obstaráva verzie. Musí odstrániť ",
"An external command handles the versioning. It has to remove the file from the synced folder.": "Verzie spravuje externý príkaz. Musí odstrániť súbor zo synchronizovaného adresára.",
"Anonymous Usage Reporting": "Anonymné hlásenie o používaní",
"Any devices configured on an introducer device will be added to this device as well.": "Všetky zariadenia nakonfigurované na uvádzači budú tiež pridané na tomto zariadení.",
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Automatická aktualizácia teraz ponúka voľbu medzi stabilnými vydaniami a kandidátmi na vydanie.",
"Automatic upgrades": "Automatické aktualizácie",
"Be careful!": "Buď opatrný!",
"Bugs": "Cyhby",
"CPU Utilization": "Využitie CPU",
"Changelog": "Záznam zmien",
"Clean out after": "Vyčistenie po",
"Click to see discovery failures": "Klikni pre zobrazenie zlyhaní objavovania.",
"Close": "Zatvoriť",
"Command": "Príkaz",
"Comment, when used at the start of a line": "Komentár, keď použité na začiatku riadku",
"Compression": "Kompresia",
"Configured": "Nakonfigurované",
"Connection Error": "Chyba pripojenia",
"Connection Type": "Typ pripojenia",
"Copied from elsewhere": "Skoprírované odinakiaľ",
"Copied from original": "Skopírované z originálu",
"Copyright © 2014-2016 the following Contributors:": "Copyright © 2014-2016 následujúci prispivatelia:",
"Copyright © 2014-2017 the following Contributors:": "Copyright © 2014-2017 následujúci prispivatelia:",
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Creating ignore patterns, overwriting an existing file at {{path}}.",
"Danger!": "Pozor!",
"Deleted": "Zmazané",
"Device": "Zariadenie",
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "Zariadenie \"{{name}}\" ({{device}} na {{address}}) sa chce pripojiť. Pridať nové zariadenie?",
"Device ID": "ID zariadenia",
"Device Identification": "Identifikácia zariadenia",
"Device Name": "Názov zariadenia",
"Devices": "Zariadenia",
"Disconnected": "Odpojené",
"Discovered": "Objavené",
"Discovery": "Objavenie",
"Discovery Failures": "Zlyhania objavovania",
"Documentation": "Dokumentácia",
"Download Rate": "Rýchlosť sťahovania",
"Downloaded": "Stiahnuté",
"Downloading": "Sťahovanie",
"Edit": "Upraviť",
"Edit Device": "Upraviť zariadenie",
"Edit Folder": "Upraviť Adresár",
"Editing": "Úprava",
"Editing {%path%}.": "Úprava {{path}}.",
"Enable NAT traversal": "Povoliť priechod NAT",
"Enable Relaying": "Povoliť prenosové uzly",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Vložte kladné číslo (napr. \"2,35\") a zvoľte jednotku. Percentá sa zobrazujú ako časť celkovej veľkosti disku.",
"Enter a non-privileged port number (1024 - 65535).": "Enter a non-privileged port number (1024 - 65535).",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Zadaj čiarkou oddelené (\"tcp://ip:port\", \"tcp://host:port\") adresy alebo \"dynamic\" na automatické zistenie adresy.",
"Enter ignore patterns, one per line.": "Zadaj ignorované vzory, jeden na riadok.",
"Error": "Chyba",
"External File Versioning": "Externé spracovanie verzií súborov",
"Failed Items": "Zlyhané položky",
"Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.": "Zlyhanie pripojenia k IPv6 serverom je očakávané ak neexistujú žiadne IPv6 pripojenia.",
"File Pull Order": "Poradie sťahovania súborov",
"File Versioning": "Verzie súborov",
"File permission bits are ignored when looking for changes. Use on FAT file systems.": "Údaje o právach súboru sú pri porovnávaní zmien ignorované. Použi pri súborových systémoch FAT.",
"Files are moved to .stversions directory when replaced or deleted by Syncthing.": "Súbory zmenené alebo zmazané aplikáciou Syncthing sú presunuté do adresára .stversions .",
"Files are moved to .stversions folder when replaced or deleted by Syncthing.": "Súbory premiestené alebo zmazané aplikáciou Sycthing sú presunuté do adresára .stversions.",
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Súbory premiestnené alebo zmazané aplikáciou Sycthing sú presunuté do verzií označených dátumov v adresári .stversions.",
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Súbory premiestnené alebo zmazané aplikáciou Syncthing sú premenované na verziu s dátumom a presunuté do adresára .stversions.",
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Soubory sú chránené pred zmenami na ostatních zariadeniach, ale zmeny provedené z tohto zariadenia budú rozoslané na zvyšok klastra.",
"Folder": "Adresár",
"Folder ID": "ID adresára",
"Folder Label": "Označenie adresára",
"Folder Path": "Cesta k adresáru",
"Folder Type": "Typ adresára",
"Folders": "Adresáre",
"GUI": "GUI",
"GUI Authentication Password": "Prihlasovacie heslo do GUI",
"GUI Authentication User": "Prihlasovacie meno do GUI",
"GUI Listen Address": "GUI Listen Address",
"GUI Listen Addresses": "Adresa pre prístup do GUI",
"GUI Theme": "Grafická téma GUI",
"Generate": "Generovať",
"Global Changes": "Globálne zmeny",
"Global Discovery": "Globálne hľadanie",
"Global Discovery Servers": "Global Discovery Servers",
"Global State": "Global State",
"Help": "Pomoc",
"Home page": "Domovská stránka",
"Ignore": "Ignorovať",
"Ignore Patterns": "Ignorované vzory",
"Ignore Permissions": "Ignorované práva",
"Incoming Rate Limit (KiB/s)": "Limit pre sťahovanie (KiB/s)",
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Nesprávna konfigurácia môže poškodiť váš adresár a spôsobiť nefunkčnosť aplikácie Súbory.",
"Introduced By": "Uvedené",
"Introducer": "Uvádzač",
"Inversion of the given condition (i.e. do not exclude)": "Inverzia danej podmienky (napr. nevynechať)",
"Keep Versions": "Ponechanie verzií",
"Largest First": "Najprv najväčšie",
"Last File Received": "Posledný prijatý súbor",
"Last Scan": "Posledný sken",
"Last seen": "Naposledy videný",
"Later": "Neskôr",
"Latest Change": "Posledná zmena",
"Learn more": "Zisti viac",
"Listeners": "Načúvajúci",
"Local Discovery": "Lokálne vyhľadávanie",
"Local State": "Lokálny status",
"Local State (Total)": "Lokálny status (celkový)",
"Major Upgrade": "Hlavná aktualizácia",
"Master": "Master",
"Maximum Age": "Maximálny časový limit",
"Metadata Only": "Iba metadáta",
"Minimum Free Disk Space": "Minimálna veľkosť voľného miesta na disku",
"Move to top of queue": "Presun na začiatok poradia",
"Multi level wildcard (matches multiple directory levels)": "Viacúrovňový zástupný znak (zhoda naprieč viacerými úrovňami adresára)",
"Never": "Nikdy",
"New Device": "Nové zariadenie",
"New Folder": "Nový adresár",
"Newest First": "Najnovší najprv",
"No": "Nie",
"No File Versioning": "Bez verzií súbor",
"No upgrades": "Bez aktualizácií",
"Normal": "Normalny",
"Notice": "Oznámenie",
"OK": "OK",
"Off": "Vypnúť",
"Oldest First": "Najstarší najprv",
"Optional descriptive label for the folder. Can be different on each device.": "Voliteľné popisné označenie adresára. Môže byť rôzne na každom zariadení.",
"Options": "Nastavenia",
"Out of Sync": "Nesynchronizované",
"Out of Sync Items": "Nezosynchronizované položky",
"Outgoing Rate Limit (KiB/s)": "Obmedzenie odchádzajúcej rýchlosti (KiB/s)",
"Override Changes": "Prepísať zmeny",
"Path": "Cesta",
"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": "Cesta k adresáru na lokálnom počítači. Ak neexistuje, bude vytvorená. Znak vlnovky (~) môže byť použitý ako skratka pre",
"Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).": "Cesta, kde budú uložené verzie (ponechajte prázdne pre predvolený adresár .stversions v zdieľanom adresari)",
"Path where versions should be stored (leave empty for the default .stversions folder in the folder).": "Cesta, kde budú uložené verzie (ponechajte prázdne pre predvolený adresár .stversions v adresári).",
"Pause": "Pozastaviť",
"Pause All": "Pozastaviť všetky",
"Paused": "Pozastavené",
"Please consult the release notes before performing a major upgrade.": "Pred spustením hlavnej aktualizácie si prosím prečítajte poznámky k vydaniu.",
"Please set a GUI Authentication User and Password in the Settings dialog.": "Zadajte prosím prihlasovanie meno a heslo v dialógovom okne nastavení.",
"Please wait": "Prosím čakajte",
"Preview": "Náhľad",
"Preview Usage Report": "Náhľad záznamu o používaní",
"Quick guide to supported patterns": "Rýchly sprievodca podporovanými vzormi",
"RAM Utilization": "Využitie RAM",
"Random": "Náhodne",
"Reduced by ignore patterns": "Znížené o ignorované vzory",
"Release Notes": "Poznámky k vydaniu",
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.",
"Remote Devices": "Vzdialené zariadenia",
"Remove": "Odstrániť",
"Required identifier for the folder. Must be the same on all cluster devices.": "Potrebný identifikátor pre adresár. Musí byť rovnaký na všetkých zariadeniach v skupine.",
"Rescan": "Opakovať skenovanie",
"Rescan All": "Opakovať skenovanie všetkých",
"Rescan Interval": "Interval opakovania skenovania",
"Restart": "Reštart",
"Restart Needed": "Potrebný reštart",
"Restarting": "Reštartovanie",
"Resume": "Pokračovať",
"Resume All": "Pokračuj so všetkými",
"Reused": "Opakovane použité",
"Save": "Uložiť",
"Scan Time Remaining": "Zostávajúci čas skenovania",
"Scanning": "Skenovanie",
"Select the devices to share this folder with.": "Vyberte zariadenia s ktorými chcete zdieľať tento adresár.",
"Select the folders to share with this device.": "Vyberte adresáre ktoré chcete zdieľať s týmto zariadením.",
"Send & Receive": "Prijímať a odosielať",
"Send Only": "Iba odosielať",
"Settings": "Nastavenia",
"Share": "Share",
"Share Folder": "Share Folder",
"Share Folders With Device": "Share Folders With Device",
"Share With Devices": "Share With Devices",
"Share this folder?": "Share this folder?",
"Shared With": "Shared With",
"Show ID": "Show ID",
"Show QR": "Show QR",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.",
"Shutdown": "Vypnutie",
"Shutdown Complete": "Shutdown Complete",
"Simple File Versioning": "Jednoduché verzie súborov",
"Single level wildcard (matches within a directory only)": "Single level wildcard (matches within a directory only)",
"Smallest First": "Smallest First",
"Source Code": "Source Code",
"Stable releases and release candidates": "Stable releases and release candidates",
"Stable releases are delayed by about two weeks. During this time they go through testing as release candidates.": "Stable releases are delayed by about two weeks. During this time they go through testing as release candidates.",
"Stable releases only": "Stable releases only",
"Staggered File Versioning": "Rozložené verzie súborov",
"Start Browser": "Start Browser",
"Statistics": "Statistics",
"Stopped": "Stopped",
"Support": "Support",
"Sync Protocol Listen Addresses": "Sync Protocol Listen Addresses",
"Syncing": "Syncing",
"Syncthing has been shut down.": "Syncthing has been shut down.",
"Syncthing includes the following software or portions thereof:": "Syncthing includes the following software or portions thereof:",
"Syncthing is restarting.": "Syncthing is restarting.",
"Syncthing is upgrading.": "Syncthing is upgrading.",
"Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…": "Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…",
"Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.": "Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.",
"The Syncthing admin interface is configured to allow remote access without a password.": "The Syncthing admin interface is configured to allow remote access without a password.",
"The aggregated statistics are publicly available at the URL below.": "The aggregated statistics are publicly available at the URL below.",
"The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.": "The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.",
"The device ID cannot be blank.": "The device ID cannot be blank.",
"The device ID to enter here can be found in the \"Actions > Show ID\" dialog on the other device. Spaces and dashes are optional (ignored).": "The device ID to enter here can be found in the \"Actions > Show ID\" dialog on the other device. Spaces and dashes are optional (ignored).",
"The encrypted usage report is sent daily. It is used to track common platforms, folder sizes and app versions. If the reported data set is changed you will be prompted with this dialog again.": "The encrypted usage report is sent daily. It is used to track common platforms, folder sizes and app versions. If the reported data set is changed you will be prompted with this dialog again.",
"The entered device ID does not look valid. It should be a 52 or 56 character string consisting of letters and numbers, with spaces and dashes being optional.": "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.",
"The first command line parameter is the folder path and the second parameter is the relative path in the folder.": "The first command line parameter is the folder path and the second parameter is the relative path in the folder.",
"The folder ID cannot be blank.": "The folder ID cannot be blank.",
"The folder ID must be unique.": "The folder ID must be unique.",
"The folder path cannot be blank.": "The folder path cannot be blank.",
"The following intervals are used: for the first hour a version is kept every 30 seconds, for the first day a version is kept every hour, for the first 30 days a version is kept every day, until the maximum age a version is kept every week.": "The following intervals are used: for the first hour a version is kept every 30 seconds, for the first day a version is kept every hour, for the first 30 days a version is kept every day, until the maximum age a version is kept every week.",
"The following items could not be synchronized.": "The following items could not be synchronized.",
"The maximum age must be a number and cannot be blank.": "The maximum age must be a number and cannot be blank.",
"The maximum time to keep a version (in days, set to 0 to keep versions forever).": "The maximum time to keep a version (in days, set to 0 to keep versions forever).",
"The minimum free disk space percentage must be a non-negative number between 0 and 100 (inclusive).": "The minimum free disk space percentage must be a non-negative number between 0 and 100 (inclusive).",
"The number of days must be a number and cannot be blank.": "The number of days must be a number and cannot be blank.",
"The number of days to keep files in the trash can. Zero means forever.": "The number of days to keep files in the trash can. Zero means forever.",
"The number of old versions to keep, per file.": "The number of old versions to keep, per file.",
"The number of versions must be a number and cannot be blank.": "The number of versions must be a number and cannot be blank.",
"The path cannot be blank.": "The path cannot be blank.",
"The rate limit must be a non-negative number (0: no limit)": "The rate limit must be a non-negative number (0: no limit)",
"The rescan interval must be a non-negative number of seconds.": "The rescan interval must be a non-negative number of seconds.",
"They are retried automatically and will be synced when the error is resolved.": "They are retried automatically and will be synced when the error is resolved.",
"This Device": "This Device",
"This can easily give hackers access to read and change any files on your computer.": "This can easily give hackers access to read and change any files on your computer.",
"This is a major version upgrade.": "This is a major version upgrade.",
"This setting controls the free space required on the home (i.e., index database) disk.": "This setting controls the free space required on the home (i.e., index database) disk.",
"Time": "Time",
"Trash Can File Versioning": "Verzie súborov v koši",
"Type": "Type",
"Unknown": "Unknown",
"Unshared": "Unshared",
"Unused": "Unused",
"Up to Date": "Up to Date",
"Updated": "Updated",
"Upgrade": "Upgrade",
"Upgrade To {%version%}": "Upgrade To {{version}}",
"Upgrading": "Upgrading",
"Upload Rate": "Upload Rate",
"Uptime": "Uptime",
"Usage reporting is always enabled for candidate releases.": "Usage reporting is always enabled for candidate releases.",
"Use HTTPS for GUI": "Use HTTPS for GUI",
"Version": "Version",
"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.",
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Warning, this path is a parent directory of an existing folder \"{{otherFolder}}\".",
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Warning, this path is a parent directory of an existing folder \"{{otherFolderLabel}}\" ({{otherFolder}}).",
"Warning, this path is a subdirectory of an existing folder \"{%otherFolder%}\".": "Warning, this path is a subdirectory of an existing folder \"{{otherFolder}}\".",
"Warning, this path is a subdirectory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Warning, this path is a subdirectory of an existing folder \"{{otherFolderLabel}}\" ({{otherFolder}}).",
"When adding a new device, keep in mind that this device must be added on the other side too.": "When adding a new device, keep in mind that this device must be added on the other side too.",
"When adding a new folder, keep in mind that the Folder ID is used to tie folders together between devices. They are case sensitive and must match exactly between all devices.": "When adding a new folder, keep in mind that the Folder ID is used to tie folders together between devices. They are case sensitive and must match exactly between all devices.",
"Yes": "Yes",
"You can change your choice at any time in the Settings dialog.": "You can change your choice at any time in the Settings dialog.",
"You can read more about the two release channels at the link below.": "You can read more about the two release channels at the link below.",
"You must keep at least one version.": "You must keep at least one version.",
"days": "days",
"directories": "directories",
"files": "files",
"full documentation": "full documentation",
"items": "items",
"{%device%} wants to share folder \"{%folder%}\".": "{{device}} wants to share folder \"{{folder}}\".",
"{%device%} wants to share folder \"{%folderlabel%}\" ({%folder%}).": "{{device}} wants to share folder \"{{folderlabel}}\" ({{folder}})."
}

View File

@@ -8,9 +8,10 @@
"Actions": "Funktioner",
"Add": "Lägg till",
"Add Device": "Lägg till enhet",
"Add Folder": "Lägg till katalog",
"Add Folder": "Lägg till mapp",
"Add Remote Device": "Lägg till fjärrenhet",
"Add new folder?": "Lägg till katalog?",
"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 mapp?",
"Address": "Adress",
"Addresses": "Adresser",
"Advanced": "Avancerat",
@@ -18,12 +19,12 @@
"Advanced settings": "Avancerade inställningar",
"All Data": "All data",
"Allow Anonymous Usage Reporting?": "Tillåt anonym användarstatistiksrapportering?",
"Allowed Networks": "Allowed Networks",
"Allowed Networks": "Tillåtna nätverk",
"Alphabetic": "Alfabetisk",
"An external command handles the versioning. It has to remove the file from the shared folder.": "Ett externt kommando hanterar versionshanteringen. Det måste ta bort filen från den delade katalogen.",
"An external command handles the versioning. It has to remove the file from the synced folder.": "Ett externt kommando sköter versionshanteringen. Den behöver ta bort filen från den synkroniserade katalogen.",
"An external command handles the versioning. It has to remove the file from the shared folder.": "Ett externt kommando hanterar versionshanteringen. Det måste ta bort filen från den delade mappen.",
"An external command handles the versioning. It has to remove the file from the synced folder.": "Ett externt kommando sköter versionshanteringen. Den behöver ta bort filen från den synkroniserade mappen.",
"Anonymous Usage Reporting": "Anonym användarstatistiksrapportering",
"Any devices configured on an introducer device will be added to this device as well.": "Alla enheter konfigurerade på en introduktörsenhet kommer också att läggas till den här enheten.",
"Any devices configured on an introducer device will be added to this device as well.": "Alla enheter konfigurerade på en introduktör enhet kommer också att läggas till den här enheten.",
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Automatisk uppgradering erbjuder nu valet mellan stabila utgåvor och utgåvskandidater.",
"Automatic upgrades": "Automatiska uppgraderingar",
"Be careful!": "Var aktsam!",
@@ -31,7 +32,7 @@
"CPU Utilization": "CPU användning",
"Changelog": "Ändringslogg",
"Clean out after": "Rensa efteråt",
"Click to see discovery failures": "Click to see discovery failures",
"Click to see discovery failures": "Klicka för att se upptäcktsmisslyckanden",
"Close": "Stäng",
"Command": "Kommando",
"Comment, when used at the start of a line": "Kommentara, vid användning i början av en rad.",
@@ -43,7 +44,7 @@
"Copied from original": "Kopierat från original",
"Copyright © 2014-2016 the following Contributors:": "Upphovsrätt © 2014-2016 följande bidragare:",
"Copyright © 2014-2017 the following Contributors:": "Upphovsrätt © 2014-2017 följande bidragande:",
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Creating ignore patterns, overwriting an existing file at {{path}}.",
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Skapa ignorera mönster, skriver över en existerande fil på {{path}}.",
"Danger!": "Fara!",
"Deleted": "Tog bort",
"Device": "Enhet",
@@ -62,11 +63,13 @@
"Downloading": "Hämtar",
"Edit": "Redigera",
"Edit Device": "Redigera enhet",
"Edit Folder": "Redigera katalog",
"Edit Folder": "Redigera mapp",
"Editing": "Redigerar",
"Editing {%path%}.": "Editing {{path}}.",
"Editing {%path%}.": "Redigerar {{path}}.",
"Enable NAT traversal": "Aktivera NAT traversering",
"Enable Relaying": "Aktivera reläa",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Ange ett icke-negativt antal (t.ex., \"2.35\") och välj en enhet. Procenttalen är som en del av den totala diskstorleken.",
"Enter a non-privileged port number (1024 - 65535).": "Ange ett icke-privilegierat portnummer (1024 - 65535).",
"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 ignore patterns, one per line.": "Ange ignorera mönster, en per rad.",
"Error": "Fel",
@@ -76,20 +79,21 @@
"File Pull Order": "Filhämtningsprioritering",
"File Versioning": "Filversionshantering",
"File permission bits are ignored when looking for changes. Use on FAT file systems.": "Filrättigheter ignoreras under sökning efter förändringar. Används på FAT-filsystem.",
"Files are moved to .stversions directory when replaced or deleted by Syncthing.": "Filer flyttas till .stversions-katalog vid byte eller tas bort av Syncthing.",
"Files are moved to .stversions folder when replaced or deleted by Syncthing.": "Filer flyttas till .stversions katalogen när de ersätts eller tas bort av Syncthing.",
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Filer flyttas till datumstämplade versioner i en .stversions-katalog när de ersätts eller tas bort av Syncthing.",
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Filer flyttas till datummärkta versioner i en .stversions katalog när de ersätts eller tas bort av Syncthing.",
"Files are moved to .stversions directory when replaced or deleted by Syncthing.": "Filer flyttas till .stversions-mapp vid byte eller tas bort av Syncthing.",
"Files are moved to .stversions folder when replaced or deleted by Syncthing.": "Filer flyttas till .stversions-mappen när de ersätts eller tas bort av Syncthing.",
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Filer flyttas till datumstämplade versioner i en .stversions-mapp när de ersätts eller tas bort av Syncthing.",
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Filer flyttas till datummärkta versioner i en .stversions mapp när de ersätts eller tas bort av Syncthing.",
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "Filer skyddas från ändringar gjorda på andra enheter, men ändringar som görs på den här noden skickas till de andra klustermedlemmarna.",
"Folder": "Katalog",
"Folder ID": "Katalog-ID",
"Folder Label": "Katalog etikett",
"Folder Path": "Katalog sökväg",
"Folder Type": "Katalogtyp",
"Folders": "Kataloger",
"Folder": "Mapp",
"Folder ID": "Mapp-ID",
"Folder Label": "Mapp-etikett",
"Folder Path": "Mappsökväg",
"Folder Type": "Mapp-typ",
"Folders": "Mappar",
"GUI": "Grafiskt gränssnitt",
"GUI Authentication Password": "GUI autentiseringslösenord",
"GUI Authentication User": "GUI autentiseringsanvändare",
"GUI Listen Address": "GUI lyssnaradresser",
"GUI Listen Addresses": "GUI lyssnaradresser",
"GUI Theme": "GUI tema",
"Generate": "Generera",
@@ -103,7 +107,7 @@
"Ignore Patterns": "Ignorera mönster",
"Ignore Permissions": "Ignorera rättigheter",
"Incoming Rate Limit (KiB/s)": "Inkommande hastighetsbegränsning (KiB/s)",
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Inkorrekt konfiguration kan skada innehållet i katalogen and få Syncthing att sluta fungera.",
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "Inkorrekt konfiguration kan skada innehållet i mappen and få Syncthing att sluta fungera.",
"Introduced By": "Introducerad av",
"Introducer": "Introduktör",
"Inversion of the given condition (i.e. do not exclude)": "Inversion av det givna tillståndet (d.v.s. exkluderar inte)",
@@ -128,7 +132,7 @@
"Multi level wildcard (matches multiple directory levels)": "Jokertecken som representerar noll eller fler godtyckliga tecken, även över kataloggränser.",
"Never": "Aldrig",
"New Device": "Ny enhet",
"New Folder": "Ny katalog",
"New Folder": "Ny mapp",
"Newest First": "Nyast först",
"No": "Nej",
"No File Versioning": "Ingen filversionshantering",
@@ -138,16 +142,16 @@
"OK": "OK",
"Off": "Av",
"Oldest First": "Äldst först",
"Optional descriptive label for the folder. Can be different on each device.": "Valfri beskrivande etikett för katalogen. Kan vara olika på varje enhet.",
"Optional descriptive label for the folder. Can be different on each device.": "Valfri beskrivande etikett för mappen. Kan vara olika på varje enhet.",
"Options": "Alternativ",
"Out of Sync": "Osynkroniserad",
"Out of Sync Items": "Osynkroniserade objekt",
"Outgoing Rate Limit (KiB/s)": "Utgående hastighetsbegränsning (KiB/s)",
"Override Changes": "Åsidosätt förändringar",
"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 katalogen på din dator. Kommer att skapas om det inte finns. Tecknet tilde (~) kan användas som en genväg för",
"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 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-katalogen i den delade katalogen).",
"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 .stversions i den ordinarie katalogen).",
"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 All": "Pausa alla",
"Paused": "Pausad",
@@ -164,7 +168,7 @@
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Utgåvskandidater innehåller de senaste funktionerna och korrigeringarna. De är lika de traditionella Syncthing-utgåvorna som kommer ut varannan vecka.",
"Remote Devices": "Fjärrenheter",
"Remove": "Ta bort",
"Required identifier for the folder. Must be the same on all cluster devices.": "Krävs identifierare för katalogen. Måste vara densamma på alla kluster enheter.",
"Required identifier for the folder. Must be the same on all cluster devices.": "Krävs identifierare för mappen. Måste vara densamma på alla kluster enheter.",
"Rescan": "Skanna om",
"Rescan All": "Skanna om alla",
"Rescan Interval": "Återskanningsintervall",
@@ -177,16 +181,16 @@
"Save": "Spara",
"Scan Time Remaining": "Återstående skanningstid",
"Scanning": "Skannar",
"Select the devices to share this folder with.": "Ange enheterna som den här katalogen ska delas med.",
"Select the folders to share with this device.": "Välj kataloger att dela med den här enheten.",
"Select the devices to share this folder with.": "Ange enheterna som den här mappen ska delas med.",
"Select the folders to share with this device.": "Välj mapparna som ska delas med den här enheten.",
"Send & Receive": "Skicka & ta emot",
"Send Only": "Skicka endast",
"Settings": "Inställningar",
"Share": "Dela",
"Share Folder": "Dela katalog",
"Share Folders With Device": "Dela kataloger med enhet",
"Share Folder": "Dela mapp",
"Share Folders With Device": "Dela mappar med enhet",
"Share With Devices": "Dela med enheter",
"Share this folder?": "Dela denna katalog?",
"Share this folder?": "Dela denna mapp?",
"Shared With": "Delad med",
"Show ID": "Visa ID",
"Show QR": "Visa QR",
@@ -219,12 +223,12 @@
"The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.": "Konfigurationen har sparats men inte aktiverats. Syncthing måste startas om för att aktivera den nya konfigurationen.",
"The device ID cannot be blank.": "Enhet-ID kan inte vara tomt.",
"The device ID to enter here can be found in the \"Actions > Show ID\" dialog on the other device. Spaces and dashes are optional (ignored).": "Enhet-ID som behövs här kan du hitta i \"Åtgärder > Visa ID\"-dialogrutan på den andra enheten. Mellanrum och bindestreck är valfria (ignoreras).",
"The encrypted usage report is sent daily. It is used to track common platforms, folder sizes and app versions. If the reported data set is changed you will be prompted with this dialog again.": "Den krypterade användarstatistiken skickas dagligen. Den används för att spåra vanliga plattformar, katalogstorlekar och versioner. Om datat som rapporteras ändras så kommer du att bli tillfrågad igen.",
"The encrypted usage report is sent daily. It is used to track common platforms, folder sizes and app versions. If the reported data set is changed you will be prompted with this dialog again.": "Den krypterade användarstatistiken skickas dagligen. Den används för att spåra vanliga plattformar, mappstorlekar och versioner. Om datat som rapporteras ändras så kommer du att bli tillfrågad igen.",
"The entered device ID does not look valid. It should be a 52 or 56 character string consisting of letters and numbers, with spaces and dashes being optional.": "Det inmatade enhet-ID verkar inte vara korrekt. Det ska vara en 52 eller 56 teckensträng bestående av siffror och bokstäver, eventuellt med mellanrum och bindestreck.",
"The first command line parameter is the folder path and the second parameter is the relative path in the folder.": "Den första kommandoparametern är sökvägen till katalogen och den andra parametern är den relativa sökvägen i katalogen.",
"The folder ID cannot be blank.": "Katalog-ID får inte vara tomt.",
"The folder ID must be unique.": "Katalog-ID måste vara unikt.",
"The folder path cannot be blank.": "Katalogsökvägen kan inte vara tom.",
"The first command line parameter is the folder path and the second parameter is the relative path in the folder.": "Den första kommandoparametern är sökvägen till mappen och den andra parametern är den relativa sökvägen i katalogen.",
"The folder ID cannot be blank.": "Mapp-ID får inte vara tomt.",
"The folder ID must be unique.": "Mapp-ID måste vara unikt.",
"The folder path cannot be blank.": "Mapp-sökvägen kan inte vara tom.",
"The following intervals are used: for the first hour a version is kept every 30 seconds, for the first day a version is kept every hour, for the first 30 days a version is kept every day, until the maximum age a version is kept every week.": "De följande intervallen används: varje 30 sekunder under den första timmen; varje timme under den första dagen; varje dag för de första 30 dagarna; varje vecka tills den maximala åldersgränsen uppnås.",
"The following items could not be synchronized.": "Följande objekt kunde inte synkroniseras.",
"The maximum age must be a number and cannot be blank.": "Åldersgränsen måste vara ett tal och kan inte lämnas tomt.",
@@ -241,6 +245,7 @@
"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.",
"This is a major version upgrade.": "Det här är en stor uppgradering.",
"This setting controls the free space required on the home (i.e., index database) disk.": "Denna inställning kontrollerar ledigt utrymme som krävs på home (d.v.s. index-databas) disk.",
"Time": "Tid",
"Trash Can File Versioning": "Papperskorgs filversionshantering",
"Type": "Typ",
@@ -259,12 +264,12 @@
"Version": "Version",
"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 tas bort automatiskt när de är äldre än den maximala åldersgränsen eller överstiger frekvensen i intervallet.",
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Varning, denna sökväg är en överordnad katalog av en befintlig katalog \"{{otherFolder}}\".",
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Varning, denna sökväg är en överordnad katalog av en befintlig katalog \"{{otherFolderLabel}}\" ({{otherFolder}}).",
"Warning, this path is a subdirectory of an existing folder \"{%otherFolder%}\".": "Varning, denna sökväg är en underkatalog till en befintlig katalog \"{{otherFolder}}\".",
"Warning, this path is a subdirectory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Varning, denna sökväg är en undermapp av en befintlig katalog \"{{otherFolderLabel}}\" ({{otherFolder}}).",
"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 \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Varning, denna sökväg är en undermapp av en befintlig mapp \"{{otherFolderLabel}}\" ({{otherFolder}}).",
"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 katalog, tänk på att katalog-ID knyter ihop kataloger mellan olika enheter. De skiftlägeskänsliga och måste matcha precis mellan alla enheter.",
"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",
"You can change your choice at any time in the Settings dialog.": "Du kan ändra ditt val när som helst i inställningsdialogrutan.",
"You can read more about the two release channels at the link below.": "Du kan läsa mer om de två publiceringsskanalerna på länken nedan.",
@@ -274,6 +279,6 @@
"files": "filer",
"full documentation": "fullständig dokumentation",
"items": "objekt",
"{%device%} wants to share folder \"{%folder%}\".": "{{device}} vill dela katalog \"{{folder}}\".",
"{%device%} wants to share folder \"{%folderlabel%}\" ({%folder%}).": "{{device}} vill dela katalog \"{{folderlabel}}\" ({{folder}})."
"{%device%} wants to share folder \"{%folder%}\".": "{{device}} vill dela mapp \"{{folder}}\".",
"{%device%} wants to share folder \"{%folderlabel%}\" ({%folder%}).": "{{device}} vill dela mapp \"{{folderlabel}}\" ({{folder}})."
}

View File

@@ -10,6 +10,7 @@
"Add Device": "Aygıt Ekle",
"Add Folder": "Klasör Ekle",
"Add Remote Device": "Uzak Aygıt Ekle",
"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?": "Yeni klasör ekle?",
"Address": "Adres",
"Addresses": "Adresler",
@@ -67,6 +68,8 @@
"Editing {%path%}.": "Editing {{path}}.",
"Enable NAT traversal": "NAT çaprazlamasına izin ver",
"Enable Relaying": "Enable Relaying",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.",
"Enter a non-privileged port number (1024 - 65535).": "Enter a non-privileged port number (1024 - 65535).",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Adreslerin kendiliğinden keşfedilebilmesi için ya adresleri virgülle ayırarak (\"tcp://ip:port\", \"tcp://host:port\") girin, ya da \"dynamic\" sözcüğünü girin.",
"Enter ignore patterns, one per line.": "Gözardı edilmesini istediğiniz kalıp dizilerini her satıra bir tane olacak şekilde girin.",
"Error": "Hata",
@@ -90,6 +93,7 @@
"GUI": "GUI / Grafiksel Kullanıcı Arayüzü",
"GUI Authentication Password": "GUI Kimlik Doğrulaması için Kullanıcı Parolası",
"GUI Authentication User": "GUI Kimlik Doğrulaması için Kullanıcı Adı",
"GUI Listen Address": "GUI Listen Address",
"GUI Listen Addresses": "GUI Dinleme/Bağlantı Adresleri",
"GUI Theme": "GUI Gövdesi",
"Generate": "Oluştur",
@@ -241,6 +245,7 @@
"This Device": "Bu Aygıt",
"This can easily give hackers access to read and change any files on your computer.": "Hacker'ların bilgisayarındaki dosyaları okuma ve değiştirme yetkisine kolayca erişmelerini sağlayabilir.",
"This is a major version upgrade.": "Ana sürüm yükseltmesidir.",
"This setting controls the free space required on the home (i.e., index database) disk.": "This setting controls the free space required on the home (i.e., index database) disk.",
"Time": "Zaman",
"Trash Can File Versioning": "Çöp Kutusu Dosya Sürümleme İşlemi",
"Type": "Tür",

View File

@@ -10,6 +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?": "Додати нову директорію?",
"Address": "Адреса",
"Addresses": "Адреси",
@@ -18,7 +19,7 @@
"Advanced settings": "Розширені налаштування",
"All Data": "Усі дані",
"Allow Anonymous Usage Reporting?": "Дозволити програмі збирати анонімну статистику використання?",
"Allowed Networks": "Allowed Networks",
"Allowed Networks": "Дозволені мережі",
"Alphabetic": "За алфавітом",
"An external command handles the versioning. It has to remove the file from the shared folder.": "Зовнішня команда керування версіями. Вона має видалити файл із спільної директорії.",
"An external command handles the versioning. It has to remove the file from the synced folder.": "Зовнішня команда керування версіями. Вона має видалити файл із директорії, що синхронізується.",
@@ -67,6 +68,8 @@
"Editing {%path%}.": "Editing {{path}}.",
"Enable NAT traversal": "Увімкнути NAT traversal",
"Enable Relaying": "Увімкнути ретрансляцію (relaying)",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.",
"Enter a non-privileged port number (1024 - 65535).": "Enter a non-privileged port number (1024 - 65535).",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Введіть розділені комою (\"tcp://ip:port\", \"tcp://host:port\") адреси або \"dynamic\" для автоматичного визначення адреси.",
"Enter ignore patterns, one per line.": "Введіть шаблони ігнорування, по одному на рядок.",
"Error": "Помилка",
@@ -90,6 +93,7 @@
"GUI": "Графічний інтерфейс",
"GUI Authentication Password": "Пароль для доступу до панелі управління",
"GUI Authentication User": "Логін користувача для доступу до панелі управління",
"GUI Listen Address": "GUI Listen Address",
"GUI Listen Addresses": "Адреса доступу до панелі управління",
"GUI Theme": "Тема інтерфейсу",
"Generate": "Згенерувати",
@@ -241,6 +245,7 @@
"This Device": "Локальний пристрій",
"This can easily give hackers access to read and change any files on your computer.": "Це легко може дати хакерам доступ до читання та зміни будь-яких файлів на вашому комп'ютері.",
"This is a major version upgrade.": "Це оновлення мажорної версії",
"This setting controls the free space required on the home (i.e., index database) disk.": "This setting controls the free space required on the home (i.e., index database) disk.",
"Time": "Час",
"Trash Can File Versioning": "Версіонування файлів у кошику ",
"Type": "Тип",

View File

@@ -10,6 +10,7 @@
"Add Device": "Thêm thiết bị",
"Add Folder": "Thêm thư mục",
"Add Remote Device": "Thêm thiết bị từ xa",
"Add devices from the introducer to our device list, for mutually shared folders.": "Add devices from the introducer to our device list, for mutually shared folders.",
"Add new folder?": "Thêm thư mục mới?",
"Address": "Địa chỉ",
"Addresses": "Các địa chỉ",
@@ -67,6 +68,8 @@
"Editing {%path%}.": "Editing {{path}}.",
"Enable NAT traversal": "Enable NAT traversal",
"Enable Relaying": "Bật chế độ ch.tiếp",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.",
"Enter a non-privileged port number (1024 - 65535).": "Enter a non-privileged port number (1024 - 65535).",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "Nhập các địa chỉ ngăn cách bởi dấu phẩy (\"tcp://ip:port\", \"tcp://host:port\") hoặc \"dynamic\" để tiến hành dò tìm địa chỉ tự động.",
"Enter ignore patterns, one per line.": "Nhập các quy luật bỏ qua, từng dòng một.",
"Error": "Lỗi",
@@ -90,6 +93,7 @@
"GUI": "GUI",
"GUI Authentication Password": "Mật khẩu xác minh GUI",
"GUI Authentication User": "Người dùng xác minh GUI",
"GUI Listen Address": "GUI Listen Address",
"GUI Listen Addresses": "Các đ.chỉ lắng nghe GUI",
"GUI Theme": "GUI Theme",
"Generate": "Tạo mới",
@@ -241,6 +245,7 @@
"This Device": "Thiết bị này",
"This can easily give hackers access to read and change any files on your computer.": "Th.tác này có thể khiến tin tặc dễ dàng tr.cập để đọc và th.đổi bất kỳ t.tin nào trên máy của bạn.",
"This is a major version upgrade.": "Đây là bản nâng cấp quan trọng.",
"This setting controls the free space required on the home (i.e., index database) disk.": "This setting controls the free space required on the home (i.e., index database) disk.",
"Time": "Time",
"Trash Can File Versioning": "Kiểu thùng rác",
"Type": "Type",

View File

@@ -10,6 +10,7 @@
"Add Device": "添加设备",
"Add Folder": "添加文件夹",
"Add Remote Device": "添加远程设备",
"Add devices from the introducer to our device list, for mutually shared folders.": "添加介绍人中的设备到我们的设备列表,以互相共享文件夹。",
"Add new folder?": "添加新文件夹?",
"Address": "地址",
"Addresses": "地址列表",
@@ -67,6 +68,8 @@
"Editing {%path%}.": "正在编辑 {{path}}。",
"Enable NAT traversal": "启用 NAT 遍历",
"Enable Relaying": "开启中继",
"Enter a non-negative number (e.g., \"2.35\") and select a unit. Percentages are as part of the total disk size.": "输入一个非负数例如“2.35”)并选择单位。百分比是磁盘总大小的一部分。",
"Enter a non-privileged port number (1024 - 65535).": "输入一个非特权的端口号 (1024 - 65535)。",
"Enter comma separated (\"tcp://ip:port\", \"tcp://host:port\") addresses or \"dynamic\" to perform automatic discovery of the address.": "输入以半角逗号分隔的 (\"tcp://ip:port\", \"tcp://host:port\") 设置可用地址列表,或者输入 \"dynamic\" 表示自动发现地址。",
"Enter ignore patterns, one per line.": "请输入忽略表达式,每行一条。",
"Error": "错误",
@@ -90,6 +93,7 @@
"GUI": "图形用户界面",
"GUI Authentication Password": "图形管理界面密码",
"GUI Authentication User": "图形管理界面用户名",
"GUI Listen Address": "GUI 监听地址",
"GUI Listen Addresses": "图形管理界面监听地址",
"GUI Theme": "GUI 主题",
"Generate": "生成",
@@ -120,7 +124,7 @@
"Local State": "本地状态",
"Local State (Total)": "本地状态汇总",
"Major Upgrade": "重大更新",
"Master": "主",
"Master": "主",
"Maximum Age": "历史版本最长保留时间",
"Metadata Only": "仅元数据",
"Minimum Free Disk Space": "最低可用磁盘空间",
@@ -241,6 +245,7 @@
"This Device": "当前设备",
"This can easily give hackers access to read and change any files on your computer.": "这会让骇客能够轻而易举地访问及修改您的文件。",
"This is a major version upgrade.": "这是一个重大版本更新。",
"This setting controls the free space required on the home (i.e., index database) disk.": "此设置控制主(例如索引数据库)磁盘上需要的可用空间。",
"Time": "时间",
"Trash Can File Versioning": "回收站式版本控制",
"Type": "类型",

View File

@@ -1,279 +0,0 @@
{
"A device with that ID is already added.": "該裝置識別碼已被新增。",
"A negative number of days doesn't make sense.": "一個負的天數並不合理。",
"A new major version may not be compatible with previous versions.": "新的主要版本可能與以前的版本不相容。",
"API Key": "API 金鑰",
"About": "關於",
"Action": "Action",
"Actions": "操作",
"Add": "增加",
"Add Device": "增加裝置",
"Add Folder": "增加資料夾",
"Add Remote Device": "新增遠端裝置",
"Add new folder?": "新增資料夾?",
"Address": "位址",
"Addresses": "位址",
"Advanced": "進階",
"Advanced Configuration": "進階配置",
"Advanced settings": "進階設定",
"All Data": "全部資料",
"Allow Anonymous Usage Reporting?": "允許匿名的使用資訊回報?",
"Allowed Networks": "Allowed Networks",
"Alphabetic": "字母順序",
"An external command handles the versioning. It has to remove the file from the shared folder.": "An external command handles the versioning. It has to remove the file from the shared folder.",
"An external command handles the versioning. It has to remove the file from the synced folder.": "An external command handles the versioning. It has to remove the file from the synced folder.",
"Anonymous Usage Reporting": "匿名的使用資訊回報",
"Any devices configured on an introducer device will be added to this device as well.": "任何在引入者裝置所設置的裝置將會一併新增至此裝置",
"Automatic upgrade now offers the choice between stable releases and release candidates.": "Automatic upgrade now offers the choice between stable releases and release candidates.",
"Automatic upgrades": "自動升級",
"Be careful!": "請小心!",
"Bugs": "程式錯誤",
"CPU Utilization": "CPU 使用",
"Changelog": "更新日誌",
"Clean out after": "於之後清空",
"Click to see discovery failures": "Click to see discovery failures",
"Close": "關閉",
"Command": "指令",
"Comment, when used at the start of a line": "註解,當輸入在一行的開頭時",
"Compression": "壓縮",
"Configured": "Configured",
"Connection Error": "連線錯誤",
"Connection Type": "Connection Type",
"Copied from elsewhere": "從別處複製",
"Copied from original": "從原處複製",
"Copyright © 2014-2016 the following Contributors:": "Copyright © 2014-2016 下列貢獻者:",
"Copyright © 2014-2017 the following Contributors:": "Copyright © 2014-2017 the following Contributors:",
"Creating ignore patterns, overwriting an existing file at {%path%}.": "Creating ignore patterns, overwriting an existing file at {{path}}.",
"Danger!": "危險!",
"Deleted": "已刪除",
"Device": "Device",
"Device \"{%name%}\" ({%device%} at {%address%}) wants to connect. Add new device?": "裝置 \"{{name}}\" ({{device}} 位於 {{address}}) 想要連線。 要增加新裝置嗎?",
"Device ID": "裝置識別碼",
"Device Identification": "裝置識別",
"Device Name": "裝置名稱",
"Devices": "裝置",
"Disconnected": "斷線",
"Discovered": "Discovered",
"Discovery": "探索",
"Discovery Failures": "Discovery Failures",
"Documentation": "說明文件",
"Download Rate": "下載速率",
"Downloaded": "已下載",
"Downloading": "正在下載",
"Edit": "編輯",
"Edit Device": "Edit Device",
"Edit Folder": "Edit Folder",
"Editing": "正在編輯",
"Editing {%path%}.": "Editing {{path}}.",
"Enable NAT traversal": "Enable NAT traversal",
"Enable Relaying": "啟用中繼",
"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.": "輸入忽略樣式,每行一種。",
"Error": "錯誤",
"External File Versioning": "外部檔案版本控制",
"Failed Items": "失敗的項目",
"Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.": "Failure to connect to IPv6 servers is expected if there is no IPv6 connectivity.",
"File Pull Order": "提取檔案的順序",
"File Versioning": "檔案版本控制",
"File permission bits are ignored when looking for changes. Use on FAT file systems.": "當改變時,檔案權限位元 File permission bits 會被忽略。用於 FAT 檔案系統上。",
"Files are moved to .stversions directory when replaced or deleted by Syncthing.": "Files are moved to .stversions directory when replaced or deleted by Syncthing.",
"Files are moved to .stversions folder when replaced or deleted by Syncthing.": "Files are moved to .stversions folder when replaced or deleted by Syncthing.",
"Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.": "Files are moved to date stamped versions in a .stversions directory when replaced or deleted by Syncthing.",
"Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.": "Files are moved to date stamped versions in a .stversions folder when replaced or deleted by Syncthing.",
"Files are protected from changes made on other devices, but changes made on this device will be sent to the rest of the cluster.": "其他裝置做的改變不會影響到此裝置的檔案,但在此裝置上的變化將被發送到叢集中的其他部分。",
"Folder": "資料夾",
"Folder ID": "資料夾識別碼",
"Folder Label": "資料夾標籤",
"Folder Path": "資料夾路徑",
"Folder Type": "Folder Type",
"Folders": "資料夾",
"GUI": "GUI",
"GUI Authentication Password": "GUI 認證密碼",
"GUI Authentication User": "GUI 使用者認證名稱",
"GUI Listen Addresses": "GUI 監聽位址",
"GUI Theme": "GUI Theme",
"Generate": "產生",
"Global Changes": "Global Changes",
"Global Discovery": "全域探索",
"Global Discovery Servers": "全域探索伺服器",
"Global State": "全域狀態",
"Help": "說明",
"Home page": "首頁",
"Ignore": "忽略",
"Ignore Patterns": "忽略樣式",
"Ignore Permissions": "忽略權限",
"Incoming Rate Limit (KiB/s)": "傳入速率限制 (KiB/s)",
"Incorrect configuration may damage your folder contents and render Syncthing inoperable.": "不正確的設定可能會損壞您的資料夾內容,並導致 Syncthing 不正常運作。",
"Introduced By": "Introduced By",
"Introducer": "引入者",
"Inversion of the given condition (i.e. do not exclude)": "反轉給定條件 (即:不要排除)",
"Keep Versions": "保留歷史版本數",
"Largest First": "最大的優先",
"Last File Received": "最後接收的檔案",
"Last Scan": "Last Scan",
"Last seen": "最後發現時間",
"Later": "稍後",
"Latest Change": "Latest Change",
"Learn more": "Learn more",
"Listeners": "Listeners",
"Local Discovery": "本機探索",
"Local State": "本機狀態",
"Local State (Total)": "本機狀態 (總結)",
"Major Upgrade": "重大更新",
"Master": "Master",
"Maximum Age": "最長保留時間",
"Metadata Only": "僅中繼資料",
"Minimum Free Disk Space": "最少閒置磁碟空間",
"Move to top of queue": "移到隊列頂端",
"Multi level wildcard (matches multiple directory levels)": "多階層萬用字元 (可比對多層資料夾)",
"Never": "從未",
"New Device": "新裝置",
"New Folder": "新資料夾",
"Newest First": "最新的優先",
"No": "否",
"No File Versioning": "無檔案版本控制",
"No upgrades": "No upgrades",
"Normal": "Normal",
"Notice": "注意",
"OK": "確定",
"Off": "關閉",
"Oldest First": "最舊的優先",
"Optional descriptive label for the folder. Can be different on each device.": "Optional descriptive label for the folder. Can be different on each device.",
"Options": "選項",
"Out of Sync": "不同步",
"Out of Sync Items": "不同步物件",
"Outgoing Rate Limit (KiB/s)": "連出速率限制 (KiB/s)",
"Override Changes": "置換改變",
"Path": "Path",
"Path to the folder on the local computer. Will be created if it does not exist. The tilde character (~) can be used as a shortcut for": "資料夾在本機的路徑。若資料夾不存在則會建立。波浪符號 (~) 可用作下列資料夾的捷徑:",
"Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).": "Path where versions should be stored (leave empty for the default .stversions directory in the shared folder).",
"Path where versions should be stored (leave empty for the default .stversions folder in the folder).": "儲存歷史版本的路徑 (若為空,則預設使用資料夾中的 .stversions 資料夾)。",
"Pause": "暫停",
"Pause All": "Pause All",
"Paused": "暫停",
"Please consult the release notes before performing a major upgrade.": "執行重大升級前請先參閱版本資訊。",
"Please set a GUI Authentication User and Password in the Settings dialog.": "請在設定對話方塊內設置 GUI 使用者認證名稱及密碼。",
"Please wait": "請稍後",
"Preview": "預覽",
"Preview Usage Report": "預覽使用資訊報告",
"Quick guide to supported patterns": "可支援樣式的快速指南",
"RAM Utilization": "記憶體使用",
"Random": "隨機",
"Reduced by ignore patterns": "Reduced by ignore patterns",
"Release Notes": "版本資訊",
"Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.": "Release candidates contain the latest features and fixes. They are similar to the traditional bi-weekly Syncthing releases.",
"Remote Devices": "遠端裝置",
"Remove": "移除",
"Required identifier for the folder. Must be the same on all cluster devices.": "Required identifier for the folder. Must be the same on all cluster devices.",
"Rescan": "重新掃描",
"Rescan All": "全部重新掃描",
"Rescan Interval": "重新掃描間隔",
"Restart": "重新啟動",
"Restart Needed": "需要重新啟動",
"Restarting": "正在重新啟動",
"Resume": "繼續",
"Resume All": "Resume All",
"Reused": "重用",
"Save": "儲存",
"Scan Time Remaining": "Scan Time Remaining",
"Scanning": "正在掃描",
"Select the devices to share this folder with.": "選擇要共享這個資料夾的裝置。",
"Select the folders to share with this device.": "選擇要共享這個資料夾的裝置。",
"Send & Receive": "Send & Receive",
"Send Only": "Send Only",
"Settings": "設定",
"Share": "分享",
"Share Folder": "分享資料夾",
"Share Folders With Device": "與裝置共享資料夾",
"Share With Devices": "與這些裝置共享",
"Share this folder?": "分享此資料夾?",
"Shared With": "與誰共享",
"Show ID": "顯示識別碼",
"Show QR": "顯示 QR 碼",
"Shown instead of Device ID in the cluster status. Will be advertised to other devices as an optional default name.": "代替裝置識別碼顯示在叢集狀態中。這段文字將會廣播到其他的裝置作為一個可選的預設名稱。",
"Shown instead of Device ID in the cluster status. Will be updated to the name the device advertises if left empty.": "代替裝置識別碼顯示在叢集狀態中。本欄若未填寫則將被更新為此裝置所廣播的名稱。",
"Shutdown": "關閉",
"Shutdown Complete": "關閉完成",
"Simple File Versioning": "簡單檔案版本控制",
"Single level wildcard (matches within a directory only)": "單階層萬用字元 (只在單個資料夾階層內比對)",
"Smallest First": "最小的優先",
"Source Code": "原始碼",
"Stable releases and release candidates": "Stable releases and release candidates",
"Stable releases are delayed by about two weeks. During this time they go through testing as release candidates.": "Stable releases are delayed by about two weeks. During this time they go through testing as release candidates.",
"Stable releases only": "Stable releases only",
"Staggered File Versioning": "變動式檔案版本控制",
"Start Browser": "啟動瀏覽器",
"Statistics": "統計",
"Stopped": "已停止",
"Support": "支援",
"Sync Protocol Listen Addresses": "同步通訊協定監聽位址",
"Syncing": "正在同步",
"Syncthing has been shut down.": "Syncthing 已經關閉。",
"Syncthing includes the following software or portions thereof:": "Syncthing 包括以下軟體或其中的一部分:",
"Syncthing is restarting.": "Syncthing 正在重新啟動。",
"Syncthing is upgrading.": "Syncthing 正在進行升級。",
"Syncthing seems to be down, or there is a problem with your Internet connection. Retrying…": "Syncthing 似乎離線了,或者您的網際網路連線出現問題。正在重試...",
"Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.": "Syncthing seems to be experiencing a problem processing your request. Please refresh the page or restart Syncthing if the problem persists.",
"The Syncthing admin interface is configured to allow remote access without a password.": "The Syncthing admin interface is configured to allow remote access without a password.",
"The aggregated statistics are publicly available at the URL below.": "The aggregated statistics are publicly available at the URL below.",
"The configuration has been saved but not activated. Syncthing must restart to activate the new configuration.": "組態已經儲存但尚未啟用。Syncthing 必須重新啟動以便啟用新的組態。",
"The device ID cannot be blank.": "裝置識別碼不能為空白。",
"The device ID to enter here can be found in the \"Actions > Show ID\" dialog on the other device. Spaces and dashes are optional (ignored).": "The device ID to enter here can be found in the \"Actions > Show ID\" dialog on the other device. Spaces and dashes are optional (ignored).",
"The encrypted usage report is sent daily. It is used to track common platforms, folder sizes and app versions. If the reported data set is changed you will be prompted with this dialog again.": "經過加密的使用資訊報告會每天傳送。報告是用來追蹤常用的平台、資料夾的大小以及應用程式的版本。若傳送的資料集有異動,您會再次看到這個對話框。",
"The entered device ID does not look valid. It should be a 52 or 56 character string consisting of letters and numbers, with spaces and dashes being optional.": "輸入的裝置識別碼似乎無效。它應該為一串包含半形英文字母及數字,並可能會含有空白或連接符號的字串,且長度為 52 或 56 個字元。",
"The first command line parameter is the folder path and the second parameter is the relative path in the folder.": "The first command line parameter is the folder path and the second parameter is the relative path in the folder.",
"The folder ID cannot be blank.": "資料夾識別碼不能為空白。",
"The folder ID must be unique.": "資料夾識別碼必須為獨一無二的。",
"The folder path cannot be blank.": "資料夾路徑不能空白。",
"The following intervals are used: for the first hour a version is kept every 30 seconds, for the first day a version is kept every hour, for the first 30 days a version is kept every day, until the maximum age a version is kept every week.": "使用下列的間隔:在第一個小時內每 30 秒保留一個版本,在第一天內每小時保留一個版本,在第 30 天內每一天保留一個版本,在達到最長保留時間前每一星期保留一個版本。",
"The following items could not be synchronized.": "以下項目不能被同步。",
"The maximum age must be a number and cannot be blank.": "最長保留時間必須為一個數字且不得為空。",
"The maximum time to keep a version (in days, set to 0 to keep versions forever).": "一個版本被保留的最長時間 (單位為天,若設定為 0 則表示永遠保留)。",
"The minimum free disk space percentage must be a non-negative number between 0 and 100 (inclusive).": "The minimum free disk space percentage must be a non-negative number between 0 and 100 (inclusive).",
"The number of days must be a number and cannot be blank.": "天數必須必須為一個數字且不得為空。",
"The number of days to keep files in the trash can. Zero means forever.": "檔案在 trash can 中保留的日子。零表示永遠地保留。",
"The number of old versions to keep, per file.": "每個檔案要保留的舊版本數量。",
"The number of versions must be a number and cannot be blank.": "每個檔案要保留的舊版本數量必須是數字且不能為空白。",
"The path cannot be blank.": "路徑不能空白。",
"The rate limit must be a non-negative number (0: no limit)": "限制速率必須為非負的數字 (0: 不設限制)",
"The rescan interval must be a non-negative number of seconds.": "重新掃描間隔必須為一個非負數的秒數。",
"They are retried automatically and will be synced when the error is resolved.": "解決間題後,將會自動重試和同步。",
"This Device": "本機",
"This can easily give hackers access to read and change any files on your computer.": "This can easily give hackers access to read and change any files on your computer.",
"This is a major version upgrade.": "這是一個主要版本更新。",
"Time": "Time",
"Trash Can File Versioning": "Trash Can File Versioning",
"Type": "Type",
"Unknown": "未知",
"Unshared": "未共享",
"Unused": "未使用",
"Up to Date": "最新",
"Updated": "已更新",
"Upgrade": "升級",
"Upgrade To {%version%}": "升級至 {{version}}",
"Upgrading": "正在升級",
"Upload Rate": "上載速率",
"Uptime": "上線時間",
"Usage reporting is always enabled for candidate releases.": "Usage reporting is always enabled for candidate releases.",
"Use HTTPS for GUI": "為 GUI 使用 HTTPS",
"Version": "版本",
"Versions Path": "歷史版本路徑",
"Versions are automatically deleted if they are older than the maximum age or exceed the number of files allowed in an interval.": "當檔案歷史版本的存留時間大於設定的最大值,或是其數量在一段時間內超出允許值時,則會被刪除。",
"Warning, this path is a parent directory of an existing folder \"{%otherFolder%}\".": "Warning, this path is a parent directory of an existing folder \"{{otherFolder}}\".",
"Warning, this path is a parent directory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Warning, this path is a parent directory of an existing folder \"{{otherFolderLabel}}\" ({{otherFolder}}).",
"Warning, this path is a subdirectory of an existing folder \"{%otherFolder%}\".": "Warning, this path is a subdirectory of an existing folder \"{{otherFolder}}\".",
"Warning, this path is a subdirectory of an existing folder \"{%otherFolderLabel%}\" ({%otherFolder%}).": "Warning, this path is a subdirectory of an existing folder \"{{otherFolderLabel}}\" ({{otherFolder}}).",
"When adding a new device, keep in mind that this device must be added on the other side too.": "當新增一個裝置時,務必記住,當前的這個裝置也同樣必須被添加至另一邊。",
"When adding a new folder, keep in mind that the Folder ID is used to tie folders together between devices. They are case sensitive and must match exactly between all devices.": "當新增一個資料夾時,請記住,資料夾識別碼是用來將裝置之間的資料夾綁定在一起的。它們有區分大小寫,且必須在所有裝置之間完全相同。",
"Yes": "是",
"You can change your choice at any time in the Settings dialog.": "You can change your choice at any time in the Settings dialog.",
"You can read more about the two release channels at the link below.": "You can read more about the two release channels at the link below.",
"You must keep at least one version.": "您必須保留至少一個版本。",
"days": "日",
"directories": "directories",
"files": "files",
"full documentation": "完整說明文件",
"items": "個項目",
"{%device%} wants to share folder \"{%folder%}\".": "{{device}} 想要分享資料夾 \"{{folder}}\"。",
"{%device%} wants to share folder \"{%folderlabel%}\" ({%folder%}).": "{{device}} 想要分享資料夾 \"{{folderlabel}}\" ({{folder}})。"
}

View File

@@ -1 +1 @@
var langPrettyprint = {"bg":"Bulgarian","ca":"Catalan","ca@valencia":"Catalan (Valencian)","cs":"Czech","da":"Danish","de":"German","el":"Greek","en":"English","en-GB":"English (United Kingdom)","eo":"Esperanto","es":"Spanish","es-ES":"Spanish (Spain)","eu":"Basque","fi":"Finnish","fr":"French","fr-CA":"French (Canada)","fy":"Western Frisian","hu":"Hungarian","id":"Indonesian","it":"Italian","ja":"Japanese","ko-KR":"Korean (Korea)","lt":"Lithuanian","nb":"Norwegian Bokmål","nl":"Dutch","nn":"Norwegian Nynorsk","pl":"Polish","pt-BR":"Portuguese (Brazil)","pt-PT":"Portuguese (Portugal)","ru":"Russian","sv":"Swedish","tr":"Turkish","uk":"Ukrainian","vi":"Vietnamese","zh-CN":"Chinese (China)","zh-TW":"Chinese (Taiwan)"}
var langPrettyprint = {"bg":"Bulgarian","ca@valencia":"Catalan (Valencian)","cs":"Czech","da":"Danish","de":"German","el":"Greek","en":"English","en-GB":"English (United Kingdom)","eo":"Esperanto","es":"Spanish","es-ES":"Spanish (Spain)","eu":"Basque","fi":"Finnish","fr":"French","fr-CA":"French (Canada)","fy":"Western Frisian","hu":"Hungarian","id":"Indonesian","it":"Italian","ja":"Japanese","ko-KR":"Korean (Korea)","lt":"Lithuanian","nb":"Norwegian Bokmål","nl":"Dutch","nn":"Norwegian Nynorsk","pl":"Polish","pt-BR":"Portuguese (Brazil)","pt-PT":"Portuguese (Portugal)","ru":"Russian","sk":"Slovak","sv":"Swedish","tr":"Turkish","uk":"Ukrainian","vi":"Vietnamese","zh-CN":"Chinese (China)"}

View File

@@ -1 +1 @@
var validLangs = ["bg","ca","ca@valencia","cs","da","de","el","en","en-GB","eo","es","es-ES","eu","fi","fr","fr-CA","fy","hu","id","it","ja","ko-KR","lt","nb","nl","nn","pl","pt-BR","pt-PT","ru","sv","tr","uk","vi","zh-CN","zh-TW"]
var validLangs = ["bg","ca@valencia","cs","da","de","el","en","en-GB","eo","es","es-ES","eu","fi","fr","fr-CA","fy","hu","id","it","ja","ko-KR","lt","nb","nl","nn","pl","pt-BR","pt-PT","ru","sk","sv","tr","uk","vi","zh-CN"]

View File

@@ -12,7 +12,7 @@
<p translate>Copyright &copy; 2014-2017 the following Contributors:</p>
<div class="row">
<div class="col-md-12" id="contributor-list">
Jakob Borg, Audrius Butkevicius, Alexander Graf, Anderson Mesquita, Antony Male, Ben Schulz, Caleb Callaway, Daniel Harte, Lars K.W. Gohlke, Lode Hoste, Michael Ploujnikov, Philippe Schommers, Ryan Sullivan, Sergey Mishin, Simon Frei, Stefan Tatschner, Aaron Bieber, Adam Piggott, Adel Qalieh, Alessandro G., Alexandre Viau, Andrew Dunham, Andrey D, Antoine Lamielle, Arthur Axel fREW Schmidt, Bart De Vries, Ben Curthoys, Ben Shepherd, Ben Sidhom, Benny Ng, Brandon Philips, Brendan Long, Brian R. Becker, Carsten Hagemann, Cathryne Linenweaver, Cedric Staniewski, Chris Howie, Chris Joel, Colin Kennedy, Daniel Bergmann, Daniel Martí, David Rimmer, Denis A., Dennis Wilson, Dominik Heidler, Elias Jarlebring, Emil Hessman, Erik Meitner, Federico Castagnini, Felix Ableitner, Felix Unterpaintner, Francois-Xavier Gsell, Frank Isemann, Gilli Sigurdsson, Heiko Zuerker, Jaakko Hannikainen, Jacek Szafarkiewicz, Jake Peterson, James Patterson, Jaroslav Malec, Jaya Chithra, Jens Diemer, Jochen Voss, Johan Vromans, Karol Różycki, Kelong Cong, Ken'ichi Kamada, Kevin Allen, Kevin White, Jr., Kurt Fitzner, Laurent Etiemble, Leo Arias, Lord Landon Agahnim, Majed Abdulaziz, Marc Laporte, Marc Pujol, Marcin Dziadus, Mark Pulford, Mateusz Naściszewski, Matt Burke, Max Schulze, Michael Jephcote, Michael Tilli, Nate Morrison, Niels Peter Roest, Pascal Jungblut, Peter Hoeg, Phill Luby, Piotr Bejda, Robert Carosi, Roman Zaynetdinov, Sacheendra Talluri, Scott Klupfel, Stefan Kuntz, Tim Abell, Tim Howes, Tobias Nygren, Tomas Cerveny, Tully Robinson, Tyler Brazier, Unrud, Veeti Paananen, Victor Buinsky, Vil Brekin, William A. Kennington III, Wulf Weich, Xavier O., Yannic A.
Jakob Borg, Audrius Butkevicius, Alexander Graf, Anderson Mesquita, Antony Male, Ben Schulz, Caleb Callaway, Daniel Harte, Lars K.W. Gohlke, Lode Hoste, Michael Ploujnikov, Philippe Schommers, Ryan Sullivan, Sergey Mishin, Simon Frei, Stefan Tatschner, Aaron Bieber, Adam Piggott, Adel Qalieh, Alessandro G., Alexandre Viau, Andrew Dunham, Andrey D, Antoine Lamielle, Arthur Axel fREW Schmidt, Bart De Vries, Ben Curthoys, Ben Shepherd, Ben Sidhom, Benny Ng, Brandon Philips, Brendan Long, Brian R. Becker, Carsten Hagemann, Cathryne Linenweaver, Cedric Staniewski, Chris Howie, Chris Joel, Colin Kennedy, Daniel Bergmann, Daniel Martí, Darshil Chanpura, David Rimmer, Denis A., Dennis Wilson, Dominik Heidler, Elias Jarlebring, Emil Hessman, Erik Meitner, Federico Castagnini, Felix Ableitner, Felix Unterpaintner, Francois-Xavier Gsell, Frank Isemann, Gilli Sigurdsson, Heiko Zuerker, Jaakko Hannikainen, Jacek Szafarkiewicz, Jake Peterson, James Patterson, Jaroslav Malec, Jaya Chithra, Jens Diemer, Jochen Voss, Johan Vromans, Karol Różycki, Kelong Cong, Ken'ichi Kamada, Kevin Allen, Kevin White, Jr., Kurt Fitzner, Laurent Etiemble, Leo Arias, Lord Landon Agahnim, Majed Abdulaziz, Marc Laporte, Marc Pujol, Marcin Dziadus, Mark Pulford, Mateusz Naściszewski, Matt Burke, Max Schulze, Michael Jephcote, Michael Tilli, Nate Morrison, Niels Peter Roest, Pascal Jungblut, Peter Hoeg, Phill Luby, Piotr Bejda, Robert Carosi, Roman Zaynetdinov, Sacheendra Talluri, Scott Klupfel, Stefan Kuntz, Tim Abell, Tim Howes, Tobias Nygren, Tomas Cerveny, Tully Robinson, Tyler Brazier, Unrud, Veeti Paananen, Victor Buinsky, Vil Brekin, William A. Kennington III, Wulf Weich, Xavier O., Yannic A.
</div>
</div>
<hr/>

View File

@@ -58,6 +58,24 @@ angular.module('syncthing.core')
$scope.metricRates = (window.localStorage["metricRates"] == "true");
} catch (exception) { }
$scope.folderDefaults = {
selectedDevices: {},
type: "readwrite",
rescanIntervalS: 60,
minDiskFree: {value: 1, unit: "%"},
maxConflicts: 10,
fsync: true,
order: "random",
fileVersioningSelector: "none",
trashcanClean: 0,
simpleKeep: 5,
staggeredMaxAge: 365,
staggeredCleanInterval: 3600,
staggeredVersionsPath: "",
externalCommand: "",
autoNormalize: true
};
$scope.localStateTotal = {
bytes: 0,
files: 0
@@ -1024,7 +1042,7 @@ angular.module('syncthing.core')
$('#settings').modal();
};
$scope.saveConfig = function () {
$scope.saveConfig = function (cb) {
var cfg = JSON.stringify($scope.config);
var opts = {
headers: {
@@ -1034,6 +1052,9 @@ angular.module('syncthing.core')
$http.post(urlbase + '/system/config', cfg, opts).success(function () {
$http.get(urlbase + '/system/config/insync').success(function (data) {
$scope.configInSync = data.configInSync;
if (cb) {
cb();
}
});
}).error($scope.emitHTTPError);
};
@@ -1080,14 +1101,14 @@ angular.module('syncthing.core')
});
});
$scope.saveConfig();
$scope.saveConfig(function () {
if (themeChanged) {
document.location.reload(true);
}
});
}
$('#settings').modal("hide");
if (themeChanged) {
document.location.reload(true);
}
};
$scope.saveAdvanced = function () {
@@ -1393,24 +1414,9 @@ angular.module('syncthing.core')
};
$scope.addFolder = function () {
$scope.currentFolder = {
selectedDevices: {},
type: "readwrite",
rescanIntervalS: 60,
minDiskFreePct: 1,
maxConflicts: 10,
fsync: true,
order: "random",
fileVersioningSelector: "none",
trashcanClean: 0,
simpleKeep: 5,
staggeredMaxAge: 365,
staggeredCleanInterval: 3600,
staggeredVersionsPath: "",
externalCommand: "",
autoNormalize: true
};
$scope.currentFolder = angular.copy($scope.folderDefaults);
$scope.editingExisting = false;
$('#editIgnores textarea').val("");
$scope.folderEditor.$setPristine();
$http.get(urlbase + '/svc/random/string?length=10').success(function (data) {
$scope.currentFolder.id = (data.random.substr(0, 5) + '-' + data.random.substr(5, 5)).toLowerCase();
@@ -1420,26 +1426,11 @@ angular.module('syncthing.core')
$scope.addFolderAndShare = function (folder, folderLabel, device) {
$scope.dismissFolderRejection(folder, device);
$scope.currentFolder = {
id: folder,
label: folderLabel,
selectedDevices: {},
rescanIntervalS: 60,
minDiskFreePct: 1,
maxConflicts: 10,
fsync: true,
order: "random",
fileVersioningSelector: "none",
trashcanClean: 0,
simpleKeep: 5,
staggeredMaxAge: 365,
staggeredCleanInterval: 3600,
staggeredVersionsPath: "",
externalCommand: "",
autoNormalize: true,
viewFlags: {
importFromOtherDevice: true
}
$scope.currentFolder = angular.copy($scope.folderDefaults);
$scope.currentFolder.id = folder;
$scope.currentFolder.label = folderLabel;
$scope.currentFolder.viewFlags = {
importFromOtherDevice: true
};
$scope.currentFolder.selectedDevices[device] = true;
@@ -1516,10 +1507,21 @@ angular.module('syncthing.core')
delete folderCfg.versioning;
}
var ignores = $('#editIgnores textarea').val().trim();
if (!$scope.editingExisting && ignores) {
folderCfg.paused = true;
};
$scope.folders[folderCfg.id] = folderCfg;
$scope.config.folders = folderList($scope.folders);
$scope.saveConfig();
$scope.saveConfig(function () {
if (!$scope.editingExisting && ignores) {
$scope.saveIgnores(function () {
$scope.setFolderPause(folderCfg.id, false);
});
}
});
};
$scope.dismissFolderRejection = function (folder, device) {
@@ -1593,13 +1595,27 @@ angular.module('syncthing.core')
});
};
$scope.saveIgnores = function () {
if (!$scope.editingExisting) {
$scope.editIgnoresOnAddingFolder = function () {
if ($scope.editingExisting) {
return;
}
if ($scope.currentFolder.path.endsWith($scope.system.pathSeparator)) {
$scope.currentFolder.path = $scope.currentFolder.path.slice(0, -1);
};
$('#editIgnores').modal().one('shown.bs.modal', function () {
textArea.focus();
});
};
$scope.saveIgnores = function (cb) {
$http.post(urlbase + '/db/ignores?folder=' + encodeURIComponent($scope.currentFolder.id), {
ignore: $('#editIgnores textarea').val().split('\n')
}).success(function () {
if (cb) {
cb();
}
});
};
@@ -1635,6 +1651,9 @@ angular.module('syncthing.core')
$scope.showFailed = function (folder) {
$scope.failedCurrent = $scope.failed[folder];
$scope.failedFolderPath = $scope.folders[folder].path;
if ($scope.failedFolderPath[$scope.failedFolderPath.length - 1] !== $scope.system.pathSeparator) {
$scope.failedFolderPath += $scope.system.pathSeparator;
}
$('#failed').modal().on('hidden.bs.modal', function () {
$scope.failedCurrent = undefined;
});

View File

@@ -14,8 +14,8 @@
<td ng-if="!changeEvent.data.modifiedBy"><span translate>Unknown</span></td>
<td>{{changeEvent.data.action}}</td>
<td>{{changeEvent.data.type}}</td>
<td>{{changeEvent.data.path}}</td>
<td>{{changeEvent.time | date:'medium'}}</td>
<td class="globalChanges-path-col">{{changeEvent.data.path}}</td>
<td class="globalChanges-time-col">{{changeEvent.time | date:"yyyy-MM-dd HH:mm:ss"}}</td>
</tr>
</table>
</div>
@@ -24,4 +24,4 @@
<span class="fa fa-times"></span>&nbsp;<span translate>Close</span>
</button>
</div>
</model>
</modal>

View File

@@ -65,19 +65,28 @@
</div>
<div id="folder-advanced" class="folder-advanced collapse">
<div class="row">
<div class="col-md-12">
<div class="col-md-6">
<div class="form-group" ng-class="{'has-error': folderEditor.rescanIntervalS.$invalid && folderEditor.rescanIntervalS.$dirty}">
<label for="rescanIntervalS"><span translate>Rescan Interval</span> (s)</label>
<label for="rescanIntervalS"><span translate>Rescan Interval</span> (s)</label><br/>
<input name="rescanIntervalS" id="rescanIntervalS" class="form-control" type="number" ng-model="currentFolder.rescanIntervalS" required min="0">
<p class="help-block">
<span translate ng-if="!folderEditor.rescanIntervalS.$valid && folderEditor.rescanIntervalS.$dirty">The rescan interval must be a non-negative number of seconds.</span>
</p>
</div>
<div class="form-group" ng-class="{'has-error': folderEditor.minDiskFreePct.$invalid && folderEditor.minDiskFreePct.$dirty}">
<label for="minDiskFreePct"><span translate>Minimum Free Disk Space</span> (0.0 - 100.0%)</label>
<input name="minDiskFreePct" id="minDiskFreePct" class="form-control" type="number" ng-model="currentFolder.minDiskFreePct" required min="0.0" max="100.0">
<p class="help-block">
<span translate ng-if="!folderEditor.minDiskFreePct.$valid && folderEditor.minDiskFreePct.$dirty">The minimum free disk space percentage must be a non-negative number between 0 and 100 (inclusive).</span>
</div>
<div class="col-md-6 form-horizontal">
<div class="form-group" ng-class="{'has-error': folderEditor.minDiskFree.$invalid && folderEditor.minDiskFree.$dirty}">
<label class="col-xs-12" for="minDiskFree"><span translate>Minimum Free Disk Space</span></label><br/>
<div class="col-xs-9"><input name="minDiskFree" id="minDiskFree" class="form-control" type="number" ng-model="currentFolder.minDiskFree.value" required min="0" step="0.01"></div>
<div class="col-xs-3"><select class="col-sm-3 form-control" ng-model="currentFolder.minDiskFree.unit">
<option value="%">%</option>
<option value="kB">kB</option>
<option value="MB">MB</option>
<option value="GB">GB</option>
<option value="TB">TB</option>
</select></div>
<p class="col-xs-12 help-block" ng-show="folderEditor.minDiskFree.$invalid">
<span translate>Enter a non-negative number (e.g., "2.35") and select a unit. Percentages are as part of the total disk size.</span>
</p>
</div>
</div>
@@ -184,7 +193,7 @@
<button type="button" class="btn btn-primary btn-sm" ng-click="saveFolder()" ng-disabled="folderEditor.$invalid">
<span class="fa fa-check"></span>&nbsp;<span translate>Save</span>
</button>
<button type="button" class="btn btn-default btn-sm" id="editIgnoresButton" ng-click="editIgnores()" ng-if="editingExisting">
<button type="button" class="btn btn-default btn-sm" id="editIgnoresButton" ng-click="editingExisting ? editIgnores() : editIgnoresOnAddingFolder()" ng-disabled="folderEditor.$invalid">
<span class="fa fa-eye-slash"></span>&nbsp;<span translate>Ignore Patterns</span>
</button>
<button type="button" class="btn btn-default btn-sm" data-dismiss="modal">

View File

@@ -1,7 +1,7 @@
<modal id="editIgnores" status="default" heading="{{'Ignore Patterns' | translate}}" large="yes" closeable="yes">
<div class="modal-body">
<p translate>Enter ignore patterns, one per line.</p>
<textarea class="form-control" rows="15"></textarea>
<textarea class="form-control" rows="5"></textarea>
<hr/>
@@ -14,12 +14,13 @@
</dl>
</div>
<div class="modal-footer">
<div class="pull-left"><span translate>Editing</span> <code>{{currentFolder.path}}{{system.pathSeparator}}.stignore</code></div>
<button type="button" class="btn btn-primary btn-sm" ng-click="saveIgnores()" data-dismiss="modal">
<div class="pull-left" ng-show="editingExisting"><span translate translate-value-path="{{currentFolder.path}}{{system.pathSeparator}}.stignore">Editing {%path%}.</span></div>
<div class="pull-left" ng-show="!editingExisting"><span translate translate-value-path="{{currentFolder.path}}{{system.pathSeparator}}.stignore">Creating ignore patterns, overwriting an existing file at {%path%}.</span></div>
<button type="button" class="btn btn-primary btn-sm" ng-click="editingExisting ? saveIgnores() : angular.noop()" data-dismiss="modal">
<span class="fa fa-check"></span>&nbsp;<span translate>Save</span>
</button>
<button type="button" class="btn btn-default btn-sm" data-dismiss="modal">
<span class="fa fa-times"></span>&nbsp;<span translate>Close</span>
</button>
</div>
</modal>
</modal>

View File

@@ -78,12 +78,34 @@
<label translate for="GlobalAnnServersStr">Global Discovery Servers</label>
<input ng-disabled="!tmpOptions.globalAnnounceEnabled" id="GlobalAnnServersStr" class="form-control" type="text" ng-model="tmpOptions._globalAnnounceServersStr">
</div>
<div class="form-horizontal">
<div class="form-group" ng-class="{'has-error': settingsEditor.minHomeDiskFree.$invalid && settingsEditor.minHomeDiskFree.$dirty}">
<label class="col-xs-12" for="minHomeDiskFree"><span translate>Minimum Free Disk Space</span></label><br/>
<div class="col-xs-9"><input name="minHomeDiskFree" id="minHomeDiskFree" class="form-control" type="number" ng-model="tmpOptions.minHomeDiskFree.value" required min="0" step="0.01"></div>
<div class="col-xs-3"><select class="col-sm-3 form-control" ng-model="tmpOptions.minHomeDiskFree.unit">
<option value="%">%</option>
<option value="kB">kB</option>
<option value="MB">MB</option>
<option value="GB">GB</option>
<option value="TB">TB</option>
</select></div>
<p class="col-xs-12 help-block">
<span translate ng-show="settingsEditor.minHomeDiskFree.$invalid">Enter a non-negative number (e.g., "2.35") and select a unit. Percentages are as part of the total disk size.</span>
<span translate ng-hide="settingsEditor.minHomeDiskFree.$invalid">This setting controls the free space required on the home (i.e., index database) disk.</span>
</p>
</div>
</div>
</div>
<div class="col-md-6">
<div class="form-group">
<label translate for="Address">GUI Listen Addresses</label>
<input id="Address" class="form-control" type="text" ng-model="tmpGUI.address">
<div class="form-group" ng-class="{'has-error': settingsEditor.Address.$invalid && settingsEditor.Address.$dirty}">
<label translate for="Address">GUI Listen Address</label>&emsp;<a href="https://docs.syncthing.net/users/guilisten.html" target="_blank"><span class="fa fa-fw fa-book"></span>&nbsp;<span translate>Help</span></a>
<input id="Address" name="Address" class="form-control" type="text" ng-model="tmpGUI.address" ng-pattern="/.*:0*((102[4-9])|(10[3-9][0-9])|(1[1-9][0-9][0-9])|([2-9][0-9][0-9][0-9])|([1-6]\d{4}))$/">
<p class="help-block" ng-show="settingsEditor.Address.$invalid" translate>
Enter a non-privileged port number (1024 - 65535).
</p>
</div>
<div class="form-group">
<label translate for="User">GUI Authentication User</label>

View File

@@ -29,7 +29,7 @@ import (
const (
OldestHandledVersion = 10
CurrentVersion = 19
CurrentVersion = 20
MaxRescanIntervalS = 365 * 24 * 60 * 60
)
@@ -292,6 +292,9 @@ func (cfg *Configuration) clean() error {
if cfg.Version == 18 {
convertV18V19(cfg)
}
if cfg.Version == 19 {
convertV19V20(cfg)
}
// Build a list of available devices
existingDevices := make(map[protocol.DeviceID]bool)
@@ -341,6 +344,18 @@ func (cfg *Configuration) clean() error {
return nil
}
func convertV19V20(cfg *Configuration) {
cfg.Options.MinHomeDiskFree = Size{Value: cfg.Options.DeprecatedMinHomeDiskFreePct, Unit: "%"}
cfg.Options.DeprecatedMinHomeDiskFreePct = 0
for i := range cfg.Folders {
cfg.Folders[i].MinDiskFree = Size{Value: cfg.Folders[i].DeprecatedMinDiskFreePct, Unit: "%"}
cfg.Folders[i].DeprecatedMinDiskFreePct = 0
}
cfg.Version = 20
}
func convertV18V19(cfg *Configuration) {
// Triggers a database tweak
cfg.Version = 19
@@ -537,7 +552,7 @@ func convertV11V12(cfg *Configuration) {
func convertV10V11(cfg *Configuration) {
// Set minimum disk free of existing folders to 1%
for i := range cfg.Folders {
cfg.Folders[i].MinDiskFreePct = 1
cfg.Folders[i].DeprecatedMinDiskFreePct = 1
}
cfg.Version = 11
}

View File

@@ -55,7 +55,7 @@ func TestDefaultValues(t *testing.T) {
CacheIgnoredFiles: false,
ProgressUpdateIntervalS: 5,
LimitBandwidthInLan: false,
MinHomeDiskFreePct: 1,
MinHomeDiskFree: Size{1, "%"},
URURL: "https://data.syncthing.net/newdata",
URInitialDelayS: 1800,
URPostInsecurely: false,
@@ -110,7 +110,7 @@ func TestDeviceConfig(t *testing.T) {
Pullers: 0,
Hashers: 0,
AutoNormalize: true,
MinDiskFreePct: 1,
MinDiskFree: Size{1, "%"},
MaxConflicts: -1,
Fsync: true,
Versioning: VersioningConfiguration{
@@ -201,7 +201,7 @@ func TestOverriddenValues(t *testing.T) {
CacheIgnoredFiles: true,
ProgressUpdateIntervalS: 10,
LimitBandwidthInLan: true,
MinHomeDiskFreePct: 5.2,
MinHomeDiskFree: Size{5.2, "%"},
URURL: "https://localhost/newdata",
URInitialDelayS: 800,
URPostInsecurely: true,

View File

@@ -26,7 +26,7 @@ type FolderConfiguration struct {
RescanIntervalS int `xml:"rescanIntervalS,attr" json:"rescanIntervalS"`
IgnorePerms bool `xml:"ignorePerms,attr" json:"ignorePerms"`
AutoNormalize bool `xml:"autoNormalize,attr" json:"autoNormalize"`
MinDiskFreePct float64 `xml:"minDiskFreePct" json:"minDiskFreePct"`
MinDiskFree Size `xml:"minDiskFree" json:"minDiskFree"`
Versioning VersioningConfiguration `xml:"versioning" json:"versioning"`
Copiers int `xml:"copiers" json:"copiers"` // This defines how many files are handled concurrently.
Pullers int `xml:"pullers" json:"pullers"` // Defines how many blocks are fetched at the same time, possibly between separate copier routines.
@@ -45,7 +45,8 @@ type FolderConfiguration struct {
cachedPath string
DeprecatedReadOnly bool `xml:"ro,attr,omitempty" json:"-"`
DeprecatedReadOnly bool `xml:"ro,attr,omitempty" json:"-"`
DeprecatedMinDiskFreePct float64 `xml:"minDiskFreePct,omitempty" json:"-"`
}
type FolderDeviceConfiguration struct {
@@ -103,6 +104,26 @@ func (f *FolderConfiguration) HasMarker() bool {
return err == nil
}
func (f *FolderConfiguration) CreateRoot() (err error) {
// Directory permission bits. Will be filtered down to something
// sane by umask on Unixes.
permBits := os.FileMode(0777)
if runtime.GOOS == "windows" {
// Windows has no umask so we must chose a safer set of bits to
// begin with.
permBits = 0700
}
if _, err = os.Stat(f.Path()); os.IsNotExist(err) {
if err = osutil.MkdirAll(f.Path(), permBits); err != nil {
l.Warnf("Creating directory for %v: %v",
f.Description(), err)
}
}
return err
}
func (f FolderConfiguration) Description() string {
if f.Label == "" {
return f.ID

View File

@@ -123,7 +123,7 @@ type OptionsConfiguration struct {
CacheIgnoredFiles bool `xml:"cacheIgnoredFiles" json:"cacheIgnoredFiles" default:"false"`
ProgressUpdateIntervalS int `xml:"progressUpdateIntervalS" json:"progressUpdateIntervalS" default:"5"`
LimitBandwidthInLan bool `xml:"limitBandwidthInLan" json:"limitBandwidthInLan" default:"false"`
MinHomeDiskFreePct float64 `xml:"minHomeDiskFreePct" json:"minHomeDiskFreePct" default:"1"`
MinHomeDiskFree Size `xml:"minHomeDiskFree" json:"minHomeDiskFree" default:"1 %"`
ReleasesURL string `xml:"releasesURL" json:"releasesURL" default:"https://upgrades.syncthing.net/meta.json"`
AlwaysLocalNets []string `xml:"alwaysLocalNet" json:"alwaysLocalNets"`
OverwriteRemoteDevNames bool `xml:"overwriteRemoteDeviceNamesOnConnect" json:"overwriteRemoteDeviceNamesOnConnect" default:"false"`
@@ -141,11 +141,12 @@ type OptionsConfiguration struct {
KCPSendWindowSize int `xml:"kcpSendWindowSize" json:"kcpSendWindowSize" default:"128"`
KCPReceiveWindowSize int `xml:"kcpReceiveWindowSize" json:"kcpReceiveWindowSize" default:"128"`
DeprecatedUPnPEnabled bool `xml:"upnpEnabled,omitempty" json:"-"`
DeprecatedUPnPLeaseM int `xml:"upnpLeaseMinutes,omitempty" json:"-"`
DeprecatedUPnPRenewalM int `xml:"upnpRenewalMinutes,omitempty" json:"-"`
DeprecatedUPnPTimeoutS int `xml:"upnpTimeoutSeconds,omitempty" json:"-"`
DeprecatedRelayServers []string `xml:"relayServer,omitempty" json:"-"`
DeprecatedUPnPEnabled bool `xml:"upnpEnabled,omitempty" json:"-"`
DeprecatedUPnPLeaseM int `xml:"upnpLeaseMinutes,omitempty" json:"-"`
DeprecatedUPnPRenewalM int `xml:"upnpRenewalMinutes,omitempty" json:"-"`
DeprecatedUPnPTimeoutS int `xml:"upnpTimeoutSeconds,omitempty" json:"-"`
DeprecatedRelayServers []string `xml:"relayServer,omitempty" json:"-"`
DeprecatedMinHomeDiskFreePct float64 `xml:"minHomeDiskFreePct" json:"-"`
}
func (orig OptionsConfiguration) Copy() OptionsConfiguration {

75
lib/config/size.go Normal file
View File

@@ -0,0 +1,75 @@
// 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 config
import (
"fmt"
"strconv"
"strings"
)
type Size struct {
Value float64 `json:"value" xml:",chardata"`
Unit string `json:"unit" xml:"unit,attr"`
}
func ParseSize(s string) (Size, error) {
s = strings.TrimSpace(s)
if len(s) == 0 {
return Size{}, nil
}
var num, unit string
for i := 0; i < len(s) && (s[i] >= '0' && s[i] <= '9' || s[i] == '.' || s[i] == ','); i++ {
num = s[:i+1]
}
var i = len(num)
for i < len(s) && s[i] == ' ' {
i++
}
unit = s[i:]
val, err := strconv.ParseFloat(num, 64)
if err != nil {
return Size{}, err
}
return Size{val, unit}, nil
}
func (s Size) BaseValue() float64 {
unitPrefix := s.Unit
if len(unitPrefix) > 1 {
unitPrefix = unitPrefix[:1]
}
mult := 1.0
switch unitPrefix {
case "k", "K":
mult = 1000
case "m", "M":
mult = 1000 * 1000
case "g", "G":
mult = 1000 * 1000 * 1000
case "t", "T":
mult = 1000 * 1000 * 1000 * 1000
}
return s.Value * mult
}
func (s Size) Percentage() bool {
return strings.Contains(s.Unit, "%")
}
func (s Size) String() string {
return fmt.Sprintf("%v %s", s.Value, s.Unit)
}
func (Size) ParseDefault(s string) (interface{}, error) {
return ParseSize(s)
}

72
lib/config/size_test.go Normal file
View File

@@ -0,0 +1,72 @@
// 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 config
import "testing"
func TestParseSize(t *testing.T) {
cases := []struct {
in string
ok bool
val float64
pct bool
}{
// We accept upper case SI units
{"5K", true, 5e3, false}, // even when they should be lower case
{"4 M", true, 4e6, false},
{"3G", true, 3e9, false},
{"2 T", true, 2e12, false},
// We accept lower case SI units out of user friendliness
{"1 k", true, 1e3, false},
{"2m", true, 2e6, false},
{"3 g", true, 3e9, false},
{"4t", true, 4e12, false},
// Fractions are OK
{"123.456 k", true, 123.456e3, false},
{"0.1234 m", true, 0.1234e6, false},
{"3.45 g", true, 3.45e9, false},
// We don't parse negative numbers
{"-1", false, 0, false},
{"-1k", false, 0, false},
{"-0.45g", false, 0, false},
// We accept various unit suffixes on the unit prefix
{"100 KBytes", true, 100e3, false},
{"100 Kbps", true, 100e3, false},
{"100 MAU", true, 100e6, false},
// Percentages are OK
{"1%", true, 1, true},
{"200%", true, 200, true}, // even large ones
{"200K%", true, 200e3, true}, // even with prefixes, although this makes no sense
{"2.34%", true, 2.34, true}, // fractions are A-ok
// The empty string is a valid zero
{"", true, 0, false},
{" ", true, 0, false},
}
for _, tc := range cases {
size, err := ParseSize(tc.in)
if !tc.ok {
if err == nil {
t.Errorf("Unexpected nil error in UnmarshalText(%q)", tc.in)
}
continue
}
if err != nil {
t.Errorf("Unexpected error in UnmarshalText(%q): %v", tc.in, err)
continue
}
if size.BaseValue() > tc.val*1.001 || size.BaseValue() < tc.val*0.999 {
// Allow 0.1% slop due to floating point multiplication
t.Errorf("Incorrect value in UnmarshalText(%q): %v, wanted %v", tc.in, size.BaseValue(), tc.val)
}
if size.Percentage() != tc.pct {
t.Errorf("Incorrect percentage bool in UnmarshalText(%q): %v, wanted %v", tc.in, size.Percentage(), tc.pct)
}
}
}

15
lib/config/testdata/v20.xml vendored Normal file
View File

@@ -0,0 +1,15 @@
<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

@@ -81,6 +81,21 @@ func TestAllowedNetworks(t *testing.T) {
[]string{"192.168.0.0/24", "fe80::/48"},
true,
},
{
"10.20.30.40",
[]string{"!10.20.30.0/24", "10.0.0.0/8"},
false,
},
{
"10.20.30.40",
[]string{"10.0.0.0/8", "!10.20.30.0/24"},
true,
},
{
"[fe80::1]:4242",
[]string{"192.168.0.0/24", "!fe00::/8", "fe80::/48"},
false,
},
}
for _, tc := range cases {

View File

@@ -12,6 +12,7 @@ import (
"fmt"
"net"
"net/url"
"strings"
"time"
"github.com/syncthing/syncthing/lib/config"
@@ -662,12 +663,17 @@ func IsAllowedNetwork(host string, allowed []string) bool {
}
for _, n := range allowed {
result := true
if strings.HasPrefix(n, "!") {
result = false
n = n[1:]
}
_, cidr, err := net.ParseCIDR(n)
if err != nil {
continue
}
if cidr.Contains(addr.IP) {
return true
return result
}
}

View File

@@ -19,7 +19,7 @@ import (
var blockFinder *BlockFinder
const maxBatchSize = 256 << 10
const maxBatchSize = 1000
type BlockMap struct {
db *Instance

View File

@@ -69,13 +69,15 @@ func getFile(db dbReader, key []byte) (protocol.FileInfo, bool) {
return protocol.FileInfo{}, false
}
if err != nil {
panic(err)
l.Debugln("surprise error:", err)
return protocol.FileInfo{}, false
}
var f protocol.FileInfo
err = f.Unmarshal(bs)
if err != nil {
panic(err)
l.Debugln("unmarshal error:", err)
return protocol.FileInfo{}, false
}
return f, true
}

View File

@@ -197,8 +197,16 @@ func (db *Instance) updateFiles(folder, device []byte, fs []protocol.FileInfo, l
for _, f := range fs {
name := []byte(f.Name)
fk = db.deviceKeyInto(fk[:cap(fk)], folder, device, name)
// Get and unmarshal the file entry. If it doesn't exist or can't be
// unmarshalled we'll add it as a new entry.
bs, err := t.Get(fk, nil)
if err == leveldb.ErrNotFound {
var ef FileInfoTruncated
if err == nil {
err = ef.Unmarshal(bs)
}
if err != nil {
if isLocalDevice {
localSize.addFile(f)
}
@@ -212,11 +220,6 @@ func (db *Instance) updateFiles(folder, device []byte, fs []protocol.FileInfo, l
continue
}
var ef FileInfoTruncated
err = ef.Unmarshal(bs)
if err != nil {
panic(err)
}
// The Invalid flag might change without the version being bumped.
if !ef.Version.Equal(f.Version) || ef.Invalid != f.Invalid {
if isLocalDevice {
@@ -262,7 +265,8 @@ func (db *Instance) withHave(folder, device, prefix []byte, truncate bool, fn It
// we need to copy it.
f, err := unmarshalTrunc(append([]byte{}, dbi.Value()...), truncate)
if err != nil {
panic(err)
l.Debugln("unmarshal error:", err)
continue
}
if cont := fn(f); !cont {
return
@@ -286,7 +290,8 @@ func (db *Instance) withAllFolderTruncated(folder []byte, fn func(device []byte,
// we need to copy it.
err := f.Unmarshal(append([]byte{}, dbi.Value()...))
if err != nil {
panic(err)
l.Debugln("unmarshal error:", err)
continue
}
switch f.Name {
@@ -315,32 +320,35 @@ func (db *Instance) getGlobal(folder, file []byte, truncate bool) (FileIntf, boo
defer t.close()
bs, err := t.Get(k, nil)
if err == leveldb.ErrNotFound {
return nil, false
}
if err != nil {
panic(err)
return nil, false
}
var vl VersionList
err = vl.Unmarshal(bs)
if err == leveldb.ErrNotFound {
return nil, false
}
if err != nil {
panic(err)
l.Debugln("unmarshal error:", k, err)
return nil, false
}
if len(vl.Versions) == 0 {
l.Debugln(k)
panic("no versions?")
l.Debugln("no versions:", k)
return nil, false
}
k = db.deviceKey(folder, vl.Versions[0].Device, file)
bs, err = t.Get(k, nil)
if err != nil {
panic(err)
l.Debugln("surprise error:", k, err)
return nil, false
}
fi, err := unmarshalTrunc(bs, truncate)
if err != nil {
panic(err)
l.Debugln("unmarshal error:", k, err)
return nil, false
}
return fi, true
}
@@ -362,11 +370,12 @@ func (db *Instance) withGlobal(folder, prefix []byte, truncate bool, fn Iterator
var vl VersionList
err := vl.Unmarshal(dbi.Value())
if err != nil {
panic(err)
l.Debugln("unmarshal error:", err)
continue
}
if len(vl.Versions) == 0 {
l.Debugln(dbi.Key())
panic("no versions?")
l.Debugln("no versions:", dbi.Key())
continue
}
name := db.globalKeyName(dbi.Key())
@@ -377,22 +386,14 @@ func (db *Instance) withGlobal(folder, prefix []byte, truncate bool, fn Iterator
fk = db.deviceKeyInto(fk[:cap(fk)], folder, vl.Versions[0].Device, name)
bs, err := t.Get(fk, nil)
if err != nil {
l.Debugf("folder: %q (%x)", folder, folder)
l.Debugf("key: %q (%x)", dbi.Key(), dbi.Key())
l.Debugf("vl: %v", vl)
l.Debugf("vl.Versions[0].Device: %x", vl.Versions[0].Device)
l.Debugf("name: %q (%x)", name, name)
l.Debugf("fk: %q", fk)
l.Debugf("fk: %x %x %x",
fk[keyPrefixLen:keyPrefixLen+keyFolderLen],
fk[keyPrefixLen+keyFolderLen:keyPrefixLen+keyFolderLen+keyDeviceLen],
fk[keyPrefixLen+keyFolderLen+keyDeviceLen:])
panic(err)
l.Debugln("surprise error:", err)
continue
}
f, err := unmarshalTrunc(bs, truncate)
if err != nil {
panic(err)
l.Debugln("unmarshal error:", err)
continue
}
if cont := fn(f); !cont {
@@ -408,13 +409,15 @@ func (db *Instance) availability(folder, file []byte) []protocol.DeviceID {
return nil
}
if err != nil {
panic(err)
l.Debugln("surprise error:", err)
return nil
}
var vl VersionList
err = vl.Unmarshal(bs)
if err != nil {
panic(err)
l.Debugln("unmarshal error:", err)
return nil
}
var devices []protocol.DeviceID
@@ -442,11 +445,12 @@ nextFile:
var vl VersionList
err := vl.Unmarshal(dbi.Value())
if err != nil {
panic(err)
l.Debugln("unmarshal error:", err)
continue
}
if len(vl.Versions) == 0 {
l.Debugln(dbi.Key())
panic("no versions?")
l.Debugln("no versions:", dbi.Key())
continue
}
have := false // If we have the file, any version
@@ -477,21 +481,14 @@ nextFile:
fk = db.deviceKeyInto(fk[:cap(fk)], folder, vl.Versions[i].Device, name)
bs, err := t.Get(fk, nil)
if err != nil {
var id protocol.DeviceID
copy(id[:], device)
l.Debugf("device: %v", id)
l.Debugf("need: %v, have: %v", need, have)
l.Debugf("key: %q (%x)", dbi.Key(), dbi.Key())
l.Debugf("vl: %v", vl)
l.Debugf("i: %v", i)
l.Debugf("fk: %q (%x)", fk, fk)
l.Debugf("name: %q (%x)", name, name)
panic(err)
l.Debugln("surprise error:", err)
continue nextVersion
}
gf, err := unmarshalTrunc(bs, truncate)
if err != nil {
panic(err)
l.Debugln("unmarshal error:", err)
continue nextVersion
}
if gf.IsInvalid() {
@@ -579,7 +576,8 @@ func (db *Instance) checkGlobals(folder []byte, globalSize *sizeTracker) {
var vl VersionList
err := vl.Unmarshal(dbi.Value())
if err != nil {
panic(err)
l.Debugln("unmarshal error:", err)
continue
}
// Check the global version list for consistency. An issue in previous
@@ -597,16 +595,15 @@ func (db *Instance) checkGlobals(folder []byte, globalSize *sizeTracker) {
continue
}
if err != nil {
panic(err)
l.Debugln("surprise error:", err)
return
}
newVL.Versions = append(newVL.Versions, version)
if i == 0 {
fi, ok := t.getFile(folder, version.Device, name)
if !ok {
panic("nonexistent global master file")
if fi, ok := t.getFile(folder, version.Device, name); ok {
globalSize.addFile(fi)
}
globalSize.addFile(fi)
}
}

View File

@@ -89,21 +89,14 @@ func (t readWriteTransaction) updateGlobal(folder, device []byte, file protocol.
l.Debugf("update global; folder=%q device=%v file=%q version=%d", folder, protocol.DeviceIDFromBytes(device), file.Name, file.Version)
name := []byte(file.Name)
gk := t.db.globalKey(folder, name)
svl, err := t.Get(gk, nil)
if err != nil && err != leveldb.ErrNotFound {
panic(err)
}
svl, _ := t.Get(gk, nil) // skip error, we check len(svl) != 0 later
var fl VersionList
var oldFile protocol.FileInfo
var hasOldFile bool
// Remove the device from the current version list
if len(svl) != 0 {
err = fl.Unmarshal(svl)
if err != nil {
panic(err)
}
fl.Unmarshal(svl) // skip error, range handles success case
for i := range fl.Versions {
if bytes.Equal(fl.Versions[i].Device, device) {
if fl.Versions[i].Version.Equal(file.Version) {
@@ -147,11 +140,10 @@ func (t readWriteTransaction) updateGlobal(folder, device []byte, file protocol.
// "Greater" in the condition above is just based on the device
// IDs in the version vector, which is not the only thing we use
// to determine the winner.)
//
// A surprise missing file entry here is counted as a win for us.
of, ok := t.getFile(folder, fl.Versions[i].Device, name)
if !ok {
panic("file referenced in version list does not exist")
}
if file.WinsConflict(of) {
if !ok || file.WinsConflict(of) {
fl.Versions = insertVersion(fl.Versions, i, nv)
insertedAt = i
goto done
@@ -174,11 +166,11 @@ done:
globalSize.removeFile(oldFile)
} else if len(fl.Versions) > 1 {
// The previous newest version is now at index 1, grab it from there.
oldFile, ok := t.getFile(folder, fl.Versions[1].Device, name)
if !ok {
panic("file referenced in version list does not exist")
if oldFile, ok := t.getFile(folder, fl.Versions[1].Device, name); ok {
// A failure to get the file here is surprising and our
// global size data will be incorrect until a restart...
globalSize.removeFile(oldFile)
}
globalSize.removeFile(oldFile)
}
}
}
@@ -206,7 +198,8 @@ func (t readWriteTransaction) removeFromGlobal(folder, device, file []byte, glob
var fl VersionList
err = fl.Unmarshal(svl)
if err != nil {
panic(err)
l.Debugln("unmarshal error:", err)
return
}
removed := false
@@ -215,7 +208,8 @@ func (t readWriteTransaction) removeFromGlobal(folder, device, file []byte, glob
if i == 0 && globalSize != nil {
f, ok := t.getFile(folder, device, file)
if !ok {
panic("removing nonexistent file")
// didn't exist anyway, apparently
continue
}
globalSize.removeFile(f)
removed = true
@@ -231,11 +225,11 @@ func (t readWriteTransaction) removeFromGlobal(folder, device, file []byte, glob
l.Debugf("new global after remove: %v", fl)
t.Put(gk, mustMarshal(&fl))
if removed {
f, ok := t.getFile(folder, fl.Versions[0].Device, file)
if !ok {
panic("new global is nonexistent file")
if f, ok := t.getFile(folder, fl.Versions[0].Device, file); ok {
// A failure to get the file here is surprising and our
// global size data will be incorrect until a restart...
globalSize.addFile(f)
}
globalSize.addFile(f)
}
}
}

View File

@@ -118,6 +118,67 @@ func (t EventType) MarshalText() ([]byte, error) {
return []byte(t.String()), nil
}
func UnmarshalEventType(s string) EventType {
switch s {
case "Starting":
return Starting
case "StartupComplete":
return StartupComplete
case "DeviceDiscovered":
return DeviceDiscovered
case "DeviceConnected":
return DeviceConnected
case "DeviceDisconnected":
return DeviceDisconnected
case "DeviceRejected":
return DeviceRejected
case "LocalChangeDetected":
return LocalChangeDetected
case "RemoteChangeDetected":
return RemoteChangeDetected
case "LocalIndexUpdated":
return LocalIndexUpdated
case "RemoteIndexUpdated":
return RemoteIndexUpdated
case "ItemStarted":
return ItemStarted
case "ItemFinished":
return ItemFinished
case "StateChanged":
return StateChanged
case "FolderRejected":
return FolderRejected
case "ConfigSaved":
return ConfigSaved
case "DownloadProgress":
return DownloadProgress
case "RemoteDownloadProgress":
return RemoteDownloadProgress
case "FolderSummary":
return FolderSummary
case "FolderCompletion":
return FolderCompletion
case "FolderErrors":
return FolderErrors
case "DevicePaused":
return DevicePaused
case "DeviceResumed":
return DeviceResumed
case "FolderScanProgress":
return FolderScanProgress
case "FolderPaused":
return FolderPaused
case "FolderResumed":
return FolderResumed
case "ListenAddressesChanged":
return ListenAddressesChanged
case "LoginAttempt":
return LoginAttempt
default:
return 0
}
}
const BufferSize = 64
type Logger struct {

View File

@@ -7,6 +7,7 @@
package fs
import (
"errors"
"os"
"time"
)
@@ -86,6 +87,11 @@ func (f *BasicFilesystem) Create(name string) (File, error) {
return fsFile{fd}, err
}
func (f *BasicFilesystem) Walk(root string, walkFn WalkFunc) error {
// implemented in WalkFilesystem
return errors.New("not implemented")
}
// fsFile implements the fs.File interface on top of an os.File
type fsFile struct {
*os.File

View File

@@ -64,7 +64,7 @@ const ModePerm = FileMode(os.ModePerm)
// DefaultFilesystem is the fallback to use when nothing explicitly has
// been passed.
var DefaultFilesystem Filesystem = NewBasicFilesystem()
var DefaultFilesystem Filesystem = NewWalkFilesystem(NewBasicFilesystem())
// SkipDir is used as a return value from WalkFuncs to indicate that
// the directory named in the call is to be skipped. It is not returned

View File

@@ -28,8 +28,16 @@ import "path/filepath"
// Walk skips the remaining files in the containing directory.
type WalkFunc func(path string, info FileInfo, err error) error
type WalkFilesystem struct {
Filesystem
}
func NewWalkFilesystem(next Filesystem) *WalkFilesystem {
return &WalkFilesystem{next}
}
// walk recursively descends path, calling walkFn.
func (f *BasicFilesystem) walk(path string, info FileInfo, walkFn WalkFunc) error {
func (f *WalkFilesystem) walk(path string, info FileInfo, walkFn WalkFunc) error {
err := walkFn(path, info, nil)
if err != nil {
if info.IsDir() && err == SkipDir {
@@ -72,7 +80,7 @@ func (f *BasicFilesystem) walk(path string, info FileInfo, walkFn WalkFunc) erro
// order, which makes the output deterministic but means that for very
// large directories Walk can be inefficient.
// Walk does not follow symbolic links.
func (f *BasicFilesystem) Walk(root string, walkFn WalkFunc) error {
func (f *WalkFilesystem) Walk(root string, walkFn WalkFunc) error {
info, err := f.Lstat(root)
if err != nil {
return walkFn(root, nil, err)

View File

@@ -19,6 +19,7 @@ import (
"time"
"github.com/gobwas/glob"
"github.com/syncthing/syncthing/lib/osutil"
"github.com/syncthing/syncthing/lib/sync"
)
@@ -64,6 +65,7 @@ func (r Result) IsCaseFolded() bool {
}
type Matcher struct {
lines []string
patterns []Pattern
withCache bool
matches *cache
@@ -120,7 +122,7 @@ func (m *Matcher) Parse(r io.Reader, file string) error {
}
func (m *Matcher) parseLocked(r io.Reader, file string) error {
patterns, err := parseIgnoreFile(r, file, m.modtimes)
lines, patterns, err := parseIgnoreFile(r, file, m.modtimes)
// Error is saved and returned at the end. We process the patterns
// (possibly blank) anyway.
@@ -131,6 +133,7 @@ func (m *Matcher) parseLocked(r io.Reader, file string) error {
}
m.curHash = newHash
m.lines = lines
m.patterns = patterns
if m.withCache {
m.matches = newCache(patterns)
@@ -160,7 +163,7 @@ func (m *Matcher) patternsUnchanged(file string) bool {
}
func (m *Matcher) Match(file string) (result Result) {
if m == nil {
if m == nil || file == "." {
return resultNotMatched
}
@@ -206,6 +209,13 @@ func (m *Matcher) Match(file string) (result Result) {
return resultNotMatched
}
// Lines return a list of the unprocessed lines in .stignore at last load
func (m *Matcher) Lines() []string {
m.mut.Lock()
defer m.mut.Unlock()
return m.lines
}
// Patterns return a list of the loaded patterns, as they've been parsed
func (m *Matcher) Patterns() []string {
if m == nil {
@@ -274,27 +284,28 @@ func hashPatterns(patterns []Pattern) string {
return fmt.Sprintf("%x", h.Sum(nil))
}
func loadIgnoreFile(file string, modtimes map[string]time.Time) ([]Pattern, error) {
func loadIgnoreFile(file string, modtimes map[string]time.Time) ([]string, []Pattern, error) {
if _, ok := modtimes[file]; ok {
return nil, fmt.Errorf("Multiple include of ignore file %q", file)
return nil, nil, fmt.Errorf("multiple include of ignore file %q", file)
}
fd, err := os.Open(file)
if err != nil {
return nil, err
return nil, nil, err
}
defer fd.Close()
info, err := fd.Stat()
if err != nil {
return nil, err
return nil, nil, err
}
modtimes[file] = info.ModTime()
return parseIgnoreFile(fd, file, modtimes)
}
func parseIgnoreFile(fd io.Reader, currentFile string, modtimes map[string]time.Time) ([]Pattern, error) {
func parseIgnoreFile(fd io.Reader, currentFile string, modtimes map[string]time.Time) ([]string, []Pattern, error) {
var lines []string
var patterns []Pattern
defaultResult := resultInclude
@@ -360,11 +371,12 @@ func parseIgnoreFile(fd io.Reader, currentFile string, modtimes map[string]time.
} else if strings.HasPrefix(line, "#include ") {
includeRel := line[len("#include "):]
includeFile := filepath.Join(filepath.Dir(currentFile), includeRel)
includes, err := loadIgnoreFile(includeFile, modtimes)
includeLines, includePatterns, err := loadIgnoreFile(includeFile, modtimes)
if err != nil {
return fmt.Errorf("include of %q: %v", includeRel, err)
}
patterns = append(patterns, includes...)
lines = append(lines, includeLines...)
patterns = append(patterns, includePatterns...)
} else {
// Path name or pattern, add it so it matches files both in
// current directory and subdirs.
@@ -389,6 +401,7 @@ func parseIgnoreFile(fd io.Reader, currentFile string, modtimes map[string]time.
var err error
for scanner.Scan() {
line := strings.TrimSpace(scanner.Text())
lines = append(lines, line)
switch {
case line == "":
continue
@@ -411,11 +424,11 @@ func parseIgnoreFile(fd io.Reader, currentFile string, modtimes map[string]time.
}
}
if err != nil {
return nil, err
return nil, nil, err
}
}
return patterns, nil
return lines, patterns, nil
}
// IsInternal returns true if the file, as a path relative to the folder
@@ -434,3 +447,22 @@ func IsInternal(file string) bool {
}
return false
}
// WriteIgnores is a convenience function to avoid code duplication
func WriteIgnores(path string, content []string) error {
fd, err := osutil.CreateAtomic(path)
if err != nil {
return err
}
for _, line := range content {
fmt.Fprintln(fd, line)
}
if err := fd.Close(); err != nil {
return err
}
osutil.HideFile(path)
return nil
}

View File

@@ -843,3 +843,32 @@ func TestIsInternal(t *testing.T) {
}
}
}
func TestRoot(t *testing.T) {
stignore := `
!/a
/*
`
testcases := []struct {
file string
matches bool
}{
{".", false},
{"a", false},
{"b", true},
}
pats := New(true)
err := pats.Parse(bytes.NewBufferString(stignore), ".stignore")
if err != nil {
t.Fatal(err)
}
for _, tc := range testcases {
res := pats.Match(tc.file).IsIgnored()
if res != tc.matches {
t.Errorf("Matches(%q) == %v, expected %v", tc.file, res, tc.matches)
}
}
}

View File

@@ -6,13 +6,19 @@
package model
import "time"
import (
"context"
"time"
)
type folder struct {
stateTracker
scan folderScanner
model *Model
stop chan struct{}
scan folderScanner
model *Model
ctx context.Context
cancel context.CancelFunc
initialScanFinished chan struct{}
}
func (f *folder) IndexUpdated() {
@@ -23,10 +29,12 @@ func (f *folder) DelayScan(next time.Duration) {
}
func (f *folder) Scan(subdirs []string) error {
<-f.initialScanFinished
return f.scan.Scan(subdirs)
}
func (f *folder) Stop() {
close(f.stop)
f.cancel()
}
func (f *folder) Jobs() ([]string, []string) {
@@ -35,13 +43,8 @@ func (f *folder) Jobs() ([]string, []string) {
func (f *folder) BringToFront(string) {}
func (f *folder) scanSubdirsIfHealthy(subDirs []string) error {
if err := f.model.CheckFolderHealth(f.folderID); err != nil {
l.Infoln("Skipping folder", f.folderID, "scan due to folder error:", err)
return err
}
l.Debugln(f, "Scanning subdirectories")
if err := f.model.internalScanFolderSubdirs(f.folderID, subDirs); err != nil {
func (f *folder) scanSubdirs(subDirs []string) error {
if err := f.model.internalScanFolderSubdirs(f.ctx, f.folderID, subDirs); err != nil {
// Potentially sets the error twice, once in the scanner just
// by doing a check, and once here, if the error returned is
// the same one as returned by CheckFolderHealth, though

View File

@@ -7,7 +7,7 @@
package model
import (
"bufio"
"context"
"crypto/tls"
"encoding/json"
"errors"
@@ -41,8 +41,8 @@ import (
// How many files to send in each Index/IndexUpdate message.
const (
indexTargetSize = 250 * 1024 // Aim for making index messages no larger than 250 KiB (uncompressed)
indexBatchSize = 1000 // Either way, don't include more files than this
maxBatchSizeBytes = 250 * 1024 // Aim for making index messages no larger than 250 KiB (uncompressed)
maxBatchSizeFiles = 1000 // Either way, don't include more files than this
)
type service interface {
@@ -110,8 +110,6 @@ var (
errFolderPathEmpty = errors.New("folder path empty")
errFolderPathMissing = errors.New("folder path missing")
errFolderMarkerMissing = errors.New("folder marker missing")
errHomeDiskNoSpace = errors.New("home disk has insufficient free space")
errFolderNoSpace = errors.New("folder has insufficient free space")
errInvalidFilename = errors.New("filename is invalid")
errDeviceUnknown = errors.New("unknown device")
errDevicePaused = errors.New("device is paused")
@@ -234,18 +232,9 @@ func (m *Model) startFolderLocked(folder string) config.FolderType {
// Directory permission bits. Will be filtered down to something
// sane by umask on Unixes.
permBits := os.FileMode(0777)
if runtime.GOOS == "windows" {
// Windows has no umask so we must chose a safer set of bits to
// begin with.
permBits = 0700
}
if _, err := os.Stat(cfg.Path()); os.IsNotExist(err) {
if err := osutil.MkdirAll(cfg.Path(), permBits); err != nil {
l.Warnln("Creating folder:", err)
}
}
cfg.CreateRoot()
if err := cfg.CreateMarker(); err != nil {
l.Warnln("Creating folder marker:", err)
}
@@ -1252,66 +1241,51 @@ func (m *Model) ConnectedTo(deviceID protocol.DeviceID) bool {
}
func (m *Model) GetIgnores(folder string) ([]string, []string, error) {
var lines []string
m.fmut.RLock()
cfg, ok := m.folderCfgs[folder]
m.fmut.RUnlock()
if !ok {
return lines, nil, fmt.Errorf("Folder %s does not exist", folder)
}
if !cfg.HasMarker() {
return lines, nil, fmt.Errorf("Folder %s stopped", folder)
}
fd, err := os.Open(filepath.Join(cfg.Path(), ".stignore"))
if err != nil {
if os.IsNotExist(err) {
return lines, nil, nil
if ok {
if !cfg.HasMarker() {
return nil, nil, fmt.Errorf("Folder %s stopped", folder)
}
l.Warnln("Loading .stignore:", err)
return lines, nil, err
}
defer fd.Close()
scanner := bufio.NewScanner(fd)
for scanner.Scan() {
lines = append(lines, strings.TrimSpace(scanner.Text()))
m.fmut.RLock()
ignores := m.folderIgnores[folder]
m.fmut.RUnlock()
return ignores.Lines(), ignores.Patterns(), nil
}
m.fmut.RLock()
patterns := m.folderIgnores[folder].Patterns()
m.fmut.RUnlock()
if cfg, ok := m.cfg.Folders()[folder]; ok {
matcher := ignore.New(false)
path := filepath.Join(cfg.Path(), ".stignore")
if err := matcher.Load(path); err != nil {
return nil, nil, err
}
return matcher.Lines(), matcher.Patterns(), nil
}
return lines, patterns, nil
return nil, nil, fmt.Errorf("Folder %s does not exist", folder)
}
func (m *Model) SetIgnores(folder string, content []string) error {
cfg, ok := m.folderCfgs[folder]
cfg, ok := m.cfg.Folders()[folder]
if !ok {
return fmt.Errorf("Folder %s does not exist", folder)
}
path := filepath.Join(cfg.Path(), ".stignore")
fd, err := osutil.CreateAtomic(path)
if err != nil {
if err := ignore.WriteIgnores(filepath.Join(cfg.Path(), ".stignore"), content); err != nil {
l.Warnln("Saving .stignore:", err)
return err
}
for _, line := range content {
fmt.Fprintln(fd, line)
m.fmut.RLock()
runner, ok := m.folderRunners[folder]
m.fmut.RUnlock()
if ok {
return runner.Scan(nil)
}
if err := fd.Close(); err != nil {
l.Warnln("Saving .stignore:", err)
return err
}
osutil.HideFile(path)
return m.ScanFolder(folder)
return nil
}
// OnHello is called when an device connects to us.
@@ -1516,8 +1490,8 @@ func sendIndexes(conn protocol.Connection, folder string, fs *db.FileSet, ignore
func sendIndexTo(minSequence int64, conn protocol.Connection, folder string, fs *db.FileSet, ignores *ignore.Matcher, dbLocation string, dropSymlinks bool) (int64, error) {
deviceID := conn.ID()
name := conn.Name()
batch := make([]protocol.FileInfo, 0, indexBatchSize)
currentBatchSize := 0
batch := make([]protocol.FileInfo, 0, maxBatchSizeFiles)
batchSizeBytes := 0
initial := minSequence == 0
maxSequence := minSequence
var err error
@@ -1548,26 +1522,26 @@ func sendIndexTo(minSequence int64, conn protocol.Connection, folder string, fs
})
sorter.Sorted(func(f protocol.FileInfo) bool {
if len(batch) == indexBatchSize || currentBatchSize > indexTargetSize {
if len(batch) == maxBatchSizeFiles || batchSizeBytes > maxBatchSizeBytes {
if initial {
if err = conn.Index(folder, batch); err != nil {
return false
}
l.Debugf("sendIndexes for %s-%s/%q: %d files (<%d bytes) (initial index)", deviceID, name, folder, len(batch), currentBatchSize)
l.Debugf("sendIndexes for %s-%s/%q: %d files (<%d bytes) (initial index)", deviceID, name, folder, len(batch), batchSizeBytes)
initial = false
} else {
if err = conn.IndexUpdate(folder, batch); err != nil {
return false
}
l.Debugf("sendIndexes for %s-%s/%q: %d files (<%d bytes) (batched update)", deviceID, name, folder, len(batch), currentBatchSize)
l.Debugf("sendIndexes for %s-%s/%q: %d files (<%d bytes) (batched update)", deviceID, name, folder, len(batch), batchSizeBytes)
}
batch = make([]protocol.FileInfo, 0, indexBatchSize)
currentBatchSize = 0
batch = make([]protocol.FileInfo, 0, maxBatchSizeFiles)
batchSizeBytes = 0
}
batch = append(batch, f)
currentBatchSize += f.ProtoSize()
batchSizeBytes += f.ProtoSize()
return true
})
@@ -1742,7 +1716,7 @@ func (m *Model) ScanFolderSubdirs(folder string, subs []string) error {
return runner.Scan(subs)
}
func (m *Model) internalScanFolderSubdirs(folder string, subDirs []string) error {
func (m *Model) internalScanFolderSubdirs(ctx context.Context, folder string, subDirs []string) error {
for i := 0; i < len(subDirs); i++ {
sub := osutil.NativeFilename(subDirs[i])
@@ -1812,14 +1786,9 @@ func (m *Model) internalScanFolderSubdirs(folder string, subDirs []string) error
return ok
})
// The cancel channel is closed whenever we return (such as from an error),
// to signal the potentially still running walker to stop.
cancel := make(chan struct{})
defer close(cancel)
runner.setState(FolderScanning)
fchan, err := scanner.Walk(scanner.Config{
fchan, err := scanner.Walk(ctx, scanner.Config{
Folder: folderCfg.ID,
Dir: folderCfg.Path(),
Subs: subDirs,
@@ -1833,7 +1802,6 @@ func (m *Model) internalScanFolderSubdirs(folder string, subDirs []string) error
Hashers: m.numHashers(folder),
ShortID: m.shortID,
ProgressTickIntervalS: folderCfg.ScanProgressIntervalS,
Cancel: cancel,
UseWeakHashes: weakhash.Enabled,
})
@@ -1848,24 +1816,21 @@ func (m *Model) internalScanFolderSubdirs(folder string, subDirs []string) error
return err
}
batchSizeFiles := 100
batchSizeBlocks := 2048 // about 256 MB
batch := make([]protocol.FileInfo, 0, batchSizeFiles)
blocksHandled := 0
batch := make([]protocol.FileInfo, 0, maxBatchSizeFiles)
batchSizeBytes := 0
for f := range fchan {
if len(batch) == batchSizeFiles || blocksHandled > batchSizeBlocks {
if len(batch) == maxBatchSizeFiles || batchSizeBytes > maxBatchSizeBytes {
if err := m.CheckFolderHealth(folder); err != nil {
l.Infof("Stopping folder %s mid-scan due to folder error: %s", folderCfg.Description(), err)
return err
}
m.updateLocalsFromScanning(folder, batch)
batch = batch[:0]
blocksHandled = 0
batchSizeBytes = 0
}
batch = append(batch, f)
blocksHandled += len(f.Blocks)
batchSizeBytes += f.ProtoSize()
}
if err := m.CheckFolderHealth(folder); err != nil {
@@ -1884,18 +1849,20 @@ func (m *Model) internalScanFolderSubdirs(folder string, subDirs []string) error
// Do a scan of the database for each prefix, to check for deleted and
// ignored files.
batch = batch[:0]
batchSizeBytes = 0
for _, sub := range subDirs {
var iterError error
fs.WithPrefixedHaveTruncated(protocol.LocalDeviceID, sub, func(fi db.FileIntf) bool {
f := fi.(db.FileInfoTruncated)
if len(batch) == batchSizeFiles {
if len(batch) == maxBatchSizeFiles || batchSizeBytes > maxBatchSizeBytes {
if err := m.CheckFolderHealth(folder); err != nil {
iterError = err
return false
}
m.updateLocalsFromScanning(folder, batch)
batch = batch[:0]
batchSizeBytes = 0
}
switch {
@@ -1915,6 +1882,7 @@ func (m *Model) internalScanFolderSubdirs(folder string, subDirs []string) error
Version: f.Version, // The file is still the same, so don't bump version
}
batch = append(batch, nf)
batchSizeBytes += nf.ProtoSize()
case !f.IsInvalid() && !f.IsDeleted():
// The file is valid and not deleted. Lets check if it's
@@ -1940,6 +1908,7 @@ func (m *Model) internalScanFolderSubdirs(folder string, subDirs []string) error
}
batch = append(batch, nf)
batchSizeBytes += nf.ProtoSize()
}
}
return true
@@ -2085,12 +2054,14 @@ func (m *Model) Override(folder string) {
}
runner.setState(FolderScanning)
batch := make([]protocol.FileInfo, 0, indexBatchSize)
batch := make([]protocol.FileInfo, 0, maxBatchSizeFiles)
batchSizeBytes := 0
fs.WithNeed(protocol.LocalDeviceID, func(fi db.FileIntf) bool {
need := fi.(protocol.FileInfo)
if len(batch) == indexBatchSize {
if len(batch) == maxBatchSizeFiles || batchSizeBytes > maxBatchSizeBytes {
m.updateLocalsFromScanning(folder, batch)
batch = batch[:0]
batchSizeBytes = 0
}
have, ok := fs.Get(protocol.LocalDeviceID, need.Name)
@@ -2107,6 +2078,7 @@ func (m *Model) Override(folder string) {
}
need.Sequence = 0
batch = append(batch, need)
batchSizeBytes += need.ProtoSize()
return true
})
if len(batch) > 0 {
@@ -2314,29 +2286,31 @@ func (m *Model) checkFolderPath(folder config.FolderConfiguration) error {
// checkFolderFreeSpace returns nil if the folder has the required amount of
// free space, or if folder free space checking is disabled.
func (m *Model) checkFolderFreeSpace(folder config.FolderConfiguration) error {
if folder.MinDiskFreePct <= 0 {
return nil
}
free, err := osutil.DiskFreePercentage(folder.Path())
if err == nil && free < folder.MinDiskFreePct {
return errFolderNoSpace
}
return nil
return m.checkFreeSpace(folder.MinDiskFree, folder.Path())
}
// checkHomeDiskFree returns nil if the home disk has the required amount of
// free space, or if home disk free space checking is disabled.
func (m *Model) checkHomeDiskFree() error {
minFree := m.cfg.Options().MinHomeDiskFreePct
if minFree <= 0 {
return m.checkFreeSpace(m.cfg.Options().MinHomeDiskFree, m.cfg.ConfigPath())
}
func (m *Model) checkFreeSpace(req config.Size, path string) error {
val := req.BaseValue()
if val <= 0 {
return nil
}
free, err := osutil.DiskFreePercentage(m.cfg.ConfigPath())
if err == nil && free < minFree {
return errHomeDiskNoSpace
if req.Percentage() {
free, err := osutil.DiskFreePercentage(path)
if err == nil && free < val {
return fmt.Errorf("insufficient space in %v: %f %% < %v", path, free, req)
}
} else {
free, err := osutil.DiskFreeBytes(path)
if err == nil && float64(free) < val {
return fmt.Errorf("insufficient space in %v: %v < %v", path, free, req)
}
}
return nil
@@ -2395,9 +2369,14 @@ func (m *Model) CommitConfiguration(from, to config.Configuration) bool {
for folderID, cfg := range toFolders {
if _, ok := fromFolders[folderID]; !ok {
// A folder was added.
l.Debugln(m, "adding folder", folderID)
m.AddFolder(cfg)
m.StartFolder(folderID)
if cfg.Paused {
l.Infoln(m, "Paused folder", cfg.Description())
cfg.CreateRoot()
} else {
l.Infoln(m, "Adding folder", cfg.Description())
m.AddFolder(cfg)
m.StartFolder(folderID)
}
}
}

View File

@@ -8,6 +8,7 @@ package model
import (
"bytes"
"context"
"encoding/json"
"fmt"
"io/ioutil"
@@ -317,7 +318,7 @@ func (f *fakeConnection) addFile(name string, flags uint32, ftype protocol.FileI
f.mut.Lock()
defer f.mut.Unlock()
blocks, _ := scanner.Blocks(bytes.NewReader(data), protocol.BlockSize, int64(len(data)), nil, true)
blocks, _ := scanner.Blocks(context.TODO(), bytes.NewReader(data), protocol.BlockSize, int64(len(data)), nil, true)
var version protocol.Vector
version = version.Update(f.id.Short())
@@ -927,7 +928,7 @@ func TestIntroducer(t *testing.T) {
}
}
func TestIgnores(t *testing.T) {
func changeIgnores(t *testing.T, m *Model, expected []string) {
arrEqual := func(a, b []string) bool {
if len(a) != len(b) {
return false
@@ -941,22 +942,6 @@ func TestIgnores(t *testing.T) {
return true
}
// Assure a clean start state
ioutil.WriteFile("testdata/.stfolder", nil, 0644)
ioutil.WriteFile("testdata/.stignore", []byte(".*\nquux\n"), 0644)
db := db.OpenMemory()
m := NewModel(defaultConfig, protocol.LocalDeviceID, "device", "syncthing", "dev", db, nil)
m.AddFolder(defaultFolderConfig)
m.StartFolder("default")
m.ServeBackground()
defer m.Stop()
expected := []string{
".*",
"quux",
}
ignores, _, err := m.GetIgnores("default")
if err != nil {
t.Error(err)
@@ -973,6 +958,8 @@ func TestIgnores(t *testing.T) {
// system into thinking the file has not changed. Work around it in
// an ugly way...
time.Sleep(time.Second)
} else {
time.Sleep(time.Millisecond)
}
err = m.SetIgnores("default", ignores)
if err != nil {
@@ -991,6 +978,8 @@ func TestIgnores(t *testing.T) {
if runtime.GOOS == "darwin" {
// see above
time.Sleep(time.Second)
} else {
time.Sleep(time.Millisecond)
}
err = m.SetIgnores("default", expected)
if err != nil {
@@ -1005,8 +994,34 @@ func TestIgnores(t *testing.T) {
if !arrEqual(ignores, expected) {
t.Errorf("Incorrect ignores: %v != %v", ignores, expected)
}
}
_, _, err = m.GetIgnores("doesnotexist")
func TestIgnores(t *testing.T) {
// Assure a clean start state
ioutil.WriteFile("testdata/.stfolder", nil, 0644)
ioutil.WriteFile("testdata/.stignore", []byte(".*\nquux\n"), 0644)
db := db.OpenMemory()
m := NewModel(defaultConfig, protocol.LocalDeviceID, "device", "syncthing", "dev", db, nil)
m.ServeBackground()
defer m.Stop()
// m.cfg.SetFolder is not usable as it is non-blocking, and there is no
// way to know when the folder is actually added.
m.AddFolder(defaultFolderConfig)
m.StartFolder("default")
// Make sure the initial scan has finished (ScanFolders is blocking)
m.ScanFolders()
expected := []string{
".*",
"quux",
}
changeIgnores(t, m, expected)
_, _, err := m.GetIgnores("doesnotexist")
if err == nil {
t.Error("No error")
}
@@ -1022,6 +1037,16 @@ func TestIgnores(t *testing.T) {
if err == nil {
t.Error("No error")
}
// Repeat tests with paused folder
pausedDefaultFolderConfig := defaultFolderConfig
pausedDefaultFolderConfig.Paused = true
m.RestartFolder(pausedDefaultFolderConfig)
// Here folder initialization is not an issue as a paused folder isn't
// added to the model and thus there is no initial scan happening.
changeIgnores(t, m, expected)
}
func TestROScanRecovery(t *testing.T) {
@@ -1769,13 +1794,8 @@ func TestIssue3028(t *testing.T) {
m.StartFolder("default")
m.ServeBackground()
// Ugly hack for testing: reach into the model for the SendReceiveFolder and wait
// for it to complete the initial scan. The risk is that it otherwise
// runs during our modifications and screws up the test.
m.fmut.RLock()
folder := m.folderRunners["default"].(*sendReceiveFolder)
m.fmut.RUnlock()
<-folder.initialScanCompleted
// Make sure the initial scan has finished (ScanFolders is blocking)
m.ScanFolders()
// Get a count of how many files are there now

View File

@@ -7,6 +7,7 @@
package model
import (
"context"
"fmt"
"github.com/syncthing/syncthing/lib/config"
@@ -24,12 +25,16 @@ type sendOnlyFolder struct {
}
func newSendOnlyFolder(model *Model, cfg config.FolderConfiguration, _ versioner.Versioner, _ *fs.MtimeFS) service {
ctx, cancel := context.WithCancel(context.Background())
return &sendOnlyFolder{
folder: folder{
stateTracker: newStateTracker(cfg.ID),
scan: newFolderScanner(cfg),
stop: make(chan struct{}),
model: model,
stateTracker: newStateTracker(cfg.ID),
scan: newFolderScanner(cfg),
ctx: ctx,
cancel: cancel,
model: model,
initialScanFinished: make(chan struct{}),
},
FolderConfiguration: cfg,
}
@@ -43,34 +48,24 @@ func (f *sendOnlyFolder) Serve() {
f.scan.timer.Stop()
}()
initialScanCompleted := false
for {
select {
case <-f.stop:
case <-f.ctx.Done():
return
case <-f.scan.timer.C:
if err := f.model.CheckFolderHealth(f.folderID); err != nil {
l.Infoln("Skipping scan of", f.Description(), "due to folder error:", err)
f.scan.Reschedule()
continue
}
l.Debugln(f, "Scanning subdirectories")
err := f.scanSubdirs(nil)
l.Debugln(f, "rescan")
if err := f.model.internalScanFolderSubdirs(f.folderID, nil); err != nil {
// Potentially sets the error twice, once in the scanner just
// by doing a check, and once here, if the error returned is
// the same one as returned by CheckFolderHealth, though
// duplicate set is handled by setError.
f.setError(err)
f.scan.Reschedule()
continue
}
if !initialScanCompleted {
l.Infoln("Completed initial scan (ro) of", f.Description())
initialScanCompleted = true
select {
case <-f.initialScanFinished:
default:
status := "Completed"
if err != nil {
status = "Failed"
}
l.Infoln(status, "initial scan (ro) of", f.Description())
close(f.initialScanFinished)
}
if f.scan.HasNoInterval() {
@@ -80,7 +75,7 @@ func (f *sendOnlyFolder) Serve() {
f.scan.Reschedule()
case req := <-f.scan.now:
req.err <- f.scanSubdirsIfHealthy(req.subdirs)
req.err <- f.scanSubdirs(req.subdirs)
case next := <-f.scan.delay:
f.scan.timer.Reset(next)

View File

@@ -7,6 +7,7 @@
package model
import (
"context"
"errors"
"fmt"
"math/rand"
@@ -96,17 +97,19 @@ type sendReceiveFolder struct {
errors map[string]string // path -> error string
errorsMut sync.Mutex
initialScanCompleted chan (struct{}) // exposed for testing
}
func newSendReceiveFolder(model *Model, cfg config.FolderConfiguration, ver versioner.Versioner, mtimeFS *fs.MtimeFS) service {
ctx, cancel := context.WithCancel(context.Background())
f := &sendReceiveFolder{
folder: folder{
stateTracker: newStateTracker(cfg.ID),
scan: newFolderScanner(cfg),
stop: make(chan struct{}),
model: model,
stateTracker: newStateTracker(cfg.ID),
scan: newFolderScanner(cfg),
ctx: ctx,
cancel: cancel,
model: model,
initialScanFinished: make(chan struct{}),
},
FolderConfiguration: cfg,
@@ -119,8 +122,6 @@ func newSendReceiveFolder(model *Model, cfg config.FolderConfiguration, ver vers
remoteIndex: make(chan struct{}, 1), // This needs to be 1-buffered so that we queue a notification if we're busy doing a pull when it comes.
errorsMut: sync.NewMutex(),
initialScanCompleted: make(chan struct{}),
}
f.configureCopiersAndPullers()
@@ -174,7 +175,7 @@ func (f *sendReceiveFolder) Serve() {
for {
select {
case <-f.stop:
case <-f.ctx.Done():
return
case <-f.remoteIndex:
@@ -184,7 +185,7 @@ func (f *sendReceiveFolder) Serve() {
case <-f.pullTimer.C:
select {
case <-f.initialScanCompleted:
case <-f.initialScanFinished:
default:
// We don't start pulling files until a scan has been completed.
l.Debugln(f, "skip (initial)")
@@ -278,20 +279,22 @@ func (f *sendReceiveFolder) Serve() {
// this is the easiest way to make sure we are not doing both at the
// same time.
case <-f.scan.timer.C:
err := f.scanSubdirsIfHealthy(nil)
l.Debugln(f, "Scanning subdirectories")
err := f.scanSubdirs(nil)
f.scan.Reschedule()
if err != nil {
continue
}
select {
case <-f.initialScanCompleted:
case <-f.initialScanFinished:
default:
l.Infoln("Completed initial scan (rw) of", f.Description())
close(f.initialScanCompleted)
close(f.initialScanFinished)
status := "Completed"
if err != nil {
status = "Failed"
}
l.Infoln(status, "initial scan (rw) of", f.Description())
}
case req := <-f.scan.now:
req.err <- f.scanSubdirsIfHealthy(req.subdirs)
req.err <- f.scanSubdirs(req.subdirs)
case next := <-f.scan.delay:
f.scan.timer.Reset(next)
@@ -493,7 +496,7 @@ func (f *sendReceiveFolder) pullerIteration(ignores *ignore.Matcher) int {
nextFile:
for {
select {
case <-f.stop:
case <-f.ctx.Done():
// Stop processing files if the puller has been told to stop.
break nextFile
default:
@@ -1063,7 +1066,7 @@ func (f *sendReceiveFolder) handleFile(file protocol.FileInfo, copyChan chan<- c
// sweep is complete. As we do retries, we'll queue the scan
// for this file up to ten times, but the last nine of those
// scans will be cheap...
go f.scan.Scan([]string{file.Name})
go f.Scan([]string{file.Name})
return
}
}
@@ -1077,7 +1080,7 @@ func (f *sendReceiveFolder) handleFile(file protocol.FileInfo, copyChan chan<- c
// Check for an old temporary file which might have some blocks we could
// reuse.
tempBlocks, err := scanner.HashFile(fs.DefaultFilesystem, tempName, protocol.BlockSize, nil, false)
tempBlocks, err := scanner.HashFile(f.ctx, fs.DefaultFilesystem, tempName, protocol.BlockSize, nil, false)
if err == nil {
// Check for any reusable blocks in the temp file
tempCopyBlocks, _ := scanner.BlockDiff(tempBlocks, file.Blocks)
@@ -1113,7 +1116,7 @@ func (f *sendReceiveFolder) handleFile(file protocol.FileInfo, copyChan chan<- c
blocksSize = file.Size
}
if f.MinDiskFreePct > 0 {
if f.MinDiskFree.BaseValue() > 0 {
if free, err := osutil.DiskFreeBytes(f.dir); err == nil && free < blocksSize {
l.Warnf(`Folder "%s": insufficient disk space in %s for %s: have %.2f MiB, need %.2f MiB`, f.folderID, f.dir, file.Name, float64(free)/1024/1024, float64(blocksSize)/1024/1024)
f.newError(file.Name, errors.New("insufficient space"))

View File

@@ -7,6 +7,7 @@
package model
import (
"context"
"crypto/rand"
"io"
"os"
@@ -77,11 +78,13 @@ func setUpModel(file protocol.FileInfo) *Model {
return model
}
func setUpSendReceiveFolder(model *Model) sendReceiveFolder {
return sendReceiveFolder{
func setUpSendReceiveFolder(model *Model) *sendReceiveFolder {
f := &sendReceiveFolder{
folder: folder{
stateTracker: newStateTracker("default"),
model: model,
stateTracker: newStateTracker("default"),
model: model,
initialScanFinished: make(chan struct{}),
ctx: context.TODO(),
},
mtimeFS: fs.NewMtimeFS(fs.DefaultFilesystem, db.NewNamespacedKV(model.db, "mtime")),
@@ -90,6 +93,11 @@ func setUpSendReceiveFolder(model *Model) sendReceiveFolder {
errors: make(map[string]string),
errorsMut: sync.NewMutex(),
}
// Folders are never actually started, so no initial scan will be done
close(f.initialScanFinished)
return f
}
// Layout of the files: (indexes from the above array)
@@ -238,7 +246,7 @@ func TestCopierFinder(t *testing.T) {
}
// Verify that the fetched blocks have actually been written to the temp file
blks, err := scanner.HashFile(fs.DefaultFilesystem, tempFile, protocol.BlockSize, nil, false)
blks, err := scanner.HashFile(context.TODO(), fs.DefaultFilesystem, tempFile, protocol.BlockSize, nil, false)
if err != nil {
t.Log(err)
}
@@ -291,7 +299,7 @@ func TestWeakHash(t *testing.T) {
// File 1: abcdefgh
// File 2: xyabcdef
f.Seek(0, os.SEEK_SET)
existing, err := scanner.Blocks(f, protocol.BlockSize, size, nil, true)
existing, err := scanner.Blocks(context.TODO(), f, protocol.BlockSize, size, nil, true)
if err != nil {
t.Error(err)
}
@@ -300,7 +308,7 @@ func TestWeakHash(t *testing.T) {
remainder := io.LimitReader(f, size-shift)
prefix := io.LimitReader(rand.Reader, shift)
nf := io.MultiReader(prefix, remainder)
desired, err := scanner.Blocks(nf, protocol.BlockSize, size, nil, true)
desired, err := scanner.Blocks(context.TODO(), nf, protocol.BlockSize, size, nil, true)
if err != nil {
t.Error(err)
}

View File

@@ -11,9 +11,8 @@ import (
"regexp"
"strings"
"github.com/syncthing/syncthing/lib/sha256"
"github.com/calmh/luhn"
"github.com/syncthing/syncthing/lib/sha256"
)
const DeviceIDLength = 32
@@ -124,7 +123,7 @@ func (n *DeviceID) UnmarshalText(bs []byte) error {
copy(n[:], dec)
return nil
default:
return errors.New("device ID invalid: incorrect length")
return fmt.Errorf("%q: device ID invalid: incorrect length", bs)
}
}
@@ -145,7 +144,7 @@ func (n *DeviceID) MarshalTo(bs []byte) (int, error) {
func (n *DeviceID) Unmarshal(bs []byte) error {
// Used by protobuf marshaller.
if len(bs) < DeviceIDLength {
return errors.New("not enough data")
return fmt.Errorf("%q: not enough data", bs)
}
copy((*n)[:], bs)
return nil
@@ -170,7 +169,7 @@ func luhnify(s string) (string, error) {
func unluhnify(s string) (string, error) {
if len(s) != 56 {
return "", fmt.Errorf("unsupported string length %d", len(s))
return "", fmt.Errorf("%q: unsupported string length %d", s, len(s))
}
res := make([]string, 0, 4)
@@ -181,7 +180,7 @@ func unluhnify(s string) (string, error) {
return "", err
}
if g := fmt.Sprintf("%s%c", p, l); g != s[i*14:(i+1)*14] {
return "", errors.New("check digit incorrect")
return "", fmt.Errorf("%q: check digit incorrect", s)
}
res = append(res, p)
}

View File

@@ -7,6 +7,7 @@
package scanner
import (
"context"
"errors"
"path/filepath"
@@ -16,7 +17,7 @@ import (
)
// HashFile hashes the files and returns a list of blocks representing the file.
func HashFile(fs fs.Filesystem, path string, blockSize int, counter Counter, useWeakHashes bool) ([]protocol.BlockInfo, error) {
func HashFile(ctx context.Context, fs fs.Filesystem, path string, blockSize int, counter Counter, useWeakHashes bool) ([]protocol.BlockInfo, error) {
fd, err := fs.Open(path)
if err != nil {
l.Debugln("open:", err)
@@ -36,7 +37,7 @@ func HashFile(fs fs.Filesystem, path string, blockSize int, counter Counter, use
// Hash the file. This may take a while for large files.
blocks, err := Blocks(fd, blockSize, size, counter, useWeakHashes)
blocks, err := Blocks(ctx, fd, blockSize, size, counter, useWeakHashes)
if err != nil {
l.Debugln("blocks:", err)
return nil, err
@@ -70,12 +71,11 @@ type parallelHasher struct {
inbox <-chan protocol.FileInfo
counter Counter
done chan<- struct{}
cancel <-chan struct{}
useWeakHashes bool
wg sync.WaitGroup
}
func newParallelHasher(fs fs.Filesystem, dir string, blockSize, workers int, outbox chan<- protocol.FileInfo, inbox <-chan protocol.FileInfo, counter Counter, done chan<- struct{}, cancel <-chan struct{}, useWeakHashes bool) {
func newParallelHasher(ctx context.Context, fs fs.Filesystem, dir string, blockSize, workers int, outbox chan<- protocol.FileInfo, inbox <-chan protocol.FileInfo, counter Counter, done chan<- struct{}, useWeakHashes bool) {
ph := &parallelHasher{
fs: fs,
dir: dir,
@@ -85,20 +85,19 @@ func newParallelHasher(fs fs.Filesystem, dir string, blockSize, workers int, out
inbox: inbox,
counter: counter,
done: done,
cancel: cancel,
useWeakHashes: useWeakHashes,
wg: sync.NewWaitGroup(),
}
for i := 0; i < workers; i++ {
ph.wg.Add(1)
go ph.hashFiles()
go ph.hashFiles(ctx)
}
go ph.closeWhenDone()
}
func (ph *parallelHasher) hashFiles() {
func (ph *parallelHasher) hashFiles(ctx context.Context) {
defer ph.wg.Done()
for {
@@ -112,7 +111,7 @@ func (ph *parallelHasher) hashFiles() {
panic("Bug. Asked to hash a directory or a deleted file.")
}
blocks, err := HashFile(ph.fs, filepath.Join(ph.dir, f.Name), ph.blockSize, ph.counter, ph.useWeakHashes)
blocks, err := HashFile(ctx, ph.fs, filepath.Join(ph.dir, f.Name), ph.blockSize, ph.counter, ph.useWeakHashes)
if err != nil {
l.Debugln("hash error:", f.Name, err)
continue
@@ -131,11 +130,11 @@ func (ph *parallelHasher) hashFiles() {
select {
case ph.outbox <- f:
case <-ph.cancel:
case <-ctx.Done():
return
}
case <-ph.cancel:
case <-ctx.Done():
return
}
}

View File

@@ -8,6 +8,7 @@ package scanner
import (
"bytes"
"context"
"fmt"
"hash"
"io"
@@ -24,7 +25,7 @@ type Counter interface {
}
// Blocks returns the blockwise hash of the reader.
func Blocks(r io.Reader, blocksize int, sizehint int64, counter Counter, useWeakHashes bool) ([]protocol.BlockInfo, error) {
func Blocks(ctx context.Context, r io.Reader, blocksize int, sizehint int64, counter Counter, useWeakHashes bool) ([]protocol.BlockInfo, error) {
hf := sha256.New()
hashLength := hf.Size()
@@ -57,6 +58,12 @@ func Blocks(r io.Reader, blocksize int, sizehint int64, counter Counter, useWeak
var offset int64
lr := io.LimitReader(r, int64(blocksize)).(*io.LimitedReader)
for {
select {
case <-ctx.Done():
return nil, ctx.Err()
default:
}
lr.N = int64(blocksize)
n, err := io.CopyBuffer(mhf, lr, buf)
if err != nil {

View File

@@ -8,6 +8,7 @@ package scanner
import (
"bytes"
"context"
"crypto/rand"
"fmt"
origAdler32 "hash/adler32"
@@ -68,7 +69,7 @@ var blocksTestData = []struct {
func TestBlocks(t *testing.T) {
for testNo, test := range blocksTestData {
buf := bytes.NewBuffer(test.data)
blocks, err := Blocks(buf, test.blocksize, -1, nil, true)
blocks, err := Blocks(context.TODO(), buf, test.blocksize, -1, nil, true)
if err != nil {
t.Fatal(err)
@@ -125,8 +126,8 @@ var diffTestData = []struct {
func TestDiff(t *testing.T) {
for i, test := range diffTestData {
a, _ := Blocks(bytes.NewBufferString(test.a), test.s, -1, nil, false)
b, _ := Blocks(bytes.NewBufferString(test.b), test.s, -1, nil, false)
a, _ := Blocks(context.TODO(), bytes.NewBufferString(test.a), test.s, -1, nil, false)
b, _ := Blocks(context.TODO(), bytes.NewBufferString(test.b), test.s, -1, nil, false)
_, d := BlockDiff(a, b)
if len(d) != len(test.d) {
t.Fatalf("Incorrect length for diff %d; %d != %d", i, len(d), len(test.d))

View File

@@ -0,0 +1,103 @@
// 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 scanner
import (
"errors"
"fmt"
"io"
"os"
"path/filepath"
"strings"
"time"
"github.com/syncthing/syncthing/lib/fs"
)
type infiniteFS struct {
width int // number of files and directories per level
depth int // number of tree levels to simulate
filesize int64 // size of each file in bytes
}
var errNotSupp = errors.New("not supported")
func (i infiniteFS) Lstat(name string) (fs.FileInfo, error) {
return fakeInfo{name, i.filesize}, nil
}
func (i infiniteFS) DirNames(name string) ([]string, error) {
// Returns a list of fake files and directories. Names are such that
// files appear before directories - this makes it so the scanner will
// actually see a few files without having to reach the max depth.
var names []string
for j := 0; j < i.width; j++ {
names = append(names, fmt.Sprintf("aa-file-%d", j))
}
if len(strings.Split(name, string(os.PathSeparator))) < i.depth {
for j := 0; j < i.width; j++ {
names = append(names, fmt.Sprintf("zz-dir-%d", j))
}
}
return names, nil
}
func (i infiniteFS) Open(name string) (fs.File, error) {
return &fakeFile{name, i.filesize, 0}, nil
}
func (infiniteFS) Chmod(name string, mode fs.FileMode) error { return errNotSupp }
func (infiniteFS) Chtimes(name string, atime time.Time, mtime time.Time) error { return errNotSupp }
func (infiniteFS) Create(name string) (fs.File, error) { return nil, errNotSupp }
func (infiniteFS) CreateSymlink(name, target string) error { return errNotSupp }
func (infiniteFS) Mkdir(name string, perm fs.FileMode) error { return errNotSupp }
func (infiniteFS) ReadSymlink(name string) (string, error) { return "", errNotSupp }
func (infiniteFS) Remove(name string) error { return errNotSupp }
func (infiniteFS) Rename(oldname, newname string) error { return errNotSupp }
func (infiniteFS) Stat(name string) (fs.FileInfo, error) { return nil, errNotSupp }
func (infiniteFS) SymlinksSupported() bool { return false }
func (infiniteFS) Walk(root string, walkFn fs.WalkFunc) error { return errNotSupp }
type fakeInfo struct {
name string
size int64
}
func (f fakeInfo) Name() string { return f.name }
func (f fakeInfo) Mode() fs.FileMode { return 0755 }
func (f fakeInfo) Size() int64 { return f.size }
func (f fakeInfo) ModTime() time.Time { return time.Unix(1234567890, 0) }
func (f fakeInfo) IsDir() bool { return strings.Contains(filepath.Base(f.name), "dir") }
func (f fakeInfo) IsRegular() bool { return !f.IsDir() }
func (f fakeInfo) IsSymlink() bool { return false }
type fakeFile struct {
name string
size int64
readOffset int64
}
func (f *fakeFile) Read(bs []byte) (int, error) {
remaining := f.size - f.readOffset
if remaining == 0 {
return 0, io.EOF
}
if remaining < int64(len(bs)) {
f.readOffset = f.size
return int(remaining), nil
}
f.readOffset += int64(len(bs))
return len(bs), nil
}
func (f *fakeFile) Stat() (fs.FileInfo, error) {
return fakeInfo{f.name, f.size}, nil
}
func (f *fakeFile) WriteAt(bs []byte, offs int64) (int, error) { return 0, errNotSupp }
func (f *fakeFile) Close() error { return nil }
func (f *fakeFile) Truncate(size int64) error { return errNotSupp }

View File

@@ -7,6 +7,7 @@
package scanner
import (
"context"
"errors"
"path/filepath"
"runtime"
@@ -69,8 +70,6 @@ type Config struct {
// Optional progress tick interval which defines how often FolderScanProgress
// events are emitted. Negative number means disabled.
ProgressTickIntervalS int
// Signals cancel from the outside - when closed, we should stop walking.
Cancel chan struct{}
// Whether or not we should also compute weak hashes
UseWeakHashes bool
}
@@ -80,7 +79,7 @@ type CurrentFiler interface {
CurrentFile(name string) (protocol.FileInfo, bool)
}
func Walk(cfg Config) (chan protocol.FileInfo, error) {
func Walk(ctx context.Context, cfg Config) (chan protocol.FileInfo, error) {
w := walker{cfg}
if w.CurrentFiler == nil {
@@ -90,7 +89,7 @@ func Walk(cfg Config) (chan protocol.FileInfo, error) {
w.Filesystem = fs.DefaultFilesystem
}
return w.walk()
return w.walk(ctx)
}
type walker struct {
@@ -99,7 +98,7 @@ type walker struct {
// Walk returns the list of files found in the local folder by scanning the
// file system. Files are blockwise hashed.
func (w *walker) walk() (chan protocol.FileInfo, error) {
func (w *walker) walk(ctx context.Context) (chan protocol.FileInfo, error) {
l.Debugln("Walk", w.Dir, w.Subs, w.BlockSize, w.Matcher)
if err := w.checkDir(); err != nil {
@@ -112,7 +111,7 @@ func (w *walker) walk() (chan protocol.FileInfo, error) {
// A routine which walks the filesystem tree, and sends files which have
// been modified to the counter routine.
go func() {
hashFiles := w.walkAndHashFiles(toHashChan, finishedChan)
hashFiles := w.walkAndHashFiles(ctx, toHashChan, finishedChan)
if len(w.Subs) == 0 {
w.Filesystem.Walk(w.Dir, hashFiles)
} else {
@@ -126,7 +125,7 @@ func (w *walker) walk() (chan protocol.FileInfo, error) {
// We're not required to emit scan progress events, just kick off hashers,
// and feed inputs directly from the walker.
if w.ProgressTickIntervalS < 0 {
newParallelHasher(w.Filesystem, w.Dir, w.BlockSize, w.Hashers, finishedChan, toHashChan, nil, nil, w.Cancel, w.UseWeakHashes)
newParallelHasher(ctx, w.Filesystem, w.Dir, w.BlockSize, w.Hashers, finishedChan, toHashChan, nil, nil, w.UseWeakHashes)
return finishedChan, nil
}
@@ -157,7 +156,7 @@ func (w *walker) walk() (chan protocol.FileInfo, error) {
done := make(chan struct{})
progress := newByteCounter()
newParallelHasher(w.Filesystem, w.Dir, w.BlockSize, w.Hashers, finishedChan, realToHashChan, progress, done, w.Cancel, w.UseWeakHashes)
newParallelHasher(ctx, w.Filesystem, w.Dir, w.BlockSize, w.Hashers, finishedChan, realToHashChan, progress, done, w.UseWeakHashes)
// A routine which actually emits the FolderScanProgress events
// every w.ProgressTicker ticks, until the hasher routines terminate.
@@ -180,7 +179,7 @@ func (w *walker) walk() (chan protocol.FileInfo, error) {
"total": total,
"rate": rate, // bytes per second
})
case <-w.Cancel:
case <-ctx.Done():
ticker.Stop()
return
}
@@ -192,7 +191,7 @@ func (w *walker) walk() (chan protocol.FileInfo, error) {
l.Debugln("real to hash:", file.Name)
select {
case realToHashChan <- file:
case <-w.Cancel:
case <-ctx.Done():
break loop
}
}
@@ -202,9 +201,15 @@ func (w *walker) walk() (chan protocol.FileInfo, error) {
return finishedChan, nil
}
func (w *walker) walkAndHashFiles(fchan, dchan chan protocol.FileInfo) fs.WalkFunc {
func (w *walker) walkAndHashFiles(ctx context.Context, fchan, dchan chan protocol.FileInfo) fs.WalkFunc {
now := time.Now()
return func(absPath string, info fs.FileInfo, err error) error {
select {
case <-ctx.Done():
return ctx.Err()
default:
}
// Return value used when we are returning early and don't want to
// process the item. For directories, this means do-not-descend.
var skip error // nil
@@ -265,7 +270,7 @@ func (w *walker) walkAndHashFiles(fchan, dchan chan protocol.FileInfo) fs.WalkFu
switch {
case info.IsSymlink():
if err := w.walkSymlink(absPath, relPath, dchan); err != nil {
if err := w.walkSymlink(ctx, absPath, relPath, dchan); err != nil {
return err
}
if info.IsDir() {
@@ -275,17 +280,17 @@ func (w *walker) walkAndHashFiles(fchan, dchan chan protocol.FileInfo) fs.WalkFu
return nil
case info.IsDir():
err = w.walkDir(relPath, info, dchan)
err = w.walkDir(ctx, relPath, info, dchan)
case info.IsRegular():
err = w.walkRegular(relPath, info, fchan)
err = w.walkRegular(ctx, relPath, info, fchan)
}
return err
}
}
func (w *walker) walkRegular(relPath string, info fs.FileInfo, fchan chan protocol.FileInfo) error {
func (w *walker) walkRegular(ctx context.Context, relPath string, info fs.FileInfo, fchan chan protocol.FileInfo) error {
curMode := uint32(info.Mode())
if runtime.GOOS == "windows" && osutil.IsWindowsExecutable(relPath) {
curMode |= 0111
@@ -326,14 +331,14 @@ func (w *walker) walkRegular(relPath string, info fs.FileInfo, fchan chan protoc
select {
case fchan <- f:
case <-w.Cancel:
return errors.New("cancelled")
case <-ctx.Done():
return ctx.Err()
}
return nil
}
func (w *walker) walkDir(relPath string, info fs.FileInfo, dchan chan protocol.FileInfo) error {
func (w *walker) walkDir(ctx context.Context, relPath string, info fs.FileInfo, dchan chan protocol.FileInfo) error {
// A directory is "unchanged", if it
// - exists
// - has the same permissions as previously, unless we are ignoring permissions
@@ -361,8 +366,8 @@ func (w *walker) walkDir(relPath string, info fs.FileInfo, dchan chan protocol.F
select {
case dchan <- f:
case <-w.Cancel:
return errors.New("cancelled")
case <-ctx.Done():
return ctx.Err()
}
return nil
@@ -370,7 +375,7 @@ func (w *walker) walkDir(relPath string, info fs.FileInfo, dchan chan protocol.F
// walkSymlink returns nil or an error, if the error is of the nature that
// it should stop the entire walk.
func (w *walker) walkSymlink(absPath, relPath string, dchan chan protocol.FileInfo) error {
func (w *walker) walkSymlink(ctx context.Context, absPath, relPath string, dchan chan protocol.FileInfo) error {
// Symlinks are not supported on Windows. We ignore instead of returning
// an error.
if runtime.GOOS == "windows" {
@@ -412,8 +417,8 @@ func (w *walker) walkSymlink(absPath, relPath string, dchan chan protocol.FileIn
select {
case dchan <- f:
case <-w.Cancel:
return errors.New("cancelled")
case <-ctx.Done():
return ctx.Err()
}
return nil

View File

@@ -8,6 +8,7 @@ package scanner
import (
"bytes"
"context"
"crypto/rand"
"fmt"
"io"
@@ -59,7 +60,7 @@ func TestWalkSub(t *testing.T) {
t.Fatal(err)
}
fchan, err := Walk(Config{
fchan, err := Walk(context.TODO(), Config{
Dir: "testdata",
Subs: []string{"dir2"},
BlockSize: 128 * 1024,
@@ -96,7 +97,7 @@ func TestWalk(t *testing.T) {
}
t.Log(ignores)
fchan, err := Walk(Config{
fchan, err := Walk(context.TODO(), Config{
Dir: "testdata",
BlockSize: 128 * 1024,
Matcher: ignores,
@@ -120,7 +121,7 @@ func TestWalk(t *testing.T) {
}
func TestWalkError(t *testing.T) {
_, err := Walk(Config{
_, err := Walk(context.TODO(), Config{
Dir: "testdata-missing",
BlockSize: 128 * 1024,
Hashers: 2,
@@ -130,7 +131,7 @@ func TestWalkError(t *testing.T) {
t.Error("no error from missing directory")
}
_, err = Walk(Config{
_, err = Walk(context.TODO(), Config{
Dir: "testdata/bar",
BlockSize: 128 * 1024,
})
@@ -148,7 +149,7 @@ func TestVerify(t *testing.T) {
progress := newByteCounter()
defer progress.Close()
blocks, err := Blocks(buf, blocksize, -1, progress, false)
blocks, err := Blocks(context.TODO(), buf, blocksize, -1, progress, false)
if err != nil {
t.Fatal(err)
}
@@ -276,7 +277,7 @@ func TestNormalization(t *testing.T) {
func TestIssue1507(t *testing.T) {
w := &walker{}
c := make(chan protocol.FileInfo, 100)
fn := w.walkAndHashFiles(c, c)
fn := w.walkAndHashFiles(context.TODO(), c, c)
fn("", nil, protocol.ErrClosed)
}
@@ -297,7 +298,7 @@ func TestWalkSymlinkUnix(t *testing.T) {
// Scan it
fchan, err := Walk(Config{
fchan, err := Walk(context.TODO(), Config{
Dir: "_symlinks",
BlockSize: 128 * 1024,
})
@@ -342,7 +343,7 @@ func TestWalkSymlinkWindows(t *testing.T) {
// Scan it
fchan, err := Walk(Config{
fchan, err := Walk(context.TODO(), Config{
Dir: "_symlinks",
BlockSize: 128 * 1024,
})
@@ -364,7 +365,7 @@ func TestWalkSymlinkWindows(t *testing.T) {
}
func walkDir(dir string) ([]protocol.FileInfo, error) {
fchan, err := Walk(Config{
fchan, err := Walk(context.TODO(), Config{
Dir: dir,
BlockSize: 128 * 1024,
AutoNormalize: true,
@@ -434,7 +435,7 @@ func BenchmarkHashFile(b *testing.B) {
b.ResetTimer()
for i := 0; i < b.N; i++ {
if _, err := HashFile(fs.DefaultFilesystem, testdataName, protocol.BlockSize, nil, true); err != nil {
if _, err := HashFile(context.TODO(), fs.DefaultFilesystem, testdataName, protocol.BlockSize, nil, true); err != nil {
b.Fatal(err)
}
}
@@ -458,3 +459,68 @@ func initTestFile() {
panic(err)
}
}
func TestStopWalk(t *testing.T) {
// Create tree that is 100 levels deep, with each level containing 100
// files (each 1 MB) and 100 directories (in turn containing 100 files
// and 100 directories, etc). That is, in total > 100^100 files and as
// many directories. It'll take a while to scan, giving us time to
// cancel it and make sure the scan stops.
fs := fs.NewWalkFilesystem(&infiniteFS{100, 100, 1e6})
const numHashers = 4
ctx, cancel := context.WithCancel(context.Background())
fchan, err := Walk(ctx, Config{
Dir: "testdir",
BlockSize: 128 * 1024,
Hashers: numHashers,
Filesystem: fs,
ProgressTickIntervalS: -1, // Don't attempt to build the full list of files before starting to scan...
})
if err != nil {
t.Fatal(err)
}
// Receive a few entries to make sure the walker is up and running,
// scanning both files and dirs. Do some quick sanity tests on the
// returned file entries to make sure we are not just reading crap from
// a closed channel or something.
dirs := 0
files := 0
for {
f := <-fchan
t.Log("Scanned", f)
if f.IsDirectory() {
if len(f.Name) == 0 || f.Permissions == 0 {
t.Error("Bad directory entry", f)
}
dirs++
} else {
if len(f.Name) == 0 || len(f.Blocks) == 0 || f.Permissions == 0 {
t.Error("Bad file entry", f)
}
files++
}
if dirs > 5 && files > 5 {
break
}
}
// Cancel the walker.
cancel()
// Empty out any waiting entries and wait for the channel to close.
// Count them, they should be zero or very few - essentially, each
// hasher has the choice of returning a fully handled entry or
// cancelling, but they should not start on another item.
extra := 0
for range fchan {
extra++
}
t.Log("Extra entries:", extra)
if extra > numHashers {
t.Error("unexpected extra entries received after cancel")
}
}

View File

@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
.TH "STDISCOSRV" "1" "March 31, 2017" "v0.14" "Syncthing"
.TH "STDISCOSRV" "1" "May 17, 2017" "v0.14" "Syncthing"
.SH NAME
stdiscosrv \- Syncthing Discovery Server
.

View File

@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
.TH "STRELAYSRV" "1" "March 31, 2017" "v0.14" "Syncthing"
.TH "STRELAYSRV" "1" "May 17, 2017" "v0.14" "Syncthing"
.SH NAME
strelaysrv \- Syncthing Relay Server
.

View File

@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
.TH "SYNCTHING-BEP" "7" "March 31, 2017" "v0.14" "Syncthing"
.TH "SYNCTHING-BEP" "7" "May 17, 2017" "v0.14" "Syncthing"
.SH NAME
syncthing-bep \- Block Exchange Protocol v1
.

View File

@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
.TH "SYNCTHING-CONFIG" "5" "March 31, 2017" "v0.14" "Syncthing"
.TH "SYNCTHING-CONFIG" "5" "May 17, 2017" "v0.14" "Syncthing"
.SH NAME
syncthing-config \- Syncthing Configuration
.

View File

@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
.TH "SYNCTHING-DEVICE-IDS" "7" "March 31, 2017" "v0.14" "Syncthing"
.TH "SYNCTHING-DEVICE-IDS" "7" "May 17, 2017" "v0.14" "Syncthing"
.SH NAME
syncthing-device-ids \- Understanding Device IDs
.

View File

@@ -1,6 +1,6 @@
.\" Man page generated from reStructuredText.
.
.TH "SYNCTHING-EVENT-API" "7" "March 31, 2017" "v0.14" "Syncthing"
.TH "SYNCTHING-EVENT-API" "7" "May 17, 2017" "v0.14" "Syncthing"
.SH NAME
syncthing-event-api \- Event API
.

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