- Регистрация
- 1 Мар 2015
- Сообщения
- 1,481
- Баллы
- 155
When building multilingual Flutter apps, the usual go-to for localization is .arb or .json files. But what if your app needs something more dynamic? What if translations can be edited by an admin? Or fetched from your backend? That’s where SQLite shines. ?
In this article, we’ll walk through setting up a SQLite-powered translation system in Flutter that’s flexible, updatable at runtime, and great for user- or admin-generated content. Ready? Let’s go!
?️ Step 1: Add Dependencies
First, pull in the packages you’ll need:
dependencies:
sqflite: ^2.3.0
path_provider: ^2.1.1
flutter_localizations:
sdk: flutter
sqflite helps us talk to the local database, and path_provider gives us the app’s file path to store it.
? Step 2: Create a Translations Table
Define your schema like this:
CREATE TABLE translations (
id INTEGER PRIMARY KEY,
locale TEXT,
key TEXT,
value TEXT
);
This simple table holds everything you need: the language (locale), the key (key), and its translation (value).
? Step 3: Translation Service
Let’s load the translations into memory so we can use them in the app:
class TranslationService {
final Database db;
TranslationService(this.db);
Future<Map<String, String>> loadTranslations(String locale) async {
final List<Map<String, dynamic>> result = await db.query(
'translations',
where: 'locale = ?',
whereArgs: [locale],
);
return {
for (var row in result) row['key'] as String: row['value'] as String,
};
}
}
This service pulls all translation entries for a given locale and returns them as a Map.
? Step 4: Custom Localization Delegate
Instead of using .arb files, we’ll build a LocalizationsDelegate that loads from SQLite.
class SQLiteLocalizationDelegate extends LocalizationsDelegate<SQLiteLocalizations> {
final TranslationService service;
SQLiteLocalizationDelegate(this.service);
@override
bool isSupported(Locale locale) => true;
@override
Future<SQLiteLocalizations> load(Locale locale) async {
final translations = await service.loadTranslations(locale.languageCode);
return SQLiteLocalizations(translations);
}
@override
bool shouldReload(covariant LocalizationsDelegate old) => false;
}
class SQLiteLocalizations {
final Map<String, String> _localizedStrings;
SQLiteLocalizations(this._localizedStrings);
String translate(String key) => _localizedStrings[key] ?? key;
static SQLiteLocalizations of(BuildContext context) =>
Localizations.of<SQLiteLocalizations>(context, SQLiteLocalizations)!;
}
With this setup, your app knows how to fetch translations from the database based on the current locale.
? Step 5: Plug It Into Your App
Now wire everything up in your MaterialApp:
MaterialApp(
localizationsDelegates: [
SQLiteLocalizationDelegate(translationService),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: [Locale('en'), Locale('es')],
home: MyHomePage(),
);
And wherever you need a translation:
Text(SQLiteLocalizations.of(context).translate('hello'));
Boom ? — your app is now powered by dynamic, database-driven translations!
Why Go with SQLite?
Using SQLite gives you:
Runtime translation updates
Support for admin or user-managed content
Easy syncing with backend-localized data
A clean, scalable structure for multi-language apps
This is especially useful for apps with content that evolves over time or needs customization per user.
? Final Thoughts
Localization doesn’t have to be static or boring. By swapping .arb files for a SQLite database, you give your Flutter app a serious power-up in flexibility and scalability. This pattern fits perfectly in modern, data-driven apps where translation isn’t just a file — it’s part of your content strategy.
Let's Connect! ?
If you found this helpful and want to stay updated with more Flutter tips, feel free to follow me:
? Dev.to:
? LinkedIn:
? GitHub:
Happy coding! ?
In this article, we’ll walk through setting up a SQLite-powered translation system in Flutter that’s flexible, updatable at runtime, and great for user- or admin-generated content. Ready? Let’s go!
?️ Step 1: Add Dependencies
First, pull in the packages you’ll need:
dependencies:
sqflite: ^2.3.0
path_provider: ^2.1.1
flutter_localizations:
sdk: flutter
sqflite helps us talk to the local database, and path_provider gives us the app’s file path to store it.
? Step 2: Create a Translations Table
Define your schema like this:
CREATE TABLE translations (
id INTEGER PRIMARY KEY,
locale TEXT,
key TEXT,
value TEXT
);
This simple table holds everything you need: the language (locale), the key (key), and its translation (value).
? Step 3: Translation Service
Let’s load the translations into memory so we can use them in the app:
class TranslationService {
final Database db;
TranslationService(this.db);
Future<Map<String, String>> loadTranslations(String locale) async {
final List<Map<String, dynamic>> result = await db.query(
'translations',
where: 'locale = ?',
whereArgs: [locale],
);
return {
for (var row in result) row['key'] as String: row['value'] as String,
};
}
}
This service pulls all translation entries for a given locale and returns them as a Map.
? Step 4: Custom Localization Delegate
Instead of using .arb files, we’ll build a LocalizationsDelegate that loads from SQLite.
class SQLiteLocalizationDelegate extends LocalizationsDelegate<SQLiteLocalizations> {
final TranslationService service;
SQLiteLocalizationDelegate(this.service);
@override
bool isSupported(Locale locale) => true;
@override
Future<SQLiteLocalizations> load(Locale locale) async {
final translations = await service.loadTranslations(locale.languageCode);
return SQLiteLocalizations(translations);
}
@override
bool shouldReload(covariant LocalizationsDelegate old) => false;
}
class SQLiteLocalizations {
final Map<String, String> _localizedStrings;
SQLiteLocalizations(this._localizedStrings);
String translate(String key) => _localizedStrings[key] ?? key;
static SQLiteLocalizations of(BuildContext context) =>
Localizations.of<SQLiteLocalizations>(context, SQLiteLocalizations)!;
}
With this setup, your app knows how to fetch translations from the database based on the current locale.
? Step 5: Plug It Into Your App
Now wire everything up in your MaterialApp:
MaterialApp(
localizationsDelegates: [
SQLiteLocalizationDelegate(translationService),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: [Locale('en'), Locale('es')],
home: MyHomePage(),
);
And wherever you need a translation:
Text(SQLiteLocalizations.of(context).translate('hello'));
Boom ? — your app is now powered by dynamic, database-driven translations!
Using SQLite gives you:
This is especially useful for apps with content that evolves over time or needs customization per user.
? Final Thoughts
Localization doesn’t have to be static or boring. By swapping .arb files for a SQLite database, you give your Flutter app a serious power-up in flexibility and scalability. This pattern fits perfectly in modern, data-driven apps where translation isn’t just a file — it’s part of your content strategy.
Let's Connect! ?
If you found this helpful and want to stay updated with more Flutter tips, feel free to follow me:
? Dev.to:
? LinkedIn:
? GitHub:
Happy coding! ?