ESO Mod:Language Data File Format
The en.lang, fr.lang, and de.lang files found in eso002.dat contain quest text.
Basic Format[edit]
The overall format of the .lang files is very simple:
[ Header (0x08 bytes) ] [ 0..N Text Records (0x10 bytes each) ] [ 0..N Text (variable, NUL terminated) ]
Note: dword is a Windows-ism that means uint32.
Header[edit]
The header is in big-endian bit order:
dword Unknown = 0x02 //? dword RecordCount
Text Records[edit]
The text records are 16 bytes (0x10 bytes) fixed-size in big-endian bit order. The number of records is given by the RecordCount field in the file header.
type | name | description |
---|---|---|
dword | Section ID | 399 unique, large values |
dword | Section Index | 0-236 |
dword | String Index | 1-56834 |
dword | Offset | Start of corresponding text data |
The record's offset tells you where you can find the corresponding string as an index from the start of the text data section. e.g. offset=32 would mean that you can get the text string for this record by seeking to the end of the text record section, skipping 32 additional bytes, and then consuming bytes until you encounter the NUL byte.
In other words, the start of the text data section is at (8 (skip header) + 16*header.RecordCount (skip text records)), and record.Offset begins indexing from there.
Each ID represents a unique section of text with the combination of ID:Index being a unique representation of every individual text. The known IDs are:
section | description |
---|---|
132143172 | Ability Raw Descriptions (index will be the ability ID) |
51188213 | Book Titles (index will be the book ID) |
21337012 | Book Text (index is the book ID) |
162658389 | Zone Name (index is the zone ID) |
52420949 | Quest Name (index is the quest ID) |
265851556 | Quest Journal Entry (index is the quest ID) |
38727365 | Set Name (index is the set ID) |
In general the index appears to be the internal ID of the item in question.
Text Data[edit]
Immediately following the text records are all the NUL-terminated texts.
Text Codes[edit]
There are various special codes used within the quest/dialogue text that get dynamically replaced by the game.
For example, the lang file text might be "<<1>> is the best", and it will be substituted ingame with a name: "Vivec is the best."
Here are some non-exhaustive examples of these codes:
<<1>>
- Replaced with the name of a person, place, or thing.
- The number can be any integer. i.e. <<1>>, <<2>>, <<3>>, one for each unique name in the dialogue.
- The following demonstrate modifiers on these integer substitutions.
<<a:1>>
- Replaced with a name that will be prefixed by an *indefinite* article ("a", "an") if the name is not a proper noun.
<<ma:1>>
- Replaced with a name that will be prefixed by "some" if the name is not a proper noun.
<<A:1>>
- Replaced with a name that will be prefixed by a *definite* article ("the") if the name is not a proper noun.
<<c:1>>
- Replaced with a name with the first letter lowercased.
<<C:1>>
- Replaced with a name with the first letter uppercased.
There are also various formatting codes(?):
[PH] [Keep Reading] [Lie] [CHARM] [INTIMIDATE]