Translating Daggerfall Unity

Introduction

Localization in Daggerfall Unity has taken a big step forward. In previous releases, translating DFU was a challenging process requiring the Unity Editor and writing code to load fonts and replace string tables at start. This approach placed a heavy technical burden on the translator, who just wants to get down to writing text.

I’ve listened to your feedback and completely reworked localization to simplify the entire process and remove technical hurdles. From release v0.15 and later, it’s no longer necessary to use the Unity Editor, write any code, or package a .dfmod. Instead, all text is edited in plain CSV files using your editor of choice and can be distributed along with fonts in a simple ZIP archive.

Rather than another multi-part tutorial series, this article will speedrun the whole translation process showing how everything is done as quickly and clearly as possible in a single article.

Getting Started

To create translations for Daggerfall Unity, you’ll need the following to get started:

  1. A working copy of Daggerfall Unity 0.15.0 or later. Setting up using the DaggerfallGameFiles method is recommended, but you can also use Steam release to get started.
  2. A good CSV editor such as Microsoft Excel or Google Sheets. You can technically get by using any text editor, but it’s best to use a dedicated spreadsheet tool.
  3. A suitable TTF or OTF font representing your alphabet. The built-in fonts have a full complement of Latin characters, but you’ll need to provide a font with the appropriate characters for whatever dialect of Kanji, Cyrillic, Hangul, etc. you are writing in.
  4. A way of extracting ZIP files and creating new ZIP files to distribute your translations. This functionality is built into Windows and other major operating systems.

Throughout this whole process, we’ll be placing files somewhere in the DaggerfallUnity_Data\StreamingAssets folder. Start by locating the below path in your Daggerfall Unity installation.

Replacing Fonts

If you’re writing translations using Latin characters (e.g. English, French, Italian, Spanish), you can skip this section. The built-in Daggerfall Unity fonts contain a full complement of Latin characters. But if you still want to assign a new font for other reasons, then keep reading.

You will need to supply a TTF or OTF font representing all the Unicode characters required for your alphabet. Daggerfall Unity uses standard Unicode codes for all text. If any characters are missing from your font, these will not display correctly in game.

Rather than use any specific language or dialect, this tutorial will use pseudo localization (e.g. ƥƨèúδô ℓôçáℓïƺáƭïôñ) to demonstrate how to setup your custom font and alphabet file so the correct characters are imported. I’ll be using the versatile NotoSans-Regular font to demo this process.

Tip: When selecting your own font, try to pick something that also contains a full complement of Latin characters. This is important so any untranslated parts of your work will still display correctly in default English.

Getting Your Fonts Into The Game

Once you’ve selected your fonts, you’ll first need to copy them into a place where Daggerfall Unity can find them and rename font files so DFU knows how to use them.

In below screenshot, I’ve copied NotoSans-Regular.ttf into StreamingAssets/Fonts and renamed file to FONT0003-SDF.ttf.

This informs DFU to use the selected font to replace FONT0003, which happens to be the font used for most general text in the game. Repeat for any other fonts as needed.

Tip: All fonts must be TTF or OTF with standard Unicodes. The legacy 8-bit pixel fonts (FNT) are not suitable for writing translations and can be ignored. Font rendering will be forced into SDF mode to display translations correctly.

Creating Alphabet File

Your translation might use different characters based on region or dialect. It’s possible for a font to include many thousands of glyphs while the written dialect uses only a subset of these. Before we can use custom characters from our font, we need to inform DFU which characters should be loaded from font. This is done using an alphabet file, which is simply a text file containing all the custom characters used by our target dialect.

In below screenshot, I’ve created a text file in StreamingAssets/Fonts called FONT0003-SDF.txt. This matches the font name and will contain a list of characters to load from font.

I’ll then add my custom characters to the alphabet file, informing the game which characters needs to be loaded. Here’s the full contents of my FONT0003-SDF.txt alphabet file. These characters represent the custom glyphs used in my pseudo localization examples.

áβçδèƒϱλïJƙℓ₥ñôƥ9řƨƭúƲωж¥ƺ
ÂßÇÐÉFGHÌJK£MNÓÞQR§TÛVWXÝZ

Tip: Daggerfall Unity will attempt to load standard Latin characters from font if available. There’s no need to specify these in your alphabet file. If you specify characters in alphabet file which do not render in game, it’s most likely your selected font is missing those Unicodes.

Editing CSV Files

