mirror of
https://github.com/schlagmichdoch/PairDrop.git
synced 2026-04-06 09:53:49 +00:00
Compare commits
82 Commits
speed-up-l
...
sw_digeste
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
50539ed485 | ||
|
|
490bad5734 | ||
|
|
1d5f2e8023 | ||
|
|
b261cb73ba | ||
|
|
f9b8b0fadf | ||
|
|
db8d5f97ea | ||
|
|
3b31472c52 | ||
|
|
f7ea519106 | ||
|
|
76c47c9623 | ||
|
|
fa86212139 | ||
|
|
331c61fec8 | ||
|
|
fa24e77d3b | ||
|
|
6ca039910a | ||
|
|
9f02f7b3ca | ||
|
|
04d65da779 | ||
|
|
e6f2c776dc | ||
|
|
b0711de5b9 | ||
|
|
d9a6ed4a47 | ||
|
|
5dd36da962 | ||
|
|
8bc65ed622 | ||
|
|
5625cb0ca6 | ||
|
|
74e5e2286f | ||
|
|
1a254765fe | ||
|
|
27a698c762 | ||
|
|
971917bc77 | ||
|
|
1eefd4720f | ||
|
|
ff92e606ff | ||
|
|
e53e4adcdf | ||
|
|
fda19dc819 | ||
|
|
78d9ba45d3 | ||
|
|
51299bcf73 | ||
|
|
5f6d330386 | ||
|
|
f103f37e16 | ||
|
|
4b99ff46da | ||
|
|
be381ea438 | ||
|
|
9b3571feac | ||
|
|
8a56a271bc | ||
|
|
07e46e472e | ||
|
|
3b772d0619 | ||
|
|
d70f9d762e | ||
|
|
8592499d22 | ||
|
|
e29ea44025 | ||
|
|
00f1a20177 | ||
|
|
3c8848d406 | ||
|
|
0d17ada58b | ||
|
|
74bd7dd406 | ||
|
|
f4a947527d | ||
|
|
90f10910aa | ||
|
|
aacf24c31f | ||
|
|
c0e5b66d41 | ||
|
|
42bd71a3dc | ||
|
|
a98499ea5a | ||
|
|
7c471910ef | ||
|
|
da558ddceb | ||
|
|
1df8fe258e | ||
|
|
65936a4d7d | ||
|
|
7c6062e1e0 | ||
|
|
902b5c6b8f | ||
|
|
19d33e11d8 | ||
|
|
d8908e01ea | ||
|
|
2d2cfec5f0 | ||
|
|
40a12b5501 | ||
|
|
5ee8bb871e | ||
|
|
ef3c338dad | ||
|
|
6d95f3f4e2 | ||
|
|
c33d49702e | ||
|
|
1d62a9ff49 | ||
|
|
3dd40e238a | ||
|
|
417d5421a6 | ||
|
|
7af51bbd5f | ||
|
|
88739107e4 | ||
|
|
6de97e7ff1 | ||
|
|
b61de4eb87 | ||
|
|
cfe5b4afda | ||
|
|
91fc2b7bf5 | ||
|
|
c670b39732 | ||
|
|
e5a09b6be1 | ||
|
|
1d81b744ea | ||
|
|
c37412cfd3 | ||
|
|
a5dc8b6da2 | ||
|
|
d81c03a560 | ||
|
|
f22abca783 |
4
.github/ISSUE_TEMPLATE/bug-report.md
vendored
4
.github/ISSUE_TEMPLATE/bug-report.md
vendored
@@ -36,7 +36,7 @@ If applicable, add screenshots to help explain your problem.
|
||||
|
||||
**Bug occurs on official PairDrop instance https://pairdrop.net/**
|
||||
No | Yes
|
||||
Version: v1.10.8
|
||||
Version: v1.10.9
|
||||
|
||||
**Bug occurs on self-hosted PairDrop instance**
|
||||
No | Yes
|
||||
@@ -44,7 +44,7 @@ No | Yes
|
||||
**Self-Hosted Setup**
|
||||
Proxy: Nginx | Apache2
|
||||
Deployment: docker run | docker compose | npm run start:prod
|
||||
Version: v1.10.8
|
||||
Version: v1.10.9
|
||||
|
||||
**Additional context**
|
||||
Add any other context about the problem here.
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -1,7 +1,6 @@
|
||||
node_modules
|
||||
.DS_Store
|
||||
fqdn.env
|
||||
/docker/certs
|
||||
/dev/certs
|
||||
qrcode-svg/
|
||||
turnserver.conf
|
||||
rtc_config.json
|
||||
|
||||
3
dev/nginx-with-openssl.Dockerfile
Normal file
3
dev/nginx-with-openssl.Dockerfile
Normal file
@@ -0,0 +1,3 @@
|
||||
FROM nginx:alpine
|
||||
|
||||
RUN apk add --no-cache openssl
|
||||
41
dev/nginx/default.conf
Normal file
41
dev/nginx/default.conf
Normal file
@@ -0,0 +1,41 @@
|
||||
server {
|
||||
listen 80;
|
||||
|
||||
expires epoch;
|
||||
|
||||
location / {
|
||||
proxy_connect_timeout 300;
|
||||
proxy_pass http://pairdrop:3000;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
}
|
||||
|
||||
location /ca.crt {
|
||||
alias /etc/ssl/certs/pairdropCA.crt;
|
||||
}
|
||||
|
||||
# To allow POST on static pages
|
||||
error_page 405 =200 $uri;
|
||||
}
|
||||
|
||||
server {
|
||||
listen 443 ssl http2;
|
||||
ssl_certificate /etc/ssl/certs/pairdrop-dev.crt;
|
||||
ssl_certificate_key /etc/ssl/certs/pairdrop-dev.key;
|
||||
|
||||
expires epoch;
|
||||
|
||||
location / {
|
||||
proxy_connect_timeout 300;
|
||||
proxy_pass http://pairdrop:3000;
|
||||
proxy_set_header Connection "upgrade";
|
||||
proxy_set_header Upgrade $http_upgrade;
|
||||
}
|
||||
|
||||
location /ca.crt {
|
||||
alias /etc/ssl/certs/pairdropCA.crt;
|
||||
}
|
||||
# To allow POST on static pages
|
||||
error_page 405 =200 $uri;
|
||||
}
|
||||
|
||||
9
dev/openssl/create.sh
Normal file
9
dev/openssl/create.sh
Normal file
@@ -0,0 +1,9 @@
|
||||
#!/bin/sh
|
||||
|
||||
cnf_dir='/mnt/openssl/'
|
||||
certs_dir='/etc/ssl/certs/'
|
||||
openssl req -config ${cnf_dir}pairdropCA.cnf -new -x509 -days 1 -keyout ${certs_dir}pairdropCA.key -out ${certs_dir}pairdropCA.crt
|
||||
openssl req -config ${cnf_dir}pairdropCert.cnf -new -out /tmp/pairdrop-dev.csr -keyout ${certs_dir}pairdrop-dev.key
|
||||
openssl x509 -req -in /tmp/pairdrop-dev.csr -CA ${certs_dir}pairdropCA.crt -CAkey ${certs_dir}pairdropCA.key -CAcreateserial -extensions req_ext -extfile ${cnf_dir}pairdropCert.cnf -sha512 -days 1 -out ${certs_dir}pairdrop-dev.crt
|
||||
|
||||
exec "$@"
|
||||
26
dev/openssl/pairdropCA.cnf
Normal file
26
dev/openssl/pairdropCA.cnf
Normal file
@@ -0,0 +1,26 @@
|
||||
[ req ]
|
||||
default_bits = 2048
|
||||
default_md = sha256
|
||||
default_days = 1
|
||||
encrypt_key = no
|
||||
distinguished_name = subject
|
||||
x509_extensions = x509_ext
|
||||
string_mask = utf8only
|
||||
prompt = no
|
||||
|
||||
[ subject ]
|
||||
organizationName = PairDrop
|
||||
OU = CA
|
||||
commonName = pairdrop-CA
|
||||
|
||||
[ x509_ext ]
|
||||
subjectKeyIdentifier = hash
|
||||
authorityKeyIdentifier = keyid:always,issuer
|
||||
|
||||
# You only need digitalSignature below. *If* you don't allow
|
||||
# RSA Key transport (i.e., you use ephemeral cipher suites), then
|
||||
# omit keyEncipherment because that's key transport.
|
||||
|
||||
basicConstraints = critical, CA:TRUE, pathlen:0
|
||||
keyUsage = critical, digitalSignature, keyEncipherment, cRLSign, keyCertSign
|
||||
|
||||
29
dev/openssl/pairdropCert.cnf
Normal file
29
dev/openssl/pairdropCert.cnf
Normal file
@@ -0,0 +1,29 @@
|
||||
[ req ]
|
||||
default_bits = 2048
|
||||
default_md = sha256
|
||||
default_days = 1
|
||||
encrypt_key = no
|
||||
distinguished_name = subject
|
||||
req_extensions = req_ext
|
||||
string_mask = utf8only
|
||||
prompt = no
|
||||
|
||||
[ subject ]
|
||||
organizationName = PairDrop
|
||||
OU = Development
|
||||
|
||||
# Use a friendly name here because it's presented to the user. The server's DNS
|
||||
# names are placed in Subject Alternate Names. Plus, DNS names here is deprecated
|
||||
# by both IETF and CA/Browser Forums. If you place a DNS name here, then you
|
||||
# must include the DNS name in the SAN too (otherwise, Chrome and others that
|
||||
# strictly follow the CA/Browser Baseline Requirements will fail).
|
||||
|
||||
commonName = ${ENV::FQDN}
|
||||
|
||||
[ req_ext ]
|
||||
subjectKeyIdentifier = hash
|
||||
basicConstraints = CA:FALSE
|
||||
keyUsage = digitalSignature, keyEncipherment
|
||||
subjectAltName = DNS:${ENV::FQDN}
|
||||
nsComment = "OpenSSL Generated Certificate"
|
||||
extendedKeyUsage = serverAuth
|
||||
34
docker-compose-dev.yml
Normal file
34
docker-compose-dev.yml
Normal file
@@ -0,0 +1,34 @@
|
||||
version: "3"
|
||||
services:
|
||||
pairdrop:
|
||||
build: .
|
||||
container_name: pairdrop
|
||||
restart: unless-stopped
|
||||
environment:
|
||||
- PUID=1000 # UID to run the application as
|
||||
- PGID=1000 # GID to run the application as
|
||||
- WS_FALLBACK=false # Set to true to enable websocket fallback if the peer to peer WebRTC connection is not available to the client.
|
||||
- RATE_LIMIT=false # Set to true to limit clients to 1000 requests per 5 min.
|
||||
- RTC_CONFIG=false # Set to the path of a file that specifies the STUN/TURN servers.
|
||||
- DEBUG_MODE=false # Set to true to debug container and peer connections.
|
||||
- TZ=Etc/UTC # Time Zone
|
||||
ports:
|
||||
- "127.0.0.1:3000:3000" # Web UI. Change the port number before the last colon e.g. `127.0.0.1:9000:3000`
|
||||
nginx:
|
||||
build:
|
||||
context: dev/
|
||||
dockerfile: nginx-with-openssl.Dockerfile
|
||||
image: "nginx-with-openssl"
|
||||
volumes:
|
||||
- ./public:/usr/share/nginx/html
|
||||
- ./dev/certs:/etc/ssl/certs
|
||||
- ./dev/openssl:/mnt/openssl
|
||||
- ./dev/nginx/default.conf:/etc/nginx/conf.d/default.conf
|
||||
ports:
|
||||
- "8080:80"
|
||||
- "8443:443"
|
||||
environment:
|
||||
- FQDN=localhost
|
||||
entrypoint: /mnt/openssl/create.sh
|
||||
command: ["nginx", "-g", "daemon off;"]
|
||||
restart: unless-stopped
|
||||
@@ -652,68 +652,74 @@ To run PairDrop including its own coturn-server you need to punch holes in the f
|
||||
|
||||
<br>
|
||||
|
||||
### Firewall
|
||||
To run PairDrop including its own coturn-server you need to punch holes in the firewall. These ports must be opened additionally:
|
||||
- 3478 tcp/udp
|
||||
- 5349 tcp/udp
|
||||
- 10000:20000 tcp/udp
|
||||
|
||||
<br>
|
||||
|
||||
## Local Development
|
||||
|
||||
### Install
|
||||
|
||||
All files needed for developing are available on the branch `dev`.
|
||||
All files needed for developing are available in the folder `./dev`.
|
||||
|
||||
First, [Install docker with docker-compose.](https://docs.docker.com/compose/install/)
|
||||
For convenience, there is also a docker compose file for developing:
|
||||
|
||||
Then, clone the repository and run docker-compose:
|
||||
#### Developing with docker compose
|
||||
First, [Install docker with docker compose.](https://docs.docker.com/compose/install/)
|
||||
|
||||
Then, clone the repository and run docker compose:
|
||||
|
||||
```bash
|
||||
git clone https://github.com/schlagmichdoch/PairDrop.git && cd PairDrop
|
||||
```
|
||||
```bash
|
||||
git checkout dev
|
||||
```
|
||||
```bash
|
||||
docker compose -f docker-compose-dev.yml up -d
|
||||
docker compose -f docker-compose-dev.yml up --no-deps --build
|
||||
```
|
||||
|
||||
Now point your web browser to `http://localhost:8080`.
|
||||
|
||||
- To restart the containers, run `docker compose restart`.
|
||||
- To stop the containers, run `docker compose stop`.
|
||||
- To debug the Node.js server, run `docker logs pairdrop`.
|
||||
|
||||
- After changes to the code you have to rerun the `docker compose` command
|
||||
|
||||
<br>
|
||||
|
||||
### Testing PWA related features
|
||||
#### Testing PWA related features
|
||||
|
||||
PWAs requires the app to be served under a correctly set up and trusted TLS endpoint.
|
||||
|
||||
The NGINX container creates a CA certificate and a website certificate for you.
|
||||
To correctly set the common name of the certificate,
|
||||
you need to change the FQDN environment variable in `docker/fqdn.env`
|
||||
to the fully qualified domain name of your workstation.
|
||||
you need to change the FQDN environment variable in `docker-compose-dev.yml`
|
||||
to the fully qualified domain name of your workstation. (Default: localhost)
|
||||
|
||||
If you want to test PWA features, you need to trust the CA of the certificate for your local deployment. \
|
||||
For your convenience, you can download the crt file from `http://<Your FQDN>:8080/ca.crt`. \
|
||||
Install that certificate to the trust store of your operating system. \
|
||||
|
||||
- On Windows, make sure to install it to the `Trusted Root Certification Authorities` store.
|
||||
- On macOS, double-click the installed CA certificate in `Keychain Access`,
|
||||
##### Windows
|
||||
- Make sure to install it to the `Trusted Root Certification Authorities` store.
|
||||
|
||||
##### macOS
|
||||
- Double-click the installed CA certificate in `Keychain Access`,
|
||||
- expand `Trust`, and select `Always Trust` for SSL.
|
||||
- Firefox uses its own trust store. To install the CA,
|
||||
- point Firefox at `http://<Your FQDN>:8080/ca.crt`.
|
||||
|
||||
##### Firefox
|
||||
Firefox uses its own trust store. To install the CA:
|
||||
- point Firefox at `http://<Your FQDN>:8080/ca.crt` (Default: `http://localhost:8080/ca.crt`)
|
||||
- When prompted, select `Trust this CA to identify websites` and click _OK_.
|
||||
|
||||
Alternatively:
|
||||
1. Download `ca.crt` from `http://<Your FQDN>:8080/ca.crt` (Default: `http://localhost:8080/ca.crt`)
|
||||
2. Go to `about:preferences#privacy` scroll down to `Security` and `Certificates` and click `View Certificates`
|
||||
3. Import the downloaded certificate file (step 1)
|
||||
|
||||
##### Chrome
|
||||
- When using Chrome, you need to restart Chrome so it reloads the trust store (`chrome://restart`).
|
||||
- Additionally, after installing a new cert, you need to clear the Storage (DevTools → Application → Clear storage → Clear site data).
|
||||
|
||||
##### Google Chrome
|
||||
- To skip the installation of the certificate, you can also open `chrome://flags/#unsafely-treat-insecure-origin-as-secure`
|
||||
- The feature `Insecure origins treated as secure` must be enabled and the list must include your PairDrop test instance. E.g.: `http://127.0.0.1:3000,https://127.0.0.1:8443`
|
||||
|
||||
Please note that the certificates (CA and webserver cert) expire after a day.
|
||||
Also, whenever you restart the NGINX Docker container new certificates are created.
|
||||
|
||||
The site is served on `https://<Your FQDN>:8443`.
|
||||
The site is served on `https://<Your FQDN>:8443` (Default: `https://localhost:8443`).
|
||||
|
||||
[< Back](/README.md)
|
||||
|
||||
@@ -45,11 +45,11 @@ This pairdrop-cli version was released alongside v1.10.4
|
||||
#### Linux / Mac
|
||||
1. Download the latest _pairdrop-cli.zip_ from the [releases page](https://github.com/schlagmichdoch/PairDrop/releases)
|
||||
```shell
|
||||
wget "https://github.com/schlagmichdoch/PairDrop/releases/download/v1.10.8/pairdrop-cli.zip"
|
||||
wget "https://github.com/schlagmichdoch/PairDrop/releases/download/v1.10.9/pairdrop-cli.zip"
|
||||
```
|
||||
or
|
||||
```shell
|
||||
curl -LO "https://github.com/schlagmichdoch/PairDrop/releases/download/v1.10.8/pairdrop-cli.zip"
|
||||
curl -LO "https://github.com/schlagmichdoch/PairDrop/releases/download/v1.10.9/pairdrop-cli.zip"
|
||||
```
|
||||
2. Unzip the archive to a folder of your choice e.g. `/usr/share/pairdrop-cli/`
|
||||
```shell
|
||||
|
||||
544
package-lock.json
generated
544
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "pairdrop",
|
||||
"version": "1.10.8",
|
||||
"lockfileVersion": 2,
|
||||
"version": "1.10.9",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "pairdrop",
|
||||
"version": "1.10.8",
|
||||
"version": "1.10.9",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"express": "^4.18.2",
|
||||
@@ -245,9 +245,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/express-rate-limit": {
|
||||
"version": "7.1.5",
|
||||
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.1.5.tgz",
|
||||
"integrity": "sha512-/iVogxu7ueadrepw1bS0X0kaRC/U0afwiYRSLg68Ts+p4Dc85Q5QKsOnPS/QUjPMHvOJQtBDrZgvkOzf8ejUYw==",
|
||||
"version": "7.3.1",
|
||||
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.3.1.tgz",
|
||||
"integrity": "sha512-BbaryvkY4wEgDqLgD18/NSy2lDO2jTuT9Y8c1Mpx0X63Yz0sYd5zN6KPe7UvpuSVvV33T6RaE1o1IVZQjHMYgw==",
|
||||
"engines": {
|
||||
"node": ">= 16"
|
||||
},
|
||||
@@ -476,9 +476,12 @@
|
||||
}
|
||||
},
|
||||
"node_modules/object-inspect": {
|
||||
"version": "1.13.1",
|
||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
|
||||
"integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ==",
|
||||
"version": "1.13.2",
|
||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz",
|
||||
"integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==",
|
||||
"engines": {
|
||||
"node": ">= 0.4"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/ljharb"
|
||||
}
|
||||
@@ -688,9 +691,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ua-parser-js": {
|
||||
"version": "1.0.37",
|
||||
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.37.tgz",
|
||||
"integrity": "sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ==",
|
||||
"version": "1.0.38",
|
||||
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.38.tgz",
|
||||
"integrity": "sha512-Aq5ppTOfvrCMgAPneW1HfWj66Xi7XL+/mIy996R1/CLS/rcyJQm6QZdsKrUeivDFQ+Oc9Wyuwor8Ze8peEoUoQ==",
|
||||
"funding": [
|
||||
{
|
||||
"type": "opencollective",
|
||||
@@ -742,9 +745,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/ws": {
|
||||
"version": "8.16.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz",
|
||||
"integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==",
|
||||
"version": "8.17.1",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz",
|
||||
"integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==",
|
||||
"engines": {
|
||||
"node": ">=10.0.0"
|
||||
},
|
||||
@@ -761,516 +764,5 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"dependencies": {
|
||||
"accepts": {
|
||||
"version": "1.3.8",
|
||||
"resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
|
||||
"integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
|
||||
"requires": {
|
||||
"mime-types": "~2.1.34",
|
||||
"negotiator": "0.6.3"
|
||||
}
|
||||
},
|
||||
"array-flatten": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
|
||||
"integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg=="
|
||||
},
|
||||
"body-parser": {
|
||||
"version": "1.20.2",
|
||||
"resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.2.tgz",
|
||||
"integrity": "sha512-ml9pReCu3M61kGlqoTm2umSXTlRTuGTx0bfYj+uIUKKYycG5NtSbeetV3faSU6R7ajOPw0g/J1PvK4qNy7s5bA==",
|
||||
"requires": {
|
||||
"bytes": "3.1.2",
|
||||
"content-type": "~1.0.5",
|
||||
"debug": "2.6.9",
|
||||
"depd": "2.0.0",
|
||||
"destroy": "1.2.0",
|
||||
"http-errors": "2.0.0",
|
||||
"iconv-lite": "0.4.24",
|
||||
"on-finished": "2.4.1",
|
||||
"qs": "6.11.0",
|
||||
"raw-body": "2.5.2",
|
||||
"type-is": "~1.6.18",
|
||||
"unpipe": "1.0.0"
|
||||
}
|
||||
},
|
||||
"bytes": {
|
||||
"version": "3.1.2",
|
||||
"resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
|
||||
"integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg=="
|
||||
},
|
||||
"call-bind": {
|
||||
"version": "1.0.7",
|
||||
"resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
|
||||
"integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
|
||||
"requires": {
|
||||
"es-define-property": "^1.0.0",
|
||||
"es-errors": "^1.3.0",
|
||||
"function-bind": "^1.1.2",
|
||||
"get-intrinsic": "^1.2.4",
|
||||
"set-function-length": "^1.2.1"
|
||||
}
|
||||
},
|
||||
"content-disposition": {
|
||||
"version": "0.5.4",
|
||||
"resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
|
||||
"integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
|
||||
"requires": {
|
||||
"safe-buffer": "5.2.1"
|
||||
}
|
||||
},
|
||||
"content-type": {
|
||||
"version": "1.0.5",
|
||||
"resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
|
||||
"integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA=="
|
||||
},
|
||||
"cookie": {
|
||||
"version": "0.6.0",
|
||||
"resolved": "https://registry.npmjs.org/cookie/-/cookie-0.6.0.tgz",
|
||||
"integrity": "sha512-U71cyTamuh1CRNCfpGY6to28lxvNwPG4Guz/EVjgf3Jmzv0vlDp1atT9eS5dDjMYHucpHbWns6Lwf3BKz6svdw=="
|
||||
},
|
||||
"cookie-signature": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
|
||||
"integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ=="
|
||||
},
|
||||
"debug": {
|
||||
"version": "2.6.9",
|
||||
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
|
||||
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
|
||||
"requires": {
|
||||
"ms": "2.0.0"
|
||||
}
|
||||
},
|
||||
"define-data-property": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
|
||||
"integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
|
||||
"requires": {
|
||||
"es-define-property": "^1.0.0",
|
||||
"es-errors": "^1.3.0",
|
||||
"gopd": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"depd": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
|
||||
"integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw=="
|
||||
},
|
||||
"destroy": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
|
||||
"integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg=="
|
||||
},
|
||||
"ee-first": {
|
||||
"version": "1.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
|
||||
"integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow=="
|
||||
},
|
||||
"encodeurl": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
|
||||
"integrity": "sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w=="
|
||||
},
|
||||
"es-define-property": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
|
||||
"integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
|
||||
"requires": {
|
||||
"get-intrinsic": "^1.2.4"
|
||||
}
|
||||
},
|
||||
"es-errors": {
|
||||
"version": "1.3.0",
|
||||
"resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
|
||||
"integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw=="
|
||||
},
|
||||
"escape-html": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
|
||||
"integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow=="
|
||||
},
|
||||
"etag": {
|
||||
"version": "1.8.1",
|
||||
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
|
||||
"integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg=="
|
||||
},
|
||||
"express": {
|
||||
"version": "4.19.2",
|
||||
"resolved": "https://registry.npmjs.org/express/-/express-4.19.2.tgz",
|
||||
"integrity": "sha512-5T6nhjsT+EOMzuck8JjBHARTHfMht0POzlA60WV2pMD3gyXw2LZnZ+ueGdNxG+0calOJcWKbpFcuzLZ91YWq9Q==",
|
||||
"requires": {
|
||||
"accepts": "~1.3.8",
|
||||
"array-flatten": "1.1.1",
|
||||
"body-parser": "1.20.2",
|
||||
"content-disposition": "0.5.4",
|
||||
"content-type": "~1.0.4",
|
||||
"cookie": "0.6.0",
|
||||
"cookie-signature": "1.0.6",
|
||||
"debug": "2.6.9",
|
||||
"depd": "2.0.0",
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"etag": "~1.8.1",
|
||||
"finalhandler": "1.2.0",
|
||||
"fresh": "0.5.2",
|
||||
"http-errors": "2.0.0",
|
||||
"merge-descriptors": "1.0.1",
|
||||
"methods": "~1.1.2",
|
||||
"on-finished": "2.4.1",
|
||||
"parseurl": "~1.3.3",
|
||||
"path-to-regexp": "0.1.7",
|
||||
"proxy-addr": "~2.0.7",
|
||||
"qs": "6.11.0",
|
||||
"range-parser": "~1.2.1",
|
||||
"safe-buffer": "5.2.1",
|
||||
"send": "0.18.0",
|
||||
"serve-static": "1.15.0",
|
||||
"setprototypeof": "1.2.0",
|
||||
"statuses": "2.0.1",
|
||||
"type-is": "~1.6.18",
|
||||
"utils-merge": "1.0.1",
|
||||
"vary": "~1.1.2"
|
||||
}
|
||||
},
|
||||
"express-rate-limit": {
|
||||
"version": "7.1.5",
|
||||
"resolved": "https://registry.npmjs.org/express-rate-limit/-/express-rate-limit-7.1.5.tgz",
|
||||
"integrity": "sha512-/iVogxu7ueadrepw1bS0X0kaRC/U0afwiYRSLg68Ts+p4Dc85Q5QKsOnPS/QUjPMHvOJQtBDrZgvkOzf8ejUYw==",
|
||||
"requires": {}
|
||||
},
|
||||
"finalhandler": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.2.0.tgz",
|
||||
"integrity": "sha512-5uXcUVftlQMFnWC9qu/svkWv3GTd2PfUhK/3PLkYNAe7FbqJMt3515HaxE6eRL74GdsriiwujiawdaB1BpEISg==",
|
||||
"requires": {
|
||||
"debug": "2.6.9",
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"on-finished": "2.4.1",
|
||||
"parseurl": "~1.3.3",
|
||||
"statuses": "2.0.1",
|
||||
"unpipe": "~1.0.0"
|
||||
}
|
||||
},
|
||||
"forwarded": {
|
||||
"version": "0.2.0",
|
||||
"resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
|
||||
"integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow=="
|
||||
},
|
||||
"fresh": {
|
||||
"version": "0.5.2",
|
||||
"resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
|
||||
"integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q=="
|
||||
},
|
||||
"function-bind": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
|
||||
"integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA=="
|
||||
},
|
||||
"get-intrinsic": {
|
||||
"version": "1.2.4",
|
||||
"resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
|
||||
"integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
|
||||
"requires": {
|
||||
"es-errors": "^1.3.0",
|
||||
"function-bind": "^1.1.2",
|
||||
"has-proto": "^1.0.1",
|
||||
"has-symbols": "^1.0.3",
|
||||
"hasown": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"gopd": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
|
||||
"integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
|
||||
"requires": {
|
||||
"get-intrinsic": "^1.1.3"
|
||||
}
|
||||
},
|
||||
"has-property-descriptors": {
|
||||
"version": "1.0.2",
|
||||
"resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
|
||||
"integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
|
||||
"requires": {
|
||||
"es-define-property": "^1.0.0"
|
||||
}
|
||||
},
|
||||
"has-proto": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
|
||||
"integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q=="
|
||||
},
|
||||
"has-symbols": {
|
||||
"version": "1.0.3",
|
||||
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
|
||||
"integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A=="
|
||||
},
|
||||
"hasown": {
|
||||
"version": "2.0.2",
|
||||
"resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
|
||||
"integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
|
||||
"requires": {
|
||||
"function-bind": "^1.1.2"
|
||||
}
|
||||
},
|
||||
"http-errors": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz",
|
||||
"integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==",
|
||||
"requires": {
|
||||
"depd": "2.0.0",
|
||||
"inherits": "2.0.4",
|
||||
"setprototypeof": "1.2.0",
|
||||
"statuses": "2.0.1",
|
||||
"toidentifier": "1.0.1"
|
||||
}
|
||||
},
|
||||
"iconv-lite": {
|
||||
"version": "0.4.24",
|
||||
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
|
||||
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
|
||||
"requires": {
|
||||
"safer-buffer": ">= 2.1.2 < 3"
|
||||
}
|
||||
},
|
||||
"inherits": {
|
||||
"version": "2.0.4",
|
||||
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
|
||||
"integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
|
||||
},
|
||||
"ipaddr.js": {
|
||||
"version": "1.9.1",
|
||||
"resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
|
||||
"integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g=="
|
||||
},
|
||||
"media-typer": {
|
||||
"version": "0.3.0",
|
||||
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
|
||||
"integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ=="
|
||||
},
|
||||
"merge-descriptors": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
|
||||
"integrity": "sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w=="
|
||||
},
|
||||
"methods": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
|
||||
"integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w=="
|
||||
},
|
||||
"mime": {
|
||||
"version": "1.6.0",
|
||||
"resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
|
||||
"integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg=="
|
||||
},
|
||||
"mime-db": {
|
||||
"version": "1.52.0",
|
||||
"resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
|
||||
"integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg=="
|
||||
},
|
||||
"mime-types": {
|
||||
"version": "2.1.35",
|
||||
"resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
|
||||
"integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
|
||||
"requires": {
|
||||
"mime-db": "1.52.0"
|
||||
}
|
||||
},
|
||||
"ms": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
|
||||
"integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
|
||||
},
|
||||
"negotiator": {
|
||||
"version": "0.6.3",
|
||||
"resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
|
||||
"integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg=="
|
||||
},
|
||||
"object-inspect": {
|
||||
"version": "1.13.1",
|
||||
"resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.1.tgz",
|
||||
"integrity": "sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ=="
|
||||
},
|
||||
"on-finished": {
|
||||
"version": "2.4.1",
|
||||
"resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
|
||||
"integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
|
||||
"requires": {
|
||||
"ee-first": "1.1.1"
|
||||
}
|
||||
},
|
||||
"parseurl": {
|
||||
"version": "1.3.3",
|
||||
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
|
||||
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ=="
|
||||
},
|
||||
"path-to-regexp": {
|
||||
"version": "0.1.7",
|
||||
"resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
|
||||
"integrity": "sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ=="
|
||||
},
|
||||
"proxy-addr": {
|
||||
"version": "2.0.7",
|
||||
"resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
|
||||
"integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
|
||||
"requires": {
|
||||
"forwarded": "0.2.0",
|
||||
"ipaddr.js": "1.9.1"
|
||||
}
|
||||
},
|
||||
"qs": {
|
||||
"version": "6.11.0",
|
||||
"resolved": "https://registry.npmjs.org/qs/-/qs-6.11.0.tgz",
|
||||
"integrity": "sha512-MvjoMCJwEarSbUYk5O+nmoSzSutSsTwF85zcHPQ9OrlFoZOYIjaqBAJIqIXjptyD5vThxGq52Xu/MaJzRkIk4Q==",
|
||||
"requires": {
|
||||
"side-channel": "^1.0.4"
|
||||
}
|
||||
},
|
||||
"range-parser": {
|
||||
"version": "1.2.1",
|
||||
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
|
||||
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg=="
|
||||
},
|
||||
"raw-body": {
|
||||
"version": "2.5.2",
|
||||
"resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.2.tgz",
|
||||
"integrity": "sha512-8zGqypfENjCIqGhgXToC8aB2r7YrBX+AQAfIPs/Mlk+BtPTztOvTS01NRW/3Eh60J+a48lt8qsCzirQ6loCVfA==",
|
||||
"requires": {
|
||||
"bytes": "3.1.2",
|
||||
"http-errors": "2.0.0",
|
||||
"iconv-lite": "0.4.24",
|
||||
"unpipe": "1.0.0"
|
||||
}
|
||||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.2.1",
|
||||
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
|
||||
"integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ=="
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
|
||||
"integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
|
||||
},
|
||||
"send": {
|
||||
"version": "0.18.0",
|
||||
"resolved": "https://registry.npmjs.org/send/-/send-0.18.0.tgz",
|
||||
"integrity": "sha512-qqWzuOjSFOuqPjFe4NOsMLafToQQwBSOEpS+FwEt3A2V3vKubTquT3vmLTQpFgMXp8AlFWFuP1qKaJZOtPpVXg==",
|
||||
"requires": {
|
||||
"debug": "2.6.9",
|
||||
"depd": "2.0.0",
|
||||
"destroy": "1.2.0",
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"etag": "~1.8.1",
|
||||
"fresh": "0.5.2",
|
||||
"http-errors": "2.0.0",
|
||||
"mime": "1.6.0",
|
||||
"ms": "2.1.3",
|
||||
"on-finished": "2.4.1",
|
||||
"range-parser": "~1.2.1",
|
||||
"statuses": "2.0.1"
|
||||
},
|
||||
"dependencies": {
|
||||
"ms": {
|
||||
"version": "2.1.3",
|
||||
"resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
|
||||
"integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
|
||||
}
|
||||
}
|
||||
},
|
||||
"serve-static": {
|
||||
"version": "1.15.0",
|
||||
"resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.15.0.tgz",
|
||||
"integrity": "sha512-XGuRDNjXUijsUL0vl6nSD7cwURuzEgglbOaFuZM9g3kwDXOWVTck0jLzjPzGD+TazWbboZYu52/9/XPdUgne9g==",
|
||||
"requires": {
|
||||
"encodeurl": "~1.0.2",
|
||||
"escape-html": "~1.0.3",
|
||||
"parseurl": "~1.3.3",
|
||||
"send": "0.18.0"
|
||||
}
|
||||
},
|
||||
"set-function-length": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
|
||||
"integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
|
||||
"requires": {
|
||||
"define-data-property": "^1.1.4",
|
||||
"es-errors": "^1.3.0",
|
||||
"function-bind": "^1.1.2",
|
||||
"get-intrinsic": "^1.2.4",
|
||||
"gopd": "^1.0.1",
|
||||
"has-property-descriptors": "^1.0.2"
|
||||
}
|
||||
},
|
||||
"setprototypeof": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
|
||||
"integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw=="
|
||||
},
|
||||
"side-channel": {
|
||||
"version": "1.0.6",
|
||||
"resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
|
||||
"integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
|
||||
"requires": {
|
||||
"call-bind": "^1.0.7",
|
||||
"es-errors": "^1.3.0",
|
||||
"get-intrinsic": "^1.2.4",
|
||||
"object-inspect": "^1.13.1"
|
||||
}
|
||||
},
|
||||
"statuses": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.1.tgz",
|
||||
"integrity": "sha512-RwNA9Z/7PrK06rYLIzFMlaF+l73iwpzsqRIFgbMLbTcLD6cOao82TaWefPXQvB2fOC4AjuYSEndS7N/mTCbkdQ=="
|
||||
},
|
||||
"toidentifier": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
|
||||
"integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA=="
|
||||
},
|
||||
"type-is": {
|
||||
"version": "1.6.18",
|
||||
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
|
||||
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
|
||||
"requires": {
|
||||
"media-typer": "0.3.0",
|
||||
"mime-types": "~2.1.24"
|
||||
}
|
||||
},
|
||||
"ua-parser-js": {
|
||||
"version": "1.0.37",
|
||||
"resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-1.0.37.tgz",
|
||||
"integrity": "sha512-bhTyI94tZofjo+Dn8SN6Zv8nBDvyXTymAdM3LDI/0IboIUwTu1rEhW7v2TfiVsoYWgkQ4kOVqnI8APUFbIQIFQ=="
|
||||
},
|
||||
"unique-names-generator": {
|
||||
"version": "4.7.1",
|
||||
"resolved": "https://registry.npmjs.org/unique-names-generator/-/unique-names-generator-4.7.1.tgz",
|
||||
"integrity": "sha512-lMx9dX+KRmG8sq6gulYYpKWZc9RlGsgBR6aoO8Qsm3qvkSJ+3rAymr+TnV8EDMrIrwuFJ4kruzMWM/OpYzPoow=="
|
||||
},
|
||||
"unpipe": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
||||
"integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ=="
|
||||
},
|
||||
"utils-merge": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
|
||||
"integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA=="
|
||||
},
|
||||
"vary": {
|
||||
"version": "1.1.2",
|
||||
"resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
|
||||
"integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg=="
|
||||
},
|
||||
"ws": {
|
||||
"version": "8.16.0",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-8.16.0.tgz",
|
||||
"integrity": "sha512-HS0c//TP7Ina87TfiPUz1rQzMhHrl/SG2guqRcTOIUYD2q8uhUdNHZYJUaQ8aTGPzCh+c6oawMKW35nFl1dxyQ==",
|
||||
"requires": {}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "pairdrop",
|
||||
"version": "1.10.8",
|
||||
"version": "1.10.9",
|
||||
"type": "module",
|
||||
"description": "",
|
||||
"main": "server/index.js",
|
||||
|
||||
@@ -192,11 +192,21 @@
|
||||
<span> - </span>
|
||||
<span>(Arabic)</span>
|
||||
</button>
|
||||
<button class="btn fw wrap" value="be">
|
||||
<span>беларуская</span>
|
||||
<span> - </span>
|
||||
<span>(Belarusian)</span>
|
||||
</button>
|
||||
<button class="btn fw wrap" value="ca">
|
||||
<span>Català</span>
|
||||
<span> - </span>
|
||||
<span>(Catalan)</span>
|
||||
</button>
|
||||
<button class="btn fw wrap" value="da">
|
||||
<span>Dansk</span>
|
||||
<span> - </span>
|
||||
<span>(Danish)</span>
|
||||
</button>
|
||||
<button class="btn fw wrap" value="de">
|
||||
<span>Deutsch</span>
|
||||
<span> - </span>
|
||||
@@ -225,6 +235,11 @@
|
||||
<span> - </span>
|
||||
<span>(Italian)</span>
|
||||
</button>
|
||||
<button class="btn fw wrap" value="he">
|
||||
<span>עִבְרִית</span>
|
||||
<span> - </span>
|
||||
<span>(Hebrew)</span>
|
||||
</button>
|
||||
<button class="btn fw wrap" value="kn">
|
||||
<span>ಕನ್ನಡ</span>
|
||||
<span> - </span>
|
||||
@@ -462,7 +477,7 @@
|
||||
<div class="center file-preview"></div>
|
||||
<div class="row-reverse center btn-row wrap">
|
||||
<button id="share-btn" class="btn btn-rounded btn-grey" data-i18n-key="dialogs.share" data-i18n-attrs="text" hidden></button>
|
||||
<button id="download-btn" class="btn btn-rounded btn-grey" data-i18n-key="dialogs.download" data-i18n-attrs="text" autofocus disabled></button>
|
||||
<button id="download-btn" class="btn btn-rounded btn-grey" data-i18n-key="dialogs.download" data-i18n-attrs="text" autofocus disabled hidden></button>
|
||||
<button class="btn btn-rounded btn-grey" data-i18n-key="dialogs.close" data-i18n-attrs="text" close></button>
|
||||
</div>
|
||||
</x-paper>
|
||||
@@ -597,7 +612,7 @@
|
||||
</svg>
|
||||
<div class="title-wrapper" dir="ltr">
|
||||
<h1>PairDrop</h1>
|
||||
<div class="font-subheading">v1.10.8</div>
|
||||
<div class="font-subheading">v1.10.9</div>
|
||||
</div>
|
||||
<div class="font-subheading" data-i18n-key="about.claim" data-i18n-attrs="text"></div>
|
||||
<div class="row">
|
||||
@@ -759,7 +774,7 @@
|
||||
<script src="scripts/ui-main.js" defer></script>
|
||||
<script src="scripts/main.js" defer></script>
|
||||
<!-- Sounds -->
|
||||
<audio id="blop" autobuffer="true">
|
||||
<audio id="blop" preload="metadata" disableremoteplayback="true" x-webkit-airplay="deny" muted>
|
||||
<source src="sounds/blop.mp3" type="audio/mpeg">
|
||||
<source src="sounds/blop.ogg" type="audio/ogg">
|
||||
</audio>
|
||||
|
||||
@@ -48,7 +48,6 @@
|
||||
"pairing-cleared": "جميع الأجهزة غير مقترنة",
|
||||
"notifications-enabled": "تم تمكين الإشعارات",
|
||||
"online-requirement-pairing": "يجب أن تكون متصلاً بالإنترنت لإقران الأجهزة",
|
||||
"ios-memory-limit": "لا يمكن إرسال ملفات إلى iOS إلا بحجم يصل إلى 200 ميجابايت مرة واحدة",
|
||||
"online-requirement-public-room": "يجب أن تكون متصلاً بالإنترنت لإنشاء غرفة عامة",
|
||||
"copied-text-error": "فشلت الكتابة من الحافظة. انسخ يدويًا!",
|
||||
"download-successful": "تم تحميل {{descriptor}}",
|
||||
|
||||
184
public/lang/be.json
Normal file
184
public/lang/be.json
Normal file
@@ -0,0 +1,184 @@
|
||||
{
|
||||
"header": {
|
||||
"about_aria-label": "Адкрыйце Аб PairDrop",
|
||||
"about_title": "Аб PairDrop",
|
||||
"theme-auto_title": "Аўтаматычная адаптацыя тэмы да сістэмы",
|
||||
"theme-light_title": "Заўсёды выкарыстоўваць светлую тэму",
|
||||
"theme-dark_title": "Заўсёды выкарыстоўваць цёмную тэму",
|
||||
"notification_title": "Уключыць апавяшчэнні",
|
||||
"edit-paired-devices_title": "Рэдагаваць злучаныя прылады",
|
||||
"join-public-room_title": "Часова далучыцца да публічнага пакоя",
|
||||
"cancel-share-mode": "Адмяніць",
|
||||
"language-selector_title": "Задаць мову",
|
||||
"install_title": "Усталяваць PairDrop",
|
||||
"pair-device_title": "Злучыце свае прылады назаўжды",
|
||||
"edit-share-mode": "Рэдагаваць",
|
||||
"expand_title": "Разгарнуць радок кнопак"
|
||||
},
|
||||
"instructions": {
|
||||
"no-peers_data-drop-bg": "Адпусціце, каб выбраць атрымальніка",
|
||||
"no-peers-title": "Адкрыйце PairDrop на іншых прыладах, каб адправіць файлы",
|
||||
"x-instructions_data-drop-peer": "Адпусціце, каб адправіць вузлу",
|
||||
"x-instructions_data-drop-bg": "Адпусціце, каб выбраць атрымальніка",
|
||||
"x-instructions-share-mode_mobile": "Дакраніцеся, каб адправіць {{descriptor}}",
|
||||
"activate-share-mode-and-other-file": "і 1 іньшы файл",
|
||||
"activate-share-mode-and-other-files-plural": "і {{count}} іньшых файла(ў)",
|
||||
"activate-share-mode-shared-text": "агульны тэкст",
|
||||
"activate-share-mode-shared-files-plural": "{{count}} агульных файлаў",
|
||||
"webrtc-requirement": "Каб выкарыстоўваць гэты асобнік Pair Drop, WebRTC павінен быць уключаны!",
|
||||
"no-peers-subtitle": "Злучыце прылады або ўвайдзіце ў публічны пакой, каб вас маглі выявіць з іншых сетак",
|
||||
"x-instructions_mobile": "Дакраніцеся, каб адправіць файлы, або доўга трымайце, каб адправіць паведамленне",
|
||||
"x-instructions-share-mode_desktop": "Націсніце, каб адправіць {{descriptor}}",
|
||||
"x-instructions_desktop": "Націсніце, каб адправіць файлы, або націсніце правай кнопкай мышы, каб адправіць паведамленне",
|
||||
"activate-share-mode-base": "Адкрыйце PairDrop на іншых прыладах, каб адправіць",
|
||||
"activate-share-mode-shared-file": "агульны файл"
|
||||
},
|
||||
"footer": {
|
||||
"known-as": "Вы вядомыя як:",
|
||||
"display-name_data-placeholder": "Загрузка…",
|
||||
"discovery": "Вас могуць выявіць:",
|
||||
"on-this-network_title": "Вас можа знайсці кожны ў гэтай сетцы.",
|
||||
"paired-devices": "з дапамогай злучаных прылад",
|
||||
"public-room-devices_title": "Вас могуць выявіць прылады ў гэтай публічнай пакоі незалежна ад сеткі.",
|
||||
"traffic": "Рух",
|
||||
"display-name_title": "Зменіце назву сваёй прылады назаўжды",
|
||||
"on-this-network": "у гэтай сетцы",
|
||||
"paired-devices_title": "Злучаныя прылады заўсёды могуць вас выявіць незалежна ад сеткі.",
|
||||
"public-room-devices": "у пакоі {{roomId}}",
|
||||
"webrtc": ", калі WebRTC недаступны.",
|
||||
"routed": "накіроўваецца праз сервер"
|
||||
},
|
||||
"dialogs": {
|
||||
"hr-or": "АБО",
|
||||
"cancel": "Адмяніць",
|
||||
"pair": "Злучыць",
|
||||
"unpair": "Разлучыць",
|
||||
"paired-devices-wrapper_data-empty": "Няма злучаных прылад.",
|
||||
"auto-accept": "аўтаматычнае прыняцце",
|
||||
"close": "Закрыць",
|
||||
"join": "Далучыцца",
|
||||
"leave": "Пакінуць",
|
||||
"decline": "Адмовіць",
|
||||
"share": "Падзяліцца",
|
||||
"copy": "Капіяваць",
|
||||
"title-image": "Малюнак",
|
||||
"system-language": "Мова сістэмы",
|
||||
"public-room-qr-code_title": "Націсніце, каб скапіяваць спасылку на публічны пакой",
|
||||
"title-file": "Файл",
|
||||
"title-file-plural": "Файлы",
|
||||
"message_placeholder": "Тэкст",
|
||||
"language-selector-title": "Задаць мову",
|
||||
"send-message-title": "Адправіць паведамленне",
|
||||
"scan-qr-code": "або сканаваць QR-код.",
|
||||
"enter-room-id-from-another-device": "Увядзіце ID пакоя з іншай прылады, каб далучыцца да пакоя.",
|
||||
"edit-paired-devices-title": "Рэдагаваць злучаныя прылады",
|
||||
"auto-accept-instructions-1": "Актываваць",
|
||||
"auto-accept-instructions-2": ", каб аўтаматычна прымаць усе файлы, адпраўленыя з гэтай прылады.",
|
||||
"accept": "Прыняць",
|
||||
"download": "Спампаваць",
|
||||
"download-again": "Спампаваць яшчэ раз",
|
||||
"pair-devices-qr-code_title": "Націсніце, каб скапіраваць спасылку для спалучэння гэтай прылады",
|
||||
"approve": "сцвердзіць",
|
||||
"pair-devices-title": "Пастаяннае злучэнне прылад",
|
||||
"enter-key-from-another-device": "Увядзіце тут ключ з іншай прылады.",
|
||||
"temporary-public-room-title": "Часовы публічны пакой",
|
||||
"input-room-id-on-another-device": "Увядзіце гэты ID пакоя на іншай прыладзе",
|
||||
"paired-device-removed": "Злучаная прылада была выдалена.",
|
||||
"would-like-to-share": "хацеў бы падзяліцца",
|
||||
"send-message-to": "Каму:",
|
||||
"message_title": "Устаўце паведамленне для адпраўкі",
|
||||
"has-sent": "адправіў:",
|
||||
"base64-processing": "Апрацоўка…",
|
||||
"send": "Адправіць",
|
||||
"base64-title-text": "Падзяліцца тэкстам",
|
||||
"base64-title-files": "Падзяліцца файламі",
|
||||
"base64-tap-to-paste": "Дакраніцеся тут, каб падзяліцца {{type}}",
|
||||
"file-other-description-image": "і 1 іньшы малюнак",
|
||||
"file-other-description-image-plural": "і {{count}} іншых малюнкаў",
|
||||
"file-other-description-file-plural": "і {{count}} іншых файлаў",
|
||||
"title-image-plural": "Малюнкі",
|
||||
"share-text-subtitle": "Рэдагаваць паведамленне перад адпраўкай:",
|
||||
"share-text-title": "Падзяліцца тэкставым паведамленнем",
|
||||
"close-toast_title": "Закрыць апавяшчэнне",
|
||||
"receive-text-title": "Паведамленне атрымана",
|
||||
"input-key-on-this-device": "Увядзіце гэты ключ на іншай прыладзе",
|
||||
"base64-files": "файлы",
|
||||
"base64-text": "тэкст",
|
||||
"base64-paste-to-send": "Устаўце сюды буфер абмену, каб падзяліцца {{type}}",
|
||||
"file-other-description-file": "і 1 іньшы файл",
|
||||
"receive-title": "{{descriptor}} атрымана",
|
||||
"share-text-checkbox": "Заўсёды паказваць гэта дыялогавае акно пры абагульванні тэксту"
|
||||
},
|
||||
"about": {
|
||||
"buy-me-a-coffee_title": "Купіць мне кавы!",
|
||||
"mastodon_title": "Напішыце пра PairDrop на Mastodon",
|
||||
"tweet_title": "Твіт пра PairDrop",
|
||||
"github_title": "PairDrop на GitHub",
|
||||
"custom_title": "Сачыце за намі",
|
||||
"bluesky_title": "Сачыце за намі на BlueSky",
|
||||
"faq_title": "Часта задаюць пытанні",
|
||||
"close-about_aria-label": "Закрыць Аб PairDrop",
|
||||
"claim": "Самы просты спосаб перадачы файлаў паміж прыладамі",
|
||||
"privacypolicy_title": "Адкрыйце нашу палітыку прыватнасці"
|
||||
},
|
||||
"notifications": {
|
||||
"link-received": "Спасылка атрымана {{name}} - Націсніце, каб адкрыць",
|
||||
"message-received": "Паведамленне атрымана {{name}} - Націсніце, каб скапіяваць",
|
||||
"click-to-download": "Націсніце, каб спампаваць",
|
||||
"click-to-show": "Націсніце, каб паказаць",
|
||||
"copied-text-error": "Памылка запісу ў буфер абмену. Скапіруйце ўручную!",
|
||||
"online": "Вы зноў у сетцы",
|
||||
"online-requirement-public-room": "Вы павінны быць падлучаныя да сеткі, каб стварыць агульны пакой",
|
||||
"connecting": "Падключэнне…",
|
||||
"public-room-id-invalid": "Несапраўдны ID пакоя",
|
||||
"notifications-permissions-error": "Дазвол на апавяшчэнні быў заблакіраваны, бо карыстальнік некалькі разоў адхіляў запыт на дазвол. Гэта можна скінуць у меню \"Аб старонцы\", доступ да якой можна атрымаць, націснуўшы на значок замка побач з радком URL.",
|
||||
"request-title": "{{name}} хоча перадаць {{count}} {{descriptor}}",
|
||||
"copied-text": "Тэкст скапіраваны ў буфер абмену",
|
||||
"offline": "Вы па-за сеткай",
|
||||
"connected": "Падключана",
|
||||
"online-requirement-pairing": "Вы павінны быць падлучаныя да сеткі для спалучэння прылад",
|
||||
"pairing-key-invalidated": "Ключ {{key}} несапраўдны",
|
||||
"display-name-random-again": "Адлюстраванае імя зноў згенеравалася выпадковым чынам",
|
||||
"download-successful": "{{descriptor}} спампавана",
|
||||
"pairing-tabs-error": "Злучэнне дзвюх укладак вэб-браўзера немагчыма",
|
||||
"display-name-changed-permanently": "Адлюстроўванае імя было зменена назаўжды",
|
||||
"pairing-cleared": "Усе прылады раз'яднаны",
|
||||
"room-url-copied-to-clipboard": "Спасылка на публічны пакой скапіравана ў буфер абмену",
|
||||
"public-room-left": "Пакінуць публічны пакой {{publicRoomId}}",
|
||||
"text-content-incorrect": "Змест тэксту няправільны",
|
||||
"clipboard-content-incorrect": "Змест буфера абмену няправільны",
|
||||
"notifications-enabled": "Апавяшчэнні ўключаны",
|
||||
"files-incorrect": "Няправільныя файлы",
|
||||
"file-transfer-completed": "Перадача файла завершана",
|
||||
"selected-peer-left": "Выбраны вузел выйшаў",
|
||||
"copied-to-clipboard": "Скапіравана ў буфер абмену",
|
||||
"pair-url-copied-to-clipboard": "Спасылка для злучэння гэтай прылады скапіравана ў буфер абмену",
|
||||
"pairing-success": "Злучаныя прылады",
|
||||
"copied-to-clipboard-error": "Капіраванне немагчымае. Скапіруйце ўручную.",
|
||||
"file-content-incorrect": "Змест файла няправільны",
|
||||
"pairing-not-persistent": "Злучаныя прылады не з'яўляюцца пастаяннымі",
|
||||
"pairing-key-invalid": "Несапраўдны ключ",
|
||||
"display-name-changed-temporarily": "Адлюстраванае імя зменена толькі для гэтага сеансу",
|
||||
"ios-memory-limit": "Адначасовая адпраўка файлаў на iOS магчымая толькі да 200 МБ",
|
||||
"message-transfer-completed": "Перадача паведамлення завершана",
|
||||
"unfinished-transfers-warning": "Ёсць незавершаныя перадачы. Вы ўпэўнены, што хочаце закрыць PairDrop?",
|
||||
"rate-limit-join-key": "Ліміт хуткасці дасягнуты. Пачакайце 10 секунд і паўтарыце спробу."
|
||||
},
|
||||
"peer-ui": {
|
||||
"preparing": "Падрыхтоўка…",
|
||||
"waiting": "Чаканне…",
|
||||
"transferring": "Перадача…",
|
||||
"processing": "Апрацоўка…",
|
||||
"click-to-send-share-mode": "Націсніце, каб адправіць {{descriptor}}",
|
||||
"connection-hash": "Каб праверыць бяспеку скразнога шыфравання, параўнайце гэты нумар бяспекі на абедзвюх прыладах",
|
||||
"click-to-send": "Націсніце, каб адправіць файлы, або націсніце правай кнопкай мышы, каб адправіць паведамленне"
|
||||
},
|
||||
"document-titles": {
|
||||
"file-received": "Файл атрыманы",
|
||||
"image-transfer-requested": "Запытана перадача малюнкаў",
|
||||
"message-received": "Паведамленне атрымана",
|
||||
"message-received-plural": "Атрымана {{count}} паведамленняў",
|
||||
"file-received-plural": "Атрымана {{count}} файлаў",
|
||||
"file-transfer-requested": "Запытана перадача файла"
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,8 @@
|
||||
"cancel-share-mode": "Cancel·lar",
|
||||
"about_title": "Sobre PairDrop",
|
||||
"about_aria-label": "Obre Sobre PairDrop",
|
||||
"theme-light_title": "Utilitza sempre el mode clar"
|
||||
"theme-light_title": "Utilitza sempre el mode clar",
|
||||
"expand_title": "Expandeix la fila de botons de la capçalera"
|
||||
},
|
||||
"dialogs": {
|
||||
"message_placeholder": "Text",
|
||||
@@ -144,7 +145,6 @@
|
||||
"pairing-cleared": "Tots els dispositius desvinculats",
|
||||
"notifications-enabled": "Notificacions habilitades",
|
||||
"online-requirement-pairing": "Has d'estar en línia per vincular dispositius",
|
||||
"ios-memory-limit": "Tan sols és possible enviar fitxers de fins a 200 MB a iOS",
|
||||
"online-requirement-public-room": "Cal que estiguis en línia per poder crear una sala pública",
|
||||
"room-url-copied-to-clipboard": "Enllaç a la sala pública copiat al porta-retalls",
|
||||
"copied-text-error": "L'escriptura al porta-retalls ha fallat. Copiar manualment!",
|
||||
@@ -166,7 +166,11 @@
|
||||
"close-about_aria-label": "Tanca Sobre PairDrop",
|
||||
"buy-me-a-coffee_title": "Convida'm a un cafè!",
|
||||
"github_title": "PairDrop a GitHub",
|
||||
"faq_title": "Preguntes freqüents"
|
||||
"faq_title": "Preguntes freqüents",
|
||||
"mastodon_title": "Escriu sobre PairDrop a Mastodon",
|
||||
"bluesky_title": "Segueix-nos a BlueSky",
|
||||
"custom_title": "Segueix-nos",
|
||||
"privacypolicy_title": "Obre la nostra política de privacitat"
|
||||
},
|
||||
"document-titles": {
|
||||
"file-transfer-requested": "Transferència de Fitxers Sol·licitada",
|
||||
|
||||
9
public/lang/cs.json
Normal file
9
public/lang/cs.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"header": {
|
||||
"about_aria-label": "Otevřít o PairDrop",
|
||||
"about_title": "O službě PairDrop",
|
||||
"language-selector_title": "Nastavit jazyk",
|
||||
"theme-auto_title": "Automatické přizpůsobení tématu systému",
|
||||
"pair-device_title": "Spárovat zařízení permanentně"
|
||||
}
|
||||
}
|
||||
184
public/lang/da.json
Normal file
184
public/lang/da.json
Normal file
@@ -0,0 +1,184 @@
|
||||
{
|
||||
"notifications": {
|
||||
"public-room-left": "Forlod det offentlige rum {{publicRoomId}}",
|
||||
"room-url-copied-to-clipboard": "Link til offentligt rum kopieret til udklipsholder",
|
||||
"notifications-enabled": "Notifikationer aktiveret",
|
||||
"notifications-permissions-error": "Notifikationstilladelsen er blevet blokeret, da brugeren har afvist tilladelsesprompten flere gange. Dette kan nulstilles i sideoplysninger, som du kan få adgang til ved at klikke på låseikonet ved siden af URL-linjen.",
|
||||
"copied-text-error": "Skrivning til udklipsholder mislykkedes. Kopier manuelt!",
|
||||
"ios-memory-limit": "Det er kun muligt at sende filer til iOS op til 200 MB på én gang",
|
||||
"display-name-random-again": "Vist navn genereres tilfældigt igen",
|
||||
"display-name-changed-permanently": "Det viste navn blec ændret permanent",
|
||||
"display-name-changed-temporarily": "Vist navn blev kun ændret for denne session",
|
||||
"download-successful": "{{descriptor}} hentet",
|
||||
"pairing-tabs-error": "Det er umuligt at parre to webbrowserfaner",
|
||||
"pairing-success": "Enheder parret",
|
||||
"pairing-not-persistent": "Parrede enheder er ikke vedvarende",
|
||||
"pairing-key-invalid": "Ugyldig nøgle",
|
||||
"pairing-key-invalidated": "Nøglen {{key}} er ugyldig",
|
||||
"pairing-cleared": "Alle enheder er frakoblet",
|
||||
"public-room-id-invalid": "Ugyldigt rum-id",
|
||||
"copied-to-clipboard": "Kopieret til udklipsholder",
|
||||
"pair-url-copied-to-clipboard": "Link til at parre denne enhed kopieret til udklipsholder",
|
||||
"copied-to-clipboard-error": "Kopiering ikke mulig. Kopier manuelt.",
|
||||
"text-content-incorrect": "Tekstindholdet er forkert",
|
||||
"file-content-incorrect": "Filens indhold er forkert",
|
||||
"clipboard-content-incorrect": "Udklipsholderens indhold er forkert",
|
||||
"link-received": "Link modtaget af {{name}} - Klik for at åbne",
|
||||
"message-received": "Besked modtaget af {{name}} - Klik for at kopiere",
|
||||
"click-to-download": "Klik for at hente",
|
||||
"request-title": "{{name}} vil gerne overføre {{count}} {{descriptor}}",
|
||||
"click-to-show": "Klik for at vise",
|
||||
"copied-text": "Kopieret tekst til udklipsholder",
|
||||
"offline": "Du er offline",
|
||||
"online": "Du er online igen",
|
||||
"connected": "Forbundet",
|
||||
"online-requirement-pairing": "Du skal være online for at parre enheder",
|
||||
"online-requirement-public-room": "Du skal være online for at oprette et offentligt rum",
|
||||
"connecting": "Forbinder…",
|
||||
"files-incorrect": "Filerne er forkerte",
|
||||
"file-transfer-completed": "Filoverførsel gennemført",
|
||||
"message-transfer-completed": "Beskedoverførsel gennemført",
|
||||
"unfinished-transfers-warning": "Der er uafsluttede overførsler. Er du sikker på, at du vil lukke PairDrop?",
|
||||
"rate-limit-join-key": "Satsgrænsen er nået. Vent 10 sekunder, og prøv igen.",
|
||||
"selected-peer-left": "Valgt peer forlod"
|
||||
},
|
||||
"dialogs": {
|
||||
"message_placeholder": "Tekst",
|
||||
"base64-files": "filer",
|
||||
"file-other-description-image": "og 1 andet billede",
|
||||
"file-other-description-file": "og 1 anden fil",
|
||||
"download-again": "Hent igen",
|
||||
"system-language": "Systemsprog",
|
||||
"pair-devices-qr-code_title": "Klik for at kopiere linket for at parre denne enhed",
|
||||
"enter-key-from-another-device": "Indtast nøgle fra en anden enhed her.",
|
||||
"temporary-public-room-title": "Midlertidigt offentligt rum",
|
||||
"edit-paired-devices-title": "Rediger parrede enheder",
|
||||
"auto-accept-instructions-2": "for automatisk at acceptere alle filer sendt fra den pågældende enhed.",
|
||||
"pair-devices-title": "Par enheder permanent",
|
||||
"input-key-on-this-device": "Indtast denne nøgle på en anden enhed",
|
||||
"scan-qr-code": "eller scan QR-koden.",
|
||||
"input-room-id-on-another-device": "Indtast dette rum-id på en anden enhed",
|
||||
"enter-room-id-from-another-device": "Indtast rum-id fra en anden enhed for at deltage i rummet.",
|
||||
"hr-or": "ELLER",
|
||||
"pair": "Par",
|
||||
"cancel": "Annuller",
|
||||
"unpair": "Fjern parring",
|
||||
"paired-device-removed": "Parret enhed er blevet fjernet.",
|
||||
"paired-devices-wrapper_data-empty": "Ingen parrede enheder.",
|
||||
"auto-accept-instructions-1": "Aktiver",
|
||||
"auto-accept": "auto-accepter",
|
||||
"close": "Luk",
|
||||
"join": "Forbinde",
|
||||
"leave": "Forlad",
|
||||
"would-like-to-share": "gerne vil dele",
|
||||
"accept": "Accepter",
|
||||
"decline": "Nægt",
|
||||
"has-sent": "har sendt:",
|
||||
"share": "Del",
|
||||
"download": "Hent",
|
||||
"send-message-title": "Send besked",
|
||||
"send-message-to": "Til:",
|
||||
"message_title": "Indsæt besked for at sende",
|
||||
"send": "Send",
|
||||
"receive-text-title": "Besked modtaget",
|
||||
"copy": "Kopier",
|
||||
"base64-title-files": "Del filer",
|
||||
"base64-title-text": "Del tekst",
|
||||
"base64-processing": "Behandler…",
|
||||
"base64-tap-to-paste": "Tryk her for at dele {{type}}",
|
||||
"base64-paste-to-send": "Indsæt udklipsholder her for at dele {{type}}",
|
||||
"base64-text": "tekst",
|
||||
"file-other-description-image-plural": "og {{count}} andre billeder",
|
||||
"file-other-description-file-plural": "og {{count}} andre filer",
|
||||
"title-image": "Billede",
|
||||
"title-file": "Fil",
|
||||
"title-image-plural": "Billeder",
|
||||
"title-file-plural": "Filer",
|
||||
"receive-title": "{{descriptor}} Modtaget",
|
||||
"language-selector-title": "Indstil sprog",
|
||||
"public-room-qr-code_title": "Klik for at kopiere linket til det offentlige rum",
|
||||
"approve": "godkend",
|
||||
"share-text-title": "Del tekstbesked",
|
||||
"share-text-subtitle": "Rediger besked, før du sender:",
|
||||
"share-text-checkbox": "Vis altid denne dialogboks, når du deler tekst",
|
||||
"close-toast_title": "Luk besked"
|
||||
},
|
||||
"about": {
|
||||
"claim": "Den nemmeste måde at overføre filer på tværs af enheder",
|
||||
"faq_title": "Ofte stillede spørgsmål",
|
||||
"close-about_aria-label": "Luk Om PairDrop",
|
||||
"github_title": "PairDrop på GitHub",
|
||||
"buy-me-a-coffee_title": "Køb mig en kop kaffe!",
|
||||
"tweet_title": "Tweet om PairDrop",
|
||||
"mastodon_title": "Skriv om PairDrop på Mastodon",
|
||||
"bluesky_title": "Følg os på BlueSky",
|
||||
"custom_title": "Følg os",
|
||||
"privacypolicy_title": "Åbn vores privatlivspolitik"
|
||||
},
|
||||
"header": {
|
||||
"language-selector_title": "Indstil sprog",
|
||||
"about_aria-label": "Åbn Om PairDrop",
|
||||
"theme-auto_title": "Tilpas temaet til systemet automatisk",
|
||||
"theme-light_title": "Brug altid lyst tema",
|
||||
"theme-dark_title": "Brug altid mørkt tema",
|
||||
"notification_title": "Aktiver notifikationer",
|
||||
"install_title": "Installer PairDrop",
|
||||
"pair-device_title": "Par dine enheder permanent",
|
||||
"edit-paired-devices_title": "Rediger parrede enheder",
|
||||
"join-public-room_title": "Deltag midlertidigt i det offentlige rum",
|
||||
"cancel-share-mode": "Annuller",
|
||||
"edit-share-mode": "Redigere",
|
||||
"expand_title": "Udvid overskriftsknaprækken",
|
||||
"about_title": "Om PairDrop"
|
||||
},
|
||||
"instructions": {
|
||||
"no-peers-subtitle": "Par enheder, eller gå ind i et offentligt rum for at være synlig på andre netværk",
|
||||
"x-instructions_desktop": "Klik for at sende filer eller højreklik for at sende en besked",
|
||||
"activate-share-mode-base": "Åbn PairDrop på andre enheder for at sende",
|
||||
"no-peers_data-drop-bg": "Slip for at vælge modtager",
|
||||
"no-peers-title": "Åbn PairDrop på andre enheder for at sende filer",
|
||||
"x-instructions_mobile": "Tryk for at sende filer, eller tryk længe for at sende en besked",
|
||||
"x-instructions_data-drop-peer": "Slip for at sende til peer",
|
||||
"x-instructions_data-drop-bg": "Slip for at vælge modtager",
|
||||
"x-instructions-share-mode_desktop": "Klik for at sende {{descriptor}}",
|
||||
"x-instructions-share-mode_mobile": "Tryk for at sende {{descriptor}}",
|
||||
"activate-share-mode-and-other-file": "og 1 anden fil",
|
||||
"activate-share-mode-and-other-files-plural": "og {{count}} andre filer",
|
||||
"activate-share-mode-shared-text": "delt tekst",
|
||||
"activate-share-mode-shared-file": "delt fil",
|
||||
"activate-share-mode-shared-files-plural": "{{count}} delte filer",
|
||||
"webrtc-requirement": "For at bruge denne PairDrop-instans skal WebRTC være aktiveret!"
|
||||
},
|
||||
"footer": {
|
||||
"on-this-network_title": "Du kan blive opdaget af alle på dette netværk.",
|
||||
"public-room-devices_title": "Du kan blive opdaget af enheder i dette offentlige rum uafhængigt af netværket.",
|
||||
"known-as": "Du er kendt som:",
|
||||
"display-name_data-placeholder": "Indlæser…",
|
||||
"display-name_title": "Rediger dit enhedsnavn permanent",
|
||||
"discovery": "Du kan blive opdaget:",
|
||||
"on-this-network": "på dette netværk",
|
||||
"paired-devices": "af parrede enheder",
|
||||
"paired-devices_title": "Du kan til enhver tid blive opdaget af parrede enheder uafhængigt af netværket.",
|
||||
"public-room-devices": "i rum {{roomId}}",
|
||||
"traffic": "Trafikken er",
|
||||
"routed": "dirigeret gennem serveren",
|
||||
"webrtc": "hvis WebRTC ikke er tilgængelig."
|
||||
},
|
||||
"document-titles": {
|
||||
"file-received": "Fil modtaget",
|
||||
"file-received-plural": "{{count}} Filer modtaget",
|
||||
"file-transfer-requested": "Filoverførsel anmodet",
|
||||
"image-transfer-requested": "Billedoverførsel anmodet",
|
||||
"message-received": "Besked modtaget",
|
||||
"message-received-plural": "{{count}} meddelelser modtaget"
|
||||
},
|
||||
"peer-ui": {
|
||||
"click-to-send-share-mode": "Klik for at sende {{descriptor}}",
|
||||
"click-to-send": "Klik for at sende filer eller højreklik for at sende en besked",
|
||||
"connection-hash": "For at kontrollere sikkerheden for end-to-end-kryptering skal du sammenligne dette sikkerhedsnummer på begge enheder",
|
||||
"preparing": "Forbereder…",
|
||||
"waiting": "Venter…",
|
||||
"processing": "Behandler…",
|
||||
"transferring": "Overfører…"
|
||||
}
|
||||
}
|
||||
@@ -138,7 +138,6 @@
|
||||
"message-transfer-completed": "Nachricht übertragen",
|
||||
"rate-limit-join-key": "Rate Limit erreicht. Warte 10 Sekunden und versuche es erneut.",
|
||||
"selected-peer-left": "Ausgewählter Peer ist gegangen",
|
||||
"ios-memory-limit": "Für Übertragungen an iOS Geräte beträgt die maximale Dateigröße 200 MB",
|
||||
"public-room-left": "Öffentlichen Raum {{publicRoomId}} verlassen",
|
||||
"copied-to-clipboard-error": "Konnte nicht kopieren. Kopiere manuell.",
|
||||
"public-room-id-invalid": "Ungültige Raum-ID",
|
||||
|
||||
@@ -158,11 +158,13 @@
|
||||
"connecting": "Connecting…",
|
||||
"files-incorrect": "Files are incorrect",
|
||||
"file-transfer-completed": "File transfer completed",
|
||||
"ios-memory-limit": "Sending files to iOS is only possible up to 200 MB at once",
|
||||
"message-transfer-completed": "Message transfer completed",
|
||||
"unfinished-transfers-warning": "There are unfinished transfers. Are you sure you want to close PairDrop?",
|
||||
"rate-limit-join-key": "Rate limit reached. Wait 10 seconds and try again.",
|
||||
"selected-peer-left": "Selected peer left"
|
||||
"selected-peer-left": "Selected peer left",
|
||||
"error-sharing-size": "Files too big to be shared. They can be downloaded instead.",
|
||||
"error-sharing-default": "Error while sharing. It can be downloaded instead.",
|
||||
"ram-exceed-ios": "One of the files is bigger than 250 MB and will crash the page on iOS. Use https and do not use private tabs on the iOS device to prevent this."
|
||||
},
|
||||
"document-titles": {
|
||||
"file-received": "File Received",
|
||||
@@ -176,9 +178,14 @@
|
||||
"click-to-send-share-mode": "Click to send {{descriptor}}",
|
||||
"click-to-send": "Click to send files or right click to send a message",
|
||||
"connection-hash": "To verify the security of the end-to-end encryption, compare this security number on both devices",
|
||||
"connecting": "Connecting…",
|
||||
"preparing": "Preparing…",
|
||||
"waiting": "Waiting…",
|
||||
"processing": "Processing…",
|
||||
"transferring": "Transferring…"
|
||||
"transferring": "Sending…",
|
||||
"receiving": "Receiving…",
|
||||
"transfer-complete": "Sent",
|
||||
"receive-complete": "Received",
|
||||
"error": "Error"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,6 @@
|
||||
"pairing-cleared": "Todos los dispositivos han sido desemparejados",
|
||||
"notifications-enabled": "Notificaciones habilitadas",
|
||||
"online-requirement-pairing": "Debes estar en línea para emparejar dispositivos",
|
||||
"ios-memory-limit": "Enviar archivos a iOS sólo admite hasta 200 MB a la vez",
|
||||
"online-requirement-public-room": "Debes estar en línea para crear una sala pública",
|
||||
"copied-text-error": "Error al escribir en el portapapeles. ¡Cópielo manualmente!",
|
||||
"download-successful": "{{descriptor}} descargado",
|
||||
|
||||
@@ -82,7 +82,7 @@
|
||||
"copy": "Copier",
|
||||
"base64-processing": "Traitement…",
|
||||
"base64-tap-to-paste": "Appuyez ici pour partager {{type}}",
|
||||
"base64-paste-to-send": "Coller ici pour partager {{type}}",
|
||||
"base64-paste-to-send": "Coller le presse-papiers ici pour partager {{type}}",
|
||||
"base64-text": "texte",
|
||||
"base64-files": "fichiers",
|
||||
"file-other-description-image": "et 1 autre image",
|
||||
@@ -119,7 +119,8 @@
|
||||
"faq_title": "Questions fréquemment posées",
|
||||
"bluesky_title": "Suis-nous sur BlueSky",
|
||||
"custom_title": "Suis-nous",
|
||||
"privacypolicy_title": "Ouvert sur notre politique de confidentialité"
|
||||
"privacypolicy_title": "Ouvert sur notre politique de confidentialité",
|
||||
"mastodon_title": "Écrire à propos de PairDrop sur Mastodon"
|
||||
},
|
||||
"notifications": {
|
||||
"display-name-changed-permanently": "Le nom d'affichage est modifié de manière permanente",
|
||||
@@ -155,7 +156,6 @@
|
||||
"connecting": "Connexion…",
|
||||
"files-incorrect": "Les fichiers sont incorrects",
|
||||
"file-transfer-completed": "Transfert de fichier terminé",
|
||||
"ios-memory-limit": "L'envoi de fichiers vers iOS n'est possible que jusqu'à 200 Mo à la fois",
|
||||
"message-transfer-completed": "Transfert de message terminé",
|
||||
"unfinished-transfers-warning": "Il y a des transferts inachevés. Êtes-vous sûr de vouloir fermer PairDrop ?",
|
||||
"rate-limit-join-key": "Limite de débit atteinte. Attendez 10 secondes et réessayez.",
|
||||
|
||||
@@ -1 +1,184 @@
|
||||
{}
|
||||
{
|
||||
"header": {
|
||||
"about_title": "אודות PairDrop",
|
||||
"theme-light_title": "השתמש תמיד במצב בהיר",
|
||||
"install_title": "התקן את PairDrop",
|
||||
"edit-share-mode": "עריכה",
|
||||
"expand_title": "הרחב את שורת כפתור הכותרת",
|
||||
"language-selector_title": "שינוי השפה",
|
||||
"about_aria-label": "פתח אודות PairDrop",
|
||||
"theme-auto_title": "התאם את הרקע למערכת באופן אוטומטי",
|
||||
"theme-dark_title": "השתמש תמיד במצב כהה",
|
||||
"notification_title": "הפעל התראות",
|
||||
"pair-device_title": "התאם את המכשירים שלך לתמיד",
|
||||
"edit-paired-devices_title": "עריכת מכשירים מתואמים",
|
||||
"join-public-room_title": "הצטרף לחדר ציבורי באופן זמני",
|
||||
"cancel-share-mode": "ביטול"
|
||||
},
|
||||
"instructions": {
|
||||
"no-peers-subtitle": "תאם מכשירים או היכנס לחדר ציבורי כדי להיות ניתן לגילוי ברשתות אחרות",
|
||||
"x-instructions_data-drop-bg": "שחרר כדי לבחור נמען",
|
||||
"activate-share-mode-and-other-file": "וקובץ 1 אחר",
|
||||
"activate-share-mode-base": "פתח את PairDrop על מכשירים אחרים כדי לשלוח",
|
||||
"activate-share-mode-shared-file": "קובץ משותף",
|
||||
"activate-share-mode-shared-files-plural": "{{count}} קבצים משותפים",
|
||||
"webrtc-requirement": "כדי להשתמש בPairdrop, WebRTC מוכרח להיות מופעל!",
|
||||
"no-peers_data-drop-bg": "שחרר כדי לבחור את הנמען",
|
||||
"no-peers-title": "פתח את PairDrop במכשירים אחרים כדי לשלוח קבצים",
|
||||
"x-instructions_desktop": "לחץ כדי לשלוח קבצים או בצע לחיצה ימנית כדי לשלוח הודעה",
|
||||
"x-instructions_mobile": "גע כדי לשלוח קבצים או בצע נגיעה ארוכה כדי לשלוח הודעה",
|
||||
"x-instructions_data-drop-peer": "שחרר כדי לשלוח למכשיר",
|
||||
"x-instructions-share-mode_desktop": "לחץ כדי לשלוח {{descriptor}}",
|
||||
"x-instructions-share-mode_mobile": "גע כדי לשלוח {{descriptor}}",
|
||||
"activate-share-mode-and-other-files-plural": "ו{{count}} קבצים אחרים",
|
||||
"activate-share-mode-shared-text": "טקסט משותף"
|
||||
},
|
||||
"footer": {
|
||||
"paired-devices_title": "הנך ניתן לגילוי על ידי מכשירים מתואמים בכל עת ללא תלות ברשת.",
|
||||
"on-this-network": "ברשת הזו",
|
||||
"on-this-network_title": "אתה ניתן לגילוי על ידי כולם ברשת הזו.",
|
||||
"display-name_data-placeholder": "טוען…",
|
||||
"display-name_title": "שנה את שם המכשיר שלך לתמיד",
|
||||
"known-as": "הנך ידוע כ:",
|
||||
"discovery": "הנך ניתן לגילוי:",
|
||||
"paired-devices": "על ידי מכשירים מתואמים",
|
||||
"public-room-devices": "בחדר {{roomId}}",
|
||||
"public-room-devices_title": "הנך ניתן לגילוי על ידי מכשירים בחדר הציבורי הזה ללא תלות ברשת.",
|
||||
"traffic": "הנתונים",
|
||||
"routed": "מנותבים דרך השרת",
|
||||
"webrtc": "אם WebRTC אינו זמין."
|
||||
},
|
||||
"dialogs": {
|
||||
"input-room-id-on-another-device": "הזן את מזהה החדר הזה במכשיר אחר",
|
||||
"edit-paired-devices-title": "ערוך מכשירים מתואמים",
|
||||
"paired-device-removed": "המכשיר המתואם הוסר.",
|
||||
"download-again": "הורד שוב",
|
||||
"public-room-qr-code_title": "לחץ כדי להעתיק את הקישור לחדר הציבורי",
|
||||
"auto-accept-instructions-2": "כדי לקבל באופן אוטומטי את כל הקבצים שנשלחים ממכשיר זה.",
|
||||
"title-file-plural": "קבצים",
|
||||
"receive-title": "{{descriptor}} התקבל",
|
||||
"download": "הורד",
|
||||
"send-message-title": "שלח הודעה",
|
||||
"message_placeholder": "טקסט",
|
||||
"receive-text-title": "ההודעה התקבלה",
|
||||
"base64-text": "טקסט",
|
||||
"share-text-checkbox": "תמיד הצג את חלונית זו כאשר טקסט משותף",
|
||||
"system-language": "שפת המערכת",
|
||||
"title-file": "קובץ",
|
||||
"pair-devices-title": "תאם מכשירים לתמיד",
|
||||
"input-key-on-this-device": "הזן את הקוד הזה במכשיר אחר",
|
||||
"scan-qr-code": "או סרוק את הברקוד.",
|
||||
"enter-key-from-another-device": "הזן את הקוד ממכשיר אחר כאן.",
|
||||
"temporary-public-room-title": "חדר ציבורי זמני",
|
||||
"enter-room-id-from-another-device": "הזן מזהה חדר ממכשיר אחר כדי להצטרף לחדר.",
|
||||
"hr-or": "או",
|
||||
"pair": "תאם",
|
||||
"cancel": "ביטול",
|
||||
"unpair": "בטל התאמה",
|
||||
"paired-devices-wrapper_data-empty": "אין מכשירים מתואמים.",
|
||||
"auto-accept-instructions-1": "הפעל",
|
||||
"auto-accept": "קבלה אוטומטית",
|
||||
"close": "סגירה",
|
||||
"join": "הצטרף",
|
||||
"leave": "עזוב",
|
||||
"would-like-to-share": "רוצה לשתף",
|
||||
"accept": "קבל",
|
||||
"decline": "סרב",
|
||||
"has-sent": "שלח:",
|
||||
"share": "שתף",
|
||||
"send-message-to": "אל:",
|
||||
"message_title": "הזן את ההודעה לשליחה",
|
||||
"send": "שלח",
|
||||
"copy": "העתק",
|
||||
"base64-title-files": "שתף קבצים",
|
||||
"base64-title-text": "שתף טקסט",
|
||||
"base64-processing": "מעבד…",
|
||||
"base64-tap-to-paste": "גע כאן כדי לשתף {{type}}",
|
||||
"base64-paste-to-send": "הדבק כאן כדי לשתף {{type}}",
|
||||
"base64-files": "קבצים",
|
||||
"file-other-description-image": "ותמונה 1 אחרת",
|
||||
"file-other-description-file": "וקובץ 1 אחר",
|
||||
"file-other-description-image-plural": "ו{{count}} תמונות אחרות",
|
||||
"file-other-description-file-plural": "ו{{count}} קבצים אחרים",
|
||||
"title-image": "תמונה",
|
||||
"title-image-plural": "תמונות",
|
||||
"language-selector-title": "הגדר שפה",
|
||||
"pair-devices-qr-code_title": "לחץ כדי להעתיק את הקישור כדי לבצע תיאום עם מכשיר זה",
|
||||
"approve": "אשר",
|
||||
"share-text-title": "שתף הודעת טקסט",
|
||||
"share-text-subtitle": "ערוך את ההודעה לפני השליחה:",
|
||||
"close-toast_title": "סגירת ההתראה"
|
||||
},
|
||||
"about": {
|
||||
"mastodon_title": "כתוב על PairDrop בMastodon",
|
||||
"buy-me-a-coffee_title": "קנה לי קפה!",
|
||||
"claim": "הדרך הקלה ביותר להעברת קבצים בין מכשירים",
|
||||
"github_title": "PairDrop בGitHub",
|
||||
"tweet_title": "צייץ על PairDrop",
|
||||
"custom_title": "עקוב אחרינו",
|
||||
"bluesky_title": "עקוב אחרינו בBlueSky",
|
||||
"privacypolicy_title": "פתח את מדיניות הפרטיות שלנו",
|
||||
"faq_title": "שאלות נפוצות",
|
||||
"close-about_aria-label": "סגירת אודות PairDrop"
|
||||
},
|
||||
"notifications": {
|
||||
"display-name-changed-permanently": "שם התצוגה משתנה לתמיד",
|
||||
"download-successful": "{{descriptor}} הורד",
|
||||
"notifications-permissions-error": "ההרשאה להתראות נחסמה עקב סגירת חלונית בקשת ההרשאה מספר פעמים. אתה יכול לאפס זאת במידע על דף זה שניתן לגישה באמצעות לחיצה על אייקון המנעול ליד שורת הכתובת.",
|
||||
"click-to-show": "לחץ כדי להציג",
|
||||
"connecting": "מתחבר…",
|
||||
"online": "הנך מחובר שוב לאינטרנט",
|
||||
"pairing-cleared": "כל ההתאמות למכשירים הוסרו",
|
||||
"pair-url-copied-to-clipboard": "הקישור להתאמת המכשיר הזה הועתק",
|
||||
"connected": "מחובר",
|
||||
"online-requirement-pairing": "אתה צריך להיות מחובר לאינטרנט כדי לתאם מכשירים",
|
||||
"online-requirement-public-room": "אתה צריך להיות מחובר כדי ליצור חדר ציבורי",
|
||||
"files-incorrect": "הקבצים שגויים",
|
||||
"unfinished-transfers-warning": "יש עוד העברות שלא הסתיימו. אתה בטוח שאתה רוצה לסגור את PairDrop?",
|
||||
"rate-limit-join-key": "הגעת למגבלה. חכה 10 שניות ונסה שנית.",
|
||||
"selected-peer-left": "המכשיר הנבחר עזב",
|
||||
"display-name-changed-temporarily": "שם התצוגה משתנה להפעלה זו בלבד",
|
||||
"display-name-random-again": "שם התצוגה נוצר שוב באופן אקראי",
|
||||
"pairing-tabs-error": "תיאום בין שני כרטיסיות בדפדפן אינו אפשרי",
|
||||
"pairing-success": "המכשירים תואמו",
|
||||
"pairing-not-persistent": "המכשירים המתואמים אינם קבועים",
|
||||
"pairing-key-invalid": "קוד שגוי",
|
||||
"pairing-key-invalidated": "הקוד {{key}} לא תקף עוד",
|
||||
"public-room-id-invalid": "מזהה חדר שגוי",
|
||||
"public-room-left": "עזבת את החדר הציבורי {{publicRoomId}}",
|
||||
"copied-to-clipboard": "הועתק",
|
||||
"room-url-copied-to-clipboard": "הקישור לחדר הציבורי הועתק",
|
||||
"copied-to-clipboard-error": "העתקה אינה אפשרית. העתק ידנית.",
|
||||
"text-content-incorrect": "תוכן הטקסט שגוי",
|
||||
"file-content-incorrect": "תוכן הקובץ שגוי",
|
||||
"clipboard-content-incorrect": "התוכן שהודבק שגוי",
|
||||
"notifications-enabled": "ההתראות אופשרו",
|
||||
"link-received": "קישור התקבל מ{{name}} - לחץ כדי לפתוח",
|
||||
"message-received": "הודעה התקבלה מ{{name}} - לחץ כדי להעתיק",
|
||||
"click-to-download": "לחץ כדי להוריד",
|
||||
"request-title": "{{name}} רוצה לשלוח {{count}} {{descriptor}}",
|
||||
"copied-text": "הטקסט הועתק",
|
||||
"copied-text-error": "ההעתקה נכשלה. העתק ידנית!",
|
||||
"offline": "הנך לא מחובר לאינטרנט",
|
||||
"file-transfer-completed": "העברת הקובץ הושלמה בהצלחה",
|
||||
"ios-memory-limit": "שליחת קבצים למכשירי iOS אפשרית רק עד 200 MB בבת אחת",
|
||||
"message-transfer-completed": "העברת ההודעה הושלמה בהצלחה"
|
||||
},
|
||||
"peer-ui": {
|
||||
"click-to-send": "לחץ כדי לשלוח קבצים או בצע לחיצה ימנית כדי לשלוח הודעה",
|
||||
"click-to-send-share-mode": "לחץ כדי לשלוח {{descriptor}}",
|
||||
"connection-hash": "כדי לאמת את האבטחה של ההצפנה מצד לצד, השווה את מספר אבטחה זה בין שני המכשירים",
|
||||
"preparing": "מתכונן…",
|
||||
"waiting": "מחכה…",
|
||||
"processing": "מעבד…",
|
||||
"transferring": "מעביר…"
|
||||
},
|
||||
"document-titles": {
|
||||
"file-received": "הקובץ התקבל",
|
||||
"file-received-plural": "{{count}} קבצים התקבלו",
|
||||
"file-transfer-requested": "העברת קבצים מתבקשת",
|
||||
"image-transfer-requested": "העברת תמונות מתבקשת",
|
||||
"message-received": "התקבלה הודעה",
|
||||
"message-received-plural": "{{count}} הודעות התקבלו"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -48,7 +48,6 @@
|
||||
"pairing-cleared": "Semua Perangkat dilepaskan",
|
||||
"notifications-enabled": "Notifikasi diaktifkan",
|
||||
"online-requirement-pairing": "Anda harus online untuk memasangkan perangkat",
|
||||
"ios-memory-limit": "Mengirim file ke iOS hanya dapat dilakukan hingga 200 MB sekaligus",
|
||||
"online-requirement-public-room": "Anda harus online untuk membuat ruang publik",
|
||||
"copied-text-error": "Menyalin ke papan klip gagal. Salinlah secara manual!",
|
||||
"download-successful": "{{descriptor}} diunduh",
|
||||
|
||||
@@ -143,7 +143,6 @@
|
||||
"pairing-cleared": "Tutti i dispositivi sono stati dissociati",
|
||||
"notifications-enabled": "Notifiche attivate",
|
||||
"online-requirement-pairing": "Devi essere online per associare dispositivi",
|
||||
"ios-memory-limit": "L'invio di file a dispositivi iOS è possibile solo 200 MB alla volta",
|
||||
"online-requirement-public-room": "Devi essere online per creare una stanza pubblica",
|
||||
"copied-text-error": "Scrittura negli appunti fallita. Copia manualmente!",
|
||||
"download-successful": "{{descriptor}} scaricato",
|
||||
|
||||
@@ -1,17 +1,17 @@
|
||||
{
|
||||
"footer": {
|
||||
"webrtc": "WebRTCが利用できない場合。",
|
||||
"public-room-devices_title": "このデバイスはネットワークと関係なく、このパブリックルームのデバイスにより発見される可能性があります。",
|
||||
"webrtc": "(WebRTCが無効なため)",
|
||||
"public-room-devices_title": "公開ルーム内のデバイスは、接続中のネットワークと関係なくアクセスできます。",
|
||||
"display-name_data-placeholder": "読み込み中…",
|
||||
"display-name_title": "永続的なデバイス名を編集する",
|
||||
"traffic": "トラフィックは",
|
||||
"paired-devices_title": "このデバイスはネットワークと関係なく、常にペア設定したデバイスにより発見される可能性があります。",
|
||||
"public-room-devices": "ルーム{{roomId}}上",
|
||||
"paired-devices": "ペア設定したデバイス",
|
||||
"display-name_title": "デバイス名を変更する",
|
||||
"traffic": "この通信は",
|
||||
"paired-devices_title": "ペアリング済みデバイスであれば、接続中のネットワークに関わらずアクセスできます。",
|
||||
"public-room-devices": "ルーム{{roomId}}",
|
||||
"paired-devices": "ペアリング済みデバイス",
|
||||
"on-this-network": "このネットワーク上",
|
||||
"routed": "サーバーを経由します",
|
||||
"discovery": "このデバイスは以下で発見される可能性があります:",
|
||||
"on-this-network_title": "このデバイスはこのネットワーク上の誰にでも発見される可能性があります。",
|
||||
"discovery": "このデバイスを検出可能なネットワーク:",
|
||||
"on-this-network_title": "このネットワーク上のすべてのデバイスからアクセスできます。",
|
||||
"known-as": "他のデバイスに表示される名前:"
|
||||
},
|
||||
"notifications": {
|
||||
@@ -23,50 +23,49 @@
|
||||
"pairing-key-invalidated": "コード{{key}}が失効しました",
|
||||
"pairing-key-invalid": "無効なコード",
|
||||
"connected": "接続しました",
|
||||
"pairing-not-persistent": "ペア設定されたデバイスは永続化されていません",
|
||||
"text-content-incorrect": "テキストの内容が不正です",
|
||||
"pairing-not-persistent": "このデバイスとのペアリングは解除される可能性があります",
|
||||
"text-content-incorrect": "無効なテキスト内容です",
|
||||
"message-transfer-completed": "メッセージの送信が完了しました",
|
||||
"file-transfer-completed": "ファイルの転送が完了しました",
|
||||
"file-content-incorrect": "ファイルの内容が不正です",
|
||||
"file-transfer-completed": "ファイル転送が完了しました",
|
||||
"file-content-incorrect": "無効なファイル内容です",
|
||||
"files-incorrect": "ファイルが間違っています",
|
||||
"selected-peer-left": "選択した相手が退出しました",
|
||||
"selected-peer-left": "選択したデバイスが退出しました",
|
||||
"link-received": "{{name}}から受信したリンク(クリックして開く)",
|
||||
"online": "オンラインに復帰しました",
|
||||
"public-room-left": "パブリックルーム{{publicRoomId}}から退出しました",
|
||||
"public-room-left": "公開ルーム{{publicRoomId}}から退出しました",
|
||||
"copied-text": "テキストをクリップボードにコピーしました",
|
||||
"display-name-random-again": "表示名がもう一度ランダムに生成されました",
|
||||
"display-name-changed-permanently": "永続的な表示名が変更されました",
|
||||
"display-name-random-again": "新しいランダムなデバイス名に変更されました",
|
||||
"display-name-changed-permanently": "デバイス名が変更されました",
|
||||
"copied-to-clipboard-error": "コピーできませんでした。手動でコピーしてください。",
|
||||
"pairing-success": "デバイスがペア設定されました",
|
||||
"clipboard-content-incorrect": "クリップボードの内容が不正です",
|
||||
"display-name-changed-temporarily": "このセッションでの表示名が変更されました",
|
||||
"pairing-success": "ペアリングしました",
|
||||
"clipboard-content-incorrect": "無効なクリップボード内容です",
|
||||
"display-name-changed-temporarily": "この接続のみデバイス名が変更されました",
|
||||
"copied-to-clipboard": "クリップボードにコピーしました",
|
||||
"offline": "オフラインです",
|
||||
"pairing-tabs-error": "同じWebブラウザーの2つのタブをペア設定することはできません",
|
||||
"pairing-tabs-error": "同じWebブラウザーで開いたタブ同士でペアリングすることはできません",
|
||||
"public-room-id-invalid": "無効なルームID",
|
||||
"click-to-download": "クリックしてダウンロード",
|
||||
"pairing-cleared": "全てのデバイスのペア設定を解除しました",
|
||||
"notifications-enabled": "通知が有効です",
|
||||
"online-requirement-pairing": "デバイスをペア設定するにはオンラインである必要があります",
|
||||
"ios-memory-limit": "iOSへのファイル送信は一度に200MBまでしかできません",
|
||||
"online-requirement-public-room": "パブリックルームを作成するにはオンラインである必要があります",
|
||||
"pairing-cleared": "全てのデバイスとのペアリングを解除しました",
|
||||
"notifications-enabled": "通知が有効になりました",
|
||||
"online-requirement-pairing": "ペアリングするにはオンラインである必要があります",
|
||||
"online-requirement-public-room": "公開ルームを作成するにはオンラインである必要があります",
|
||||
"copied-text-error": "クリップボードにコピーできませんでした。手動でコピーしてください。",
|
||||
"download-successful": "{{descriptor}}をダウンロードしました",
|
||||
"click-to-show": "クリックして表示",
|
||||
"notifications-permissions-error": "ユーザーが権限のプロンプトを何度か閉じたため、通知の権限がブロックされました。これは、URL バーの横にある鍵アイコンをクリックしてアクセスできるページ情報からリセットできます。",
|
||||
"pair-url-copied-to-clipboard": "このデバイスをペア設定するリンクをクリップボードにコピーしました",
|
||||
"room-url-copied-to-clipboard": "パブリックルームへのリンクをクリップボードにコピーしました"
|
||||
"notifications-permissions-error": "通知がブロックされました。これはユーザーが通知許可を何度も拒否したためです。これをリセットするには、URLバーの隣にある鍵アイコンをクリックして、ページ情報にアクセスしてください。",
|
||||
"pair-url-copied-to-clipboard": "このデバイスとペアリングするリンクをクリップボードにコピーしました",
|
||||
"room-url-copied-to-clipboard": "公開ルームへのリンクをクリップボードにコピーしました"
|
||||
},
|
||||
"header": {
|
||||
"cancel-share-mode": "完了",
|
||||
"theme-auto_title": "テーマをシステムの設定に自動的に合わせる",
|
||||
"cancel-share-mode": "キャンセル",
|
||||
"theme-auto_title": "システムテーマに合わせる",
|
||||
"install_title": "PairDropをインストール",
|
||||
"theme-dark_title": "常にダークテーマを使用する",
|
||||
"pair-device_title": "あなたのデバイスを永続的にペア設定する",
|
||||
"join-public-room_title": "パブリックルームに一時的に参加する",
|
||||
"pair-device_title": "他のデバイスとペアリングする",
|
||||
"join-public-room_title": "公開ルームに参加する",
|
||||
"notification_title": "通知を有効にする",
|
||||
"edit-paired-devices_title": "ペア設定したデバイスを編集する",
|
||||
"language-selector_title": "言語を設定",
|
||||
"edit-paired-devices_title": "ペアリング設定",
|
||||
"language-selector_title": "言語設定",
|
||||
"about_title": "PairDropについて",
|
||||
"about_aria-label": "PairDropについてを開く",
|
||||
"theme-light_title": "常にライトテーマを使用する",
|
||||
@@ -74,19 +73,19 @@
|
||||
"expand_title": "ヘッダーボタン列を拡大する"
|
||||
},
|
||||
"instructions": {
|
||||
"x-instructions_mobile": "タップしてファイルを送信または長押ししてメッセージを送信します",
|
||||
"x-instructions-share-mode_desktop": "クリックして{{descriptor}}送信",
|
||||
"x-instructions_mobile": "タップでファイルを送信、長押しでメッセージを送信します",
|
||||
"x-instructions-share-mode_desktop": "クリックして{{descriptor}}を送信",
|
||||
"activate-share-mode-and-other-files-plural": "とその他{{count}}個のファイル",
|
||||
"x-instructions-share-mode_mobile": "タップして{{descriptor}}送信",
|
||||
"x-instructions-share-mode_mobile": "タップして{{descriptor}}を送信",
|
||||
"activate-share-mode-base": "他のデバイスでPairDropを開いて送信します",
|
||||
"no-peers-subtitle": "デバイスをペア設定するかパブリックルームに参加すると、他のネットワーク上からも見つけられるようになります",
|
||||
"no-peers-subtitle": "ペアリングや公開ルームを使用すると、他のネットワーク上のデバイスと共有できます",
|
||||
"activate-share-mode-shared-text": "共有されたテキスト",
|
||||
"x-instructions_desktop": "左クリックしてファイルを送信または右クリックしてメッセージを送信します",
|
||||
"no-peers-title": "他のデバイスでPairDropを開いてファイルを送信します",
|
||||
"x-instructions_data-drop-peer": "離すとこの相手に送信します",
|
||||
"x-instructions_data-drop-bg": "送信したい相手の上で離してください",
|
||||
"no-peers_data-drop-bg": "送信したい相手の上で離してください",
|
||||
"activate-share-mode-and-other-file": "もう1つの別のファイル",
|
||||
"x-instructions_desktop": "左クリックでファイルを送信、右クリックでメッセージを送信します",
|
||||
"no-peers-title": "ファイルを共有するには他のデバイスでPairDropを開いてください",
|
||||
"x-instructions_data-drop-peer": "ドロップするとこのデバイスに送信します",
|
||||
"x-instructions_data-drop-bg": "送信したいデバイスの上でドロップしてください",
|
||||
"no-peers_data-drop-bg": "送信したいデバイスの上でドロップしてください",
|
||||
"activate-share-mode-and-other-file": "とその他1個のファイル",
|
||||
"activate-share-mode-shared-file": "共有されたファイル",
|
||||
"activate-share-mode-shared-files-plural": "{{count}}個の共有されたファイル",
|
||||
"webrtc-requirement": "このPairDropインスタンスを使用するには、WebRTCを有効にする必要があります!"
|
||||
@@ -94,20 +93,20 @@
|
||||
"peer-ui": {
|
||||
"processing": "処理中…",
|
||||
"click-to-send-share-mode": "クリックして{{descriptor}}を送信",
|
||||
"click-to-send": "クリックしてファイルを送信または右クリックしてメッセージを送信します",
|
||||
"click-to-send": "左クリックでファイルを送信、右クリックでメッセージを送信します",
|
||||
"waiting": "待機中…",
|
||||
"connection-hash": "エンドツーエンド暗号化のセキュリティを確認するには、両方のデバイスのセキュリティナンバーを確認します",
|
||||
"connection-hash": "エンドツーエンド暗号化のセキュリティを確認するには、両方のデバイスのセキュリティナンバーを確認してください",
|
||||
"preparing": "準備中…",
|
||||
"transferring": "転送中…"
|
||||
},
|
||||
"dialogs": {
|
||||
"base64-paste-to-send": "ここをタップして{{type}}を送信",
|
||||
"auto-accept-instructions-2": "そのデバイスから送信される全てのファイルを自動的に承諾します。",
|
||||
"auto-accept-instructions-2": "」を有効にすると、そのデバイスから送信されたすべてのファイルを自動的に受け入れます。",
|
||||
"receive-text-title": "メッセージを受信しました",
|
||||
"edit-paired-devices-title": "ペア設定したデバイスを編集",
|
||||
"edit-paired-devices-title": "ペアリング設定",
|
||||
"cancel": "キャンセル",
|
||||
"auto-accept-instructions-1": "有効化",
|
||||
"pair-devices-title": "デバイスを永続的にペア設定",
|
||||
"auto-accept-instructions-1": "「",
|
||||
"pair-devices-title": "新規ペアリング",
|
||||
"download": "ダウンロード",
|
||||
"title-file": "ファイル",
|
||||
"base64-processing": "処理中…",
|
||||
@@ -117,58 +116,58 @@
|
||||
"join": "参加",
|
||||
"title-image-plural": "複数の画像",
|
||||
"send": "送信",
|
||||
"base64-tap-to-paste": "ここをタップして{{type}}を貼り付け",
|
||||
"base64-tap-to-paste": "ここをタップして{{type}}を共有",
|
||||
"base64-text": "テキスト",
|
||||
"copy": "コピー",
|
||||
"file-other-description-image": "と1個の他の画像",
|
||||
"temporary-public-room-title": "一時的なパブリックルーム",
|
||||
"file-other-description-image": "とその他1個の画像",
|
||||
"temporary-public-room-title": "公開ルーム",
|
||||
"base64-files": "ファイル",
|
||||
"has-sent": "が送信しました:",
|
||||
"file-other-description-file": "と1個の他のファイル",
|
||||
"file-other-description-file": "とその他1個のファイル",
|
||||
"close": "閉じる",
|
||||
"system-language": "システムの言語",
|
||||
"unpair": "ペア解除",
|
||||
"system-language": "システム言語",
|
||||
"unpair": "ペアリング解除",
|
||||
"title-image": "画像",
|
||||
"file-other-description-file-plural": "と{{count}}個の他のファイル",
|
||||
"file-other-description-file-plural": "とその他{{count}}個のファイル",
|
||||
"would-like-to-share": "が以下のファイルを共有しようとしています",
|
||||
"send-message-to": "このデバイスにメッセージを送信:",
|
||||
"language-selector-title": "言語を設定",
|
||||
"pair": "ペア設定",
|
||||
"language-selector-title": "言語設定",
|
||||
"pair": "ペアリング",
|
||||
"hr-or": "または",
|
||||
"scan-qr-code": "もしくはQRコードをスキャンします。",
|
||||
"input-key-on-this-device": "このキーを他のデバイスに入力する",
|
||||
"scan-qr-code": "もしくはQRコードをスキャンしてください。",
|
||||
"input-key-on-this-device": "このコードを他のデバイスに入力するか",
|
||||
"download-again": "もう一度ダウンロードする",
|
||||
"accept": "承諾",
|
||||
"paired-devices-wrapper_data-empty": "ペア設定したデバイスはありません。",
|
||||
"enter-key-from-another-device": "他のデバイスに表示されたキーをここに入力します。",
|
||||
"paired-devices-wrapper_data-empty": "ペアリングしたデバイスはありません。",
|
||||
"enter-key-from-another-device": "他のデバイスに表示されたコードを入力してください。",
|
||||
"share": "共有",
|
||||
"auto-accept": "自動承諾",
|
||||
"title-file-plural": "複数のファイル",
|
||||
"send-message-title": "メッセージを送信",
|
||||
"input-room-id-on-another-device": "このルームIDを他のデバイスに入力",
|
||||
"file-other-description-image-plural": "と{{count}}個の他の画像",
|
||||
"enter-room-id-from-another-device": "他のデバイスに表示された参加したいルームのIDを入力します。",
|
||||
"input-room-id-on-another-device": "このルームIDを他のデバイスに入力するか",
|
||||
"file-other-description-image-plural": "とその他{{count}}個の画像",
|
||||
"enter-room-id-from-another-device": "他のデバイスに表示されたルームIDを入力してください。",
|
||||
"message_title": "送信するメッセージを挿入",
|
||||
"pair-devices-qr-code_title": "クリックしてこのデバイスをペア設定するリンクをコピー",
|
||||
"public-room-qr-code_title": "クリックしてパブリックルームへのリンクをコピー",
|
||||
"paired-device-removed": "ペア設定されたデバイスが削除されました。",
|
||||
"pair-devices-qr-code_title": "クリックしてこのデバイスとペアリングするリンクをコピー",
|
||||
"public-room-qr-code_title": "クリックして公開ルームへのリンクをコピー",
|
||||
"paired-device-removed": "ペアリングを解除しました。",
|
||||
"message_placeholder": "テキスト",
|
||||
"base64-title-files": "共有されたファイル",
|
||||
"base64-title-text": "テキストを共有",
|
||||
"approve": "承諾",
|
||||
"approve": "OK",
|
||||
"share-text-subtitle": "送信する前にメッセージを編集する:",
|
||||
"share-text-checkbox": "テキストを共有するときに常にこのダイアログを表示する",
|
||||
"share-text-checkbox": "テキスト共有する際、毎回この画面を表示する",
|
||||
"close-toast_title": "通知を閉じる",
|
||||
"share-text-title": "テキストメッセージを共有します"
|
||||
},
|
||||
"about": {
|
||||
"claim": "デバイス間でファイルを転送する最も簡単な方法",
|
||||
"tweet_title": "PairDropについてツイートする",
|
||||
"claim": "デバイス間のファイル共有を手軽に実現します",
|
||||
"tweet_title": "PairDropのことをポストする",
|
||||
"close-about_aria-label": "PairDropについてを閉じる",
|
||||
"buy-me-a-coffee_title": "コーヒーをおごってください!",
|
||||
"github_title": "GitHubでPairDropを見る",
|
||||
"buy-me-a-coffee_title": "コーヒーを一杯おごってください!",
|
||||
"github_title": "PairDrop on GitHub",
|
||||
"faq_title": "FAQ",
|
||||
"mastodon_title": "MastodonにPairDropについて書く",
|
||||
"mastodon_title": "MastodonにPairDropのことをトゥートする",
|
||||
"bluesky_title": "BlueSkyでフォロー",
|
||||
"custom_title": "フォロー",
|
||||
"privacypolicy_title": "プライバシーポリシーを開く"
|
||||
|
||||
@@ -128,7 +128,6 @@
|
||||
"pairing-cleared": "ಎಲ್ಲಾ ಸಾಧನಗಳನ್ನು ಜೋಡಿಯಾಗಿ ತೆಗೆಯಲಾಗಿದೆ",
|
||||
"notifications-enabled": "ಸೂಚನೆಗಳನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಲಾಗಿದೆ",
|
||||
"online-requirement-pairing": "ಸಾಧನಗಳನ್ನು ಜೋಡಿಸಲು ನೀವು ಆನ್ಲೈನ್ ಇರಬೇಕು",
|
||||
"ios-memory-limit": "iOSಗೆ ಫೈಲ್ಗಳನ್ನು ಕಳುಹಿಸುವುದು ಒಂದೇ ಬಾರಿಗೆ 200 MB ವರೆಗೆ ಮಾತ್ರ ಸಾಧ್ಯವಾಗಿದೆ",
|
||||
"online-requirement-public-room": "ಸಾರ್ವಜನಿಕ ಕೊಠಡಿಯನ್ನು ರಚಿಸಲು ನೀವು ಆನ್ಲೈನ್ ಇರಬೇಕು",
|
||||
"room-url-copied-to-clipboard": "ಸಾರ್ವಜನಿಕ ಕೊಠಡಿಯ ಲಿಂಕ್ ಅನ್ನು ಕ್ಲಿಪ್ಬೋರ್ಡ್ಗೆ ನಕಲಿಸಲಾಗಿದೆ",
|
||||
"copied-text-error": "ಕ್ಲಿಪ್ಬೋರ್ಡ್ಗೆ ಬರೆಯುವುದು ವಿಫಲವಾಗಿದೆ. ಕೈಯಾರೆ ನಕಲಿಸಿ!",
|
||||
|
||||
29
public/lang/ko.json
Normal file
29
public/lang/ko.json
Normal file
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"header": {
|
||||
"notification_title": "알림 켜기",
|
||||
"edit-paired-devices_title": "연결된 기기 편집하기",
|
||||
"install_title": "PairDrop 설치",
|
||||
"theme-dark_title": "항상 다크 테마 사용",
|
||||
"about_title": "PairDrop에 대하여",
|
||||
"language-selector_title": "언어 설정",
|
||||
"about_aria-label": "PairDrop에 대하여 보기",
|
||||
"theme-light_title": "항상 라이트 테마 사용",
|
||||
"theme-auto_title": "시스템에 맞춰 테마 자동 적용",
|
||||
"join-public-room_title": "일시적으로 공개 방에 참여하기",
|
||||
"cancel-share-mode": "취소",
|
||||
"edit-share-mode": "편집",
|
||||
"pair-device_title": "영구적으로 기기 연결하기",
|
||||
"expand_title": "머리글 버튼 행 펼치기"
|
||||
},
|
||||
"instructions": {
|
||||
"no-peers-subtitle": "장치를 연결하거나 공개 방에 들어가 다른 네트워크에서 검색 가능하게 하세요",
|
||||
"no-peers_data-drop-bg": "해제하여 수신자 선택하기",
|
||||
"x-instructions_mobile": "탭하여 파일을 보내거나 길게 탭하여 메시지를 보내세요",
|
||||
"x-instructions_desktop": "클릭해 파일을 보내거나 오른쪽 클릭으로 메시지를 보내세요",
|
||||
"no-peers-title": "다른 장치에서 PairDrop을 열어 파일 보내기",
|
||||
"x-instructions_data-drop-bg": "해제하여 수신자 선택하기",
|
||||
"x-instructions-share-mode_desktop": "클릭하여 {{descriptor}} 보내기",
|
||||
"x-instructions-share-mode_mobile": "탭하여 {{descriptor}} 보내기",
|
||||
"activate-share-mode-base": "다른 기기에서 PairDrop을 열어 보내기"
|
||||
}
|
||||
}
|
||||
@@ -116,7 +116,6 @@
|
||||
"request-title": "{{name}} ønsker å overføre {{count}} {{descriptor}}",
|
||||
"message-received": "Melding mottatt av {{name}} - Klikk for å åpne",
|
||||
"files-incorrect": "Filene er uriktige",
|
||||
"ios-memory-limit": "Forsendelse av filer til iOS er kun mulig opptil 200 MB av gangen",
|
||||
"unfinished-transfers-warning": "Lukk med ufullførte overføringer?",
|
||||
"rate-limit-join-key": "Forsøksgrense overskredet. Vent 10 sek. og prøv igjen."
|
||||
},
|
||||
|
||||
@@ -48,7 +48,6 @@
|
||||
"pairing-cleared": "Alle apparaten ontkoppeld",
|
||||
"notifications-enabled": "Meldingen geactiveerd",
|
||||
"online-requirement-pairing": "U moet online zijn om apparaten te koppelen",
|
||||
"ios-memory-limit": "Bestandsoverdrachten naar iOS kunnen slechts met 200 MB per keer",
|
||||
"online-requirement-public-room": "U moet online zijn om een openbare kamer te maken",
|
||||
"copied-text-error": "Schrijven naar klembord mislukt. Kopieer handmatig!",
|
||||
"download-successful": "{{descriptor}} downloaden",
|
||||
|
||||
@@ -153,7 +153,6 @@
|
||||
"connecting": "Conectando…",
|
||||
"files-incorrect": "Os arquivos estão incorretos",
|
||||
"file-transfer-completed": "Transferência de arquivo concluída",
|
||||
"ios-memory-limit": "Enviar arquivos para iOS só é possível até 200 MB de uma vez",
|
||||
"message-transfer-completed": "Transferência de mensagem concluída",
|
||||
"unfinished-transfers-warning": "Há transferências inacabadas. Tem certeza de que deseja fechar o PairDrop?",
|
||||
"rate-limit-join-key": "Limite de taxa atingido. Aguarde 10 segundos e tente novamente.",
|
||||
|
||||
@@ -48,7 +48,6 @@
|
||||
"pairing-cleared": "Toate dispozitivele sunt decuplate",
|
||||
"notifications-enabled": "Notificări activate",
|
||||
"online-requirement-pairing": "Trebuie să fiți online pentru a asocia dispozitivele",
|
||||
"ios-memory-limit": "Trimiterea de fișiere pe iOS este posibilă doar până la 200 MB simultan",
|
||||
"online-requirement-public-room": "Trebuie să fiți online pentru a crea o cameră publică",
|
||||
"copied-text-error": "Scrierea în clipboard a eșuat. Copiați manual!",
|
||||
"download-successful": "{{descriptor}} descărcat",
|
||||
|
||||
@@ -93,7 +93,9 @@
|
||||
"temporary-public-room-title": "Временная публичная комната",
|
||||
"message_title": "Вставьте сообщение для отправки",
|
||||
"pair-devices-qr-code_title": "Нажмите, чтобы скопировать ссылку для привязки этого устройства",
|
||||
"public-room-qr-code_title": "Нажмите, чтобы скопировать ссылку на публичную комнату"
|
||||
"public-room-qr-code_title": "Нажмите, чтобы скопировать ссылку на публичную комнату",
|
||||
"message_placeholder": "Текст",
|
||||
"paired-device-removed": "Связанное устройство удалено."
|
||||
},
|
||||
"about": {
|
||||
"close-about-aria-label": "Закрыть страницу \"О сервисе\"",
|
||||
@@ -122,7 +124,6 @@
|
||||
"online-requirement": "Для сопряжения устройств вам нужно быть в сети.",
|
||||
"files-incorrect": "Файлы неверны",
|
||||
"message-transfer-completed": "Передача сообщения завершена",
|
||||
"ios-memory-limit": "Отправка файлов на iOS устройства возможна только до 200 МБ за один раз",
|
||||
"selected-peer-left": "Выбранный узел вышел",
|
||||
"request-title": "{{name}} хотел бы передать {{count}} {{descriptor}}",
|
||||
"rate-limit-join-key": "Достигнут предел скорости. Подождите 10 секунд и повторите попытку.",
|
||||
|
||||
@@ -1,163 +1,163 @@
|
||||
{
|
||||
"header": {
|
||||
"about_title": "PairDrop Hakkında",
|
||||
"about_aria-label": "PairDrop Hakkındayı Aç",
|
||||
"theme-auto_title": "Temayı sisteme uyarla",
|
||||
"theme-light_title": "Daima açık tema kullan",
|
||||
"theme-dark_title": "Daima koyu tema kullan",
|
||||
"about_aria-label": "PairDrop Hakkında'yı Aç",
|
||||
"theme-auto_title": "Temayı sisteme otomatik olarak adapte et",
|
||||
"theme-light_title": "Her zaman açık temayı kullan",
|
||||
"theme-dark_title": "Her zaman koyu temayı kullan",
|
||||
"notification_title": "Bildirimleri etkinleştir",
|
||||
"install_title": "PairDrop'u Yükle",
|
||||
"pair-device_title": "Cihazı kalıcı olarak eşle",
|
||||
"edit-paired-devices_title": "Eşleştirilmiş cihazları düzenle",
|
||||
"cancel-share-mode": "Bitti",
|
||||
"join-public-room_title": "Geçici olarak genel odaya katılın",
|
||||
"language-selector_title": "Dili Seç",
|
||||
"pair-device_title": "Cihazlarınızı kalıcı olarak eşleştirin",
|
||||
"edit-paired-devices_title": "Eşleşmiş cihazları düzenle",
|
||||
"cancel-share-mode": "İptal Et",
|
||||
"join-public-room_title": "Geçici olarak ortak odaya katıl",
|
||||
"language-selector_title": "Dili Ayarla",
|
||||
"edit-share-mode": "Düzenle",
|
||||
"expand_title": "Başlık düğmesi satırını genişlet"
|
||||
"expand_title": "Başlık buton satırını genişlet"
|
||||
},
|
||||
"instructions": {
|
||||
"no-peers_data-drop-bg": "Alıcıyı seçmek için bırakın",
|
||||
"x-instructions_mobile": "Dosya göndermek için dokun veya mesaj göndermek için uzun dokun",
|
||||
"x-instructions-share-mode_desktop": "{{descriptor}} kişisine göndermek için tıkla",
|
||||
"x-instructions_mobile": "Dosya göndermek için dokunun veya mesaj göndermek için uzun dokunun",
|
||||
"x-instructions-share-mode_desktop": "{{descriptor}} göndermek için tıklayın",
|
||||
"activate-share-mode-and-other-files-plural": "ve {{count}} diğer dosya",
|
||||
"x-instructions-share-mode_mobile": "{{descriptor}} kişisine göndermek için dokun",
|
||||
"x-instructions-share-mode_mobile": "{{descriptor}} göndermek için dokunun",
|
||||
"activate-share-mode-base": "Göndermek için diğer cihazlarda PairDrop'u açın",
|
||||
"no-peers-subtitle": "Diğer ağlarda keşfedilebilir olmak için cihazları eşleştirin veya ortak bir odaya girin",
|
||||
"no-peers-subtitle": "Cihazları eşleştirin veya keşfedilebilir olmak için ortak bir odaya girin",
|
||||
"activate-share-mode-shared-text": "paylaşılan metin",
|
||||
"x-instructions_desktop": "Dosya göndermek için tıkla veya mesaj göndermek için sağ tıkla",
|
||||
"x-instructions_desktop": "Dosya göndermek için tıklayın veya mesaj göndermek için sağ tıklayın",
|
||||
"no-peers-title": "Dosya göndermek için diğer cihazlarda PairDrop'u açın",
|
||||
"x-instructions_data-drop-peer": "Göndermek için serbest bırak",
|
||||
"x-instructions_data-drop-peer": "Eşleştiriciye göndermek için bırakın",
|
||||
"x-instructions_data-drop-bg": "Alıcıyı seçmek için bırakın",
|
||||
"webrtc-requirement": "Bu PairDrop örneğini kullanmak için WebRTC etkinleştirilmelidir!",
|
||||
"activate-share-mode-shared-files-plural": "{{count}} adet paylaşılan dosya",
|
||||
"webrtc-requirement": "Bu PairDrop örneğini kullanmak için WebRTC etkin olmalı!",
|
||||
"activate-share-mode-shared-files-plural": "{{count}} paylaşılan dosya",
|
||||
"activate-share-mode-shared-file": "paylaşılan dosya",
|
||||
"activate-share-mode-and-other-file": "ve 1 dosya"
|
||||
"activate-share-mode-and-other-file": "ve 1 diğer dosya"
|
||||
},
|
||||
"footer": {
|
||||
"display-name_data-placeholder": "Yükleniyor…",
|
||||
"display-name_title": "Cihazının adını kalıcı olarak düzenle",
|
||||
"display-name_title": "Cihaz adınızı kalıcı olarak düzenleyin",
|
||||
"webrtc": "WebRTC mevcut değilse.",
|
||||
"public-room-devices_title": "Genel odada ağdan bağımsız olarak cihazlar tarafından keşfedilebilirsiniz.",
|
||||
"public-room-devices_title": "Ağdan bağımsız olarak bu ortak odadaki cihazlar tarafından keşfedilebilir olabilirsiniz.",
|
||||
"traffic": "Trafik",
|
||||
"paired-devices_title": "Eşleştirilmiş cihazlarda ağdan bağımsız olarak her zaman keşfedilebilirsiniz.",
|
||||
"public-room-devices": "{{roomId}} odası",
|
||||
"paired-devices_title": "Ağdan bağımsız olarak her zaman eşleştirilmiş cihazlar tarafından keşfedilebilir olabilirsiniz.",
|
||||
"public-room-devices": "{{roomId}} odasında",
|
||||
"paired-devices": "eşleştirilmiş cihazlar tarafından",
|
||||
"on-this-network": "bu ağ üzerinde",
|
||||
"routed": "sunucu üzerinden yönlendirilir",
|
||||
"discovery": "Keşfedilebilirsin:",
|
||||
"on-this-network_title": "Bu ağdaki herkes tarafından keşfedilebilirsiniz.",
|
||||
"known-as": "Bilinen adın:"
|
||||
"on-this-network": "bu ağda",
|
||||
"routed": "sunucu üzerinden yönlendirilmiş",
|
||||
"discovery": "Keşfedilebilir durumdasınız:",
|
||||
"on-this-network_title": "Bu ağdaki herkes tarafından keşfedilebilir olabilirsiniz.",
|
||||
"known-as": "Şu adla biliniyorsunuz:"
|
||||
},
|
||||
"dialogs": {
|
||||
"cancel": "İptal",
|
||||
"edit-paired-devices-title": "Eşleştirilmiş Cihazları Düzenle",
|
||||
"base64-paste-to-send": "{{type}} paylaşmak için buraya yapıştır",
|
||||
"auto-accept-instructions-2": "böylelikle cihazdan gönderilen tüm dosyaları otomatik olarak kabul eder.",
|
||||
"edit-paired-devices-title": "Eşleşmiş Cihazları Düzenle",
|
||||
"base64-paste-to-send": "{{type}} paylaşmak için buraya yapıştırın",
|
||||
"auto-accept-instructions-2": "bu cihazdan gönderilen tüm dosyaları otomatik olarak kabul etmek için.",
|
||||
"receive-text-title": "Mesaj Alındı",
|
||||
"auto-accept-instructions-1": "Etkinleştir",
|
||||
"pair-devices-title": "Cihazları Kalıcı Eşleştir",
|
||||
"auto-accept-instructions-1": "Aktive et",
|
||||
"pair-devices-title": "Cihazları Kalıcı Olarak Eşleştir",
|
||||
"download": "İndir",
|
||||
"title-file": "Dosya",
|
||||
"base64-processing": "İşleniyor…",
|
||||
"decline": "Reddet",
|
||||
"receive-title": "{{descriptor}} Alındı",
|
||||
"leave": "Ayrıl",
|
||||
"message_title": "Göndermek için mesaj girin",
|
||||
"message_title": "Göndermek için mesaj ekle",
|
||||
"join": "Katıl",
|
||||
"title-image-plural": "Resimler",
|
||||
"send": "Gönder",
|
||||
"base64-tap-to-paste": "{{type}} paylaşmak için buraya dokun",
|
||||
"base64-tap-to-paste": "{{type}} paylaşmak için buraya dokunun",
|
||||
"base64-text": "metin",
|
||||
"copy": "Kopyala",
|
||||
"file-other-description-image": "ve 1 diğer resim",
|
||||
"pair-devices-qr-code_title": "Bu cihazı eşleştirmek üzere bağlantıyı kopyalamak için tıklayın",
|
||||
"temporary-public-room-title": "Geçici Genel Oda",
|
||||
"pair-devices-qr-code_title": "Bu cihazı eşleştirmek için bağlantıyı kopyalamak için tıklayın",
|
||||
"temporary-public-room-title": "Geçici Ortak Oda",
|
||||
"base64-files": "dosyalar",
|
||||
"has-sent": "gönderdi:",
|
||||
"file-other-description-file": "ve 1 diğer dosya",
|
||||
"public-room-qr-code_title": "Genel odanın bağlantı linkini kopyalamak için tıkla",
|
||||
"public-room-qr-code_title": "Ortak oda bağlantısını kopyalamak için tıklayın",
|
||||
"close": "Kapat",
|
||||
"system-language": "Sistem Dili",
|
||||
"unpair": "Eşlemeyi Kaldır",
|
||||
"unpair": "Eşleşmeyi Kaldır",
|
||||
"title-image": "Resim",
|
||||
"file-other-description-file-plural": "ve {{count}} diğer dosya",
|
||||
"would-like-to-share": "paylaşmak istiyor",
|
||||
"send-message-to": "Kime:",
|
||||
"language-selector-title": "Dili Seç",
|
||||
"pair": "Eşle",
|
||||
"send-message-to": "Alıcı:",
|
||||
"language-selector-title": "Dili Ayarla",
|
||||
"pair": "Eşleştir",
|
||||
"hr-or": "VEYA",
|
||||
"scan-qr-code": "veya QR kodunu tarayın.",
|
||||
"input-key-on-this-device": "Bu anahtarı başka bir cihazda girin",
|
||||
"input-key-on-this-device": "Bu anahtarı başka bir cihaza girin",
|
||||
"download-again": "Tekrar indir",
|
||||
"accept": "Kabul Et",
|
||||
"paired-devices-wrapper_data-empty": "Eşlenmiş cihaz yok.",
|
||||
"enter-key-from-another-device": "Buraya başka bir cihazdan anahtar girin.",
|
||||
"paired-devices-wrapper_data-empty": "Eşleşmiş cihaz yok.",
|
||||
"enter-key-from-another-device": "Başka bir cihazdan alınan anahtarı buraya girin.",
|
||||
"share": "Paylaş",
|
||||
"auto-accept": "otomatik-kabul",
|
||||
"auto-accept": "otomatik kabul",
|
||||
"title-file-plural": "Dosyalar",
|
||||
"send-message-title": "Mesaj Gönder",
|
||||
"input-room-id-on-another-device": "Bu ID'yi diğer cihaza girin",
|
||||
"input-room-id-on-another-device": "Bu oda kimliğini başka bir cihaza girin",
|
||||
"file-other-description-image-plural": "ve {{count}} diğer resim",
|
||||
"enter-room-id-from-another-device": "Odaya katılmak için diğer cihazın ID'sini girin.",
|
||||
"enter-room-id-from-another-device": "Odaya katılmak için başka bir cihazdan oda kimliğini girin.",
|
||||
"message_placeholder": "Metin",
|
||||
"close-toast_title": "Bildirimleri kapat",
|
||||
"share-text-checkbox": "Metin paylaşırken her zaman bu pencereyi göster",
|
||||
"close-toast_title": "Bildirim kapat",
|
||||
"share-text-checkbox": "Metin paylaşırken her zaman bu iletişim kutusunu göster",
|
||||
"base64-title-files": "Dosyaları Paylaş",
|
||||
"approve": "onayla",
|
||||
"paired-device-removed": "Eşleştirilmiş cihaz kaldırıldı.",
|
||||
"share-text-title": "Kısa Mesaj Paylaş",
|
||||
"share-text-subtitle": "Göndermeden önce mesajı düzenle:",
|
||||
"base64-title-text": "Metin Paylaş"
|
||||
"paired-device-removed": "Eşleşmiş cihaz kaldırıldı.",
|
||||
"share-text-title": "Metin Mesajı Paylaş",
|
||||
"share-text-subtitle": "Göndermeden önce mesajı düzenleyin:",
|
||||
"base64-title-text": "Metni Paylaş"
|
||||
},
|
||||
"notifications": {
|
||||
"request-title": "{{name}} {{count}} {{descriptor}} transfer etmek istiyor",
|
||||
"unfinished-transfers-warning": "Bitmemiş transferler var. PairDrop'u kapatmak istediğinize emin misiniz?",
|
||||
"message-received": "Mesaj {{name}} tarafından alındı - Kopyalamak için tıkla",
|
||||
"notifications-permissions-error": "Kullanıcı izin isteğini birkaç kez reddettiği için bildirimler engellenmiştir. URL çubuğunun yanındaki kilit simgesine tıklayarak sıfırlanabilir.",
|
||||
"rate-limit-join-key": "İstek sınırına ulaşıldı. 10 saniye bekleyin ve tekrar deneyin.",
|
||||
"pair-url-copied-to-clipboard": "Bu cihazı eşleştirmek için bağlantı linki panoya kopyalandı",
|
||||
"connecting": "Bağlanılıyor…",
|
||||
"pairing-key-invalidated": "{{key}} anahtarı geçersiz",
|
||||
"unfinished-transfers-warning": "Tamamlanmamış transferler var. PairDrop'u kapatmak istediğinizden emin misiniz?",
|
||||
"message-received": "{{name}} tarafından mesaj alındı - Kopyalamak için tıklayın",
|
||||
"notifications-permissions-error": "Bildirim izinleri birkaç kez reddedildiği için engellendi. Bu, URL çubuğunun yanındaki kilit simgesine tıklayarak erişilebilen Sayfa Bilgilerinde sıfırlanabilir.",
|
||||
"rate-limit-join-key": "Hız sınırına ulaşıldı. 10 saniye bekleyin ve tekrar deneyin.",
|
||||
"pair-url-copied-to-clipboard": "Bu cihazı eşleştirmek için bağlantı panoya kopyalandı",
|
||||
"connecting": "Bağlanıyor…",
|
||||
"pairing-key-invalidated": "Anahtar {{key}} geçersiz kılındı",
|
||||
"pairing-key-invalid": "Geçersiz anahtar",
|
||||
"connected": "Bağlandı",
|
||||
"pairing-not-persistent": "Eşleştirilmiş cihazlar kalıcı değildir",
|
||||
"text-content-incorrect": "Metin içeriği yanlış",
|
||||
"connected": "Bağlı",
|
||||
"pairing-not-persistent": "Eşleşmiş cihazlar kalıcı değil",
|
||||
"text-content-incorrect": "Metin içeriği hatalı",
|
||||
"message-transfer-completed": "Mesaj transferi tamamlandı",
|
||||
"file-transfer-completed": "Dosya transferi bitti",
|
||||
"file-content-incorrect": "Dosya içeriği yanlış",
|
||||
"files-incorrect": "Dosyalar yanlış",
|
||||
"selected-peer-left": "Seçili aygıt ayrıldı",
|
||||
"link-received": "Link {{name}} tarafından alındı - Açmak için tıkla",
|
||||
"online": "Tekrar çevrimiçisin",
|
||||
"public-room-left": "{{publicRoomId}} genel odasından ayrıldın",
|
||||
"file-transfer-completed": "Dosya transferi tamamlandı",
|
||||
"file-content-incorrect": "Dosya içeriği hatalı",
|
||||
"files-incorrect": "Dosyalar hatalı",
|
||||
"selected-peer-left": "Seçilen eş ayrıldı",
|
||||
"link-received": "{{name}} tarafından bağlantı alındı - Açmak için tıklayın",
|
||||
"online": "Tekrar çevrimiçisiniz",
|
||||
"public-room-left": "Ortak odadan ayrıldı {{publicRoomId}}",
|
||||
"copied-text": "Metin panoya kopyalandı",
|
||||
"display-name-random-again": "Mevcut adın tekrardan rastgele oluşturuldu",
|
||||
"display-name-changed-permanently": "Mevcut adın kalıcı olarak değiştirildi",
|
||||
"copied-to-clipboard-error": "Kopyalama mümkün değil. Manuel olarak kopyalayın.",
|
||||
"display-name-random-again": "Görünen ad tekrar rastgele oluşturuldu",
|
||||
"display-name-changed-permanently": "Görünen ad kalıcı olarak değiştirildi",
|
||||
"copied-to-clipboard-error": "Kopyalama mümkün değil. Elle kopyalayın.",
|
||||
"pairing-success": "Cihazlar eşleştirildi",
|
||||
"clipboard-content-incorrect": "Pano içeriği yanlış",
|
||||
"display-name-changed-temporarily": "Mevcut adın yalnızca bu oturum için değiştirildi",
|
||||
"clipboard-content-incorrect": "Panodaki içerik hatalı",
|
||||
"display-name-changed-temporarily": "Görünen ad sadece bu oturum için değiştirildi",
|
||||
"copied-to-clipboard": "Panoya kopyalandı",
|
||||
"offline": "Çevrimdışısın",
|
||||
"pairing-tabs-error": "İki web tarayıcı sekmesini eşleştirmek mümkün değildir",
|
||||
"public-room-id-invalid": "Geçersiz oda ID'si",
|
||||
"click-to-download": "İndirmek için tıkla",
|
||||
"pairing-cleared": "Tüm cihazlar eşleştirmeden çıkarıldı",
|
||||
"offline": "Çevrimdışısınız",
|
||||
"pairing-tabs-error": "İki web tarayıcı sekmesini eşleştirmek imkansız",
|
||||
"public-room-id-invalid": "Geçersiz oda kimliği",
|
||||
"click-to-download": "İndirmek için tıklayın",
|
||||
"pairing-cleared": "Tüm cihazların eşleşmesi kaldırıldı",
|
||||
"notifications-enabled": "Bildirimler etkinleştirildi",
|
||||
"online-requirement-pairing": "Cihazları eşleştirmek için çevrimiçi olmanız lazım",
|
||||
"ios-memory-limit": "iOS'a tek seferde sadece 200MB'a kadar dosya gönderebilirsin",
|
||||
"online-requirement-public-room": "Genel oda oluşturmak için çevrimiçi olmanız lazım",
|
||||
"room-url-copied-to-clipboard": "Genel oda bağlantı linki panoya kopyalandı",
|
||||
"copied-text-error": "Panoya kopyalanamadı. Lütfen manuel olarak kopyalayın!",
|
||||
"online-requirement-pairing": "Cihazları eşleştirmek için çevrimiçi olmalısınız",
|
||||
"ios-memory-limit": "iOS'a dosya göndermek sadece bir seferde 200 MB'a kadar mümkündür",
|
||||
"online-requirement-public-room": "Ortak oda oluşturmak için çevrimiçi olmalısınız",
|
||||
"room-url-copied-to-clipboard": "Ortak oda bağlantısı panoya kopyalandı",
|
||||
"copied-text-error": "Panoya yazma başarısız oldu. Elle kopyalayın!",
|
||||
"download-successful": "{{descriptor}} indirildi",
|
||||
"click-to-show": "Görmek için tıkla"
|
||||
"click-to-show": "Göstermek için tıklayın"
|
||||
},
|
||||
"peer-ui": {
|
||||
"processing": "İşleniyor…",
|
||||
"click-to-send-share-mode": "{{descriptor}} göndermek için tıkla",
|
||||
"click-to-send": "Dosya göndermek için tıkla veya mesaj göndermek için sağ tıkla",
|
||||
"click-to-send-share-mode": "{{descriptor}} göndermek için tıklayın",
|
||||
"click-to-send": "Dosya göndermek için tıklayın veya mesaj göndermek için sağ tıklayın",
|
||||
"waiting": "Bekleniyor…",
|
||||
"connection-hash": "Uçtan uca şifrelemenin güvenliğini doğrulamak için her iki cihazda da bu güvenlik numarasını karşılaştırın",
|
||||
"connection-hash": "Uçtan uca şifrelemenin güvenliğini doğrulamak için, bu güvenlik numarasını her iki cihazda da karşılaştırın",
|
||||
"preparing": "Hazırlanıyor…",
|
||||
"transferring": "Transfer ediliyor…"
|
||||
},
|
||||
@@ -165,17 +165,17 @@
|
||||
"claim": "Cihazlar arasında dosya aktarmanın en kolay yolu",
|
||||
"tweet_title": "PairDrop hakkında tweet at",
|
||||
"close-about_aria-label": "PairDrop Hakkında'yı Kapat",
|
||||
"buy-me-a-coffee_title": "Bana bir kahve al!",
|
||||
"buy-me-a-coffee_title": "Bana bir kahve ısmarla!",
|
||||
"github_title": "GitHub'da PairDrop",
|
||||
"faq_title": "Sıkça sorulan sorular",
|
||||
"custom_title": "Bizi takip edin",
|
||||
"privacypolicy_title": "Gizlilik politikamızı açın",
|
||||
"mastodon_title": "Mastodon'da PairDrop hakkında yazın",
|
||||
"bluesky_title": "Bizi BlueSky'da takip edin"
|
||||
"privacypolicy_title": "Gizlilik politikamızı aç",
|
||||
"mastodon_title": "Mastodon'da PairDrop hakkında yaz",
|
||||
"bluesky_title": "BlueSky'da bizi takip edin"
|
||||
},
|
||||
"document-titles": {
|
||||
"file-transfer-requested": "Dosya Transferi Talep Edildi",
|
||||
"image-transfer-requested": "Görüntü Aktarımı Talep Edildi",
|
||||
"image-transfer-requested": "Görüntü Transferi Talep Edildi",
|
||||
"message-received-plural": "{{count}} Mesaj Alındı",
|
||||
"message-received": "Mesaj Alındı",
|
||||
"file-received": "Dosya Alındı",
|
||||
|
||||
@@ -154,7 +154,6 @@
|
||||
"files-incorrect": "文件不正确",
|
||||
"file-transfer-completed": "文件传输已完成",
|
||||
"connecting": "连接中…",
|
||||
"ios-memory-limit": "向 iOS 发送文件 一次最多只能发送 200 MB",
|
||||
"rate-limit-join-key": "已达连接限制。请等待 10秒 后再试。",
|
||||
"public-room-left": "已退出公共房间 {{publicRoomId}}",
|
||||
"copied-to-clipboard-error": "无法复制。请手动复制。",
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
"background_color": "#efefef",
|
||||
"start_url": "/",
|
||||
"scope": "/",
|
||||
"display": "minimal-ui",
|
||||
"display": "standalone",
|
||||
"theme_color": "#3367d6",
|
||||
"screenshots" : [
|
||||
{
|
||||
|
||||
@@ -2,18 +2,27 @@ class BrowserTabsConnector {
|
||||
constructor() {
|
||||
this.bc = new BroadcastChannel('pairdrop');
|
||||
this.bc.addEventListener('message', e => this._onMessage(e));
|
||||
Events.on('broadcast-send', e => this._broadcastSend(e.detail));
|
||||
Events.on('broadcast-send', e => this._broadcastSend(e.detail.type, e.detail.data));
|
||||
Events.on('broadcast-self-display-name-changed', e => this._onBroadcastSelfDisplayNameChanged(e.detail.displayName));
|
||||
}
|
||||
|
||||
_broadcastSend(message) {
|
||||
this.bc.postMessage(message);
|
||||
_broadcastSend(type, data) {
|
||||
this.bc.postMessage({ type, data });
|
||||
}
|
||||
|
||||
_onBroadcastSelfDisplayNameChanged(displayName) {
|
||||
this._broadcastSend('self-display-name-changed', { displayName: displayName });
|
||||
}
|
||||
|
||||
_onMessage(e) {
|
||||
console.log('Broadcast:', e.data)
|
||||
switch (e.data.type) {
|
||||
const type = e.data.type;
|
||||
const data = e.data.data;
|
||||
|
||||
Logger.debug('Broadcast:', type, data);
|
||||
|
||||
switch (type) {
|
||||
case 'self-display-name-changed':
|
||||
Events.fire('self-display-name-changed', e.data.detail);
|
||||
Events.fire('self-display-name-changed', data.displayName);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -25,6 +34,11 @@ class BrowserTabsConnector {
|
||||
: false;
|
||||
}
|
||||
|
||||
static isOnlyTab() {
|
||||
let peerIdsBrowser = JSON.parse(localStorage.getItem('peer_ids_browser'));
|
||||
return peerIdsBrowser.length <= 1;
|
||||
}
|
||||
|
||||
static async addPeerIdToLocalStorage() {
|
||||
const peerId = sessionStorage.getItem('peer_id');
|
||||
if (!peerId) return false;
|
||||
|
||||
@@ -2,28 +2,28 @@ class Localization {
|
||||
constructor() {
|
||||
Localization.$htmlRoot = document.querySelector('html');
|
||||
|
||||
Localization.defaultLocale = "en";
|
||||
Localization.supportedLocales = ["ar", "ca", "de", "en", "es", "fr", "hu", "id", "it", "ja", "kn", "nb", "nl", "pl", "pt-BR", "ro", "ru", "tr", "zh-CN", "zh-TW"];
|
||||
Localization.supportedLocalesRtl = ["ar"];
|
||||
Localization.localeDefault = "en";
|
||||
Localization.localesSupported = ["ar", "be", "ca", "da", "de", "en", "es", "fr", "he", "hu", "id", "it", "ja", "kn", "nb", "nl", "pl", "pt-BR", "ro", "ru", "tr", "zh-CN", "zh-TW"];
|
||||
Localization.localesRtl = ["ar", "he"];
|
||||
|
||||
Localization.translations = {};
|
||||
Localization.translationsDefaultLocale = {};
|
||||
|
||||
Localization.systemLocale = Localization.getSupportedOrDefaultLocales(navigator.languages);
|
||||
Localization.localeSystem = Localization.getSupportedOrDefaultLocales(navigator.languages);
|
||||
|
||||
let storedLanguageCode = localStorage.getItem('language_code');
|
||||
|
||||
Localization.initialLocale = storedLanguageCode && Localization.localeIsSupported(storedLanguageCode)
|
||||
Localization.localeInitial = storedLanguageCode && Localization.localeIsSupported(storedLanguageCode)
|
||||
? storedLanguageCode
|
||||
: Localization.systemLocale;
|
||||
: Localization.localeSystem;
|
||||
}
|
||||
|
||||
static localeIsSupported(locale) {
|
||||
return Localization.supportedLocales.indexOf(locale) > -1;
|
||||
return Localization.localesSupported.indexOf(locale) > -1;
|
||||
}
|
||||
|
||||
static localeIsRtl(locale) {
|
||||
return Localization.supportedLocalesRtl.indexOf(locale) > -1;
|
||||
return Localization.localesRtl.indexOf(locale) > -1;
|
||||
}
|
||||
|
||||
static currentLocaleIsRtl() {
|
||||
@@ -31,7 +31,7 @@ class Localization {
|
||||
}
|
||||
|
||||
static currentLocaleIsDefault() {
|
||||
return Localization.locale === Localization.defaultLocale
|
||||
return Localization.locale === Localization.localeDefault
|
||||
}
|
||||
|
||||
static getSupportedOrDefaultLocales(locales) {
|
||||
@@ -44,15 +44,15 @@ class Localization {
|
||||
// If there is no perfect match for browser locales, try generic locales first before resorting to the default locale
|
||||
return locales.find(Localization.localeIsSupported)
|
||||
|| localesGeneric.find(Localization.localeIsSupported)
|
||||
|| Localization.defaultLocale;
|
||||
|| Localization.localeDefault;
|
||||
}
|
||||
|
||||
async setInitialTranslation() {
|
||||
await Localization.setTranslation(Localization.initialLocale)
|
||||
await Localization.setTranslation(Localization.localeInitial)
|
||||
}
|
||||
|
||||
static async setTranslation(locale) {
|
||||
if (!locale) locale = Localization.systemLocale;
|
||||
if (!locale) locale = Localization.localeSystem;
|
||||
|
||||
await Localization.setLocale(locale)
|
||||
await Localization.translatePage();
|
||||
@@ -67,8 +67,8 @@ class Localization {
|
||||
Localization.$htmlRoot.setAttribute('lang', locale);
|
||||
|
||||
|
||||
console.log("Page successfully translated",
|
||||
`System language: ${Localization.systemLocale}`,
|
||||
Logger.debug("Page successfully translated",
|
||||
`System language: ${Localization.localeSystem}`,
|
||||
`Selected language: ${locale}`
|
||||
);
|
||||
|
||||
@@ -78,7 +78,7 @@ class Localization {
|
||||
static async setLocale(newLocale) {
|
||||
if (newLocale === Localization.locale) return false;
|
||||
|
||||
Localization.defaultTranslations = await Localization.fetchTranslationsFor(Localization.defaultLocale);
|
||||
Localization.translationsDefaultLocale = await Localization.fetchTranslationsFor(Localization.localeDefault);
|
||||
|
||||
const newTranslations = await Localization.fetchTranslationsFor(newLocale);
|
||||
|
||||
@@ -145,7 +145,7 @@ class Localization {
|
||||
translation = translationObj[lastKey];
|
||||
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
Logger.error(e);
|
||||
}
|
||||
|
||||
if (!translation) {
|
||||
@@ -179,7 +179,7 @@ class Localization {
|
||||
}
|
||||
catch (e) {
|
||||
// Log warnings and help calls
|
||||
console.warn(e);
|
||||
Logger.warn(e);
|
||||
Localization.logTranslationMissingOrBroken(key, attr, data, useDefault);
|
||||
Localization.logHelpCallKey(key, attr);
|
||||
Localization.logHelpCall();
|
||||
@@ -192,7 +192,7 @@ class Localization {
|
||||
else {
|
||||
// Is not default locale yet
|
||||
// Get translation for default language with same arguments
|
||||
console.log(`Using default language ${Localization.defaultLocale.toUpperCase()} instead.`);
|
||||
Logger.debug(`Using default language ${Localization.localeDefault.toUpperCase()} instead.`);
|
||||
translation = this.getTranslation(key, attr, data, true);
|
||||
}
|
||||
}
|
||||
@@ -202,14 +202,14 @@ class Localization {
|
||||
|
||||
static logTranslationMissingOrBroken(key, attr, data, useDefault) {
|
||||
let usedLocale = useDefault
|
||||
? Localization.defaultLocale.toUpperCase()
|
||||
? Localization.localeDefault.toUpperCase()
|
||||
: Localization.locale.toUpperCase();
|
||||
|
||||
console.warn(`Missing or broken translation for language ${usedLocale}.\n`, 'key:', key, 'attr:', attr, 'data:', data);
|
||||
Logger.warn(`Missing or broken translation for language ${usedLocale}.\n`, 'key:', key, 'attr:', attr, 'data:', data);
|
||||
}
|
||||
|
||||
static logHelpCall() {
|
||||
console.log("Help translating PairDrop: https://hosted.weblate.org/engage/pairdrop/");
|
||||
Logger.warn("Help translating PairDrop: https://hosted.weblate.org/engage/pairdrop/");
|
||||
}
|
||||
|
||||
static logHelpCallKey(key, attr) {
|
||||
@@ -219,7 +219,7 @@ class Localization {
|
||||
? key
|
||||
: `${key}_${attr}`;
|
||||
|
||||
console.warn(`Translate this string here: https://hosted.weblate.org/browse/pairdrop/pairdrop-spa/${locale}/?q=${keyComplete}`);
|
||||
Logger.warn(`Translate this string here: https://hosted.weblate.org/browse/pairdrop/pairdrop-spa/${locale}/?q=${keyComplete}`);
|
||||
}
|
||||
|
||||
static escapeHTML(unsafeText) {
|
||||
|
||||
@@ -1,3 +1,23 @@
|
||||
class Logger {
|
||||
|
||||
static debug(message, ...optionalParams) {
|
||||
if (window.debugMode) {
|
||||
console.debug("DEBUG:", message, ...optionalParams);
|
||||
}
|
||||
}
|
||||
static log(message, ...optionalParams) {
|
||||
console.log("LOG:", message, ...optionalParams);
|
||||
}
|
||||
|
||||
static warn(message, ...optionalParams) {
|
||||
console.warn("WARN:", message, ...optionalParams);
|
||||
}
|
||||
|
||||
static error(message, ...optionalParams) {
|
||||
console.error("ERROR:", message, ...optionalParams);
|
||||
}
|
||||
}
|
||||
|
||||
class PairDrop {
|
||||
|
||||
constructor() {
|
||||
@@ -34,14 +54,14 @@ class PairDrop {
|
||||
|
||||
this.initialize()
|
||||
.then(_ => {
|
||||
console.log("Initialization completed.");
|
||||
Logger.log("Initialization completed.");
|
||||
});
|
||||
}
|
||||
|
||||
async initialize() {
|
||||
// Translate page before fading in
|
||||
await this.localization.setInitialTranslation()
|
||||
console.log("Initial translation successful.");
|
||||
Logger.log("Initial translation successful.");
|
||||
|
||||
// Show "Loading..." until connected to WsServer
|
||||
await this.footerUI.showLoading();
|
||||
@@ -56,16 +76,16 @@ class PairDrop {
|
||||
await this.backgroundCanvas.fadeIn();
|
||||
|
||||
// Load deferred assets
|
||||
console.log("Load deferred assets...");
|
||||
Logger.log("Load deferred assets...");
|
||||
await this.loadDeferredAssets();
|
||||
console.log("Loading of deferred assets completed.");
|
||||
Logger.log("Loading of deferred assets completed.");
|
||||
|
||||
console.log("Hydrate UI...");
|
||||
Logger.log("Hydrate UI...");
|
||||
await this.hydrate();
|
||||
console.log("UI hydrated.");
|
||||
Logger.log("UI hydrated.");
|
||||
|
||||
// Evaluate url params as soon as ws is connected
|
||||
console.log("Evaluate URL params as soon as websocket connection is established.");
|
||||
Logger.log("Evaluate URL params as soon as websocket connection is established.");
|
||||
Events.on('ws-connected', _ => this.evaluateUrlParams(), {once: true});
|
||||
}
|
||||
|
||||
@@ -74,14 +94,14 @@ class PairDrop {
|
||||
navigator.serviceWorker
|
||||
.register('service-worker.js')
|
||||
.then(serviceWorker => {
|
||||
console.log('Service Worker registered');
|
||||
Logger.log('Service Worker registered');
|
||||
window.serviceWorker = serviceWorker
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
onPwaInstallable(e) {
|
||||
if (!window.matchMedia('(display-mode: minimal-ui)').matches) {
|
||||
if (!window.matchMedia('(display-mode: standalone)').matches) {
|
||||
// only display install btn when not installed
|
||||
this.$headerInstallBtn.removeAttribute('hidden');
|
||||
this.$headerInstallBtn.addEventListener('click', () => {
|
||||
@@ -117,6 +137,7 @@ class PairDrop {
|
||||
let stylesheet = document.createElement('link');
|
||||
stylesheet.rel = 'preload';
|
||||
stylesheet.as = 'style';
|
||||
stylesheet.defer = true;
|
||||
stylesheet.href = url;
|
||||
stylesheet.onload = _ => {
|
||||
stylesheet.onload = null;
|
||||
@@ -133,10 +154,10 @@ class PairDrop {
|
||||
return new Promise( async (resolve) => {
|
||||
try {
|
||||
await this.loadStyleSheet(url);
|
||||
console.log(`Stylesheet loaded successfully: ${url}`);
|
||||
Logger.log(`Stylesheet loaded successfully: ${url}`);
|
||||
resolve();
|
||||
} catch (error) {
|
||||
console.error('Error loading stylesheet:', error);
|
||||
Logger.error('Error loading stylesheet:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -156,10 +177,10 @@ class PairDrop {
|
||||
return new Promise( async (resolve) => {
|
||||
try {
|
||||
await this.loadScript(url);
|
||||
console.log(`Script loaded successfully: ${url}`);
|
||||
Logger.log(`Script loaded successfully: ${url}`);
|
||||
resolve();
|
||||
} catch (error) {
|
||||
console.error('Error loading script:', error);
|
||||
Logger.error('Error loading script:', error);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -229,12 +250,17 @@ class PairDrop {
|
||||
this.publicRoomDialog._createPublicRoom();
|
||||
}
|
||||
}
|
||||
else if (urlParams.has("debug") && urlParams.get("debug") === "true") {
|
||||
window.debugMode = true;
|
||||
}
|
||||
|
||||
// remove url params from url
|
||||
const urlWithoutParams = getUrlWithoutArguments();
|
||||
window.history.replaceState({}, "Rewrite URL", urlWithoutParams);
|
||||
if (!window.debugMode) {
|
||||
// remove url params from url
|
||||
const urlWithoutParams = getUrlWithoutArguments();
|
||||
window.history.replaceState({}, "Rewrite URL", urlWithoutParams);
|
||||
}
|
||||
|
||||
console.log("URL params evaluated.");
|
||||
Logger.log("URL params evaluated.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -7,19 +7,18 @@ class PersistentStorage {
|
||||
const DBOpenRequest = window.indexedDB.open('pairdrop_store', 5);
|
||||
DBOpenRequest.onerror = e => {
|
||||
PersistentStorage.logBrowserNotCapable();
|
||||
console.log('Error initializing database: ');
|
||||
console.log(e)
|
||||
Logger.error('Error initializing database:', e);
|
||||
};
|
||||
DBOpenRequest.onsuccess = _ => {
|
||||
console.log('Database initialised.');
|
||||
Logger.debug('Database initialised.');
|
||||
};
|
||||
DBOpenRequest.onupgradeneeded = async e => {
|
||||
const db = e.target.result;
|
||||
const txn = e.target.transaction;
|
||||
|
||||
db.onerror = e => console.log('Error loading database: ' + e);
|
||||
db.onerror = e => Logger.error('Error loading database:', e);
|
||||
|
||||
console.log(`Upgrading IndexedDB database from version ${e.oldVersion} to version ${e.newVersion}`);
|
||||
Logger.debug(`Upgrading IndexedDB database from version ${e.oldVersion} to version ${e.newVersion}`);
|
||||
|
||||
if (e.oldVersion === 0) {
|
||||
// initiate v1
|
||||
@@ -54,7 +53,7 @@ class PersistentStorage {
|
||||
}
|
||||
|
||||
static logBrowserNotCapable() {
|
||||
console.log("This browser does not support IndexedDB. Paired devices will be gone after the browser is closed.");
|
||||
Logger.log("This browser does not support IndexedDB. Paired devices will be gone after the browser is closed.");
|
||||
}
|
||||
|
||||
static set(key, value) {
|
||||
@@ -66,7 +65,7 @@ class PersistentStorage {
|
||||
const objectStore = transaction.objectStore('keyval');
|
||||
const objectStoreRequest = objectStore.put(value, key);
|
||||
objectStoreRequest.onsuccess = _ => {
|
||||
console.log(`Request successful. Added key-pair: ${key} - ${value}`);
|
||||
Logger.debug(`Request successful. Added key-pair: ${key} - ${value}`);
|
||||
resolve(value);
|
||||
};
|
||||
}
|
||||
@@ -85,7 +84,7 @@ class PersistentStorage {
|
||||
const objectStore = transaction.objectStore('keyval');
|
||||
const objectStoreRequest = objectStore.get(key);
|
||||
objectStoreRequest.onsuccess = _ => {
|
||||
console.log(`Request successful. Retrieved key-pair: ${key} - ${objectStoreRequest.result}`);
|
||||
Logger.debug(`Request successful. Retrieved key-pair: ${key} - ${objectStoreRequest.result}`);
|
||||
resolve(objectStoreRequest.result);
|
||||
}
|
||||
}
|
||||
@@ -104,7 +103,7 @@ class PersistentStorage {
|
||||
const objectStore = transaction.objectStore('keyval');
|
||||
const objectStoreRequest = objectStore.delete(key);
|
||||
objectStoreRequest.onsuccess = _ => {
|
||||
console.log(`Request successful. Deleted key: ${key}`);
|
||||
Logger.debug(`Request successful. Deleted key: ${key}`);
|
||||
resolve();
|
||||
};
|
||||
}
|
||||
@@ -128,7 +127,7 @@ class PersistentStorage {
|
||||
'auto_accept': false
|
||||
});
|
||||
objectStoreRequest.onsuccess = e => {
|
||||
console.log(`Request successful. RoomSecret added: ${e.target.result}`);
|
||||
Logger.debug(`Request successful. RoomSecret added: ${e.target.result}`);
|
||||
resolve();
|
||||
}
|
||||
}
|
||||
@@ -145,7 +144,7 @@ class PersistentStorage {
|
||||
for (let i = 0; i < roomSecrets.length; i++) {
|
||||
secrets.push(roomSecrets[i].secret);
|
||||
}
|
||||
console.log(`Request successful. Retrieved ${secrets.length} room_secrets`);
|
||||
Logger.debug(`Request successful. Retrieved ${secrets.length} room_secrets`);
|
||||
return(secrets);
|
||||
} catch (e) {
|
||||
this.logBrowserNotCapable();
|
||||
@@ -182,13 +181,13 @@ class PersistentStorage {
|
||||
objectStoreRequestKey.onsuccess = e => {
|
||||
const key = e.target.result;
|
||||
if (!key) {
|
||||
console.log(`Nothing to retrieve. Entry for room_secret not existing: ${roomSecret}`);
|
||||
Logger.debug(`Nothing to retrieve. Entry for room_secret not existing: ${roomSecret}`);
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
const objectStoreRequestRetrieval = objectStore.get(key);
|
||||
objectStoreRequestRetrieval.onsuccess = e => {
|
||||
console.log(`Request successful. Retrieved entry for room_secret: ${key}`);
|
||||
Logger.debug(`Request successful. Retrieved entry for room_secret: ${key}`);
|
||||
resolve({
|
||||
"entry": e.target.result,
|
||||
"key": key
|
||||
@@ -215,14 +214,14 @@ class PersistentStorage {
|
||||
const objectStoreRequestKey = objectStore.index("secret").getKey(roomSecret);
|
||||
objectStoreRequestKey.onsuccess = e => {
|
||||
if (!e.target.result) {
|
||||
console.log(`Nothing to delete. room_secret not existing: ${roomSecret}`);
|
||||
Logger.debug(`Nothing to delete. room_secret not existing: ${roomSecret}`);
|
||||
resolve();
|
||||
return;
|
||||
}
|
||||
const key = e.target.result;
|
||||
const objectStoreRequestDeletion = objectStore.delete(key);
|
||||
objectStoreRequestDeletion.onsuccess = _ => {
|
||||
console.log(`Request successful. Deleted room_secret: ${key}`);
|
||||
Logger.debug(`Request successful. Deleted room_secret: ${key}`);
|
||||
resolve(roomSecret);
|
||||
}
|
||||
objectStoreRequestDeletion.onerror = e => {
|
||||
@@ -245,7 +244,7 @@ class PersistentStorage {
|
||||
const objectStore = transaction.objectStore('room_secrets');
|
||||
const objectStoreRequest = objectStore.clear();
|
||||
objectStoreRequest.onsuccess = _ => {
|
||||
console.log('Request successful. All room_secrets cleared');
|
||||
Logger.debug('Request successful. All room_secrets cleared');
|
||||
resolve();
|
||||
};
|
||||
}
|
||||
@@ -255,15 +254,15 @@ class PersistentStorage {
|
||||
})
|
||||
}
|
||||
|
||||
static updateRoomSecretNames(roomSecret, displayName, deviceName) {
|
||||
return this.updateRoomSecret(roomSecret, undefined, displayName, deviceName);
|
||||
static updateRoomSecretDisplayName(roomSecret, displayName) {
|
||||
return this.updateRoomSecret(roomSecret, null, displayName, null);
|
||||
}
|
||||
|
||||
static updateRoomSecretAutoAccept(roomSecret, autoAccept) {
|
||||
return this.updateRoomSecret(roomSecret, undefined, undefined, undefined, autoAccept);
|
||||
return this.updateRoomSecret(roomSecret, null, null, null, autoAccept);
|
||||
}
|
||||
|
||||
static updateRoomSecret(roomSecret, updatedRoomSecret = undefined, updatedDisplayName = undefined, updatedDeviceName = undefined, updatedAutoAccept = undefined) {
|
||||
static updateRoomSecret(roomSecret, updatedRoomSecret = null, updatedDisplayName = null, updatedDeviceName = null, updatedAutoAccept = null) {
|
||||
return new Promise((resolve, reject) => {
|
||||
const DBOpenRequest = window.indexedDB.open('pairdrop_store');
|
||||
DBOpenRequest.onsuccess = e => {
|
||||
@@ -278,16 +277,16 @@ class PersistentStorage {
|
||||
const objectStore = transaction.objectStore('room_secrets');
|
||||
// Do not use `updatedRoomSecret ?? roomSecretEntry.entry.secret` to ensure compatibility with older browsers
|
||||
const updatedRoomSecretEntry = {
|
||||
'secret': updatedRoomSecret !== undefined ? updatedRoomSecret : roomSecretEntry.entry.secret,
|
||||
'display_name': updatedDisplayName !== undefined ? updatedDisplayName : roomSecretEntry.entry.display_name,
|
||||
'device_name': updatedDeviceName !== undefined ? updatedDeviceName : roomSecretEntry.entry.device_name,
|
||||
'auto_accept': updatedAutoAccept !== undefined ? updatedAutoAccept : roomSecretEntry.entry.auto_accept
|
||||
'secret': updatedRoomSecret !== null ? updatedRoomSecret : roomSecretEntry.entry.secret,
|
||||
'display_name': updatedDisplayName !== null ? updatedDisplayName : roomSecretEntry.entry.display_name,
|
||||
'device_name': updatedDeviceName !== null ? updatedDeviceName : roomSecretEntry.entry.device_name,
|
||||
'auto_accept': updatedAutoAccept !== null ? updatedAutoAccept : roomSecretEntry.entry.auto_accept
|
||||
};
|
||||
|
||||
const objectStoreRequestUpdate = objectStore.put(updatedRoomSecretEntry, roomSecretEntry.key);
|
||||
|
||||
objectStoreRequestUpdate.onsuccess = e => {
|
||||
console.log(`Request successful. Updated room_secret: ${roomSecretEntry.key}`);
|
||||
Logger.debug(`Request successful. Updated room_secret: ${roomSecretEntry.key}`);
|
||||
resolve({
|
||||
"entry": updatedRoomSecretEntry,
|
||||
"key": roomSecretEntry.key
|
||||
|
||||
131
public/scripts/sw-file-digester.js
Normal file
131
public/scripts/sw-file-digester.js
Normal file
@@ -0,0 +1,131 @@
|
||||
self.accessHandle = undefined;
|
||||
self.messageQueue = [];
|
||||
self.busy = false;
|
||||
|
||||
|
||||
self.addEventListener('message', async e => {
|
||||
// Put message into queue if busy
|
||||
if (self.busy) {
|
||||
self.messageQueue.push(e.data);
|
||||
return;
|
||||
}
|
||||
|
||||
await digestMessage(e.data);
|
||||
});
|
||||
|
||||
async function digestMessage(message) {
|
||||
self.busy = true;
|
||||
try {
|
||||
switch (message.type) {
|
||||
case "check-support":
|
||||
await checkSupport();
|
||||
break;
|
||||
case "chunk":
|
||||
await onChunk(message.id, message.chunk, message.offset);
|
||||
break;
|
||||
case "get-file":
|
||||
await onGetFile(message.id);
|
||||
break;
|
||||
case "delete-file":
|
||||
await onDeleteFile(message.id);
|
||||
break;
|
||||
case "clear-directory":
|
||||
await onClearDirectory();
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch (e) {
|
||||
self.postMessage({type: "error", error: e});
|
||||
}
|
||||
|
||||
// message is digested. Digest next message.
|
||||
await messageDigested();
|
||||
}
|
||||
|
||||
async function messageDigested() {
|
||||
if (!self.messageQueue.length) {
|
||||
// no chunk in queue -> set flag to false and stop
|
||||
this.busy = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// Digest next message in queue
|
||||
await this.digestMessage(self.messageQueue.pop());
|
||||
}
|
||||
|
||||
async function checkSupport() {
|
||||
try {
|
||||
const accessHandle = await getAccessHandle("test");
|
||||
self.postMessage({type: "support", supported: true});
|
||||
accessHandle.close();
|
||||
}
|
||||
catch (e) {
|
||||
self.postMessage({type: "support", supported: false});
|
||||
}
|
||||
}
|
||||
|
||||
async function getFileHandle(id) {
|
||||
const dirHandle = await navigator.storage.getDirectory();
|
||||
return await dirHandle.getFileHandle(id, {create: true});
|
||||
}
|
||||
|
||||
async function getAccessHandle(id) {
|
||||
const fileHandle = await getFileHandle(id);
|
||||
|
||||
if (!self.accessHandle) {
|
||||
// Create FileSystemSyncAccessHandle on the file.
|
||||
self.accessHandle = await fileHandle.createSyncAccessHandle();
|
||||
}
|
||||
|
||||
return self.accessHandle;
|
||||
}
|
||||
|
||||
async function onChunk(id, chunk, offset) {
|
||||
const accessHandle = await getAccessHandle(id);
|
||||
|
||||
// Write the message to the end of the file.
|
||||
let encodedMessage = new DataView(chunk);
|
||||
accessHandle.write(encodedMessage, { at: offset });
|
||||
|
||||
self.postMessage({type: "chunk-written", offset: offset});
|
||||
}
|
||||
|
||||
async function onGetFile(id) {
|
||||
const fileHandle = await getFileHandle(id);
|
||||
let file = await fileHandle.getFile();
|
||||
|
||||
self.postMessage({type: "file", file: file});
|
||||
}
|
||||
|
||||
async function onDeleteFile(id) {
|
||||
const accessHandle = await getAccessHandle(id);
|
||||
|
||||
// Truncate the file to 0 bytes
|
||||
accessHandle.truncate(0);
|
||||
|
||||
// Persist changes to disk.
|
||||
accessHandle.flush();
|
||||
|
||||
// Always close FileSystemSyncAccessHandle if done.
|
||||
accessHandle.close();
|
||||
|
||||
self.postMessage({type: "file-deleted", id: id});
|
||||
}
|
||||
|
||||
async function onClearDirectory() {
|
||||
const dirHandle = await navigator.storage.getDirectory();
|
||||
|
||||
// Iterate through directory entries and truncate all entries to 0
|
||||
for await (const [id, fileHandle] of dirHandle.entries()) {
|
||||
const accessHandle = await fileHandle.createSyncAccessHandle();
|
||||
|
||||
// Truncate the file to 0 bytes
|
||||
accessHandle.truncate(0);
|
||||
|
||||
// Persist changes to disk.
|
||||
accessHandle.flush();
|
||||
|
||||
// Always close FileSystemSyncAccessHandle if done.
|
||||
accessHandle.close();
|
||||
}
|
||||
}
|
||||
@@ -205,7 +205,7 @@ class FooterUI {
|
||||
this.$displayName.addEventListener('blur', e => this._saveDisplayName(e.target.innerText));
|
||||
|
||||
Events.on('display-name', e => this._onDisplayName(e.detail.displayName));
|
||||
Events.on('self-display-name-changed', e => this._insertDisplayName(e.detail));
|
||||
Events.on('self-display-name-changed', e => this._insertDisplayName(e.detail.displayName));
|
||||
|
||||
// Load saved display name on page load
|
||||
Events.on('ws-connected', _ => this._loadSavedDisplayName());
|
||||
@@ -238,8 +238,8 @@ class FooterUI {
|
||||
|
||||
if (!displayName) return;
|
||||
|
||||
console.log("Retrieved edited display name:", displayName)
|
||||
Events.fire('self-display-name-changed', displayName);
|
||||
Logger.debug("Retrieved edited display name:", displayName)
|
||||
Events.fire('self-display-name-changed', { displayName: displayName });
|
||||
}
|
||||
|
||||
_onDisplayName(displayName){
|
||||
@@ -275,25 +275,25 @@ class FooterUI {
|
||||
Events.fire('notify-user', Localization.getTranslation("notifications.display-name-changed-permanently"));
|
||||
})
|
||||
.catch(_ => {
|
||||
console.log("This browser does not support IndexedDB. Use localStorage instead.");
|
||||
Logger.debug("This browser does not support IndexedDB. Use localStorage instead.");
|
||||
localStorage.setItem('edited_display_name', newDisplayName);
|
||||
Events.fire('notify-user', Localization.getTranslation("notifications.display-name-changed-temporarily"));
|
||||
})
|
||||
.finally(() => {
|
||||
Events.fire('self-display-name-changed', newDisplayName);
|
||||
Events.fire('broadcast-send', {type: 'self-display-name-changed', detail: newDisplayName});
|
||||
Events.fire('self-display-name-changed', { displayName: newDisplayName });
|
||||
Events.fire('broadcast-self-display-name-changed', { displayName: newDisplayName });
|
||||
});
|
||||
}
|
||||
else {
|
||||
PersistentStorage.delete('edited_display_name')
|
||||
.catch(_ => {
|
||||
console.log("This browser does not support IndexedDB. Use localStorage instead.")
|
||||
Logger.debug("This browser does not support IndexedDB. Use localStorage instead.")
|
||||
localStorage.removeItem('edited_display_name');
|
||||
})
|
||||
.finally(() => {
|
||||
Events.fire('notify-user', Localization.getTranslation("notifications.display-name-random-again"));
|
||||
Events.fire('self-display-name-changed', '');
|
||||
Events.fire('broadcast-send', {type: 'self-display-name-changed', detail: ''});
|
||||
Events.fire('self-display-name-changed', { displayName: '' });
|
||||
Events.fire('broadcast-self-display-name-changed', { displayName: '' });
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
1231
public/scripts/ui.js
1231
public/scripts/ui.js
File diff suppressed because it is too large
Load Diff
@@ -62,41 +62,67 @@ window.isMobile = window.iOS || window.android;
|
||||
|
||||
|
||||
// Helper functions
|
||||
|
||||
const audioPlayer = (() => {
|
||||
const blop = document.getElementById('blop');
|
||||
blop.addEventListener('ended', _ => {
|
||||
blop.muted = true
|
||||
});
|
||||
|
||||
|
||||
return {
|
||||
playBlop() {
|
||||
if (window.isMobile) return;
|
||||
|
||||
blop.muted = false;
|
||||
blop.play();
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
const zipper = (() => {
|
||||
|
||||
let zipWriter;
|
||||
return {
|
||||
createNewZipWriter() {
|
||||
zipWriter = new zip.ZipWriter(new zip.BlobWriter("application/zip"), { bufferedWrite: true, level: 0 });
|
||||
},
|
||||
addFile(file, options) {
|
||||
return zipWriter.add(file.name, new zip.BlobReader(file), options);
|
||||
},
|
||||
async getBlobURL() {
|
||||
if (zipWriter) {
|
||||
const blobURL = URL.createObjectURL(await zipWriter.close());
|
||||
zipWriter = null;
|
||||
return blobURL;
|
||||
async getObjectUrlOfZipFile(files, onZipProgressCallback){
|
||||
try {
|
||||
const zipWriter = new zip.ZipWriter(new zip.BlobWriter("application/zip"));
|
||||
|
||||
let bytesProcessed = 0;
|
||||
for (let i = 0; i < files.length; i++) {
|
||||
await zipWriter.add(
|
||||
files[i].name,
|
||||
new zip.BlobReader(files[i]),
|
||||
{
|
||||
onprogress: (progress) => onZipProgressCallback(bytesProcessed + progress)
|
||||
}
|
||||
);
|
||||
bytesProcessed += files[i].size;
|
||||
}
|
||||
|
||||
return URL.createObjectURL(await zipWriter.close());
|
||||
}
|
||||
else {
|
||||
throw new Error("Zip file closed");
|
||||
}
|
||||
},
|
||||
async getZipFile(filename = "archive.zip") {
|
||||
if (zipWriter) {
|
||||
const file = new File([await zipWriter.close()], filename, {type: "application/zip"});
|
||||
zipWriter = null;
|
||||
return file;
|
||||
}
|
||||
else {
|
||||
throw new Error("Zip file closed");
|
||||
catch (e) {
|
||||
Logger.error(e);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
async getEntries(file, options) {
|
||||
return await (new zip.ZipReader(new zip.BlobReader(file))).getEntries(options);
|
||||
try {
|
||||
return await (new zip.ZipReader(new zip.BlobReader(file))).getEntries(options);
|
||||
}
|
||||
catch (e) {
|
||||
Logger.error(e);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
async getData(entry, options) {
|
||||
return await entry.getData(new zip.BlobWriter(), options);
|
||||
try {
|
||||
return await entry.getData(new zip.BlobWriter(), options);
|
||||
}
|
||||
catch (e) {
|
||||
Logger.error(e);
|
||||
return false;
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
@@ -521,7 +547,7 @@ function getThumbnailAsDataUrl(file, width = undefined, height = undefined, qual
|
||||
let dataUrl = canvas.toDataURL("image/jpeg", quality);
|
||||
resolve(dataUrl);
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
Logger.error(e);
|
||||
reject(new Error(`Could not create an image thumbnail from type ${file.type}`));
|
||||
}
|
||||
})
|
||||
@@ -593,4 +619,27 @@ function isUrlValid(url) {
|
||||
catch (e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// polyfill for crypto.randomUUID()
|
||||
// Credits: @Briguy37 - https://stackoverflow.com/a/8809472/14678591
|
||||
function generateUUID() {
|
||||
return crypto && crypto.randomUUID()
|
||||
? crypto.randomUUID()
|
||||
: () => {
|
||||
let
|
||||
d = new Date().getTime(),
|
||||
d2 = ((typeof performance !== 'undefined') && performance.now && (performance.now() * 1000)) || 0;
|
||||
return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, c => {
|
||||
let r = Math.random() * 16;
|
||||
if (d > 0) {
|
||||
r = (d + r) % 16 | 0;
|
||||
d = Math.floor(d / 16);
|
||||
} else {
|
||||
r = (d2 + r) % 16 | 0;
|
||||
d2 = Math.floor(d2 / 16);
|
||||
}
|
||||
return (c == 'x' ? r : (r & 0x7 | 0x8)).toString(16);
|
||||
});
|
||||
};
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
const cacheVersion = 'v1.10.8';
|
||||
const cacheVersion = 'v1.10.9';
|
||||
const cacheTitle = `pairdrop-cache-${cacheVersion}`;
|
||||
const forceFetch = false; // FOR DEVELOPMENT: Set to true to always update assets instead of using cached versions
|
||||
const relativePathsToCache = [
|
||||
@@ -27,11 +27,14 @@ const relativePathsToCache = [
|
||||
'images/android-chrome-512x512-maskable.png',
|
||||
'images/apple-touch-icon.png',
|
||||
'lang/ar.json',
|
||||
'lang/be.json',
|
||||
'lang/ca.json',
|
||||
'lang/da.json',
|
||||
'lang/de.json',
|
||||
'lang/en.json',
|
||||
'lang/es.json',
|
||||
'lang/fr.json',
|
||||
'lang/he.json',
|
||||
'lang/hu.json',
|
||||
'lang/id.json',
|
||||
'lang/it.json',
|
||||
|
||||
@@ -104,6 +104,8 @@ x-peer {
|
||||
padding: 8px;
|
||||
align-content: start;
|
||||
flex-wrap: wrap;
|
||||
transition: transform 150ms;
|
||||
will-change: transform;
|
||||
}
|
||||
|
||||
x-peer input[type="file"] {
|
||||
@@ -121,8 +123,6 @@ x-peer label {
|
||||
x-peer x-icon {
|
||||
--icon-size: 40px;
|
||||
margin-bottom: 4px;
|
||||
transition: transform 150ms;
|
||||
will-change: transform;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
@@ -148,7 +148,7 @@ x-peer:not(.type-ip):not(.type-secret).type-public-id .icon-wrapper {
|
||||
.highlight-wrapper {
|
||||
align-self: center;
|
||||
align-items: center;
|
||||
margin: 7px auto 0;
|
||||
margin: 10px auto 0;
|
||||
height: 6px;
|
||||
}
|
||||
|
||||
@@ -187,14 +187,16 @@ x-peer:not(.type-public-id) .highlight-room-public-id {
|
||||
display: none;
|
||||
}
|
||||
|
||||
x-peer:not([status]):hover x-icon,
|
||||
x-peer:not([status]):focus x-icon {
|
||||
x-peer:is(:not([status]), [status$=-complete], [status=error]):hover,
|
||||
x-peer:is(:not([status]), [status$=-complete], [status=error]):focus {
|
||||
transform: scale(1.05);
|
||||
}
|
||||
|
||||
x-peer[status] x-icon {
|
||||
x-peer[status]:not([status$=-complete]) x-icon {
|
||||
box-shadow: none;
|
||||
opacity: 0.8;
|
||||
}
|
||||
|
||||
x-peer[status] {
|
||||
transform: scale(1);
|
||||
}
|
||||
|
||||
@@ -237,7 +239,7 @@ x-peer.ws-peer .highlight-wrapper {
|
||||
|
||||
.status,
|
||||
.device-name {
|
||||
opacity: 0.7;
|
||||
color: color-mix(in srgb, rgb(var(--text-color)) 30%, grey);
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
@@ -246,14 +248,22 @@ x-peer[status] .device-name {
|
||||
display: none;
|
||||
}
|
||||
|
||||
x-peer[status] {
|
||||
x-peer[status]:not([status$=-complete]):not([status=error]) {
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
x-peer x-icon {
|
||||
x-peer {
|
||||
animation: pop 600ms ease-out 1;
|
||||
}
|
||||
|
||||
x-peer[status$=-complete] .status {
|
||||
color: var(--primary-color);
|
||||
}
|
||||
|
||||
x-peer[status=error] .status {
|
||||
color: var(--error-color);
|
||||
}
|
||||
|
||||
@keyframes pop {
|
||||
0% {
|
||||
transform: scale(0.7);
|
||||
@@ -744,7 +754,6 @@ x-dialog .dialog-subheader {
|
||||
top: -8px;
|
||||
clip: rect(0px, 80px, 80px, 40px);
|
||||
--progress: rotate(0deg);
|
||||
transition: transform 200ms;
|
||||
}
|
||||
|
||||
.circle {
|
||||
@@ -758,6 +767,10 @@ x-dialog .dialog-subheader {
|
||||
transform: var(--progress);
|
||||
}
|
||||
|
||||
.animate .circle {
|
||||
transition: transform 200ms linear;
|
||||
}
|
||||
|
||||
.over50 {
|
||||
clip: rect(auto, auto, auto, auto);
|
||||
}
|
||||
|
||||
@@ -924,6 +924,7 @@ x-peers:empty~x-instructions {
|
||||
body {
|
||||
/* Constant colors */
|
||||
--primary-color: #4285f4;
|
||||
--error-color: #ff6b6b;
|
||||
--paired-device-color: #00a69c;
|
||||
--public-room-color: #ed9d01;
|
||||
--accent-color: var(--primary-color);
|
||||
|
||||
@@ -44,15 +44,18 @@ export default class Peer {
|
||||
_setIP(request) {
|
||||
if (request.headers['cf-connecting-ip']) {
|
||||
this.ip = request.headers['cf-connecting-ip'].split(/\s*,\s*/)[0];
|
||||
} else if (request.headers['x-forwarded-for']) {
|
||||
}
|
||||
else if (request.headers['x-forwarded-for']) {
|
||||
this.ip = request.headers['x-forwarded-for'].split(/\s*,\s*/)[0];
|
||||
} else {
|
||||
this.ip = request.connection.remoteAddress;
|
||||
}
|
||||
else {
|
||||
this.ip = request.socket.remoteAddress ?? '';
|
||||
}
|
||||
|
||||
// remove the prefix used for IPv4-translated addresses
|
||||
if (this.ip.substring(0,7) === "::ffff:")
|
||||
if (this.ip.substring(0,7) === "::ffff:") {
|
||||
this.ip = this.ip.substring(7);
|
||||
}
|
||||
|
||||
let ipv6_was_localized = false;
|
||||
if (this.conf.ipv6Localize && this.ip.includes(':')) {
|
||||
|
||||
@@ -89,22 +89,12 @@ export default class PairDropWsServer {
|
||||
this._onLeavePublicRoom(sender);
|
||||
break;
|
||||
case 'signal':
|
||||
this._signalAndRelay(sender, message);
|
||||
this._signalAndWsRelay(sender, message);
|
||||
break;
|
||||
case 'request':
|
||||
case 'header':
|
||||
case 'partition':
|
||||
case 'partition-received':
|
||||
case 'progress':
|
||||
case 'files-transfer-response':
|
||||
case 'file-transfer-complete':
|
||||
case 'message-transfer-complete':
|
||||
case 'text':
|
||||
case 'display-name-changed':
|
||||
case 'ws-chunk':
|
||||
case 'ws-relay':
|
||||
// relay ws-fallback
|
||||
if (this._conf.wsFallback) {
|
||||
this._signalAndRelay(sender, message);
|
||||
this._signalAndWsRelay(sender, message);
|
||||
}
|
||||
else {
|
||||
console.log("Websocket fallback is not activated on this instance.")
|
||||
@@ -112,7 +102,7 @@ export default class PairDropWsServer {
|
||||
}
|
||||
}
|
||||
|
||||
_signalAndRelay(sender, message) {
|
||||
_signalAndWsRelay(sender, message) {
|
||||
const room = message.roomType === 'ip'
|
||||
? sender.ip
|
||||
: message.roomId;
|
||||
@@ -261,7 +251,6 @@ export default class PairDropWsServer {
|
||||
return;
|
||||
}
|
||||
|
||||
this._leavePublicRoom(sender);
|
||||
this._joinPublicRoom(sender, message.publicRoomId);
|
||||
}
|
||||
|
||||
@@ -322,7 +311,7 @@ export default class PairDropWsServer {
|
||||
|
||||
_joinPublicRoom(peer, publicRoomId) {
|
||||
// prevent joining of 2 public rooms simultaneously
|
||||
this._leavePublicRoom(peer);
|
||||
this._leavePublicRoom(peer, true);
|
||||
|
||||
this._joinRoom(peer, 'public-id', publicRoomId);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user