-
Notifications
You must be signed in to change notification settings - Fork 3
09. Argument‐Formatted Strings: Phrase Maps
The Phrase Maps tool is a standalone utility designed for creating reusable, dynamically formatted, and conditionally varied text strings.
- Role: Ideal for UI labels, notifications, system messages, combat text, or any text outside of the main dialogue system that requires dynamic formatting logic.
-
Storage: Each Phrase Map is stored as a single
PhraseMapresource file (.tres), which features a custom icon.
Note
Unlike the Discourse tool, which manages localization internally, each PhraseMap resource file corresponds to only one locale.
To support multiple languages, you must create separate files for each one (e.g., ui_text_en_US.tres, ui_text_es_MX.tres).
Double-clicking a PhraseMap resource file will automatically open it within the Nexus Forge Phrase Map tool.
The editor is designed for managing multiple files and defining complex conditional formatting cases.
This column controls resource loading and sets the context for the phrase map.
-
File Access:
- A text field at the top allows searching among open files.
- A vertical three-dot menu provides options to Create New or Open Phrase Map resources.
- Open Files Tree: Lists all the opened files.
-
Locale Selection:
- Two dropdown menus allow the user to explicitly define the Language and Country for this Phrase Map file (e.g., "English" and "United States of America" for
en_USor "French" + "N/A" forfr). - These dropdowns are pre-populated with all locales supported by Godot and default to the user's system language on launch.
- Two dropdown menus allow the user to explicitly define the Language and Country for this Phrase Map file (e.g., "English" and "United States of America" for
Note
The file tree lists all loaded files by name. Hovering over a file displays its full file path in a tooltip.
This column manages the creation and base text assignment for all phrases.
- Search Functionality: A search bar allows filtering keys.
- Creation: A button featuring a dialog bubble and a green '+' adds a new key-value pair to the map.
-
Key/Text Fields: This is where the unique Key (e.g.,
GREETING) and the Base Text (e.g.,Hello {player_name}) are defined. - Conflict Resolution: If a newly entered key is identical to an existing key, the text fields for both entries will turn red, signaling a conflict.
-
Case Editing Toggle:
- A Pencil Icon next to the key/text pair toggles the case editing mode.
- When pressed, the icon changes to an Unlocked Lock, the Base Text field is disabled (as its content is now managed by cases), and Column 3 is enabled. The Key field remains editable.
- Pressing the Unlocked Lock icon again saves the cases and re-enables the Base Text field.
Tip
The search bar by default searches on both keys and text, but supports prefixes for targeted searching:
-
key:: Searches only within the unique key fields.
-
text:: Searches only within the assigned base text fields.
Caution
To prevent data loss on save, the editor will automatically solve key conflicts by adding numerical suffixes (1, 2, 3, etc.) to the conflicting or empty keys.
This column is used to define the complex, argument-based output logic for the selected phrase.
- Case Search: A search bar allows filtering cases.
-
Format Field Selection:
- A dropdown lists all format tags (e.g.,
$player/name,!potion_count,day_time) found in the base text without curly brackets. You select one to define conditional cases for it. - A button next to the dropdown (Curly brackets with a green +) adds a new custom case for the selected tag.
- A dropdown lists all format tags (e.g.,
- Case Conflicts: If two custom cases share the exact same condition (e.g., two cases for "1"), the text will turn red.
Tip
The search bar by default searches on both cases and results, but supports prefixes for targeted searching:
-
case:: Searches only within the specific case condition (e.g., "0" or "Jhon").
-
result:: Searches only within the resulting output text.
Note
- The default case is always visible and cannot be removed.
Caution
To prevent data loss on save, the editor will automatically solve case conflicts by adding numerical suffixes (1, 2, 3, etc.) to the conflicting or empty keys.
The Phrase Maps tool combines the power of the Nexus Forge variable system and a specific object for method calling, with standard Godot argument formatting.
Phrase Maps support all three primary formatting syntax types within a single phrase definition:
| Syntax | Name | Source | Usage |
|---|---|---|---|
{$...} |
Variable Access | NexusForge.Blackboard |
Retrieves data (e.g., {$player/level}) from global state. |
{!...} |
Method Call |
PhraseAPI[1]
|
Calls a function and inserts its return value. Supports stacking (e.g., {!capitalize|!get_player_name}). |
{...} |
Standard Arguments | Passed via API call | Inserts arguments (e.g., {day_time}) passed explicitly to the get_text function. |
Important
When defining conditional cases, the value being checked is always converted to a string before comparison.
This is especially important for variable access ({$...}) or method calls ({!...}) that return numbers.
A float value of 1 will be converted to the string "1.0", which will NOT match a custom case defined for the string "1".
The API is accessed directly from an instance of the loaded PhraseMap resource.
| Function Signature | Purpose | Return Type |
|---|---|---|
get_text(key, override_values = {}) |
Primary Function: Retrieves and formats the phrase text. | String |
This dictionary is the key to the tool's flexibility. It provides values for all format types:
-
Standard Placeholders (
{...}): You must provide a key for standard placeholders (e.g.,{"day_time": "morning"}). -
Expression Overrides (
{$...}and{!...}): You can provide a key matching the full expression string (e.g.,{"$player/level": "99", "!player_name": "james"}). If these keys exist, the system uses the provided value and skips the internal Blackboard lookup or method call entirely.
| Function Signature | Purpose | Return Type |
|---|---|---|
entries() |
Returns a list of all registered format entries. | Array[StringName] |
set_entry(key, text = "") |
Creates a new format entry and sets its base text. | - |
get_entry(key) |
Returns the base text of the format entry. | String |
has_entry(key) |
Returns true if the format entry key exists. |
Bool |
erase_entry(key) |
Deletes the format entry. | - |
These functions allow granular, programmatic control over the conditional logic.
| Function Signature | Purpose | Return Type |
|---|---|---|
get_valid_formats(phrase_text) |
Static helper that returns all format tags ({...}) found in a string. |
Array[String] |
get_formats(of) |
Returns all parts that can be formatted on an entry. | Array[String] |
has_format(entry, format) |
Checks if the phrase's base text contains the specified format tag (format). |
Bool |
set_format_default(entry, format, value) |
Sets the fallback text (default case) for a specific format tag. | - |
get_case_default(entry, of) |
Returns the default case text for a format tag. | String |
set_case(entry, argument, case, value) |
Sets a custom case condition (case) and its result (value) for a format tag. |
- |
clear_cases(entry, argument |
Clears all custom cases for a specific format tag. | - |
get_case(entry, argument, case) |
Returns the result for a specific custom case. | String |
has_case(entry, argument, case) |
Checks if a specific custom case condition exists. | Bool |
Tip
- In order to use the passed down argument in a case text, you need to write down the case between curly braces. (e.g., Using
{$player/name}). - When creating cases for a format tag you can use the arguments from other tags in your main one. (e.g., Using
"There are {!potion_count}"as a case result when editing the cases for$player/name).
Using the text "{!companion_count} collected {potion_count} {$player/name}{$player/companion/name}".
| Format Tag | Cases | Note |
|---|---|---|
!companion_count |
Default: You and {$player/companion/name}"0": You've
|
We're using the passed argument from $player/companion/name in a !companion_count case. |
potion_count |
Default: {potion_count} potions0: no potions. Well that's a shocker1: one single potion. Try harder next time
|
We need to pass this argument via overrides. |
$player/name |
Default: {$player/name}.mxyzptlk: m-mx...you!
|
|
$player/companion/name |
Default:
|
We needed this info for a case in !companion_count but we don't want it in the final text, so we default to empty so it'll be removed. |
Two examples of possible result are:
- You and Mia collected one single potion. Try harder next time John.
- You've collected 13 potions m-mx...you!
- The default path of the PhraseAPI is:
res://addons/nexus_forge/resources/localization/phrase_api.gd