diff --git a/lib/l10n/app_en.arb b/lib/l10n/app_en.arb index 62bffca..6269274 100644 --- a/lib/l10n/app_en.arb +++ b/lib/l10n/app_en.arb @@ -251,5 +251,58 @@ "@newCharacterTitle": { "description": "New character screen title" }, "soldButton": "Sold!", - "@soldButton": { "description": "Confirm character creation button" } + "@soldButton": { "description": "Confirm character creation button" }, + + "endingCongratulations": "★ CONGRATULATIONS ★", + "@endingCongratulations": { "description": "Victory overlay congratulations" }, + + "endingGameComplete": "You have completed the game!", + "@endingGameComplete": { "description": "Game completion message" }, + + "endingTheHero": "THE HERO", + "@endingTheHero": { "description": "Hero section title" }, + + "endingLevelFormat": "Level {level}", + "@endingLevelFormat": { + "description": "Level display format", + "placeholders": { + "level": { "type": "int" } + } + }, + + "endingJourneyStats": "JOURNEY STATISTICS", + "@endingJourneyStats": { "description": "Journey statistics section title" }, + + "endingMonstersSlain": "Monsters Slain", + "@endingMonstersSlain": { "description": "Monsters killed stat label" }, + + "endingQuestsCompleted": "Quests Completed", + "@endingQuestsCompleted": { "description": "Quests completed stat label" }, + + "endingPlayTime": "Play Time", + "@endingPlayTime": { "description": "Play time stat label" }, + + "endingFinalStats": "FINAL STATS", + "@endingFinalStats": { "description": "Final stats section title" }, + + "endingCredits": "CREDITS", + "@endingCredits": { "description": "Credits section title" }, + + "endingThankYou": "Thank you for playing!", + "@endingThankYou": { "description": "Thank you message" }, + + "endingLegendLivesOn": "Your legend lives on...", + "@endingLegendLivesOn": { "description": "Legend message" }, + + "endingHallOfFameLine1": "Your heroic deeds will be", + "@endingHallOfFameLine1": { "description": "Hall of fame message line 1" }, + + "endingHallOfFameLine2": "remembered in the Hall of Fame", + "@endingHallOfFameLine2": { "description": "Hall of fame message line 2" }, + + "endingSkip": "SKIP", + "@endingSkip": { "description": "Skip button" }, + + "endingTapToSkip": "TAP TO SKIP", + "@endingTapToSkip": { "description": "Tap to skip hint" } } diff --git a/lib/l10n/app_ja.arb b/lib/l10n/app_ja.arb index 30268a9..31b6385 100644 --- a/lib/l10n/app_ja.arb +++ b/lib/l10n/app_ja.arb @@ -74,5 +74,22 @@ "classTitle": "Class", "percentComplete": "{percent}% complete", "newCharacterTitle": "ASCII NEVER DIE - New Character", - "soldButton": "Sold!" + "soldButton": "Sold!", + + "endingCongratulations": "★ おめでとうございます ★", + "endingGameComplete": "ゲームをクリアしました!", + "endingTheHero": "英雄", + "endingLevelFormat": "レベル {level}", + "endingJourneyStats": "冒険の記録", + "endingMonstersSlain": "倒したモンスター", + "endingQuestsCompleted": "完了したクエスト", + "endingPlayTime": "プレイ時間", + "endingFinalStats": "最終ステータス", + "endingCredits": "クレジット", + "endingThankYou": "プレイしていただきありがとうございます!", + "endingLegendLivesOn": "あなたの伝説は続く...", + "endingHallOfFameLine1": "あなたの英雄的な功績は", + "endingHallOfFameLine2": "殿堂に記録されます", + "endingSkip": "スキップ", + "endingTapToSkip": "タップでスキップ" } diff --git a/lib/l10n/app_ko.arb b/lib/l10n/app_ko.arb index b86ff65..5ea8f91 100644 --- a/lib/l10n/app_ko.arb +++ b/lib/l10n/app_ko.arb @@ -74,5 +74,22 @@ "classTitle": "직업", "percentComplete": "{percent}% 완료", "newCharacterTitle": "아스키 네버 다이 - 새 캐릭터", - "soldButton": "확인!" + "soldButton": "확인!", + + "endingCongratulations": "★ 축하합니다 ★", + "endingGameComplete": "게임을 클리어하셨습니다!", + "endingTheHero": "영웅", + "endingLevelFormat": "레벨 {level}", + "endingJourneyStats": "여정 통계", + "endingMonstersSlain": "처치한 몬스터", + "endingQuestsCompleted": "완료한 퀘스트", + "endingPlayTime": "플레이 시간", + "endingFinalStats": "최종 능력치", + "endingCredits": "크레딧", + "endingThankYou": "플레이해 주셔서 감사합니다!", + "endingLegendLivesOn": "당신의 전설은 계속됩니다...", + "endingHallOfFameLine1": "당신의 영웅적인 업적이", + "endingHallOfFameLine2": "명예의 전당에 기록됩니다", + "endingSkip": "건너뛰기", + "endingTapToSkip": "탭하여 건너뛰기" } diff --git a/lib/l10n/app_localizations.dart b/lib/l10n/app_localizations.dart index 25f807d..f9170c3 100644 --- a/lib/l10n/app_localizations.dart +++ b/lib/l10n/app_localizations.dart @@ -544,6 +544,102 @@ abstract class L10n { /// In en, this message translates to: /// **'Sold!'** String get soldButton; + + /// Victory overlay congratulations + /// + /// In en, this message translates to: + /// **'★ CONGRATULATIONS ★'** + String get endingCongratulations; + + /// Game completion message + /// + /// In en, this message translates to: + /// **'You have completed the game!'** + String get endingGameComplete; + + /// Hero section title + /// + /// In en, this message translates to: + /// **'THE HERO'** + String get endingTheHero; + + /// Level display format + /// + /// In en, this message translates to: + /// **'Level {level}'** + String endingLevelFormat(int level); + + /// Journey statistics section title + /// + /// In en, this message translates to: + /// **'JOURNEY STATISTICS'** + String get endingJourneyStats; + + /// Monsters killed stat label + /// + /// In en, this message translates to: + /// **'Monsters Slain'** + String get endingMonstersSlain; + + /// Quests completed stat label + /// + /// In en, this message translates to: + /// **'Quests Completed'** + String get endingQuestsCompleted; + + /// Play time stat label + /// + /// In en, this message translates to: + /// **'Play Time'** + String get endingPlayTime; + + /// Final stats section title + /// + /// In en, this message translates to: + /// **'FINAL STATS'** + String get endingFinalStats; + + /// Credits section title + /// + /// In en, this message translates to: + /// **'CREDITS'** + String get endingCredits; + + /// Thank you message + /// + /// In en, this message translates to: + /// **'Thank you for playing!'** + String get endingThankYou; + + /// Legend message + /// + /// In en, this message translates to: + /// **'Your legend lives on...'** + String get endingLegendLivesOn; + + /// Hall of fame message line 1 + /// + /// In en, this message translates to: + /// **'Your heroic deeds will be'** + String get endingHallOfFameLine1; + + /// Hall of fame message line 2 + /// + /// In en, this message translates to: + /// **'remembered in the Hall of Fame'** + String get endingHallOfFameLine2; + + /// Skip button + /// + /// In en, this message translates to: + /// **'SKIP'** + String get endingSkip; + + /// Tap to skip hint + /// + /// In en, this message translates to: + /// **'TAP TO SKIP'** + String get endingTapToSkip; } class _L10nDelegate extends LocalizationsDelegate { diff --git a/lib/l10n/app_localizations_en.dart b/lib/l10n/app_localizations_en.dart index a412214..12f2e18 100644 --- a/lib/l10n/app_localizations_en.dart +++ b/lib/l10n/app_localizations_en.dart @@ -241,4 +241,54 @@ class L10nEn extends L10n { @override String get soldButton => 'Sold!'; + + @override + String get endingCongratulations => '★ CONGRATULATIONS ★'; + + @override + String get endingGameComplete => 'You have completed the game!'; + + @override + String get endingTheHero => 'THE HERO'; + + @override + String endingLevelFormat(int level) { + return 'Level $level'; + } + + @override + String get endingJourneyStats => 'JOURNEY STATISTICS'; + + @override + String get endingMonstersSlain => 'Monsters Slain'; + + @override + String get endingQuestsCompleted => 'Quests Completed'; + + @override + String get endingPlayTime => 'Play Time'; + + @override + String get endingFinalStats => 'FINAL STATS'; + + @override + String get endingCredits => 'CREDITS'; + + @override + String get endingThankYou => 'Thank you for playing!'; + + @override + String get endingLegendLivesOn => 'Your legend lives on...'; + + @override + String get endingHallOfFameLine1 => 'Your heroic deeds will be'; + + @override + String get endingHallOfFameLine2 => 'remembered in the Hall of Fame'; + + @override + String get endingSkip => 'SKIP'; + + @override + String get endingTapToSkip => 'TAP TO SKIP'; } diff --git a/lib/l10n/app_localizations_ja.dart b/lib/l10n/app_localizations_ja.dart index 40bafb6..696345a 100644 --- a/lib/l10n/app_localizations_ja.dart +++ b/lib/l10n/app_localizations_ja.dart @@ -241,4 +241,54 @@ class L10nJa extends L10n { @override String get soldButton => 'Sold!'; + + @override + String get endingCongratulations => '★ おめでとうございます ★'; + + @override + String get endingGameComplete => 'ゲームをクリアしました!'; + + @override + String get endingTheHero => '英雄'; + + @override + String endingLevelFormat(int level) { + return 'レベル $level'; + } + + @override + String get endingJourneyStats => '冒険の記録'; + + @override + String get endingMonstersSlain => '倒したモンスター'; + + @override + String get endingQuestsCompleted => '完了したクエスト'; + + @override + String get endingPlayTime => 'プレイ時間'; + + @override + String get endingFinalStats => '最終ステータス'; + + @override + String get endingCredits => 'クレジット'; + + @override + String get endingThankYou => 'プレイしていただきありがとうございます!'; + + @override + String get endingLegendLivesOn => 'あなたの伝説は続く...'; + + @override + String get endingHallOfFameLine1 => 'あなたの英雄的な功績は'; + + @override + String get endingHallOfFameLine2 => '殿堂に記録されます'; + + @override + String get endingSkip => 'スキップ'; + + @override + String get endingTapToSkip => 'タップでスキップ'; } diff --git a/lib/l10n/app_localizations_ko.dart b/lib/l10n/app_localizations_ko.dart index 27f64b8..610aa3d 100644 --- a/lib/l10n/app_localizations_ko.dart +++ b/lib/l10n/app_localizations_ko.dart @@ -241,4 +241,54 @@ class L10nKo extends L10n { @override String get soldButton => '확인!'; + + @override + String get endingCongratulations => '★ 축하합니다 ★'; + + @override + String get endingGameComplete => '게임을 클리어하셨습니다!'; + + @override + String get endingTheHero => '영웅'; + + @override + String endingLevelFormat(int level) { + return '레벨 $level'; + } + + @override + String get endingJourneyStats => '여정 통계'; + + @override + String get endingMonstersSlain => '처치한 몬스터'; + + @override + String get endingQuestsCompleted => '완료한 퀘스트'; + + @override + String get endingPlayTime => '플레이 시간'; + + @override + String get endingFinalStats => '최종 능력치'; + + @override + String get endingCredits => '크레딧'; + + @override + String get endingThankYou => '플레이해 주셔서 감사합니다!'; + + @override + String get endingLegendLivesOn => '당신의 전설은 계속됩니다...'; + + @override + String get endingHallOfFameLine1 => '당신의 영웅적인 업적이'; + + @override + String get endingHallOfFameLine2 => '명예의 전당에 기록됩니다'; + + @override + String get endingSkip => '건너뛰기'; + + @override + String get endingTapToSkip => '탭하여 건너뛰기'; } diff --git a/lib/l10n/app_localizations_zh.dart b/lib/l10n/app_localizations_zh.dart index 34652aa..851336c 100644 --- a/lib/l10n/app_localizations_zh.dart +++ b/lib/l10n/app_localizations_zh.dart @@ -241,4 +241,54 @@ class L10nZh extends L10n { @override String get soldButton => 'Sold!'; + + @override + String get endingCongratulations => '★ 恭喜通关 ★'; + + @override + String get endingGameComplete => '您已完成游戏!'; + + @override + String get endingTheHero => '英雄'; + + @override + String endingLevelFormat(int level) { + return '等级 $level'; + } + + @override + String get endingJourneyStats => '冒险记录'; + + @override + String get endingMonstersSlain => '击败的怪物'; + + @override + String get endingQuestsCompleted => '完成的任务'; + + @override + String get endingPlayTime => '游戏时间'; + + @override + String get endingFinalStats => '最终属性'; + + @override + String get endingCredits => '制作人员'; + + @override + String get endingThankYou => '感谢您的游玩!'; + + @override + String get endingLegendLivesOn => '您的传奇将永远流传...'; + + @override + String get endingHallOfFameLine1 => '您的英雄事迹'; + + @override + String get endingHallOfFameLine2 => '将被铭记于荣誉殿堂'; + + @override + String get endingSkip => '跳过'; + + @override + String get endingTapToSkip => '点击跳过'; } diff --git a/lib/l10n/app_zh.arb b/lib/l10n/app_zh.arb index 4bb1cb3..9c42997 100644 --- a/lib/l10n/app_zh.arb +++ b/lib/l10n/app_zh.arb @@ -74,5 +74,22 @@ "classTitle": "Class", "percentComplete": "{percent}% complete", "newCharacterTitle": "ASCII NEVER DIE - New Character", - "soldButton": "Sold!" + "soldButton": "Sold!", + + "endingCongratulations": "★ 恭喜通关 ★", + "endingGameComplete": "您已完成游戏!", + "endingTheHero": "英雄", + "endingLevelFormat": "等级 {level}", + "endingJourneyStats": "冒险记录", + "endingMonstersSlain": "击败的怪物", + "endingQuestsCompleted": "完成的任务", + "endingPlayTime": "游戏时间", + "endingFinalStats": "最终属性", + "endingCredits": "制作人员", + "endingThankYou": "感谢您的游玩!", + "endingLegendLivesOn": "您的传奇将永远流传...", + "endingHallOfFameLine1": "您的英雄事迹", + "endingHallOfFameLine2": "将被铭记于荣誉殿堂", + "endingSkip": "跳过", + "endingTapToSkip": "点击跳过" } diff --git a/lib/src/features/game/widgets/victory_overlay.dart b/lib/src/features/game/widgets/victory_overlay.dart index ed6c7bc..0c59efc 100644 --- a/lib/src/features/game/widgets/victory_overlay.dart +++ b/lib/src/features/game/widgets/victory_overlay.dart @@ -1,5 +1,6 @@ import 'package:flutter/material.dart'; +import 'package:asciineverdie/l10n/app_localizations.dart'; import 'package:asciineverdie/src/core/l10n/game_data_l10n.dart'; import 'package:asciineverdie/src/core/model/game_state.dart'; import 'package:asciineverdie/src/shared/retro_colors.dart'; @@ -92,7 +93,7 @@ class _VictoryOverlayState extends State child: TextButton( onPressed: widget.onComplete, child: Text( - 'SKIP', + L10n.of(context).endingSkip, style: TextStyle( fontFamily: 'PressStart2P', fontSize: 10, @@ -108,7 +109,7 @@ class _VictoryOverlayState extends State left: 0, right: 0, child: Text( - 'TAP TO SKIP', + L10n.of(context).endingTapToSkip, style: TextStyle( fontFamily: 'PressStart2P', fontSize: 8, @@ -148,6 +149,7 @@ class _VictoryOverlayState extends State } Widget _buildCreditContent(BuildContext context) { + final l10n = L10n.of(context); final gold = RetroColors.goldOf(context); final textPrimary = RetroColors.textPrimaryOf(context); @@ -168,7 +170,7 @@ class _VictoryOverlayState extends State // CONGRATULATIONS // ═══════════════════════════════════ Text( - '★ CONGRATULATIONS ★', + l10n.endingCongratulations, style: TextStyle( fontFamily: 'PressStart2P', fontSize: 14, @@ -178,7 +180,7 @@ class _VictoryOverlayState extends State ), const SizedBox(height: 16), Text( - 'You have completed the game!', + l10n.endingGameComplete, style: TextStyle( fontFamily: 'JetBrainsMono', fontSize: 14, @@ -190,7 +192,7 @@ class _VictoryOverlayState extends State // ═══════════════════════════════════ // THE HERO // ═══════════════════════════════════ - _buildSectionTitle('THE HERO', gold), + _buildSectionTitle(l10n.endingTheHero, gold), const SizedBox(height: 20), _buildHeroInfo(context), const SizedBox(height: 80), @@ -198,7 +200,7 @@ class _VictoryOverlayState extends State // ═══════════════════════════════════ // JOURNEY STATISTICS // ═══════════════════════════════════ - _buildSectionTitle('JOURNEY STATISTICS', gold), + _buildSectionTitle(l10n.endingJourneyStats, gold), const SizedBox(height: 20), _buildStatistics(context), const SizedBox(height: 80), @@ -206,7 +208,7 @@ class _VictoryOverlayState extends State // ═══════════════════════════════════ // FINAL STATS // ═══════════════════════════════════ - _buildSectionTitle('FINAL STATS', gold), + _buildSectionTitle(l10n.endingFinalStats, gold), const SizedBox(height: 20), _buildFinalStats(context), const SizedBox(height: 100), @@ -220,7 +222,7 @@ class _VictoryOverlayState extends State // ═══════════════════════════════════ // CREDITS // ═══════════════════════════════════ - _buildSectionTitle('CREDITS', gold), + _buildSectionTitle(l10n.endingCredits, gold), const SizedBox(height: 20), _buildCredits(context), const SizedBox(height: 100), @@ -228,7 +230,7 @@ class _VictoryOverlayState extends State // ═══════════════════════════════════ // THE END // ═══════════════════════════════════ - _buildTheEnd(gold), + _buildTheEnd(context, gold), const SizedBox(height: 200), // 여백 (스크롤 끝) ], ), @@ -303,6 +305,7 @@ class _VictoryOverlayState extends State } Widget _buildHeroInfo(BuildContext context) { + final l10n = L10n.of(context); final gold = RetroColors.goldOf(context); final textPrimary = RetroColors.textPrimaryOf(context); final textMuted = RetroColors.textMutedOf(context); @@ -321,7 +324,7 @@ class _VictoryOverlayState extends State const SizedBox(height: 12), // 레벨, 종족, 직업 Text( - 'Level ${widget.traits.level}', + l10n.endingLevelFormat(widget.traits.level), style: TextStyle( fontFamily: 'PressStart2P', fontSize: 10, @@ -343,6 +346,7 @@ class _VictoryOverlayState extends State } Widget _buildStatistics(BuildContext context) { + final l10n = L10n.of(context); final textPrimary = RetroColors.textPrimaryOf(context); final exp = RetroColors.expOf(context); @@ -357,13 +361,14 @@ class _VictoryOverlayState extends State return Column( children: [ - _buildStatLine('Monsters Slain', '${widget.progress.monstersKilled}', - textPrimary, exp), + _buildStatLine(l10n.endingMonstersSlain, + '${widget.progress.monstersKilled}', textPrimary, exp), const SizedBox(height: 8), - _buildStatLine('Quests Completed', '${widget.progress.questCount}', - textPrimary, exp), + _buildStatLine(l10n.endingQuestsCompleted, + '${widget.progress.questCount}', textPrimary, exp), const SizedBox(height: 8), - _buildStatLine('Play Time', playTimeStr, textPrimary, textPrimary), + _buildStatLine( + l10n.endingPlayTime, playTimeStr, textPrimary, textPrimary), ], ); } @@ -474,6 +479,7 @@ class _VictoryOverlayState extends State } Widget _buildCredits(BuildContext context) { + final l10n = L10n.of(context); final textPrimary = RetroColors.textPrimaryOf(context); final textMuted = RetroColors.textMutedOf(context); final gold = RetroColors.goldOf(context); @@ -481,7 +487,7 @@ class _VictoryOverlayState extends State return Column( children: [ Text( - 'ASCII NEVER DIE', + l10n.appTitle, style: TextStyle( fontFamily: 'PressStart2P', fontSize: 12, @@ -490,7 +496,7 @@ class _VictoryOverlayState extends State ), const SizedBox(height: 16), Text( - 'Thank you for playing!', + l10n.endingThankYou, style: TextStyle( fontFamily: 'JetBrainsMono', fontSize: 12, @@ -499,7 +505,7 @@ class _VictoryOverlayState extends State ), const SizedBox(height: 8), Text( - 'Your legend lives on...', + l10n.endingLegendLivesOn, style: TextStyle( fontFamily: 'JetBrainsMono', fontSize: 10, @@ -511,7 +517,8 @@ class _VictoryOverlayState extends State ); } - Widget _buildTheEnd(Color gold) { + Widget _buildTheEnd(BuildContext context, Color gold) { + final l10n = L10n.of(context); const theEnd = ''' ████████╗██╗ ██╗███████╗ ███████╗███╗ ██╗██████╗ ╚══██╔══╝██║ ██║██╔════╝ ██╔════╝████╗ ██║██╔══██╗ @@ -534,7 +541,7 @@ class _VictoryOverlayState extends State ), const SizedBox(height: 24), Text( - 'Your heroic deeds will be', + l10n.endingHallOfFameLine1, style: TextStyle( fontFamily: 'JetBrainsMono', fontSize: 12, @@ -543,7 +550,7 @@ class _VictoryOverlayState extends State ), const SizedBox(height: 4), Text( - 'remembered in the Hall of Fame', + l10n.endingHallOfFameLine2, style: TextStyle( fontFamily: 'JetBrainsMono', fontSize: 12, diff --git a/lib/src/features/new_character/new_character_screen.dart b/lib/src/features/new_character/new_character_screen.dart index d12ea94..f5ca910 100644 --- a/lib/src/features/new_character/new_character_screen.dart +++ b/lib/src/features/new_character/new_character_screen.dart @@ -2,6 +2,7 @@ import 'dart:math' as math; import 'package:flutter/foundation.dart'; import 'package:flutter/material.dart'; +import 'package:flutter/services.dart' show FilteringTextInputFormatter; import 'package:asciineverdie/data/class_data.dart'; import 'package:asciineverdie/data/game_text_l10n.dart' as game_l10n; @@ -398,6 +399,10 @@ class _NewCharacterScreenState extends State { fontSize: 10, color: RetroColors.textLight, ), + // 영문 알파벳만 허용 (공백 불가) + inputFormatters: [ + FilteringTextInputFormatter.allow(RegExp(r'[a-zA-Z]')), + ], decoration: InputDecoration( labelText: l10n.name, labelStyle: const TextStyle(