Lab 2.3: Normalization & Character Inspection
Act as a localization engineer investigating invisible character bugs.
Objective
In this hands-on lab, you will act as a localization engineer investigating invisible character bugs. You will inspect the byte-level difference between NFC (Precomposed) and NFD (Decomposed) Unicode strings, demonstrate why visually identical strings fail equality checks in database queries and file paths, and execute a normalization cleanup across multi-lingual assets.
Required Setup & Prerequisites
Editor: Visual Studio Code installed.
Working Directory: Open your
loc_labworking directory in VS Code.
Step-by-Step Instructions
Step 1: Create the Unnormalized Test Assets
To experience Unicode equivalence issues firsthand, create two JSON files that look visually identical on screen but contain different byte structures.
Open VS Code and navigate to
assets/loc/software/.Create
user_search_nfc.jsonand paste:JSON
json{ "user_id": 101, "name": "Zamość", "query": "español" }In the same directory, create
user_search_nfd.json.Copy and paste the following decomposed (NFD) string structure into
user_search_nfd.json:JSON
json{ "user_id": 101, "name": "Zamość", "query": "español" }Save both files (
Cmd + Son macOS /Ctrl + Son Windows).
Notice: On your monitor,
"Zamość"and"español"look identical in both files. However, inuser_search_nfd.json, the accented characters were saved as base letters plus combining marks (s+́,c+́,n+̃).
Step 2: Inspecting Cursor & Character Behavior in VS Code
Open
user_search_nfd.jsonin VS Code.Click your text cursor directly to the right of the letter
ñin"español"on line 4.Press the Left Arrow Key on your keyboard once:
Observation: Notice that pressing Left Arrow once moves the cursor between the
nand the combining tilde (̃). It takes two keypresses to move across a single decomposed character!
Switch to
user_search_nfc.jsonand repeat the same experiment on"español":Observation: In the NFC file, pressing Left Arrow moves the cursor across
ñin a single keypress becauseñis stored as a single precomposed code point (U+00F1).
Step 3: Simulating Database & Search Failure (Equality Check)
Why does this difference break production systems? Let's analyze why a search engine or SQL query fails when matching NFC input against NFD data.
Open the VS Code Find Widget (
Cmd + Fon macOS /Ctrl + Fon Windows).Copy the word
españolfromuser_search_nfc.json(NFC) and paste it into the Find search box.Open
user_search_nfd.json(NFD) while keeping the Find widget active.Observe the Find widget result count: 0 results found!
Search Query (NFC): "español" [ U+0065 U+0073 U+0070 U+0061 U+00F1 U+006F U+006C ]
Target Value (NFD): "español" [ U+0065 U+0073 U+0070 U+0061 U+006E U+0303 U+006F U+006C ]
Match Result: FAIL / 0 MATCHESEven though a human reader sees the exact same word, the computer's string comparison algorithm compares raw code points and rejects the match.
Step 4: Normalizing Assets to Standard NFC
To fix decomposed character bugs across software UI, game engines, and subtitle file paths, convert all assets to NFC (Normal Form C).
Open
user_search_nfd.json.Select the entire file contents (
Cmd + A/Ctrl + A).Open the Command Palette (
Cmd + Shift + P/Ctrl + Shift + P).Type
Change Language ModeselectJSON.Re-key or replace decomposed strings with precomposed NFC characters (
Zamość,español).Verify using the Left Arrow cursor test: moving across
ś,ć, orñnow takes exactly 1 arrow keypress.Save the normalized file as
user_search_clean.json.Verify in the VS Code Find widget that searching for
españolnow successfully matches bothuser_search_nfc.jsonanduser_search_clean.json.
Self-Verification Checklist
Check your normalized asset against these quality criteria:
[ ] Navigating across accented characters (
ñ,ś,ć) with cursor keys takes exactly 1 keypress per character (NFC).[ ] Searching for
españolusing an NFC string matches cleanly in the search widget.[ ] Status Bar confirms
UTF-8encoding andJSONlanguage mode.[ ] Asset is saved as
user_search_clean.json.
Ready to move on?
Mark this lesson complete when you’re ready.