## Overview
Refactored the entire internationalization (i18n) system from hardcoded Go functions to a dynamic JSON-based loader using reflection. This change makes adding new languages as simple as creating a JSON file - no code changes required.
## What Changed
### Before (Static Approach)
- Each language required a new Go function (e.g., `spanishSet()`, `frenchSet()`)
- 100+ lines of manual field mapping per language
- Required recompilation for every new language
- Not accessible to non-developers/translators
### After (Dynamic Approach)
- Languages defined in JSON files (`translations/en.json`, `translations/es.json`, etc.)
- Automatic mapping using reflection
- Zero code changes needed for new languages
- Translators can directly edit JSON files
## Technical Details
### New Architecture
1. **TranslationLoader**: Manages loading and caching of translations from JSON
2. **Reflection-based Mapping**: Automatically maps JSON keys to struct fields
3. **Cache System**: Loaded translations are cached for performance
4. **Fallback Chain**: Automatically falls back to English if requested language unavailable
### Key Files Added
- `pkg/i18n/i18n.go` - Dynamic loader with reflection
- `pkg/i18n/types.go` - Type definitions
- `translations/*.json` - Language files (en, az, tr, es)
- `create_language.py` - Utility to generate new language files
- `create_language.sh` - Bash alternative for language generation
### Performance
- First load: Reads from JSON (slower)
- Subsequent loads: Retrieved from cache (fast)
- Memory overhead: Minimal (only loaded languages cached)
## Migration Guide
### Old Code
```go
func spanishSet() TranslationSet {
return TranslationSet{
GlobalTitle: "Global",
MainTitle: "Inicio",
Remove: "borrar",
// ... 100+ more lines
}
}
```
### New Code
```json
{
"code": "es",
"name": "Español",
"translations": {
"GlobalTitle": "Global",
"MainTitle": "Inicio",
"Remove": "borrar"
}
}
```
### Usage Example
```go
// Load translation dynamically
ts, err := i18n.NewTranslationSetFromConfig(
logger,
"es", // language code
"./translations", // path to JSON files
)
// Use it
fmt.Println(ts.GlobalTitle) // "Global"
```
## Adding New Languages
### Method 1: Using Python Script
```bash
python3 create_language.py ru "Русский"
# Edit translations/ru.json
```
### Method 2: Using Bash Script
```bash
./create_language.sh de "Deutsch"
# Edit translations/de.json
```
### Method 3: Manual
Create `translations/xx.json` with structure:
```json
{
"code": "xx",
"name": "Language Name",
"translations": {
"Key": "Translation"
}
}
```
## Benefits
### For Developers
- ✅ No more repetitive code for each language
- ✅ Easier to maintain and extend
- ✅ Type-safe through reflection
- ✅ Automatic validation
### For Translators
- ✅ Simple JSON format
- ✅ No programming knowledge required
- ✅ Can use translation tools/editors
- ✅ Easy to review changes in PRs
### For Project
- ✅ Scalable to 100+ languages
- ✅ Reduced code complexity
- ✅ Better separation of concerns
- ✅ Community contributions easier
## Backward Compatibility
The old static functions (`englishSet()`, `spanishSet()`, etc.) remain as fallback if JSON loading fails, ensuring zero breaking changes.
## Testing
Tested with 4 languages:
- ✅ English (en) - Base language
- ✅ Azerbaijani (az) - Full translation
- ✅ Turkish (tr) - Full translation
- ✅ Spanish (es) - Full translation
## Files Changed
- Modified: `pkg/i18n/i18n.go` (refactored to use reflection)
- Added: `pkg/i18n/types.go` (type definitions)
- Added: `translations/en.json` (English)
- Added: `translations/az.json` (Azerbaijani)
- Added: `translations/tr.json` (Turkish)
- Added: `translations/es.json` (Spanish)
- Added: `create_language.py` (utility script)
- Added: `create_language.sh` (utility script)
- Added: `USAGE.md` (documentation)
## Future Enhancements
Possible additions:
1. Hot-reload support (file watcher)
2. Remote translation loading (API/database)
3. Plural forms support
4. Variable interpolation
5. Translation validation tools
## Breaking Changes
None. The system maintains backward compatibility with existing code.
---
**Closes**: #XXX (if applicable)
**Related**: Translation system modernization initiative
A la lazygit, we can now navigate between panels using numbers
(1,2,3,4,5,6,7)
Add translation for number navigation
reformat
oops
fix translation case & generate docs
pluralize networks
update to the current version, which addresses some issues with current
Go versions, and removes the legacy konsorten/go-windows-terminal-sequences
dependency.
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
It took me a fair bit of time before i understood that '{{ .DockerCompose }}' was defined by the dockerCompose var in commandTemplates.
In hindsight it is VERY obvious.. so i just wanted to contribute a comment that would have been useful to me when i first tried to set this up.
Apparently:
"
Error: Whoops, the lazydocker formula has its version update
pull requests automatically opened by BrewTestBot!
We'd still love your contributions, though, so try another one
that's not in the autobump list
"
So looks like we don't need to have this action anymore because homebrew
will be updated automatically.