flutter_locale_master 1.0.1 
flutter_locale_master: ^1.0.1 copied to clipboard
Advanced Flutter localization package with automatic RTL/LTR text direction switching, reactive UI updates, asset-based translations, pluralization, parameter interpolation, namespace support, and cus [...]
Flutter Locale Master #
A comprehensive, production-ready Flutter localization package with automatic text direction switching, custom widgets, and developer-friendly APIs. Built for modern Flutter apps with performance and ease of use in mind.
β¨ Features #
- π One-line initialization with asset-based translations
 - π Automatic text direction switching (LTR/RTL) based on locale
 - β‘ Reactive UI updates when locale changes
 - π Namespace support for organized translation files
 - π± Built-in pluralization with ICU MessageFormat syntax
 - π§ Parameter interpolation with named placeholders
 - π¨ Context extensions for convenient access
 - π§΅ String extensions for BuildContext-free usage
 - ποΈ Custom widgets for automatic translation
 - π¦ Type-safe API with full null-safety
 - π― Performance optimized with caching and preloading
 - π§ͺ Comprehensive testing coverage
 - π Rich documentation and examples
 
π¦ Installation #
Add this to your pubspec.yaml:
dependencies:
  flutter_locale_master: ^1.0.0
π Quick Start #
1. Setup Translation Files #
Create translation files in your assets/ directory:
assets/
  lang/
    en/
      en.json          # General translations (default namespace)
      fields.json      # Form field labels
      validation.json  # Validation messages
    ar/
      ar.json          # General translations (default namespace)
      fields.json      # Form field labels
      validation.json  # Validation messages
    fr/
      fr.json          # General translations (default namespace)
      fields.json      # Form field labels
      validation.json  # Validation messages
Example en.json (general translations):
{
  "hello": "Hello",
  "welcome": "Welcome {name}!",
  "item_count": "no items | {count} item | {count} items",
  "current_time": "Current time: {time}",
  "user_greeting": "Hello {name}, welcome back!"
}
Example fields.json (form field labels):
{
  "email": "Email Address",
  "password": "Password",
**Example `validation.json` (validation messages):**
```json
{
  "required": "This field is required",
  "email_invalid": "Please enter a valid email address",
  "password_too_short": "Password must be at least 8 characters",
  "passwords_not_match": "Passwords do not match",
  "phone_invalid": "Please enter a valid phone number",
  "min_length": "Minimum length is {min} characters",
  "max_length": "Maximum length is {max} characters"
}
### 2. Initialize the Package
```dart
import 'package:flutter/material.dart';
import 'package:flutter_locale_master/flutter_locale_master.dart';
void main() async {
  WidgetsFlutterBinding.ensureInitialized();
  // Initialize with asset translations
  final localeMaster = await FlutterLocaleMaster.initialize(
    basePath: 'lang/',
    initialLocale: const Locale('en'),
    fallbackLocale: const Locale('en'),
  );
  runApp(MyApp(localeMaster: localeMaster));
}
3. Wrap Your App #
class MyApp extends StatelessWidget {
  final FlutterLocaleMaster localeMaster;
  const MyApp({super.key, required this.localeMaster});
  @override
  Widget build(BuildContext context) {
    return localeMaster.wrapApp(
      (locale) => MaterialApp(
        title: 'My App',
        localizationsDelegates: [
          localeMaster.delegate,
          GlobalMaterialLocalizations.delegate,
          GlobalWidgetsLocalizations.delegate,
          GlobalCupertinoLocalizations.delegate,
        ],
        supportedLocales: localeMaster.supportedLocales,
        locale: locale,
        home: const HomePage(),
      ),
    );
  }
}
That's it! Your app now supports multiple languages with automatic RTL/LTR switching.
π― Usage Examples #
Basic Translation #
Using Widgets (Recommended)
class HomePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: TranslatedText('app_title'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            TranslatedText(
              'welcome',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
            const SizedBox(height: 20),
            TranslatedText(
              'current_time',
              parameters: {'time': DateTime.now().toString()},
            ),
          ],
        ),
      ),
    );
  }
}
Using Context Extensions
class ProfilePage extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Column(
      children: [
        Text(context.tr('profile_title')),
        Text(context.tr('welcome', parameters: {'name': user.name})),
        Text(context.plural('item_count', itemCount)),
        Text(context.field('email')),
      ],
    );
  }
}
Using String Extensions
class Utils {
  static String getGreeting(String userName) {
    return 'welcome'.tr(parameters: {'name': userName});
  }
  static String formatItemCount(int count) {
    return 'item_count'.plural(count);
  }
  static bool hasTranslation(String key) {
    return key.exists();
  }
}
class FormLabels {
  static String get email => 'email'.field();
  static String get password => 'password'.field();
}
Advanced Features #
Locale Management
class LanguageSelector extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return DropdownButton<Locale>(
      value: context.currentLocaleObj,
      items: context.supportedLocales.map((localeString) {
        final locale = Locale(localeString);
        return DropdownMenuItem(
          value: locale,
          child: Text(locale.languageCode.toUpperCase()),
        );
      }).toList(),
      onChanged: (newLocale) {
        if (newLocale != null) {
          context.setLocaleObj(newLocale);
        }
      },
    );
  }
}
Rich Text Translation
TranslatedRichText.rich(
  'terms_agreement',
  parameters: {'app': 'MyApp'},
  spanBuilder: (translatedText) {
    final parts = translatedText.split('{app}');
    return TextSpan(
      children: [
        TextSpan(text: parts[0]),
        TextSpan(
          text: 'MyApp',
          style: TextStyle(fontWeight: FontWeight.bold),
        ),
        if (parts.length > 1) TextSpan(text: parts[1]),
      ],
    );
  },
)
Locale Consumer for Complex UI
class AdaptiveLayout extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return LocaleConsumer(
      builder: (context, localization, child) {
        final isRTL = localization.notifier.isRTL;
        return Directionality(
          textDirection: isRTL ? TextDirection.rtl : TextDirection.ltr,
          child: Row(
            children: [
              if (!isRTL) child!,
              Expanded(
                child: Text(localization.provider.t('content')),
              ),
              if (isRTL) child!,
            ],
          ),
        );
      },
      child: IconButton(
        icon: Icon(Icons.menu),
        onPressed: () => Scaffold.of(context).openDrawer(),
      ),
    );
  }
}
π§ API Reference #
FlutterLocaleMaster (Singleton) #
| Method | Description | 
|---|---|
initialize() | 
Initialize the localization system | 
wrapApp() | 
Wrap MaterialApp with localization support | 
tr() | 
Translate a key with optional parameters | 
plural() | 
Translate with pluralization | 
field() | 
Translate a field key | 
setLocale() | 
Change the current locale | 
reset() | 
Reset to initial locale | 
resetToSystemLocale() | 
Reset to system locale | 
isCurrentLocale() | 
Check if locale is current | 
toggleLocale() | 
Toggle between two locales | 
supportedLocales | 
Get supported locales | 
isLocaleSupported() | 
Check if locale is supported | 
currentLocale | 
Get current locale | 
textDirection | 
Get current text direction | 
BuildContext Extensions #
| Method | Description | 
|---|---|
tr() | 
Translate with parameters and namespace | 
plural() | 
Pluralize with count | 
field() | 
Translate field keys | 
hasTranslation() | 
Check if key exists | 
setLocale() | 
Set locale by string | 
setLocaleObj() | 
Set locale by Locale object | 
currentLocale | 
Get current locale string | 
currentLocaleObj | 
Get current locale object | 
supportedLocales | 
Get supported locales | 
fallbackLocale | 
Get fallback locale | 
textDirection | 
Get text direction | 
isRTL | 
Check if current locale is RTL | 
String Extensions #
| Method | Description | 
|---|---|
tr() | 
Translate string key | 
plural() | 
Pluralize string key | 
field() | 
Translate as field key | 
exists() | 
Check if translation exists | 
Widgets #
| Widget | Description | 
|---|---|
TranslatedText | 
Simple translated text widget | 
TranslatedRichText | 
Rich translated text widget | 
LocaleConsumer | 
Consumer that rebuilds on locale change | 
ποΈ Architecture #
Flutter Locale Master follows a clean, layered architecture:
βββββββββββββββββββ
β   Extensions    β  String & Context APIs
βββββββββββββββββββ€
β    Widgets      β  TranslatedText, LocaleConsumer
βββββββββββββββββββ€
β   Controllers   β  Locale state management
βββββββββββββββββββ€
β   Providers     β  Translation data access
βββββββββββββββββββ€
β   Services      β  Core functionality
βββββββββββββββββββ
Key Components #
- Services Layer: Asset loading, caching, validation, pluralization
 - Providers Layer: Translation data management and access
 - Controllers Layer: Locale state and change notifications
 - Widgets Layer: Reactive UI components
 - Extensions Layer: Developer-friendly APIs
 