To get started on translating Daggerfall Unity, a master set of CSV files in English are included in StreamingAssets/Text in 0.15 and later. Start by unzipping Master Localization CSV Files {version}.zip (whatever your version is) directly into the StreamingAssets/Text folder as shown below.

Tips:

  • Don’t extract Master Localization CSV Files into a subfolder, extract directly into the StreamingAssets/Text folder as shown above.
  • You can start your own CSV files from empty and just copy over Key/Value row as you write translations. If DFU can’t find a translated string in your CSV, it will fallback to the built-in English text.
  • All the text files, CSV, alphabet file, etc. must be saved in UTF-8 format.

To translate text, simply open CSV file in a spreadsheet program, rewrite the text in a cell, then save and run game to test.

Here, I’m using Excel to edit a string in Internal_Strings. I’ve changed the Value field of the key in row 3.

Tip: Never change the contents of Key column. This is how the game knows which text your translation should map to. Only change text in Value column.

If I save my file and run the game, I’ll see my translation when starting a new character.

That all there is to it. Keep on translating strings and don’t forget to keep backups of your work!

RSC Markup

In some CSV files, you’ll note there are markup codes enclosed in [square brackets] and variables starting with a % symbol. Example below from Internal_RSC.

When translating this text, do not translate the markup codes in [square brackets] or variables preceded by a %. Here’s an example pseudo translation of above. Note that markup like [/center] and variables like %ark are not translated.

§TRÉNGTH[/center]
§ƭřèñϱƭλ ϱôƲèřñƨ èñçú₥βřáñçè, ωèáƥôñ δá₥áϱè[/left]
áñδ ƭλè èáƨè ôƒ ïñçřèáƨïñϱ ƨƭřèñϱƭλ-řèℓáƭèδ ƨƙïℓℓƨ.[/left]
Wïƭλ ¥ôúř ƨƭřèñϱƭλ ôƒ %str, ¥ôú ářè çôñƨïδèřèδ %ark[/left]
[/pos:x=20,y=0]%dam [/pos:x=40,y=0]₥ôδïƒïèř ïƨ ƒáçƭôřèδ ïñƭô ¥ôúř[/left]
[/pos:x=40,y=0]λáñδ-ƭô-λáñδ / ωèáƥôñ δá₥áϱè.[/left]
[/pos:x=20,y=0]%enc [/pos:x=40,y=0]ƙïℓôϱřá₥ƨ ïƨ ¥ôúř ₥áжï₥ú₥ èñçú₥βřáñçè.[/left]
[/end]

After saving this text and restarting game, our translation is active with formatting and variables intact.

Tip: Depending on your language, you might need to add additional line breaks or formatting to ensure all text fits in the available space.

That’s the most technical aspect of writing translations out of the way. As a general rule, just follow the usage in the Master CSV files and you should be able to translate everything over time.

Now that you know how to translate text, we’ll cover the individual areas of the game where text is found.

Building Names

Building names are composed using Part A and Part B components found in Internal_Strings starting from row 901. See this article for a more detailed explanation of how Daggerfall creates building names from a seed.

This text is exposed as-is. You’ll need to translate building name parts so these makes sense to your language’s grammar rules. Example below in pseudo localization.

Locations

Unlike building names, location names are not procedurally generated from seed. These are simply string literals in MAPS.BSA inside Daggerfall’s game data. This data is a combination of bespoke names and many randomly generated names created at development.

This text is exposed as-is in Internal_Locations. You can use whatever process works best for your language to translate location names. Connecting your spreadsheet to a translation API might help you bulk translate the names, followed by hand-tuning as necessary.

Quests

Quests files are composed with both text and scripted logic elements. You could edit the quest file directly, but this means you’ll need to maintain the quest file with any bug fixes or changes added to the quest scripting later.

To help avoid this maintenance, Daggerfall Unity will seek replacement quest text from Internal_Quests. Unlike other CSV files, this file does not contain text for every quest currently available. You will need to add rows as you translate.

The Key format for quest rows is QuestName.ID. For example the below quest message from S0000999.txt has ID 1011. So the full key is S0000999.1011.

Message:  1011
%qdt:
 I met with Lady Brisienna in a tavern room. She
 told me that the three major powers of the Iliac
 bay are Daggerfall, Wayrest, and Sentinel. If I
 am to investigate the mystery of Lysandus' ghost,
 I should start by speaking with the royal families
 of these fiefdoms.

To translate this message, create a new row in Internal_Quests with the Key S0000999.1011 and translate the text part. As before, we don’t change the variable %qdt. We also don’t need to include the Message: 1011 line from quest source, just the actual contents of text block.

