Base de internacionalización y localización de la pantalla de récords implentadas

parent aaf9d98d
synthetic-package: false
arb-dir: lib/l10n
template-arb-file: app_en.arb
output-localization-file: app_localizations.dart
\ No newline at end of file
{
"yes": "Yes",
"no": "No",
"@yes": {
"description": "Expression of affirmation"
},
"@no": {
"description": "Expression of negation"
},
"highScores": "Hi-Scores",
"highest20Scores": "The 20 all-of-time highest scores ever registered in Peponator!",
"noRecordsYet": "There are currently no registered records.",
"playToRegister": "Play the game, register the first one!",
"deleteHighScores": "Delete Hi-Scores",
"noUndo": "This action cannot be undone.",
"reallyDeleteHiScores": "Do you really want to delete all Hi-Scores?",
"@highScores": {
"description": "Name of the 'High Scores' page"
},
"@highest20Scores": {
"description": "A text describing that the following page contains the 20 highest scores obtained in the game"
},
"@noRecordsYet": {
"description": "Text that informs that there are no registered high scores yet"
},
"@playToRegister": {
"description": "Text that invites the user to play the game in order to register the first high score"
},
"@deleteHighScores": {
"description": "Action of deleting all high scores"
},
"@noUndo": {
"description": "Text that indicates that the action the user is about to do cannot be undone"
},
"@reallyDeleteHiScores": {
"description": "Interrogates the user whether they are sure that they want to delete all of their Hi-Scores"
}
}
\ No newline at end of file
{
"yes": "Sí",
"no": "No",
"highScores": "Récords",
"highest20Scores": "¡Las 20 mejores puntuaciones registradas en Peponator!",
"noRecordsYet": "No hay ningún récord registrado de momento.",
"playToRegister": "¡Juega y registra el primero!",
"deleteHighScores": "Borrar récords",
"noUndo": "Esta acción no se puede deshacer.",
"reallyDeleteHiScores": "¿Seguro que quieres borrar todos los récords?"
}
\ No newline at end of file
import 'dart:async';
import 'package:flutter/foundation.dart';
import 'package:flutter/widgets.dart';
import 'package:flutter_localizations/flutter_localizations.dart';
import 'package:intl/intl.dart' as intl;
import 'app_localizations_en.dart';
import 'app_localizations_es.dart';
// ignore_for_file: type=lint
/// Callers can lookup localized strings with an instance of AppLocalizations
/// returned by `AppLocalizations.of(context)`.
///
/// Applications need to include `AppLocalizations.delegate()` in their app's
/// `localizationDelegates` list, and the locales they support in the app's
/// `supportedLocales` list. For example:
///
/// ```dart
/// import 'l10n/app_localizations.dart';
///
/// return MaterialApp(
/// localizationsDelegates: AppLocalizations.localizationsDelegates,
/// supportedLocales: AppLocalizations.supportedLocales,
/// home: MyApplicationHome(),
/// );
/// ```
///
/// ## Update pubspec.yaml
///
/// Please make sure to update your pubspec.yaml to include the following
/// packages:
///
/// ```yaml
/// dependencies:
/// # Internationalization support.
/// flutter_localizations:
/// sdk: flutter
/// intl: any # Use the pinned version from flutter_localizations
///
/// # Rest of dependencies
/// ```
///
/// ## iOS Applications
///
/// iOS applications define key application metadata, including supported
/// locales, in an Info.plist file that is built into the application bundle.
/// To configure the locales supported by your app, you’ll need to edit this
/// file.
///
/// First, open your project’s ios/Runner.xcworkspace Xcode workspace file.
/// Then, in the Project Navigator, open the Info.plist file under the Runner
/// project’s Runner folder.
///
/// Next, select the Information Property List item, select Add Item from the
/// Editor menu, then select Localizations from the pop-up menu.
///
/// Select and expand the newly-created Localizations item then, for each
/// locale your application supports, add a new item and select the locale
/// you wish to add from the pop-up menu in the Value field. This list should
/// be consistent with the languages listed in the AppLocalizations.supportedLocales
/// property.
abstract class AppLocalizations {
AppLocalizations(String locale) : localeName = intl.Intl.canonicalizedLocale(locale.toString());
final String localeName;
static AppLocalizations? of(BuildContext context) {
return Localizations.of<AppLocalizations>(context, AppLocalizations);
}
static const LocalizationsDelegate<AppLocalizations> delegate = _AppLocalizationsDelegate();
/// A list of this localizations delegate along with the default localizations
/// delegates.
///
/// Returns a list of localizations delegates containing this delegate along with
/// GlobalMaterialLocalizations.delegate, GlobalCupertinoLocalizations.delegate,
/// and GlobalWidgetsLocalizations.delegate.
///
/// Additional delegates can be added by appending to this list in
/// MaterialApp. This list does not have to be used at all if a custom list
/// of delegates is preferred or required.
static const List<LocalizationsDelegate<dynamic>> localizationsDelegates = <LocalizationsDelegate<dynamic>>[
delegate,
GlobalMaterialLocalizations.delegate,
GlobalCupertinoLocalizations.delegate,
GlobalWidgetsLocalizations.delegate,
];
/// A list of this localizations delegate's supported locales.
static const List<Locale> supportedLocales = <Locale>[
Locale('en'),
Locale('es')
];
/// Expression of affirmation
///
/// In en, this message translates to:
/// **'Yes'**
String get yes;
/// Expression of negation
///
/// In en, this message translates to:
/// **'No'**
String get no;
/// Name of the 'High Scores' page
///
/// In en, this message translates to:
/// **'Hi-Scores'**
String get highScores;
/// A text describing that the following page contains the 20 highest scores obtained in the game
///
/// In en, this message translates to:
/// **'The 20 all-of-time highest scores ever registered in Peponator!'**
String get highest20Scores;
/// Text that informs that there are no registered high scores yet
///
/// In en, this message translates to:
/// **'There are currently no registered records.'**
String get noRecordsYet;
/// Text that invites the user to play the game in order to register the first high score
///
/// In en, this message translates to:
/// **'Play the game, register the first one!'**
String get playToRegister;
/// Action of deleting all high scores
///
/// In en, this message translates to:
/// **'Delete Hi-Scores'**
String get deleteHighScores;
/// Text that indicates that the action the user is about to do cannot be undone
///
/// In en, this message translates to:
/// **'This action cannot be undone.'**
String get noUndo;
/// Interrogates the user whether they are sure that they want to delete all of their Hi-Scores
///
/// In en, this message translates to:
/// **'Do you really want to delete all Hi-Scores?'**
String get reallyDeleteHiScores;
}
class _AppLocalizationsDelegate extends LocalizationsDelegate<AppLocalizations> {
const _AppLocalizationsDelegate();
@override
Future<AppLocalizations> load(Locale locale) {
return SynchronousFuture<AppLocalizations>(lookupAppLocalizations(locale));
}
@override
bool isSupported(Locale locale) => <String>['en', 'es'].contains(locale.languageCode);
@override
bool shouldReload(_AppLocalizationsDelegate old) => false;
}
AppLocalizations lookupAppLocalizations(Locale locale) {
// Lookup logic when only language code is specified.
switch (locale.languageCode) {
case 'en': return AppLocalizationsEn();
case 'es': return AppLocalizationsEs();
}
throw FlutterError(
'AppLocalizations.delegate failed to load unsupported locale "$locale". This is likely '
'an issue with the localizations generation tool. Please file an issue '
'on GitHub with a reproducible sample app and the gen-l10n configuration '
'that was used.'
);
}
// ignore: unused_import
import 'package:intl/intl.dart' as intl;
import 'app_localizations.dart';
// ignore_for_file: type=lint
/// The translations for English (`en`).
class AppLocalizationsEn extends AppLocalizations {
AppLocalizationsEn([String locale = 'en']) : super(locale);
@override
String get yes => 'Yes';
@override
String get no => 'No';
@override
String get highScores => 'Hi-Scores';
@override
String get highest20Scores => 'The 20 all-of-time highest scores ever registered in Peponator!';
@override
String get noRecordsYet => 'There are currently no registered records.';
@override
String get playToRegister => 'Play the game, register the first one!';
@override
String get deleteHighScores => 'Delete Hi-Scores';
@override
String get noUndo => 'This action cannot be undone.';
@override
String get reallyDeleteHiScores => 'Do you really want to delete all Hi-Scores?';
}
// ignore: unused_import
import 'package:intl/intl.dart' as intl;
import 'app_localizations.dart';
// ignore_for_file: type=lint
/// The translations for Spanish Castilian (`es`).
class AppLocalizationsEs extends AppLocalizations {
AppLocalizationsEs([String locale = 'es']) : super(locale);
@override
String get yes => 'Sí';
@override
String get no => 'No';
@override
String get highScores => 'Récords';
@override
String get highest20Scores => '¡Las 20 mejores puntuaciones registradas en Peponator!';
@override
String get noRecordsYet => 'No hay ningún récord registrado de momento.';
@override
String get playToRegister => '¡Juega y registra el primero!';
@override
String get deleteHighScores => 'Borrar récords';
@override
String get noUndo => 'Esta acción no se puede deshacer.';
@override
String get reallyDeleteHiScores => '¿Seguro que quieres borrar todos los récords?';
}
......@@ -2,8 +2,10 @@ import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:intl/intl.dart';
import 'package:path_provider/path_provider.dart';
import 'package:peponator/modelo/modelo.dart';
import 'package:peponator/l10n/app_localizations.dart';
class PantallaRecords extends StatefulWidget {
static const int maxRecords = 20;
......@@ -85,7 +87,7 @@ class _PantallaRecordsState extends State<PantallaRecords> {
crossAxisAlignment: CrossAxisAlignment.stretch,
children: [
Text(
'Récords',
AppLocalizations.of(context)?.highScores ?? 'Récords',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.headlineLarge?.copyWith(
color: Theme.of(context).colorScheme.onPrimary,
......@@ -94,7 +96,7 @@ class _PantallaRecordsState extends State<PantallaRecords> {
),
const SizedBox(height: 8.0),
Text(
'¡Las 20 mejores puntuaciones registradas en el juego!',
AppLocalizations.of(context)?.highest20Scores ?? '¡Las 20 mejores puntuaciones registradas en el juego!',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleLarge?.copyWith(
color: Theme.of(context).colorScheme.onPrimary,
......@@ -108,6 +110,7 @@ class _PantallaRecordsState extends State<PantallaRecords> {
}
Widget _buildRecordsView(BuildContext context, Orientation orientation, List<PeponatorRecord> records){
records.add(new PeponatorRecord(jugador: "AAAAA", puntuacion: 2000, fecha: DateTime.now()));
if(records.isNotEmpty) {
final vistaRecords = ListView.builder(
shrinkWrap: true,
......@@ -165,7 +168,7 @@ class _PantallaRecordsState extends State<PantallaRecords> {
),
const SizedBox(height: 8.0),
Text(
'${fecha.day}/${fecha.month}/${fecha.year}',
DateFormat.yMd(Localizations.localeOf(context).languageCode).format(fecha),
textAlign: TextAlign.start,
style: Theme.of(context).textTheme.titleLarge?.copyWith(
color: t,
......@@ -201,9 +204,11 @@ class _PantallaRecordsState extends State<PantallaRecords> {
}
}
else {
final String noRecord = AppLocalizations.of(context)?.noRecordsYet ?? 'No hay ningún récord registrado de momento.';
final String playToRegister = AppLocalizations.of(context)?.playToRegister ?? '¡Juega y registra el primero!';
final message = Center(
child: Text(
'No hay ningún récord registrado de momento.\n\n¡Juega y registra el primero!',
'$noRecord\n\n$playToRegister',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleLarge,
)
......@@ -221,6 +226,8 @@ class _PantallaRecordsState extends State<PantallaRecords> {
}
Widget _buildFAB(BuildContext context, Orientation orientation){
final noUndo = AppLocalizations.of(context)?.noUndo ?? 'Esta acción no se puede deshacer.';
final reallyDeleteHiScores = AppLocalizations.of(context)?.reallyDeleteHiScores ?? '¿Seguro que quieres borrar todos los récords?';
return Align(
alignment: (orientation == Orientation.portrait)? Alignment.bottomCenter : Alignment.bottomRight,
child: Padding(
......@@ -232,14 +239,14 @@ class _PantallaRecordsState extends State<PantallaRecords> {
builder: (context) {
return AlertDialog(
title: Center(child: Text(
'Borrar récords',
AppLocalizations.of(context)?.deleteHighScores ?? 'Borrar récords',
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleLarge,
)),
content: Text(
(orientation == Orientation.portrait)?
'Esta acción no se puede deshacer. ¿Seguro que quieres borrar todos los récords?':
'Esta acción no se puede deshacer.\n¿Seguro que quieres borrar todos los récords?'
'$noUndo $reallyDeleteHiScores' :
'$noUndo\n$reallyDeleteHiScores'
,
textAlign: TextAlign.center,
style: Theme.of(context).textTheme.titleMedium,
......@@ -260,7 +267,7 @@ class _PantallaRecordsState extends State<PantallaRecords> {
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 24.0),
child: Text(
'Sí',
AppLocalizations.of(context)?.yes ?? 'Sí',
style: Theme.of(context).textTheme.titleMedium?.copyWith(
color: Theme.of(context).colorScheme.primary
),
......@@ -270,6 +277,7 @@ class _PantallaRecordsState extends State<PantallaRecords> {
TextButton(
onPressed: () {
Navigator.pop(context);
Navigator.pop(context);
},
style: TextButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.primary
......@@ -277,7 +285,7 @@ class _PantallaRecordsState extends State<PantallaRecords> {
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 24.0),
child: Text(
'No',
AppLocalizations.of(context)?.no ?? 'No',
style: Theme.of(context).textTheme.titleMedium?.copyWith(
color: Theme.of(context).colorScheme.onPrimary
),
......@@ -291,7 +299,7 @@ class _PantallaRecordsState extends State<PantallaRecords> {
},
backgroundColor: Colors.red,
label: Text(
'Borrar récords',
AppLocalizations.of(context)?.deleteHighScores ?? 'Borrar récords',
style: Theme.of(context).textTheme.titleLarge?.copyWith(
color: Colors.white
),
......@@ -321,7 +329,9 @@ class _PantallaRecordsState extends State<PantallaRecords> {
Future<void> _deleteRecords() async {
final file = await PantallaRecords.localFile();
await file.delete();
if(await file.exists()){
await file.delete();
}
setState(() {});
}
}
\ No newline at end of file
import 'package:flutter/material.dart';
import 'package:peponator/paginas/paginas.dart';
import 'package:peponator/paginas/pantalla_juego.dart';
import 'package:peponator/l10n/app_localizations.dart';
class PeponatorApp extends StatelessWidget {
const PeponatorApp({super.key});
......@@ -15,6 +15,8 @@ class PeponatorApp extends StatelessWidget {
brightness: Brightness.light,
useMaterial3: true
),
localizationsDelegates: AppLocalizations.localizationsDelegates,
supportedLocales: AppLocalizations.supportedLocales,
darkTheme: ThemeData.dark(),
themeMode: ThemeMode.system,
home: PantallaRecords()
......
......@@ -86,6 +86,11 @@ packages:
url: "https://pub.dev"
source: hosted
version: "5.0.0"
flutter_localizations:
dependency: "direct main"
description: flutter
source: sdk
version: "0.0.0"
flutter_test:
dependency: "direct dev"
description: flutter
......@@ -96,6 +101,14 @@ packages:
description: flutter
source: sdk
version: "0.0.0"
intl:
dependency: "direct main"
description:
name: intl
sha256: d6f56758b7d3014a48af9701c085700aac781a92a87a62b1333b46d8879661cf
url: "https://pub.dev"
source: hosted
version: "0.19.0"
leak_tracker:
dependency: transitive
description:
......
......@@ -36,6 +36,9 @@ dependencies:
cupertino_icons: ^1.0.8
shared_preferences: ^2.5.3
path_provider: ^2.1.5
flutter_localizations:
sdk: flutter
intl: any
dev_dependencies:
flutter_test:
......@@ -59,6 +62,9 @@ flutter:
# the material Icons class.
uses-material-design: true
# Enables generation of localized YAML files
generate: true
# To add assets to your application, add an assets section, like this:
# assets:
# - images/a_dot_burr.jpeg
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or sign in to comment