See why two identical-looking strings never match, across NFC, NFD, NFKC and NFKD
| Form | Result | UTF-16 | UTF-8 | vs input | Code points |
|---|
The Japanese kana "が" can be written two ways: as the single character U+304C, or as "か" U+304B followed by the combining voiced mark U+3099. They look identical on screen but are different strings, so a plain comparison or search will not match them. This is why file names containing voiced kana can sort or search inconsistently on macOS.
Unicode defines normalization forms to reconcile this. NFC composes toward the single character; NFD decomposes. The web and most protocols assume NFC, so normalizing incoming strings to NFC before storing or comparing them is the practical default.
The forms with a K apply compatibility decomposition. Full-width "A" becomes "A", half-width kana "ガ" becomes "ガ", and the enclosed "㈱" becomes "(株)". This is useful for search keys, but it is lossy: you cannot recover the original spelling. Applying it to display strings destroys the intended appearance.
In short, NFC makes the same character have one representation, while NFKC makes different characters compare as equal. Use NFC for stored values and NFKC for search indexes.
| Input | NFC | NFD | NFKC |
|---|---|---|---|
| が (precomposed) | が (1 char) | か + mark (2 chars) | が (1 char) |
| ガ (half-width kana) | ガ (stays 2 chars) | ガ (stays 2 chars) | ガ (1 char) |
| A (full-width) | A | A | A (half-width) |
| ㈱ | ㈱ | ㈱ | (株) |
Normalization uses the browser's built-in String.prototype.normalize. Nothing you type is sent to a server.
A character such as が can be a single code point U+304C or か U+304B plus the combining mark U+3099. They render the same but are different strings, so a plain comparison fails. Normalizing both to NFC makes them equal.
Use NFC for values you store or display. NFKC folds full-width, half-width and enclosed characters together, which suits search indexes but loses the original spelling.
No. Compatibility decomposition discards information. Once ㈱ becomes (株) there is no way to tell which one was written. Keep the original string separately if you need it back.
No. Normalization uses the browser built-in String.prototype.normalize, and nothing you type leaves the page.