The Custom Header field is a Text Editor,

I found the issue. The Custom Header field is a Text Editor, so it stores HTML (e.g., <p>Dear Sir or Madam</p><p>We would like to invoice you as follows:</p>). However, the Translation record currently contains plain text. Since Frappe matches the source text exactly, the translation is not applied. We need to either store the exact HTML in the Translation record or change the field to a plain text field (Small Text/Text) if we want to use standard translations.

When you type “Dear Sir” in a Text Editor field, Frappe secretly saves it as:

Dear Sir

But your Translation record stores just: Dear Sir So when Frappe looks for a match, it’s comparing

Dear Sir

vs Dear Sir
, they don’t match, so the translation fails.
The fix: Change the field to Small Text (plain text, no HTML wrapping). Then the translation will match exactly.