diff --git a/babel/messages/mofile.py b/babel/messages/mofile.py index 2413f7139..3e4f0ff7f 100644 --- a/babel/messages/mofile.py +++ b/babel/messages/mofile.py @@ -82,6 +82,10 @@ def read_mo(fileobj: SupportsRead[bytes]) -> Catalog: elif lastkey: headers[lastkey] += b'\n' + item + # 2026-10-10: Decode metadata using its declared charset. + if b'content-type' in headers: + catalog.mime_headers = [(b'content-type', headers[b'content-type'])] + ctxt: str | None = None msg: list[str] | str tmsg: list[str] | str diff --git a/tests/messages/test_mofile.py b/tests/messages/test_mofile.py index e572931c2..ec3cb1f34 100644 --- a/tests/messages/test_mofile.py +++ b/tests/messages/test_mofile.py @@ -104,3 +104,22 @@ def test_read_mo_decodes_message_context() -> None: assert message.context == 'ほげ' assert message.string == 'åäöÅÄÖ' assert not catalog.get('x') # Not without the context + + +def test_read_mo_decodes_non_ascii_headers(): + # 2026-10-10: The declared charset also applies to non-ASCII metadata. + for charset in ['utf-8', 'iso-8859-1', 'cp1252']: + catalog = Catalog( + charset=charset, + project='Caf\u00e9', + last_translator='Ren\u00e9 ', + ) + catalog.add('caf\u00e9', 'ol\u00e9', context='m\u00e9ta') + buf = BytesIO() + mofile.write_mo(buf, catalog) + buf.seek(0) + restored = mofile.read_mo(buf) + assert restored.charset == charset + assert restored.project == 'Caf\u00e9' + assert restored.last_translator == 'Ren\u00e9 ' + assert restored.get('caf\u00e9', context='m\u00e9ta').string == 'ol\u00e9'