Refactor: Introduce AppStrings for soft i18n
This commit is contained in:
parent
9a9022356a
commit
c570d61563
|
|
@ -0,0 +1,64 @@
|
||||||
|
class AppStrings {
|
||||||
|
// Main Menu
|
||||||
|
static const String gameTitle = "Colosseum's Choice";
|
||||||
|
static const String startGame = "Start Game";
|
||||||
|
static const String continueGame = "Continue";
|
||||||
|
static const String exitGame = "Exit Game";
|
||||||
|
static const String credits = "Credits";
|
||||||
|
|
||||||
|
// Common Actions
|
||||||
|
static const String confirm = "Confirm";
|
||||||
|
static const String cancel = "Cancel";
|
||||||
|
static const String back = "Back";
|
||||||
|
static const String close = "Close";
|
||||||
|
static const String equip = "Equip";
|
||||||
|
static const String unequip = "Unequip";
|
||||||
|
static const String discard = "Discard";
|
||||||
|
static const String sell = "Sell";
|
||||||
|
static const String buy = "Buy";
|
||||||
|
|
||||||
|
// Stats
|
||||||
|
static const String hp = "HP";
|
||||||
|
static const String atk = "ATK";
|
||||||
|
static const String def = "DEF";
|
||||||
|
static const String armor = "Armor";
|
||||||
|
static const String luck = "Luck";
|
||||||
|
static const String gold = "Gold";
|
||||||
|
|
||||||
|
// Battle
|
||||||
|
static const String attack = "Attack";
|
||||||
|
static const String defend = "Defend";
|
||||||
|
static const String turn = "Turn";
|
||||||
|
static const String playerTurn = "Player's Turn";
|
||||||
|
static const String enemyTurn = "Enemy's Turn";
|
||||||
|
static const String victory = "Victory!";
|
||||||
|
static const String defeat = "Defeat";
|
||||||
|
static const String reward = "Reward";
|
||||||
|
static const String chooseReward = "Choose a Reward";
|
||||||
|
static const String skip = "Skip";
|
||||||
|
static const String nextStage = "Next Stage";
|
||||||
|
static const String returnToMenu = "Return to Menu";
|
||||||
|
static const String restart = "Restart";
|
||||||
|
|
||||||
|
// Inventory
|
||||||
|
static const String inventory = "Inventory";
|
||||||
|
static const String equipment = "Equipment";
|
||||||
|
static const String bag = "Bag";
|
||||||
|
static const String emptySlot = "Empty";
|
||||||
|
static const String noItems = "No items in inventory";
|
||||||
|
|
||||||
|
// Shop
|
||||||
|
static const String shopTitle = "Merchant";
|
||||||
|
static const String shopWelcome = "Welcome, traveler!";
|
||||||
|
static const String refreshShop = "Restock";
|
||||||
|
static const String notEnoughGold = "Not enough gold!";
|
||||||
|
static const String inventoryFull = "Inventory is full!";
|
||||||
|
|
||||||
|
// Risk Levels
|
||||||
|
static const String riskSafe = "Safe";
|
||||||
|
static const String riskNormal = "Normal";
|
||||||
|
static const String riskRisky = "Risky";
|
||||||
|
|
||||||
|
// Settings
|
||||||
|
static const String settings = "Settings";
|
||||||
|
}
|
||||||
|
|
@ -21,6 +21,7 @@ import '../widgets/battle/explosion_widget.dart';
|
||||||
import 'main_menu_screen.dart';
|
import 'main_menu_screen.dart';
|
||||||
import '../game/config/battle_config.dart';
|
import '../game/config/battle_config.dart';
|
||||||
import '../game/config/theme_config.dart';
|
import '../game/config/theme_config.dart';
|
||||||
|
import '../game/config/app_strings.dart';
|
||||||
|
|
||||||
class BattleScreen extends StatefulWidget {
|
class BattleScreen extends StatefulWidget {
|
||||||
const BattleScreen({super.key});
|
const BattleScreen({super.key});
|
||||||
|
|
@ -43,7 +44,7 @@ class _BattleScreenState extends State<BattleScreen> {
|
||||||
GlobalKey<BattleAnimationWidgetState>();
|
GlobalKey<BattleAnimationWidgetState>();
|
||||||
final GlobalKey<ExplosionWidgetState> _explosionKey =
|
final GlobalKey<ExplosionWidgetState> _explosionKey =
|
||||||
GlobalKey<ExplosionWidgetState>();
|
GlobalKey<ExplosionWidgetState>();
|
||||||
bool _showLogs = true;
|
bool _showLogs = false;
|
||||||
bool _isPlayerAttacking = false; // Player Attack Animation State
|
bool _isPlayerAttacking = false; // Player Attack Animation State
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|
@ -421,7 +422,7 @@ class _BattleScreenState extends State<BattleScreen> {
|
||||||
child: FittedBox(
|
child: FittedBox(
|
||||||
fit: BoxFit.scaleDown,
|
fit: BoxFit.scaleDown,
|
||||||
child: Text(
|
child: Text(
|
||||||
"Turn ${battleProvider.turnCount}",
|
"${AppStrings.turn} ${battleProvider.turnCount}",
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
color: ThemeConfig.textColorWhite,
|
color: ThemeConfig.textColorWhite,
|
||||||
fontSize: ThemeConfig.fontSizeHeader,
|
fontSize: ThemeConfig.fontSizeHeader,
|
||||||
|
|
@ -540,12 +541,16 @@ class _BattleScreenState extends State<BattleScreen> {
|
||||||
child: SimpleDialog(
|
child: SimpleDialog(
|
||||||
title: Row(
|
title: Row(
|
||||||
children: [
|
children: [
|
||||||
const Text("Victory! Choose a Reward"),
|
const Text("${AppStrings.victory} ${AppStrings.chooseReward}"),
|
||||||
const Spacer(),
|
const Spacer(),
|
||||||
Row(
|
Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Icon(Icons.monetization_on, color: ThemeConfig.statGoldColor, size: 18),
|
Icon(
|
||||||
|
Icons.monetization_on,
|
||||||
|
color: ThemeConfig.statGoldColor,
|
||||||
|
size: 18,
|
||||||
|
),
|
||||||
const SizedBox(width: 4),
|
const SizedBox(width: 4),
|
||||||
Text(
|
Text(
|
||||||
"${battleProvider.lastGoldReward} G",
|
"${battleProvider.lastGoldReward} G",
|
||||||
|
|
@ -568,7 +573,7 @@ class _BattleScreenState extends State<BattleScreen> {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
const SnackBar(
|
const SnackBar(
|
||||||
content: Text(
|
content: Text(
|
||||||
"Inventory is full! Cannot take item.",
|
"${AppStrings.inventoryFull} Cannot take item.",
|
||||||
),
|
),
|
||||||
backgroundColor: Colors.red,
|
backgroundColor: Colors.red,
|
||||||
),
|
),
|
||||||
|
|
@ -586,10 +591,11 @@ class _BattleScreenState extends State<BattleScreen> {
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
color: Colors.blueGrey[700],
|
color: Colors.blueGrey[700],
|
||||||
borderRadius: BorderRadius.circular(
|
borderRadius: BorderRadius.circular(
|
||||||
4),
|
4,
|
||||||
|
),
|
||||||
border: Border.all(
|
border: Border.all(
|
||||||
color: item.rarity !=
|
color:
|
||||||
ItemRarity.magic
|
item.rarity != ItemRarity.magic
|
||||||
? ItemUtils.getRarityColor(
|
? ItemUtils.getRarityColor(
|
||||||
item.rarity,
|
item.rarity,
|
||||||
)
|
)
|
||||||
|
|
@ -613,7 +619,8 @@ class _BattleScreenState extends State<BattleScreen> {
|
||||||
color: isSkip
|
color: isSkip
|
||||||
? ThemeConfig.textColorGrey
|
? ThemeConfig.textColorGrey
|
||||||
: ItemUtils.getRarityColor(
|
: ItemUtils.getRarityColor(
|
||||||
item.rarity),
|
item.rarity,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
@ -651,7 +658,7 @@ class _BattleScreenState extends State<BattleScreen> {
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
const Text(
|
const Text(
|
||||||
"DEFEAT",
|
AppStrings.defeat,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: ThemeConfig.statHpColor,
|
color: ThemeConfig.statHpColor,
|
||||||
fontSize: ThemeConfig.fontSizeHuge,
|
fontSize: ThemeConfig.fontSizeHuge,
|
||||||
|
|
@ -677,7 +684,7 @@ class _BattleScreenState extends State<BattleScreen> {
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: const Text(
|
child: const Text(
|
||||||
"Return to Main Menu",
|
AppStrings.returnToMenu,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: ThemeConfig.textColorWhite,
|
color: ThemeConfig.textColorWhite,
|
||||||
fontSize: ThemeConfig.fontSizeHeader,
|
fontSize: ThemeConfig.fontSizeHeader,
|
||||||
|
|
@ -698,10 +705,10 @@ class _BattleScreenState extends State<BattleScreen> {
|
||||||
|
|
||||||
Widget _buildItemStatText(Item item) {
|
Widget _buildItemStatText(Item item) {
|
||||||
List<String> stats = [];
|
List<String> stats = [];
|
||||||
if (item.atkBonus > 0) stats.add("+${item.atkBonus} ATK");
|
if (item.atkBonus > 0) stats.add("+${item.atkBonus} ${AppStrings.atk}");
|
||||||
if (item.hpBonus > 0) stats.add("+${item.hpBonus} HP");
|
if (item.hpBonus > 0) stats.add("+${item.hpBonus} ${AppStrings.hp}");
|
||||||
if (item.armorBonus > 0) stats.add("+${item.armorBonus} DEF");
|
if (item.armorBonus > 0) stats.add("+${item.armorBonus} ${AppStrings.def}");
|
||||||
if (item.luck > 0) stats.add("+${item.luck} Luck");
|
if (item.luck > 0) stats.add("+${item.luck} ${AppStrings.luck}");
|
||||||
|
|
||||||
List<String> effectTexts = item.effects.map((e) => e.description).toList();
|
List<String> effectTexts = item.effects.map((e) => e.description).toList();
|
||||||
|
|
||||||
|
|
@ -715,7 +722,10 @@ class _BattleScreenState extends State<BattleScreen> {
|
||||||
padding: const EdgeInsets.only(top: 4.0, bottom: 4.0),
|
padding: const EdgeInsets.only(top: 4.0, bottom: 4.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
stats.join(", "),
|
stats.join(", "),
|
||||||
style: const TextStyle(fontSize: ThemeConfig.fontSizeMedium, color: ThemeConfig.statAtkColor),
|
style: const TextStyle(
|
||||||
|
fontSize: ThemeConfig.fontSizeMedium,
|
||||||
|
color: ThemeConfig.statAtkColor,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (effectTexts.isNotEmpty)
|
if (effectTexts.isNotEmpty)
|
||||||
|
|
@ -723,7 +733,10 @@ class _BattleScreenState extends State<BattleScreen> {
|
||||||
padding: const EdgeInsets.only(bottom: 4.0),
|
padding: const EdgeInsets.only(bottom: 4.0),
|
||||||
child: Text(
|
child: Text(
|
||||||
effectTexts.join(", "),
|
effectTexts.join(", "),
|
||||||
style: const TextStyle(fontSize: 11, color: ThemeConfig.rarityLegendary), // 11 is custom, keep or change? Let's use Small
|
style: const TextStyle(
|
||||||
|
fontSize: 11,
|
||||||
|
color: ThemeConfig.rarityLegendary,
|
||||||
|
), // 11 is custom, keep or change? Let's use Small
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import '../game/data/player_table.dart';
|
||||||
import 'main_wrapper.dart';
|
import 'main_wrapper.dart';
|
||||||
import '../widgets/responsive_container.dart';
|
import '../widgets/responsive_container.dart';
|
||||||
import '../game/config/theme_config.dart';
|
import '../game/config/theme_config.dart';
|
||||||
|
import '../game/config/app_strings.dart';
|
||||||
|
|
||||||
class CharacterSelectionScreen extends StatelessWidget {
|
class CharacterSelectionScreen extends StatelessWidget {
|
||||||
const CharacterSelectionScreen({super.key});
|
const CharacterSelectionScreen({super.key});
|
||||||
|
|
@ -83,19 +84,19 @@ class CharacterSelectionScreen extends StatelessWidget {
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"HP: ${warrior.baseHp}",
|
"${AppStrings.hp}: ${warrior.baseHp}",
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontWeight: ThemeConfig.fontWeightBold,
|
fontWeight: ThemeConfig.fontWeightBold,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
"ATK: ${warrior.baseAtk}",
|
"${AppStrings.atk}: ${warrior.baseAtk}",
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontWeight: ThemeConfig.fontWeightBold,
|
fontWeight: ThemeConfig.fontWeightBold,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
"DEF: ${warrior.baseDefense}",
|
"${AppStrings.def}: ${warrior.baseDefense}",
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontWeight: ThemeConfig.fontWeightBold,
|
fontWeight: ThemeConfig.fontWeightBold,
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ import '../game/model/item.dart';
|
||||||
import '../game/enums.dart';
|
import '../game/enums.dart';
|
||||||
import '../utils/item_utils.dart';
|
import '../utils/item_utils.dart';
|
||||||
import '../game/config/theme_config.dart';
|
import '../game/config/theme_config.dart';
|
||||||
|
import '../game/config/app_strings.dart';
|
||||||
|
|
||||||
class InventoryScreen extends StatelessWidget {
|
class InventoryScreen extends StatelessWidget {
|
||||||
const InventoryScreen({super.key});
|
const InventoryScreen({super.key});
|
||||||
|
|
@ -37,28 +38,28 @@ class InventoryScreen extends StatelessWidget {
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
mainAxisAlignment: MainAxisAlignment.spaceAround,
|
||||||
children: [
|
children: [
|
||||||
_buildStatItem(
|
_buildStatItem(
|
||||||
"HP",
|
AppStrings.hp,
|
||||||
"${player.hp}/${player.totalMaxHp}",
|
"${player.hp}/${player.totalMaxHp}",
|
||||||
color: ThemeConfig.statHpColor,
|
color: ThemeConfig.statHpColor,
|
||||||
),
|
),
|
||||||
_buildStatItem(
|
_buildStatItem(
|
||||||
"ATK",
|
AppStrings.atk,
|
||||||
"${player.totalAtk}",
|
"${player.totalAtk}",
|
||||||
color: ThemeConfig.statAtkColor,
|
color: ThemeConfig.statAtkColor,
|
||||||
),
|
),
|
||||||
_buildStatItem(
|
_buildStatItem(
|
||||||
"DEF",
|
AppStrings.def,
|
||||||
"${player.totalDefense}",
|
"${player.totalDefense}",
|
||||||
color: ThemeConfig.statDefColor,
|
color: ThemeConfig.statDefColor,
|
||||||
),
|
),
|
||||||
_buildStatItem("Shield", "${player.armor}"),
|
_buildStatItem(AppStrings.armor, "${player.armor}"),
|
||||||
_buildStatItem(
|
_buildStatItem(
|
||||||
"Luck",
|
AppStrings.luck,
|
||||||
"${player.totalLuck}",
|
"${player.totalLuck}",
|
||||||
color: ThemeConfig.statLuckColor,
|
color: ThemeConfig.statLuckColor,
|
||||||
),
|
),
|
||||||
_buildStatItem(
|
_buildStatItem(
|
||||||
"Gold",
|
AppStrings.gold,
|
||||||
"${player.gold} G",
|
"${player.gold} G",
|
||||||
color: ThemeConfig.statGoldColor,
|
color: ThemeConfig.statGoldColor,
|
||||||
),
|
),
|
||||||
|
|
@ -162,7 +163,7 @@ class InventoryScreen extends StatelessWidget {
|
||||||
FittedBox(
|
FittedBox(
|
||||||
fit: BoxFit.scaleDown,
|
fit: BoxFit.scaleDown,
|
||||||
child: Text(
|
child: Text(
|
||||||
item?.name ?? "Empty",
|
item?.name ?? AppStrings.emptySlot,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize:
|
fontSize:
|
||||||
|
|
@ -208,7 +209,7 @@ class InventoryScreen extends StatelessWidget {
|
||||||
child: Align(
|
child: Align(
|
||||||
alignment: Alignment.centerLeft,
|
alignment: Alignment.centerLeft,
|
||||||
child: Text(
|
child: Text(
|
||||||
"Bag (${player.inventory.length}/${player.maxInventorySize})",
|
"${AppStrings.bag} (${player.inventory.length}/${player.maxInventorySize})",
|
||||||
style: const TextStyle(
|
style: const TextStyle(
|
||||||
fontSize: ThemeConfig.fontSizeHeader,
|
fontSize: ThemeConfig.fontSizeHeader,
|
||||||
fontWeight: ThemeConfig.fontWeightBold,
|
fontWeight: ThemeConfig.fontWeightBold,
|
||||||
|
|
@ -371,7 +372,7 @@ class InventoryScreen extends StatelessWidget {
|
||||||
children: [
|
children: [
|
||||||
Icon(Icons.shield, color: ThemeConfig.btnDefendActive),
|
Icon(Icons.shield, color: ThemeConfig.btnDefendActive),
|
||||||
SizedBox(width: 10),
|
SizedBox(width: 10),
|
||||||
Text("Equip"),
|
Text(AppStrings.equip),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -391,7 +392,7 @@ class InventoryScreen extends StatelessWidget {
|
||||||
color: ThemeConfig.statGoldColor,
|
color: ThemeConfig.statGoldColor,
|
||||||
),
|
),
|
||||||
const SizedBox(width: 10),
|
const SizedBox(width: 10),
|
||||||
Text("Sell (${item.price} G)"),
|
Text("${AppStrings.sell} (${item.price} G)"),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -407,7 +408,7 @@ class InventoryScreen extends StatelessWidget {
|
||||||
children: [
|
children: [
|
||||||
Icon(Icons.delete, color: ThemeConfig.btnActionActive),
|
Icon(Icons.delete, color: ThemeConfig.btnActionActive),
|
||||||
SizedBox(width: 10),
|
SizedBox(width: 10),
|
||||||
Text("Discard"),
|
Text(AppStrings.discard),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|
@ -430,7 +431,7 @@ class InventoryScreen extends StatelessWidget {
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.pop(ctx),
|
onPressed: () => Navigator.pop(ctx),
|
||||||
child: const Text("Cancel"),
|
child: const Text(AppStrings.cancel),
|
||||||
),
|
),
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
|
|
@ -440,7 +441,7 @@ class InventoryScreen extends StatelessWidget {
|
||||||
provider.sellItem(item);
|
provider.sellItem(item);
|
||||||
Navigator.pop(ctx);
|
Navigator.pop(ctx);
|
||||||
},
|
},
|
||||||
child: const Text("Sell", style: TextStyle(color: Colors.black)),
|
child: const Text(AppStrings.sell, style: TextStyle(color: Colors.black)),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -460,7 +461,7 @@ class InventoryScreen extends StatelessWidget {
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.pop(ctx),
|
onPressed: () => Navigator.pop(ctx),
|
||||||
child: const Text("Cancel"),
|
child: const Text(AppStrings.cancel),
|
||||||
),
|
),
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
|
|
@ -470,7 +471,7 @@ class InventoryScreen extends StatelessWidget {
|
||||||
provider.discardItem(item);
|
provider.discardItem(item);
|
||||||
Navigator.pop(ctx);
|
Navigator.pop(ctx);
|
||||||
},
|
},
|
||||||
child: const Text("Discard"),
|
child: const Text(AppStrings.discard),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -510,7 +511,7 @@ class InventoryScreen extends StatelessWidget {
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Equip ${newItem.name}?",
|
"${AppStrings.equip} ${newItem.name}?",
|
||||||
style: const TextStyle(fontWeight: ThemeConfig.fontWeightBold),
|
style: const TextStyle(fontWeight: ThemeConfig.fontWeightBold),
|
||||||
),
|
),
|
||||||
if (oldItem != null)
|
if (oldItem != null)
|
||||||
|
|
@ -524,8 +525,8 @@ class InventoryScreen extends StatelessWidget {
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
_buildStatChangeRow("Max HP", currentMaxHp, newMaxHp),
|
_buildStatChangeRow("Max HP", currentMaxHp, newMaxHp),
|
||||||
_buildStatChangeRow("Current HP", currentHp, newHp),
|
_buildStatChangeRow("Current HP", currentHp, newHp),
|
||||||
_buildStatChangeRow("ATK", currentAtk, newAtk),
|
_buildStatChangeRow(AppStrings.atk, currentAtk, newAtk),
|
||||||
_buildStatChangeRow("DEF", currentDef, newDef),
|
_buildStatChangeRow(AppStrings.def, currentDef, newDef),
|
||||||
_buildStatChangeRow(
|
_buildStatChangeRow(
|
||||||
"LUCK",
|
"LUCK",
|
||||||
player.totalLuck,
|
player.totalLuck,
|
||||||
|
|
@ -536,14 +537,14 @@ class InventoryScreen extends StatelessWidget {
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.pop(ctx),
|
onPressed: () => Navigator.pop(ctx),
|
||||||
child: const Text("Cancel"),
|
child: const Text(AppStrings.cancel),
|
||||||
),
|
),
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
provider.equipItem(newItem);
|
provider.equipItem(newItem);
|
||||||
Navigator.pop(ctx);
|
Navigator.pop(ctx);
|
||||||
},
|
},
|
||||||
child: const Text("Confirm"),
|
child: const Text(AppStrings.confirm),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -582,27 +583,27 @@ class InventoryScreen extends StatelessWidget {
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
"Unequip ${itemToUnequip.name}?",
|
"${AppStrings.unequip} ${itemToUnequip.name}?",
|
||||||
style: const TextStyle(fontWeight: ThemeConfig.fontWeightBold),
|
style: const TextStyle(fontWeight: ThemeConfig.fontWeightBold),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
_buildStatChangeRow("Max HP", currentMaxHp, newMaxHp),
|
_buildStatChangeRow("Max HP", currentMaxHp, newMaxHp),
|
||||||
_buildStatChangeRow("Current HP", currentHp, newHp),
|
_buildStatChangeRow("Current HP", currentHp, newHp),
|
||||||
_buildStatChangeRow("ATK", currentAtk, newAtk),
|
_buildStatChangeRow(AppStrings.atk, currentAtk, newAtk),
|
||||||
_buildStatChangeRow("DEF", currentDef, newDef),
|
_buildStatChangeRow(AppStrings.def, currentDef, newDef),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.pop(ctx),
|
onPressed: () => Navigator.pop(ctx),
|
||||||
child: const Text("Cancel"),
|
child: const Text(AppStrings.cancel),
|
||||||
),
|
),
|
||||||
ElevatedButton(
|
ElevatedButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
provider.unequipItem(itemToUnequip);
|
provider.unequipItem(itemToUnequip);
|
||||||
Navigator.pop(ctx);
|
Navigator.pop(ctx);
|
||||||
},
|
},
|
||||||
child: const Text("Confirm"),
|
child: const Text(AppStrings.confirm),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -657,10 +658,10 @@ class InventoryScreen extends StatelessWidget {
|
||||||
|
|
||||||
Widget _buildItemStatText(Item item) {
|
Widget _buildItemStatText(Item item) {
|
||||||
List<String> stats = [];
|
List<String> stats = [];
|
||||||
if (item.atkBonus > 0) stats.add("+${item.atkBonus} ATK");
|
if (item.atkBonus > 0) stats.add("+${item.atkBonus} ${AppStrings.atk}");
|
||||||
if (item.hpBonus > 0) stats.add("+${item.hpBonus} HP");
|
if (item.hpBonus > 0) stats.add("+${item.hpBonus} ${AppStrings.hp}");
|
||||||
if (item.armorBonus > 0) stats.add("+${item.armorBonus} DEF");
|
if (item.armorBonus > 0) stats.add("+${item.armorBonus} ${AppStrings.def}");
|
||||||
if (item.luck > 0) stats.add("+${item.luck} Luck");
|
if (item.luck > 0) stats.add("+${item.luck} ${AppStrings.luck}");
|
||||||
|
|
||||||
// Include effects
|
// Include effects
|
||||||
List<String> effectTexts = item.effects.map((e) => e.description).toList();
|
List<String> effectTexts = item.effects.map((e) => e.description).toList();
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ import '../widgets/responsive_container.dart';
|
||||||
import '../game/save_manager.dart';
|
import '../game/save_manager.dart';
|
||||||
import '../providers/battle_provider.dart';
|
import '../providers/battle_provider.dart';
|
||||||
import '../game/config/theme_config.dart';
|
import '../game/config/theme_config.dart';
|
||||||
|
import '../game/config/app_strings.dart';
|
||||||
|
|
||||||
class MainMenuScreen extends StatefulWidget {
|
class MainMenuScreen extends StatefulWidget {
|
||||||
const MainMenuScreen({super.key});
|
const MainMenuScreen({super.key});
|
||||||
|
|
@ -79,7 +80,7 @@ class _MainMenuScreenState extends State<MainMenuScreen> {
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
const Text(
|
const Text(
|
||||||
"COLOSSEUM'S CHOICE",
|
AppStrings.gameTitle,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: ThemeConfig.fontSizeHero,
|
fontSize: ThemeConfig.fontSizeHero,
|
||||||
fontWeight: ThemeConfig.fontWeightBold,
|
fontWeight: ThemeConfig.fontWeightBold,
|
||||||
|
|
@ -112,7 +113,7 @@ class _MainMenuScreenState extends State<MainMenuScreen> {
|
||||||
fontWeight: ThemeConfig.fontWeightBold,
|
fontWeight: ThemeConfig.fontWeightBold,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: const Text("CONTINUE"),
|
child: const Text(AppStrings.continueGame),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 20),
|
const SizedBox(height: 20),
|
||||||
],
|
],
|
||||||
|
|
@ -139,7 +140,7 @@ class _MainMenuScreenState extends State<MainMenuScreen> {
|
||||||
fontWeight: ThemeConfig.fontWeightBold,
|
fontWeight: ThemeConfig.fontWeightBold,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
child: const Text("NEW GAME"),
|
child: const Text(AppStrings.startGame),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -3,6 +3,7 @@ import 'package:provider/provider.dart';
|
||||||
import '../providers/battle_provider.dart';
|
import '../providers/battle_provider.dart';
|
||||||
import 'main_menu_screen.dart';
|
import 'main_menu_screen.dart';
|
||||||
import '../game/config/theme_config.dart';
|
import '../game/config/theme_config.dart';
|
||||||
|
import '../game/config/app_strings.dart';
|
||||||
|
|
||||||
class SettingsScreen extends StatelessWidget {
|
class SettingsScreen extends StatelessWidget {
|
||||||
const SettingsScreen({super.key});
|
const SettingsScreen({super.key});
|
||||||
|
|
@ -14,7 +15,7 @@ class SettingsScreen extends StatelessWidget {
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
const Text(
|
const Text(
|
||||||
'Settings',
|
AppStrings.settings,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
fontSize: ThemeConfig.fontSizeTitle,
|
fontSize: ThemeConfig.fontSizeTitle,
|
||||||
fontWeight: ThemeConfig.fontWeightBold,
|
fontWeight: ThemeConfig.fontWeightBold,
|
||||||
|
|
@ -43,7 +44,7 @@ class SettingsScreen extends StatelessWidget {
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
_showConfirmationDialog(
|
_showConfirmationDialog(
|
||||||
context,
|
context,
|
||||||
title: 'Restart Game?',
|
title: '${AppStrings.restart} Game?',
|
||||||
content: 'All progress will be lost. Are you sure?',
|
content: 'All progress will be lost. Are you sure?',
|
||||||
onConfirm: () {
|
onConfirm: () {
|
||||||
context.read<BattleProvider>().initializeBattle();
|
context.read<BattleProvider>().initializeBattle();
|
||||||
|
|
@ -70,7 +71,7 @@ class SettingsScreen extends StatelessWidget {
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
_showConfirmationDialog(
|
_showConfirmationDialog(
|
||||||
context,
|
context,
|
||||||
title: 'Return to Main Menu?',
|
title: '${AppStrings.returnToMenu}?',
|
||||||
content: 'Unsaved progress may be lost. (Progress is saved automatically after each stage)',
|
content: 'Unsaved progress may be lost. (Progress is saved automatically after each stage)',
|
||||||
onConfirm: () {
|
onConfirm: () {
|
||||||
Navigator.of(context).pushAndRemoveUntil(
|
Navigator.of(context).pushAndRemoveUntil(
|
||||||
|
|
@ -80,7 +81,7 @@ class SettingsScreen extends StatelessWidget {
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
child: const Text('Return to Main Menu'),
|
child: const Text(AppStrings.returnToMenu),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
@ -96,14 +97,14 @@ class SettingsScreen extends StatelessWidget {
|
||||||
actions: [
|
actions: [
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () => Navigator.pop(context),
|
onPressed: () => Navigator.pop(context),
|
||||||
child: const Text('Cancel'),
|
child: const Text(AppStrings.cancel),
|
||||||
),
|
),
|
||||||
TextButton(
|
TextButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
onConfirm();
|
onConfirm();
|
||||||
},
|
},
|
||||||
child: const Text('Confirm', style: TextStyle(color: Colors.red)),
|
child: const Text(AppStrings.confirm, style: TextStyle(color: Colors.red)),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
# 60. Introduce AppStrings for Soft i18n
|
||||||
|
|
||||||
|
## 1. 목표 (Goal)
|
||||||
|
- UI 텍스트 하드코딩을 방지하고 추후 본격적인 i18n 적용을 대비하기 위해 `AppStrings` 상수 클래스를 도입합니다.
|
||||||
|
- 자주 사용되는 UI 텍스트(메뉴, 스탯, 행동 등)를 한 곳에서 관리합니다.
|
||||||
|
|
||||||
|
## 2. 구현 계획 (Implementation Plan)
|
||||||
|
1. **`lib/game/config/app_strings.dart` 생성:**
|
||||||
|
- `actionAttack`, `actionDefend`, `statHp`, `statAtk` 등 카테고리별로 정적 상수를 정의합니다.
|
||||||
|
2. **UI 코드 수정:**
|
||||||
|
- `BattleScreen`, `InventoryScreen`, `MainMenuScreen` 등에서 하드코딩된 문자열을 `AppStrings.xxx`로 교체합니다.
|
||||||
|
- *Note:* 전투 로그와 같이 동적으로 생성되는 복잡한 문장은 이번 단계에서 제외합니다.
|
||||||
|
|
||||||
|
## 3. 기대 효과 (Expected Outcome)
|
||||||
|
- 텍스트 변경 시 `AppStrings`만 수정하면 되므로 유지보수성 향상.
|
||||||
|
- 추후 다국어 지원 라이브러리 도입 시 마이그레이션이 매우 쉬워짐.
|
||||||
Loading…
Reference in New Issue