feat(l10n): 국제화(L10n) 시스템 도입 및 하드코딩 텍스트 변환
- flutter_localizations 및 intl 패키지 추가 - l10n.yaml 설정 파일 및 app_ko.arb 메시지 파일 생성 - 모든 화면(app, front, game_play, new_character, save_picker)의 하드코딩 텍스트를 L10n 키로 변환 - 테스트 파일에 localizationsDelegates 추가하여 L10n 지원
This commit is contained in:
246
lib/l10n/app_en.arb
Normal file
246
lib/l10n/app_en.arb
Normal file
@@ -0,0 +1,246 @@
|
||||
{
|
||||
"@@locale": "en",
|
||||
|
||||
"appTitle": "Ascii Never Die",
|
||||
"@appTitle": { "description": "Application title" },
|
||||
|
||||
"tagNoNetwork": "No network",
|
||||
"@tagNoNetwork": { "description": "Tag indicating offline mode" },
|
||||
|
||||
"tagIdleRpg": "Idle RPG loop",
|
||||
"@tagIdleRpg": { "description": "Tag indicating idle RPG gameplay" },
|
||||
|
||||
"tagLocalSaves": "Local saves",
|
||||
"@tagLocalSaves": { "description": "Tag indicating local save support" },
|
||||
|
||||
"newCharacter": "New character",
|
||||
"@newCharacter": { "description": "New character button" },
|
||||
|
||||
"loadSave": "Load save",
|
||||
"@loadSave": { "description": "Load save button" },
|
||||
|
||||
"loadGame": "Load Game",
|
||||
"@loadGame": { "description": "Load game dialog title" },
|
||||
|
||||
"viewBuildPlan": "View build plan",
|
||||
"@viewBuildPlan": { "description": "View build plan button" },
|
||||
|
||||
"buildRoadmap": "Build roadmap",
|
||||
"@buildRoadmap": { "description": "Build roadmap section title" },
|
||||
|
||||
"techStack": "Tech stack",
|
||||
"@techStack": { "description": "Tech stack section title" },
|
||||
|
||||
"cancel": "Cancel",
|
||||
"@cancel": { "description": "Cancel button" },
|
||||
|
||||
"exitGame": "Exit Game",
|
||||
"@exitGame": { "description": "Exit game dialog title" },
|
||||
|
||||
"saveProgressQuestion": "Save your progress before leaving?",
|
||||
"@saveProgressQuestion": { "description": "Save progress confirmation message" },
|
||||
|
||||
"exitWithoutSaving": "Exit without saving",
|
||||
"@exitWithoutSaving": { "description": "Exit without saving button" },
|
||||
|
||||
"saveAndExit": "Save and Exit",
|
||||
"@saveAndExit": { "description": "Save and exit button" },
|
||||
|
||||
"progressQuestTitle": "Progress Quest - {name}",
|
||||
"@progressQuestTitle": {
|
||||
"description": "Game screen title with character name",
|
||||
"placeholders": {
|
||||
"name": { "type": "String" }
|
||||
}
|
||||
},
|
||||
|
||||
"levelUp": "Level Up",
|
||||
"@levelUp": { "description": "Level up tooltip" },
|
||||
|
||||
"completeQuest": "Complete Quest",
|
||||
"@completeQuest": { "description": "Complete quest tooltip" },
|
||||
|
||||
"completePlot": "Complete Plot",
|
||||
"@completePlot": { "description": "Complete plot tooltip" },
|
||||
|
||||
"characterSheet": "Character Sheet",
|
||||
"@characterSheet": { "description": "Character sheet panel title" },
|
||||
|
||||
"traits": "Traits",
|
||||
"@traits": { "description": "Traits section title" },
|
||||
|
||||
"stats": "Stats",
|
||||
"@stats": { "description": "Stats section title" },
|
||||
|
||||
"experience": "Experience",
|
||||
"@experience": { "description": "Experience section title" },
|
||||
|
||||
"xpNeededForNextLevel": "XP needed for next level",
|
||||
"@xpNeededForNextLevel": { "description": "XP needed tooltip" },
|
||||
|
||||
"spellBook": "Spell Book",
|
||||
"@spellBook": { "description": "Spell book section title" },
|
||||
|
||||
"noSpellsYet": "No spells yet",
|
||||
"@noSpellsYet": { "description": "Empty spell book message" },
|
||||
|
||||
"equipment": "Equipment",
|
||||
"@equipment": { "description": "Equipment panel title" },
|
||||
|
||||
"inventory": "Inventory",
|
||||
"@inventory": { "description": "Inventory panel title" },
|
||||
|
||||
"encumbrance": "Encumbrance",
|
||||
"@encumbrance": { "description": "Encumbrance section title" },
|
||||
|
||||
"plotDevelopment": "Plot Development",
|
||||
"@plotDevelopment": { "description": "Plot development panel title" },
|
||||
|
||||
"quests": "Quests",
|
||||
"@quests": { "description": "Quests panel title" },
|
||||
|
||||
"traitName": "Name",
|
||||
"@traitName": { "description": "Name trait label" },
|
||||
|
||||
"traitRace": "Race",
|
||||
"@traitRace": { "description": "Race trait label" },
|
||||
|
||||
"traitClass": "Class",
|
||||
"@traitClass": { "description": "Class trait label" },
|
||||
|
||||
"traitLevel": "Level",
|
||||
"@traitLevel": { "description": "Level trait label" },
|
||||
|
||||
"statStr": "STR",
|
||||
"@statStr": { "description": "Strength stat" },
|
||||
|
||||
"statCon": "CON",
|
||||
"@statCon": { "description": "Constitution stat" },
|
||||
|
||||
"statDex": "DEX",
|
||||
"@statDex": { "description": "Dexterity stat" },
|
||||
|
||||
"statInt": "INT",
|
||||
"@statInt": { "description": "Intelligence stat" },
|
||||
|
||||
"statWis": "WIS",
|
||||
"@statWis": { "description": "Wisdom stat" },
|
||||
|
||||
"statCha": "CHA",
|
||||
"@statCha": { "description": "Charisma stat" },
|
||||
|
||||
"statHpMax": "HP Max",
|
||||
"@statHpMax": { "description": "Max HP stat" },
|
||||
|
||||
"statMpMax": "MP Max",
|
||||
"@statMpMax": { "description": "Max MP stat" },
|
||||
|
||||
"equipWeapon": "Weapon",
|
||||
"@equipWeapon": { "description": "Weapon equipment slot" },
|
||||
|
||||
"equipShield": "Shield",
|
||||
"@equipShield": { "description": "Shield equipment slot" },
|
||||
|
||||
"equipHelm": "Helm",
|
||||
"@equipHelm": { "description": "Helm equipment slot" },
|
||||
|
||||
"equipHauberk": "Hauberk",
|
||||
"@equipHauberk": { "description": "Hauberk equipment slot" },
|
||||
|
||||
"equipBrassairts": "Brassairts",
|
||||
"@equipBrassairts": { "description": "Brassairts equipment slot" },
|
||||
|
||||
"equipVambraces": "Vambraces",
|
||||
"@equipVambraces": { "description": "Vambraces equipment slot" },
|
||||
|
||||
"equipGauntlets": "Gauntlets",
|
||||
"@equipGauntlets": { "description": "Gauntlets equipment slot" },
|
||||
|
||||
"equipGambeson": "Gambeson",
|
||||
"@equipGambeson": { "description": "Gambeson equipment slot" },
|
||||
|
||||
"equipCuisses": "Cuisses",
|
||||
"@equipCuisses": { "description": "Cuisses equipment slot" },
|
||||
|
||||
"equipGreaves": "Greaves",
|
||||
"@equipGreaves": { "description": "Greaves equipment slot" },
|
||||
|
||||
"equipSollerets": "Sollerets",
|
||||
"@equipSollerets": { "description": "Sollerets equipment slot" },
|
||||
|
||||
"gold": "Gold",
|
||||
"@gold": { "description": "Gold label" },
|
||||
|
||||
"goldAmount": "Gold: {amount}",
|
||||
"@goldAmount": {
|
||||
"description": "Gold with amount",
|
||||
"placeholders": {
|
||||
"amount": { "type": "int" }
|
||||
}
|
||||
},
|
||||
|
||||
"prologue": "Prologue",
|
||||
"@prologue": { "description": "Prologue plot stage" },
|
||||
|
||||
"actNumber": "Act {number}",
|
||||
"@actNumber": {
|
||||
"description": "Act with roman numeral",
|
||||
"placeholders": {
|
||||
"number": { "type": "String" }
|
||||
}
|
||||
},
|
||||
|
||||
"noActiveQuests": "No active quests",
|
||||
"@noActiveQuests": { "description": "Empty quests message" },
|
||||
|
||||
"questNumber": "Quest #{number}",
|
||||
"@questNumber": {
|
||||
"description": "Quest with number",
|
||||
"placeholders": {
|
||||
"number": { "type": "int" }
|
||||
}
|
||||
},
|
||||
|
||||
"welcomeMessage": "Welcome to Progress Quest!",
|
||||
"@welcomeMessage": { "description": "Welcome message in task progress panel" },
|
||||
|
||||
"noSavedGames": "No saved games found.",
|
||||
"@noSavedGames": { "description": "No saved games message" },
|
||||
|
||||
"loadError": "Failed to load save file: {error}",
|
||||
"@loadError": {
|
||||
"description": "Load error message",
|
||||
"placeholders": {
|
||||
"error": { "type": "String" }
|
||||
}
|
||||
},
|
||||
|
||||
"name": "Name",
|
||||
"@name": { "description": "Name label in character creation" },
|
||||
|
||||
"generateName": "Generate Name",
|
||||
"@generateName": { "description": "Generate name tooltip" },
|
||||
|
||||
"total": "Total",
|
||||
"@total": { "description": "Total label for stats" },
|
||||
|
||||
"unroll": "Unroll",
|
||||
"@unroll": { "description": "Unroll button" },
|
||||
|
||||
"roll": "Roll",
|
||||
"@roll": { "description": "Roll button" },
|
||||
|
||||
"race": "Race",
|
||||
"@race": { "description": "Race selection title" },
|
||||
|
||||
"classTitle": "Class",
|
||||
"@classTitle": { "description": "Class selection title" },
|
||||
|
||||
"percentComplete": "{percent}% complete",
|
||||
"@percentComplete": {
|
||||
"description": "Percentage complete",
|
||||
"placeholders": {
|
||||
"percent": { "type": "int" }
|
||||
}
|
||||
}
|
||||
}
|
||||
75
lib/l10n/app_ja.arb
Normal file
75
lib/l10n/app_ja.arb
Normal file
@@ -0,0 +1,75 @@
|
||||
{
|
||||
"@@locale": "ja",
|
||||
|
||||
"appTitle": "Ascii Never Die",
|
||||
"tagNoNetwork": "No network",
|
||||
"tagIdleRpg": "Idle RPG loop",
|
||||
"tagLocalSaves": "Local saves",
|
||||
"newCharacter": "New character",
|
||||
"loadSave": "Load save",
|
||||
"loadGame": "Load Game",
|
||||
"viewBuildPlan": "View build plan",
|
||||
"buildRoadmap": "Build roadmap",
|
||||
"techStack": "Tech stack",
|
||||
"cancel": "Cancel",
|
||||
"exitGame": "Exit Game",
|
||||
"saveProgressQuestion": "Save your progress before leaving?",
|
||||
"exitWithoutSaving": "Exit without saving",
|
||||
"saveAndExit": "Save and Exit",
|
||||
"progressQuestTitle": "Progress Quest - {name}",
|
||||
"levelUp": "Level Up",
|
||||
"completeQuest": "Complete Quest",
|
||||
"completePlot": "Complete Plot",
|
||||
"characterSheet": "Character Sheet",
|
||||
"traits": "Traits",
|
||||
"stats": "Stats",
|
||||
"experience": "Experience",
|
||||
"xpNeededForNextLevel": "XP needed for next level",
|
||||
"spellBook": "Spell Book",
|
||||
"noSpellsYet": "No spells yet",
|
||||
"equipment": "Equipment",
|
||||
"inventory": "Inventory",
|
||||
"encumbrance": "Encumbrance",
|
||||
"plotDevelopment": "Plot Development",
|
||||
"quests": "Quests",
|
||||
"traitName": "Name",
|
||||
"traitRace": "Race",
|
||||
"traitClass": "Class",
|
||||
"traitLevel": "Level",
|
||||
"statStr": "STR",
|
||||
"statCon": "CON",
|
||||
"statDex": "DEX",
|
||||
"statInt": "INT",
|
||||
"statWis": "WIS",
|
||||
"statCha": "CHA",
|
||||
"statHpMax": "HP Max",
|
||||
"statMpMax": "MP Max",
|
||||
"equipWeapon": "Weapon",
|
||||
"equipShield": "Shield",
|
||||
"equipHelm": "Helm",
|
||||
"equipHauberk": "Hauberk",
|
||||
"equipBrassairts": "Brassairts",
|
||||
"equipVambraces": "Vambraces",
|
||||
"equipGauntlets": "Gauntlets",
|
||||
"equipGambeson": "Gambeson",
|
||||
"equipCuisses": "Cuisses",
|
||||
"equipGreaves": "Greaves",
|
||||
"equipSollerets": "Sollerets",
|
||||
"gold": "Gold",
|
||||
"goldAmount": "Gold: {amount}",
|
||||
"prologue": "Prologue",
|
||||
"actNumber": "Act {number}",
|
||||
"noActiveQuests": "No active quests",
|
||||
"questNumber": "Quest #{number}",
|
||||
"welcomeMessage": "Welcome to Progress Quest!",
|
||||
"noSavedGames": "No saved games found.",
|
||||
"loadError": "Failed to load save file: {error}",
|
||||
"name": "Name",
|
||||
"generateName": "Generate Name",
|
||||
"total": "Total",
|
||||
"unroll": "Unroll",
|
||||
"roll": "Roll",
|
||||
"race": "Race",
|
||||
"classTitle": "Class",
|
||||
"percentComplete": "{percent}% complete"
|
||||
}
|
||||
75
lib/l10n/app_ko.arb
Normal file
75
lib/l10n/app_ko.arb
Normal file
@@ -0,0 +1,75 @@
|
||||
{
|
||||
"@@locale": "ko",
|
||||
|
||||
"appTitle": "Ascii Never Die",
|
||||
"tagNoNetwork": "No network",
|
||||
"tagIdleRpg": "Idle RPG loop",
|
||||
"tagLocalSaves": "Local saves",
|
||||
"newCharacter": "New character",
|
||||
"loadSave": "Load save",
|
||||
"loadGame": "Load Game",
|
||||
"viewBuildPlan": "View build plan",
|
||||
"buildRoadmap": "Build roadmap",
|
||||
"techStack": "Tech stack",
|
||||
"cancel": "Cancel",
|
||||
"exitGame": "Exit Game",
|
||||
"saveProgressQuestion": "Save your progress before leaving?",
|
||||
"exitWithoutSaving": "Exit without saving",
|
||||
"saveAndExit": "Save and Exit",
|
||||
"progressQuestTitle": "Progress Quest - {name}",
|
||||
"levelUp": "Level Up",
|
||||
"completeQuest": "Complete Quest",
|
||||
"completePlot": "Complete Plot",
|
||||
"characterSheet": "Character Sheet",
|
||||
"traits": "Traits",
|
||||
"stats": "Stats",
|
||||
"experience": "Experience",
|
||||
"xpNeededForNextLevel": "XP needed for next level",
|
||||
"spellBook": "Spell Book",
|
||||
"noSpellsYet": "No spells yet",
|
||||
"equipment": "Equipment",
|
||||
"inventory": "Inventory",
|
||||
"encumbrance": "Encumbrance",
|
||||
"plotDevelopment": "Plot Development",
|
||||
"quests": "Quests",
|
||||
"traitName": "Name",
|
||||
"traitRace": "Race",
|
||||
"traitClass": "Class",
|
||||
"traitLevel": "Level",
|
||||
"statStr": "STR",
|
||||
"statCon": "CON",
|
||||
"statDex": "DEX",
|
||||
"statInt": "INT",
|
||||
"statWis": "WIS",
|
||||
"statCha": "CHA",
|
||||
"statHpMax": "HP Max",
|
||||
"statMpMax": "MP Max",
|
||||
"equipWeapon": "Weapon",
|
||||
"equipShield": "Shield",
|
||||
"equipHelm": "Helm",
|
||||
"equipHauberk": "Hauberk",
|
||||
"equipBrassairts": "Brassairts",
|
||||
"equipVambraces": "Vambraces",
|
||||
"equipGauntlets": "Gauntlets",
|
||||
"equipGambeson": "Gambeson",
|
||||
"equipCuisses": "Cuisses",
|
||||
"equipGreaves": "Greaves",
|
||||
"equipSollerets": "Sollerets",
|
||||
"gold": "Gold",
|
||||
"goldAmount": "Gold: {amount}",
|
||||
"prologue": "Prologue",
|
||||
"actNumber": "Act {number}",
|
||||
"noActiveQuests": "No active quests",
|
||||
"questNumber": "Quest #{number}",
|
||||
"welcomeMessage": "Welcome to Progress Quest!",
|
||||
"noSavedGames": "No saved games found.",
|
||||
"loadError": "Failed to load save file: {error}",
|
||||
"name": "Name",
|
||||
"generateName": "Generate Name",
|
||||
"total": "Total",
|
||||
"unroll": "Unroll",
|
||||
"roll": "Roll",
|
||||
"race": "Race",
|
||||
"classTitle": "Class",
|
||||
"percentComplete": "{percent}% complete"
|
||||
}
|
||||
566
lib/l10n/app_localizations.dart
Normal file
566
lib/l10n/app_localizations.dart
Normal file
@@ -0,0 +1,566 @@
|
||||
import 'dart:async';
|
||||
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/widgets.dart';
|
||||
import 'package:flutter_localizations/flutter_localizations.dart';
|
||||
import 'package:intl/intl.dart' as intl;
|
||||
|
||||
import 'app_localizations_en.dart';
|
||||
import 'app_localizations_ja.dart';
|
||||
import 'app_localizations_ko.dart';
|
||||
import 'app_localizations_zh.dart';
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
|
||||
/// Callers can lookup localized strings with an instance of L10n
|
||||
/// returned by `L10n.of(context)`.
|
||||
///
|
||||
/// Applications need to include `L10n.delegate()` in their app's
|
||||
/// `localizationDelegates` list, and the locales they support in the app's
|
||||
/// `supportedLocales` list. For example:
|
||||
///
|
||||
/// ```dart
|
||||
/// import 'l10n/app_localizations.dart';
|
||||
///
|
||||
/// return MaterialApp(
|
||||
/// localizationsDelegates: L10n.localizationsDelegates,
|
||||
/// supportedLocales: L10n.supportedLocales,
|
||||
/// home: MyApplicationHome(),
|
||||
/// );
|
||||
/// ```
|
||||
///
|
||||
/// ## Update pubspec.yaml
|
||||
///
|
||||
/// Please make sure to update your pubspec.yaml to include the following
|
||||
/// packages:
|
||||
///
|
||||
/// ```yaml
|
||||
/// dependencies:
|
||||
/// # Internationalization support.
|
||||
/// flutter_localizations:
|
||||
/// sdk: flutter
|
||||
/// intl: any # Use the pinned version from flutter_localizations
|
||||
///
|
||||
/// # Rest of dependencies
|
||||
/// ```
|
||||
///
|
||||
/// ## iOS Applications
|
||||
///
|
||||
/// iOS applications define key application metadata, including supported
|
||||
/// locales, in an Info.plist file that is built into the application bundle.
|
||||
/// To configure the locales supported by your app, you’ll need to edit this
|
||||
/// file.
|
||||
///
|
||||
/// First, open your project’s ios/Runner.xcworkspace Xcode workspace file.
|
||||
/// Then, in the Project Navigator, open the Info.plist file under the Runner
|
||||
/// project’s Runner folder.
|
||||
///
|
||||
/// Next, select the Information Property List item, select Add Item from the
|
||||
/// Editor menu, then select Localizations from the pop-up menu.
|
||||
///
|
||||
/// Select and expand the newly-created Localizations item then, for each
|
||||
/// locale your application supports, add a new item and select the locale
|
||||
/// you wish to add from the pop-up menu in the Value field. This list should
|
||||
/// be consistent with the languages listed in the L10n.supportedLocales
|
||||
/// property.
|
||||
abstract class L10n {
|
||||
L10n(String locale)
|
||||
: localeName = intl.Intl.canonicalizedLocale(locale.toString());
|
||||
|
||||
final String localeName;
|
||||
|
||||
static L10n of(BuildContext context) {
|
||||
return Localizations.of<L10n>(context, L10n)!;
|
||||
}
|
||||
|
||||
static const LocalizationsDelegate<L10n> delegate = _L10nDelegate();
|
||||
|
||||
/// A list of this localizations delegate along with the default localizations
|
||||
/// delegates.
|
||||
///
|
||||
/// Returns a list of localizations delegates containing this delegate along with
|
||||
/// GlobalMaterialLocalizations.delegate, GlobalCupertinoLocalizations.delegate,
|
||||
/// and GlobalWidgetsLocalizations.delegate.
|
||||
///
|
||||
/// Additional delegates can be added by appending to this list in
|
||||
/// MaterialApp. This list does not have to be used at all if a custom list
|
||||
/// of delegates is preferred or required.
|
||||
static const List<LocalizationsDelegate<dynamic>> localizationsDelegates =
|
||||
<LocalizationsDelegate<dynamic>>[
|
||||
delegate,
|
||||
GlobalMaterialLocalizations.delegate,
|
||||
GlobalCupertinoLocalizations.delegate,
|
||||
GlobalWidgetsLocalizations.delegate,
|
||||
];
|
||||
|
||||
/// A list of this localizations delegate's supported locales.
|
||||
static const List<Locale> supportedLocales = <Locale>[
|
||||
Locale('en'),
|
||||
Locale('ja'),
|
||||
Locale('ko'),
|
||||
Locale('zh'),
|
||||
];
|
||||
|
||||
/// Application title
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Ascii Never Die'**
|
||||
String get appTitle;
|
||||
|
||||
/// Tag indicating offline mode
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'No network'**
|
||||
String get tagNoNetwork;
|
||||
|
||||
/// Tag indicating idle RPG gameplay
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Idle RPG loop'**
|
||||
String get tagIdleRpg;
|
||||
|
||||
/// Tag indicating local save support
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Local saves'**
|
||||
String get tagLocalSaves;
|
||||
|
||||
/// New character button
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'New character'**
|
||||
String get newCharacter;
|
||||
|
||||
/// Load save button
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Load save'**
|
||||
String get loadSave;
|
||||
|
||||
/// Load game dialog title
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Load Game'**
|
||||
String get loadGame;
|
||||
|
||||
/// View build plan button
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'View build plan'**
|
||||
String get viewBuildPlan;
|
||||
|
||||
/// Build roadmap section title
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Build roadmap'**
|
||||
String get buildRoadmap;
|
||||
|
||||
/// Tech stack section title
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Tech stack'**
|
||||
String get techStack;
|
||||
|
||||
/// Cancel button
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Cancel'**
|
||||
String get cancel;
|
||||
|
||||
/// Exit game dialog title
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Exit Game'**
|
||||
String get exitGame;
|
||||
|
||||
/// Save progress confirmation message
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Save your progress before leaving?'**
|
||||
String get saveProgressQuestion;
|
||||
|
||||
/// Exit without saving button
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Exit without saving'**
|
||||
String get exitWithoutSaving;
|
||||
|
||||
/// Save and exit button
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Save and Exit'**
|
||||
String get saveAndExit;
|
||||
|
||||
/// Game screen title with character name
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Progress Quest - {name}'**
|
||||
String progressQuestTitle(String name);
|
||||
|
||||
/// Level up tooltip
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Level Up'**
|
||||
String get levelUp;
|
||||
|
||||
/// Complete quest tooltip
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Complete Quest'**
|
||||
String get completeQuest;
|
||||
|
||||
/// Complete plot tooltip
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Complete Plot'**
|
||||
String get completePlot;
|
||||
|
||||
/// Character sheet panel title
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Character Sheet'**
|
||||
String get characterSheet;
|
||||
|
||||
/// Traits section title
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Traits'**
|
||||
String get traits;
|
||||
|
||||
/// Stats section title
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Stats'**
|
||||
String get stats;
|
||||
|
||||
/// Experience section title
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Experience'**
|
||||
String get experience;
|
||||
|
||||
/// XP needed tooltip
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'XP needed for next level'**
|
||||
String get xpNeededForNextLevel;
|
||||
|
||||
/// Spell book section title
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Spell Book'**
|
||||
String get spellBook;
|
||||
|
||||
/// Empty spell book message
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'No spells yet'**
|
||||
String get noSpellsYet;
|
||||
|
||||
/// Equipment panel title
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Equipment'**
|
||||
String get equipment;
|
||||
|
||||
/// Inventory panel title
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Inventory'**
|
||||
String get inventory;
|
||||
|
||||
/// Encumbrance section title
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Encumbrance'**
|
||||
String get encumbrance;
|
||||
|
||||
/// Plot development panel title
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Plot Development'**
|
||||
String get plotDevelopment;
|
||||
|
||||
/// Quests panel title
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Quests'**
|
||||
String get quests;
|
||||
|
||||
/// Name trait label
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Name'**
|
||||
String get traitName;
|
||||
|
||||
/// Race trait label
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Race'**
|
||||
String get traitRace;
|
||||
|
||||
/// Class trait label
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Class'**
|
||||
String get traitClass;
|
||||
|
||||
/// Level trait label
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Level'**
|
||||
String get traitLevel;
|
||||
|
||||
/// Strength stat
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'STR'**
|
||||
String get statStr;
|
||||
|
||||
/// Constitution stat
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'CON'**
|
||||
String get statCon;
|
||||
|
||||
/// Dexterity stat
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'DEX'**
|
||||
String get statDex;
|
||||
|
||||
/// Intelligence stat
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'INT'**
|
||||
String get statInt;
|
||||
|
||||
/// Wisdom stat
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'WIS'**
|
||||
String get statWis;
|
||||
|
||||
/// Charisma stat
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'CHA'**
|
||||
String get statCha;
|
||||
|
||||
/// Max HP stat
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'HP Max'**
|
||||
String get statHpMax;
|
||||
|
||||
/// Max MP stat
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'MP Max'**
|
||||
String get statMpMax;
|
||||
|
||||
/// Weapon equipment slot
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Weapon'**
|
||||
String get equipWeapon;
|
||||
|
||||
/// Shield equipment slot
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Shield'**
|
||||
String get equipShield;
|
||||
|
||||
/// Helm equipment slot
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Helm'**
|
||||
String get equipHelm;
|
||||
|
||||
/// Hauberk equipment slot
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Hauberk'**
|
||||
String get equipHauberk;
|
||||
|
||||
/// Brassairts equipment slot
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Brassairts'**
|
||||
String get equipBrassairts;
|
||||
|
||||
/// Vambraces equipment slot
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Vambraces'**
|
||||
String get equipVambraces;
|
||||
|
||||
/// Gauntlets equipment slot
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Gauntlets'**
|
||||
String get equipGauntlets;
|
||||
|
||||
/// Gambeson equipment slot
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Gambeson'**
|
||||
String get equipGambeson;
|
||||
|
||||
/// Cuisses equipment slot
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Cuisses'**
|
||||
String get equipCuisses;
|
||||
|
||||
/// Greaves equipment slot
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Greaves'**
|
||||
String get equipGreaves;
|
||||
|
||||
/// Sollerets equipment slot
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Sollerets'**
|
||||
String get equipSollerets;
|
||||
|
||||
/// Gold label
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Gold'**
|
||||
String get gold;
|
||||
|
||||
/// Gold with amount
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Gold: {amount}'**
|
||||
String goldAmount(int amount);
|
||||
|
||||
/// Prologue plot stage
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Prologue'**
|
||||
String get prologue;
|
||||
|
||||
/// Act with roman numeral
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Act {number}'**
|
||||
String actNumber(String number);
|
||||
|
||||
/// Empty quests message
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'No active quests'**
|
||||
String get noActiveQuests;
|
||||
|
||||
/// Quest with number
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Quest #{number}'**
|
||||
String questNumber(int number);
|
||||
|
||||
/// Welcome message in task progress panel
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Welcome to Progress Quest!'**
|
||||
String get welcomeMessage;
|
||||
|
||||
/// No saved games message
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'No saved games found.'**
|
||||
String get noSavedGames;
|
||||
|
||||
/// Load error message
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Failed to load save file: {error}'**
|
||||
String loadError(String error);
|
||||
|
||||
/// Name label in character creation
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Name'**
|
||||
String get name;
|
||||
|
||||
/// Generate name tooltip
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Generate Name'**
|
||||
String get generateName;
|
||||
|
||||
/// Total label for stats
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Total'**
|
||||
String get total;
|
||||
|
||||
/// Unroll button
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Unroll'**
|
||||
String get unroll;
|
||||
|
||||
/// Roll button
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Roll'**
|
||||
String get roll;
|
||||
|
||||
/// Race selection title
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Race'**
|
||||
String get race;
|
||||
|
||||
/// Class selection title
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'Class'**
|
||||
String get classTitle;
|
||||
|
||||
/// Percentage complete
|
||||
///
|
||||
/// In en, this message translates to:
|
||||
/// **'{percent}% complete'**
|
||||
String percentComplete(int percent);
|
||||
}
|
||||
|
||||
class _L10nDelegate extends LocalizationsDelegate<L10n> {
|
||||
const _L10nDelegate();
|
||||
|
||||
@override
|
||||
Future<L10n> load(Locale locale) {
|
||||
return SynchronousFuture<L10n>(lookupL10n(locale));
|
||||
}
|
||||
|
||||
@override
|
||||
bool isSupported(Locale locale) =>
|
||||
<String>['en', 'ja', 'ko', 'zh'].contains(locale.languageCode);
|
||||
|
||||
@override
|
||||
bool shouldReload(_L10nDelegate old) => false;
|
||||
}
|
||||
|
||||
L10n lookupL10n(Locale locale) {
|
||||
// Lookup logic when only language code is specified.
|
||||
switch (locale.languageCode) {
|
||||
case 'en':
|
||||
return L10nEn();
|
||||
case 'ja':
|
||||
return L10nJa();
|
||||
case 'ko':
|
||||
return L10nKo();
|
||||
case 'zh':
|
||||
return L10nZh();
|
||||
}
|
||||
|
||||
throw FlutterError(
|
||||
'L10n.delegate failed to load unsupported locale "$locale". This is likely '
|
||||
'an issue with the localizations generation tool. Please file an issue '
|
||||
'on GitHub with a reproducible sample app and the gen-l10n configuration '
|
||||
'that was used.',
|
||||
);
|
||||
}
|
||||
235
lib/l10n/app_localizations_en.dart
Normal file
235
lib/l10n/app_localizations_en.dart
Normal file
@@ -0,0 +1,235 @@
|
||||
// ignore: unused_import
|
||||
import 'package:intl/intl.dart' as intl;
|
||||
import 'app_localizations.dart';
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
|
||||
/// The translations for English (`en`).
|
||||
class L10nEn extends L10n {
|
||||
L10nEn([String locale = 'en']) : super(locale);
|
||||
|
||||
@override
|
||||
String get appTitle => 'Ascii Never Die';
|
||||
|
||||
@override
|
||||
String get tagNoNetwork => 'No network';
|
||||
|
||||
@override
|
||||
String get tagIdleRpg => 'Idle RPG loop';
|
||||
|
||||
@override
|
||||
String get tagLocalSaves => 'Local saves';
|
||||
|
||||
@override
|
||||
String get newCharacter => 'New character';
|
||||
|
||||
@override
|
||||
String get loadSave => 'Load save';
|
||||
|
||||
@override
|
||||
String get loadGame => 'Load Game';
|
||||
|
||||
@override
|
||||
String get viewBuildPlan => 'View build plan';
|
||||
|
||||
@override
|
||||
String get buildRoadmap => 'Build roadmap';
|
||||
|
||||
@override
|
||||
String get techStack => 'Tech stack';
|
||||
|
||||
@override
|
||||
String get cancel => 'Cancel';
|
||||
|
||||
@override
|
||||
String get exitGame => 'Exit Game';
|
||||
|
||||
@override
|
||||
String get saveProgressQuestion => 'Save your progress before leaving?';
|
||||
|
||||
@override
|
||||
String get exitWithoutSaving => 'Exit without saving';
|
||||
|
||||
@override
|
||||
String get saveAndExit => 'Save and Exit';
|
||||
|
||||
@override
|
||||
String progressQuestTitle(String name) {
|
||||
return 'Progress Quest - $name';
|
||||
}
|
||||
|
||||
@override
|
||||
String get levelUp => 'Level Up';
|
||||
|
||||
@override
|
||||
String get completeQuest => 'Complete Quest';
|
||||
|
||||
@override
|
||||
String get completePlot => 'Complete Plot';
|
||||
|
||||
@override
|
||||
String get characterSheet => 'Character Sheet';
|
||||
|
||||
@override
|
||||
String get traits => 'Traits';
|
||||
|
||||
@override
|
||||
String get stats => 'Stats';
|
||||
|
||||
@override
|
||||
String get experience => 'Experience';
|
||||
|
||||
@override
|
||||
String get xpNeededForNextLevel => 'XP needed for next level';
|
||||
|
||||
@override
|
||||
String get spellBook => 'Spell Book';
|
||||
|
||||
@override
|
||||
String get noSpellsYet => 'No spells yet';
|
||||
|
||||
@override
|
||||
String get equipment => 'Equipment';
|
||||
|
||||
@override
|
||||
String get inventory => 'Inventory';
|
||||
|
||||
@override
|
||||
String get encumbrance => 'Encumbrance';
|
||||
|
||||
@override
|
||||
String get plotDevelopment => 'Plot Development';
|
||||
|
||||
@override
|
||||
String get quests => 'Quests';
|
||||
|
||||
@override
|
||||
String get traitName => 'Name';
|
||||
|
||||
@override
|
||||
String get traitRace => 'Race';
|
||||
|
||||
@override
|
||||
String get traitClass => 'Class';
|
||||
|
||||
@override
|
||||
String get traitLevel => 'Level';
|
||||
|
||||
@override
|
||||
String get statStr => 'STR';
|
||||
|
||||
@override
|
||||
String get statCon => 'CON';
|
||||
|
||||
@override
|
||||
String get statDex => 'DEX';
|
||||
|
||||
@override
|
||||
String get statInt => 'INT';
|
||||
|
||||
@override
|
||||
String get statWis => 'WIS';
|
||||
|
||||
@override
|
||||
String get statCha => 'CHA';
|
||||
|
||||
@override
|
||||
String get statHpMax => 'HP Max';
|
||||
|
||||
@override
|
||||
String get statMpMax => 'MP Max';
|
||||
|
||||
@override
|
||||
String get equipWeapon => 'Weapon';
|
||||
|
||||
@override
|
||||
String get equipShield => 'Shield';
|
||||
|
||||
@override
|
||||
String get equipHelm => 'Helm';
|
||||
|
||||
@override
|
||||
String get equipHauberk => 'Hauberk';
|
||||
|
||||
@override
|
||||
String get equipBrassairts => 'Brassairts';
|
||||
|
||||
@override
|
||||
String get equipVambraces => 'Vambraces';
|
||||
|
||||
@override
|
||||
String get equipGauntlets => 'Gauntlets';
|
||||
|
||||
@override
|
||||
String get equipGambeson => 'Gambeson';
|
||||
|
||||
@override
|
||||
String get equipCuisses => 'Cuisses';
|
||||
|
||||
@override
|
||||
String get equipGreaves => 'Greaves';
|
||||
|
||||
@override
|
||||
String get equipSollerets => 'Sollerets';
|
||||
|
||||
@override
|
||||
String get gold => 'Gold';
|
||||
|
||||
@override
|
||||
String goldAmount(int amount) {
|
||||
return 'Gold: $amount';
|
||||
}
|
||||
|
||||
@override
|
||||
String get prologue => 'Prologue';
|
||||
|
||||
@override
|
||||
String actNumber(String number) {
|
||||
return 'Act $number';
|
||||
}
|
||||
|
||||
@override
|
||||
String get noActiveQuests => 'No active quests';
|
||||
|
||||
@override
|
||||
String questNumber(int number) {
|
||||
return 'Quest #$number';
|
||||
}
|
||||
|
||||
@override
|
||||
String get welcomeMessage => 'Welcome to Progress Quest!';
|
||||
|
||||
@override
|
||||
String get noSavedGames => 'No saved games found.';
|
||||
|
||||
@override
|
||||
String loadError(String error) {
|
||||
return 'Failed to load save file: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get name => 'Name';
|
||||
|
||||
@override
|
||||
String get generateName => 'Generate Name';
|
||||
|
||||
@override
|
||||
String get total => 'Total';
|
||||
|
||||
@override
|
||||
String get unroll => 'Unroll';
|
||||
|
||||
@override
|
||||
String get roll => 'Roll';
|
||||
|
||||
@override
|
||||
String get race => 'Race';
|
||||
|
||||
@override
|
||||
String get classTitle => 'Class';
|
||||
|
||||
@override
|
||||
String percentComplete(int percent) {
|
||||
return '$percent% complete';
|
||||
}
|
||||
}
|
||||
235
lib/l10n/app_localizations_ja.dart
Normal file
235
lib/l10n/app_localizations_ja.dart
Normal file
@@ -0,0 +1,235 @@
|
||||
// ignore: unused_import
|
||||
import 'package:intl/intl.dart' as intl;
|
||||
import 'app_localizations.dart';
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
|
||||
/// The translations for Japanese (`ja`).
|
||||
class L10nJa extends L10n {
|
||||
L10nJa([String locale = 'ja']) : super(locale);
|
||||
|
||||
@override
|
||||
String get appTitle => 'Ascii Never Die';
|
||||
|
||||
@override
|
||||
String get tagNoNetwork => 'No network';
|
||||
|
||||
@override
|
||||
String get tagIdleRpg => 'Idle RPG loop';
|
||||
|
||||
@override
|
||||
String get tagLocalSaves => 'Local saves';
|
||||
|
||||
@override
|
||||
String get newCharacter => 'New character';
|
||||
|
||||
@override
|
||||
String get loadSave => 'Load save';
|
||||
|
||||
@override
|
||||
String get loadGame => 'Load Game';
|
||||
|
||||
@override
|
||||
String get viewBuildPlan => 'View build plan';
|
||||
|
||||
@override
|
||||
String get buildRoadmap => 'Build roadmap';
|
||||
|
||||
@override
|
||||
String get techStack => 'Tech stack';
|
||||
|
||||
@override
|
||||
String get cancel => 'Cancel';
|
||||
|
||||
@override
|
||||
String get exitGame => 'Exit Game';
|
||||
|
||||
@override
|
||||
String get saveProgressQuestion => 'Save your progress before leaving?';
|
||||
|
||||
@override
|
||||
String get exitWithoutSaving => 'Exit without saving';
|
||||
|
||||
@override
|
||||
String get saveAndExit => 'Save and Exit';
|
||||
|
||||
@override
|
||||
String progressQuestTitle(String name) {
|
||||
return 'Progress Quest - $name';
|
||||
}
|
||||
|
||||
@override
|
||||
String get levelUp => 'Level Up';
|
||||
|
||||
@override
|
||||
String get completeQuest => 'Complete Quest';
|
||||
|
||||
@override
|
||||
String get completePlot => 'Complete Plot';
|
||||
|
||||
@override
|
||||
String get characterSheet => 'Character Sheet';
|
||||
|
||||
@override
|
||||
String get traits => 'Traits';
|
||||
|
||||
@override
|
||||
String get stats => 'Stats';
|
||||
|
||||
@override
|
||||
String get experience => 'Experience';
|
||||
|
||||
@override
|
||||
String get xpNeededForNextLevel => 'XP needed for next level';
|
||||
|
||||
@override
|
||||
String get spellBook => 'Spell Book';
|
||||
|
||||
@override
|
||||
String get noSpellsYet => 'No spells yet';
|
||||
|
||||
@override
|
||||
String get equipment => 'Equipment';
|
||||
|
||||
@override
|
||||
String get inventory => 'Inventory';
|
||||
|
||||
@override
|
||||
String get encumbrance => 'Encumbrance';
|
||||
|
||||
@override
|
||||
String get plotDevelopment => 'Plot Development';
|
||||
|
||||
@override
|
||||
String get quests => 'Quests';
|
||||
|
||||
@override
|
||||
String get traitName => 'Name';
|
||||
|
||||
@override
|
||||
String get traitRace => 'Race';
|
||||
|
||||
@override
|
||||
String get traitClass => 'Class';
|
||||
|
||||
@override
|
||||
String get traitLevel => 'Level';
|
||||
|
||||
@override
|
||||
String get statStr => 'STR';
|
||||
|
||||
@override
|
||||
String get statCon => 'CON';
|
||||
|
||||
@override
|
||||
String get statDex => 'DEX';
|
||||
|
||||
@override
|
||||
String get statInt => 'INT';
|
||||
|
||||
@override
|
||||
String get statWis => 'WIS';
|
||||
|
||||
@override
|
||||
String get statCha => 'CHA';
|
||||
|
||||
@override
|
||||
String get statHpMax => 'HP Max';
|
||||
|
||||
@override
|
||||
String get statMpMax => 'MP Max';
|
||||
|
||||
@override
|
||||
String get equipWeapon => 'Weapon';
|
||||
|
||||
@override
|
||||
String get equipShield => 'Shield';
|
||||
|
||||
@override
|
||||
String get equipHelm => 'Helm';
|
||||
|
||||
@override
|
||||
String get equipHauberk => 'Hauberk';
|
||||
|
||||
@override
|
||||
String get equipBrassairts => 'Brassairts';
|
||||
|
||||
@override
|
||||
String get equipVambraces => 'Vambraces';
|
||||
|
||||
@override
|
||||
String get equipGauntlets => 'Gauntlets';
|
||||
|
||||
@override
|
||||
String get equipGambeson => 'Gambeson';
|
||||
|
||||
@override
|
||||
String get equipCuisses => 'Cuisses';
|
||||
|
||||
@override
|
||||
String get equipGreaves => 'Greaves';
|
||||
|
||||
@override
|
||||
String get equipSollerets => 'Sollerets';
|
||||
|
||||
@override
|
||||
String get gold => 'Gold';
|
||||
|
||||
@override
|
||||
String goldAmount(int amount) {
|
||||
return 'Gold: $amount';
|
||||
}
|
||||
|
||||
@override
|
||||
String get prologue => 'Prologue';
|
||||
|
||||
@override
|
||||
String actNumber(String number) {
|
||||
return 'Act $number';
|
||||
}
|
||||
|
||||
@override
|
||||
String get noActiveQuests => 'No active quests';
|
||||
|
||||
@override
|
||||
String questNumber(int number) {
|
||||
return 'Quest #$number';
|
||||
}
|
||||
|
||||
@override
|
||||
String get welcomeMessage => 'Welcome to Progress Quest!';
|
||||
|
||||
@override
|
||||
String get noSavedGames => 'No saved games found.';
|
||||
|
||||
@override
|
||||
String loadError(String error) {
|
||||
return 'Failed to load save file: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get name => 'Name';
|
||||
|
||||
@override
|
||||
String get generateName => 'Generate Name';
|
||||
|
||||
@override
|
||||
String get total => 'Total';
|
||||
|
||||
@override
|
||||
String get unroll => 'Unroll';
|
||||
|
||||
@override
|
||||
String get roll => 'Roll';
|
||||
|
||||
@override
|
||||
String get race => 'Race';
|
||||
|
||||
@override
|
||||
String get classTitle => 'Class';
|
||||
|
||||
@override
|
||||
String percentComplete(int percent) {
|
||||
return '$percent% complete';
|
||||
}
|
||||
}
|
||||
235
lib/l10n/app_localizations_ko.dart
Normal file
235
lib/l10n/app_localizations_ko.dart
Normal file
@@ -0,0 +1,235 @@
|
||||
// ignore: unused_import
|
||||
import 'package:intl/intl.dart' as intl;
|
||||
import 'app_localizations.dart';
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
|
||||
/// The translations for Korean (`ko`).
|
||||
class L10nKo extends L10n {
|
||||
L10nKo([String locale = 'ko']) : super(locale);
|
||||
|
||||
@override
|
||||
String get appTitle => 'Ascii Never Die';
|
||||
|
||||
@override
|
||||
String get tagNoNetwork => 'No network';
|
||||
|
||||
@override
|
||||
String get tagIdleRpg => 'Idle RPG loop';
|
||||
|
||||
@override
|
||||
String get tagLocalSaves => 'Local saves';
|
||||
|
||||
@override
|
||||
String get newCharacter => 'New character';
|
||||
|
||||
@override
|
||||
String get loadSave => 'Load save';
|
||||
|
||||
@override
|
||||
String get loadGame => 'Load Game';
|
||||
|
||||
@override
|
||||
String get viewBuildPlan => 'View build plan';
|
||||
|
||||
@override
|
||||
String get buildRoadmap => 'Build roadmap';
|
||||
|
||||
@override
|
||||
String get techStack => 'Tech stack';
|
||||
|
||||
@override
|
||||
String get cancel => 'Cancel';
|
||||
|
||||
@override
|
||||
String get exitGame => 'Exit Game';
|
||||
|
||||
@override
|
||||
String get saveProgressQuestion => 'Save your progress before leaving?';
|
||||
|
||||
@override
|
||||
String get exitWithoutSaving => 'Exit without saving';
|
||||
|
||||
@override
|
||||
String get saveAndExit => 'Save and Exit';
|
||||
|
||||
@override
|
||||
String progressQuestTitle(String name) {
|
||||
return 'Progress Quest - $name';
|
||||
}
|
||||
|
||||
@override
|
||||
String get levelUp => 'Level Up';
|
||||
|
||||
@override
|
||||
String get completeQuest => 'Complete Quest';
|
||||
|
||||
@override
|
||||
String get completePlot => 'Complete Plot';
|
||||
|
||||
@override
|
||||
String get characterSheet => 'Character Sheet';
|
||||
|
||||
@override
|
||||
String get traits => 'Traits';
|
||||
|
||||
@override
|
||||
String get stats => 'Stats';
|
||||
|
||||
@override
|
||||
String get experience => 'Experience';
|
||||
|
||||
@override
|
||||
String get xpNeededForNextLevel => 'XP needed for next level';
|
||||
|
||||
@override
|
||||
String get spellBook => 'Spell Book';
|
||||
|
||||
@override
|
||||
String get noSpellsYet => 'No spells yet';
|
||||
|
||||
@override
|
||||
String get equipment => 'Equipment';
|
||||
|
||||
@override
|
||||
String get inventory => 'Inventory';
|
||||
|
||||
@override
|
||||
String get encumbrance => 'Encumbrance';
|
||||
|
||||
@override
|
||||
String get plotDevelopment => 'Plot Development';
|
||||
|
||||
@override
|
||||
String get quests => 'Quests';
|
||||
|
||||
@override
|
||||
String get traitName => 'Name';
|
||||
|
||||
@override
|
||||
String get traitRace => 'Race';
|
||||
|
||||
@override
|
||||
String get traitClass => 'Class';
|
||||
|
||||
@override
|
||||
String get traitLevel => 'Level';
|
||||
|
||||
@override
|
||||
String get statStr => 'STR';
|
||||
|
||||
@override
|
||||
String get statCon => 'CON';
|
||||
|
||||
@override
|
||||
String get statDex => 'DEX';
|
||||
|
||||
@override
|
||||
String get statInt => 'INT';
|
||||
|
||||
@override
|
||||
String get statWis => 'WIS';
|
||||
|
||||
@override
|
||||
String get statCha => 'CHA';
|
||||
|
||||
@override
|
||||
String get statHpMax => 'HP Max';
|
||||
|
||||
@override
|
||||
String get statMpMax => 'MP Max';
|
||||
|
||||
@override
|
||||
String get equipWeapon => 'Weapon';
|
||||
|
||||
@override
|
||||
String get equipShield => 'Shield';
|
||||
|
||||
@override
|
||||
String get equipHelm => 'Helm';
|
||||
|
||||
@override
|
||||
String get equipHauberk => 'Hauberk';
|
||||
|
||||
@override
|
||||
String get equipBrassairts => 'Brassairts';
|
||||
|
||||
@override
|
||||
String get equipVambraces => 'Vambraces';
|
||||
|
||||
@override
|
||||
String get equipGauntlets => 'Gauntlets';
|
||||
|
||||
@override
|
||||
String get equipGambeson => 'Gambeson';
|
||||
|
||||
@override
|
||||
String get equipCuisses => 'Cuisses';
|
||||
|
||||
@override
|
||||
String get equipGreaves => 'Greaves';
|
||||
|
||||
@override
|
||||
String get equipSollerets => 'Sollerets';
|
||||
|
||||
@override
|
||||
String get gold => 'Gold';
|
||||
|
||||
@override
|
||||
String goldAmount(int amount) {
|
||||
return 'Gold: $amount';
|
||||
}
|
||||
|
||||
@override
|
||||
String get prologue => 'Prologue';
|
||||
|
||||
@override
|
||||
String actNumber(String number) {
|
||||
return 'Act $number';
|
||||
}
|
||||
|
||||
@override
|
||||
String get noActiveQuests => 'No active quests';
|
||||
|
||||
@override
|
||||
String questNumber(int number) {
|
||||
return 'Quest #$number';
|
||||
}
|
||||
|
||||
@override
|
||||
String get welcomeMessage => 'Welcome to Progress Quest!';
|
||||
|
||||
@override
|
||||
String get noSavedGames => 'No saved games found.';
|
||||
|
||||
@override
|
||||
String loadError(String error) {
|
||||
return 'Failed to load save file: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get name => 'Name';
|
||||
|
||||
@override
|
||||
String get generateName => 'Generate Name';
|
||||
|
||||
@override
|
||||
String get total => 'Total';
|
||||
|
||||
@override
|
||||
String get unroll => 'Unroll';
|
||||
|
||||
@override
|
||||
String get roll => 'Roll';
|
||||
|
||||
@override
|
||||
String get race => 'Race';
|
||||
|
||||
@override
|
||||
String get classTitle => 'Class';
|
||||
|
||||
@override
|
||||
String percentComplete(int percent) {
|
||||
return '$percent% complete';
|
||||
}
|
||||
}
|
||||
235
lib/l10n/app_localizations_zh.dart
Normal file
235
lib/l10n/app_localizations_zh.dart
Normal file
@@ -0,0 +1,235 @@
|
||||
// ignore: unused_import
|
||||
import 'package:intl/intl.dart' as intl;
|
||||
import 'app_localizations.dart';
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
|
||||
/// The translations for Chinese (`zh`).
|
||||
class L10nZh extends L10n {
|
||||
L10nZh([String locale = 'zh']) : super(locale);
|
||||
|
||||
@override
|
||||
String get appTitle => 'Ascii Never Die';
|
||||
|
||||
@override
|
||||
String get tagNoNetwork => 'No network';
|
||||
|
||||
@override
|
||||
String get tagIdleRpg => 'Idle RPG loop';
|
||||
|
||||
@override
|
||||
String get tagLocalSaves => 'Local saves';
|
||||
|
||||
@override
|
||||
String get newCharacter => 'New character';
|
||||
|
||||
@override
|
||||
String get loadSave => 'Load save';
|
||||
|
||||
@override
|
||||
String get loadGame => 'Load Game';
|
||||
|
||||
@override
|
||||
String get viewBuildPlan => 'View build plan';
|
||||
|
||||
@override
|
||||
String get buildRoadmap => 'Build roadmap';
|
||||
|
||||
@override
|
||||
String get techStack => 'Tech stack';
|
||||
|
||||
@override
|
||||
String get cancel => 'Cancel';
|
||||
|
||||
@override
|
||||
String get exitGame => 'Exit Game';
|
||||
|
||||
@override
|
||||
String get saveProgressQuestion => 'Save your progress before leaving?';
|
||||
|
||||
@override
|
||||
String get exitWithoutSaving => 'Exit without saving';
|
||||
|
||||
@override
|
||||
String get saveAndExit => 'Save and Exit';
|
||||
|
||||
@override
|
||||
String progressQuestTitle(String name) {
|
||||
return 'Progress Quest - $name';
|
||||
}
|
||||
|
||||
@override
|
||||
String get levelUp => 'Level Up';
|
||||
|
||||
@override
|
||||
String get completeQuest => 'Complete Quest';
|
||||
|
||||
@override
|
||||
String get completePlot => 'Complete Plot';
|
||||
|
||||
@override
|
||||
String get characterSheet => 'Character Sheet';
|
||||
|
||||
@override
|
||||
String get traits => 'Traits';
|
||||
|
||||
@override
|
||||
String get stats => 'Stats';
|
||||
|
||||
@override
|
||||
String get experience => 'Experience';
|
||||
|
||||
@override
|
||||
String get xpNeededForNextLevel => 'XP needed for next level';
|
||||
|
||||
@override
|
||||
String get spellBook => 'Spell Book';
|
||||
|
||||
@override
|
||||
String get noSpellsYet => 'No spells yet';
|
||||
|
||||
@override
|
||||
String get equipment => 'Equipment';
|
||||
|
||||
@override
|
||||
String get inventory => 'Inventory';
|
||||
|
||||
@override
|
||||
String get encumbrance => 'Encumbrance';
|
||||
|
||||
@override
|
||||
String get plotDevelopment => 'Plot Development';
|
||||
|
||||
@override
|
||||
String get quests => 'Quests';
|
||||
|
||||
@override
|
||||
String get traitName => 'Name';
|
||||
|
||||
@override
|
||||
String get traitRace => 'Race';
|
||||
|
||||
@override
|
||||
String get traitClass => 'Class';
|
||||
|
||||
@override
|
||||
String get traitLevel => 'Level';
|
||||
|
||||
@override
|
||||
String get statStr => 'STR';
|
||||
|
||||
@override
|
||||
String get statCon => 'CON';
|
||||
|
||||
@override
|
||||
String get statDex => 'DEX';
|
||||
|
||||
@override
|
||||
String get statInt => 'INT';
|
||||
|
||||
@override
|
||||
String get statWis => 'WIS';
|
||||
|
||||
@override
|
||||
String get statCha => 'CHA';
|
||||
|
||||
@override
|
||||
String get statHpMax => 'HP Max';
|
||||
|
||||
@override
|
||||
String get statMpMax => 'MP Max';
|
||||
|
||||
@override
|
||||
String get equipWeapon => 'Weapon';
|
||||
|
||||
@override
|
||||
String get equipShield => 'Shield';
|
||||
|
||||
@override
|
||||
String get equipHelm => 'Helm';
|
||||
|
||||
@override
|
||||
String get equipHauberk => 'Hauberk';
|
||||
|
||||
@override
|
||||
String get equipBrassairts => 'Brassairts';
|
||||
|
||||
@override
|
||||
String get equipVambraces => 'Vambraces';
|
||||
|
||||
@override
|
||||
String get equipGauntlets => 'Gauntlets';
|
||||
|
||||
@override
|
||||
String get equipGambeson => 'Gambeson';
|
||||
|
||||
@override
|
||||
String get equipCuisses => 'Cuisses';
|
||||
|
||||
@override
|
||||
String get equipGreaves => 'Greaves';
|
||||
|
||||
@override
|
||||
String get equipSollerets => 'Sollerets';
|
||||
|
||||
@override
|
||||
String get gold => 'Gold';
|
||||
|
||||
@override
|
||||
String goldAmount(int amount) {
|
||||
return 'Gold: $amount';
|
||||
}
|
||||
|
||||
@override
|
||||
String get prologue => 'Prologue';
|
||||
|
||||
@override
|
||||
String actNumber(String number) {
|
||||
return 'Act $number';
|
||||
}
|
||||
|
||||
@override
|
||||
String get noActiveQuests => 'No active quests';
|
||||
|
||||
@override
|
||||
String questNumber(int number) {
|
||||
return 'Quest #$number';
|
||||
}
|
||||
|
||||
@override
|
||||
String get welcomeMessage => 'Welcome to Progress Quest!';
|
||||
|
||||
@override
|
||||
String get noSavedGames => 'No saved games found.';
|
||||
|
||||
@override
|
||||
String loadError(String error) {
|
||||
return 'Failed to load save file: $error';
|
||||
}
|
||||
|
||||
@override
|
||||
String get name => 'Name';
|
||||
|
||||
@override
|
||||
String get generateName => 'Generate Name';
|
||||
|
||||
@override
|
||||
String get total => 'Total';
|
||||
|
||||
@override
|
||||
String get unroll => 'Unroll';
|
||||
|
||||
@override
|
||||
String get roll => 'Roll';
|
||||
|
||||
@override
|
||||
String get race => 'Race';
|
||||
|
||||
@override
|
||||
String get classTitle => 'Class';
|
||||
|
||||
@override
|
||||
String percentComplete(int percent) {
|
||||
return '$percent% complete';
|
||||
}
|
||||
}
|
||||
75
lib/l10n/app_zh.arb
Normal file
75
lib/l10n/app_zh.arb
Normal file
@@ -0,0 +1,75 @@
|
||||
{
|
||||
"@@locale": "zh",
|
||||
|
||||
"appTitle": "Ascii Never Die",
|
||||
"tagNoNetwork": "No network",
|
||||
"tagIdleRpg": "Idle RPG loop",
|
||||
"tagLocalSaves": "Local saves",
|
||||
"newCharacter": "New character",
|
||||
"loadSave": "Load save",
|
||||
"loadGame": "Load Game",
|
||||
"viewBuildPlan": "View build plan",
|
||||
"buildRoadmap": "Build roadmap",
|
||||
"techStack": "Tech stack",
|
||||
"cancel": "Cancel",
|
||||
"exitGame": "Exit Game",
|
||||
"saveProgressQuestion": "Save your progress before leaving?",
|
||||
"exitWithoutSaving": "Exit without saving",
|
||||
"saveAndExit": "Save and Exit",
|
||||
"progressQuestTitle": "Progress Quest - {name}",
|
||||
"levelUp": "Level Up",
|
||||
"completeQuest": "Complete Quest",
|
||||
"completePlot": "Complete Plot",
|
||||
"characterSheet": "Character Sheet",
|
||||
"traits": "Traits",
|
||||
"stats": "Stats",
|
||||
"experience": "Experience",
|
||||
"xpNeededForNextLevel": "XP needed for next level",
|
||||
"spellBook": "Spell Book",
|
||||
"noSpellsYet": "No spells yet",
|
||||
"equipment": "Equipment",
|
||||
"inventory": "Inventory",
|
||||
"encumbrance": "Encumbrance",
|
||||
"plotDevelopment": "Plot Development",
|
||||
"quests": "Quests",
|
||||
"traitName": "Name",
|
||||
"traitRace": "Race",
|
||||
"traitClass": "Class",
|
||||
"traitLevel": "Level",
|
||||
"statStr": "STR",
|
||||
"statCon": "CON",
|
||||
"statDex": "DEX",
|
||||
"statInt": "INT",
|
||||
"statWis": "WIS",
|
||||
"statCha": "CHA",
|
||||
"statHpMax": "HP Max",
|
||||
"statMpMax": "MP Max",
|
||||
"equipWeapon": "Weapon",
|
||||
"equipShield": "Shield",
|
||||
"equipHelm": "Helm",
|
||||
"equipHauberk": "Hauberk",
|
||||
"equipBrassairts": "Brassairts",
|
||||
"equipVambraces": "Vambraces",
|
||||
"equipGauntlets": "Gauntlets",
|
||||
"equipGambeson": "Gambeson",
|
||||
"equipCuisses": "Cuisses",
|
||||
"equipGreaves": "Greaves",
|
||||
"equipSollerets": "Sollerets",
|
||||
"gold": "Gold",
|
||||
"goldAmount": "Gold: {amount}",
|
||||
"prologue": "Prologue",
|
||||
"actNumber": "Act {number}",
|
||||
"noActiveQuests": "No active quests",
|
||||
"questNumber": "Quest #{number}",
|
||||
"welcomeMessage": "Welcome to Progress Quest!",
|
||||
"noSavedGames": "No saved games found.",
|
||||
"loadError": "Failed to load save file: {error}",
|
||||
"name": "Name",
|
||||
"generateName": "Generate Name",
|
||||
"total": "Total",
|
||||
"unroll": "Unroll",
|
||||
"roll": "Roll",
|
||||
"race": "Race",
|
||||
"classTitle": "Class",
|
||||
"percentComplete": "{percent}% complete"
|
||||
}
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:askiineverdie/l10n/app_localizations.dart';
|
||||
import 'package:askiineverdie/src/core/engine/game_mutations.dart';
|
||||
import 'package:askiineverdie/src/core/engine/progress_service.dart';
|
||||
import 'package:askiineverdie/src/core/engine/reward_service.dart';
|
||||
@@ -51,6 +52,8 @@ class _AskiiNeverDieAppState extends State<AskiiNeverDieApp> {
|
||||
return MaterialApp(
|
||||
title: 'Ascii Never Die',
|
||||
debugShowCheckedModeBanner: false,
|
||||
localizationsDelegates: L10n.localizationsDelegates,
|
||||
supportedLocales: L10n.supportedLocales,
|
||||
theme: ThemeData(
|
||||
colorScheme: ColorScheme.fromSeed(seedColor: const Color(0xFF234361)),
|
||||
scaffoldBackgroundColor: const Color(0xFFF4F5F7),
|
||||
@@ -85,9 +88,9 @@ class _AskiiNeverDieAppState extends State<AskiiNeverDieApp> {
|
||||
|
||||
if (saves.isEmpty) {
|
||||
// 저장 파일이 없으면 안내 메시지
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(const SnackBar(content: Text('저장된 게임이 없습니다.')));
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text(L10n.of(context).noSavedGames)),
|
||||
);
|
||||
return;
|
||||
} else if (saves.length == 1) {
|
||||
// 파일이 하나면 바로 선택
|
||||
@@ -114,7 +117,7 @@ class _AskiiNeverDieAppState extends State<AskiiNeverDieApp> {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text(
|
||||
'저장 파일을 불러올 수 없습니다: ${_controller.error ?? "알 수 없는 오류"}',
|
||||
L10n.of(context).loadError(_controller.error ?? 'Unknown error'),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:askiineverdie/l10n/app_localizations.dart';
|
||||
|
||||
class FrontScreen extends StatelessWidget {
|
||||
const FrontScreen({super.key, this.onNewCharacter, this.onLoadSave});
|
||||
|
||||
@@ -107,7 +109,7 @@ class _HeroHeader extends StatelessWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
'Ascii Never Die',
|
||||
L10n.of(context).appTitle,
|
||||
style: theme.textTheme.headlineSmall?.copyWith(
|
||||
color: colorScheme.onPrimary,
|
||||
fontWeight: FontWeight.w700,
|
||||
@@ -126,14 +128,19 @@ class _HeroHeader extends StatelessWidget {
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 14),
|
||||
Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: const [
|
||||
_Tag(icon: Icons.cloud_off_outlined, label: 'No network'),
|
||||
_Tag(icon: Icons.timer_outlined, label: 'Idle RPG loop'),
|
||||
_Tag(icon: Icons.storage_rounded, label: 'Local saves'),
|
||||
],
|
||||
Builder(
|
||||
builder: (context) {
|
||||
final l10n = L10n.of(context);
|
||||
return Wrap(
|
||||
spacing: 8,
|
||||
runSpacing: 8,
|
||||
children: [
|
||||
_Tag(icon: Icons.cloud_off_outlined, label: l10n.tagNoNetwork),
|
||||
_Tag(icon: Icons.timer_outlined, label: l10n.tagIdleRpg),
|
||||
_Tag(icon: Icons.storage_rounded, label: l10n.tagLocalSaves),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -151,6 +158,7 @@ class _ActionRow extends StatelessWidget {
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final l10n = L10n.of(context);
|
||||
|
||||
return Wrap(
|
||||
spacing: 12,
|
||||
@@ -159,7 +167,7 @@ class _ActionRow extends StatelessWidget {
|
||||
FilledButton.icon(
|
||||
onPressed: onNewCharacter,
|
||||
icon: const Icon(Icons.casino_outlined),
|
||||
label: const Text('New character'),
|
||||
label: Text(l10n.newCharacter),
|
||||
style: FilledButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 14),
|
||||
textStyle: theme.textTheme.titleMedium,
|
||||
@@ -168,7 +176,7 @@ class _ActionRow extends StatelessWidget {
|
||||
OutlinedButton.icon(
|
||||
onPressed: onLoadSave,
|
||||
icon: const Icon(Icons.folder_open),
|
||||
label: const Text('Load save'),
|
||||
label: Text(l10n.loadSave),
|
||||
style: OutlinedButton.styleFrom(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 18, vertical: 14),
|
||||
textStyle: theme.textTheme.titleMedium,
|
||||
@@ -177,7 +185,7 @@ class _ActionRow extends StatelessWidget {
|
||||
TextButton.icon(
|
||||
onPressed: () => _showPlaceholder(context),
|
||||
icon: const Icon(Icons.menu_book_outlined),
|
||||
label: const Text('View build plan'),
|
||||
label: Text(l10n.viewBuildPlan),
|
||||
),
|
||||
],
|
||||
);
|
||||
@@ -189,11 +197,12 @@ class _StatusCards extends StatelessWidget {
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final l10n = L10n.of(context);
|
||||
return Column(
|
||||
children: const [
|
||||
children: [
|
||||
_InfoCard(
|
||||
icon: Icons.route_outlined,
|
||||
title: 'Build roadmap',
|
||||
title: l10n.buildRoadmap,
|
||||
points: [
|
||||
'Port PQ 6.4 data set (Config.dfm) into Dart constants.',
|
||||
'Recreate quest/task loop with deterministic RNG + saves.',
|
||||
@@ -203,7 +212,7 @@ class _StatusCards extends StatelessWidget {
|
||||
SizedBox(height: 16),
|
||||
_InfoCard(
|
||||
icon: Icons.auto_fix_high_outlined,
|
||||
title: 'Tech stack',
|
||||
title: l10n.techStack,
|
||||
points: [
|
||||
'Flutter (Material 3) with multiplatform targets enabled.',
|
||||
'path_provider + shared_preferences for local storage hooks.',
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:intl/intl.dart';
|
||||
|
||||
import 'package:askiineverdie/l10n/app_localizations.dart';
|
||||
import 'package:askiineverdie/src/core/storage/save_service.dart'
|
||||
show SaveFileInfo;
|
||||
|
||||
@@ -20,7 +21,7 @@ class SavePickerDialog extends StatelessWidget {
|
||||
// 저장 파일이 없으면 안내 메시지
|
||||
ScaffoldMessenger.of(
|
||||
context,
|
||||
).showSnackBar(const SnackBar(content: Text('저장된 게임이 없습니다.')));
|
||||
).showSnackBar(SnackBar(content: Text(L10n.of(context).noSavedGames)));
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -35,12 +36,13 @@ class SavePickerDialog extends StatelessWidget {
|
||||
final theme = Theme.of(context);
|
||||
final colorScheme = theme.colorScheme;
|
||||
|
||||
final l10n = L10n.of(context);
|
||||
return AlertDialog(
|
||||
title: Row(
|
||||
children: [
|
||||
Icon(Icons.folder_open, color: colorScheme.primary),
|
||||
const SizedBox(width: 12),
|
||||
const Text('Load Game'),
|
||||
Text(l10n.loadGame),
|
||||
],
|
||||
),
|
||||
content: SizedBox(
|
||||
@@ -64,7 +66,7 @@ class SavePickerDialog extends StatelessWidget {
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(null),
|
||||
child: const Text('Cancel'),
|
||||
child: Text(l10n.cancel),
|
||||
),
|
||||
],
|
||||
);
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:askiineverdie/l10n/app_localizations.dart';
|
||||
import 'package:askiineverdie/src/core/animation/ascii_animation_data.dart';
|
||||
import 'package:askiineverdie/src/core/animation/ascii_animation_type.dart';
|
||||
import 'package:askiineverdie/src/core/model/game_state.dart';
|
||||
@@ -129,21 +130,22 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
||||
|
||||
/// 뒤로가기 시 저장 확인 다이얼로그
|
||||
Future<bool> _onPopInvoked() async {
|
||||
final l10n = L10n.of(context);
|
||||
final shouldPop = await showDialog<bool>(
|
||||
context: context,
|
||||
builder: (context) => AlertDialog(
|
||||
title: const Text('Exit Game'),
|
||||
content: const Text('Save your progress before leaving?'),
|
||||
title: Text(l10n.exitGame),
|
||||
content: Text(l10n.saveProgressQuestion),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed: () => Navigator.of(context).pop(false),
|
||||
child: const Text('Cancel'),
|
||||
child: Text(l10n.cancel),
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
Navigator.of(context).pop(true);
|
||||
},
|
||||
child: const Text('Exit without saving'),
|
||||
child: Text(l10n.exitWithoutSaving),
|
||||
),
|
||||
FilledButton(
|
||||
onPressed: () async {
|
||||
@@ -152,7 +154,7 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
||||
Navigator.of(context).pop(true);
|
||||
}
|
||||
},
|
||||
child: const Text('Save and Exit'),
|
||||
child: Text(l10n.saveAndExit),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -189,23 +191,23 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
||||
},
|
||||
child: Scaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('Progress Quest - ${state.traits.name}'),
|
||||
title: Text(L10n.of(context).progressQuestTitle(state.traits.name)),
|
||||
actions: [
|
||||
// 치트 버튼 (디버그용)
|
||||
if (widget.controller.cheatsEnabled) ...[
|
||||
IconButton(
|
||||
icon: const Text('L+1'),
|
||||
tooltip: 'Level Up',
|
||||
tooltip: L10n.of(context).levelUp,
|
||||
onPressed: () => widget.controller.loop?.cheatCompleteTask(),
|
||||
),
|
||||
IconButton(
|
||||
icon: const Text('Q!'),
|
||||
tooltip: 'Complete Quest',
|
||||
tooltip: L10n.of(context).completeQuest,
|
||||
onPressed: () => widget.controller.loop?.cheatCompleteQuest(),
|
||||
),
|
||||
IconButton(
|
||||
icon: const Text('P!'),
|
||||
tooltip: 'Complete Plot',
|
||||
tooltip: L10n.of(context).completePlot,
|
||||
onPressed: () => widget.controller.loop?.cheatCompletePlot(),
|
||||
),
|
||||
],
|
||||
@@ -250,34 +252,35 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
||||
|
||||
/// 좌측 패널: Character Sheet (Traits, Stats, Experience, Spells)
|
||||
Widget _buildCharacterPanel(GameState state) {
|
||||
final l10n = L10n.of(context);
|
||||
return Card(
|
||||
margin: const EdgeInsets.all(4),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
_buildPanelHeader('Character Sheet'),
|
||||
_buildPanelHeader(l10n.characterSheet),
|
||||
|
||||
// Traits 목록
|
||||
_buildSectionHeader('Traits'),
|
||||
_buildSectionHeader(l10n.traits),
|
||||
_buildTraitsList(state),
|
||||
|
||||
// Stats 목록
|
||||
_buildSectionHeader('Stats'),
|
||||
_buildSectionHeader(l10n.stats),
|
||||
Expanded(flex: 2, child: _buildStatsList(state)),
|
||||
|
||||
// Experience 바
|
||||
_buildSectionHeader('Experience'),
|
||||
_buildSectionHeader(l10n.experience),
|
||||
_buildProgressBar(
|
||||
state.progress.exp.position,
|
||||
state.progress.exp.max,
|
||||
Colors.blue,
|
||||
tooltip:
|
||||
'${state.progress.exp.max - state.progress.exp.position} '
|
||||
'XP needed for next level',
|
||||
'${l10n.xpNeededForNextLevel}',
|
||||
),
|
||||
|
||||
// Spell Book
|
||||
_buildSectionHeader('Spell Book'),
|
||||
_buildSectionHeader(l10n.spellBook),
|
||||
Expanded(flex: 2, child: _buildSpellsList(state)),
|
||||
],
|
||||
),
|
||||
@@ -286,22 +289,23 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
||||
|
||||
/// 중앙 패널: Equipment/Inventory
|
||||
Widget _buildEquipmentPanel(GameState state) {
|
||||
final l10n = L10n.of(context);
|
||||
return Card(
|
||||
margin: const EdgeInsets.all(4),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
_buildPanelHeader('Equipment'),
|
||||
_buildPanelHeader(l10n.equipment),
|
||||
|
||||
// Equipment 목록
|
||||
Expanded(flex: 2, child: _buildEquipmentList(state)),
|
||||
|
||||
// Inventory
|
||||
_buildPanelHeader('Inventory'),
|
||||
_buildPanelHeader(l10n.inventory),
|
||||
Expanded(flex: 3, child: _buildInventoryList(state)),
|
||||
|
||||
// Encumbrance 바
|
||||
_buildSectionHeader('Encumbrance'),
|
||||
_buildSectionHeader(l10n.encumbrance),
|
||||
_buildProgressBar(
|
||||
state.progress.encumbrance.position,
|
||||
state.progress.encumbrance.max,
|
||||
@@ -314,12 +318,13 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
||||
|
||||
/// 우측 패널: Plot/Quest
|
||||
Widget _buildQuestPanel(GameState state) {
|
||||
final l10n = L10n.of(context);
|
||||
return Card(
|
||||
margin: const EdgeInsets.all(4),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
_buildPanelHeader('Plot Development'),
|
||||
_buildPanelHeader(l10n.plotDevelopment),
|
||||
|
||||
// Plot 목록
|
||||
Expanded(child: _buildPlotList(state)),
|
||||
@@ -334,7 +339,7 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
||||
: null,
|
||||
),
|
||||
|
||||
_buildPanelHeader('Quests'),
|
||||
_buildPanelHeader(l10n.quests),
|
||||
|
||||
// Quest 목록
|
||||
Expanded(child: _buildQuestList(state)),
|
||||
@@ -345,7 +350,10 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
||||
state.progress.quest.max,
|
||||
Colors.green,
|
||||
tooltip: state.progress.quest.max > 0
|
||||
? '${(100 * state.progress.quest.position ~/ state.progress.quest.max)}% complete'
|
||||
? l10n.percentComplete(
|
||||
100 * state.progress.quest.position ~/
|
||||
state.progress.quest.max,
|
||||
)
|
||||
: null,
|
||||
),
|
||||
],
|
||||
@@ -398,11 +406,12 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
||||
}
|
||||
|
||||
Widget _buildTraitsList(GameState state) {
|
||||
final l10n = L10n.of(context);
|
||||
final traits = [
|
||||
('Name', state.traits.name),
|
||||
('Race', state.traits.race),
|
||||
('Class', state.traits.klass),
|
||||
('Level', '${state.traits.level}'),
|
||||
(l10n.traitName, state.traits.name),
|
||||
(l10n.traitRace, state.traits.race),
|
||||
(l10n.traitClass, state.traits.klass),
|
||||
(l10n.traitLevel, '${state.traits.level}'),
|
||||
];
|
||||
|
||||
return Padding(
|
||||
@@ -433,15 +442,16 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
||||
}
|
||||
|
||||
Widget _buildStatsList(GameState state) {
|
||||
final l10n = L10n.of(context);
|
||||
final stats = [
|
||||
('STR', state.stats.str),
|
||||
('CON', state.stats.con),
|
||||
('DEX', state.stats.dex),
|
||||
('INT', state.stats.intelligence),
|
||||
('WIS', state.stats.wis),
|
||||
('CHA', state.stats.cha),
|
||||
('HP Max', state.stats.hpMax),
|
||||
('MP Max', state.stats.mpMax),
|
||||
(l10n.statStr, state.stats.str),
|
||||
(l10n.statCon, state.stats.con),
|
||||
(l10n.statDex, state.stats.dex),
|
||||
(l10n.statInt, state.stats.intelligence),
|
||||
(l10n.statWis, state.stats.wis),
|
||||
(l10n.statCha, state.stats.cha),
|
||||
(l10n.statHpMax, state.stats.hpMax),
|
||||
(l10n.statMpMax, state.stats.mpMax),
|
||||
];
|
||||
|
||||
return ListView.builder(
|
||||
@@ -467,8 +477,8 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
||||
|
||||
Widget _buildSpellsList(GameState state) {
|
||||
if (state.spellBook.spells.isEmpty) {
|
||||
return const Center(
|
||||
child: Text('No spells yet', style: TextStyle(fontSize: 11)),
|
||||
return Center(
|
||||
child: Text(L10n.of(context).noSpellsYet, style: const TextStyle(fontSize: 11)),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -498,18 +508,19 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
||||
|
||||
Widget _buildEquipmentList(GameState state) {
|
||||
// 원본 Main.dfm Equips ListView - 11개 슬롯
|
||||
final l10n = L10n.of(context);
|
||||
final equipment = [
|
||||
('Weapon', state.equipment.weapon),
|
||||
('Shield', state.equipment.shield),
|
||||
('Helm', state.equipment.helm),
|
||||
('Hauberk', state.equipment.hauberk),
|
||||
('Brassairts', state.equipment.brassairts),
|
||||
('Vambraces', state.equipment.vambraces),
|
||||
('Gauntlets', state.equipment.gauntlets),
|
||||
('Gambeson', state.equipment.gambeson),
|
||||
('Cuisses', state.equipment.cuisses),
|
||||
('Greaves', state.equipment.greaves),
|
||||
('Sollerets', state.equipment.sollerets),
|
||||
(l10n.equipWeapon, state.equipment.weapon),
|
||||
(l10n.equipShield, state.equipment.shield),
|
||||
(l10n.equipHelm, state.equipment.helm),
|
||||
(l10n.equipHauberk, state.equipment.hauberk),
|
||||
(l10n.equipBrassairts, state.equipment.brassairts),
|
||||
(l10n.equipVambraces, state.equipment.vambraces),
|
||||
(l10n.equipGauntlets, state.equipment.gauntlets),
|
||||
(l10n.equipGambeson, state.equipment.gambeson),
|
||||
(l10n.equipCuisses, state.equipment.cuisses),
|
||||
(l10n.equipGreaves, state.equipment.greaves),
|
||||
(l10n.equipSollerets, state.equipment.sollerets),
|
||||
];
|
||||
|
||||
return ListView.builder(
|
||||
@@ -543,10 +554,11 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
||||
}
|
||||
|
||||
Widget _buildInventoryList(GameState state) {
|
||||
final l10n = L10n.of(context);
|
||||
if (state.inventory.items.isEmpty) {
|
||||
return Center(
|
||||
child: Text(
|
||||
'Gold: ${state.inventory.gold}',
|
||||
l10n.goldAmount(state.inventory.gold),
|
||||
style: const TextStyle(fontSize: 11),
|
||||
),
|
||||
);
|
||||
@@ -559,8 +571,8 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
||||
if (index == 0) {
|
||||
return Row(
|
||||
children: [
|
||||
const Expanded(
|
||||
child: Text('Gold', style: TextStyle(fontSize: 11)),
|
||||
Expanded(
|
||||
child: Text(l10n.gold, style: const TextStyle(fontSize: 11)),
|
||||
),
|
||||
Text(
|
||||
'${state.inventory.gold}',
|
||||
@@ -594,10 +606,11 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
||||
|
||||
Widget _buildPlotList(GameState state) {
|
||||
// 플롯 단계를 표시 (Act I, Act II, ...)
|
||||
final l10n = L10n.of(context);
|
||||
final plotCount = state.progress.plotStageCount;
|
||||
if (plotCount == 0) {
|
||||
return const Center(
|
||||
child: Text('Prologue', style: TextStyle(fontSize: 11)),
|
||||
return Center(
|
||||
child: Text(l10n.prologue, style: const TextStyle(fontSize: 11)),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -615,7 +628,7 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
||||
),
|
||||
const SizedBox(width: 4),
|
||||
Text(
|
||||
index == 0 ? 'Prologue' : 'Act ${_toRoman(index)}',
|
||||
index == 0 ? l10n.prologue : l10n.actNumber(_toRoman(index)),
|
||||
style: TextStyle(
|
||||
fontSize: 11,
|
||||
decoration: isCompleted
|
||||
@@ -630,10 +643,11 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
||||
}
|
||||
|
||||
Widget _buildQuestList(GameState state) {
|
||||
final l10n = L10n.of(context);
|
||||
final questCount = state.progress.questCount;
|
||||
if (questCount == 0) {
|
||||
return const Center(
|
||||
child: Text('No active quests', style: TextStyle(fontSize: 11)),
|
||||
return Center(
|
||||
child: Text(l10n.noActiveQuests, style: const TextStyle(fontSize: 11)),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -649,7 +663,7 @@ class _GamePlayScreenState extends State<GamePlayScreen>
|
||||
child: Text(
|
||||
currentTask.caption.isNotEmpty
|
||||
? currentTask.caption
|
||||
: 'Quest #$questCount',
|
||||
: l10n.questNumber(questCount),
|
||||
style: const TextStyle(fontSize: 11),
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:askiineverdie/l10n/app_localizations.dart';
|
||||
import 'package:askiineverdie/src/core/animation/ascii_animation_data.dart';
|
||||
import 'package:askiineverdie/src/core/animation/ascii_animation_type.dart';
|
||||
import 'package:askiineverdie/src/core/model/game_state.dart';
|
||||
@@ -60,7 +61,7 @@ class TaskProgressPanel extends StatelessWidget {
|
||||
child: Text(
|
||||
progress.currentTask.caption.isNotEmpty
|
||||
? progress.currentTask.caption
|
||||
: 'Welcome to Progress Quest!',
|
||||
: L10n.of(context).welcomeMessage,
|
||||
style: Theme.of(context).textTheme.bodyMedium,
|
||||
textAlign: TextAlign.center,
|
||||
),
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'dart:math' as math;
|
||||
|
||||
import 'package:flutter/material.dart';
|
||||
|
||||
import 'package:askiineverdie/l10n/app_localizations.dart';
|
||||
import 'package:askiineverdie/src/core/model/game_state.dart';
|
||||
import 'package:askiineverdie/src/core/model/pq_config.dart';
|
||||
import 'package:askiineverdie/src/core/util/deterministic_random.dart';
|
||||
@@ -241,6 +242,7 @@ class _NewCharacterScreenState extends State<NewCharacterScreen> {
|
||||
}
|
||||
|
||||
Widget _buildNameSection() {
|
||||
final l10n = L10n.of(context);
|
||||
return Card(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
@@ -249,9 +251,9 @@ class _NewCharacterScreenState extends State<NewCharacterScreen> {
|
||||
Expanded(
|
||||
child: TextField(
|
||||
controller: _nameController,
|
||||
decoration: const InputDecoration(
|
||||
labelText: 'Name',
|
||||
border: OutlineInputBorder(),
|
||||
decoration: InputDecoration(
|
||||
labelText: l10n.name,
|
||||
border: const OutlineInputBorder(),
|
||||
),
|
||||
maxLength: 30,
|
||||
),
|
||||
@@ -260,7 +262,7 @@ class _NewCharacterScreenState extends State<NewCharacterScreen> {
|
||||
IconButton.filled(
|
||||
onPressed: _onGenerateName,
|
||||
icon: const Icon(Icons.casino),
|
||||
tooltip: 'Generate Name',
|
||||
tooltip: l10n.generateName,
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -269,29 +271,30 @@ class _NewCharacterScreenState extends State<NewCharacterScreen> {
|
||||
}
|
||||
|
||||
Widget _buildStatsSection() {
|
||||
final l10n = L10n.of(context);
|
||||
return Card(
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('Stats', style: Theme.of(context).textTheme.titleMedium),
|
||||
Text(l10n.stats, style: Theme.of(context).textTheme.titleMedium),
|
||||
const SizedBox(height: 12),
|
||||
|
||||
// 스탯 그리드
|
||||
Row(
|
||||
children: [
|
||||
Expanded(child: _buildStatTile('STR', _str)),
|
||||
Expanded(child: _buildStatTile('CON', _con)),
|
||||
Expanded(child: _buildStatTile('DEX', _dex)),
|
||||
Expanded(child: _buildStatTile(l10n.statStr, _str)),
|
||||
Expanded(child: _buildStatTile(l10n.statCon, _con)),
|
||||
Expanded(child: _buildStatTile(l10n.statDex, _dex)),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 8),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(child: _buildStatTile('INT', _int)),
|
||||
Expanded(child: _buildStatTile('WIS', _wis)),
|
||||
Expanded(child: _buildStatTile('CHA', _cha)),
|
||||
Expanded(child: _buildStatTile(l10n.statInt, _int)),
|
||||
Expanded(child: _buildStatTile(l10n.statWis, _wis)),
|
||||
Expanded(child: _buildStatTile(l10n.statCha, _cha)),
|
||||
],
|
||||
),
|
||||
const SizedBox(height: 12),
|
||||
@@ -307,9 +310,9 @@ class _NewCharacterScreenState extends State<NewCharacterScreen> {
|
||||
child: Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
const Text(
|
||||
'Total',
|
||||
style: TextStyle(fontWeight: FontWeight.bold),
|
||||
Text(
|
||||
l10n.total,
|
||||
style: const TextStyle(fontWeight: FontWeight.bold),
|
||||
),
|
||||
Text(
|
||||
'$_total',
|
||||
@@ -333,7 +336,7 @@ class _NewCharacterScreenState extends State<NewCharacterScreen> {
|
||||
OutlinedButton.icon(
|
||||
onPressed: _onUnroll,
|
||||
icon: const Icon(Icons.undo),
|
||||
label: const Text('Unroll'),
|
||||
label: Text(l10n.unroll),
|
||||
style: OutlinedButton.styleFrom(
|
||||
foregroundColor: _rollHistory.isEmpty ? Colors.grey : null,
|
||||
),
|
||||
@@ -342,7 +345,7 @@ class _NewCharacterScreenState extends State<NewCharacterScreen> {
|
||||
FilledButton.icon(
|
||||
onPressed: _onReroll,
|
||||
icon: const Icon(Icons.casino),
|
||||
label: const Text('Roll'),
|
||||
label: Text(l10n.roll),
|
||||
),
|
||||
],
|
||||
),
|
||||
@@ -389,7 +392,7 @@ class _NewCharacterScreenState extends State<NewCharacterScreen> {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('Race', style: Theme.of(context).textTheme.titleMedium),
|
||||
Text(L10n.of(context).race, style: Theme.of(context).textTheme.titleMedium),
|
||||
const SizedBox(height: 8),
|
||||
SizedBox(
|
||||
height: 300,
|
||||
@@ -434,7 +437,7 @@ class _NewCharacterScreenState extends State<NewCharacterScreen> {
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('Class', style: Theme.of(context).textTheme.titleMedium),
|
||||
Text(L10n.of(context).classTitle, style: Theme.of(context).textTheme.titleMedium),
|
||||
const SizedBox(height: 8),
|
||||
SizedBox(
|
||||
height: 300,
|
||||
|
||||
Reference in New Issue
Block a user