Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Simple app localization with JSON as input format and access without BuildContext. Used on https://www.flutterclutter.dev/flutter/tutorials/internationalization-i18n-in-flutter-an-easy-and-quick-approach/2020/213/
import 'dart:convert';
import 'dart:ui';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
class AppLocalizations {
AppLocalizations(this.locale);
final Locale fallbackLocale = Locale('en');
static AppLocalizations of(BuildContext context) {
return Localizations.of<AppLocalizations>(context, AppLocalizations);
}
static AppLocalizations instance;
AppLocalizations._init(Locale locale) {
instance = this;
this.locale = locale;
}
static const LocalizationsDelegate<AppLocalizations> delegate = _AppLocalizationsDelegate();
Locale locale;
Map<String, String> _localizedStrings;
Map<String, String> _fallbackLocalizedStrings;
Future<void> load() async {
_localizedStrings = await _loadLocalizedStrings(locale);
_fallbackLocalizedStrings = {};
if (locale != fallbackLocale) {
_fallbackLocalizedStrings = await _loadLocalizedStrings(fallbackLocale);
}
}
Future<Map<String, String>> _loadLocalizedStrings(Locale localeToBeLoaded) async {
String jsonString;
Map<String, String> localizedStrings = {};
try {
jsonString = await rootBundle.loadString('assets/translations/${localeToBeLoaded.languageCode}.json');
} catch (exception) {
print(exception);
return localizedStrings;
}
Map<String, dynamic> jsonMap = json.decode(jsonString);
localizedStrings = jsonMap.map((key, value) {
return MapEntry(key, value.toString());
});
return localizedStrings;
}
String translate(String key, [Map<String, String> arguments]) {
String translation = _localizedStrings[key];
translation = translation ?? _fallbackLocalizedStrings[key];
translation = translation ?? "";
if (arguments == null || arguments.length == 0) {
return translation;
}
arguments.forEach((argumentKey, value) {
if (value == null) {
print('Value for "$argumentKey" is null in call of translate(\'$key\')');
value = '';
}
translation = translation.replaceAll("\$$argumentKey", value);
});
return translation;
}
}
class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
const _AppLocalizationsDelegate();
@override
bool isSupported(Locale locale) {
return true;
}
@override
Future<AppLocalizations> load(Locale locale) async {
AppLocalizations localizations = AppLocalizations._init(locale);
await localizations.load();
return localizations;
}
@override
bool shouldReload(_AppLocalizationsDelegate old) => false;
}
{
"string": "Beeindruckend!",
"string_with_interpolation": "Hey $name, wie geht es dir?"
}
{
"string": "Impressive!",
"string_with_interpolation": "Hey $name, how are you?"
}
import 'package:flutter/material.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:flutterclutter/app_localizations.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
supportedLocales: [
const Locale('en', 'US'),
const Locale('de', 'DE'),
],
localizationsDelegates: [
AppLocalizations.delegate,
GlobalMaterialLocalizations.delegate,
],
home: MyHomePage(title: "Flutterclutter: i18n",),
);
}
}
class MyHomePage extends StatelessWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(title),
),
body: Builder(
builder: (context) {
return Padding(
padding: EdgeInsets.all(16),
child: Center(
child: Text(
AppLocalizations.instance.translate(
'string_with_interpolation',
{'name': 'Test'}
),
style: TextStyle(
fontSize: 32
),
)
)
);
}
)
);
}
}
...
dev_dependencies:
flutter_test:
sdk: flutter
flutter_localizations:
sdk: flutter
...
flutter:
...
assets:
- assets/
- assets/translations/de.json
- assets/translations/en.json
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment