flutter_bhasha 1.0.1 copy "flutter_bhasha: ^1.0.1" to clipboard
flutter_bhasha: ^1.0.1 copied to clipboard

A production-grade Flutter localization package with dynamic language switching, JSON translations, RTL/LTR support, interpolation, fallback language, persistent storage, and a clean developer API.

example/lib/main.dart

import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutter_bhasha/flutter_bhasha.dart';
import 'package:provider/provider.dart';

// ── Supported locales ─────────────────────────────────────────────────────

const enLocale = BhashaLocale(
  languageCode: 'en',
  displayName: 'English',
  nativeName: 'English',
  flagEmoji: '🇺🇸',
);

const teLocale = BhashaLocale(
  languageCode: 'te',
  displayName: 'Telugu',
  nativeName: 'తెలుగు',
  flagEmoji: '🇮🇳',
);

const hiLocale = BhashaLocale(
  languageCode: 'hi',
  displayName: 'Hindi',
  nativeName: 'हिन्दी',
  flagEmoji: '🇮🇳',
);

const arLocale = BhashaLocale(
  languageCode: 'ar',
  displayName: 'Arabic',
  nativeName: 'العربية',
  flagEmoji: '🇸🇦',
  textDirection: TextDirection.rtl,
);

// ── Entry point ───────────────────────────────────────────────────────────

Future<void> main() async {
  WidgetsFlutterBinding.ensureInitialized();

  final controller = await BhashaController.initialize(
    config: const BhashaConfig(
      supportedLocales: [enLocale, teLocale, hiLocale, arLocale],
      fallbackLocale: enLocale,
      // Example app bundles its own translation files directly.
      assetPath: 'assets/translations',
      persistLocale: true,
      useDeviceLocale: true,
      logMissingKeys: true,
    ),
  );

  runApp(
    BhashaProvider(
      controller: controller,
      child: const ExampleApp(),
    ),
  );
}

// ── Root app ──────────────────────────────────────────────────────────────

class ExampleApp extends StatelessWidget {
  const ExampleApp({super.key});

  @override
  Widget build(BuildContext context) {
    final controller = context.watch<BhashaController>();
    return MaterialApp(
      title: 'flutter_bhasha Demo',
      debugShowCheckedModeBanner: false,
      locale: controller.currentLocale.toLocale(),
      supportedLocales: controller.config.flutterLocales,
      localizationsDelegates: const [
        GlobalMaterialLocalizations.delegate,
        GlobalWidgetsLocalizations.delegate,
        GlobalCupertinoLocalizations.delegate,
      ],
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.indigo),
        useMaterial3: true,
      ),
      home: const HomeScreen(),
    );
  }
}

// ── Home screen ───────────────────────────────────────────────────────────

class HomeScreen extends StatefulWidget {
  const HomeScreen({super.key});

  @override
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  final _nameController = TextEditingController(text: 'Ravi');

