krinkle/intuition
Intuition is a PHP internationalization library for Wikimedia and Toolforge developers, providing message translation, language negotiation, and a simple API to localize tool interfaces into hundreds of languages using community-maintained message files.
Architecture fit. Intuition is a standalone, framework-agnostic localisation runtime — a message-catalog loader plus a formatter — not a Laravel translation driver. It does not implement Illuminate\Contracts\Translation\Loader or decorate Translator, ships no service provider, no config file, and no Blade/__() bridge. Its model is domain → locale → JSON message file (i18n/messages-en.json), with a fallback chain, MediaWiki-style {{PLURAL:$1|…}} / {{GENDER:…}} syntax, $1-style positional parameters, qqq (message documentation) and qqx (key-as-value debug) pseudo-locales, and autonym/RTL metadata. That is a genuinely different architecture from Laravel's lang/{locale}/*.php + :attribute placeholders + | pluralisation.
Where it fits well: platforms hosting many independently-translated "tools"/tenants with per-domain catalogs, and any roadmap that involves translatewiki.net-style volunteer translation. Where it does not fit: a conventional single-tenant SaaS where Laravel's native translator plus laravel-lang and a DB-backed loader already covers the need.
Integration feasibility. Composer-installable, MIT, PHP-only, minimal dependency surface. Two concrete friction points to verify in a spike rather than assume: (1) the PHP version constraint of the current tag versus your runtime (older tags predate modern PHP), and (2) autoloading — the class has historically lived in the global namespace, which creates collision risk and argues for wrapping it behind your own interface instead of calling it directly. Intuition also carries opinions you must actively disable: it reads ?uselang= from the request, persists a language cookie, and can emit its own language-selector markup. All three conflict with Laravel's session/CSRF middleware and with a single, centrally-negotiated locale pipeline.
Technical risk. Medium-to-high, concentrated in three areas. Bus factor: 39 stars and effectively zero Packagist dependents means the real consumption is via git submodules inside Wikimedia Toolforge, not the Composer ecosystem — so there is little external bug-finding, no Laravel community familiarity, and no Stack Overflow substrate. Assume one primary maintainer. Dual source of truth: running Laravel's translator and Intuition side by side will drift; the message file formats are not interchangeable, so you cannot share catalogs without a conversion step. Output safety: Intuition returns raw strings and performs positional substitution without escaping; safe rendering depends entirely on the caller. Interpolating user input into an Intuition message and echoing it unescaped is a straightforward XSS path, and it bypasses Blade's {{ }} guarantee. Content licensing: the code is MIT, but imported message catalogs from translatewiki contributors typically carry CC-BY-SA-style terms — verify provenance before vendoring.
Key questions.
qqq documentation workflow) actually on the roadmap, or is this professional/agency translation? If the latter, this library's main differentiator is irrelevant.Accept-Language?Stack fit. Treat Intuition as a bounded-context library, not an application-wide i18n layer. Three viable shapes, in ascending cost:
__(), validation messages, pagination and Blade directives all keep working. Use Intuition solely to parse existing Wikimedia-format catalogs, exporting them one-way into lang/{locale}.json at build time. No runtime dependency, no cookie conflicts, trivially reversible.?uselang= handling, drive setLang() from your negotiated locale, and expose it through a thin Translator decorator or a @intuition('key') Blade directive. Own the escaping at that boundary.Migration path. Inventory and classify strings first (UI chrome vs. user content vs. validation). Pick one authoring source of truth and make the other direction read-only — bidirectional sync is the failure mode that kills these projects. Then bridge the syntax gap: flatten {{PLURAL:}}/{{GENDER:}} to Laravel's pluraliser where expressible, and keep an Intuition-backed formatter for the locales where it isn't. Only after that, retire any Intuition-driven cookie/query locale switching in favour of your existing middleware.
Compatibility. Four checks before committing: PHP constraint of the target tag; global-namespace class collision (wrap it); locale-code normalisation — MediaWiki-style codes (en-gb, zh-hans) will not match your en_GB/zh_Hans and a silent English fallback is the likely symptom of a mismatch, so build an explicit mapping table; and whether the bundled front-end assets are needed at all, since they are jQuery-era and may be dead weight.
Sequencing. One-week spike (PHP/autoload verification, one locale end-to-end, plural and RTL smoke test) → adapter plus a conformance test suite over every locale you intend to ship (1–2 weeks) → pilot on a single low-traffic surface → full rollout. Gate the whole thing on the translatewiki question: if the answer is no, stop at shape A or drop the dependency entirely in favour of spatie/laravel-translation-loader.
Maintenance. Low release cadence and single-maintainer risk mean you should plan to vendor or fork, and to keep the integration surface small enough that replacement is a one-file change. There is no Laravel-ecosystem alignment to lean on — no upgrade guides, no framework-version support matrix, no deprecation path. Budget a modest recurring allowance for upstream review rather than assuming passive stability.
Support. No commercial support; upstream help is GitHub issues and Wikimedia Phabricator. Nobody on a typical Laravel team will have encountered this library, so knowledge must be built internally and written down: key-naming convention, "how to add a language," fallback-chain behaviour, escaping rules. This documentation is the actual deliverable that makes the dependency safe.
Scaling. Catalogs are file-per-locale-per-domain, resolved and parsed per request. Fine at small and medium scale; at many locales × domains you will see repeated stat/parse work and should resolve the fallback chain once and cache the composite catalog (opcache or a Laravel cache layer keyed by domain+locale). Also ensure any full-page cache keys include the resolved locale, or localized variants will bleed across users.
Failure modes.
en, and log missing-key hits outside production.uselang override → cache fragmentation or, worse, cache poisoning when the cache key ignores locale.Ramp-up. Roughly one to two days for a mid-level developer to become productive with the API itself; the real cost is the translation workflow — qqq documentation conventions, the fallback chain, and the catalog-to-Laravel conversion — which is where the schedule risk sits.
How can I help you explore Laravel packages today?