Stop Hardcoding Translations in Laravel - Use Translatable
Source: Dev.to
🤔 The Problem
Building a multilingual Laravel app? You might end up with messy code like this:
// ❌ The nightmare approach
switch ($status) {
case 'draft':
return $locale === 'es' ? 'Borrador' :
($locale === 'fr' ? 'Brouillon' : 'Draft');
// ... more chaos
}
There’s a much cleaner way.
✨ The Solution: Translatable Enums
Install It
composer require osama/laravel-enum-translatable
Create Your Enum
// Example enum (Laravel Enum Translatable)
enum ArticleStatus: string
{
use EnumTranslatable;
case DRAFT = 'draft';
case PUBLISHED = 'published';
case REJECTED = 'rejected';
}
// lang/en/enums.php
return [
'article_statuses' => [
'draft' => 'Draft',
'published' => 'Published',
'rejected' => 'Rejected',
],
];
// lang/es/enums.php
return [
'article_statuses' => [
'draft' => 'Borrador',
'published' => 'Publicado',
'rejected' => 'Rechazado',
],
];
// lang/fr/enums.php
return [
'article_statuses' => [
'draft' => 'Brouillon',
'published' => 'Publié',
'rejected' => 'Rejeté',
],
];
Use It Everywhere
$status = ArticleStatus::DRAFT;
// Current locale
$label = $status->trans(); // "Draft" (en) or "Borrador" (es) or "Brouillon" (fr)
// Specific locale
$spanish = $status->trans('es'); // "Borrador"
// All translations at once
$all = $status->allTrans(); // ['en' => 'Draft', 'es' => 'Borrador', 'fr' => 'Brouillon']
🚀 Real Example: Blog API
The Model
use App\Enums\ArticleStatus;
use Illuminate\Database\Eloquent\Model;
class Article extends Model
{
protected function casts(): array
{
return [
'status' => ArticleStatus::class,
];
}
}
The Controller
public function show(Article $article)
{
return response()->json([
'id' => $article->id,
'title' => $article->title,
'status'=> [
'value' => $article->status->value,
'label' => $article->status->trans(),
'all_translations' => $article->status->allTrans(),
],
]);
}
The Response
{
"id": 1,
"title": "Getting Started with Laravel",
"status": {
"value": "published",
"label": "Published",
"all_translations": {
"en": "Published",
"es": "Publicado",
"fr": "Publié"
}
}
}
Perfect for multi‑language frontends! 🌍
💪 Advanced: Combine with Business Logic
Enum Definition
enum OrderStatus: string
{
use EnumTranslatable;
case PENDING = 'pending';
case PAID = 'paid';
case SHIPPED = 'shipped';
case DELIVERED = 'delivered';
public function badge(): string
{
return match ($this) {
self::PENDING => 'warning',
self::PAID => 'info',
self::SHIPPED => 'primary',
self::DELIVERED => 'success',
};
}
public function canBeCancelled(): bool
{
return in_array($this, [self::PENDING, self::PAID]);
}
}
In Your Blade View
<span class="badge badge-{{ $order->status->badge() }}">
{{ $order->status->trans() }}
</span>
@if ($order->status->canBeCancelled())
<button>{{ __('Cancel Order') }}</button>
@endif
Clean, readable, maintainable! ✨
🎯 Why This Rocks
- Type‑Safe – PHP 8.1+ enum power
- DRY – Write translation once, use everywhere
- Clean Code – No scattered conditionals
- Scalable – Add languages without code changes
- Testable – Easy to unit test
🧪 Quick Test Example
public function test_translations_exist_for_all_locales()
{
$locales = ['en', 'es', 'fr'];
foreach (ArticleStatus::cases() as $status) {
foreach ($locales as $locale) {
$translation = $status->trans($locale);
$this->assertNotNull($translation);
$this->assertNotEmpty($translation);
}
}
}
📦 Quick Reference
// Get current locale translation
$status->trans();
// Get specific locale
$status->trans('es');
// Get all translations
$status->allTrans();
// In models (automatic casting)
protected $casts = ['status' => ArticleStatus::class];
💡 Pro Tips
Always set a fallback
// config/app.php
'fallback_locale' => 'en',
Dynamic form selects
$options = collect(ArticleStatus::cases())
->map(fn($s) => [
'value' => $s->value,
'label' => $s->trans(),
]);
Localized notifications
$locale = $user->locale ?? 'en';
$message = "Status changed to: " . $order->status->trans($locale);
🌟 Common Use Cases
- E‑commerce: Order statuses, payment statuses
- CMS: Article statuses, content types
- SaaS: Subscription tiers, user roles
- Task Management: Priority levels, task states
- Multi‑tenant Apps: Per‑tenant translations