libicu clib

ICU (International Components for Unicode) for PascalAI. Unicode normalization, locale-aware collation and sorting, date/number formatting, transliteration between scripts, text boundary detection, charset encoding conversion — the gold standard for i18n.

ppm install libicu
System dependency: requires libicu-dev (Ubuntu/Debian: sudo apt install libicu-dev). On macOS: brew install icu4c. On Windows: download the ICU binary distribution from icu.unicode.org.

Overview

ICU is the Unicode Consortium's reference implementation for internationalization. It handles the full complexity of human language that ASCII-era string libraries ignore: Turkish dotless i, German umlaut collation, right-to-left Arabic text, Japanese word boundaries, French date formats, and the thousand other cases where naive string handling produces wrong results for non-English users.

The PascalAI libicu binding wraps ICU's C API in a clean, resource-safe interface. All opaque handle types (collators, formatters, break iterators, converters) are allocated with a New* function and released with the corresponding Free* function.

Quick Start

Normalization and Case

uses libicu;

{ Normalize to NFC (standard form for storage and comparison) }
var s := Normalize('café', nfNFC);

{ Locale-aware case (Turkish 'I' -> 'i' with dot, not plain 'i') }
WriteLn(ToLower('ISTANBUL', 'tr_TR'));   { 'istanbul' }
WriteLn(ToLower('ISTANBUL', 'en_US'));   { 'istanbul' }
WriteLn(ToUpper('istanbul', 'tr_TR'));   { 'ISTANBUL' with dotted I }

Locale-Aware Sorting

uses libicu;

var col := NewCollator('de');  { German collation rules }
var words := ['Arger', 'Apfel', 'Zebra', 'ahnlich'];
SortStrings(col, words);
{ Result: ['ahnlich', 'Apfel', 'Arger', 'Zebra'] -- a-umlaut sorts near a }
FreeCollator(col);

Date and Number Formatting

uses libicu;

var dateFmt := NewDateFormat(dsMedium, dsShort, 'fr_FR');
WriteLn(FormatDate(dateFmt, 1700000000000));  { '14 nov. 2023, 22:13' }
FreeDateFormat(dateFmt);

var numFmt := NewCurrencyFormat('de_DE', 'EUR');
WriteLn(FormatNumber(numFmt, 1234567.89));   { '1.234.567,89 EUR' }
FreeNumberFormat(numFmt);

API Reference

Normalization

ICU supports four Unicode normalization forms. NFC (Canonical Decomposition followed by Canonical Composition) is the standard form for storage and string comparison. NFD decomposes characters into base + combining marks. NFKC/NFKD additionally fold compatibility characters (e.g. ligatures, half-width katakana) into their canonical equivalents.

FunctionDescription
Normalize(s, form)Return s in the given normalization form; form is one of nfNFC, nfNFD, nfNFKC, nfNFKD
IsNormalized(s, form)Return True if s is already in the given normalization form (fast check, no allocation)

Case Conversion

FunctionDescription
ToUpper(s, locale)Locale-aware uppercase conversion; handles Turkish dotted I, Greek final sigma, etc.
ToLower(s, locale)Locale-aware lowercase conversion; pass an empty string for the default locale
ToTitle(s, locale)Title-case conversion (first letter of each word uppercased) following Unicode word-break rules for the locale
CaseFold(s)Locale-independent case folding for case-insensitive comparison; more aggressive than ToLower

Collation

FunctionDescription
NewCollator(locale)Create a collator for the given locale string (e.g. 'de', 'zh_CN', 'es_419'); returns a collator handle
FreeCollator(col)Release a collator handle and its associated resources
Compare(col, a, b)Compare two strings using locale collation rules; returns -1, 0, or 1
SortStrings(col, arr)In-place sort of a string array using the collator's ordering; stable sort
GetSortKey(col, s)Return a byte array sort key for s; memcmp on sort keys gives the same order as Compare

Date Formatting

