阅读文本 / Reading text
This paper uses synthetic samples to demonstrate the processing method. The code has been verified using examples in an isolated environment; this does not guarantee effectiveness for all real files or products. Before processing important files, please retain the original copies and verify them against the boundaries and acceptance criteria outlined in this document.
The term is clearly listed in the glossary, yet the program reports no match. Printing out the string reveals that both sides appear identical. The issue may not lie with the translation itself, but rather with Unicode representation: a character with an accent can be encoded either as a single code point or as a base letter combined with a combining diacritical mark.
first confirms whether it represents a difference or a content discrepancy
performs NFC normalization before comparison, commonly used to align representations that are normatively equivalent. NFKC has a broader scope and collapses certain compatibility characters; while this may suit search requirements, it does not necessarily meet the needs of archival preservation or technical symbol comparison. Do not mistake “easier matching” for “semantic invariance.”
In the synthetic example,
é
The two writing styles should be consistent after NFC; full-width letters and superscript characters, on the other hand, help illustrate the changes that NFKC brings. These are specific examples, not requirements for all items to uniformly adopt one particular form.
uses code to reveal differences that were previously unseen
import unicodedata as ud
composed = "café"
decomposed = "cafe\u0301"
assert composed != decomposed
assert ud.normalize("NFC", composed) == ud.normalize("NFC", decomposed)
fullwidth = "ABC"
assert ud.normalize("NFC", fullwidth) == fullwidth
assert ud.normalize("NFKC", fullwidth) == "ABC"
assert ud.normalize("NFKC", "x²") == "x2"
def term_key(text):
return ud.normalize("NFC", text).casefold()
assert term_key("CAFÉ") == term_key(decomposed)
assert term_key("x²") != term_key("x2")
print([f"U+{ord(c):04X}" for c in decomposed])
The example selected NFC plus for term matching.
casefold
, this is an intentionally constrained matching strategy.
casefold
also produces language-specific folding results, so we cannot simply replace all the original text with the generated keys just because it is convenient.
original text and the matching key are stored separately as
preserves
original_text
, and build another
normalized_key
. The former is used for display, traceability, and review, while the latter is used for retrieval under the current policy. Record the policy name and version so that, when a different rule is adopted in the future, the index can be rebuilt rather than discovering that the original text has already been irreversibly overwritten.
observation
can attempt the actions
should not be done casually
combination of accent differences
performs NFC according to a defined policy
claims that the number of characters is no longer important
full-width/half-width difference
Assess NFKC according to business requirements
directly overwrites the original technical document
case sensitivity
establishes a case-insensitive matching key
converts all displayed text to lowercase
still misses
view code points and actual context
continuously applies replacement rules by chance
normalization does not resolve all cases of “looking the same”
Latin letters that look similar to one another, as well as characters from other scripts, do not necessarily have normative or compatibility equivalence. Zero-width characters, different types of spaces, and OCR systems that mistake letters for digits each require their own diagnostics. In security-sensitive scenarios involving account numbers, file identifiers, and the like, do not treat the terminology-matching examples in this article as a comprehensive solution for protecting against obfuscated characters.
positional tracing also has an easily overlooked point: after normalization, the length may change. Using character offsets from the matching key to trim the original text may result in incorrect segmentation. When highlighting or writing back, one should preserve the mapping of original text segments, or re-locate at the original-text level.
Before handing the issue over to translation, first preserve the evidence.
evaluation
OmniDoc (product entry point)
When working with terminology and translation workflows, it is possible to prepare two Unicode representations of the same term, recording the source text, the strategy, and the target translation. In this way, when inconsistencies are detected, one can distinguish whether the issue lies in input matching or in translation selection, rather than attributing all discrepancies to the translation model.
Reference:
Python unicodedata
。
- 1 -
Updated 2026-10-08