feat(ui): 반응형 레이아웃 및 저장 시스템 개선

## 반응형 레이아웃
- app.dart: 화면 크기별 레이아웃 분기 로직 추가 (+173 라인)
- game_play_screen.dart: 반응형 UI 구조 개선
- layouts/, pages/ 디렉토리 추가 (새 레이아웃 시스템)
- carousel_nav_bar.dart: 캐러셀 네비게이션 바 추가
- enhanced_animation_panel.dart: 향상된 애니메이션 패널

## 저장 시스템
- save_manager.dart: 저장 관리 기능 확장
- save_repository.dart: 저장소 인터페이스 개선
- save_service.dart: 저장 서비스 로직 추가

## UI 개선
- notification_service.dart: 알림 시스템 기능 확장
- notification_overlay.dart: 오버레이 UI 개선
- equipment_stats_panel.dart: 장비 스탯 패널 개선
- cinematic_view.dart: 시네마틱 뷰 개선
- new_character_screen.dart: 캐릭터 생성 화면 개선

## 다국어
- game_text_l10n.dart: 텍스트 추가 (+182 라인)

## 테스트
- 관련 테스트 파일 업데이트
This commit is contained in:
JiWoong Sul
2025-12-23 17:52:43 +09:00
parent 1da6fa7a2b
commit e6af7dd91a
28 changed files with 2734 additions and 73 deletions

View File

@@ -1042,7 +1042,29 @@ String translateItemNameL10n(String itemString) {
// 2. 몬스터 드롭 형식: "{monster} {drop}" (예: "syntax error fragment")
final words = itemString.split(' ');
if (words.length >= 2) {
// 마지막 단어가 드롭 아이템인지 확인
// 2-1. 마지막 2단어가 드롭 아이템인지 먼저 확인 (예: "outdated syntax")
if (words.length >= 3) {
final lastTwoWords = '${words[words.length - 2]} ${words.last}'
.toLowerCase();
final dropKo2 =
dropItemTranslationsKo[lastTwoWords] ??
additionalDropTranslationsKo[lastTwoWords];
final dropJa2 =
dropItemTranslationsJa[lastTwoWords] ??
additionalDropTranslationsJa[lastTwoWords];
if (dropKo2 != null || dropJa2 != null) {
final monsterPart = words.sublist(0, words.length - 2).join(' ');
final translatedMonster = translateMonster(monsterPart);
if (isKoreanLocale && dropKo2 != null) {
return '$translatedMonster $dropKo2';
} else if (isJapaneseLocale && dropJa2 != null) {
return '$translatedMonsterの$dropJa2';
}
}
}
// 2-2. 마지막 단어가 드롭 아이템인지 확인
final lastWord = words.last.toLowerCase();
final dropKo =
dropItemTranslationsKo[lastWord] ??
@@ -1479,3 +1501,161 @@ String get uiEnterName {
if (isJapaneseLocale) return '名前を入力してください。';
return 'Please enter a name.';
}
String get uiTestMode {
if (isKoreanLocale) return '테스트 모드';
if (isJapaneseLocale) return 'テストモード';
return 'Test Mode';
}
String get uiTestModeDesc {
if (isKoreanLocale) return '웹에서 모바일 레이아웃 사용';
if (isJapaneseLocale) return 'Webでモバイルレイアウトを使用';
return 'Use mobile layout on web';
}
// ============================================================================
// 캐로셀 네비게이션 텍스트
// ============================================================================
String get navSkills {
if (isKoreanLocale) return '스킬';
if (isJapaneseLocale) return 'スキル';
return 'Skills';
}
String get navInventory {
if (isKoreanLocale) return '인벤토리';
if (isJapaneseLocale) return '所持品';
return 'Inventory';
}
String get navEquipment {
if (isKoreanLocale) return '장비';
if (isJapaneseLocale) return '装備';
return 'Equip';
}
String get navCharacter {
if (isKoreanLocale) return '캐릭터';
if (isJapaneseLocale) return 'キャラ';
return 'Character';
}
String get navCombatLog {
if (isKoreanLocale) return '전투로그';
if (isJapaneseLocale) return '戦闘ログ';
return 'Combat';
}
String get navStory {
if (isKoreanLocale) return '스토리';
if (isJapaneseLocale) return 'ストーリー';
return 'Story';
}
String get navQuest {
if (isKoreanLocale) return '퀘스트';
if (isJapaneseLocale) return 'クエスト';
return 'Quest';
}
// ============================================================================
// 옵션 메뉴 텍스트
// ============================================================================
String get menuOptions {
if (isKoreanLocale) return '옵션';
if (isJapaneseLocale) return 'オプション';
return 'Options';
}
String get menuPause {
if (isKoreanLocale) return '일시정지';
if (isJapaneseLocale) return '一時停止';
return 'Pause';
}
String get menuResume {
if (isKoreanLocale) return '재개';
if (isJapaneseLocale) return '再開';
return 'Resume';
}
String get menuSpeed {
if (isKoreanLocale) return '속도';
if (isJapaneseLocale) return '速度';
return 'Speed';
}
String get menuSave {
if (isKoreanLocale) return '저장';
if (isJapaneseLocale) return 'セーブ';
return 'Save';
}
String get menuSaved {
if (isKoreanLocale) return '저장되었습니다';
if (isJapaneseLocale) return '保存しました';
return 'Game saved';
}
String get menuLanguage {
if (isKoreanLocale) return '언어';
if (isJapaneseLocale) return '言語';
return 'Language';
}
String get languageEnglish {
if (isKoreanLocale) return '영어';
if (isJapaneseLocale) return '英語';
return 'English';
}
String get languageKorean {
if (isKoreanLocale) return '한국어';
if (isJapaneseLocale) return '韓国語';
return 'Korean';
}
String get languageJapanese {
if (isKoreanLocale) return '일본어';
if (isJapaneseLocale) return '日本語';
return 'Japanese';
}
String get menuDeleteSave {
if (isKoreanLocale) return '세이브 삭제';
if (isJapaneseLocale) return 'セーブ削除';
return 'Delete Save';
}
String get menuNewGame {
if (isKoreanLocale) return '새로하기';
if (isJapaneseLocale) return '新規ゲーム';
return 'New Game';
}
String get confirmDeleteTitle {
if (isKoreanLocale) return '세이브 삭제';
if (isJapaneseLocale) return 'セーブ削除';
return 'Delete Save';
}
String get confirmDeleteMessage {
if (isKoreanLocale) return '정말 삭제하시겠습니까?\n모든 진행 상황이 사라집니다.';
if (isJapaneseLocale) return '本当に削除しますか?\nすべての進行状況が失われます。';
return 'Are you sure?\nAll progress will be lost.';
}
String get buttonConfirm {
if (isKoreanLocale) return '확인';
if (isJapaneseLocale) return '確認';
return 'Confirm';
}
String get buttonCancel {
if (isKoreanLocale) return '취소';
if (isJapaneseLocale) return 'キャンセル';
return 'Cancel';
}