In flutter string text are directly set to the TextField
widget like:
new Text(\'Hello, How are you?\')
Is correct way ? or we ca
I would separate these classes into individual files, but just to explain my approach for this question.
I have a base class which has my strings getters. Each language I want to support I have to create a class which extends from this class and override its getters. Thus, whenever I create a string, I have to override in each implementation of this base class. It is helpful to avoid forgetting create some locale specific string.
/// Interface strings
class Strings {
String get hello;
}
/// English strings
class StringsEnglish extends Strings {
@override
String get hello => 'Hello';
}
/// Russian strings
class StringsRussian extends Strings {
@override
String get hello => 'Привет';
}
/// Portuguese strings
class StringsPortuguese extends Strings {
@override
String get hello => 'Olá';
}
After that, in a global scope of your application, you could declare a unique instance of the locale you want to use (using a singleton is a good option).
Just showing a short example of using it:
class Resources {
BuildContext _context;
Resources(this._context);
Strings get strings {
// It could be from the user preferences or even from the current locale
Locale locale = Localizations.localeOf(_context);
switch (locale.languageCode) {
case 'pt':
return StringsPortuguese();
case 'ru':
return StringsRussian();
default:
return StringsEnglish();
}
}
static Resources from(BuildContext context){
return Resources(context);
}
}
And finally, using it in some widget:
Text(Resources.from(context).strings.hello)
Using an extension from BuildContext
You can extend BuildContext to create some particular features and give more power to your application. This is available from Dart 2.7. See more.
app_context_extension.dart
extension AppContext on BuildContext {
Resources get resources => Resources.from(this);
}
favorites_page.dart
import 'package:flutter/material.dart';
// you have to import it yourself. The auto import does not work in this case
import 'package:myapp/ui/extensions/app_context_extension.dart';
class FavoritesPage extends StatefulWidget {
@override
_FavoritesPageState createState() => _FavoritesPageState();
}
class _FavoritesPageState extends State {
@override
Widget build(BuildContext context) {
return Text(context.resources.strings.hello);
}
}
Using GlobalKey
Along with an extension of BuildContext as shown above, you can also use GlobalKey. Basically, you could use it when you do not have a context instance. This last one has a good advantage. You could use strings anywhere in your application. In other words, if you use some pattern like MVC for instance and want to use strings in your controllers, you could easily do it.
You can declare something like this:
application.dart
import 'package:myapp/ui/extensions/app_context_extension.dart';
import 'package:myapp/ui/values/resources.dart';
import 'package:flutter/material.dart';
class Application {
static GlobalKey navKey = GlobalKey();
static Resources get resources {
return navKey.currentContext.resources;
}
}
main.dart
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
navigatorKey: Application.navKey,
...
And then:
import 'package:flutter/material.dart';
import 'package:myapp/application/application.dart';
class FavoritesPage extends StatefulWidget {
@override
_FavoritesPageState createState() => _FavoritesPageState();
}
class _FavoritesPageState extends State {
@override
Widget build(BuildContext context) {
return Text(Application.resources.strings.hello);
}
}
Hope it helps!