mirror of
https://github.com/schlagmichdoch/PairDrop.git
synced 2026-04-17 23:02:15 +00:00
Compare commits
15 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c3e92d7d4c | ||
|
|
b90924af68 | ||
|
|
4f80ab4401 | ||
|
|
f299c90f47 | ||
|
|
6737dcacf7 | ||
|
|
5d39bf4a76 | ||
|
|
5c70c873ab | ||
|
|
b336c75b72 | ||
|
|
b3f5619f2d | ||
|
|
939ca3d35d | ||
|
|
c2ee459231 | ||
|
|
c08b324d6a | ||
|
|
d3a623d352 | ||
|
|
d8f9532039 | ||
|
|
9847feeb52 |
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/**
|
**Bug occurs on official PairDrop instance https://pairdrop.net/**
|
||||||
No | Yes
|
No | Yes
|
||||||
Version: v1.10.1
|
Version: v1.10.2
|
||||||
|
|
||||||
**Bug occurs on self-hosted PairDrop instance**
|
**Bug occurs on self-hosted PairDrop instance**
|
||||||
No | Yes
|
No | Yes
|
||||||
@@ -44,7 +44,7 @@ No | Yes
|
|||||||
**Self-Hosted Setup**
|
**Self-Hosted Setup**
|
||||||
Proxy: Nginx | Apache2
|
Proxy: Nginx | Apache2
|
||||||
Deployment: docker run | docker compose | npm run start:prod
|
Deployment: docker run | docker compose | npm run start:prod
|
||||||
Version: v1.10.1
|
Version: v1.10.2
|
||||||
|
|
||||||
**Additional context**
|
**Additional context**
|
||||||
Add any other context about the problem here.
|
Add any other context about the problem here.
|
||||||
|
|||||||
@@ -399,7 +399,8 @@ RTC_CONFIG="rtc_config.json"
|
|||||||
|
|
||||||
You can host an instance that uses another signaling server
|
You can host an instance that uses another signaling server
|
||||||
This can be useful if you don't want to trust the client files that are hosted on another instance but still want to connect to devices that use https://pairdrop.net.
|
This can be useful if you don't want to trust the client files that are hosted on another instance but still want to connect to devices that use https://pairdrop.net.
|
||||||
### Host Websocket Server (for VPN)
|
|
||||||
|
### Specify Signaling Server
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
SIGNALING_SERVER="pairdrop.net"
|
SIGNALING_SERVER="pairdrop.net"
|
||||||
@@ -415,9 +416,9 @@ SIGNALING_SERVER="pairdrop.net"
|
|||||||
> E.g. host your own client files under *pairdrop.your-domain.com* but use the official signaling server under *pairdrop.net*
|
> E.g. host your own client files under *pairdrop.your-domain.com* but use the official signaling server under *pairdrop.net*
|
||||||
> This way devices connecting to *pairdrop.your-domain.com* and *pairdrop.net* can discover each other.
|
> This way devices connecting to *pairdrop.your-domain.com* and *pairdrop.net* can discover each other.
|
||||||
>
|
>
|
||||||
> Beware that the version of your PairDrop server is compatible with the version of the signaling server.
|
> Beware that the version of your PairDrop server must be compatible with the version of the signaling server.
|
||||||
>
|
>
|
||||||
> `WS_SERVER` must be a valid url without the protocol prefix.
|
> `SIGNALING_SERVER` must be a valid url without the protocol prefix.
|
||||||
> Examples of valid values: `pairdrop.net`, `pairdrop.your-domain.com:3000`, `your-domain.com/pairdrop`
|
> Examples of valid values: `pairdrop.net`, `pairdrop.your-domain.com:3000`, `your-domain.com/pairdrop`
|
||||||
|
|
||||||
<br>
|
<br>
|
||||||
|
|||||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
|||||||
{
|
{
|
||||||
"name": "pairdrop",
|
"name": "pairdrop",
|
||||||
"version": "1.10.1",
|
"version": "1.10.2",
|
||||||
"lockfileVersion": 2,
|
"lockfileVersion": 2,
|
||||||
"requires": true,
|
"requires": true,
|
||||||
"packages": {
|
"packages": {
|
||||||
"": {
|
"": {
|
||||||
"name": "pairdrop",
|
"name": "pairdrop",
|
||||||
"version": "1.10.1",
|
"version": "1.10.2",
|
||||||
"license": "ISC",
|
"license": "ISC",
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"express": "^4.18.2",
|
"express": "^4.18.2",
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "pairdrop",
|
"name": "pairdrop",
|
||||||
"version": "1.10.1",
|
"version": "1.10.2",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"description": "",
|
"description": "",
|
||||||
"main": "server/index.js",
|
"main": "server/index.js",
|
||||||
|
|||||||
@@ -225,6 +225,11 @@
|
|||||||
<span> - </span>
|
<span> - </span>
|
||||||
<span>(Italian)</span>
|
<span>(Italian)</span>
|
||||||
</button>
|
</button>
|
||||||
|
<button class="btn fw wrap" value="kn">
|
||||||
|
<span>ಕನ್ನಡ</span>
|
||||||
|
<span> - </span>
|
||||||
|
<span>(Kannada)</span>
|
||||||
|
</button>
|
||||||
<button class="btn fw wrap" value="nl">
|
<button class="btn fw wrap" value="nl">
|
||||||
<span>Nederlands</span>
|
<span>Nederlands</span>
|
||||||
<span> - </span>
|
<span> - </span>
|
||||||
@@ -577,7 +582,7 @@
|
|||||||
</svg>
|
</svg>
|
||||||
<div class="title-wrapper" dir="ltr">
|
<div class="title-wrapper" dir="ltr">
|
||||||
<h1>PairDrop</h1>
|
<h1>PairDrop</h1>
|
||||||
<div class="font-subheading">v1.10.1</div>
|
<div class="font-subheading">v1.10.2</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="font-subheading" data-i18n-key="about.claim" data-i18n-attrs="text"></div>
|
<div class="font-subheading" data-i18n-key="about.claim" data-i18n-attrs="text"></div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@@ -734,10 +739,10 @@
|
|||||||
</symbol>
|
</symbol>
|
||||||
</svg>
|
</svg>
|
||||||
<!-- Scripts -->
|
<!-- Scripts -->
|
||||||
<script src="scripts/localization.js"></script>
|
<script src="scripts/localization.js" defer></script>
|
||||||
<script src="scripts/persistent-storage.js"></script>
|
<script src="scripts/persistent-storage.js" defer></script>
|
||||||
<script src="scripts/ui-main.js"></script>
|
<script src="scripts/ui-main.js" defer></script>
|
||||||
<script src="scripts/main.js"></script>
|
<script src="scripts/main.js" defer></script>
|
||||||
<!-- Sounds -->
|
<!-- Sounds -->
|
||||||
<audio id="blop" autobuffer="true">
|
<audio id="blop" autobuffer="true">
|
||||||
<source src="sounds/blop.mp3" type="audio/mpeg">
|
<source src="sounds/blop.mp3" type="audio/mpeg">
|
||||||
|
|||||||
@@ -12,7 +12,8 @@
|
|||||||
"cancel-share-mode": "Fertig",
|
"cancel-share-mode": "Fertig",
|
||||||
"language-selector_title": "Sprache Wählen",
|
"language-selector_title": "Sprache Wählen",
|
||||||
"join-public-room_title": "Öffentlichen Raum temporär betreten",
|
"join-public-room_title": "Öffentlichen Raum temporär betreten",
|
||||||
"edit-share-mode": "Bearbeiten"
|
"edit-share-mode": "Bearbeiten",
|
||||||
|
"expand_title": "Schaltflächenzeile ausklappen"
|
||||||
},
|
},
|
||||||
"dialogs": {
|
"dialogs": {
|
||||||
"share": "Teilen",
|
"share": "Teilen",
|
||||||
@@ -81,7 +82,11 @@
|
|||||||
"close-about_aria-label": "Schließe Über PairDrop",
|
"close-about_aria-label": "Schließe Über PairDrop",
|
||||||
"github_title": "PairDrop auf GitHub",
|
"github_title": "PairDrop auf GitHub",
|
||||||
"buy-me-a-coffee_title": "Kauf mir einen Kaffee!",
|
"buy-me-a-coffee_title": "Kauf mir einen Kaffee!",
|
||||||
"claim": "Der einfachste Weg, Dateien zwischen Geräten zu übertragen"
|
"claim": "Der einfachste Weg, Dateien zwischen Geräten zu übertragen",
|
||||||
|
"bluesky_title": "Folge uns auf BlueSky",
|
||||||
|
"privacypolicy_title": "Öffne unsere Datenschutzerklärung",
|
||||||
|
"mastodon_title": "Schreibe über PairDrop auf Mastodon",
|
||||||
|
"custom_title": "Folge uns"
|
||||||
},
|
},
|
||||||
"footer": {
|
"footer": {
|
||||||
"known-as": "Du wirst angezeigt als:",
|
"known-as": "Du wirst angezeigt als:",
|
||||||
|
|||||||
@@ -11,7 +11,9 @@
|
|||||||
"join-public-room_title": "Unirse a una sala pública temporalmente",
|
"join-public-room_title": "Unirse a una sala pública temporalmente",
|
||||||
"notification_title": "Activar notificaciones",
|
"notification_title": "Activar notificaciones",
|
||||||
"edit-paired-devices_title": "Editar dispositivos emparejados",
|
"edit-paired-devices_title": "Editar dispositivos emparejados",
|
||||||
"theme-light_title": "Siempre usar tema claro"
|
"theme-light_title": "Siempre usar tema claro",
|
||||||
|
"expand_title": "Ampliar la fila de botones de la cabecera",
|
||||||
|
"edit-share-mode": "Editar"
|
||||||
},
|
},
|
||||||
"footer": {
|
"footer": {
|
||||||
"webrtc": "si WebRTC no está disponible.",
|
"webrtc": "si WebRTC no está disponible.",
|
||||||
@@ -73,9 +75,9 @@
|
|||||||
},
|
},
|
||||||
"instructions": {
|
"instructions": {
|
||||||
"x-instructions_mobile": "Toque para enviar archivos o toque prologádamente para enviar un mensaje",
|
"x-instructions_mobile": "Toque para enviar archivos o toque prologádamente para enviar un mensaje",
|
||||||
"x-instructions-share-mode_desktop": "Haga clic para enviar",
|
"x-instructions-share-mode_desktop": "Haga clic para enviar {{descriptor}}",
|
||||||
"activate-share-mode-and-other-files-plural": "y {{count}} archivos diferentes",
|
"activate-share-mode-and-other-files-plural": "y {{count}} archivos diferentes",
|
||||||
"x-instructions-share-mode_mobile": "Toca para enviar",
|
"x-instructions-share-mode_mobile": "Toque para enviar {{descriptor}}",
|
||||||
"activate-share-mode-base": "Abra PairDrop en otros dispositivos para enviar",
|
"activate-share-mode-base": "Abra PairDrop en otros dispositivos para enviar",
|
||||||
"no-peers-subtitle": "Empareje dispositivos o ingrese a una sala pública para que lo puedan encontrar en otras redes",
|
"no-peers-subtitle": "Empareje dispositivos o ingrese a una sala pública para que lo puedan encontrar en otras redes",
|
||||||
"activate-share-mode-shared-text": "texto compartido",
|
"activate-share-mode-shared-text": "texto compartido",
|
||||||
@@ -84,7 +86,10 @@
|
|||||||
"x-instructions_data-drop-peer": "Liberar para enviar a un par",
|
"x-instructions_data-drop-peer": "Liberar para enviar a un par",
|
||||||
"x-instructions_data-drop-bg": "Liberar para seleccionar destinatario",
|
"x-instructions_data-drop-bg": "Liberar para seleccionar destinatario",
|
||||||
"no-peers_data-drop-bg": "Liberar para seleccionar destinatario",
|
"no-peers_data-drop-bg": "Liberar para seleccionar destinatario",
|
||||||
"webrtc-requirement": "Para utilizar esta instancia de PairDrop, ¡WebRTC debe estar activado!"
|
"webrtc-requirement": "Para utilizar esta instancia de PairDrop, ¡WebRTC debe estar activado!",
|
||||||
|
"activate-share-mode-shared-files-plural": "{{count}} archivos compartidos",
|
||||||
|
"activate-share-mode-shared-file": "archivo compartido",
|
||||||
|
"activate-share-mode-and-other-file": "y 1 archivo más"
|
||||||
},
|
},
|
||||||
"peer-ui": {
|
"peer-ui": {
|
||||||
"processing": "Procesando…",
|
"processing": "Procesando…",
|
||||||
@@ -96,7 +101,7 @@
|
|||||||
"transferring": "Transferiendo…"
|
"transferring": "Transferiendo…"
|
||||||
},
|
},
|
||||||
"dialogs": {
|
"dialogs": {
|
||||||
"base64-paste-to-send": "Pegar aquí para enviar {{type}}",
|
"base64-paste-to-send": "Pegar el portapapeles aquí para compartir {{type}}",
|
||||||
"auto-accept-instructions-2": "para aceptar automáticamente todos los archivos enviados desde ese dispositivo.",
|
"auto-accept-instructions-2": "para aceptar automáticamente todos los archivos enviados desde ese dispositivo.",
|
||||||
"receive-text-title": "Mensaje Recibido",
|
"receive-text-title": "Mensaje Recibido",
|
||||||
"edit-paired-devices-title": "Editar Dispositivos Emparejados",
|
"edit-paired-devices-title": "Editar Dispositivos Emparejados",
|
||||||
@@ -112,7 +117,7 @@
|
|||||||
"join": "Unirse",
|
"join": "Unirse",
|
||||||
"title-image-plural": "Imágenes",
|
"title-image-plural": "Imágenes",
|
||||||
"send": "Enviar",
|
"send": "Enviar",
|
||||||
"base64-tap-to-paste": "Toca aquí para pegar {{type}}",
|
"base64-tap-to-paste": "Pulse aquí para compartir {{type}}",
|
||||||
"base64-text": "texto",
|
"base64-text": "texto",
|
||||||
"copy": "Copiar",
|
"copy": "Copiar",
|
||||||
"file-other-description-image": "y una imagen mas",
|
"file-other-description-image": "y una imagen mas",
|
||||||
@@ -146,7 +151,15 @@
|
|||||||
"message_title": "Insertar el mensaje a enviar",
|
"message_title": "Insertar el mensaje a enviar",
|
||||||
"pair-devices-qr-code_title": "Haz clic para copiar el enlace para emparejar este dispositivo",
|
"pair-devices-qr-code_title": "Haz clic para copiar el enlace para emparejar este dispositivo",
|
||||||
"public-room-qr-code_title": "Haz clic para copiar el enlace a la sala pública",
|
"public-room-qr-code_title": "Haz clic para copiar el enlace a la sala pública",
|
||||||
"message_placeholder": "Texto"
|
"message_placeholder": "Texto",
|
||||||
|
"close-toast_title": "Cerrar la notificación",
|
||||||
|
"share-text-checkbox": "Mostrar siempre este cuadro de diálogo al compartir texto",
|
||||||
|
"base64-title-files": "Compartir archivos",
|
||||||
|
"approve": "aprobar",
|
||||||
|
"paired-device-removed": "Se ha eliminado el dispositivo emparejado.",
|
||||||
|
"share-text-title": "Compartir un mensaje de texto",
|
||||||
|
"share-text-subtitle": "Edita el mensaje antes de enviarlo:",
|
||||||
|
"base64-title-text": "Compartir el texto"
|
||||||
},
|
},
|
||||||
"about": {
|
"about": {
|
||||||
"claim": "La forma más sencilla de transferir archivos entre dispositivos",
|
"claim": "La forma más sencilla de transferir archivos entre dispositivos",
|
||||||
@@ -154,7 +167,11 @@
|
|||||||
"close-about_aria-label": "Cerrar Sobre PairDrop",
|
"close-about_aria-label": "Cerrar Sobre PairDrop",
|
||||||
"buy-me-a-coffee_title": "¡Cómprame un café!",
|
"buy-me-a-coffee_title": "¡Cómprame un café!",
|
||||||
"github_title": "PairDrop en GitHub",
|
"github_title": "PairDrop en GitHub",
|
||||||
"faq_title": "Preguntas frecuentes"
|
"faq_title": "Preguntas frecuentes",
|
||||||
|
"bluesky_title": "Síganos en BlueSky",
|
||||||
|
"privacypolicy_title": "Abrir nuestra política de privacidad",
|
||||||
|
"mastodon_title": "Escriba sobre PairDrop en Mastodon",
|
||||||
|
"custom_title": "Síguenos en"
|
||||||
},
|
},
|
||||||
"document-titles": {
|
"document-titles": {
|
||||||
"file-transfer-requested": "Transferencia de archivos solicitada",
|
"file-transfer-requested": "Transferencia de archivos solicitada",
|
||||||
|
|||||||
@@ -11,11 +11,13 @@
|
|||||||
"edit-paired-devices_title": "ಜೋಡಿಯಾಗಿರುವ ಸಾಧನಗಳನ್ನು ಎಡಿಟ್ ಮಾಡಿ",
|
"edit-paired-devices_title": "ಜೋಡಿಯಾಗಿರುವ ಸಾಧನಗಳನ್ನು ಎಡಿಟ್ ಮಾಡಿ",
|
||||||
"language-selector_title": "ಭಾಷೆಯನ್ನು ಆಯ್ಕೆ ಮಾಡಿ",
|
"language-selector_title": "ಭಾಷೆಯನ್ನು ಆಯ್ಕೆ ಮಾಡಿ",
|
||||||
"about_aria-label": "PairDrop ಕುರಿತು ಪುಟವನ್ನು ತೆರೆಯಿರಿ",
|
"about_aria-label": "PairDrop ಕುರಿತು ಪುಟವನ್ನು ತೆರೆಯಿರಿ",
|
||||||
"theme-light_title": "ಯಾವಾಗಲೂ ಲೈಟ್ ಥೀಮ್ ಅನ್ನು ಬಳಸಿ"
|
"theme-light_title": "ಯಾವಾಗಲೂ ಲೈಟ್ ಥೀಮ್ ಅನ್ನು ಬಳಸಿ",
|
||||||
|
"edit-share-mode": "ಎಡಿಟ್ ಮಾಡಿ",
|
||||||
|
"cancel-share-mode": "ರದ್ದುಗೊಳಿಸಿ"
|
||||||
},
|
},
|
||||||
"dialogs": {
|
"dialogs": {
|
||||||
"message_placeholder": "ಪಠ್ಯ",
|
"message_placeholder": "ಪಠ್ಯ",
|
||||||
"base64-paste-to-send": "{{type}} ಕಳುಹಿಸಲು ಇಲ್ಲಿ ಅಂಟಿಸಿ",
|
"base64-paste-to-send": "{{type}} ಅನ್ನು ಹಂಚಿಕೊಳ್ಳಲು ಕ್ಲಿಪ್ಬೋರ್ಡ್ ಅನ್ನು ಇಲ್ಲಿ ಅಂಟಿಸಿ",
|
||||||
"auto-accept-instructions-2": "ಆ ಸಾಧನದಿಂದ ಕಳುಹಿಸಲಾದ ಎಲ್ಲಾ ಫೈಲ್ಗಳನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಸ್ವೀಕರಿಸಲು.",
|
"auto-accept-instructions-2": "ಆ ಸಾಧನದಿಂದ ಕಳುಹಿಸಲಾದ ಎಲ್ಲಾ ಫೈಲ್ಗಳನ್ನು ಸ್ವಯಂಚಾಲಿತವಾಗಿ ಸ್ವೀಕರಿಸಲು.",
|
||||||
"receive-text-title": "ಸಂದೇಶವನ್ನು ಸ್ವೀಕರಿಸಲಾಗಿದೆ",
|
"receive-text-title": "ಸಂದೇಶವನ್ನು ಸ್ವೀಕರಿಸಲಾಗಿದೆ",
|
||||||
"edit-paired-devices-title": "ಜೋಡಿಯಾಗಿರುವ ಸಾಧನಗಳನ್ನು ಎಡಿಟ್ ಮಾಡಿ",
|
"edit-paired-devices-title": "ಜೋಡಿಯಾಗಿರುವ ಸಾಧನಗಳನ್ನು ಎಡಿಟ್ ಮಾಡಿ",
|
||||||
@@ -32,7 +34,7 @@
|
|||||||
"join": "ಸೇರಿಕೊಳ್ಳಿ",
|
"join": "ಸೇರಿಕೊಳ್ಳಿ",
|
||||||
"title-image-plural": "ಚಿತ್ರಗಳು",
|
"title-image-plural": "ಚಿತ್ರಗಳು",
|
||||||
"send": "ಕಳುಹಿಸಿ",
|
"send": "ಕಳುಹಿಸಿ",
|
||||||
"base64-tap-to-paste": "{{type}} ಅಂಟಿಸಲು ಇಲ್ಲಿ ಟ್ಯಾಪ್ ಮಾಡಿ",
|
"base64-tap-to-paste": "{{type}} ಹಂಚಿಕೊಳ್ಳಲು ಇಲ್ಲಿ ಟ್ಯಾಪ್ ಮಾಡಿ",
|
||||||
"base64-text": "ಪಠ್ಯ",
|
"base64-text": "ಪಠ್ಯ",
|
||||||
"copy": "ನಕಲು ಮಾಡಿ",
|
"copy": "ನಕಲು ಮಾಡಿ",
|
||||||
"file-other-description-image": "ಮತ್ತು ಇನ್ನೊಂದು ಚಿತ್ರ",
|
"file-other-description-image": "ಮತ್ತು ಇನ್ನೊಂದು ಚಿತ್ರ",
|
||||||
@@ -64,7 +66,15 @@
|
|||||||
"send-message-title": "ಸಂದೇಶ ಕಳುಹಿಸಿ",
|
"send-message-title": "ಸಂದೇಶ ಕಳುಹಿಸಿ",
|
||||||
"input-room-id-on-another-device": "ಇನ್ನೊಂದು ಸಾಧನದಲ್ಲಿ ಈ ರೂಮ್ ಐಡಿಯನ್ನು ನಮೂದಿಸಿ",
|
"input-room-id-on-another-device": "ಇನ್ನೊಂದು ಸಾಧನದಲ್ಲಿ ಈ ರೂಮ್ ಐಡಿಯನ್ನು ನಮೂದಿಸಿ",
|
||||||
"file-other-description-image-plural": "ಮತ್ತು {{count}} ಇತರ ಚಿತ್ರಗಳು",
|
"file-other-description-image-plural": "ಮತ್ತು {{count}} ಇತರ ಚಿತ್ರಗಳು",
|
||||||
"enter-room-id-from-another-device": "ಕೊಠಡಿ ಸೇರಲು ಇನ್ನೊಂದು ಸಾಧನದಿಂದ ರೂಮ್ ಐಡಿ ನಮೂದಿಸಿ."
|
"enter-room-id-from-another-device": "ಕೊಠಡಿ ಸೇರಲು ಇನ್ನೊಂದು ಸಾಧನದಿಂದ ರೂಮ್ ಐಡಿ ನಮೂದಿಸಿ.",
|
||||||
|
"close-toast_title": "ಅಧಿಸೂಚನೆಯನ್ನು ಮುಚ್ಚಿರಿ",
|
||||||
|
"share-text-checkbox": "ಪಠ್ಯವನ್ನು ಹಂಚಿಕೊಳ್ಳುವಾಗ ಯಾವಾಗಲೂ ಈ ಡೈಲಾಗ್ ಅನ್ನು ತೋರಿಸಿ",
|
||||||
|
"base64-title-files": "ಫೈಲ್ಗಳನ್ನು ಹಂಚಿಕೊಳ್ಳಿ",
|
||||||
|
"approve": "ಅನುಮೋದಿಸಿ",
|
||||||
|
"paired-device-removed": "ಜೋಡಿಸಲಾದ ಸಾಧನವನ್ನು ತೆಗೆದುಹಾಕಲಾಗಿದೆ.",
|
||||||
|
"share-text-title": "ಪಠ್ಯ ಸಂದೇಶವನ್ನು ಹಂಚಿಕೊಳ್ಳಿ",
|
||||||
|
"share-text-subtitle": "ಸಂದೇಶವನ್ನು ಕಳುಹಿಸುವ ಮೊದಲು ಎಡಿಟ್ ಮಾಡಿ:",
|
||||||
|
"base64-title-text": "ಪಠ್ಯವನ್ನು ಹಂಚಿಕೊಳ್ಳಿ"
|
||||||
},
|
},
|
||||||
"footer": {
|
"footer": {
|
||||||
"webrtc": "WebRTC ಲಭ್ಯವಿಲ್ಲದಿದ್ದರೆ.",
|
"webrtc": "WebRTC ಲಭ್ಯವಿಲ್ಲದಿದ್ದರೆ.",
|
||||||
@@ -137,7 +147,15 @@
|
|||||||
"x-instructions_data-drop-peer": "ಪೀರ್ಗೆ ಕಳುಹಿಸಲು ಬಿಡುಗಡೆ ಮಾಡಿ",
|
"x-instructions_data-drop-peer": "ಪೀರ್ಗೆ ಕಳುಹಿಸಲು ಬಿಡುಗಡೆ ಮಾಡಿ",
|
||||||
"x-instructions_data-drop-bg": "ಸ್ವೀಕರಿಸುವವರನ್ನು ಆಯ್ಕೆ ಮಾಡಲು ಬಿಡುಗಡೆ ಮಾಡಿ",
|
"x-instructions_data-drop-bg": "ಸ್ವೀಕರಿಸುವವರನ್ನು ಆಯ್ಕೆ ಮಾಡಲು ಬಿಡುಗಡೆ ಮಾಡಿ",
|
||||||
"no-peers_data-drop-bg": "ಸ್ವೀಕರಿಸುವವರನ್ನು ಆಯ್ಕೆ ಮಾಡಲು ಬಿಡುಗಡೆ ಮಾಡಿ",
|
"no-peers_data-drop-bg": "ಸ್ವೀಕರಿಸುವವರನ್ನು ಆಯ್ಕೆ ಮಾಡಲು ಬಿಡುಗಡೆ ಮಾಡಿ",
|
||||||
"webrtc-requirement": "ಈ PairDrop ನಿದರ್ಶನವನ್ನು ಬಳಸಲು, WebRTC ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಬೇಕು!"
|
"webrtc-requirement": "ಈ PairDrop ನಿದರ್ಶನವನ್ನು ಬಳಸಲು, WebRTC ಅನ್ನು ಸಕ್ರಿಯಗೊಳಿಸಬೇಕು!",
|
||||||
|
"activate-share-mode-base": "ಕಳುಹಿಸಲು ಇತರ ಸಾಧನಗಳಲ್ಲಿ PairDrop ತೆರೆಯಿರಿ",
|
||||||
|
"activate-share-mode-shared-files-plural": "{{count}} ಹಂಚಿದ ಫೈಲ್ಗಳು",
|
||||||
|
"x-instructions-share-mode_desktop": "{{descriptor}} ಕಳುಹಿಸಲು ಕ್ಲಿಕ್ ಮಾಡಿ",
|
||||||
|
"activate-share-mode-shared-file": "ಹಂಚಿದ ಫೈಲ್",
|
||||||
|
"activate-share-mode-and-other-file": "ಮತ್ತು ಇತರ 1 ಫೈಲ್",
|
||||||
|
"x-instructions-share-mode_mobile": "{{descriptor}} ಕಳುಹಿಸಲು ಟ್ಯಾಪ್ ಮಾಡಿ",
|
||||||
|
"activate-share-mode-and-other-files-plural": "ಮತ್ತು ಇತರ {{count}} ಫೈಲ್ಗಳು",
|
||||||
|
"activate-share-mode-shared-text": "ಹಂಚಿದ ಪಠ್ಯ"
|
||||||
},
|
},
|
||||||
"peer-ui": {
|
"peer-ui": {
|
||||||
"processing": "ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲಾಗುತ್ತಿದೆ…",
|
"processing": "ಪ್ರಕ್ರಿಯೆಗೊಳಿಸಲಾಗುತ್ತಿದೆ…",
|
||||||
@@ -146,7 +164,8 @@
|
|||||||
"waiting": "ನಿರೀಕ್ಷಿಸಲಾಗುತ್ತಿದೆ…",
|
"waiting": "ನಿರೀಕ್ಷಿಸಲಾಗುತ್ತಿದೆ…",
|
||||||
"connection-hash": "ಎಂಡ್-ಟು-ಎಂಡ್ ಎನ್ಕ್ರಿಪ್ಶನ್ನ ಭದ್ರತೆಯನ್ನು ಪರಿಶೀಲಿಸಲು, ಎರಡೂ ಸಾಧನಗಳಲ್ಲಿ ಈ ಭದ್ರತಾ ಸಂಖ್ಯೆಯನ್ನು ಹೋಲಿಸಿ",
|
"connection-hash": "ಎಂಡ್-ಟು-ಎಂಡ್ ಎನ್ಕ್ರಿಪ್ಶನ್ನ ಭದ್ರತೆಯನ್ನು ಪರಿಶೀಲಿಸಲು, ಎರಡೂ ಸಾಧನಗಳಲ್ಲಿ ಈ ಭದ್ರತಾ ಸಂಖ್ಯೆಯನ್ನು ಹೋಲಿಸಿ",
|
||||||
"preparing": "ಸಿದ್ಧಪಡಿಸಲಾಗುತ್ತಿದೆ…",
|
"preparing": "ಸಿದ್ಧಪಡಿಸಲಾಗುತ್ತಿದೆ…",
|
||||||
"transferring": "ವರ್ಗಾಯಿಸಲಾಗುತ್ತಿದೆ…"
|
"transferring": "ವರ್ಗಾಯಿಸಲಾಗುತ್ತಿದೆ…",
|
||||||
|
"click-to-send-share-mode": "{{descriptor}} ಕಳುಹಿಸಲು ಕ್ಲಿಕ್ ಮಾಡಿ"
|
||||||
},
|
},
|
||||||
"about": {
|
"about": {
|
||||||
"claim": "ಸಾಧನಗಳಾದ್ಯಂತ ಫೈಲ್ಗಳನ್ನು ವರ್ಗಾಯಿಸಲು ಸುಲಭವಾದ ಮಾರ್ಗ",
|
"claim": "ಸಾಧನಗಳಾದ್ಯಂತ ಫೈಲ್ಗಳನ್ನು ವರ್ಗಾಯಿಸಲು ಸುಲಭವಾದ ಮಾರ್ಗ",
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"header": {
|
"header": {
|
||||||
"about_title": "PairDrop Hakkında",
|
"about_title": "PairDrop Hakkında",
|
||||||
"about_aria-label": "PairDrop Hakkında Aç",
|
"about_aria-label": "PairDrop Hakkındayı Aç",
|
||||||
"theme-auto_title": "Temayı sisteme uyarla",
|
"theme-auto_title": "Temayı sisteme uyarla",
|
||||||
"theme-light_title": "Daima açık tema kullan",
|
"theme-light_title": "Daima açık tema kullan",
|
||||||
"theme-dark_title": "Daima koyu tema kullan",
|
"theme-dark_title": "Daima koyu tema kullan",
|
||||||
@@ -17,13 +17,13 @@
|
|||||||
"instructions": {
|
"instructions": {
|
||||||
"no-peers_data-drop-bg": "Alıcıyı seçmek için bırakın",
|
"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_mobile": "Dosya göndermek için dokun veya mesaj göndermek için uzun dokun",
|
||||||
"x-instructions-share-mode_desktop": "Göndermek için tıkla {{descriptor}}",
|
"x-instructions-share-mode_desktop": "{{descriptor}} kişisine göndermek için tıkla",
|
||||||
"activate-share-mode-and-other-files-plural": "ve {{count}} diğer dosya",
|
"activate-share-mode-and-other-files-plural": "ve {{count}} diğer dosya",
|
||||||
"x-instructions-share-mode_mobile": "Göndermek için dokun {{descriptor}}",
|
"x-instructions-share-mode_mobile": "{{descriptor}} kişisine göndermek için dokun",
|
||||||
"activate-share-mode-base": "Göndermek için diğer cihazlarda PairDrop'u açın",
|
"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": "Diğer ağlarda keşfedilebilir olmak için cihazları eşleştirin veya ortak bir odaya girin",
|
||||||
"activate-share-mode-shared-text": "paylaşılan metin",
|
"activate-share-mode-shared-text": "paylaşılan metin",
|
||||||
"x-instructions_desktop": "Dosya göndermek için tıkla ya da mesaj göndermek için sağ tıkla",
|
"x-instructions_desktop": "Dosya göndermek için tıkla veya mesaj göndermek için sağ tıkla",
|
||||||
"no-peers-title": "Dosya göndermek için diğer cihazlarda PairDrop'u açı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": "Göndermek için serbest bırak",
|
||||||
"x-instructions_data-drop-bg": "Alıcıyı seçmek için bırakın",
|
"x-instructions_data-drop-bg": "Alıcıyı seçmek için bırakın",
|
||||||
@@ -131,11 +131,11 @@
|
|||||||
"public-room-left": "{{publicRoomId}} genel odasından ayrıldın",
|
"public-room-left": "{{publicRoomId}} genel odasından ayrıldın",
|
||||||
"copied-text": "Metin panoya kopyalandı",
|
"copied-text": "Metin panoya kopyalandı",
|
||||||
"display-name-random-again": "Mevcut adın tekrardan rastgele oluşturuldu",
|
"display-name-random-again": "Mevcut adın tekrardan rastgele oluşturuldu",
|
||||||
"display-name-changed-permanently": "Mevcut adın kalıcı olarak değiştirilir",
|
"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.",
|
"copied-to-clipboard-error": "Kopyalama mümkün değil. Manuel olarak kopyalayın.",
|
||||||
"pairing-success": "Cihazlar eşleştirildi",
|
"pairing-success": "Cihazlar eşleştirildi",
|
||||||
"clipboard-content-incorrect": "Pano içeriği yanlış",
|
"clipboard-content-incorrect": "Pano içeriği yanlış",
|
||||||
"display-name-changed-temporarily": "Mevcut adın yalnızca bu oturum için değiştirilir",
|
"display-name-changed-temporarily": "Mevcut adın yalnızca bu oturum için değiştirildi",
|
||||||
"copied-to-clipboard": "Panoya kopyalandı",
|
"copied-to-clipboard": "Panoya kopyalandı",
|
||||||
"offline": "Çevrimdışısın",
|
"offline": "Çevrimdışısın",
|
||||||
"pairing-tabs-error": "İki web tarayıcı sekmesini eşleştirmek mümkün değildir",
|
"pairing-tabs-error": "İki web tarayıcı sekmesini eşleştirmek mümkün değildir",
|
||||||
@@ -149,7 +149,7 @@
|
|||||||
"room-url-copied-to-clipboard": "Genel oda bağlantı linki panoya kopyalandı",
|
"room-url-copied-to-clipboard": "Genel oda bağlantı linki panoya kopyalandı",
|
||||||
"copied-text-error": "Panoya kopyalanamadı. Lütfen manuel olarak kopyalayın!",
|
"copied-text-error": "Panoya kopyalanamadı. Lütfen manuel olarak kopyalayın!",
|
||||||
"download-successful": "{{descriptor}} indirildi",
|
"download-successful": "{{descriptor}} indirildi",
|
||||||
"click-to-show": "Göstermek için tıkla"
|
"click-to-show": "Görmek için tıkla"
|
||||||
},
|
},
|
||||||
"peer-ui": {
|
"peer-ui": {
|
||||||
"processing": "İşleniyor…",
|
"processing": "İşleniyor…",
|
||||||
|
|||||||
@@ -1,40 +1,49 @@
|
|||||||
class Localization {
|
class Localization {
|
||||||
constructor() {
|
constructor() {
|
||||||
|
Localization.$htmlRoot = document.querySelector('html');
|
||||||
|
|
||||||
Localization.defaultLocale = "en";
|
Localization.defaultLocale = "en";
|
||||||
Localization.supportedLocales = ["ar", "ca", "de", "en", "es", "fr", "id", "it", "ja", "nb", "nl", "pt-BR", "ro", "ru", "tr", "zh-CN"];
|
Localization.supportedLocales = ["ar", "ca", "de", "en", "es", "fr", "id", "it", "ja", "kn", "nb", "nl", "pt-BR", "ro", "ru", "tr", "zh-CN"];
|
||||||
Localization.supportedLocalesRtl = ["ar"];
|
Localization.supportedLocalesRtl = ["ar"];
|
||||||
|
|
||||||
Localization.translations = {};
|
Localization.translations = {};
|
||||||
Localization.defaultTranslations = {};
|
Localization.translationsDefaultLocale = {};
|
||||||
|
|
||||||
Localization.systemLocale = Localization.getSupportedOrDefault(navigator.languages);
|
Localization.systemLocale = Localization.getSupportedOrDefaultLocales(navigator.languages);
|
||||||
|
|
||||||
let storedLanguageCode = localStorage.getItem('language_code');
|
let storedLanguageCode = localStorage.getItem('language_code');
|
||||||
|
|
||||||
Localization.initialLocale = storedLanguageCode && Localization.isSupported(storedLanguageCode)
|
Localization.initialLocale = storedLanguageCode && Localization.localeIsSupported(storedLanguageCode)
|
||||||
? storedLanguageCode
|
? storedLanguageCode
|
||||||
: Localization.systemLocale;
|
: Localization.systemLocale;
|
||||||
}
|
}
|
||||||
|
|
||||||
static isSupported(locale) {
|
static localeIsSupported(locale) {
|
||||||
return Localization.supportedLocales.indexOf(locale) > -1;
|
return Localization.supportedLocales.indexOf(locale) > -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static isRtlLanguage(locale) {
|
static localeIsRtl(locale) {
|
||||||
return Localization.supportedLocalesRtl.indexOf(locale) > -1;
|
return Localization.supportedLocalesRtl.indexOf(locale) > -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static isCurrentLocaleRtl() {
|
static currentLocaleIsRtl() {
|
||||||
return Localization.isRtlLanguage(Localization.locale);
|
return Localization.localeIsRtl(Localization.locale);
|
||||||
}
|
}
|
||||||
|
|
||||||
static getSupportedOrDefault(locales) {
|
static currentLocaleIsDefault() {
|
||||||
|
return Localization.locale === Localization.defaultLocale
|
||||||
|
}
|
||||||
|
|
||||||
|
static getSupportedOrDefaultLocales(locales) {
|
||||||
|
// get generic locales not included in locales
|
||||||
|
// ["en-us", "de-CH", "fr"] --> ["en", "de"]
|
||||||
let localesGeneric = locales
|
let localesGeneric = locales
|
||||||
.map(locale => locale.split("-")[0])
|
.map(locale => locale.split("-")[0])
|
||||||
.filter(locale => locales.indexOf(locale) === -1);
|
.filter(locale => locales.indexOf(locale) === -1);
|
||||||
|
|
||||||
return locales.find(Localization.isSupported)
|
// If there is no perfect match for browser locales, try generic locales first before resorting to the default locale
|
||||||
|| localesGeneric.find(Localization.isSupported)
|
return locales.find(Localization.localeIsSupported)
|
||||||
|
|| localesGeneric.find(Localization.localeIsSupported)
|
||||||
|| Localization.defaultLocale;
|
|| Localization.defaultLocale;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -48,16 +57,14 @@ class Localization {
|
|||||||
await Localization.setLocale(locale)
|
await Localization.setLocale(locale)
|
||||||
await Localization.translatePage();
|
await Localization.translatePage();
|
||||||
|
|
||||||
const htmlRootNode = document.querySelector('html');
|
if (Localization.localeIsRtl(locale)) {
|
||||||
|
Localization.$htmlRoot.setAttribute('dir', 'rtl');
|
||||||
if (Localization.isRtlLanguage(locale)) {
|
|
||||||
htmlRootNode.setAttribute('dir', 'rtl');
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
htmlRootNode.removeAttribute('dir');
|
Localization.$htmlRoot.removeAttribute('dir');
|
||||||
}
|
}
|
||||||
|
|
||||||
htmlRootNode.setAttribute('lang', locale);
|
Localization.$htmlRoot.setAttribute('lang', locale);
|
||||||
|
|
||||||
|
|
||||||
console.log("Page successfully translated",
|
console.log("Page successfully translated",
|
||||||
@@ -111,75 +118,108 @@ class Localization {
|
|||||||
const key = element.getAttribute("data-i18n-key");
|
const key = element.getAttribute("data-i18n-key");
|
||||||
const attrs = element.getAttribute("data-i18n-attrs").split(" ");
|
const attrs = element.getAttribute("data-i18n-attrs").split(" ");
|
||||||
|
|
||||||
for (let i in attrs) {
|
attrs.forEach(attr => {
|
||||||
let attr = attrs[i];
|
|
||||||
if (attr === "text") {
|
if (attr === "text") {
|
||||||
element.innerText = Localization.getTranslation(key);
|
element.innerText = Localization.getTranslation(key);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
element.setAttribute(attr, Localization.getTranslation(key, attr));
|
element.setAttribute(attr, Localization.getTranslation(key, attr));
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
static getTranslation(key, attr = null, data = {}, useDefault = false) {
|
static getTranslationFromTranslationsObj(translationObj, key, attr) {
|
||||||
const keys = key.split(".");
|
|
||||||
|
|
||||||
let translationCandidates = useDefault
|
|
||||||
? Localization.defaultTranslations
|
|
||||||
: Localization.translations;
|
|
||||||
|
|
||||||
let translation;
|
let translation;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
const keys = key.split(".");
|
||||||
|
|
||||||
for (let i = 0; i < keys.length - 1; i++) {
|
for (let i = 0; i < keys.length - 1; i++) {
|
||||||
translationCandidates = translationCandidates[keys[i]]
|
// iterate into translation object until last layer
|
||||||
|
translationObj = translationObj[keys[i]]
|
||||||
}
|
}
|
||||||
|
|
||||||
let lastKey = keys[keys.length - 1];
|
let lastKey = keys[keys.length - 1];
|
||||||
|
|
||||||
if (attr) lastKey += "_" + attr;
|
if (attr) lastKey += "_" + attr;
|
||||||
|
|
||||||
translation = translationCandidates[lastKey];
|
translation = translationObj[lastKey];
|
||||||
|
|
||||||
for (let j in data) {
|
|
||||||
if (translation.includes(`{{${j}}}`)) {
|
|
||||||
translation = translation.replace(`{{${j}}}`, data[j]);
|
|
||||||
} else {
|
|
||||||
console.warn(`Translation for your language ${Localization.locale.toUpperCase()} misses at least one data placeholder:`, key, attr, data);
|
|
||||||
Localization.logHelpCallKey(key);
|
|
||||||
Localization.logHelpCall();
|
|
||||||
translation = "";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
console.error(e);
|
console.error(e);
|
||||||
translation = "";
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!translation) {
|
if (!translation) {
|
||||||
if (!useDefault) {
|
throw new Error(`Translation misses entry. Key: ${key} Attribute: ${attr}`);
|
||||||
console.warn(`Missing translation entry for your language ${Localization.locale.toUpperCase()}. Using ${Localization.defaultLocale.toUpperCase()} instead.`, key, attr);
|
}
|
||||||
Localization.logHelpCallKey(key);
|
|
||||||
Localization.logHelpCall();
|
return translation;
|
||||||
translation = this.getTranslation(key, attr, data, true);
|
}
|
||||||
|
|
||||||
|
static addDataToTranslation(translation, data) {
|
||||||
|
for (let j in data) {
|
||||||
|
if (!translation.includes(`{{${j}}}`)) {
|
||||||
|
throw new Error(`Translation misses data placeholder: ${j}`);
|
||||||
|
}
|
||||||
|
// Add data to translation
|
||||||
|
translation = translation.replace(`{{${j}}}`, data[j]);
|
||||||
|
}
|
||||||
|
return translation;
|
||||||
|
}
|
||||||
|
|
||||||
|
static getTranslation(key, attr = null, data = {}, useDefault = false) {
|
||||||
|
let translationObj = useDefault
|
||||||
|
? Localization.translationsDefaultLocale
|
||||||
|
: Localization.translations;
|
||||||
|
|
||||||
|
let translation;
|
||||||
|
|
||||||
|
try {
|
||||||
|
translation = Localization.getTranslationFromTranslationsObj(translationObj, key, attr);
|
||||||
|
translation = Localization.addDataToTranslation(translation, data);
|
||||||
|
}
|
||||||
|
catch (e) {
|
||||||
|
// Log warnings and help calls
|
||||||
|
console.warn(e);
|
||||||
|
Localization.logTranslationMissingOrBroken(key, attr, data, useDefault);
|
||||||
|
Localization.logHelpCallKey(key, attr);
|
||||||
|
Localization.logHelpCall();
|
||||||
|
|
||||||
|
if (useDefault || Localization.currentLocaleIsDefault()) {
|
||||||
|
// Is default locale already
|
||||||
|
// Use empty string as translation
|
||||||
|
translation = ""
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
console.warn("Missing translation in default language:", key, attr);
|
// Is not default locale yet
|
||||||
Localization.logHelpCall();
|
// Get translation for default language with same arguments
|
||||||
|
console.log(`Using default language ${Localization.defaultLocale.toUpperCase()} instead.`);
|
||||||
|
translation = this.getTranslation(key, attr, data, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Localization.escapeHTML(translation);
|
return Localization.escapeHTML(translation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static logTranslationMissingOrBroken(key, attr, data, useDefault) {
|
||||||
|
let usedLocale = useDefault
|
||||||
|
? Localization.defaultLocale.toUpperCase()
|
||||||
|
: Localization.locale.toUpperCase();
|
||||||
|
|
||||||
|
console.warn(`Missing or broken translation for language ${usedLocale}.\n`, 'key:', key, 'attr:', attr, 'data:', data);
|
||||||
|
}
|
||||||
|
|
||||||
static logHelpCall() {
|
static logHelpCall() {
|
||||||
console.log("Help translating PairDrop: https://hosted.weblate.org/engage/pairdrop/");
|
console.log("Help translating PairDrop: https://hosted.weblate.org/engage/pairdrop/");
|
||||||
}
|
}
|
||||||
|
|
||||||
static logHelpCallKey(key) {
|
static logHelpCallKey(key, attr) {
|
||||||
console.warn(`Translate this string here: https://hosted.weblate.org/browse/pairdrop/pairdrop-spa/${Localization.locale.toLowerCase()}/?q=${key}`);
|
let locale = Localization.locale.toLowerCase();
|
||||||
|
|
||||||
|
let keyComplete = !attr || attr === "text"
|
||||||
|
? key
|
||||||
|
: `${key}_${attr}`;
|
||||||
|
|
||||||
|
console.warn(`Translate this string here: https://hosted.weblate.org/browse/pairdrop/pairdrop-spa/${locale}/?q=${keyComplete}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
static escapeHTML(unsafeText) {
|
static escapeHTML(unsafeText) {
|
||||||
|
|||||||
@@ -56,13 +56,16 @@ class PairDrop {
|
|||||||
await this.backgroundCanvas.fadeIn();
|
await this.backgroundCanvas.fadeIn();
|
||||||
|
|
||||||
// Load deferred assets
|
// Load deferred assets
|
||||||
|
console.log("Load deferred assets...");
|
||||||
await this.loadDeferredAssets();
|
await this.loadDeferredAssets();
|
||||||
console.log("Loading of deferred assets completed.");
|
console.log("Loading of deferred assets completed.");
|
||||||
|
|
||||||
|
console.log("Hydrate UI...");
|
||||||
await this.hydrate();
|
await this.hydrate();
|
||||||
console.log("UI hydrated.");
|
console.log("UI hydrated.");
|
||||||
|
|
||||||
// Evaluate url params as soon as ws is connected
|
// Evaluate url params as soon as ws is connected
|
||||||
|
console.log("Evaluate URL params as soon as websocket connection is established.");
|
||||||
Events.on('ws-connected', _ => this.evaluateUrlParams(), {once: true});
|
Events.on('ws-connected', _ => this.evaluateUrlParams(), {once: true});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,36 +105,40 @@ class PairDrop {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadDeferredAssets() {
|
loadDeferredAssets() {
|
||||||
console.log("Load deferred assets");
|
const stylePromises = this.deferredStyles.map(url => this.loadAndApplyStylesheet(url));
|
||||||
for (const url of this.deferredStyles) {
|
const scriptPromises = this.deferredScripts.map(url => this.loadAndApplyScript(url));
|
||||||
await this.loadAndApplyStylesheet(url);
|
|
||||||
}
|
return Promise.all([...stylePromises, ...scriptPromises]);
|
||||||
for (const url of this.deferredScripts) {
|
|
||||||
await this.loadAndApplyScript(url);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
loadStyleSheet(url) {
|
loadStyleSheet(url) {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
let stylesheet = document.createElement('link');
|
let stylesheet = document.createElement('link');
|
||||||
stylesheet.rel = 'stylesheet';
|
stylesheet.rel = 'preload';
|
||||||
|
stylesheet.as = 'style';
|
||||||
stylesheet.href = url;
|
stylesheet.href = url;
|
||||||
stylesheet.type = 'text/css';
|
stylesheet.onload = _ => {
|
||||||
stylesheet.onload = resolve;
|
stylesheet.onload = null;
|
||||||
|
stylesheet.rel = 'stylesheet';
|
||||||
|
resolve();
|
||||||
|
};
|
||||||
stylesheet.onerror = reject;
|
stylesheet.onerror = reject;
|
||||||
|
|
||||||
document.head.appendChild(stylesheet);
|
document.head.appendChild(stylesheet);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadAndApplyStylesheet(url) {
|
loadAndApplyStylesheet(url) {
|
||||||
try {
|
return new Promise( async (resolve) => {
|
||||||
await this.loadStyleSheet(url);
|
try {
|
||||||
console.log(`Stylesheet loaded successfully: ${url}`);
|
await this.loadStyleSheet(url);
|
||||||
} catch (error) {
|
console.log(`Stylesheet loaded successfully: ${url}`);
|
||||||
console.error('Error loading stylesheet:', error);
|
resolve();
|
||||||
}
|
} catch (error) {
|
||||||
|
console.error('Error loading stylesheet:', error);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
loadScript(url) {
|
loadScript(url) {
|
||||||
@@ -145,13 +152,16 @@ class PairDrop {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async loadAndApplyScript(url) {
|
loadAndApplyScript(url) {
|
||||||
try {
|
return new Promise( async (resolve) => {
|
||||||
await this.loadScript(url);
|
try {
|
||||||
console.log(`Script loaded successfully: ${url}`);
|
await this.loadScript(url);
|
||||||
} catch (error) {
|
console.log(`Script loaded successfully: ${url}`);
|
||||||
console.error('Error loading script:', error);
|
resolve();
|
||||||
}
|
} catch (error) {
|
||||||
|
console.error('Error loading script:', error);
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async hydrate() {
|
async hydrate() {
|
||||||
@@ -223,6 +233,8 @@ class PairDrop {
|
|||||||
// remove url params from url
|
// remove url params from url
|
||||||
const urlWithoutParams = getUrlWithoutArguments();
|
const urlWithoutParams = getUrlWithoutArguments();
|
||||||
window.history.replaceState({}, "Rewrite URL", urlWithoutParams);
|
window.history.replaceState({}, "Rewrite URL", urlWithoutParams);
|
||||||
|
|
||||||
|
console.log("URL params evaluated.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -132,7 +132,7 @@ class HeaderUI {
|
|||||||
this.$header.classList.remove('overflow-expanded');
|
this.$header.classList.remove('overflow-expanded');
|
||||||
|
|
||||||
|
|
||||||
const rtlLocale = Localization.isCurrentLocaleRtl();
|
const rtlLocale = Localization.currentLocaleIsRtl();
|
||||||
let icon;
|
let icon;
|
||||||
const $headerIconsShown = document.querySelectorAll('body > header:first-of-type > *:not([hidden])');
|
const $headerIconsShown = document.querySelectorAll('body > header:first-of-type > *:not([hidden])');
|
||||||
|
|
||||||
|
|||||||
@@ -2420,14 +2420,9 @@ class Notifications {
|
|||||||
|
|
||||||
_downloadNotification(files) {
|
_downloadNotification(files) {
|
||||||
if (document.visibilityState !== 'visible') {
|
if (document.visibilityState !== 'visible') {
|
||||||
let imagesOnly = true;
|
let imagesOnly = files.every(file => file.type.split('/')[0] === 'image');
|
||||||
for(let i=0; i<files.length; i++) {
|
|
||||||
if (files[i].type.split('/')[0] !== 'image') {
|
|
||||||
imagesOnly = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
let title;
|
let title;
|
||||||
|
|
||||||
if (files.length === 1) {
|
if (files.length === 1) {
|
||||||
title = `${files[0].name}`;
|
title = `${files[0].name}`;
|
||||||
}
|
}
|
||||||
@@ -2452,15 +2447,8 @@ class Notifications {
|
|||||||
|
|
||||||
_requestNotification(request, peerId) {
|
_requestNotification(request, peerId) {
|
||||||
if (document.visibilityState !== 'visible') {
|
if (document.visibilityState !== 'visible') {
|
||||||
let imagesOnly = true;
|
let imagesOnly = request.header.every(header => header.mime.split('/')[0] === 'image');
|
||||||
for(let i=0; i<request.header.length; i++) {
|
let displayName = $(peerId).querySelector('.name').textContent;
|
||||||
if (request.header[i].mime.split('/')[0] !== 'image') {
|
|
||||||
imagesOnly = false;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let displayName = $(peerId).querySelector('.name').textContent
|
|
||||||
|
|
||||||
let descriptor;
|
let descriptor;
|
||||||
if (request.header.length === 1) {
|
if (request.header.length === 1) {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
const cacheVersion = 'v1.10.1';
|
const cacheVersion = 'v1.10.2';
|
||||||
const cacheTitle = `pairdrop-cache-${cacheVersion}`;
|
const cacheTitle = `pairdrop-cache-${cacheVersion}`;
|
||||||
const forceFetch = false; // FOR DEVELOPMENT: Set to true to always update assets instead of using cached versions
|
const forceFetch = false; // FOR DEVELOPMENT: Set to true to always update assets instead of using cached versions
|
||||||
const relativePathsToCache = [
|
const relativePathsToCache = [
|
||||||
@@ -35,6 +35,7 @@ const relativePathsToCache = [
|
|||||||
'lang/id.json',
|
'lang/id.json',
|
||||||
'lang/it.json',
|
'lang/it.json',
|
||||||
'lang/ja.json',
|
'lang/ja.json',
|
||||||
|
'lang/kn.json',
|
||||||
'lang/nb.json',
|
'lang/nb.json',
|
||||||
'lang/nl.json',
|
'lang/nl.json',
|
||||||
'lang/pt-BR.json',
|
'lang/pt-BR.json',
|
||||||
|
|||||||
@@ -32,10 +32,14 @@ process.on('unhandledRejection', (reason, promise) => {
|
|||||||
|
|
||||||
// Evaluate arguments for deployment with Docker and Node.js
|
// Evaluate arguments for deployment with Docker and Node.js
|
||||||
let conf = {};
|
let conf = {};
|
||||||
|
|
||||||
conf.debugMode = process.env.DEBUG_MODE === "true";
|
conf.debugMode = process.env.DEBUG_MODE === "true";
|
||||||
|
|
||||||
conf.port = process.env.PORT || 3000;
|
conf.port = process.env.PORT || 3000;
|
||||||
|
|
||||||
conf.wsFallback = process.argv.includes('--include-ws-fallback') || process.env.WS_FALLBACK === "true";
|
conf.wsFallback = process.argv.includes('--include-ws-fallback') || process.env.WS_FALLBACK === "true";
|
||||||
conf.rtcConfig = process.env.RTC_CONFIG
|
|
||||||
|
conf.rtcConfig = process.env.RTC_CONFIG && process.env.RTC_CONFIG !== "false"
|
||||||
? JSON.parse(fs.readFileSync(process.env.RTC_CONFIG, 'utf8'))
|
? JSON.parse(fs.readFileSync(process.env.RTC_CONFIG, 'utf8'))
|
||||||
: {
|
: {
|
||||||
"sdpSemantics": "unified-plan",
|
"sdpSemantics": "unified-plan",
|
||||||
@@ -47,7 +51,10 @@ conf.rtcConfig = process.env.RTC_CONFIG
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
conf.signalingServer = process.env.SIGNALING_SERVER || false;
|
conf.signalingServer = process.env.SIGNALING_SERVER && process.env.SIGNALING_SERVER !== "false"
|
||||||
|
? process.env.SIGNALING_SERVER
|
||||||
|
: false;
|
||||||
|
|
||||||
conf.ipv6Localize = parseInt(process.env.IPV6_LOCALIZE) || false;
|
conf.ipv6Localize = parseInt(process.env.IPV6_LOCALIZE) || false;
|
||||||
|
|
||||||
let rateLimit = false;
|
let rateLimit = false;
|
||||||
@@ -61,6 +68,7 @@ else {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
conf.rateLimit = rateLimit;
|
conf.rateLimit = rateLimit;
|
||||||
|
|
||||||
conf.buttons = {
|
conf.buttons = {
|
||||||
"donation_button": {
|
"donation_button": {
|
||||||
"active": process.env.DONATION_BUTTON_ACTIVE,
|
"active": process.env.DONATION_BUTTON_ACTIVE,
|
||||||
@@ -96,8 +104,10 @@ conf.buttons = {
|
|||||||
|
|
||||||
// Evaluate arguments for deployment with Node.js only
|
// Evaluate arguments for deployment with Node.js only
|
||||||
conf.autoStart = process.argv.includes('--auto-restart');
|
conf.autoStart = process.argv.includes('--auto-restart');
|
||||||
|
|
||||||
conf.localhostOnly = process.argv.includes('--localhost-only');
|
conf.localhostOnly = process.argv.includes('--localhost-only');
|
||||||
|
|
||||||
|
|
||||||
// Validate configuration
|
// Validate configuration
|
||||||
if (conf.ipv6Localize) {
|
if (conf.ipv6Localize) {
|
||||||
if (!(0 < conf.ipv6Localize && conf.ipv6Localize < 8)) {
|
if (!(0 < conf.ipv6Localize && conf.ipv6Localize < 8)) {
|
||||||
|
|||||||
Reference in New Issue
Block a user