Pseudolocalization: testing text
Safe text length testing, C# placeholder limitations and plural behavior.
Pseudolocalization changes text for testing: add padding, replace letters or mark translated strings. Use it to find text that clips or bypasses translation. It does not produce a real translation or certify fonts, Arabic shaping or RTL layout.
Start with a format-safe length test
Add this complete PseudoTextQA.cs to your C# project. Call PseudoTextQA.Enable() from a development-only action after your UI is created. Disable() returns normal message lookup; the helper does not save project settings to disk.
using Reckfell;
public static class PseudoTextQA
{
public static void Enable()
{
const string prefix = "internationalization/pseudolocalization/";
ProjectSettings.SetSetting(prefix + "replace_with_accents", false);
ProjectSettings.SetSetting(prefix + "double_vowels", false);
ProjectSettings.SetSetting(prefix + "fake_bidi", false);
ProjectSettings.SetSetting(prefix + "override", false);
ProjectSettings.SetSetting(prefix + "skip_placeholders", true);
ProjectSettings.SetSetting(prefix + "expansion_ratio", 0.5f);
ProjectSettings.SetSetting(prefix + "prefix", "[");
ProjectSettings.SetSetting(prefix + "suffix", "]");
TranslationServer.ReloadPseudolocalization();
TranslationServer.PseudolocalizationEnabled = true;
}
public static void Disable()
{
TranslationServer.PseudolocalizationEnabled = false;
}
}With an English translation Ready, Translate returns [Ready] in this mode. Padding per side is the original character count multiplied by expansion_ratio/2, rounded down; wrappers are additional. The result is not exactly 50% longer for every string: short text may receive no underscores. Increase the ratio for a stronger stress test.
This mode preserves composite format strings because it adds text around the message without changing its contents. Disable() leaves the configured transformation parameters in memory; it switches off their automatic application. Enable() sets the stated parameters again.
Settings and runtime updates
In Project Settings, enable Advanced and open General → Internationalization → Pseudolocalization. Settings use the prefix internationalization/pseudolocalization/.
| Setting | Effect |
|---|---|
| use_pseudolocalization | Startup enable setting; use TranslationServer.PseudolocalizationEnabled to toggle the running game |
| replace_with_accents | Replace supported Latin characters with accented variants |
| double_vowels | Duplicate supported vowels to lengthen words |
| fake_bidi | Insert directional control markers; not a complete RTL simulation |
| override | Replace message characters with asterisks, except recognized placeholders when skipping is enabled |
| expansion_ratio | Add underscores on each side, based on original length |
| prefix / suffix | Wrap the transformed text |
| skip_placeholders | Preserve the limited placeholder syntax described below |
After changing runtime ProjectSettings values, call ReloadPseudolocalization. It reloads transformation parameters and sends a translation-change notification. It does not read use_pseudolocalization to toggle the current enable state: set PseudolocalizationEnabled separately. These runtime changes are not a persistent preference unless your code explicitly saves them.
Code that calculates UI text must refresh on the notification. If testing only a local TranslationDomain, changing its transformation properties does not notify your whole UI; refresh that domain's consumers yourself.
Placeholder limitation: C# is not protected automatically
In the current runtime, skip_placeholders recognizes these simple two-character sequences: %s, %c, %d, %o, %x, %X and %f. It is not a general printf or C# format parser.
- With override enabled, Hi %s becomes ***%s before wrappers: the placeholder survives.
- Hi {0} becomes ******: the C# placeholder is destroyed despite skip_placeholders being enabled.
- A width specifier such as %02d is not protected either.
For C# string.Format templates, use the padding-only helper above. Test accents and overrides separately on plain text. Do not infer that all formatting survives because a single %s example works.
Plural lookup limitation
Translate applies pseudolocalization when enabled, including to a missing key. TranslatePlural currently returns its selected plural string without that automatic transformation. A plural counter staying unchanged therefore does not by itself prove that it bypassed localization.
To stress a plural message explicitly, first select the form, then apply Pseudolocalize, then format. Use the safe padding configuration above:
string form = TranslationServer.TranslatePlural("ITEM", "ITEMS", count).ToString();
if (TranslationServer.PseudolocalizationEnabled)
form = TranslationServer.Pseudolocalize(form).ToString();
label.Text = string.Format(form, count);These statements go inside a method with count and label already defined. Pseudolocalize is an explicit transformation and works even when the enable property is false; the condition prevents that in normal play. Keep automatic translation disabled on a Label that receives already calculated text, as in the complete plural Label example.
What to inspect
Check narrow buttons, wrapped text, tooltips, dialogs and keyboard/controller focus at the smallest supported window size. Confirm both the expanded text and all controls remain usable. Test real ru/en text as well: pseudolocalized English does not replace translation review.
Text unchanged by Translate may bypass lookup, have automatic translation disabled or be cached before enabling the test. Text visibly marked may still be an untranslated key, since missing keys are transformed too. Check the actual catalog rather than counting brackets.
For Arabic/Hebrew, test real mixed-direction text and the actual controls. fake_bidi inserts markers around text lines; it does not prove correct glyph shaping, mirrored controls or meaningful reading order. Accented Latin letters likewise do not establish CJK font coverage.
Before release, disable the test and clear any deliberately saved startup setting. Native tests cover exact transformations, rounding, placeholder/plural limitations, runtime reload notifications and the complete helper. Editor preview interaction, rendered overflow, fonts, RTL layout and exported builds are not covered by this run.