FunctionDescription
NewDateFormat(dateStyle, timeStyle, locale)Create a date/time formatter; styles are dsNone, dsShort, dsMedium, dsLong, dsFull
NewDateFormatPattern(pattern, locale)Create a formatter with an explicit ICU skeleton pattern (e.g. 'yyyy-MM-dd HH:mm')
FreeDateFormat(fmt)Release a date format handle
FormatDate(fmt, epochMs)Format a Unix timestamp (milliseconds since epoch) as a locale string
ParseDate(fmt, s)Parse a locale-formatted date string and return a Unix timestamp in milliseconds
FormatRelativeTime(locale, diffSec)Format a signed seconds offset as a relative string like '3 hours ago' or 'in 2 days'

Number Formatting

FunctionDescription
NewNumberFormat(locale)Create a decimal number formatter for the given locale; handles decimal separators, grouping, etc.
NewCurrencyFormat(locale, currency)Create a currency formatter; currency is a 3-letter ISO 4217 code (e.g. 'EUR', 'JPY')
NewPercentFormat(locale)Create a percentage formatter that multiplies by 100 and appends the locale's percent symbol
FreeNumberFormat(fmt)Release a number format handle
FormatNumber(fmt, value)Format a Float value as a locale string using the formatter's rules
ParseNumber(fmt, s)Parse a locale-formatted number string and return a Float

Transliteration

Transliterators convert text between scripts or apply Unicode transformations. Common IDs: 'Latin-Cyrillic', 'Cyrillic-Latin', 'Any-Latin', 'Latin-Arabic', 'Hiragana-Katakana', 'NFD; [:Mn:] Remove; NFC' (strip all accent/combining marks). Call ListTranslitIDs to enumerate all available transforms.

FunctionDescription
NewTranslit(id)Create a transliterator from an ICU transform ID string; returns a translit handle
FreeTranslit(t)Release a transliterator handle
Transliterate(t, s)Apply the transform to string s and return the result
ListTranslitIDs()Return a List of all registered transform IDs available in the current ICU installation

Text Boundary Detection

FunctionDescription
NewWordBreaker(locale)Create a word-boundary iterator for the given locale; aware of CJK, Thai, and other non-space-delimited scripts
NewSentenceBreaker(locale)Create a sentence-boundary iterator; handles abbreviations, ellipses, and quotation marks correctly
NewLineBreaker(locale)Create a line-break opportunity iterator for text layout and wrapping
FreeBreakIter(bi)Release a break iterator handle
BreakText(bi, s)Return a List of substrings split at each boundary position for the given text
CountWords(locale, s)Convenience function returning the number of words in s using locale word-break rules

Encoding Conversion

FunctionDescription
NewConverter(fromEnc, toEnc)Create a charset converter between two encoding names (e.g. 'windows-1252' to 'UTF-8')
FreeConverter(cv)Release a converter handle
BytesToUTF8(cv, bytes)Convert a byte array in the source encoding to a UTF-8 string using the converter
UTF8ToBytes(cv, s)Convert a UTF-8 string to a byte array in the target encoding using the converter
DetectCharset(bytes)Heuristically detect the charset of a raw byte array; returns a TCharsetMatch with Name and Confidence (0.0–1.0)

Locale Information

FunctionDescription
GetLocaleInfo(locale)Return a TLocaleInfo record with DisplayName, Language, Country, Script, and Variant fields
ListLocales()Return a List of all locale identifiers available in the current ICU data file
DefaultLocale()Return the ICU default locale string for the current process (e.g. 'en_US')

IDNA / Punycode

IDNA (Internationalized Domain Names in Applications) converts Unicode domain names to their ASCII-compatible encoding for DNS lookup. Example: 'münchen.de''xn--mnchen-3ya.de'.

FunctionDescription
DomainToASCII(domain)Convert a Unicode domain name to its ACE/Punycode form for DNS queries (e.g. 'münchen.de''xn--mnchen-3ya.de')
DomainToUnicode(domain)Convert an ACE/Punycode domain back to its Unicode display form (e.g. 'xn--mnchen-3ya.de''münchen.de')