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 Translatable And Injectable Laravel Package

creativeorange/laravel-translatable-and-injectable

Add translatable attributes to Laravel Eloquent models and inject dynamic values into translation strings at runtime, so locale-aware text can include model data, placeholders, or custom variables without hardcoding.

View on GitHub
Deep Wiki
Context7

Getting Started

creativeorange/laravel-translatable-and-injectable combines the familiar "one JSON column, many locales" model (à la spatie/laravel-translatable) with placeholder injection, so a single stored string such as "Hi :name, your order :ref shipped" can be rendered with per-request values.

Minimal steps:

  1. composer require creativeorange/laravel-translatable-and-injectable
  2. Open the package's composer.json first — v3.0.1 is a packaging-only release (PR #2 touched composer.json), so the illuminate/Laravel version constraints are the single most important thing to verify before you commit to v3. Confirm your app version is inside those constraints; if not, stay on the 2.x line.
  3. Publish any package config if the service provider exposes it (php artisan vendor:publish --provider="Creativeorange\...\ServiceProvider"), then check config/app.php for locale and fallback_locale.
  4. Add the package trait to a model and declare the translatable attributes, e.g. protected $translatable = ['name', 'description'];. The backing columns must be json (MySQL 5.7+/Postgres) or text.
  5. First real use case: an editable CMS field — a marketing banner or product description authored per locale, with a :customer_name or :discount placeholder injected at render time rather than string-concatenated in Blade.

Implementation Patterns

Model-level translation with injection. The core workflow is write-once, render-many:

$product->setTranslation('description', 'en', 'Hi :name, the :product is back in stock.');
$product->setTranslation('description', 'nl', 'Hallo :name, de :product is weer op voorraad.');

echo $product->translate('description', ['name' => $user->first_name, 'product' => $product->sku]);

Wrap this in a small presenter/view-model rather than calling translate() from controllers — you will want a single place to default the injection payload (e.g. always pass name and app_url).

Form + validation workflow. Editing translations usually means an array-shaped form. Validate with 'name.*' => ['required', 'string', 'max:255'] and loop config('app.locales') when building the inputs, then setTranslations() per attribute on save. Keep the locale list in a config file, not hard-coded in views.

Blade usage. Expose a computed accessor (getDescriptionAttribute()) that calls translate() with a default payload, so templates stay {{ $product->description }}. For anything user-supplied, escape at the template: {!! nl2br(e($product->translate('description', $payload))) !!}.

Seeding and factories. Seed the source locale only; let the fallback chain handle the rest during development. Define a factory state per locale so tests can assert both the happy path and the fallback path.

Integration tips. If you already use spatie/laravel-translatable, do not put both traits on the same model — pick one per model. When exposing models through an API, be explicit about whether toArray() returns the resolved translation or the raw locale map; wrap in an API Resource to control it.

Gotchas and Tips

  • The v3.0.1 release is packaging-only. PR #2 edited composer.json. That usually means widened or narrowed Laravel/illuminate constraints. Diff it (https://github.com/creativeorange/laravel-translatable-and-injectable/compare/v3.0.0...v3.0.1) before trusting a green composer update, and pin with ^3.0 rather than *. No migrations or code changes should be required, but if the constraint narrowed, composer update will silently keep you on 3.0.0 — check composer show afterwards.
  • Placeholder syntax is not Laravel's. This package's injection is separate from __()/trans(). Don't nest a :attribute placeholder inside a string that also passes through trans() — you'll get double replacement or a leaked placeholder in production.
  • Injection output is not escaped. If a value comes from user input, escape it yourself. This is the most likely XSS vector with any injection-style translator.
  • Locale key drift. Keys must match your configured locale codes exactly (en vs en_US vs en-GB). A mismatched key fails silently into the fallback rather than throwing — dump the raw JSON column ($model->getRawOriginal('name')) when a translation "doesn't appear."
  • Fallback masks missing data. Great in dev, dangerous in prod: a missing nl translation renders English and nobody notices. Add a test or a lint command that asserts every configured locale has a non-empty value for required attributes.
  • JSON querying has a floor. Filtering on whereJsonContains requires MySQL 5.7+/Postgres/SQLite 3.38+; on MariaDB and older MySQL the semantics differ. If you need searchable translations, denormalise the primary locale into a plain column.
  • Casts conflict. Don't add the attribute to $casts as array/json alongside the trait — the trait expects to own the serialisation. Also ensure the attribute isn't in $hidden/$appends inconsistently across the two.
  • Extension points. The trait's translate/resolve methods are the natural override surface: subclass or re-trait to add caching, a per-tenant payload resolver, or logging of unresolved placeholders. Prefer that over forking the package — v3 is still moving and forks will diverge.
  • Debug checklist for a blank/injected-wrong string: (1) is the column actually json? (2) does the raw value contain the locale key? (3) does your injection array key match the placeholder exactly, including case? (4) is the fallback locale returning something you mistook for a hit?
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.
3mdikram/worldmoneywords
snowsoft/config
itmosoft/laravel-subscriptions
larva/laravel-ai-qwen
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib