From 18a09882b874904e0d0288ca879f23345761cf80 Mon Sep 17 00:00:00 2001 From: Storm Dragon Date: Fri, 27 Feb 2026 23:55:31 -0500 Subject: [PATCH] Translation updates. Almost done I think. --- draugnorak.nvgt | 61 ++- .../validate_i18n_catalog.cpython-314.pyc | Bin 0 -> 7966 bytes scripts/audit_untranslated_strings.py | 2 +- scripts/generate_i18n_catalog.py | 489 +++++++++++++++++- scripts/validate_i18n_catalog.py | 8 +- sounds/dialog.ogg | 3 + src/base_system.nvgt | 173 +++---- src/bosses/adventure_system.nvgt | 16 +- src/bosses/bandit_hideout.nvgt | 28 +- src/bosses/unicorn/unicorn_boss.nvgt | 55 +- src/constants.nvgt | 2 +- src/crafting/craft_barricade.nvgt | 72 +-- src/crafting/craft_buildings.nvgt | 52 +- src/crafting/craft_clothing.nvgt | 44 +- src/crafting/craft_materials.nvgt | 72 +-- src/crafting/craft_runes.nvgt | 51 +- src/crafting/craft_tools.nvgt | 50 +- src/crafting/craft_weapons.nvgt | 26 +- src/crafting/crafting_core.nvgt | 4 +- src/enemies/bandit.nvgt | 6 +- src/enemies/undead.nvgt | 8 +- src/environment.nvgt | 51 +- src/fishing.nvgt | 45 +- src/flying_creature_template.nvgt | 2 +- src/fylgja_system.nvgt | 34 +- src/i18n.nvgt | 14 +- src/intro.nvgt | 84 +++ src/inventory_items.nvgt | 22 +- src/learn_sounds.nvgt | 2 +- src/menus/action_menu.nvgt | 124 +++-- src/menus/altar_menu.nvgt | 49 +- src/menus/base_info.nvgt | 16 +- src/menus/equipment_menu.nvgt | 32 +- src/menus/menu_utils.nvgt | 10 +- src/menus/storage_menu.nvgt | 57 +- src/pet_system.nvgt | 101 ++-- src/quest_system.nvgt | 80 +-- src/quests/bat_invasion_game.nvgt | 6 +- src/quests/catch_the_boomerang_game.nvgt | 45 +- src/quests/enchanted_melody_game.nvgt | 9 +- src/quests/escape_from_hel_game.nvgt | 4 +- src/quests/skeletal_bard_game.nvgt | 16 +- src/save_system.nvgt | 4 +- src/time_system.nvgt | 89 ++-- src/world/world_fires.nvgt | 10 +- src/world/world_snares.nvgt | 16 +- 46 files changed, 1542 insertions(+), 602 deletions(-) create mode 100644 scripts/__pycache__/validate_i18n_catalog.cpython-314.pyc create mode 100644 sounds/dialog.ogg create mode 100644 src/intro.nvgt diff --git a/draugnorak.nvgt b/draugnorak.nvgt index 77fb196..10a43de 100644 --- a/draugnorak.nvgt +++ b/draugnorak.nvgt @@ -45,6 +45,7 @@ sound_pool p(300); #include "src/text_reader_aliases.nvgt" #include "src/notify_compat.nvgt" #include "src/learn_sounds.nvgt" +#include "src/intro.nvgt" #include "src/bosses/adventure_system.nvgt" const string MAIN_MENU_MUSIC_TRACK = "sounds/menu/Draugnorak.ogg; loop; f=1"; @@ -54,8 +55,9 @@ music_manager mainMenuMusic; const int MAIN_MENU_NEW_GAME = 0; const int MAIN_MENU_LOAD_GAME = 1; -const int MAIN_MENU_LEARN_SOUNDS = 2; -const int MAIN_MENU_EXIT = 3; +const int MAIN_MENU_STORY = 2; +const int MAIN_MENU_LEARN_SOUNDS = 3; +const int MAIN_MENU_EXIT = 4; void start_main_menu_music() { menu_music_resume_or_play(mainMenuMusic, MAIN_MENU_MUSIC_TRACK, MAIN_MENU_MUSIC_FADE_IN_MS); @@ -67,7 +69,7 @@ void stop_main_menu_music() { int run_main_menu() { start_main_menu_music(); - speak_with_history("Draugnorak. Main menu.", true); + speak_with_history(tr("system.main_menu.prompt"), true); int selection = 0; string load_label = has_save_game() ? i18n_text("Load Game") : i18n_text("Load Game (no saves found)"); @@ -86,6 +88,11 @@ int run_main_menu() { entry_types.insert_last(0); action_ids.insert_last(MAIN_MENU_LOAD_GAME); + options.insert_last(tr("system.menu.main.story")); + entry_paths.insert_last(""); + entry_types.insert_last(0); + action_ids.insert_last(MAIN_MENU_STORY); + options.insert_last(i18n_text("Learn Sounds")); entry_paths.insert_last(""); entry_types.insert_last(0); @@ -180,11 +187,11 @@ void run_game() { continue; } start_new_game(); - speak_with_history("New game started.", true); + speak_with_history(tr("system.game.new_game_started"), true); game_started = true; } else if (selection == MAIN_MENU_LOAD_GAME) { if (!has_save_game()) { - ui_info_box("Draugnorak", "Load Game", "No saves found."); + ui_info_box(tr("system.ui.window_title"), i18n_text("Load Game"), tr("system.load_game.no_saves_found")); continue; } string selectedFile; @@ -192,14 +199,17 @@ void run_game() { continue; } if (load_game_state_from_file(selectedFile)) { - speak_with_history("Game loaded.", true); + speak_with_history(tr("system.game.loaded"), true); game_started = true; } else { string message = last_save_error; if (message == "") - message = "Unable to load save."; - ui_info_box("Draugnorak", "Load Game", message); + message = tr("system.load_game.unable_to_load"); + ui_info_box(tr("system.ui.window_title"), i18n_text("Load Game"), message); } + } else if (selection == MAIN_MENU_STORY) { + run_story_dialog(); + continue; } else if (selection == MAIN_MENU_LEARN_SOUNDS) { run_learn_sounds_menu(); continue; @@ -226,12 +236,12 @@ void run_game() { game_paused = !game_paused; if (game_paused) { p.pause_all(); - speak_with_history("Paused. Press backspace to resume.", true); + speak_with_history(tr("system.game.paused_prompt"), true); } else { p.resume_all(); // Restart all timers to prevent time from accumulating while paused restart_all_timers(); - speak_with_history("Resumed.", true); + speak_with_history(tr("system.game.resumed"), true); } continue; } @@ -244,7 +254,7 @@ void run_game() { check_pet_call_key(); if (key_pressed(KEY_ESCAPE)) { - int really_exit = ui_question("", "Really exit?"); + int really_exit = ui_question("", tr("system.exit.confirm")); if (really_exit == 1) { return_to_main_menu_requested = true; continue; @@ -274,7 +284,9 @@ void run_game() { if (fire_on_tile != null && !jumping && fire_damage_timer.elapsed > 1000) { player_health--; fire_damage_timer.restart(); - speak_with_history("Burning! " + player_health + " health remaining.", true); + dictionary burningArgs; + burningArgs.set("health", player_health); + speak_with_history(trf("system.combat.burning", burningArgs), true); } // Healing in base area @@ -286,14 +298,16 @@ void run_game() { if (healing_timer.elapsed > heal_interval) { player_health++; healing_timer.restart(); - speak_with_history(player_health + " health.", true); + dictionary healthArgs; + healthArgs.set("health", player_health); + speak_with_history(trf("system.combat.health_status", healthArgs), true); } } // Death check if (player_health <= 0) { if (!try_consume_heal_scroll()) { - speak_with_history("You have died.", true); + speak_with_history(tr("system.combat.you_died"), true); wait(2000); return_to_main_menu_requested = true; continue; @@ -326,12 +340,19 @@ void run_game() { // Coordinates Key if (key_pressed(KEY_X)) { - string direction_label = (facing == 1) ? "east" : "west"; - string terrain = get_terrain_at_position(x); + string direction_label = (facing == 1) ? tr("system.direction.east") : tr("system.direction.west"); + string terrain = i18n_translate_fragment_value(get_terrain_at_position(x)); if (get_mountain_at(x) !is null) { - terrain += ". Mountains"; + dictionary terrainArgs; + terrainArgs.set("terrain", terrain); + terrain = trf("system.character.report.terrain_mountains", terrainArgs); } - speak_with_history(direction_label + ", x " + x + ", y " + y + ", terrain " + terrain, true); + dictionary positionArgs; + positionArgs.set("direction", direction_label); + positionArgs.set("x", x); + positionArgs.set("y", y); + positionArgs.set("terrain", terrain); + speak_with_history(trf("system.character.report.position", positionArgs), true); } // Base Info Key (base only) @@ -415,14 +436,14 @@ void run_game() { // Movement Logic if (key_pressed(KEY_LEFT) && facing != 0 && !climbing && !falling && !rope_climbing) { facing = 0; - speak_with_history("west", true); + speak_with_history(tr("system.direction.west"), true); walktimer.restart(); // Cancel pending rope climb when changing direction pending_rope_climb_x = -1; } if (key_pressed(KEY_RIGHT) && facing != 1 && !climbing && !falling && !rope_climbing) { facing = 1; - speak_with_history("east", true); + speak_with_history(tr("system.direction.east"), true); walktimer.restart(); // Cancel pending rope climb when changing direction pending_rope_climb_x = -1; diff --git a/scripts/__pycache__/validate_i18n_catalog.cpython-314.pyc b/scripts/__pycache__/validate_i18n_catalog.cpython-314.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b536219442d8399a9818a3fc497d7cb201329f67 GIT binary patch literal 7966 zcmdPqO5n^h9 zB!osLO`x0rDJTPpieuD45-s72DGTvedNG!?FWVyxSl9^m`i^V6ixa1adaB9gd){xSIoYY$^If;4czxY%0^h#25 z3vv=mQuQ+PGOL7Rsx_h$b*mh8qYQK{<72foV``H@feykTt3c7p%)r3-S%Co*tzist zOcpH+3@OYYPXsb%Fa|LOF$FOPvFI}?Gib8DWMW`oxW!VCSdvi$(t3-nD7B=tDDM{^ z$X(IJB}F<4#U(|tD;YEyZ?UE27v(0F6oc$ix@E1Ok)NBYUtE%3l&hbfS)!j(lvtXc zmtT~atzVp6lvz+xtY4OxlbMoOk{X|BXptA6oLG{Wlb^0vPAx{h?wB=0YuG+1M@zEJP7tJhylW^3=9ll-)>?8`8J55fKi{J zfGLb20OUrH3M35ixjD$k3=9kb%t%sDCM+Ta7+e|MbQl;4n8TO@Kz2aoVH8YV0ZSN* zI#e(n9Kzmm3=Cl`0qjsgBr1pnmOS7(BtUV3Lp3Y9YDf%v`{6X74MT@6)O=1PXF!>V zOagOFiWo$79AgkSBLiMvGkQ;CUHyRS_cV-P1e3k!k7g1Ew1Eg4`g z4q^3W3uEMA0EzN27%>;H`>H_rMoa}9VXWBVFpL8ujKQ%U!s^Q!#=*l7#>&HB#8ki@ z!wd6$7(7^%)pA8RQtkK>3g77DE+lX-S%{#Vz)t)PkJE zK7j`J8?y2ZZVyBxru$9wTj9RLbAsPx5x46iffq#ruZskCaNOV*@2~5uyUZ`&!E&Ep z_$H6Y4Q~E^`%e2A#@D&!FLBE+Fj;QD(0+sQb!GEQ%H~+)U6%VU^xdF*UB&E@irEb@ zsTqbdf+l2L7gM_^rgm9Oqr?3skH`aVz6mKk_8{G&lGCFmMlE1o5O`Tsy_2hh`39e0 ze`aT9cXkK!4FS>V+!MJc^LDV_=NG!kBl4VI?1s2hr^gLmkr`Z9c$IF*DJ}?}lQpq; zgZKu{9fCWIcc@;_bLjMVprAgZas}gz*bcuNa*FfwX6CJkyDn#QNzP_s@qxGtE+H2} zBQAtQUT}))@VFzbyCU_nv`Gis6%L7y#tfn%j33Mxc!U~!i$oY07{KKstkeS)<=}FW zKrO%ot_4_%co-NMiu6Fy!dzTZRKy433NSD*XfhTFg34u(xk})81DDlc0u*cT0$Y+% z;v<73qr{Bl4n<)ll1z1%W11ytS2r)3EoCamx za3VOh7*ailM0w!;328bwB1VmwV z!yX2P6k*)91Ti9P@huAn*#j~Picwt662=n51TK#7nTO`tx$r-np z^D0V;K@~B$5P>8_4NxKl5#WS)5Zv6kAu8VBe1n6t!SMzccTe&J)$Xhwy&Jqjy%8Nu zH@JBxi1b+9;NkE0>hzjW)Z=%9hj)TtuUm&BIH&V;6!w}*Bm#vHO z0XJ{Id8hdV<8GS^EaHg#0?Q5X{6ZijLz{Dmj9g?43La2KuHpzzEdjOUVv7i6Xt zJmAVRBR?l4wWzqrgMono>={r$q=DfMH{TV0rR)4!7x}eTm|o^Lyv%KMfyD^n7g%t! z!P=85V87sQJqNJ{vFS4_Gib7dgZvgtQetsx5vUD&i@PMTC_S|#9^R$~7pGNf;C6j9 zsG$#z3>^h*Ou}#O<6#|P9-=4aIV$iUC2H^c7(h}t0nrY<;TfJGtxgU12`0|Tf# z2#zaI+%zyC;tG*%3z%ZyE#nwa+=62;i~(DF2-XgU#UPS;CSug=aco>2h5WWtBR}nl6L5xV^@D?x+gAr22 z;~fQQ)rOmdu^NN&1ydEbl|pJoL27bIYKlS?hmJy8eraBcf+icdxp#}LIKQYQHKoWE z)aYQzPOXGw+9F#}wZK{A1uDI~L2_)6>~xDgH?z1H)Fx(4ttcrE+ds)Nks;JdvKI;beJ3K;D zj3<;$ubx;vx%RR!NRi8W&y}95y)SE6Totys%wyT$dP7C+0*lxae$gq(GgRhl&eWW( zeOXLxjqr-F_0cP%SI1t~w7x24eU0CygZYk(#tM9uTu`#z5pg8#f^WiQx5NvsNf!i? zzcDlM@_poF5U~9qz`!GXL0b0$x9$ZNT}Yt;N|YcBN_?OK1YBsyfP(;gp{UQO%%I5( zE)2ot-7V(Kyb^*HPBN%41NHtvg_$9v+(!mOM!Ak;Fa>c4$N?}6>Q#ds(!t8W&;UxW zFd2pbkR#zd2qOq(PzluYD`1ELRj6QTeB~3oFDVLY_#yIG5EDW_sHX?Zhw=<@Ov(%~ z@O*_(1yfPLi0BgrF^eFQjUycP-X~X zD_{;|5@2v;a+76XC}4>J1vS{3a1nT)oEg+7FJMRNRcnJx4P%4bq73GE(0=8o*{%CNetX$muCoJLx`nt zK-7gXz+9q*s5LmkIAEeFVDo}F3Ydv-BPX&OeIFCFI%^HU8PLh7uQ&IecMU1mhoWJ|vXV zVJ`ZI;v(c!fTROoSh+HJD?n0P7&AP7fycb!7?l}7WsIgs6_2iNd16tXF1TX0dI_pG z{QRoKeIXUL0;oP#fQ@2XDS!tmz}W)Q*k&*W4OfFId?f~Xh6aWZ1~*9thC;yrm>MKH zhzT_02yM)Wf``}8Zq~?1Jw*g(V+GOsI>_i zde2MD1r4(?=^20rxr#w5)SyiOPMh@9ywr+4sP&<5lboNDY6sG#spnS3Vx{2k9a6<+ zrQqi1=>wv}9fSO;1QZlt!3=6cDQHwNXCcon3tkZ z#j22-UzA$Kr=Z{pYDp@FTbxdg z!LIRco<6R(*itJpi%W`cu@)48+6tgq1+KAk@_(3j<2PeAt{Jfk>aHH`SA1Lrj6Vp@U!C`xg4dm9;6mU!zfznhF zs5w^@1Ts!IBe6I>DJMTUJ2NjGr4h*rX;Fe|bWqqqF{G8q0!kM}d7v>jP)cwBPd(fa zQ(42jo?|7)2BEb)7sX5({GV`(T<4a)$Sr-HTlNyS>>Uo?3j*qEI2Tl3;4{9$VRDmS z;0d?Ll*r56@(nIeM5QlEm#v9dAGbVKL`G3zS=Huw4EmX}{Q_q-z@dO-@t~v?AFnBOiz_}pt+b@H2sAwg>W|-IDoQO%1SMK_(7-}YW)gJ1uB5Uc zGcUae)Kf144PO+2TFFJAvIk@yC=bNPgC-Y>^K;5lZ?P977NzEu6yIVA^7juZN&^*( zphoyD_T>EBg3O%MA~%o_I4^?6*1#hvkPHY)@E{{WrDuHnEtb@ZOh^MC?087l;IPTf zPbtkwwJWM-U|;}M1jQ2=7#Kbn?-DeFn|T44MzwxjQ_X>#noQ zUSyZO%r1YOUHu}v`U=LY>{<;hH@NvHsP)=5aNOV#xgf4_l}Dq2^M;tj^sGr)7ZlAe zi&?Bt}sj9U}10fX!7U` R=?=TbBJz=$fkg`JVgPn%?FIk< literal 0 HcmV?d00001 diff --git a/scripts/audit_untranslated_strings.py b/scripts/audit_untranslated_strings.py index e3c9f99..356411f 100755 --- a/scripts/audit_untranslated_strings.py +++ b/scripts/audit_untranslated_strings.py @@ -68,7 +68,7 @@ class Finding: def iter_nvgt_files() -> List[Path]: files: List[Path] = [] - entrypoints = [ROOT / "draugnorak.nvgt", ROOT / "excluded_sounds.nvgt"] + entrypoints = [ROOT / "draugnorak.nvgt", ROOT / "src" / "sound_settings.nvgt"] for entry in entrypoints: if entry.exists(): files.append(entry) diff --git a/scripts/generate_i18n_catalog.py b/scripts/generate_i18n_catalog.py index dd23352..5920395 100644 --- a/scripts/generate_i18n_catalog.py +++ b/scripts/generate_i18n_catalog.py @@ -51,7 +51,7 @@ SKIP_FILE_NAMES = {"crash.log"} def iter_nvgt_files() -> List[Path]: files: List[Path] = [] - entrypoints = [ROOT / "draugnorak.nvgt", ROOT / "excluded_sounds.nvgt"] + entrypoints = [ROOT / "draugnorak.nvgt", ROOT / "src" / "sound_settings.nvgt"] for entry in entrypoints: if entry.exists(): files.append(entry) @@ -449,6 +449,14 @@ def write_catalog(entries: Dict[str, Dict[str, object]], output_path: Path) -> N ("system.language.selected", "Language set to {language}."), ("system.language.english_label", "English (en)"), ("system.ui.window_title", "Draugnorak"), + ("system.main_menu.prompt", "Draugnorak. Main menu."), + ("system.game.new_game_started", "New game started."), + ("system.game.loaded", "Game loaded."), + ("system.game.paused_prompt", "Paused. Press backspace to resume."), + ("system.game.resumed", "Resumed."), + ("system.exit.confirm", "Really exit?"), + ("system.direction.west", "west"), + ("system.direction.east", "east"), ("system.sex.male", "Male"), ("system.sex.female", "Female"), ("system.new_character.choose_sex", "Choose your sex."), @@ -460,11 +468,16 @@ def write_catalog(entries: Dict[str, Dict[str, object]], output_path: Path) -> N "Are you sure you want to delete the character {name} gender {sex} days {day}?"), ("system.load_game.delete_save_heading", "Delete Save"), ("system.load_game.delete_save_failed", "Unable to delete save."), + ("system.load_game.save_deleted", "Save deleted."), + ("system.load_game.no_saves_found", "No saves found."), + ("system.load_game.unable_to_load", "Unable to load save."), + ("system.load_game.select_prompt", "Load game. Select character. Press delete to remove a save."), ("system.quick_slot.no_item_bound", "No item bound to slot {slot}."), ("system.menu.closed", "Closed."), ("system.menu.canceled", "Canceled."), ("system.menu.no_options", "No options."), ("system.menu.no_matches", "No matches for {arg1}."), + ("system.menu.main.story", "The story"), ("system.option.no", "No"), ("system.option.yes", "Yes"), ("system.inventory.cant_carry_any_more_item", "You can't carry any more {item}."), @@ -474,9 +487,146 @@ def write_catalog(entries: Dict[str, Dict[str, object]], output_path: Path) -> N ("system.inventory.option.base_storage", "Base storage"), ("system.inventory.count_set_to_slot", "{name} count set to slot {slot}."), ("system.inventory.need_quiver_for_arrows", "You need a quiver to carry arrows."), + ("system.inventory.max_arrows_with_quivers", "You can only carry {max} arrows with your current quivers."), + ("system.inventory.item_not_available", "Item not available."), ("system.search.found_item", "Found {item}."), ("system.search.found_nothing", "Found nothing."), ("system.pickup.item", "Picked up {item}."), + ("system.time.period.am", "am"), + ("system.time.period.pm", "pm"), + ("system.time.report", "{hour} oclock {period} day {day}"), + ("system.time.report_with_conditions", "{time}. {conditions}"), + ("system.time.condition.sunny", "Sunny"), + ("system.time.condition.daylight", "Daylight"), + ("system.time.condition.dark", "Dark"), + ("system.time.condition.windy", "Windy"), + ("system.time.condition.raining", "Raining"), + ("system.time.condition.storming", "Storming"), + ("system.time.condition.moon_and_stars", "Moon and stars"), + ("system.time.event.area_expanded", "The area has expanded! New territory discovered to the east."), + ("system.time.event.mountain_discovered", "A mountain range has been discovered to the east!"), + ("system.time.event.invasion_source_mountains", "the mountains"), + ("system.time.event.invasion_source_new_area", "the new area"), + ("system.time.event.invasion_start", "{enemy_plural} are invading from {source}!"), + ("system.time.event.zombie_swarm_spotted", "A swarm of zombies has been spotted."), + ("system.time.event.survivor_joins_one", "A survivor joins your base."), + ("system.time.event.survivor_joins_many", "{count} survivors join your base."), + ("system.time.event.base_max_capacity", "Your base is at maximum capacity."), + ("system.time.event.invasion_ended", "The {enemy} invasion has ended."), + ("system.time.event.blessing_speed_fades", "The speed blessing fades."), + ("system.time.event.blessing_resident_fades", "The residents' purpose fades."), + ("system.time.event.blessing_search_fades", "The eagle's sight fades."), + ("system.time.event.sun_setting", "The sun is setting."), + ("system.time.event.sky_brightening", "The sky begins to brighten."), + ("system.time.event.residents_repaired_barricade", "Residents repaired the barricade. +{health} health."), + ("system.time.event.incense_burned_out", "The incense has burned out."), + ("system.combat.burning", "Burning! {health} health remaining."), + ("system.combat.health_status", "{health} health."), + ("system.combat.you_died", "You have died."), + ("system.enemies.residents_killed_attacker", "Residents killed an attacking {enemy}."), + ("system.enemies.resident_taken", "A resident has been taken."), + ("system.action.fire.intensity.giant_blaze", "Giant blaze"), + ("system.action.fire.intensity.small_fire", "Small fire"), + ("system.action.fire.intensity.glowing_coals", "A few glowing coals"), + ("system.action.fire.estimate.less_than_one_hour", "less than 1 hour"), + ("system.action.fire.estimate.approximately_one_hour", "approximately 1 hour"), + ("system.action.fire.estimate.approximately_hours", "approximately {hours} hours"), + ("system.action.fire.status", "{label}. {estimate} remaining."), + ("system.action.no_fire_nearby", "No fire nearby."), + ("system.action.no_snare_nearby", "No snare nearby."), + ("system.action.snare_holds", "Snare holds a {catch_type}."), + ("system.action.snare_set_inactive", "Snare is set but not active yet."), + ("system.action.snare_set_empty", "Snare is set and empty."), + ("system.action.fish_on_line", "Fish on the line."), + ("system.action.no_fish_on_line", "No fish on the line."), + ("system.action.cannot_place_snares_in_base", "Cannot place snares in the base area."), + ("system.action.snare_already_here", "There is already a snare here."), + ("system.action.snare_set", "Snare set."), + ("system.action.no_snares_to_place", "No snares to place."), + ("system.action.feed_fire.stick", "You dump an arm load of sticks into the fire."), + ("system.action.feed_fire.vine", "You toss a few vines and leaves into the fire."), + ("system.action.feed_fire.log", "You heave a log into the fire."), + ("system.action.no_altar_built", "No altar built."), + ("system.action.need_clay_pot_for_incense", "You need a clay pot to burn incense."), + ("system.action.no_incense_to_burn", "No incense to burn."), + ("system.action.incense_burning", "Incense burning. {hours} hours remaining."), + ("system.action.no_sticks_to_feed_fire", "No sticks to feed fire."), + ("system.action.dumped_sticks", "Dumped {amount} sticks into the fire."), + ("system.action.no_vines_to_feed_fire", "No vines to feed fire."), + ("system.action.dumped_vines", "Dumped {amount} vines into the fire."), + ("system.action.no_logs_to_feed_fire", "No logs to feed fire."), + ("system.action.dumped_logs", "Dumped {amount} logs into the fire."), + ("system.action.burned_incense", "Burned {amount} incense. +{hours} hours."), + ("system.action.option.place_snare", "Place Snare"), + ("system.action.option.feed_fire_stick", "Feed fire with stick"), + ("system.action.option.feed_fire_vine", "Feed fire with vine"), + ("system.action.option.feed_fire_log", "Feed fire with log"), + ("system.action.option.burn_incense", "Burn incense"), + ("system.action.option.check_fire", "Check fire"), + ("system.action.option.check_snare", "Check snare"), + ("system.action.option.check_fishing_pole", "Check fishing pole"), + ("system.action.menu.prompt", "Action menu. {option}"), + ("system.action.cant_do_that", "Can't do that."), + ("system.base_info.not_in_base", "You are not in the base."), + ("system.base_info.menu.no_options", "Base info. No options."), + ("system.base_info.menu.prompt", "Base info. {option}"), + ("system.base.barricade_fallen", "The barricade has fallen!"), + ("system.base.no_food_residents_hungry", "No food, residents are hungry."), + ("system.base.resident_fishing_pole_broke_one", "A resident's fishing pole broke."), + ("system.base.resident_fishing_pole_broke_many", "{count} fishing poles broke."), + ("system.base.resident_caught_fish_one", "Resident caught a fish and added it to storage."), + ("system.base.resident_caught_fish_many", "Residents caught {count} fish and added them to storage."), + ("system.base.resident_smoked_fish", "Resident smoked a fish into {yield} smoked fish."), + ("system.base.livestock_produced", + "Livestock produced {meat} meat, {skins} skins, and {feathers} feathers and added to storage."), + ("system.base.resident_spear_broke_one", "A resident's spear broke from wear."), + ("system.base.resident_spear_broke_many", "{count} spears broke from wear."), + ("system.base.resident_sling_broke_one", "A resident's sling broke from wear."), + ("system.base.resident_sling_broke_many", "{count} slings broke from wear."), + ("system.base.resident_bow_broke_one", "A resident's bow broke from wear."), + ("system.base.resident_bow_broke_many", "{count} bows broke from wear."), + ("system.base.resident_clothing_repair_one", + "A resident is mending clothing. Used {vines} vines, {skins} skins, and {down} down."), + ("system.base.resident_clothing_repair_many", + "Residents are mending clothing. Used {vines} vines, {skins} skins, and {down} down."), + ("system.base.snare_escape_during_check", + "A {catch_type} escaped while a resident checked the snare at x {position}."), + ("system.base.resident_retrieved_from_snare", + "Resident retrieved {game_type} from snare at x {position} y 0 and reset it."), + ("system.base.resident_knife_broke_butchering", "A resident's knife broke while butchering."), + ("system.base.resident_butchered_result", + "Resident butchered {game_type}. Added {meat} meat, {skins} skins, {feathers} feathers, {down} down, {sinew} sinew to storage."), + ("system.base.resident_added_to_storage", "Resident added {item} to storage."), + ("system.base.resident_basket_broke_one", "A resident's basket broke."), + ("system.base.resident_basket_broke_many", "{count} baskets broke."), + ("system.base.resident_basket_broke_foraging_one", "A resident's basket broke while foraging."), + ("system.base.resident_basket_broke_foraging_many", "{count} baskets broke while foraging."), + ("system.base.resident_gathered_basket_food_one", "Resident gathered a basket of fruits and nuts."), + ("system.base.resident_gathered_basket_food_many", + "Residents gathered {count} baskets of fruits and nuts."), + ("system.fishing.size.small", "small"), + ("system.fishing.size.medium", "medium sized"), + ("system.fishing.size.large", "large"), + ("system.fishing.size.monster", "monster"), + ("system.fishing.pole_broke.default", "Your fishing pole broke."), + ("system.fishing.pole_broke.switched_weapons", "You switched weapons and your fishing pole broke."), + ("system.fishing.pole_broke.moved_fish_got_away", "You moved and the fish got away. Your fishing pole broke."), + ("system.fishing.pole_broke.moved", "You moved and your fishing pole broke."), + ("system.fishing.require_pole_equipped", "You need a fishing pole equipped."), + ("system.fishing.require_near_stream", "You need to be within 2 tiles of a stream."), + ("system.fishing.fish_on_line", "A fish is on the line!"), + ("system.fishing.caught", "Caught a {size} {fish}."), + ("system.fishing.fish_slipped_off_water", "The fish slipped off in the water."), + ("system.fishing.fish_got_away", "The fish got away."), + ("system.fishing.fish_still_on_line", "The fish is still on the line."), + ("system.fishing.stopped", "You stop fishing."), + ("system.altar.must_be_in_base", "Must be in base to use altar."), + ("system.altar.no_altar_built", "No altar built."), + ("system.altar.runed_cannot_sacrifice", "Runed items cannot be sacrificed."), + ("system.altar.nothing_to_sacrifice", "Nothing to sacrifice."), + ("system.altar.sacrificed_one", "Sacrificed 1 {item}. Favor +{gain}. Total {total}."), + ("system.altar.sacrificed_many", "Sacrificed {count} {items}. Favor +{gain}. Total {total}."), + ("system.altar.menu.prompt", "Altar. Favor {favor}."), ("system.storage.window_title", "Inventory"), ("system.storage.transfer_prompt", "{prompt} (max {max})"), ("system.storage.deposit_how_many", "Deposit how many?"), @@ -489,6 +639,11 @@ def write_catalog(entries: Dict[str, Dict[str, object]], output_path: Path) -> N ("system.storage.menu_title", "Base storage."), ("system.storage.menu.prompt", "Base storage. {option}"), ("system.storage.menu.no_options", "Base storage. No options."), + ("system.storage.runed_item_name", "Runed {equipment} of {rune}"), + ("system.storage.deposited_one", "Deposited {name}."), + ("system.storage.deposited_many", "Deposited {amount} {item}."), + ("system.storage.withdrew_one", "Withdrew {name}."), + ("system.storage.withdrew_many", "Withdrew {amount} {item}."), ("system.crafting.require.fire_within_three_clay_pot", "You need a fire within 3 tiles to craft a clay pot."), ("system.crafting.require.fire_within_three_clay_pots", @@ -511,10 +666,152 @@ def write_catalog(entries: Dict[str, Dict[str, object]], output_path: Path) -> N ("system.character.pet.abandon_confirm", "Really abandon your pet? {option}"), ("system.character.pet.unconscious_cannot_abandon", "Your {pet} is unconscious. You can't abandon it right now."), + ("system.character.info.name_sex", "Name {name}, {sex}"), + ("system.character.info.name_unknown", "Name unknown"), + ("system.character.info.health", "Health {health} of {max}"), + ("system.character.info.weapon", "Weapon {weapon}"), + ("system.character.info.clothing_equipped", "Clothing equipped: {items}"), + ("system.character.info.no_clothing", "No clothing equipped."), + ("system.character.info.missing", "Missing: {slots}"), + ("system.character.info.favor", "Favor {favor}"), + ("system.character.info.speed", "Speed {status}"), + ("system.character.info.pet", "Pet {pet}, health {health} of {max_health}, loyalty {loyalty} of {max_loyalty}"), + ("system.character.info.pet_knocked_out", "Knocked out for {hours} {hour_label}."), + ("system.character.info.pet_none", "No pet."), + ("system.character.word.hour", "hour"), + ("system.character.word.hours", "hours"), + ("system.pet.default_name", "pet"), + ("system.pet.returned", "A {pet} returns to you."), + ("system.pet.knocked_out", "Your {pet} has been knocked out."), + ("system.pet.knocked_out_with_remaining", "Your {pet} has been knocked out. {hours} {hour_label} remaining."), + ("system.pet.leaves", "{pet} leaves."), + ("system.pet.leaving", "Your {pet} is leaving."), + ("system.pet.on_the_way", "Your pet is on its way."), + ("system.pet.hungry_unresponsive", "A {pet} is hungry and unresponsive."), + ("system.pet.joins_you", "A {pet} joins you."), + ("system.pet.offer.prompt", "A friendly looking {pet} begs for food. Accept?"), + ("system.pet.offer.declined", "Declined."), + ("system.pet.retrieve.cant_carry_chew_on", + "You can't carry a {item}, so you give it to a {pet} to chew on."), + ("system.pet.retrieve.retrieved_item", "Your {pet} retrieved {item}."), + ("system.pet.retrieve.random_find", "Your {pet} retrieved {count} {item}."), + ("system.pet.recovered_from_injuries", "Your {pet} has recovered from its injuries."), + ("system.pet.getting_hungry", "A {pet} is getting hungry."), + ("system.fylgja.already_used_today", "You have already used your Fylgja today."), + ("system.fylgja.menu.prompt", "Fylgja menu."), + ("system.fylgja.need_open_ground_to_charge", "You need open ground in front of you to charge."), + ("system.fylgja.option", "{name} Fylgja"), + ("system.fylgja.connection_with_target", "You have a {stage} connection with the {target}."), + ("system.fylgja.unlocked", "You have unlocked the {name} Fylgja!"), + ("system.fylgja.already_unlocked", "You have already unlocked the {name} Fylgja."), + ("system.fylgja.name.unicorn", "Unicorn"), + ("system.fylgja.target.unicorn", "unicorn"), + ("system.fylgja.stage.tenuous", "tenuous"), + ("system.fylgja.stage.faint", "faint"), + ("system.fylgja.stage.stirring", "stirring"), + ("system.fylgja.stage.budding", "budding"), + ("system.fylgja.stage.kindled", "kindled"), + ("system.fylgja.stage.bound", "bound"), + ("system.fylgja.stage.sworn", "sworn"), + ("system.fylgja.stage.ascendant", "ascendant"), + ("system.fylgja.stage.ultimate", "ultimate"), + ("system.quest.name.bat_invasion", "Bat Invasion"), + ("system.quest.name.catch_boomerang", "Catch the Boomerang"), + ("system.quest.name.enchanted_melody", "Enchanted Melody"), + ("system.quest.name.escape_from_hel", "Escape from Hel"), + ("system.quest.name.skeletal_bard", "Skeletal Bard"), + ("system.quest.name.unknown", "Unknown Quest"), + ("system.quest.description.bat_invasion", + "Bat Invasion. Giant killer bats are attacking. Press space to throw when the bat is centered."), + ("system.quest.description.catch_boomerang", + "Catch the Boomerang. Throw and catch the boomerang as it returns for up to 4 points."), + ("system.quest.description.enchanted_melody", + "Enchanted Melody. Repeat the pattern using E R D F or U I J K. Lowest to highest pitch."), + ("system.quest.description.escape_from_hel", + "Escape from Hel. Press space to jump over open graves. The pace quickens."), + ("system.quest.description.skeletal_bard", + "Skeletal Bard. A skeleton named Billy Bones is practicing to become a bard. Count the notes."), + ("system.quest.description.unknown", "Unknown quest."), + ("system.quest.new_available", "A new quest is available: {quest}."), + ("system.quest.none_available", "No quests available."), + ("system.quest.favor_phrase.displeased", "The gods are displeased with your performance."), + ("system.quest.favor_phrase.pleased", "The gods are pleased with your performance."), + ("system.quest.favor_phrase.very_pleased", "The gods are very pleased with your performance."), + ("system.quest.favor_phrase.extremely_pleased", "The gods are extremely pleased with your performance."), + ("system.quest.favor_phrase.ultimately_pleased", "The gods are ultimately pleased with your performance."), + ("system.quest.rewards.title", "Quest Rewards"), + ("system.quest.rewards.complete_heading", "Quest Complete!"), + ("system.quest.rewards.heading", "Rewards:"), + ("system.quest.rewards.favor_line", "Favor: +{favor}"), + ("system.quest.rewards.item_line", "{item}: +{amount}"), + ("system.quest.rewards.inventory_full_line", "Inventory full, could not receive {item}."), + ("system.quest.rewards.no_items_awarded", "No items awarded."), + ("system.quest.rewards.score_line", "Score: {score}"), + ("system.quest.menu.prompt", "Quest menu."), + ("system.quest.menu.count", "{index} of {total}"), + ("system.quest.minigame.starting", "Starting."), + ("system.quest.bat_invasion.complete_score", "Bat invasion complete. Score {score}."), + ("system.quest.boomerang.press_space_to_throw", "Press Space to throw."), + ("system.quest.boomerang.skill.almost_dropped", "almost dropped"), + ("system.quest.boomerang.skill.managed_to_catch", "managed to catch"), + ("system.quest.boomerang.skill.caught", "caught"), + ("system.quest.boomerang.skill.expertly_caught", "expertly caught"), + ("system.quest.boomerang.caught_result", "You {skill} the boomerang. {points} points.{suffix}"), + ("system.quest.boomerang.missed", "You missed the boomerang.{suffix}"), + ("system.quest.boomerang.hit_you", "The boomerang hit you.{suffix}"), + ("system.quest.boomerang.summary", "You caught {count} boomerangs for a total of {score} points."), + ("system.quest.enchanted_melody.practice_prompt", "Practice mode. Press Enter to begin, Escape to cancel."), + ("system.quest.enchanted_melody.starting_prompt", "Starting. Repeat the pattern."), + ("system.quest.enchanted_melody.score", "You matched {rounds} notes. Score {score}."), + ("system.quest.skeletal_bard.select_notes", "Select number of notes. {selection}."), + ("system.quest.skeletal_bard.round_result", + "You entered {guess} notes and the actual number was {actual}. {points} points. Press Enter to continue."), + ("system.quest.skeletal_bard.complete_score", "Skeletal Bard complete. Your score for all five tunes is {score}."), + ("system.quest.escape_from_hel.fell_in_score", "You fell in. Score {score}."), + ("system.adventure.none_in_base", "No adventures available in the base."), + ("system.adventure.already_attempted_today", "You have already attempted an adventure today."), + ("system.adventure.option.unicorn_hunt", "Unicorn Hunt (Mountain Boss)"), + ("system.adventure.option.bandit_hideout", "Bandit's Hideout"), + ("system.adventure.none_in_area", "No adventures found in this area."), + ("system.adventure.menu.prompt", "Adventure menu."), + ("system.adventure.victory", "Victory!"), + ("system.adventure.rewards.title", "=== Victory Rewards ==="), + ("system.adventure.unicorn.flee", "You fled from the unicorn."), + ("system.adventure.unicorn.position_report", + "X {x}, {terrain}, facing {direction}"), + ("system.adventure.unicorn.player_trampled", "The unicorn trampled you!"), + ("system.adventure.unicorn.victory_title", "Unicorn Victory"), + ("system.adventure.unicorn.reward.favor_awarded", + "The gods are pleased with your victory! {favor} favor awarded."), + ("system.adventure.unicorn.reward.heal_scrolls", "Heal Scrolls: +{count}."), + ("system.adventure.unicorn.reward.learned_rune_swiftness", "Learned Rune of Swiftness!"), + ("system.adventure.unicorn.reward.engrave_unlocked", + "You can now engrave equipment with this rune at the crafting menu."), + ("system.adventure.unicorn.reward.mastered_rune_swiftness", + "You have already mastered the Rune of Swiftness."), + ("system.adventure.unicorn.horses.no_stable_or_storage", + "Stable or storage not built. No horses were captured."), + ("system.adventure.unicorn.horses.stable_full", "Stable is full. No horses were captured."), + ("system.adventure.unicorn.horses.joined_stable", "A horse joins your stable."), + ("system.adventure.unicorn.horses.none_captured", "No horses were captured."), + ("system.adventure.bandit_hideout.flee", "You fled from the bandit hideout."), + ("system.adventure.bandit_hideout.position_report", + "X {x}, {terrain}. Distance to base {distance}. Facing {direction}. Base health {health} of {max}."), + ("system.adventure.bandit_hideout.player_defeated", "You were defeated in the bandit hideout."), + ("system.character.report.position", "{direction}, x {x}, y {y}, terrain {terrain}"), + ("system.character.report.terrain_mountains", "{terrain}. Mountains"), + ("system.character.report.player", "{health} of {max} health"), + ("system.character.report.pet", + "{pet}: {health} of {max} health, loyalty {loyalty} of {max_loyalty}"), ("system.item.label.items", "items"), ("system.item.label.item", "item"), ("system.item.label.unknown", "Unknown"), + ("system.equipment.menu.prompt", "Equipment menu. {option}"), + ("system.equipment.menu.nothing_to_equip", "Nothing to equip."), ("system.equipment.menu.equipped_suffix", " (equipped)"), + ("system.equipment.set_to_slot", "{name} set to slot {slot}."), + ("system.equipment.equipped", "{name} equipped."), + ("system.equipment.unequipped", "{name} unequipped."), ("system.equipment.name.none", "None"), ("system.equipment.name.unknown", "Unknown"), ("system.equipment.name.spear", "Spear"), @@ -546,6 +843,31 @@ def write_catalog(entries: Dict[str, Dict[str, object]], output_path: Path) -> N ("system.environment.tree.fell_with_loot", "Tree fell! Got {sticks} {sticks_label}, {vines} {vines_label}, and {logs} {logs_label}."), ("system.environment.tree.inventory_full", "Inventory full."), + ("system.environment.fall.damage_report", + "Fell {height} feet! Took {damage} damage. {health} health remaining."), + ("system.environment.snare.collected_with_catch", "Collected {catch_type} and snare."), + ("system.environment.snare.collected_empty", "Collected snare."), + ("system.environment.tree.cut_down", "This tree has been cut down."), + ("system.environment.tree.empty", "This tree is empty."), + ("system.environment.area.nothing_left", "This area has nothing left."), + ("system.environment.tree.climb_started", "Started climbing tree. Height is {height} feet."), + ("system.environment.tree.climb_reached_top", "Reached the top at {height} feet."), + ("system.environment.tree.climb_reached_ground", "Safely reached the ground."), + ("system.environment.tree.climb_down", "Climbing down."), + ("system.environment.movement.need_rope", "You'll need a rope to climb there."), + ("system.environment.movement.press_up_climb", "Press up to climb up."), + ("system.environment.movement.press_down_climb", "Press down to climb down."), + ("system.environment.movement.need_canoe", "You need a canoe to cross deep water."), + ("system.environment.rope_climb.direction.up", "up"), + ("system.environment.rope_climb.direction.down", "down"), + ("system.environment.rope_climb.progress", "Climbing {direction}. {distance} feet."), + ("system.environment.rope_climb.reached_elevation", "Reached elevation {elevation}."), + ("system.snare.escape_at", "A {catch_type} escaped from your snare at x {position} y 0!"), + ("system.snare.caught_at", "{catch_type} caught in snare at x {position} y 0!"), + ("system.snare.stepped_on_with_escape", "You stepped on your snare! The {catch_type} escaped."), + ("system.snare.stepped_on_broke", "You stepped on your snare and broke it!"), + ("system.fire.low_fuel_at", "Fire at x {position} y {y} is getting low!"), + ("system.fire.went_out_at", "Fire at x {position} y {y} has gone out."), ("system.crafting.menu.prompt", "Crafting menu. {option}"), ("system.crafting.category.weapons", "Weapons"), ("system.crafting.category.tools", "Tools"), @@ -554,10 +876,19 @@ def write_catalog(entries: Dict[str, Dict[str, object]], output_path: Path) -> N ("system.crafting.category.buildings", "Buildings"), ("system.crafting.category.barricade", "Barricade"), ("system.crafting.category.runes", "Runes"), + ("system.crafting.in_progress", "Crafting..."), ("system.crafting.weapons.prompt", "Weapons. {option}"), ("system.crafting.weapons.option.spear", "Spear (1 Stick, 1 Vine, 1 Stone) [Requires Knife]"), ("system.crafting.weapons.option.sling", "Sling (1 Skin, 2 Vines)"), ("system.crafting.weapons.option.bow", "Bow (1 Stick, 1 Bowstring)"), + ("system.crafting.weapons.crafted.spear", "Crafted a Spear."), + ("system.crafting.weapons.crafted.sling", "Crafted a Sling."), + ("system.crafting.weapons.crafted.bow", "Crafted a Bow."), + ("system.crafting.weapons.crafted.stone_axe", "Crafted a Stone Axe."), + ("system.crafting.weapons.crafted_max.spears", "Crafted {count} Spears."), + ("system.crafting.weapons.crafted_max.slings", "Crafted {count} Slings."), + ("system.crafting.weapons.crafted_max.bows", "Crafted {count} Bows."), + ("system.crafting.weapons.crafted_max.stone_axes", "Crafted {count} Stone Axes."), ("system.crafting.tools.prompt", "Tools. {option}"), ("system.crafting.tools.option.stone_knife", "Stone Knife (2 Stones)"), ("system.crafting.tools.option.snare", "Snare (1 Stick, 2 Vines)"), @@ -568,12 +899,44 @@ def write_catalog(entries: Dict[str, Dict[str, object]], output_path: Path) -> N ("system.crafting.tools.option.canoe", "Canoe (4 Logs, 11 Sticks, 11 Vines, 6 Skins, 2 Rope, 6 Reeds)"), ("system.crafting.tools.option.reed_basket", "Reed Basket (3 Reeds)"), ("system.crafting.tools.option.clay_pot", "Clay Pot (3 Clay)"), + ("system.crafting.tools.crafted.stone_knife", "Crafted a Stone Knife."), + ("system.crafting.tools.crafted.snare", "Crafted a Snare."), + ("system.crafting.tools.crafted.fishing_pole", "Crafted a Fishing Pole."), + ("system.crafting.tools.crafted.rope", "Crafted rope."), + ("system.crafting.tools.crafted.quiver", "Crafted a Quiver."), + ("system.crafting.tools.crafted.canoe", "Crafted a Canoe."), + ("system.crafting.tools.crafted.reed_basket", "Crafted a reed basket."), + ("system.crafting.tools.crafted.clay_pot", "Crafted a clay pot."), + ("system.crafting.tools.crafted_max.stone_knives", "Crafted {count} Stone Knives."), + ("system.crafting.tools.crafted_max.snares", "Crafted {count} Snares."), + ("system.crafting.tools.crafted_max.fishing_poles", "Crafted {count} Fishing Poles."), + ("system.crafting.tools.crafted_max.ropes", "Crafted {count} Rope."), + ("system.crafting.tools.crafted_max.quivers", "Crafted {count} Quivers."), + ("system.crafting.tools.crafted_max.canoes", "Crafted {count} Canoes."), + ("system.crafting.tools.crafted_max.reed_baskets", "Crafted {count} Reed Baskets."), + ("system.crafting.tools.crafted_max.clay_pots", "Crafted {count} Clay Pots."), ("system.crafting.materials.prompt", "Materials. {option}"), ("system.crafting.materials.option.butcher_game", "Butcher Game [Requires Game, Knife, Fire nearby]"), ("system.crafting.materials.option.smoke_fish", "Smoke Fish (1 Fish, 1 Stick) [Requires Fire nearby]"), ("system.crafting.materials.option.arrows", "Arrows (2 Sticks, 4 Feathers, 2 Stones) [Requires Quiver]"), ("system.crafting.materials.option.bowstring", "Bowstring (3 Sinew) [Requires Fire nearby]"), ("system.crafting.materials.option.incense", "Incense (6 Sticks, 2 Vines, 1 Reed) [Requires Altar]"), + ("system.crafting.materials.not_enough_quiver_capacity_for_arrows", "Not enough quiver capacity for arrows."), + ("system.crafting.materials.crafted.arrows", "Crafted {count} arrows."), + ("system.crafting.materials.crafted.bowstring", "Crafted a bowstring."), + ("system.crafting.materials.crafted_max.bowstrings", "Crafted {count} Bowstrings."), + ("system.crafting.materials.crafted.incense", "Crafted incense."), + ("system.crafting.materials.crafted_max.incense", "Crafted {count} Incense."), + ("system.crafting.materials.smoke_fish.crafted", "Smoked a fish into {yield} smoked fish."), + ("system.crafting.materials.smoke_fish.crafted_max", + "Smoked {count} fish into {yield} smoked fish."), + ("system.crafting.materials.butcher.goose", "Butchered goose. Got 1 meat, feathers, and down."), + ("system.crafting.materials.butcher.turkey", "Butchered turkey. Got 1 meat and feathers."), + ("system.crafting.materials.butcher.boar", "Butchered boar. Got meat, 3 skins, and 2 sinew."), + ("system.crafting.materials.butcher.default", "Butchered {game}. Got 1 meat and 1 skin."), + ("system.crafting.materials.butcher.no_space_outputs", "No space for outputs."), + ("system.crafting.materials.butcher.max_result", + "Butchered {count} game. Got {meat} meat, {skins} skins, {feathers} feathers, {down} down, {sinew} sinew."), ("system.crafting.clothing.prompt", "Clothing. {option}"), ("system.crafting.clothing.option.skin_hat", "Skin Hat (1 Skin, 1 Vine)"), ("system.crafting.clothing.option.skin_gloves", "Skin Gloves (1 Skin, 1 Vine)"), @@ -582,6 +945,20 @@ def write_catalog(entries: Dict[str, Dict[str, object]], output_path: Path) -> N ("system.crafting.clothing.option.moccasins", "Moccasins (2 Skins, 1 Vine)"), ("system.crafting.clothing.option.skin_pouch", "Skin Pouch (2 Skins, 1 Vine)"), ("system.crafting.clothing.option.backpack", "Backpack (11 Skins, 5 Vines, 4 Skin Pouches)"), + ("system.crafting.clothing.crafted.skin_hat", "Crafted a Skin Hat."), + ("system.crafting.clothing.crafted.skin_gloves", "Crafted Skin Gloves."), + ("system.crafting.clothing.crafted.skin_pants", "Crafted Skin Pants."), + ("system.crafting.clothing.crafted.skin_tunic", "Crafted a Skin Tunic."), + ("system.crafting.clothing.crafted.moccasins", "Crafted moccasins."), + ("system.crafting.clothing.crafted.skin_pouch", "Crafted a Skin Pouch."), + ("system.crafting.clothing.crafted.backpack", "Crafted a Backpack."), + ("system.crafting.clothing.crafted_max.skin_hats", "Crafted {count} Skin Hats."), + ("system.crafting.clothing.crafted_max.skin_gloves", "Crafted {count} Skin Gloves."), + ("system.crafting.clothing.crafted_max.skin_pants", "Crafted {count} Skin Pants."), + ("system.crafting.clothing.crafted_max.skin_tunics", "Crafted {count} Skin Tunics."), + ("system.crafting.clothing.crafted_max.moccasins", "Crafted {count} Moccasins."), + ("system.crafting.clothing.crafted_max.skin_pouches", "Crafted {count} Skin Pouches."), + ("system.crafting.clothing.crafted_max.backpacks", "Crafted {count} Backpacks."), ("system.crafting.buildings.prompt", "Buildings. {option}"), ("system.crafting.buildings.option.firepit", "Firepit (9 Stones)"), ("system.crafting.buildings.option.fire", "Fire (2 Sticks, 1 Log) [Requires Firepit]"), @@ -594,6 +971,42 @@ def write_catalog(entries: Dict[str, Dict[str, object]], output_path: Path) -> N ("system.crafting.buildings.option.stable", "Stable (10 Logs, 15 Stones, 10 Vines) [Base Only, Requires Storage Upgrade]"), ("system.crafting.buildings.option.altar", "Altar (9 Stones, 3 Sticks) [Base Only]"), + ("system.crafting.buildings.none_available", "No buildings available."), + ("system.crafting.buildings.firepit.already_in_base", "There is already a firepit in the base."), + ("system.crafting.buildings.firepit.already_here", "There is already a firepit here."), + ("system.crafting.buildings.firepit.built", "Firepit built here."), + ("system.crafting.buildings.fire.requires_firepit_nearby", "You need a firepit within 2 tiles to build a fire."), + ("system.crafting.buildings.fire.already_in_base", "There is already a fire in the base."), + ("system.crafting.buildings.fire.built", "Fire built at firepit."), + ("system.crafting.buildings.herb_garden.base_only", "Herb garden can only be built in the base area."), + ("system.crafting.buildings.herb_garden.already_in_base", "There is already an herb garden in the base."), + ("system.crafting.buildings.herb_garden.built", "Herb garden built. The base now heals faster."), + ("system.crafting.buildings.storage.base_only", "Storage must be built in the base."), + ("system.crafting.buildings.storage.fully_upgraded", "Storage is fully upgraded."), + ("system.crafting.buildings.storage.upgraded", "Storage upgraded. Capacity is now {capacity} per item."), + ("system.crafting.buildings.pasture.base_only", "Pasture must be built in the base."), + ("system.crafting.buildings.pasture.requires_storage_upgrade", "Storage must be upgraded before a pasture."), + ("system.crafting.buildings.pasture.already_built", "Pasture already built."), + ("system.crafting.buildings.pasture.built", "Pasture built."), + ("system.crafting.buildings.stable.base_only", "Stable must be built in the base."), + ("system.crafting.buildings.stable.requires_storage_upgrade", "Storage must be upgraded before a stable."), + ("system.crafting.buildings.stable.already_built", "Stable already built."), + ("system.crafting.buildings.stable.built", "Stable built."), + ("system.crafting.buildings.altar.base_only", "Altar must be built in the base."), + ("system.crafting.buildings.altar.already_built", "Altar already built."), + ("system.crafting.buildings.altar.built", "Altar built."), + ("system.crafting.runes.base_only", "Rune engraving can only be done in the base area."), + ("system.crafting.runes.option", "{rune} (1 Clay, 1 Favor) [Requires Knife]"), + ("system.crafting.runes.none_unlocked", "No runes unlocked yet."), + ("system.crafting.runes.prompt", "Runes. {option}"), + ("system.crafting.runes.equipment_option", "{name} ({count} available)"), + ("system.crafting.runes.no_equipment_available", "No equipment available to engrave."), + ("system.crafting.runes.select_equipment_prompt", + "Select equipment to engrave with {rune}. {option}"), + ("system.crafting.runes.no_item_available", "No {item} available."), + ("system.crafting.runes.runed_name", "Runed {equipment} of {rune}"), + ("system.crafting.runes.engraved", "Engraved {item}."), + ("system.crafting.runes.engraved_max", "Engraved {count} {item} with {rune}."), ("system.crafting.barricade.prompt", "Barricade. {option}"), ("system.crafting.barricade.option.reinforce_sticks", "Reinforce with sticks ({cost} sticks, +{health} health)"), @@ -601,11 +1014,85 @@ def write_catalog(entries: Dict[str, Dict[str, object]], output_path: Path) -> N ("system.crafting.barricade.option.reinforce_log", "Reinforce with log ({cost} log, +{health} health)"), ("system.crafting.barricade.option.reinforce_stones", "Reinforce with stones ({cost} stones, +{health} health)"), + ("system.crafting.barricade.full_health", "Barricade is already at full health."), + ("system.crafting.barricade.no_materials", "No materials to reinforce the barricade."), + ("system.crafting.barricade.reinforced.sticks", + "Reinforced barricade with sticks. +{gained} health. Now {health} of {max}."), + ("system.crafting.barricade.reinforced.vines", + "Reinforced barricade with vines. +{gained} health. Now {health} of {max}."), + ("system.crafting.barricade.reinforced.log", + "Reinforced barricade with log. +{gained} health. Now {health} of {max}."), + ("system.crafting.barricade.reinforced.stones", + "Reinforced barricade with stones. +{gained} health. Now {health} of {max}."), + ("system.crafting.barricade.reinforced_max.sticks", + "Reinforced barricade {count} times with sticks. Health now {health}."), + ("system.crafting.barricade.reinforced_max.vines", + "Reinforced barricade {count} times with vines. Health now {health}."), + ("system.crafting.barricade.reinforced_max.log", + "Reinforced barricade {count} times with log. Health now {health}."), + ("system.crafting.barricade.reinforced_max.stones", + "Reinforced barricade {count} times with stones. Health now {health}."), + ("system.crafting.barricade.not_enough.sticks", "Not enough sticks."), + ("system.crafting.barricade.not_enough.vines", "Not enough vines."), + ("system.crafting.barricade.not_enough.logs", "Not enough logs."), + ("system.crafting.barricade.not_enough.stones", "Not enough stones."), ("system.crafting.missing", "Missing: {requirements}"), ("system.crafting.requirement.stone_knife", "Stone Knife"), ("system.crafting.requirement.game", "Game"), ("system.crafting.requirement.favor", "favor"), ("system.crafting.requirement.resources", "resources"), + ("system.story.voice.format", "{speaker}: {line}"), + ("system.story.god.fallback", "A god"), + ("system.story.god.odin", "Odin"), + ("system.story.god.thor", "Thor"), + ("system.story.god.freyja", "Freyja"), + ("system.story.god.loki", "Loki"), + ("system.story.god.tyr", "Tyr"), + ("system.story.god.baldur", "Baldur"), + ("system.story.god.frigg", "Frigg"), + ("system.story.god.heimdall", "Heimdall"), + ("system.story.god.hel", "Hel"), + ("system.story.god.fenrir", "Fenrir"), + ("system.story.god.freyr", "Freyr"), + ("system.story.line01", "The world has fallen."), + ("system.story.line02", "Once-great cities lie in ruin."), + ("system.story.line03", "In most places, not two stones remain as mankind set them."), + ("system.story.line04", "The gods, long thought sleeping, achieved the impossible."), + ("system.story.line05", "Ragnarok was averted."), + ("system.story.line06", "Great Fenrir was freed and did not strike down his captors."), + ("system.story.line07", "Surtr did not lay waste to our world with his flaming greatsword."), + ("system.story.line08", "For a fleeting age, the gods wrestled fate into silence."), + ("system.story.line09", "But the end of the world was delayed, never denied."), + ("system.story.line10", "One force lay beyond even divine command: mankind."), + ("system.story.line11", "Hatred swelled."), + ("system.story.line12", "Greed answered it."), + ("system.story.line13", "Mercy withered."), + ("system.story.line14", "Differences became crimes."), + ("system.story.line15", "Folk no longer argued; they tore at one another like beasts."), + ("system.story.line16", "Neighbors became enemies for trifles: a color, a song, a single word."), + ("system.story.line17", "War followed."), + ("system.story.line18", "Cities burned, roads broke, and monsters wearing human faces roamed the streets."), + ("system.story.line19", "Then ruin deepened into terror."), + ("system.story.line20", "The dead, enraged by wanton slaughter, rose from their graves."), + ("system.story.line21", "Corpses woke and hunted the living."), + ("system.story.line22", "Night-stalkers fed on blood."), + ("system.story.line23", "Even ash and dust remembered form and rose again."), + ("system.story.line24", "Soon all that remained was rubble and bone."), + ("system.story.line25", "Your last memory is flight from a vast horde of nightmare creatures."), + ("system.story.line26", "When you wake, you are somewhere strange."), + ("system.story.line27", + "A crude wooden shelter stands against the wind, open to the elements, braced with sticks and logs."), + ("system.story.line28", "As your senses return, faint voices stir in the dark."), + ("system.story.line29", "After the death of this world, another shall rise."), + ("system.story.line30", "You have been judged worthy to try and survive."), + ("system.story.line31", "This world belongs to the dead."), + ("system.story.line32", "In time, they will slay even us."), + ("system.story.line33", "Prove yourself, warrior, and you may walk into the next world."), + ("system.story.line34", "May your death, when it comes, be honorable."), + ("system.story.line35", "We will aid you while we still have strength, but time is against us."), + ("system.story.line36", + "Beyond your shelter lies grassland, and farther off, broken stone that may once have been a city."), + ("system.story.line37", "In the total devastation, even memory has lost its shape."), ] lines: List[str] = [] diff --git a/scripts/validate_i18n_catalog.py b/scripts/validate_i18n_catalog.py index 6128de2..79e1312 100644 --- a/scripts/validate_i18n_catalog.py +++ b/scripts/validate_i18n_catalog.py @@ -34,7 +34,13 @@ def parse_ini(path: Path) -> Dict[str, str]: if not key: continue - full_key = key if not section or "." in key else f"{section}.{key}" + if not section: + full_key = key + elif section == "messages": + full_key = key if "." in key else f"{section}.{key}" + else: + section_prefix = f"{section}." + full_key = key if key.startswith(section_prefix) else f"{section_prefix}{key}" result[full_key] = unescape_ini_value(value) return result diff --git a/sounds/dialog.ogg b/sounds/dialog.ogg new file mode 100644 index 0000000..49971cc --- /dev/null +++ b/sounds/dialog.ogg @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:c08df4614917374bf113d4cdc71600c565368ea46290fb45182699ba14f9565f +size 5794 diff --git a/src/base_system.nvgt b/src/base_system.nvgt index d372471..cb81c29 100644 --- a/src/base_system.nvgt +++ b/src/base_system.nvgt @@ -144,7 +144,7 @@ void consume_food_for_residents() { set_storage_count(ITEM_SMOKED_FISH, 0); set_storage_count(ITEM_BASKET_FOOD, 0); if (x <= BASE_END) { - notify("No food, residents are hungry."); + notify(tr("system.base.no_food_residents_hungry")); } } } @@ -189,17 +189,23 @@ void attempt_resident_fishing() { if (poles_broken > 0) { add_storage_count(ITEM_FISHING_POLES, -poles_broken); if (x <= BASE_END) { - string msg = - (poles_broken == 1) ? "A resident's fishing pole broke." : poles_broken + " fishing poles broke."; + string msg = tr("system.base.resident_fishing_pole_broke_one"); + if (poles_broken > 1) { + dictionary polesBrokenArgs; + polesBrokenArgs.set("count", poles_broken); + msg = trf("system.base.resident_fishing_pole_broke_many", polesBrokenArgs); + } speak_with_history(msg, true); } } if (caught > 0 && x <= BASE_END) { if (caught == 1) { - speak_with_history("Resident caught a fish and added it to storage.", true); + speak_with_history(tr("system.base.resident_caught_fish_one"), true); } else { - speak_with_history("Residents caught " + caught + " fish and added them to storage.", true); + dictionary caughtFishArgs; + caughtFishArgs.set("count", caught); + speak_with_history(trf("system.base.resident_caught_fish_many", caughtFishArgs), true); } } } @@ -237,7 +243,9 @@ void attempt_resident_fish_smoking() { add_storage_count(ITEM_SMOKED_FISH, yield); if (x <= BASE_END) { - speak_with_history("Resident smoked a fish into " + yield + " smoked fish.", true); + dictionary smokedFishArgs; + smokedFishArgs.set("yield", yield); + speak_with_history(trf("system.base.resident_smoked_fish", smokedFishArgs), true); } } } @@ -282,27 +290,11 @@ void attempt_livestock_production() { } if ((meat_produced > 0 || skins_produced > 0 || feathers_produced > 0) && x <= BASE_END) { - string msg = "Livestock produced "; - string[] outputs; - if (meat_produced > 0) - outputs.insert_last(meat_produced + " meat"); - if (skins_produced > 0) - outputs.insert_last(skins_produced + " skins"); - if (feathers_produced > 0) - outputs.insert_last(feathers_produced + " feathers"); - - for (uint i = 0; i < outputs.length(); i++) { - if (i > 0) { - if (i == outputs.length() - 1) { - msg += " and "; - } else { - msg += ", "; - } - } - msg += outputs[i]; - } - msg += " and added to storage."; - speak_with_history(msg, true); + dictionary livestockArgs; + livestockArgs.set("meat", meat_produced); + livestockArgs.set("skins", skins_produced); + livestockArgs.set("feathers", feathers_produced); + speak_with_history(trf("system.base.livestock_produced", livestockArgs), true); } } @@ -643,8 +635,12 @@ void process_daily_weapon_breakage() { for (int i = 0; i < spearsBroken; i++) { remove_random_stored_weapon(EQUIP_SPEAR, ITEM_SPEARS); } - string msg = - (spearsBroken == 1) ? "A resident's spear broke from wear." : spearsBroken + " spears broke from wear."; + string msg = tr("system.base.resident_spear_broke_one"); + if (spearsBroken > 1) { + dictionary spearsBrokenArgs; + spearsBrokenArgs.set("count", spearsBroken); + msg = trf("system.base.resident_spear_broke_many", spearsBrokenArgs); + } notify(msg); } @@ -652,8 +648,12 @@ void process_daily_weapon_breakage() { for (int i = 0; i < slingsBroken; i++) { remove_random_stored_weapon(EQUIP_SLING, ITEM_SLINGS); } - string msg = - (slingsBroken == 1) ? "A resident's sling broke from wear." : slingsBroken + " slings broke from wear."; + string msg = tr("system.base.resident_sling_broke_one"); + if (slingsBroken > 1) { + dictionary slingsBrokenArgs; + slingsBrokenArgs.set("count", slingsBroken); + msg = trf("system.base.resident_sling_broke_many", slingsBrokenArgs); + } notify(msg); } @@ -661,7 +661,12 @@ void process_daily_weapon_breakage() { for (int i = 0; i < bowsBroken; i++) { remove_random_stored_weapon(EQUIP_BOW, ITEM_BOWS); } - string msg = (bowsBroken == 1) ? "A resident's bow broke from wear." : bowsBroken + " bows broke from wear."; + string msg = tr("system.base.resident_bow_broke_one"); + if (bowsBroken > 1) { + dictionary bowsBrokenArgs; + bowsBrokenArgs.set("count", bowsBroken); + msg = trf("system.base.resident_bow_broke_many", bowsBrokenArgs); + } notify(msg); } } @@ -718,30 +723,13 @@ void attempt_resident_clothing_repairs() { } if (repairs_done > 0 && x <= BASE_END) { - string msg = (repairs_done == 1) ? "A resident is mending clothing." : "Residents are mending clothing."; - string[] materials; - if (vines_used > 0) - materials.insert_last(vines_used + " vines"); - if (skins_used > 0) - materials.insert_last(skins_used + " skins"); - if (down_used > 0) - materials.insert_last(down_used + " down"); - - if (materials.length() > 0) { - msg += " Used "; - for (uint i = 0; i < materials.length(); i++) { - if (i > 0) { - if (i == materials.length() - 1) { - msg += " and "; - } else { - msg += ", "; - } - } - msg += materials[i]; - } - msg += "."; - } - + dictionary repairArgs; + repairArgs.set("vines", vines_used); + repairArgs.set("skins", skins_used); + repairArgs.set("down", down_used); + string msg = trf("system.base.resident_clothing_repair_many", repairArgs); + if (repairs_done == 1) + msg = trf("system.base.resident_clothing_repair_one", repairArgs); speak_with_history(msg, true); } } @@ -777,8 +765,10 @@ void attempt_resident_snare_retrieval() { // Small chance the game escapes during retrieval (like normal) if (random(1, 100) <= escape_chance) { - notify("A " + snare.catch_type + " escaped while a resident checked the snare at x " + snare.position + - "."); + dictionary escapedArgs; + escapedArgs.set("catch_type", i18n_translate_fragment_value(snare.catch_type)); + escapedArgs.set("position", snare.position); + notify(trf("system.base.snare_escape_during_check", escapedArgs)); remove_snare_at(snare.position); continue; } @@ -803,7 +793,10 @@ void attempt_resident_snare_retrieval() { snare.hours_with_catch = 0; snare.hour_timer.restart(); - notify("Resident retrieved " + game_type + " from snare at x " + pos + " y 0 and reset it."); + dictionary snareRetrievedArgs; + snareRetrievedArgs.set("game_type", i18n_translate_fragment_value(game_type)); + snareRetrievedArgs.set("position", pos); + notify(trf("system.base.resident_retrieved_from_snare", snareRetrievedArgs)); } } @@ -899,7 +892,7 @@ void attempt_resident_butchering() { // Check for knife breakage if (random(1, 100) <= break_chance) { add_storage_count(ITEM_KNIVES, -1); - notify("A resident's knife broke while butchering."); + notify(tr("system.base.resident_knife_broke_butchering")); } // Add outputs to storage @@ -914,33 +907,14 @@ void attempt_resident_butchering() { if (sinew_yield > 0) add_storage_count(ITEM_SINEW, sinew_yield); - // Build notification message - string result = "Resident butchered " + game_type + ". Added "; - string[] outputs; - if (meat_yield > 0) - outputs.insert_last(meat_yield + " meat"); - if (skins_yield > 0) - outputs.insert_last(skins_yield + " skins"); - if (feathers_yield > 0) - outputs.insert_last(feathers_yield + " feathers"); - if (down_yield > 0) - outputs.insert_last(down_yield + " down"); - if (sinew_yield > 0) - outputs.insert_last(sinew_yield + " sinew"); - - for (uint i = 0; i < outputs.length(); i++) { - if (i > 0) { - if (i == outputs.length() - 1) { - result += " and "; - } else { - result += ", "; - } - } - result += outputs[i]; - } - result += " to storage."; - - notify(result); + dictionary butcherArgs; + butcherArgs.set("game_type", i18n_translate_fragment_value(game_type)); + butcherArgs.set("meat", meat_yield); + butcherArgs.set("skins", skins_yield); + butcherArgs.set("feathers", feathers_yield); + butcherArgs.set("down", down_yield); + butcherArgs.set("sinew", sinew_yield); + notify(trf("system.base.resident_butchered_result", butcherArgs)); } } @@ -1003,7 +977,9 @@ void attempt_resident_collection() { // Announce only if player is in base if (x <= BASE_END) { - speak_with_history("Resident added " + item_name + " to storage.", true); + dictionary addedArgs; + addedArgs.set("item", i18n_translate_fragment_value(item_name)); + speak_with_history(trf("system.base.resident_added_to_storage", addedArgs), true); } } @@ -1011,7 +987,12 @@ void attempt_resident_collection() { if (baskets_broken > 0) { add_storage_count(ITEM_REED_BASKETS, -baskets_broken); if (x <= BASE_END) { - string msg = (baskets_broken == 1) ? "A resident's basket broke." : baskets_broken + " baskets broke."; + string msg = tr("system.base.resident_basket_broke_one"); + if (baskets_broken > 1) { + dictionary basketBrokenArgs; + basketBrokenArgs.set("count", baskets_broken); + msg = trf("system.base.resident_basket_broke_many", basketBrokenArgs); + } speak_with_history(msg, true); } } @@ -1070,8 +1051,12 @@ void attempt_resident_foraging() { if (baskets_broken > 0) { add_storage_count(ITEM_REED_BASKETS, -baskets_broken); if (x <= BASE_END) { - string msg = (baskets_broken == 1) ? "A resident's basket broke while foraging." - : baskets_broken + " baskets broke while foraging."; + string msg = tr("system.base.resident_basket_broke_foraging_one"); + if (baskets_broken > 1) { + dictionary basketForagingArgs; + basketForagingArgs.set("count", baskets_broken); + msg = trf("system.base.resident_basket_broke_foraging_many", basketForagingArgs); + } speak_with_history(msg, true); } } @@ -1079,9 +1064,11 @@ void attempt_resident_foraging() { // Notify of production if (baskets_produced > 0 && x <= BASE_END) { if (baskets_produced == 1) { - speak_with_history("Resident gathered a basket of fruits and nuts.", true); + speak_with_history(tr("system.base.resident_gathered_basket_food_one"), true); } else { - speak_with_history("Residents gathered " + baskets_produced + " baskets of fruits and nuts.", true); + dictionary basketFoodArgs; + basketFoodArgs.set("count", baskets_produced); + speak_with_history(trf("system.base.resident_gathered_basket_food_many", basketFoodArgs), true); } } } diff --git a/src/bosses/adventure_system.nvgt b/src/bosses/adventure_system.nvgt index b45a654..1642405 100644 --- a/src/bosses/adventure_system.nvgt +++ b/src/bosses/adventure_system.nvgt @@ -13,12 +13,12 @@ void check_adventure_menu(int player_x) { void run_adventure_menu(int player_x) { if (player_x <= BASE_END) { - speak_with_history("No adventures available in the base.", true); + speak_with_history(tr("system.adventure.none_in_base"), true); return; } if (last_adventure_day == current_day) { - speak_with_history("You have already attempted an adventure today.", true); + speak_with_history(tr("system.adventure.already_attempted_today"), true); return; } @@ -31,24 +31,22 @@ void run_adventure_menu(int player_x) { if (mountain !is null) { // Mountain terrain - options.insert_last("Unicorn Hunt (Mountain Boss)"); + options.insert_last(tr("system.adventure.option.unicorn_hunt")); adventure_ids.insert_last(1); } if (mountain is null && (terrain == "forest" || terrain == "deep_forest")) { - options.insert_last("Bandit's Hideout"); + options.insert_last(tr("system.adventure.option.bandit_hideout")); adventure_ids.insert_last(ADVENTURE_BANDIT_HIDEOUT); } - i18n_translate_string_array_in_place(options); - if (options.length() == 0) { - speak_with_history("No adventures found in this area.", true); + speak_with_history(tr("system.adventure.none_in_area"), true); return; } // Show Menu - speak_with_history("Adventure Menu.", true); + speak_with_history(tr("system.adventure.menu.prompt"), true); int selection = 0; speak_with_history(options[selection], true); @@ -57,7 +55,7 @@ void run_adventure_menu(int player_x) { handle_global_volume_keys(); if (key_pressed(KEY_ESCAPE)) { - speak_with_history("Closed.", true); + speak_with_history(tr("system.menu.closed"), true); return; } diff --git a/src/bosses/bandit_hideout.nvgt b/src/bosses/bandit_hideout.nvgt index 8704901..f2ca65c 100644 --- a/src/bosses/bandit_hideout.nvgt +++ b/src/bosses/bandit_hideout.nvgt @@ -319,12 +319,12 @@ void run_bandit_hideout_adventure() { adventurePaused = !adventurePaused; if (adventurePaused) { p.pause_all(); - speak_with_history("Paused. Press backspace to resume.", true); + speak_with_history(tr("system.game.paused_prompt"), true); } else { p.resume_all(); restart_hideout_adventure_timers(); restart_all_timers(); - speak_with_history("Resumed.", true); + speak_with_history(tr("system.game.resumed"), true); } continue; } @@ -337,7 +337,7 @@ void run_bandit_hideout_adventure() { if (key_pressed(KEY_ESCAPE)) { cleanup_bandit_hideout_adventure(); - speak_with_history("You flee the hideout.", true); + speak_with_history(tr("system.adventure.bandit_hideout.flee"), true); return; } @@ -355,11 +355,15 @@ void run_bandit_hideout_adventure() { int distanceToBase = hideoutBaseX - hideoutPlayerX; if (distanceToBase < 0) distanceToBase = 0; - string terrain = get_hideout_terrain_at(hideoutPlayerX); - speak_with_history("x " + hideoutPlayerX + ", terrain " + terrain + ". Base " + distanceToBase + - " tiles east. Barricade " + hideoutBarricadeHealth + " of " + hideoutBarricadeMax + - ".", - true); + string terrain = i18n_translate_fragment_value(get_hideout_terrain_at(hideoutPlayerX)); + dictionary reportArgs; + reportArgs.set("x", hideoutPlayerX); + reportArgs.set("terrain", terrain); + reportArgs.set("distance", distanceToBase); + reportArgs.set("direction", tr("system.direction.east")); + reportArgs.set("health", hideoutBarricadeHealth); + reportArgs.set("max", hideoutBarricadeMax); + speak_with_history(trf("system.adventure.bandit_hideout.position_report", reportArgs), true); } handle_hideout_player_movement(); @@ -381,7 +385,7 @@ void run_bandit_hideout_adventure() { if (player_health <= 0) { cleanup_bandit_hideout_adventure(); - speak_with_history("The bandits cut you down.", true); + speak_with_history(tr("system.adventure.bandit_hideout.player_defeated"), true); return; } @@ -392,12 +396,12 @@ void run_bandit_hideout_adventure() { void handle_hideout_player_movement() { if (key_pressed(KEY_LEFT) && hideoutPlayerFacing != 0) { hideoutPlayerFacing = 0; - speak_with_history("west", true); + speak_with_history(tr("system.direction.west"), true); hideoutWalkTimer.restart(); } if (key_pressed(KEY_RIGHT) && hideoutPlayerFacing != 1) { hideoutPlayerFacing = 1; - speak_with_history("east", true); + speak_with_history(tr("system.direction.east"), true); hideoutWalkTimer.restart(); } @@ -777,7 +781,7 @@ int add_hideout_storage_item(int itemType, int amount) { } void give_bandit_hideout_rewards() { - speak_with_history("Victory!", true); + speak_with_history(tr("system.adventure.victory"), true); string[] rewards; rewards.insert_last("=== Victory Rewards ==="); diff --git a/src/bosses/unicorn/unicorn_boss.nvgt b/src/bosses/unicorn/unicorn_boss.nvgt index 4aca8bd..301e4eb 100644 --- a/src/bosses/unicorn/unicorn_boss.nvgt +++ b/src/bosses/unicorn/unicorn_boss.nvgt @@ -132,12 +132,12 @@ void run_unicorn_adventure() { adventurePaused = !adventurePaused; if (adventurePaused) { p.pause_all(); - speak_with_history("Paused. Press backspace to resume.", true); + speak_with_history(tr("system.game.paused_prompt"), true); } else { p.resume_all(); restart_unicorn_adventure_timers(); restart_all_timers(); - speak_with_history("Resumed.", true); + speak_with_history(tr("system.game.resumed"), true); } continue; } @@ -151,7 +151,7 @@ void run_unicorn_adventure() { // Input Handling if (key_pressed(KEY_ESCAPE)) { cleanup_unicorn_adventure(); - speak_with_history("You flee the encounter.", true); + speak_with_history(tr("system.adventure.unicorn.flee"), true); return; } @@ -168,11 +168,15 @@ void run_unicorn_adventure() { // Coordinates if (key_pressed(KEY_X)) { - string facing_dir = (unicorn.facing == 1) ? "east" : "west"; - string terrain = (player_arena_x >= BRIDGE_START && player_arena_x <= BRIDGE_END && !bridge_collapsed) - ? "wood" - : "grass"; - speak_with_history("x " + player_arena_x + ", terrain " + terrain + ". Unicorn facing " + facing_dir, true); + string facing_dir = (unicorn.facing == 1) ? tr("system.direction.east") : tr("system.direction.west"); + string terrain = (player_arena_x >= BRIDGE_START && player_arena_x <= BRIDGE_END && !bridge_collapsed) ? + i18n_translate_fragment_value("wood") : + i18n_translate_fragment_value("grass"); + dictionary reportArgs; + reportArgs.set("x", player_arena_x); + reportArgs.set("terrain", terrain); + reportArgs.set("direction", facing_dir); + speak_with_history(trf("system.adventure.unicorn.position_report", reportArgs), true); } handle_player_movement(); @@ -208,7 +212,7 @@ void run_unicorn_adventure() { if (player_health <= 0) { cleanup_unicorn_adventure(); - speak_with_history("The Unicorn trampled you.", true); + speak_with_history(tr("system.adventure.unicorn.player_trampled"), true); // Player death will be handled by main game loop checking player_health <= 0 return; } @@ -223,12 +227,12 @@ void handle_player_movement() { // Direction change announces if (key_pressed(KEY_LEFT) && player_arena_facing != 0) { player_arena_facing = 0; - speak_with_history("west", true); + speak_with_history(tr("system.direction.west"), true); arena_walk_timer.restart(); } if (key_pressed(KEY_RIGHT) && player_arena_facing != 1) { player_arena_facing = 1; - speak_with_history("east", true); + speak_with_history(tr("system.direction.east"), true); arena_walk_timer.restart(); } @@ -679,7 +683,7 @@ void play_unicorn_death_sequence() { } void give_unicorn_rewards() { - speak_with_history("Victory!", true); + speak_with_history(tr("system.adventure.victory"), true); // Calculate rewards double favor_reward = double(random(7, 10)) / 10.0; // 0.7-1.0 favor @@ -694,37 +698,40 @@ void give_unicorn_rewards() { // Build rewards display string[] rewards; - rewards.insert_last("=== Victory Rewards ==="); + rewards.insert_last(tr("system.adventure.rewards.title")); rewards.insert_last(""); - rewards.insert_last("The gods are pleased with your victory! " + format_favor(favor_reward) + " favor awarded."); - rewards.insert_last("Heal Scrolls: +" + scrolls_added + "."); + dictionary favorArgs; + favorArgs.set("favor", format_favor(favor_reward)); + rewards.insert_last(trf("system.adventure.unicorn.reward.favor_awarded", favorArgs)); + dictionary scrollArgs; + scrollArgs.set("count", scrolls_added); + rewards.insert_last(trf("system.adventure.unicorn.reward.heal_scrolls", scrollArgs)); rewards.insert_last(""); if (new_rune) { - rewards.insert_last("Learned Rune of Swiftness!"); - rewards.insert_last("You can now engrave equipment with this rune at the crafting menu."); + rewards.insert_last(tr("system.adventure.unicorn.reward.learned_rune_swiftness")); + rewards.insert_last(tr("system.adventure.unicorn.reward.engrave_unlocked")); } else { - rewards.insert_last("You have already mastered the Rune of Swiftness."); + rewards.insert_last(tr("system.adventure.unicorn.reward.mastered_rune_swiftness")); } rewards.insert_last(""); if (world_stables.length() == 0 || world_storages.length() == 0) { - rewards.insert_last("Stable or storage not built. No horses were captured."); + rewards.insert_last(tr("system.adventure.unicorn.horses.no_stable_or_storage")); } else if (horses_count >= MAX_HORSES) { - rewards.insert_last("Stable is full. No horses were captured."); + rewards.insert_last(tr("system.adventure.unicorn.horses.stable_full")); } else { int horseRoll = random(1, 100); if (horseRoll <= HORSE_ADVENTURE_CHANCE) { horses_count++; - rewards.insert_last("A horse joins your stable."); + rewards.insert_last(tr("system.adventure.unicorn.horses.joined_stable")); } else { - rewards.insert_last("No horses were captured."); + rewards.insert_last(tr("system.adventure.unicorn.horses.none_captured")); } } append_adventure_completion_rewards(ADVENTURE_UNICORN, rewards); // Display rewards in text reader - i18n_translate_string_array_in_place(rewards); - text_reader_lines(rewards, i18n_text("Unicorn Victory"), true); + text_reader_lines(rewards, tr("system.adventure.unicorn.victory_title"), true); attempt_pet_offer_from_adventure(); } diff --git a/src/constants.nvgt b/src/constants.nvgt index b7272d4..c83138a 100644 --- a/src/constants.nvgt +++ b/src/constants.nvgt @@ -32,7 +32,7 @@ const int BLESSING_RESIDENT_DURATION = 300000; const int BLESSING_SEARCH_DURATION = 300000; const int BLESSING_TRIGGER_CHANCE = 10; const int BLESSING_WALK_SPEED = 320; -const int BLESSING_SEARCH_GATHER_BONUS = 30; +const int BLESSING_SEARCH_GATHER_BONUS = 35; const int GATHER_TIME_REDUCTION_CAP = 75; const int FISH_WEIGHT_MIN = 1; const int FISH_WEIGHT_MAX = 30; diff --git a/src/crafting/craft_barricade.nvgt b/src/crafting/craft_barricade.nvgt index 1259818..9e9c357 100644 --- a/src/crafting/craft_barricade.nvgt +++ b/src/crafting/craft_barricade.nvgt @@ -6,9 +6,24 @@ string get_barricade_option_text(const string& in key, int cost, int health) { return trf(key, args); } +void speak_barricade_reinforced_status(const string& in key, int gainedHealth) { + dictionary args; + args.set("gained", gainedHealth); + args.set("health", barricade_health); + args.set("max", BARRICADE_MAX_HEALTH); + speak_with_history(trf(key, args), true); +} + +void speak_barricade_reinforced_max_status(const string& in key, int reinforceCount) { + dictionary args; + args.set("count", reinforceCount); + args.set("health", barricade_health); + speak_with_history(trf(key, args), true); +} + void run_barricade_menu() { if (barricade_health >= BARRICADE_MAX_HEALTH) { - speak_with_history("Barricade is already at full health.", true); + speak_with_history(tr("system.crafting.barricade.full_health"), true); return; } @@ -39,7 +54,7 @@ void run_barricade_menu() { } if (options.length() == 0) { - speak_with_history("No materials to reinforce the barricade.", true); + speak_with_history(tr("system.crafting.barricade.no_materials"), true); return; } speak_menu_prompt("system.crafting.barricade.prompt", options[selection]); @@ -50,7 +65,7 @@ void run_barricade_menu() { return; } if (key_pressed(KEY_ESCAPE)) { - speak_with_history("Closed.", true); + speak_with_history(tr("system.menu.closed"), true); break; } @@ -102,79 +117,71 @@ void run_barricade_menu() { void reinforce_barricade_with_sticks() { if (barricade_health >= BARRICADE_MAX_HEALTH) { - speak_with_history("Barricade is already at full health.", true); + speak_with_history(tr("system.crafting.barricade.full_health"), true); return; } if (get_personal_count(ITEM_STICKS) < BARRICADE_STICK_COST) { - speak_with_history("Not enough sticks.", true); + speak_with_history(tr("system.crafting.barricade.not_enough.sticks"), true); return; } simulate_crafting(BARRICADE_STICK_COST); add_personal_count(ITEM_STICKS, -BARRICADE_STICK_COST); int gained = add_barricade_health(BARRICADE_STICK_HEALTH); - speak_with_history("Reinforced barricade with sticks. +" + gained + " health. Now " + barricade_health + " of " + - BARRICADE_MAX_HEALTH + ".", - true); + speak_barricade_reinforced_status("system.crafting.barricade.reinforced.sticks", gained); } void reinforce_barricade_with_vines() { if (barricade_health >= BARRICADE_MAX_HEALTH) { - speak_with_history("Barricade is already at full health.", true); + speak_with_history(tr("system.crafting.barricade.full_health"), true); return; } if (get_personal_count(ITEM_VINES) < BARRICADE_VINE_COST) { - speak_with_history("Not enough vines.", true); + speak_with_history(tr("system.crafting.barricade.not_enough.vines"), true); return; } simulate_crafting(BARRICADE_VINE_COST); add_personal_count(ITEM_VINES, -BARRICADE_VINE_COST); int gained = add_barricade_health(BARRICADE_VINE_HEALTH); - speak_with_history("Reinforced barricade with vines. +" + gained + " health. Now " + barricade_health + " of " + - BARRICADE_MAX_HEALTH + ".", - true); + speak_barricade_reinforced_status("system.crafting.barricade.reinforced.vines", gained); } void reinforce_barricade_with_log() { if (barricade_health >= BARRICADE_MAX_HEALTH) { - speak_with_history("Barricade is already at full health.", true); + speak_with_history(tr("system.crafting.barricade.full_health"), true); return; } if (get_personal_count(ITEM_LOGS) < BARRICADE_LOG_COST) { - speak_with_history("Not enough logs.", true); + speak_with_history(tr("system.crafting.barricade.not_enough.logs"), true); return; } simulate_crafting(BARRICADE_LOG_COST); add_personal_count(ITEM_LOGS, -BARRICADE_LOG_COST); int gained = add_barricade_health(BARRICADE_LOG_HEALTH); - speak_with_history("Reinforced barricade with log. +" + gained + " health. Now " + barricade_health + " of " + - BARRICADE_MAX_HEALTH + ".", - true); + speak_barricade_reinforced_status("system.crafting.barricade.reinforced.log", gained); } void reinforce_barricade_with_stones() { if (barricade_health >= BARRICADE_MAX_HEALTH) { - speak_with_history("Barricade is already at full health.", true); + speak_with_history(tr("system.crafting.barricade.full_health"), true); return; } if (get_personal_count(ITEM_STONES) < BARRICADE_STONE_COST) { - speak_with_history("Not enough stones.", true); + speak_with_history(tr("system.crafting.barricade.not_enough.stones"), true); return; } simulate_crafting(BARRICADE_STONE_COST); add_personal_count(ITEM_STONES, -BARRICADE_STONE_COST); int gained = add_barricade_health(BARRICADE_STONE_HEALTH); - speak_with_history("Reinforced barricade with stones. +" + gained + " health. Now " + barricade_health + " of " + - BARRICADE_MAX_HEALTH + ".", - true); + speak_barricade_reinforced_status("system.crafting.barricade.reinforced.stones", gained); } void reinforce_barricade_max_with_sticks() { if (barricade_health >= BARRICADE_MAX_HEALTH) { - speak_with_history("Barricade is already at full health.", true); + speak_with_history(tr("system.crafting.barricade.full_health"), true); return; } @@ -197,13 +204,12 @@ void reinforce_barricade_max_with_sticks() { if (barricade_health > BARRICADE_MAX_HEALTH) barricade_health = BARRICADE_MAX_HEALTH; - speak_with_history("Reinforced barricade " + to_do + " times with sticks. Health now " + barricade_health + ".", - true); + speak_barricade_reinforced_max_status("system.crafting.barricade.reinforced_max.sticks", to_do); } void reinforce_barricade_max_with_vines() { if (barricade_health >= BARRICADE_MAX_HEALTH) { - speak_with_history("Barricade is already at full health.", true); + speak_with_history(tr("system.crafting.barricade.full_health"), true); return; } @@ -226,13 +232,12 @@ void reinforce_barricade_max_with_vines() { if (barricade_health > BARRICADE_MAX_HEALTH) barricade_health = BARRICADE_MAX_HEALTH; - speak_with_history("Reinforced barricade " + to_do + " times with vines. Health now " + barricade_health + ".", - true); + speak_barricade_reinforced_max_status("system.crafting.barricade.reinforced_max.vines", to_do); } void reinforce_barricade_max_with_log() { if (barricade_health >= BARRICADE_MAX_HEALTH) { - speak_with_history("Barricade is already at full health.", true); + speak_with_history(tr("system.crafting.barricade.full_health"), true); return; } @@ -255,12 +260,12 @@ void reinforce_barricade_max_with_log() { if (barricade_health > BARRICADE_MAX_HEALTH) barricade_health = BARRICADE_MAX_HEALTH; - speak_with_history("Reinforced barricade " + to_do + " times with log. Health now " + barricade_health + ".", true); + speak_barricade_reinforced_max_status("system.crafting.barricade.reinforced_max.log", to_do); } void reinforce_barricade_max_with_stones() { if (barricade_health >= BARRICADE_MAX_HEALTH) { - speak_with_history("Barricade is already at full health.", true); + speak_with_history(tr("system.crafting.barricade.full_health"), true); return; } @@ -283,6 +288,5 @@ void reinforce_barricade_max_with_stones() { if (barricade_health > BARRICADE_MAX_HEALTH) barricade_health = BARRICADE_MAX_HEALTH; - speak_with_history("Reinforced barricade " + to_do + " times with stones. Health now " + barricade_health + ".", - true); + speak_barricade_reinforced_max_status("system.crafting.barricade.reinforced_max.stones", to_do); } diff --git a/src/crafting/craft_buildings.nvgt b/src/crafting/craft_buildings.nvgt index 7853152..a57c606 100644 --- a/src/crafting/craft_buildings.nvgt +++ b/src/crafting/craft_buildings.nvgt @@ -97,7 +97,7 @@ void run_buildings_menu() { } if (options.length() == 0) { - speak_with_history("No buildings available.", true); + speak_with_history(tr("system.crafting.buildings.none_available"), true); return; } speak_menu_prompt("system.crafting.buildings.prompt", options[selection]); @@ -108,7 +108,7 @@ void run_buildings_menu() { return; } if (key_pressed(KEY_ESCAPE)) { - speak_with_history("Closed.", true); + speak_with_history(tr("system.menu.closed"), true); break; } @@ -155,7 +155,7 @@ void craft_firepit() { if (x <= BASE_END) { for (uint i = 0; i < world_firepits.length(); i++) { if (world_firepits[i].position <= BASE_END) { - speak_with_history("There is already a firepit in the base.", true); + speak_with_history(tr("system.crafting.buildings.firepit.already_in_base"), true); return; } } @@ -163,7 +163,7 @@ void craft_firepit() { // Check if there's already a firepit here if (get_firepit_at(x) != null) { - speak_with_history("There is already a firepit here.", true); + speak_with_history(tr("system.crafting.buildings.firepit.already_here"), true); return; } @@ -175,7 +175,7 @@ void craft_firepit() { simulate_crafting(9); add_personal_count(ITEM_STONES, -9); add_world_firepit(x); - speak_with_history("Firepit built here.", true); + speak_with_history(tr("system.crafting.buildings.firepit.built"), true); } else { speak_crafting_missing(missing); } @@ -185,7 +185,7 @@ void craft_campfire() { // Check if there's a firepit within 2 tiles WorldFirepit @firepit = get_firepit_near(x, 2); if (firepit == null) { - speak_with_history("You need a firepit within 2 tiles to build a fire.", true); + speak_with_history(tr("system.crafting.buildings.fire.requires_firepit_nearby"), true); return; } @@ -193,7 +193,7 @@ void craft_campfire() { if (firepit.position <= BASE_END) { for (uint i = 0; i < world_fires.length(); i++) { if (world_fires[i].position <= BASE_END) { - speak_with_history("There is already a fire in the base.", true); + speak_with_history(tr("system.crafting.buildings.fire.already_in_base"), true); return; } } @@ -211,7 +211,7 @@ void craft_campfire() { add_personal_count(ITEM_STICKS, -2); // Build the fire at the firepit location, not player location add_world_fire(firepit.position); - speak_with_history("Fire built at firepit.", true); + speak_with_history(tr("system.crafting.buildings.fire.built"), true); } else { speak_crafting_missing(missing); } @@ -220,13 +220,13 @@ void craft_campfire() { void craft_herb_garden() { // Can only build in base area if (x > BASE_END) { - speak_with_history("Herb garden can only be built in the base area.", true); + speak_with_history(tr("system.crafting.buildings.herb_garden.base_only"), true); return; } // Check if there's already an herb garden in the base if (get_herb_garden_at_base() != null) { - speak_with_history("There is already an herb garden in the base.", true); + speak_with_history(tr("system.crafting.buildings.herb_garden.already_in_base"), true); return; } @@ -244,7 +244,7 @@ void craft_herb_garden() { add_personal_count(ITEM_VINES, -3); add_personal_count(ITEM_LOGS, -2); add_world_herb_garden(x); - speak_with_history("Herb garden built. The base now heals faster.", true); + speak_with_history(tr("system.crafting.buildings.herb_garden.built"), true); } else { speak_crafting_missing(missing); } @@ -252,11 +252,11 @@ void craft_herb_garden() { void craft_storage() { if (x > BASE_END) { - speak_with_history("Storage must be built in the base.", true); + speak_with_history(tr("system.crafting.buildings.storage.base_only"), true); return; } if (storage_level >= STORAGE_LEVEL_UPGRADE_2) { - speak_with_history("Storage is fully upgraded.", true); + speak_with_history(tr("system.crafting.buildings.storage.fully_upgraded"), true); return; } string missing = ""; @@ -290,7 +290,9 @@ void craft_storage() { add_world_storage(x); } storage_level = targetLevel; - speak_with_history("Storage upgraded. Capacity is now " + newCapacity + " per item.", true); + dictionary storageArgs; + storageArgs.set("capacity", newCapacity); + speak_with_history(trf("system.crafting.buildings.storage.upgraded", storageArgs), true); } else { speak_crafting_missing(missing); } @@ -298,15 +300,15 @@ void craft_storage() { void craft_pasture() { if (x > BASE_END) { - speak_with_history("Pasture must be built in the base.", true); + speak_with_history(tr("system.crafting.buildings.pasture.base_only"), true); return; } if (storage_level < STORAGE_LEVEL_UPGRADE_1) { - speak_with_history("Storage must be upgraded before a pasture.", true); + speak_with_history(tr("system.crafting.buildings.pasture.requires_storage_upgrade"), true); return; } if (world_pastures.length() > 0) { - speak_with_history("Pasture already built.", true); + speak_with_history(tr("system.crafting.buildings.pasture.already_built"), true); return; } string missing = ""; @@ -320,7 +322,7 @@ void craft_pasture() { add_personal_count(ITEM_LOGS, -PASTURE_LOG_COST); add_personal_count(ITEM_ROPES, -PASTURE_ROPE_COST); add_world_pasture(x); - speak_with_history("Pasture built.", true); + speak_with_history(tr("system.crafting.buildings.pasture.built"), true); } else { speak_crafting_missing(missing); } @@ -328,15 +330,15 @@ void craft_pasture() { void craft_stable() { if (x > BASE_END) { - speak_with_history("Stable must be built in the base.", true); + speak_with_history(tr("system.crafting.buildings.stable.base_only"), true); return; } if (storage_level < STORAGE_LEVEL_UPGRADE_1) { - speak_with_history("Storage must be upgraded before a stable.", true); + speak_with_history(tr("system.crafting.buildings.stable.requires_storage_upgrade"), true); return; } if (world_stables.length() > 0) { - speak_with_history("Stable already built.", true); + speak_with_history(tr("system.crafting.buildings.stable.already_built"), true); return; } string missing = ""; @@ -353,7 +355,7 @@ void craft_stable() { add_personal_count(ITEM_STONES, -STABLE_STONE_COST); add_personal_count(ITEM_VINES, -STABLE_VINE_COST); add_world_stable(x); - speak_with_history("Stable built.", true); + speak_with_history(tr("system.crafting.buildings.stable.built"), true); } else { speak_crafting_missing(missing); } @@ -361,11 +363,11 @@ void craft_stable() { void craft_altar() { if (x > BASE_END) { - speak_with_history("Altar must be built in the base.", true); + speak_with_history(tr("system.crafting.buildings.altar.base_only"), true); return; } if (world_altars.length() > 0) { - speak_with_history("Altar already built.", true); + speak_with_history(tr("system.crafting.buildings.altar.already_built"), true); return; } string missing = ""; @@ -379,7 +381,7 @@ void craft_altar() { add_personal_count(ITEM_STONES, -ALTAR_STONE_COST); add_personal_count(ITEM_STICKS, -ALTAR_STICK_COST); add_world_altar(x); - speak_with_history("Altar built.", true); + speak_with_history(tr("system.crafting.buildings.altar.built"), true); } else { speak_crafting_missing(missing); } diff --git a/src/crafting/craft_clothing.nvgt b/src/crafting/craft_clothing.nvgt index d662dcb..165033a 100644 --- a/src/crafting/craft_clothing.nvgt +++ b/src/crafting/craft_clothing.nvgt @@ -59,7 +59,7 @@ void run_clothing_menu() { return; } if (key_pressed(KEY_ESCAPE)) { - speak_with_history("Closed.", true); + speak_with_history(tr("system.menu.closed"), true); break; } @@ -135,7 +135,7 @@ void craft_skin_hat() { add_personal_count(ITEM_SKINS, -1); add_personal_count(ITEM_VINES, -1); add_personal_count(ITEM_SKIN_HATS, 1); - speak_with_history("Crafted a Skin Hat.", true); + speak_with_history(tr("system.crafting.clothing.crafted.skin_hat"), true); } else { speak_crafting_missing(missing); } @@ -173,7 +173,9 @@ void craft_skin_hat_max() { add_personal_count(ITEM_SKINS, -max_craft); add_personal_count(ITEM_VINES, -max_craft); add_personal_count(ITEM_SKIN_HATS, max_craft); - speak_with_history("Crafted " + max_craft + " Skin Hats.", true); + dictionary skinHatArgs; + skinHatArgs.set("count", max_craft); + speak_with_history(trf("system.crafting.clothing.crafted_max.skin_hats", skinHatArgs), true); } void craft_skin_gloves() { @@ -192,7 +194,7 @@ void craft_skin_gloves() { add_personal_count(ITEM_SKINS, -1); add_personal_count(ITEM_VINES, -1); add_personal_count(ITEM_SKIN_GLOVES, 1); - speak_with_history("Crafted Skin Gloves.", true); + speak_with_history(tr("system.crafting.clothing.crafted.skin_gloves"), true); } else { speak_crafting_missing(missing); } @@ -230,7 +232,9 @@ void craft_skin_gloves_max() { add_personal_count(ITEM_SKINS, -max_craft); add_personal_count(ITEM_VINES, -max_craft); add_personal_count(ITEM_SKIN_GLOVES, max_craft); - speak_with_history("Crafted " + max_craft + " Skin Gloves.", true); + dictionary skinGlovesArgs; + skinGlovesArgs.set("count", max_craft); + speak_with_history(trf("system.crafting.clothing.crafted_max.skin_gloves", skinGlovesArgs), true); } void craft_skin_pants() { @@ -249,7 +253,7 @@ void craft_skin_pants() { add_personal_count(ITEM_SKINS, -6); add_personal_count(ITEM_VINES, -3); add_personal_count(ITEM_SKIN_PANTS, 1); - speak_with_history("Crafted Skin Pants.", true); + speak_with_history(tr("system.crafting.clothing.crafted.skin_pants"), true); } else { speak_crafting_missing(missing); } @@ -286,7 +290,9 @@ void craft_skin_pants_max() { add_personal_count(ITEM_SKINS, -(max_craft * 6)); add_personal_count(ITEM_VINES, -(max_craft * 3)); add_personal_count(ITEM_SKIN_PANTS, max_craft); - speak_with_history("Crafted " + max_craft + " Skin Pants.", true); + dictionary skinPantsArgs; + skinPantsArgs.set("count", max_craft); + speak_with_history(trf("system.crafting.clothing.crafted_max.skin_pants", skinPantsArgs), true); } void craft_skin_tunic() { @@ -305,7 +311,7 @@ void craft_skin_tunic() { add_personal_count(ITEM_SKINS, -4); add_personal_count(ITEM_VINES, -2); add_personal_count(ITEM_SKIN_TUNICS, 1); - speak_with_history("Crafted a Skin Tunic.", true); + speak_with_history(tr("system.crafting.clothing.crafted.skin_tunic"), true); } else { speak_crafting_missing(missing); } @@ -342,7 +348,9 @@ void craft_skin_tunic_max() { add_personal_count(ITEM_SKINS, -(max_craft * 4)); add_personal_count(ITEM_VINES, -(max_craft * 2)); add_personal_count(ITEM_SKIN_TUNICS, max_craft); - speak_with_history("Crafted " + max_craft + " Skin Tunics.", true); + dictionary skinTunicArgs; + skinTunicArgs.set("count", max_craft); + speak_with_history(trf("system.crafting.clothing.crafted_max.skin_tunics", skinTunicArgs), true); } void craft_moccasins() { @@ -361,7 +369,7 @@ void craft_moccasins() { add_personal_count(ITEM_SKINS, -2); add_personal_count(ITEM_VINES, -1); add_personal_count(ITEM_MOCCASINS, 1); - speak_with_history("Crafted moccasins.", true); + speak_with_history(tr("system.crafting.clothing.crafted.moccasins"), true); } else { speak_crafting_missing(missing); } @@ -399,7 +407,9 @@ void craft_moccasins_max() { add_personal_count(ITEM_SKINS, -(max_craft * 2)); add_personal_count(ITEM_VINES, -max_craft); add_personal_count(ITEM_MOCCASINS, max_craft); - speak_with_history("Crafted " + max_craft + " Moccasins.", true); + dictionary moccasinArgs; + moccasinArgs.set("count", max_craft); + speak_with_history(trf("system.crafting.clothing.crafted_max.moccasins", moccasinArgs), true); } void craft_skin_pouch() { @@ -418,7 +428,7 @@ void craft_skin_pouch() { add_personal_count(ITEM_SKINS, -2); add_personal_count(ITEM_VINES, -1); add_personal_count(ITEM_SKIN_POUCHES, 1); - speak_with_history("Crafted a Skin Pouch.", true); + speak_with_history(tr("system.crafting.clothing.crafted.skin_pouch"), true); } else { speak_crafting_missing(missing); } @@ -456,7 +466,9 @@ void craft_skin_pouch_max() { add_personal_count(ITEM_SKINS, -(max_craft * 2)); add_personal_count(ITEM_VINES, -max_craft); add_personal_count(ITEM_SKIN_POUCHES, max_craft); - speak_with_history("Crafted " + max_craft + " Skin Pouches.", true); + dictionary skinPouchArgs; + skinPouchArgs.set("count", max_craft); + speak_with_history(trf("system.crafting.clothing.crafted_max.skin_pouches", skinPouchArgs), true); } void craft_backpack() { @@ -478,7 +490,7 @@ void craft_backpack() { add_personal_count(ITEM_VINES, -5); consume_pouches(4); add_personal_count(ITEM_BACKPACKS, 1); - speak_with_history("Crafted a Backpack.", true); + speak_with_history(tr("system.crafting.clothing.crafted.backpack"), true); } else { speak_crafting_missing(missing); } @@ -521,5 +533,7 @@ void craft_backpack_max() { add_personal_count(ITEM_VINES, -(max_craft * 5)); consume_pouches(max_craft * 4); add_personal_count(ITEM_BACKPACKS, max_craft); - speak_with_history("Crafted " + max_craft + " Backpacks.", true); + dictionary backpackArgs; + backpackArgs.set("count", max_craft); + speak_with_history(trf("system.crafting.clothing.crafted_max.backpacks", backpackArgs), true); } diff --git a/src/crafting/craft_materials.nvgt b/src/crafting/craft_materials.nvgt index 8516b56..a5f4d75 100644 --- a/src/crafting/craft_materials.nvgt +++ b/src/crafting/craft_materials.nvgt @@ -14,7 +14,7 @@ void run_materials_menu() { return; } if (key_pressed(KEY_ESCAPE)) { - speak_with_history("Closed.", true); + speak_with_history(tr("system.menu.closed"), true); break; } @@ -68,14 +68,14 @@ void run_materials_menu() { void craft_arrows() { if (get_personal_count(ITEM_QUIVERS) <= 0) { - speak_with_history("You need a quiver to craft arrows.", true); + speak_with_history(tr("system.inventory.need_quiver_for_arrows"), true); return; } int currentArrows = get_personal_count(ITEM_ARROWS); int capacity = get_arrow_limit() - currentArrows; if (capacity < ARROWS_PER_CRAFT) { - speak_with_history("Not enough quiver capacity for arrows.", true); + speak_with_history(tr("system.crafting.materials.not_enough_quiver_capacity_for_arrows"), true); return; } @@ -93,7 +93,9 @@ void craft_arrows() { add_personal_count(ITEM_FEATHERS, -4); add_personal_count(ITEM_STONES, -2); add_personal_count(ITEM_ARROWS, ARROWS_PER_CRAFT); - speak_with_history("Crafted " + ARROWS_PER_CRAFT + " arrows.", true); + dictionary arrowArgs; + arrowArgs.set("count", ARROWS_PER_CRAFT); + speak_with_history(trf("system.crafting.materials.crafted.arrows", arrowArgs), true); } else { speak_crafting_missing(missing); } @@ -101,7 +103,7 @@ void craft_arrows() { void craft_arrows_max() { if (get_personal_count(ITEM_QUIVERS) <= 0) { - speak_with_history("You need a quiver to craft arrows.", true); + speak_with_history(tr("system.inventory.need_quiver_for_arrows"), true); return; } @@ -109,7 +111,7 @@ void craft_arrows_max() { int capacity = get_arrow_limit() - currentArrows; int maxByCapacity = capacity / ARROWS_PER_CRAFT; if (maxByCapacity <= 0) { - speak_with_history("Not enough quiver capacity for arrows.", true); + speak_with_history(tr("system.crafting.materials.not_enough_quiver_capacity_for_arrows"), true); return; } @@ -143,7 +145,9 @@ void craft_arrows_max() { add_personal_count(ITEM_FEATHERS, -(maxCraft * 4)); add_personal_count(ITEM_STONES, -(maxCraft * 2)); add_personal_count(ITEM_ARROWS, ARROWS_PER_CRAFT * maxCraft); - speak_with_history("Crafted " + (ARROWS_PER_CRAFT * maxCraft) + " arrows.", true); + dictionary arrowsMaxArgs; + arrowsMaxArgs.set("count", ARROWS_PER_CRAFT * maxCraft); + speak_with_history(trf("system.crafting.materials.crafted.arrows", arrowsMaxArgs), true); } void craft_bowstring() { @@ -165,7 +169,7 @@ void craft_bowstring() { simulate_crafting(3); add_personal_count(ITEM_SINEW, -3); add_personal_count(ITEM_BOWSTRINGS, 1); - speak_with_history("Crafted a bowstring.", true); + speak_with_history(tr("system.crafting.materials.crafted.bowstring"), true); } else { speak_crafting_missing(missing); } @@ -200,7 +204,9 @@ void craft_bowstring_max() { simulate_crafting(craft_time); add_personal_count(ITEM_SINEW, -(max_craft * 3)); add_personal_count(ITEM_BOWSTRINGS, max_craft); - speak_with_history("Crafted " + max_craft + " Bowstrings.", true); + dictionary bowstringArgs; + bowstringArgs.set("count", max_craft); + speak_with_history(trf("system.crafting.materials.crafted_max.bowstrings", bowstringArgs), true); } void craft_incense() { @@ -227,7 +233,7 @@ void craft_incense() { add_personal_count(ITEM_VINES, -INCENSE_VINE_COST); add_personal_count(ITEM_REEDS, -INCENSE_REED_COST); add_personal_count(ITEM_INCENSE, 1); - speak_with_history("Crafted incense.", true); + speak_with_history(tr("system.crafting.materials.crafted.incense"), true); } else { speak_crafting_missing(missing); } @@ -276,7 +282,9 @@ void craft_incense_max() { add_personal_count(ITEM_VINES, -(max_craft * INCENSE_VINE_COST)); add_personal_count(ITEM_REEDS, -(max_craft * INCENSE_REED_COST)); add_personal_count(ITEM_INCENSE, max_craft); - speak_with_history("Crafted " + max_craft + " Incense.", true); + dictionary incenseArgs; + incenseArgs.set("count", max_craft); + speak_with_history(trf("system.crafting.materials.crafted_max.incense", incenseArgs), true); } void craft_smoke_fish() { @@ -305,7 +313,9 @@ void craft_smoke_fish() { add_personal_count(ITEM_FISH, -1); add_personal_count(ITEM_STICKS, -1); add_personal_count(ITEM_SMOKED_FISH, yield); - speak_with_history("Smoked a fish into " + yield + " smoked fish.", true); + dictionary smokeFishArgs; + smokeFishArgs.set("yield", yield); + speak_with_history(trf("system.crafting.materials.smoke_fish.crafted", smokeFishArgs), true); } else { speak_crafting_missing(missing); } @@ -365,7 +375,10 @@ void craft_smoke_fish_max() { add_personal_count(ITEM_FISH, -fish_to_smoke); add_personal_count(ITEM_STICKS, -fish_to_smoke); add_personal_count(ITEM_SMOKED_FISH, total_yield); - speak_with_history("Smoked " + fish_to_smoke + " fish into " + total_yield + " smoked fish.", true); + dictionary smokeFishMaxArgs; + smokeFishMaxArgs.set("count", fish_to_smoke); + smokeFishMaxArgs.set("yield", total_yield); + speak_with_history(trf("system.crafting.materials.smoke_fish.crafted_max", smokeFishMaxArgs), true); } void butcher_small_game() { @@ -411,20 +424,22 @@ void butcher_small_game() { add_personal_count(ITEM_MEAT, 1); add_personal_count(ITEM_FEATHERS, random(3, 6)); add_personal_count(ITEM_DOWN, random(1, 3)); - speak_with_history("Butchered goose. Got 1 meat, feathers, and down.", true); + speak_with_history(tr("system.crafting.materials.butcher.goose"), true); } else if (game_type == "turkey") { add_personal_count(ITEM_MEAT, 1); add_personal_count(ITEM_FEATHERS, random(1, 4)); - speak_with_history("Butchered turkey. Got 1 meat and feathers.", true); + speak_with_history(tr("system.crafting.materials.butcher.turkey"), true); } else if (game_type == "boar carcass") { add_personal_count(ITEM_MEAT, random(2, 3)); add_personal_count(ITEM_SKINS, 3); add_personal_count(ITEM_SINEW, 2); - speak_with_history("Butchered boar. Got meat, 3 skins, and 2 sinew.", true); + speak_with_history(tr("system.crafting.materials.butcher.boar"), true); } else { add_personal_count(ITEM_MEAT, 1); add_personal_count(ITEM_SKINS, 1); - speak_with_history("Butchered " + game_type + ". Got 1 meat and 1 skin.", true); + dictionary butcherDefaultArgs; + butcherDefaultArgs.set("game", i18n_translate_fragment_value(game_type)); + speak_with_history(trf("system.crafting.materials.butcher.default", butcherDefaultArgs), true); } // Play sound @@ -480,7 +495,7 @@ void butcher_small_game_max() { max_craft = skins_space; if (max_craft <= 0) { - speak_with_history("No space for outputs.", true); + speak_with_history(tr("system.crafting.materials.butcher.no_space_outputs"), true); return; } @@ -539,18 +554,13 @@ void butcher_small_game_max() { add_personal_count(ITEM_DOWN, total_down); add_personal_count(ITEM_SINEW, total_sinew); - // Build result message - string result = "Butchered " + max_craft + " game. Got " + total_meat + " meat"; - if (total_skins > 0) - result += ", " + total_skins + " skins"; - if (total_feathers > 0) - result += ", feathers"; - if (total_down > 0) - result += ", and down"; - if (total_sinew > 0) - result += ", and " + total_sinew + " sinew"; - result += "."; - - speak_with_history(result, true); + dictionary butcherMaxArgs; + butcherMaxArgs.set("count", max_craft); + butcherMaxArgs.set("meat", total_meat); + butcherMaxArgs.set("skins", total_skins); + butcherMaxArgs.set("feathers", total_feathers); + butcherMaxArgs.set("down", total_down); + butcherMaxArgs.set("sinew", total_sinew); + speak_with_history(trf("system.crafting.materials.butcher.max_result", butcherMaxArgs), true); p.play_stationary("sounds/items/miscellaneous.ogg", false); } diff --git a/src/crafting/craft_runes.nvgt b/src/crafting/craft_runes.nvgt index 346e17e..324e4cf 100644 --- a/src/crafting/craft_runes.nvgt +++ b/src/crafting/craft_runes.nvgt @@ -143,7 +143,7 @@ void decrement_unruned_equipment(int equip_type) { void run_runes_menu() { // Check if in base area if (x > BASE_END) { - speak_with_history("Rune engraving can only be done in the base area.", true); + speak_with_history(tr("system.crafting.runes.base_only"), true); return; } @@ -154,18 +154,20 @@ void run_runes_menu() { get_unlocked_rune_types(unlocked_runes); for (uint i = 0; i < unlocked_runes.length(); i++) { int rune_type = unlocked_runes[i]; - string label = get_rune_name(rune_type) + " (1 Clay, 1 Favor) [Requires Knife]"; + dictionary runeOptionArgs; + runeOptionArgs.set("rune", get_rune_name(rune_type)); + string label = trf("system.crafting.runes.option", runeOptionArgs); rune_options.insert_last(label); rune_types.insert_last(rune_type); } if (rune_options.length() == 0) { - speak_with_history("No runes unlocked yet.", true); + speak_with_history(tr("system.crafting.runes.none_unlocked"), true); return; } int selection = 0; - speak_with_history("Runes. " + rune_options[selection], true); + speak_menu_prompt("system.crafting.runes.prompt", rune_options[selection]); while (true) { wait(5); @@ -173,7 +175,7 @@ void run_runes_menu() { return; } if (key_pressed(KEY_ESCAPE)) { - speak_with_history("Closed.", true); + speak_with_history(tr("system.menu.closed"), true); break; } @@ -213,19 +215,24 @@ void run_rune_equipment_menu(int rune_type) { int unruned_count = get_unruned_equipment_count(equip_type); if (unruned_count > 0) { string name = get_base_equipment_name(equip_type); - equipment_options.insert_last(i18n_text(name + " (" + unruned_count + " available)")); + dictionary equipmentOptionArgs; + equipmentOptionArgs.set("name", name); + equipmentOptionArgs.set("count", unruned_count); + equipment_options.insert_last(trf("system.crafting.runes.equipment_option", equipmentOptionArgs)); equipment_types.insert_last(equip_type); } } if (equipment_options.length() == 0) { - speak_with_history("No equipment available to engrave.", true); + speak_with_history(tr("system.crafting.runes.no_equipment_available"), true); return; } int selection = 0; - speak_with_history( - "Select equipment to engrave with " + get_rune_name(rune_type) + ". " + equipment_options[selection], true); + dictionary equipmentPromptArgs; + equipmentPromptArgs.set("rune", get_rune_name(rune_type)); + equipmentPromptArgs.set("option", equipment_options[selection]); + speak_with_history(trf("system.crafting.runes.select_equipment_prompt", equipmentPromptArgs), true); while (true) { wait(5); @@ -233,7 +240,7 @@ void run_rune_equipment_menu(int rune_type) { return; } if (key_pressed(KEY_ESCAPE)) { - speak_with_history("Closed.", true); + speak_with_history(tr("system.menu.closed"), true); break; } @@ -281,7 +288,9 @@ void engrave_rune(int equip_type, int rune_type) { // Check equipment is still available if (get_unruned_equipment_count(equip_type) < 1) { - speak_with_history("No " + get_base_equipment_name(equip_type) + " available.", true); + dictionary noItemArgs; + noItemArgs.set("item", get_base_equipment_name(equip_type)); + speak_with_history(trf("system.crafting.runes.no_item_available", noItemArgs), true); return; } @@ -299,8 +308,14 @@ void engrave_rune(int equip_type, int rune_type) { // Play crafting animation simulate_crafting(6); - string runed_name = "Runed " + get_base_equipment_name(equip_type) + " of " + get_rune_effect_name(rune_type); - speak_with_history("Engraved " + runed_name + ".", true); + dictionary runedNameArgs; + runedNameArgs.set("equipment", get_base_equipment_name(equip_type)); + runedNameArgs.set("rune", get_rune_effect_name(rune_type)); + string runed_name = trf("system.crafting.runes.runed_name", runedNameArgs); + + dictionary engravedArgs; + engravedArgs.set("item", runed_name); + speak_with_history(trf("system.crafting.runes.engraved", engravedArgs), true); } else { speak_crafting_missing(missing); } @@ -314,7 +329,9 @@ void engrave_rune_max(int equip_type, int rune_type) { int unruned_count = get_unruned_equipment_count(equip_type); if (unruned_count < 1) { - speak_with_history("No " + get_base_equipment_name(equip_type) + " available.", true); + dictionary noItemArgs; + noItemArgs.set("item", get_base_equipment_name(equip_type)); + speak_with_history(trf("system.crafting.runes.no_item_available", noItemArgs), true); return; } @@ -355,5 +372,9 @@ void engrave_rune_max(int equip_type, int rune_type) { string item_name = (max_craft == 1) ? get_base_equipment_name(equip_type) : get_base_equipment_name_plural(equip_type); - speak_with_history("Engraved " + max_craft + " " + item_name + " with " + get_rune_name(rune_type) + ".", true); + dictionary engravedMaxArgs; + engravedMaxArgs.set("count", max_craft); + engravedMaxArgs.set("item", item_name); + engravedMaxArgs.set("rune", get_rune_name(rune_type)); + speak_with_history(trf("system.crafting.runes.engraved_max", engravedMaxArgs), true); } diff --git a/src/crafting/craft_tools.nvgt b/src/crafting/craft_tools.nvgt index 2c63228..f51a62b 100644 --- a/src/crafting/craft_tools.nvgt +++ b/src/crafting/craft_tools.nvgt @@ -18,7 +18,7 @@ void run_tools_menu() { return; } if (key_pressed(KEY_ESCAPE)) { - speak_with_history("Closed.", true); + speak_with_history(tr("system.menu.closed"), true); break; } @@ -99,7 +99,7 @@ void craft_knife() { simulate_crafting(2); add_personal_count(ITEM_STONES, -2); add_personal_count(ITEM_KNIVES, 1); - speak_with_history("Crafted a Stone Knife.", true); + speak_with_history(tr("system.crafting.tools.crafted.stone_knife"), true); } else { speak_crafting_missing(missing); } @@ -126,7 +126,9 @@ void craft_knife_max() { simulate_crafting(craft_time); add_personal_count(ITEM_STONES, -(max_possible * 2)); add_personal_count(ITEM_KNIVES, max_possible); - speak_with_history("Crafted " + max_possible + " Stone Knives.", true); + dictionary knifeArgs; + knifeArgs.set("count", max_possible); + speak_with_history(trf("system.crafting.tools.crafted_max.stone_knives", knifeArgs), true); } void craft_snare() { @@ -145,7 +147,7 @@ void craft_snare() { add_personal_count(ITEM_STICKS, -1); add_personal_count(ITEM_VINES, -2); add_personal_count(ITEM_SNARES, 1); - speak_with_history("Crafted a Snare.", true); + speak_with_history(tr("system.crafting.tools.crafted.snare"), true); } else { speak_crafting_missing(missing); } @@ -183,7 +185,9 @@ void craft_snare_max() { add_personal_count(ITEM_STICKS, -max_craft); add_personal_count(ITEM_VINES, -(max_craft * 2)); add_personal_count(ITEM_SNARES, max_craft); - speak_with_history("Crafted " + max_craft + " Snares.", true); + dictionary snareArgs; + snareArgs.set("count", max_craft); + speak_with_history(trf("system.crafting.tools.crafted_max.snares", snareArgs), true); } void craft_fishing_pole() { @@ -202,7 +206,7 @@ void craft_fishing_pole() { add_personal_count(ITEM_STICKS, -1); add_personal_count(ITEM_VINES, -2); add_personal_count(ITEM_FISHING_POLES, 1); - speak_with_history("Crafted a Fishing Pole.", true); + speak_with_history(tr("system.crafting.tools.crafted.fishing_pole"), true); } else { speak_crafting_missing(missing); } @@ -240,7 +244,9 @@ void craft_fishing_pole_max() { add_personal_count(ITEM_STICKS, -max_craft); add_personal_count(ITEM_VINES, -(max_craft * 2)); add_personal_count(ITEM_FISHING_POLES, max_craft); - speak_with_history("Crafted " + max_craft + " Fishing Poles.", true); + dictionary fishingPoleArgs; + fishingPoleArgs.set("count", max_craft); + speak_with_history(trf("system.crafting.tools.crafted_max.fishing_poles", fishingPoleArgs), true); } void craft_rope() { @@ -256,7 +262,7 @@ void craft_rope() { simulate_crafting(3); add_personal_count(ITEM_VINES, -3); add_personal_count(ITEM_ROPES, 1); - speak_with_history("Crafted rope.", true); + speak_with_history(tr("system.crafting.tools.crafted.rope"), true); } else { speak_crafting_missing(missing); } @@ -284,7 +290,9 @@ void craft_rope_max() { simulate_crafting(craft_time); add_personal_count(ITEM_VINES, -(max_craft * 3)); add_personal_count(ITEM_ROPES, max_craft); - speak_with_history("Crafted " + max_craft + " Rope.", true); + dictionary ropeArgs; + ropeArgs.set("count", max_craft); + speak_with_history(trf("system.crafting.tools.crafted_max.ropes", ropeArgs), true); } void craft_quiver() { @@ -303,7 +311,7 @@ void craft_quiver() { add_personal_count(ITEM_SKINS, -2); add_personal_count(ITEM_VINES, -2); add_personal_count(ITEM_QUIVERS, 1); - speak_with_history("Crafted a Quiver.", true); + speak_with_history(tr("system.crafting.tools.crafted.quiver"), true); } else { speak_crafting_missing(missing); } @@ -341,7 +349,9 @@ void craft_quiver_max() { add_personal_count(ITEM_SKINS, -(maxCraft * 2)); add_personal_count(ITEM_VINES, -(maxCraft * 2)); add_personal_count(ITEM_QUIVERS, maxCraft); - speak_with_history("Crafted " + maxCraft + " Quivers.", true); + dictionary quiverArgs; + quiverArgs.set("count", maxCraft); + speak_with_history(trf("system.crafting.tools.crafted_max.quivers", quiverArgs), true); } void craft_canoe() { @@ -372,7 +382,7 @@ void craft_canoe() { add_personal_count(ITEM_ROPES, -2); add_personal_count(ITEM_REEDS, -6); add_personal_count(ITEM_CANOES, 1); - speak_with_history("Crafted a Canoe.", true); + speak_with_history(tr("system.crafting.tools.crafted.canoe"), true); } else { speak_crafting_missing(missing); } @@ -434,7 +444,9 @@ void craft_canoe_max() { add_personal_count(ITEM_ROPES, -(maxCraft * 2)); add_personal_count(ITEM_REEDS, -(maxCraft * 6)); add_personal_count(ITEM_CANOES, maxCraft); - speak_with_history("Crafted " + maxCraft + " Canoes.", true); + dictionary canoeArgs; + canoeArgs.set("count", maxCraft); + speak_with_history(trf("system.crafting.tools.crafted_max.canoes", canoeArgs), true); } void craft_reed_basket() { @@ -450,7 +462,7 @@ void craft_reed_basket() { simulate_crafting(3); add_personal_count(ITEM_REEDS, -3); add_personal_count(ITEM_REED_BASKETS, 1); - speak_with_history("Crafted a reed basket.", true); + speak_with_history(tr("system.crafting.tools.crafted.reed_basket"), true); } else { speak_crafting_missing(missing); } @@ -478,7 +490,9 @@ void craft_reed_basket_max() { simulate_crafting(craft_time); add_personal_count(ITEM_REEDS, -(max_craft * 3)); add_personal_count(ITEM_REED_BASKETS, max_craft); - speak_with_history("Crafted " + max_craft + " Reed Baskets.", true); + dictionary reedBasketArgs; + reedBasketArgs.set("count", max_craft); + speak_with_history(trf("system.crafting.tools.crafted_max.reed_baskets", reedBasketArgs), true); } void craft_clay_pot() { @@ -501,7 +515,7 @@ void craft_clay_pot() { simulate_crafting(3); add_personal_count(ITEM_CLAY, -3); add_personal_count(ITEM_CLAY_POTS, 1); - speak_with_history("Crafted a clay pot.", true); + speak_with_history(tr("system.crafting.tools.crafted.clay_pot"), true); } else { speak_crafting_missing(missing); } @@ -536,5 +550,7 @@ void craft_clay_pot_max() { simulate_crafting(craft_time); add_personal_count(ITEM_CLAY, -(max_craft * 3)); add_personal_count(ITEM_CLAY_POTS, max_craft); - speak_with_history("Crafted " + max_craft + " Clay Pots.", true); + dictionary clayPotArgs; + clayPotArgs.set("count", max_craft); + speak_with_history(trf("system.crafting.tools.crafted_max.clay_pots", clayPotArgs), true); } diff --git a/src/crafting/craft_weapons.nvgt b/src/crafting/craft_weapons.nvgt index fc7ddcd..10d5aa7 100644 --- a/src/crafting/craft_weapons.nvgt +++ b/src/crafting/craft_weapons.nvgt @@ -11,7 +11,7 @@ void run_weapons_menu() { return; } if (key_pressed(KEY_ESCAPE)) { - speak_with_history("Closed.", true); + speak_with_history(tr("system.menu.closed"), true); break; } @@ -76,7 +76,7 @@ void craft_spear() { add_personal_count(ITEM_VINES, -1); add_personal_count(ITEM_STONES, -1); add_personal_count(ITEM_SPEARS, 1); - speak_with_history("Crafted a Spear.", true); + speak_with_history(tr("system.crafting.weapons.crafted.spear"), true); } else { speak_crafting_missing(missing); } @@ -124,7 +124,9 @@ void craft_spear_max() { add_personal_count(ITEM_VINES, -max_craft); add_personal_count(ITEM_STONES, -max_craft); add_personal_count(ITEM_SPEARS, max_craft); - speak_with_history("Crafted " + max_craft + " Spears.", true); + dictionary spearArgs; + spearArgs.set("count", max_craft); + speak_with_history(trf("system.crafting.weapons.crafted_max.spears", spearArgs), true); } void craft_sling() { @@ -143,7 +145,7 @@ void craft_sling() { add_personal_count(ITEM_SKINS, -1); add_personal_count(ITEM_VINES, -2); add_personal_count(ITEM_SLINGS, 1); - speak_with_history("Crafted a Sling.", true); + speak_with_history(tr("system.crafting.weapons.crafted.sling"), true); } else { speak_crafting_missing(missing); } @@ -181,7 +183,9 @@ void craft_sling_max() { add_personal_count(ITEM_SKINS, -max_craft); add_personal_count(ITEM_VINES, -(max_craft * 2)); add_personal_count(ITEM_SLINGS, max_craft); - speak_with_history("Crafted " + max_craft + " Slings.", true); + dictionary slingArgs; + slingArgs.set("count", max_craft); + speak_with_history(trf("system.crafting.weapons.crafted_max.slings", slingArgs), true); } void craft_bow() { @@ -200,7 +204,7 @@ void craft_bow() { add_personal_count(ITEM_STICKS, -1); add_personal_count(ITEM_BOWSTRINGS, -1); add_personal_count(ITEM_BOWS, 1); - speak_with_history("Crafted a Bow.", true); + speak_with_history(tr("system.crafting.weapons.crafted.bow"), true); } else { speak_crafting_missing(missing); } @@ -238,7 +242,9 @@ void craft_bow_max() { add_personal_count(ITEM_STICKS, -max_craft); add_personal_count(ITEM_BOWSTRINGS, -max_craft); add_personal_count(ITEM_BOWS, max_craft); - speak_with_history("Crafted " + max_craft + " Bows.", true); + dictionary bowArgs; + bowArgs.set("count", max_craft); + speak_with_history(trf("system.crafting.weapons.crafted_max.bows", bowArgs), true); } void craft_axe() { @@ -262,7 +268,7 @@ void craft_axe() { add_personal_count(ITEM_VINES, -1); add_personal_count(ITEM_STONES, -2); add_personal_count(ITEM_AXES, 1); - speak_with_history("Crafted a Stone Axe.", true); + speak_with_history(tr("system.crafting.weapons.crafted.stone_axe"), true); } else { speak_crafting_missing(missing); } @@ -309,5 +315,7 @@ void craft_axe_max() { add_personal_count(ITEM_VINES, -max_craft); add_personal_count(ITEM_STONES, -(max_craft * 2)); add_personal_count(ITEM_AXES, max_craft); - speak_with_history("Crafted " + max_craft + " Stone Axes.", true); + dictionary axeArgs; + axeArgs.set("count", max_craft); + speak_with_history(trf("system.crafting.weapons.crafted_max.stone_axes", axeArgs), true); } diff --git a/src/crafting/crafting_core.nvgt b/src/crafting/crafting_core.nvgt index 616b97a..764ad4a 100644 --- a/src/crafting/crafting_core.nvgt +++ b/src/crafting/crafting_core.nvgt @@ -160,7 +160,7 @@ void run_crafting_menu() { return; } if (key_pressed(KEY_ESCAPE)) { - speak_with_history("Closed.", true); + speak_with_history(tr("system.menu.closed"), true); break; } @@ -203,7 +203,7 @@ void run_crafting_menu() { } void simulate_crafting(int item_count) { - speak_with_history("Crafting...", true); + speak_with_history(tr("system.crafting.in_progress"), true); // Nothing should take less than 4. if (item_count < 4) { item_count = 4; diff --git a/src/enemies/bandit.nvgt b/src/enemies/bandit.nvgt index 9c4b067..be97f16 100644 --- a/src/enemies/bandit.nvgt +++ b/src/enemies/bandit.nvgt @@ -386,13 +386,15 @@ void try_attack_barricade_bandit(Bandit @bandit) { int before_health = bandit.health; damage_bandit_at(bandit.position, counterDamage); if (before_health - counterDamage <= 0 && x <= BASE_END) { - speak_with_history("Residents killed an attacking bandit.", true); + dictionary residentsKilledArgs; + residentsKilledArgs.set("enemy", i18n_translate_fragment_value("bandit")); + speak_with_history(trf("system.enemies.residents_killed_attacker", residentsKilledArgs), true); } } } if (barricade_health == 0) { - notify("The barricade has fallen!"); + notify(tr("system.base.barricade_fallen")); } } diff --git a/src/enemies/undead.nvgt b/src/enemies/undead.nvgt index fa0fe1a..dbac127 100644 --- a/src/enemies/undead.nvgt +++ b/src/enemies/undead.nvgt @@ -305,13 +305,15 @@ void try_attack_barricade_undead(Undead @undead) { int before_health = undead.health; damage_undead_at(undead.position, counterDamage); if (before_health - counterDamage <= 0 && x <= BASE_END) { - speak_with_history("Residents killed an attacking " + get_undead_label(undead.undead_type) + ".", true); + dictionary residentsKilledArgs; + residentsKilledArgs.set("enemy", i18n_translate_fragment_value(get_undead_label(undead.undead_type))); + speak_with_history(trf("system.enemies.residents_killed_attacker", residentsKilledArgs), true); } } } if (barricade_health == 0) { - notify("The barricade has fallen!"); + notify(tr("system.base.barricade_fallen")); } } @@ -384,7 +386,7 @@ void try_capture_resident_vampyr(Undead @undead) { if (residents_count < 0) residents_count = 0; undead_residents_pending++; - speak_with_history("A resident has been taken.", true); + speak_with_history(tr("system.enemies.resident_taken"), true); start_vampyr_retreat(undead); } } diff --git a/src/environment.nvgt b/src/environment.nvgt index 468fd6b..0d7ab86 100644 --- a/src/environment.nvgt +++ b/src/environment.nvgt @@ -26,8 +26,11 @@ void apply_falling_damage(int fall_height) { } // Feedback - speak_with_history( - "Fell " + fall_height + " feet! Took " + damage + " damage. " + player_health + " health remaining.", true); + dictionary fallArgs; + fallArgs.set("height", fall_height); + fallArgs.set("damage", damage); + fallArgs.set("health", player_health); + speak_with_history(trf("system.environment.fall.damage_report", fallArgs), true); } // Tree Object class Tree { @@ -765,14 +768,16 @@ void perform_search(int current_x) { add_personal_count(ITEM_SMALL_GAME, 1); personal_small_game_types.insert_last(s.catch_type); add_personal_count(ITEM_SNARES, 1); // Recover snare - speak_with_history("Collected " + s.catch_type + " and snare.", true); + dictionary collectedSnareArgs; + collectedSnareArgs.set("catch_type", i18n_translate_fragment_value(s.catch_type)); + speak_with_history(trf("system.environment.snare.collected_with_catch", collectedSnareArgs), true); } else { if (get_personal_count(ITEM_SNARES) >= get_personal_stack_limit()) { speak_cant_carry_any_more_item(ITEM_SNARES); return; } add_personal_count(ITEM_SNARES, 1); // Recover snare - speak_with_history("Collected snare.", true); + speak_with_history(tr("system.environment.snare.collected_empty"), true); } string collectSoundItem = s.has_catch ? s.catch_type : "snare"; play_item_collect_sound(collectSoundItem); @@ -844,12 +849,12 @@ void perform_search(int current_x) { if (@nearest != null) { if (nearest.is_chopped) { - speak_with_history("This tree has been cut down.", true); + speak_with_history(tr("system.environment.tree.cut_down"), true); return; } if (nearest.depleted) { - speak_with_history("This tree is empty.", true); + speak_with_history(tr("system.environment.tree.empty"), true); return; } @@ -904,7 +909,7 @@ void perform_search(int current_x) { nearest.minutes_since_depletion = 0; } } else { - speak_with_history("This area has nothing left.", true); + speak_with_history(tr("system.environment.area.nothing_left"), true); } return; } @@ -927,7 +932,9 @@ void start_climbing_tree(int target_x) { climbing = true; climb_target_y = ground_elevation + tree.height; climb_timer.restart(); - speak_with_history("Started climbing tree. Height is " + tree.height + " feet.", true); + dictionary climbTreeArgs; + climbTreeArgs.set("height", tree.height); + speak_with_history(trf("system.environment.tree.climb_started", climbTreeArgs), true); } void update_climbing() { @@ -951,7 +958,9 @@ void update_climbing() { climbing = false; int ground_elevation = get_mountain_elevation_at(x); int height_above_ground = y - ground_elevation; - speak_with_history("Reached the top at " + height_above_ground + " feet.", true); + dictionary reachedTopArgs; + reachedTopArgs.set("height", height_above_ground); + speak_with_history(trf("system.environment.tree.climb_reached_top", reachedTopArgs), true); attempt_pet_offer_from_tree(); } } @@ -963,7 +972,7 @@ void update_climbing() { if (y <= climb_target_y) { climbing = false; y = climb_target_y; - speak_with_history("Safely reached the ground.", true); + speak_with_history(tr("system.environment.tree.climb_reached_ground"), true); } } } @@ -977,7 +986,7 @@ void climb_down_tree() { climbing = true; climb_target_y = ground_elevation; climb_timer.restart(); - speak_with_history("Climbing down.", true); + speak_with_history(tr("system.environment.tree.climb_down"), true); } void start_falling() { @@ -1065,16 +1074,16 @@ bool can_move_mountain(int from_x, int to_x) { if (mountain.is_steep_section(from_x, to_x)) { // Need rope if (get_personal_count(ITEM_ROPES) < 1) { - speak_movement_blocked("You'll need a rope to climb there."); + speak_movement_blocked(tr("system.environment.movement.need_rope")); return false; } // Prompt for rope climb int elevation_change = mountain.get_elevation_change(from_x, to_x); if (elevation_change > 0) { - speak_movement_blocked("Press up to climb up."); + speak_movement_blocked(tr("system.environment.movement.press_up_climb")); } else { - speak_movement_blocked("Press down to climb down."); + speak_movement_blocked(tr("system.environment.movement.press_down_climb")); } // Store pending rope climb info @@ -1091,7 +1100,7 @@ bool can_enter_stream_tile(int pos) { return true; if (get_personal_count(ITEM_CANOES) > 0) return true; - speak_movement_blocked("You need a canoe to cross deep water."); + speak_movement_blocked(tr("system.environment.movement.need_canoe")); return false; } @@ -1132,8 +1141,12 @@ void start_rope_climb(bool climbing_up, int target_x, int target_elevation) { // Calculate distance to climb (use actual distance from current position) int distance = abs(elevation_diff); - string direction = rope_climb_up ? "up" : "down"; - speak_with_history("Climbing " + direction + ". " + distance + " feet.", true); + string direction = rope_climb_up ? tr("system.environment.rope_climb.direction.up") + : tr("system.environment.rope_climb.direction.down"); + dictionary ropeClimbArgs; + ropeClimbArgs.set("direction", direction); + ropeClimbArgs.set("distance", distance); + speak_with_history(trf("system.environment.rope_climb.progress", ropeClimbArgs), true); rope_climb_sound_handle = -1; } @@ -1188,7 +1201,9 @@ void complete_rope_climb() { // Play footstep for new terrain play_footstep(x, BASE_END, GRASS_END); - speak_with_history("Reached elevation " + y + ".", true); + dictionary elevationArgs; + elevationArgs.set("elevation", y); + speak_with_history(trf("system.environment.rope_climb.reached_elevation", elevationArgs), true); } void check_rope_climb_fall() { diff --git a/src/fishing.nvgt b/src/fishing.nvgt index b5bf7a9..6d6291f 100644 --- a/src/fishing.nvgt +++ b/src/fishing.nvgt @@ -125,12 +125,12 @@ string get_random_fish_type() { string get_fish_size_label(int weight) { int clamped = clamp_fish_weight(weight); if (clamped <= 7) - return "small"; + return tr("system.fishing.size.small"); if (clamped <= 17) - return "medium sized"; + return tr("system.fishing.size.medium"); if (clamped <= 27) - return "large"; - return "monster"; + return tr("system.fishing.size.large"); + return tr("system.fishing.size.monster"); } void break_fishing_pole(string message) { @@ -142,7 +142,7 @@ void break_fishing_pole(string message) { reset_fishing_session(); if (message == "") { - message = "Your fishing pole broke."; + message = tr("system.fishing.pole_broke.default"); } speak_with_history(message, true); } @@ -158,14 +158,14 @@ void start_casting() { if (is_casting || line_in_water || fish_on_line || is_reeling) return; if (!fishing_pole_equipped) { - speak_with_history("You need a fishing pole equipped.", true); + speak_with_history(tr("system.fishing.require_pole_equipped"), true); return; } int stream_start = -1; int stream_end = -1; if (!get_nearby_stream(x, FISHING_NEAR_STREAM_RANGE, stream_start, stream_end)) { - speak_with_history("You need to be within 2 tiles of a stream.", true); + speak_with_history(tr("system.fishing.require_near_stream"), true); return; } @@ -231,7 +231,7 @@ void release_cast() { p.play_stationary("sounds/actions/bad_cast.ogg", false); line_position = -1; if (random(1, 100) <= FISHING_BAD_CAST_BREAK_CHANCE) { - break_fishing_pole("Your fishing pole broke."); + break_fishing_pole(tr("system.fishing.pole_broke.default")); return; } } @@ -260,7 +260,7 @@ void update_waiting_for_fish() { reel_position = (line_position >= 0) ? line_position : get_random_stream_tile(); reel_direction = 0; hooked_fish_type = get_random_fish_type(); - speak_with_history("A fish is on the line!", true); + speak_with_history(tr("system.fishing.fish_on_line"), true); break; } } @@ -327,8 +327,13 @@ void catch_fish() { string fish_name = hooked_fish_type; if (fish_name == "") - fish_name = "fish"; - speak_with_history("Caught a " + size_label + " " + fish_name + ".", true); + fish_name = i18n_translate_fragment_value("fish"); + else + fish_name = i18n_translate_fragment_value(fish_name); + dictionary catchArgs; + catchArgs.set("size", size_label); + catchArgs.set("fish", fish_name); + speak_with_history(trf("system.fishing.caught", catchArgs), true); reset_fishing_session(); } @@ -349,9 +354,9 @@ void release_reel() { if (is_any_water_at(reel_position)) { if (random(1, 100) <= FISHING_EARLY_ESCAPE_CHANCE) { - lose_fish("The fish slipped off in the water."); + lose_fish(tr("system.fishing.fish_slipped_off_water")); } else { - speak_with_history("The fish is still on the line.", true); + speak_with_history(tr("system.fishing.fish_still_on_line"), true); } return; } @@ -368,7 +373,7 @@ void release_reel() { if (past_player) { p.play_stationary("sounds/actions/bad_cast.ogg", false); if (random(1, 100) <= FISHING_LATE_ESCAPE_CHANCE) { - lose_fish("The fish got away."); + lose_fish(tr("system.fishing.fish_got_away")); } else { catch_fish(); } @@ -377,9 +382,9 @@ void release_reel() { if (before_player) { if (random(1, 100) <= FISHING_EARLY_ESCAPE_CHANCE) { - lose_fish("The fish got away."); + lose_fish(tr("system.fishing.fish_got_away")); } else { - speak_with_history("The fish is still on the line.", true); + speak_with_history(tr("system.fishing.fish_still_on_line"), true); } return; } @@ -390,15 +395,15 @@ bool handle_fishing_breaks() { return false; if (!fishing_pole_equipped) { - break_fishing_pole("You switched weapons and your fishing pole broke."); + break_fishing_pole(tr("system.fishing.pole_broke.switched_weapons")); return true; } if (key_down(KEY_LEFT) || key_down(KEY_RIGHT) || key_pressed(KEY_UP) || jumping) { if (fish_on_line || is_reeling) { - break_fishing_pole("You moved and the fish got away. Your fishing pole broke."); + break_fishing_pole(tr("system.fishing.pole_broke.moved_fish_got_away")); } else { - break_fishing_pole("You moved and your fishing pole broke."); + break_fishing_pole(tr("system.fishing.pole_broke.moved")); } return true; } @@ -431,7 +436,7 @@ void update_fishing() { catch_chance = 0; fishing_checks_done = 0; fishing_timer.restart(); - speak_with_history("You stop fishing.", true); + speak_with_history(tr("system.fishing.stopped"), true); } else { update_waiting_for_fish(); } diff --git a/src/flying_creature_template.nvgt b/src/flying_creature_template.nvgt index c5b1baa..d646290 100644 --- a/src/flying_creature_template.nvgt +++ b/src/flying_creature_template.nvgt @@ -67,5 +67,5 @@ // add_personal_count(ITEM_MEAT, 1); // add_personal_count(ITEM_FEATHERS, random(2, 4)); // add_personal_count(ITEM_DOWN, random(1, 2)); -// speak_with_history("Butchered duck. Got 1 meat, feathers, and down.", true); +// speak_with_history(tr("system.crafting.butcher.duck_example"), true); // } diff --git a/src/fylgja_system.nvgt b/src/fylgja_system.nvgt index 2999770..26f2565 100644 --- a/src/fylgja_system.nvgt +++ b/src/fylgja_system.nvgt @@ -10,11 +10,11 @@ string[] fylgjaStageNames = {"tenuous", "faint", "stirring", "budding", "kindle "bound", "sworn", "ascendant", "ultimate"}; int[] adventureIds = {ADVENTURE_UNICORN}; -string[] adventureStageTargets = {"unicorn"}; +string[] adventureStageTargetKeys = {"unicorn"}; int[] adventureCompletionCounts = {0}; int[] fylgjaAdventureIds = {ADVENTURE_UNICORN}; -string[] fylgjaNames = {"Unicorn"}; +string[] fylgjaNameKeys = {"unicorn"}; int lastFylgjaDay = -1; bool fylgjaCharging = false; @@ -65,7 +65,7 @@ bool is_fylgja_unlocked(int fylgjaIndex) { int get_unlocked_fylgja_count() { int unlockedCount = 0; - for (uint i = 0; i < fylgjaNames.length(); i++) { + for (uint i = 0; i < fylgjaNameKeys.length(); i++) { if (is_fylgja_unlocked(int(i))) unlockedCount++; } @@ -87,18 +87,25 @@ void append_adventure_completion_rewards(int adventureId, string[] @rewards) { stageIndex = int(fylgjaStageNames.length()) - 1; string stageName = fylgjaStageNames[stageIndex]; - string targetName = adventureStageTargets[adventureIndex]; - rewards.insert_last(i18n_text("You have a " + stageName + " connection with the " + targetName + ".")); + string stageLabel = tr("system.fylgja.stage." + stageName); + string targetKey = adventureStageTargetKeys[adventureIndex]; + string targetLabel = tr("system.fylgja.target." + targetKey); + dictionary connectionArgs; + connectionArgs.set("stage", stageLabel); + connectionArgs.set("target", targetLabel); + rewards.insert_last(trf("system.fylgja.connection_with_target", connectionArgs)); int fylgjaIndex = get_fylgja_index_for_adventure(adventureId); if (fylgjaIndex == -1) return; if (completionCount >= FYLGJA_STAGE_COUNT) { + dictionary unlockedArgs; + unlockedArgs.set("name", tr("system.fylgja.name." + fylgjaNameKeys[fylgjaIndex])); if (completionCount == FYLGJA_STAGE_COUNT) { - rewards.insert_last(i18n_text("You have unlocked the " + fylgjaNames[fylgjaIndex] + " Fylgja!")); + rewards.insert_last(trf("system.fylgja.unlocked", unlockedArgs)); } else { - rewards.insert_last(i18n_text("You have already unlocked the " + fylgjaNames[fylgjaIndex] + " Fylgja.")); + rewards.insert_last(trf("system.fylgja.already_unlocked", unlockedArgs)); } } } @@ -112,7 +119,7 @@ void check_fylgja_menu() { return; if (lastFylgjaDay == current_day) { - speak_with_history("You have already used your Fylgja today.", true); + speak_with_history(tr("system.fylgja.already_used_today"), true); return; } @@ -123,18 +130,19 @@ void run_fylgja_menu() { string[] options; int[] fylgjaIndices; - for (uint i = 0; i < fylgjaNames.length(); i++) { + for (uint i = 0; i < fylgjaNameKeys.length(); i++) { if (is_fylgja_unlocked(int(i))) { - options.insert_last(fylgjaNames[i] + " Fylgja"); + dictionary optionArgs; + optionArgs.set("name", tr("system.fylgja.name." + fylgjaNameKeys[i])); + options.insert_last(trf("system.fylgja.option", optionArgs)); fylgjaIndices.insert_last(int(i)); } } - i18n_translate_string_array_in_place(options); if (options.length() == 0) return; - speak_with_history("Fylgja menu.", true); + speak_with_history(tr("system.fylgja.menu.prompt"), true); int selection = 0; speak_with_history(options[selection], true); @@ -179,7 +187,7 @@ void run_fylgja_menu() { bool activate_fylgja(int fylgjaIndex) { if (fylgjaIndex == FYLGJA_UNICORN) { if (!can_start_unicorn_fylgja_charge()) { - speak_with_history("You need open ground in front of you to charge.", true); + speak_with_history(tr("system.fylgja.need_open_ground_to_charge"), true); return false; } start_unicorn_fylgja_charge(); diff --git a/src/i18n.nvgt b/src/i18n.nvgt index 3252e25..8275cc4 100644 --- a/src/i18n.nvgt +++ b/src/i18n.nvgt @@ -466,10 +466,18 @@ string i18n_translate_fragment_value(const string& in value) { return value; string key = ""; - if (!i18n_catalog_get_string(i18nExactEnglishToKey, value, key)) - return value; + string fallbackValue = value; + if (!i18n_catalog_get_string(i18nExactEnglishToKey, value, key)) { + if (value.find_first("_") < 0) + return value; + string normalized = value; + normalized.replace("_", " "); + fallbackValue = normalized; + if (!i18n_catalog_get_string(i18nExactEnglishToKey, normalized, key)) + return value; + } - return i18n_lookup_key_with_fallback(key, value); + return i18n_lookup_key_with_fallback(key, fallbackValue); } string i18n_translate_speech_message(const string& in message) { diff --git a/src/intro.nvgt b/src/intro.nvgt new file mode 100644 index 0000000..7efa4f2 --- /dev/null +++ b/src/intro.nvgt @@ -0,0 +1,84 @@ +#include "libstorm-nvgt/character_dialog.nvgt" + +bool story_dialog_configured = false; +string[] story_voice_god_keys = {"system.story.god.odin", "system.story.god.thor", "system.story.god.freyja", + "system.story.god.loki", "system.story.god.tyr", "system.story.god.baldur", + "system.story.god.frigg", "system.story.god.heimdall", "system.story.god.hel", + "system.story.god.fenrir", "system.story.god.freyr"}; + +void story_dialog_speak(const string& in message, bool interrupt) { + speak_with_history(message, interrupt); +} + +string get_random_story_voice_god() { + if (story_voice_god_keys.length() == 0) { + return tr("system.story.god.fallback"); + } + + int index = random(0, story_voice_god_keys.length() - 1); + return tr(story_voice_god_keys[index]); +} + +string format_story_voice_line(const string& in god_name, const string& in line) { + dictionary args; + args.set("speaker", god_name); + args.set("line", line); + return trf("system.story.voice.format", args); +} + +void configure_story_dialog_if_needed() { + if (story_dialog_configured) { + return; + } + + character_dialog_set_speak_callback(story_dialog_speak); + character_dialog_set_sound_path("sounds/dialog"); + character_dialog_set_show_usage_instructions(true); + story_dialog_configured = true; +} + +void run_story_dialog() { + configure_story_dialog_if_needed(); + character_dialog_reset_usage_instructions(); + + string[] story_lines; + story_lines.insert_last(tr("system.story.line01")); + story_lines.insert_last(tr("system.story.line02")); + story_lines.insert_last(tr("system.story.line03")); + story_lines.insert_last(tr("system.story.line04")); + story_lines.insert_last(tr("system.story.line05")); + story_lines.insert_last(tr("system.story.line06")); + story_lines.insert_last(tr("system.story.line07")); + story_lines.insert_last(tr("system.story.line08")); + story_lines.insert_last(tr("system.story.line09")); + story_lines.insert_last(tr("system.story.line10")); + story_lines.insert_last(tr("system.story.line11")); + story_lines.insert_last(tr("system.story.line12")); + story_lines.insert_last(tr("system.story.line13")); + story_lines.insert_last(tr("system.story.line14")); + story_lines.insert_last(tr("system.story.line15")); + story_lines.insert_last(tr("system.story.line16")); + story_lines.insert_last(tr("system.story.line17")); + story_lines.insert_last(tr("system.story.line18")); + story_lines.insert_last(tr("system.story.line19")); + story_lines.insert_last(tr("system.story.line20")); + story_lines.insert_last(tr("system.story.line21")); + story_lines.insert_last(tr("system.story.line22")); + story_lines.insert_last(tr("system.story.line23")); + story_lines.insert_last(tr("system.story.line24")); + story_lines.insert_last(tr("system.story.line25")); + story_lines.insert_last(tr("system.story.line26")); + story_lines.insert_last(tr("system.story.line27")); + story_lines.insert_last(tr("system.story.line28")); + story_lines.insert_last(format_story_voice_line(get_random_story_voice_god(), tr("system.story.line29"))); + story_lines.insert_last(format_story_voice_line(get_random_story_voice_god(), tr("system.story.line30"))); + story_lines.insert_last(format_story_voice_line(tr("system.story.god.hel"), tr("system.story.line31"))); + story_lines.insert_last(format_story_voice_line(get_random_story_voice_god(), tr("system.story.line32"))); + story_lines.insert_last(format_story_voice_line(get_random_story_voice_god(), tr("system.story.line33"))); + story_lines.insert_last(format_story_voice_line(get_random_story_voice_god(), tr("system.story.line34"))); + story_lines.insert_last(format_story_voice_line(get_random_story_voice_god(), tr("system.story.line35"))); + story_lines.insert_last(tr("system.story.line36")); + story_lines.insert_last(tr("system.story.line37")); + + character_dialog_show_lines(story_lines, true); +} diff --git a/src/inventory_items.nvgt b/src/inventory_items.nvgt index bc73211..d0c6e4a 100644 --- a/src/inventory_items.nvgt +++ b/src/inventory_items.nvgt @@ -96,7 +96,9 @@ void clamp_arrows_to_quiver_limit() { if (maxArrows == 0) { speak_need_quiver_for_arrows(); } else { - speak_with_history("You can only carry " + maxArrows + " arrows with your current quivers.", true); + dictionary arrowArgs; + arrowArgs.set("max", maxArrows); + speak_with_history(trf("system.inventory.max_arrows_with_quivers", arrowArgs), true); } } @@ -467,35 +469,41 @@ void activate_quick_slot(int slot_index) { if (equipment_is_equipped(equip_type)) { if (get_equipped_rune_for_slot(equip_type) != rune_type) { if (rune_type != RUNE_NONE && get_runed_item_count(equip_type, rune_type) <= 0) { - speak_with_history("Item not available.", true); + speak_with_history(tr("system.inventory.item_not_available"), true); return; } set_equipped_rune_for_slot(equip_type, rune_type); update_max_health_from_equipment(); - speak_with_history(get_equipment_display_name_with_rune(equip_type, rune_type) + " equipped.", true); + dictionary equip_args; + equip_args.set("name", get_equipment_display_name_with_rune(equip_type, rune_type)); + speak_with_history(trf("system.equipment.equipped", equip_args), true); return; } unequip_equipment_type(equip_type); clear_equipped_rune_for_slot(equip_type); update_max_health_from_equipment(); - speak_with_history(get_equipment_display_name_with_rune(equip_type, rune_type) + " unequipped.", true); + dictionary unequip_args; + unequip_args.set("name", get_equipment_display_name_with_rune(equip_type, rune_type)); + speak_with_history(trf("system.equipment.unequipped", unequip_args), true); return; } if (rune_type != RUNE_NONE) { if (get_runed_item_count(equip_type, rune_type) <= 0) { - speak_with_history("Item not available.", true); + speak_with_history(tr("system.inventory.item_not_available"), true); return; } } else if (!equipment_available(equip_type)) { - speak_with_history("Item not available.", true); + speak_with_history(tr("system.inventory.item_not_available"), true); return; } equip_equipment_type(equip_type); set_equipped_rune_for_slot(equip_type, rune_type); update_max_health_from_equipment(); - speak_with_history(get_equipment_display_name_with_rune(equip_type, rune_type) + " equipped.", true); + dictionary equip_args; + equip_args.set("name", get_equipment_display_name_with_rune(equip_type, rune_type)); + speak_with_history(trf("system.equipment.equipped", equip_args), true); } void check_quick_slot_keys() { diff --git a/src/learn_sounds.nvgt b/src/learn_sounds.nvgt index 8019cad..35358a8 100644 --- a/src/learn_sounds.nvgt +++ b/src/learn_sounds.nvgt @@ -1,6 +1,6 @@ #include "libstorm-nvgt/learn_sounds.nvgt" #include "libstorm-nvgt/docs_browser.nvgt" -#include "excluded_sounds.nvgt" +#include "src/sound_settings.nvgt" bool learnSoundsConfigured = false; bool docsBrowserConfigured = false; diff --git a/src/menus/action_menu.nvgt b/src/menus/action_menu.nvgt index b62a934..1ed2524 100644 --- a/src/menus/action_menu.nvgt +++ b/src/menus/action_menu.nvgt @@ -23,72 +23,79 @@ WorldSnare @get_snare_within_range(int pos, int range) { string get_fire_intensity_label(int fuel_remaining) { int hours_remaining = fuel_remaining / 60000; if (hours_remaining >= 8) - return "Giant blaze"; + return tr("system.action.fire.intensity.giant_blaze"); if (hours_remaining >= 2) - return "Small fire"; - return "A few glowing coals"; + return tr("system.action.fire.intensity.small_fire"); + return tr("system.action.fire.intensity.glowing_coals"); } string get_fire_time_estimate(int fuel_remaining) { int approx_hours = (fuel_remaining + 30000) / 60000; if (approx_hours <= 0) - return "less than 1 hour"; + return tr("system.action.fire.estimate.less_than_one_hour"); if (approx_hours == 1) - return "approximately 1 hour"; - return "approximately " + approx_hours + " hours"; + return tr("system.action.fire.estimate.approximately_one_hour"); + dictionary args; + args.set("hours", approx_hours); + return trf("system.action.fire.estimate.approximately_hours", args); } void check_fire_status(WorldFire @fire) { if (fire == null) { - speak_with_history("No fire nearby.", true); + speak_with_history(tr("system.action.no_fire_nearby"), true); return; } string label = get_fire_intensity_label(fire.fuel_remaining); string estimate = get_fire_time_estimate(fire.fuel_remaining); - speak_with_history(label + ". " + estimate + " remaining.", true); + dictionary args; + args.set("label", label); + args.set("estimate", estimate); + speak_with_history(trf("system.action.fire.status", args), true); } void check_snare_status(WorldSnare @snare) { if (snare == null) { - speak_with_history("No snare nearby.", true); + speak_with_history(tr("system.action.no_snare_nearby"), true); return; } if (snare.has_catch) { - speak_with_history("Snare holds a " + snare.catch_type + ".", true); + dictionary args; + args.set("catch_type", i18n_translate_speech_message(snare.catch_type)); + speak_with_history(trf("system.action.snare_holds", args), true); } else if (!snare.active) { - speak_with_history("Snare is set but not active yet.", true); + speak_with_history(tr("system.action.snare_set_inactive"), true); } else { - speak_with_history("Snare is set and empty.", true); + speak_with_history(tr("system.action.snare_set_empty"), true); } } void check_fishing_status() { if (fish_on_line) { - speak_with_history("Fish on the line.", true); + speak_with_history(tr("system.action.fish_on_line"), true); return; } - speak_with_history("No fish on the line.", true); + speak_with_history(tr("system.action.no_fish_on_line"), true); } void try_place_snare(int x) { if (get_personal_count(ITEM_SNARES) > 0) { // Prevent placing in base area if (x <= BASE_END) { - speak_with_history("Cannot place snares in the base area.", true); + speak_with_history(tr("system.action.cannot_place_snares_in_base"), true); return; } // Prevent placing if one already exists here if (get_snare_at(x) != null) { - speak_with_history("There is already a snare here.", true); + speak_with_history(tr("system.action.snare_already_here"), true); return; } add_personal_count(ITEM_SNARES, -1); add_world_snare(x); - speak_with_history("Snare set.", true); + speak_with_history(tr("system.action.snare_set"), true); } else { - speak_with_history("No snares to place.", true); + speak_with_history(tr("system.action.no_snares_to_place"), true); } } @@ -96,7 +103,7 @@ void try_feed_fire_stick(WorldFire @fire) { if (get_personal_count(ITEM_STICKS) > 0 && fire != null) { add_personal_count(ITEM_STICKS, -1); fire.add_fuel(300000); // 5 minutes - speak_with_history("You dump an arm load of sticks into the fire.", true); + speak_with_history(tr("system.action.feed_fire.stick"), true); p.play_stationary("sounds/actions/feed_fire.ogg", false); } } @@ -105,7 +112,7 @@ void try_feed_fire_vine(WorldFire @fire) { if (get_personal_count(ITEM_VINES) > 0 && fire != null) { add_personal_count(ITEM_VINES, -1); fire.add_fuel(60000); // 1 minute - speak_with_history("You toss a fiew vines and leaves into the fire.", true); + speak_with_history(tr("system.action.feed_fire.vine"), true); p.play_stationary("sounds/actions/feed_fire.ogg", false); } } @@ -114,22 +121,22 @@ void try_feed_fire_log(WorldFire @fire) { if (get_personal_count(ITEM_LOGS) > 0 && fire != null) { add_personal_count(ITEM_LOGS, -1); fire.add_fuel(720000); // 12 minutes - speak_with_history("You heave a log into the fire.", true); + speak_with_history(tr("system.action.feed_fire.log"), true); p.play_stationary("sounds/actions/feed_fire.ogg", false); } } void try_burn_incense() { if (world_altars.length() == 0) { - speak_with_history("No altar built.", true); + speak_with_history(tr("system.action.no_altar_built"), true); return; } if (get_personal_count(ITEM_CLAY_POTS) <= 0) { - speak_with_history("You need a clay pot to burn incense.", true); + speak_with_history(tr("system.action.need_clay_pot_for_incense"), true); return; } if (get_personal_count(ITEM_INCENSE) <= 0) { - speak_with_history("No incense to burn.", true); + speak_with_history(tr("system.action.no_incense_to_burn"), true); return; } @@ -137,12 +144,14 @@ void try_burn_incense() { add_personal_count(ITEM_CLAY_POTS, -1); incense_hours_remaining += INCENSE_HOURS_PER_STICK; incense_burning = true; - speak_with_history("Incense burning. " + incense_hours_remaining + " hours remaining.", true); + dictionary args; + args.set("hours", incense_hours_remaining); + speak_with_history(trf("system.action.incense_burning", args), true); } void try_feed_fire_stick_max(WorldFire @fire) { if (get_personal_count(ITEM_STICKS) <= 0 || fire == null) { - speak_with_history("No sticks to feed fire.", true); + speak_with_history(tr("system.action.no_sticks_to_feed_fire"), true); return; } @@ -152,12 +161,14 @@ void try_feed_fire_stick_max(WorldFire @fire) { fire.add_fuel(fuel_added); p.play_stationary("sounds/actions/feed_fire.ogg", false); - speak_with_history("Dumped " + amount + " sticks into the fire.", true); + dictionary args; + args.set("amount", amount); + speak_with_history(trf("system.action.dumped_sticks", args), true); } void try_feed_fire_vine_max(WorldFire @fire) { if (get_personal_count(ITEM_VINES) <= 0 || fire == null) { - speak_with_history("No vines to feed fire.", true); + speak_with_history(tr("system.action.no_vines_to_feed_fire"), true); return; } @@ -167,12 +178,14 @@ void try_feed_fire_vine_max(WorldFire @fire) { fire.add_fuel(fuel_added); p.play_stationary("sounds/actions/feed_fire.ogg", false); - speak_with_history("Dumped " + amount + " vines into the fire.", true); + dictionary args; + args.set("amount", amount); + speak_with_history(trf("system.action.dumped_vines", args), true); } void try_feed_fire_log_max(WorldFire @fire) { if (get_personal_count(ITEM_LOGS) <= 0 || fire == null) { - speak_with_history("No logs to feed fire.", true); + speak_with_history(tr("system.action.no_logs_to_feed_fire"), true); return; } @@ -182,20 +195,22 @@ void try_feed_fire_log_max(WorldFire @fire) { fire.add_fuel(fuel_added); p.play_stationary("sounds/actions/feed_fire.ogg", false); - speak_with_history("Dumped " + amount + " logs into the fire.", true); + dictionary args; + args.set("amount", amount); + speak_with_history(trf("system.action.dumped_logs", args), true); } void try_burn_incense_max() { if (world_altars.length() == 0) { - speak_with_history("No altar built.", true); + speak_with_history(tr("system.action.no_altar_built"), true); return; } if (get_personal_count(ITEM_CLAY_POTS) <= 0) { - speak_with_history("You need a clay pot to burn incense.", true); + speak_with_history(tr("system.action.need_clay_pot_for_incense"), true); return; } if (get_personal_count(ITEM_INCENSE) <= 0) { - speak_with_history("No incense to burn.", true); + speak_with_history(tr("system.action.no_incense_to_burn"), true); return; } @@ -207,12 +222,13 @@ void try_burn_incense_max() { incense_hours_remaining += total_hours; incense_burning = true; - speak_with_history("Burned " + amount + " incense. +" + total_hours + " hours.", true); + dictionary args; + args.set("amount", amount); + args.set("hours", total_hours); + speak_with_history(trf("system.action.burned_incense", args), true); } void run_action_menu(int x) { - speak_with_history("Action menu.", true); - int selection = 0; string[] options; int[] action_types; // Track what action each option corresponds to @@ -225,46 +241,52 @@ void run_action_menu(int x) { WorldSnare @check_snare = get_snare_within_range(x, check_range); // Build menu options dynamically - options.insert_last("Place Snare"); + options.insert_last(tr("system.action.option.place_snare")); action_types.insert_last(0); if (can_feed_fire) { if (get_personal_count(ITEM_STICKS) > 0) { - options.insert_last("Feed fire with stick"); + options.insert_last(tr("system.action.option.feed_fire_stick")); action_types.insert_last(1); } if (get_personal_count(ITEM_VINES) > 0) { - options.insert_last("Feed fire with vine"); + options.insert_last(tr("system.action.option.feed_fire_vine")); action_types.insert_last(2); } if (get_personal_count(ITEM_LOGS) > 0) { - options.insert_last("Feed fire with log"); + options.insert_last(tr("system.action.option.feed_fire_log")); action_types.insert_last(3); } } if (x <= BASE_END && world_altars.length() > 0 && get_personal_count(ITEM_INCENSE) > 0) { - options.insert_last("Burn incense"); + options.insert_last(tr("system.action.option.burn_incense")); action_types.insert_last(4); } if (check_fire != null) { - options.insert_last("Check fire"); + options.insert_last(tr("system.action.option.check_fire")); action_types.insert_last(5); } if (check_snare != null) { - options.insert_last("Check snare"); + options.insert_last(tr("system.action.option.check_snare")); action_types.insert_last(6); } if (line_in_water || fish_on_line || is_reeling || is_casting) { - options.insert_last("Check fishing pole"); + options.insert_last(tr("system.action.option.check_fishing_pole")); action_types.insert_last(7); } - i18n_translate_string_array_in_place(options); string filter_text = ""; int[] filtered_indices; string[] filtered_options; apply_menu_filter(filter_text, options, filtered_indices, filtered_options); + if (filtered_options.length() == 0) { + speak_with_history(tr("system.menu.no_options"), true); + } else { + dictionary promptArgs; + promptArgs.set("option", filtered_options[selection]); + speak_with_history(trf("system.action.menu.prompt", promptArgs), true); + } while (true) { wait(5); @@ -272,7 +294,7 @@ void run_action_menu(int x) { return; } if (key_pressed(KEY_ESCAPE)) { - speak_with_history("Closed.", true); + speak_with_history(tr("system.menu.closed"), true); break; } @@ -281,9 +303,11 @@ void run_action_menu(int x) { if (filter_changed) { if (filtered_options.length() == 0) { if (filter_text.length() > 0) { - speak_with_history("No matches for " + filter_text + ".", true); + dictionary filterArgs; + filterArgs.set("arg1", filter_text); + speak_with_history(trf("system.menu.no_matches", filterArgs), true); } else { - speak_with_history("No options.", true); + speak_with_history(tr("system.menu.no_options"), true); } } else { speak_with_history(filtered_options[selection], true); @@ -343,7 +367,7 @@ void run_action_menu(int x) { play_menu_select_sound(); int action = action_types[filtered_indices[selection]]; if (action == 0) { - speak_with_history("Can't do that.", true); + speak_with_history(tr("system.action.cant_do_that"), true); } else if (action == 1) { try_feed_fire_stick_max(nearby_fire); } else if (action == 2) { diff --git a/src/menus/altar_menu.nvgt b/src/menus/altar_menu.nvgt index 7d8c5b3..a6031e8 100644 --- a/src/menus/altar_menu.nvgt +++ b/src/menus/altar_menu.nvgt @@ -13,13 +13,13 @@ void check_altar_menu(int player_x) { // Must be in base if (player_x > BASE_END) { - speak_with_history("Must be in base to use altar.", true); + speak_with_history(tr("system.altar.must_be_in_base"), true); return; } // Must have altar if (world_altars.length() == 0) { - speak_with_history("No altar built.", true); + speak_with_history(tr("system.altar.no_altar_built"), true); return; } @@ -28,12 +28,12 @@ void check_altar_menu(int player_x) { void sacrifice_item(int item_type) { if (item_type == -2 || is_runed_item_type(item_type)) { - speak_with_history("Runed items cannot be sacrificed.", true); + speak_with_history(tr("system.altar.runed_cannot_sacrifice"), true); return; } int available = get_personal_count(item_type); if (available <= 0) { - speak_with_history("Nothing to sacrifice.", true); + speak_with_history(tr("system.altar.nothing_to_sacrifice"), true); return; } @@ -49,19 +49,21 @@ void sacrifice_item(int item_type) { cleanup_equipment_after_inventory_change(); double favor_gain = get_item_favor_value(item_type); favor += favor_gain; - speak_with_history("Sacrificed 1 " + get_item_label_singular(item_type) + ". Favor +" + - format_altar_favor(favor_gain) + ". Total " + format_altar_favor(favor) + ".", - true); + dictionary args; + args.set("item", get_item_label_singular(item_type)); + args.set("gain", format_altar_favor(favor_gain)); + args.set("total", format_altar_favor(favor)); + speak_with_history(trf("system.altar.sacrificed_one", args), true); } void sacrifice_item_max(int item_type) { if (item_type == -2 || is_runed_item_type(item_type)) { - speak_with_history("Runed items cannot be sacrificed.", true); + speak_with_history(tr("system.altar.runed_cannot_sacrifice"), true); return; } int available = get_personal_count(item_type); if (available <= 0) { - speak_with_history("Nothing to sacrifice.", true); + speak_with_history(tr("system.altar.nothing_to_sacrifice"), true); return; } @@ -78,13 +80,18 @@ void sacrifice_item_max(int item_type) { double total_favor = favor_per_item * available; favor += total_favor; - speak_with_history("Sacrificed " + available + " " + get_item_label(item_type) + ". Favor +" + - format_altar_favor(total_favor) + ". Total " + format_altar_favor(favor) + ".", - true); + dictionary args; + args.set("count", available); + args.set("items", get_item_label(item_type)); + args.set("gain", format_altar_favor(total_favor)); + args.set("total", format_altar_favor(favor)); + speak_with_history(trf("system.altar.sacrificed_many", args), true); } void run_altar_menu() { - speak_with_history("Altar. Favor " + format_altar_favor(favor) + ".", true); + dictionary favorArgs; + favorArgs.set("favor", format_altar_favor(favor)); + speak_with_history(trf("system.altar.menu.prompt", favorArgs), true); int selection = 0; string[] options; @@ -101,7 +108,7 @@ void run_altar_menu() { return; } if (key_pressed(KEY_ESCAPE)) { - speak_with_history("Closed.", true); + speak_with_history(tr("system.menu.closed"), true); break; } @@ -110,9 +117,11 @@ void run_altar_menu() { if (filter_changed) { if (filtered_options.length() == 0) { if (filter_text.length() > 0) { - speak_with_history("No matches for " + filter_text + ".", true); + dictionary filterArgs; + filterArgs.set("arg1", filter_text); + speak_with_history(trf("system.menu.no_matches", filterArgs), true); } else { - speak_with_history("No options.", true); + speak_with_history(tr("system.menu.no_options"), true); } } else { speak_with_history(filtered_options[selection], true); @@ -150,7 +159,9 @@ void run_altar_menu() { if (filtered_options.length() > 0) { speak_with_history(filtered_options[selection], true); } else if (filter_text.length() > 0) { - speak_with_history("No matches for " + filter_text + ".", true); + dictionary filterArgs; + filterArgs.set("arg1", filter_text); + speak_with_history(trf("system.menu.no_matches", filterArgs), true); } } } @@ -166,7 +177,9 @@ void run_altar_menu() { if (filtered_options.length() > 0) { speak_with_history(filtered_options[selection], true); } else if (filter_text.length() > 0) { - speak_with_history("No matches for " + filter_text + ".", true); + dictionary filterArgs; + filterArgs.set("arg1", filter_text); + speak_with_history(trf("system.menu.no_matches", filterArgs), true); } } } diff --git a/src/menus/base_info.nvgt b/src/menus/base_info.nvgt index b214112..9a79fee 100644 --- a/src/menus/base_info.nvgt +++ b/src/menus/base_info.nvgt @@ -3,7 +3,7 @@ void run_base_info_menu() { if (x > BASE_END) { - speak_with_history("You are not in the base.", true); + speak_with_history(tr("system.base_info.not_in_base"), true); return; } @@ -59,9 +59,11 @@ void run_base_info_menu() { string[] filtered_options; apply_menu_filter(filter_text, options, filtered_indices, filtered_options); if (filtered_options.length() == 0) { - speak_with_history("Base info. No options.", true); + speak_with_history(tr("system.base_info.menu.no_options"), true); } else { - speak_with_history("Base info. " + filtered_options[selection], true); + dictionary promptArgs; + promptArgs.set("option", filtered_options[selection]); + speak_with_history(trf("system.base_info.menu.prompt", promptArgs), true); } while (true) { @@ -70,7 +72,7 @@ void run_base_info_menu() { return; } if (key_pressed(KEY_ESCAPE)) { - speak_with_history("Closed.", true); + speak_with_history(tr("system.menu.closed"), true); break; } @@ -79,9 +81,11 @@ void run_base_info_menu() { if (filter_changed) { if (filtered_options.length() == 0) { if (filter_text.length() > 0) { - speak_with_history("No matches for " + filter_text + ".", true); + dictionary filterArgs; + filterArgs.set("arg1", filter_text); + speak_with_history(trf("system.menu.no_matches", filterArgs), true); } else { - speak_with_history("No options.", true); + speak_with_history(tr("system.menu.no_options"), true); } } else { speak_with_history(filtered_options[selection], true); diff --git a/src/menus/equipment_menu.nvgt b/src/menus/equipment_menu.nvgt index 938e79d..a2fb2e4 100644 --- a/src/menus/equipment_menu.nvgt +++ b/src/menus/equipment_menu.nvgt @@ -31,7 +31,7 @@ bool has_any_equipment() { void check_equipment_menu() { if (key_pressed(KEY_E)) { if (!has_any_equipment()) { - speak_with_history("Nothing to equip.", true); + speak_with_history(tr("system.equipment.menu.nothing_to_equip"), true); } else { run_equipment_menu(); } @@ -61,8 +61,6 @@ string get_equipment_menu_equipped_suffix(bool equipped) { } void run_equipment_menu() { - speak_with_history("Equipment menu.", true); - int selection = 0; string[] options; int[] equipment_types; @@ -164,6 +162,13 @@ void run_equipment_menu() { int[] filtered_indices; string[] filtered_options; apply_menu_filter(filter_text, options, filtered_indices, filtered_options); + if (filtered_options.length() == 0) { + speak_with_history(tr("system.menu.no_options"), true); + } else { + dictionary promptArgs; + promptArgs.set("option", filtered_options[selection]); + speak_with_history(trf("system.equipment.menu.prompt", promptArgs), true); + } while (true) { wait(5); @@ -171,7 +176,7 @@ void run_equipment_menu() { return; } if (key_pressed(KEY_ESCAPE)) { - speak_with_history("Closed.", true); + speak_with_history(tr("system.menu.closed"), true); break; } @@ -180,9 +185,11 @@ void run_equipment_menu() { if (filter_changed) { if (filtered_options.length() == 0) { if (filter_text.length() > 0) { - speak_with_history("No matches for " + filter_text + ".", true); + dictionary filterArgs; + filterArgs.set("arg1", filter_text); + speak_with_history(trf("system.menu.no_matches", filterArgs), true); } else { - speak_with_history("No options.", true); + speak_with_history(tr("system.menu.no_options"), true); } } else { speak_with_history(filtered_options[selection], true); @@ -218,7 +225,10 @@ void run_equipment_menu() { quick_slot_runes[slot_index] = rune_type; } string name = get_full_equipment_name(equip_type, rune_type); - speak_with_history(name + " set to slot " + slot_index + ".", true); + dictionary args; + args.set("name", name); + args.set("slot", slot_index); + speak_with_history(trf("system.equipment.set_to_slot", args), true); } if (key_pressed(KEY_RETURN)) { @@ -234,12 +244,16 @@ void run_equipment_menu() { // Unequip unequip_equipment_type(equip_type); clear_equipped_rune_for_slot(equip_type); - speak_with_history(name + " unequipped.", true); + dictionary unequip_args; + unequip_args.set("name", name); + speak_with_history(trf("system.equipment.unequipped", unequip_args), true); } else { // Equip equip_equipment_type(equip_type); set_equipped_rune_for_slot(equip_type, rune_type); - speak_with_history(name + " equipped.", true); + dictionary equip_args; + equip_args.set("name", name); + speak_with_history(trf("system.equipment.equipped", equip_args), true); } update_max_health_from_equipment(); break; diff --git a/src/menus/menu_utils.nvgt b/src/menus/menu_utils.nvgt index fc630da..8f1c15d 100644 --- a/src/menus/menu_utils.nvgt +++ b/src/menus/menu_utils.nvgt @@ -32,7 +32,9 @@ bool menu_background_tick() { if (fire_on_tile != null && !jumping && fire_damage_timer.elapsed > 1000) { player_health--; fire_damage_timer.restart(); - speak_with_history("Burning! " + player_health + " health remaining.", true); + dictionary burningArgs; + burningArgs.set("health", player_health); + speak_with_history(trf("system.combat.burning", burningArgs), true); } // Healing in base area @@ -43,14 +45,16 @@ bool menu_background_tick() { if (healing_timer.elapsed > heal_interval) { player_health++; healing_timer.restart(); - speak_with_history(player_health + " health.", true); + dictionary healthArgs; + healthArgs.set("health", player_health); + speak_with_history(trf("system.combat.health_status", healthArgs), true); } } // Death check if (player_health <= 0) { if (!try_consume_heal_scroll()) { - speak_with_history("You have died.", true); + speak_with_history(tr("system.combat.you_died"), true); wait(2000); return_to_main_menu_requested = true; return true; diff --git a/src/menus/storage_menu.nvgt b/src/menus/storage_menu.nvgt index ad62fa8..197169c 100644 --- a/src/menus/storage_menu.nvgt +++ b/src/menus/storage_menu.nvgt @@ -13,9 +13,16 @@ void speak_storage_menu_no_matches(const string& in filter_text) { speak_with_history(trf("system.menu.no_matches", args), true); } +string get_storage_runed_item_name(int equip_type, int rune_type) { + dictionary args; + args.set("equipment", get_base_equipment_name(equip_type)); + args.set("rune", get_rune_effect_name(rune_type)); + return trf("system.storage.runed_item_name", args); +} + void move_small_game_to_storage(int amount) { for (int i = 0; i < amount; i++) { - string game_type = "small game"; + string game_type = get_item_label_singular(ITEM_SMALL_GAME); if (personal_small_game_types.length() > 0) { game_type = personal_small_game_types[0]; personal_small_game_types.remove_at(0); @@ -26,7 +33,7 @@ void move_small_game_to_storage(int amount) { void move_small_game_to_personal(int amount) { for (int i = 0; i < amount; i++) { - string game_type = "small game"; + string game_type = get_item_label_singular(ITEM_SMALL_GAME); if (storage_small_game_types.length() > 0) { game_type = storage_small_game_types[0]; storage_small_game_types.remove_at(0); @@ -62,9 +69,11 @@ void deposit_item(int item_type) { int equip_type, rune_type; decode_runed_item_type(item_type, equip_type, rune_type); if (deposit_runed_item(equip_type, rune_type)) { - string name = "Runed " + get_base_equipment_name(equip_type) + " of " + get_rune_effect_name(rune_type); + string name = get_storage_runed_item_name(equip_type, rune_type); cleanup_equipment_after_inventory_change(); - speak_with_history("Deposited " + name + ".", true); + dictionary args; + args.set("name", name); + speak_with_history(trf("system.storage.deposited_one", args), true); } else { speak_with_history(tr("system.storage.nothing_to_deposit"), true); } @@ -103,7 +112,10 @@ void deposit_item(int item_type) { } cleanup_equipment_after_inventory_change(); - speak_with_history("Deposited " + amount + " " + get_item_label(item_type) + ".", true); + dictionary args; + args.set("amount", amount); + args.set("item", get_item_label(item_type)); + speak_with_history(trf("system.storage.deposited_many", args), true); } void deposit_item_max(int item_type) { @@ -121,9 +133,12 @@ void deposit_item_max(int item_type) { deposit_runed_item(equip_type, rune_type); count++; } - string name = "Runed " + get_base_equipment_name(equip_type) + " of " + get_rune_effect_name(rune_type); + string name = get_storage_runed_item_name(equip_type, rune_type); cleanup_equipment_after_inventory_change(); - speak_with_history("Deposited " + count + " " + name + ".", true); + dictionary args; + args.set("amount", count); + args.set("item", name); + speak_with_history(trf("system.storage.deposited_many", args), true); return; } // Handle legacy -2 marker @@ -158,7 +173,10 @@ void deposit_item_max(int item_type) { } cleanup_equipment_after_inventory_change(); - speak_with_history("Deposited " + amount + " " + get_item_label(item_type) + ".", true); + dictionary args; + args.set("amount", amount); + args.set("item", get_item_label(item_type)); + speak_with_history(trf("system.storage.deposited_many", args), true); } void withdraw_item(int item_type) { @@ -167,8 +185,10 @@ void withdraw_item(int item_type) { int equip_type, rune_type; decode_runed_item_type(item_type, equip_type, rune_type); if (withdraw_runed_item(equip_type, rune_type)) { - string name = "Runed " + get_base_equipment_name(equip_type) + " of " + get_rune_effect_name(rune_type); - speak_with_history("Withdrew " + name + ".", true); + string name = get_storage_runed_item_name(equip_type, rune_type); + dictionary args; + args.set("name", name); + speak_with_history(trf("system.storage.withdrew_one", args), true); } else { speak_with_history(tr("system.storage.nothing_to_withdraw"), true); } @@ -210,7 +230,10 @@ void withdraw_item(int item_type) { move_fish_to_personal(amount); } - speak_with_history("Withdrew " + amount + " " + get_item_label(item_type) + ".", true); + dictionary args; + args.set("amount", amount); + args.set("item", get_item_label(item_type)); + speak_with_history(trf("system.storage.withdrew_many", args), true); } void withdraw_item_max(int item_type) { @@ -228,8 +251,11 @@ void withdraw_item_max(int item_type) { withdraw_runed_item(equip_type, rune_type); count++; } - string name = "Runed " + get_base_equipment_name(equip_type) + " of " + get_rune_effect_name(rune_type); - speak_with_history("Withdrew " + count + " " + name + ".", true); + string name = get_storage_runed_item_name(equip_type, rune_type); + dictionary args; + args.set("amount", count); + args.set("item", name); + speak_with_history(trf("system.storage.withdrew_many", args), true); return; } int available = get_storage_count(item_type); @@ -272,7 +298,10 @@ void withdraw_item_max(int item_type) { move_fish_to_personal(amount); } - speak_with_history("Withdrew " + amount + " " + get_item_label(item_type) + ".", true); + dictionary args; + args.set("amount", amount); + args.set("item", get_item_label(item_type)); + speak_with_history(trf("system.storage.withdrew_many", args), true); } void build_storage_inventory_options(string[] @options, int[] @item_types) { diff --git a/src/pet_system.nvgt b/src/pet_system.nvgt index bd872e9..89594f9 100644 --- a/src/pet_system.nvgt +++ b/src/pet_system.nvgt @@ -217,7 +217,7 @@ void queue_pet_event(const string& in message, int soundPos = -1, bool playSound string get_pet_display_name() { string name = normalize_pet_name_text(petType); if (name == "") - return "pet"; + return tr("system.pet.default_name"); return name; } @@ -342,7 +342,9 @@ void end_pet_adventure() { void queue_pet_return_event() { if (!petActive) return; - queue_pet_event("A " + get_pet_display_name() + " returns to you."); + dictionary returnArgs; + returnArgs.set("pet", get_pet_display_name()); + queue_pet_event(trf("system.pet.returned", returnArgs)); } bool is_pet_at_player_position() { @@ -377,7 +379,9 @@ void knock_out_pet() { petOut = false; petPositionValid = false; stop_pet_travel(); - queue_pet_event("Your " + get_pet_display_name() + " has been knocked out."); + dictionary knockedOutArgs; + knockedOutArgs.set("pet", get_pet_display_name()); + queue_pet_event(trf("system.pet.knocked_out", knockedOutArgs)); } void update_pet_events() { @@ -462,8 +466,10 @@ void pet_leave() { string oldPet = normalize_pet_name_text(petType); if (oldPet == "") - oldPet = "pet"; - speak_with_history(oldPet + " leaves.", true); + oldPet = tr("system.pet.default_name"); + dictionary leaveArgs; + leaveArgs.set("pet", oldPet); + speak_with_history(trf("system.pet.leaves", leaveArgs), true); if (!petOut) { reset_pet_state(); @@ -481,7 +487,9 @@ bool abandon_pet() { return false; if (is_pet_knocked_out()) { - speak_with_history("Your " + get_pet_display_name() + " is unconscious. You can't abandon it right now.", true); + dictionary unconsciousArgs; + unconsciousArgs.set("pet", get_pet_display_name()); + speak_with_history(trf("system.character.pet.unconscious_cannot_abandon", unconsciousArgs), true); return false; } @@ -547,19 +555,26 @@ void check_pet_call_key() { if (petLeaving) { string name = petLeavingName; if (name == "") - name = "pet"; - speak_with_history("Your " + name + " is leaving.", true); + name = tr("system.pet.default_name"); + dictionary leavingArgs; + leavingArgs.set("pet", name); + speak_with_history(trf("system.pet.leaving", leavingArgs), true); return; } if (!petActive) { - speak_with_history("No pet.", true); + speak_with_history(tr("system.character.pet.no_pet"), true); return; } if (is_pet_knocked_out()) { - string message = "Your " + get_pet_display_name() + " has been knocked out."; + dictionary messageArgs; + messageArgs.set("pet", get_pet_display_name()); + string message = trf("system.pet.knocked_out", messageArgs); if (petKnockoutHoursRemaining > 0) { - string hourLabel = (petKnockoutHoursRemaining == 1) ? "hour" : "hours"; - message += " " + petKnockoutHoursRemaining + " " + hourLabel + " remaining."; + string hourLabel = (petKnockoutHoursRemaining == 1) ? tr("system.character.word.hour") + : tr("system.character.word.hours"); + messageArgs.set("hours", petKnockoutHoursRemaining); + messageArgs.set("hour_label", hourLabel); + message = trf("system.pet.knocked_out_with_remaining", messageArgs); } speak_with_history(message, true); return; @@ -567,12 +582,14 @@ void check_pet_call_key() { if (petOut) { petRecallRequested = true; play_pet_recall_ack(); - speak_with_history("Your pet is on its way.", true); + speak_with_history(tr("system.pet.on_the_way"), true); request_pet_return(); return; } if (petLoyalty <= 2) { - speak_with_history("A " + get_pet_display_name() + " is hungry and unresponsive.", true); + dictionary hungryArgs; + hungryArgs.set("pet", get_pet_display_name()); + speak_with_history(trf("system.pet.hungry_unresponsive", hungryArgs), true); return; } adjust_pet_loyalty(-PET_LOYALTY_CALLOUT_COST); @@ -605,7 +622,9 @@ void adopt_pet(const string& in soundPath) { petAttackTimer.restart(); petRetrieveTimer.restart(); petTravelTimer.restart(); - speak_with_history("A " + get_pet_display_name() + " joins you.", true); + dictionary joinsArgs; + joinsArgs.set("pet", get_pet_display_name()); + speak_with_history(trf("system.pet.joins_you", joinsArgs), true); } void stop_pet_travel() { @@ -892,15 +911,16 @@ bool run_pet_offer_menu(const string& in soundPath, const string& in reasonText) return false; string petName = get_pet_name_from_sound_path(soundPath); - string prompt = "A friendly looking " + petName + " begs for food. Accept?"; + dictionary promptArgs; + promptArgs.set("pet", petName); + string prompt = trf("system.pet.offer.prompt", promptArgs); if (reasonText != "") { prompt += " " + reasonText; } string[] options; - options.insert_last("Yes"); - options.insert_last("No"); - i18n_translate_string_array_in_place(options); + options.insert_last(tr("system.option.yes")); + options.insert_last(tr("system.option.no")); int selection = 0; speak_with_history(prompt + " " + options[selection], true); @@ -911,7 +931,7 @@ bool run_pet_offer_menu(const string& in soundPath, const string& in reasonText) return false; } if (key_pressed(KEY_ESCAPE)) { - speak_with_history("Declined.", true); + speak_with_history(tr("system.pet.offer.declined"), true); return false; } if (key_pressed(KEY_DOWN)) { @@ -934,7 +954,7 @@ bool run_pet_offer_menu(const string& in soundPath, const string& in reasonText) adopt_pet(soundPath); return true; } - speak_with_history("Declined.", true); + speak_with_history(tr("system.pet.offer.declined"), true); return false; } } @@ -979,13 +999,17 @@ void attempt_pet_offer_from_tree() { } bool try_pet_pickup_small_game(const string& in gameType, string& out message) { + string localizedGameType = i18n_translate_fragment_value(gameType); + dictionary pickupArgs; + pickupArgs.set("item", localizedGameType); + pickupArgs.set("pet", get_pet_display_name()); if (get_personal_count(ITEM_SMALL_GAME) >= get_personal_stack_limit()) { - message = "You can't carry a " + gameType + ", so you give it to a " + get_pet_display_name() + " to chew on."; + message = trf("system.pet.retrieve.cant_carry_chew_on", pickupArgs); return true; } add_personal_count(ITEM_SMALL_GAME, 1); personal_small_game_types.insert_last(gameType); - message = "Your " + get_pet_display_name() + " retrieved " + gameType + "."; + message = trf("system.pet.retrieve.retrieved_item", pickupArgs); return true; } @@ -996,26 +1020,32 @@ bool try_pet_pickup_world_drop(WorldDrop @drop, string& out message) { return try_pet_pickup_small_game(drop.type, message); } if (drop.type == "arrow") { + dictionary arrowArgs; + arrowArgs.set("item", i18n_translate_fragment_value("arrow")); + arrowArgs.set("pet", get_pet_display_name()); int maxArrows = get_arrow_limit(); if (maxArrows <= 0) { - message = "You can't carry an arrow, so you give it to a " + get_pet_display_name() + " to chew on."; + message = trf("system.pet.retrieve.cant_carry_chew_on", arrowArgs); return true; } if (get_personal_count(ITEM_ARROWS) >= maxArrows) { - message = "You can't carry an arrow, so you give it to a " + get_pet_display_name() + " to chew on."; + message = trf("system.pet.retrieve.cant_carry_chew_on", arrowArgs); return true; } add_personal_count(ITEM_ARROWS, 1); - message = "Your " + get_pet_display_name() + " retrieved an arrow."; + message = trf("system.pet.retrieve.retrieved_item", arrowArgs); return true; } if (drop.type == "boar carcass") { + dictionary boarArgs; + boarArgs.set("item", i18n_translate_fragment_value("boar carcass")); + boarArgs.set("pet", get_pet_display_name()); if (get_personal_count(ITEM_BOAR_CARCASSES) >= get_personal_stack_limit()) { - message = "You can't carry a boar carcass, so you give it to a " + get_pet_display_name() + " to chew on."; + message = trf("system.pet.retrieve.cant_carry_chew_on", boarArgs); return true; } add_personal_count(ITEM_BOAR_CARCASSES, 1); - message = "Your " + get_pet_display_name() + " retrieved a boar carcass."; + message = trf("system.pet.retrieve.retrieved_item", boarArgs); return true; } return false; @@ -1233,8 +1263,11 @@ void attempt_pet_random_find() { add_personal_count(itemType, added); string itemName = (added == 1) ? item_registry[itemType].singular : item_registry[itemType].name; - queue_pet_event("Your " + get_pet_display_name() + " retrieved " + added + " " + itemName + ".", - petPositionValid ? petPosition : x, false); + dictionary randomFindArgs; + randomFindArgs.set("pet", get_pet_display_name()); + randomFindArgs.set("count", added); + randomFindArgs.set("item", i18n_translate_fragment_value(itemName)); + queue_pet_event(trf("system.pet.retrieve.random_find", randomFindArgs), petPositionValid ? petPosition : x, false); request_pet_follow(); } @@ -1249,7 +1282,9 @@ void handle_pet_hourly_update(int hour) { if (petKnockoutHoursRemaining <= 0) { petKnockoutHoursRemaining = 0; petHealth = PET_HEALTH_MAX; - notify("Your " + get_pet_display_name() + " has recovered from its injuries."); + dictionary recoveredArgs; + recoveredArgs.set("pet", get_pet_display_name()); + notify(trf("system.pet.recovered_from_injuries", recoveredArgs)); } } @@ -1264,7 +1299,9 @@ void handle_pet_hourly_update(int hour) { if (!petActive || petLeaving) return; if (petLoyalty <= 1 && !petHungryWarned) { - notify("A " + get_pet_display_name() + " is getting hungry."); + dictionary hungryArgs; + hungryArgs.set("pet", get_pet_display_name()); + notify(trf("system.pet.getting_hungry", hungryArgs)); petHungryWarned = true; } } diff --git a/src/quest_system.nvgt b/src/quest_system.nvgt index 24ea059..5000412 100644 --- a/src/quest_system.nvgt +++ b/src/quest_system.nvgt @@ -17,35 +17,35 @@ bool quest_roll_done_today = false; string get_quest_name(int quest_type) { if (quest_type == QUEST_BAT_INVASION) - return "Bat Invasion"; + return tr("system.quest.name.bat_invasion"); if (quest_type == QUEST_CATCH_BOOMERANG) - return "Catch the Boomerang"; + return tr("system.quest.name.catch_boomerang"); if (quest_type == QUEST_ENCHANTED_MELODY) - return "Enchanted Melody"; + return tr("system.quest.name.enchanted_melody"); if (quest_type == QUEST_ESCAPE_FROM_HEL) - return "Escape from Hel"; + return tr("system.quest.name.escape_from_hel"); if (quest_type == QUEST_SKELETAL_BARD) - return "Skeletal Bard"; - return "Unknown Quest"; + return tr("system.quest.name.skeletal_bard"); + return tr("system.quest.name.unknown"); } string get_quest_description(int quest_type) { if (quest_type == QUEST_BAT_INVASION) { - return "Bat Invasion. Giant killer bats are attacking. Press space to throw when the bat is centered."; + return tr("system.quest.description.bat_invasion"); } if (quest_type == QUEST_CATCH_BOOMERANG) { - return "Catch the Boomerang. Throw and catch the boomerang as it returns for up to 4 points."; + return tr("system.quest.description.catch_boomerang"); } if (quest_type == QUEST_ENCHANTED_MELODY) { - return "Enchanted Melody. Repeat the pattern using E R D F or U I J K. Lowest to highest pitch."; + return tr("system.quest.description.enchanted_melody"); } if (quest_type == QUEST_ESCAPE_FROM_HEL) { - return "Escape from Hel. Press space to jump over open graves. The pace quickens."; + return tr("system.quest.description.escape_from_hel"); } if (quest_type == QUEST_SKELETAL_BARD) { - return "Skeletal Bard. A skeleton named Billy Bones is practicing to become a bard. Count the notes."; + return tr("system.quest.description.skeletal_bard"); } - return "Unknown quest."; + return tr("system.quest.description.unknown"); } int get_quest_chance_from_favor() { @@ -69,7 +69,9 @@ void add_quest(int quest_type) { if (quest_queue.length() >= QUEST_MAX_ACTIVE) return; quest_queue.insert_last(quest_type); - notify("A new quest is available: " + get_quest_name(quest_type) + "."); + dictionary newQuestArgs; + newQuestArgs.set("quest", get_quest_name(quest_type)); + notify(trf("system.quest.new_available", newQuestArgs)); } void attempt_daily_quest() { @@ -95,11 +97,11 @@ void attempt_daily_quest() { void check_quest_menu() { if (key_pressed(KEY_Q)) { if (x > BASE_END) { - speak_with_history("You are not in the base.", true); + speak_with_history(tr("system.base_info.not_in_base"), true); return; } if (quest_queue.length() == 0) { - speak_with_history("No quests available.", true); + speak_with_history(tr("system.quest.none_available"), true); return; } run_quest_menu(); @@ -108,15 +110,15 @@ void check_quest_menu() { string get_quest_favor_phrase(int score) { if (score <= 2) - return "The gods are displeased with your performance."; + return tr("system.quest.favor_phrase.displeased"); if (score < QUEST_STONE_SCORE) - return "The gods are pleased with your performance."; + return tr("system.quest.favor_phrase.pleased"); int extreme_threshold = QUEST_LOG_SCORE - 2; if (score < extreme_threshold) - return "The gods are very pleased with your performance."; + return tr("system.quest.favor_phrase.very_pleased"); if (score < QUEST_LOG_SCORE) - return "The gods are extremely pleased with your performance."; - return "The gods are ultimately pleased with your performance."; + return tr("system.quest.favor_phrase.extremely_pleased"); + return tr("system.quest.favor_phrase.ultimately_pleased"); } void apply_quest_reward(int score) { @@ -162,20 +164,29 @@ void apply_quest_reward(int score) { } } - string message = "Quest Complete!\n\nRewards:\n"; + string message = tr("system.quest.rewards.complete_heading") + "\n\n" + tr("system.quest.rewards.heading") + "\n"; message += get_quest_favor_phrase(score) + "\n"; - message += "Favor: +" + format_favor(favor_gain) + "\n"; + dictionary favorArgs; + favorArgs.set("favor", format_favor(favor_gain)); + message += trf("system.quest.rewards.favor_line", favorArgs) + "\n"; if (added_amount > 0) { - message += get_item_display_name(reward_item) + ": +" + added_amount + "\n"; + dictionary itemLineArgs; + itemLineArgs.set("item", get_item_display_name(reward_item)); + itemLineArgs.set("amount", added_amount); + message += trf("system.quest.rewards.item_line", itemLineArgs) + "\n"; } else if (quantity > 0) { - message += "Inventory full, could not receive " + get_item_display_name(reward_item) + ".\n"; + dictionary inventoryFullArgs; + inventoryFullArgs.set("item", get_item_display_name(reward_item)); + message += trf("system.quest.rewards.inventory_full_line", inventoryFullArgs) + "\n"; } else { - message += "No items awarded.\n"; + message += tr("system.quest.rewards.no_items_awarded") + "\n"; } - message += "\nScore: " + score; - text_reader(message, i18n_text("Quest Rewards"), true); + dictionary scoreArgs; + scoreArgs.set("score", score); + message += "\n" + trf("system.quest.rewards.score_line", scoreArgs); + text_reader(message, tr("system.quest.rewards.title"), true); attempt_pet_offer_from_quest(score); } @@ -201,7 +212,7 @@ void run_quest(int quest_type) { } void run_quest_menu() { - speak_with_history("Quest menu.", true); + speak_with_history(tr("system.quest.menu.prompt"), true); int selection = 0; string[] options; @@ -215,18 +226,22 @@ void run_quest_menu() { return; } if (key_pressed(KEY_ESCAPE)) { - speak_with_history("Closed.", true); + speak_with_history(tr("system.menu.closed"), true); break; } - string count_str = " " + (selection + 1) + " of " + options.length(); + dictionary countArgs; + countArgs.set("index", selection + 1); + countArgs.set("total", options.length()); + string count_str = " " + trf("system.quest.menu.count", countArgs); if (key_pressed(KEY_DOWN)) { play_menu_move_sound(); selection++; if (selection >= options.length()) selection = 0; - count_str = " " + (selection + 1) + " of " + options.length(); + countArgs.set("index", selection + 1); + count_str = " " + trf("system.quest.menu.count", countArgs); speak_with_history(options[selection] + count_str, true); } @@ -235,7 +250,8 @@ void run_quest_menu() { selection--; if (selection < 0) selection = options.length() - 1; - count_str = " " + (selection + 1) + " of " + options.length(); + countArgs.set("index", selection + 1); + count_str = " " + trf("system.quest.menu.count", countArgs); speak_with_history(options[selection] + count_str, true); } diff --git a/src/quests/bat_invasion_game.nvgt b/src/quests/bat_invasion_game.nvgt index 9d0812d..71897c4 100644 --- a/src/quests/bat_invasion_game.nvgt +++ b/src/quests/bat_invasion_game.nvgt @@ -18,7 +18,7 @@ int run_bat_invasion() { i18n_translate_string_array_in_place(instructions); text_reader_lines(instructions, i18n_text("Quest Instructions"), true); - speak_with_history("Starting.", true); + speak_with_history(tr("system.quest.minigame.starting"), true); wait(500); int turns = 10; @@ -101,6 +101,8 @@ int run_bat_invasion() { wait(400); } - speak_with_history("Bat invasion complete. Score " + score + ".", true); + dictionary batScoreArgs; + batScoreArgs.set("score", score); + speak_with_history(trf("system.quest.bat_invasion.complete_score", batScoreArgs), true); return score; } diff --git a/src/quests/catch_the_boomerang_game.nvgt b/src/quests/catch_the_boomerang_game.nvgt index 3964535..e99a904 100644 --- a/src/quests/catch_the_boomerang_game.nvgt +++ b/src/quests/catch_the_boomerang_game.nvgt @@ -1,4 +1,14 @@ // Catch the Boomerang quest game +string get_boomerang_skill_text(int points) { + if (points <= 1) + return tr("system.quest.boomerang.skill.almost_dropped"); + if (points == 2) + return tr("system.quest.boomerang.skill.managed_to_catch"); + if (points == 3) + return tr("system.quest.boomerang.skill.caught"); + return tr("system.quest.boomerang.skill.expertly_caught"); +} + int run_catch_the_boomerang() { string[] instructions; instructions.insert_last("=== Catch the Boomerang ==="); @@ -21,13 +31,12 @@ int run_catch_the_boomerang() { const int turnsTotal = 5; int score = 0; int caughtCount = 0; - string[] skillLevel = {"", "almost dropped", "managed to catch", "caught", "expertly caught"}; bool firstTurnPrompt = true; for (int turn = 0; turn < turnsTotal; turn++) { if (firstTurnPrompt) { - speak_with_history("Press Space to throw.", true); + speak_with_history(tr("system.quest.boomerang.press_space_to_throw"), true); firstTurnPrompt = false; } @@ -67,12 +76,21 @@ int run_catch_the_boomerang() { points = 4; score += points; caughtCount++; - string promptSuffix = (turn < turnsTotal - 1) ? " Press Space to throw." : ""; - speak_with_history( - "You " + skillLevel[points] + " the boomerang. " + points + " points." + promptSuffix, true); + string promptSuffix = ""; + if (turn < turnsTotal - 1) + promptSuffix = " " + tr("system.quest.boomerang.press_space_to_throw"); + dictionary skillArgs; + skillArgs.set("skill", get_boomerang_skill_text(points)); + skillArgs.set("points", points); + skillArgs.set("suffix", promptSuffix); + speak_with_history(trf("system.quest.boomerang.caught_result", skillArgs), true); } else { - string promptSuffix = (turn < turnsTotal - 1) ? " Press Space to throw." : ""; - speak_with_history("You missed the boomerang." + promptSuffix, true); + string promptSuffix = ""; + if (turn < turnsTotal - 1) + promptSuffix = " " + tr("system.quest.boomerang.press_space_to_throw"); + dictionary missedArgs; + missedArgs.set("suffix", promptSuffix); + speak_with_history(trf("system.quest.boomerang.missed", missedArgs), true); } resolved = true; } @@ -86,8 +104,12 @@ int run_catch_the_boomerang() { // Give one centered pass (y == 0) as a final catch window. if (boomerangY > 0) { - string promptSuffix = (turn < turnsTotal - 1) ? " Press Space to throw." : ""; - speak_with_history("The boomerang hit you." + promptSuffix, true); + string promptSuffix = ""; + if (turn < turnsTotal - 1) + promptSuffix = " " + tr("system.quest.boomerang.press_space_to_throw"); + dictionary hitArgs; + hitArgs.set("suffix", promptSuffix); + speak_with_history(trf("system.quest.boomerang.hit_you", hitArgs), true); quest_boomerang_hit_sound(); resolved = true; } @@ -97,6 +119,9 @@ int run_catch_the_boomerang() { wait(400); } - speak_with_history("You caught " + caughtCount + " boomerangs for a total of " + score + " points.", true); + dictionary boomerangSummaryArgs; + boomerangSummaryArgs.set("count", caughtCount); + boomerangSummaryArgs.set("score", score); + speak_with_history(trf("system.quest.boomerang.summary", boomerangSummaryArgs), true); return score; } diff --git a/src/quests/enchanted_melody_game.nvgt b/src/quests/enchanted_melody_game.nvgt index 513999d..49bd824 100644 --- a/src/quests/enchanted_melody_game.nvgt +++ b/src/quests/enchanted_melody_game.nvgt @@ -39,7 +39,7 @@ void run_practice_mode() { text_reader_lines(instructions, i18n_text("Quest Instructions"), true); // Practice mode announcement - speak_with_history("Practice mode. Press Enter to begin, Escape to cancel.", true); + speak_with_history(tr("system.quest.enchanted_melody.practice_prompt"), true); while (true) { wait(5); @@ -72,7 +72,7 @@ int run_enchanted_melody() { return 0; } - speak_with_history("Starting. Repeat the pattern.", true); + speak_with_history(tr("system.quest.enchanted_melody.starting_prompt"), true); wait(500); int[] pattern; @@ -96,7 +96,10 @@ int run_enchanted_melody() { play_note(note); if (note != pattern[index]) { int score = rounds * 2; - speak_with_history("You matched " + rounds + " notes. Score " + score + ".", true); + dictionary melodyScoreArgs; + melodyScoreArgs.set("rounds", rounds); + melodyScoreArgs.set("score", score); + speak_with_history(trf("system.quest.enchanted_melody.score", melodyScoreArgs), true); return score; } index++; diff --git a/src/quests/escape_from_hel_game.nvgt b/src/quests/escape_from_hel_game.nvgt index 7fff9c2..e369166 100644 --- a/src/quests/escape_from_hel_game.nvgt +++ b/src/quests/escape_from_hel_game.nvgt @@ -116,7 +116,9 @@ int run_escape_from_hel() { pit_handle = -1; } p.play_2d("sounds/quests/fall.ogg", listener_x, listener_y, listener_x, listener_y, false); - speak_with_history("You fell in. Score " + score + ".", true); + dictionary fellInArgs; + fellInArgs.set("score", score); + speak_with_history(trf("system.quest.escape_from_hel.fell_in_score", fellInArgs), true); return score; } diff --git a/src/quests/skeletal_bard_game.nvgt b/src/quests/skeletal_bard_game.nvgt index 513de0a..9a7afe5 100644 --- a/src/quests/skeletal_bard_game.nvgt +++ b/src/quests/skeletal_bard_game.nvgt @@ -10,7 +10,9 @@ void play_skeletal_bard_note() { int select_note_count(int minNotes, int maxNotes, int startValue) { int selection = startValue; - speak_with_history("Select number of notes. " + selection + ".", true); + dictionary selectArgs; + selectArgs.set("selection", selection); + speak_with_history(trf("system.quest.skeletal_bard.select_notes", selectArgs), true); while (true) { wait(5); @@ -82,9 +84,11 @@ int run_skeletal_bard() { points = 0; score += points; - speak_with_history("You entered " + guess + " notes and the actual number was " + length + ". " + points + - " points. Press Enter to continue.", - true); + dictionary roundResultArgs; + roundResultArgs.set("guess", guess); + roundResultArgs.set("actual", length); + roundResultArgs.set("points", points); + speak_with_history(trf("system.quest.skeletal_bard.round_result", roundResultArgs), true); while (true) { wait(5); handle_global_volume_keys(); @@ -97,6 +101,8 @@ int run_skeletal_bard() { } } - speak_with_history("Skeletal Bard complete. Your score for all five tunes is " + score + ".", true); + dictionary bardSummaryArgs; + bardSummaryArgs.set("score", score); + speak_with_history(trf("system.quest.skeletal_bard.complete_score", bardSummaryArgs), true); return score; } diff --git a/src/save_system.nvgt b/src/save_system.nvgt index f45b68b..4a76079 100644 --- a/src/save_system.nvgt +++ b/src/save_system.nvgt @@ -436,7 +436,7 @@ bool select_save_file(string& out filename) { } int selection = 0; - speak_with_history("Load game. Select character. Press delete to remove a save.", true); + speak_with_history(tr("system.load_game.select_prompt"), true); speak_with_history(options[selection], true); bool refreshList = false; @@ -473,7 +473,7 @@ bool select_save_file(string& out filename) { int confirm = ui_question("", prompt); if (confirm == 1) { if (file_delete(resolve_save_path(files[selection]))) { - speak_with_history("Save deleted.", true); + speak_with_history(tr("system.load_game.save_deleted"), true); refreshList = true; break; } else { diff --git a/src/time_system.nvgt b/src/time_system.nvgt index fb69da9..231fe98 100644 --- a/src/time_system.nvgt +++ b/src/time_system.nvgt @@ -279,7 +279,7 @@ string expand_regular_area() { } area_expanded_today = true; - notify("The area has expanded! New territory discovered to the east."); + notify(tr("system.time.event.area_expanded")); return terrain_type; } @@ -334,7 +334,7 @@ void expand_mountain() { } area_expanded_today = true; - notify("A mountain range has been discovered to the east!"); + notify(tr("system.time.event.mountain_discovered")); } void start_invasion() { @@ -343,9 +343,14 @@ void start_invasion() { invasion_start_hour = current_hour; invasion_enemy_type = get_invasion_enemy_type_for_terrain(expansion_terrain); invasion_started_once = true; - string source = (expansion_terrain == "mountain") ? "the mountains" : "the new area"; + string source = + (expansion_terrain == "mountain") ? tr("system.time.event.invasion_source_mountains") + : tr("system.time.event.invasion_source_new_area"); string enemy_plural = get_invasion_enemy_plural(invasion_enemy_type); - notify(enemy_plural + " are invading from " + source + "!"); + dictionary args; + args.set("enemy_plural", enemy_plural); + args.set("source", source); + notify(trf("system.time.event.invasion_start", args)); } void update_invasion_chance_for_new_day() { @@ -466,7 +471,7 @@ void start_zombie_swarm() { zombie_swarm_active = true; zombie_swarm_start_hour = current_hour; zombie_swarm_duration_hours = get_zombie_swarm_duration_hours(); - speak_with_history("A swarm of zombies has been spotted.", true); + speak_with_history(tr("system.time.event.zombie_swarm_spotted"), true); } void end_zombie_swarm() { @@ -642,12 +647,19 @@ void attempt_resident_recruitment() { return; residents_count += added; - string join_message = (added == 1) ? "A survivor joins your base." : "" + added + " survivors join your base."; + string join_message = ""; + if (added == 1) { + join_message = tr("system.time.event.survivor_joins_one"); + } else { + dictionary joinArgs; + joinArgs.set("count", added); + join_message = trf("system.time.event.survivor_joins_many", joinArgs); + } notify(join_message); // Notify if base is now full if (residents_count >= MAX_RESIDENTS) { - notify("Your base is at maximum capacity."); + notify(tr("system.time.event.base_max_capacity")); } } @@ -655,7 +667,9 @@ void end_invasion() { invasion_active = false; invasion_start_hour = -1; transition_bandits_to_wandering(); - notify("The " + get_invasion_enemy_label(invasion_enemy_type) + " invasion has ended."); + dictionary args; + args.set("enemy", get_invasion_enemy_label(invasion_enemy_type)); + notify(trf("system.time.event.invasion_ended", args)); attempt_resident_recruitment(); } @@ -709,15 +723,15 @@ void update_blessings() { if (blessing_speed_active && blessing_speed_timer.elapsed >= BLESSING_SPEED_DURATION) { blessing_speed_active = false; update_max_health_from_equipment(); - speak_with_history("The speed blessing fades.", true); + speak_with_history(tr("system.time.event.blessing_speed_fades"), true); } if (blessing_resident_active && blessing_resident_timer.elapsed >= BLESSING_RESIDENT_DURATION) { blessing_resident_active = false; - speak_with_history("The residents' purpose fades.", true); + speak_with_history(tr("system.time.event.blessing_resident_fades"), true); } if (blessing_search_active && blessing_search_timer.elapsed >= BLESSING_SEARCH_DURATION) { blessing_search_active = false; - speak_with_history("The eagle's sight fades.", true); + speak_with_history(tr("system.time.event.blessing_search_fades"), true); } } @@ -827,13 +841,13 @@ void update_time() { handle_pet_hourly_update(current_hour); if (current_hour == 18 && !sun_setting_warned) { - notify("The sun is setting."); + notify(tr("system.time.event.sun_setting")); sun_setting_warned = true; } else if (current_hour == 19) { sun_setting_warned = false; } if (current_hour == 5 && !sunrise_warned) { - notify("The sky begins to brighten."); + notify(tr("system.time.event.sky_brightening")); sunrise_warned = true; } else if (current_hour == 6) { sunrise_warned = false; @@ -866,7 +880,9 @@ void update_time() { if (has_any_storage_food()) { int gained = add_barricade_health(residents_count * get_resident_effect_multiplier()); if (gained > 0 && x <= BASE_END) { - speak_with_history("Residents repaired the barricade. +" + gained + " health.", true); + dictionary args; + args.set("health", gained); + speak_with_history(trf("system.time.event.residents_repaired_barricade", args), true); } } } @@ -929,7 +945,7 @@ void update_incense_burning() { if (incense_hours_remaining <= 0) { incense_hours_remaining = 0; incense_burning = false; - notify("The incense has burned out."); + notify(tr("system.time.event.incense_burned_out")); } } @@ -941,46 +957,57 @@ void check_time_input() { string get_time_string() { int display_hour = current_hour; - string period = "am"; + string periodKey = "system.time.period.am"; if (display_hour == 0) { display_hour = 12; } else if (display_hour == 12) { - period = "pm"; + periodKey = "system.time.period.pm"; } else if (display_hour > 12) { display_hour -= 12; - period = "pm"; + periodKey = "system.time.period.pm"; } - string result = display_hour + " oclock " + period + " day " + current_day; + dictionary timeArgs; + timeArgs.set("hour", display_hour); + timeArgs.set("period", tr(periodKey)); + timeArgs.set("day", current_day); + string result = trf("system.time.report", timeArgs); + string[] conditions; if (is_daytime) { if (weather_state == WEATHER_CLEAR) { - conditions.insert_last("Sunny"); + conditions.insert_last(tr("system.time.condition.sunny")); } else { - conditions.insert_last("Daylight"); + conditions.insert_last(tr("system.time.condition.daylight")); } } else { - conditions.insert_last("Dark"); + conditions.insert_last(tr("system.time.condition.dark")); } if (weather_state == WEATHER_WINDY) { - conditions.insert_last("Windy"); + conditions.insert_last(tr("system.time.condition.windy")); } else if (weather_state == WEATHER_RAINY) { - conditions.insert_last("Raining"); + conditions.insert_last(tr("system.time.condition.raining")); } else if (weather_state == WEATHER_STORMY) { - conditions.insert_last("Storming"); + conditions.insert_last(tr("system.time.condition.storming")); } - bool can_see_night_sky = (weather_state == WEATHER_CLEAR || weather_state == WEATHER_WINDY); - if (!is_daytime && can_see_night_sky) { - conditions.insert_last("Moon and stars"); + bool canSeeNightSky = (weather_state == WEATHER_CLEAR || weather_state == WEATHER_WINDY); + if (!is_daytime && canSeeNightSky) { + conditions.insert_last(tr("system.time.condition.moon_and_stars")); } + if (conditions.length() > 0) { - string condition_text = conditions[0]; + string conditionText = conditions[0]; for (uint i = 1; i < conditions.length(); i++) { - condition_text += ", " + conditions[i]; + conditionText += ", " + conditions[i]; } - result += ". " + condition_text; + + dictionary conditionArgs; + conditionArgs.set("time", result); + conditionArgs.set("conditions", conditionText); + result = trf("system.time.report_with_conditions", conditionArgs); } + return result; } diff --git a/src/world/world_fires.nvgt b/src/world/world_fires.nvgt index cad30ff..e29f39a 100644 --- a/src/world/world_fires.nvgt +++ b/src/world/world_fires.nvgt @@ -35,13 +35,19 @@ class WorldFire { // Warn when fuel is low (30 seconds remaining) if (!low_fuel_warned && fuel_remaining <= 30000 && fuel_remaining > 0) { low_fuel_warned = true; - notify("Fire at x " + position + " y " + y + " is getting low!"); + dictionary fireLowArgs; + fireLowArgs.set("position", position); + fireLowArgs.set("y", y); + notify(trf("system.fire.low_fuel_at", fireLowArgs)); } // Fire went out if (fuel_remaining <= 0) { fuel_remaining = 0; - notify("Fire at x " + position + " y " + y + " has gone out."); + dictionary fireOutArgs; + fireOutArgs.set("position", position); + fireOutArgs.set("y", y); + notify(trf("system.fire.went_out_at", fireOutArgs)); if (sound_handle != -1) { p.destroy_sound(sound_handle); sound_handle = -1; diff --git a/src/world/world_snares.nvgt b/src/world/world_snares.nvgt index bfbb5f0..3af0961 100644 --- a/src/world/world_snares.nvgt +++ b/src/world/world_snares.nvgt @@ -78,7 +78,10 @@ class WorldSnare { int roll = random(1, 100); if (roll <= escape_chance) { // Animal escaped! - notify("A " + catch_type + " escaped from your snare at x " + position + " y 0!"); + dictionary snareEscapeArgs; + snareEscapeArgs.set("catch_type", i18n_translate_fragment_value(catch_type)); + snareEscapeArgs.set("position", position); + notify(trf("system.snare.escape_at", snareEscapeArgs)); remove_snare_at(position); return; } @@ -95,7 +98,10 @@ class WorldSnare { catch_type = get_random_small_game(); escape_chance = 0; hours_with_catch = 0; - notify(catch_type + " caught in snare at x " + position + " y 0!"); + dictionary snareCaughtArgs; + snareCaughtArgs.set("catch_type", i18n_translate_fragment_value(catch_type)); + snareCaughtArgs.set("position", position); + notify(trf("system.snare.caught_at", snareCaughtArgs)); } } } @@ -141,9 +147,11 @@ void check_snare_collision(int player_x) { p.play_stationary("sounds/actions/break_snare.ogg", false); if (s.has_catch) { - speak_with_history("You stepped on your snare! The " + s.catch_type + " escaped.", true); + dictionary snareSteppedArgs; + snareSteppedArgs.set("catch_type", i18n_translate_fragment_value(s.catch_type)); + speak_with_history(trf("system.snare.stepped_on_with_escape", snareSteppedArgs), true); } else { - speak_with_history("You stepped on your snare and broke it!", true); + speak_with_history(tr("system.snare.stepped_on_broke"), true); } remove_snare_at(player_x);