marko/translation
Translation and i18n interface with placeholder replacement, pluralization, and fallback locale support --- so your application speaks every language your users need. This package provides the TranslatorInterface and TranslationLoaderInterface contracts for loading and resolving translated strings. It supports dot-notation keys, namespaced translations for packages, :placeholder replacement, and pluralization with labeled variants (zero, one, few, many, other). When a key is missing for the current locale, the translator falls back automatically.
This package defines contracts and core logic. Install an implementation package such as marko/translation-file to load translations from disk.
Installation
Section titled “Installation”composer require marko/translationNote: You typically install an implementation package (like marko/translation-file) which requires this automatically.
Translating Strings
Section titled “Translating Strings”Inject TranslatorInterface and call get() with a dot-notation key:
use Marko\Translation\Contracts\TranslatorInterface;
class WelcomeController{ public function __construct( private readonly TranslatorInterface $translator, ) {}
public function greet(): string { return $this->translator->get('messages.welcome'); }}Placeholder Replacement
Section titled “Placeholder Replacement”Pass an array of replacements for :placeholder tokens:
$this->translator->get( 'messages.hello', ['name' => 'Alice'],);// Translation string: "Hello, :name!" => "Hello, Alice!"Pluralization
Section titled “Pluralization”Use choice() with a count to select the correct plural form:
$this->translator->choice( 'messages.items', $count, ['count' => (string) $count],);Plural strings use pipe-separated labeled forms:
return [ 'items' => 'zero:No items|one:One item|other::count items',];Supported labels: zero, one, few (2—4), many (5+), other (default).
Namespaced Translations
Section titled “Namespaced Translations”Package translations use the namespace::group.key format:
$this->translator->get('blog::posts.title');Switching Locale
Section titled “Switching Locale”$this->translator->setLocale('fr');$greeting = $this->translator->get('messages.welcome');Configuration
Section titled “Configuration”The TranslationConfig class provides typed access to translation configuration values:
use Marko\Translation\Config\TranslationConfig;
class MyService{ public function __construct( private TranslationConfig $translationConfig, ) {}
public function setup(): void { $locale = $this->translationConfig->locale; $fallback = $this->translationConfig->fallbackLocale; }}Customization
Section titled “Customization”Replace the Translator with a custom implementation via Preferences:
use Marko\Core\Attributes\Preference;use Marko\Translation\Translator;
#[Preference(replaces: Translator::class)]class MyTranslator extends Translator{ public function get( string $key, array $replacements = [], ?string $locale = null, ): string { // Custom behavior return parent::get($key, $replacements, $locale); }}API Reference
Section titled “API Reference”TranslatorInterface
Section titled “TranslatorInterface”use Marko\Translation\Contracts\TranslatorInterface;
public function get(string $key, array $replacements = [], ?string $locale = null): string;public function choice(string $key, int $count, array $replacements = [], ?string $locale = null): string;public function setLocale(string $locale): void;public function getLocale(): string;Both get() and choice() throw MissingTranslationException when a key cannot be resolved in the current or fallback locale.
TranslationLoaderInterface
Section titled “TranslationLoaderInterface”use Marko\Translation\Contracts\TranslationLoaderInterface;
public function load(string $locale, string $group, ?string $namespace = null): array;TranslationConfig
Section titled “TranslationConfig”use Marko\Translation\Config\TranslationConfig;
public string $locale;public string $fallbackLocale;Exceptions
Section titled “Exceptions”| Exception | Description |
|---|---|
TranslationException | Base exception for all translation errors --- includes getContext() and getSuggestion() methods |
MissingTranslationException | Thrown when a translation key is not found for the current or fallback locale |