Docs

I18n

A tiny, JSON-file-driven translation layer for MonkeysLegion.

Load one file per locale, translate a key with optional placeholders, and drop @lang() tags straight into your MLView templates—no ICU, no heavy runtime.

1 · Installation

composer require monkeyscloud/monkeyslegion-i18n

The package is pure PHP 8.4—only the JSON extension is required.

2 · Directory Layout

resources/lang/
├─ en.json      ← default / fallback
├─ fr.json
└─ es.json

Each file is a flat key → string map:

{
  "welcome":       "Welcome to MonkeysLegion!",
  "posts.count":   "There are :count posts",
  "user.greeting": "Hello, :name!"
}

3 · Bootstrapping the Translator

use MonkeysLegion\I18n\Translator;

return [
    Translator::class => fn ($c) => new Translator(
        locale:   $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? 'en',
        path:     base_path('resources/lang'),
        fallback: 'en',
    ),
];

The first argument can be anything—hard-coded, pulled from config, or read from the incoming request.

4 · Basic Usage

/** @var Translator $t */
$t = $container->get(Translator::class);

echo $t->trans('welcome');                       // → “Welcome to MonkeysLegion!”
echo $t->trans('posts.count', ['count' => 5]);   // → “There are 5 posts”

$t->setLocale('fr');
echo $t->trans('welcome');                       // → “Bienvenue sur MonkeysLegion !”
  • Missing in the current locale? Falls back to fallback (en).

  • Still missing? Returns the key so bugs are obvious.

5 · Template Integration (MLView)

5.1 Global helper

function trans(string $key, array $r = []): string {
    return ML_CONTAINER->get(\MonkeysLegion\I18n\Translator::class)
                       ->trans($key, $r);
}

5.2 Blade-style directive

Extend the MLView compiler once:

Compiler::directive('lang', fn($expr) => "<?php echo trans{$expr}; ?>");

Now, in any template:

<h1>@lang('welcome')</h1>
<p>@lang('posts.count', ['count' => $count])</p>

6 · Runtime Locale Switching

$translator->setLocale($req->getHeaderLine('X-Locale') ?: 'en');

Because Translator is stateful, all subsequent trans() calls in the same request use the new locale.

7 · Advanced Tips

  • Pluralisation – keep multiple keys (posts.zero, posts.one, posts.other) and choose in code.

  • Nested namespaces – use dot notation (auth.password.reset) to mimic folders without extra I/O.

  • Missing-key collector – wrap trans() in development, push unknown keys into a “todo” file.

License

MIT © 2025 MonkeysCloud