1109 lines
48 KiB
Dart
1109 lines
48 KiB
Dart
// 게임 텍스트 로컬라이제이션 (BuildContext 없이 사용)
|
||
// progress_service.dart, pq_logic.dart 등에서 사용
|
||
// 지원 언어: 한국어(ko), 영어(en), 일본어(ja)
|
||
|
||
import 'package:asciineverdie/data/game_translations_ko.dart';
|
||
import 'package:asciineverdie/data/game_translations_ja.dart';
|
||
|
||
/// 현재 게임 로케일 설정 (전역)
|
||
String _currentLocale = 'en';
|
||
|
||
/// 현재 로케일 가져오기
|
||
String get currentGameLocale => _currentLocale;
|
||
|
||
/// 로케일 설정 (앱 시작 시 호출)
|
||
void setGameLocale(String locale) {
|
||
_currentLocale = locale;
|
||
}
|
||
|
||
/// 한국어 여부 확인
|
||
bool get isKoreanLocale => _currentLocale == 'ko';
|
||
|
||
/// 일본어 여부 확인
|
||
bool get isJapaneseLocale => _currentLocale == 'ja';
|
||
|
||
/// 로케일별 문자열 반환 헬퍼 (리팩토링용)
|
||
///
|
||
/// 영문(en), 한국어(ko), 일본어(ja) 순서로 인자를 받아
|
||
/// 현재 로케일에 맞는 문자열을 반환합니다.
|
||
String _l(String en, String ko, String ja) {
|
||
if (isKoreanLocale) return ko;
|
||
if (isJapaneseLocale) return ja;
|
||
return en;
|
||
}
|
||
|
||
/// 각 단어 첫 글자를 대문자로 변환 (Title Case)
|
||
///
|
||
/// 예: "syntax error" → "Syntax Error"
|
||
String _toTitleCase(String text) {
|
||
return text
|
||
.split(' ')
|
||
.map((word) {
|
||
if (word.isEmpty) return word;
|
||
return word[0].toUpperCase() + word.substring(1).toLowerCase();
|
||
})
|
||
.join(' ');
|
||
}
|
||
|
||
// ============================================================================
|
||
// 프롤로그 텍스트
|
||
// ============================================================================
|
||
|
||
const _prologueTextsEn = [
|
||
'Receiving an ominous vision from the Code God',
|
||
'The old Compiler Sage reveals a prophecy: "The Glitch God has awakened"',
|
||
'A sudden Buffer Overflow resets your village, leaving you as the sole survivor',
|
||
'With unexpected resolve, you embark on a perilous journey to the Null Kingdom',
|
||
];
|
||
|
||
const _prologueTextsKo = [
|
||
'코드의 신으로부터 불길한 환영을 받다',
|
||
'늙은 컴파일러 현자가 예언을 밝히다: "글리치 신이 깨어났다"',
|
||
'갑작스러운 버퍼 오버플로우가 마을을 초기화하고, 당신만이 유일한 생존자로 남다',
|
||
'예상치 못한 결의로 널(Null) 왕국을 향한 위험한 여정을 시작하다',
|
||
];
|
||
|
||
const _prologueTextsJa = [
|
||
'コードの神から不吉な幻影を受ける',
|
||
'老いたコンパイラー賢者が予言を明かす:「グリッチゴッドが目覚めた」',
|
||
'突然のバッファオーバーフローが村をリセットし、あなただけが唯一の生存者となる',
|
||
'予想外の決意で、ヌル(Null)王国への危険な旅に出発する',
|
||
];
|
||
|
||
List<String> get prologueTexts {
|
||
if (isKoreanLocale) return _prologueTextsKo;
|
||
if (isJapaneseLocale) return _prologueTextsJa;
|
||
return _prologueTextsEn;
|
||
}
|
||
|
||
// ============================================================================
|
||
// 태스크 캡션
|
||
// ============================================================================
|
||
|
||
String get taskCompiling => _l('Compiling', '컴파일 중', 'コンパイル中');
|
||
String get taskPrologue => _l('Prologue', '프롤로그', 'プロローグ');
|
||
|
||
String taskHeadingToMarket() => _l(
|
||
'Heading to the Data Market to trade loot',
|
||
'전리품을 팔기 위해 데이터 마켓으로 이동 중',
|
||
'戦利品を売るためデータマーケットへ移動中',
|
||
);
|
||
|
||
String taskUpgradingHardware() => _l(
|
||
'Upgrading hardware at the Tech Shop',
|
||
'테크 샵에서 하드웨어 업그레이드 중',
|
||
'テックショップでハードウェアをアップグレード中',
|
||
);
|
||
|
||
String taskEnteringDebugZone() =>
|
||
_l('Entering the Debug Zone', '디버그 존 진입 중', 'デバッグゾーンに進入中');
|
||
|
||
String taskDebugging(String monsterName) => _l(
|
||
'Debugging $monsterName',
|
||
'$monsterName 디버깅 중',
|
||
'$monsterName をデバッグ中',
|
||
);
|
||
|
||
String taskFinalBoss(String bossName) => _l(
|
||
'Final Battle: $bossName',
|
||
'최종 보스와 대결: $bossName',
|
||
'最終ボスと対決: $bossName',
|
||
);
|
||
|
||
String taskSelling(String itemDescription) => _l(
|
||
'Selling $itemDescription',
|
||
'$itemDescription 판매 중',
|
||
'$itemDescription を販売中',
|
||
);
|
||
|
||
// ============================================================================
|
||
// 부활 시퀀스 메시지
|
||
// ============================================================================
|
||
|
||
/// 부활 애니메이션 중 표시 메시지
|
||
String get animationResurrecting => _l('Resurrecting...', '부활 중...', '復活中...');
|
||
String get taskReturningToTown =>
|
||
_l('Returning to town...', '마을로 귀환 중...', '町に戻っている...');
|
||
String get taskRestockingAtShop =>
|
||
_l('Restocking at shop...', '상점에서 장비 정비 중...', 'ショップで装備を整備中...');
|
||
String get taskHeadingToHuntingGrounds =>
|
||
_l('Heading to hunting grounds...', '사냥터로 이동 중...', '狩り場へ向かっている...');
|
||
|
||
// ============================================================================
|
||
// 사망 화면 메시지
|
||
// ============================================================================
|
||
|
||
String get deathYouDied => _l('YOU DIED', '사망', '死亡');
|
||
String get deathSacrificedToResurrect =>
|
||
_l('Sacrificed to Resurrect', '부활 대가로 희생됨', '復活のために犠牲');
|
||
String get deathEquipment => _l('Equipment', '장비', '装備');
|
||
String get deathNoSacrificeNeeded =>
|
||
_l('No sacrifice needed', '희생 없이 부활', '犠牲なしで復活');
|
||
String get deathCoinRemaining => _l('Coin Remaining', '남은 코인', '残りコイン');
|
||
String get deathResurrect => _l('Resurrect', '부활', '復活');
|
||
String get deathAutoResurrect => _l('Auto Resurrect', '자동 부활', '自動復活');
|
||
String get deathCombatLog => _l('Combat Log', '전투 기록', '戦闘ログ');
|
||
|
||
String deathKilledBy(String killerName) =>
|
||
_l('Killed by $killerName', '$killerName에게 사망', '$killerNameに倒された');
|
||
String get deathEnvironmentalHazard =>
|
||
_l('Environmental hazard', '환경 피해로 사망', '環境ダメージで死亡');
|
||
|
||
// ============================================================================
|
||
// UI 일반 메시지
|
||
// ============================================================================
|
||
|
||
String get uiNoPotions => _l('No potions', '포션 없음', 'ポーションなし');
|
||
String get uiTapToContinue => _l('Tap to continue', '탭하여 계속', 'タップして続行');
|
||
String get uiNoSkills => _l('No skills', '습득한 스킬이 없습니다', 'スキルなし');
|
||
String get uiNoBonusStats =>
|
||
_l('No bonus stats', '추가 스탯 없음', 'ボーナスステータスなし');
|
||
String get uiNoActiveBuffs =>
|
||
_l('No active buffs', '활성 버프 없음', 'アクティブバフなし');
|
||
String get uiReady => _l('Ready', '준비', '準備完了');
|
||
String get uiPotions => _l('Potions', '포션', 'ポーション');
|
||
String get uiBuffs => _l('Buffs', '버프', 'バフ');
|
||
|
||
// ============================================================================
|
||
// 스탯 약어
|
||
// ============================================================================
|
||
|
||
String get statStr => _l('STR', '힘', '筋力');
|
||
String get statCon => _l('CON', '체력', '耐久');
|
||
String get statDex => _l('DEX', '민첩', '敏捷');
|
||
String get statInt => _l('INT', '지능', '知力');
|
||
String get statWis => _l('WIS', '지혜', '精神');
|
||
String get statCha => _l('CHA', '매력', '魅力');
|
||
|
||
// ============================================================================
|
||
// 패시브 능력 설명
|
||
// ============================================================================
|
||
|
||
// HP/MP 보너스는 동일 형식이므로 그대로 유지
|
||
String passiveHpBonus(int percent) => 'HP +$percent%';
|
||
String passiveMpBonus(int percent) => 'MP +$percent%';
|
||
|
||
String passivePhysicalBonus(int percent) =>
|
||
_l('Physical +$percent%', '물리 공격 +$percent%', '物理攻撃 +$percent%');
|
||
String passiveDefenseBonus(int percent) =>
|
||
_l('Defense +$percent%', '방어력 +$percent%', '防御力 +$percent%');
|
||
String passiveMagicBonus(int percent) =>
|
||
_l('Magic +$percent%', '마법 공격 +$percent%', '魔法攻撃 +$percent%');
|
||
String passiveEvasionBonus(int percent) =>
|
||
_l('Evasion +$percent%', '회피율 +$percent%', '回避率 +$percent%');
|
||
String passiveCritBonus(int percent) =>
|
||
_l('Critical +$percent%', '크리티컬 +$percent%', 'クリティカル +$percent%');
|
||
String passiveHpRegen(int percent) => _l(
|
||
'Recover $percent% HP after combat',
|
||
'전투 후 HP $percent% 회복',
|
||
'戦闘後HP $percent%回復',
|
||
);
|
||
String passiveMpRegen(int percent) => _l(
|
||
'Recover $percent% MP after combat',
|
||
'전투 후 MP $percent% 회복',
|
||
'戦闘後MP $percent%回復',
|
||
);
|
||
|
||
// ============================================================================
|
||
// 전투 로그 메시지
|
||
// ============================================================================
|
||
|
||
String combatYouHit(String targetName, int damage) => _l(
|
||
'You hit $targetName for $damage damage',
|
||
'$targetName에게 $damage 데미지',
|
||
'$targetNameに$damageダメージ',
|
||
);
|
||
String combatYouEvaded(String targetName) => _l(
|
||
'You evaded $targetName\'s attack!',
|
||
'$targetName의 공격 회피!',
|
||
'$targetNameの攻撃を回避!',
|
||
);
|
||
String combatEvadedAttackFrom(String targetName) => _l(
|
||
'Evaded attack from $targetName',
|
||
'$targetName의 공격 회피',
|
||
'$targetNameの攻撃を回避',
|
||
);
|
||
String combatHealedFor(int amount) =>
|
||
_l('Healed for $amount HP', 'HP $amount 회복', 'HP $amount回復');
|
||
String combatCritical(int damage, String targetName) => _l(
|
||
'CRITICAL! $damage damage to $targetName!',
|
||
'크리티컬! $targetName에게 $damage 데미지!',
|
||
'クリティカル! $targetNameに$damageダメージ!',
|
||
);
|
||
String combatMonsterHitsYou(String monsterName, int damage) => _l(
|
||
'$monsterName hits you for $damage damage',
|
||
'$monsterName이(가) $damage 데미지',
|
||
'$monsterNameが$damageダメージを与えた',
|
||
);
|
||
String combatMonsterEvaded(String monsterName) => _l(
|
||
'$monsterName evaded your attack!',
|
||
'$monsterName이(가) 공격 회피!',
|
||
'$monsterNameが攻撃を回避!',
|
||
);
|
||
String combatBlocked(int damage) => _l(
|
||
'Blocked! Reduced to $damage damage',
|
||
'방어! $damage 데미지로 감소',
|
||
'ブロック! $damageダメージに軽減',
|
||
);
|
||
|
||
String combatParried(int damage) => _l(
|
||
'Parried! Reduced to $damage damage',
|
||
'패리! $damage 데미지로 감소',
|
||
'パリィ! $damageダメージに軽減',
|
||
);
|
||
|
||
// 스킬 관련 전투 메시지
|
||
String combatSkillCritical(String skillName, int damage) => _l(
|
||
'CRITICAL $skillName! $damage damage!',
|
||
'크리티컬 $skillName! $damage 데미지!',
|
||
'クリティカル$skillName! $damageダメージ!',
|
||
);
|
||
String combatSkillDamage(String skillName, int damage) =>
|
||
_l('$skillName: $damage damage', '$skillName: $damage 데미지', '$skillName: $damageダメージ');
|
||
// HP 형식이 동일하므로 단순화
|
||
String combatSkillHeal(String skillName, int amount) => '$skillName: +$amount HP';
|
||
String get uiHeal => _l('Heal', '힐', 'ヒール');
|
||
String combatBuffActivated(String skillName) =>
|
||
_l('$skillName activated!', '$skillName 발동!', '$skillName 発動!');
|
||
String combatDebuffApplied(String skillName, String targetName) => _l(
|
||
'$skillName applied to $targetName!',
|
||
'$skillName → $targetName에 적용!',
|
||
'$skillName → $targetNameに適用!',
|
||
);
|
||
String combatDotTick(String skillName, int damage) => _l(
|
||
'$skillName ticks for $damage damage',
|
||
'$skillName: $damage 지속 데미지',
|
||
'$skillName: $damage 継続ダメージ',
|
||
);
|
||
// 포션 형식이 동일하므로 단순화
|
||
String combatPotionUsed(String potionName, int amount, String statName) =>
|
||
'$potionName: +$amount $statName';
|
||
String combatPotionDrop(String potionName) =>
|
||
_l('Dropped: $potionName', '획득: $potionName', '獲得: $potionName');
|
||
|
||
// 사망 화면 전투 로그 (death overlay)
|
||
String combatBlockedAttack(String monsterName, int reducedDamage) => _l(
|
||
'Blocked $monsterName\'s attack ($reducedDamage reduced)',
|
||
'$monsterName의 공격 방어 ($reducedDamage 감소)',
|
||
'$monsterNameの攻撃を防御 ($reducedDamage軽減)',
|
||
);
|
||
String combatParriedAttack(String monsterName, int reducedDamage) => _l(
|
||
'Parried $monsterName\'s attack ($reducedDamage reduced)',
|
||
'$monsterName의 공격 패리 ($reducedDamage 감소)',
|
||
'$monsterNameの攻撃をパリィ ($reducedDamage軽減)',
|
||
);
|
||
String get deathSelfInflicted =>
|
||
_l('Self-inflicted damage', '자해 데미지로 사망', '自傷ダメージで死亡');
|
||
|
||
// ============================================================================
|
||
// 퀘스트 캡션
|
||
// ============================================================================
|
||
|
||
String questPatch(String name) =>
|
||
_l('Patch $name', '$name 패치하기', '$name をパッチする');
|
||
String questLocate(String item) =>
|
||
_l('Locate $item', '$item 찾기', '$item を探す');
|
||
String questTransfer(String item) =>
|
||
_l('Transfer this $item', '이 $item 전송하기', 'この$item を転送する');
|
||
String questDownload(String item) =>
|
||
_l('Download $item', '$item 다운로드하기', '$item をダウンロードする');
|
||
String questStabilize(String name) =>
|
||
_l('Stabilize $name', '$name 안정화하기', '$name を安定化する');
|
||
|
||
// ============================================================================
|
||
// Act 제목
|
||
// ============================================================================
|
||
|
||
String actTitle(String romanNumeral) =>
|
||
_l('Act $romanNumeral', '$romanNumeral막', '第$romanNumeral幕');
|
||
|
||
// ============================================================================
|
||
// 시네마틱 텍스트 - 시나리오 1: 캐시 존
|
||
// ============================================================================
|
||
|
||
String cinematicCacheZone1() => _l(
|
||
'Exhausted, you reach a safe Cache Zone in the corrupted network',
|
||
'지쳐서 손상된 네트워크의 안전한 캐시 존에 도착하다',
|
||
'疲れ果てて、破損したネットワークの安全なキャッシュゾーンに到着する',
|
||
);
|
||
String cinematicCacheZone2() => _l(
|
||
'You reconnect with old allies and fork new ones',
|
||
'옛 동맹들과 재연결하고 새로운 동료들을 포크하다',
|
||
'古い同盟者と再接続し、新しい仲間をフォークする',
|
||
);
|
||
String cinematicCacheZone3() => _l(
|
||
'You attend a council of the Debugger Knights',
|
||
'디버거 기사단 회의에 참석하다',
|
||
'デバッガー騎士団の会議に参加する',
|
||
);
|
||
String cinematicCacheZone4() => _l(
|
||
'Many bugs await. You are chosen to patch them!',
|
||
'많은 버그들이 기다린다. 당신이 패치하도록 선택되었다!',
|
||
'多くのバグが待っている。あなたがパッチを当てるよう選ばれた!',
|
||
);
|
||
|
||
// ============================================================================
|
||
// 시네마틱 텍스트 - 시나리오 2: 전투
|
||
// ============================================================================
|
||
|
||
String cinematicCombat1() => _l(
|
||
'Your target is in sight, but a critical bug blocks your path!',
|
||
'목표가 눈앞에 있지만, 치명적인 버그가 길을 막는다!',
|
||
'ターゲットは目の前だが、致命的なバグが道を塞ぐ!',
|
||
);
|
||
String cinematicCombat2(String nemesis) => _l(
|
||
'A desperate debugging session begins with $nemesis',
|
||
'$nemesis와의 필사적인 디버깅 세션이 시작되다',
|
||
'$nemesisとの必死のデバッグセッションが始まる',
|
||
);
|
||
String cinematicCombatLocked(String nemesis) => _l(
|
||
'Locked in intense debugging with $nemesis',
|
||
'$nemesis와 치열한 디버깅 중',
|
||
'$nemesisと激しいデバッグ中',
|
||
);
|
||
String cinematicCombatCorrupts(String nemesis) => _l(
|
||
'$nemesis corrupts your stack trace',
|
||
'$nemesis가 당신의 스택 트레이스를 손상시키다',
|
||
'$nemesisがあなたのスタックトレースを破損させる',
|
||
);
|
||
String cinematicCombatWorking(String nemesis) => _l(
|
||
'Your patch seems to be working against $nemesis',
|
||
'당신의 패치가 $nemesis에게 효과를 보이는 것 같다',
|
||
'あなたのパッチが$nemesisに効いているようだ',
|
||
);
|
||
String cinematicCombatVictory(String nemesis) => _l(
|
||
'Victory! $nemesis is patched! System reboots for recovery',
|
||
'승리! $nemesis가 패치되었다! 복구를 위해 시스템이 재부팅된다',
|
||
'勝利!$nemesisはパッチされた!復旧のためシステムが再起動する',
|
||
);
|
||
String cinematicCombatWakeUp() => _l(
|
||
'You wake up in a Safe Mode, but the kernel awaits',
|
||
'안전 모드에서 깨어나지만, 커널이 기다린다',
|
||
'セーフモードで目覚めるが、カーネルが待ち構えている',
|
||
);
|
||
|
||
// ============================================================================
|
||
// 시네마틱 텍스트 - 시나리오 3: 배신
|
||
// ============================================================================
|
||
|
||
String cinematicBetrayal1(String guy) => _l(
|
||
'What relief! You reach the secure server of $guy',
|
||
'안도감! $guy의 보안 서버에 도착하다',
|
||
'安堵!$guyのセキュアサーバーに到着する',
|
||
);
|
||
String cinematicBetrayal2(String guy) => _l(
|
||
'There is celebration, and a suspicious private handshake with $guy',
|
||
'축하가 이어지고, $guy와 수상한 비밀 핸드셰이크를 나누다',
|
||
'祝賀が続き、$guyと怪しい秘密のハンドシェイクを交わす',
|
||
);
|
||
String cinematicBetrayal3(String item) => _l(
|
||
'You forget your $item and go back to retrieve it',
|
||
'$item을 잊고 다시 가져오러 돌아가다',
|
||
'$itemを忘れて取りに戻る',
|
||
);
|
||
String cinematicBetrayal4() => _l(
|
||
'What is this!? You intercept a corrupted packet!',
|
||
'이게 뭐지!? 손상된 패킷을 가로채다!',
|
||
'これは何だ!?破損したパケットを傍受する!',
|
||
);
|
||
String cinematicBetrayal5(String guy) => _l(
|
||
'Could $guy be a backdoor for the Glitch God?',
|
||
'$guy가 글리치 신의 백도어일 수 있을까?',
|
||
'$guyはグリッチゴッドのバックドアなのか?',
|
||
);
|
||
String cinematicBetrayal6() => _l(
|
||
'Who can be trusted with this intel!? -- The Binary Temple, of course',
|
||
'이 정보를 누구에게 맡길 수 있을까!? -- 바이너리 신전이다',
|
||
'この情報を誰に託せるか!? -- バイナリ神殿だ',
|
||
);
|
||
|
||
// ============================================================================
|
||
// 몬스터 수식어
|
||
// ============================================================================
|
||
|
||
String modifierDead(String s) => _l('fallen $s', '쓰러진 $s', '倒れた$s');
|
||
String modifierComatose(String s) => _l('lurking $s', '잠복하는 $s', '潜む$s');
|
||
String modifierCrippled(String s) => _l('twisted $s', '흉측한 $s', '歪んだ$s');
|
||
String modifierSick(String s) => _l('tainted $s', '오염된 $s', '汚染された$s');
|
||
String modifierUndernourished(String s) =>
|
||
_l('ravenous $s', '굶주린 $s', '飢えた$s');
|
||
String modifierFoetal(String s) => _l('nascent $s', '태동기 $s', '胎動期$s');
|
||
String modifierBaby(String s) => _l('fledgling $s', '초기형 $s', '初期型$s');
|
||
String modifierPreadolescent(String s) =>
|
||
_l('evolving $s', '진화 중인 $s', '進化中の$s');
|
||
String modifierTeenage(String s) => _l('lesser $s', '하급 $s', '下級$s');
|
||
String modifierUnderage(String s) =>
|
||
_l('incomplete $s', '불완전한 $s', '不完全な$s');
|
||
String modifierGreater(String s) => _l('greater $s', '상위 $s', '上位$s');
|
||
String modifierMassive(String s) => _l('massive $s', '거대한 $s', '巨大な$s');
|
||
String modifierEnormous(String s) => _l('enormous $s', '초거대 $s', '超巨大$s');
|
||
String modifierGiant(String s) =>
|
||
_l('giant $s', '자이언트 $s', 'ジャイアント$s');
|
||
|
||
String modifierTitanic(String s) =>
|
||
_l('titanic $s', '타이타닉 $s', 'タイタニック$s');
|
||
String modifierVeteran(String s) =>
|
||
_l('veteran $s', '베테랑 $s', 'ベテラン$s');
|
||
String modifierBattle(String s) => _l('Battle-$s', '전투-$s', '戦闘-$s');
|
||
String modifierCursed(String s) =>
|
||
_l('cursed $s', '저주받은 $s', '呪われた$s');
|
||
String modifierWarrior(String s) => _l('warrior $s', '전사 $s', '戦士$s');
|
||
String modifierWere(String s) => _l('Were-$s', '늑대인간-$s', '狼男-$s');
|
||
String modifierUndead(String s) =>
|
||
_l('undead $s', '언데드 $s', 'アンデッド$s');
|
||
String modifierDemon(String s) => _l('demon $s', '데몬 $s', 'デーモン$s');
|
||
String modifierMessianic(String s) =>
|
||
_l('messianic $s', '메시아닉 $s', 'メシアニック$s');
|
||
String modifierImaginary(String s) =>
|
||
_l('imaginary $s', '상상의 $s', '想像上の$s');
|
||
String modifierPassing(String s) =>
|
||
_l('passing $s', '지나가는 $s', '通りすがりの$s');
|
||
|
||
// ============================================================================
|
||
// 시간 표시
|
||
// ============================================================================
|
||
|
||
String roughTimeSeconds(int seconds) =>
|
||
_l('$seconds seconds', '$seconds초', '$seconds秒');
|
||
String roughTimeMinutes(int minutes) =>
|
||
_l('$minutes minutes', '$minutes분', '$minutes分');
|
||
String roughTimeHours(int hours) =>
|
||
_l('$hours hours', '$hours시간', '$hours時間');
|
||
String roughTimeDays(int days) => _l('$days days', '$days일', '$days日');
|
||
|
||
// ============================================================================
|
||
// 영어 문법 함수 (한국어/일본어에서는 단순화)
|
||
// ============================================================================
|
||
|
||
/// 관사 + 명사 (한국어/일본어: 수량만 표시)
|
||
String indefiniteL10n(String s, int qty) {
|
||
if (isKoreanLocale) {
|
||
return qty == 1 ? s : '$qty $s';
|
||
}
|
||
if (isJapaneseLocale) {
|
||
return qty == 1 ? s : '$qty $s';
|
||
}
|
||
// 영어 로직
|
||
if (qty == 1) {
|
||
const vowels = 'AEIOUÜaeiouü';
|
||
final first = s.isNotEmpty ? s[0] : 'a';
|
||
final article = vowels.contains(first) ? 'an' : 'a';
|
||
return '$article $s';
|
||
}
|
||
return '$qty ${_pluralize(s)}';
|
||
}
|
||
|
||
/// the + 명사 (한국어/일본어: 그냥 명사)
|
||
String definiteL10n(String s, int qty) {
|
||
if (isKoreanLocale || isJapaneseLocale) {
|
||
return s;
|
||
}
|
||
// 영어 로직
|
||
if (qty > 1) {
|
||
s = _pluralize(s);
|
||
}
|
||
return 'the $s';
|
||
}
|
||
|
||
/// 복수형 (영어만 해당)
|
||
String _pluralize(String s) {
|
||
if (s.endsWith('y')) return '${s.substring(0, s.length - 1)}ies';
|
||
if (s.endsWith('us')) return '${s.substring(0, s.length - 2)}i';
|
||
if (s.endsWith('ch') || s.endsWith('x') || s.endsWith('s')) return '${s}es';
|
||
if (s.endsWith('f')) return '${s.substring(0, s.length - 1)}ves';
|
||
if (s.endsWith('man') || s.endsWith('Man')) {
|
||
return '${s.substring(0, s.length - 2)}en';
|
||
}
|
||
return '${s}s'; // ignore: unnecessary_brace_in_string_interp
|
||
}
|
||
|
||
// ============================================================================
|
||
// impressiveGuy 관련
|
||
// ============================================================================
|
||
|
||
String impressiveGuyPattern1(String title, String race) {
|
||
if (isKoreanLocale) {
|
||
// ignore: unnecessary_brace_in_string_interps
|
||
return '${race}들의 $title'; // 한국어 조사 연결을 위해 중괄호 필요
|
||
}
|
||
if (isJapaneseLocale) {
|
||
// ignore: unnecessary_brace_in_string_interps
|
||
return '${race}たちの$title'; // 일본어 연결을 위해 중괄호 필요
|
||
}
|
||
return 'the $title of the ${_pluralize(race)}';
|
||
}
|
||
|
||
String impressiveGuyPattern2(String title, String name1, String name2) {
|
||
if (isKoreanLocale) return '$name2의 $title $name1';
|
||
if (isJapaneseLocale) return '$name2の$title $name1';
|
||
return '$title $name1 of $name2';
|
||
}
|
||
|
||
// ============================================================================
|
||
// namedMonster 관련
|
||
// ============================================================================
|
||
|
||
String namedMonsterFormat(String generatedName, String monsterType) {
|
||
if (isKoreanLocale) return '$monsterType $generatedName';
|
||
if (isJapaneseLocale) return '$monsterType $generatedName';
|
||
return '$generatedName the $monsterType';
|
||
}
|
||
|
||
// ============================================================================
|
||
// 게임 데이터 번역 함수 (BuildContext 없이 사용)
|
||
// 지원 언어: 한국어(ko), 영어(en), 일본어(ja)
|
||
// ============================================================================
|
||
|
||
/// 몬스터 이름 번역 (기본 + 고급 몬스터 포함)
|
||
///
|
||
/// 대소문자 무시 검색: "syntax error" → "Syntax Error"로 변환 후 검색
|
||
String translateMonster(String englishName) {
|
||
// 대소문자 무시를 위해 Title Case로 변환
|
||
final titleCaseName = _toTitleCase(englishName);
|
||
|
||
if (isKoreanLocale) {
|
||
return monsterTranslationsKo[titleCaseName] ??
|
||
advancedMonsterTranslationsKo[titleCaseName] ??
|
||
monsterTranslationsKo[englishName] ??
|
||
advancedMonsterTranslationsKo[englishName] ??
|
||
englishName;
|
||
}
|
||
if (isJapaneseLocale) {
|
||
return monsterTranslationsJa[titleCaseName] ??
|
||
advancedMonsterTranslationsJa[titleCaseName] ??
|
||
monsterTranslationsJa[englishName] ??
|
||
advancedMonsterTranslationsJa[englishName] ??
|
||
englishName;
|
||
}
|
||
return englishName;
|
||
}
|
||
|
||
/// 종족 이름 번역
|
||
String translateRace(String englishName) {
|
||
if (isKoreanLocale) return raceTranslationsKo[englishName] ?? englishName;
|
||
if (isJapaneseLocale) return raceTranslationsJa[englishName] ?? englishName;
|
||
return englishName;
|
||
}
|
||
|
||
/// 직업 이름 번역
|
||
String translateKlass(String englishName) {
|
||
if (isKoreanLocale) return klassTranslationsKo[englishName] ?? englishName;
|
||
if (isJapaneseLocale) return klassTranslationsJa[englishName] ?? englishName;
|
||
return englishName;
|
||
}
|
||
|
||
/// 칭호 이름 번역
|
||
String translateTitle(String englishName) {
|
||
if (isKoreanLocale) return titleTranslationsKo[englishName] ?? englishName;
|
||
if (isJapaneseLocale) return titleTranslationsJa[englishName] ?? englishName;
|
||
return englishName;
|
||
}
|
||
|
||
/// 인상적인 칭호 번역 (impressiveTitles용)
|
||
String translateImpressiveTitle(String englishName) {
|
||
if (isKoreanLocale) {
|
||
return impressiveTitleTranslationsKo[englishName] ?? englishName;
|
||
}
|
||
if (isJapaneseLocale) {
|
||
return impressiveTitleTranslationsJa[englishName] ?? englishName;
|
||
}
|
||
return englishName;
|
||
}
|
||
|
||
/// 특수 아이템 이름 번역
|
||
String translateSpecial(String englishName) {
|
||
if (isKoreanLocale) return specialTranslationsKo[englishName] ?? englishName;
|
||
if (isJapaneseLocale)
|
||
return specialTranslationsJa[englishName] ?? englishName;
|
||
return englishName;
|
||
}
|
||
|
||
/// 아이템 속성 이름 번역 (기본 + 추가 속성 포함)
|
||
String translateItemAttrib(String englishName) {
|
||
if (isKoreanLocale) {
|
||
return itemAttribTranslationsKo[englishName] ??
|
||
additionalItemAttribTranslationsKo[englishName] ??
|
||
englishName;
|
||
}
|
||
if (isJapaneseLocale) {
|
||
return itemAttribTranslationsJa[englishName] ??
|
||
additionalItemAttribTranslationsJa[englishName] ??
|
||
englishName;
|
||
}
|
||
return englishName;
|
||
}
|
||
|
||
/// 아이템 "~의" 접미사 번역 (기본 + 추가 포함)
|
||
String translateItemOf(String englishName) {
|
||
if (isKoreanLocale) {
|
||
return itemOfsTranslationsKo[englishName] ??
|
||
additionalItemOfsTranslationsKo[englishName] ??
|
||
englishName;
|
||
}
|
||
if (isJapaneseLocale) {
|
||
return itemOfsTranslationsJa[englishName] ??
|
||
additionalItemOfsTranslationsJa[englishName] ??
|
||
englishName;
|
||
}
|
||
return englishName;
|
||
}
|
||
|
||
/// 단순 아이템 번역 (기본 + 추가 드롭 포함)
|
||
String translateBoringItem(String englishName) {
|
||
if (isKoreanLocale) {
|
||
return boringItemTranslationsKo[englishName] ??
|
||
dropItemTranslationsKo[englishName] ??
|
||
additionalDropTranslationsKo[englishName] ??
|
||
englishName;
|
||
}
|
||
if (isJapaneseLocale) {
|
||
return boringItemTranslationsJa[englishName] ??
|
||
dropItemTranslationsJa[englishName] ??
|
||
additionalDropTranslationsJa[englishName] ??
|
||
englishName;
|
||
}
|
||
return englishName;
|
||
}
|
||
|
||
/// interestingItem 번역 (attrib + special 조합)
|
||
/// 예: "Golden Iterator" → "황금 이터레이터" / "黄金のイテレーター"
|
||
String translateInterestingItem(String attrib, String special) {
|
||
if (isKoreanLocale) {
|
||
final translatedAttrib =
|
||
itemAttribTranslationsKo[attrib] ??
|
||
additionalItemAttribTranslationsKo[attrib] ??
|
||
attrib;
|
||
final translatedSpecial = specialTranslationsKo[special] ?? special;
|
||
return '$translatedAttrib $translatedSpecial';
|
||
}
|
||
if (isJapaneseLocale) {
|
||
final translatedAttrib =
|
||
itemAttribTranslationsJa[attrib] ??
|
||
additionalItemAttribTranslationsJa[attrib] ??
|
||
attrib;
|
||
final translatedSpecial = specialTranslationsJa[special] ?? special;
|
||
return '$translatedAttrib$translatedSpecial';
|
||
}
|
||
return '$attrib $special';
|
||
}
|
||
|
||
/// 아이템 이름 문자열 전체 번역 (판매, 로그 등에 사용)
|
||
/// 예: "Golden Iterator of Compilation" → "컴파일의 황금 이터레이터"
|
||
/// 예: "Syntax Error fragment" → "구문 오류 조각"
|
||
String translateItemNameL10n(String itemString) {
|
||
if (!isKoreanLocale && !isJapaneseLocale) return itemString;
|
||
if (itemString.isEmpty) return itemString;
|
||
|
||
// 1. specialItem 형식: "Attrib Special of ItemOf"
|
||
final ofMatch = RegExp(r'^(.+)\s+of\s+(.+)$').firstMatch(itemString);
|
||
if (ofMatch != null) {
|
||
final beforeOf = ofMatch.group(1)!;
|
||
final afterOf = ofMatch.group(2)!;
|
||
|
||
// afterOf가 itemOfs 목록에 있는지 확인
|
||
final itemOfKo =
|
||
itemOfsTranslationsKo[afterOf] ??
|
||
additionalItemOfsTranslationsKo[afterOf];
|
||
final itemOfJa =
|
||
itemOfsTranslationsJa[afterOf] ??
|
||
additionalItemOfsTranslationsJa[afterOf];
|
||
|
||
if (itemOfKo != null || itemOfJa != null) {
|
||
// beforeOf를 interestingItem으로 분리 (attrib + special)
|
||
final beforeWords = beforeOf.split(' ');
|
||
if (beforeWords.length >= 2) {
|
||
final attrib = beforeWords[0];
|
||
final special = beforeWords.sublist(1).join(' ');
|
||
final translatedBefore = translateInterestingItem(attrib, special);
|
||
if (isKoreanLocale) {
|
||
return '$itemOfKo의 $translatedBefore';
|
||
} else if (isJapaneseLocale) {
|
||
return '$itemOfJaの$translatedBefore';
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
// 2. 몬스터 드롭 형식: "{monster} {drop}" (예: "syntax error fragment")
|
||
final words = itemString.split(' ');
|
||
if (words.length >= 2) {
|
||
// 2-1. 마지막 2단어가 드롭 아이템인지 먼저 확인 (예: "outdated syntax")
|
||
// boringItemTranslations도 확인 (2단어 boringItem: "null pointer" 등)
|
||
if (words.length >= 3) {
|
||
final lastTwoWords = '${words[words.length - 2]} ${words.last}'
|
||
.toLowerCase();
|
||
final dropKo2 =
|
||
dropItemTranslationsKo[lastTwoWords] ??
|
||
additionalDropTranslationsKo[lastTwoWords] ??
|
||
boringItemTranslationsKo[lastTwoWords];
|
||
final dropJa2 =
|
||
dropItemTranslationsJa[lastTwoWords] ??
|
||
additionalDropTranslationsJa[lastTwoWords] ??
|
||
boringItemTranslationsJa[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. 마지막 단어가 드롭 아이템인지 확인
|
||
// boringItemTranslations도 확인 (monsterPart로 사용되는 경우)
|
||
final lastWord = words.last.toLowerCase();
|
||
final dropKo =
|
||
dropItemTranslationsKo[lastWord] ??
|
||
additionalDropTranslationsKo[lastWord] ??
|
||
boringItemTranslationsKo[lastWord];
|
||
final dropJa =
|
||
dropItemTranslationsJa[lastWord] ??
|
||
additionalDropTranslationsJa[lastWord] ??
|
||
boringItemTranslationsJa[lastWord];
|
||
|
||
if (dropKo != null || dropJa != null) {
|
||
// 앞 부분은 몬스터 이름
|
||
final monsterPart = words.sublist(0, words.length - 1).join(' ');
|
||
final translatedMonster = translateMonster(monsterPart);
|
||
if (isKoreanLocale && dropKo != null) {
|
||
return '$translatedMonster $dropKo';
|
||
} else if (isJapaneseLocale && dropJa != null) {
|
||
return '$translatedMonsterの$dropJa';
|
||
}
|
||
}
|
||
|
||
// 3. interestingItem 형식: "Attrib Special" (2단어)
|
||
if (words.length == 2) {
|
||
return translateInterestingItem(words[0], words[1]);
|
||
}
|
||
}
|
||
|
||
// 4. 단일 단어 - boringItem 번역 시도
|
||
return translateBoringItem(itemString);
|
||
}
|
||
|
||
// ============================================================================
|
||
// 스토리/시네마틱 번역 함수 (Story/Cinematic Translation Functions)
|
||
// ============================================================================
|
||
|
||
/// Act 제목 번역
|
||
String translateActTitle(String englishTitle) {
|
||
if (isKoreanLocale)
|
||
return actTitleTranslationsKo[englishTitle] ?? englishTitle;
|
||
if (isJapaneseLocale)
|
||
return actTitleTranslationsJa[englishTitle] ?? englishTitle;
|
||
return englishTitle;
|
||
}
|
||
|
||
/// Act 보스 이름 번역
|
||
String translateActBoss(String englishBoss) {
|
||
if (isKoreanLocale) return actBossTranslationsKo[englishBoss] ?? englishBoss;
|
||
if (isJapaneseLocale)
|
||
return actBossTranslationsJa[englishBoss] ?? englishBoss;
|
||
return englishBoss;
|
||
}
|
||
|
||
/// Act 퀘스트 번역
|
||
String translateActQuest(String englishQuest) {
|
||
if (isKoreanLocale)
|
||
return actQuestTranslationsKo[englishQuest] ?? englishQuest;
|
||
if (isJapaneseLocale)
|
||
return actQuestTranslationsJa[englishQuest] ?? englishQuest;
|
||
return englishQuest;
|
||
}
|
||
|
||
/// 시네마틱 텍스트 번역
|
||
String translateCinematic(String englishText) {
|
||
if (isKoreanLocale)
|
||
return cinematicTranslationsKo[englishText] ?? englishText;
|
||
if (isJapaneseLocale)
|
||
return cinematicTranslationsJa[englishText] ?? englishText;
|
||
return englishText;
|
||
}
|
||
|
||
/// 지역 이름 번역
|
||
String translateLocation(String englishLocation) {
|
||
if (isKoreanLocale)
|
||
return locationTranslationsKo[englishLocation] ?? englishLocation;
|
||
if (isJapaneseLocale)
|
||
return locationTranslationsJa[englishLocation] ?? englishLocation;
|
||
return englishLocation;
|
||
}
|
||
|
||
/// 세력/조직 이름 번역
|
||
String translateFaction(String englishFaction) {
|
||
if (isKoreanLocale)
|
||
return factionTranslationsKo[englishFaction] ?? englishFaction;
|
||
if (isJapaneseLocale)
|
||
return factionTranslationsJa[englishFaction] ?? englishFaction;
|
||
return englishFaction;
|
||
}
|
||
|
||
/// 스킬/주문 이름 번역 (전투 로그용)
|
||
String translateSpell(String englishName) {
|
||
if (isKoreanLocale) {
|
||
return spellTranslationsKo[englishName] ?? englishName;
|
||
}
|
||
if (isJapaneseLocale) {
|
||
return spellTranslationsJa[englishName] ?? englishName;
|
||
}
|
||
return englishName;
|
||
}
|
||
|
||
// ============================================================================
|
||
// 프론트 화면 텍스트
|
||
// ============================================================================
|
||
|
||
String get uiHallOfFame => _l('Hall of Fame', '명예의 전당', '栄誉の殿堂');
|
||
String get uiLocalArena => _l('Local Arena', '로컬 아레나', 'ローカルアリーナ');
|
||
String get frontDescription => _l(
|
||
'A retro-style offline single-player RPG',
|
||
'레트로 감성의 오프라인 싱글플레이어 RPG',
|
||
'レトロ感のあるオフラインシングルプレイヤーRPG',
|
||
);
|
||
String get frontTodayFocus =>
|
||
_l("Today's focus", '오늘의 중점', '今日のフォーカス');
|
||
|
||
// ============================================================================
|
||
// 명예의 전당 화면 텍스트
|
||
// ============================================================================
|
||
|
||
String get hofNoHeroes =>
|
||
_l('No heroes yet', '영웅이 아직 없습니다', 'まだ英雄がいません');
|
||
String get hofDefeatGlitchGod => _l(
|
||
'Defeat the Glitch God to enshrine your legend!',
|
||
'글리치 신을 처치하여 전설을 남기세요!',
|
||
'グリッチゴッドを倒して伝説を刻もう!',
|
||
);
|
||
String get hofVictory => _l('VICTORY!', '승리!', '勝利!');
|
||
String get hofDefeatedGlitchGod => _l(
|
||
'You have defeated the Glitch God!',
|
||
'글리치 신을 처치했습니다!',
|
||
'グリッチゴッドを倒しました!',
|
||
);
|
||
String get hofLegendEnshrined => _l(
|
||
'Your legend has been enshrined in the Hall of Fame!',
|
||
'당신의 전설이 명예의 전당에 기록되었습니다!',
|
||
'あなたの伝説が栄誉の殿堂に刻まれました!',
|
||
);
|
||
String get hofViewHallOfFame =>
|
||
_l('View Hall of Fame', '명예의 전당 보기', '栄誉の殿堂を見る');
|
||
String get hofNewGame => _l('New Game', '새 게임', '新しいゲーム');
|
||
String get hofLevel => _l('Level', '레벨', 'レベル');
|
||
String get hofTime => _l('Time', '시간', '時間');
|
||
String get hofDeaths => _l('Deaths', '사망', '死亡');
|
||
String get hofQuests => _l('Quests', '퀘스트', 'クエスト');
|
||
String get hofStats => _l('Statistics', '통계', '統計');
|
||
String get hofMonsters => _l('Monsters', '몬스터', 'モンスター');
|
||
String get hofCleared => _l('Cleared', '클리어', 'クリア');
|
||
String get hofSkills => _l('Skills', '스킬', 'スキル');
|
||
String get hofNoSkills => _l('No Skills', '스킬 없음', 'スキルなし');
|
||
String get hofCombatStats => _l('Combat Stats', '전투 스탯', '戦闘ステータス');
|
||
String get hofCharacterPreview =>
|
||
_l('Character Preview', '캐릭터 미리보기', 'キャラクタープレビュー');
|
||
String get buttonClose => _l('Close', '닫기', '閉じる');
|
||
|
||
// Lv. 형식이 모든 언어에서 동일
|
||
String uiLevel(int level) => 'Lv.$level';
|
||
|
||
// ============================================================================
|
||
// 시네마틱 뷰 텍스트
|
||
// ============================================================================
|
||
|
||
String get uiSkip => _l('SKIP', '건너뛰기', 'スキップ');
|
||
|
||
// ============================================================================
|
||
// 게임 플레이 화면 텍스트
|
||
// ============================================================================
|
||
|
||
String get uiLevelUp => _l('Level Up!', '레벨 업!', 'レベルアップ!');
|
||
String uiQuestComplete(String questName) =>
|
||
_l('Quest Complete: $questName', '퀘스트 완료: $questName', 'クエスト完了: $questName');
|
||
|
||
// ============================================================================
|
||
// 장비 패널 텍스트
|
||
// ============================================================================
|
||
|
||
String get uiEquipmentScore =>
|
||
_l('Equipment Score', '장비 점수', '装備スコア');
|
||
String get uiEmpty => _l('(empty)', '(비어있음)', '(空)');
|
||
String uiWeight(int weight) => _l('Wt.$weight', '무게 $weight', '重量 $weight');
|
||
/// 남은 시간 표시
|
||
String uiTimeRemaining(String time) =>
|
||
_l('$time remaining', '$time 남음', '残り$time');
|
||
|
||
// 장비 슬롯 이름
|
||
String get slotWeapon => _l('Weapon', '무기', '武器');
|
||
String get slotShield => _l('Shield', '방패', '盾');
|
||
String get slotHelm => _l('Helm', '투구', '兜');
|
||
String get slotHauberk => _l('Hauberk', '갑옷', '鎧');
|
||
String get slotBrassairts => _l('Brassairts', '상완갑', '上腕甲');
|
||
String get slotVambraces => _l('Vambraces', '전완갑', '前腕甲');
|
||
String get slotGauntlets => _l('Gauntlets', '건틀릿', 'ガントレット');
|
||
String get slotGambeson => _l('Gambeson', '패딩', 'パッデッドアーマー');
|
||
String get slotCuisses => _l('Cuisses', '허벅지갑', '腿当て');
|
||
String get slotGreaves => _l('Greaves', '정강이갑', '脛当て');
|
||
String get slotSollerets => _l('Sollerets', '철제부츠', '鉄靴');
|
||
|
||
// 스탯 약어 (장비용)
|
||
String get statAtk => _l('ATK', '공격', '攻撃');
|
||
String get statMAtk => _l('MATK', '마공', '魔攻');
|
||
String get statCri => _l('CRI', '치명', 'クリ');
|
||
String get statParry => _l('PARRY', '패리', 'パリィ');
|
||
String get statDef => _l('DEF', '방어', '防御');
|
||
String get statMDef => _l('MDEF', '마방', '魔防');
|
||
String get statBlock => _l('BLOCK', '블록', 'ブロック');
|
||
String get statEva => _l('EVA', '회피', '回避');
|
||
// HP/MP는 모든 언어에서 동일
|
||
String get statHp => 'HP';
|
||
String get statMp => 'MP';
|
||
String get statSpeed => _l('SPEED', '속도', '速度');
|
||
|
||
// ============================================================================
|
||
// 스킬 패널 텍스트
|
||
// ============================================================================
|
||
|
||
String get uiDot => _l('DOT', '지속', 'DOT');
|
||
|
||
// ============================================================================
|
||
// 아이템 희귀도
|
||
// ============================================================================
|
||
|
||
String get rarityCommon => _l('COMMON', '일반', 'コモン');
|
||
String get rarityUncommon => _l('UNCOMMON', '고급', 'アンコモン');
|
||
String get rarityRare => _l('RARE', '희귀', 'レア');
|
||
String get rarityEpic => _l('EPIC', '영웅', 'エピック');
|
||
String get rarityLegendary => _l('LEGENDARY', '전설', 'レジェンダリー');
|
||
|
||
// ============================================================================
|
||
// 캐릭터 생성 화면 텍스트
|
||
// ============================================================================
|
||
|
||
String uiRollHistory(int count) =>
|
||
_l('$count roll(s) in history', '리롤 기록: $count회', 'リロール履歴: $count回');
|
||
String get uiEnterName => _l(
|
||
'Please enter a name.',
|
||
'이름을 입력해주세요.',
|
||
'名前を入力してください。',
|
||
);
|
||
String get uiTestMode => _l('Test Mode', '테스트 모드', 'テストモード');
|
||
String get uiTestModeDesc => _l(
|
||
'Use mobile layout on web',
|
||
'웹에서 모바일 레이아웃 사용',
|
||
'Webでモバイルレイアウトを使用',
|
||
);
|
||
|
||
// ============================================================================
|
||
// 캐로셀 네비게이션 텍스트
|
||
// ============================================================================
|
||
|
||
String get navSkills => _l('Skills', '스킬', 'スキル');
|
||
String get navInventory => _l('Inventory', '인벤토리', '所持品');
|
||
String get navEquipment => _l('Equip', '장비', '装備');
|
||
String get navCharacter => _l('Character', '캐릭터', 'キャラ');
|
||
String get navCombatLog => _l('Combat', '전투로그', '戦闘ログ');
|
||
String get navStory => _l('Story', '스토리', 'ストーリー');
|
||
String get navQuest => _l('Quest', '퀘스트', 'クエスト');
|
||
|
||
// ============================================================================
|
||
// 옵션 메뉴 텍스트
|
||
// ============================================================================
|
||
|
||
String get menuOptions => _l('Options', '옵션', 'オプション');
|
||
String get menuPause => _l('Pause', '일시정지', '一時停止');
|
||
String get menuResume => _l('Resume', '재개', '再開');
|
||
String get menuSpeed => _l('Speed', '속도', '速度');
|
||
String get menuSave => _l('Save', '저장', 'セーブ');
|
||
String get menuSaved => _l('Game saved', '저장되었습니다', '保存しました');
|
||
String get menuLanguage => _l('Language', '언어', '言語');
|
||
String get languageEnglish => _l('English', '영어', '英語');
|
||
String get languageKorean => _l('Korean', '한국어', '韓国語');
|
||
String get languageJapanese => _l('Japanese', '일본어', '日本語');
|
||
String get menuDeleteSave => _l('Delete Save', '세이브 삭제', 'セーブ削除');
|
||
String get menuNewGame => _l('New Game', '새로하기', '新規ゲーム');
|
||
String get confirmDeleteTitle => _l('Delete Save', '세이브 삭제', 'セーブ削除');
|
||
|
||
String get confirmDeleteMessage => _l(
|
||
'Are you sure?\nAll progress will be lost.',
|
||
'정말 삭제하시겠습니까?\n모든 진행 상황이 사라집니다.',
|
||
'本当に削除しますか?\nすべての進行状況が失われます。',
|
||
);
|
||
String get buttonConfirm => _l('Confirm', '확인', '確認');
|
||
String get buttonCancel => _l('Cancel', '취소', 'キャンセル');
|
||
|
||
// ============================================================================
|
||
// 프론트 화면 경고/푸터 텍스트
|
||
// ============================================================================
|
||
|
||
String get uiWarning => _l('Warning', '경고', '警告');
|
||
String get warningDeleteSave => _l(
|
||
'Existing save file will be deleted. Continue?',
|
||
'기존 저장 파일이 삭제됩니다. 계속하시겠습니까?',
|
||
'既存のセーブファイルが削除されます。続行しますか?',
|
||
);
|
||
// 카피라이트 텍스트는 언어에 따라 변하지 않음
|
||
String get copyrightText => '© 2025 NatureBridgeAi & cclabs all rights reserved';
|
||
|
||
// ============================================================================
|
||
// 테마 설정 텍스트
|
||
// ============================================================================
|
||
|
||
String get menuTheme => _l('Theme', '테마', 'テーマ');
|
||
String get themeLight => _l('Light', '라이트', 'ライト');
|
||
String get themeDark => _l('Dark', '다크', 'ダーク');
|
||
String get themeSystem => _l('System', '시스템', 'システム');
|
||
|
||
// ============================================================================
|
||
// 로딩 텍스트
|
||
// ============================================================================
|
||
|
||
String get uiLoading => _l('Loading...', '불러오는 중...', '読み込み中...');
|
||
|
||
// ============================================================================
|
||
// 설정 화면 텍스트
|
||
// ============================================================================
|
||
|
||
String get uiSettings => _l('Settings', '설정', '設定');
|
||
String get uiStatistics => _l('Statistics', '통계', '統計');
|
||
String get uiHelp => _l('Help', '도움말', 'ヘルプ');
|
||
String get uiTheme => _l('Theme', '테마', 'テーマ');
|
||
String get uiThemeLight => _l('Light', '라이트', 'ライト');
|
||
String get uiThemeDark => _l('Dark', '다크', 'ダーク');
|
||
String get uiThemeSystem => _l('System', '시스템', 'システム');
|
||
String get uiLanguage => _l('Language', '언어', '言語');
|
||
String get uiSound => _l('Sound', '사운드', 'サウンド');
|
||
String get uiBgmVolume => _l('BGM Volume', 'BGM 볼륨', 'BGM音量');
|
||
String get uiSfxVolume => _l('SFX Volume', '효과음 볼륨', '効果音音量');
|
||
String get uiSoundOff => _l('Muted', '음소거', 'ミュート');
|
||
String get uiAnimationSpeed =>
|
||
_l('Animation Speed', '애니메이션 속도', 'アニメーション速度');
|
||
String get uiSpeedSlow => _l('Slow', '느림', '遅い');
|
||
String get uiSpeedNormal => _l('Normal', '보통', '普通');
|
||
String get uiSpeedFast => _l('Fast', '빠름', '速い');
|
||
String get uiAbout => _l('About', '정보', '情報');
|
||
String get uiAboutDescription => _l(
|
||
'An offline single-player RPG with ASCII art and retro vibes.',
|
||
'ASCII 아트와 레트로 감성의 오프라인 싱글플레이어 RPG입니다.',
|
||
'ASCIIアートとレトロ感のあるオフラインシングルプレイヤーRPGです。',
|
||
);
|
||
|
||
// ============================================================================
|
||
// 공통 UI 액션 텍스트
|
||
// ============================================================================
|
||
|
||
String get uiConfirm => _l('Confirm', '확인', '確認');
|
||
|
||
String get uiCancel => _l('Cancel', '취소', 'キャンセル');
|
||
String get uiDelete => _l('Delete', '삭제', '削除');
|
||
String get uiConfirmDelete =>
|
||
_l('Are you sure you want to delete?', '정말로 삭제하시겠습니까?', '本当に削除しますか?');
|
||
String get uiDeleted => _l('Deleted', '삭제되었습니다', '削除されました');
|
||
String get uiError =>
|
||
_l('An error occurred', '오류가 발생했습니다', 'エラーが発生しました');
|
||
String get uiSaved => _l('Saved', '저장됨', '保存しました');
|
||
String get uiSaveBattleLog =>
|
||
_l('Save Battle Log', '배틀로그 저장', 'バトルログ保存');
|