From ec49db974a60d522cf282ccf7f7a282cbcf94dec Mon Sep 17 00:00:00 2001 From: Mattk70 Date: Sat, 16 Nov 2024 17:10:23 +0000 Subject: [PATCH] Fairly complete, Probably buggy. Ready for language check. --- I18n/index.da.json | 82 ++++- I18n/index.de.json | 79 +++++ I18n/index.en.json | 111 ++++++- I18n/index.es.json | 81 ++++- I18n/index.fr.json | 85 ++++- I18n/index.nl.json | 82 ++++- I18n/index.pt.json | 81 ++++- I18n/index.ru.json | 82 ++++- I18n/index.sv.json | 81 ++++- I18n/index.zh.json | 81 ++++- build/get-text-for-translations.html | 43 ++- index.html | 74 ++--- js/i18n.js | 459 +++++++++++++++++++++++++++ js/ui.js | 234 +++++--------- 14 files changed, 1426 insertions(+), 229 deletions(-) create mode 100644 js/i18n.js diff --git a/I18n/index.da.json b/I18n/index.da.json index 62cdc42..bfa1f07 100644 --- a/I18n/index.da.json +++ b/I18n/index.da.json @@ -153,6 +153,12 @@ "Analyser alle åbne filer", "Ctrl+Shift+A" ], + "retrieve": [ + "Hent resultater for den aktuelle fil" + ], + "retrieveAll": [ + "Hent resultater for alle åbne filer" + ], "reanalyse": [ "Gen-analyser nuværende fil" ], @@ -188,5 +194,79 @@ ], "update-progress": [ "Downloader opdatering:" - ] + ], + "record-add": ["Tilføj"], + "record-dismiss": ["Afvis"], + "help-modal-close": ["Luk"], + "export-list": ["Eksporter den inkluderede liste"], + "go": ["Gå"], + "set-location": ["Angiv placering"], + "reset-spec-frequency": ["Nulstil"], + "list-file-selector": ["Vælg fil"], + "clear-call-cache": ["Ryd referencelyd-cache"], + "apply-location": ["Sæt"], + "cancel-location": ["Annuller"], + "archive-location-select": ["Biblioteksplacering:"], + "reset-defaults": ["Nulstil til standardindstillinger"], + "close-tour": ["Luk"], + "settings": { + "model-to-use": "Model:", + "confidence": "Konfidensinterval:", + "list-to-use": "Liste:", + "local": "Brug Lokationsindstillinger", + "species-frequency-threshold": "Artstrøskel", + "species-week": "Justér listen for årets uge", + "nocmig": "Analyser kun nattetimer.", + "iucn": "Vis IUCN Rød Liste status for arter i oversigten.", + "iucn-scope": "Vurderingsomfang:", + "locale": "Sprog:", + "null": "Dekoratører:", + "tensorflow": "CPU", + "webgl": "WebGL", + "webgpu": "WebGPU", + "thread-slider": "Tråde:", + "batch-size": "Batch Størrelse:", + "audio-notification": "Aktivér analyse færdiggørelsesmeddelelser", + "power-save-block": "Forhindr system i at gå i dvale", + "font": "Juster skrifttypestørrelse", + "gain": "Volumenjustering:", + "normalise": "Normaliser Lyd:", + "HighPassFrequency": "Højpasfilter:", + "lowShelfFrequency": "Skæringsfrekvens:", + "attenuation": "Dæmpning:", + "format": "Format:", + "bitrate": "Bitrate:", + "quality": "Kompression:", + "downmix": "Konverter til mono", + "padding": "Pudse", + "fade": "Fade", + "auto-archive": "Tilføj til bibliotek ved gemning", + "library-trim": "Skær biblioteksljud til nattetimer", + "archive-format": "Biblioteksformat:", + "spec-labels": "Vis frekvensetiketter:", + "colourmap": "Farvekort:", + "loud-color": "Topfarve", + "mid-color": "Mellemfrekvensfarve", + "quiet-color": "Lavfrekvensfarve", + "color-threshold-slider": "Mid-position:", + "window-function": "Vinduesfunktion:", + "timelineSetting": "Tidslinje:", + "send-filtered-audio-to-model": "Send filtreret lyd til analyse", + "context": "Konteksttilstand", + "snrValue": "SNR filter:", + "debug-mode": "Fejlfindingstilstand" + }, + "headings": [ + "Indstillinger", + "Detektioner", + "Standardplacering", + "System", + "Lydindstillinger", + "Low Shelf filter", + "Lydeksport", + "Lydbibliotek", + "Spektrogramindstillinger", + "Avanceret" + ] + } diff --git a/I18n/index.de.json b/I18n/index.de.json index 0f8b3e4..ab2da29 100644 --- a/I18n/index.de.json +++ b/I18n/index.de.json @@ -153,6 +153,12 @@ "Alle geöffneten Dateien analysieren", "Ctrl+Shift+A" ], + "retrieve": [ + "Ergebnisse für die aktuelle Datei abrufen" + ], + "retrieveAll": [ + "Ergebnisse für alle offenen Dateien abrufen" + ], "reanalyse": [ "Aktuelle Datei erneut analysieren" ], @@ -188,5 +194,78 @@ ], "update-progress": [ "Update wird heruntergeladen:" + ], + "record-add": ["Hinzufügen"], + "record-dismiss": ["Verwerfen"], + "help-modal-close": ["Schließen"], + "export-list": ["Liste exportieren"], + "go": ["Los"], + "set-location": ["Standort festlegen"], + "reset-spec-frequency": ["Zurücksetzen"], + "list-file-selector": ["Datei auswählen"], + "clear-call-cache": ["Referenzruf-Cache löschen"], + "apply-location": ["Festlegen"], + "cancel-location": ["Abbrechen"], + "archive-location-select": ["Bibliotheksspeicherort:"], + "reset-defaults": ["Auf Standardeinstellungen zurücksetzen"], + "close-tour": ["Schließen"], + "settings": { + "model-to-use": "Modell:", + "confidence": "Vertrauensschwelle:", + "list-to-use": "Liste:", + "local": "Verwenden Sie Standorteinstellungen", + "species-frequency-threshold": "Arten-Schwelle", + "species-week": "Liste für die Woche des Jahres anpassen", + "nocmig": "Nur Nachts analysieren.", + "iucn": "Zeige den IUCN Rotlistenzustand der Arten im Überblick.", + "iucn-scope": "Bewertungsumfang:", + "locale": "Sprache:", + "null": "Dekoratoren:", + "tensorflow": "CPU", + "webgl": "WebGL", + "webgpu": "WebGPU", + "thread-slider": "Threads:", + "batch-size": "Batch-Größe:", + "audio-notification": "Benachrichtigungen bei Analyseabschluss aktivieren", + "power-save-block": "System in den Ruhezustand verhindern", + "font": "Schriftgröße anpassen", + "gain": "Lautstärkeregelung:", + "normalise": "Audio normalisieren:", + "HighPassFrequency": "Hochpassfilter:", + "lowShelfFrequency": "Grenzfrequenz:", + "attenuation": "Dämpfung:", + "format": "Format:", + "bitrate": "Bitrate:", + "quality": "Kompression:", + "downmix": "In Mono umwandeln", + "padding": "Padding", + "fade": "Verblassen", + "auto-archive": "Zur Bibliothek bei Speicherung hinzufügen", + "library-trim": "Bibliotheksaudio auf Nachtperioden zuschneiden", + "archive-format": "Bibliotheksformat:", + "spec-labels": "Frequenzbeschriftungen anzeigen:", + "colourmap": "Farbenkarte:", + "loud-color": "Spitzenfarbe", + "mid-color": "Mitteltonfarbe", + "quiet-color": "Leise Farbe", + "color-threshold-slider": "Mittelposition:", + "window-function": "Fensterfunktion:", + "timelineSetting": "Zeitleiste:", + "send-filtered-audio-to-model": "Gefiltertes Audio zur Analyse senden", + "context": "Kontextmodus", + "snrValue": "SNR-Filter:", + "debug-mode": "Fehlermodus" + }, + "headings": [ + "Einstellungen", + "Erkennungen", + "Standardstandort", + "System", + "Audioeinstellungen", + "Low Shelf-Filter", + "Audioexport", + "Audiobibliothek", + "Spektrogrammeinstellungen", + "Erweitert" ] } diff --git a/I18n/index.en.json b/I18n/index.en.json index 3569b17..d91847b 100644 --- a/I18n/index.en.json +++ b/I18n/index.en.json @@ -166,6 +166,12 @@ "Analyse All Open Files", "Ctrl+Shift+A" ], + "retrieve": [ + "Get Results for Current File" + ], + "retrieveAll": [ + "Get Results for All Open Files" + ], "reanalyse": [ "Re-analyse Current File" ], @@ -201,5 +207,108 @@ ], "update-progress": [ "Downloading update:" - ] + ], + + + "record-add": [ + "Add" + ], + "record-dismiss": [ + "Dismiss" + ], + "help-modal-close": [ + "Close" + ], + "export-list": [ + "Export the Included List" + ], + "go": [ + "Go" + ], + "set-location": [ + "Set Location" + ], + "reset-spec-frequency": [ + "Reset" + ], + "list-file-selector": [ + "Select file" + ], + "clear-call-cache": [ + "Clear Reference Call Cache" + ], + "apply-location": [ + "Set" + ], + "cancel-location": [ + "Cancel" + ], + "archive-location-select": [ + "Library Location:" + ], + "reset-defaults": [ + "Reset to default settings" + ], + "close-tour": [ + "Close" + ], + "settings": { + "model-to-use": "Model:", + "confidence": "Confidence threshold:", + "list-to-use": "List:", + "local": "Use Location settings", + "species-frequency-threshold": "Species Threshold", + "species-week": "Adjust list for the week of the year", + "nocmig": "Only analyse night time periods.", + "iucn": "Show species IUCN Red List status in summary.", + "iucn-scope": "Assessment Scope:", + "locale": "Language:", + "null": "Decorators:", + "tensorflow": "CPU", + "webgl": "WebGL", + "webgpu": "WebGPU", + "thread-slider": "Threads:", + "batch-size": "Batch Size:", + "audio-notification": "Enable analysis completion notifications", + "power-save-block": "Prevent system sleep", + "font": "Adjust font size", + "gain": "Volume Adjustment:", + "normalise": "Normalise Audio:", + "HighPassFrequency": "High Pass filter:", + "lowShelfFrequency": "Cut-off Frequency:", + "attenuation": "Attenuation:", + "format": "Format:", + "bitrate": "Bitrate:", + "quality": "Compression:", + "downmix": "Convert to mono", + "padding": "Pad", + "fade": "Fade", + "auto-archive": "Add to Library on Save", + "library-trim": "Crop Library audio to night time periods", + "archive-format": "Library Format:", + "spec-labels": "Display frequency labels:", + "colourmap": "Colourmap:", + "loud-color": "Peak colour", + "mid-color": "Mid colour", + "quiet-color": "Quiet colour", + "color-threshold-slider": "Mid Position:", + "window-function": "Window function:", + "timelineSetting": "Timeline:", + "send-filtered-audio-to-model": "Send Filtered Audio for Analysis", + "context": "Context mode", + "snrValue": "SNR filter:", + "debug-mode": "Debug mode" + }, + "headings": [ + "Settings", + "Detections", + "Default Location", + "System", + "Audio Preferences", + "Low Shelf filter", + "Audio Export", + "Audio Library", + "Spectrogram Preferences", + "Advanced" + ] } \ No newline at end of file diff --git a/I18n/index.es.json b/I18n/index.es.json index 93ed56a..266e508 100644 --- a/I18n/index.es.json +++ b/I18n/index.es.json @@ -153,6 +153,12 @@ "Analizar todos los archivos abiertos", "Ctrl+Shift+A" ], + "retrieve": [ + "Obtener resultados para el archivo actual" + ], + "retrieveAll": [ + "Obtener resultados para todos los archivos abiertos" + ], "reanalyse": [ "Reanalizar archivo actual" ], @@ -188,5 +194,78 @@ ], "update-progress": [ "Descargando actualización:" - ] + ], + "record-add": ["Añadir"], + "record-dismiss": ["Descartar"], + "help-modal-close": ["Cerrar"], + "export-list": ["Exportar la lista incluida"], + "go": ["Ir"], + "set-location": ["Establecer ubicación"], + "reset-spec-frequency": ["Restablecer"], + "list-file-selector": ["Seleccionar archivo"], + "clear-call-cache": ["Borrar caché de llamadas de referencia"], + "apply-location": ["Establecer"], + "cancel-location": ["Cancelar"], + "archive-location-select": ["Ubicación de la biblioteca:"], + "reset-defaults": ["Restablecer a la configuración predeterminada"], + "close-tour": ["Cerrar"], + "settings": { + "model-to-use": "Modelo:", + "confidence": "Umbral de confianza:", + "list-to-use": "Lista:", + "local": "Usar configuraciones de ubicación", + "species-frequency-threshold": "Umbral de Especies", + "species-week": "Ajustar la lista para la semana del año", + "nocmig": "Analizar solo períodos nocturnos.", + "iucn": "Mostrar el estado de la Lista Roja de la UICN en el resumen de especies.", + "iucn-scope": "Alcance de la evaluación:", + "locale": "Idioma:", + "null": "Decoradores:", + "tensorflow": "CPU", + "webgl": "WebGL", + "webgpu": "WebGPU", + "thread-slider": "Hilos:", + "batch-size": "Tamaño de lote:", + "audio-notification": "Habilitar notificaciones de finalización de análisis", + "power-save-block": "Evitar que el sistema entre en suspensión", + "gain": "Ajuste de volumen:", + "font": "Ajustar el tamaño de la fuente", + "normalise": "Normalizar audio:", + "HighPassFrequency": "Filtro pasa altos:", + "lowShelfFrequency": "Frecuencia de corte:", + "attenuation": "Atenuación:", + "format": "Formato:", + "bitrate": "Tasa de bits:", + "quality": "Compresión:", + "downmix": "Convertir a mono", + "padding": "Rellenar", + "fade": "Desvanecer", + "auto-archive": "Añadir a la biblioteca al guardar", + "library-trim": "Recortar el audio de la biblioteca a períodos nocturnos", + "archive-format": "Formato de la biblioteca:", + "spec-labels": "Mostrar etiquetas de frecuencia:", + "colourmap": "Mapa de colores:", + "loud-color": "Color de pico", + "mid-color": "Color medio", + "quiet-color": "Color bajo", + "color-threshold-slider": "Posición media:", + "window-function": "Función de ventana:", + "timelineSetting": "Línea de tiempo:", + "send-filtered-audio-to-model": "Enviar audio filtrado para análisis", + "context": "Modo contexto", + "snrValue": "Filtro SNR:", + "debug-mode": "Modo depuración" + }, + "headings": [ + "Configuración", + "Detecciones", + "Ubicación predeterminada", + "Sistema", + "Preferencias de audio", + "Filtro de bajo estante", + "Exportación de audio", + "Biblioteca de audio", + "Preferencias de espectrograma", + "Avanzado" + ] } diff --git a/I18n/index.fr.json b/I18n/index.fr.json index e203025..283d06d 100644 --- a/I18n/index.fr.json +++ b/I18n/index.fr.json @@ -153,6 +153,12 @@ "Analyser tous les fichiers ouverts", "Ctrl+Shift+A" ], + "retrieve": [ + "Obtenir les résultats pour le fichier actuel" + ], + "retrieveAll": [ + "Obtenir les résultats pour tous les fichiers ouverts" + ], "reanalyse": [ "Ré-analyser le fichier actuel" ], @@ -188,7 +194,78 @@ ], "update-progress": [ "Téléchargement de la mise à jour :" - ] - - -} \ No newline at end of file + ], + "record-add": ["Ajouter"], + "record-dismiss": ["Ignorer"], + "help-modal-close": ["Fermer"], + "export-list": ["Exporter la liste incluse"], + "go": ["Aller"], + "set-location": ["Définir l'emplacement"], + "reset-spec-frequency": ["Réinitialiser"], + "list-file-selector": ["Sélectionner le fichier"], + "clear-call-cache": ["Effacer le cache des appels de référence"], + "apply-location": ["Définir"], + "cancel-location": ["Annuler"], + "archive-location-select": ["Emplacement de la bibliothèque:"], + "reset-defaults": ["Réinitialiser aux paramètres par défaut"], + "close-tour": ["Fermer"], + "settings": { + "model-to-use": "Modèle :", + "confidence": "Seuil de confiance :", + "list-to-use": "Liste :", + "local": "Utiliser les paramètres de localisation", + "species-frequency-threshold": "Seuil des Espèces", + "species-week": "Ajuster la liste pour la semaine de l'année", + "nocmig": "Analyser uniquement les périodes nocturnes.", + "iucn": "Afficher le statut de la liste rouge de l'UICN dans le résumé des espèces.", + "iucn-scope": "Portée de l'évaluation :", + "locale": "Langue :", + "null": "Décorateurs :", + "tensorflow": "CPU", + "webgl": "WebGL", + "webgpu": "WebGPU", + "thread-slider": "Threads :", + "batch-size": "Taille du lot :", + "audio-notification": "Activer les notifications de fin d'analyse", + "power-save-block": "Empêcher le système de se mettre en veille", + "font": "Ajuster la taille de la police", + "gain": "Réglage du volume :", + "normalise": "Normaliser l'audio :", + "HighPassFrequency": "Filtre passe-haut :", + "lowShelfFrequency": "Fréquence de coupure :", + "attenuation": "Atténuation :", + "format": "Format :", + "bitrate": "Débit binaire :", + "quality": "Compression :", + "downmix": "Convertir en mono", + "padding": "Rembourrage", + "fade": "Fondu", + "auto-archive": "Ajouter à la bibliothèque lors de l'enregistrement", + "library-trim": "Recadrer l'audio de la bibliothèque aux périodes nocturnes", + "archive-format": "Format de bibliothèque :", + "spec-labels": "Afficher les étiquettes de fréquence :", + "colourmap": "Carte des couleurs :", + "loud-color": "Couleur de crête", + "mid-color": "Couleur moyenne", + "quiet-color": "Couleur faible", + "color-threshold-slider": "Position moyenne :", + "window-function": "Fonction de fenêtre :", + "timelineSetting": "Chronologie :", + "send-filtered-audio-to-model": "Envoyer l'audio filtré pour analyse", + "context": "Mode contexte", + "snrValue": "Filtre SNR :", + "debug-mode": "Mode débogage" + }, + "headings": [ + "Paramètres", + "Détections", + "Emplacement par défaut", + "Système", + "Préférences audio", + "Filtre Low Shelf", + "Exportation audio", + "Bibliothèque audio", + "Préférences spectrogramme", + "Avancé" + ] +} diff --git a/I18n/index.nl.json b/I18n/index.nl.json index bf2c1b4..be222c1 100644 --- a/I18n/index.nl.json +++ b/I18n/index.nl.json @@ -153,6 +153,12 @@ "Analyseer Alle Open Bestanden", "Ctrl+Shift+A" ], + "retrieve": [ + "Verkrijg resultaten voor het huidige bestand" + ], + "retrieveAll": [ + "Verkrijg resultaten voor alle geopende bestanden" + ], "reanalyse": [ "Hernanalyseer Huidig Bestand" ], @@ -188,6 +194,78 @@ ], "update-progress": [ "Downloaden van update:" - ] - + ], + "record-add": ["Toevoegen"], + "record-dismiss": ["Afwijzen"], + "help-modal-close": ["Sluiten"], + "export-list": ["Lijst exporteren"], + "go": ["Ga"], + "set-location": ["Locatie instellen"], + "reset-spec-frequency": ["Reset"], + "list-file-selector": ["Selecteer bestand"], + "clear-call-cache": ["Referentieoproep-cache wissen"], + "apply-location": ["Instellen"], + "cancel-location": ["Annuleren"], + "archive-location-select": ["Bibliotheeklocatie:"], + "reset-defaults": ["Herstellen naar standaardinstellingen"], + "close-tour": ["Sluiten"], + "settings": { + "model-to-use": "Model:", + "confidence": "Vertrouwensdrempel:", + "list-to-use": "Lijst:", + "local": "Gebruik locatie-instellingen", + "species-frequency-threshold": "Soortdrempel", + "species-week": "Pas de lijst aan voor de week van het jaar", + "nocmig": "Analyseer alleen nachtelijke perioden.", + "iucn": "Toon de IUCN Rode Lijststatus van soorten in het overzicht.", + "iucn-scope": "Beoordelingsomvang:", + "locale": "Taal:", + "null": "Decorateurs:", + "tensorflow": "CPU", + "webgl": "WebGL", + "webgpu": "WebGPU", + "thread-slider": "Threads:", + "batch-size": "Batchgrootte:", + "audio-notification": "Schakel meldingen in bij voltooiing van analyse", + "power-save-block": "Voorkom slaapstand van het systeem", + "font": "Pas de lettergrootte aan", + "gain": "Volume-aanpassing:", + "normalise": "Audio normaliseren:", + "HighPassFrequency": "Hoogdoorlaatfilter:", + "lowShelfFrequency": "Snijfrequentie:", + "attenuation": "Verzwakking:", + "format": "Formaat:", + "bitrate": "Bitrate:", + "quality": "Compressie:", + "downmix": "Omzetten naar mono", + "padding": "Vulling", + "fade": "Vervagen", + "auto-archive": "Toevoegen aan bibliotheek bij opslaan", + "library-trim": "Snijd bibliotheekgeluid bij tot nachtelijke perioden", + "archive-format": "Bibliotheekformaat:", + "spec-labels": "Toon frequentielabels:", + "colourmap": "Kleurkaart:", + "loud-color": "Piek kleur", + "mid-color": "Middelste kleur", + "quiet-color": "Stille kleur", + "color-threshold-slider": "Middenpositie:", + "window-function": "Vensterfunctie:", + "timelineSetting": "Tijdlijn:", + "send-filtered-audio-to-model": "Verstuur gefilterd geluid voor analyse", + "context": "Contextmodus", + "snrValue": "SNR-filter:", + "debug-mode": "Foutopsporingsmodus" + }, + "headings": [ + "Instellingen", + "Detecties", + "Standaardlocatie", + "Systeem", + "Audio-instellingen", + "Low Shelf-filter", + "Audio-export", + "Audio-bibliotheek", + "Spectrogramvoorkeuren", + "Geavanceerd" + ] } diff --git a/I18n/index.pt.json b/I18n/index.pt.json index 73cf4cd..7bad614 100644 --- a/I18n/index.pt.json +++ b/I18n/index.pt.json @@ -153,6 +153,12 @@ "Analisar Todos os Arquivos Abertos", "Ctrl+Shift+A" ], + "retrieve": [ + "Obter resultados para o arquivo atual" + ], + "retrieveAll": [ + "Obter resultados para todos os arquivos abertos" + ], "reanalyse": [ "Reanalisar Arquivo Atual" ], @@ -188,5 +194,78 @@ ], "update-progress": [ "Baixando atualização:" - ] + ], + "record-add": ["Adicionar"], + "record-dismiss": ["Descartar"], + "help-modal-close": ["Fechar"], + "export-list": ["Exportar a lista incluída"], + "go": ["Ir"], + "set-location": ["Definir localização"], + "reset-spec-frequency": ["Redefinir"], + "list-file-selector": ["Selecionar arquivo"], + "clear-call-cache": ["Limpar cache de chamadas de referência"], + "apply-location": ["Definir"], + "cancel-location": ["Cancelar"], + "archive-location-select": ["Localização da biblioteca:"], + "reset-defaults": ["Redefinir para as configurações padrão"], + "close-tour": ["Fechar"], + "settings": { + "model-to-use": "Modelo:", + "confidence": "Limite de confiança:", + "list-to-use": "Lista:", + "local": "Usar configurações de localização", + "species-frequency-threshold": "Limite de Espécies", + "species-week": "Ajustar a lista para a semana do ano", + "nocmig": "Analisar apenas períodos noturnos.", + "iucn": "Mostrar o status da Lista Vermelha da IUCN no resumo das espécies.", + "iucn-scope": "Escopo da avaliação:", + "locale": "Idioma:", + "null": "Decoradores:", + "tensorflow": "CPU", + "webgl": "WebGL", + "webgpu": "WebGPU", + "thread-slider": "Threads:", + "batch-size": "Tamanho do lote:", + "audio-notification": "Habilitar notificações de conclusão da análise", + "power-save-block": "Impedir o sistema de entrar em modo de espera", + "font": "Ajustar o tamanho da fonte", + "gain": "Ajuste de volume:", + "normalise": "Normalizar áudio:", + "HighPassFrequency": "Filtro passa-alto:", + "lowShelfFrequency": "Frequência de corte:", + "attenuation": "Atuação:", + "format": "Formato:", + "bitrate": "Taxa de bits:", + "quality": "Compressão:", + "downmix": "Converter para mono", + "padding": "Preenchimento", + "fade": "Desvanecimento", + "auto-archive": "Adicionar à biblioteca ao salvar", + "library-trim": "Cortar áudio da biblioteca para períodos noturnos", + "archive-format": "Formato da biblioteca:", + "spec-labels": "Mostrar rótulos de frequência:", + "colourmap": "Mapa de cores:", + "loud-color": "Cor de pico", + "mid-color": "Cor média", + "quiet-color": "Cor silenciosa", + "color-threshold-slider": "Posição média:", + "window-function": "Função de janela:", + "timelineSetting": "Linha do tempo:", + "send-filtered-audio-to-model": "Enviar áudio filtrado para análise", + "context": "Modo contexto", + "snrValue": "Filtro SNR:", + "debug-mode": "Modo de depuração" + }, + "headings": [ + "Configurações", + "Detecções", + "Localização padrão", + "Sistema", + "Preferências de áudio", + "Filtro de Low Shelf", + "Exportação de áudio", + "Biblioteca de áudio", + "Preferências de espectrograma", + "Avançado" + ] } diff --git a/I18n/index.ru.json b/I18n/index.ru.json index 74ac043..ce05788 100644 --- a/I18n/index.ru.json +++ b/I18n/index.ru.json @@ -153,6 +153,12 @@ "Анализировать все открытые файлы", "Ctrl+Shift+A" ], + "retrieve": [ + "Получить результаты для текущего файла" + ], + "retrieveAll": [ + "Получить результаты для всех открытых файлов" + ], "reanalyse": [ "Повторный анализ текущего файла" ], @@ -188,6 +194,78 @@ ], "update-progress": [ "Загрузка обновления:" - ] - + ], + "record-add": ["Добавить"], + "record-dismiss": ["Отклонить"], + "help-modal-close": ["Закрыть"], + "export-list": ["Экспортировать включенный список"], + "go": ["Вперёд"], + "set-location": ["Установить местоположение"], + "reset-spec-frequency": ["Сбросить"], + "list-file-selector": ["Выбрать файл"], + "clear-call-cache": ["Очистить кэш справочных вызовов"], + "apply-location": ["Установить"], + "cancel-location": ["Отмена"], + "archive-location-select": ["Расположение библиотеки:"], + "reset-defaults": ["Сбросить настройки по умолчанию"], + "close-tour": ["Закрыть"], + "settings": { + "model-to-use": "Модель:", + "confidence": "Порог уверенности:", + "list-to-use": "Список:", + "local": "Использовать настройки местоположения", + "species-frequency-threshold": "Порог вида", + "species-week": "Корректировать список по неделе года", + "nocmig": "Анализировать только ночные периоды.", + "iucn": "Показать статус Красного списка IUCN в сводке по видам.", + "iucn-scope": "Объем оценки:", + "locale": "Язык:", + "null": "Декораторы:", + "tensorflow": "ЦПУ", + "webgl": "WebGL", + "webgpu": "WebGPU", + "thread-slider": "Потоки:", + "batch-size": "Размер партии:", + "audio-notification": "Включить уведомления о завершении анализа", + "power-save-block": "Запретить переход системы в спящий режим", + "font": "Изменить размер шрифта", + "gain": "Регулировка громкости:", + "normalise": "Нормализовать аудио:", + "HighPassFrequency": "Фильтр верхних частот:", + "lowShelfFrequency": "Частота среза:", + "attenuation": "Аттенюация:", + "format": "Формат:", + "bitrate": "Битрейт:", + "quality": "Сжатие:", + "downmix": "Преобразовать в моно", + "padding": "Заполнение", + "fade": "Затухание", + "auto-archive": "Добавить в библиотеку при сохранении", + "library-trim": "Обрезать аудио библиотеки до ночных периодов", + "archive-format": "Формат библиотеки:", + "spec-labels": "Показать метки частоты:", + "colourmap": "Цветовая карта:", + "loud-color": "Цвет пика", + "mid-color": "Цвет средней частоты", + "quiet-color": "Тихий цвет", + "color-threshold-slider": "Среднее положение:", + "window-function": "Окно функции:", + "timelineSetting": "Таймлайн:", + "send-filtered-audio-to-model": "Отправить отфильтрованный звук на анализ", + "context": "Контекстный режим", + "snrValue": "Фильтр SNR:", + "debug-mode": "Режим отладки" + }, + "headings": [ + "Настройки", + "Обнаружения", + "Местоположение по умолчанию", + "Система", + "Настройки звука", + "Фильтр Low Shelf", + "Экспорт аудио", + "Аудиобиблиотека", + "Настройки спектрограммы", + "Продвинутый" + ] } diff --git a/I18n/index.sv.json b/I18n/index.sv.json index 2db8825..eb92b65 100644 --- a/I18n/index.sv.json +++ b/I18n/index.sv.json @@ -153,6 +153,12 @@ "Analysera alla öppna filer", "Ctrl+Shift+A" ], + "retrieve": [ + "Hämta resultat för aktuell fil" + ], + "retrieveAll": [ + "Hämta resultat för alla öppna filer" + ], "reanalyse": [ "Re-analysera aktuell fil" ], @@ -188,5 +194,78 @@ ], "update-progress": [ "Laddar ner uppdatering:" - ] + ], + "record-add": ["Lägg till"], + "record-dismiss": ["Avvisa"], + "help-modal-close": ["Stäng"], + "export-list": ["Exportera den inkluderade listan"], + "go": ["Gå"], + "set-location": ["Ange plats"], + "reset-spec-frequency": ["Återställ"], + "list-file-selector": ["Välj fil"], + "clear-call-cache": ["Rensa referenssamtalscache"], + "apply-location": ["Ange"], + "cancel-location": ["Avbryt"], + "archive-location-select": ["Bibliotekets plats:"], + "reset-defaults": ["Återställ till standardinställningar"], + "close-tour": ["Stäng"], + "settings": { + "model-to-use": "Modell:", + "confidence": "Konfidensnivå:", + "list-to-use": "Lista:", + "local": "Använd platsinställningar", + "species-frequency-threshold": "Arttröskel", + "species-week": "Justera lista för veckans vecka", + "nocmig": "Analysera endast nattperioder.", + "iucn": "Visa IUCN Röd Lista status i sammanfattningen för arter.", + "iucn-scope": "Bedömningsomfattning:", + "locale": "Språk:", + "null": "Dekoratörer:", + "tensorflow": "CPU", + "webgl": "WebGL", + "webgpu": "WebGPU", + "thread-slider": "Trådar:", + "batch-size": "Batchstorlek:", + "audio-notification": "Aktivera analysfullföljande meddelanden", + "power-save-block": "Förhindra att systemet går i viloläge", + "font": "Justera teckenstorlek", + "gain": "Volymjustering:", + "normalise": "Normalisera ljud:", + "HighPassFrequency": "Högpassfilter:", + "lowShelfFrequency": "Gränsfrekvens:", + "attenuation": "Dämpning:", + "format": "Format:", + "bitrate": "Bitrate:", + "quality": "Komprimering:", + "downmix": "Konvertera till mono", + "padding": "Fyllning", + "fade": "Utsuddning", + "auto-archive": "Lägg till i bibliotek vid sparande", + "library-trim": "Klipp biblioteksljud till nattperioder", + "archive-format": "Biblioteksformat:", + "spec-labels": "Visa frekvenstagg:", + "colourmap": "Färggalleri:", + "loud-color": "Toppfärg", + "mid-color": "Mellanfärg", + "quiet-color": "Tyst färg", + "color-threshold-slider": "Mittenposition:", + "window-function": "Fönsterfunktion:", + "timelineSetting": "Tidslinje:", + "send-filtered-audio-to-model": "Skicka filtrerat ljud för analys", + "context": "Kontextläge", + "snrValue": "SNR-filter:", + "debug-mode": "Felsökningsläge" + }, + "headings": [ + "Inställningar", + "Detektioner", + "Standardplats", + "System", + "Ljudinställningar", + "Low Shelf-filter", + "Ljudexport", + "Ljudbibliotek", + "Spektrograminställningar", + "Avancerat" + ] } diff --git a/I18n/index.zh.json b/I18n/index.zh.json index f891fa8..9e4e365 100644 --- a/I18n/index.zh.json +++ b/I18n/index.zh.json @@ -153,6 +153,12 @@ "分析所有打开的文件", "Ctrl+Shift+A" ], + "retrieve": [ + "获取当前文件的结果" + ], + "retrieveAll": [ + "获取所有打开文件的结果" + ], "reanalyse": [ "重新分析当前文件" ], @@ -188,5 +194,78 @@ ], "update-progress": [ "正在下载更新:" - ] + ], + "record-add": ["添加"], + "record-dismiss": ["取消"], + "help-modal-close": ["关闭"], + "export-list": ["导出包含的列表"], + "go": ["前往"], + "set-location": ["设置位置"], + "reset-spec-frequency": ["重置"], + "list-file-selector": ["选择文件"], + "clear-call-cache": ["清除参考通话缓存"], + "apply-location": ["设置"], + "cancel-location": ["取消"], + "archive-location-select": ["库位置:"], + "reset-defaults": ["恢复默认设置"], + "close-tour": ["关闭"], + "settings": { + "model-to-use": "模型:", + "confidence": "置信度阈值:", + "list-to-use": "列表:", + "local": "使用位置设置", + "species-frequency-threshold": "物种阈值", + "species-week": "根据年份的周调整列表", + "nocmig": "仅分析夜间时期。", + "iucn": "在摘要中显示物种的IUCN红色名单状态。", + "iucn-scope": "评估范围:", + "locale": "语言:", + "null": "装饰器:", + "tensorflow": "CPU", + "webgl": "WebGL", + "webgpu": "WebGPU", + "thread-slider": "线程:", + "batch-size": "批次大小:", + "audio-notification": "启用分析完成通知", + "power-save-block": "防止系统进入睡眠模式", + "font": "调整字体大小", + "gain": "音量调整:", + "normalise": "音频标准化:", + "HighPassFrequency": "高通滤波器:", + "lowShelfFrequency": "截止频率:", + "attenuation": "衰减:", + "format": "格式:", + "bitrate": "比特率:", + "quality": "压缩:", + "downmix": "转换为单声道", + "padding": "填充", + "fade": "渐变", + "auto-archive": "保存时添加到库", + "library-trim": "将图书馆音频裁剪为夜间时期", + "archive-format": "库格式:", + "spec-labels": "显示频率标签:", + "colourmap": "色彩图:", + "loud-color": "峰值颜色", + "mid-color": "中频颜色", + "quiet-color": "安静颜色", + "color-threshold-slider": "中位位置:", + "window-function": "窗口函数:", + "timelineSetting": "时间轴:", + "send-filtered-audio-to-model": "发送过滤后的音频进行分析", + "context": "上下文模式", + "snrValue": "SNR滤波器:", + "debug-mode": "调试模式" + }, + "headings": [ + "设置", + "检测", + "默认位置", + "系统", + "音频偏好设置", + "低架滤波器", + "音频导出", + "音频库", + "频谱图偏好设置", + "高级" + ] } diff --git a/build/get-text-for-translations.html b/build/get-text-for-translations.html index 909fa26..9d06e32 100644 --- a/build/get-text-for-translations.html +++ b/build/get-text-for-translations.html @@ -88,21 +88,34 @@ // }); } }); - // // Assuming textAndTitles is the object you want to sort by keys - // const sortedKeys = Object.keys(textAndTitles).sort(); - - // // Now you can iterate over the sorted keys to access the content - // sortedKeys.forEach(key => { - // console.log(key, textAndTitles[key]); // Output sorted key and its associated list - // }); - // const sortedTextAndTitles = {}; - // sortedKeys.forEach(key => { - // sortedTextAndTitles[key] = textAndTitles[key]; - // }); - - // Generate JSON output - const jsonOutput = JSON.stringify(textAndTitles, null, 2); - + const buttons = doc.querySelectorAll('button:not([id])') + buttonCollection = {} + buttons.forEach(button => { + const label = button.textContent; + const closestId = getClosestId(button); + buttonCollection[closestId] = buttonCollection[closestId] || []; + buttonCollection[closestId].push(label); + }) + const labels = doc.getElementById('settings').querySelectorAll('label') + labelCollection = {} + labels.forEach(item => { + const label = item.textContent.trim(); + const key = item.getAttribute('for') + //const closestId = getClosestId(item); + labelCollection['settings'] = labelCollection['settings'] || {}; + labelCollection['settings'][key] = label; + }) + const headings = doc.getElementById('settings').querySelectorAll( 'h4,h5,h6,legend'); + const hCollection = {} + headings.forEach(item => { + const label = item.textContent.trim(); + + //const closestId = getClosestId(item); + hCollection['headings'] = hCollection['headings'] || []; + hCollection['headings'].push(label); + }) + let jsonOutput = JSON.stringify(textAndTitles, null, 2); + jsonOutput += JSON.stringify(buttonCollection, null, 2) + JSON.stringify(labelCollection, null, 2) + JSON.stringify(hCollection, null, 2); // Display JSON in the output area document.getElementById('output').textContent = jsonOutput; }; diff --git a/index.html b/index.html index 9f70288..a6b785c 100644 --- a/index.html +++ b/index.html @@ -72,11 +72,11 @@
@@ -496,9 +496,9 @@
-
+
-
Settings
+
Settings
@@ -561,7 +561,7 @@
Settings
?
- Threshold: +
@@ -629,34 +629,34 @@
Settings
@@ -665,7 +665,7 @@
Settings
?
- +
@@ -727,9 +727,9 @@
Settings
?
- Adjust font size: - text_decrease - text_increase + + text_decrease + text_increase
@@ -738,9 +738,7 @@
Settings
? - +
@@ -752,9 +750,8 @@
Settings

