jdz / language
JDZ Translator (i18n) and Inflector library based on Symfony components
Requires
- php: >=8.2
- symfony/string: ^7.4
- symfony/translation: ^7.4
- symfony/yaml: ^7.4
Requires (Dev)
- phpunit/phpunit: ^11.0
Suggests
None
Provides
None
Conflicts
None
Replaces
None
README
Language is a proxy to the symfony/translation component - a modular PHP package designed for managing and translating multilingual content in your web projects. This project simplifies the use of language files and provides a clear API for easily handling translations.
Features
- Built on the symfony/translation component for robust translation capabilities.
- Uses the symfony/string inflector for pluralization and singularization.
- LanguageCode enum for type-safe language code handling.
- Custom LanguageException for language-specific error handling.
- Load default or application-specific language files.
- Flexible management of translation keys.
- Support for YAML format language files.
- Easy integration with other frameworks or custom solutions.
- Optimized for fast performance and maximum extensibility.
- Inflector support for French, English & Spanish (introduced in symfony/string 7.2, requires PHP >= 8.2).
Installation
Add the package to your project using Composer:
composer require jdz/language
Requirements
- PHP 8.2 or higher
- symfony/translation ^7.4
- symfony/string ^7.4
- symfony/yaml ^7.4
Usage
For a complete example, check example/example.php (and its example/example.yml) in the repository.
Initialization
use JDZ\Language\Language; $language = new Language( // app languages ['fr', 'en'], // default language 'fr' );
Load User Language
The code must be one of the LanguageCode cases (fr, en, es); anything else throws a LanguageException.
Loading reads the language metadata shipped in resources/metadata-<code>.yml, picks the matching inflector and sets the process locale (setlocale(LC_ALL, …)).
$language->load('fr');
Load Translations from Array
$language->loadArray([ 'welcome_message' => 'Hi !', 'test' => [ 'key1' => 'Test 1 nested', 'key2' => 'Test 1 nested 2', ], 'test2' => 'Test 2', ]);
Load Translations from YAML File
$language->loadYamlFiles([ __DIR__ . '/file1.yml', __DIR__ . '/file2.yml', ]); $language->loadYamlFile(__DIR__ . '/file3.yml');
Example YAML file:
welcome_message: "Welcome" goodbye_message: "Goodbye"
Setting Values
$language->set('custom.key', 'My custom value');
Getting Values
$welcomeMessage = $language->get('welcome_message'); // Hi ! $customMessage = $language->get('custom.key'); // My custom value $notDefined = $language->get('test.me'); // test.me (returns key if not found) $notDefinedButDefault = $language->get('test.me', [], 'Default value'); // Default value
Using LanguageCode Enum
use JDZ\Language\LanguageCode; // Check if a language code is valid if (LanguageCode::isValid('fr')) { // Valid language } // Get language from enum $french = LanguageCode::FRENCH; echo $french->value; // 'fr' // Try to get enum from string $lang = LanguageCode::tryFrom('en'); // Returns LanguageCode::ENGLISH or null
API Reference
Language Class Methods
The loaders and set() also accept an optional ?string $locale (defaults to the loaded language) and string $domain = 'messages'.
| Method | Description |
|---|---|
__construct(array $languages = [], ?string $defaultLang = null) |
App languages and default language (fr when omitted). Invalid codes are dropped. |
load(string $lang) |
Load a user language. Throws LanguageException if invalid. |
loadYamlFiles(array $resources) |
Load translations from an array of YAML files. |
loadYamlFile(string $resource) |
Load translations from a single YAML file (loadYmlFile() is a deprecated alias). |
loadArray(array $strings) |
Load translations from an array of key => value pairs. |
set(string $key, mixed $value) |
Adds a translation. |
get(string $key, array $parameters = [], ?string $default = null) |
Retrieves a translation at the specified path. |
getIf(string $key, array $parameters = [], ?string $default = null) |
Same, but returns $default (or the key) when the translation is missing. |
has(string $key, array $parameters = [], ?string $domain = null, ?string $locale = null) |
Checks if a translation exists at the specified path. |
plural(string $key, int $count = 0, array $parameters = [], ?string $domain = null, ?string $locale = null) |
Load a plural translation with count parameter (%count%). |
pluralize(string $string) |
Uses the symfony/string inflector to pluralize a word. |
singularize(string $string) |
Uses the symfony/string inflector to singularize a word. |
After load(), the public $metadata property holds the loaded LanguageMetas.
Other classes
| Class | Description |
|---|---|
JDZ\Language\LanguageMetas |
Language metadata (iso, tag, label, code, name, inflector, rtl, firstDay, locale) loaded from resources/metadata-<code>.yml. |
JDZ\Language\Inflector\DefaultInflector |
No-op inflector (returns the word unchanged), used when no symfony/string inflector matches the language. |
JDZ\Language\Contract\LanguageInterface |
get(), getIf(), has() — the contract Language implements. |
LanguageCode Enum
Available language codes:
LanguageCode::FRENCH(value: 'fr')LanguageCode::ENGLISH(value: 'en')LanguageCode::SPANISH(value: 'es')
Methods:
LanguageCode::isValid(string $value): bool- Check if a string is a valid language code
LanguageException
Custom exception class for language-specific errors. Extends \Exception.
Testing
The package includes a PHPUnit test suite (tests/).
To run the tests:
composer test # For detailed test output: composer test -- --testdox
Or directly with PHPUnit:
vendor/bin/phpunit --colors=always --testdox
Changelog
- 2.0.5 (2026-10-11) —
has()asks the translator's catalogue (fallback locales included) instead of comparing the translation with the key: a translation equal to its key (PDF: PDF) is found, soget()returns it instead of the default andgetIf()returns it instead of echoing the key.
License
This project is licensed under the MIT License - see the LICENSE file for details.