Skip to content

Instantly share code, notes, and snippets.

@flodolo
Created February 11, 2026 13:23
Show Gist options
  • Select an option

  • Save flodolo/c8aeae0f4fdd6992cd724f8cfe525325 to your computer and use it in GitHub Desktop.

Select an option

Save flodolo/c8aeae0f4fdd6992cd724f8cfe525325 to your computer and use it in GitHub Desktop.
Firefox Onboarding Refresh completion status (v148)
#!/usr/bin/env python3
"""
Pontoon translation coverage report for a given search query.
- Queries Pontoon search/translations endpoint (custom User-Agent).
- Extracts entity IDs.
- Fetches translations for each entity.
- Computes per-locale completion across the entity set.
Requires: requests
pip install requests
"""
import sys
import time
from typing import Dict, List, Optional, Set
import requests
SEARCH_URL = "https://pontoon.mozilla.org/api/v2/search/translations/"
ENTITY_URL = "https://pontoon.mozilla.org/api/v2/entities/{id}/"
def build_session(user_agent: str) -> requests.Session:
session = requests.Session()
session.headers.update(
{
"User-Agent": user_agent,
"Accept": "application/json",
}
)
return session
def fetch_all_entity_ids(
session: requests.Session,
locale: str,
text: str,
project: str,
search_identifiers: bool = True,
page_size: int = 100,
timeout: int = 30,
) -> Set[int]:
params = {
"locale": locale,
"text": text,
"search_identifiers": "true" if search_identifiers else "false",
"project": project,
"page_size": page_size,
}
ids: Set[int] = set()
url = SEARCH_URL
while True:
r = session.get(url, params=params, timeout=timeout)
r.raise_for_status()
data = r.json()
for item in data.get("results", []):
entity_id = item.get("id")
if entity_id:
ids.add(entity_id)
next_url = data.get("next")
if not next_url:
break
url = next_url
params = {}
return ids
def fetch_entity_locale_set(
session: requests.Session,
entity_id: int,
timeout: int = 30,
) -> Set[str]:
url = ENTITY_URL.format(id=entity_id)
params = {"include_translations": "true"}
r = session.get(url, params=params, timeout=timeout)
r.raise_for_status()
data = r.json()
locales_with_translation: Set[str] = set()
for t in data.get("translations", []):
locale_code = t.get("locale", {}).get("code")
if locale_code:
locales_with_translation.add(locale_code)
return locales_with_translation
def compute_grouped_completion(
entity_ids: Set[int],
entity_to_locales: Dict[int, Set[str]],
) -> Dict[int, List[str]]:
"""
Returns:
{
percentage_int: [locale1, locale2, ...]
}
"""
total = len(entity_ids)
per_locale_count: Dict[str, int] = {}
for eid in entity_ids:
for loc in entity_to_locales.get(eid, set()):
per_locale_count[loc] = per_locale_count.get(loc, 0) + 1
grouped: Dict[int, List[str]] = {}
for loc, count in per_locale_count.items():
percentage = round((count / total) * 100) if total else 0
grouped.setdefault(percentage, []).append(loc)
# Sort locales alphabetically inside each percentage
for loc_list in grouped.values():
loc_list.sort()
return grouped
def main(argv: Optional[List[str]] = None) -> int:
user_agent = "l10n-team-stats/1.0"
timeout = 30
sleep = 0
locale = "it"
text = "onboarding-refresh"
project = "firefox"
session = build_session(user_agent)
print("Searching entity IDs...")
entity_ids = fetch_all_entity_ids(
session=session,
locale=locale,
text=text,
project=project,
timeout=timeout,
)
if not entity_ids:
print("No entity IDs found. Exiting.")
return 0
print(f"Found {len(entity_ids)} unique entity IDs.")
entity_to_locales: Dict[int, Set[str]] = {}
for i, eid in enumerate(entity_ids, start=1):
try:
entity_to_locales[eid] = fetch_entity_locale_set(
session, eid, timeout=timeout
)
except requests.HTTPError as e:
print(f"[WARN] Failed entity {eid}: {e}", file=sys.stderr)
entity_to_locales[eid] = set()
if sleep > 0 and i < len(entity_ids):
time.sleep(sleep)
if i % 25 == 0 or i == len(entity_ids):
print(f" Processed {i}/{len(entity_ids)} entities...")
grouped = compute_grouped_completion(entity_ids, entity_to_locales)
print("\nCompletion by locale:\n")
for percentage in sorted(grouped.keys(), reverse=True):
locales = grouped[percentage]
print(f"{percentage}%: {', '.join(locales)}")
return 0
if __name__ == "__main__":
raise SystemExit(main())
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment