Internationalization
This commit is contained in:
+77
-77
@@ -141,17 +141,17 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
}
|
||||
const next = highest + 1;
|
||||
if (!Number.isSafeInteger(next)) {
|
||||
throw new TypeError('Für diese lokale Strecke kann keine weitere Streckenpunkt-ID vergeben werden.');
|
||||
throw new TypeError(ns.I18n.t("editor-ui.zu.dieser.strecke.kann.gerade.keine.weitere"));
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
function routeName(route) {
|
||||
return text(route?.name || route?.title || 'Unbenannte Strecke');
|
||||
return text(route?.name || route?.title || ns.I18n.t("editor-ui.unbenannte.strecke"));
|
||||
}
|
||||
|
||||
function poiTitle(poi) {
|
||||
return text(poi?.title || poi?.name || 'Unbenannter Streckenpunkt');
|
||||
return text(poi?.title || poi?.name || ns.I18n.t("editor-ui.station.ohne.namen"));
|
||||
}
|
||||
|
||||
function apiBase() {
|
||||
@@ -184,7 +184,7 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
function setStatus(message, isError = false) {
|
||||
const status = byId(ids.status);
|
||||
if (!status) return;
|
||||
status.textContent = message;
|
||||
status.textContent = isError ? (ns.UserMessages?.error(message) || message) : message;
|
||||
status.hidden = !message;
|
||||
status.dataset.kind = isError ? 'error' : 'notice';
|
||||
}
|
||||
@@ -196,9 +196,9 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
|
||||
function routeDialogTitle() {
|
||||
if (state.currentSource === 'local') {
|
||||
return routeId(state.currentRoute) ? 'Lokale Strecke bearbeiten' : 'Neue lokale Strecke';
|
||||
return routeId(state.currentRoute) ? ns.I18n.t("editor-ui.eigene.strecke.bearbeiten") : ns.I18n.t("editor-ui.neue.strecke");
|
||||
}
|
||||
return 'Veröffentlichte Strecke bearbeiten';
|
||||
return ns.I18n.t("editor-ui.strecke.ansehen");
|
||||
}
|
||||
|
||||
function showListView() {
|
||||
@@ -216,7 +216,7 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
}
|
||||
|
||||
function showPoiView() {
|
||||
setDialogTitle(state.currentPoi ? 'Streckenpunkt bearbeiten' : 'Streckenpunkt hinzufügen');
|
||||
setDialogTitle(state.currentPoi ? ns.I18n.t("editor-ui.station.bearbeiten") : ns.I18n.t("editor-ui.station.hinzufugen"));
|
||||
setHidden(byId(ids.routeListView), true);
|
||||
setHidden(byId(ids.routeDetailView), true);
|
||||
setHidden(byId(ids.poiFormView), false);
|
||||
@@ -264,8 +264,8 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
|
||||
async function handleResponse(response) {
|
||||
if (response.ok) return parseJson(response);
|
||||
const message = await response.text();
|
||||
const error = new Error(message || `HTTP ${response.status}`);
|
||||
const payload = await parseJson(response);
|
||||
const error = new Error(payload.message || ns.I18n.t("editor-ui.die.aktion.konnte.nicht.ausgefuhrt.werden.bitte"));
|
||||
error.status = response.status;
|
||||
throw error;
|
||||
}
|
||||
@@ -354,13 +354,13 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
|
||||
const label = document.createElement('div');
|
||||
appendText(label, 'strong', routeName(route));
|
||||
appendText(label, 'small', routeSource(route) === 'local' ? 'Lokaler Entwurf' : 'Veröffentlichte Strecke');
|
||||
appendText(label, 'small', routeSource(route) === 'local' ? ns.I18n.t("app.eigener.entwurf") : ns.I18n.t("editor-ui.veroffentlichte.strecke"));
|
||||
|
||||
const actions = document.createElement('div');
|
||||
actions.className = classes.iconRow;
|
||||
actions.appendChild(iconButton('Strecke bearbeiten', '✎', 'edit-route'));
|
||||
actions.appendChild(iconButton(ns.I18n.t("editor-ui.strecke.bearbeiten"), '✎', 'edit-route'));
|
||||
if (routeSource(route) === 'local') {
|
||||
actions.appendChild(iconButton('Strecke löschen', '×', 'delete-route', false, true));
|
||||
actions.appendChild(iconButton(ns.I18n.t("editor-ui.strecke.loschen"), '×', 'delete-route', false, true));
|
||||
}
|
||||
item.append(label, actions);
|
||||
return item;
|
||||
@@ -380,13 +380,13 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
const title = poiTitle(poi);
|
||||
const label = document.createElement('div');
|
||||
appendText(label, 'strong', title);
|
||||
appendText(label, 'small', `Streckenpunkt ${index + 1}`);
|
||||
appendText(label, 'small', ns.I18n.t("editor-ui.station", { value1: index + 1 }));
|
||||
const actions = document.createElement('div');
|
||||
actions.className = classes.iconRow;
|
||||
actions.appendChild(iconButton(`${title} nach oben schieben`, '↑', 'move-poi-up', index === 0));
|
||||
actions.appendChild(iconButton(`${title} nach unten schieben`, '↓', 'move-poi-down', index === state.pois.length - 1));
|
||||
actions.appendChild(iconButton(ns.I18n.t("editor.station.up", { value1: title }), '↑', 'move-poi-up', index === 0));
|
||||
actions.appendChild(iconButton(ns.I18n.t("editor.station.down", { value1: title }), '↓', 'move-poi-down', index === state.pois.length - 1));
|
||||
actions.appendChild(iconButton(`${title} bearbeiten`, '✎', 'edit-poi'));
|
||||
actions.appendChild(iconButton(`${title} löschen`, '×', 'delete-poi', false, true));
|
||||
actions.appendChild(iconButton(ns.I18n.t("editor-ui.loschen", { value1: title }), '×', 'delete-poi', false, true));
|
||||
item.append(label, actions);
|
||||
return item;
|
||||
}
|
||||
@@ -409,8 +409,8 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
list.textContent = '';
|
||||
const serverRoutes = state.routes.filter(route => routeSource(route) === 'server');
|
||||
const localRoutes = state.routes.filter(route => routeSource(route) === 'local');
|
||||
renderRouteGroup(list, 'Veröffentlichte Strecken', serverRoutes, 'Keine veröffentlichte Strecke vorhanden.');
|
||||
renderRouteGroup(list, 'Lokale Strecken', localRoutes, 'Noch kein lokaler Entwurf vorhanden.');
|
||||
renderRouteGroup(list, ns.I18n.t("editor-ui.strecken.fur.alle"), serverRoutes, ns.I18n.t("app.hier.gibt.es.noch.keine.strecken.fur"));
|
||||
renderRouteGroup(list, ns.I18n.t("editor-ui.meine.entwurfe"), localRoutes, ns.I18n.t("editor-ui.noch.kein.eigener.entwurf.vorhanden"));
|
||||
}
|
||||
|
||||
function renderPoiList() {
|
||||
@@ -420,7 +420,7 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
if (!state.pois.length) {
|
||||
const item = document.createElement('li');
|
||||
item.className = classes.poiItem;
|
||||
appendText(item, 'span', 'Noch keine Streckenpunkte angelegt.');
|
||||
appendText(item, 'span', ns.I18n.t("editor-ui.noch.keine.stationen.angelegt"));
|
||||
list.appendChild(item);
|
||||
return;
|
||||
}
|
||||
@@ -437,7 +437,7 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
}
|
||||
|
||||
async function loadRoutes() {
|
||||
setStatus('Strecken werden geladen …');
|
||||
setStatus(ns.I18n.t("editor-ui.strecken.werden.geladen"));
|
||||
const payload = await readJson('/routes?activatedOnly=true');
|
||||
const serverRoutes = routeArray(payload).map(route => ({ ...route, _source: 'server' }));
|
||||
let localRoutes = [];
|
||||
@@ -496,7 +496,7 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
|
||||
function fillRouteForm(route) {
|
||||
byId(ids.routeId).value = routeId(route);
|
||||
byId(ids.routeName).value = routeName(route) === 'Unbenannte Strecke' ? '' : routeName(route);
|
||||
byId(ids.routeName).value = routeName(route) === ns.I18n.t("editor-ui.unbenannte.strecke") ? '' : routeName(route);
|
||||
byId(ids.routeDescription).value = text(route?.description);
|
||||
byId(ids.routeGpx).value = '';
|
||||
setHidden(byId(ids.routeGpxGroup), state.currentSource !== 'server');
|
||||
@@ -506,16 +506,16 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
const uploaded = Boolean(route?.serverRouteId);
|
||||
setHidden(uploadButton, false);
|
||||
setDisabled(uploadButton, uploaded);
|
||||
if (uploadButton) uploadButton.textContent = uploaded ? 'Bereits übertragen' : 'An Server übertragen';
|
||||
if (uploadButton) uploadButton.textContent = uploaded ? ns.I18n.t("editor-ui.schon.zur.prufung.gesendet") : ns.I18n.t("editor-ui.zur.prufung.senden");
|
||||
byId(ids.routeActivated).textContent = uploaded
|
||||
? `Lokaler Entwurf. Bereits als unveröffentlichte Server-Strecke ${route.serverRouteId} zur Prüfung übertragen.`
|
||||
: 'Lokaler Entwurf: GPX, Texte und Medien bleiben im Browser, bis „An Server übertragen“ gewählt wird.';
|
||||
? ns.I18n.t("editor-ui.diese.strecke.wurde.zur.prufung.gesendet.andere")
|
||||
: ns.I18n.t("editor-ui.dieser.entwurf.bleibt.auf.deinem.gerat.mit");
|
||||
} else {
|
||||
setHidden(uploadButton, true);
|
||||
setDisabled(uploadButton, true);
|
||||
byId(ids.routeActivated).textContent = route?.activatedAt || route?.activated_at
|
||||
? `Veröffentlicht am ${route.activatedAt || route.activated_at}. Der Editor verändert die Freigabe nicht.`
|
||||
: 'Server-Strecke ohne Freigabedatum. Der Editor verändert activated_at nicht.';
|
||||
? ns.I18n.t("editor-ui.diese.strecke.ist.fur.alle.freigegeben.und")
|
||||
: ns.I18n.t("editor-ui.diese.strecke.wurde.noch.nicht.fur.alle");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -559,7 +559,7 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
select.dataset.mediaKey = key;
|
||||
select.type = 'button';
|
||||
select.setAttribute('aria-expanded', String(state.selectedMediaKey === key));
|
||||
select.setAttribute('aria-label', `${label}: Entfernen-Schaltfläche ${state.selectedMediaKey === key ? 'ausblenden' : 'anzeigen'}`);
|
||||
select.setAttribute('aria-label', ns.I18n.t("editor-ui.knopf.zum.entfernen", { value1: label, value2: state.selectedMediaKey === key ? 'ausblenden' : 'anzeigen' }));
|
||||
|
||||
if (kind === 'image' && previewUrl) {
|
||||
const image = document.createElement('img');
|
||||
@@ -603,7 +603,7 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
preview.appendChild(mediaPreviewCard({
|
||||
key: 'existing-audio',
|
||||
kind: 'audio',
|
||||
label: poi?.audio?.name || 'Audioaufnahme',
|
||||
label: poi?.audio?.name || 'Tonaufnahme',
|
||||
source: 'existing'
|
||||
}));
|
||||
}
|
||||
@@ -612,7 +612,7 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
preview.appendChild(mediaPreviewCard({
|
||||
key: 'pending-audio',
|
||||
kind: 'audio',
|
||||
label: state.pendingAudioFile.name || 'Neue Audioaufnahme',
|
||||
label: state.pendingAudioFile.name || ns.I18n.t("editor-ui.neue.tonaufnahme"),
|
||||
source: 'pending'
|
||||
}));
|
||||
}
|
||||
@@ -622,7 +622,7 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
preview.appendChild(mediaPreviewCard({
|
||||
key: `existing-image-${image.id ?? index}`,
|
||||
kind: 'image',
|
||||
label: image.name || image.caption || `Bild ${index + 1}`,
|
||||
label: image.name || image.caption || ns.I18n.t("editor-ui.bild", { value1: index + 1 }),
|
||||
mediaId: image.id ?? '',
|
||||
mediaIndex: index,
|
||||
previewUrl: imagePreviewUrl(image),
|
||||
@@ -634,7 +634,7 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
preview.appendChild(mediaPreviewCard({
|
||||
key: pending.key,
|
||||
kind: 'image',
|
||||
label: pending.file?.name || `Neues Bild ${index + 1}`,
|
||||
label: pending.file?.name || ns.I18n.t("editor-ui.neues.bild", { value1: index + 1 }),
|
||||
mediaIndex: index,
|
||||
previewUrl: pending.previewUrl || null,
|
||||
source: 'pending'
|
||||
@@ -651,12 +651,12 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
const imageCount = existingImages + state.pendingImages.length;
|
||||
const parts = [];
|
||||
|
||||
if (audioCount) parts.push(`${audioCount} Audio${audioCount === 1 ? 'aufnahme' : 'aufnahmen'}`);
|
||||
if (imageCount) parts.push(`${imageCount} Bild${imageCount === 1 ? '' : 'er'}`);
|
||||
if (audioCount) parts.push(ns.I18n.t('media.audio.count', { count: audioCount }));
|
||||
if (imageCount) parts.push(ns.I18n.t('media.image.count', { count: imageCount }));
|
||||
|
||||
status.textContent = parts.length
|
||||
? `${parts.join(' · ')}. Vorschau antippen, um die Entfernen-Schaltfläche einzublenden.`
|
||||
: 'Noch keine Medien vorhanden.';
|
||||
? ns.I18n.t("editor-ui.tippe.auf.ein.bild.oder.eine.tonaufnahme", { value1: parts.join(' · ') })
|
||||
: ns.I18n.t("editor-ui.noch.keine.bilder.oder.tonaufnahmen.vorhanden");
|
||||
}
|
||||
|
||||
function openFilePicker(inputId) {
|
||||
@@ -668,12 +668,12 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
if (kind === 'audio') {
|
||||
return {
|
||||
multiple: false,
|
||||
types: [{ description: 'Audio', accept: { 'audio/*': ['.mp3', '.m4a', '.wav', '.ogg', '.webm'] } }]
|
||||
types: [{ description: ns.I18n.t("editor-ui.tonaufnahmen"), accept: { 'audio/*': ['.mp3', '.m4a', '.wav', '.ogg', '.webm'] } }]
|
||||
};
|
||||
}
|
||||
return {
|
||||
multiple: true,
|
||||
types: [{ description: 'Bilder', accept: { 'image/*': ['.jpg', '.jpeg', '.png', '.webp'] } }]
|
||||
types: [{ description: ns.I18n.t("editor-ui.bilder"), accept: { 'image/*': ['.jpg', '.jpeg', '.png', '.webp'] } }]
|
||||
};
|
||||
}
|
||||
|
||||
@@ -721,7 +721,7 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
function fillPoiForm(poi) {
|
||||
resetPendingMedia();
|
||||
byId(ids.poiId).value = poiId(poi);
|
||||
byId(ids.poiTitle).value = poiTitle(poi) === 'Unbenannter Streckenpunkt' ? '' : poiTitle(poi);
|
||||
byId(ids.poiTitle).value = poiTitle(poi) === ns.I18n.t("editor-ui.station.ohne.namen") ? '' : poiTitle(poi);
|
||||
byId(ids.poiDescription).value = text(poi?.description || poi?.text);
|
||||
byId(ids.poiLat).value = text(poi?.lat ?? poi?.latitude);
|
||||
byId(ids.poiLon).value = text(poi?.lon ?? poi?.longitude);
|
||||
@@ -759,12 +759,12 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
async function loadRoute(route) {
|
||||
const id = routeId(route);
|
||||
if (!id) return;
|
||||
setStatus('Streckendetails werden geladen …');
|
||||
setStatus(ns.I18n.t("editor.route.loading"));
|
||||
state.currentSource = routeSource(route);
|
||||
|
||||
if (state.currentSource === 'local') {
|
||||
const routePackage = await ns.LocalRoutes.getWithMedia(id, { requestPermission: true });
|
||||
if (!routePackage) throw new Error('Der lokale Entwurf wurde nicht gefunden.');
|
||||
if (!routePackage) throw new Error(ns.I18n.t("editor-ui.dein.entwurf.wurde.nicht.gefunden"));
|
||||
state.currentRoute = {
|
||||
...routePackage.route,
|
||||
id: routePackage.id,
|
||||
@@ -792,7 +792,7 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
id: '',
|
||||
name: '',
|
||||
description: '',
|
||||
gpx: ns.LocalRoutes.emptyGpx('Neue Strecke'),
|
||||
gpx: ns.LocalRoutes.emptyGpx(ns.I18n.t("editor-ui.neue.strecke")),
|
||||
_source: 'local'
|
||||
};
|
||||
state.currentPoi = null;
|
||||
@@ -800,7 +800,7 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
fillRouteForm(state.currentRoute);
|
||||
renderPoiList();
|
||||
showRouteView();
|
||||
setStatus('Neue Strecke wird als lokaler GPX-/JSON-Entwurf angelegt.');
|
||||
setStatus(ns.I18n.t("editor-ui.deine.neue.strecke.bleibt.zuerst.auf.diesem"));
|
||||
}
|
||||
|
||||
function formDataFromRoute(values) {
|
||||
@@ -838,12 +838,12 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
state.pois = saved.pois;
|
||||
await loadRoutes();
|
||||
await loadRoute({ id: saved.id, _source: 'local' });
|
||||
setStatus('Speichern erfolgreich.');
|
||||
setStatus(ns.I18n.t("editor-ui.gespeichert"));
|
||||
}
|
||||
|
||||
async function saveServerRoute(values) {
|
||||
const id = routeId(state.currentRoute);
|
||||
if (!id) throw new Error('Neue Strecken werden ausschließlich lokal angelegt.');
|
||||
if (!id) throw new Error(ns.I18n.t("editor-ui.lege.eine.neue.strecke.zuerst.auf.diesem"));
|
||||
const file = byId(ids.routeGpx)?.files?.[0];
|
||||
const path = `/routes/${encodeURIComponent(id)}`;
|
||||
const payload = file
|
||||
@@ -853,12 +853,12 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
state.currentRoute = { ...saved, _source: 'server' };
|
||||
await loadRoutes();
|
||||
await loadRoute({ id, _source: 'server' });
|
||||
setStatus('Speichern erfolgreich.');
|
||||
setStatus(ns.I18n.t("editor-ui.gespeichert"));
|
||||
}
|
||||
|
||||
async function saveRoute() {
|
||||
const values = routeFromForm();
|
||||
if (!values.name) throw new Error('Der Name der Strecke ist erforderlich.');
|
||||
if (!values.name) throw new Error(ns.I18n.t("editor-ui.gib.deiner.strecke.einen.namen"));
|
||||
if (state.currentSource === 'server') await saveServerRoute(values);
|
||||
else await saveLocalRoute(values);
|
||||
}
|
||||
@@ -877,7 +877,7 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
|
||||
function localRouteUploadForm(routePackage) {
|
||||
const data = new FormData();
|
||||
data.append('name', routePackage.route?.name || 'Unbenannte Strecke');
|
||||
data.append('name', routePackage.route?.name || ns.I18n.t("editor-ui.unbenannte.strecke"));
|
||||
data.append('description', routePackage.route?.description || '');
|
||||
const uploadGpx = ns.LocalRoutes.gpxForUpload(routePackage);
|
||||
const gpx = new Blob([uploadGpx], { type: 'application/gpx+xml' });
|
||||
@@ -888,7 +888,7 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
async function storedMediaBlob(media) {
|
||||
const blob = await ns.LocalRoutes.mediaBlob(media, { requestPermission: true });
|
||||
if (!blob) {
|
||||
throw new Error(`Die Mediendatei ${media?.name || ''} konnte nicht für den Upload vorbereitet werden.`.trim());
|
||||
throw new Error(ns.I18n.t("editor-ui.die.datei.konnte.nicht.gesendet.werden.bitte", { value1: media?.name || '' }).trim());
|
||||
}
|
||||
return blob;
|
||||
}
|
||||
@@ -918,12 +918,12 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
const payload = await sendForm('/routes', 'POST', localRouteUploadForm(routePackage));
|
||||
const serverRoute = payload.route || payload;
|
||||
createdRouteId = routeId(serverRoute);
|
||||
if (!createdRouteId) throw new Error('Der Server hat keine Strecken-ID für den Upload zurückgegeben.');
|
||||
if (!createdRouteId) throw new Error(ns.I18n.t("editor-ui.die.strecke.konnte.nicht.gesendet.werden.bitte"));
|
||||
|
||||
const orderedPois = [...(routePackage.pois || [])]
|
||||
.sort((left, right) => Number(left.sequence) - Number(right.sequence));
|
||||
for (const [index, poi] of orderedPois.entries()) {
|
||||
const poiTitle = poi.title || `Streckenpunkt ${index + 1}`;
|
||||
const poiTitle = poi.title || ns.I18n.t("editor-ui.station", { value1: index + 1 });
|
||||
const poiPayload = await sendJson(`/routes/${encodeURIComponent(createdRouteId)}/pois`, 'POST', {
|
||||
description: poi.description || '',
|
||||
lat: poi.lat,
|
||||
@@ -934,7 +934,7 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
});
|
||||
const serverPoi = poiPayload.poi || poiPayload;
|
||||
const serverPoiId = poiId(serverPoi);
|
||||
if (!serverPoiId) throw new Error(`Für ${poiTitle} wurde keine Server-ID zurückgegeben.`);
|
||||
if (!serverPoiId) throw new Error(ns.I18n.t("editor-ui.die.station.konnte.nicht.gesendet.werden.bitte", { value1: poiTitle }));
|
||||
await uploadLocalPoiMedia(createdRouteId, serverPoiId, poi);
|
||||
}
|
||||
return createdRouteId;
|
||||
@@ -951,11 +951,11 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
}
|
||||
|
||||
async function uploadLocalRoute() {
|
||||
if (state.currentSource !== 'local') throw new Error('Nur lokale Strecken können hochgeladen werden.');
|
||||
if (state.currentSource !== 'local') throw new Error(ns.I18n.t("editor-ui.du.kannst.nur.deine.eigenen.entwurfe.zur"));
|
||||
const values = routeFromForm();
|
||||
if (!values.name) throw new Error('Der Name der Strecke ist erforderlich.');
|
||||
if (!values.name) throw new Error(ns.I18n.t("editor-ui.gib.deiner.strecke.einen.namen"));
|
||||
if (state.currentRoute?.serverRouteId) {
|
||||
setStatus('Diese Strecke wurde bereits an den Server übertragen.');
|
||||
setStatus(ns.I18n.t("editor-ui.diese.strecke.wurde.schon.zur.prufung.gesendet"));
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -963,10 +963,10 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
setDisabled(uploadButton, true);
|
||||
try {
|
||||
await saveLocalRoute(values);
|
||||
setStatus('Übertragung läuft …');
|
||||
setStatus(ns.I18n.t("editor-ui.deine.strecke.wird.gesendet"));
|
||||
const localId = routeId(state.currentRoute);
|
||||
const routePackage = ns.LocalRoutes.get(localId);
|
||||
if (!routePackage) throw new Error('Der lokale Streckenentwurf wurde nicht gefunden.');
|
||||
if (!routePackage) throw new Error(ns.I18n.t("editor-ui.dein.entwurf.wurde.nicht.gefunden"));
|
||||
|
||||
const serverRouteId = await createServerRouteFromLocal(routePackage);
|
||||
const uploadedAt = new Date().toISOString();
|
||||
@@ -982,7 +982,7 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
state.pois = saved.pois;
|
||||
fillRouteForm(state.currentRoute);
|
||||
await loadRoutes();
|
||||
setStatus('Upload erfolgreich.');
|
||||
setStatus(ns.I18n.t("editor-ui.zur.prufung.gesendet"));
|
||||
} finally {
|
||||
if (!state.currentRoute?.serverRouteId) setDisabled(uploadButton, false);
|
||||
}
|
||||
@@ -997,7 +997,7 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
const lat = Number(position?.lat);
|
||||
const lon = Number(position?.lon);
|
||||
if (!Number.isFinite(lat) || !Number.isFinite(lon)) {
|
||||
setStatus('Für einen neuen Streckenpunkt muss zuerst eine aktuelle GPS-Position verfügbar sein.', true);
|
||||
setStatus(ns.I18n.t("editor-ui.fur.eine.neue.station.brauchen.wir.deinen"), true);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1010,20 +1010,20 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
lon,
|
||||
triggerRadiusM: Number.isFinite(accuracy) && accuracy > 0 ? accuracy : 25
|
||||
});
|
||||
byId(ids.poiFormTitle).textContent = 'Streckenpunkt hinzufügen';
|
||||
byId(ids.poiFormTitle).textContent = ns.I18n.t("editor-ui.station.hinzufugen");
|
||||
showPoiView();
|
||||
}
|
||||
|
||||
function editPoi(poi) {
|
||||
state.currentPoi = poi;
|
||||
fillPoiForm(poi);
|
||||
byId(ids.poiFormTitle).textContent = 'Streckenpunkt bearbeiten';
|
||||
byId(ids.poiFormTitle).textContent = ns.I18n.t("editor-ui.station.bearbeiten");
|
||||
showPoiView();
|
||||
}
|
||||
|
||||
async function mediaFromLocalForm(existingPoi, poiIdentifier) {
|
||||
const routeIdentifier = routeId(state.currentRoute);
|
||||
if (!routeIdentifier) throw new Error('Speichere zuerst die Strecke.');
|
||||
if (!routeIdentifier) throw new Error(ns.I18n.t("editor-ui.speichere.zuerst.die.strecke"));
|
||||
|
||||
const storedNow = [];
|
||||
const replacedAfterSave = [];
|
||||
@@ -1063,7 +1063,7 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
|
||||
async function persistLocalCurrentRoute() {
|
||||
const id = routeId(state.currentRoute);
|
||||
if (!id) throw new Error('Speichere zuerst die Strecke.');
|
||||
if (!id) throw new Error(ns.I18n.t("editor-ui.speichere.zuerst.die.strecke"));
|
||||
const currentPoiId = poiId(state.currentPoi);
|
||||
const saved = ns.LocalRoutes.save({
|
||||
id,
|
||||
@@ -1082,7 +1082,7 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
|
||||
async function saveLocalPoi(values) {
|
||||
if (!Number.isFinite(values.lat) || !Number.isFinite(values.lon)) {
|
||||
throw new TypeError('Für einen Streckenpunkt sind gültige Breiten- und Längengrade erforderlich.');
|
||||
throw new TypeError(ns.I18n.t("editor-ui.der.ort.dieser.station.fehlt.erlaube.deinen"));
|
||||
}
|
||||
const currentId = numericPoiId(byId(ids.poiId).value);
|
||||
const identifier = currentId ?? nextLocalPoiId();
|
||||
@@ -1109,7 +1109,7 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
}
|
||||
await Promise.allSettled(media.replacedAfterSave.map(ns.LocalRoutes.removeMedia));
|
||||
resetPendingMedia();
|
||||
setStatus('Streckenpunkt und zugehörige Mediendaten lokal gespeichert.');
|
||||
setStatus(ns.I18n.t("editor-ui.station.mit.bildern.und.ton.auf.diesem"));
|
||||
await loadRoute({ id: routeId(state.currentRoute), _source: 'local' });
|
||||
}
|
||||
|
||||
@@ -1132,7 +1132,7 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
|
||||
async function saveServerPoi(values) {
|
||||
const currentRouteId = routeId(state.currentRoute);
|
||||
if (!currentRouteId) throw new Error('Speichere zuerst die Strecke.');
|
||||
if (!currentRouteId) throw new Error(ns.I18n.t("editor-ui.speichere.zuerst.die.strecke"));
|
||||
const currentPoiId = byId(ids.poiId).value;
|
||||
const path = currentPoiId
|
||||
? `/routes/${encodeURIComponent(currentRouteId)}/pois/${encodeURIComponent(currentPoiId)}`
|
||||
@@ -1142,13 +1142,13 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
const saved = payload.poi || payload;
|
||||
const savedPoiId = poiId(saved) || currentPoiId;
|
||||
if (savedPoiId) await uploadPoiMedia(currentRouteId, savedPoiId);
|
||||
setStatus('Streckenpunkt gespeichert.');
|
||||
setStatus(ns.I18n.t("editor-ui.station.gespeichert"));
|
||||
await loadRoute({ id: currentRouteId, _source: 'server' });
|
||||
}
|
||||
|
||||
async function savePoi() {
|
||||
const values = poiFromForm();
|
||||
if (!values.title) throw new Error('Der Titel des Streckenpunkts ist erforderlich.');
|
||||
if (!values.title) throw new Error(ns.I18n.t("editor-ui.gib.deiner.station.einen.namen"));
|
||||
if (state.currentSource === 'local') await saveLocalPoi(values);
|
||||
else await saveServerPoi(values);
|
||||
}
|
||||
@@ -1196,13 +1196,13 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
state.selectedMediaKey = null;
|
||||
renderPoiMediaPreview();
|
||||
updatePoiMediaStatus();
|
||||
setStatus(kind === 'audio' ? 'Audioaufnahme entfernt.' : 'Bild entfernt.');
|
||||
setStatus(kind === 'audio' ? ns.I18n.t("editor.audio.removed") : ns.I18n.t("editor-ui.bild.entfernt"));
|
||||
}
|
||||
|
||||
async function removeExistingServerMedia(kind, mediaId) {
|
||||
const currentRouteId = routeId(state.currentRoute);
|
||||
const currentPoiId = poiId(state.currentPoi);
|
||||
if (!currentRouteId || !currentPoiId) throw new Error('Der Streckenpunkt ist noch nicht gespeichert.');
|
||||
if (!currentRouteId || !currentPoiId) throw new Error(ns.I18n.t("editor-ui.die.station.ist.noch.nicht.gespeichert"));
|
||||
const basePath = `/routes/${encodeURIComponent(currentRouteId)}/pois/${encodeURIComponent(currentPoiId)}`;
|
||||
const updated = { ...state.currentPoi };
|
||||
|
||||
@@ -1212,7 +1212,7 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
updated.audioUrl = null;
|
||||
updated.audio_path = null;
|
||||
} else {
|
||||
if (!mediaId) throw new Error('Das Bild besitzt keine Server-ID und kann nicht entfernt werden.');
|
||||
if (!mediaId) throw new Error(ns.I18n.t("editor-ui.das.bild.konnte.nicht.entfernt.werden.lade"));
|
||||
await sendDelete(`${basePath}/pictures/${encodeURIComponent(mediaId)}`);
|
||||
updated.images = (state.currentPoi.images || []).filter(image => text(image.id) !== text(mediaId));
|
||||
}
|
||||
@@ -1221,7 +1221,7 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
state.selectedMediaKey = null;
|
||||
renderPoiMediaPreview();
|
||||
updatePoiMediaStatus();
|
||||
setStatus(kind === 'audio' ? 'Audioaufnahme entfernt.' : 'Bild entfernt.');
|
||||
setStatus(kind === 'audio' ? ns.I18n.t("editor.audio.removed") : ns.I18n.t("editor-ui.bild.entfernt"));
|
||||
}
|
||||
|
||||
async function removeMedia(control) {
|
||||
@@ -1266,13 +1266,13 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
await Promise.allSettled(removedMedia.map(ns.LocalRoutes.removeMedia));
|
||||
renderPoiList();
|
||||
showRouteView();
|
||||
setStatus('Streckenpunkt entfernt und lokale Strecke aktualisiert.');
|
||||
setStatus(ns.I18n.t("editor-ui.station.entfernt.deine.strecke.wurde.gespeichert"));
|
||||
return;
|
||||
}
|
||||
|
||||
await sendDelete(`/routes/${encodeURIComponent(currentRouteId)}/pois/${encodeURIComponent(currentPoiId)}`);
|
||||
await loadRoute({ id: currentRouteId, _source: 'server' });
|
||||
setStatus('Streckenpunkt entfernt.');
|
||||
setStatus(ns.I18n.t("editor-ui.station.entfernt"));
|
||||
}
|
||||
|
||||
function reorderPois(index, offset) {
|
||||
@@ -1295,7 +1295,7 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
if (!currentRouteId) return;
|
||||
if (state.currentSource === 'local') {
|
||||
await persistLocalCurrentRoute();
|
||||
setStatus('Lokale Streckenpunkt-Reihenfolge gespeichert.');
|
||||
setStatus(ns.I18n.t("editor-ui.reihenfolge.der.stationen.gespeichert"));
|
||||
return;
|
||||
}
|
||||
const jobs = state.pois.map((poi, index) => {
|
||||
@@ -1305,7 +1305,7 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
return sendJson(path, 'PUT', { ...poi, sequence: index, sortOrder: index });
|
||||
}).filter(Boolean);
|
||||
await Promise.all(jobs);
|
||||
setStatus('Reihenfolge gespeichert.');
|
||||
setStatus(ns.I18n.t("editor.order.saved"));
|
||||
}
|
||||
|
||||
function routeForItem(target) {
|
||||
@@ -1340,7 +1340,7 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
|
||||
await loadRoutes();
|
||||
showListView();
|
||||
setStatus('Strecke gelöscht.');
|
||||
setStatus(ns.I18n.t("editor-ui.strecke.geloscht"));
|
||||
}
|
||||
|
||||
async function routeListAction(event) {
|
||||
@@ -1387,7 +1387,7 @@ globalThis.Wegwichtel = globalThis.Wegwichtel || {};
|
||||
await ns.StorageUsage?.refresh();
|
||||
} catch (error) {
|
||||
ns.StorageUsage?.reportError(error);
|
||||
setStatus(error.message || 'Die Aktion konnte nicht ausgeführt werden.', true);
|
||||
setStatus(ns.UserMessages?.error(error) || ns.I18n.t("editor-ui.das.hat.leider.nicht.geklappt.bitte.versuche"), true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user