tecnickcom/tc-lib-unicode
tc-lib-unicode is a PHP library for working with Unicode text, offering character data, normalization forms, case mapping, and grapheme-aware string utilities. It helps PHP applications handle multilingual input correctly through a clean object-oriented API.
What the package is. tecnickcom/tc-lib-unicode is a pure-PHP Unicode utility library from the TCPDF author (Nicola Asuni). It sits in the tc-lib-* family (tc-lib-pdf, tc-lib-pdf-font, tc-lib-barcode, tc-lib-unicode-data) and primarily provides Unicode normalization plus string/character helpers backed by bundled data tables. It exists largely so the TCPDF stack can operate without ext-intl.
Architecture fit. Fit is narrow and conditional. It is a good fit if (a) we generate or parse PDFs in the TCPDF lineage, or (b) we must run in environments where ext-intl is unavailable or undesired (shared hosting, distroless/minimal images, locked-down enterprise PHP builds). It is a poor fit as a general-purpose Unicode layer for a modern application: ext-intl (Normalizer, IntlChar, grapheme_*) is C-speed, ships with PHP, and tracks ICU. Adopting this library means deliberately trading performance and ecosystem breadth for portability.
Integration feasibility. Technically straightforward: Composer-installable, PSR-4 autoloaded, small surface area, no service dependencies, no native build step. It can be adopted inside a single bounded context in days. The real constraint is not effort but governance — the package's metadata is not clean enough to wave through.
Technical risk.
tc-lib-* family is generally LGPL-3.0, but the tooling could not assert it. LGPL obligations around static linking, modification, and relinking affect distribution of our product. This must be resolved by legal before any code is merged, not after.composer.lock hash.Key questions for the team.
ext-intl genuinely unavailable in every target deployment, or is this a convenience choice?tc-lib-pdf? If transitive, the decision may already be made for us.Stack fit. Requires PHP with Composer and a reasonably modern runtime; confirm the minimum PHP constraint of the specific tag against our supported matrix before committing. It composes cleanly with any PSR-4 codebase and introduces no framework coupling. It is not a drop-in for ext-intl semantics — the API shape differs, so a wrapper is mandatory regardless.
Recommended pattern: adapter behind a port. Define a first-party UnicodeNormalizerInterface (and, if needed, a CharacterClassifierInterface) in our domain. Provide two implementations: an Intl-backed one used by default, and a TcLibUnicode one selected when extension_loaded('intl') is false or when a config flag forces it. This contains the dependency to one file, makes the library swappable for symfony/polyfill-intl-normalizer or voku/portable-utf8, and converts a vendor decision into a configuration decision.
Migration path. If the library is already present transitively via the TCPDF/PDF stack, do not rip it out — inventory it, pin it, and wrap the call sites we own. If we are introducing it deliberately, start in a non-critical path (display-name normalization, search-input folding) where incorrect output degrades gracefully, and only then consider the document-rendering path where errors are customer-visible.
Compatibility. Verify: minimum PHP version; whether tc-lib-unicode-data is pulled as a separate package (it usually is, and that is a second supply-chain entry to review); presence of any ext-* requirements; PSR-4 namespace stability across minor versions. Pin to an exact version in composer.lock and treat minor bumps as reviewable changes, since data-table updates can alter output for existing stored data.
Sequencing.
ext-intl at our realistic volume; characterize malformed-UTF-8 behavior; diff normalization output against ICU for a sample of our real corpus.Intl implementation first, with no new dependency.tc-lib-unicode implementation as the fallback path; exercise it in CI by running the suite with ext-intl disabled.Maintenance. Low ongoing effort, high concentration risk. One maintainer, infrequent releases, small API. The realistic burden is not patching — it is periodically auditing whether the bundled Unicode data has fallen behind and whether the project is still alive. Budget a recurring quarterly check, and maintain the ability to fork/vendor the package internally; it is small enough that forking is a credible contingency, which materially defuses the bus-factor concern.
Support. Community-only, GitHub issues, no SLA, no commercial backing. Escalation path is "we fix it ourselves." Acceptable for a leaf utility; unacceptable for anything on the critical rendering path without the internal-fork option documented and rehearsed.
Scaling. CPU-bound within PHP workers, no external state, scales horizontally with the app tier. Two watch items: (1) the generated Unicode data tables load into memory per process — measure baseline memory delta under PHP-FPM, and avoid loading them on requests that do not need them; (2) normalization is called per-string, so high-cardinality pipelines should memoize results or normalize at write time rather than read time. There is no shared cache or lock contention to worry about, which is a genuine operational simplification.
Failure modes.
composer update bumps the data package and changes normalization output for already-stored values; pin, and treat data-package bumps as data migrations.Ramp-up. Days, not weeks. The API is small and the concepts are the hard part, not the code: engineers need fluency in normalization forms (NFC/NFD/NFKC/NFKD), code points versus grapheme clusters, and why "string length" is ambiguous in Unicode. Expect at least one real bug from someone applying byte-oriented intuition to a Unicode string. Pair the adoption with a short internal write-up and a handful of property-based tests, and the team will be productive within a sprint.
Bottom line for the decision log. Approve as a conditional, wrapped, pinned fallback dependency for the PDF/rendering context, gated on license clearance and a benchmark spike. Do not approve it as the primary Unicode layer for application-wide string handling.
How can I help you explore Laravel packages today?