feat(l10n): 게임 텍스트 다국어 지원 확장

- game_text_l10n.dart: 스탯/UI 텍스트 추가 (+61 라인)
- 한국어/일본어 번역 업데이트
- game_data_l10n.dart: 텍스트 접근자 추가
- equipment_stats_panel: l10n 적용 및 레이아웃 개선
- active_buff_panel, potion_inventory_panel: 코드 정리
- new_character_screen: 코드 정리
- progress_service: 마이너 개선
This commit is contained in:
JiWoong Sul
2025-12-23 15:51:56 +09:00
parent 99f5b74802
commit 1da6fa7a2b
10 changed files with 137 additions and 26 deletions

View File

@@ -174,6 +174,10 @@ class _GamePlayScreenState extends State<GamePlayScreen>
/// 전투 이벤트를 메시지와 타입으로 변환
(String, CombatLogType) _formatCombatEvent(CombatEvent event) {
final target = event.targetName ?? '';
// 스킬/포션 이름 번역 (전역 로케일 사용)
final skillName = event.skillName != null
? game_l10n.translateSpell(event.skillName!)
: '';
return switch (event.type) {
CombatEventType.playerAttack =>
event.isCritical
@@ -208,41 +212,34 @@ class _GamePlayScreenState extends State<GamePlayScreen>
CombatEventType.playerSkill =>
event.isCritical
? (
game_l10n.combatSkillCritical(
event.skillName ?? '',
event.damage,
),
game_l10n.combatSkillCritical(skillName, event.damage),
CombatLogType.critical,
)
: (
game_l10n.combatSkillDamage(event.skillName ?? '', event.damage),
game_l10n.combatSkillDamage(skillName, event.damage),
CombatLogType.spell,
),
CombatEventType.playerHeal => (
game_l10n.combatSkillHeal(
event.skillName ?? game_l10n.uiHeal,
skillName.isNotEmpty ? skillName : game_l10n.uiHeal,
event.healAmount,
),
CombatLogType.heal,
),
CombatEventType.playerBuff => (
game_l10n.combatBuffActivated(event.skillName ?? ''),
game_l10n.combatBuffActivated(skillName),
CombatLogType.buff,
),
CombatEventType.dotTick => (
game_l10n.combatDotTick(event.skillName ?? '', event.damage),
game_l10n.combatDotTick(skillName, event.damage),
CombatLogType.dotTick,
),
CombatEventType.playerPotion => (
game_l10n.combatPotionUsed(
event.skillName ?? '',
event.healAmount,
target,
),
game_l10n.combatPotionUsed(skillName, event.healAmount, target),
CombatLogType.potion,
),
CombatEventType.potionDrop => (
game_l10n.combatPotionDrop(event.skillName ?? ''),
game_l10n.combatPotionDrop(skillName),
CombatLogType.potionDrop,
),
};

View File

@@ -127,7 +127,7 @@ class _BuffRow extends StatelessWidget {
if (effect.atkModifier != 0) {
modifiers.add(
_ModifierChip(
label: 'ATK',
label: l10n.statAtk,
value: effect.atkModifier,
isPositive: effect.atkModifier > 0,
),
@@ -137,7 +137,7 @@ class _BuffRow extends StatelessWidget {
if (effect.defModifier != 0) {
modifiers.add(
_ModifierChip(
label: 'DEF',
label: l10n.statDef,
value: effect.defModifier,
isPositive: effect.defModifier > 0,
),
@@ -147,7 +147,7 @@ class _BuffRow extends StatelessWidget {
if (effect.criRateModifier != 0) {
modifiers.add(
_ModifierChip(
label: 'CRI',
label: l10n.statCri,
value: effect.criRateModifier,
isPositive: effect.criRateModifier > 0,
),
@@ -157,7 +157,7 @@ class _BuffRow extends StatelessWidget {
if (effect.evasionModifier != 0) {
modifiers.add(
_ModifierChip(
label: 'EVA',
label: l10n.statEva,
value: effect.evasionModifier,
isPositive: effect.evasionModifier > 0,
),

View File

@@ -2,6 +2,7 @@ import 'package:flutter/material.dart';
import 'package:askiineverdie/data/game_text_l10n.dart' as l10n;
import 'package:askiineverdie/src/core/engine/item_service.dart';
import 'package:askiineverdie/src/core/l10n/game_data_l10n.dart';
import 'package:askiineverdie/src/core/model/equipment_item.dart';
import 'package:askiineverdie/src/core/model/equipment_slot.dart';
import 'package:askiineverdie/src/core/model/game_state.dart';
@@ -80,6 +81,12 @@ class _EquipmentSlotTile extends StatelessWidget {
final score = ItemService.calculateEquipmentScore(item);
final rarityColor = _getRarityColor(item.rarity);
// 슬롯 인덱스로 아이템 이름 번역 (0: weapon, 1: shield, 2+: armor)
final translatedName = GameDataL10n.translateEquipString(
context,
item.name,
item.slot.index,
);
return ExpansionTile(
initiallyExpanded: initiallyExpanded,
@@ -92,7 +99,7 @@ class _EquipmentSlotTile extends StatelessWidget {
const SizedBox(width: 4),
Expanded(
child: Text(
item.name,
translatedName,
style: TextStyle(
fontSize: 11,
color: rarityColor,
@@ -426,7 +433,7 @@ class _ItemMetaRow extends StatelessWidget {
@override
Widget build(BuildContext context) {
final rarityName = item.rarity.name.toUpperCase();
final rarityName = _getTranslatedRarity(item.rarity);
return Row(
children: [
@@ -479,3 +486,14 @@ String _getSlotName(EquipmentSlot slot) {
EquipmentSlot.sollerets => l10n.slotSollerets,
};
}
/// 희귀도 번역 반환
String _getTranslatedRarity(ItemRarity rarity) {
return switch (rarity) {
ItemRarity.common => l10n.rarityCommon,
ItemRarity.uncommon => l10n.rarityUncommon,
ItemRarity.rare => l10n.rarityRare,
ItemRarity.epic => l10n.rarityEpic,
ItemRarity.legendary => l10n.rarityLegendary,
};
}

View File

@@ -110,10 +110,10 @@ class _PotionRow extends StatelessWidget {
_PotionIcon(type: potion.type, tier: potion.tier),
const SizedBox(width: 4),
// 물약 이름
// 물약 이름 (번역 적용)
Expanded(
child: Text(
potion.name,
l10n.translateSpell(potion.name),
style: TextStyle(
fontSize: 11,
color: color,