Files
asciinevrdie/lib/data/game_text_l10n.dart
JiWoong Sul d07a0c5554 style: dart format 적용
- 전체 Dart 소스 및 테스트 파일 포매팅 통일
- trailing comma, 줄바꿈, 인덴트 정리
2026-02-13 16:08:23 +09:00

1233 lines
55 KiB
Dart
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// 게임 텍스트 로컬라이제이션 (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 deathCombatLog => _l('Combat Log', '전투 기록', '戦闘ログ');
// 광고 부활 (통합)
String get deathAdRevive => _l('Watch Ad & Revive', '광고보고 부활', '広告視聴で復活');
String get deathAdReviveHp => _l('HP 100% Recovery', 'HP 100% 회복', 'HP 100%回復');
String get deathAdReviveItem => _l('Item Recovery', '아이템 복구', 'アイテム回収');
String get deathAdReviveAuto =>
_l('10min Auto-Revive Buff', '10분간 자동부활 버프', '10分間自動復活バフ');
String get deathAdRevivePaidDesc =>
_l('Premium: No ads required', '프리미엄: 광고 없이 이용', 'プレミアム: 広告不要');
String deathKilledBy(String killerName) =>
_l('Killed by $killerName', '$killerName에게 사망', '$killerNameに倒された');
String get deathEnvironmentalHazard =>
_l('Environmental hazard', '환경 피해로 사망', '環境ダメージで死亡');
// ============================================================================
// 속도 부스트 (Phase 6)
// ============================================================================
String get speedBoostTitle => _l('Speed Boost', '속도 부스트', 'スピードブースト');
String get speedBoostActivate =>
_l('Activate 10x Speed', '10배속 활성화', '10倍速を有効化');
String speedBoostRemaining(int seconds) =>
_l('${seconds}s remaining', '${seconds}초 남음', '残り${seconds}');
String get speedBoostActive => _l('BOOST ACTIVE', '부스트 활성화', 'ブースト中');
// ============================================================================
// 복귀 보상 (Phase 7)
// ============================================================================
String get returnRewardTitle => _l('Welcome Back!', '돌아오셨군요!', 'おかえりなさい!');
String returnRewardHoursAway(String time) =>
_l('You were away for $time', '$time 동안 떠나있었습니다', '$time 離れていました');
String returnRewardChests(int count) =>
_l('$count Treasure Chest(s)', '보물 상자 $count개', '宝箱 $count個');
String get returnRewardOpenChests => _l('Open Chests', '상자 열기', '宝箱を開ける');
String get returnRewardBonusChests => _l('Bonus Chests', '보너스 상자', 'ボーナス宝箱');
String get returnRewardClaimBonus =>
_l('Get Bonus (AD)', '보너스 받기 (광고)', 'ボーナス受取 (広告)');
String get returnRewardClaimBonusFree =>
_l('Get Bonus (Free)', '보너스 받기 (무료)', 'ボーナス受取 (無料)');
String get returnRewardSkip => _l('Skip', '건너뛰기', 'スキップ');
String get returnRewardOpening => _l('Opening...', '여는 중...', '開封中...');
String get returnRewardComplete => _l('Complete!', '완료!', '完了!');
// 상자 보상 타입
String get chestRewardEquipment => _l('Equipment', '장비', '装備');
String get chestRewardPotion => _l('Potion', '포션', 'ポーション');
String get chestRewardGold => _l('Gold', '골드', 'ゴールド');
String get chestRewardExperience => _l('Experience', '경험치', '経験値');
String chestRewardGoldAmount(int gold) =>
_l('+$gold Gold', '+$gold 골드', '+$gold ゴールド');
String chestRewardExpAmount(int exp) =>
_l('+$exp EXP', '+$exp 경험치', '+$exp 経験値');
String chestRewardPotionAmount(String name, int count) =>
_l('$name x$count', '$name x$count', '$name x$count');
String get chestRewardEquipped => _l('Equipped!', '장착됨!', '装備しました!');
String get chestRewardBetterItem =>
_l('Better than current!', '현재보다 좋습니다!', '現在より良い!');
// ============================================================================
// 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', '배틀로그 저장', 'バトルログ保存');
// ============================================================================
// IAP 구매 텍스트
// ============================================================================
String get iapRemoveAds => _l('Remove Ads', '광고 제거', '広告削除');
String get iapRemoveAdsDesc =>
_l('Enjoy ad-free experience', '광고 없이 플레이', '広告なしでプレイ');
String get iapBenefitTitle => _l('Premium Benefits', '프리미엄 혜택', 'プレミアム特典');
String get iapBenefit1 => _l('Ad-free gameplay', '광고 없는 쾌적한 플레이', '広告なしの快適プレイ');
String get iapBenefit2 =>
_l('Unlimited speed boost', '속도 부스트 무제한', 'スピードブースト無制限');
String get iapBenefit3 =>
_l('Stat reroll undo: 3 times', '신규 캐릭터 스탯 가챠 되돌리기 3회', '新キャラステ振り直し3回');
String get iapBenefit4 => _l('Unlimited rerolls', '굴리기 무제한', 'リロール無制限');
String get iapBenefit5 =>
_l('2x offline time credited', '오프라인 시간 2배 인정', 'オフライン時間2倍適用');
String get iapBenefit6 =>
_l('Return chests: 10 max', '복귀 상자 최대 10개', '帰還ボックス最大10個');
String get iapPurchaseButton => _l('Purchase', '구매하기', '購入する');
String get iapAlreadyPurchased => _l('Already purchased', '이미 구매됨', '購入済み');
String get iapPurchaseSuccess => _l('Purchase successful!', '구매 완료!', '購入完了!');
String get iapPurchaseFailed => _l(
'Purchase failed. Please try again.',
'구매 실패. 다시 시도해주세요.',
'購入失敗。もう一度お試しください。',
);
String get iapStoreUnavailable =>
_l('Store unavailable', '스토어 사용 불가', 'ストア利用不可');
String get iapRestorePurchase => _l('Restore Purchase', '구매 복원', '購入を復元');
String get iapRestoreSuccess =>
_l('Purchase restored!', '구매 복원 완료!', '購入を復元しました!');
String get iapRestoreFailed => _l('Restore failed', '복원 실패', '復元失敗');
// ============================================================================
// 스킬 상세 정보 라벨 (Skill Detail Labels)
// ============================================================================
// 공통 라벨
String get skillTier => _l('Tier', '티어', 'ティア');
String get skillMpCost => _l('MP', 'MP', 'MP');
String get skillCooldown => _l('CD', '쿨타임', 'CT');
String get skillSeconds => _l('s', '', '');
// 공격 스킬 라벨
String get skillPower => _l('Power', '위력', '威力');
String get skillHits => _l('Hits', '타격', 'ヒット');
String get skillDot => _l('DOT', '지속피해', 'DOT');
String get skillLifesteal => _l('Lifesteal', 'HP흡수', 'HP吸収');
String get skillDefPen => _l('DEF Pen', '방어무시', '防御貫通');
String get skillSelfDmg => _l('Self Dmg', '자해', '自傷');
// 회복 스킬 라벨
String get skillHealFixed => _l('Heal', '회복', '回復');
String get skillHealPercent => _l('HP%', 'HP%', 'HP%');
String get skillMpHeal => _l('MP Heal', 'MP회복', 'MP回復');
// 버프/디버프 라벨
String get skillBuffDuration => _l('Duration', '지속', '持続');
String get skillAtkMod => _l('ATK', '공격', '攻撃');
String get skillDefMod => _l('DEF', '방어', '防御');
String get skillCriMod => _l('CRI', '치명', 'クリ');
String get skillEvaMod => _l('EVA', '회피', '回避');
// 스킬 타입 이름
String get skillTypeAttack => _l('Attack', '공격', '攻撃');
String get skillTypeHeal => _l('Heal', '회복', '回復');
String get skillTypeBuff => _l('Buff', '버프', 'バフ');
String get skillTypeDebuff => _l('Debuff', '디버프', 'デバフ');
// 속성 이름 (SkillElement)
String get elementLogic => _l('Logic', '논리', 'ロジック');
String get elementMemory => _l('Memory', '메모리', 'メモリ');
String get elementNetwork => _l('Network', '네트워크', 'ネットワーク');
String get elementFire => _l('Fire', '화염', '火炎');
String get elementIce => _l('Ice', '빙결', '氷結');
String get elementLightning => _l('Lightning', '전기', '電撃');
String get elementVoid => _l('Void', '공허', 'ヴォイド');
String get elementChaos => _l('Chaos', '혼돈', 'カオス');
// 스킬 상세 정보 없음
String get skillNoDetails => _l('No details', '상세 정보 없음', '詳細情報なし');
// ============================================================================
// 알림 텍스트 (Notification Texts)
// ============================================================================
String get notifyLevelUp => _l('LEVEL UP!', '레벨 업!', 'レベルアップ!');
String notifyLevel(int level) => _l('Level $level', '레벨 $level', 'レベル $level');
String get notifyQuestComplete => _l('QUEST COMPLETE!', '퀘스트 완료!', 'クエスト完了!');
String get notifyPrologueComplete =>
_l('PROLOGUE COMPLETE!', '프롤로그 완료!', 'プロローグ完了!');
String notifyActComplete(int actNumber) =>
_l('ACT $actNumber COMPLETE!', '${actNumber}막 완료!', '${actNumber}幕完了!');
String get notifyNewSpell => _l('NEW SPELL!', '새 주문!', '新しい呪文!');
String get notifyNewEquipment => _l('NEW EQUIPMENT!', '새 장비!', '新しい装備!');
String get notifyBossDefeated => _l('BOSS DEFEATED!', '보스 처치!', 'ボス撃破!');