diff --git a/babel/messages/extract.py b/babel/messages/extract.py index 6fad84304..6ebaad8ee 100644 --- a/babel/messages/extract.py +++ b/babel/messages/extract.py @@ -710,6 +710,8 @@ def _parse_python_string(value: str, encoding: str, future_flags: int) -> str | if isinstance(code, ast.Expression): body = code.body if isinstance(body, ast.Constant): + if isinstance(body.value, bytes): + return None # byte strings are not translatable return body.value if isinstance(body, ast.JoinedStr): # f-string if all(isinstance(node, ast.Constant) for node in body.values): diff --git a/tests/messages/test_extract.py b/tests/messages/test_extract.py index 41eda8903..92b6efaed 100644 --- a/tests/messages/test_extract.py +++ b/tests/messages/test_extract.py @@ -180,3 +180,17 @@ def test_issue_1195_2(): 'NOTE: This should still be considered, even if', 'the text is far away', ] + + +def test_extract_byte_string_does_not_crash(): + """Byte strings like _(b'foo') should be skipped without crashing.""" + buf = BytesIO(b"""\ +_(b'foo') +_('hello') +_(b"bar") +_('world') +""") + messages = list(extract.extract('python', buf, {'_': None}, [], {})) + assert len(messages) == 2 + assert messages[0][1] == 'hello' + assert messages[1][1] == 'world'