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:
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.