localization_gen 1.0.6
localization_gen: ^1.0.6 copied to clipboard
Type-safe localization generator for Flutter with nested JSON support, modular organization, parameter interpolation, watch mode, and strict validation.
Localization Generator #
A powerful and type-safe localization generator for Flutter applications using JSON files.
Latest Update - v1.0.6
Version 1.0.6 introduces watch mode and strict validation:
- Watch Mode: Auto-regenerate on file changes with
--watch- Strict Validation: Ensure locale consistency with
strict_validation: true- Enhanced Error Handling: Clear error messages with file paths and line numbers
- Better Performance: Optimized code generation
Previous Update - v1.0.4
Named parameters for better code clarity:l10n.welcome(name: 'John')
See MIGRATION_V1.0.4.md
Features #
- Type-Safe: Compile-time checking of translation keys
- Nested JSON: Organize translations hierarchically up to 10 levels deep
- Watch Mode: Auto-regenerate on file changes during development
- Modular: Support for feature-based file organization
- Parameter Interpolation: Dynamic values with named parameters
- Strict Validation: Ensure all locales have consistent keys and parameters
- Multi-Package: Monorepo support with independent localization per package
- Customizable: Flexible configuration options
- Production Ready: Comprehensive testing and error handling
Why Use This Package? #
Traditional flat key-value translation files can become messy in large projects. This package uses nested JSON for better organization:
Traditional Approach:
{
"auth_login_title": "Login",
"auth_login_email": "Email",
"auth_login_password": "Password"
}
Our Approach:
{
"auth": {
"login": {
"title": "Login",
"email": "Email",
"password": "Password"
}
}
}
This generates clean, hierarchical code:
final l10n = AppLocalizations.of(context);
l10n.auth.login.title // "Login"
l10n.auth.login.email // "Email"
l10n.auth.login.password // "Password"
Installation #
Add to your pubspec.yaml:
dev_dependencies:
localization_gen: ^1.0.6
dependencies:
flutter_localizations:
sdk: flutter
Then run:
dart pub get
Quick Start #
1. Configure #
Add configuration to pubspec.yaml:
localization_gen:
input_dir: assets/localizations
output_dir: lib/assets
class_name: AppLocalizations
strict_validation: true # Optional: ensure all locales match
2. Create JSON Files #
Create assets/localizations/app_en.json:
{
"@@locale": "en",
"common": {
"hello": "Hello",
"save": "Save"
},
"home": {
"welcome": "Welcome, {name}!"
}
}
Create assets/localizations/app_id.json:
{
"@@locale": "id",
"common": {
"hello": "Halo",
"save": "Simpan"
},
"home": {
"welcome": "Selamat datang, {name}!"
}
}
3. Generate Code #
One-time generation:
dart run localization_gen
Watch mode (auto-regenerate on file changes):
dart run localization_gen --watch
Custom debounce delay:
dart run localization_gen --watch --debounce=500
4. Use in App #
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'assets/app_localizations.dart';
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
localizationsDelegates: const [
AppLocalizationsExtension.delegate,
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: AppLocalizations.supportedLocales,
home: HomePage(),
);
}
}
class HomePage extends StatelessWidget {
@override
Widget build(BuildContext context) {
final l10n = AppLocalizations.of(context);
return Scaffold(
appBar: AppBar(title: Text(l10n.common.hello)),
body: Text(l10n.home.welcome(name: 'John')),
);
}
}
Configuration Options #
All configuration options in pubspec.yaml:
localization_gen:
# Required
input_dir: assets/localizations # Directory containing JSON files
output_dir: lib/assets # Where to generate Dart code
class_name: AppLocalizations # Name of generated class
# Optional
use_context: true # Enable context-aware access (default: true)
nullable: false # Make translations nullable (default: false)
modular: false # Use modular file organization (default: false)
file_prefix: app # Prefix for JSON files (default: app)
strict_validation: false # Validate locale consistency (default: false)
Configuration Details #
- input_dir: Where your JSON translation files are located
- output_dir: Where the generated Dart code will be saved
- class_name: Main class name for localization (e.g.,
AppLocalizations) - use_context: Generates static
of(BuildContext)method for easy access - nullable: Whether
of(context)returns nullable type - modular: Enable modular file organization (see Modular Organization)
- file_prefix: Prefix for JSON files when using modular mode
- strict_validation: Ensures all locales have identical keys and parameters
Strict Validation #
When strict_validation: true, the generator will:
- Ensure all locales have the same translation keys
- Verify parameters match across locales (order-independent)
- Throw clear errors if locales are inconsistent
Example error:
LocaleValidationException: Locale has missing translation keys
Locale: id
Missing keys (2):
- auth.login.forgot_password
- settings.theme
File: assets/localizations/app_id.json
CLI Options #
The generator supports several command-line options:
# Show help
dart run localization_gen --help
# Generate once
dart run localization_gen
# Watch mode - auto-regenerate on changes
dart run localization_gen --watch
# Watch mode with custom debounce (milliseconds)
dart run localization_gen --watch --debounce=500
# Custom config file
dart run localization_gen --config=custom_pubspec.yaml
Available Options #
-h, --help: Show usage information-w, --watch: Enable watch mode for auto-regeneration-d, --debounce: Debounce delay in milliseconds (default: 300)-c, --config: Path to pubspec.yaml file (default: pubspec.yaml)
Watch Mode #
Watch mode automatically regenerates localization files when JSON files change. Perfect for development!
Usage #
dart run localization_gen --watch
Features #
- 👀 Monitors your
input_dirfor JSON file changes - ⚡ Debounced regeneration (default 300ms, customizable)
- 🎯 Only processes
.jsonfiles - ⌨️ Press
Ctrl+Cto stop - 📝 Clear console output showing what changed
Example Output #
Starting localization generation...
Config:
Input: assets/localizations
Output: lib/assets
Class: AppLocalizations
Modular: false
Scanning JSON localization files...
Found 2 locale(s): en, id
Generating Dart code...
Generated: lib/assets/app_localizations.dart
Done! Generated 25 translations.
👀 Watching for changes in: assets/localizations
Press Ctrl+C to stop
🔄 File modified: app_en.json
Regenerating...
✅ Regeneration complete
Best Practices #
- Use During Development: Run watch mode in a terminal while developing
- Adjust Debounce: Increase debounce for slower machines or very large files
- Git Integration: Add generated files to
.gitignoreif regenerating in CI/CD
Error Handling #
The generator provides detailed error messages to help you fix issues quickly.
Common Errors #
Missing Translation Keys
LocaleValidationException: Locale has missing translation keys
Locale: id
Missing keys (2):
- auth.login.title
- home.welcome
File: assets/localizations/app_id.json
Fix: Add the missing keys to the Indonesian locale file.
Parameter Mismatch
ParameterException: Parameter mismatch between locales
Key: home.welcome
Expected parameters: name
Actual parameters: user
File: assets/localizations/app_id.json
Fix: Use the same parameter names in all locale files.
Invalid JSON
JsonParseException: Invalid JSON format
File: assets/localizations/app_en.json
Line: 5
Content: {"key": "value",}
Fix: Remove the trailing comma or fix JSON syntax.
Unsupported Value Types
Warning: Unsupported value type int for key "version"
File: assets/localizations/app_en.json
Fix: JSON values must be strings or nested objects. Convert numbers/booleans to strings.
JSON File Format #
Basic Structure #
{
"@@locale": "en",
"section": {
"key": "Value",
"nested": {
"key": "Nested value"
}
}
}
With Parameters #
{
"@@locale": "en",
"greetings": {
"welcome": "Welcome, {name}!",
"items": "You have {count} items"
}
}
Usage:
l10n.greetings.welcome(name: 'John') // "Welcome, John!"
l10n.greetings.items(count: '5') // "You have 5 items"
Modular Organization #
For large projects, use modular organization with modular: true:
assets/localizations/
├── app_auth_en.json # Authentication module
├── app_auth_id.json
├── app_home_en.json # Home module
└── app_home_id.json
Each file includes module metadata:
{
"@@locale": "en",
"@@module": "auth",
"login": {
"title": "Login"
}
}
Examples #
This package includes three comprehensive examples:
Default Example #
Traditional nested JSON approach. Best for small to medium apps.
- View Example
- 12 tests, all passing
Modular Example #
Feature-based file organization. Best for large apps with multiple teams.
- View Example
- 19 tests, all passing
Monorepo Example #
Multi-package architecture. Best for enterprise applications.
- View Example
- 28 tests, all passing
See EXAMPLES.md for detailed comparison and usage.
Advanced Usage #
Language Switching #
class MyApp extends StatefulWidget {
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
Locale _locale = const Locale('en');
void _changeLanguage(Locale locale) {
setState(() => _locale = locale);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
locale: _locale,
localizationsDelegates: const [
AppLocalizationsExtension.delegate,
GlobalMaterialLocalizations.delegate,
],
supportedLocales: AppLocalizations.supportedLocales,
home: HomePage(onLanguageChange: _changeLanguage),
);
}
}
Accessing Translations #
// In a widget with BuildContext
final l10n = AppLocalizations.of(context);
// Nested access
l10n.auth.login.title
// With parameters (using named parameters)
l10n.home.welcome(name: 'John')
// Deep nesting
l10n.settings.profile.edit.title
Multiple Locales #
Create one JSON file per locale:
app_en.json- Englishapp_id.json- Indonesianapp_es.json- Spanish- etc.
All files must have the same structure.
Testing #
Run tests for all examples:
./run_all_tests.sh
Or test individually:
cd example/default && flutter test
cd example/modular && flutter test
cd example/monorepo/app && flutter test
cd example/monorepo/core && flutter test
CI/CD Integration #
# .github/workflows/test.yml
name: Test
on: [ push, pull_request ]
jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
- uses: subosito/flutter-action@v2
- run: flutter pub get
- run: ./run_all_tests.sh
Comparison with Other Solutions #
| Feature | localization_gen | intl | easy_localization |
|---|---|---|---|
| Nested JSON | Yes | No | Limited |
| Type Safety | Full | Partial | No |
| Modular Files | Yes | No | No |
| Code Generation | Yes | Yes | No |
| Configuration | YAML | Separate | YAML |
| Monorepo Support | Yes | No | No |
Migration Guide #
From v1.0.3 to v1.0.4 #
Version 1.0.4 introduces improved parameter handling with named parameters for better code clarity and safety.
What Changed:
// Before (v1.0.3 and earlier) - Positional parameters
l10n.welcome_user('John')
l10n.item_count('5')
l10n.discount('20')
// After (v1.0.4+) - Named parameters with required keyword
l10n.welcome_user(name: 'John')
l10n.item_count(count: '5')
l10n.discount(value: '20')
Migration Steps:
-
Update the package:
dev_dependencies: localization_gen: ^1.0.4 -
Regenerate localization files:
dart run localization_gen:localization_gen -
Update all method calls with parameters:
- Find all calls to methods with parameters
- Convert from positional to named parameters
- Use the parameter name from your JSON (e.g.,
{name}becomesname:)
-
Test your application:
- Run all tests to catch any missed conversions
- The compiler will show errors for any unconverted calls
Example Migration:
Before:
Text(l10n.home.welcome_user('Alice'))
Text(l10n.shop.discount('25'))
Text(l10n.cart.item_count('10'))
After:
Text(l10n.home.welcome_user(name: 'Alice'))
Text(l10n.shop.discount(value: '25'))
Text(l10n.cart.item_count(count: '10'))
Why This Change?
Named parameters provide:
- Better code clarity
- Prevention of parameter order mistakes
- Improved IDE autocomplete
- Easier maintenance
For detailed migration guide, see MIGRATION_V1.0.4.md.
From intl #
- Convert ARB files to nested JSON
- Update configuration
- Generate code
- Update import statements
- Replace
AppLocalizations.of(context)!.keywithAppLocalizations.of(context).section.key
From easy_localization #
- Convert flat JSON to nested structure
- Add configuration to pubspec.yaml
- Generate code
- Replace
tr('key')withAppLocalizations.of(context).section.key
Troubleshooting #
Issue: Generated file not found
- Check
output_dirin configuration - Ensure generator ran successfully
- Verify file permissions
Issue: Translations not updating
- Regenerate after JSON changes
- Perform full restart (not hot reload)
- Check for JSON syntax errors
Issue: Type errors
- Ensure all locale files have same structure
- Check for missing keys
- Regenerate code
Issue: Locale not switching
- Verify
localeparameter in MaterialApp - Check
supportedLocaleslist - Ensure delegates are properly configured
Best Practices #
- Organize by Feature: Group related translations together
- Use Nested Structure: Take advantage of hierarchical organization
- Consistent Naming: Use clear, descriptive key names
- Parameter Naming: Use meaningful parameter names like
{userName}not{x} - Keep Synced: Ensure all locale files have the same structure
- Version Control: Commit generated files for easier code review
- Testing: Write tests for localized widgets
- Documentation: Document special translation rules in code comments
Contributing #
Contributions are welcome! Please:
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests
- Submit a pull request
License #
MIT License - see LICENSE file for details.
Support #
Documentation #
- Quick Start Guide - Get started in 5 minutes
- Examples - Real-world examples
- Changelog - Version history
v1.0.4 Update Resources #
- Update Guide - Complete update documentation
- Migration Guide - Step-by-step migration
Get Help #
- Report Issues
- Discussions
- Contact maintainer via GitHub
Acknowledgments #
Inspired by the need for better localization organization in large Flutter projects.
Version: 1.0.4
Dart SDK: >=3.0.0 <4.0.0
Flutter: >=3.0.0