Моя команда и я работаем над мобильной игрой, которая позволяет пользователю установить свой основной язык. При первой загрузке появляется красный экран, показывающий, что некоторые переводы не были загружены, и через некоторое время исчезает.
Мы следовали инструкциям Флаттера и можем получитьпереводы, но при изменении языка в параметрах и при запуске, мы получаем этот экран.
Наш главный:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import ...
void main() {
SystemChrome.setPreferredOrientations(...).then((_){runApp(MyApp());});
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Trade on Tubes',
theme: ThemeData(...),
localizationsDelegates: [
const TranslationsDelegate(),
GlobalMaterialLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
],
supportedLocales: [
const Locale('en', ''),
const Locale('fr', ''),
const Locale('es', ''),
],
home: RootPage(auth: Auth(), lateralMenuPage: 0,)
);
}
}
Вот наша RootPage:
import 'package:flutter/material.dart';
import 'package:shared_preferences/shared_preferences.dart';
import ...
class RootPage extends StatefulWidget {
RootPage({this.auth, this.lateralMenuPage});
final AuthImpl auth;
final int lateralMenuPage;
@override
State<StatefulWidget> createState() => _RootPageState();
}
enum AuthStatus {...}
class _RootPageState extends State<RootPage> {
AuthStatus authStatus = AuthStatus.NOT_DETERMINED;
User currentUser;
String locale;
String devise;
bool theme;
@override
void initState() {
super.initState();
_loadPreferences();
widget.auth.getCurrentUserID().then((user) {
setState(() {
if (user == null) {
authStatus = AuthStatus.NOT_SIGNED_IN;
}
else {
widget.auth.getUserInfos(user).then(...);
}
});
});
}
void _signedInAndRegistered() {
setState(() {
widget.auth.getUserAvatar(currentUser.userID).then((ava){...});
authStatus = AuthStatus.SIGNED_IN_AND_REGISTERED;
});
}
void _signedInAndNotRegistered() {
widget.auth.getCurrentUserID().then((user){
setState(() {
widget.auth.getUserInfos(user).then(...);
});
});
}
void _signedOut() {
setState(() {
authStatus = AuthStatus.NOT_SIGNED_IN;
});
}
Future<void> _loadPreferences() async {
SharedPreferences prefs = await SharedPreferences.getInstance();
setState(() {
theme = (prefs.getBool('switchButton') ?? true);
devise = (prefs.getString('deviseButton') ?? "EUR");
locale = (prefs.getString('_radioValue1') ?? 'fr');
Translations.load(Locale.fromSubtags(languageCode: locale));
});
await Themes.load(theme);
await Devise.load(devise);
}
@override
Widget build(BuildContext context) {
...
switch (authStatus) {
case AuthStatus.NOT_DETERMINED:
return Container(
height: GV.globalH,
width: GV.globalW,
color: Colors.white,
child: Center(
child: CircularProgressIndicator()
),
);
case AuthStatus.NOT_SIGNED_IN:
return LoginPage(
auth: widget.auth,
onSignedIn: _signedInAndNotRegistered,
);
case AuthStatus.SIGNED_IN_AND_REGISTERED:
return currentUser.friends.isEmpty
? Tutorial(currentUser, widget.auth, 0)
:RadialMenu(
currentUser: currentUser,
auth: widget.auth,
page: widget.lateralMenuPage,);
case AuthStatus.SIGNED_IN_AND_NOT_REGISTERED:
return RegistrationPage(
auth: widget.auth,
onSignedOut: _signedOut,
onRegistered: _signedInAndRegistered,
);
}
}
}
И нашLoginPage:
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:trade_on_tube/translation/translations.dart';
import ...
class LoginPage extends StatefulWidget {
LoginPage({this.auth, this.onSignedIn});
final AuthImpl auth;
final VoidCallback onSignedIn;
@override
State<StatefulWidget> createState() => _LoginPageState();
}
enum FormMode{SIGNIN, SIGNUP}
class _LoginPageState extends State<LoginPage> {
final formKey = GlobalKey<FormState>();
bool _isLoading;
bool _alpha = false;
bool _obscureText = true;
String _email;
String _password;
FormMode _formMode = FormMode.SIGNIN;
bool _checkBox;
@override
void initState(){
_checkBox = false;
_isLoading = false;
super.initState();
}
Widget _showCircularProgress(){...}
bool validateAndSave() {...}
void validateAndSubmit()async{
setState(() {...});
if(validateAndSave()) {
String userId = '';
try {
if(_formMode == FormMode.SIGNIN) {
userId = await widget.auth.signIn(_email, _password);
_alpha = true;
} else {
if(_checkBox) {
userId = await widget.auth.signUp(_email, _password);
_showDialog2();
setState(() {
_formMode = FormMode.SIGNIN;
_isLoading = false;
});
}else {
_alpha = false;
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25.0)),
title: Text(Translations.of(context).text('cgu')),
content: Text(Translations.of(context).text('read_cgu')),
actions: <Widget>[
RaisedButton(
onPressed: () => Navigator.of(context).pop(),
padding: EdgeInsets.symmetric(
vertical: 10.0, horizontal: 12.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25.0)),
color: Theme
.of(context)
.primaryColor,
child: Text(Translations.of(context).text('the_what'),
style: TextStyle(
fontSize: 15.0, color: Colors.white70),),
)
],
);
},
);
}
}
setState(() {
_isLoading = false;
});
if(userId.length > 0 && userId != null && _alpha)
widget.onSignedIn();
} catch (e) {
setState(() {
print(e);
_isLoading = false;
if(userId == null) {
showDialog(
context: context,
builder: (BuildContext context){
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25.0)),
title: Text(Translations.of(context).text('email')),
content: Text(Translations.of(context).text('email_not_verified')),
actions: <Widget>[
RaisedButton(
onPressed: () => Navigator.of(context).pop(),
padding: EdgeInsets.symmetric(
vertical: 10.0, horizontal: 12.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25.0)),
color: Theme
.of(context)
.primaryColor,
child: Text(Translations.of(context).text('my_bad'),
style: TextStyle(fontSize: 15.0, color: Colors.white70),),
)
],
);
},
);
}else
_showDialog();
});
}
}
}
void validateAndSubmitGoogleSignIn() async {...}
void _signUp() {...}
void _signIn() {...}
void _showDialog(){
showDialog(
context: context,
builder: (BuildContext context){
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25.0)),
title: Text(Translations.of(context).text('problem')),
content: Text(Translations.of(context).text('problem_2'),),
actions: <Widget>[
RaisedButton(
onPressed: (){
Navigator.of(context).pop();
},
padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 12.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25.0)),
color: Theme.of(context).primaryColor,
child: Text(Translations.of(context).text('ok'),
style: TextStyle(fontSize: 15.0, color: Colors.white),),
),
],
);
}
);
}
void _showDialog2(){
String title = Translations.of(context).text('welcome');
String message = Translations.of(context).text('welcome_message');
String button = Translations.of(context).text('go');
showDialog(
context: context,
builder: (BuildContext context){
return AlertDialog(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25.0)),
title: Text(title),
content: Text(message),
actions: <Widget>[
RaisedButton(
onPressed: () => Navigator.of(context).pop(),
padding: EdgeInsets.symmetric(vertical: 10.0, horizontal: 12.0),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(25.0)),
color: Theme.of(context).primaryColor,
child: Text(button, style: TextStyle(fontSize: 15.0, color: Colors.white70),),
)
],
);
},
);
}
Widget _logo(String path, double radius, String tag) {...}
Widget _checkboxCGU(){
if(_formMode == FormMode.SIGNUP) {
return Row(
children: <Widget>[
InkWell(
onTap: () {
setState(() {
_checkBox = !_checkBox;
});
},
child: Container(
child: Padding(
padding: const EdgeInsets.all(10.0),
child: _checkBox
? Icon(Icons.check_circle, size: 22.0, color: Colors.blue,)
: Icon(FontAwesomeIcons.circle, size: 22.0, color: Colors.blue,),
),
),
),
GestureDetector(
onTap: () => launch("http://www.barracudapps.com/applis/trade_on_tubes.php"),
child: Text(Translations.of(context).text('cgu'),
style: TextStyle(fontSize: 13.0,
color: Colors.blue,
decoration: TextDecoration.underline,
),
),
)
],
);
} else{
return SizedBox(height: 2.0);
}
}
Widget _emailInput() {
return TextFormField(
style: TextStyle(color: Themes.themes.text),
keyboardType: TextInputType.emailAddress,
autofocus: false,
decoration: InputDecoration(
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Themes.themes.text),
),
hintText: Translations.of(context).text('email'),
hintStyle: TextStyle(color: Themes.themes.text),
icon: Icon(
Icons.mail,
color: Themes.themes.text,
),
),
validator: (value) =>
value.isEmpty ? Translations.of(context).text('email_empty') : null,
onSaved: (value) => _email = value,
);
}
Widget _passwordInput() {
return Row(
mainAxisSize: MainAxisSize.max,
children: <Widget>[
Container(
width: MediaQuery
.of(context)
.size
.width / 2 - 90,
child: TextFormField(
style: TextStyle(color: Themes.themes.text),
obscureText: _obscureText,
autofocus: false,
decoration: InputDecoration(
enabledBorder: UnderlineInputBorder(
borderSide: BorderSide(color: Themes.themes.text),
),
hintText: Translations.of(context).text('password'),
hintStyle: TextStyle(color: Themes.themes.text),
icon: Icon(
Icons.lock,
color: Themes.themes.text,
),
),
validator: (value) =>
value.isEmpty ? Translations.of(context)
.text('password_empty') : null,
onSaved: (value) => _password = value,
),
),
FlatButton(
onPressed: () =>
setState(() {
_obscureText = !_obscureText;
}),
child: Icon(
_obscureText ? FontAwesomeIcons.solidEye : FontAwesomeIcons
.solidEyeSlash, color: Themes.themes.text,),
),
],
);
}
Widget _forgotPassword() {
return GestureDetector(
onTap: () => Navigator.push(
context,
MaterialPageRoute(builder: (context) => ForgotPasswordPage(auth: widget.auth)),
),
child: Text(
Translations.of(context).text('forgot_password'),
style: TextStyle(fontSize: 13.0, color: Colors.blue, decoration: TextDecoration.underline),
),
);
}
Widget _label() {
return FlatButton(
child: _formMode == FormMode.SIGNIN
? Text(Translations.of(context).text('click_create_account'),
style: TextStyle(fontSize: 18.0, fontWeight: FontWeight.w600, color: Themes.themes.text))
: Text(Translations.of(context).text('click_login'),
style: TextStyle(fontSize: 18.0, fontWeight: FontWeight.w600, color: Themes.themes.text)),
onPressed: _formMode == FormMode.SIGNIN
? _signUp
: _signIn,
);
}
Widget _submitButton() {
if (_formMode == FormMode.SIGNIN) {
return Padding(
padding: EdgeInsets.symmetric(vertical: 0.0),
child: Material(
borderRadius: BorderRadius.circular(30.0),
shadowColor: Colors.redAccent.shade100,
elevation: 1.0,
child: MaterialButton(
minWidth: 290.0,
height: 35.0,
color: GV.firstColor,
child: Text(Translations.of(context).text('login'),
style: TextStyle(fontSize: 20.0, color: Colors.white),),
onPressed: validateAndSubmit,
),
),
);
} else {
return Padding(
padding: EdgeInsets.symmetric(vertical: 0.0),
child: Material(
borderRadius: BorderRadius.circular(30.0),
shadowColor: Colors.redAccent.shade100,
elevation: 1.0,
child: MaterialButton(
minWidth: 290.0,
height: 35.0,
color: GV.firstColor,
child: Text(Translations.of(context).text('create_account'),
style: TextStyle(fontSize: 20.0, color: Colors.white),),
onPressed: validateAndSubmit,
),
),
);
}
}
Widget _googleSignIn(){
return Padding(
padding: EdgeInsets.symmetric(vertical: 8.0),
child: RaisedButton(
color: Colors.transparent,
elevation: 0.0,
child:_logo("assets/Autres/google.png", 20, 'google'),
onPressed: validateAndSubmitGoogleSignIn,
),
);
}
Widget _bodyOne(){
return Container(
width: GV.globalW,
height: GV.globalH,
decoration: BoxDecoration(color: GV.firstColor),
child: Themes.themes.background_inscription,
);
}
Widget _bodyTwo(){
return Container(
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceEvenly,
children: [
SizedBox(width: GV.globalW/4,),
Flexible(
child: Form(
key: formKey,
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
_emailInput(),
_passwordInput(),
SizedBox(height: GV.globalH/35,),
Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.end,
children: <Widget>[
_checkboxCGU(),
_forgotPassword(),
],
),
SizedBox(height: GV.globalH/35,),
_submitButton(),
_label(),
Row(
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[
SizedBox(
width: 130.0,
height: 1.0,
child: const DecoratedBox(
decoration: const BoxDecoration(
color: Colors.white,
),
),
),
Text(Translations.of(context).text('or'),
style: TextStyle(fontSize: 15.0, fontWeight: FontWeight.w300, color: Themes.themes.text),),
SizedBox(
width: 130.0,
height: 1.0,
child: const DecoratedBox(
decoration: const BoxDecoration(
color: Colors.white,
),
),
),
],
),
_googleSignIn(),
],
),
),
),
SizedBox(width: GV.globalW/4,),
],
),
);
}
@override
Widget build(BuildContext context) {
SystemChrome.setEnabledSystemUIOverlays([]);
return Scaffold(
resizeToAvoidBottomPadding: false,
body: Stack(
children: <Widget>[
_bodyOne(),
_bodyTwo(),
_showCircularProgress(),
],
),
);
}
}