  @override
  void dispose() {
    _nameController.dispose();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    final controller = context.watch<BhashaController>();
    final name = _nameController.text;

    return Directionality(
      textDirection: controller.textDirection,
      child: Scaffold(
        appBar: AppBar(
          title: Text(context.tr('settings')),
          actions: [
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 12),
              child: LanguageSelectorDropdown(
                style: const TextStyle(fontSize: 14),
              ),
            ),
          ],
        ),
        body: SingleChildScrollView(
          padding: const EdgeInsets.all(24),
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.stretch,
            children: [
              // ── Greeting card ───────────────────────────────────────────
              Card(
                child: Padding(
                  padding: const EdgeInsets.all(20),
                  child: Column(
                    crossAxisAlignment: CrossAxisAlignment.start,
                    children: [
                      Text(
                        context.tr('hello'),
                        style: Theme.of(context).textTheme.headlineMedium,
                      ),
                      const SizedBox(height: 8),
                      Text(
                        context.tr('welcome', params: {'name': name}),
                        style: Theme.of(context).textTheme.titleMedium,
                      ),
                    ],
                  ),
                ),
              ),

              const SizedBox(height: 16),

              // ── Name input ──────────────────────────────────────────────
              TextField(
                controller: _nameController,
                decoration: InputDecoration(
                  labelText:
                      context.tr('auth.email').replaceAll('Email', 'Name'),
                  border: const OutlineInputBorder(),
                ),
                onChanged: (_) => setState(() {}),
              ),

              const SizedBox(height: 24),

              // ── Translation showcase ────────────────────────────────────
              _SectionHeader(title: 'Translations'),
              _TranslationRow(key_: 'auth.login'),
              _TranslationRow(key_: 'auth.logout'),
              _TranslationRow(key_: 'auth.forgot_password'),
              _TranslationRow(key_: 'errors.network'),
              _TranslationRow(
                key_: 'auth.welcome_back',
                params: {'name': name},
              ),
              _TranslationRow(
                key_: 'home.greeting',
                params: {'timeOfDay': 'morning', 'name': name},
              ),

              const SizedBox(height: 24),

              // ── Language picker list tile ───────────────────────────────
              _SectionHeader(title: 'Language Picker'),
              Card(
                child: LanguageSelectorListTile(
                  title: context.tr('language'),
                ),
              ),

              const SizedBox(height: 24),

              // ── RTL / LTR indicator ─────────────────────────────────────
              _SectionHeader(title: 'Text Direction'),
              Card(
                child: Padding(
                  padding: const EdgeInsets.all(16),
                  child: Row(
                    children: [
                      Icon(
                        controller.isRTL
                            ? Icons.format_textdirection_r_to_l
                            : Icons.format_textdirection_l_to_r,
                        size: 28,
                        color: Colors.indigo,
                      ),
                      const SizedBox(width: 12),
                      Text(
                        controller.isRTL
                            ? 'Right-to-Left (RTL)'
                            : 'Left-to-Right (LTR)',
                        style: Theme.of(context).textTheme.titleMedium,
                      ),
                    ],
                  ),
                ),
              ),

              const SizedBox(height: 24),

              // ── Action buttons ──────────────────────────────────────────
              _SectionHeader(title: 'Actions'),
              Wrap(
                spacing: 8,
                runSpacing: 8,
                children: [
                  ElevatedButton(
                    onPressed: () => controller.resetLocale(),
                    child: Text(context.tr('retry')),
                  ),
                  OutlinedButton(
                    onPressed: () => controller.setLocaleByCode('te'),
                    child: const Text('Switch → తెలుగు'),
                  ),
                  OutlinedButton(
                    onPressed: () => controller.setLocaleByCode('ar'),
                    child: const Text('Switch → العربية'),
                  ),
                ],
              ),
            ],
          ),
        ),
      ),
    );
  }
}

// ── Helper widgets ────────────────────────────────────────────────────────

class _SectionHeader extends StatelessWidget {
  const _SectionHeader({required this.title});
  final String title;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.only(bottom: 8),
      child: Text(
        title,
        style: Theme.of(context)
            .textTheme
            .labelLarge
            ?.copyWith(color: Colors.indigo, fontWeight: FontWeight.bold),
      ),
    );
  }
}

class _TranslationRow extends StatelessWidget {
  const _TranslationRow({required this.key_, this.params});
  final String key_;
  final Map<String, dynamic>? params;

  @override
  Widget build(BuildContext context) {
    return Padding(
      padding: const EdgeInsets.symmetric(vertical: 4),
      child: Row(
        children: [
          SizedBox(
            width: 180,
            child: Text(
              key_,
              style: const TextStyle(
                fontFamily: 'monospace',
                fontSize: 12,
                color: Colors.grey,
              ),
            ),
          ),
          Expanded(
            child: Text(
              context.tr(key_, params: params),
              style: const TextStyle(fontSize: 14),
            ),
          ),
        ],
      ),
    );
  }
}
0
likes
140
points
41
downloads

Documentation

API reference

Publisher

unverified uploader

Weekly Downloads

A production-grade Flutter localization package with dynamic language switching, JSON translations, RTL/LTR support, interpolation, fallback language, persistent storage, and a clean developer API.

Repository (GitHub)
View/report issues

Topics

#localization #i18n #l10n #multilingual #flutter

License

MIT (license)

Dependencies

flutter, flutter_localizations, intl, provider, shared_preferences

More

Packages that depend on flutter_bhasha