How Fixing 15-Year-Old Code Finally Opens Elemental to the World
By Brad Wardell
August 2025
Localization: How to double your market size
Here's a business truth that haunts game developers: English speakers represent only 40% of the strategy 4X gaming market. The other 60%? They're playing games in German, Chinese, French, Spanish, Polish, Russian, and so many others.
For 15 years, Elemental was locked out of that 60%. That was because back in 2008, when we were developing the game, we were thinking mostly retail and that meant North America.
Now, in 2025, when looking at remastering Elemental and combining FE, SK, and WOM into a single integrated game, we need to reach that other 60%. This means revisiting the way we do strings.
BEFORE: Hard-coded strings everywhere
Problem 1: Hardcoded Strings in XML Data Files
Every piece of game text was baked directly into the data files:
<!-- From CoreUnits.xml (2010) -->
<UnitType InternalName="Champion_Donya">
<DisplayName>Donya, Tinker</DisplayName>
<Description>Tinkers are rare crafters that can create powerful items.</Description>
<BackStory>In the frozen North, in a town trapped under snow for half
the year, Donya was born to a struggling merchant family...</BackStory>
<Quote>If you can dream it, I can build it!</Quote>
</UnitType>
Want to translate this to German? You'd need to maintain completely separate XML files for every language. Change Donya's abilities? Update it in 7 different places. Don’t forget, this means breaking every mod.
At the same time, our UI strings used printf-style formatting:
// From the 2010 codebase
FormatSTLString(strMessage,
GetString("BattleMessage"), // "%s attacks %s for %d damage"
attacker,
defender,
damage);
The problems with this approach:
Type mismatches cause crashes: Pass a string where it expects a number? Crash.
Translation nightmare: German might need "für %d Schaden greift %s %s an" (completely different order)
Zero context for translators: What's the first %s? The second %s? Who knows!
Why We Stopped After Sorcerer King
We released:
Elemental: War of Magic (2010) - English only
Fallen Enchantress (2012) - English only
Sorcerer King (2014) - English only
Then we stopped. We had no choice. First, because these were 32-bit games and we could never fit the full game design into a single game because each one was a different aspect. Secondly, it became an ever increasing problem to have an “English only” game.
The 2025 Reforging: Fixing Everything
When we decided to create Elemental: Reforged, we knew this had to be fixed, but the scope was staggering:
The Archaeological Dig: What We Found
12,000+ hardcoded strings in XML files
514 FormatSTLString calls with printf formatting
467 broken parameter replacements (missing assignments)
71 C++ files with string handling code
3 competing string systems used simultaneously
Some files were museums of bad practices:
Unit.cpp: 69 broken parameter replacements
BattleEngine.cpp: All three systems in the same function
ElementalUI.cpp: Calls to put %d and %s together for tooltips.
Before (2010):
<Provides>Reduces unrest in this city by 5</Provides>
After (2025):
<Provides>TXT_COREUNITS_REDUCES_UNREST</Provides>
With the actual text in Strings.xml:
<Line Key="TXT_COREUNITS_REDUCES_UNREST">
<Text>Reduces unrest in {CITY_NAME} by {VALUE}</Text>
</Line>
Step 2: Replace Printf with Named Parameters
Before (2010):
FormatSTLString(msg, "%s deals %d damage to %s", attacker, damage, target);
// Translator sees: "%s deals %d damage to %s" (What does %s mean?)
After (2025):
str = CStringParameterReplacer::ReplaceParameter(str, _T("ATTACKER"), attacker);
str = CStringParameterReplacer::ReplaceParameter(str, _T("DAMAGE"), damage);
str = CStringParameterReplacer::ReplaceParameter(str, _T("TARGET"), target);
// Translator sees: "{ATTACKER} deals {DAMAGE} damage to {TARGET}"
// And can reorder: "{TARGET} nimmt {DAMAGE} Schaden von {ATTACKER}"
The Business Impact: Finally Reaching the Other 60%
With these fixes complete:
✅ Chinese localization: Now possible (1.4 billion potential players)
✅ Japanese localization: Now possible (125 million potential players)
✅ Korean localization: Now possible (75 million potential players)
✅ European languages: Germany and France and Poland are huge markets!
✅ Modding support: Community translations become feasible and modding is much more robust.
The Bottom Line
Fixing this for Elemental: Reforged wasn't just about clean code - it was about bringing Elemental to a worldwide audience.
Sometimes the most important feature is invisible, but it was worth it.
Now, finally, Elemental is for everyone.