I can see nice things happen here and on nexus mods, so I think it's time to write up some stuff for the others. As I work mostly with the Stringtables I begin with them. And I hope, BMac or any other Dev could add things I am missing or explain stuff in greater detail. Let's begin. ~99,5% of the visible Text ingame is externalised in the exported folder. And translated into 8 languages. The Exceptions are the Credits, News (they come via web request) and a few which the developers missed to mark as “externalize”. The exported Text is stored in xml Files with a .stringtable fileextension diveded into files according to usage, be it Gui, Abilities or a Conversation with Edér.
<?xml version="1.0" encoding="utf-8"?>
<StringTableFile xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<Name>game\itemmods</Name>
<NextEntryID>1</NextEntryID>
<EntryCount>1024</EntryCount>
<Entries>
<Entry>
<ID>2</ID>
<DefaultText>Water proof</DefaultText>
<FemaleText />
</Entry>
<Entry>
<ID>3</ID>
<DefaultText>Dishwasher proof</DefaultText>
<FemaleText />
</Entry>
</Entries>
</StringTableFile>
That's the structure of any Stringtable file. It has:
a XML header,
a <Stringtable> wrapper with ‘some’ namespace,
a <Name> which must correspond to the folder and filename of the file itself
a <NextEntryID> whose value is not important for us
a <EntryCount> whose value is not important for us
and a list of <Entries>Each of them has exactly 3 elements.
a <ID> which is used by the game to reference this particular string
a <DefaultText> which is shown per default
and a <FemaleText> which is shown if the person in the current context is female, may it your main character or a female NPC
Rule 1 When editing a Stringtable, or creating a new one for the Override folder of your mod. Always make sure the File is valid xml! You can test that with this little xsd file and a validator tool:
Name the file stringtable.xsd
<xsd:schema attributeFormDefault="unqualified" elementFormDefault="qualified" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<xsd:element name="StringTableFile">
<xsd:complexType>
<xsd:sequence>
<xsd:element type="xsd:string" name="Name"/>
<xsd:element type="xsd:integer" name="NextEntryID"/>
<xsd:element type="xsd:integer" name="EntryCount"/>
<xsd:element name="Entries">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="Entry" maxOccurs="unbounded" minOccurs="0">
<xsd:complexType>
<xsd:sequence>
<xsd:element type="xsd:integer" name="ID"/>
<xsd:element type="xsd:string" name="DefaultText"/>
<xsd:element type="xsd:string" name="FemaleText"/>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
</xsd:element>
</xsd:sequence>
</xsd:complexType>
<xsd:unique name="ids_sind_unique">
<xsd:selector xpath="Entries/Entry"/>
<xsd:field xpath="ID"/>
</xsd:unique>
</xsd:element>
</xsd:schema>
Validation Tools
The validation tool I use is xsvd.jar from https://github.com/amouat/xsd-validator/tree/master/lib so if you use that you also need java installed.
alternative online tool https://devutilsonline.com/xml/validate
alternative online tool https://www.freeformatter.com/xml-validator-xsd.html
The most basic invocation of xsvd.jar on a terminal would be:
java -jar xsdv.jar stringtable.xsd yourChangedFile.stringtable
To which it can respond with:
yourChangedFile.stringtable validates.
or
yourChangedFile.stringtable fails to validate because:
<reason>
If all files validate you can enjoy your changes. What can one do with this? You can override any line, with anything, as is done here: https://www.nexusmods.com/pillarsofeternity2/mods/5 or here: https://www.nexusmods.com/pillarsofeternity2/mods/42 You can add your own texts via the override folder for your custom items, conversations or quests You can style the text mostly free. Known limitations The font ingame has no iconographies for Cyrillic or Korean, or any other non Latin script.
As the file has to be valid XML all helpers, which use < and > have to be written as their replacement Tags < and >. XML in general has 3 more escapes, but they are, so far, not needed for stringtable files. Full reference: https://stackoverflow.com/questions/1091945/what-characters-do-i-need-to-escape-in-xml-documents General text handling In the text you have various helper elements to style the text or insert variable values. Which variables are available depends on the context. Besides the replacement system there is an automatic coloring system in place, which recognizes direct speech and changes the font color from gray to white. This system works flawless in PoE 2 and all available translations.
Links get always a teal color in Conversations and the Log, while they are blue by default in popups and the cyclopedia. For displays which have Iconographies all non Word Characters from the Start of the Sentence are removed. So if the Text is Wrapped in „“ your result is a stray “ at the end of the Text. Ex-curse There are 2 types of String renderings for “conversations”. One is the big modal two part speech box and the other one are barks. These are displayed as floating text above the head of the speaker.
Basic text effects
<b>Bold</b>
<i>Italic</i>
<u>Underline</u> Be careful with that one. The underline line in the log window stays visible if the hud is hidden.
<ispeech>Used when the Watcher has a Vision and “speaks“ with himself</ispeech> The text is Italic in the conversation panel and Italic and white in the log panel
<#FF0000>Red!</color> Same colors as in html
Links of various kind
<g>Link to a Cyclopedia entry</g> Most of the time the game finds out when to set a link if the word is the same, but for non English languages that's not that easy. So for example in German to add a link to Zersetzung – the name of the Cyclopedia entry – in the word „Zersetzungsschaden“ (corrode damage) one would write <g>Zersetzung</g>sschaden. The text will be displayed in teal.
<xg> Anti Link. Prevents an automatic link to a normally linked word.
<link="gamedata://b863a8c3-ed3b-4787-8b3f-2bdea96c47a1">Machtschwung</link> Link to Items or Ability popups. Good for showing a quest reward
<link=https://forums.obsidian.net/forum/126–pillars–of–eternity–ii–deadfire–backer–beta/>forums.obsidian.net</link>or link to the web
<link="glossary://GlossaryEntry_Skaen">Der Stille Sklave</link> Link to named entries of the glossary. Words which have an entry in the Cyclopdia are linked automatically.
<link="stringtooltip://cyclopedia/56">strudelt gefährlich</link> Make Tooltips with texts from this file. For the Example it's ID 56 from cyclopedia.stringtable. You could use any file of the game folder.
<link="neutralvalue://Vailian: Gebt mir den Seelenverschlinger!>„Derme o Engoliero me Espirs!</link> Link to inline translations of all the different con langs. Which are these in Eora known ones, and then any you want:Eld Aedyran
Vailian
Ixamitl
Engwithan
Ordhjóma
Huana
Rauataian
Lembur
<sprite="Inline" name="action_hold" tint=1> Use sprites in the text. Currently they are on mass in the Ship battle and the Tutorial. Attention: Sprites have no end tag! There are plenty of icons to use. See the List from BMacs Post: https://forums.obsidian.net/topic/100818-how-to-work-with-stringtables/?p=2041213
Replacement Token
{0}, {1} etc. get replaced with numbers or texts from some source. Like function evaluations. Which functions there are, and how many return values they have is a whole different topic. Example: {0} {1} {2} for {3} damage {4}. Could result in Aloth hits Edér for 12 fire damage. (and I have forgotten what the {4} does.)The curly braces replacements can have subvalues which can be at least these. Percent gets a % sign from itself.
{0:AfflictionType}
{0:DamageType}
{0:Equippable}
{0:WeaponType}
{0:Value}
{0:Value:DamageProc}
{0:Value:Duration}
{0:Value:PercentBonus}
{0:Value:DurationBonus}
{0:Value:InvertPercentBonus}
{0:Value:Percent}
{0:Value:Straight}
{0:ExtraValue:straight}
{0:ExtraValue:Percent}
{0:ExtraValue:Duration}
[specified 0] get replaced with the name of the user character at the current selection for this particular scripted interaction. If you choose “Edér should jump the cliff“ and then „Aloth should watch it“ Aloth will be [specified 1]
[slot 0] is comparable to [specified x] but it refers to the order of your party members. The left most portrait is Slot 0. It is replaced with the character name.
[skillCheck 0] Is replaced with the character name which do the task
[Player Animal Companion] is replaced with the Name of your cat, äh, animal companion [Player Class] [Player Culture] [Player Deity] [Player Name] [Player Race] [Player Ship] [Player Subrace]
[Death Grunt/Cry 1] According to BMac this is only to show sounds, it has no significance ingame. Maybe a feature to play that audio was once planned but got clipped.
[OrlansHeadGame_OpponentLastResult] these are for the knive throwing minigame [OrlansHeadGame_OpponentLastScore] [OrlansHeadGame_OpponentTotalScore] [OrlansHeadGame_PlayerLastResult] [OrlansHeadGame_PlayerLastScore] [OrlansHeadGame_PlayerTotalScore]
[shipDuel_BraceChance] [shipDuel_OpponentShip] [shipDuel_Opponent] [shipDuel_PlayerFullSailDist] [shipDuel_PlayerHalfSailDist] [shipDuel_PlayerShip] [shipDuel_SurrenderCost]
A few more Images: https://imgur.com/a/LfuSA08