better utilize arb localization features

no concatenation enymore :)
This commit is contained in:
Leptopoda-GitHub 2021-11-08 16:59:14 +01:00
parent ea3ac68cc7
commit 49709772e0
7 changed files with 292 additions and 210 deletions

View File

@ -44,13 +44,15 @@
"@testViaLAN": {
"description": "Test Via LAN"
},
"move": "Move",
"@move": {
"description": "Move"
},
"moves": " Moves",
"@moves": {
"description": " Moves"
"move_number": "{count,plural, =0{Move}=1{{count} Move}other{{count} Moves}}",
"@move_number": {
"description": "moves to take back",
"placeholders": {
"count": {
"description": "number of Moves",
"example": "3"
}
}
},
"showMoveList": "Move list",
"@showMoveList": {
@ -160,9 +162,15 @@
"@tipCanMoveToAnyPoint": {
"description": "You can move to any point you like."
},
"tipToMove": " to move.",
"tipToMove": "{player} to move.",
"@tipToMove": {
"description": " to move."
"description": "Tip that the given player is to move",
"placeholders": {
"player": {
"description": "The player who's turn it is",
"example": "Player 1"
}
}
},
"whiteWin": "Player 1 wins!",
"@whiteWin": {
@ -204,9 +212,15 @@
"@gameImported": {
"description": "Game imported from the clipboard."
},
"cannotImport": "Cannot import",
"cannotImport": "Cannot import {error}",
"@cannotImport": {
"description": "Cannot import"
"description": "Cannot import",
"placeholders": {
"error": {
"description": "the error causing this message",
"example": "insufficient permissions"
}
}
},
"movesAndRulesNotMatch": "Moves and rules do not match.",
"@movesAndRulesNotMatch": {
@ -252,15 +266,21 @@
"@analyzing": {
"description": "Analyzing ..."
},
"error": "Error",
"error": "Error: {message}",
"@error": {
"description": "Error"
"description": "Error",
"placeholders": {
"message": {
"description": "the Error message",
"example": "x was not ready yet"
}
}
},
"winRate": "Win Rate",
"@winRate": {
"description": "Win Rate"
},
"score": "Score",
"score": "Score:",
"@score": {
"description": "Score"
},
@ -272,25 +292,55 @@
"@black": {
"description": "Player 2"
},
"loseReasonlessThanThree": " piece count is less than three.",
"loseReasonlessThanThree": "{player} piece count is less than three.",
"@loseReasonlessThanThree": {
"description": " piece count is less than three."
"description": "Indicate that the player lost because they had less then three pieces left",
"placeholders": {
"player": {
"description": "The player who lost",
"example": "Player 1"
}
}
},
"loseReasonResign": " resign.",
"loseReasonResign": "{player} resigned.",
"@loseReasonResign": {
"description": " resign."
"description": "Indicate that the player resigned",
"placeholders": {
"player": {
"description": "The player who resigns",
"example": "Player 1"
}
}
},
"loseReasonNoWay": " is no way to go.",
"loseReasonNoWay": "{player} has no way to go.",
"@loseReasonNoWay": {
"description": " is no way to go."
"description": "Indicate that the player has no way to go",
"placeholders": {
"player": {
"description": "The player who lost",
"example": "Player 1"
}
}
},
"loseReasonBoardIsFull": "The board is full, and no way to go.",
"loseReasonBoardIsFull": "The board is full, and {player} has no way to go.",
"@loseReasonBoardIsFull": {
"description": "The board is full, no way to go."
"description": "The board is full, no way to go.",
"placeholders": {
"player": {
"description": "The player who lost",
"example": "Player 1"
}
}
},
"loseReasonTimeOver": "Time Over",
"loseReasonTimeOver": "Time Over, {player} lost",
"@loseReasonTimeOver": {
"description": "Time Over"
"description": "Time Over",
"placeholders": {
"player": {
"description": "The player who lost",
"example": "Player 1"
}
}
},
"drawReasonRule50": "In the moving phase, no piece has been removed in the last specific number of moves.",
"@drawReasonRule50": {
@ -316,9 +366,15 @@
"@youWin": {
"description": "You win! Congratulations!"
},
"challengeHarderLevel": "Challenge harder level? The new level will be level ",
"challengeHarderLevel": "Challenge harder level? The new level will be level {level}!",
"@challengeHarderLevel": {
"description": "Challenge harder level?"
"description": "Challenge harder level?",
"placeholders": {
"level": {
"description": "The new level",
"example": "5"
}
}
},
"youLose": "You Lose!",
"@youLose": {
@ -336,9 +392,15 @@
"@about": {
"description": "About"
},
"version": "Version",
"version": "Version: {version_number}",
"@version": {
"description": "Version"
"description": "Version",
"placeholders": {
"version_number": {
"description": "the current Sanmill version",
"example": "1.38.1"
}
}
},
"thanks": "Thanks",
"@thanks": {
@ -636,17 +698,15 @@
"@restoreDefaultSettings": {
"description": "Restore Default Settings"
},
"exitApp": "The app will exit.",
"@exitApp": {
"description": "The app will exit."
},
"exitAppManually": "You have to close immediately and reopen the app to take effect.",
"@exitAppManually": {
"description": "You have to close immediately and reopen the app to take effect."
},
"pick": "Pick",
"pick": "Pick {element}",
"@pick": {
"description": "Pick "
"description": "Used in the color picker",
"placeholders": {
"element": {
"description": "The element to pick the color for",
"example": "Background color"
}
}
},
"info": "Info",
"@info": {
@ -881,17 +941,37 @@
"@considerMobility": {
"description": "Consider mobility of pieces"
},
"pieceCount": "Piece count",
"pieceCount": "Piece count:",
"@pieceCount": {
"description": "Piece count"
},
"inHand": "in hand",
"inHand": "{player} in hand: {amount}",
"@inHand": {
"description": "in hand"
"description": "The pieces a player has in their board",
"placeholders": {
"player": {
"description": "The specified player",
"example": "White"
},
"amount": {
"description": "The amount of pieces",
"example": "5"
}
}
},
"onBoard": "on board",
"onBoard": "{player} on board: {amount}",
"@onBoard": {
"description": "on board"
"description": "The pieces a player has on the board",
"placeholders": {
"player": {
"description": "The specified player",
"example": "White"
},
"amount": {
"description": "The amount of pieces",
"example": "5"
}
}
},
"boardTop": "Board offset from the top",
"@boardTop": {
@ -1161,22 +1241,30 @@
"@flyingPhase": {
"description": "Flying phase"
},
"sideToMove": "Side to move",
"sideToMove": "Side to move: {player}",
"@sideToMove": {
"description": "Side to move"
"description": "The player whos turn it is",
"placeholders": {
"player": {
"description": "The player to move",
"example": "Player 1"
}
}
},
"lastMove": "Last move",
"lastMove": "Last move: {move}",
"@lastMove": {
"description": "Last move"
"description": "Last move",
"placeholders": {
"move": {
"description": "The last move",
"example": "f4"
}
}
},
"selected": "Selected",
"@selected": {
"description": "Selected"
},
"mainMenu": "Main menu",
"@mainMenu": {
"description": "Main menu"
},
"accessibility": "Accessibility",
"@accessibility": {
"description": "Accessibility"

View File

@ -257,7 +257,7 @@ class _VersionDialog extends StatelessWidget {
mainAxisSize: MainAxisSize.min,
crossAxisAlignment: CrossAxisAlignment.start,
children: <Widget>[
Text("${S.of(context).version}: $version"),
Text(S.of(context).version(version)),
const CustomSpacer(),
Text(
S.of(context).copyright,

View File

@ -49,6 +49,7 @@ part 'package:sanmill/shared/painters/board_painter.dart';
part 'package:sanmill/shared/painters/painter_base.dart';
part 'package:sanmill/shared/painters/pieces_painter.dart';
// TODO: [Leptopoda] remove variables that are not part of an object
double boardWidth = 0.0;
class GamePage extends StatefulWidget {
@ -68,7 +69,7 @@ class _GamePageState extends State<GamePage>
double screenPaddingH = AppTheme.boardScreenPaddingH;
final double boardMargin = AppTheme.boardMargin;
String? _tip = '';
late String _tip;
bool isReady = false;
bool isGoingToHistory = false;
late Timer timer;
@ -124,44 +125,37 @@ class _GamePageState extends State<GamePage>
}
}
void showTip(String? tip) {
void showTip(String tip) {
if (!mounted) return;
if (tip != null) {
debugPrint("[tip] $tip");
if (LocalDatabaseService.preferences.screenReaderSupport) {
//showSnackBar(context, tip);
}
debugPrint("[tip] $tip");
if (LocalDatabaseService.preferences.screenReaderSupport) {
//showSnackBar(context, tip);
}
setState(() => _tip = tip);
}
void showTips() {
if (!mounted) {
return;
}
if (!mounted) return;
final winner = gameInstance.position.winner;
final Map<String, String> colorWinStrings = {
PieceColor.white: S.of(context).whiteWin,
PieceColor.black: S.of(context).blackWin,
PieceColor.draw: S.of(context).isDraw
};
if (winner == PieceColor.nobody) {
if (gameInstance.position.phase == Phase.placing) {
if (mounted) {
showTip(S.of(context).tipPlace);
switch (winner) {
case PieceColor.white:
return showTip(S.of(context).whiteWin);
case PieceColor.black:
return showTip(S.of(context).blackWin);
case PieceColor.draw:
return showTip(S.of(context).isDraw);
case PieceColor.nobody:
switch (gameInstance.position.phase) {
case Phase.placing:
return showTip(S.of(context).tipPlace);
case Phase.moving:
return showTip(S.of(context).tipMove);
default:
}
} else if (gameInstance.position.phase == Phase.moving) {
if (mounted) {
showTip(S.of(context).tipMove);
}
}
} else {
if (mounted) {
showTip(colorWinStrings[winner]);
}
}
if (!LocalDatabaseService.preferences.isAutoRestart) {
@ -198,9 +192,6 @@ class _GamePageState extends State<GamePage>
}
// If nobody has placed, start to go.
// TODO
// WAR: Fix first tap response slow when piece count changed
if (position.phase == Phase.placing &&
position.pieceOnBoardCount[PieceColor.white] == 0 &&
position.pieceOnBoardCount[PieceColor.black] == 0) {
@ -259,7 +250,7 @@ class _GamePageState extends State<GamePage>
final side = gameInstance.sideToMove == PieceColor.white
? S.of(context).black
: S.of(context).white;
showTip(side + S.of(context).tipToMove);
showTip(S.of(context).tipToMove(side));
}
}
}
@ -396,7 +387,7 @@ class _GamePageState extends State<GamePage>
? S.of(context).black
: S.of(context).white;
if (mounted) {
showTip(them + S.of(context).tipToMove);
showTip(S.of(context).tipToMove(them));
}
}
}
@ -544,9 +535,8 @@ class _GamePageState extends State<GamePage>
if (LocalDatabaseService.preferences.screenReaderSupport &&
gameInstance.position.action != Act.remove &&
m != null &&
m.notation != null) {
showSnackBar(context, "${S.of(context).human}: ${m.notation!}");
m?.notation != null) {
showSnackBar(context, "${S.of(context).human}: ${m!.notation!}");
}
}
}
@ -596,14 +586,9 @@ class _GamePageState extends State<GamePage>
showSnackBar(context, S.of(context).timeout);
}
}
//if (LocalDatabaseService.developerMode) {
//assert(false);
//}
return;
default:
showTip('Error: ${response.type}');
break;
showTip(S.of(context).error(response.type));
}
if (LocalDatabaseService.preferences.isAutoRestart == true &&
@ -658,10 +643,10 @@ class _GamePageState extends State<GamePage>
final importFailedStr = gameInstance.position.recorder.import(text);
if (importFailedStr != "") {
showTip("${S.of(context).cannotImport} $importFailedStr");
showTip(S.of(context).cannotImport(importFailedStr));
if (LocalDatabaseService.preferences.screenReaderSupport) {
ScaffoldMessenger.of(context).clearSnackBars();
showSnackBar(context, "${S.of(context).cannotImport} $importFailedStr");
showSnackBar(context, S.of(context).cannotImport(importFailedStr));
}
return;
}
@ -792,7 +777,7 @@ class _GamePageState extends State<GamePage>
context: context,
backgroundColor: Colors.transparent,
builder: (context) => Semantics(
label: S.of(context).move,
label: S.of(context).move_number(0),
child: SimpleDialog(
backgroundColor: Colors.transparent,
children: <Widget>[
@ -877,8 +862,8 @@ class _GamePageState extends State<GamePage>
late final String text;
final lastEffectiveMove = pos.recorder.lastEffectiveMove;
if (lastEffectiveMove != null && lastEffectiveMove.notation != null) {
text = "${S.of(context).lastMove}: ${lastEffectiveMove.notation}";
if (lastEffectiveMove?.notation != null) {
text = S.of(context).lastMove(lastEffectiveMove!.notation!);
} else {
text = S.of(context).atEnd;
}
@ -1040,14 +1025,13 @@ class _GamePageState extends State<GamePage>
final Map<GameOverReason, String> reasonMap = {
GameOverReason.loseReasonlessThanThree:
loserStr + S.of(context).loseReasonlessThanThree,
GameOverReason.loseReasonResign:
loserStr + S.of(context).loseReasonResign,
GameOverReason.loseReasonNoWay: loserStr + S.of(context).loseReasonNoWay,
S.of(context).loseReasonlessThanThree(loserStr),
GameOverReason.loseReasonResign: S.of(context).loseReasonResign(loserStr),
GameOverReason.loseReasonNoWay: S.of(context).loseReasonNoWay(loserStr),
GameOverReason.loseReasonBoardIsFull:
loserStr + S.of(context).loseReasonBoardIsFull,
S.of(context).loseReasonBoardIsFull(loserStr),
GameOverReason.loseReasonTimeOver:
loserStr + S.of(context).loseReasonTimeOver,
S.of(context).loseReasonTimeOver(loserStr),
GameOverReason.drawReasonRule50: S.of(context).drawReasonRule50,
GameOverReason.drawReasonEndgameRule50:
S.of(context).drawReasonEndgameRule50,
@ -1101,23 +1085,11 @@ class _GamePageState extends State<GamePage>
return GameResult.none;
}
// TODO: [Leptopoda] deduplicate the code
void showGameResult(String winner) {
final GameResult result = getGameResult(winner);
gameInstance.position.result = result;
switch (result) {
case GameResult.win:
//Audios.playTone(Audios.win);
break;
case GameResult.lose:
//Audios.playTone(Audios.lose);
break;
case GameResult.draw:
break;
default:
break;
}
final Map<GameResult, String> retMap = {
GameResult.win: gameInstance.engineType == EngineType.humanVsAi
? S.of(context).youWin
@ -1128,9 +1100,7 @@ class _GamePageState extends State<GamePage>
final dialogTitle = retMap[result];
if (dialogTitle == null) {
return;
}
if (dialogTitle == null) return;
final bool isTopLevel =
LocalDatabaseService.preferences.skillLevel == 30; // TODO: 30
@ -1138,14 +1108,21 @@ class _GamePageState extends State<GamePage>
if (result == GameResult.win &&
!isTopLevel &&
gameInstance.engineType == EngineType.humanVsAi) {
var contentStr = getGameOverReasonString(
gameInstance.position.gameOverReason,
gameInstance.position.winner,
final contentStr = StringBuffer(
getGameOverReasonString(
gameInstance.position.gameOverReason,
gameInstance.position.winner,
),
);
if (!isTopLevel) {
contentStr +=
"\n\n${S.of(context).challengeHarderLevel}${LocalDatabaseService.preferences.skillLevel + 1}!";
contentStr.writeln();
contentStr.writeln();
contentStr.writeln(
S.of(context).challengeHarderLevel(
LocalDatabaseService.preferences.skillLevel + 1,
),
);
}
showDialog(
@ -1157,9 +1134,7 @@ class _GamePageState extends State<GamePage>
dialogTitle,
style: AppTheme.dialogTitleTextStyle,
),
content: Text(
contentStr,
),
content: Text(contentStr.toString()),
actions: <Widget>[
TextButton(
child: Text(
@ -1178,9 +1153,7 @@ class _GamePageState extends State<GamePage>
},
),
TextButton(
child: Text(
S.of(context).no,
),
child: Text(S.of(context).no),
onPressed: () => Navigator.pop(context),
),
],
@ -1205,9 +1178,7 @@ class _GamePageState extends State<GamePage>
),
actions: <Widget>[
TextButton(
child: Text(
S.of(context).restart,
),
child: Text(S.of(context).restart),
onPressed: () {
Navigator.pop(context);
gameInstance.newGame();
@ -1226,9 +1197,7 @@ class _GamePageState extends State<GamePage>
},
),
TextButton(
child: Text(
S.of(context).cancel,
),
child: Text(S.of(context).cancel),
onPressed: () => Navigator.pop(context),
),
],
@ -1239,7 +1208,6 @@ class _GamePageState extends State<GamePage>
}
double get _screenPaddingH {
//
// when screen's height/width rate is less than 16/9, limit width of board
final windowSize = MediaQuery.of(context).size;
final double height = windowSize.height;
@ -1308,7 +1276,7 @@ class _GamePageState extends State<GamePage>
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16),
child: Text(
_tip!,
_tip,
maxLines: 1,
style: TextStyle(
color: LocalDatabaseService.colorSettings.messageColor,
@ -1361,73 +1329,95 @@ class _GamePageState extends State<GamePage>
}
String get infoText {
String phase = "";
final String period =
LocalDatabaseService.preferences.screenReaderSupport ? "." : "";
final String comma =
LocalDatabaseService.preferences.screenReaderSupport ? "," : "";
final buffer = StringBuffer();
final pos = gameInstance.position;
late final String us;
late final String them;
switch (pos.side) {
case PieceColor.white:
us = S.of(context).player1;
them = S.of(context).player2;
break;
case PieceColor.black:
us = S.of(context).player2;
them = S.of(context).player1;
break;
default:
assert(false);
}
switch (pos.phase) {
case Phase.placing:
phase = S.of(context).placingPhase;
buffer.writeln(S.of(context).placingPhase);
break;
case Phase.moving:
phase = S.of(context).movingPhase;
buffer.writeln(S.of(context).movingPhase);
break;
default:
break;
}
final String pieceCountInHand = pos.phase == Phase.placing
? "${S.of(context).player1} ${S.of(context).inHand}: ${pos.pieceInHandCount[PieceColor.white]}$comma\n${S.of(context).player2} ${S.of(context).inHand}: ${pos.pieceInHandCount[PieceColor.black]}$comma\n"
: "";
String us = "";
String them = "";
if (pos.side == PieceColor.white) {
us = S.of(context).player1;
them = S.of(context).player2;
} else if (pos.side == PieceColor.black) {
us = S.of(context).player2;
them = S.of(context).player1;
}
final String tip =
(_tip == null || !LocalDatabaseService.preferences.screenReaderSupport)
? ""
: "\n$_tip";
String lastMove = "";
// last Move information
if (pos.recorder.lastMove?.notation != null) {
final String n1 = pos.recorder.lastMove!.notation!;
// TODO: [Leptopdoa] why is $them only shown with the screen reader?
if (LocalDatabaseService.preferences.screenReaderSupport) {
buffer.write(S.of(context).lastMove("$them, "));
} else {
buffer.write(S.of(context).lastMove(""));
}
if (n1.startsWith("x")) {
final String n2 =
pos.recorder.moveAt(pos.recorder.movesCount - 2).notation!;
lastMove = n2 + n1;
} else {
lastMove = n1;
}
if (LocalDatabaseService.preferences.screenReaderSupport) {
lastMove = "${S.of(context).lastMove}: $them, $lastMove$period\n";
} else {
lastMove = "${S.of(context).lastMove}: $lastMove$period\n";
buffer.writeln(
pos.recorder.moveAt(pos.recorder.movesCount - 2).notation,
);
}
buffer.writePeriod(n1);
}
String addedPeriod = "";
buffer.writePeriod(S.of(context).sideToMove(us));
// the tip
if (LocalDatabaseService.preferences.screenReaderSupport &&
tip.isNotEmpty &&
tip[tip.length - 1] != '.' &&
tip[tip.length - 1] != '!') {
addedPeriod = ".";
_tip[_tip.length - 1] != '.' &&
_tip[_tip.length - 1] != '!') {
buffer.writePeriod(_tip);
}
final String ret =
"$phase$period\n$lastMove${S.of(context).sideToMove}: $us$period$tip$addedPeriod\n\n${S.of(context).pieceCount}:\n$pieceCountInHand${S.of(context).player1} ${S.of(context).onBoard}: ${pos.pieceOnBoardCount[PieceColor.white]}$comma\n${S.of(context).player2} ${S.of(context).onBoard}: ${pos.pieceOnBoardCount[PieceColor.black]}$period\n\n${S.of(context).score}:\n${S.of(context).player1}: ${pos.score[PieceColor.white]}$comma\n${S.of(context).player2}: ${pos.score[PieceColor.black]}$comma\n${S.of(context).draw}: ${pos.score[PieceColor.draw]}$period";
return ret;
buffer.writeln();
buffer.writeln(S.of(context).pieceCount);
buffer.writeComma(
S.of(context).inHand(
S.of(context).player1,
pos.pieceInHandCount[PieceColor.white]!,
),
);
buffer.writeComma(
S.of(context).inHand(
S.of(context).player2,
pos.pieceInHandCount[PieceColor.black]!,
),
);
buffer.writeComma(
S.of(context).onBoard(
S.of(context).player1,
pos.pieceOnBoardCount[PieceColor.white]!,
),
);
buffer.writePeriod(
S.of(context).onBoard(
S.of(context).player2,
pos.pieceOnBoardCount[PieceColor.black]!,
),
);
buffer.writeln();
buffer.writeln(S.of(context).score);
buffer
.writeComma("${S.of(context).player1}: ${pos.score[PieceColor.white]}");
buffer
.writeComma("${S.of(context).player2}: ${pos.score[PieceColor.black]}");
buffer.writePeriod("${S.of(context).draw}: ${pos.score[PieceColor.draw]}");
return buffer.toString();
}
Widget get toolbar {
@ -1477,7 +1467,7 @@ class _GamePageState extends State<GamePage>
color: _iconColor,
),
Text(
S.of(context).move,
S.of(context).move_number(0),
style: AppTheme.mainToolbarTextStyle,
),
],
@ -1616,14 +1606,11 @@ class _GamePageState extends State<GamePage>
super.didChangeDependencies();
screenPaddingH = _screenPaddingH;
ltr = Directionality.of(context) == TextDirection.ltr;
_tip = S.of(context).welcome;
}
@override
Widget build(BuildContext context) {
if (_tip == '') {
_tip = S.of(context).welcome;
}
return Scaffold(
appBar: AppBar(
leading: DrawerIcon.of(context)?.icon,
@ -1660,3 +1647,21 @@ class _GamePageState extends State<GamePage>
super.dispose();
}
}
extension CustomStringBuffer on StringBuffer {
void writeComma([Object? obj = ""]) {
if (LocalDatabaseService.preferences.screenReaderSupport) {
writeln("$obj,");
} else {
writeln(obj);
}
}
void writePeriod([Object? obj = ""]) {
if (LocalDatabaseService.preferences.screenReaderSupport) {
writeln("$obj.");
} else {
writeln(obj);
}
}
}

View File

@ -21,7 +21,7 @@ part of 'package:sanmill/screens/game_settings/game_settings_page.dart';
class _ResetSettingsAlert extends StatelessWidget {
const _ResetSettingsAlert({Key? key}) : super(key: key);
void cancel(BuildContext context) => Navigator.pop(context);
void _cancel(BuildContext context) => Navigator.pop(context);
Future<void> _restore(BuildContext context) async {
Navigator.pop(context);
@ -35,19 +35,13 @@ class _ResetSettingsAlert extends StatelessWidget {
@override
Widget build(BuildContext context) {
// TODO: [Leptopoda] remove these strings as they aren't needed anymore
//S.of(context).exitApp;
//S.of(context).exitAppManually
return AlertDialog(
title: Text(
S.of(context).restore,
style: AppTheme.dialogTitleTextStyle,
),
content: SingleChildScrollView(
child: Text(
"${S.of(context).restoreDefaultSettings}?",
),
child: Text("${S.of(context).restoreDefaultSettings}?"),
),
actions: <Widget>[
TextButton(
@ -57,7 +51,7 @@ class _ResetSettingsAlert extends StatelessWidget {
),
),
TextButton(
onPressed: () => cancel(context),
onPressed: () => _cancel(context),
child: Text(
S.of(context).cancel,
),

View File

@ -83,7 +83,7 @@ class _ColorPickerAlertState extends State<_ColorPickerAlert> {
Widget build(BuildContext context) {
return AlertDialog(
title: Text(
"${S.of(context).pick} ${widget.title}",
S.of(context).pick(widget.title),
style: AppTheme.dialogTitleTextStyle,
),
content: SingleChildScrollView(

View File

@ -129,8 +129,6 @@ class _CustomDrawerState extends State<CustomDrawer>
progress: ReverseAnimation(_animationController),
),
tooltip: MaterialLocalizations.of(context).openAppDrawerTooltip,
// TODO: [Leptopoda] remove this unused string
//S.of(context).mainMenu,
onPressed: () => _controller.toggleDrawer(),
);

View File

@ -36,12 +36,9 @@ class NumberPicker extends StatelessWidget {
final _size = Theme.of(context).textTheme.bodyText1!.fontSize!;
late int _selectValue;
// TODO: [Leptopdoa] use arb pluralization support
final List<Widget> _items = List.generate(
end - start,
(index) => Text(
'${start + index} ${S.of(context).moves}',
),
(index) => Text(S.of(context).move_number(start + index)),
);
return AlertDialog(