Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Laravel Multi Language Laravel Package

renatomarinho/laravel-multi-language

Laravel Multi Language adds locale-aware routing and translation helpers to Laravel apps, letting you define routes and content per language, switch locales, and generate localized URLs for multilingual sites.

View on GitHub
Deep Wiki
Context7

Getting Started

This package is a 2017-era, low-traffic (23 stars, no dependents) Laravel library for multi-language handling, and its most common day-to-day use is storing translations in the database rather than in resources/lang. Treat it as a small utility to read before adopting — the README and composer.json constraints are the primary source of truth, not blog posts.

Minimal steps:

  1. Check compatibility first. composer require renatomarinho/laravel-multi-language and inspect the resolved version in composer.lock. The last release (2017-09-29) predates Laravel 6+, so on modern Laravel you will likely need --ignore-platform-reqs or a fork with an updated illuminate/support constraint. Confirm the service provider namespace from the package's composer.json before registering anything.
  2. Register the provider. On Laravel 5.5+ check composer.json for extra.laravel.providers first — if absent, add the provider manually to config/app.php and register any facade alias.
  3. Publish assets. Run php artisan vendor:publish --provider="RenatoMarinho\LaravelMultiLanguage\...ServiceProvider". This is typically where the config file and migrations appear. Read the migrations — they tell you the schema (languages, translations, or similar) far faster than the README.
  4. Migrate and seed. php artisan migrate, then either seed languages or use whatever artisan command the package ships. php artisan list filtered by the package vendor prefix is the quickest way to discover available commands.
  5. First use case: create two locales (e.g. en, pt_BR), add a translation key/value through the package's model or API, then confirm trans('your.key') or the package's own helper resolves it instead of falling back to your lang files.

Where to look first: config/ for the table names and default locale, database/migrations/ for the schema, and src/ for the facade/helper methods you'll actually call. Skip the README's marketing prose and read the source; it's a small package.

Implementation Patterns

Database as the translation source of truth. The typical integration is to let this package populate the same key namespace that trans()/__() already use, so application code doesn't change. Wrap __() in a helper only if the package doesn't already hook the translator. Test this early — if it doesn't intercept the translator, you'll need a custom Loader implementation (Illuminate\Translation\FileLoader subclass) to read from the DB.

Locale selection middleware. The usual pattern is a middleware that resolves the locale from, in order: an explicit ?lang= / session value the user picked, the Accept-Language header, then config('app.fallback_locale'). Register it on the web group and call App::setLocale() inside handle(). Keep the middleware in your app, not the package — it's the piece you'll want to customize per project.

Routes grouped per locale. For SEO-friendly URLs, group routes with a {locale} prefix and validate the value against your languages table in a route pattern constraint (->where('locale', 'en|pt_BR|es')). Pair this with a RouteServiceProvider that reads the segment and sets the locale before the controller runs.

CRUD for translations. If you're building an admin translation UI (the main reason to DB-back translations instead of files), generate a resource controller for the package's Translation model. Cache-bust on save — see Gotchas.

Importing existing lang files. A one-off artisan command that walks resources/lang/**/*.php, flattens the arrays with Arr::dot(), and upserts into the translations table is the fastest migration path from file-based translations. Do this once, then commit the seeders, not the language files.

Blade. Look for a directive like @lang(...) or a language switcher component in src/. If none exists, build a small <x-language-switcher> component that iterates the languages table — you'll want your own styling anyway.

Gotchas and Tips

It's abandoned software. Last release 2017, zero dependents. There is no upstream to fix bugs. Budget for either a fork in your composer.json repositories block (type: vcs) or a straight copy of the src/ into your app. For a package this small, vendoring is often faster than fighting version constraints.

Composer/Laravel version conflicts. The illuminate/support constraint is almost certainly ^5.x. On Laravel 8+ this will fail to resolve. Prefer installing from dev-master with an explicit branch alias, or fork and widen the constraint. Never ship --ignore-platform-reqs to production.

Manual provider registration on Laravel 5.4 and earlier. There's no auto-discovery before 5.5. Missing config/app.php entries produce a Target class [...] does not exist or "class not found" error — check the provider string character-for-character; namespace casing matters.

Migrations are published, not run from the package. If you migrate:fresh without re-publishing after an upgrade (or fork), you get schema drift between your DB and the package's expectations. Commit published migrations to version control.

Caching is the classic failure mode. DB-backed translations hit the database on every trans() call unless you cache. Wrap lookups in Cache::rememberForever("translations.{$locale}", ...) and — critically — flush that key whenever a translation row is created, updated, or deleted. Invalidate in the model's saved/deleted events, or via a TranslationObserver, so the admin UI can't leave stale strings in the cache.

Fallback locale behavior is non-obvious. Test explicitly: request a key that exists only in the fallback locale, and a key that exists in neither. In Laravel, a missing key returns the key string itself, which is easy to miss in a UI and looks like a bug.

Testing. Use RefreshDatabase and seed the languages table in setUp(). Assert on App::getLocale() after hitting routes rather than asserting on rendered text, so the test survives translation edits. Add a translation factory if you're writing more than a couple of tests.

Debugging translation misses is much easier with php artisan tinker than request-level debugging: App::setLocale('pt_BR'); trans('your.key'); isolates whether the package's loader is wired correctly, independent of middleware and routing.

Extension points worth knowing: the Translation and Language Eloquent models (override via config if supported), any config key for table names, and the translation loader binding in the service container (app('translation.loader')). If you need custom behavior beyond those — pluralization rules, namespaced groups, per-tenant translations — you're better off writing ~100 lines yourself than extending this package.

Security angle. If the package exposes translation CRUD routes or a language-switching endpoint, verify there's authorization on the admin side and that the locale parameter is validated against the DB (not passed straight to setLocale). An unvalidated locale can leak into redirects and cache keys.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings