Localization Checker Manual, part 1: the checks and their results
On this page
- How a scan works
- What a scan reads
- UI Toolkit (Unity 6)
- Where translations come from
- Unity Localization
- Translation files
- I2 Localization
- How a text is bound to a key
- The checks
- Overflow
- Layout
- Overlapping texts
- Line breaks
- Pseudo-localization
- Variable samples
- Missing glyphs
- Placeholders
- Rich text tags
- Translation
- The patrol in Play mode
- Pseudo-language
- Superseded by the patrol
- Characters TextMeshPro reported missing
- The command line (continuous integration)
- Code and data
- Exports
- Reading the results
- The window
- Severity and “for reference”
- Confidence
- The issue list
- Since the last scan
- Preview, side by side, heat map
This part explains scan inputs, individual checks, Play mode patrols and result interpretation. The Quick Start provides a walkthrough. Manual part 2 (Manual-Safety.md) covers project safety, prerequisites and limitations, including false positives and missed cases.
How a scan works
For each configured resolution and language:
copy the scoped Canvases into a hidden preview scene
remove project scripts and use in-memory font and material copies
apply all translations for that language together
rebuild the layout and measure with the text engine
├─ text against its box: Overflow
├─ layouts that size text: Layout
├─ intersecting text bounds: Overlapping texts
└─ Japanese, Chinese, Korean and Thai: Line breaks
Without a layout pass:
├─ look up characters through each font's fallback chain: Missing glyphs
└─ compare every table key: Placeholders, Rich text tags, Translation
The overview groups these results into five columns: Overflow includes overflow, layout, overlaps and line breaks; Missing glyphs includes character coverage and font configuration; Placeholders and Rich text tags cover string structure; Translation includes table values, right-to-left and encoding concerns, and text outside localization.
What a scan reads
Choose Scope in the Scope row of Before you scan.
| Scope | Input |
|---|---|
| Open scenes | The current objects in every loaded scene in the Hierarchy. Each scene must have been saved at least once; current unsaved edits are included. |
| Selected objects | The selected objects in open scenes that have been saved at least once, including their current edits. |
| Prefab | One prefab or prefab variant from its saved asset. Unsaved Prefab Mode edits are excluded. |
| Prefabs in a folder | Saved prefab assets in the folder and its subfolders. The default Assets folder covers the project. No scene is opened. |
- The checker does not open closed scenes. Opening a scene may run
[ExecuteAlways]scripts that change assets. Open the required scene yourself, then use Open scenes. - Scene scans exclude objects tagged EditorOnly because builds strip them. Prefab scans include them.
- The line below the scope dropdown describes the current input. Scans are unavailable in Play mode.
Text components and elements. The scan reads content, font, bounds and layout from TextMeshPro uGUI and legacy UI Text components. On Unity 6, it also reads UI Toolkit documents as described below.
Languages to check. Select languages found in the translation tables. To check font coverage before translations exist, use Add a language: choose one of sixteen common languages or Enter a code…. Language-code matching is case-insensitive. Pseudo-localization adds a generated test language.
Source language. Choose the language in which the strings were originally written. It provides the comparison values for table checks and the content lookup for components containing source text instead of keys. Checks for text outside localization also require it. If it is not selected for checking, the scanner lays it out only as a comparison baseline.
Resolutions. Each configured resolution is measured separately. Overflow results identify the resolution used.
UI Toolkit (Unity 6)
On Unity 6, the scan builds scoped UIDocuments from their UXML in memory, including nested templates. It checks Labels, Buttons and control labels for localization, missing glyphs, overflow, overlaps and layout, plus line breaks from Unity 6000.3. The document copy renders into a checker-owned texture rather than the Game view. This support is unavailable on Unity 2022.3 and Tuanjie Engine.
- Results identify an element by object and element path, such as
Menu/Document › panel/title. - A Unity Localization
LocalizedStringbinding on an element’stextproperty in UXML gives High binding confidence. The scan cannot see bindings assigned throughSetBinding, strings assigned by code, or elements created at runtime. - Elements hidden by UXML (
display: none) are revealed on the copy one group at a time. Their results include hidden in the document. - From Unity 6000.5, an element with no font in its styles uses the theme’s default font. The engine does not expose that font, so its characters are skipped and the summary counts these elements.
- UI Toolkit layout requires editor frames to advance. Do not add
-quitto command-line scans.
Where translations come from
Unity Localization
The checker automatically reads Unity Localization 1.5.2 or later, below 2.0:
- All String Table Collections.
- LocalizeStringEvent bindings whose enabled dynamic-string update listener targets the text component, provided the localization component is also enabled.
- GameObjectLocalizer bindings that track the text component with a String Table. The checker reads per-language fonts from these bindings and custom font components derived from
LocalizedAssetEvent. It resolves asset-table fonts by GUID without loading them through Addressables. - Supported font-size, size, position, enabled-state and font changes from GameObjectLocalizer, applied to the copy before measuring each language.
Translation files
Add files under Translation files (CSV, Excel, JSON, XLIFF, PO), or drag them from the Project window into that group. The file extension selects Format.
| Format | Structure |
|---|---|
| CSV (comma or semicolon), TSV | UTF-8 with a header, one key column and one column per language. TSV support follows Google Sheets’ unquoted download format. |
| Excel workbook (.xlsx, .xlsm) | One sheet per table, using the same columns as CSV. The first nonempty row is the header. Choose Sheet; add the workbook again to read another sheet. |
| JSON | One file per language ({"key": "text"}), grouped by key ({"key": {"fr": "text"}}), or grouped by language ({"fr": {"key": "text"}}). Nested sections form dotted keys such as menu.start. |
| JSON, i18next style | One file per language. Suffixes such as _one, _few and _many identify plural forms; {{name}} identifies a placeholder. |
| XLIFF 1.2 or 2.0 | One file per language, as exported by Unity Localization or translation platforms. |
| PO (gettext) | One file per language, with msgid as the key. Set msgid language if msgid contains source text; X-Source-Language fills this automatically when present. Leave it empty when msgid is only a key and files supply every language. |
- Column mapping. The first column defaults to the key. Headers such as
en,English,Deutschand日本語map to language codes. Map unrecognized columns yourself;IDandNoare never treated as languages. Edit… opens the mapping. - Invalid files. A syntax error, duplicate key or missing mapped header prevents the whole file from being read. Its status gives the reason and line number, or worksheet row number.
- i18next. Each language requires
item_otherand the plural forms its rules use for whole numbers: for example, Germanitem_one, or Russian and Polishitem_one,item_few,item_many. A required form that is absent produces Missing translation. - XLIFF. Inline codes such as
<g>,<x/>and<ph>, or units divided into several segments, prevent the file from being read. - Excel. The parser reads saved cell values and cached formula results, without evaluating formulas or applying cell display formats. Rich-text runs are joined and their formatting discarded. Whole numbers of up to 15 digits are normalized to digits; other numeric values retain their stored representation, so dates usually appear as serial numbers. Save keys and translations as text. An open workbook is read from its last saved version. Legacy
.xlsand password-protected workbooks are unsupported; save an unprotected.xlsxcopy. - PO entries. Context prefixes the key with a bar, as in
menu|Open. An empty msgstr or fuzzy entry produces Missing translation, since gettext falls back to msgid. Plural entries create keys such asitem[0],item[1]and so on.Plural-Formsdetermines the count, defaulting to two; an empty requiredmsgstr[n]is missing, but forms unused by that language are not. - PO placeholder comparison. With msgid language set, every form is compared with
msgid_plural, following msgfmt’s approach. A form used for fewer than five values from 0 through 1000, according toplural=, may omit the number placeholder but cannot add one; other forms must retain all placeholders. English’s singular form is one example. Files must be UTF-8. An unreadablePlural-Formsexpression, or one producing an out-of-range form for a number from 0 through 1000, prevents the file from being read.
I2 Localization
The checker automatically reads I2 Localization 2.8.9 or later without calling its API during scans.
- Tables: the
I2Languagessource in a Resources folder and LanguageSource components in scanned files. Only Text terms become keys. - Bindings: an enabled Localize component binds the text component on its object to its term with High confidence. A component with no term is Unbound.
- Measurement: the Localize case modifier, prefix and suffix are applied before layout.
- Play mode: the patrol uses I2 to switch the game’s language.
How a text is bound to a key
Key binding describes the match and its confidence.
| Binding method | Confidence |
|---|---|
| LocalizeStringEvent, GameObjectLocalizer or I2 Localize drives the component | High |
| A Declared key field identifies the string field in your component | High |
| Component content matches a key in a table marked Text boxes hold this table’s keys | High |
| Component content matches a source-language translation | Medium |
| Multiple components drive the same text component, including components of the same type | Medium |
| Map a key… assigns a key manually | Low |
A key found in several tables reduces High confidence to Medium. Unbound means no key was identified. Broken means the binding names a table or key absent from the sources read. If component contents resemble a table’s keys but the table option is off, the scan offers Turn it on and scan again.
Unreadable tables and duplicate keys belong to Sources. When any exist, the overview shows Problems with the translation tables themselves (a table not read, a key twice): below its counts. Click the count for details.
The checks
Overflow
| Issue | Severity | Meaning |
|---|---|---|
| Text overflows | Critical | Rendered text extends beyond its box. |
| Text truncated | Warning | Ellipsis or Truncate cuts the string short. |
| Text nearly overflows | Info | Less than 5% of the available space remains on a checked axis. |
| Text auto-sized too small | Warning | Auto Size or Best Fit reduces the font below three quarters of its configured maximum. |
| Text not measured | Info | Measurement was unavailable; Detail explains why. |
- Height is checked; width is checked only without wrapping. An axis controlled by Content Size Fitter or a Layout Group is handled by the layout check instead.
- Measurement requires a translation for the bound key in that language. Other reasons to skip include UI text outside a Canvas, custom text or layout classes, input-field labels and dropdown captions rewritten by their controls, a Canvas that could not be copied, missing TMP Essential Resources, or translations referencing font, style, material or sprite assets.
- A Mesh Renderer-based 3D TextMeshPro under a Canvas is measured with it. Outside a Canvas, it is copied with its ancestor RectTransforms and measured in its own box, identically at every resolution. It receives no layout or overlap check and no side-by-side image.
- Screen Space - Camera Canvases use the camera viewport configured in the editor at scan time. A Scroll View with automatically hidden scrollbars reserves scrollbar space only when content overflows.
Common Detail notes:
- hidden in the scene: the component or an ancestor is inactive. Measurement revealed all hidden objects in that Canvas together.
- measured without these scripts: the listed scripts were removed from the copy and may change content, fonts or sizes at runtime.
- the source text too, not grown in this language: for reference: the source has the same issue at that resolution and the translation does not worsen it. A growth note such as the source text too, 20 more in this language means the issue still counts.
- Fixes: for overflow and truncation, the checker tries wrapping, Auto Size or Best Fit, and font sizes down to three quarters of the configured size, on a copy. Examples include fits at font size 30 (now 36) and does not fit wrapped. These are suggestions; no fix is applied to the original component.
Layout
The scan follows each text component’s sizing layout up to its root.
| Issue | Severity | Meaning |
|---|---|---|
| Layout runs off the screen | Critical | The layout root extends beyond the screen. |
| Layout runs past its parent | Warning | The layout root extends beyond its parent. |
| Child runs past its layout group | Warning | A child extends beyond its Horizontal or Vertical Layout Group. |
| Child squeezed by its layout group | Info | A non-text child receives less space than it requests. |
| Layout not measured | Info | Measurement was unavailable; Detail explains why. |
Detail gives distances in canvas units, such as past its parent: left 12, right 12. As with overflow, an unchanged issue already present in the source language is listed for reference only.
Overlapping texts
| Issue | Severity | Meaning |
|---|---|---|
| Texts overlap | Warning | Translated text intersects another text’s rendered bounds where the original scene does not. |
- Comparisons are limited to text components in the same Canvas that can appear together. Components in a closed dialog are compared only with each other.
- The engine’s rendered text bounds form rectangles. An intersection must be at least 1 unit on each axis. Pairs already overlapping in the original scene are excluded.
- A component with an overflow issue in that language is excluded from overlap comparisons; overflow takes priority.
- Detail identifies the other component and intersection depth, for example covers the glyphs of Canvas/Options/Value, 12 units deep.
Line breaks
| Issue | Severity | Meaning |
|---|---|---|
| Bad line break | Warning | An automatic break violates Japanese or Chinese rules, splits a Thai syllable, or splits a Korean word in a UI Toolkit element. |
| Korean breaks inside words | Warning | Korean is selected and TextMeshPro is present, but TMP Settings’ Use Modern Hangul Line Breaking Rules is off. TextMeshPro may split words between syllables. Reported once per checked Korean language on TMP Settings. |
| May break inside a word | Info | A Thai break falls between letters without a marked word boundary. |
- Only automatic breaks are checked. Explicit line breaks in translations are excluded. Japanese and Chinese rules restrict punctuation at line starts and ends and keep pairs such as …… and —— together.
- Thai checks detect syllable violations: a leading vowel (เ แ โ ใ ไ) cannot end a line, and a dependent vowel, tone mark or sign cannot start one. Word-boundary detection requires a dictionary that the checker does not provide. An unmarked break between Thai letters therefore produces May break inside a word, even if it happens to be valid. Detail may say line 2 breaks between มก, where no word boundary is marked. A zero width space (U+200B) marks a boundary for TextMeshPro and UI Toolkit, suppressing that warning at the boundary; legacy Text ignores it.
- Detail lists the break locations, such as line 1 ends with ( · line 3 starts with 。. Hover over the issue kind for guidance.
- TextMeshPro uses the two Line Breaking for Asian languages files in TMP Settings. Missing or empty files provide no rules. TextMeshPro in Unity 6 can still leave opening brackets and quotation marks at line ends. Legacy Text does not apply these rules. UI Toolkit handles most itself; from Unity 6000.3 the scan checks its resulting lines, excluding strings containing rich-text tags or escapes and counting those exclusions in the summary.
- Modern Korean breaks at word spaces. Enabling Use Modern Hangul Line Breaking Rules changes TextMeshPro’s line-breaking behavior only. Legacy Text already breaks at spaces. UI Toolkit has no equivalent switch and can split between syllables; from Unity 6000.3 the scan reports these element-level breaks as Bad line break, for example the word at 니다 split at the end of line 2.
Pseudo-localization
Scan Pseudo-localization generates qps-ploc from source strings, accents letters and expands length by about 40%: Settings becomes ŚéţţîñĝśŚéţţ. Tags and placeholders remain unchanged. This requires no translated table and checks only overflow, overlaps and layout, with Static Estimate confidence.
This generated scan language is separate from the game-provided Pseudo-language used by the Play mode patrol.
Variable samples
Under Variable samples, assign the longest expected runtime value to each placeholder. The scanner substitutes these values when measuring overflow and layout in every language. Use the exact placeholder spelling, such as {playerName}, {0}, %s or %1$s; names are case-sensitive. Unsampled placeholders are measured literally, and Detail identifies them.
In the patrol, Use variable samples asks the game to display the samples. Matching Unity Localization global string variables are set automatically. For custom code, declare a static void Method(IReadOnlyDictionary<string, string> samples) under Variable samples for patrols (the project’s own code). The checker passes null when the original values should be restored.
Missing glyphs
The scan resolves characters through the text system’s font chain without querying the editor computer’s system fonts:
- TextMeshPro: the font asset and its fallbacks, TMP Settings fallbacks, then the default font. Dynamic assets also use their source font file. Bold and italic lookups start with the weight table’s typeface.
- Legacy Text: the assigned font, followed by fonts referenced in its import settings.
- UI Toolkit: the resolved font and its fallbacks, followed by the owning panel’s Text Settings. Panels sharing a font retain separate fallback settings.
Tags and placeholders are excluded. Case styles are applied before lookup: uppercase é, for example, is checked as É.
| Issue | Severity | Meaning |
|---|---|---|
| Missing glyphs | Critical; Warning for a legacy dynamic font | The checked font chain lacks the characters. They may display as replacement glyphs or boxes. |
| Left to the device’s fonts | Warning | Rendering depends on system fonts, including Dynamic OS assets and fonts without readable font data. |
| Drawn by a fallback font | Info | A fallback supplies the characters; review its visual consistency. Listed for reference only. |
| Font lacks the language | See below | Language character-set coverage is incomplete. |
| Dynamic font with one atlas | Warning | Multi Atlas Textures is disabled; new characters can fail when the atlas fills. |
| Source font file unreadable | Warning | The dynamic font cannot add characters from its source file. |
| One font for Chinese and Japanese | Info | Shared Han characters may require different regional glyph shapes. |
| Right-to-left text | Warning | Review direction and shaping for Arabic, Hebrew and similar scripts in the game. |
| Suspected encoding problem | Warning | Potentially unintended zero-width characters, a byte order mark, decomposed accents, private-use characters or U+FFFD. A zero width space in a Thai translation is accepted as a line-break hint. |
Language coverage. The checker looks up built-in character sets and punctuation before translations exist. These cover the languages fully supported by Steam, including Chinese, Japanese, Korean, Thai, Arabic, Greek, Russian, Ukrainian, Bulgarian and Latin-script languages. Language coverage reports none, partial with a percentage, complete, or left to device fonts. Font lacks the language is Critical if no language characters are covered, reduced to Warning when system fonts may supply them. Partial dependence on system fonts is Warning; incomplete character or punctuation coverage is Info.
UI Toolkit coverage uses the font’s own fallback chain without a panel’s global fallbacks. An element may therefore render successfully through its panel even when the font’s coverage is incomplete.
Fonts by language lets you provide replacements when your game’s font-switching mechanism is not detected. The scan uses the replacement for character lookup and overflow in that language. Also check the language coverage of every TextMeshPro font asset in Assets adds project-wide font-coverage hints.
The scan’s missing characters by font groups missing characters by font. Copy for Font Asset Creator copies them for Font Asset Creator’s Custom Characters input.
Placeholders
Supported placeholders include {0}, {name}, Smart String formats such as {count:plural:item|items}, %s, %d, %1$s, {[NAME]} and i18next {{name}}. Translations may reorder them.
| Problem | Severity |
|---|---|
| Missing or added placeholder | Critical |
Renamed placeholder, such as {name} → {nombre} | Critical |
Translated placeholder name, such as {玩家名} | Critical |
| Different occurrence count | Warning |
Rich text tags
The checker interprets tags according to the relevant text engine and compares them with the source string. Intentional source formatting is accepted, as are complete tag pairs added or removed together.
| Problem | Meaning |
|---|---|
| Left open | A tag closed in the source is not closed in the translation. |
| Machine-translated | Tag syntax becomes look-alike text, such as internal spaces, full-width brackets or </br>. |
| Crossed | Tags close in the wrong order: <b><i></b></i>. |
| Attribute changed | An attribute differs: <color=#FF0000> → <color=#00FF00>. |
Tag problems are grouped into one issue per key and language. Attribute-only differences are Warning; other problems are Critical. A translated tag value such as <color=红色> is Critical.
Tag names a missing asset is Critical when a TextMeshPro <font="…">, <sprite="…">, <sprite name="…"> or <style="…"> references a name absent from the project. Such references can render incorrectly or appear literally. The issue appears once per name and table under (no language); it does not validate runtime asset resolution.
Translation
These checks require Source language and examine every key in every table, including keys unused by the scanned UI.
| Issue | Severity | Meaning |
|---|---|---|
| Missing translation | Critical | The language exists in the table, but the key has no entry. |
| Empty translation | Warning | The value is empty or contains only spaces. |
| Same as the source text | Warning | The value equals the source, including names and OK; review whether this is intentional. |
| Placeholder marker | Critical | A marker such as TODO, ### or [NEEDS TRANSLATION] remains. |
| Table lacks the language | Critical | A checked language has no column or file. |
| Table lacks the source language | Warning | The source language has no column or file. |
| Suspected mojibake | Critical | Values appear corrupted by an encoding mismatch, such as é, å¼€, 锟斤拷 or Привет. Reported once per table. |
| Suspected escape leak | Warning | Literal escapes such as \n, \" or & occur more often than in the source. |
| Ending punctuation differs | Warning | The translation changes or omits the source’s final punctuation type. |
| Extra whitespace | Warning | Leading, trailing or doubled spaces appear where the source has none. |
| Unpaired brackets or quotes | Warning | Brackets or quotation marks paired in the source are unpaired in the translation. |
| Numbers differ | Warning | Numeric values are missing, changed or added. Missing values from 1 to 12 are exempt because translations may spell them out. |
| Translation may be too long | Info | An unbound table key is longer than expected for its source length. This is a character-based estimate without layout measurement. |
| Inconsistent translations | Info | A table translates the same source string of at least 16 text units in several ways. |
Texts outside localization:
| Issue | Severity | Included in counts |
|---|---|---|
| Hard-coded text | Warning | Yes |
| Broken binding | Warning | Yes |
| Unbound | Info | Reference only |
| May be set by a script | Info | Reference only |
A component matched only by its source content is also hard-coded: the match does not establish runtime replacement. May be set by a script means a script field references the text component, or the UIDocument containing the element. Empty values, New Text and strings without letters are excluded.
Ignore list. Key rules suppress eligible per-key table-value issues. They do not suppress UI overflow or glyph issues, or table-level issues such as missing languages, suspected mojibake and missing asset references. Path rules and text regular expressions suppress Hard-coded text, Unbound and May be set by a script, plus the patrol’s Strings joined at run time and Hard-coded at run time. They do not suppress Broken binding or other checks. Ignore adds an applicable rule from the selected issue.
The patrol in Play mode
The patrol asks the game’s localization system to switch languages, then reads the UI as the game laid it out. It does not assign translations to text components or read translation tables. It does not run the table placeholder, rich-text or translation checks, or the scan’s layout checks. Its optional pseudo-language check is described below.
Eligible components and elements. The patrol reads enabled, active TextMeshPro and legacy UI Text components under enabled Canvases in loaded scenes and DontDestroyOnLoad. It excludes those fully hidden by a Canvas Group or culled by RectMask2D. On Unity 6, it also reads displayed elements in active UIDocuments. It reads 3D TextMeshPro when an enabled game camera can render it on screen: the renderer must be enabled, within that camera’s view and visible layer mask, and the camera must not target a texture. These 3D components are framed using that camera and excluded from overlap comparisons. UI text components outside a Canvas are unsupported.
Language switching, shown under Switch in the patrol bar:
- Unity Localization: sets the selected locale through Localization Settings in Play mode and waits for displayed LocalizeStringEvents to load.
- Your own system: invokes the two static methods declared under Language switch for patrols (the project’s own localization system). Returning from the switch method marks the switch complete.
- I2 Localization: becomes available when I2 is installed and switches without saving I2’s language preference.
Per-language checks:
| Issue | Severity | Meaning |
|---|---|---|
| Text overflows | Critical | The game’s rendered text exceeds its box. |
| Text truncated | Warning | The displayed string is cut short. |
| Text nearly overflows | Info | Less than 5% of the checked space remains, as in a scan. |
| Text auto-sized too small | Warning | The same font-shrink threshold used by scans. |
| Texts overlap | Warning | Rendered bounds intersect under the same root Canvas, or within the same UI Toolkit document, where they do not in the page’s source-language version. |
| Bad line break | Warning | A TextMeshPro or legacy Text break violates Japanese, Chinese or Thai rules. |
| May break inside a word | Info | A Thai break has no marked word boundary. |
| Missing glyphs | Critical | TextMeshPro used its replacement glyph, or a UI Toolkit element’s resolved font lacks the character. |
| Left to the device’s fonts | Warning | A Dynamic OS font asset supplied the characters. |
| Drawn by a fallback font | Info | Another font asset supplied the characters. Listed without an outline. |
Patrol issues have Play Verified confidence. Overlap comparisons and source-language equivalence require Languages to check to include the source language so the patrol can read that version of the page.
Checking a page. Click Check page in all languages (F8), or focus Localization Checker and press F8. This starts a patrol if needed. For each selected language, it switches, waits Page check: frames to wait after each switch (120 by default), also waits for Unity Localization’s displayed strings, then reads the UI and captures the Game view. It restores the previous language and retains the completed page for this editor session.
Stopping the patrol or leaving Play mode during a check discards that unfinished page; earlier completed pages remain. If an initially visible root Canvas or UI Toolkit document disappears, the patrol ends and explains why. Check again when the screen is stable. An additional popup appearing does not by itself count as leaving the page.
Page names. The suggested name uses “scene: Canvas”, based on the topmost root Canvas and its scene. A DontDestroyOnLoad Canvas uses the active scene; a UI Toolkit-only page uses the first document. Automatically suggested names gain a number when already used, such as Title: MainCanvas (2). A manually entered existing name replaces that page; the bar warns before the check.
Results and persistence. Each completed page has an overview block with language rows and Open screenshot. A dash means not checked, rather than zero issues. In Issues, patrol rows follow scan rows of the same severity and include Page. Map a key… and Scene preview are unavailable for patrol rows. Ignore applies only to the two pseudo-language issue kinds. Completed pages survive domain reloads and leaving Play mode, until cleared or the Editor exits; they are not project assets.
Screenshots. Each language captures the Game view in the frame read, including outlines if Outlines is enabled. Files are kept in Temp/LocalizationChecker/Patrol. Export screenshots… copies them to a chosen location with one folder per language.
Pseudo-language
Your game’s localization system must supply a pseudo-language that brackets each localized string, such as [Šţáŕţ]. The checker does not generate this runtime language. Joined strings produce several bracketed groups in one component; hard-coded words appear outside the groups. Check page in all languages reads this language last and runs only these checks:
| Issue | Severity | Meaning |
|---|---|---|
| Strings joined at run time | Warning | One displayed value contains two or more bracketed strings. Use one localized phrase with placeholders so translators can reorder its parts. |
| Hard-coded at run time | Warning | Letters appear outside the brackets, or in a value with no brackets. They may have bypassed localization. |
- Tags are stripped before checking. Digits, punctuation and spaces outside the brackets, such as scores and times, are accepted. Placeholder values already enclosed within a localized string are accepted too.
- Unity Localization: uses the first Pseudo-Locale in the project. Its final method must be the bracket-adding Encapsulator. Earlier padding may contain bracket characters only if a subsequent Accenter replaces them. An unsuitable configuration skips this check and explains why in the page block.
- I2 Localization and custom systems: enter an implemented pseudo-language code and its brackets under ⚙ Settings › Patrols › Pseudo-language. The default brackets are
[and]. That code is removed from the normal checked languages and read last. Never assign a real language code here. - The Pseudo row contributes only to Translation. It does not check overflow, glyphs or overlaps, and TextMeshPro missing-character warnings are not collected while it is active.
- Intentional literal values, such as player names or language names, can be reported. Ignore creates an object-path rule for these issues. Existing patrol results immediately follow the updated ignore list; scans use it on the next run. Text rules match the value displayed in the pseudo-language.
Superseded by the patrol
A retained page can supersede scan issues for the same component and language. The scan row remains for reference, with Detail beginning superseded by the patrol’s page ”…”, checked ….
- Overflow issues require the Game view to match the scan resolution exactly and the displayed string to equal the string measured by the scan.
- Missing glyphs, Left to the device’s fonts and Drawn by a fallback font require a non-truncated TextMeshPro component displaying every character named by the scan issue.
- Layout, encoding, font-configuration, table and unlocalized-text issues are never superseded. Neither are legacy Text character issues, overflow issues with a different runtime string, or issues from prefab assets: runtime instances are separate objects.
If a page captured the previous language before the UI updated, increase the wait frames and check it again. Clear patrol results restores superseded scan issues to the counts.
Characters TextMeshPro reported missing
During a patrol, The patrol’s missing characters by font collects missing-character warnings from any TextMeshPro component the game displays, including player names, chat and server strings. It is not limited to checked pages. Collection depends on TextMeshPro’s Console warnings; Disable warnings in TMP Settings prevents it. The list remains until the next patrol starts.
The command line (continuous integration)
A build server can scan a prefab folder without opening the checker window:
Unity -batchmode -projectPath <project> -executeMethod Fastzhuzhu.LocalizationChecker.Editor.Ugui.CommandLine.Scan -logFile <log>
[-locchkFolder Assets/UI] [-locchkReport <file.csv>] [-locchkJUnit <file.xml>] [-locchkFailOn critical|warning]
- Scope: all prefabs in
-locchkFolderand its subfolders, defaulting toAssets. This matches Prefabs in a folder and opens no scene. - Settings: uses
ProjectSettings/LocalizationChecker.json. Configure the project in the window and commit that file for CI. - Reports:
-locchkReportwrites the Export CSV… format.-locchkJUnitwrites JUnit XML with one test case per overview cell and failures determined by the run’s verdict. Paths are relative to the project and cannot be underAssets,Packagesor a package folder. - Log: includes the summary, notes and verdict, for example Failed: counted issues at Critical or worse: 3.
- Exit codes:
0means every prefab was read and no counted issue met or exceeded the-locchkFailOnthreshold (criticalby default). Reference-only issues do not fail the run.2means the threshold was reached or a prefab could not be read.3means the run could not complete the request: invalid or repeated arguments, refused report paths, missing language selection, invalid folders, interrupted scans, report-writing failures or unexpected errors. The log gives the reason.1indicates a Unity failure, such as compilation errors. - Do not add
-quit. The scan exits the Editor itself; an early exit prevents checks that need editor frames from completing.
Code and data
Code & data finds potential strings outside scene and prefab scans, plus culture-sensitive code calls. These text searches have Low confidence: they do not establish that a string reaches players or a call is incorrect. Both scans are read-only.
- Scan code reads C# under
Assetsthat is included in the game, excludingEditorfolders, editor-only assemblies and tests. It lists string values assigned totextor passed toSetText, directly or throughstring.Format, such asAssets/Scripts/Shop.cs:42and$"Coins: {coins}". Empty values, the defaultNew Text, strings without letters and lines containinglocchk:ignoreare excluded. Click a row to highlight the script; double-click to open its line. - Scan code also lists culture-sensitive calls in a separate card: parameterless
ToUpper()andToLower();char.ToUpper(c)andchar.ToLower(c);float,doubleanddecimalParseorTryParsewithout anIFormatProvider; and single-argumentConvert.ToSingle,ToDoubleandToDecimal. Turkish casing changesitoİ; German and French numeric conventions can change how1.5is parsed. For culture-independent keys, filenames, saves and settings, useToUpperInvariant/ToLowerInvariantor passCultureInfo.InvariantCulture. Custom methods with the same names can also be listed.locchk:ignoreexcludes a line. - Scan data reads saved ScriptableObject
.assettext without loading assets or executing their code. It lists likely human-readable values with at least two words, or at least two characters in scripts such as Chinese, Japanese, Korean or Thai, for exampleAssets/Data/Shop/Gems.asset › m_ItemName. Single words,LocalizedStringfields and I2 sources are excluded. Binary assets cannot be read; use Asset Serialization Force Text. Click to highlight the asset in the Project window, or double-click to select it.
Exports
The Export menu beside Rows listed exports the currently displayed rows in their current order. The file dialog remembers the last export folder. Exports cannot be saved under Assets, Packages or a package folder.
- Export HTML… creates one offline UTF-8 file that follows the system’s light or dark appearance. Click counts to filter by severity, check or language; press / to search; expand rows to compare source and translation. Select in Unity copies a selection command. Return to Unity with Localization Checker open to select the object; objects in closed scenes are pinged without opening the scene. The report describes the exported rows and does not certify that all checks passed.
- Export CSV… writes the same rows as UTF-8 CSV, including resolution, page, check time and object ID. Filter from the overview or enable Hide rows for reference to narrow the export. To prevent spreadsheet formulas, cells beginning with
=,+,-,@, a tab or a carriage return receive a leading apostrophe. The same protection applies after semicolons within a cell. - Export screenshots… copies patrol screenshots into one folder per language.
- Export context package… writes retained patrol pages as
context.jsonand screenshots in your chosen folder. Each nonempty text value has an entry per language and page, including the page, screenshot, text bounds on that image, object, binding keys from open scenes, displayed value, rendered font and size, component dimensions, wrapping and fit. Pseudo-language results and empty labels, such as those on icon-only buttons, are excluded. Missing screenshot files are not recreated. Leave Play mode before exporting because bindings are read from open scenes.formatandversionidentify the JSON schema. - Export images…, in the side-by-side window, saves PNG files named by object, resolution and language. Invalid filename characters become underscores, long names are shortened, and collisions gain a number to preserve every image.
Reading the results
The window
Top band: logo · Localization Checker · version · author's signature
Toolbar: ▶ Scan · setup status · ⚙ Settings · window language · ⋮ menu
Tabs: Overview · Issues · Code & data
Drawer: Key bindings · Measuring · Ignore list · Patrols
Footer: summary · scan notes · messages
The ⋮ menu provides Clear scan results, Clear patrol results and About. The overview begins with Before you scan, renamed This scan after scanning. Its rows are Translation sources, Languages to check, Source language, Scope, Scan and Patrols (optional). The first five contain their related settings. Each numbered indicator shows status: green for complete, red for a blocker, yellow for review, and blue for ready. The blue-highlighted row is the first blocking setup step, or Scan when ready. After a scan, rows collapse; editing a setting changes the scan status to Out of date: settings changed. In Play mode, Languages for the patrol replaces this setup list.
Severity and “for reference”
- Critical: high-priority findings with possible player impact. Confirm the context before treating them as defects.
- Warning: potential problems or behavior that may vary by device or context.
- Info: findings worth reviewing or additional diagnostic information.
Some findings are reference-only: Unbound, May be set by a script, fallback-rendered characters, unmeasured input-field labels, unchanged source-language issues and scan issues superseded by patrol pages. Detail identifies these rows. They do not contribute to overview cells or severity totals. Hide rows for reference removes them from the issue list and exports.
Confidence
- Play Verified: observed by the patrol in the running game’s layout.
- Engine Verified: measured by the text engine on a copy.
- Engine Metadata: read from font data.
- Static Estimate: measured using a generated pseudo-translation.
- No value: derived from strings, tables or bindings.
Confidence describes the source of evidence, not whether the finding is an intentional design choice.
The issue list
Default columns are Severity, Issue, Language, Object and Detail. (no language) identifies language-independent issues. Object shows the name followed by its location in lighter text. Retained patrol pages add Page. Right-click the header to enable Check, Confidence, Table, Key and Key binding. Hover over a cell for its full value.
Click a row to select its object. The right-hand details panel shows all fields and applicable actions: Map a key…, Ignore, Side by side and Open screenshot. For patrol issues, the screenshot is the page in that issue’s language.
Two additional Detail notes explain binding caveats:
- mapped by hand, but a component drives it: the mapping is not used.
- a script references the component that drives it: …: runtime code may change the displayed value; check that screen with the patrol.
Since the last scan
When comparable results are replaced, the overview counts New and No longer reported issues. Click either count to filter; Change identifies each row. A disappeared finding may be fixed, ignored or unmeasured, so inspect the cause. Comparisons require matching scope, languages, resolutions, source language and enabled checks. Comparison data is lost when the scan results are cleared or discarded.
Preview, side by side, heat map
- Preview: select a scan overflow issue to temporarily display and outline its translation in the Scene view. Selecting another row or leaving the checker window restores the original. Only components in open scenes saved at least once are supported.
- Side by side: overflow, overlap, line-break and layout issues can render their Canvas or UI Toolkit document at the issue resolution, with one image per language and the source first. The affected component or layout root is outlined in red. Follow selection tracks the selected row, Zoom changes display scale, Render again refreshes, and Export images… saves PNGs. Outline in files includes outlines in exports. Patrol issues instead show the page’s captured screenshots.
- Heat map: the Scene view outlines objects represented by listed issues, using the most severe issue color per object. The legend groups Overflows, Cut short, Missing glyphs, Placeholders and tags, and Nearly overflows, too small, with matching numbers. Reference-only issues, unmeasured text, translation checks and font-asset issues are excluded. Click an outline to select its row.
- Hierarchy marks: in the classic Hierarchy, a colored square marks each object with counted issues. Hover for counts or click to select the corresponding issue.