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:
@@ -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
|
||||||
|
|||||||
@@ -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' }
|
||||||
|
|||||||
@@ -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})\}\}$/)
|
||||||
|
|||||||
@@ -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})\}\}$/)
|
||||||
|
|||||||
Reference in New Issue
Block a user