The fifth prose-content branch, and it was broken before anyone translated it
exp-shepherd swept all of plugin-designs and library on main for branches on a
user-visible string's CONTENT and found a FIFTH instance in my file that my own
fix had missed:
copyFlash.value = ok ? 'Copied!' : 'Copy failed — press Ctrl/Cmd-C'
setTimeout(() => { if (copyFlash.value.startsWith('Copied')) copyFlash.value = '' }, 1800)
★ THAT GUARD ONLY MATCHED THE SUCCESS BRANCH. "Copy failed" NEVER CLEARED — in
English, today, before any of this was translated. A pre-existing bug that the
prose fix alone would have widened to both branches in ten languages. It is
rendered at :2649, so it is genuinely user-visible.
WHY I MISSED IT, which is the part worth keeping: I grepped
`status.value.startsWith` — the exact shape I already knew — and found four.
exp-shepherd grepped for the PATTERN CLASS across the whole tree and found the
ternary form. I searched for the instance; they searched for the property. Same
distinction that has cost me three wrong conclusions today.
Both strings now come from messages.* in eleven locales, and flashStatus is
generalised to flashRef(target, text, ms) so the identity-clear works for any
transient ref rather than only `status`. flashStatus stays as a thin alias, so
the four existing call sites are untouched.
VERIFIED: zero LIVE prose-content branches remain anywhere in my plugin — the two
grep hits left are my own comments describing the removed code.
check:i18n-parity PASS (0 debt), check:i18n-never-translated PASS with both new
keys 11/11 distinct and adding nothing to the allowlist.
BUNDLE=my-upg-100-list vite build clean.
exp-shepherd confirms upg-neighbor, pplr and country-posters have no such guards,
so this class is now closed across the tree rather than only in my file.
This commit is contained in:
parent
aaf0a336dc
commit
5747c2ef88
13 changed files with 81 additions and 54 deletions
|
|
@ -12,5 +12,7 @@
|
|||
"selectionPacketFailed": "فشل إنشاء كُتيّب التحديد: {reason}",
|
||||
"posterOneTerritory": "الملصق يطبع منطقة واحدة في كل مرة — {count} محددة.",
|
||||
"selectionPosterFailed": "فشل إنشاء ملصق التحديد: {reason}",
|
||||
"mapUnavailable": "الخريطة غير متاحة"
|
||||
"mapUnavailable": "الخريطة غير متاحة",
|
||||
"copied": "تم النسخ!",
|
||||
"copyFailed": "فشل النسخ — اضغط Ctrl/Cmd-C"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,5 +12,7 @@
|
|||
"selectionPacketFailed": "Heft der Auswahl fehlgeschlagen: {reason}",
|
||||
"posterOneTerritory": "Das Plakat druckt ein Gebiet auf einmal — {count} ausgewählt.",
|
||||
"selectionPosterFailed": "Plakat der Auswahl fehlgeschlagen: {reason}",
|
||||
"mapUnavailable": "Karte nicht verfügbar"
|
||||
"mapUnavailable": "Karte nicht verfügbar",
|
||||
"copied": "Kopiert!",
|
||||
"copyFailed": "Kopieren fehlgeschlagen — Strg/Cmd-C drücken"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,5 +12,7 @@
|
|||
"selectionPacketFailed": "Selection packet failed: {reason}",
|
||||
"posterOneTerritory": "Poster prints one territory at a time — {count} selected.",
|
||||
"selectionPosterFailed": "Selection poster failed: {reason}",
|
||||
"mapUnavailable": "Map unavailable"
|
||||
"mapUnavailable": "Map unavailable",
|
||||
"copied": "Copied!",
|
||||
"copyFailed": "Copy failed — press Ctrl/Cmd-C"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,5 +12,7 @@
|
|||
"selectionPacketFailed": "Error al generar el cuadernillo de la selección: {reason}",
|
||||
"posterOneTerritory": "El cartel imprime un territorio a la vez: {count} seleccionados.",
|
||||
"selectionPosterFailed": "Error al generar el cartel de la selección: {reason}",
|
||||
"mapUnavailable": "Mapa no disponible"
|
||||
"mapUnavailable": "Mapa no disponible",
|
||||
"copied": "¡Copiado!",
|
||||
"copyFailed": "Error al copiar: pulsa Ctrl/Cmd-C"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,5 +12,7 @@
|
|||
"selectionPacketFailed": "Échec du livret de la sélection : {reason}",
|
||||
"posterOneTerritory": "L’affiche imprime un territoire à la fois — {count} sélectionnés.",
|
||||
"selectionPosterFailed": "Échec de l’affiche de la sélection : {reason}",
|
||||
"mapUnavailable": "Carte indisponible"
|
||||
"mapUnavailable": "Carte indisponible",
|
||||
"copied": "Copié !",
|
||||
"copyFailed": "Échec de la copie — appuyez sur Ctrl/Cmd-C"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,5 +12,7 @@
|
|||
"selectionPacketFailed": "चयन की पुस्तिका विफल: {reason}",
|
||||
"posterOneTerritory": "पोस्टर एक समय में एक क्षेत्र छापता है — {count} चयनित।",
|
||||
"selectionPosterFailed": "चयन का पोस्टर विफल: {reason}",
|
||||
"mapUnavailable": "मानचित्र अनुपलब्ध"
|
||||
"mapUnavailable": "मानचित्र अनुपलब्ध",
|
||||
"copied": "कॉपी हो गया!",
|
||||
"copyFailed": "कॉपी विफल — Ctrl/Cmd-C दबाएँ"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,5 +12,7 @@
|
|||
"selectionPacketFailed": "Libretto della selezione non riuscito: {reason}",
|
||||
"posterOneTerritory": "Il manifesto stampa un territorio alla volta — {count} selezionati.",
|
||||
"selectionPosterFailed": "Manifesto della selezione non riuscito: {reason}",
|
||||
"mapUnavailable": "Mappa non disponibile"
|
||||
"mapUnavailable": "Mappa non disponibile",
|
||||
"copied": "Copiato!",
|
||||
"copyFailed": "Copia non riuscita — premi Ctrl/Cmd-C"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,5 +12,7 @@
|
|||
"selectionPacketFailed": "Falha ao gerar o caderno da seleção: {reason}",
|
||||
"posterOneTerritory": "O cartaz imprime um território de cada vez — {count} selecionados.",
|
||||
"selectionPosterFailed": "Falha ao gerar o cartaz da seleção: {reason}",
|
||||
"mapUnavailable": "Mapa indisponível"
|
||||
"mapUnavailable": "Mapa indisponível",
|
||||
"copied": "Copiado!",
|
||||
"copyFailed": "Falha ao copiar — pressione Ctrl/Cmd-C"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,5 +12,7 @@
|
|||
"selectionPacketFailed": "Broșura selecției a eșuat: {reason}",
|
||||
"posterOneTerritory": "Afișul tipărește un teritoriu pe rând — {count} selectate.",
|
||||
"selectionPosterFailed": "Afișul selecției a eșuat: {reason}",
|
||||
"mapUnavailable": "Harta indisponibilă"
|
||||
"mapUnavailable": "Harta indisponibilă",
|
||||
"copied": "Copiat!",
|
||||
"copyFailed": "Copierea a eșuat — apasă Ctrl/Cmd-C"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,5 +12,7 @@
|
|||
"selectionPacketFailed": "Не удалось создать буклет выбора: {reason}",
|
||||
"posterOneTerritory": "Плакат печатает по одной территории — выбрано {count}.",
|
||||
"selectionPosterFailed": "Не удалось создать плакат выбора: {reason}",
|
||||
"mapUnavailable": "Карта недоступна"
|
||||
"mapUnavailable": "Карта недоступна",
|
||||
"copied": "Скопировано!",
|
||||
"copyFailed": "Не удалось скопировать — нажмите Ctrl/Cmd-C"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -12,5 +12,7 @@
|
|||
"selectionPacketFailed": "所选内容的祷告册生成失败:{reason}",
|
||||
"posterOneTerritory": "海报一次只能打印一个区域——已选 {count} 个。",
|
||||
"selectionPosterFailed": "所选内容的海报生成失败:{reason}",
|
||||
"mapUnavailable": "地图不可用"
|
||||
"mapUnavailable": "地图不可用",
|
||||
"copied": "已复制!",
|
||||
"copyFailed": "复制失败——请按 Ctrl/Cmd-C"
|
||||
}
|
||||
|
|
|
|||
|
|
@ -808,8 +808,12 @@ async function copySelection() {
|
|||
} catch (err) {
|
||||
ok = legacyCopy(text) // secure-context / permission failure → fallback
|
||||
}
|
||||
copyFlash.value = ok ? 'Copied!' : 'Copy failed — press Ctrl/Cmd-C'
|
||||
setTimeout(() => { if (copyFlash.value.startsWith('Copied')) copyFlash.value = '' }, 1800)
|
||||
// ⚠ THE OLD GUARD ONLY MATCHED THE SUCCESS BRANCH — `startsWith('Copied')` — so "Copy failed" NEVER
|
||||
// CLEARED, in English, before any of this was translated. A pre-existing bug that the prose fix would
|
||||
// have widened to both branches in ten languages. Found by exp-shepherd sweeping the whole tree for the
|
||||
// PATTERN (a branch on a user-visible string's content) after I had only grepped for the exact shape I
|
||||
// already knew, `status.value.startsWith` — which is why I missed the ternary form in my own file.
|
||||
flashRef(copyFlash, ok ? t('messages.copied') : t('messages.copyFailed'), 1800)
|
||||
}
|
||||
|
||||
// textarea + execCommand('copy') fallback (non-secure context, no clipboard API).
|
||||
|
|
@ -1314,10 +1318,11 @@ async function packetMapSvg(zoneId, R) {
|
|||
// the status never clears in any non-English locale: a stuck error message, in ten languages, from a fix
|
||||
// that looked purely cosmetic. Same family as counting prayer points by matching the English word
|
||||
// "prayer". So compare against the exact string we set instead — locale-independent by construction.
|
||||
function flashStatus(text, ms) {
|
||||
status.value = text;
|
||||
setTimeout(() => { if (status.value === text) status.value = ''; }, ms);
|
||||
function flashRef(target, text, ms) {
|
||||
target.value = text;
|
||||
setTimeout(() => { if (target.value === text) target.value = ''; }, ms);
|
||||
}
|
||||
const flashStatus = (text, ms) => flashRef(status, text, ms);
|
||||
|
||||
async function printPrayerPacket(zoneId) {
|
||||
const zone = allLists().find((z) => z.id === zoneId);
|
||||
|
|
|
|||
File diff suppressed because one or more lines are too long
Loading…
Reference in a new issue