π Automatic Text Direction #
The package automatically handles RTL/LTR switching:
- LTR Languages: English, French, German, Spanish, etc.
 - RTL Languages: Arabic, Hebrew, Persian, Urdu, etc.
 
// Automatic RTL support - no extra code needed!
class MyWidget extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: TranslatedText('app_title'), // Automatically RTL in Arabic
      ),
      body: TranslatedText('content'), // Text direction adapts automatically
    );
  }
}
π Translation File Organization #
Basic Structure #
assets/
  lang/
    en/
      en.json          # General messages
      fields.json      # Form field labels
      validation.json  # Validation messages
    ar/
      ar.json
      fields.json
      validation.json
Namespace Usage #
// Access general translations (default namespace from en.json)
context.tr('welcome')
// Access fields namespace (from fields.json)
context.field('email')  // Same as: context.tr('email', namespace: 'fields')
// Access validation namespace (from validation.json)
context.tr('required', namespace: 'validation')
Pluralization Syntax #
{
  "item": "no items | {count} item | {count} items",
  "day": "today | yesterday | {count} days ago"
}
π§ͺ Testing #
The package includes comprehensive tests. Run tests with:
flutter test
Example test:
void main() {
  test('Translation loading', () async {
    final localeMaster = await FlutterLocaleMaster.initialize(
      basePath: 'lang/',
    );
    expect(localeMaster.tr('hello'), 'Hello');
    expect(localeMaster.plural('item', 2), '2 items');
  });
}
οΏ½ Performance #
- 
Preloading: All translations loaded at startup
 - 
Caching: In-memory caching prevents disk I/O
 - 
Lazy initialization: Singleton pattern prevents waste
 - 
Concurrent loading: Multiple files loaded simultaneously
 - 
Minimal rebuilds: Only affected widgets update on locale change
 - 
Preloading: All translations loaded at startup
 - 
Caching: In-memory caching prevents disk I/O
 - 
Lazy initialization: Singleton pattern prevents waste
 - 
Concurrent loading: Multiple files loaded simultaneously
 - 
Minimal rebuilds: Only affected widgets update on locale change
 
π€ Contributing #
Contributions are welcome! Please:
- Fork the repository
 - Create a feature branch
 - Add tests for new features
 - Ensure all tests pass
 - Update documentation
 - Submit a pull request
 
π License #
MIT License - see LICENSE file for details.
π Support #
- π Documentation
 - π Issues
 - π¬ Discussions
 
Made with β€οΈ for the Flutter community