Flutter Get Current Locale: Complete Guide to Detecting User Language
Knowing your user's current locale is essential for delivering personalized experiences. Whether you need to format dates, display the right currency, or load appropriate translations, Flutter provides several ways to get the current locale.
Quick Answer: Get Current Locale
// Method 1: From BuildContext (most common)
Locale currentLocale = Localizations.localeOf(context);
// Method 2: Platform locale (device setting)
Locale deviceLocale = WidgetsBinding.instance.platformDispatcher.locale;
// Method 3: All preferred locales
List<Locale> preferredLocales = WidgetsBinding.instance.platformDispatcher.locales;
Understanding Locale in Flutter
A Locale object contains:
- languageCode: ISO 639-1 code (e.g., 'en', 'es', 'zh')
- countryCode: ISO 3166-1 code (e.g., 'US', 'GB', 'CN')
- scriptCode: Script variant (e.g., 'Hans', 'Hant' for Chinese)
Locale locale = Locale('en', 'US');
print(locale.languageCode); // 'en'
print(locale.countryCode); // 'US'
print(locale.toString()); // 'en_US'
Method 1: Get App's Current Locale (Recommended)
This returns the locale currently used by your app's localization system:
import 'package:flutter/material.dart';
class MyWidget extends StatelessWidget {
@override
Widget build(BuildContext context) {
// Get the locale your app is currently using
Locale currentLocale = Localizations.localeOf(context);
print('Language: ${currentLocale.languageCode}');
print('Country: ${currentLocale.countryCode}');
return Text('Current: ${currentLocale.toString()}');
}
}
When to use: When you need the locale your app is actually displaying content in.
Method 2: Get Device/Platform Locale
This returns the user's device language setting:
import 'package:flutter/widgets.dart';
// Get primary device locale
Locale deviceLocale = WidgetsBinding.instance.platformDispatcher.locale;
// Get all preferred locales (user's language preference list)
List<Locale> allLocales = WidgetsBinding.instance.platformDispatcher.locales;
When to use: When you want to know what language the user prefers, regardless of what your app supports.
Method 3: Get Locale Without Context
Sometimes you need the locale outside of a widget (in a service, repository, or utility function):
Option A: Global Navigator Key
// In your app setup
final GlobalKey<NavigatorState> navigatorKey = GlobalKey<NavigatorState>();
MaterialApp(
navigatorKey: navigatorKey,
// ...
)
// Anywhere in your code
Locale? getLocaleWithoutContext() {
final context = navigatorKey.currentContext;
if (context != null) {
return Localizations.localeOf(context);
}
return null;
}
Option B: Platform Dispatcher (No Context Needed)
import 'dart:ui' as ui;
Locale getDeviceLocale() {
return ui.PlatformDispatcher.instance.locale;
}
List<Locale> getAllPreferredLocales() {
return ui.PlatformDispatcher.instance.locales;
}
Option C: Locale Provider with GetIt
import 'package:get_it/get_it.dart';
class LocaleService {
Locale _currentLocale = Locale('en');
Locale get currentLocale => _currentLocale;
void updateLocale(Locale locale) {
_currentLocale = locale;
}
}
// Register
GetIt.I.registerSingleton<LocaleService>(LocaleService());
// Use anywhere
Locale locale = GetIt.I<LocaleService>().currentLocale;
Detecting Locale Changes
Listen for locale changes when the user changes their device language:
class MyApp extends StatefulWidget {
@override
State<MyApp> createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> with WidgetsBindingObserver {
@override
void initState() {
super.initState();
WidgetsBinding.instance.addObserver(this);
}
@override
void dispose() {
WidgetsBinding.instance.removeObserver(this);
super.dispose();
}
@override
void didChangeLocales(List<Locale>? locales) {
// Called when device locale changes
if (locales != null && locales.isNotEmpty) {
print('Device locale changed to: ${locales.first}');
// Handle locale change
}
}
@override
Widget build(BuildContext context) {
return MaterialApp(
// ...
);
}
}
Locale Resolution: How Flutter Chooses
When your app starts, Flutter resolves which locale to use:
MaterialApp(
supportedLocales: [
Locale('en'),
Locale('es'),
Locale('fr'),
],
localeResolutionCallback: (deviceLocale, supportedLocales) {
// Custom resolution logic
for (var locale in supportedLocales) {
if (locale.languageCode == deviceLocale?.languageCode) {
return locale;
}
}
return supportedLocales.first; // Fallback
},
)
Default Resolution Order
- Exact match (language + country):
en_USmatchesen_US - Language match:
en_USmatchesen - First supported locale (fallback)
Common Use Cases
Format Dates Based on Locale
import 'package:intl/intl.dart';
String formatDate(BuildContext context, DateTime date) {
final locale = Localizations.localeOf(context).toString();
return DateFormat.yMMMd(locale).format(date);
}
// Usage
formatDate(context, DateTime.now());
// en_US: "Dec 6, 2025"
// de_DE: "6. Dez. 2025"
// ja_JP: "2025年12月6日"
Format Currency Based on Locale
String formatCurrency(BuildContext context, double amount) {
final locale = Localizations.localeOf(context).toString();
final format = NumberFormat.currency(
locale: locale,
symbol: _getCurrencySymbol(locale),
);
return format.format(amount);
}
// en_US: "$1,234.56"
// de_DE: "1.234,56 €"
// ja_JP: "¥1,235"
Load Locale-Specific Assets
String getLocalizedAsset(BuildContext context, String assetName) {
final locale = Localizations.localeOf(context);
final localizedPath = 'assets/${locale.languageCode}/$assetName';
final defaultPath = 'assets/en/$assetName';
// Check if localized asset exists, otherwise use default
return localizedPath; // Add proper asset checking
}
Store User's Preferred Locale
import 'package:shared_preferences/shared_preferences.dart';
class LocalePreferences {
static const _key = 'user_locale';
static Future<void> saveLocale(Locale locale) async {
final prefs = await SharedPreferences.getInstance();
await prefs.setString(_key, locale.toString());
}
static Future<Locale?> getSavedLocale() async {
final prefs = await SharedPreferences.getInstance();
final localeString = prefs.getString(_key);
if (localeString != null) {
final parts = localeString.split('_');
return Locale(parts[0], parts.length > 1 ? parts[1] : null);
}
return null;
}
}
Complete Example: Locale-Aware App
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/app_localizations.dart';
class LocaleAwareApp extends StatefulWidget {
@override
State<LocaleAwareApp> createState() => _LocaleAwareAppState();
}
class _LocaleAwareAppState extends State<LocaleAwareApp> {
Locale? _locale;
@override
void initState() {
super.initState();
_loadSavedLocale();
}
Future<void> _loadSavedLocale() async {
final savedLocale = await LocalePreferences.getSavedLocale();
if (savedLocale != null) {
setState(() => _locale = savedLocale);
}
}
void _changeLocale(Locale newLocale) {
setState(() => _locale = newLocale);
LocalePreferences.saveLocale(newLocale);
}
@override
Widget build(BuildContext context) {
return MaterialApp(
locale: _locale,
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
home: HomePage(onLocaleChange: _changeLocale),
);
}
}
class HomePage extends StatelessWidget {
final Function(Locale) onLocaleChange;
const HomePage({required this.onLocaleChange});
@override
Widget build(BuildContext context) {
final currentLocale = Localizations.localeOf(context);
final l10n = AppLocalizations.of(context)!;
return Scaffold(
appBar: AppBar(title: Text(l10n.appTitle)),
body: Column(
children: [
Text('Current locale: ${currentLocale.toString()}'),
ElevatedButton(
onPressed: () => onLocaleChange(Locale('en')),
child: Text('English'),
),
ElevatedButton(
onPressed: () => onLocaleChange(Locale('es')),
child: Text('Español'),
),
],
),
);
}
}
Troubleshooting
"Locale not found" Error
// Make sure locale is in supportedLocales
MaterialApp(
supportedLocales: [
Locale('en'),
Locale('es'),
// Add all locales you want to support
],
)
Locale Returns Null
// Use null-safe access
final locale = Localizations.localeOf(context);
// Instead of potentially nullable platform access
Locale Doesn't Update
// Ensure you're calling setState when changing locale
void changeLocale(Locale newLocale) {
setState(() {
_currentLocale = newLocale;
});
}
FlutterLocalisation Makes Locale Management Easy
Managing locales across your app becomes complex fast. FlutterLocalisation helps you:
- ✅ Visual locale management - See all supported locales at a glance
- ✅ Missing translation detection - Know exactly what's missing per locale
- ✅ AI translation - Add new languages instantly
- ✅ Export ready ARB files - Perfectly formatted for Flutter
Stop wrestling with locale code. Try FlutterLocalisation free and manage all your locales from one dashboard.