Restart the game and the quest log will show the translated text.

Books

In Daggerfall Unity versions prior to 0.15, books were converted at runtime from classic BOK*.txt format. This has drawbacks such as books containing formatting errors and not supporting Unicode characters.

From version 0.15 and later, books are included in the StreamingAssets/Text/Books folder using a new text format compatible with localization system. This enables Unicode characters for books and opens fixes to book spelling, grammar, and formatting via open source pull requests.

To edit a book, locate the book file in StreamingAssets/Text/Books and translate the contents. As we covered earlier, don’t translate any markup content such as [/font] or [/center].

Below is a the beginning of The Faerie (BOK00006-LOC.txt). The file names are the same as classic, except with -LOC appended. Internally these files are in a new format.

Title: The Faerie
Author: Szun Triop
IsNaughty: False
Price: 580
IsUnique: False
WhenVarSet: 
Content:


[/font=2]

[/center]The Faerie



[/font=4]

 Faerie have been on Tamriel, in all probability, long
before recorded history, perhaps since or before the days of
the Elder Ones. The tales of their mischief are found in every
culture, in most every village, town, and city-states in
the Empire. Alternately they are called Faerie, Fey,
Illyadi, Sprites, Pixies, and Sylphim, and their natures seem
to flit from one story to the next with the same variation.
It could almost be said that Faeries are anything
unpredictable in nature.

The tags at start of book file contain data about that book. Some of this data is visible in-game e.g. Title:. Some tags control how book is released e.g. WhenVarSet: prevents book from being available until after a global variable is raised. Don’t translate the tags themselves or any non-text values (e.g. numbers, True/False). Translating text values like the title is OK.

Note: At time of writing in 0.15.1, not all tags are used in-game from new -LOC book files. This limitation will be corrected in a future release.

To translate, edit the book contents as we did earlier then save file and restart game. Following is an example pseudo translation of above.

Title: Tλè Fáèřïè
Author: §ƺúñ Třïôƥ
IsNaughty: False
Price: 580
IsUnique: False
WhenVarSet: 
Content:


[/font=2]

[/center]Tλè Fáèřïè



[/font=4]

Fáèřïè λáƲè βèèñ ôñ Tá₥řïèℓ, ïñ áℓℓ ƥřôβáβïℓïƭ¥, ℓôñϱ
βèƒôřè řèçôřδèδ λïƨƭôř¥, ƥèřλáƥƨ ƨïñçè ôř βèƒôřè ƭλè δá¥ƨ ôƒ
ƭλè Éℓδèř Óñèƨ. Tλè ƭáℓèƨ ôƒ ƭλèïř ₥ïƨçλïèƒ ářè ƒôúñδ ïñ èƲèř¥
çúℓƭúřè, ïñ ₥ôƨƭ èƲèř¥ Ʋïℓℓáϱè, ƭôωñ, áñδ çïƭ¥-ƨƭáƭèƨ ïñ
ƭλè É₥ƥïřè. Âℓƭèřñáƭèℓ¥ ƭλè¥ ářè çáℓℓèδ Fáèřïè, Fè¥,
Ìℓℓ¥áδï, §ƥřïƭèƨ, Þïжïèƨ, áñδ §¥ℓƥλï₥, áñδ ƭλèïř ñáƭúřèƨ ƨèè₥
ƭô ƒℓïƭ ƒřô₥ ôñè ƨƭôř¥ ƭô ƭλè ñèжƭ ωïƭλ ƭλè ƨá₥è Ʋářïáƭïôñ.
Ìƭ çôúℓδ áℓ₥ôƨƭ βè ƨáïδ ƭλáƭ Fáèřïèƨ ářè áñ¥ƭλïñϱ
úñƥřèδïçƭáβℓè ïñ ñáƭúřè.

The translated book now displays in game as below. Title, author, tooltips, and content are all translated.

Note: The default title font is missing some characters that display as a ? instead. This is because the title font does not contain a matching Unicode character for these glyphs. Replacing the title font with one containing these Unicodes will correct problem.

Book Images

Books files can also reference images placed in StreamingAssets/Text/Books/BookImages folder. In this example, an image is saved into this folder as test1.jpg.

It is then added to book directly below title using the [/image={filename}] markup like so.

[/center]Tλè Fáèřïè

[/image=test1.jpg]

The added image displays in-game when player opens book.

Note: Book images are always scaled and centred on their own line. At time of writing, there’s a bug where book image is not properly clipped to scroll area.

Book Scaling and Colours

