Featured image of post A Script to Fix Missing Name Localization Entries in CK3

A Script to Fix Missing Name Localization Entries in CK3

Quickly resolve 'Missing loc' errors related to character names.

Introduction

A common challenge in Crusader Kings 3 modding is figuring out how to quickly transfer hard-coded character names into localization files.

Fortunately, this problem is quite simple to solve. When a character’s name is defined in the character files but not in the localization files, the game’s error.log will report errors for the missing localization entries. For example:

1
2
[15:47:18][E][culture_name_equivalency.cpp:101]: Missing loc Chrysanthius: "Chrysanthius"
[15:47:18][E][culture_name_equivalency.cpp:101]: Missing loc Oribasius: "Oribasius"

Since these errors follow a consistent format, the issue can be easily resolved with a simple script to process the log file.

The Script

Code

You can use the code below directly.

Python is required.

Click to view the code
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
import re
import os
from collections import OrderedDict

def generate_loc_from_log(log_file_path, output_file_path):
    """
    Extracts missing localization entries from a CK3 error.log file
    and generates a .yml file.
    """
    # Regular expression to match the "Missing loc KEY: " format
    # It captures the part after "Missing loc " and before the colon ":" as the key (KEY)
    pattern = re.compile(r"Missing loc ([^:]+):")

    # Use a set to store all found keys, which automatically handles duplicates
    found_keys = set()

    print(f"Reading log file: {log_file_path}")

    try:
        with open(log_file_path, 'r', encoding='utf-8', errors='ignore') as log_file:
            for line in log_file:
                match = pattern.search(line)
                if match:
                    # Extract the matched key and strip any leading/trailing whitespace
                    key = match.group(1).strip()
                    if key:  # Ensure the key is not empty
                        found_keys.add(key)
    except FileNotFoundError:
        print(f"Error: File not found at '{log_file_path}'. Please ensure the path is correct.")
        return
    except Exception as e:
        print(f"An error occurred while reading the file: {e}")
        return

    if not found_keys:
        print("No 'Missing loc' errors found in the log file.")
        return

    # Convert the set to a list and sort it alphabetically for a clean output file
    sorted_keys = sorted(list(found_keys))

    print(f"Found {len(sorted_keys)} unique missing localization entries.")

    try:
        with open(output_file_path, 'w', encoding='utf-8-sig') as output_file:
            # Write the required language header for the yml file
            output_file.write("l_english:\n")

            # Iterate through all sorted keys and write them to the file in the correct format
            for key in sorted_keys:
                # Format as:  KEY:0 "KEY"
                # Note: The two leading spaces are required by the yml format
                output_line = f' {key}:0 "{key}"\n'
                output_file.write(output_line)

        print(f"Success! Localization file generated at: {output_file_path}")
        print("You can copy and paste the contents of this file into your mod's localization file.")

    except Exception as e:
        print(f"An error occurred while writing to the output file: {e}")

if __name__ == "__main__":
    # 1. Place the path to your error.log file here
    #    Example: "C:/Users/YourUser/Documents/Paradox Interactive/Crusader Kings III/logs/error.log"
    #    If the script is in the same folder as the log file, you can just use "error.log"
    input_log_path = "error.log"

    # 2. This is the name of the generated output file
    output_yml_path = "generated_names_loc.yml"

    # Run the main function
    generate_loc_from_log(input_log_path, output_yml_path)

How to Use

It is recommended to create the generate_loc.py file in the same directory as error.log. The path is typically:

1
%USERPROFILE%\Documents\Paradox Interactive\Crusader Kings III\logs

Then, open a Command Prompt or PowerShell in that directory and execute the following command:

1
python generate_loc.py

After the script finishes, a new file named generated_names_loc.yml will be created in the same folder. This file will contain all the necessary localization entries.