Download the PHP package rivalex/lingua without Composer
On this page you can find all versions of the php package rivalex/lingua. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download rivalex/lingua
More information about rivalex/lingua
Files in rivalex/lingua
Package lingua
Short Description Self-hosted Laravel translation manager for the TALL stack: edit, sync, import/export and AI-translate your i18n / l10n language files via a Livewire UI. Database & file drivers, vendor translations, CSV/JSON/XLSX/ODS. A native alternative to laravel-lang and external services.
License MIT
Homepage https://github.com/rivalex/lingua
Informations about the package lingua
**Lingua** is a self-hosted translation management package for Laravel — a native, database-driven alternative to tools like Weblate, Locize, Lokalise, Crowdin, and SimpleLocalize, and a drop-in replacement for `spatie/laravel-translation-loader` and `laravel-lang/common`. If you need to manage translations in a Laravel application without depending on an external SaaS or downloading third-party language packages, Lingua gives you a complete Livewire admin UI to edit, organize, import, export, and synchronize your i18n / l10n strings directly inside your app. Built on the TALL stack (Tailwind, Alpine, Livewire), Lingua stores translations in either your **database** or your native `lang/` **files** — switchable with a single config value. It ships a bundled dataset of 26 locales aligned to Laravel 13 (no `laravel-lang` required), handles published vendor translations safely, supports **CSV, JSON, XLSX, and ODS** import/export with a mandatory dry-run preview, offers full RTL support, and can optionally AI-translate missing strings via Lingua Pro. Built for **Laravel 11–13, Livewire 4, and PHP 8.3+**. [Features](#-features) · [Installation](#-installation) · [Configuration](#-configuration) · [Storage Drivers](#-storage-drivers) · [Artisan Commands](#-artisan-commands) · [Publishing](#-publishing) · [UI Guide](#-ui-guide) · [Import / Export](#-import--export) · [Language Selector](#-language-selector) · [Facade](#-lingua-facade) · [Architecture](#-architecture) · [Lingua Pro](#-lingua-pro)
✨ Features
| Feature | Description |
|---|---|
| Database-backed translations | All translations stored in the database, editable instantly without deployments |
| File-mode driver | Optional file-mode stores translations directly in lang/ PHP/JSON files — no database required |
| Livewire UI | Reactive, real-time language and translation management interface |
| Flux UI components | Modern, accessible UI built with Livewire Flux |
| Bi-directional sync | Push translations to the database or pull them back to local PHP/JSON files |
| Import / Export | Export and import translations as CSV, JSON, XLSX, or ODS; bilingual and multi-locale scopes |
| Bundled translation dataset | 26 locales × 7 groups (5 902 strings) aligned to Laravel 13 — provisioned at locale install-time |
| Rich text support | Translations can be plain text, HTML, or Markdown |
| Language selector | Configurable sidebar, dropdown, modal, or headless language switcher |
| Translation statistics | Per-language coverage with progress bars, group breakdown, and missing-key drill-down |
| Shared navigation menu | Built-in nav bar on all admin pages; active-page highlighting; toggleable |
| Force dark mode | Render Lingua's dark theme regardless of host app / OS color scheme — config or Settings UI |
| DB-persisted settings | Selector mode, flags, nav, editor toolbar managed from the UI |
| Headless language selector | Zero-CSS semantic HTML component for full styling freedom |
| RTL support | First-class right-to-left language handling |
| Vendor translations | Manage package translations alongside your own |
| Authorization gate | Role-based access control via LINGUA_GATE env and Laravel Gates |
| Database-agnostic | Full support for SQLite, MySQL, PostgreSQL, and SQL Server |
| Safe uninstall | lingua:uninstall exports translations before removing tables and published files |
| Lingua Facade | Fluent programmatic API for reading, writing, and managing languages and translations |
| Flexible routing | Route prefix/suffix config, optional gate, layout override, wire:navigate toggle |
| Lingua Pro | Optional add-on: AI translation, translation memory, glossary, usage analytics |
| Fully tested | 780+ tests with Pest, covering commands, Livewire components, Blade, helpers, and facade |
📦 Requirements
- PHP 8.3+
- Laravel 11 | 12 | 13
- Livewire 4.1+
- Livewire Flux 2.12+
Optional:
openspout/openspout— required for XLSX and ODS import/exportrivalex/lingua-pro— AI translation, translation memory, glossary, and analytics
🚀 Installation
1. Install via Composer
2. Run the interactive installer
The installer will:
- Prompt you to choose a storage driver: database (recommended) or file
- Publish
config/lingua.php - Publish and run the database migrations (driver-aware: file mode skips the
language_linestable) - Seed the database with your default language and its bundled translations (database mode)
- Or write default lang/ files (file mode)
After installation, set LINGUA_STORAGE_DRIVER=database (or file) in your .env and run php artisan config:clear.
3. Access the UI
| Page | URL | Route name |
|---|---|---|
| Languages | your-app.test/lingua/languages |
lingua.languages |
| Translations | your-app.test/lingua/translations/{locale?} |
lingua.translations |
| Statistics | your-app.test/lingua/statistics |
lingua.statistics |
| Settings | your-app.test/lingua/settings |
lingua.settings |
| Transfer | your-app.test/lingua/transfer |
lingua.transfer |
⚙️ Configuration
After installation, config/lingua.php gives you full control:
Environment variables
| Variable | Default | Description |
|---|---|---|
LINGUA_STORAGE_DRIVER |
database |
Storage driver: database or file |
LINGUA_GATE |
null |
Laravel Gate name for admin authorization |
LINGUA_CACHE_STORE |
null |
Cache store (null = app default) |
LINGUA_CACHE_PREFIX |
lingua.trans |
Cache key prefix |
LINGUA_FORCE_DARK_MODE |
false |
Force Lingua's dark theme regardless of host app / OS color scheme |
LINGUA_SUPPRESS_PRO_NUDGE |
false |
Hide the Lingua Pro upgrade prompt |
LINGUA_PRO_UPGRADE_URL |
https://lingua.rivalex.dev |
Pro upgrade link shown in admin UI |
LINGUA_EXTENSIONS_ENABLED |
true |
Enable/disable the extension system |
💾 Storage Drivers
Lingua supports two storage backends, selectable at install time or switched later.
database (recommended)
- Translations stored in the
language_linestable (one JSONtextcolumn, all locales per row) - Runtime DB queries cached
rememberForeverper(locale, group)pair; surgical invalidation on save/delete - Full-featured: HTML/Markdown translation types, vendor translation guard, statistics, import/export
- Works with SQLite, MySQL, PostgreSQL, and SQL Server
file
- Reads and writes lang/ PHP/JSON files directly — no
language_linestable required - Lightweight: suitable for simple projects or when a database is unavailable
- Translation types are flattened to plain text when files are written
- Sync buttons (Sync to DB / Sync to Local) are hidden in the UI
lingua:sync-to-localis a no-op unless--forceis passed- Deploy pipelines (Forge / Envoyer / CI) may overwrite lang/ files — coordinate with your deployment strategy
Switching drivers
Or set the env variable directly:
Then run php artisan config:clear.
Options for lingua:storage:
| Option | Description |
|---|---|
--force |
Skip confirmation prompts |
--write-env |
Automatically update LINGUA_STORAGE_DRIVER in your .env file |
--no-migrate |
Skip running migrations when switching to database driver |
File-mode deploy caveat: In CI/CD pipelines, lang/ files are typically checked in to version control. Any translation edited in the Lingua UI will modify those files. Ensure your deployment pipeline does not overwrite them with stale copies. HTML and Markdown translation types will be lost when switching from database to file mode, as file-based drivers store only plain text.
🛠 Artisan Commands
Lingua ships with a complete command suite for terminal-driven language and translation management.
Language management
| Command | Description |
|---|---|
lingua:add {locale} |
Install a new language: creates DB/file record, seeds bundled translations |
lingua:remove {locale} |
Remove a language: deletes record and cleans up storage |
lingua:update-lang |
Re-sync translations for all installed locales |
Note:
lingua:addandlingua:removeare DB-native — they do not uselaravel-lang. The bundled dataset provides translations for 26 locales automatically. Lingua does not require or download any external language packages.
Translation sync
| Command | Description |
|---|---|
lingua:sync-to-database |
Import all local lang/ PHP/JSON files into the database |
lingua:sync-to-local [--force] |
Export database translations to lang/ files (--force overrides file-mode no-op guard) |
Setup & maintenance
| Command | Description |
|---|---|
lingua:install |
Interactive first-time setup wizard |
lingua:storage {driver} [options] |
Switch storage driver between database and file |
lingua:uninstall [options] |
Safely remove Lingua (exports translations first) |
lingua:install
Interactive setup wizard. Prompts for driver selection (arrow-key), publishes config, publishes driver-aware migrations, optionally runs them, and seeds default language data.
lingua:storage {driver}
Switch between database and file storage without data loss. Syncs translations before switching and warns on
HTML/Markdown type-loss when moving to file mode.
| Option | Description |
|---|---|
--force |
Skip confirmation prompts |
--write-env |
Update LINGUA_STORAGE_DRIVER in .env automatically |
--no-migrate |
Skip running migrations (database driver switch only) |
lingua:uninstall
Exports all translations to lang/ files first, then drops the three Lingua database tables and removes published files. Your lang/ directory is always preserved.
| Option | Description |
|---|---|
--force |
Skip confirmation prompts |
--keep-config |
Do not delete config/lingua.php |
--keep-published |
Do not delete published views and translations |
📤 Publishing
Lingua ships several publishable groups so you can override only what you need.
Publish everything at once
Publish individual tags
lingua-config
Publishes the configuration file to config/lingua.php.
Use this when you want to customise routes, middleware, the language selector mode, the rich-text editor toolbar, or any other package option. The file is well-commented and safe to edit — Lingua reads it on every request.
lingua-migrations
Publishes the database migrations to database/migrations/.
Driver-aware: file mode only publishes the languages and lingua_settings table migrations (skips language_lines).
Use this when you need to modify the schema — for example to add indexes or change column types. After publishing, run
php artisan migrate as normal.
Note: The
lingua:installwizard publishes and runs the migrations automatically. Only publish manually if you need to customise the schema before running them.
lingua-translations
Publishes the package's own UI translation strings to lang/vendor/lingua/.
This exposes all the labels, headings, buttons, and messages used in the Lingua admin UI. The admin interface is localised in 9 languages: Arabic, English, Spanish, French, Hindi, Italian, Portuguese, Russian, and Chinese ( Simplified). Override any string to adapt the wording to your project's style.
lingua-views
Publishes all Blade and Livewire views to resources/views/vendor/lingua/.
The full view tree is:
Tip: Only publish views you intend to change. Unpublished views are served directly from the package and will receive upstream updates automatically.
Re-publishing after upgrades
After updating Lingua via Composer, re-publish any tags that may have changed:
The --force flag overwrites existing files. Omit it for views and config so your local customisations are not lost.
Note: Compiled CSS and JavaScript assets are served directly from the package via Lingua's own asset route (
lingua.assets). Publishing assets topublic/is not required.
🖥 UI Guide
Languages page — /lingua/languages
The languages page is your control center for installed locales.
Available actions:
- Add a language — choose from 26 bundled locales; the record is created and bundled translations are seeded automatically
- Remove a language — confirmation modal prevents accidental deletion; the default language is protected
- Set the default language — one click sets the new application default
- Reorder languages — drag-and-drop to control display order across the UI
- Sync to database — import all local lang/ files into the database (database mode only)
- Sync to local — export database translations back to lang/ files (database mode only)
- Update translations — re-sync strings for all installed locales
Each language row shows the completion percentage and a count of missing translations so you can prioritise your translation effort. Sync buttons are hidden in file mode.
Translations page — /lingua/translations/{locale?}
Manage individual translation strings with a filterable, paginated table.
Available actions:
- Search by key, group, or value
- Filter by locale, group, or translation type (text / HTML / Markdown)
- Show only missing translations for a locale to focus your translation work
- Create new custom translation entries
- Edit any string inline — the rich-text editor activates automatically for HTML and Markdown types
- Delete translations globally or for a specific locale only
- Copy the translation key to clipboard with one click
The filter bar is sticky with a configurable top offset (ui.sticky_top) for apps with a fixed header.
Statistics page — /lingua/statistics
The statistics page gives you a bird's-eye view of your translation coverage.
What it shows:
- Per-language coverage — progress bar for each installed locale with the percentage of translated keys and a count of missing ones
- Group breakdown — table showing how many keys are translated per locale across each translation group
- Missing-key drill-down — click the missing count for any language to expand a list of untranslated keys with direct links to the translation editor
- Vendor toggle — include or exclude vendor translations from all statistics with a single switch
Settings page — /lingua/settings
The settings page lets you configure Lingua's UI behaviour without touching config files or redeploying.
What you can configure:
- Selector mode — choose between
sidebar,modal,dropdown, orheadless - Flag icons — toggle country flag icons next to language names
- Navigation menu — enable or disable the shared nav bar shown on all Lingua pages
- Routing — toggle
wire:navigate, set sticky bar top offset (ui.sticky_top), configure extra route parameters - Appearance — force Lingua's dark theme on regardless of the host app / OS color scheme (
dark_mode.force) - Editor toolbar — enable or disable individual toolbar buttons (bold, italic, headings, code-block, …) across 3 groups (13 toggles total)
Settings are stored in the lingua_settings database table and take effect immediately. Values from config/lingua.php
serve as fallback when no database setting has been saved.
Transfer page — /lingua/transfer
The transfer page provides file-based import and export of translation data.
- Export — select a scope and format, download the file
- Import — upload a file, review a dry-run diff, confirm to commit
See Import / Export for full details.
RTL / LTR text direction
Some languages (Arabic, Hebrew, Persian, Urdu, …) are written right-to-left. Lingua stores the text direction for every
installed language and exposes it via Lingua::getDirection(). Add dir and lang attributes to your main Blade
layout:
Lingua::getDirection() returns 'rtl' for right-to-left languages and 'ltr' for all others. Pass an explicit locale
when needed:
Tailwind CSS
The dir attribute on <html> activates Tailwind's built-in rtl: variant automatically:
Checking direction in Blade
Note:
Lingua::getDirection()defaults to'ltr'if the locale is not found, so it is always safe to call even before any language is installed.
Flux UI Assets
Lingua uses Flux UI for its interface. Include Flux assets in your application layout:
📦 Import / Export
The Transfer page (/lingua/transfer) provides Livewire-powered export and import of translation data.
Export
Three export scopes:
| Scope | Description |
|---|---|
| Bilingual | Source strings + one target locale (two columns) |
| Multi-locale | Source + all installed locales (one column per locale) |
| JSON-native | Raw key/value JSON without a source column |
Four export formats:
| Format | Dependencies |
|---|---|
| CSV | Built-in — no extra packages |
| JSON | Built-in — no extra packages |
| XLSX | Requires openspout/openspout |
| ODS | Requires openspout/openspout |
Formula-injection guard: cells starting with = + - @ are automatically prefixed with ' in all spreadsheet formats to
prevent formula execution.
Import
The import flow is a two-step process:
- Upload — select your file; Lingua runs a dry-run analysis and shows a preview: create / update / skip / error counts and a capped row-by-row diff
- Review & confirm — inspect the diff, then commit when ready
Import behavior:
- Commit is transactional in database mode (all-or-nothing) and sequential in file mode
- Vendor translations are protected — import cannot create or delete vendor-namespaced keys
- Bilingual single-column fallback: when a bilingual file has exactly one data column and the locale code doesn't
exactly match the header (e.g.
it_ITvsit - Italian), Lingua uses that column automatically
🌐 Language Selector
Embed a language switcher anywhere in your Blade layouts:
Control the display mode via config or inline props:
The selector reads the active mode and flag preference from the database (configurable in the Settings page). The
:mode and :show-flags props override the database setting for a specific instance.
Headless mode
The headless selector renders zero CSS and no framework-specific markup — just semantic HTML that you style entirely with your own CSS or utility classes.
Named slots:
Override individual language items using the $item slot (receives the Language model):
Override the currently selected language with the $current slot (falls through to $item if not provided):
*CSS targeting API (`data-lingua-` attributes):**
| Attribute | Element |
|---|---|
data-lingua-selector |
Root <nav> element |
data-lingua-list |
The <ul> language list |
data-lingua-item |
Each <li> language entry |
data-lingua-active |
The <li> of the active language |
data-lingua-button |
The <button> inside each <li> |
data-lingua-name |
Language English display name <span> |
data-lingua-native |
Language native name <span> |
data-lingua-code |
Language ISO code <span> |
Plain CSS example:
Tailwind CSS example:
💎 Lingua Facade
Lingua ships a static Lingua facade that gives you programmatic access to language and translation data from anywhere
in your application.
Locale helpers
Availability checks
Language models
Translation statistics
Reading translations
Writing & deleting translations
Vendor translations
Language lifecycle
Note:
addLanguage()andremoveLanguage()manage the Language record and storage. Use the Artisan commandslingua:add/lingua:removefor the fully orchestrated operation (record + storage + cache invalidation).
Sync
Note:
Lingua::optimize()is deprecated — surgical cache invalidation per(locale, group)pair makes it unnecessary.
🏗 Architecture
How translations are stored
In database mode, Lingua stores translations in the language_lines table. Each row holds all locales in a single
JSON text column, eliminating the need for per-locale rows:
This design allows instant locale switching at runtime without additional queries per language.
Storage abstraction
Lingua defines a TranslationRepository contract with two implementations:
| Implementation | Driver | Description |
|---|---|---|
DatabaseRepository |
database |
Reads/writes language_lines; supports HTML/Markdown types, vendor guard, statistics |
FileRepository |
file |
Reads/writes lang/ PHP/JSON files; types flattened to plain text |
Bundled translation dataset
Lingua ships a bundled dataset of 5 902 strings across 26 locales and 7 translation groups (auth,
pagination, passwords, validation, http-statuses, errors, notifications), aligned to Laravel v13.14.0. The dataset
is read by BundledTranslationSource at locale install-time and merged into the database or lang/ files during
syncToDatabase() and installLocale(). Notification strings are projected into lang/{locale}.json by
NotificationProjector.
Bundled locales: Arabic, German, English, Spanish, Persian, French, Hebrew, Hindi, Indonesian, Italian, Japanese, Korean, Malay, Norwegian Bokmål, Dutch, Polish, Portuguese, Brazilian Portuguese, Romanian, Russian, Swedish, Thai, Turkish, Ukrainian, Vietnamese, Chinese (Simplified).
This replaces the need for laravel-lang or any external language package.
Translation loading at runtime
LinguaManager extends Laravel's built-in FileLoader and is registered via extend() on the translation.loader
binding. At runtime it merges:
- File-based translations from
lang/(viaFileLoader) - Database translations via the
Dbloader (Rivalex\Lingua\Database\Db)
Database translations take precedence over file translations. All translations are cached per (locale, group) pair via
Cache::rememberForever. Cache is invalidated surgically on model save/delete — no full-cache flush required.
Translation types
Each string is classified automatically during sync:
| Type | Use case | Auto-detected when… |
|---|---|---|
text |
Plain strings, labels, messages | Default |
html |
Rich content with HTML markup | String contains HTML tags |
markdown |
Markdown-formatted content | String parses as Markdown |
The type drives which editor is shown in the Translations UI. Types are preserved in database mode; flattened to text
in file mode.
Bi-directional sync
sync-to-database— reads every locale file (core + vendor packages) and upserts rows inlanguage_lines, auto-creatinglanguagesrecords for any new locales discovered. The default locale is processed first and its keys form the reference set.sync-to-local— reads every row inlanguage_linesand writes locale-specific PHP/JSON files back tolang/, including vendor subdirectories.
Locale middleware
LinguaMiddleware is automatically appended to the web middleware group on boot. It:
- Reads the active locale from the session (
lingua.session_variable) - Falls back to the database default language
- Calls
app()->setLocale()and conditionally writes the locale to session (avoids dirty session on every request)
Authorization
When LINGUA_GATE is set, can:{gate} middleware is added to all admin routes. Configure the gate in
AuthServiceProvider or AppServiceProvider:
💎 Lingua Pro
Lingua Pro is an optional add-on that extends the base package with premium features:
- AI-powered translation — DeepL, Anthropic, and Google Translate integrations
- Translation memory — avoid re-translating identical or similar strings
- Glossary — enforce consistent terminology across your project
- Usage analytics — track which strings are most accessed
Requires a Lingua Pro license. See lingua.rivalex.dev for details.
To suppress the upgrade nudge in the admin UI (e.g. when Lingua Pro is installed):
🧪 Testing
The suite uses Pest v4 and covers:
- All Artisan commands — happy paths, driver-aware behavior, and error handling
- All Livewire components — rendering, interactions, and event dispatching
- Bi-directional sync operations
- Import and export (all formats, all scopes, dry-run and commit flows)
- All Blade components
- Helper functions
- The Lingua facade
780+ tests total (2 skipped without openspout/openspout: XLSX and ODS integration).
🤝 Contributing
Contributions are welcome! Please open an issue first to discuss your proposed change, then submit a PR. Run
composer lint before pushing.
📄 License
The MIT License (MIT). Please see LICENSE.md for more information.
All versions of lingua with dependencies
ext-dom Version *
ext-libxml Version *
illuminate/contracts Version ^11.0 || ^12.0 || ^13.0
league/html-to-markdown Version ^5.1
livewire/flux Version ^v2.12.0
livewire/livewire Version ^v4.1.0
outhebox/blade-flags Version ^1.6
spatie/laravel-package-tools Version ^1.92