# How to Add Support for New Languages in the Undertale Changer Template

> Learn how to add new languages to Undertale Changer Template. Follow simple steps to copy, rename, and populate language pack files for custom translations. Extend your game experience today.

- Repository: [Archived AIk/undertale-changer-template](https://github.com/arch-aik/undertale-changer-template)
- Tags: how-to-guide
- Published: 2026-02-25

---

**To add a new language to the Undertale Changer Template, copy an existing language pack folder into `Assets/LanguagePacks/` for external (user-added) packs or `TextAssets/LanguagePacks/` for internal (built-in) packs, rename it, populate the [`LanguagePackInformation.txt`](https://github.com/arch-aik/undertale-changer-template/blob/main/LanguagePackInformation.txt) metadata file and the text assets under `UI/` and `Scene/`, then verify it appears in Settings → Language Pack without modifying core game logic.**

The Undertale Changer Template by arch-aik uses a data-driven localization system that loads translation assets at runtime. Whether you are creating a fan translation or building a multi-language mod, you can add new language support by providing properly structured text files in the correct directory hierarchy. This article details the exact folder layout, configuration files, and service methods—such as `DataHandlerService.LoadLanguageData`—that enable seamless language integration.

## Language Pack Architecture: Internal vs. External

The template distinguishes between two pack types based on their location in the project hierarchy.

**Internal packs** reside in `TextAssets/LanguagePacks/` and compile directly into the Unity build. The engine expects exactly `MainControl.LanguagePackageInternalNumber` (default: 3) internal packs, mapped to IDs 0–2 via `DataHandlerService.GetLanguageInsideId`.

**External packs** live in `Assets/LanguagePacks/` and load from the host file system at runtime. The engine discovers these automatically using `Directory.GetDirectories`, requiring no code changes to add new languages.

For rapid iteration and distribution, external packs are recommended; internal packs are reserved for translations that must ship with the executable on platforms without file-system access.

## Creating an External Language Pack

External packs require zero C# modifications. Follow these steps to register a new language.

### Copy an Existing Template

Duplicate one of the existing pack folders—such as `US_Template`—into the external directory:

```bash
cp -r Assets/LanguagePacks/US_Template Assets/LanguagePacks/JP_Template

```

Rename the folder to your desired language identifier (e.g., `JP_Template`). This name appears in the Settings menu and serves as the pack’s unique handle.

### Configure LanguagePackInformation.txt

Inside the pack root, create or edit [`LanguagePackInformation.txt`](https://github.com/arch-aik/undertale-changer-template/blob/main/LanguagePackInformation.txt). This metadata file drives the UI display in `SettingsController.GetLanguagePacksName`. Use the following key-value format:

```text
LanguagePackName=Japanese
LanguagePackAuthor=Your Name
LanguagePackInformation=Japanese translation for the template.
LanguagePackFullWidth=False
CultureInfo=ja-JP

```

The `SettingsController` reads these values via `DataHandlerService.LoadItemData`, which calls `TextProcessingService.GetFirstChildStringByPrefix` to extract each field.

### Translate UI Text Files

Create the `UI/` subdirectory and populate these required text files:

- [`Setting.txt`](https://github.com/arch-aik/undertale-changer-template/blob/main/Setting.txt) – Menu labels and option names.
- [`ItemText.txt`](https://github.com/arch-aik/undertale-changer-template/blob/main/ItemText.txt) – Item descriptions and inventory strings.

Each file contains key-value pairs, one per line:

```text
LanguagePack=言語パック
LanguageBack=戻る
Open=開く
Close=閉じる

```

`SettingsController.UpdateLanguagePacksConfigDisplay` (lines 800–822) references these keys when rendering the settings interface.

### Translate Scene Text

Under `Scene/`, replicate the file structure from the template (e.g., [`Story.txt`](https://github.com/arch-aik/undertale-changer-template/blob/main/Story.txt), [`Menu.txt`](https://github.com/arch-aik/undertale-changer-template/blob/main/Menu.txt), [`Battle.txt`](https://github.com/arch-aik/undertale-changer-template/blob/main/Battle.txt)). The engine loads these via `DataHandlerService.LoadLanguageData` when the player enters the corresponding scene.

```text
Title=はじまりの物語
Start=ゲーム開始

```

### Optional: Add Ink Dialogue Scripts

If your narrative uses Ink, create an `Ink/` subfolder containing `InkExample.ink` and its compiled JSON. `TypeWritterTagProcessor` loads these scripts when the active `languagePackId` matches your pack index (lines 593–603).

## Creating an Internal Language Pack

To embed a language directly into the build, place the pack folder under `TextAssets/LanguagePacks/` instead of `Assets/LanguagePacks/`. This requires two code modifications in [`Assets/Scripts/UCT/Core/MainControl.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/Assets/Scripts/UCT/Core/MainControl.cs) and [`Assets/Scripts/UCT/Service/DataHandlerService.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/Assets/Scripts/UCT/Service/DataHandlerService.cs).

### Update the Internal Pack Count

Open [`MainControl.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/MainControl.cs) and increment `LanguagePackageInternalNumber` to reflect the new total:

```csharp
public static int LanguagePackageInternalNumber => 4;  // Increased from 3

```

*Source: [`MainControl.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/MainControl.cs) (line 115).*

### Map the New Language ID

Extend the switch expression in `DataHandlerService.GetLanguageInsideId` to assign a two-letter code to the new index:

```csharp
public static string GetLanguageInsideId(int id)
{
    return id switch
    {
        0 => "CN",
        1 => "TCN",
        2 => "US",
        3 => "JP",  // Add this line for the new internal language
        _ => "US"
    };
}

```

*Source: [`DataHandlerService.cs`](https://github.com/arch-aik/undertale-changer-template/blob/main/DataHandlerService.cs) (line 78).*

The engine now treats index 3 as the internal Japanese pack, loading it from `Resources.Load` instead of the file system.

## How the Engine Loads Language Data

Understanding the loading mechanism helps debug missing translations. The `DataHandlerService.LoadLanguageData` method (line 307) branches based on the language ID:

```csharp
public static string LoadLanguageData(string path, int id)
{
    return id < MainControl.LanguagePackageInternalNumber
        ? Resources.Load<TextAsset>($"TextAssets/LanguagePacks/{GetLanguageInsideId(id)}/{path}").text
        : File.ReadAllText($"{Directory.GetDirectories(Application.dataPath + "/LanguagePacks")[id - MainControl.LanguagePackageInternalNumber]}\\{path}.txt");
}

```

For IDs less than `LanguagePackageInternalNumber`, the method pulls from compiled Resources; for higher IDs, it calculates an offset into the external directory array and reads from disk.

## Verifying the New Language

1. Launch the Unity Editor or a built executable.
2. Navigate to **Settings → Language Pack**.
3. Select your new language from the list; the UI should immediately refresh using your [`Setting.txt`](https://github.com/arch-aik/undertale-changer-template/blob/main/Setting.txt) values.

If the language fails to appear:
- Confirm [`LanguagePackInformation.txt`](https://github.com/arch-aik/undertale-changer-template/blob/main/LanguagePackInformation.txt) contains a non-empty `LanguagePackName`.
- Verify the folder resides in the correct path (`Assets/LanguagePacks/` for external, `TextAssets/LanguagePacks/` for internal).
- Check the Unity console for `DataHandlerService` IO exceptions or missing key errors from `TextProcessingService`.

## Summary

- **External packs** drop into `Assets/LanguagePacks/` and require no code changes; the engine discovers them via `Directory.GetDirectories`.
- **Internal packs** require incrementing `MainControl.LanguagePackageInternalNumber` and updating `DataHandlerService.GetLanguageInsideId` to map new indices.
- Every pack needs [`LanguagePackInformation.txt`](https://github.com/arch-aik/undertale-changer-template/blob/main/LanguagePackInformation.txt) at the root, plus `UI/` and `Scene/` subfolders containing `.txt` key-value files.
- The UI renders language names using `SettingsController.GetLanguagePacksName`, which parses metadata through `DataHandlerService.LoadItemData`.
- Ink dialogue support requires an optional `Ink/` folder with `.ink` and JSON assets.

## Frequently Asked Questions

### Can I add a new language without recompiling the Unity project?

Yes. Place your translation folder in `Assets/LanguagePacks/` (external packs). The `DataHandlerService` scans this directory at runtime using `Directory.GetDirectories`, making the language available immediately without touching `MainControl.LanguagePackageInternalNumber` or any C# scripts.

### What files are mandatory for a language pack to appear in the Settings menu?

At minimum, the pack folder must contain [`LanguagePackInformation.txt`](https://github.com/arch-aik/undertale-changer-template/blob/main/LanguagePackInformation.txt) with a defined `LanguagePackName` key. Without this value, `SettingsController.GetLanguagePacksName` cannot populate the dropdown. Additionally, include [`UI/Setting.txt`](https://github.com/arch-aik/undertale-changer-template/blob/main/UI/Setting.txt) to ensure the settings interface itself has translated labels.

### How does the engine decide whether to load a pack from Resources or from disk?

The decision happens in `DataHandlerService.LoadLanguageData`. If the requested language ID is less than `MainControl.LanguagePackageInternalNumber`, the engine calls `Resources.Load` on `TextAssets/LanguagePacks/`; otherwise, it calculates an external index and reads from `Application.dataPath + "/LanguagePacks"` using `File.ReadAllText`.

### What is the difference between `LanguagePackFullWidth` and `CultureInfo` in the metadata?

`LanguagePackFullWidth` is a boolean flag that toggles full-width text rendering for languages like Chinese or Japanese, read by the UI layout system. `CultureInfo` specifies the .NET culture code (e.g., `ja-JP`) used for number, date, and currency formatting during localization parsing. Both are optional keys in [`LanguagePackInformation.txt`](https://github.com/arch-aik/undertale-changer-template/blob/main/LanguagePackInformation.txt).