fix: index.html nicht cachen + unaufgelöste ⟦PHn:wort⟧-Tokens defensiv anzeigen

- nginx: Cache-Control no-cache für index.html — Browser hingen sonst auf
  alten JS-Bundles (gehashte Assets bleiben immutable gecacht)
- Karten: Pipeline-Tokens ⟦PHn:wort⟧ aus der Übersetzung werden als blankes
  Wort gerendert/gesprochen statt roh angezeigt (Datenfix gehört ins Backend)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This commit is contained in:
2026-06-12 21:58:28 +02:00
parent acfd57ee87
commit 8154f08e04
4 changed files with 11 additions and 2 deletions

View File

@@ -4,9 +4,10 @@ server {
root /usr/share/nginx/html; root /usr/share/nginx/html;
index index.html; index index.html;
# SPA fallback # SPA fallback — index.html nie cachen, sonst hängen Browser auf alten Bundles
location / { location / {
try_files $uri $uri/ /index.html; try_files $uri $uri/ /index.html;
add_header Cache-Control "no-cache";
} }
# Cache static assets # Cache static assets

View File

@@ -53,6 +53,8 @@ function SelectionOverlay({ chip }) {
// Sentence format: {{label.w:uuid}} or {{label.o:uuid}} // Sentence format: {{label.w:uuid}} or {{label.o:uuid}}
function resolveSentence(sentence, placeholders, onChipClick, activeId) { function resolveSentence(sentence, placeholders, onChipClick, activeId) {
if (!sentence) return null if (!sentence) return null
// Unaufgelöste Pipeline-Tokens (⟦PHn:wort⟧) defensiv als blankes Wort anzeigen
sentence = sentence.replace(/[⟦〚]PH\d+:([^⟧〛]*)[⟧〛]/g, '$1')
const parts = sentence.split(/(\{\{[^}]+\.[wo]:[0-9a-f-]{36}\}\})/) const parts = sentence.split(/(\{\{[^}]+\.[wo]:[0-9a-f-]{36}\}\})/)
return parts.map((part, i) => { return parts.map((part, i) => {
const m = part.match(/^\{\{([^.]+)\.(w|o):([0-9a-f-]{36})\}\}$/) const m = part.match(/^\{\{([^.]+)\.(w|o):([0-9a-f-]{36})\}\}$/)
@@ -88,7 +90,9 @@ function extractVocab(sentence) {
// Strip placeholders to plain text for TTS // Strip placeholders to plain text for TTS
function toPlainText(sentence) { function toPlainText(sentence) {
if (!sentence) return '' if (!sentence) return ''
return sentence.replace(/\{\{([^.]+)\.[wo]:[0-9a-f-]{36}\}\}/g, '$1') return sentence
.replace(/\{\{([^.]+)\.[wo]:[0-9a-f-]{36}\}\}/g, '$1')
.replace(/[⟦〚]PH\d+:([^⟧〛]*)[⟧〛]/g, '$1')
} }
const LANG_LABELS = { sv: 'Svenska', en: 'English', de: 'Deutsch' } const LANG_LABELS = { sv: 'Svenska', en: 'English', de: 'Deutsch' }

View File

@@ -53,6 +53,8 @@ function SelectionOverlay({ chip }) {
// Sentence format: {{label.w:uuid}} or {{label.o:uuid}} // Sentence format: {{label.w:uuid}} or {{label.o:uuid}}
function resolveSentence(sentence, placeholders, onChipClick, activeId) { function resolveSentence(sentence, placeholders, onChipClick, activeId) {
if (!sentence) return null if (!sentence) return null
// Unaufgelöste Pipeline-Tokens (⟦PHn:wort⟧) defensiv als blankes Wort anzeigen
sentence = sentence.replace(/[⟦〚]PH\d+:([^⟧〛]*)[⟧〛]/g, '$1')
const parts = sentence.split(/(\{\{[^}]+\.[wo]:[0-9a-f-]{36}\}\})/) const parts = sentence.split(/(\{\{[^}]+\.[wo]:[0-9a-f-]{36}\}\})/)
return parts.map((part, i) => { return parts.map((part, i) => {
const m = part.match(/^\{\{([^.]+)\.(w|o):([0-9a-f-]{36})\}\}$/) const m = part.match(/^\{\{([^.]+)\.(w|o):([0-9a-f-]{36})\}\}$/)

View File

@@ -53,6 +53,8 @@ function SelectionOverlay({ chip }) {
// Sentence format: {{label.w:uuid}} or {{label.o:uuid}} // Sentence format: {{label.w:uuid}} or {{label.o:uuid}}
function resolveSentence(sentence, placeholders, onChipClick, activeId) { function resolveSentence(sentence, placeholders, onChipClick, activeId) {
if (!sentence) return null if (!sentence) return null
// Unaufgelöste Pipeline-Tokens (⟦PHn:wort⟧) defensiv als blankes Wort anzeigen
sentence = sentence.replace(/[⟦〚]PH\d+:([^⟧〛]*)[⟧〛]/g, '$1')
const parts = sentence.split(/(\{\{[^}]+\.[wo]:[0-9a-f-]{36}\}\})/) const parts = sentence.split(/(\{\{[^}]+\.[wo]:[0-9a-f-]{36}\}\})/)
return parts.map((part, i) => { return parts.map((part, i) => {
const m = part.match(/^\{\{([^.]+)\.(w|o):([0-9a-f-]{36})\}\}$/) const m = part.match(/^\{\{([^.]+)\.(w|o):([0-9a-f-]{36})\}\}$/)