Hey there, Flutter fam! 👋
Welcome back to another exciting adventure in the world of Flutter! Are you looking to make your Flutter app multilingual(i18n)? Today, we're diving into something that can truly take your app global: Multilanguage Support using GetX. 🌍
If you've ever thought:
"How can I make my Flutter app support more languages without
jumping through hoops?"
Whether you're targeting global users, improving accessibility,
or just want to offer a localized user experience, you are in
the right place. Grab your coffee☕ --this blog post is for you!
Why bother with Multilanguage Support?
Picture this:
You build an amazing app. Clean UI, slick animations, and top-notch
performance. But... it only supports English. 😬That means you're
unintentionally ignoring a massive chunk of the global
audience!
Adding multilanguage support:
- Increases your user base📈
- Improves accessibility
- Delivers a personalized experience🌎
And the best part?
GetX makes it smooth --no app restart, no drama. Let's get
multilingual!
Step 1: Setting Up the Main File (main.dart)
Here, we set the stage. We're going to initialize our
dependencies(especially for languages) and set up GetMaterialApp
to handle our multilingual magic.
Future<void> main() async {
WidgetsFlutterBinding.ensureInitialized();
await GetStorage.init();
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
await FirebaseAppCheck.instance.activate(
androidProvider: AndroidProvider.playIntegrity,
appleProvider: AppleProvider.appAttestWithDeviceCheckFallback,
);
Map<String, Map<String, String>>? languages = await di.init();
runApp(MyApp(languages: languages));
}
Now for the MyApp widget
Notice how each locale has a unique key (
class MyApp extends StatelessWidget {
final Map<String, Map<String, String>>? languages;
const MyApp({super.key, this.languages});
@override
Widget build(BuildContext context) {
return _buildApp(context);
}
Widget _buildApp(BuildContext context) {
return GetBuilder<LocalizationController>(
builder: (localizeController) {
return GetMaterialApp(
locale: localizeController.locale, // Fixed typo
translations: Message(
languages: languages,
), // Assuming Message handles translations
);
},
);
}
}
Step 2: Initializing dependencies (init.dart)
This is where we load the user's saved language from SharedPreferences
and lazily inject services like API clients and language repositories. Why
lazyPut? It ensures the object is only created when it is needed, saving
resources and speeding up app startup.
Future<Map<String, Map<String, String>>?> init() async {
final sharedPreferences = await SharedPreferences.getInstance();
Get.lazyPut(() => ApiClient());
Get.lazyPut(() => sharedPreferences);
Get.lazyPut(() => LanguageRepo());
Get.lazyPut(() => LocalizationController(
sharedPreferences: Get.find(), languageRepo: Get.find()));
Map<String, Map<String, String>>? mappedJson =
await Get.find<LocalizationController>().getLanguages();
return mappedJson;
}
Step 3: Fetching Translations with fallback (getLanguages())
In this step, we try to fetch the translation file from Firebase(dynamic,
updatable content), and if that fails(e.g,. no internet), we gracefully
fall back to a local asset that we will be saving inside the assets
folder.
Map<String, Map<String, String>>? mappedJson = {};
Future<Map<String, Map<String, String>>?> getLanguages() async {
try {
final http.Response response = await languageRepo.getLanguages();
if (response.statusCode == 200) {
var responseBody = json.decode(
utf8.decode(
response.bodyBytes,
),
);
responseBody.forEach(
(
key,
value,
) {
if (value is Map) {
mappedJson?[key] = value.map(
(innerKey, innerValue) {
return MapEntry(
innerKey,
innerValue.toString(),
);
},
);
}
},
);
return mappedJson;
} else {
return null;
}
} catch (e) {
final context = Get.context;
if (context != null) {
final String data = await DefaultAssetBundle.of(
context,
).loadString(
'assets/language/translation.json',
);
mappedJson = json.decode(
data,
);
}
return mappedJson;
}
}
Step 4: The Magical .tr Method (text.tr)
This is where it gets fun. To make a string translatable, just wrap it
with .tr, that's it.
Text("hello_world".tr)
Sample Translation file(translation.json)
Place this file in your assets/language/ directory. And don't forget to
declare it in your pubspec.yaml
{
"en_US": {
"hello_world": "Hello World"
},
"ar_SA": {
"hellow_world": "مرحبا بالعالم"
}
}
en_US
, ar_SA
) and inside that, a
bunch of key-value translation pairs.
By following this guide, you've just enabled your Flutter localization with
supported offline fallback. Now, your Flutter app is ready for the
world.
💬 Loved This Guide?
- ⭐ Bookmark it!
- 🔁 Share it with your dev squad.
- 💬 Comment below if you need help with dynamic translation loading or auto language detection.