localization_gen 1.0.5
localization_gen: ^1.0.5 copied to clipboard
Type-safe localization generator for Flutter with nested JSON support, modular organization, and parameter interpolation.
Localization Generator #
A powerful and type-safe localization generator for Flutter applications using JSON files.
Important Update - v1.0.4
Version 1.0.4 introduces named parameters for better code clarity. If you're upgrading from v1.0.3 or earlier:
- Update guide: UPDATE_V1.0.4.md
- Migration steps: MIGRATION_V1.0.4.md
Quick Summary:
l10n.welcome('John')becomesl10n.welcome(name: 'John')
Features #
- Type-Safe: Compile-time checking of translation keys
- Nested JSON: Organize translations hierarchically for better maintainability
- Modular: Support for feature-based file organization
- Parameter Interpolation: Dynamic values in translations
- Multi-Package: Monorepo support with independent localization per package
- Customizable: Flexible configuration options
- Production Ready: Comprehensive examples and testing
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.4
dependencies:
flutter_localizations:
sdk: flutter
Quick Start #
1. Configure #
Add configuration to pubspec.yaml:
localization_gen:
input_dir: assets/localizations
output_dir: lib/assets
class_name: AppLocalizations
2. Create JSON Files #
Create assets/localizations/app_en.json:
{
"@@locale": "en",
"common": {
"hello": "Hello",
"save": "Save"
},
"home": {
"welcome": "Welcome, {name}!"
}
}
3. Generate Code #
dart run localization_gen:localization_gen
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 #
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 non-nullable (default: false)
modular: false # Use modular file organization (default: false)
file_prefix: app # Prefix for JSON files (default: app)
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