- + + ?
@@ -840,7 +837,7 @@
Audio Export:
- +
- + + ?
@@ -909,9 +904,8 @@
Audio Library:Spectrogram Preferences @@ -1026,10 +1020,8 @@
Audio Library:
- + + ?
diff --git a/js/i18n.js b/js/i18n.js new file mode 100644 index 0000000..5fb40a7 --- /dev/null +++ b/js/i18n.js @@ -0,0 +1,459 @@ +const i18nHeadings = { + en: { + position: ['Position', "Sort results by detection time"], + time: ['Time', "Sort results by detection time"], + species: ['Species', "Sort results by detection confidence"], + calls: 'Calls', + label: 'Label', + notes: 'Notes', + max: 'Maximum', + detections: 'Detections' + }, + da: { + position: ['Position', "Sorter resultater efter detektionstid"], + time: ['Tid', "Sorter resultater efter detektionstid"], + species: ['Arter', "Sorter resultater efter detektionssikkerhed"], + calls: 'Kald', + label: 'Etiket', + notes: 'Noter', + max: 'Maksimum', + detections: 'Detektioner' + }, + de: { + position: ['Position', "Ergebnisse nach Erkennungszeit sortieren"], + time: ['Zeit', "Ergebnisse nach Erkennungszeit sortieren"], + species: ['Arten', "Ergebnisse nach Erkennungssicherheit sortieren"], + calls: 'Rufe', + label: 'Etikett', + notes: 'Notizen', + max: 'Maximum', + detections: 'Erkennungen' + }, + es: { + position: ['Posición', "Ordenar resultados por tiempo de detección"], + time: ['Tiempo', "Ordenar resultados por tiempo de detección"], + species: ['Especies', "Ordenar resultados por confianza en la detección"], + calls: 'Llamadas', + label: 'Etiqueta', + notes: 'Notas', + max: 'Máximo', + detections: 'Detecciones' + }, + fr: { + position: ['Position', "Trier les résultats par heure de détection"], + time: ['Temps', "Trier les résultats par heure de détection"], + species: ['Espèces', "Trier les résultats par confiance en la détection"], + calls: 'Appels', + label: 'Étiquette', + notes: 'Notes', + max: 'Maximum', + detections: 'Détections' + }, + nl: { + position: ['Positie', "Sorteer resultaten op detectietijd"], + time: ['Tijd', "Sorteer resultaten op detectietijd"], + species: ['Soorten', "Sorteer resultaten op detectiezekerheid"], + calls: 'Oproepen', + label: 'Label', + notes: 'Notities', + max: 'Maximum', + detections: 'Detecties' + }, + pt: { + position: ['Posição', "Ordenar resultados por tempo de detecção"], + time: ['Tempo', "Ordenar resultados por tempo de detecção"], + species: ['Espécies', "Ordenar resultados por confiança na detecção"], + calls: 'Chamadas', + label: 'Rótulo', + notes: 'Notas', + max: 'Máximo', + detections: 'Detecções' + }, + ru: { + position: ['Позиция', "Сортировать результаты по времени обнаружения"], + time: ['Время', "Сортировать результаты по времени обнаружения"], + species: ['Виды', "Сортировать результаты по уровню доверия к обнаружению"], + calls: 'Звонки', + label: 'Метка', + notes: 'Заметки', + max: 'Максимум', + detections: 'Обнаружения' + }, + sv: { + position: ['Position', "Sortera resultat efter upptäcktstid"], + time: ['Tid', "Sortera resultat efter upptäcktstid"], + species: ['Art', "Sortera resultat efter upptäcktsförtroende"], + calls: 'Samtal', + label: 'Etikett', + notes: 'Anteckningar', + max: 'Maximum', + detections: 'Upptäckter' + }, + zh: { + position: ['位置', "按检测时间排序结果"], + time: ['时间', "按检测时间排序结果"], + species: ['物种', "按检测置信度排序结果"], + calls: '调用', + label: '标签', + notes: '备注', + max: '最大值', + detections: '检测' + } +}; + +const i18nHelp = { + keyboard: { + en: 'Keyboard Shortcuts', + fr: 'Raccourcis clavier', + de: 'Tastenkombinationen', + es: 'Atajos de teclado', + pt: 'Atalhos de teclado', + ru: 'Горячие клавиши', + nl: 'Sneltoetsen', + zh: '键盘快捷键', + sv: 'Tangentbordsgenvägar', // Swedish + da: 'Tastaturgenveje' // Danish + }, + settings: { + en: 'Settings Help', + fr: 'Aide des paramètres', + de: 'Einstellungen Hilfe', + es: 'Ayuda de configuración', + pt: 'Ajuda de configurações', + ru: 'Помощь по настройкам', + nl: 'Instellingen help', + zh: '设置帮助', + sv: 'Inställningshjälp', // Swedish + da: 'Indstillinger Hjælp' // Danish + }, + usage: { + en: 'Usage Guide', + fr: 'Guide d\'utilisation', + de: 'Benutzerhandbuch', + es: 'Guía de uso', + pt: 'Guia de uso', + ru: 'Руководство пользователя', + nl: 'Gebruikershandleiding', + zh: '使用指南', + sv: 'Användarguide', // Swedish + da: 'Brugervejledning' // Danish + }, + eBird: { + en: 'eBird Record FAQ', + fr: 'FAQ des enregistrements eBird', + de: 'eBird Datensatz FAQ', + es: 'Preguntas frecuentes sobre los registros de eBird', + pt: 'FAQ de Registros do eBird', + ru: 'Часто задаваемые вопросы о записях eBird', + nl: 'eBird Record FAQ', + zh: 'eBird记录常见问题', + sv: 'eBird Poster FAQ', // Swedish + da: 'eBird Record FAQ' // Danish + }, + community: { + en: 'Join the Chirpity Users Community', + fr: 'Rejoindre la communauté des utilisateurs de Chirpity', + de: 'Treten Sie der Chirpity-Benutzergemeinschaft bei', + es: 'Únete a la comunidad de usuarios de Chirpity', + pt: 'Junte-se à comunidade de usuários do Chirpity', + ru: 'Присоединиться к сообществу пользователей Chirpity', + nl: 'Word lid van de Chirpity-gebruikersgemeenschap', + zh: '加入Chirpity用户社区', + sv: 'Gå med i Chirpity-användargemenskapen', // Swedish + da: 'Bliv medlem af Chirpity-brugerfællesskabet' // Danish + } + } + + +const i18nLocation = { + en: [ + 'Set Location', + 'Delete Location', + 'Pick A Saved Location', + 'Add, Edit or Delete Location', + 'Update ALL open files to this location' + ], + da: [ + 'Angiv placering', + 'Slet placering', + 'Vælg en gemt placering', + 'Tilføj, rediger eller slet placering', + 'Opdater ALLE åbne filer til denne placering' + ], + de: [ + 'Standort festlegen', + 'Standort löschen', + 'Gespeicherten Standort auswählen', + 'Standort hinzufügen, bearbeiten oder löschen', + 'Alle geöffneten Dateien auf diesen Standort aktualisieren' + ], + es: [ + 'Establecer ubicación', + 'Eliminar ubicación', + 'Seleccionar una ubicación guardada', + 'Añadir, editar o eliminar ubicación', + 'Actualizar TODAS las archivos abiertos a esta ubicación' + ], + fr: [ + 'Définir l’emplacement', + 'Supprimer l’emplacement', + 'Choisir un emplacement enregistré', + 'Ajouter, modifier ou supprimer un emplacement', + 'Mettre à jour TOUS les fichiers ouverts à cet emplacement' + ], + nl: [ + 'Locatie instellen', + 'Locatie verwijderen', + 'Kies een opgeslagen locatie', + 'Locatie toevoegen, bewerken of verwijderen', + 'Werk ALLE geopende bestanden bij naar deze locatie' + ], + pt: [ + 'Definir localização', + 'Excluir localização', + 'Escolher uma localização salva', + 'Adicionar, editar ou excluir localização', + 'Atualizar TODOS os arquivos abertos para esta localização' + ], + ru: [ + 'Установить местоположение', + 'Удалить местоположение', + 'Выбрать сохранённое местоположение', + 'Добавить, изменить или удалить местоположение', + 'Обновить ВСЕ открытые файлы до этого местоположения' + ], + sv: [ + 'Ange plats', + 'Radera plats', + 'Välj en sparad plats', + 'Lägg till, redigera eller radera plats', + 'Uppdatera ALLA öppna filer till denna plats' + ], + zh: [ + '设置位置', + '删除位置', + '选择一个保存的位置', + '添加、编辑或删除位置', + '更新所有打开的文件到此位置' + ] +}; + +const i18nContext = { + en: { + play: 'Play', + pause: 'Pause', + analyse: 'Analyse', + create: 'Create', edit: 'Edit', record: 'Record', + export: 'Export Audio Clip', + compare: 'Compare with Reference Calls', + delete: 'Delete Record', + location: 'Amend File Recording Location', + time: 'Amend File Start Time', + plural: 's' + }, + da: { + play: 'Afspil', + pause: 'Pause', + analyse: 'Analysér', + create: 'Opret', edit: 'Rediger', record: 'post', + export: 'Eksportér lydklip', + compare: 'Sammenlign med referenceopkald', + delete: 'Slet post', + location: 'Rediger filens optagelsesplacering', + time: 'Rediger filens starttid', + plural: 'er' + }, + de: { + play: 'Abspielen', + pause: 'Pause', + analyse: 'Analysieren', + create: 'Erstellen', edit: 'Bearbeiten', record: 'den Eintrag', + export: 'Audioausschnitt exportieren', + compare: 'Mit Referenzaufnahmen vergleichen', + delete: 'Eintrag löschen', + location: 'Aufnahmeort der Datei ändern', + time: 'Startzeit der Datei ändern', + plural: 'e' + }, + es: { + play: 'Reproducir', + pause: 'Pausa', + analyse: 'Analizar', + create: 'Crear', edit: 'Editar', record: 'el Registro', + export: 'Exportar fragmento de audio', + compare: 'Comparar con llamadas de referencia', + delete: 'Eliminar registro', + location: 'Modificar la ubicación de grabación del archivo', + time: 'Modificar la hora de inicio del archivo', + plural: 's' + }, + fr: { + play: 'Jouer', + pause: 'Pause', + analyse: 'Analyser', + create: 'Créer', edit: 'Modifier', record: 'l’Enregistrement', + export: 'Exporter un extrait audio', + compare: 'Comparer avec des appels de référence', + delete: 'Supprimer l’enregistrement', + location: 'Modifier l’emplacement d’enregistrement du fichier', + time: 'Modifier l’heure de début du fichier', + plural: 's' + }, + nl: { + play: 'Afspelen', + pause: 'Pauze', + analyse: 'Analyseren', + create: 'Aanmaken', edit: 'Bewerken', record: 'de Record', + export: 'Audiofragment exporteren', + compare: 'Vergelijk met referentieoproepen', + delete: 'Record verwijderen', + location: 'Opnamelocatie van bestand aanpassen', + time: 'Starttijd van bestand aanpassen', + plural: 'en' + }, + pt: { + play: 'Reproduzir', + pause: 'Pausar', + analyse: 'Analisar', + create: 'Criar', edit: 'Editar', record: 'o Registro', + export: 'Exportar trecho de áudio', + compare: 'Comparar com chamadas de referência', + delete: 'Excluir registro', + location: 'Alterar local de gravação do arquivo', + time: 'Alterar horário de início do arquivo', + plural: 's' + }, + ru: { + play: 'Воспроизвести', + pause: 'Пауза', + analyse: 'Анализировать', + create: 'Создать', edit: 'Редактировать', record: 'запись', + export: 'Экспортировать аудиофрагмент', + compare: 'Сравнить с эталонными записями', + delete: 'Удалить запись', + location: 'Изменить место записи файла', + time: 'Изменить время начала файла', + plural: '' + }, + sv: { + play: 'Spela upp', + pause: 'Paus', + analyse: 'Analysera', + create: 'Skapa', edit: 'Redigera', record: 'posten', + export: 'Exportera ljudklipp', + compare: 'Jämför med referenssamtal', + delete: 'Ta bort post', + location: 'Ändra filens inspelningsplats', + time: 'Ändra filens starttid', + plural: 'er' + }, + zh: { + play: '播放', + pause: '暂停', + analyse: '分析', + create: '创建', edit: '编辑', record: '记录', + export: '导出音频片段', + compare: '与参考调用进行比较', + delete: '删除记录', + location: '修改文件录制位置', + time: '修改文件开始时间', + plural: '' + } +}; + +const i18nForm = { + en: {submit: 'Submit', cancel: 'Cancel', select: "Select New Date and Time:"}, + da: {submit: 'Indsend', cancel: 'Annuller', select: "Vælg ny dato og tid:"}, + de: {submit: 'Absenden', cancel: 'Abbrechen', select: "Neues Datum und Uhrzeit auswählen:"}, + es: {submit: 'Enviar', cancel: 'Cancelar', select: "Seleccionar nueva fecha y hora:"}, + fr: {submit: 'Soumettre', cancel: 'Annuler', select: "Sélectionnez une nouvelle date et heure :"}, + nl: {submit: 'Verzenden', cancel: 'Annuleren', select: "Selecteer een nieuwe datum en tijd:"}, + pt: {submit: 'Enviar', cancel: 'Cancelar', select: "Selecione uma nova data e hora:"}, + ru: {submit: 'Отправить', cancel: 'Отмена', select: "Выберите новую дату и время:"}, + sv: {submit: 'Skicka', cancel: 'Avbryt', select: "Välj nytt datum och tid:"}, + zh: {submit: '提交', cancel: '取消', select: "选择新的日期和时间:"} +}; + +async function localiseUI(locale) { + let t0 = Date.now(); + locale = locale.replace('_uk', ''); + try { + // Try fetching the localisation JSON file + let localisationData = {}; + try { + const jsonResponse = await fetch(`./I18n/index.${locale}.json`) + if (jsonResponse.ok) { + localisationData = await jsonResponse.json(); + } else { + console.warn(`JSON file not found: index.${locale}.json`); + return; // Return unmodified HTML if JSON not found + } + } catch (error) { + console.warn(`Failed to fetch JSON file: index.${locale}.json`, error); + // go for english + locale = 'en'; + const jsonResponse = await fetch(`./I18n/index.en.json`) + if (jsonResponse.ok) { + localisationData = await jsonResponse.json(); + } else { + console.warn(`JSON file not found: index.en.json`); + return; // Return unmodified HTML if JSON not found + } + } + // Update elements with IDs + for (const key in localisationData) { + // Skip settings + if (key === 'settings') continue; + if (localisationData.hasOwnProperty(key)) { + + const element = document.getElementById(key); + if (element) { + if (key.indexOf('circle-help') !==-1){ + // Help button popup text + element.setAttribute('data-bs-content', localisationData[key]); + // refresh the tooltip to reflect the change + const popover = new bootstrap.Popover(element); + popover.update(); + + } else { + // Replace the inner text of the tag but leave unaffected + const spans = element.querySelectorAll('span'); + element.textContent = ' ' + localisationData[key][0]; + spans.length && element.insertBefore(spans[0], element.firstChild); + spans.length > 1 && element.appendChild(spans[1]) + }; + // element.innerHTML = localisationData[key]; + + } + } + } + // Update buttons without ID + const buttons = document.querySelectorAll('button:not([id])') + buttons.forEach(button => button.textContent &&= localisationData['help-modal-close']); + + // Translate settings labels + const form = document.getElementById('settings'); + const labels = form.querySelectorAll('label'); + labels.forEach(label => { + const id = label.getAttribute('for'); + label.textContent = localisationData['settings'][id]; + }) + const play = document.querySelector('#playToggle :nth-child(2)'); + const pause = document.querySelector('#playToggle :nth-child(4)'); + play.textContent = i18nContext[locale].play; + pause.textContent = i18nContext[locale].pause; + const headings = form.querySelectorAll('h4,h5,h6,legend'); + for (let i=0;i { //e.preventDefault(); e.stopImmediatePropagation(); const menu = DOM.contextMenu; + const i18n = getI18n(i18nContext); menu.innerHTML = ` edit_location_alt Amend File Recording Location + class="material-symbols-outlined align-bottom pointer">edit_location_alt ${i18n.location} edit_calendar Amend File Start Time + class="material-symbols-outlined align-bottom pointer">edit_calendar ${i18n.time} `; positionMenu(menu, e); } @@ -549,12 +550,13 @@ function getDatetimeLocalFromEpoch(date) { function showDatePicker() { // Create a form element + const i18n = getI18n(i18nForm); const form = document.createElement("form"); form.classList.add("mt-3", "mb-3", "p-3", "rounded", "text-bg-light", 'position-relative'); form.style.zIndex = "1000"; // Create a label for the datetime-local input const label = document.createElement("label"); - label.innerHTML = "Select New Date and Time:"; + label.innerHTML = i18n.select; label.classList.add("form-label"); form.appendChild(label); @@ -569,13 +571,13 @@ function showDatePicker() { // Create a submit button const submitButton = document.createElement("button"); - submitButton.innerHTML = "Submit"; + submitButton.innerHTML = i18n.submit; submitButton.classList.add("btn", "btn-primary", "mt-2"); form.appendChild(submitButton); // Create a cancel button var cancelButton = document.createElement("button"); - cancelButton.innerHTML = "Cancel"; + cancelButton.innerHTML = i18n.cancel; cancelButton.classList.add("btn", "btn-secondary", "mt-2", "ms-2"); form.appendChild(cancelButton); @@ -715,14 +717,15 @@ function renderFilenamePanel() { function customAnalysisAllMenu(saved){ + const analyseAllMenu = document.getElementById('analyseAll'); const modifier = isMac ? '⌘' : 'Ctrl'; if (saved) { - analyseAllMenu.innerHTML = `upload_file Get Results for All Open Files + analyseAllMenu.innerHTML = `upload_file ${STATE.i18n.retrieveAll} ${modifier}+Shift+A`; enableMenuItem(['reanalyseAll']); } else { - analyseAllMenu.innerHTML = `search Analyse All Open Files + analyseAllMenu.innerHTML = `search ${STATE.i18n.analyseAll} ${modifier}+Shift+A`; disableMenuItem(['reanalyseAll']); } @@ -736,7 +739,7 @@ function customiseAnalysisMenu(saved) { ${modifier}+A`; enableMenuItem(['reanalyse']); } else { - analyseMenu.innerHTML = `search Analyse File + analyseMenu.innerHTML = `search Analyse Current File ${modifier}+A`; disableMenuItem(['reanalyse']); } @@ -744,7 +747,20 @@ function customiseAnalysisMenu(saved) { async function generateLocationList(id) { - const defaultText = id === 'savedLocations' ? '(Default)' : 'All'; + const d = { + "en": ["(Default)", "All"], + "da": ["(Standard)", "Alle"], + "de": ["(Standard)", "Alle"], + "es": ["(Predeterminado)", "Todos"], + "fr": ["(Par défaut)", "Tout"], + "nl": ["(Standaard)", "Alles"], + "pt": ["(Padrão)", "Todos"], + "ru": ["(По умолчанию)", "Все"], + "sv": ["(Standard)", "Alla"], + "zh": ["(默认)", "所有"] + } + const i18n = d[locale] || d['en']; + const defaultText = id === 'savedLocations' ? i18n[0] : i18n[1]; const el = document.getElementById(id); LOCATIONS = undefined; worker.postMessage({ action: 'get-locations', file: STATE.currentFile }); @@ -875,13 +891,15 @@ async function setCustomLocation() { savedLocationSelect.addEventListener('change', function () { showLocation(true); }) + + const i18n = getI18n(i18nLocation) const addOrDelete = () => { if (customPlaceEl.value) { - locationAdd.textContent = 'Set Location' + locationAdd.textContent = i18n[0]; locationAdd.classList.remove('btn-danger'); locationAdd.classList.add('button-primary'); } else { - locationAdd.textContent = 'Delete Location' + locationAdd.textContent = i18n[1]; locationAdd.classList.add('btn-danger'); locationAdd.classList.remove('button-primary'); } @@ -889,6 +907,12 @@ async function setCustomLocation() { // Highlight delete customPlaceEl.addEventListener('keyup', addOrDelete); addOrDelete(); + locationModalDiv.querySelector('h5').textContent = i18n[0]; + const legends = locationModalDiv.querySelectorAll('legend'); + for (let i = 0; i < legends.length; i++) { + legends[i].textContent = i18n[i+2]; // process each node + } + locationModalDiv.querySelector('label[for="batchLocations"]').textContent = i18n[4]; const locationModal = new bootstrap.Modal(locationModalDiv); locationModal.show(); @@ -1738,7 +1762,7 @@ window.onload = async () => { // Show Locale DOM.locale.value = config[config.model].locale; // Localise UI - localiseUI(DOM.locale.value) + STATE.i18n = localiseUI(DOM.locale.value) // remember audio notification setting DOM.audioNotification.checked = config.audio.notification; @@ -3120,15 +3144,16 @@ function centreSpec(){ } const updateSummary = async ( { summary = [], filterSpecies = '' }) => { + const i18n = getI18n(i18nHeadings); const showIUCN = config.detect.iucn; if (summary.length){ let summaryHTML = ` - - + + ${showIUCN ? '' : ''} - - + + `; let selectedRow = null; @@ -3367,7 +3392,7 @@ function formatDuration(seconds){ } // TODO: show every detection in the spec window as a region on the spectrogram - + async function renderResult({ index = 1, result = {}, @@ -3384,14 +3409,15 @@ function formatDuration(seconds){ selectionTable.textContent = ''; } else { + const i18n = getI18n(i18nHeadings); DOM.resultHeader.innerHTML =` - - - - - - + + + + + + `; setTimelinePreferences(); showElement(['resultTableContainer', 'resultsHead'], false); @@ -3705,58 +3731,7 @@ function formatDuration(seconds){ } } - async function localiseUI(locale) { - try { - // Try fetching the localisation JSON file - let localisationData = {}; - try { - // Fetch the localisation JSON file - const basename = 'index'; - // If no localisation, default to English - if (! fs.existsSync(p.join('I18n', `${basename}.${locale}.json`))) { - // Let me know someone was looking for a non-existant locale - console.warn(`User requested ${locale}`); - locale = 'en'; - } - const jsonResponse = await fetch(p.join('I18n', `${basename}.${locale}.json`)) - if (jsonResponse.ok) { - localisationData = await jsonResponse.json(); - } else { - console.warn(`JSON file not found: ${filename} parsed to ${locale}.json`); - return; // Return unmodified HTML if JSON not found - } - } catch (error) { - console.warn(`Failed to fetch JSON file: ${filename} parsed to ${locale}.json`, error); - return; // Return unmodified HTML if JSON fetch fails - } - // Update elements - for (const key in localisationData) { - if (localisationData.hasOwnProperty(key)) { - const element = document.getElementById(key); - if (element) { - if (key.indexOf('circle-help') !==-1){ - // Help button popup text - element.setAttribute('data-bs-content', localisationData[key]); - // refresh the tooltip to reflect the change - const popover = new bootstrap.Popover(element); - popover.update(); - - } else { - // Replace the inner text of the tag but leave unaffected - const spans = element.querySelectorAll('span'); - element.textContent = ' ' + localisationData[key][0]; - spans.length && element.insertBefore(spans[0], element.firstChild); - spans.length > 1 && element.appendChild(spans[1]) - }; - // element.innerHTML = localisationData[key]; - - } - } - } - } catch (error) { - console.error('Localisation Error:', error.message); - } - } + const populateHelpModal = async (file, label) => { document.getElementById('helpModalLabel').textContent = label; @@ -3767,18 +3742,16 @@ function formatDuration(seconds){ document.removeEventListener('show.bs.modal', replaceCtrlWithCommand); document.addEventListener('show.bs.modal', replaceCtrlWithCommand); const close = { - fr: 'Fermer', + da: 'Luk', de: 'Schließen', es: 'Cerrar', + fr: 'Fermer', + nl: 'Sluiten', pt: 'Fechar', ru: 'Закрыть', - nl: 'Sluiten', - zh: '关闭', - sv: 'Stäng', // Swedish - da: 'Luk' // Danish + sv: 'Stäng', + zh: '关闭' } - - console.log(close.locale) document.getElementById('help-modal-close').innerText = close[locale] || 'Close'; help.show(); } @@ -4521,74 +4494,12 @@ function playRegion(){ } } - const localeHelp = { - keyboard: { - en: 'Keyboard Shortcuts', - fr: 'Raccourcis clavier', - de: 'Tastenkombinationen', - es: 'Atajos de teclado', - pt: 'Atalhos de teclado', - ru: 'Горячие клавиши', - nl: 'Sneltoetsen', - zh: '键盘快捷键', - sv: 'Tangentbordsgenvägar', // Swedish - da: 'Tastaturgenveje' // Danish - }, - settings: { - en: 'Settings Help', - fr: 'Aide des paramètres', - de: 'Einstellungen Hilfe', - es: 'Ayuda de configuración', - pt: 'Ajuda de configurações', - ru: 'Помощь по настройкам', - nl: 'Instellingen help', - zh: '设置帮助', - sv: 'Inställningshjälp', // Swedish - da: 'Indstillinger Hjælp' // Danish - }, - usage: { - en: 'Usage Guide', - fr: 'Guide d\'utilisation', - de: 'Benutzerhandbuch', - es: 'Guía de uso', - pt: 'Guia de uso', - ru: 'Руководство пользователя', - nl: 'Gebruikershandleiding', - zh: '使用指南', - sv: 'Användarguide', // Swedish - da: 'Brugervejledning' // Danish - }, - eBird: { - en: 'eBird Record FAQ', - fr: 'FAQ des enregistrements eBird', - de: 'eBird Datensatz FAQ', - es: 'Preguntas frecuentes sobre los registros de eBird', - pt: 'FAQ de Registros do eBird', - ru: 'Часто задаваемые вопросы о записях eBird', - nl: 'eBird Record FAQ', - zh: 'eBird记录常见问题', - sv: 'eBird Poster FAQ', // Swedish - da: 'eBird Record FAQ' // Danish - }, - community: { - en: 'Join the Chirpity Users Community', - fr: 'Rejoindre la communauté des utilisateurs de Chirpity', - de: 'Treten Sie der Chirpity-Benutzergemeinschaft bei', - es: 'Únete a la comunidad de usuarios de Chirpity', - pt: 'Junte-se à comunidade de usuários do Chirpity', - ru: 'Присоединиться к сообществу пользователей Chirpity', - nl: 'Word lid van de Chirpity-gebruikersgemeenschap', - zh: '加入Chirpity用户社区', - sv: 'Gå med i Chirpity-användargemenskapen', // Swedish - da: 'Bliv medlem af Chirpity-brugerfællesskabet' // Danish - } - } - document.addEventListener('click', function (e) { const element = e.target; const target = element.closest('[id]')?.id; + const locale = config[config.model].locale.replace('_uk', ''); switch (target) { // File menu @@ -4643,13 +4554,13 @@ function playRegion(){ } // Help Menu - case 'keyboardHelp': { (async () => await populateHelpModal('Help/keyboard.html', localeHelp.keyboard[config[config.model].locale]))(); break } - case 'settingsHelp': { (async () => await populateHelpModal('Help/settings.html', localeHelp.settings[config[config.model].locale]))(); break } - case 'usage': { (async () => await populateHelpModal('Help/usage.html', localeHelp.usage[config[config.model].locale]))(); break } - case 'bugs': { (async () => await populateHelpModal('Help/community.html', localeHelp.community[config[config.model].locale]))(); break } + case 'keyboardHelp': { (async () => await populateHelpModal('Help/keyboard.html', i18nHelp.keyboard[locale]))(); break } + case 'settingsHelp': { (async () => await populateHelpModal('Help/settings.html', i18nHelp.settings[locale]))(); break } + case 'usage': { (async () => await populateHelpModal('Help/usage.html', i18nHelp.usage[locale]))(); break } + case 'bugs': { (async () => await populateHelpModal('Help/community.html', i18nHelp.community[locale]))(); break } case 'species': { worker.postMessage({action: 'get-valid-species', file: STATE.currentFile}); break } case 'startTour': { prepTour(); break } - case 'eBird': { (async () => await populateHelpModal('Help/ebird.html', localeHelp.eBird[config[config.model].locale]))(); break } + case 'eBird': { (async () => await populateHelpModal('Help/ebird.html', i18nHelp.eBird[locale]))(); break } case 'copy-uuid': { // Get the value from the input element const copyText = document.getElementById('uuid').textContent.split('\n')[0]; @@ -4891,7 +4802,7 @@ function playRegion(){ } else { const chirpity = element.value === 'en_uk' && config.model !== 'birdnet' ? 'chirpity' : ''; labelFile = `labels/V2.4/BirdNET_GLOBAL_6K_V2.4_${chirpity}Labels_${element.value}.txt`; - localiseUI(element.value) + STATE.i18n = localiseUI(element.value) } config[config.model].locale = element.value; readLabels(labelFile, 'locale'); @@ -5095,8 +5006,13 @@ async function readLabels(labelFile, updating){ }) } +function getI18n(context){ + const locale = config[config.model].locale.replace('_uk', ''); + return context[locale] || context['en']; +} async function createContextMenu(e) { + const i18n = getI18n(i18nContext); const target = e.target; if (target.classList.contains('circle') || target.closest('thead')) return; let hideInSummary = '', hideInSelection = '', @@ -5120,27 +5036,27 @@ async function readLabels(labelFile, updating){ } } if (region === undefined && ! inSummary) return; - const createOrEdit = ((region?.attributes.label || target.closest('#summary'))) ? 'Edit' : 'Create'; + const createOrEdit = ((region?.attributes.label || target.closest('#summary'))) ? i18n.edit : i18n.create; contextMenu.innerHTML = ` `;
MaxSpecies${i18n.max}${i18n.species[0]}DetectionsCalls${i18n.detections}${i18n.calls}
sort Timesort Positionsort SpeciesCallsLabelNotessort ${i18n.time[0]}sort ${i18n.position[0]}sort ${i18n.species[0]}${i18n.calls}${i18n.label}${i18n.notes}