It’s also possible to adjust book scaling and colours using the [/color={RGBHex}] and [/scale={value}] markup like so.

[/color=ff8040][/scale=2.0]Fáèřïè λáƲè βèèñ ôñ Tá₥řïèℓ, ïñ áℓℓ ƥřôβáβïℓïƭ¥, ℓôñϱ

This changes the colour and scale of the first paragraph. Like other formatting, colour and scale reset at every newline. The untranslated portion of book follows the first paragraph.

Biography Text

Biography text can be edited directly in StreamingAssets/BIOGs. In below example, one of the questions and answers in BIOG00T0.txt (e.g. Mage class) have been translated.

Note: It is important not to translate the non-text parts or formatting of file. Incorrect changes can crash the game or cause other problems.

1.	Wλáƭ ƨçλôôℓ ôƒ ₥áϱïç λáƲè ¥ôú βèèñ
	ƨƭúδ¥ïñϱ ƭλè ℓôñϱèƨƭ?
a.	Ðèƨƭřúçƭïôñ
	#4150
	!4156
	22 +6
b.	Rèƨƭôřáƭïôñ
	#4151
	!4157
	23 +6
c.	Ìℓℓúƨïôñ
	#4152
	!4158
	24 +6
d.	Âℓƭèřáƭïôñ
	#4153
	!4159
	25 +6
e.	Tλáú₥áƭúřϱ¥
	#4154
	!4160
	26 +6
f.	M¥ƨƭïçïƨ₥
	#4155
	!4161
	27 +6

This will display in-game like below.

Faction Text

FACTION.TXT can be edited directly in StreamingAssets/Factions. This file contains the canonical names of fixed NPCs and guilds.

Note: Faction data is also copied to FactionData.txt in player saves. This is necessary as part of faction alliance simulation and player guild rankings, which all change over time. As faction text fields are not decoupled from FACTION.TXT file, it is necessary for player to start a new game for these changes to take effect. Faction text might be decoupled in a future release.

Below, we edit the name of Queen Barenziah in her FACTION.TXT entry #391. As always, don’t translate tags and other non-text values. Changing non-text values or formatting below can crash the game.

#391
	Type: 4
	name: Qúèèñ ßářèñƺïáλ
	rep: 0
	summon: -1
	region: 24
	power: 15
	flags: 0
	face: 43
	race: 7
	flat: 346 22
	sgroup: 3
	ggroup: -1
	minf: 10
	maxf: 80

This change is now visible in-game.

Menus

Menu text can be edited directly in StreamingAssets/Text. These are special CSV data files, but still in the format key, value. As fonts are loaded earlier than mod, it’s now possible to translate menu text. An example below.

Note: The key is not changed, only the text value.

startInDungeon,      §ƭářƭ Ìñ Ðúñϱèôñ
startInDungeonInfo,  §ƭářƭ ñèω ϱá₥è ïñƨïδè ƭλè ƒïřƨƭ δúñϱèôñ
smallerDungeons,     §₥áℓℓèř Ðúñϱèôñƨ
smallerDungeonsInfo, Ráñδô₥ δúñϱèôñƨ ωïℓℓ λáƲè ôñℓ¥ ôñè ïñƭèřïôř βℓôçƙ áñδ ƒôúř βôřδèř βℓôçƙƨ

This is visible in-game like below.

Images, Sounds, and More

It’s also possible to translate menu image, sounds, and more using loose files in StreamingAssets. This is beyond the scope of this article. See Daggerfall Unity Modding System as a starting point.

Distributing Translations

As translations are just a collection of loose files spread throughout StreamingAssets, they can be distributed as a zip file. After testing, bundle all your changed text files into a single .zip archive with correct paths and release.

The end user then needs only unzip whole archive into StreamingAssets while keeping paths so everything goes into the correct folder.

Please consider the source text files can change over time. It will become necessary to maintain your translation mod to ensure it remains compatible with new versions of Daggerfall Unity.

Conclusion

As of Daggerfall Unity 0.15, its now possible to translate the game using simple font and text files distributed as a .zip archive. It’s no longer necessary to use Unity Editor or package a .dfmod. Simply edit the required text files and distribute in a .zip archive.

Almost the entire game can be translated at time of writing, with some limitations. Notably, it’s not yet possible to translate random name banks and faction names require a new game to take effect. Also, editing some files incorrectly can break the game if file edited incorrectly. These limitations will hopefully be improved in future releases.

I hope this article proves useful to Daggerfall Unity players around the world. Best of luck to everyone working on translations!