🌍 Localization (i18n) System¶
The Autograder features a robust, multi-language localization system that allows all student-facing feedback, error messages, and test reports to be delivered in the student's preferred language.
Architecture Overview¶
The system follows an "English Internals + Structured Locales" strategy:
- Source Code: All internal logic, variable names, and developer-facing logs remain in English.
- Student-Facing Text: Externalized into centralized JSON catalogs for maximum interoperability with other services.
- Dynamic Selection: The language is selected per-submission via the locale parameter (e.g., pt-br).
The t() Function¶
The core of the system is the t(key, locale=..., **kwargs) function, located in autograder/translations.
Usage Example¶
from autograder.translations import t
# Basic translation
name = t("web_dev.html.check_head.description", locale="pt-br")
# Translation with variables
report = t(
"web_dev.html.has_tag.report",
locale="en",
tag="div",
found_count=2,
required_count=5
)
Key Features¶
- Nested Lookup: Supports dot-notation (e.g.,
a.b.c) to traverse hierarchical dictionaries. - Graceful Fallback: If a key is missing in the target locale (e.g.,
pt-br), it automatically falls back to the default locale (en). - Locale Normalization: Common formats like
pt-brare automatically normalized topt_brto match Python module naming conventions. - Variable Interpolation: Uses standard Python
.format()syntax for dynamic values.
Translation Catalogs¶
Catalogs are JSON files located in autograder/translations/. Using JSON allows the same translation keys to be shared across a multi-language ecosystem (e.g., Prisma API, Frontend, CLI).
Catalog Structure (Nested)¶
We use a nested structure to organize strings by domain and feature:
// autograder/translations/en.json
{
"web_dev": {
"html": {
"check_head": {
"description": "Checks if a tag exists in the <head>.",
"report": {
"found": "Tag <{tag}> found.",
"not_found": "Tag <{tag}> not found."
}
}
}
}
}
Main Categories¶
preflight: Errors during environment setup and requirement checks.feedback: Report headers, category labels (Essential vs. Bonus), and instructions.ai: Prompts used by theAiExecutor.web_dev: Specialized test strings for the Web Development library.
Adding a New Language¶
- Create a new file in
autograder/translations/named after the ISO 639-1 code + region, using snake_case for the filename (e.g.,pt_br.json). - Define the JSON structure by copying it from
en.json. - The new language will be automatically available via
t(..., locale="pt-br").
Best Practices¶
- Never Hardcode: Any string that a student will see must use
t(). - Use Dot-Notation: Use descriptive paths that reflect the module structure.
- Keep Parity: Always ensure that new keys added to
en.jsonare also added to local catalogs (e.g.,pt_br.json) to avoid unexpected fallbacks. - Leaf Strings: Ensure the path points to a string, not a sub-dictionary. For example, use
report.foundinstead of justreport.