fix(gettext): extract template-literal translations with correct line numbers (#38063)

This commit is contained in:
Raffael Meyer 2026-03-16 19:52:04 +01:00 committed by GitHub
parent b60a980fd4
commit 163094c898
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
2 changed files with 44 additions and 17 deletions

View file

@ -185,27 +185,40 @@ def parse_template_string(
:param options: a dictionary of additional options (optional)
:param lineno: starting line number (optional)
"""
from babel.messages.jslexer import line_re
prev_character = None
current_lineno = lineno
level = 0
inside_str = False
inside_expression_str = False
expression_lineno = lineno
expression_contents = ""
for character in template_string[1:-1]:
if not inside_str and character in ('"', "'", "`"):
inside_str = character
elif inside_str == character and prev_character != r"\\":
inside_str = False
if level:
expression_contents += character
if not inside_str:
if not level:
if character == "{" and prev_character == "$":
expression_lineno = current_lineno
level += 1
elif level and character == "}":
else:
expression_contents += character
if inside_expression_str:
if inside_expression_str == character and prev_character != r"\\":
inside_expression_str = False
else:
if character in ('"', "'", "`"):
inside_expression_str = character
elif character == "{":
level += 1
elif character == "}":
level -= 1
if level == 0 and expression_contents:
expression_contents = expression_contents[:-1]
yield from extract_javascript(expression_contents, keywords, options, lineno)
lineno += len(line_re.findall(expression_contents))
yield from extract_javascript(
expression_contents,
keywords,
options,
expression_lineno,
)
expression_contents = ""
inside_expression_str = False
if character == "\n":
current_lineno += 1
prev_character = character

View file

@ -15,3 +15,17 @@ class TestJavaScript(IntegrationTestCase):
next(extract_javascript(code)),
(1, "__", ("Test", None, "Context")),
)
def test_extract_javascript_from_template_literal_attribute(self):
code = "let test = `<button title=\"${__('In attribute')}\">${__('In text')}</button>`;"
self.assertEqual(
list(extract_javascript(code)),
[(1, "__", "In attribute"), (1, "__", "In text")],
)
def test_extract_javascript_template_literal_multiline_line_numbers(self):
code = "let test = `\n<button title=\"${__('In attribute')}\">\n ${__('In text')}\n</button>\n`;"
self.assertEqual(
list(extract_javascript(code)),
[(2, "__", "In attribute"), (3, "__", "In text")],
)