Use translation keys for all FX row labels; append currency dynamically

All four FX sub-row labels now come from config translations instead of
hardcoded English strings. Labels with a currency suffix (per-item,
total-foreign) have the currency code appended by updateFxLabels() so
they read e.g. "Price per item in USD" / "Line total in USD" and update
when the foreign currency dropdown changes. Language switching also
re-applies all four labels via the existing updateFxLabels() call in
relabel().

Translation key values updated:
- currency-code  → "Foreign currency code"
- exchange-rate  → "Exchange rate" (dropped the redundant convention note)
- per-item       → "Price per item in"  (currency appended at runtime)
- total-foreign  → "Line total in"      (currency appended at runtime)

PDF note updated to match: "Price per item in USD: 100.00 (35 THB per USD)"

https://claude.ai/code/session_0151QtsUhzXmgzEhSvXG2SDt
This commit is contained in:
Claude 2026-06-02 01:31:18 +00:00
parent 77cf865ddc
commit 0f26de9222
No known key found for this signature in database
2 changed files with 30 additions and 24 deletions

View file

@ -408,25 +408,25 @@ translations:
fr: Devise étrangère
"no": Utenlandsk valuta
currency-code:
en: Currency code
de: Währungscode
fr: Code devise
"no": Valutakode
en: Foreign currency code
de: Fremdwährungscode
fr: Code devise étrangère
"no": Utenlandsk valutakode
exchange-rate:
en: "Exchange rate (1 foreign = X local)"
de: "Wechselkurs (1 Fremd = X Inland)"
fr: "Taux de change (1 étranger = X local)"
"no": "Valutakurs (1 utenlandsk = X lokal)"
en: Exchange rate
de: Wechselkurs
fr: Taux de change
"no": Valutakurs
per-item:
en: Price per item (foreign currency)
de: Preis je Einheit (Fremdwährung)
fr: Prix par unité (devise étrangère)
"no": Pris per enhet (utenlandsk valuta)
en: Price per item in
de: Preis je Einheit in
fr: Prix par unité en
"no": Pris per enhet i
total-foreign:
en: Line total in foreign currency
de: Zeilenbetrag (Fremdwährung)
fr: Total ligne en devise étrangère
"no": Linjebeløp i utenlandsk valuta
en: Line total in
de: Zeilenbetrag in
fr: Total ligne en
"no": Linjebeløp i
add-line:
en: "+ Add new line"
de: "+ Neue Zeile hinzufügen"

View file

@ -931,11 +931,11 @@ function toggleFx(i) {
<td colspan="6">
<div class="fx-grid">
<div>
<div class="fx-label">${t("currency-code")}</div>
<div class="fx-label" id="fcur-lbl-${i}">${t("currency-code")}</div>
<select id="fcur-${i}" onchange="updateFxLabels(${i});calcLine(${i});saveLines()">${currOpts(defaultFcy)}</select>
</div>
<div>
<div class="fx-label">Exchange rate</div>
<div class="fx-label" id="frate-lbl-${i}">${t("exchange-rate")}</div>
<div style="display:flex;align-items:center;gap:4px;flex-wrap:wrap">
<input type="number" id="frate-${i}" value="" min="0" step="any" style="width:80px" oninput="calcFxFromPer(${i})">
<select id="rcur-${i}" style="width:auto" onchange="updateFxLabels(${i});calcFxFromPer(${i});saveLines()">
@ -947,11 +947,11 @@ function toggleFx(i) {
</div>
</div>
<div>
<div class="fx-label" id="fper-lbl-${i}">Price per item in ${h(defaultFcy)}</div>
<div class="fx-label" id="fper-lbl-${i}">${t("per-item")} ${h(defaultFcy)}</div>
<input type="number" id="fper-${i}" value="" min="0" step="any" oninput="calcFxFromPer(${i})">
</div>
</div>
<div class="fx-note">${t("total-foreign")}: <strong id="fltot-${i}">0.00</strong></div>
<div class="fx-note"><span id="ftot-lbl-${i}">${t("total-foreign")} ${h(defaultFcy)}</span>: <strong id="fltot-${i}">0.00</strong></div>
</td>`;
lr?.insertAdjacentElement("afterend", fxTr);
calcLine(i);
@ -1406,7 +1406,7 @@ function buildPDF() {
let fxH = 0;
if (row.fxNote) {
const fxOther = row.fxNote.rcur === iCur ? row.fxNote.cur : iCur;
const fxStr = `${td("per-item")}: ${row.fxNote.cur} ${fmt(row.fxNote.per)} `
const fxStr = `${td("per-item")} ${row.fxNote.cur}: ${fmt(row.fxNote.per)} `
+ `(${(+row.fxNote.rate).toFixed(5)} ${row.fxNote.rcur} per ${fxOther})`;
const fxLines = sp(fxStr, CD + CP - 4);
fxH = fxLines.length * 3.5 + 1;
@ -1440,7 +1440,7 @@ function buildPDF() {
if (row.fxNote) {
const fxOther = row.fxNote.rcur === iCur ? row.fxNote.cur : iCur;
const fxStr = `${td("per-item")}: ${row.fxNote.cur} ${fmt(row.fxNote.per)} `
const fxStr = `${td("per-item")} ${row.fxNote.cur}: ${fmt(row.fxNote.per)} `
+ `(${(+row.fxNote.rate).toFixed(5)} ${row.fxNote.rcur} per ${fxOther})`;
fn(7); tc(107,114,128);
const fxLines = sp(fxStr, CD + CP - 4);
@ -1491,14 +1491,20 @@ function updateFxLabels(i) {
const lcy = document.getElementById("icur")?.value || "";
const rcurEl = document.getElementById(`rcur-${i}`);
const rotherEl = document.getElementById(`rother-${i}`);
const pl = document.getElementById(`fper-lbl-${i}`);
if (rcurEl) {
const prev = rcurEl.value;
rcurEl.innerHTML = `<option value="${h(lcy)}">${h(lcy)}</option><option value="${h(fcy)}">${h(fcy)}</option>`;
rcurEl.value = (prev === lcy || prev === fcy) ? prev : lcy;
}
if (rotherEl) rotherEl.textContent = rcurEl?.value === lcy ? fcy : lcy;
if (pl) pl.textContent = `Price per item in ${fcy}`;
const cl = document.getElementById(`fcur-lbl-${i}`);
if (cl) cl.textContent = t("currency-code");
const rl = document.getElementById(`frate-lbl-${i}`);
if (rl) rl.textContent = t("exchange-rate");
const pl = document.getElementById(`fper-lbl-${i}`);
if (pl) pl.textContent = t("per-item") + " " + fcy;
const tl = document.getElementById(`ftot-lbl-${i}`);
if (tl) tl.textContent = t("total-foreign") + " " + fcy;
}
// ── Save / load invoice lines ──────────────────────────────────────────────────