Internationalization (i18n) module for the RegressionLab application.
The i18n.py module provides language support for the application, allowing all UI messages, logs, and errors to be displayed in different languages based on the LANGUAGE environment variable.
- Spanish (
'es','español','spanish','esp'): Default language - English (
'en','english','eng', etc.): Secondary language - German (
'de','german','deutsch','ger'): Supported viasrc/locales/de.json
Initialize the internationalization system.
This function should be called once at application startup. If no language is specified, it reads from the LANGUAGE environment variable.
Parameters:
language: Optional language code ('es', 'en', or 'de'). If None, reads from env var.
Example:
from i18n import initialize_i18n
# Initialize with default (from env var)
initialize_i18n()
# Initialize with specific language
initialize_i18n('en')Translate a key to the current language.
This function retrieves the translation for a given key in the current language. The key uses dot notation to navigate nested dictionaries.
Parameters:
key: Translation key in dot notation (e.g., 'menu.welcome')**kwargs: Optional format parameters for string interpolation
Returns:
- Translated string, or the key itself if translation not found
Examples:
from i18n import t
# Simple translation
message = t('menu.welcome')
# Returns: 'Welcome, scientist. What would you like to do?' (in English)
# Translation with formatting
error_msg = t('error.fitting_failed_details', error='Invalid data')
# Returns: 'RegressionLab was unable to fit the data.\n\nDetails: Invalid data'Translations are stored in JSON files in the locales/ directory (pretty-printed for readability and maintainability):
src/locales/
├── en.json # English translations
├── es.json # Spanish translations
└── de.json # German translations
Keys use dot notation to represent nested structure:
{
"menu": {
"title": "RegressionLab",
"welcome": "Welcome, scientist. What would you like to do?",
"exit": "Exit"
},
"error": {
"title": "Error",
"fitting_failed": "Fitting failed"
}
}Access with: t('menu.welcome'), t('error.fitting_failed')
from tkinter import messagebox
from i18n import t
# Show error dialog
messagebox.showerror(
t('error.title'),
t('error.fitting_failed')
)from utils.logger import get_logger
from i18n import t
logger = get_logger(__name__)
logger.info(t('log.application_starting'))from i18n import t
# Translation with placeholders
message = t('log.data_loaded', rows=100, cols=5)
# Translation file: "Data loaded: {rows} rows, {cols} columns"
# Result: "Data loaded: 100 rows, 5 columns"The module automatically detects language from:
- Environment variable:
LANGUAGE(e.g.,LANGUAGE=es) - Function parameter: When calling
initialize_i18n('en') - Default fallback: Spanish (
'es') if not specified
The module accepts various formats and normalizes them:
- Spanish:
'es','español','spanish','esp' - English:
'en','english','inglés','ingles','eng' - German:
'de','german','deutsch','ger'
If a translation file is missing or a key is not found:
- Missing file: Falls back to default language (Spanish)
- Missing key: Returns the key itself as fallback
# If 'menu.unknown_key' doesn't exist
result = t('menu.unknown_key')
# Returns: 'menu.unknown_key' (the key itself)The module does not automatically initialize on import for performance reasons. Applications should call initialize_i18n() explicitly:
# In main_program.py or app.py
from i18n import initialize_i18n
# Initialize at startup
initialize_i18n()
# Now translations are available
from i18n import t
message = t('menu.welcome')-
Set language: Use
LANGUAGEenvironment variable in.env:LANGUAGE=es -
Restart app: Language changes require application restart
-
Always initialize: Call
initialize_i18n()before usingt() -
Use descriptive keys: Use clear, hierarchical key names
# Good t('error.fitting.failed') # Bad t('err1')
-
Provide context: Include format parameters for dynamic content
t('log.file_loaded', filename='data.csv', size=1024)
-
Add translations: When adding new UI text, add keys to
en.json,es.json, andde.json
To add a new translation:
-
Add key to English file (
locales/en.json):{ "new_section": { "new_key": "English text" } } -
Add key to Spanish and German files (
locales/es.json,locales/de.json) with the same structure and translated values. -
Use in code:
message = t('new_section.new_key')
- Translations are loaded on first use of each language and cached in memory
- Each language file is read at most once; switching language (e.g. en → es → en) reuses the cached data
- After initialization, no file I/O for the current language
- Per-language cache: Loaded translation dicts are kept in
_translation_cache; switching back to a language does not re-read or re-parse the JSON file - Resolved-key cache: For the current language, each resolved key (e.g.
menu.welcome) is cached so repeatedt('menu.welcome')calls avoid repeated nested lookups - Key resolution is O(n) in key depth on first lookup, then O(1) for the same key
For more information about internationalization, see Customization Guide.