translation of comments and some other german terms
This commit is contained in:
1 parent
5d54f574e0
commit
3267b6a6a3
3 files changed
+120
-119
No files matched your search
+4
-4
@@ -1,7 +1,7 @@
|
|||||||
{
|
{
|
||||||
"en": {
|
"en": {
|
||||||
"pageTitle": "Jitsi Meeting",
|
"pageTitle": "Jitsi Meeting",
|
||||||
"impressum": "Legal Notice",
|
"legal_notice": "Legal Notice",
|
||||||
"source": "Source",
|
"source": "Source",
|
||||||
"launcher": {
|
"launcher": {
|
||||||
"title": "Jitsi Meeting",
|
"title": "Jitsi Meeting",
|
||||||
@@ -91,7 +91,7 @@
|
|||||||
},
|
},
|
||||||
"de": {
|
"de": {
|
||||||
"pageTitle": "Jitsi Meeting öffnen",
|
"pageTitle": "Jitsi Meeting öffnen",
|
||||||
"impressum": "Impressum",
|
"legal_notice": "Impressum",
|
||||||
"source": "Quellcode",
|
"source": "Quellcode",
|
||||||
"launcher": {
|
"launcher": {
|
||||||
"title": "Jitsi Meeting",
|
"title": "Jitsi Meeting",
|
||||||
@@ -181,7 +181,7 @@
|
|||||||
},
|
},
|
||||||
"fr": {
|
"fr": {
|
||||||
"pageTitle": "Réunion Jitsi",
|
"pageTitle": "Réunion Jitsi",
|
||||||
"impressum": "Mentions légales",
|
"legal_notice": "Mentions légales",
|
||||||
"source": "Code source",
|
"source": "Code source",
|
||||||
"launcher": {
|
"launcher": {
|
||||||
"title": "Réunion Jitsi",
|
"title": "Réunion Jitsi",
|
||||||
@@ -271,7 +271,7 @@
|
|||||||
},
|
},
|
||||||
"zh": {
|
"zh": {
|
||||||
"pageTitle": "Jitsi 会议",
|
"pageTitle": "Jitsi 会议",
|
||||||
"impressum": "法律声明",
|
"legal_notice": "法律声明",
|
||||||
"source": "源代码",
|
"source": "源代码",
|
||||||
"launcher": {
|
"launcher": {
|
||||||
"title": "Jitsi 会议",
|
"title": "Jitsi 会议",
|
||||||
|
|||||||
+114
-113
@@ -1,13 +1,13 @@
|
|||||||
"use strict";
|
"use strict";
|
||||||
|
|
||||||
/* ============================================================
|
/* ============================================================
|
||||||
* KONFIGURATION
|
* CONFIGURATION
|
||||||
* ============================================================
|
* ============================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Konfiguration liegt in assets/config.json und wird beim
|
* Configuration lives in assets/config.json and is loaded
|
||||||
* Start asynchron geladen (siehe START).
|
* asynchronously at startup (see START).
|
||||||
*/
|
*/
|
||||||
let CONFIG = {};
|
let CONFIG = {};
|
||||||
const CONFIG_URL = "assets/config.json";
|
const CONFIG_URL = "assets/config.json";
|
||||||
@@ -18,8 +18,8 @@ const CONFIG_URL = "assets/config.json";
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sprachen liegen in assets/i18n.json und werden beim
|
* Translations live in assets/i18n.json and are loaded
|
||||||
* Start asynchron geladen (siehe START).
|
* asynchronously at startup (see START).
|
||||||
*/
|
*/
|
||||||
let TRANSLATIONS = {};
|
let TRANSLATIONS = {};
|
||||||
const I18N_URL = "assets/i18n.json";
|
const I18N_URL = "assets/i18n.json";
|
||||||
@@ -31,7 +31,7 @@ const I18N_URL = "assets/i18n.json";
|
|||||||
|
|
||||||
function detectLanguage() {
|
function detectLanguage() {
|
||||||
/*
|
/*
|
||||||
* Gespeicherte Sprachwahl hat Vorrang.
|
* Saved language choice takes precedence.
|
||||||
*/
|
*/
|
||||||
try {
|
try {
|
||||||
const saved = localStorage.getItem("jitsiLauncherLanguage");
|
const saved = localStorage.getItem("jitsiLauncherLanguage");
|
||||||
@@ -41,7 +41,7 @@ function detectLanguage() {
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
/*
|
/*
|
||||||
* localStorage kann z.B. im Privat-Modus blockiert sein.
|
* localStorage can be blocked, e.g. in private mode.
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@ function detectLanguage() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Englisch ist der Standard/Fallback.
|
* English is the default/fallback.
|
||||||
*/
|
*/
|
||||||
return "en";
|
return "en";
|
||||||
}
|
}
|
||||||
@@ -93,7 +93,7 @@ function applyTranslations() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Platzhalter von Eingabefeldern übersetzen.
|
* Translate placeholders of input fields.
|
||||||
*/
|
*/
|
||||||
document
|
document
|
||||||
.querySelectorAll("[data-i18n-placeholder]")
|
.querySelectorAll("[data-i18n-placeholder]")
|
||||||
@@ -107,13 +107,13 @@ function applyTranslations() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Übersetzung anhand eines Pfades lesen.
|
* Read a translation by path.
|
||||||
*
|
*
|
||||||
* Beispiel:
|
* Example:
|
||||||
*
|
*
|
||||||
* "downloads.windows.title"
|
* "downloads.windows.title"
|
||||||
*
|
*
|
||||||
* ergibt:
|
* resolves to:
|
||||||
*
|
*
|
||||||
* translation.downloads.windows.title
|
* translation.downloads.windows.title
|
||||||
*/
|
*/
|
||||||
@@ -182,7 +182,7 @@ function setLanguage(language) {
|
|||||||
localStorage.setItem("jitsiLauncherLanguage", language);
|
localStorage.setItem("jitsiLauncherLanguage", language);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
/*
|
/*
|
||||||
* localStorage kann z.B. im Privat-Modus blockiert sein.
|
* localStorage can be blocked, e.g. in private mode.
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -236,7 +236,7 @@ function savedTheme() {
|
|||||||
}
|
}
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
/*
|
/*
|
||||||
* localStorage kann z.B. im Privat-Modus blockiert sein.
|
* localStorage can be blocked, e.g. in private mode.
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,7 +249,7 @@ function systemIsDark() {
|
|||||||
|
|
||||||
function detectTheme() {
|
function detectTheme() {
|
||||||
/*
|
/*
|
||||||
* Gespeicherte Wahl hat Vorrang, sonst System-Einstellung.
|
* Saved choice takes precedence, otherwise system setting.
|
||||||
*/
|
*/
|
||||||
return savedTheme() || (systemIsDark() ? "dark" : "light");
|
return savedTheme() || (systemIsDark() ? "dark" : "light");
|
||||||
}
|
}
|
||||||
@@ -273,7 +273,7 @@ function toggleTheme() {
|
|||||||
localStorage.setItem(THEME_KEY, currentTheme);
|
localStorage.setItem(THEME_KEY, currentTheme);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
/*
|
/*
|
||||||
* localStorage kann z.B. im Privat-Modus blockiert sein.
|
* localStorage can be blocked, e.g. in private mode.
|
||||||
*/
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -315,8 +315,8 @@ function applyLogo() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Nur anzeigen, wenn eine Nextcloud-Instanz konfiguriert
|
* Only show if a Nextcloud instance is configured
|
||||||
* ist (CONFIG.nextcloudBase in assets/config.json).
|
* (CONFIG.nextcloudBase in assets/config.json).
|
||||||
*/
|
*/
|
||||||
function applyNextcloudButton() {
|
function applyNextcloudButton() {
|
||||||
if (!CONFIG.nextcloudBase || !createNextcloudButton) {
|
if (!CONFIG.nextcloudBase || !createNextcloudButton) {
|
||||||
@@ -332,7 +332,7 @@ function applyNextcloudButton() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Nur anzeigen, wenn explizit aktiviert
|
* Only show if explicitly enabled
|
||||||
* (CONFIG.allowAdhocMeetings in assets/config.json).
|
* (CONFIG.allowAdhocMeetings in assets/config.json).
|
||||||
*/
|
*/
|
||||||
function applyAdhocButton() {
|
function applyAdhocButton() {
|
||||||
@@ -421,11 +421,11 @@ const themeIconMoon = document.getElementById("themeIconMoon");
|
|||||||
* GET ROOM FROM QUERY-PARAMETER
|
* GET ROOM FROM QUERY-PARAMETER
|
||||||
* ============================================================
|
* ============================================================
|
||||||
*
|
*
|
||||||
* Beispiel:
|
* Example:
|
||||||
*
|
*
|
||||||
* https://<YOURJITSIINSTANCEADDRESS>/launch.html?room=abc-defg-hij
|
* https://<YOURJITSIINSTANCEADDRESS>/launch.html?room=abc-defg-hij
|
||||||
*
|
*
|
||||||
* ergibt:
|
* results in:
|
||||||
*
|
*
|
||||||
* abc-defg-hij
|
* abc-defg-hij
|
||||||
*
|
*
|
||||||
@@ -438,16 +438,16 @@ function getRoom() {
|
|||||||
);
|
);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Parameter nicht vorhanden.
|
* Parameter missing.
|
||||||
*/
|
*/
|
||||||
if (!params.has("room")) {
|
if (!params.has("room")) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Leerzeichen etc. verhindern.
|
* Prevent whitespace etc.
|
||||||
*
|
*
|
||||||
* "?room=" ohne Wert ergibt einen leeren String.
|
* "?room=" without a value yields an empty string.
|
||||||
*/
|
*/
|
||||||
return params.get("room").trim();
|
return params.get("room").trim();
|
||||||
}
|
}
|
||||||
@@ -456,11 +456,11 @@ function getRoom() {
|
|||||||
* VALIDATE ROOM
|
* VALIDATE ROOM
|
||||||
* ============================================================
|
* ============================================================
|
||||||
*
|
*
|
||||||
* Jitsi-Roomnamen können je nach Konfiguration relativ
|
* Jitsi room names can contain rather different
|
||||||
* unterschiedliche Zeichen enthalten.
|
* characters depending on the configuration.
|
||||||
*
|
*
|
||||||
* Wir verhindern hier lediglich Steuerzeichen und
|
* We only prevent control characters and obvious
|
||||||
* offensichtliche URL-Manipulation.
|
* URL manipulation here.
|
||||||
*
|
*
|
||||||
* ============================================================
|
* ============================================================
|
||||||
*/
|
*/
|
||||||
@@ -473,7 +473,7 @@ function isValidRoom(room) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Nur Buchstaben, Zahlen und Bindestriche.
|
* Only letters, numbers and hyphens.
|
||||||
*/
|
*/
|
||||||
return ROOM_PATTERN.test(room);
|
return ROOM_PATTERN.test(room);
|
||||||
}
|
}
|
||||||
@@ -511,10 +511,10 @@ function createAppUrl(room) {
|
|||||||
* ============================================================ */
|
* ============================================================ */
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Die Android-App registriert "org.jitsi.meet", nicht das
|
* The Android app registers "org.jitsi.meet", not the
|
||||||
* Desktop-Schema. Chrome & Co. verlangen intent://, ohne App
|
* desktop scheme. Chrome & co. require intent://; without
|
||||||
* bietet Chrome den Play-Store-Eintrag aus "package=" an.
|
* the app Chrome offers the Play Store entry from "package=".
|
||||||
* Firefox ignoriert intent://, kennt aber das Custom-Schema.
|
* Firefox ignores intent:// but knows the custom scheme.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function createAndroidIntentUrl(room) {
|
function createAndroidIntentUrl(room) {
|
||||||
@@ -528,8 +528,8 @@ function createAndroidIntentUrl(room) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Die Mobile-Apps (iOS, Firefox auf Android) registrieren
|
* The mobile apps (iOS, Firefox on Android) register
|
||||||
* "org.jitsi.meet", nicht das Desktop-Schema.
|
* "org.jitsi.meet", not the desktop scheme.
|
||||||
*/
|
*/
|
||||||
const APP_SCHEME = "org.jitsi.meet://";
|
const APP_SCHEME = "org.jitsi.meet://";
|
||||||
|
|
||||||
@@ -543,14 +543,14 @@ function createAppSchemeUrl(room) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ============================================================
|
/* ============================================================
|
||||||
* URL NACH PLATTFORM/BROWSER
|
* URL BY PLATFORM/BROWSER
|
||||||
* ============================================================ */
|
* ============================================================ */
|
||||||
|
|
||||||
function selectProtocolUrl(room) {
|
function selectProtocolUrl(room) {
|
||||||
const os = detectOperatingSystem();
|
const os = detectOperatingSystem();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* iOS-App kennt nur das App-Schema.
|
* The iOS app only knows the app scheme.
|
||||||
*/
|
*/
|
||||||
if (os === "ios") {
|
if (os === "ios") {
|
||||||
return createAppSchemeUrl(room);
|
return createAppSchemeUrl(room);
|
||||||
@@ -571,8 +571,8 @@ function selectProtocolUrl(room) {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Einmal parsen (assets/lib/ua-parser.min.js).
|
* Parse once (assets/lib/ua-parser.min.js).
|
||||||
* Fällt die Bibliothek aus, bleibt die Seite bedienbar.
|
* If the library is missing, the page stays usable.
|
||||||
*/
|
*/
|
||||||
const uaResult =
|
const uaResult =
|
||||||
typeof UAParser === "function"
|
typeof UAParser === "function"
|
||||||
@@ -580,8 +580,8 @@ const uaResult =
|
|||||||
: { os: {}, browser: {} };
|
: { os: {}, browser: {} };
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* UAParser-Namen -> interne Kürzel.
|
* UAParser names -> internal shortcuts.
|
||||||
* iPadOS meldet sich als macOS – Touchpunkte gelten als iOS.
|
* iPadOS reports as macOS – touch points count as iOS.
|
||||||
*/
|
*/
|
||||||
const OS_NAMES = {
|
const OS_NAMES = {
|
||||||
Android: "android",
|
Android: "android",
|
||||||
@@ -614,9 +614,9 @@ const BROWSER_NAMES = {
|
|||||||
|
|
||||||
function detectOperatingSystem() {
|
function detectOperatingSystem() {
|
||||||
/*
|
/*
|
||||||
* Chrome im "Desktop-Modus" auf Android sendet einen
|
* Chrome in "desktop mode" on Android sends a desktop
|
||||||
* Desktop-UA (z.B. X11; Linux). Client Hints verraten
|
* UA (e.g. X11; Linux). Client hints reveal the real
|
||||||
* das echte System. Firefox/Safari kennen sie nicht.
|
* system. Firefox/Safari do not support them.
|
||||||
*/
|
*/
|
||||||
const hints = navigator.userAgentData;
|
const hints = navigator.userAgentData;
|
||||||
if (hints && hints.platform === "Android") {
|
if (hints && hints.platform === "Android") {
|
||||||
@@ -624,8 +624,9 @@ function detectOperatingSystem() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* iPadOS tarnt sich als macOS – Touchpunkte verraten das iPad.
|
* iPadOS masquerades as macOS – touch points give the
|
||||||
* Der Plattform-Check greift auch ohne geladenen ua-parser.
|
* iPad away. The platform check also works without the
|
||||||
|
* ua-parser loaded.
|
||||||
*/
|
*/
|
||||||
if (
|
if (
|
||||||
navigator.maxTouchPoints > 1 &&
|
navigator.maxTouchPoints > 1 &&
|
||||||
@@ -638,7 +639,7 @@ function detectOperatingSystem() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ============================================================
|
/* ============================================================
|
||||||
* BROWSER ERKENNEN
|
* DETECT BROWSER
|
||||||
* ============================================================
|
* ============================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -696,12 +697,12 @@ function configureDownloads() {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Alles andere */
|
/* Everything else */
|
||||||
otherDownload.classList.remove("hidden");
|
otherDownload.classList.remove("hidden");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ============================================================
|
/* ============================================================
|
||||||
* FALLBACK ANZEIGEN
|
* SHOW FALLBACK
|
||||||
* ============================================================
|
* ============================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -714,7 +715,7 @@ function showFallback() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ============================================================
|
/* ============================================================
|
||||||
* JITSI DESKTOP STARTEN
|
* START JITSI DESKTOP
|
||||||
* ============================================================
|
* ============================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -729,12 +730,12 @@ function launchJitsi() {
|
|||||||
const browserUrl = createBrowserUrl(room);
|
const browserUrl = createBrowserUrl(room);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Browser-Fallback vorbereiten.
|
* Prepare the browser fallback.
|
||||||
*/
|
*/
|
||||||
browserLink.href = browserUrl;
|
browserLink.href = browserUrl;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* UI auf "Startvorgang" setzen.
|
* Set the UI to the "starting" state.
|
||||||
*/
|
*/
|
||||||
launcher.classList.add("hidden");
|
launcher.classList.add("hidden");
|
||||||
fallback.classList.add("hidden");
|
fallback.classList.add("hidden");
|
||||||
@@ -744,13 +745,13 @@ function launchJitsi() {
|
|||||||
let timeout = null;
|
let timeout = null;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Unsichtbarer iframe für den Protocol Handler.
|
* Invisible iframe for the protocol handler.
|
||||||
*/
|
*/
|
||||||
const iframe = document.createElement("iframe");
|
const iframe = document.createElement("iframe");
|
||||||
iframe.style.display = "none";
|
iframe.style.display = "none";
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Aufräumen.
|
* Clean up.
|
||||||
*/
|
*/
|
||||||
function cleanup() {
|
function cleanup() {
|
||||||
if (completed) {
|
if (completed) {
|
||||||
@@ -768,25 +769,25 @@ function launchJitsi() {
|
|||||||
|
|
||||||
/*
|
/*
|
||||||
* --------------------------------------------------------
|
* --------------------------------------------------------
|
||||||
* WICHTIG:
|
* IMPORTANT:
|
||||||
*
|
*
|
||||||
* Kein "blur" mehr als Erfolgskriterium verwenden.
|
* Do not use "blur" as a success criterion anymore.
|
||||||
*
|
*
|
||||||
* Der Browser kann beim Protocol-Dialog ebenfalls
|
* The browser can also trigger blur when showing
|
||||||
* blur auslösen.
|
* the protocol dialog.
|
||||||
*
|
*
|
||||||
* Wenn der Benutzer den Dialog abbricht, bleibt die
|
* If the user cancels the dialog, the page stays
|
||||||
* Seite sichtbar und unser Timeout läuft weiter.
|
* visible and our timeout keeps running.
|
||||||
* --------------------------------------------------------
|
* --------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
document.body.appendChild(iframe);
|
document.body.appendChild(iframe);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Protocol Handler starten.
|
* Start the protocol handler.
|
||||||
*
|
*
|
||||||
* Firefox ignoriert externe Protokolle aus iframes –
|
* Firefox ignores external protocols from iframes –
|
||||||
* das Custom-Schema direkt in der Hauptnavigation starten.
|
* start the custom scheme directly in the main navigation.
|
||||||
*/
|
*/
|
||||||
try {
|
try {
|
||||||
if (protocolUrl.startsWith(APP_SCHEME)) {
|
if (protocolUrl.startsWith(APP_SCHEME)) {
|
||||||
@@ -811,19 +812,19 @@ function launchJitsi() {
|
|||||||
* FALLBACK
|
* FALLBACK
|
||||||
* --------------------------------------------------------
|
* --------------------------------------------------------
|
||||||
*
|
*
|
||||||
* Wir warten unabhängig davon, ob der Browser kurz
|
* We wait regardless of whether the browser briefly
|
||||||
* den Fokus verliert.
|
* loses focus.
|
||||||
*
|
*
|
||||||
* Wenn Jitsi erfolgreich startet:
|
* If Jitsi starts successfully:
|
||||||
*
|
*
|
||||||
* -> Jitsi kommt in den Vordergrund
|
* -> Jitsi comes to the foreground
|
||||||
* -> Benutzer sieht diese Seite nicht mehr
|
* -> the user no longer sees this page
|
||||||
*
|
*
|
||||||
* Wenn der Benutzer den Browser-Dialog abbricht:
|
* If the user cancels the browser dialog:
|
||||||
*
|
*
|
||||||
* -> diese Seite bleibt sichtbar
|
* -> this page stays visible
|
||||||
* -> Timeout läuft ab
|
* -> the timeout expires
|
||||||
* -> Fallback wird angezeigt
|
* -> the fallback is shown
|
||||||
* --------------------------------------------------------
|
* --------------------------------------------------------
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -843,13 +844,13 @@ function launchJitsi() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Sonderzeichen in das nächstliegende ASCII-Zeichen
|
* Convert special characters to the closest ASCII
|
||||||
* umwandeln.
|
* character.
|
||||||
*
|
*
|
||||||
* Beispiel:
|
* Example:
|
||||||
*
|
*
|
||||||
* "Grundstück" ergibt "Grundstueck"
|
* "Grundstück" becomes "Grundstueck"
|
||||||
* "François" ergibt "Francois"
|
* "François" becomes "Francois"
|
||||||
*/
|
*/
|
||||||
function transliterate(text) {
|
function transliterate(text) {
|
||||||
const extras = {
|
const extras = {
|
||||||
@@ -870,11 +871,11 @@ function transliterate(text) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Aus dem Meeting-Namen einen gültigen Room-Namen ableiten.
|
* Derive a valid room name from the meeting name.
|
||||||
*
|
*
|
||||||
* Beispiel:
|
* Example:
|
||||||
*
|
*
|
||||||
* "Grund Stück Planung" ergibt "grund-stuck-planung"
|
* "Grund Stück Planung" becomes "grund-stuck-planung"
|
||||||
*/
|
*/
|
||||||
function createRoomName(meetingName) {
|
function createRoomName(meetingName) {
|
||||||
return transliterate(meetingName)
|
return transliterate(meetingName)
|
||||||
@@ -954,12 +955,12 @@ const MINUTES_STEP = 15;
|
|||||||
const DEFAULT_DURATION_MINUTES = 30;
|
const DEFAULT_DURATION_MINUTES = 30;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Minuten auf das 15-Minuten-Raster aufrunden.
|
* Round minutes up to the 15-minute grid.
|
||||||
*
|
*
|
||||||
* Beispiel:
|
* Example:
|
||||||
*
|
*
|
||||||
* 14:07 ergibt 14:15
|
* 14:07 becomes 14:15
|
||||||
* 14:50 ergibt 15:00
|
* 14:50 becomes 15:00
|
||||||
*/
|
*/
|
||||||
function roundMinutes(date) {
|
function roundMinutes(date) {
|
||||||
const rounded = new Date(date);
|
const rounded = new Date(date);
|
||||||
@@ -973,11 +974,11 @@ function roundMinutes(date) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Lokale Zeit für datetime-local formatieren.
|
* Format local time for datetime-local.
|
||||||
*
|
*
|
||||||
* Beispiel:
|
* Example:
|
||||||
*
|
*
|
||||||
* 1. Januar 2026, 14:15 ergibt "2026-01-01T14:15"
|
* January 1, 2026, 14:15 becomes "2026-01-01T14:15"
|
||||||
*/
|
*/
|
||||||
function formatLocal(date) {
|
function formatLocal(date) {
|
||||||
const pad = (num) => num.toString().padStart(2, "0");
|
const pad = (num) => num.toString().padStart(2, "0");
|
||||||
@@ -1066,8 +1067,8 @@ function openNextcloudCalendarCreator() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Nextcloud validiert die E-Mail serverseitig und
|
* Nextcloud validates the email server-side and
|
||||||
* bricht sonst mit einer Fehlerseite ab.
|
* aborts with an error page otherwise.
|
||||||
*/
|
*/
|
||||||
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
const emailPattern = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
||||||
|
|
||||||
@@ -1177,17 +1178,17 @@ function createMeeting() {
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Zeitspanne, nach der der "Kopiert!"-Text zum
|
* Time span after which the "Copied!" text returns
|
||||||
* normalen Button-Label zurückkehrt.
|
* to the normal button label.
|
||||||
*/
|
*/
|
||||||
const COPY_RESET_MS = 2000;
|
const COPY_RESET_MS = 2000;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Launch-URL, die das Meeting im Jitsi-Client öffnet.
|
* Launch URL that opens the meeting in the Jitsi client.
|
||||||
*
|
*
|
||||||
* Beispiel:
|
* Example:
|
||||||
*
|
*
|
||||||
* "projekt-kickoff" ergibt
|
* "projekt-kickoff" becomes
|
||||||
* https://meet.bnvb.eu/launch.html?room=projekt-kickoff
|
* https://meet.bnvb.eu/launch.html?room=projekt-kickoff
|
||||||
*/
|
*/
|
||||||
function createLaunchUrl(roomName) {
|
function createLaunchUrl(roomName) {
|
||||||
@@ -1221,7 +1222,7 @@ function createAdhocLink() {
|
|||||||
async function copyAdhocLink() {
|
async function copyAdhocLink() {
|
||||||
const url = adhocLink.href;
|
const url = adhocLink.href;
|
||||||
|
|
||||||
/* Clipboard-API, mit Fallback für ältere Browser */
|
/* Clipboard API, with a fallback for older browsers */
|
||||||
try {
|
try {
|
||||||
await navigator.clipboard.writeText(url);
|
await navigator.clipboard.writeText(url);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
@@ -1233,7 +1234,7 @@ async function copyAdhocLink() {
|
|||||||
document.body.removeChild(input);
|
document.body.removeChild(input);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Kurzes Feedback, dann zurück zum normalen Label */
|
/* Brief feedback, then back to the normal label */
|
||||||
copyAdhocLinkButton.textContent = getTranslation('creator.copiedLabel') || 'Copied!';
|
copyAdhocLinkButton.textContent = getTranslation('creator.copiedLabel') || 'Copied!';
|
||||||
setTimeout(() => {
|
setTimeout(() => {
|
||||||
copyAdhocLinkButton.textContent = getTranslation('creator.copyLinkButton') || 'Copy Link';
|
copyAdhocLinkButton.textContent = getTranslation('creator.copyLinkButton') || 'Copy Link';
|
||||||
@@ -1255,7 +1256,7 @@ function cancelCreateMeeting() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ============================================================
|
/* ============================================================
|
||||||
* INITIALISIERUNG
|
* INITIALIZATION
|
||||||
* ============================================================
|
* ============================================================
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@@ -1263,8 +1264,8 @@ function initialize() {
|
|||||||
const room = getRoom();
|
const room = getRoom();
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Kein room-Parameter: Meldungen ausblenden,
|
* No room parameter: hide the messages,
|
||||||
* nur den Create-Button anzeigen.
|
* only show the Create button.
|
||||||
*/
|
*/
|
||||||
if (room === null) {
|
if (room === null) {
|
||||||
missingRoomTitle.classList.add("hidden");
|
missingRoomTitle.classList.add("hidden");
|
||||||
@@ -1277,8 +1278,8 @@ function initialize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Leerer room-Parameter ("?room="):
|
* Empty room parameter ("?room="):
|
||||||
* "No meeting specified" anzeigen.
|
* show "No meeting specified".
|
||||||
*/
|
*/
|
||||||
if (room === "") {
|
if (room === "") {
|
||||||
missingRoomTitle.classList.remove("hidden");
|
missingRoomTitle.classList.remove("hidden");
|
||||||
@@ -1291,8 +1292,8 @@ function initialize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ungültiger room-Parameter: nur die
|
* Invalid room parameter: only show
|
||||||
* Invalid-Name-Meldung anzeigen.
|
* the invalid-name message.
|
||||||
*/
|
*/
|
||||||
if (!isValidRoom(room)) {
|
if (!isValidRoom(room)) {
|
||||||
missingRoomTitle.classList.add("hidden");
|
missingRoomTitle.classList.add("hidden");
|
||||||
@@ -1306,17 +1307,17 @@ function initialize() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Room anzeigen.
|
* Show the room.
|
||||||
*/
|
*/
|
||||||
roomName.textContent = room;
|
roomName.textContent = room;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Browser-Fallback vorbereiten.
|
* Prepare the browser fallback.
|
||||||
*/
|
*/
|
||||||
browserLink.href = createBrowserUrl(room);
|
browserLink.href = createBrowserUrl(room);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Launcher anzeigen.
|
* Show the launcher.
|
||||||
*/
|
*/
|
||||||
launcher.classList.remove("hidden");
|
launcher.classList.remove("hidden");
|
||||||
|
|
||||||
@@ -1326,7 +1327,7 @@ function initialize() {
|
|||||||
createNewFromLauncherButton.classList.add("hidden");
|
createNewFromLauncherButton.classList.add("hidden");
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Debug-Informationen.
|
* Debug information.
|
||||||
*/
|
*/
|
||||||
console.log(
|
console.log(
|
||||||
"Jitsi Launcher",
|
"Jitsi Launcher",
|
||||||
@@ -1441,7 +1442,7 @@ navToggle.addEventListener(
|
|||||||
);
|
);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Ohne gespeicherte Wahl dem System folgen.
|
* Follow the system if no choice is saved.
|
||||||
*/
|
*/
|
||||||
window
|
window
|
||||||
.matchMedia("(prefers-color-scheme: dark)")
|
.matchMedia("(prefers-color-scheme: dark)")
|
||||||
@@ -1463,8 +1464,8 @@ async function loadConfig() {
|
|||||||
CONFIG = await response.json();
|
CONFIG = await response.json();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
/*
|
/*
|
||||||
* Ohne Datei bleiben Launcher unbrauchbar – Fehler
|
* Without the file the launcher stays unusable –
|
||||||
* melden und mit leerer Konfiguration fortfahren.
|
* report the error and continue with an empty config.
|
||||||
*/
|
*/
|
||||||
console.error("Error loading config:", error);
|
console.error("Error loading config:", error);
|
||||||
}
|
}
|
||||||
@@ -1476,7 +1477,7 @@ async function loadTranslations() {
|
|||||||
TRANSLATIONS = await response.json();
|
TRANSLATIONS = await response.json();
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
/*
|
/*
|
||||||
* Ohne Datei bleibt der englische Text aus dem HTML stehen.
|
* Without the file the English text from the HTML stays.
|
||||||
*/
|
*/
|
||||||
console.error("Error loading translations:", error);
|
console.error("Error loading translations:", error);
|
||||||
}
|
}
|
||||||
@@ -1486,8 +1487,8 @@ async function loadTranslations() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Theme/Logo sofort anwenden, damit nichts aufblinkt –
|
* Apply theme/logo immediately so nothing flickers –
|
||||||
* Text erst nach dem Laden der Übersetzungen.
|
* text only after the translations have loaded.
|
||||||
*/
|
*/
|
||||||
async function start() {
|
async function start() {
|
||||||
applyTheme();
|
applyTheme();
|
||||||
|
|||||||
+2
-2
@@ -31,8 +31,8 @@
|
|||||||
</svg>
|
</svg>
|
||||||
</button>
|
</button>
|
||||||
<div id="navActions" class="nav-actions">
|
<div id="navActions" class="nav-actions">
|
||||||
<a class="button secondary" href="https://www.bnvb-ingenieure.de/impressum" target="_blank" rel="noopener noreferrer" data-i18n="impressum">
|
<a class="button secondary" href="https://www.bnvb-ingenieure.de/impressum" target="_blank" rel="noopener noreferrer" data-i18n="legal_notice">
|
||||||
Impressum
|
Legal Notice
|
||||||
</a>
|
</a>
|
||||||
<a class="button secondary" href="https://git.bnvb.eu/stefan.tollkuehn/jitsi-launch" target="_blank" rel="noopener noreferrer" data-i18n="source">
|
<a class="button secondary" href="https://git.bnvb.eu/stefan.tollkuehn/jitsi-launch" target="_blank" rel="noopener noreferrer" data-i18n="source">
|
||||||
Source
|
Source
|
||||||
|
|||||||
Reference in new issue
Block a user