This is an automated email from the ASF dual-hosted git repository.
potiuk pushed a commit to branch main
in repository https://gitbox.apache.org/repos/asf/airflow.git
The following commit(s) were added to refs/heads/main by this push:
new fa602298f4b Feat: Improve check translations script with Coverage and
Completion metrics (#53524)
fa602298f4b is described below
commit fa602298f4b7f3f2f178d7f01ea3f590ed98c053
Author: Yeonguk Choo <[email protected]>
AuthorDate: Sat Jul 19 19:54:08 2025 +0900
Feat: Improve check translations script with Coverage and Completion
metrics (#53524)
---
dev/i18n/check_translations_completeness.py | 80 ++++++++++++++---------------
1 file changed, 40 insertions(+), 40 deletions(-)
diff --git a/dev/i18n/check_translations_completeness.py
b/dev/i18n/check_translations_completeness.py
index b8d5437d631..4f62ddeead2 100755
--- a/dev/i18n/check_translations_completeness.py
+++ b/dev/i18n/check_translations_completeness.py
@@ -285,34 +285,25 @@ def get_outdated_entries_for_language(
return outdated
-def count_todo_and_total(obj):
- """Recursively count TODO: translate entries and total entries in a dict
or list."""
- todo = 0
- total = 0
+def count_todos(obj) -> int:
+ """Count TODO: translate entries in a dict or list."""
if isinstance(obj, dict):
- for v in obj.values():
- t, n = count_todo_and_total(v)
- todo += t
- total += n
- elif isinstance(obj, list):
- for v in obj:
- t, n = count_todo_and_total(v)
- todo += t
- total += n
- else:
- total = 1
- if isinstance(obj, str) and obj.strip().startswith("TODO: translate"):
- todo = 1
- return todo, total
+ return sum(count_todos(v) for v in obj.values())
+ if isinstance(obj, list):
+ return sum(count_todos(v) for v in obj)
+ if isinstance(obj, str) and obj.strip().startswith("TODO: translate"):
+ return 1
+ return 0
def print_translation_progress(console, locale_files, missing_counts, summary):
- from rich.table import Table
-
tables = defaultdict(lambda: Table(show_lines=True))
all_files = set()
for lf in locale_files:
all_files.update(lf.files)
+
+ has_todos = False
+
for lf in sorted(locale_files):
lang = lf.locale
if lang == "en":
@@ -325,7 +316,8 @@ def print_translation_progress(console, locale_files,
missing_counts, summary):
table.add_column("TODOs", style="magenta")
table.add_column("Translated", style="green")
table.add_column("Total", style="bold")
- table.add_column("Percent", style="bold")
+ table.add_column("Coverage", style="bold")
+ table.add_column("Completion", style="bold")
total_missing = 0
total_extra = 0
total_todos = 0
@@ -347,19 +339,15 @@ def print_translation_progress(console, locale_files,
missing_counts, summary):
file_missing = missing_counts.get(filename, {}).get(lang, 0)
file_extra = len(summary.get(filename, LocaleSummary({},
{})).extra_keys.get(lang, []))
- # Count TODOs
- def count_todos(obj):
- if isinstance(obj, dict):
- return sum(count_todos(v) for v in obj.values())
- if isinstance(obj, list):
- return sum(count_todos(v) for v in obj)
- if isinstance(obj, str) and obj.strip().startswith("TODO:
translate"):
- return 1
- return 0
-
file_todos = count_todos(data)
+ if file_todos > 0:
+ has_todos = True
file_translated = file_total - file_missing
- percent = 100 * file_translated / file_total if file_total
else 100
+ # Coverage: translated / total
+ file_coverage_percent = 100 * file_translated / file_total if
file_total else 100
+ # Complete percent: (translated - todos) / translated
+ file_actual_translated = file_translated - file_todos
+ complete_percent = 100 * file_actual_translated /
file_translated if file_translated else 100
style = (
"bold green"
if file_missing == 0 and file_extra == 0 and file_todos == 0
@@ -372,7 +360,9 @@ def print_translation_progress(console, locale_files,
missing_counts, summary):
file_extra = len(summary.get(filename, LocaleSummary({},
{})).extra_keys.get(lang, []))
file_todos = 0
file_translated = 0
- percent = 0
+ file_actual_translated = 0
+ file_coverage_percent = 0
+ complete_percent = 0
style = "red"
table.add_row(
f"[bold reverse]{filename}[/bold reverse]",
@@ -381,7 +371,8 @@ def print_translation_progress(console, locale_files,
missing_counts, summary):
str(file_todos),
str(file_translated),
str(file_total),
- f"{percent:.1f}%",
+ f"{file_coverage_percent:.1f}%",
+ f"{complete_percent:.1f}%",
style=style,
)
total_missing += file_missing
@@ -389,7 +380,12 @@ def print_translation_progress(console, locale_files,
missing_counts, summary):
total_todos += file_todos
total_translated += file_translated
total_total += file_total
- percent = 100 * total_translated / total_total if total_total else 100
+
+ # Calculate totals for this language
+ total_coverage_percent = 100 * total_translated / total_total if
total_total else 100
+ total_actual_translated = total_translated - total_todos
+ total_complete_percent = 100 * total_actual_translated /
total_translated if total_translated else 100
+
table.add_row(
"All files",
str(total_missing),
@@ -397,12 +393,16 @@ def print_translation_progress(console, locale_files,
missing_counts, summary):
str(total_todos),
str(total_translated),
str(total_total),
- f"{percent:.1f}%",
- style="red" if percent < 100 else "bold green",
+ f"{total_coverage_percent:.1f}%",
+ f"{total_complete_percent:.1f}%",
+ style="red" if total_complete_percent < 100 else "bold green",
)
+
for _lang, table in tables.items():
console.print(table)
+ return has_todos
+
@click.command()
@click.option(
@@ -450,14 +450,14 @@ def cli(language: str | None = None, add_missing: bool =
False):
else:
lang_diff = print_language_summary(locale_files, summary, console)
found_difference = found_difference or lang_diff
- print_translation_progress(
+ has_todos = print_translation_progress(
console,
[lf for lf in locale_files if language is None or lf.locale ==
language],
missing_counts,
summary,
)
- if not found_difference:
- console.print("[green]All translations are complete and
consistent![green]")
+ if not found_difference and not has_todos:
+ console.print("[green]All translations are complete and
consistent![/green]")
if found_difference:
sys.exit(1)