-
-
Notifications
You must be signed in to change notification settings - Fork 2
Recipes
Practical, copy-pasteable patterns for using initphp/translator in a real
application. Every snippet runs against the released package.
Most apps want a short function instead of passing the translator around. Build the translator once, then expose a helper:
use InitPHP\Translator\Translator;
function translator(): Translator
{
static $lang = null;
if ($lang === null) {
$lang = new Translator();
$lang->setDir(__DIR__ . '/languages/')
->setDefault('en');
}
return $lang;
}
/** Translate-and-return. */
function t(string $key, ?string $fallback = null, array $context = []): string
{
return translator()->translate($key, $fallback, $context);
}
/** Translate-and-echo. */
function te(string $key, ?string $fallback = null, array $context = []): void
{
translator()->render($key, $fallback, $context);
}echo t('welcome', null, ['user' => 'Ada']);
te('hello'); // echoesResolve the active language from the request, always validating against a known list so an unknown value can't throw on a missing pack:
$supported = ['en', 'tr', 'fr'];
$requested = $_GET['lang']
?? $_COOKIE['lang']
?? 'en';
translator()->change(in_array($requested, $supported, true) ? $requested : 'en');function preferredLanguage(array $supported, string $default): string
{
$header = $_SERVER['HTTP_ACCEPT_LANGUAGE'] ?? '';
foreach (explode(',', $header) as $part) {
$code = strtolower(substr(trim($part), 0, 2)); // "en-US;q=0.9" → "en"
if (in_array($code, $supported, true)) {
return $code;
}
}
return $default;
}
translator()->change(preferredLanguage(['en', 'tr', 'fr'], 'en'));Depend on TranslatorInterface, not the
concrete class, so the dependency can be swapped in tests:
use InitPHP\Translator\TranslatorInterface;
final class Mailer
{
public function __construct(private TranslatorInterface $lang)
{
}
public function welcomeSubject(string $user): string
{
return $this->lang->translate('emails.welcome.subject', 'Welcome, {user}!', [
'user' => $user,
]);
}
}Wire it up once (here with a plain factory; any PSR-11 container works the same way):
$lang = new Translator();
$lang->setDir(__DIR__ . '/languages/')->setDefault('en');
$mailer = new Mailer($lang);Use Directory Mode and split each language into focused files. The file name becomes the key prefix:
languages/
en/
admin.php → admin.*
user.php → user.*
emails.php → emails.*
errors.php → errors.*
tr/
admin.php
user.php
emails.php
errors.php
$lang->useDirectory()->setDir(__DIR__ . '/languages/')->setDefault('en');
$lang->translate('emails.welcome.subject');
$lang->translate('errors.http.404');If you prefer "never show a raw key", pass an inline fallback at the call site — it is interpolated too:
$label = $lang->translate('ui.save_button', 'Save'); // "Save" if the key is missingFor a project-wide default, centralize it in your helper:
function t(string $key, string $fallback, array $context = []): string
{
return translator()->translate($key, $fallback, $context);
}
echo t('ui.save_button', 'Save');
echo t('ui.cancel_button', 'Cancel');The translator caches each language it loads, so switching back and forth is cheap:
$lang->change('en');
$english = $lang->translate('welcome', null, ['user' => 'Ada']);
$lang->change('tr');
$turkish = $lang->translate('welcome', null, ['user' => 'Ada']);var_dump() shows a compact snapshot via
__debugInfo():
var_dump($lang);
// system => 'file', default => 'en', current => 'tr', container => [ ...active language... ]- Testing — testing code that depends on the translator.
- Keys & Fallback — the resolution rules behind these patterns.
- FAQ — scope questions (plurals, caching, formats).
initphp/translator · MIT License · part of the InitPHP family
Source · Issues · Discussions · Packagist · Contributing · Security Policy
Getting Started
Core Usage
Reference
Practical Guides
Migration & Help