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