Back to Documentation
Guide

📚Internationalization Guide

The `Lang` class provides translation support for multiple locales.

Lang Class#

The Lang class provides translation support for multiple locales.

Configuration#

env
APP_LOCALE=en            # Default locale
APP_FALLBACK_LOCALE=en   # Fallback when translation is missing

Translation Files#

Translations are stored in language files under the project's language directory:

lang/
  en/
    messages.php
    validation.php
  vi/
    messages.php
    validation.php

Example lang/en/messages.php:

php
return [
    'welcome' => 'Welcome',
    'greeting' => 'Hello, :name!',
    'apples' => '{0} No apples|[1,9] :count apples|[10,*] Many apples',
];

Example lang/vi/messages.php:

php
return [
    'welcome' => 'Chào mừng',
    'greeting' => 'Xin chào, :name!',
];

Basic Usage#

php
use Siro\Core\Lang;

// Get a translation
echo Lang::get('messages.welcome');        // "Welcome" (en) / "Chào mừng" (vi)

// With parameter replacement
echo Lang::get('messages.greeting', ['name' => 'John']);  // "Hello, John!"

// Check key existence
if (Lang::has('messages.welcome')) {
    // Key exists
}

// Returns the key itself when translation is not found
echo Lang::get('nonexistent.key');         // "nonexistent.key"

Pluralization#

php
echo Lang::plural('messages.apples', 0);   // "No apples"
echo Lang::plural('messages.apples', 1);   // "1 apple"
echo Lang::plural('messages.apples', 5);   // "5 apples"
echo Lang::plural('messages.apples', 100); // "Many apples"

Plural forms follow CLDR rules with pipe-separated conditions:

{0} Zero items|[1,9] Some items|[10,*] Many items

Counting Translations#

php
$count = Lang::count('validation');  // Number of keys in validation file

Locale Detection#

Set locale manually:

php
Lang::setLocale('vi');
echo Lang::locale();  // "vi"

Detect from request (typical in a route):

php
$router->get('/profile', function (Request $req): array {
    $locale = $req->queryString('locale', 'en');
    Lang::setLocale($locale);

    return [
        'success' => true,
        'message' => Lang::get('messages.greeting', ['name' => $req->query('name', 'Guest')]),
        'data' => [
            'locale' => $locale,
            'available_locales' => ['en', 'vi'],
        ],
    ];
});

Validation Messages#

Validation automatically uses localized messages:

php
use Siro\Core\Validator;

Lang::setLocale('vi');
$errors = Validator::make(['email' => ''], ['email' => 'required']);
// Returns: ['email' => ['Email không được để trống']]

Lang::setLocale('en');
$errors = Validator::make(['email' => ''], ['email' => 'required']);
// Returns: ['email' => ['Email is required']]

Built-in validation messages supported: required, email, min, max, integer, numeric, in, date, url.

Creating Language Packs#

bash
php siro make:lang fr     # Create French language pack
php siro make:lang ja     # Create Japanese language pack

This generates translation stub files under lang/{locale}/.

Best Practices#

  • Always use :param placeholders in translation strings for dynamic values.
  • Set APP_FALLBACK_LOCALE so your app degrades gracefully when translations are missing.
  • Store locale preference per-user in the database and apply via middleware.
  • Use Lang::has() to check for key existence before accessing.
  • Group translations by feature/domain (e.g. messages, validation, emails).
  • Keep translation files focused — one file per domain of content.