i18n Translation Management¶
This document describes how translation keys are managed in the aiohomematic project.
Overview¶
The project uses a custom i18n system with the following catalog files:
aiohomematic/strings.json- Base catalog with English translations (source of truth)aiohomematic/translations/en.json- English catalog (mirrors strings.json)aiohomematic/translations/de.json- German catalog
Linting Tools¶
check_i18n.py¶
Ensures that all exceptions and INFO+ level log messages use i18n.tr() for translation.
Rules:
- All
raisestatements with string literals must usei18n.tr() - All INFO, WARNING, ERROR, EXCEPTION, CRITICAL log messages must use
i18n.tr() - DEBUG log messages are exempt (can use plain strings)
Skip checks:
# Inline skip for exceptions
raise ValueError("message") # i18n-exc: ignore
# Inline skip for logs
_LOGGER.info("message") # i18n-log: ignore
# Skip next line
# i18n-exc: ignore-next
raise ValueError("message")
check_i18n_catalogs.py¶
Validates translation catalogs and ensures consistency between code and catalog files.
Checks performed:
- Missing keys - Every key used in code via
i18n.tr("key")must exist instrings.json - Unused keys - Every key in
strings.jsonshould be used in the codebase - Catalog sync -
en.jsonmust be identical tostrings.json - German catalog - Reports missing/extra keys in
de.json - Formatting - All JSON files must be sorted by key and properly formatted
Usage:
# Check for issues
python script/check_i18n_catalogs.py
# Auto-fix sync and formatting issues
python script/check_i18n_catalogs.py --fix
# Remove unused translation keys
python script/check_i18n_catalogs.py --remove-unused
# Combine both
python script/check_i18n_catalogs.py --fix --remove-unused
Example output:
Warnings:
Unused key in strings.json: exception.validator.custom_definition.invalid (run with --remove-unused to remove)
Unused key in strings.json: log.client.json_rpc.rename_channel.failed (run with --remove-unused to remove)
Errors:
de.json missing key: exception.new.error
File not sorted/formatted: aiohomematic/strings.json (run with --fix)
Adding New Translation Keys¶
- Add the key to
strings.json:
- Use it in code:
- Run the catalog checker:
This will automatically sync en.json and sort all files.
- Add German translation: Edit
translations/de.jsonand add the corresponding German text:
Key Naming Conventions¶
Translation keys follow a hierarchical naming scheme:
Exceptions¶
Examples:
exception.central.create_devices.no_clientsexception.client.get_value.failedexception.model.device.export_device_definition.failed
Log Messages¶
Examples:
log.client.reconnect.reconnectedlog.client.circuit_breaker.state_transitionlog.central.restart_clients.restarted
prek Hooks¶
The i18n checks are automatically run as prek hooks:
- id: check-i18n
name: Check i18n translations
entry: script/run-in-env.sh python script/check_i18n.py
- id: check-i18n-catalogs
name: Check i18n catalogs
entry: script/run-in-env.sh python script/check_i18n_catalogs.py --fix
Statistics¶
Current catalog statistics:
- Total keys: 185 (as of 2025-12-11)
- Used keys: 181
- Unused keys: 4
- Key categories:
- Exceptions: 111 keys
- Log messages: 74 keys
Maintenance¶
Finding Unused Keys¶
# Show unused keys
python script/check_i18n_catalogs.py
# Remove unused keys from all catalogs
python script/check_i18n_catalogs.py --remove-unused
Verifying Coverage¶
Syncing Catalogs¶
# Auto-sync en.json to match strings.json and sort all files
python script/check_i18n_catalogs.py --fix
Best Practices¶
- Always use
i18n.tr()for user-facing messages (exceptions, INFO+ logs) - Use English in base catalog -
strings.jsonshould always be in English - Keep keys organized - Follow the naming conventions for consistency
- Remove unused keys - Run
--remove-unusedperiodically to keep catalogs clean - Test translations - Verify both English and German locales work correctly
- DEBUG logs exempt - Low-level debug messages can use plain strings for performance
Troubleshooting¶
"Missing key in strings.json"¶
Add the missing key to strings.json or remove the i18n.tr() call if it's not needed.
"en.json differs from strings.json"¶
Run python script/check_i18n_catalogs.py --fix to auto-sync.
"de.json missing key"¶
Add the German translation to translations/de.json.
"Unused key in strings.json"¶
Either:
- Start using the key in code, or
- Remove it with
python script/check_i18n_catalogs.py --remove-unused