iobroker.script-restore 0.1.0 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.de.md +8 -0
- package/README.md +8 -11
- package/admin/tab_m.html +654 -44
- package/build/main.js +17 -3
- package/build/main.js.map +2 -2
- package/io-package.json +27 -27
- package/package.json +5 -5
package/admin/tab_m.html
CHANGED
|
@@ -356,6 +356,26 @@
|
|
|
356
356
|
body.dark .restore-modal label { color: #aaa; }
|
|
357
357
|
body.dark .restore-modal input[type=text] { background: #1a1a2e; border-color: #4a4a6a; color: #e0e0e0; }
|
|
358
358
|
body.dark .restore-modal-preview { color: #7a7aaa; }
|
|
359
|
+
.restore-modal-warning {
|
|
360
|
+
background: #fff3cd; border: 1px solid #ffc107; border-radius: 6px;
|
|
361
|
+
padding: 12px 14px; margin-top: 14px; display: none;
|
|
362
|
+
}
|
|
363
|
+
.restore-modal-warning p { margin: 0 0 10px; font-size: 0.88rem; color: #664d03; line-height: 1.5; }
|
|
364
|
+
.restore-modal-warning code { background: rgba(0,0,0,0.08); padding: 1px 5px; border-radius: 3px; font-family: 'Consolas', monospace; word-break: break-all; font-size: 0.85em; }
|
|
365
|
+
.restore-modal-warning .rmw-actions { display: flex; gap: 8px; justify-content: flex-end; }
|
|
366
|
+
.btn-danger { background: #dc3545; color: white; border-color: #dc3545; }
|
|
367
|
+
.btn-danger:hover { background: #bb2d3b; border-color: #b02a37; }
|
|
368
|
+
body.dark .restore-modal-warning { background: #2d1f00; border-color: #7a5f00; }
|
|
369
|
+
body.dark .restore-modal-warning p { color: #ffd966; }
|
|
370
|
+
body.dark .restore-modal-warning code { background: rgba(255,255,255,0.1); color: #ffb347; }
|
|
371
|
+
.restore-modal-success {
|
|
372
|
+
background: #d1e7dd; border: 1px solid #a3cfbb; border-radius: 6px;
|
|
373
|
+
padding: 12px 14px; margin-top: 14px; display: none;
|
|
374
|
+
}
|
|
375
|
+
.restore-modal-success p { margin: 0 0 10px; font-size: 0.88rem; color: #0a3622; line-height: 1.5; }
|
|
376
|
+
.restore-modal-success .rmw-actions { display: flex; gap: 8px; justify-content: flex-end; }
|
|
377
|
+
body.dark .restore-modal-success { background: #0d2b1f; border-color: #1a5c38; }
|
|
378
|
+
body.dark .restore-modal-success p { color: #6fdc9e; }
|
|
359
379
|
|
|
360
380
|
/* Responsive */
|
|
361
381
|
@media (max-width: 768px) {
|
|
@@ -373,25 +393,39 @@
|
|
|
373
393
|
<div class="progress-inner"><span id="progressPercent">0%</span></div>
|
|
374
394
|
</div>
|
|
375
395
|
<div id="spinnerEl" class="spinner" style="display:none;"></div>
|
|
376
|
-
<div id="loaderText">Lade Backup...</div>
|
|
396
|
+
<div id="loaderText" data-i18n="loaderLoading">Lade Backup...</div>
|
|
377
397
|
</div>
|
|
378
398
|
|
|
379
399
|
<!-- Restore Modal -->
|
|
380
400
|
<div class="restore-modal-overlay" id="restoreModalOverlay" onclick="closeRestoreModal(event)">
|
|
381
401
|
<div class="restore-modal" onclick="event.stopPropagation()">
|
|
382
|
-
<h3>In ioBroker laden</h3>
|
|
402
|
+
<h3 data-i18n="modalTitle">In ioBroker laden</h3>
|
|
383
403
|
<div class="restore-modal-meta">
|
|
384
|
-
<div>Skript
|
|
385
|
-
<div>Pfad
|
|
386
|
-
<div>Typ
|
|
404
|
+
<div><span data-i18n="modalLabelScript">Skript:</span> <strong id="rmScriptName"></strong></div>
|
|
405
|
+
<div><span data-i18n="modalLabelPath">Pfad:</span> <strong id="rmScriptPath"></strong></div>
|
|
406
|
+
<div><span data-i18n="modalLabelType">Typ:</span> <strong id="rmScriptType"></strong></div>
|
|
387
407
|
</div>
|
|
388
|
-
<label for="rmSuffix">Suffix (wird an den Skriptnamen angehängt)</label>
|
|
389
|
-
<input type="text" id="rmSuffix" value="_rcvr" oninput="updateRestorePreview()">
|
|
408
|
+
<label for="rmSuffix" data-i18n="modalLabelSuffix">Suffix (wird an den Skriptnamen angehängt)</label>
|
|
409
|
+
<input type="text" id="rmSuffix" value="_rcvr" oninput="updateRestorePreview();">
|
|
390
410
|
<div class="restore-modal-preview" id="rmPreview"></div>
|
|
411
|
+
<div class="restore-modal-warning" id="rmWarning">
|
|
412
|
+
<p></p>
|
|
413
|
+
<div class="rmw-actions">
|
|
414
|
+
<button class="btn btn-outline" onclick="dismissWarning()" data-i18n="modalDismiss">Anderen Suffix wählen</button>
|
|
415
|
+
<button class="btn btn-danger" onclick="overwriteConfirmed()" data-i18n="modalOverwrite">Überschreiben</button>
|
|
416
|
+
</div>
|
|
417
|
+
</div>
|
|
418
|
+
<div class="restore-modal-success" id="rmSuccess">
|
|
419
|
+
<p data-i18n-html="modalSuccess">✓ Erfolgreich wiederhergestellt.<br>Soll das Skript jetzt gestartet werden?</p>
|
|
420
|
+
<div class="rmw-actions">
|
|
421
|
+
<button class="btn btn-outline" onclick="closeRestoreModal()" data-i18n="modalClose">Nein danke</button>
|
|
422
|
+
<button class="btn btn-outline-success" id="rmStartBtn" onclick="startRestoredScript()" data-i18n="modalStart">Jetzt starten</button>
|
|
423
|
+
</div>
|
|
424
|
+
</div>
|
|
391
425
|
<div class="restore-modal-footer">
|
|
392
426
|
<span id="rmMsg" style="flex:1;font-size:0.85rem;align-self:center;"></span>
|
|
393
|
-
<button class="btn btn-outline" onclick="closeRestoreModal()">
|
|
394
|
-
<button class="btn btn-outline-success" id="rmConfirmBtn" onclick="confirmRestoreScript()">Laden</button>
|
|
427
|
+
<button class="btn btn-outline" onclick="closeRestoreModal()">Schließen</button>
|
|
428
|
+
<button class="btn btn-outline-success" id="rmConfirmBtn" onclick="confirmRestoreScript(false)" data-i18n="modalLoad">Laden</button>
|
|
395
429
|
</div>
|
|
396
430
|
</div>
|
|
397
431
|
</div>
|
|
@@ -399,56 +433,56 @@
|
|
|
399
433
|
<div class="toolbar">
|
|
400
434
|
<div class="toolbar-left">
|
|
401
435
|
<label class="file-input-label">
|
|
402
|
-
|
|
436
|
+
<span data-i18n="uploadLabel">📂 Backup hochladen</span>
|
|
403
437
|
<input type="file" id="fileInput" accept=".tar,.gz,.tar.gz,.json,.jsonl">
|
|
404
438
|
</label>
|
|
405
439
|
<div class="dropdown-wrapper" id="localDropdown">
|
|
406
|
-
<button class="btn btn-outline" onclick="toggleDropdown('local')">
|
|
440
|
+
<button class="btn btn-outline" onclick="toggleDropdown('local')" data-i18n="localDropdown">
|
|
407
441
|
🗂️ Lokale Backups ▾
|
|
408
442
|
</button>
|
|
409
443
|
<div class="dropdown-menu" id="localMenu"></div>
|
|
410
444
|
</div>
|
|
411
445
|
<div class="dropdown-wrapper" id="ftpDropdown" style="display:none;">
|
|
412
|
-
<button class="btn btn-outline" onclick="toggleDropdown('ftp')">
|
|
446
|
+
<button class="btn btn-outline" onclick="toggleDropdown('ftp')" data-i18n="ftpDropdown">
|
|
413
447
|
🌐 FTP Backups ▾
|
|
414
448
|
</button>
|
|
415
449
|
<div class="dropdown-menu" id="ftpMenu"></div>
|
|
416
450
|
</div>
|
|
417
451
|
<div class="dropdown-wrapper" id="smbDropdown" style="display:none;">
|
|
418
|
-
<button class="btn btn-outline" onclick="toggleDropdown('smb')">
|
|
452
|
+
<button class="btn btn-outline" onclick="toggleDropdown('smb')" data-i18n="smbDropdown">
|
|
419
453
|
🗄️ SMB Backups ▾
|
|
420
454
|
</button>
|
|
421
455
|
<div class="dropdown-menu" id="smbMenu"></div>
|
|
422
456
|
</div>
|
|
423
457
|
<div class="dropdown-wrapper" id="sftpDropdown" style="display:none;">
|
|
424
|
-
<button class="btn btn-outline" onclick="toggleDropdown('sftp')">
|
|
458
|
+
<button class="btn btn-outline" onclick="toggleDropdown('sftp')" data-i18n="sftpDropdown">
|
|
425
459
|
🔒 SFTP Backups ▾
|
|
426
460
|
</button>
|
|
427
461
|
<div class="dropdown-menu" id="sftpMenu"></div>
|
|
428
462
|
</div>
|
|
429
463
|
<div class="dropdown-wrapper" id="webdavDropdown" style="display:none;">
|
|
430
|
-
<button class="btn btn-outline" onclick="toggleDropdown('webdav')">
|
|
464
|
+
<button class="btn btn-outline" onclick="toggleDropdown('webdav')" data-i18n="webdavDropdown">
|
|
431
465
|
☁️ WebDAV Backups ▾
|
|
432
466
|
</button>
|
|
433
467
|
<div class="dropdown-menu" id="webdavMenu"></div>
|
|
434
468
|
</div>
|
|
435
469
|
<div id="httpInputWrapper" style="display:none; align-items:center; gap:6px;">
|
|
436
470
|
<input type="text" id="httpUrlInput" placeholder="https://..." style="padding:0.35rem 0.6rem; border:1px solid #ced4da; border-radius:4px; font-size:0.875rem; min-width:260px; font-family:inherit;">
|
|
437
|
-
<button type="button" class="btn btn-outline" onclick="loadHttpUrl()">🌐 URL laden</button>
|
|
471
|
+
<button type="button" class="btn btn-outline" onclick="loadHttpUrl()" data-i18n="httpLoadBtn">🌐 URL laden</button>
|
|
438
472
|
</div>
|
|
439
|
-
<button id="zipBtn" class="btn btn-outline" onclick="downloadZip()" style="display:none;">📦 ZIP</button>
|
|
440
|
-
<span class="status-msg" id="statusMsg">Backup laden oder Quelle wählen</span>
|
|
473
|
+
<button id="zipBtn" class="btn btn-outline" onclick="downloadZip()" style="display:none;" data-i18n="zipBtn">📦 ZIP</button>
|
|
474
|
+
<span class="status-msg" id="statusMsg" data-i18n="statusDefault">Backup laden oder Quelle wählen</span>
|
|
441
475
|
</div>
|
|
442
476
|
</div>
|
|
443
477
|
|
|
444
478
|
<div class="main-container">
|
|
445
479
|
<div class="sidebar" id="sidebar">
|
|
446
480
|
<div class="sidebar-header">
|
|
447
|
-
<input type="text" id="q" placeholder="Suche in Namen, Ordner & Code...">
|
|
448
|
-
<button class="btn-icon" id="expandToggleBtn" onclick="toggleExpandAll()" title="Alle Ordner aufklappen">📂</button>
|
|
481
|
+
<input type="text" id="q" data-i18n-placeholder="searchPlaceholder" placeholder="Suche in Namen, Ordner & Code...">
|
|
482
|
+
<button class="btn-icon" id="expandToggleBtn" onclick="toggleExpandAll()" data-i18n-title="expandAll" title="Alle Ordner aufklappen">📂</button>
|
|
449
483
|
</div>
|
|
450
484
|
<div class="type-filter-bar">
|
|
451
|
-
<button class="btn-type active" onclick="setTypeFilter(this, '')">Alle</button>
|
|
485
|
+
<button class="btn-type active" onclick="setTypeFilter(this, '')" data-i18n="typeAll">Alle</button>
|
|
452
486
|
<button class="btn-type" onclick="setTypeFilter(this, 'JS')"><span class="type-badge badge-JS">JS</span></button>
|
|
453
487
|
<button class="btn-type" onclick="setTypeFilter(this, 'TypeScript')"><span class="type-badge badge-TypeScript">TS</span></button>
|
|
454
488
|
<button class="btn-type" onclick="setTypeFilter(this, 'Blockly')"><span class="type-badge badge-Blockly">Blockly</span></button>
|
|
@@ -464,17 +498,16 @@
|
|
|
464
498
|
<div class="action-bar-inner">
|
|
465
499
|
<div class="btn-group" id="viewSwitcher"></div>
|
|
466
500
|
<div style="display:flex;gap:8px;align-items:center;flex-wrap:wrap;">
|
|
467
|
-
<button onclick="openRestoreModal()" class="btn btn-outline-success" id="restoreBtn">In ioBroker laden</button>
|
|
468
|
-
<button onclick="copyCode(this)" class="btn btn-outline-light">Code Kopieren</button>
|
|
469
|
-
<button onclick="downloadActive()" class="btn btn-primary" id="dlBtn">Download</button>
|
|
501
|
+
<button onclick="openRestoreModal()" class="btn btn-outline-success" id="restoreBtn" data-i18n="restoreBtn">In ioBroker laden</button>
|
|
502
|
+
<button onclick="copyCode(this)" class="btn btn-outline-light" data-i18n="copyBtnAction">Code Kopieren</button>
|
|
503
|
+
<button onclick="downloadActive()" class="btn btn-primary" id="dlBtn" data-i18n="downloadBtn">Download</button>
|
|
470
504
|
</div>
|
|
471
505
|
</div>
|
|
472
506
|
</div>
|
|
473
507
|
<div id="codeContainer" class="code-empty">
|
|
474
508
|
<div>
|
|
475
509
|
<strong>ioBroker Script Restore</strong><br><br>
|
|
476
|
-
Lade ein Backup hoch oder wähle eine lokale Datei,<br>
|
|
477
|
-
um Skripte anzuzeigen und wiederherzustellen.
|
|
510
|
+
<span data-i18n-html="welcomeText">Lade ein Backup hoch oder wähle eine lokale Datei,<br>um Skripte anzuzeigen und wiederherzustellen.</span>
|
|
478
511
|
</div>
|
|
479
512
|
</div>
|
|
480
513
|
</div>
|
|
@@ -486,6 +519,534 @@
|
|
|
486
519
|
const instance = urlParams.get('instance') || '0';
|
|
487
520
|
const adapterInst = 'script-restore.' + instance;
|
|
488
521
|
|
|
522
|
+
// === i18n ===
|
|
523
|
+
const TRANSLATIONS = {
|
|
524
|
+
de: {
|
|
525
|
+
loaderLoading: 'Lade Backup...',
|
|
526
|
+
loaderProcessing: 'Verarbeite...',
|
|
527
|
+
modalTitle: 'In ioBroker laden',
|
|
528
|
+
modalLabelScript: 'Skript:',
|
|
529
|
+
modalLabelPath: 'Pfad:',
|
|
530
|
+
modalLabelType: 'Typ:',
|
|
531
|
+
modalLabelSuffix: 'Suffix (wird an den Skriptnamen angehängt)',
|
|
532
|
+
modalWarning: '⚠ Ein Skript unter {path} existiert bereits.<br>Soll es wirklich überschrieben werden?',
|
|
533
|
+
modalDismiss: 'Anderen Suffix wählen',
|
|
534
|
+
modalOverwrite: 'Überschreiben',
|
|
535
|
+
modalSuccess: '✓ Erfolgreich wiederhergestellt.<br>Soll das Skript jetzt gestartet werden?',
|
|
536
|
+
modalClose: 'Nein danke',
|
|
537
|
+
modalStart: 'Jetzt starten',
|
|
538
|
+
modalLoad: 'Laden',
|
|
539
|
+
modalLoading: '⏳ Laden...',
|
|
540
|
+
modalStarting: '⏳ Starte...',
|
|
541
|
+
modalStarted: '✓ Gestartet',
|
|
542
|
+
modalLoaded: '✓ Geladen!',
|
|
543
|
+
modalUnknownError: '✗ Unbekannter Fehler',
|
|
544
|
+
modalErrorPrefix: '✗ Fehler: ',
|
|
545
|
+
copyBtn: 'Code Kopieren',
|
|
546
|
+
copyBtnAction: 'Code Kopieren',
|
|
547
|
+
copied: '✓ Kopiert!',
|
|
548
|
+
uploadLabel: '📂 Backup hochladen',
|
|
549
|
+
localDropdown: '🗂️ Lokale Backups ▾',
|
|
550
|
+
ftpDropdown: '🌐 FTP Backups ▾',
|
|
551
|
+
smbDropdown: '🗄️ SMB Backups ▾',
|
|
552
|
+
sftpDropdown: '🔒 SFTP Backups ▾',
|
|
553
|
+
webdavDropdown: '☁️ WebDAV Backups ▾',
|
|
554
|
+
httpLoadBtn: '🌐 URL laden',
|
|
555
|
+
zipBtn: '📦 ZIP',
|
|
556
|
+
statusDefault: 'Backup laden oder Quelle wählen',
|
|
557
|
+
searchPlaceholder: 'Suche in Namen, Ordner & Code...',
|
|
558
|
+
expandAll: 'Alle aufklappen',
|
|
559
|
+
collapseAll: 'Alle einklappen',
|
|
560
|
+
typeAll: 'Alle',
|
|
561
|
+
restoreBtn: 'In ioBroker laden',
|
|
562
|
+
downloadBtn: 'Download',
|
|
563
|
+
welcomeText: 'Lade ein Backup hoch oder wähle eine lokale Datei,<br>um Skripte anzuzeigen und wiederherzustellen.',
|
|
564
|
+
noSocket: 'Kein Socket. Bitte prüfen ob script-restore.{i} läuft.',
|
|
565
|
+
timeout: 'Timeout: Adapter antwortet nicht. Läuft script-restore.{i}?',
|
|
566
|
+
},
|
|
567
|
+
en: {
|
|
568
|
+
loaderLoading: 'Loading backup...',
|
|
569
|
+
loaderProcessing: 'Processing...',
|
|
570
|
+
modalTitle: 'Load into ioBroker',
|
|
571
|
+
modalLabelScript: 'Script:',
|
|
572
|
+
modalLabelPath: 'Path:',
|
|
573
|
+
modalLabelType: 'Type:',
|
|
574
|
+
modalLabelSuffix: 'Suffix (appended to the script name)',
|
|
575
|
+
modalWarning: '⚠ A script at {path} already exists.<br>Do you really want to overwrite it?',
|
|
576
|
+
modalDismiss: 'Choose different suffix',
|
|
577
|
+
modalOverwrite: 'Overwrite',
|
|
578
|
+
modalSuccess: '✓ Successfully restored.<br>Do you want to start the script now?',
|
|
579
|
+
modalClose: 'No thanks',
|
|
580
|
+
modalStart: 'Start now',
|
|
581
|
+
modalLoad: 'Load',
|
|
582
|
+
modalLoading: '⏳ Loading...',
|
|
583
|
+
modalStarting: '⏳ Starting...',
|
|
584
|
+
modalStarted: '✓ Started',
|
|
585
|
+
modalLoaded: '✓ Loaded!',
|
|
586
|
+
modalUnknownError: '✗ Unknown error',
|
|
587
|
+
modalErrorPrefix: '✗ Error: ',
|
|
588
|
+
copyBtn: 'Copy Code',
|
|
589
|
+
copyBtnAction: 'Copy Code',
|
|
590
|
+
copied: '✓ Copied!',
|
|
591
|
+
uploadLabel: '📂 Upload backup',
|
|
592
|
+
localDropdown: '🗂️ Local Backups ▾',
|
|
593
|
+
ftpDropdown: '🌐 FTP Backups ▾',
|
|
594
|
+
smbDropdown: '🗄️ SMB Backups ▾',
|
|
595
|
+
sftpDropdown: '🔒 SFTP Backups ▾',
|
|
596
|
+
webdavDropdown: '☁️ WebDAV Backups ▾',
|
|
597
|
+
httpLoadBtn: '🌐 Load URL',
|
|
598
|
+
zipBtn: '📦 ZIP',
|
|
599
|
+
statusDefault: 'Load a backup or select a source',
|
|
600
|
+
searchPlaceholder: 'Search in names, folders & code...',
|
|
601
|
+
expandAll: 'Expand all',
|
|
602
|
+
collapseAll: 'Collapse all',
|
|
603
|
+
typeAll: 'All',
|
|
604
|
+
restoreBtn: 'Load into ioBroker',
|
|
605
|
+
downloadBtn: 'Download',
|
|
606
|
+
welcomeText: 'Upload a backup or select a local file,<br>to view and restore scripts.',
|
|
607
|
+
noSocket: 'No socket. Please check if script-restore.{i} is running.',
|
|
608
|
+
timeout: 'Timeout: Adapter not responding. Is script-restore.{i} running?',
|
|
609
|
+
},
|
|
610
|
+
fr: {
|
|
611
|
+
loaderLoading: 'Chargement de la sauvegarde...',
|
|
612
|
+
loaderProcessing: 'Traitement en cours...',
|
|
613
|
+
modalTitle: 'Charger dans ioBroker',
|
|
614
|
+
modalLabelScript: 'Script :',
|
|
615
|
+
modalLabelPath: 'Chemin :',
|
|
616
|
+
modalLabelType: 'Type :',
|
|
617
|
+
modalLabelSuffix: 'Suffixe (ajouté au nom du script)',
|
|
618
|
+
modalWarning: '⚠ Un script à {path} existe déjà.<br>Voulez-vous vraiment l\'écraser ?',
|
|
619
|
+
modalDismiss: 'Choisir un autre suffixe',
|
|
620
|
+
modalOverwrite: 'Écraser',
|
|
621
|
+
modalSuccess: '✓ Restauré avec succès.<br>Voulez-vous démarrer le script maintenant ?',
|
|
622
|
+
modalClose: 'Non merci',
|
|
623
|
+
modalStart: 'Démarrer maintenant',
|
|
624
|
+
modalLoad: 'Charger',
|
|
625
|
+
modalLoading: '⏳ Chargement...',
|
|
626
|
+
modalStarting: '⏳ Démarrage...',
|
|
627
|
+
modalStarted: '✓ Démarré',
|
|
628
|
+
modalLoaded: '✓ Chargé !',
|
|
629
|
+
modalUnknownError: '✗ Erreur inconnue',
|
|
630
|
+
modalErrorPrefix: '✗ Erreur : ',
|
|
631
|
+
copyBtn: 'Copier le code',
|
|
632
|
+
copyBtnAction: 'Copier le code',
|
|
633
|
+
copied: '✓ Copié !',
|
|
634
|
+
uploadLabel: '📂 Téléverser une sauvegarde',
|
|
635
|
+
localDropdown: '🗂️ Sauvegardes locales ▾',
|
|
636
|
+
ftpDropdown: '🌐 Sauvegardes FTP ▾',
|
|
637
|
+
smbDropdown: '🗄️ Sauvegardes SMB ▾',
|
|
638
|
+
sftpDropdown: '🔒 Sauvegardes SFTP ▾',
|
|
639
|
+
webdavDropdown: '☁️ Sauvegardes WebDAV ▾',
|
|
640
|
+
httpLoadBtn: '🌐 Charger URL',
|
|
641
|
+
zipBtn: '📦 ZIP',
|
|
642
|
+
statusDefault: 'Charger une sauvegarde ou choisir une source',
|
|
643
|
+
searchPlaceholder: 'Rechercher dans les noms, dossiers et code...',
|
|
644
|
+
expandAll: 'Tout développer',
|
|
645
|
+
collapseAll: 'Tout réduire',
|
|
646
|
+
typeAll: 'Tous',
|
|
647
|
+
restoreBtn: 'Charger dans ioBroker',
|
|
648
|
+
downloadBtn: 'Télécharger',
|
|
649
|
+
welcomeText: 'Téléversez une sauvegarde ou sélectionnez un fichier local,<br>pour afficher et restaurer des scripts.',
|
|
650
|
+
noSocket: 'Pas de socket. Vérifiez si script-restore.{i} est en cours d\'exécution.',
|
|
651
|
+
timeout: 'Délai d\'attente : l\'adaptateur ne répond pas. script-restore.{i} est-il en cours d\'exécution ?',
|
|
652
|
+
},
|
|
653
|
+
es: {
|
|
654
|
+
loaderLoading: 'Cargando copia de seguridad...',
|
|
655
|
+
loaderProcessing: 'Procesando...',
|
|
656
|
+
modalTitle: 'Cargar en ioBroker',
|
|
657
|
+
modalLabelScript: 'Script:',
|
|
658
|
+
modalLabelPath: 'Ruta:',
|
|
659
|
+
modalLabelType: 'Tipo:',
|
|
660
|
+
modalLabelSuffix: 'Sufijo (se añade al nombre del script)',
|
|
661
|
+
modalWarning: '⚠ Ya existe un script en {path}.<br>¿Realmente desea sobrescribirlo?',
|
|
662
|
+
modalDismiss: 'Elegir otro sufijo',
|
|
663
|
+
modalOverwrite: 'Sobrescribir',
|
|
664
|
+
modalSuccess: '✓ Restaurado con éxito.<br>¿Desea iniciar el script ahora?',
|
|
665
|
+
modalClose: 'No gracias',
|
|
666
|
+
modalStart: 'Iniciar ahora',
|
|
667
|
+
modalLoad: 'Cargar',
|
|
668
|
+
modalLoading: '⏳ Cargando...',
|
|
669
|
+
modalStarting: '⏳ Iniciando...',
|
|
670
|
+
modalStarted: '✓ Iniciado',
|
|
671
|
+
modalLoaded: '✓ ¡Cargado!',
|
|
672
|
+
modalUnknownError: '✗ Error desconocido',
|
|
673
|
+
modalErrorPrefix: '✗ Error: ',
|
|
674
|
+
copyBtn: 'Copiar código',
|
|
675
|
+
copyBtnAction: 'Copiar código',
|
|
676
|
+
copied: '✓ ¡Copiado!',
|
|
677
|
+
uploadLabel: '📂 Subir copia de seguridad',
|
|
678
|
+
localDropdown: '🗂️ Copias locales ▾',
|
|
679
|
+
ftpDropdown: '🌐 Copias FTP ▾',
|
|
680
|
+
smbDropdown: '🗄️ Copias SMB ▾',
|
|
681
|
+
sftpDropdown: '🔒 Copias SFTP ▾',
|
|
682
|
+
webdavDropdown: '☁️ Copias WebDAV ▾',
|
|
683
|
+
httpLoadBtn: '🌐 Cargar URL',
|
|
684
|
+
zipBtn: '📦 ZIP',
|
|
685
|
+
statusDefault: 'Cargar una copia de seguridad o seleccionar una fuente',
|
|
686
|
+
searchPlaceholder: 'Buscar en nombres, carpetas y código...',
|
|
687
|
+
expandAll: 'Expandir todo',
|
|
688
|
+
collapseAll: 'Contraer todo',
|
|
689
|
+
typeAll: 'Todos',
|
|
690
|
+
restoreBtn: 'Cargar en ioBroker',
|
|
691
|
+
downloadBtn: 'Descargar',
|
|
692
|
+
welcomeText: 'Sube una copia de seguridad o selecciona un archivo local,<br>para ver y restaurar scripts.',
|
|
693
|
+
noSocket: 'Sin socket. Compruebe si script-restore.{i} está en ejecución.',
|
|
694
|
+
timeout: 'Tiempo de espera agotado: el adaptador no responde. ¿Está script-restore.{i} en ejecución?',
|
|
695
|
+
},
|
|
696
|
+
it: {
|
|
697
|
+
loaderLoading: 'Caricamento backup...',
|
|
698
|
+
loaderProcessing: 'Elaborazione...',
|
|
699
|
+
modalTitle: 'Carica in ioBroker',
|
|
700
|
+
modalLabelScript: 'Script:',
|
|
701
|
+
modalLabelPath: 'Percorso:',
|
|
702
|
+
modalLabelType: 'Tipo:',
|
|
703
|
+
modalLabelSuffix: 'Suffisso (aggiunto al nome dello script)',
|
|
704
|
+
modalWarning: '⚠ Esiste già uno script in {path}.<br>Vuoi davvero sovrascriverlo?',
|
|
705
|
+
modalDismiss: 'Scegli un suffisso diverso',
|
|
706
|
+
modalOverwrite: 'Sovrascrivi',
|
|
707
|
+
modalSuccess: '✓ Ripristinato con successo.<br>Vuoi avviare lo script adesso?',
|
|
708
|
+
modalClose: 'No grazie',
|
|
709
|
+
modalStart: 'Avvia ora',
|
|
710
|
+
modalLoad: 'Carica',
|
|
711
|
+
modalLoading: '⏳ Caricamento...',
|
|
712
|
+
modalStarting: '⏳ Avvio...',
|
|
713
|
+
modalStarted: '✓ Avviato',
|
|
714
|
+
modalLoaded: '✓ Caricato!',
|
|
715
|
+
modalUnknownError: '✗ Errore sconosciuto',
|
|
716
|
+
modalErrorPrefix: '✗ Errore: ',
|
|
717
|
+
copyBtn: 'Copia codice',
|
|
718
|
+
copyBtnAction: 'Copia codice',
|
|
719
|
+
copied: '✓ Copiato!',
|
|
720
|
+
uploadLabel: '📂 Carica backup',
|
|
721
|
+
localDropdown: '🗂️ Backup locali ▾',
|
|
722
|
+
ftpDropdown: '🌐 Backup FTP ▾',
|
|
723
|
+
smbDropdown: '🗄️ Backup SMB ▾',
|
|
724
|
+
sftpDropdown: '🔒 Backup SFTP ▾',
|
|
725
|
+
webdavDropdown: '☁️ Backup WebDAV ▾',
|
|
726
|
+
httpLoadBtn: '🌐 Carica URL',
|
|
727
|
+
zipBtn: '📦 ZIP',
|
|
728
|
+
statusDefault: 'Carica un backup o seleziona una sorgente',
|
|
729
|
+
searchPlaceholder: 'Cerca in nomi, cartelle e codice...',
|
|
730
|
+
expandAll: 'Espandi tutto',
|
|
731
|
+
collapseAll: 'Comprimi tutto',
|
|
732
|
+
typeAll: 'Tutti',
|
|
733
|
+
restoreBtn: 'Carica in ioBroker',
|
|
734
|
+
downloadBtn: 'Scarica',
|
|
735
|
+
welcomeText: 'Carica un backup o seleziona un file locale,<br>per visualizzare e ripristinare gli script.',
|
|
736
|
+
noSocket: 'Nessun socket. Verificare se script-restore.{i} è in esecuzione.',
|
|
737
|
+
timeout: 'Timeout: l\'adattatore non risponde. script-restore.{i} è in esecuzione?',
|
|
738
|
+
},
|
|
739
|
+
nl: {
|
|
740
|
+
loaderLoading: 'Back-up laden...',
|
|
741
|
+
loaderProcessing: 'Verwerken...',
|
|
742
|
+
modalTitle: 'Laden in ioBroker',
|
|
743
|
+
modalLabelScript: 'Script:',
|
|
744
|
+
modalLabelPath: 'Pad:',
|
|
745
|
+
modalLabelType: 'Type:',
|
|
746
|
+
modalLabelSuffix: 'Achtervoegsel (toegevoegd aan de scriptnaam)',
|
|
747
|
+
modalWarning: '⚠ Er bestaat al een script op {path}.<br>Wilt u het echt overschrijven?',
|
|
748
|
+
modalDismiss: 'Ander achtervoegsel kiezen',
|
|
749
|
+
modalOverwrite: 'Overschrijven',
|
|
750
|
+
modalSuccess: '✓ Succesvol hersteld.<br>Wilt u het script nu starten?',
|
|
751
|
+
modalClose: 'Nee bedankt',
|
|
752
|
+
modalStart: 'Nu starten',
|
|
753
|
+
modalLoad: 'Laden',
|
|
754
|
+
modalLoading: '⏳ Laden...',
|
|
755
|
+
modalStarting: '⏳ Starten...',
|
|
756
|
+
modalStarted: '✓ Gestart',
|
|
757
|
+
modalLoaded: '✓ Geladen!',
|
|
758
|
+
modalUnknownError: '✗ Onbekende fout',
|
|
759
|
+
modalErrorPrefix: '✗ Fout: ',
|
|
760
|
+
copyBtn: 'Code kopiëren',
|
|
761
|
+
copyBtnAction: 'Code kopiëren',
|
|
762
|
+
copied: '✓ Gekopieerd!',
|
|
763
|
+
uploadLabel: '📂 Back-up uploaden',
|
|
764
|
+
localDropdown: '🗂️ Lokale back-ups ▾',
|
|
765
|
+
ftpDropdown: '🌐 FTP back-ups ▾',
|
|
766
|
+
smbDropdown: '🗄️ SMB back-ups ▾',
|
|
767
|
+
sftpDropdown: '🔒 SFTP back-ups ▾',
|
|
768
|
+
webdavDropdown: '☁️ WebDAV back-ups ▾',
|
|
769
|
+
httpLoadBtn: '🌐 URL laden',
|
|
770
|
+
zipBtn: '📦 ZIP',
|
|
771
|
+
statusDefault: 'Laad een back-up of kies een bron',
|
|
772
|
+
searchPlaceholder: 'Zoeken in namen, mappen en code...',
|
|
773
|
+
expandAll: 'Alles uitklappen',
|
|
774
|
+
collapseAll: 'Alles inklappen',
|
|
775
|
+
typeAll: 'Alle',
|
|
776
|
+
restoreBtn: 'Laden in ioBroker',
|
|
777
|
+
downloadBtn: 'Downloaden',
|
|
778
|
+
welcomeText: 'Upload een back-up of selecteer een lokaal bestand,<br>om scripts te bekijken en te herstellen.',
|
|
779
|
+
noSocket: 'Geen socket. Controleer of script-restore.{i} actief is.',
|
|
780
|
+
timeout: 'Time-out: adapter reageert niet. Is script-restore.{i} actief?',
|
|
781
|
+
},
|
|
782
|
+
pl: {
|
|
783
|
+
loaderLoading: 'Wczytywanie kopii zapasowej...',
|
|
784
|
+
loaderProcessing: 'Przetwarzanie...',
|
|
785
|
+
modalTitle: 'Wczytaj do ioBroker',
|
|
786
|
+
modalLabelScript: 'Skrypt:',
|
|
787
|
+
modalLabelPath: 'Ścieżka:',
|
|
788
|
+
modalLabelType: 'Typ:',
|
|
789
|
+
modalLabelSuffix: 'Sufiks (dodawany do nazwy skryptu)',
|
|
790
|
+
modalWarning: '⚠ Skrypt w {path} już istnieje.<br>Czy na pewno chcesz go nadpisać?',
|
|
791
|
+
modalDismiss: 'Wybierz inny sufiks',
|
|
792
|
+
modalOverwrite: 'Nadpisz',
|
|
793
|
+
modalSuccess: '✓ Przywrócono pomyślnie.<br>Czy chcesz teraz uruchomić skrypt?',
|
|
794
|
+
modalClose: 'Nie, dziękuję',
|
|
795
|
+
modalStart: 'Uruchom teraz',
|
|
796
|
+
modalLoad: 'Wczytaj',
|
|
797
|
+
modalLoading: '⏳ Wczytywanie...',
|
|
798
|
+
modalStarting: '⏳ Uruchamianie...',
|
|
799
|
+
modalStarted: '✓ Uruchomiono',
|
|
800
|
+
modalLoaded: '✓ Wczytano!',
|
|
801
|
+
modalUnknownError: '✗ Nieznany błąd',
|
|
802
|
+
modalErrorPrefix: '✗ Błąd: ',
|
|
803
|
+
copyBtn: 'Kopiuj kod',
|
|
804
|
+
copyBtnAction: 'Kopiuj kod',
|
|
805
|
+
copied: '✓ Skopiowano!',
|
|
806
|
+
uploadLabel: '📂 Prześlij kopię zapasową',
|
|
807
|
+
localDropdown: '🗂️ Lokalne kopie ▾',
|
|
808
|
+
ftpDropdown: '🌐 Kopie FTP ▾',
|
|
809
|
+
smbDropdown: '🗄️ Kopie SMB ▾',
|
|
810
|
+
sftpDropdown: '🔒 Kopie SFTP ▾',
|
|
811
|
+
webdavDropdown: '☁️ Kopie WebDAV ▾',
|
|
812
|
+
httpLoadBtn: '🌐 Wczytaj URL',
|
|
813
|
+
zipBtn: '📦 ZIP',
|
|
814
|
+
statusDefault: 'Wczytaj kopię zapasową lub wybierz źródło',
|
|
815
|
+
searchPlaceholder: 'Szukaj w nazwach, folderach i kodzie...',
|
|
816
|
+
expandAll: 'Rozwiń wszystko',
|
|
817
|
+
collapseAll: 'Zwiń wszystko',
|
|
818
|
+
typeAll: 'Wszystkie',
|
|
819
|
+
restoreBtn: 'Wczytaj do ioBroker',
|
|
820
|
+
downloadBtn: 'Pobierz',
|
|
821
|
+
welcomeText: 'Prześlij kopię zapasową lub wybierz plik lokalny,<br>aby wyświetlić i przywrócić skrypty.',
|
|
822
|
+
noSocket: 'Brak gniazda. Sprawdź, czy script-restore.{i} działa.',
|
|
823
|
+
timeout: 'Przekroczono czas: adapter nie odpowiada. Czy script-restore.{i} działa?',
|
|
824
|
+
},
|
|
825
|
+
pt: {
|
|
826
|
+
loaderLoading: 'A carregar cópia de segurança...',
|
|
827
|
+
loaderProcessing: 'A processar...',
|
|
828
|
+
modalTitle: 'Carregar no ioBroker',
|
|
829
|
+
modalLabelScript: 'Script:',
|
|
830
|
+
modalLabelPath: 'Caminho:',
|
|
831
|
+
modalLabelType: 'Tipo:',
|
|
832
|
+
modalLabelSuffix: 'Sufixo (adicionado ao nome do script)',
|
|
833
|
+
modalWarning: '⚠ Já existe um script em {path}.<br>Tem a certeza que deseja substituí-lo?',
|
|
834
|
+
modalDismiss: 'Escolher outro sufixo',
|
|
835
|
+
modalOverwrite: 'Substituir',
|
|
836
|
+
modalSuccess: '✓ Restaurado com sucesso.<br>Deseja iniciar o script agora?',
|
|
837
|
+
modalClose: 'Não, obrigado',
|
|
838
|
+
modalStart: 'Iniciar agora',
|
|
839
|
+
modalLoad: 'Carregar',
|
|
840
|
+
modalLoading: '⏳ A carregar...',
|
|
841
|
+
modalStarting: '⏳ A iniciar...',
|
|
842
|
+
modalStarted: '✓ Iniciado',
|
|
843
|
+
modalLoaded: '✓ Carregado!',
|
|
844
|
+
modalUnknownError: '✗ Erro desconhecido',
|
|
845
|
+
modalErrorPrefix: '✗ Erro: ',
|
|
846
|
+
copyBtn: 'Copiar código',
|
|
847
|
+
copyBtnAction: 'Copiar código',
|
|
848
|
+
copied: '✓ Copiado!',
|
|
849
|
+
uploadLabel: '📂 Carregar cópia de segurança',
|
|
850
|
+
localDropdown: '🗂️ Cópias locais ▾',
|
|
851
|
+
ftpDropdown: '🌐 Cópias FTP ▾',
|
|
852
|
+
smbDropdown: '🗄️ Cópias SMB ▾',
|
|
853
|
+
sftpDropdown: '🔒 Cópias SFTP ▾',
|
|
854
|
+
webdavDropdown: '☁️ Cópias WebDAV ▾',
|
|
855
|
+
httpLoadBtn: '🌐 Carregar URL',
|
|
856
|
+
zipBtn: '📦 ZIP',
|
|
857
|
+
statusDefault: 'Carregar uma cópia de segurança ou selecionar uma fonte',
|
|
858
|
+
searchPlaceholder: 'Pesquisar em nomes, pastas e código...',
|
|
859
|
+
expandAll: 'Expandir tudo',
|
|
860
|
+
collapseAll: 'Recolher tudo',
|
|
861
|
+
typeAll: 'Todos',
|
|
862
|
+
restoreBtn: 'Carregar no ioBroker',
|
|
863
|
+
downloadBtn: 'Transferir',
|
|
864
|
+
welcomeText: 'Carregue uma cópia de segurança ou selecione um ficheiro local,<br>para ver e restaurar scripts.',
|
|
865
|
+
noSocket: 'Sem socket. Verifique se script-restore.{i} está em execução.',
|
|
866
|
+
timeout: 'Tempo esgotado: o adaptador não responde. O script-restore.{i} está em execução?',
|
|
867
|
+
},
|
|
868
|
+
ru: {
|
|
869
|
+
loaderLoading: 'Загрузка резервной копии...',
|
|
870
|
+
loaderProcessing: 'Обработка...',
|
|
871
|
+
modalTitle: 'Загрузить в ioBroker',
|
|
872
|
+
modalLabelScript: 'Скрипт:',
|
|
873
|
+
modalLabelPath: 'Путь:',
|
|
874
|
+
modalLabelType: 'Тип:',
|
|
875
|
+
modalLabelSuffix: 'Суффикс (добавляется к имени скрипта)',
|
|
876
|
+
modalWarning: '⚠ Скрипт по пути {path} уже существует.<br>Вы действительно хотите перезаписать его?',
|
|
877
|
+
modalDismiss: 'Выбрать другой суффикс',
|
|
878
|
+
modalOverwrite: 'Перезаписать',
|
|
879
|
+
modalSuccess: '✓ Успешно восстановлено.<br>Хотите запустить скрипт сейчас?',
|
|
880
|
+
modalClose: 'Нет, спасибо',
|
|
881
|
+
modalStart: 'Запустить сейчас',
|
|
882
|
+
modalLoad: 'Загрузить',
|
|
883
|
+
modalLoading: '⏳ Загрузка...',
|
|
884
|
+
modalStarting: '⏳ Запуск...',
|
|
885
|
+
modalStarted: '✓ Запущен',
|
|
886
|
+
modalLoaded: '✓ Загружен!',
|
|
887
|
+
modalUnknownError: '✗ Неизвестная ошибка',
|
|
888
|
+
modalErrorPrefix: '✗ Ошибка: ',
|
|
889
|
+
copyBtn: 'Копировать код',
|
|
890
|
+
copyBtnAction: 'Копировать код',
|
|
891
|
+
copied: '✓ Скопировано!',
|
|
892
|
+
uploadLabel: '📂 Загрузить резервную копию',
|
|
893
|
+
localDropdown: '🗂️ Локальные резервные копии ▾',
|
|
894
|
+
ftpDropdown: '🌐 Резервные копии FTP ▾',
|
|
895
|
+
smbDropdown: '🗄️ Резервные копии SMB ▾',
|
|
896
|
+
sftpDropdown: '🔒 Резервные копии SFTP ▾',
|
|
897
|
+
webdavDropdown: '☁️ Резервные копии WebDAV ▾',
|
|
898
|
+
httpLoadBtn: '🌐 Загрузить URL',
|
|
899
|
+
zipBtn: '📦 ZIP',
|
|
900
|
+
statusDefault: 'Загрузите резервную копию или выберите источник',
|
|
901
|
+
searchPlaceholder: 'Поиск по именам, папкам и коду...',
|
|
902
|
+
expandAll: 'Развернуть всё',
|
|
903
|
+
collapseAll: 'Свернуть всё',
|
|
904
|
+
typeAll: 'Все',
|
|
905
|
+
restoreBtn: 'Загрузить в ioBroker',
|
|
906
|
+
downloadBtn: 'Скачать',
|
|
907
|
+
welcomeText: 'Загрузите резервную копию или выберите локальный файл,<br>чтобы просмотреть и восстановить скрипты.',
|
|
908
|
+
noSocket: 'Нет сокета. Проверьте, запущен ли script-restore.{i}.',
|
|
909
|
+
timeout: 'Таймаут: адаптер не отвечает. Запущен ли script-restore.{i}?',
|
|
910
|
+
},
|
|
911
|
+
uk: {
|
|
912
|
+
loaderLoading: 'Завантаження резервної копії...',
|
|
913
|
+
loaderProcessing: 'Обробка...',
|
|
914
|
+
modalTitle: 'Завантажити в ioBroker',
|
|
915
|
+
modalLabelScript: 'Скрипт:',
|
|
916
|
+
modalLabelPath: 'Шлях:',
|
|
917
|
+
modalLabelType: 'Тип:',
|
|
918
|
+
modalLabelSuffix: 'Суфікс (додається до назви скрипта)',
|
|
919
|
+
modalWarning: '⚠ Скрипт за шляхом {path} вже існує.<br>Ви дійсно хочете його перезаписати?',
|
|
920
|
+
modalDismiss: 'Вибрати інший суфікс',
|
|
921
|
+
modalOverwrite: 'Перезаписати',
|
|
922
|
+
modalSuccess: '✓ Успішно відновлено.<br>Хочете запустити скрипт зараз?',
|
|
923
|
+
modalClose: 'Ні, дякую',
|
|
924
|
+
modalStart: 'Запустити зараз',
|
|
925
|
+
modalLoad: 'Завантажити',
|
|
926
|
+
modalLoading: '⏳ Завантаження...',
|
|
927
|
+
modalStarting: '⏳ Запуск...',
|
|
928
|
+
modalStarted: '✓ Запущено',
|
|
929
|
+
modalLoaded: '✓ Завантажено!',
|
|
930
|
+
modalUnknownError: '✗ Невідома помилка',
|
|
931
|
+
modalErrorPrefix: '✗ Помилка: ',
|
|
932
|
+
copyBtn: 'Копіювати код',
|
|
933
|
+
copyBtnAction: 'Копіювати код',
|
|
934
|
+
copied: '✓ Скопійовано!',
|
|
935
|
+
uploadLabel: '📂 Завантажити резервну копію',
|
|
936
|
+
localDropdown: '🗂️ Локальні резервні копії ▾',
|
|
937
|
+
ftpDropdown: '🌐 Резервні копії FTP ▾',
|
|
938
|
+
smbDropdown: '🗄️ Резервні копії SMB ▾',
|
|
939
|
+
sftpDropdown: '🔒 Резервні копії SFTP ▾',
|
|
940
|
+
webdavDropdown: '☁️ Резервні копії WebDAV ▾',
|
|
941
|
+
httpLoadBtn: '🌐 Завантажити URL',
|
|
942
|
+
zipBtn: '📦 ZIP',
|
|
943
|
+
statusDefault: 'Завантажте резервну копію або оберіть джерело',
|
|
944
|
+
searchPlaceholder: 'Пошук за іменами, папками та кодом...',
|
|
945
|
+
expandAll: 'Розгорнути все',
|
|
946
|
+
collapseAll: 'Згорнути все',
|
|
947
|
+
typeAll: 'Усі',
|
|
948
|
+
restoreBtn: 'Завантажити в ioBroker',
|
|
949
|
+
downloadBtn: 'Завантажити',
|
|
950
|
+
welcomeText: 'Завантажте резервну копію або оберіть локальний файл,<br>щоб переглянути та відновити скрипти.',
|
|
951
|
+
noSocket: 'Немає сокета. Перевірте, чи запущено script-restore.{i}.',
|
|
952
|
+
timeout: 'Час очікування вичерпано: адаптер не відповідає. Чи запущено script-restore.{i}?',
|
|
953
|
+
},
|
|
954
|
+
'zh-cn': {
|
|
955
|
+
loaderLoading: '正在加载备份...',
|
|
956
|
+
loaderProcessing: '处理中...',
|
|
957
|
+
modalTitle: '加载到 ioBroker',
|
|
958
|
+
modalLabelScript: '脚本:',
|
|
959
|
+
modalLabelPath: '路径:',
|
|
960
|
+
modalLabelType: '类型:',
|
|
961
|
+
modalLabelSuffix: '后缀(附加到脚本名称)',
|
|
962
|
+
modalWarning: '⚠ {path} 下已存在一个脚本。<br>您真的要覆盖它吗?',
|
|
963
|
+
modalDismiss: '选择其他后缀',
|
|
964
|
+
modalOverwrite: '覆盖',
|
|
965
|
+
modalSuccess: '✓ 恢复成功。<br>是否立即启动该脚本?',
|
|
966
|
+
modalClose: '不,谢谢',
|
|
967
|
+
modalStart: '立即启动',
|
|
968
|
+
modalLoad: '加载',
|
|
969
|
+
modalLoading: '⏳ 加载中...',
|
|
970
|
+
modalStarting: '⏳ 启动中...',
|
|
971
|
+
modalStarted: '✓ 已启动',
|
|
972
|
+
modalLoaded: '✓ 已加载!',
|
|
973
|
+
modalUnknownError: '✗ 未知错误',
|
|
974
|
+
modalErrorPrefix: '✗ 错误:',
|
|
975
|
+
copyBtn: '复制代码',
|
|
976
|
+
copyBtnAction: '复制代码',
|
|
977
|
+
copied: '✓ 已复制!',
|
|
978
|
+
uploadLabel: '📂 上传备份',
|
|
979
|
+
localDropdown: '🗂️ 本地备份 ▾',
|
|
980
|
+
ftpDropdown: '🌐 FTP 备份 ▾',
|
|
981
|
+
smbDropdown: '🗄️ SMB 备份 ▾',
|
|
982
|
+
sftpDropdown: '🔒 SFTP 备份 ▾',
|
|
983
|
+
webdavDropdown: '☁️ WebDAV 备份 ▾',
|
|
984
|
+
httpLoadBtn: '🌐 加载 URL',
|
|
985
|
+
zipBtn: '📦 ZIP',
|
|
986
|
+
statusDefault: '加载备份或选择来源',
|
|
987
|
+
searchPlaceholder: '在名称、文件夹和代码中搜索...',
|
|
988
|
+
expandAll: '全部展开',
|
|
989
|
+
collapseAll: '全部折叠',
|
|
990
|
+
typeAll: '全部',
|
|
991
|
+
restoreBtn: '加载到 ioBroker',
|
|
992
|
+
downloadBtn: '下载',
|
|
993
|
+
welcomeText: '上传备份或选择本地文件,<br>以查看和恢复脚本。',
|
|
994
|
+
noSocket: '无套接字。请检查 script-restore.{i} 是否正在运行。',
|
|
995
|
+
timeout: '超时:适配器无响应。script-restore.{i} 是否正在运行?',
|
|
996
|
+
},
|
|
997
|
+
};
|
|
998
|
+
|
|
999
|
+
function detectLang() {
|
|
1000
|
+
// 1. URL parameter
|
|
1001
|
+
const lp = urlParams.get('lang') || urlParams.get('language');
|
|
1002
|
+
if (lp) return normLang(lp);
|
|
1003
|
+
// 2. localStorage
|
|
1004
|
+
try {
|
|
1005
|
+
const ls = localStorage.getItem('App.language') || localStorage.getItem('ioBroker.locale');
|
|
1006
|
+
if (ls) return normLang(ls);
|
|
1007
|
+
} catch(e) {}
|
|
1008
|
+
// 3. Parent frame
|
|
1009
|
+
try {
|
|
1010
|
+
const p = window.parent;
|
|
1011
|
+
if (p && (p.sysLang || p.systemLang)) return normLang(p.sysLang || p.systemLang);
|
|
1012
|
+
} catch(e) {}
|
|
1013
|
+
// 4. Navigator
|
|
1014
|
+
return normLang(navigator.language || 'en');
|
|
1015
|
+
}
|
|
1016
|
+
|
|
1017
|
+
function normLang(l) {
|
|
1018
|
+
if (!l) return 'en';
|
|
1019
|
+
const ll = l.toLowerCase().replace('_', '-');
|
|
1020
|
+
if (ll === 'zh-cn' || ll === 'zh') return 'zh-cn';
|
|
1021
|
+
return ll.slice(0, 2);
|
|
1022
|
+
}
|
|
1023
|
+
|
|
1024
|
+
const LANG = (function() {
|
|
1025
|
+
const detected = detectLang();
|
|
1026
|
+
return TRANSLATIONS[detected] ? detected : 'en';
|
|
1027
|
+
})();
|
|
1028
|
+
|
|
1029
|
+
function t(key) {
|
|
1030
|
+
return (TRANSLATIONS[LANG] && TRANSLATIONS[LANG][key]) || (TRANSLATIONS.en && TRANSLATIONS.en[key]) || key;
|
|
1031
|
+
}
|
|
1032
|
+
|
|
1033
|
+
function applyTranslations() {
|
|
1034
|
+
document.querySelectorAll('[data-i18n]').forEach(function(el) {
|
|
1035
|
+
el.textContent = t(el.getAttribute('data-i18n'));
|
|
1036
|
+
});
|
|
1037
|
+
document.querySelectorAll('[data-i18n-html]').forEach(function(el) {
|
|
1038
|
+
el.innerHTML = t(el.getAttribute('data-i18n-html'));
|
|
1039
|
+
});
|
|
1040
|
+
document.querySelectorAll('[data-i18n-placeholder]').forEach(function(el) {
|
|
1041
|
+
el.placeholder = t(el.getAttribute('data-i18n-placeholder'));
|
|
1042
|
+
});
|
|
1043
|
+
document.querySelectorAll('[data-i18n-title]').forEach(function(el) {
|
|
1044
|
+
el.title = t(el.getAttribute('data-i18n-title'));
|
|
1045
|
+
});
|
|
1046
|
+
}
|
|
1047
|
+
|
|
1048
|
+
applyTranslations();
|
|
1049
|
+
|
|
489
1050
|
// === Dark Theme Detection ===
|
|
490
1051
|
function applyTheme(isDark) {
|
|
491
1052
|
document.body.classList.toggle('dark', !!isDark);
|
|
@@ -591,14 +1152,14 @@
|
|
|
591
1152
|
|
|
592
1153
|
function sendTo(command, message, callback) {
|
|
593
1154
|
if (!socket) {
|
|
594
|
-
callback({ error: '
|
|
1155
|
+
callback({ error: t('noSocket').replace('{i}', instance) });
|
|
595
1156
|
return;
|
|
596
1157
|
}
|
|
597
1158
|
let done = false;
|
|
598
1159
|
const timer = setTimeout(() => {
|
|
599
1160
|
if (done) return;
|
|
600
1161
|
done = true;
|
|
601
|
-
callback({ error: '
|
|
1162
|
+
callback({ error: t('timeout').replace('{i}', instance) });
|
|
602
1163
|
}, 30000);
|
|
603
1164
|
const wrapped = (result) => {
|
|
604
1165
|
if (done) return;
|
|
@@ -1004,13 +1565,13 @@
|
|
|
1004
1565
|
document.getElementById('spinnerEl').style.display = 'none';
|
|
1005
1566
|
document.getElementById('progressCircle').style.background = 'conic-gradient(var(--primary) 0%, #e9ecef 0%)';
|
|
1006
1567
|
document.getElementById('progressPercent').textContent = '0%';
|
|
1007
|
-
document.getElementById('loaderText').textContent = text || '
|
|
1568
|
+
document.getElementById('loaderText').textContent = text || t('loaderLoading');
|
|
1008
1569
|
document.getElementById('loader').style.display = 'flex';
|
|
1009
1570
|
}
|
|
1010
1571
|
function showLoaderSpinner(text) {
|
|
1011
1572
|
document.getElementById('progressContainer').style.display = 'none';
|
|
1012
1573
|
document.getElementById('spinnerEl').style.display = 'block';
|
|
1013
|
-
document.getElementById('loaderText').textContent = text || '
|
|
1574
|
+
document.getElementById('loaderText').textContent = text || t('loaderProcessing');
|
|
1014
1575
|
document.getElementById('loader').style.display = 'flex';
|
|
1015
1576
|
}
|
|
1016
1577
|
function updateProgress(pct) {
|
|
@@ -1027,7 +1588,7 @@
|
|
|
1027
1588
|
isAllExpanded = !isAllExpanded;
|
|
1028
1589
|
const btn = document.getElementById('expandToggleBtn');
|
|
1029
1590
|
btn.innerHTML = isAllExpanded ? '📁' : '📂';
|
|
1030
|
-
btn.title = isAllExpanded ? '
|
|
1591
|
+
btn.title = isAllExpanded ? t('collapseAll') : t('expandAll');
|
|
1031
1592
|
document.querySelectorAll('.tree-folder').forEach(el => {
|
|
1032
1593
|
const p = el.dataset.path;
|
|
1033
1594
|
const icon = el.querySelector('.folder-icon');
|
|
@@ -1214,12 +1775,12 @@
|
|
|
1214
1775
|
ta.value = txt; document.body.appendChild(ta); ta.select();
|
|
1215
1776
|
try {
|
|
1216
1777
|
document.execCommand('copy');
|
|
1217
|
-
btn.textContent = '
|
|
1778
|
+
btn.textContent = t('copied');
|
|
1218
1779
|
btn.classList.replace('btn-outline-light', 'btn-outline-success');
|
|
1219
1780
|
} finally {
|
|
1220
1781
|
document.body.removeChild(ta);
|
|
1221
1782
|
setTimeout(() => {
|
|
1222
|
-
btn.textContent = '
|
|
1783
|
+
btn.textContent = t('copyBtnAction');
|
|
1223
1784
|
btn.classList.replace('btn-outline-success', 'btn-outline-light');
|
|
1224
1785
|
}, 1500);
|
|
1225
1786
|
}
|
|
@@ -1245,6 +1806,8 @@
|
|
|
1245
1806
|
}
|
|
1246
1807
|
|
|
1247
1808
|
// === Restore Modal ===
|
|
1809
|
+
let _restoredScriptId = null;
|
|
1810
|
+
|
|
1248
1811
|
function openRestoreModal() {
|
|
1249
1812
|
if (cur.index < 0) return;
|
|
1250
1813
|
const s = scriptsData[cur.index];
|
|
@@ -1252,9 +1815,13 @@
|
|
|
1252
1815
|
document.getElementById('rmScriptPath').textContent = s.path;
|
|
1253
1816
|
document.getElementById('rmScriptType').textContent = s.type;
|
|
1254
1817
|
document.getElementById('rmSuffix').value = '_rcvr';
|
|
1818
|
+
document.getElementById('rmSuffix').disabled = false;
|
|
1255
1819
|
document.getElementById('rmMsg').textContent = '';
|
|
1256
1820
|
document.getElementById('rmMsg').style.color = '';
|
|
1821
|
+
document.getElementById('rmWarning').style.display = 'none';
|
|
1822
|
+
document.getElementById('rmSuccess').style.display = 'none';
|
|
1257
1823
|
document.getElementById('rmConfirmBtn').disabled = false;
|
|
1824
|
+
_restoredScriptId = null;
|
|
1258
1825
|
updateRestorePreview();
|
|
1259
1826
|
document.getElementById('restoreModalOverlay').classList.add('open');
|
|
1260
1827
|
setTimeout(() => document.getElementById('rmSuffix').focus(), 50);
|
|
@@ -1262,6 +1829,10 @@
|
|
|
1262
1829
|
|
|
1263
1830
|
function closeRestoreModal(e) {
|
|
1264
1831
|
if (e && e.target !== document.getElementById('restoreModalOverlay')) return;
|
|
1832
|
+
document.getElementById('rmWarning').style.display = 'none';
|
|
1833
|
+
document.getElementById('rmSuccess').style.display = 'none';
|
|
1834
|
+
document.getElementById('rmSuffix').disabled = false;
|
|
1835
|
+
_restoredScriptId = null;
|
|
1265
1836
|
document.getElementById('restoreModalOverlay').classList.remove('open');
|
|
1266
1837
|
}
|
|
1267
1838
|
|
|
@@ -1274,27 +1845,66 @@
|
|
|
1274
1845
|
document.getElementById('rmPreview').textContent = '→ script.js.' + parts.join('.');
|
|
1275
1846
|
}
|
|
1276
1847
|
|
|
1277
|
-
function confirmRestoreScript() {
|
|
1848
|
+
function confirmRestoreScript(overwrite) {
|
|
1278
1849
|
if (cur.index < 0) return;
|
|
1279
1850
|
const s = scriptsData[cur.index];
|
|
1280
|
-
const suffix = document.getElementById('rmSuffix').value.trim()
|
|
1851
|
+
const suffix = document.getElementById('rmSuffix').value.trim();
|
|
1281
1852
|
const msgEl = document.getElementById('rmMsg');
|
|
1282
1853
|
const confirmBtn = document.getElementById('rmConfirmBtn');
|
|
1283
1854
|
msgEl.style.color = '#aaa';
|
|
1284
|
-
msgEl.textContent = '
|
|
1855
|
+
msgEl.textContent = t('modalLoading');
|
|
1285
1856
|
confirmBtn.disabled = true;
|
|
1286
|
-
sendTo('restoreScript', { path: s.path, name: s.name, type: s.type, source: s.source, suffix }, function(result) {
|
|
1287
|
-
|
|
1288
|
-
|
|
1857
|
+
sendTo('restoreScript', { path: s.path, name: s.name, type: s.type, source: s.source, suffix, overwrite: !!overwrite }, function(result) {
|
|
1858
|
+
if (result && result.exists) {
|
|
1859
|
+
document.querySelector('#rmWarning p').innerHTML = t('modalWarning').replace('{path}', '<code>' + escapeHTML(result.id.replace(/^script\.js\./, '')) + '</code>');
|
|
1860
|
+
document.getElementById('rmWarning').style.display = 'block';
|
|
1861
|
+
document.getElementById('rmSuffix').disabled = true;
|
|
1862
|
+
msgEl.textContent = '';
|
|
1863
|
+
} else if (result && result.error) {
|
|
1864
|
+
confirmBtn.disabled = false;
|
|
1289
1865
|
msgEl.style.color = '#dc3545';
|
|
1290
|
-
msgEl.textContent = '
|
|
1866
|
+
msgEl.textContent = t('modalErrorPrefix') + result.error;
|
|
1291
1867
|
} else if (result && result.success) {
|
|
1292
|
-
|
|
1293
|
-
msgEl.textContent = '
|
|
1294
|
-
|
|
1868
|
+
_restoredScriptId = result.id;
|
|
1869
|
+
msgEl.textContent = '';
|
|
1870
|
+
document.getElementById('rmSuffix').disabled = true;
|
|
1871
|
+
document.getElementById('rmSuccess').style.display = 'block';
|
|
1295
1872
|
} else {
|
|
1873
|
+
confirmBtn.disabled = false;
|
|
1296
1874
|
msgEl.style.color = '#dc3545';
|
|
1297
|
-
msgEl.textContent = '
|
|
1875
|
+
msgEl.textContent = t('modalUnknownError');
|
|
1876
|
+
}
|
|
1877
|
+
});
|
|
1878
|
+
}
|
|
1879
|
+
|
|
1880
|
+
function dismissWarning() {
|
|
1881
|
+
document.getElementById('rmWarning').style.display = 'none';
|
|
1882
|
+
document.getElementById('rmSuffix').disabled = false;
|
|
1883
|
+
document.getElementById('rmConfirmBtn').disabled = false;
|
|
1884
|
+
document.getElementById('rmMsg').textContent = '';
|
|
1885
|
+
}
|
|
1886
|
+
|
|
1887
|
+
function overwriteConfirmed() {
|
|
1888
|
+
document.getElementById('rmWarning').style.display = 'none';
|
|
1889
|
+
document.getElementById('rmSuffix').disabled = false;
|
|
1890
|
+
confirmRestoreScript(true);
|
|
1891
|
+
}
|
|
1892
|
+
|
|
1893
|
+
function startRestoredScript() {
|
|
1894
|
+
if (!_restoredScriptId) return;
|
|
1895
|
+
const startBtn = document.getElementById('rmStartBtn');
|
|
1896
|
+
startBtn.disabled = true;
|
|
1897
|
+
startBtn.textContent = t('modalStarting');
|
|
1898
|
+
sendTo('enableScript', { id: _restoredScriptId }, function(result) {
|
|
1899
|
+
if (result && result.success) {
|
|
1900
|
+
startBtn.textContent = t('modalStarted');
|
|
1901
|
+
setTimeout(() => closeRestoreModal(), 1000);
|
|
1902
|
+
} else {
|
|
1903
|
+
startBtn.disabled = false;
|
|
1904
|
+
startBtn.textContent = t('modalStart');
|
|
1905
|
+
const p = document.querySelector('#rmSuccess p');
|
|
1906
|
+
p.innerHTML = t('modalErrorPrefix') + escapeHTML((result && result.error) || 'Unbekannt');
|
|
1907
|
+
p.style.color = '#dc3545';
|
|
1298
1908
|
}
|
|
1299
1909
|
});
|
|
1300
1910
|
}
|