Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
33 changes: 21 additions & 12 deletions pontoon/checks/libraries/custom.py
Original file line number Diff line number Diff line change
Expand Up @@ -70,18 +70,21 @@ def run_custom_checks(entity: Entity, string: str) -> dict[str, list[str]]:
msg = None
patterns = ()
errors.append(f"Parse error: {e}")

orig_pct_count = 0
orig_ph_strings: set[str] = set()
try:
orig_msg = mf2_parse_message(entity.string)
orig_ph_iter = (
el
for pattern in get_patterns(orig_msg)
for el in pattern
if not isinstance(el, str)
)
orig_ps = {preview_placeholder(ph) for ph in orig_ph_iter}
for pattern in get_patterns(orig_msg):
pattern_pct_count = 0
for el in pattern:
if isinstance(el, str):
pattern_pct_count += el.count("%")
else:
orig_ph_strings.add(preview_placeholder(el))
orig_pct_count = max(orig_pct_count, pattern_pct_count)
except ValueError:
orig_msg = None
orig_ps = set()

if any(all(el == "" for el in pattern) for pattern in patterns):
errors.append("Empty translations are not allowed")
Expand All @@ -94,22 +97,28 @@ def run_custom_checks(entity: Entity, string: str) -> dict[str, list[str]]:
# Inlined Android checks from compare-locales to support <plurals>
found_ps: set[str] = set()
try:
pct_count = 0
for pattern in patterns:
android_msg = android_parse_message(
escape(get_simple_preview(Resource.Format.ANDROID, pattern))
)
pattern_pct_count = 0
for el in android_msg.pattern:
if not isinstance(el, str):
if isinstance(el, str):
pattern_pct_count += el.count("%")
else:
ps = preview_placeholder(el)
if ps in orig_ps:
if ps in orig_ph_strings:
found_ps.add(ps)
else:
errors.append(
f"Placeholder {ps} not found in reference"
)
for ps in orig_ps:
pct_count = max(pct_count, pattern_pct_count)
for ps in orig_ph_strings:
if ps not in found_ps:
warnings.append(f"Placeholder {ps} not found in translation")
ew_list = errors if pct_count > orig_pct_count else warnings
ew_list.append(f"Placeholder {ps} not found in translation")
except Exception as e:
errors.append(f"Parse error: {e}")

Expand Down
41 changes: 41 additions & 0 deletions pontoon/checks/tests/test_custom.py
Comment thread
eemeli marked this conversation as resolved.
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,20 @@ def test_android_apostrophes():
assert run_custom_checks(entity, translation) == {}


def test_android_percent_signs_same():
original = "Source string 100%"
translation = "Translation string 100%"
entity = mock_entity("android", string=original)
assert run_custom_checks(entity, translation) == {}


def test_android_percent_signs_more():
original = "Source string 100%"
translation = "Translation 100%! string 100%"
entity = mock_entity("android", string=original)
assert run_custom_checks(entity, translation) == {}


def test_android_literal_newline():
original = "Source string"
translation = r"Translation with an escaped \\n newline"
Expand All @@ -200,6 +214,24 @@ def test_android_same_placeholder():
assert run_custom_checks(entity, translation) == {}


def test_android_plural_placeholders():
original = """
.input {$n :number}
.match $n
one {{One item}}
* {{{$arg1 :number @source=|%1$d|} items}}
"""
translation = """
.input {$n :number}
.match $n
one {{{$arg1 :number @source=|%1$d|} item}}
many {{{$arg1 :number @source=|%1$d|} items}}
* {{{$arg1 :number @source=|%1$d|} items}}
"""
entity = mock_entity("android", string=original)
assert run_custom_checks(entity, translation) == {}


def test_android_missing_placeholder():
original = "Source string with a {$arg1 :string @source=|%1$s|}"
translation = "Translation"
Expand All @@ -209,6 +241,15 @@ def test_android_missing_placeholder():
}


def test_android_mistyped_placeholder():
original = "Source string with a {$arg1 :string @source=|%1$s|}"
translation = "Translation %1"
entity = mock_entity("android", string=original)
assert run_custom_checks(entity, translation) == {
"pErrors": ["Placeholder %1$s not found in translation"]
}


def test_android_extra_placeholder():
original = "Source string"
translation = "Translation with a {$arg1 :string @source=|%1$s|}"
Expand Down
Loading