TSLPatcher TLKList Syntax - NickHugi/PyKotor GitHub Wiki
The [TLKList] section in TSLPatcher's changes.ini file enables you to modify TLK (Talk Table) files used throughout KotOR. TLK files store all in-game text strings and their associated voiceover sound references. The most important TLK file is dialog.tlk, which contains all dialog, item descriptions, conversations, and other text displayed in the game.
TSLPatcher was designed by Stoffe with an append-only philosophy for TLK modifications. This design maximizes mod compatibility by non-destructively adding new entries to the end of dialog.tlk, allowing multiple mods to safely coexist without conflicts.
TSLPatcher's TLK modification system provides several key advantages:
-
Avoid distributing large files: The
dialog.tlkfile is approximately 10 MB. Instead of distributing the entire modified file, TSLPatcher allows you to add only your new entries, significantly reducing mod file size. -
Memory system integration: TSLPatcher keeps StrRefs of newly added entries in memory, allowing you to insert those StrRefs into 2DA and GFF files as needed. For example, if you add the name of a new force power to
dialog.tlk, TSLPatcher can memorize the StrRef the name string ended up as, and insert that value into the "name" column inspells.2da. -
Cross-section token usage: StrRef tokens created in
[TLKList]can be used throughout other sections:- In
[2DAList]to assign stringrefs to 2DA cells - In
[GFFList]to assign stringrefs to GFF fields (including ExoLocString fields) - In
[CompileList]scripts where#StrRef#tokens are replaced during compilation - In
[SSFList]to assign stringrefs to soundset entries
- In
-
TLK (Talk Table): Binary file format storing text strings and voiceover references. The primary file is
dialog.tlk. -
StringRef (StrRef): Short for "String Reference", this is a numeric identifier/index for an entry in a TLK file. StringRefs start at 0 and increment sequentially. Example: StringRef 12345 refers to the 12346th entry in a TLK file. The StrRef is the identifier number that the game engine uses to retrieve text strings from
dialog.tlk. -
Key: The left side of the
=symbol in an INI entry (e.g.,StrRef0,AppendFile0) -
Value: The right side of the
=symbol in an INI entry. In[TLKList], values specify the index into TLK source files to read from. -
Token: A placeholder like
StrRef0orStrRef1that gets replaced with an actual StringRef during patching. -
Append: Non-destructive operation that adds new entries to the end of
dialog.tlk. This is TSLPatcher's primary and recommended method. -
Replace: Destructive operation that overwrites existing entries in
dialog.tlk. Should ONLY be used for fixing grammar, spelling, or typographical errors in existing game content. See Replace Functionality Warning for details. -
append.tlk: Default source file containing new strings to append. Created using TalkEd.exe (see Creating TLK Files). Located in
tslpatchdatafolder. -
appendf.tlk: Feminine/non-English localized version of
append.tlk. Used exclusively for KotOR1 Polish localization. Must have exactly the same number of entries asappend.tlk. See Localized Versions for details. -
dialog.tlk: The game's main TLK file containing all in-game text (typically ~10 MB). Modified files are written to the game's root directory (not override folder). TSLPatcher allows you to add new entries without distributing the entire large file.
- Glossary
- Benefits of TLK Modification
- Replace Functionality Warning
- Creating TLK Files
- Basic Structure
- Configuration Keys
- Entry Syntax
- Localized Versions
- Memory System
- Processing Order
- File Structure
- Complete Examples
- Common Use Cases
- Troubleshooting
- Best Practices
- Reference
TSLPatcher was designed by Stoffe to be append-only for TLK modifications. The original TSLPatcher exclusively appended new entries to the end of dialog.tlk and never replaced existing entries. This design was intentional to maximize mod compatibility:
- Breaks mod compatibility: If two mods replace the same stringref, they conflict irreconcilably
- Destroys vanilla content: Replaces original game text permanently, making it impossible to restore
- Prevents mod stacking: Can't safely use multiple mods that replace different entries simultaneously
- Defeats TSLPatcher's design: The tool was specifically designed for non-destructive appending to avoid conflicts
- Non-destructive: Appending preserves all existing game text, preventing conflicts between mods
-
Dynamic indexing: Uses tokens (
StrRef#) to handle variable stringref assignments without hard-coding indices - Mod stacking: Multiple mods can safely add entries without interfering with each other
-
Compatibility: Avoids the need to distribute full
dialog.tlkfiles (10+ MB), reducing mod size
- ✅ Fixing typos in base game text (e.g., "teh" → "the")
- ✅ Correcting grammar mistakes in vanilla content
- ✅ Fixing broken or corrupted entries
- ✅ Community patch projects (like K1CP) that systematically fix errors
- ❌ Adding new content (use AppendFile or StrRef syntax instead)
- ❌ Modifying existing text for flavor/preference
- ❌ Any scenario where append would work
For all new content, always use the append-based syntaxes described in Entry Syntax.
To use custom dialog.tlk entries in your mod, you must create source TLK files containing your new strings:
- Create a new TLK file: Use TalkEd.exe (a TLK editor tool) to create a new TLK file
- Add your entries: Add all your new text strings and voiceover sound references to this file
-
Save as append.tlk: Name the file exactly
append.tlk(case-sensitive) -
Place in tslpatchdata: Save
append.tlkin thetslpatchdatafolder
If you are using a non-English version of KotOR1 that has a dialogf.tlk file (Polish localization), you must also:
- Create appendf.tlk: Create a new file with the feminine form of your strings
-
Name it appendf.tlk: Must be named exactly
appendf.tlk(case-sensitive) -
Match entry count:
appendf.tlkmust have exactly the same number of entries asappend.tlk -
Matching indices: Each index in
appendf.tlkshould correspond to the same index inappend.tlk - Handle missing forms: If a string has no specific feminine form, put the same text in both files
Important: The entry count must match exactly. If append.tlk has 100 entries, appendf.tlk must also have exactly 100 entries, even if some are identical between the two files.
The ChangeEdit application provides a user-friendly GUI interface for configuring TLK entries without manually editing the INI file:
- Open append.tlk: In ChangeEdit, navigate to the "TLK Entries" section in the tree view
- Load file: Press the "Open append.tlk file..." button on top of the right list
- View entries: This lists all your custom text entries in the list to the right
-
Select entries: Select an entry you wish TSLPatcher to add to
dialog.tlk - Add to list: Press the left arrow icon (←) to add the entry to the list on the left
-
Token creation: Take note of the value in the left column, which should look like
StrRef0for the first entry, with an incrementing number (StrRef1,StrRef2, etc.) for each subsequent entry -
Use tokens: This token (e.g.,
StrRef0) is what you'll use in the 2DA and GFF sections to assign the resulting StrRef value to a 2DA cell or GFF field
Manual Editing: While ChangeEdit provides a GUI interface, you can also edit the changes.ini file directly with any text editor (Notepad, VS Code, etc.). The INI format is plain text and human-readable.
Important: When using ChangeEdit, always verify the generated INI entries match your expectations, especially for token names and entry indices.
[TLKList]
!DefaultDestination=.
!DefaultSourceFolder=.
!SourceFile=append.tlk
!SourceFileF=appendf.tlk
; Append new entries
StrRef0=0
StrRef1=1
; Append from custom file (Useful if you have a LOT of TLK entries and want to organize within multiple TLK files)
AppendFile0=custom_entries.tlk
[custom_entries.tlk]
0=10
1=11Key Points:
- All examples use append operations - the recommended approach
- Values specify which StrRef indices to read from source files
- Type: String (path)
-
Default:
.(kotor game installation path root) - Description: Default destination folder for TLK files when not overridden
-
Example:
!DefaultDestination=override
- Type: String (path)
-
Default:
.(tslpatchdata folder) -
Description: Default folder to search for TLK source files (e.g.,
append.tlk). This is a relative path frommod_path, which is typically thetslpatchdatafolder (the parent directory of thechanges.inifile). The default value.refers to thetslpatchdatafolder itself. -
Path Resolution: Files are resolved as
mod_path / !DefaultSourceFolder / filename. Whenmod_path = "C:/Mod/tslpatchdata":-
!DefaultSourceFolder=.resolves to e.g."C:/Mod/tslpatchdata" -
!DefaultSourceFolder=tlk_filesresolves to e.g."C:/Mod/tslpatchdata/tlk_files"
-
-
Example:
!DefaultSourceFolder=.(default, refers to tslpatchdata folder)
- Type: String (filename)
-
Default:
append.tlk - Description: Name of the TLK file to use when appending entries via StrRef syntax
-
Example:
!SourceFile=my_strings.tlk
- Type: String (filename)
-
Default:
appendf.tlk - Description: Name of the TLK file to use for feminine/non-English localized versions (exclusively KotOR1 Polish)
- Version Added: 1.2.8b6
-
Note: Must have exactly the same number of entries as
!SourceFile. Each index inappendf.tlkmaps directly to the same index inappend.tlk. If a string has no specific feminine form, put the same text in both files. -
Example:
!SourceFileF=my_strings_f.tlk
The following keys are NOT supported in [TLKList]:
-
!ReplaceFile- Not applicable to TLK files -
!OverrideType- Not applicable to TLK files
The [TLKList] section supports two primary entry syntax patterns, both using append operations:
-
StrRef Entries - Append from the default source file (
append.tlk) - AppendFile Syntax - Append from custom TLK files with flexible mappings
Important: Tokens are created from the value (the number on the right side of =). For StrRef<number>=<number> entries, the number in the key and value must match, and this matching number determines the token name.
-
StrRef0=0creates tokenStrRef0(reads index 0 fromappend.tlk) -
StrRef5=5creates tokenStrRef5(reads index 5 fromappend.tlk) - For AppendFile subsections,
10=10creates tokenStrRef10(reads index 10 from the source TLK)
The token name StrRef<number> is created from the matching number, and this token stores the new stringref that gets appended to dialog.tlk for use in other sections.
Purpose: Append new entries to dialog.tlk from the default source file (append.tlk)
Syntax:
StrRef<number>=<number>Parameters:
-
<number>- The index intoappend.tlk(or!SourceFile) to read from. This number must match in both the key and value.
Behavior:
- Appends a new entry to the end of
dialog.tlk(non-destructive) - Reads text and sound from
append.tlkat the specified index - The new entry receives the next available stringref automatically
- Creates token
StrRef<number>from the matching number (see How Token Creation Works) - Stores that new stringref in memory for use in other sections via the token
Examples:
[TLKList]
StrRef0=0 ; Reads index 0 from append.tlk, creates token StrRef0
StrRef1=1 ; Reads index 1 from append.tlk, creates token StrRef1
StrRef2=2 ; Reads index 2 from append.tlk, creates token StrRef2Purpose: Add entries from a custom TLK file using index mappings
Syntax:
AppendFile<anything>=<tlk_filename>Parameters:
-
<tlk_filename>- Name of a TLK file in the source folder OR name of a subsection in the INI
Behavior:
- Creates a new section
[<tlk_filename>]if the file doesn't exist in source - Maps entries from the source TLK to
dialog.tlkusing the subsection mappings - All entries are added (not replaced) to
dialog.tlk - For AppendFile, entries are appended and tokens are created from the mapping values
Subsection Syntax:
[<tlk_filename>]
<token_identifier>=<source_index>
StrRef<token_identifier>=StrRef<source_index> ; Alternative explicit syntaxSubsection Parameters:
-
<source_index>- The index into the source TLK file to read from. TokenStrRef{source_index}is created from this value. The number in the key should match the number in the value for clarity.
Examples:
[TLKList]
AppendFile0=planets.tlk ; Creates subsection [planets.tlk] for mappings
[planets.tlk]
10=10 ; Reads index 10, creates token StrRef10
11=11 ; Reads index 11, creates token StrRef11
12=12 ; Reads index 12, creates token StrRef12 (alternative: StrRef12=StrRef12)Important Notes:
- The
<anything>inAppendFile<anything>is arbitrary and ignored - The subsection
[planets.tlk]can define mappings using numeric indices orStrRefsyntax
KotOR1 Polish edition uses both dialog.tlk and dialogf.tlk files. If your mod supports this localization:
-
Create both files: Create
append.tlk(masculine/standard) andappendf.tlk(feminine/localized) - Match entry counts: Both files must have exactly the same number of entries
-
Map indices: Entry at index 0 in
append.tlkcorresponds to index 0 inappendf.tlk - Handle duplicates: If a string doesn't have a feminine form, use the same text in both files
[TLKList]
!SourceFile=append.tlk
!SourceFileF=appendf.tlk
StrRef0=0
StrRef1=1When TSLPatcher processes entries, it automatically uses appendf.tlk when the target game has dialogf.tlk present.
-
KotOR2: Does not use
dialogf.tlk- onlydialog.tlkis used - Other Languages: Currently only KotOR1 Polish uses the dual-TLK system
- Entry Matching: The strict requirement for matching entry counts ensures proper localization mapping
When TLK entries are added via append operations, TSLPatcher stores them in memory for use in other patch sections.
# After append operation (StrRef or AppendFile)
memory.memory_str[token_identifier] = new_stringrefBehavior:
- For append operations: Stores the new stringref that was added, mapped to the token identifier (see How Token Creation Works)
- For replace operations: Memory is not typically stored (no need since stringref is static)
Tokens are created from the matching number in both the key and value. See How Token Creation Works for details. After processing, tokens are available for use in other sections like [2DAList], [GFFList], and [CompileList].
In 2DA files:
[TLKList]
StrRef0=0 ; Creates token StrRef0
[2DAList]
Table0=spells.2da
[spells.2da]
AddRow0=new_spell
2DAMEMORY0=StrRef0 ; Store stringref in 2DA memory for cross-file use
[new_spell]
name=StrRef0 ; Token gets replaced with actual stringrefIn GFF files:
[TLKList]
StrRef0=0 ; Creates token StrRef0
[GFFList]
File0=item.uti
[item.uti]
LocalizedName=StrRef0 ; Token gets replaced with actual stringrefIn NSS Scripts (CompileList):
// Script compilation will replace #StrRef# tokens
void main() {
// #StrRef0# token gets replaced with actual stringref during compilation
SendMessageToPC(GetFirstPC(), #StrRef0#);
}In TSLPatcher v1.2.8 and later, the TLKList section is processed first in the patching pipeline (before InstallList):
TSLPatcher Execution Order (v1.2.8+):
1. [TLKList] - Add TLK entries (append operations)
2. [InstallList] - Copy files to installation
3. [2DAList] - Add/Modify 2DA entries
4. [GFFList] - Add/Modify GFF entries
5. [CompileList] - Compile NSS scripts (replaces #StrRef# tokens)
6. [SSFList] - Modify soundset files
Note: In TSLPatcher v1.2.8b0 (2006-08-06), the processing order was changed so that TLK Appending happens before Install List. According to the official change log, this allows ERF/MOD/RIM files to be placed in their proper locations before GFF and script compilation sections run, so modified files can be saved into those archive files.
Older TSLPatcher versions (before 1.2.8) processed InstallList before TLKList.
HoloPatcher (a modern Python drop-in replacement for TSLPatcher) uses a different execution order:
HoloPatcher Execution Order:
1. [InstallList] - Copy files to installation
2. [TLKList] - Add TLK entries (append operations) ← HERE
3. [2DAList] - Add/Modify 2DA entries
4. [GFFList] - Add/Modify GFF entries
5. [CompileList] - Compile NSS scripts (replaces #StrRef# tokens)
6. [HACKList] - Patch NCS files
7. [SSFList] - Modify soundset files
Important Compatibility Note: This is a backwards-compatible discrepancy between TSLPatcher and HoloPatcher. HoloPatcher processes InstallList before TLKList to allow users to install a base dialog.tlk file (or other files) via InstallList, which can then be modified by TLK appending operations. This order provides greater flexibility for mod workflows.
TSLPatcher's reasoning (TLKList → InstallList):
- Allows ERF/MOD/RIM files to be placed before GFF/Compile sections that save into them
HoloPatcher's reasoning (InstallList → TLKList):
- ✅ More flexible: Users can install a custom base
dialog.tlkfile via InstallList, then TLK appending modifies it - ✅ Better for testing: Allows installing known-good TLK files before appending new entries
- ✅ Preserves dependencies: TLK entries are still processed before 2DA/GFF/Compile/SSF sections that reference them
- ✅ More intuitive: File installation happens first, then modifications are applied
Critical Timing (applies to both TSLPatcher and HoloPatcher):
- TLK entries are added to the destination target
dialog.tlkbefore 2DA and GFF modifications - This ensures stringrefs/tlk entries are available when referenced by other sections
- Script compilation happens after TLK processing, so
#StrRef#tokens can be resolved - Tokens are substituted in 2DA, GFF, and script files after TLK entries have been appended
A TLK file is a binary format containing:
-
Header: File type (
TLK), version (V3.0), language ID, string count, entries offset - Entry Headers: Flags, sound ResRef (16 bytes), volume/pitch variance (unused), text offset, text length, sound length (unused)
- Text Data: Actual string content stored at the specified offsets
TLK Entry Structure:
class TLKEntry:
text: str # The display text (UTF-8 or cp1252 encoding)
voiceover: ResRef # Sound file ResRef (max 16 characters)
sound_length: float # Unused by KotOR (present in format but ignored)String Length Limitations:
- TSLPatcher v1.2.8b6 and later: Can handle TLK entries with strings of any size (no practical limit)
- Earlier versions: Had a bug that prevented proper handling of strings longer than 4096 characters
- If you encounter issues with long strings, ensure you're using TSLPatcher v1.2.8b6 or later. HoloPatcher does NOT have this bug.
Standard Files:
-
dialog.tlk- Main English dialog (always present in game directory)
Localized Versions (exclusively KotOR1 Polish):
-
dialogf.tlk- Feminine/non-English localized version - Must match the number of entries in
dialog.tlkexactly
Entry Indices:
- StringRefs start at 0 and increment sequentially
- Valid entries: 0 to (total_entries - 1)
- Reference entries as integers throughout the game and mod files
Add new string entries from append.tlk to dialog.tlk:
[TLKList]
StrRef0=0
StrRef1=1
StrRef2=2Files: tslpatchdata/append.tlk contains entries 0, 1, 2 with your custom text
Result: Each entry from append.tlk is appended to dialog.tlk and assigned the next available stringref (e.g., 123456, 123457, 123458). These new stringrefs are stored in memory as tokens StrRef0, StrRef1, StrRef2 for use in other sections.
Add entries from a custom TLK file using index mappings:
[TLKList]
AppendFile0=planets.tlk
[planets.tlk]
0=10 ; Reads index 10, creates token StrRef10
1=11 ; Reads index 11, creates token StrRef11
2=12 ; Reads index 12, creates token StrRef12Files: tslpatchdata/planets.tlk contains entries at indices 10, 11, 12, etc.
Result: Each entry from planets.tlk is appended to dialog.tlk and tokens StrRef10, StrRef11, StrRef12 are created (from the values, not the keys).
Use multiple append methods together:
[TLKList]
!SourceFile=append.tlk
StrRef0=0
StrRef1=1
AppendFile0=items.tlk
[items.tlk]
0=100 ; Creates token StrRef100
1=101 ; Creates token StrRef101Files: tslpatchdata/append.tlk (entries 0, 1), tslpatchdata/items.tlk (entries 100, 101)
Processing Order: Entries are processed sequentially, creating tokens StrRef0, StrRef1, StrRef100, StrRef101.
Support for feminine/localized versions:
[TLKList]
!SourceFile=append.tlk
!SourceFileF=appendf.tlk
StrRef0=0
StrRef1=1
StrRef2=2Files:
-
append.tlk(masculine/English) - Contains 3 entries (indices 0, 1, 2) -
appendf.tlk(feminine/Polish) - Must have exactly 3 entries (indices 0, 1, 2)
Requirements:
- Both files must have exactly the same number of entries
- Entry at index 0 in
append.tlkmaps to index 0 inappendf.tlk - If a string has no feminine form, use the same text in both files
- TSLPatcher automatically uses
appendf.tlkwhen the target game hasdialogf.tlkpresent
Scenario: Add custom lines for a new NPC
Solution:
[TLKList]
StrRef0=0 ; Greeting line
StrRef1=1 ; Quest offer
StrRef2=2 ; Refusal response
[GFFList]
File0=my_npc.dlg
[my_npc.dlg]
; Reference tokens StrRef0, StrRef1, StrRef2 in dialog entriesScenario: Add descriptions for new items
Solution:
[TLKList]
AppendFile0=items.tlk
[items.tlk]
0=10 ; Item name → token StrRef10
1=11 ; Item description → token StrRef11
2=12 ; Another item name → token StrRef12
3=13 ; Another item description → token StrRef13
[GFFList]
File0=new_item.uti
[new_item.uti]
LocalizedName=StrRef10
DescIdentified=StrRef11Scenario: Create English and non-English versions
Solution:
[TLKList]
!SourceFile=append_en.tlk
!SourceFileF=append_de.tlk
StrRef0=0
StrRef1=1
StrRef2=2Files: Both append_en.tlk (English) and append_de.tlk (German) must match entry count exactly. TSLPatcher uses the appropriate file based on game localization.
Cause: Unrecognized key format
Solutions:
- Check for typos in key names
- Ensure you're using one of the supported syntaxes:
StrRef<key>=<value>orAppendFile<key>=<value> - Verify the key matches the expected pattern
Correct Syntaxes:
; StrRef syntax: Key can be anything, value must be numeric
StrRef0=0
StrRef1=1
; AppendFile syntax: Key starts with "AppendFile", value is filename
AppendFile0=file.tlk
AppendFile1=another.tlkCause: Invalid numeric values or malformed entries
Solutions:
- Ensure values are valid integers for StrRef/AppendFile mappings
- Check that numeric keys can be parsed as integers if using numeric format
- Verify no extra spaces or invalid characters
Correct:
StrRef0=0
StrRef123=123Incorrect:
StrRef0=abc ; Value must be numeric
StrRef=0 ; Missing numeric part in keyCause: Referenced TLK file or subsection doesn't exist
Solutions:
-
Create the subsection in the INI if using internal mappings:
AppendFile0=myfile.tlk [myfile.tlk] ; Must create this subsection 0=1
-
Or ensure the file exists in the source folder if using external TLK files
-
Check
!DefaultSourceFolderpath is correct
Cause: Trying to replace an entry that doesn't exist (if using replace functionality)
Solutions:
- For new content, use append syntax (
StrReforAppendFile) instead of replace - Verify the stringref number is correct if you must use replace for error fixing
- Remember: Always use append for new content - see Replace Functionality Warning
Adding New (use this):
StrRef0=0 ; Appends new entry, creates token StrRef0Cause: Multiple possible issues
Solutions:
- Check file paths:
!DefaultSourceFolderand file locations - Verify TLK file format: must be valid binary TLK
- Check file encoding: should be UTF-8 or cp1252
- Ensure the file is in the tslpatchdata folder (or specified source folder)
- Review the log for processing errors
- Verify keys and values are correctly formatted
Cause: Confusion about token creation from keys vs values
Solutions:
- See How Token Creation Works - tokens are created from the value (matching number)
-
StrRef0=0creates tokenStrRef0 -
StrRef5=5creates tokenStrRef5
Cause: Token not created or not accessible in other sections
Solutions:
- Verify the stringref was actually added (check logs)
- Ensure you're using the correct token name (created from matching number)
- Check memory is being used in the correct execution order
- Tokens are only created for append operations, not replace operations
Example:
[TLKList]
StrRef0=0 ; Creates token StrRef0
[2DAList]
Table0=spells.2da
[spells.2da]
name=StrRef0 ; Use the tokenBest Practice: Use AppendFile with subsections for clarity and organization
Good (Organized by content type):
[TLKList]
AppendFile0=items.tlk
AppendFile1=npcs.tlk
[items.tlk]
0=100 ; Token: StrRef100 - Item name
1=101 ; Token: StrRef101 - Item description
; ... many more entries
[npcs.tlk]
0=200 ; Token: StrRef200 - NPC greeting
1=201 ; Token: StrRef201 - NPC dialogue
; ... many more entriesLess Ideal (but still works for small mods):
[TLKList]
StrRef0=0
StrRef1=1
StrRef2=2
; ... 200 more lines becomes hard to manageCause: Some systems have dialog.tlk set to read-only or write-protected
Solutions:
- Check file permissions on
dialog.tlkin the game directory - Run TSLPatcher with administrator privileges if needed
- Ensure the game is not running when installing mods
- Check if antivirus software is blocking file modification
Note: TSLPatcher v1.2.8b8 fixed a bug where installation would stop when dialog.tlk was write-protected. If using an older version, ensure the file is writable.
- Group related entries in separate TLK files
- Use descriptive file names:
npcs.tlk,items.tlk,planets.tlk - Keep the main INI clean with AppendFile/StrRef references
- Document which tokens correspond to which content
-
See How Token Creation Works for token creation details
-
Use consistent numbering to create predictable token names
-
Document token usage in comments when helpful:
StrRef0=0 ; NPC greeting
- Always use append for new content - this is TSLPatcher's design
- Never use replace functionality except for fixing existing errors (see Replace Functionality Warning)
- Document which stringrefs are custom vs modified
- Use descriptive token names by choosing appropriate numbers
- Verify all TLK files are valid before packaging
- Check stringref assignments in logs
- Test with multiple mods installed to check compatibility
- Use
KotorDiffto compare before/afterdialog.tlk - Verify tokens are correctly created and accessible
- Create with TalkEd.exe: Use TalkEd.exe to create and edit your source TLK files (see Creating TLK Files)
- Keep source TLK files readable: Use JSON export for debugging if your TLK editor supports it
-
Maintain consistent naming: Always use
append.tlkandappendf.tlk(or set!SourceFile/!SourceFileFif using custom names) - Version control: Keep TLK files separately from other mod files for easier management
-
Match entry counts: If using localized versions, ensure
append.tlkandappendf.tlkhave exactly the same number of entries -
File size considerations: The
dialog.tlkfile is ~10 MB, but you only need to distribute smallappend.tlkfiles with your mod
-
KotOR1 Polish only: The dual-TLK system (
dialog.tlk+dialogf.tlk) is exclusively for KotOR1 Polish localization -
Maintain parallel files: If supporting Polish, maintain both
append.tlkandappendf.tlk -
Exact entry matching: Entry counts must match exactly between
append.tlkandappendf.tlk - Map indices: Each index must correspond between the two files (index 0 → index 0, index 1 → index 1, etc.)
- Handle duplicates: If a string has no feminine form, use the same text in both files
-
Use configuration keys: Set
!SourceFileFto specify the feminine version filename - Documentation: Document language support in your mod's README
-
KotOR2/TSL: Does not use
dialogf.tlk- only createappend.tlkfor KotOR2 mods
- Keys appear on the left side of
=, values on the right - For
StrRef<number>=<number>, numbers must match for proper token creation - Use consistent numbering for readability
| Pattern | Syntax | Purpose | Replacement |
|---|---|---|---|
| StrRef | StrRef<number>=<number> |
Append from default file | No |
| AppendFile | AppendFile<anything>=<filename> |
Append from custom file | No |
# After StrRef append
# StrRef0=0 → Creates token StrRef0
# Memory: memory.memory_str[0] = new_stringref (from dialog.tlk append)
# After AppendFile append
# Subsection: 10=10 → Creates token StrRef10
# Memory: memory.memory_str[10] = new_stringref (from dialog.tlk append)Key Points: See How Token Creation Works and Memory System for details. Tokens are available for use in [2DAList], [GFFList], and [CompileList] sections.
- Parse [TLKList] section
- Load source TLK files from
!SourceFile/!SourceFileFe.g.!SourceFile=append.tlk - For each StrRef entry:
- Parse: Key (ignored), Value (source index)
- Load entry from source file at Value index
- Append to dialog.tlk (gets new stringref)
- Create token StrRef{value} from Value to store the new stringref
- For each AppendFile entry:
- Parse: Key (part after the word 'append' is ignored), Value (filename) e.g.
AppendFile0=some_append_contents.tlk - Parse subsection [filename] mappings
- For each mapping:
- Parse: Key (ignored), Value (source index)
- Load entry from referenced file at Value index
- Append to dialog.tlk (gets new stringref)
- Create token StrRef{value} from Value to store the new stringref
- Parse: Key (part after the word 'append' is ignored), Value (filename) e.g.
- Tokens are now available for substitution in:
- [2DAList] sections (2DAMEMORY#=StrRef#)
- [GFFList] sections (FieldName=StrRef#)
- [CompileList] scripts (#StrRef# tokens)
In 2DA files: name=StrRef0 (token gets replaced with actual stringref)
In GFF files: LocalizedName=StrRef0 (token gets replaced with actual stringref)
In NSS scripts: SendMessageToPC(GetFirstPC(), #StrRef0#); (token gets replaced during compilation)
TSLPatcher v1.2.8b6 (2006-10-03):
- Added optional
!SourceFileand!SourceFileFkeys to the[TLKList]section - If present, these can be used to set an alternative name of the TLK file to use
- If left out, default values are
append.tlkandappendf.tlkas before - Fixed bug: Previously couldn't handle TLK entries with strings longer than 4096 characters - now supports strings of any size
TSLPatcher v1.2.8b0 (2006-08-06):
- Changed processing order: TLK Appending now happens before Install List
- This allows ERF/MOD/RIM files to be placed before GFF and script compilation sections run
TSLPatcher v1.2.8b8 (2006-12-02):
- Fixed bug that caused TSLPatcher to stop installation into games where the
dialog.tlkfile was write-protected
- TSLPatcher's Official Readme - General TSLPatcher information and ChangeEdit usage
- TSLPatcher 2DAList Syntax - How to modify 2DA files (can use StrRef tokens)
- TSLPatcher GFFList Syntax - How to modify GFF files (can use StrRef tokens)
- TSLPatcher SSFList Syntax - How to modify soundset files (can use StrRef tokens)
- TSLPatcher CompileList Syntax - How to compile scripts (can use #StrRef# tokens)
- Mod Creation Best Practices - Best practices for modding
- HoloPatcher Documentation - PyKotor implementation details