Laravel Framework

Localization & Internationalization

15 min Lesson 28 of 45

Localization & Internationalization

Localization (l10n) and internationalization (i18n) allow your Laravel application to support multiple languages and regional preferences. Laravel provides powerful features to easily translate your application's text, format dates and numbers, and manage multilingual content.

Understanding Localization

Key concepts:

  • Internationalization (i18n): Designing your application to support multiple languages
  • Localization (l10n): Adapting your application for specific languages and regions
  • Locale: A language code (e.g., "en", "ar", "fr") that identifies a language and region
  • Translation Strings: Text that can be translated into different languages
Note: Laravel stores translation files in the resources/lang directory (Laravel 8) or lang/ directory (Laravel 9+). Each language has its own subdirectory.

Configuration

Configure your default and fallback locales in config/app.php:

<?php return [ // Default application locale 'locale' => 'en', // Fallback locale when translation is missing 'fallback_locale' => 'en', // Available locales 'available_locales' => ['en', 'ar', 'fr', 'es'], ];

Creating Translation Files

Create language directories and translation files:

# Directory structure resources/lang/ ├── en/ │ ├── messages.php │ ├── auth.php │ └── validation.php ├── ar/ │ ├── messages.php │ ├── auth.php │ └── validation.php └── fr/ ├── messages.php ├── auth.php └── validation.php

Example translation file resources/lang/en/messages.php:

<?php return [ 'welcome' => 'Welcome to our application', 'goodbye' => 'Goodbye, :name!', 'user_greeting' => 'Hello, :name! You have :count messages.', 'items' => 'You have :count item|You have :count items', 'profile' => [ 'title' => 'Profile', 'edit' => 'Edit Profile', 'settings' => 'Settings', ], 'notifications' => [ 'success' => 'Operation completed successfully!', 'error' => 'An error occurred. Please try again.', 'warning' => 'Please check your input.', ], ];

Arabic translation resources/lang/ar/messages.php:

<?php return [ 'welcome' => 'مرحبًا بك في تطبيقنا', 'goodbye' => 'وداعًا، :name!', 'user_greeting' => 'مرحبًا، :name! لديك :count رسائل.', 'items' => 'لديك :count عنصر|لديك :count عناصر', 'profile' => [ 'title' => 'الملف الشخصي', 'edit' => 'تعديل الملف الشخصي', 'settings' => 'الإعدادات', ], 'notifications' => [ 'success' => 'تمت العملية بنجاح!', 'error' => 'حدث خطأ. يرجى المحاولة مرة أخرى.', 'warning' => 'يرجى التحقق من إدخالك.', ], ];

Retrieving Translation Strings

Use the __() helper function or trans() to retrieve translations:

<?php // Basic translation echo __('messages.welcome'); // Output: "Welcome to our application" // Translation with parameters echo __('messages.goodbye', ['name' => 'John']); // Output: "Goodbye, John!" // Nested translation keys echo __('messages.profile.title'); // Output: "Profile" // Default value if translation missing echo __('messages.unknown', [], 'Default text'); // Output: "Default text" // Using trans() helper echo trans('messages.welcome');

Using Translations in Blade

Use the @lang directive or translation helpers in Blade templates:

<!-- Using @lang directive --> <h1>@lang('messages.welcome')</h1> <!-- Using __() helper --> <p>{{ __('messages.goodbye', ['name' => $user->name]) }}</p> <!-- Translation with HTML --> <div class="alert"> {!! __('messages.notifications.success') !!} </div> <!-- Loop with translations --> @foreach($items as $item) <li>{{ __("messages.items.$item->type") }}</li> @endforeach

Switching Locales

Change the application locale at runtime:

<?php namespace App\Http\Controllers; use Illuminate\Http\Request; use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\Session; class LocaleController extends Controller { public function switch($locale) { // Validate locale if (!in_array($locale, ['en', 'ar', 'fr'])) { abort(404); } // Set application locale App::setLocale($locale); // Store in session for persistence Session::put('locale', $locale); return redirect()->back(); } } // In a middleware namespace App\Http\Middleware; use Closure; use Illuminate\Support\Facades\App; use Illuminate\Support\Facades\Session; class SetLocale { public function handle($request, Closure $next) { // Get locale from session, URL, or default $locale = Session::get('locale', config('app.locale')); App::setLocale($locale); return $next($request); } }

URL-Based Localization

Include locale in URLs for better SEO:

<?php // routes/web.php Route::prefix('{locale}')->middleware('setlocale')->group(function () { Route::get('/', [HomeController::class, 'index'])->name('home'); Route::get('/about', [PageController::class, 'about'])->name('about'); Route::get('/contact', [PageController::class, 'contact'])->name('contact'); }); // Middleware to set locale from URL namespace App\Http\Middleware; use Closure; use Illuminate\Support\Facades\App; class SetLocaleFromUrl { public function handle($request, Closure $next) { $locale = $request->segment(1); if (in_array($locale, config('app.available_locales'))) { App::setLocale($locale); } return $next($request); } } // Generate localized URLs route('home', ['locale' => 'en']); // /en route('about', ['locale' => 'ar']); // /ar/about

Pluralization

Laravel supports pluralization rules for different languages:

<?php // In translation file 'apples' => '{0} No apples|{1} One apple|[2,*] :count apples', 'time' => '{1} :value minute ago|[2,*] :value minutes ago', // Usage echo trans_choice('messages.apples', 0); // "No apples" echo trans_choice('messages.apples', 1); // "One apple" echo trans_choice('messages.apples', 5); // "5 apples" // Arabic pluralization (more complex) 'posts' => '{0} لا توجد منشورات|{1} منشور واحد|{2} منشوران|[3,10] :count منشورات|[11,*] :count منشور',

JSON Translation Files

For simple key-value translations without nesting:

// resources/lang/en.json { "Welcome": "Welcome", "Login": "Login", "Register": "Register", "Email": "Email Address", "Password": "Password" } // resources/lang/ar.json { "Welcome": "مرحبًا", "Login": "تسجيل الدخول", "Register": "التسجيل", "Email": "عنوان البريد الإلكتروني", "Password": "كلمة المرور" } // Usage (uses the English text as the key) {{ __('Welcome') }} {{ __('Email') }}
Tip: JSON translation files are great for simple translations and work well with JavaScript frameworks. Use PHP arrays for complex translations with nesting and pluralization.

Date and Number Formatting

Format dates and numbers according to locale:

<?php use Illuminate\Support\Carbon; // Date formatting with Carbon $date = Carbon::parse('2024-01-15'); App::setLocale('en'); echo $date->translatedFormat('l, F j, Y'); // Output: "Monday, January 15, 2024" App::setLocale('ar'); echo $date->translatedFormat('l، j F، Y'); // Output: "الاثنين، 15 يناير، 2024" // Number formatting $number = 1234567.89; App::setLocale('en'); echo number_format($number, 2); // Output: "1,234,567.89" App::setLocale('ar'); setlocale(LC_NUMERIC, 'ar_AE.utf8'); echo number_format($number, 2); // May need additional formatting for Arabic numerals

RTL (Right-to-Left) Support

Support RTL languages like Arabic and Hebrew:

<!-- In Blade layout --> <html lang="{{ app()->getLocale() }}" dir="{{ in_array(app()->getLocale(), ['ar', 'he', 'fa']) ? 'rtl' : 'ltr' }}"> <head> @if(in_array(app()->getLocale(), ['ar', 'he', 'fa'])) <link rel="stylesheet" href="{{ asset('css/rtl.css') }}"> @else <link rel="stylesheet" href="{{ asset('css/app.css') }}"> @endif </head>
/* CSS for RTL support */ [dir="rtl"] { text-align: right; } [dir="rtl"] .float-left { float: right; } [dir="rtl"] .float-right { float: left; } [dir="rtl"] .text-left { text-align: right; } [dir="rtl"] .ml-3 { margin-left: 0; margin-right: 0.75rem; }

Spatie Laravel Translatable

Use the popular Spatie package for translatable database models:

# Install package composer require spatie/laravel-translatable <?php // Model namespace App\Models; use Illuminate\Database\Eloquent\Model; use Spatie\Translatable\HasTranslations; class Post extends Model { use HasTranslations; public $translatable = ['title', 'content']; } // Migration Schema::create('posts', function (Blueprint $table) { $table->id(); $table->json('title'); $table->json('content'); $table->timestamps(); }); // Usage $post = new Post(); $post->setTranslation('title', 'en', 'Hello World'); $post->setTranslation('title', 'ar', 'مرحبا بالعالم'); $post->save(); // Retrieve translations echo $post->getTranslation('title', 'en'); // "Hello World" echo $post->title; // Automatically uses current locale

Exercise 1: Basic Localization

Set up a multilingual application:

  1. Create translation files for English and Arabic
  2. Add translations for navigation, forms, and messages
  3. Create a locale switcher in your layout
  4. Store the selected locale in the session
  5. Test switching between languages

Exercise 2: URL-Based Locales

Implement locale prefixes in URLs:

  1. Add locale prefix to all routes (/en/*, /ar/*)
  2. Create middleware to set locale from URL
  3. Update all route() helpers to include locale parameter
  4. Implement hreflang tags for SEO
  5. Add automatic redirection based on browser language

Exercise 3: Translatable Models

Create a multilingual blog:

  1. Install Spatie Laravel Translatable
  2. Make Post model translatable (title, content, excerpt)
  3. Create forms to input translations for each language
  4. Display posts in the current locale
  5. Add RTL CSS support for Arabic

Best Practices

  • Organize Translations: Group related translations in separate files
  • Use Keys: Use descriptive keys instead of full sentences
  • Fallback Locale: Always provide a fallback locale
  • Test All Languages: Regularly test your app in all supported languages
  • SEO: Use hreflang tags and locale-specific URLs
  • RTL Support: Design with RTL in mind from the start
  • Professional Translation: Use professional translators, not machine translation
  • Context: Provide context for translators (comments in translation files)

Summary

In this lesson, you learned:

  • The difference between localization and internationalization
  • How to create and organize translation files
  • Using the __() helper and @lang directive
  • Switching locales at runtime and via URLs
  • Pluralization rules for different languages
  • Date and number formatting for locales
  • Supporting RTL languages like Arabic
  • Using Spatie Translatable for database content

Proper localization makes your application accessible to a global audience and provides a better user experience. Plan for localization early in development for easier implementation.