feat(l10n): 퀘스트 및 시네마틱 텍스트 번역 적용
- game_text_l10n.dart에 게임 데이터 번역 함수 추가 - translateMonster, translateRace, translateKlass - translateTitle, translateImpressiveTitle - translateBoringItem, translateInterestingItem - pq_logic.dart monsterTask에서 몬스터 이름 번역 - completeQuest에서 퀘스트 아이템/몬스터 번역 - impressiveGuy, namedMonster에서 NPC 이름 번역 - interplotCinematic에서 시네마틱 아이템 번역
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
// 게임 텍스트 로컬라이제이션 (BuildContext 없이 사용)
|
||||
// progress_service.dart, pq_logic.dart 등에서 사용
|
||||
|
||||
import 'package:askiineverdie/data/game_translations_ko.dart';
|
||||
|
||||
/// 현재 게임 로케일 설정 (전역)
|
||||
String _currentLocale = 'en';
|
||||
|
||||
@@ -282,3 +284,52 @@ String namedMonsterFormat(String generatedName, String monsterType) =>
|
||||
isKoreanLocale
|
||||
? '$monsterType $generatedName'
|
||||
: '$generatedName the $monsterType';
|
||||
|
||||
// ============================================================================
|
||||
// 게임 데이터 번역 함수 (BuildContext 없이 사용)
|
||||
// ============================================================================
|
||||
|
||||
/// 몬스터 이름 번역
|
||||
String translateMonster(String englishName) =>
|
||||
isKoreanLocale ? (monsterTranslationsKo[englishName] ?? englishName) : englishName;
|
||||
|
||||
/// 종족 이름 번역
|
||||
String translateRace(String englishName) =>
|
||||
isKoreanLocale ? (raceTranslationsKo[englishName] ?? englishName) : englishName;
|
||||
|
||||
/// 직업 이름 번역
|
||||
String translateKlass(String englishName) =>
|
||||
isKoreanLocale ? (klassTranslationsKo[englishName] ?? englishName) : englishName;
|
||||
|
||||
/// 칭호 이름 번역
|
||||
String translateTitle(String englishName) =>
|
||||
isKoreanLocale ? (titleTranslationsKo[englishName] ?? englishName) : englishName;
|
||||
|
||||
/// 인상적인 칭호 번역 (impressiveTitles용)
|
||||
String translateImpressiveTitle(String englishName) =>
|
||||
isKoreanLocale ? (impressiveTitleTranslationsKo[englishName] ?? englishName) : englishName;
|
||||
|
||||
/// 특수 아이템 이름 번역
|
||||
String translateSpecial(String englishName) =>
|
||||
isKoreanLocale ? (specialTranslationsKo[englishName] ?? englishName) : englishName;
|
||||
|
||||
/// 아이템 속성 이름 번역
|
||||
String translateItemAttrib(String englishName) =>
|
||||
isKoreanLocale ? (itemAttribTranslationsKo[englishName] ?? englishName) : englishName;
|
||||
|
||||
/// 아이템 "~의" 접미사 번역
|
||||
String translateItemOf(String englishName) =>
|
||||
isKoreanLocale ? (itemOfsTranslationsKo[englishName] ?? englishName) : englishName;
|
||||
|
||||
/// 단순 아이템 번역
|
||||
String translateBoringItem(String englishName) =>
|
||||
isKoreanLocale ? (boringItemTranslationsKo[englishName] ?? englishName) : englishName;
|
||||
|
||||
/// interestingItem 번역 (attrib + special 조합)
|
||||
/// 예: "Golden Iterator" → "황금 이터레이터"
|
||||
String translateInterestingItem(String attrib, String special) {
|
||||
if (!isKoreanLocale) return '$attrib $special';
|
||||
final translatedAttrib = itemAttribTranslationsKo[attrib] ?? attrib;
|
||||
final translatedSpecial = specialTranslationsKo[special] ?? special;
|
||||
return '$translatedAttrib $translatedSpecial';
|
||||
}
|
||||
|
||||
@@ -510,15 +510,18 @@ MonsterTaskResult monsterTask(
|
||||
|
||||
// 원본 Main.pas:537-547: 가끔 NPC를 몬스터로 사용
|
||||
if (rng.nextInt(25) == 0) {
|
||||
final race = pick(config.races, rng).split('|').first;
|
||||
final raceEn = pick(config.races, rng).split('|').first;
|
||||
final race = l10n.translateRace(raceEn);
|
||||
if (rng.nextInt(2) == 0) {
|
||||
// 'passing Race Class' 형태
|
||||
final klass = pick(config.klasses, rng).split('|').first;
|
||||
final klassEn = pick(config.klasses, rng).split('|').first;
|
||||
final klass = l10n.translateKlass(klassEn);
|
||||
monster = l10n.modifierPassing('$race $klass');
|
||||
} else {
|
||||
// 'Title Name the Race' 형태 (원본은 PickLow(Titles) 사용)
|
||||
final title = pickLow(config.titles, rng);
|
||||
monster = '$title ${generateName(rng)} the $race';
|
||||
final titleEn = pickLow(config.titles, rng);
|
||||
final title = l10n.translateTitle(titleEn);
|
||||
monster = l10n.namedMonsterFormat(generateName(rng), '$title $race');
|
||||
definite = true;
|
||||
}
|
||||
monsterLevel = targetLevel;
|
||||
@@ -553,7 +556,8 @@ MonsterTaskResult monsterTask(
|
||||
// Adjust quantity and adjectives based on level delta.
|
||||
var qty = 1;
|
||||
final levelDiff = targetLevel - monsterLevel;
|
||||
var name = baseName;
|
||||
// 몬스터 이름 번역 (l10n 지원)
|
||||
var name = l10n.translateMonster(baseName);
|
||||
|
||||
if (levelDiff > 10) {
|
||||
qty =
|
||||
@@ -669,7 +673,8 @@ QuestResult completeQuest(PqConfig config, DeterministicRandom rng, int level) {
|
||||
bestIndex = monsterIndex;
|
||||
}
|
||||
}
|
||||
final name = best.split('|').first;
|
||||
final nameEn = best.split('|').first;
|
||||
final name = l10n.translateMonster(nameEn);
|
||||
return QuestResult(
|
||||
caption: l10n.questPatch(l10n.definiteL10n(name, 2)),
|
||||
reward: reward,
|
||||
@@ -678,19 +683,24 @@ QuestResult completeQuest(PqConfig config, DeterministicRandom rng, int level) {
|
||||
monsterIndex: bestIndex,
|
||||
);
|
||||
case 1:
|
||||
final item = interestingItem(config, rng);
|
||||
// interestingItem: attrib + special 조합 후 번역
|
||||
final attr = pick(config.itemAttrib, rng);
|
||||
final special = pick(config.specials, rng);
|
||||
final item = l10n.translateInterestingItem(attr, special);
|
||||
return QuestResult(
|
||||
caption: l10n.questLocate(l10n.definiteL10n(item, 1)),
|
||||
reward: reward,
|
||||
);
|
||||
case 2:
|
||||
final item = boringItem(config, rng);
|
||||
final itemEn = boringItem(config, rng);
|
||||
final item = l10n.translateBoringItem(itemEn);
|
||||
return QuestResult(
|
||||
caption: l10n.questTransfer(item),
|
||||
reward: reward,
|
||||
);
|
||||
case 3:
|
||||
final item = boringItem(config, rng);
|
||||
final itemEn = boringItem(config, rng);
|
||||
final item = l10n.translateBoringItem(itemEn);
|
||||
return QuestResult(
|
||||
caption: l10n.questDownload(l10n.indefiniteL10n(item, 1)),
|
||||
reward: reward,
|
||||
@@ -708,7 +718,8 @@ QuestResult completeQuest(PqConfig config, DeterministicRandom rng, int level) {
|
||||
bestLevel = l;
|
||||
}
|
||||
}
|
||||
final name = best.split('|').first;
|
||||
final nameEn = best.split('|').first;
|
||||
final name = l10n.translateMonster(nameEn);
|
||||
// Stabilize는 fQuest.Caption := '' 로 비움 → monsterIndex 미저장
|
||||
return QuestResult(
|
||||
caption: l10n.questStabilize(l10n.definiteL10n(name, 2)),
|
||||
@@ -926,11 +937,13 @@ String _pick(String pipeSeparated, DeterministicRandom rng) {
|
||||
/// NPC 이름 생성 (ImpressiveGuy, Main.pas:514-521)
|
||||
/// 인상적인 타이틀 + 종족 또는 이름 조합 (l10n 지원)
|
||||
String impressiveGuy(PqConfig config, DeterministicRandom rng) {
|
||||
final title = pick(config.impressiveTitles, rng);
|
||||
final titleEn = pick(config.impressiveTitles, rng);
|
||||
final title = l10n.translateImpressiveTitle(titleEn);
|
||||
switch (rng.nextInt(2)) {
|
||||
case 0:
|
||||
// "the King of the Elves" / "엘프들의 왕" 형태
|
||||
final race = pick(config.races, rng).split('|').first;
|
||||
final raceEn = pick(config.races, rng).split('|').first;
|
||||
final race = l10n.translateRace(raceEn);
|
||||
return l10n.impressiveGuyPattern1(title, race);
|
||||
case 1:
|
||||
// "King Vrognak of Zoxzik" / "Zoxzik의 왕 Vrognak" 형태
|
||||
@@ -961,8 +974,10 @@ String namedMonster(PqConfig config, DeterministicRandom rng, int level) {
|
||||
}
|
||||
}
|
||||
|
||||
// 몬스터 이름 번역
|
||||
final translatedMonster = l10n.translateMonster(best);
|
||||
// "GeneratedName the MonsterType" / "몬스터타입 GeneratedName" 형태
|
||||
return l10n.namedMonsterFormat(generateName(rng), best);
|
||||
return l10n.namedMonsterFormat(generateName(rng), translatedMonster);
|
||||
}
|
||||
|
||||
/// 플롯 간 시네마틱 이벤트 생성 (InterplotCinematic, Main.pas:456-495)
|
||||
@@ -1021,9 +1036,11 @@ List<QueueEntry> interplotCinematic(
|
||||
case 2:
|
||||
// 시나리오 3: 내부자 위협 발견
|
||||
final guy = impressiveGuy(config, rng);
|
||||
final itemEn = boringItem(config, rng);
|
||||
final item = l10n.translateBoringItem(itemEn);
|
||||
q(QueueKind.task, 2, l10n.cinematicBetrayal1(guy));
|
||||
q(QueueKind.task, 3, l10n.cinematicBetrayal2(guy));
|
||||
q(QueueKind.task, 2, l10n.cinematicBetrayal3(boringItem(config, rng)));
|
||||
q(QueueKind.task, 2, l10n.cinematicBetrayal3(item));
|
||||
q(QueueKind.task, 2, l10n.cinematicBetrayal4());
|
||||
q(QueueKind.task, 2, l10n.cinematicBetrayal5(guy));
|
||||
q(QueueKind.task, 3, l10n.cinematicBetrayal6());
|
||||
|
||||
Reference in New Issue
Block a user