Magesh Pandian
En flutter string, el texto se establece directamente en el TextField
widget como:
new Text('Hello, How are you?')
¿Es la forma correcta? o podemos mantener todas las cadenas en un archivo y usarlo como:
<string name="name_hint">Hello, How are you?</string>
Es posible ?
MVelocidad
Flutter actualmente no tiene un sistema similar a recursos dedicados para cadenas. Por el momento, la mejor práctica es mantener su copia de texto en una clase como campos estáticos y acceder a ellos desde allí. Por ejemplo:
class Strings {
static const String welcomeMessage = "Welcome To Flutter";
}
Luego, en su código, puede acceder a sus cadenas como tales:
Text(Strings.welcomeMessage)
Edición de mayo de 2019:
ahora hay este paquete que le permite crear archivos json con sus cadenas. Le permitirá crear cadenas para plurales, géneros e idiomas, etc.
Puede crear un archivo json separado para cada idioma de la siguiente manera:
string_en.json
{
"thanks": "Thanks."
}
cadena_nl.json
{
"thanks": "Dankjewel."
}
Y luego usa esto para acceder a él.
S.of(context).thanks;
Sabrá qué idioma elegir según el idioma predeterminado de su teléfono.
-
Tal vez se pueda mejorar haciéndolo singleton también
– atascado desbordamiento
13 de marzo de 2019 a las 7:37
-
Sugiero hacer cada cadena
static const
– André Sousa
18 mayo 2019 a las 22:11
policíasencarretera
Captura de pantalla:
Código completo (seguro nulo):
Para aquellos de ustedes que no quieren usar ningún complemento de terceros, así es como pueden hacerlo.
-
crear una carpeta
strings
enassets
. Ponga su archivo de idioma en él.assets strings - en.json // for english - ru.json // for russian
-
Ahora en
en.json
escriba su cadena, por ejemplo.{ "text1": "Hello", "text2": "World" }
Del mismo modo, en
ru.json
,{ "text1": "Привет", "text2": "Мир" }
-
Añadir esto a
pubspec.yaml
archivo (cuidado con los espacios)flutter: uses-material-design: true assets: - assets/strings/en.json - assets/strings/ru.json flutter_localizations: sdk: flutter
-
Ahora ya está todo listo para usar estas cadenas en su aplicación. Aquí está el código de muestra, el
AppBar
muestra el texto traducido.void main() { runApp( MaterialApp( locale: Locale("ru"), // switch between en and ru to see effect localizationsDelegates: [const DemoLocalizationsDelegate()], supportedLocales: [const Locale('en', ''), const Locale('ru', '')], home: HomePage(), ), ); } class HomePage extends StatelessWidget { @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar(title: Text(DemoLocalizations.of(context).getText("text2") ?? "Error")), ); } } // this class is used for localizations class DemoLocalizations { static DemoLocalizations? of(BuildContext context) { return Localizations.of<DemoLocalizations>(context, DemoLocalizations); } String getText(String key) => language[key]; } late Map<String, dynamic> language; class DemoLocalizationsDelegate extends LocalizationsDelegate<DemoLocalizations> { const DemoLocalizationsDelegate(); @override bool isSupported(Locale locale) => ['en', 'ru'].contains(locale.languageCode); @override Future<DemoLocalizations> load(Locale locale) async { String string = await rootBundle.loadString("assets/strings/${locale.languageCode}.json"); language = json.decode(string); return SynchronousFuture<DemoLocalizations>(DemoLocalizations()); } @override bool shouldReload(DemoLocalizationsDelegate old) => false; }
-
al llamar al método getText() recibo un error como si el método no estuviera definido
–Maaz Patel
27 de mayo de 2020 a las 10:41
-
@MaazPatel ¿Está utilizando el código completo, sin modificarlo?
– Policías en la carretera
27 de mayo de 2020 a las 11:10
-
Actualmente, estoy siguiendo este código completo. más tarde agregaré mis cadenas
–Maaz Patel
27 de mayo de 2020 a las 11:31
-
@MaazPatel No estoy seguro de qué error está cometiendo, pero este es el código completo (probado por otros)
– Policías en la carretera
27 de mayo de 2020 a las 11:34
-
@Fatimaayaa ¿Quiere decir que desea pasar un argumento del archivo json local? Lamentablemente, no puede hacerlo.
– Policías en la carretera
20 de julio de 2021 a las 15:04
Puede utilizar los métodos representados en las secciones de internacionalización de la documentación para controlar tanto la gestión centralizada de cadenas como las traducciones (si necesita traducciones)
https://flutter.io/tutorials/internacionalización/
Sin embargo, podría ser excesivo para una aplicación simple con solo unas pocas cadenas.
Cícero Moura
Separaría estas clases en archivos individuales, pero solo para explicar mi enfoque para esta pregunta.
Tengo una clase base que tiene mis captadores de cadenas. Cada idioma que quiero admitir, tengo que crear una clase que se extienda desde esta clase y anule sus captadores. Por lo tanto, cada vez que creo una cadena, debo anular cada implementación de esta clase base. Es útil evitar olvidarse de crear una cadena específica de configuración regional.
/// Interface strings
class Strings {
String get hello;
}
/// English strings
class EnglishStrings extends Strings {
@override
String get hello => 'Hello';
}
/// Russian strings
class RussianStrings extends Strings {
@override
String get hello => 'Привет';
}
/// Portuguese strings
class PortugueseStrings extends Strings {
@override
String get hello => 'Olá';
}
Después de eso, en un ámbito global de su aplicación, puede declarar una instancia única de la configuración regional que desea usar (usar un singleton es una buena opción).
Solo mostrando un breve ejemplo de su uso:
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 PortugueseStrings();
case 'ru':
return RussianStrings();
default:
return EnglishStrings();
}
}
static Resources of(BuildContext context){
return Resources(context);
}
}
Y finalmente, usándolo en algún widget:
Text(Resources.of(context).strings.hello)
Usando una extensión de BuildContext
Puede extender BuildContext para crear algunas características particulares y darle más poder a su aplicación.
Esto está disponible desde Dardo 2.7. Ver más.
app_context_extension.dart
extension AppContext on BuildContext {
Resources get resources => Resources.from(this);
}
página_favoritos.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<FavoritesPage> {
@override
Widget build(BuildContext context) {
return Text(context.resources.strings.hello);
}
}
Uso de clave global
Junto con una extensión de BuildContext como se muestra arriba, también puede usar GlobalKey. Básicamente, puede usarlo cuando no tiene una instancia de contexto. Este último tiene una buena ventaja. Puede usar cadenas en cualquier parte de su aplicación. En otras palabras, si usa algún patrón como MVC, por ejemplo, y quiere usar cadenas en sus controladores, podría hacerlo fácilmente.
Puedes declarar algo como esto:
aplicacion.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<NavigatorState> navKey = GlobalKey();
static Resources get resources {
return navKey.currentContext.resources;
}
}
dardo principal
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
navigatorKey: Application.navKey,
...
Y luego:
import 'package:flutter/material.dart';
import 'package:myapp/application/application.dart';
class FavoritesPage extends StatefulWidget {
@override
_FavoritesPageState createState() => _FavoritesPageState();
}
class _FavoritesPageState extends State<FavoritesPage> {
@override
Widget build(BuildContext context) {
return Text(Application.resources.strings.hello);
}
}
¡Espero eso ayude!
En primer lugar, cree una nueva carpeta de cadenas en assets
y agregue sus archivos JSON de idioma.
assets
strings
- en.json
- ar.json
Esta es tu en.json
archivo
{
"title": "Flutter app"
}
Y este es tu ar.json
archivo
{
"title": "تطبيق Flutter"
}
Entonces, cambia tu pubspec.yaml
archivo como a continuación.
dependencies:
# your other codes
intl: ^0.17.0
flutter_localizations:
sdk: flutter
# your other codes
flutter:
uses-material-design: true
assets:
- assets/strings/en.json
- assets/strings/ar.json
Después de eso, crea AppLocalizations.dart
clase
import 'dart:convert';
import 'package:flutter/cupertino.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter/services.dart';
class AppLocalizations {
static AppLocalizations of(BuildContext context) {
return Localizations.of<AppLocalizations>(context, AppLocalizations);
}
String getText(String key) => language[key];
}
Map<String, dynamic> language;
class AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
const AppLocalizationsDelegate();
@override
bool isSupported(Locale locale) => ['en', 'ar'].contains(locale.languageCode);
@override
Future<AppLocalizations> load(Locale locale) async {
String string = await rootBundle.loadString("assets/strings/${locale.languageCode}.json");
language = json.decode(string);
return SynchronousFuture<AppLocalizations>(AppLocalizations());
}
@override
bool shouldReload(AppLocalizationsDelegate old) => false;
}
Finalmente en tu main.dart
archivo haga los cambios a continuación
void main() async {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: AppLocalizations.of(context).getText("title"),
locale: Locale("en"),
localizationsDelegates: [const AppLocalizationsDelegate()],
supportedLocales: [const Locale('en', ''), const Locale('ar', '')],
home: HomeScreen(),
);
}
}
-
¡Esta es una buena solución! Extendí su solución para proporcionar una mejor usabilidad mientras codificaba con esa solución, vea mi respuesta.
–Marcel Hofgesang
16 de abril de 2022 a las 14:03
Jebran
create "Strings.dart" file and add the below line==>
class Strings
{
static String welcomeScreen="WelCome Page";
static String loadingMessage="Loading Please Wait...!";
}
And then call the file using the below line using the widget
Text(Strings.loadingMessage)
Make sure that the String.dart file has been imported
-
¡Esta es una buena solución! Extendí su solución para proporcionar una mejor usabilidad mientras codificaba con esa solución, vea mi respuesta.
–Marcel Hofgesang
16 de abril de 2022 a las 14:03
Irfandi D. Vendy
Uso este método en lugar de usar lib de terceros. Básicamente, creo una clase que contiene esos valores (cadena, colores, dimensiones, etc.)
recursos.dart
import 'dart:ui';
class ResString{
var data = {
'url' : 'https://facebook.com/',
'welcome' : 'Welcome Home',
};
String get(String key){
return data[key];
}
}
class ResColor{
var data = {
'colorPrimary' : 0xff652A04,
'colorPrimaryDark' : 0xffFFFFFF,
'colorPrimaryLight' : 0xffF6EDDD,
};
Color get(String key){
return Color(data[key]);
}
}
Para usarlo, simplemente llame al método get
dardo principal
import 'package:my_app/resources.dart';
...
return Container(
color: ResColor().get('colorPrimary')
);
...