feat(l10n): 게임 텍스트 로컬라이제이션 확장

- game_text_l10n.dart: BuildContext 없이 사용할 수 있는 게임 텍스트 l10n 파일 생성
- progress_service.dart: 프롤로그/태스크 캡션 l10n 함수 사용으로 변경
- pq_logic.dart: 퀘스트/시네마틱/몬스터 수식어 l10n 함수 사용으로 변경

번역 적용 범위:
- 프롤로그 텍스트 (4개)
- 태스크 캡션 (컴파일, 이동, 디버깅, 판매 등)
- 퀘스트 캡션 (패치, 찾기, 전송, 다운로드, 안정화)
- 시네마틱 텍스트 (캐시 존, 전투, 배신 시나리오)
- 몬스터 수식어 (sick, young, big, special 등 모든 수식어)
- 시간 표시 (초, 분, 시간, 일)
- impressiveGuy, namedMonster 패턴
This commit is contained in:
JiWoong Sul
2025-12-11 18:49:02 +09:00
parent d4acd3503b
commit 0216eb1261
3 changed files with 389 additions and 127 deletions

View File

@@ -1,5 +1,6 @@
import 'dart:math' as math;
import 'package:askiineverdie/data/game_text_l10n.dart' as l10n;
import 'package:askiineverdie/src/core/engine/game_mutations.dart';
import 'package:askiineverdie/src/core/engine/reward_service.dart';
import 'package:askiineverdie/src/core/model/game_state.dart';
@@ -37,48 +38,47 @@ class ProgressService {
/// 새 게임 초기화 (원본 GoButtonClick, Main.pas:741-767)
/// Prologue 태스크들을 큐에 추가하고 첫 태스크 시작
GameState initializeNewGame(GameState state) {
// 초기 큐 설정 - 아스키나라(ASCII-Nara) 세계관 프롤로그
// 초기 큐 설정 - 아스키나라(ASCII-Nara) 세계관 프롤로그 (l10n 지원)
final prologueTexts = l10n.prologueTexts;
final initialQueue = <QueueEntry>[
const QueueEntry(
QueueEntry(
kind: QueueKind.task,
durationMillis: 10 * 1000,
caption: 'Receiving an ominous vision from the Code God',
caption: prologueTexts[0],
taskType: TaskType.load,
),
const QueueEntry(
QueueEntry(
kind: QueueKind.task,
durationMillis: 6 * 1000,
caption:
'The old Compiler Sage reveals a prophecy: '
'"The Glitch God has awakened"',
caption: prologueTexts[1],
taskType: TaskType.load,
),
const QueueEntry(
QueueEntry(
kind: QueueKind.task,
durationMillis: 6 * 1000,
caption:
'A sudden Buffer Overflow resets your village, '
'leaving you as the sole survivor',
caption: prologueTexts[2],
taskType: TaskType.load,
),
const QueueEntry(
QueueEntry(
kind: QueueKind.task,
durationMillis: 4 * 1000,
caption:
'With unexpected resolve, you embark on a perilous journey '
'to the Null Kingdom',
caption: prologueTexts[3],
taskType: TaskType.load,
),
const QueueEntry(
QueueEntry(
kind: QueueKind.plot,
durationMillis: 2 * 1000,
caption: 'Compiling',
caption: l10n.taskCompiling,
taskType: TaskType.plot,
),
];
// 첫 번째 태스크 시작 (원본 752줄)
final taskResult = pq_logic.startTask(state.progress, 'Compiling', 2 * 1000);
final taskResult = pq_logic.startTask(
state.progress,
l10n.taskCompiling,
2 * 1000,
);
// ExpBar 초기화 (원본 743-746줄)
final expBar = ProgressBarState(position: 0, max: pq_logic.levelUpTime(1));
@@ -89,10 +89,13 @@ class ProgressService {
final progress = taskResult.progress.copyWith(
exp: expBar,
plot: plotBar,
currentTask: const TaskInfo(caption: 'Compiling...', type: TaskType.load),
currentTask: TaskInfo(
caption: '${l10n.taskCompiling}...',
type: TaskType.load,
),
plotStageCount: 1, // Prologue
questCount: 0,
plotHistory: const [HistoryEntry(caption: 'Prologue', isComplete: false)],
plotHistory: [HistoryEntry(caption: l10n.taskPrologue, isComplete: false)],
questHistory: const [],
);
@@ -295,7 +298,7 @@ class ProgressService {
progress.encumbrance.max > 0) {
final taskResult = pq_logic.startTask(
progress,
'Heading to the Data Market to trade loot',
l10n.taskHeadingToMarket(),
4 * 1000,
);
progress = taskResult.progress.copyWith(
@@ -316,7 +319,7 @@ class ProgressService {
if (gold > equipPrice) {
final taskResult = pq_logic.startTask(
progress,
'Upgrading hardware at the Tech Shop',
l10n.taskUpgradingHardware(),
5 * 1000,
);
progress = taskResult.progress.copyWith(
@@ -331,7 +334,7 @@ class ProgressService {
// Gold가 부족하면 전장으로 이동 (원본 674-676줄)
final taskResult = pq_logic.startTask(
progress,
'Entering the Debug Zone',
l10n.taskEnteringDebugZone(),
4 * 1000,
);
progress = taskResult.progress.copyWith(
@@ -370,7 +373,7 @@ class ProgressService {
final taskResult = pq_logic.startTask(
progress,
'Debugging ${monsterResult.displayName}',
l10n.taskDebugging(monsterResult.displayName),
durationMillis,
);
@@ -711,9 +714,10 @@ class ProgressService {
if (hasItemsToSell) {
// 다음 아이템 판매 태스크 시작
final nextItem = items.first;
final itemDesc = l10n.indefiniteL10n(nextItem.name, nextItem.count);
final taskResult = pq_logic.startTask(
state.progress,
'Selling ${pq_logic.indefinite(nextItem.name, nextItem.count)}',
l10n.taskSelling(itemDesc),
1 * 1000,
);
final progress = taskResult.progress.copyWith(