Unicode Tokeniser

What it is

A Unicode tokeniser determines token boundaries by consulting Unicode character properties — the officially assigned category, script, and breaking behaviour of every code point — rather than pattern-matching on a fixed ASCII character set. The governing specification is UAX #29 (Unicode Standard Annex 29, Unicode Text Segmentation), which defines a state-machine algorithm for locating word boundaries in any language the Unicode standard covers.

The practical consequence: a Unicode tokeniser that has never been told anything about Thai, Arabic, or Devanagari still applies correct boundary rules for those scripts, because the rules are derived from the character database, not from hand-written per-language patterns.

How it works

Unicode assigns every code point a General Category — a two-letter code that classifies its broad function:

Category code Name Examples
L* Letter a, é, , ش, α
N* Number 3, ³, ٤
P* Punctuation ., , «,
Z* Separator space (U+0020), line separator (U+2028)
S* Symbol $, ©,

UAX #29 builds on these categories and script-level properties to define word boundary rules — 23 numbered rules (WB1–WB999) applied in priority order. Key rules handle:

  • MidLetter sequences — an apostrophe or middle dot between two letters is not a boundary (it's stays intact via WB6/WB7; · in Catalan col·legi similarly)
  • Numeric sequences — digits, commas, and periods inside a number run are not boundaries ($3,999.99 is one token)
  • Extend and Format characters — combining marks, zero-width joiners, and variation selectors attach to the preceding character rather than splitting (café is one token even if decomposed as cafe + combining acute)
  • Script-specific handling — Katakana runs stay together; emoji with skin-tone modifiers form single tokens via ZWJ sequences

The algorithm consumes the string left to right, maintaining a small state context to implement look-ahead rules (WB6 and WB7 both require checking the character after the potential boundary before deciding).

Example

Input: "Héllo, 日本語 and 3.14!"

Tokeniser Tokens
ASCII punctuation split Héllo, 日本語 and 3, 14
Whitespace "Héllo,, 日本語, and, 3.14!"
Unicode (UAX #29) Héllo, ,, 日本語, and, 3.14, !

The ASCII split mishandles the decimal point by treating . as a boundary inside 3.14. The whitespace tokeniser leaves the comma and exclamation mark glued to adjacent tokens. The Unicode tokeniser emits clean word and number tokens, and correctly treats the unspaced Japanese string 日本語 as a single token — full word segmentation for CJK requires a separate dictionary-based segmenter chained after Unicode tokenisation.

Variants and history

UAX #29 was first published with Unicode 4.0 (2003) and has been revised with each major Unicode release to cover new scripts and emoji behaviour.

ICU BreakIterator (International Components for Unicode) is the canonical reference implementation. It exposes word, sentence, line, and grapheme-cluster break iterators through C++, Java, and — via bindings — Python and other languages. Any implementation claiming UAX #29 conformance is measured against ICU’s behaviour.

Lucene’s Standard Tokeniser (introduced in Lucene 3.1) replaced the earlier Classic Tokeniser with a UAX #29-compliant implementation generated from the rule table using JFlex. It is the default tokeniser in Elasticsearch, OpenSearch, and Solr, and updates with each Lucene release as new Unicode versions ship.

Solr’s ICUTokenizerFactory uses ICU4J directly rather than JFlex-generated code, offering stricter conformance and better handling of edge cases around combining characters and script-mixing.

When to use it

A Unicode tokeniser is the correct default for any pipeline that may encounter text outside the ASCII range:

  • Multilingual search indices where documents arrive in mixed scripts. A single UAX #29 pass handles Latin, Cyrillic, Greek, Arabic, Hebrew, and Indic scripts without per-language configuration.
  • User-generated content — social media, product reviews, support tickets — where script mixing and emoji are routine.
  • Elasticsearch and OpenSearch deployments — the Standard Analyser’s built-in tokeniser is UAX #29. Switching to Classic or a punctuation tokeniser for performance trades correctness on non-ASCII input.

Limitations: UAX #29 does not segment CJK languages at the word level — it treats contiguous Han, Hiragana, or Hangul runs as single tokens. Word-level segmentation for those scripts requires a dedicated dictionary segmenter (Lucene’s CJKAnalyzer, Kuromoji for Japanese, Nori for Korean) chained after Unicode tokenisation. UAX #29 is also a word-boundary algorithm, not a linguistic analyser — it does not handle English contractions with the precision of a language-specific word tokeniser.

See also