elcheco / translator
Translation system using neon files, supports plurals and string replacements, fallback language. Extension to Nette Framework ^3.0
Installs: 1 511
Dependents: 0
Suggesters: 0
Security: 0
Stars: 2
Watchers: 1
Forks: 0
Open Issues: 0
Requires
- php: >=8.3
- ext-intl: *
- ext-tokenizer: *
- dibi/dibi: ^v5.0
- nette/di: ^3.1
- nette/neon: ^3.0
- nette/safe-stream: ^2.4|^3.0
- nette/utils: ^3.0|^4.0
- psr/log: ^1.0
- symfony/console: ^7.2
Requires (Dev)
- mockery/mockery: ^1.5
- nette/tester: ^2.0
- phpstan/phpstan: ^1.10
README
A powerful and flexible translation library for PHP applications with support for both NEON files and database storage.
Features
- Support for multiple translation storage backends (NEON files, Database)
- Pluralization rules for many languages
- Fallback locale support
- Translation usage tracking
- Console commands for importing and exporting translations
- Compatible with Nette Framework
Requirements
- PHP 8.3 or higher
- Nette Framework 3.0 or higher (if using with Nette)
- Dibi database library (if using database storage)
Installation
composer require elcheco/translator
Configuration
Basic Configuration (Nette DI)
extensions: translator: ElCheco\Translator\Extension
NEON File-Based Translations
translator: default: en_US # Default locale fallback: en_US # Fallback locale debugMode: %debugMode% dictionary: factory: ElCheco\Translator\NeonDictionary\NeonDictionaryFactory args: directory: %appDir%/translations # Directory with NEON files cache: %tempDir%/cache/translations # Cache directory autoRefresh: %debugMode% # Auto refresh translations
Database-Based Translations
translator: default: en_US # Default locale fallback: en_US # Fallback locale dictionary: factory: ElCheco\Translator\DbDictionary\DbDictionaryFactory args: - @Dibi\Connection # Database connection - MyModule # Module name - true # Track usage commands: - ElCheco\Translator\Console\ImportNeonTranslationsCommand(@Dibi\Connection) - ElCheco\Translator\Console\ExportNeonTranslationsCommand(@Dibi\Connection)
Usage
In Presenters or Services
use ElCheco\Translator\Translator; class BasePresenter extends \Nette\Application\UI\Presenter { private Translator $translator; public function injectTranslator(Translator $translator) { $this->translator = $translator; } public function beforeRender() { // Set translator for templates $this->template->setTranslator($this->translator); } public function handleSwitchLocale(string $locale) { $this->translator->setLocale($locale); $this->redirect('this'); } }
In Templates (Latte)
{* Simple translation *} <h1>{_'Welcome to our website'}</h1> {* Translation with parameters *} <p>{_'Hello %s', $userName}</p> {* Translation with pluralization *} <p>{_'You have %s new messages', $count}</p>
Direct Usage in PHP
use ElCheco\Translator\Translator; $translator = new Translator($dictionaryFactory); $translator->setLocale('en_US'); // Simple translation echo $translator->translate('Welcome to our website'); // Translation with parameters echo $translator->translate('Hello %s', 'John'); // Translation with pluralization echo $translator->translate('You have %s new messages', 5);
NEON Translation Files Format
Translation files are named according to locale, e.g., en_US.neon
, cs_CZ.neon
.
Simple Translations
# en_US.neon Welcome to our website: Welcome to our website Hello %s: Hello %s
Translations with Pluralization
# en_US.neon You have %s new messages: 1: You have %s new message 2: You have %s new messages %s bedrooms: 1: %s bedroom 2: %s bedrooms
Translations with Pluralization Ranges
# cs_CZ.neon You have %s points: 1: Máš %s bod "2-4": Máš %s body 5: Máš %s bodů
or simplified
# cs_CZ.neon You have %s points: 1: Máš %s bod 2: Máš %s body 5: Máš %s bodů
Command Line Tools
Import Translations from NEON to Database
php bin/console translations:import-neon /path/to/neon/files ModuleName \ --locale=en_US \ --mark-as-translated \ --mark-as-approved \ --overwrite
Options:
--locale
or-l
: Import only a specific locale--mark-as-approved
or-a
: Mark imported translations as approved--overwrite
or-o
: Overwrite existing translations
Export Translations from Database to NEON
php bin/console translations:export-neon ModuleName en_US \ --output-dir=./translations \ --include-keys=key1,key2 \ --include-untranslated
Options:
--output-dir
or-o
: Output directory for NEON files--include-keys
or-k
: Include only specific keys--include-untranslated
or-u
: Include keys without translations
Database Structure
The database storage uses the following tables:
translation_modules
: Modules (groups of keys)translation_keys
: Translation keystranslations
: Actual translations for different locales
See the included db/structure.sql
file for complete database schema.
Testing
composer install vendor/bin/tester tests/
Examples
NEON Dictionary With Fallback Locale
use ElCheco\Translator\NeonDictionary\NeonDictionaryFactory; use ElCheco\Translator\Translator; $factory = new NeonDictionaryFactory( __DIR__ . '/translations', // Directory with translation files __DIR__ . '/temp/cache', // Cache directory true // Auto refresh ); $translator = new Translator($factory); $translator->setLocale('fr_FR'); // Primary locale $translator->setFallbackLocale('en_US'); // Fallback locale
DB Dictionary With Usage Tracking
use ElCheco\Translator\DbDictionary\DbDictionaryFactory; use ElCheco\Translator\Translator; $factory = new DbDictionaryFactory( $connection, // Dibi or other DB connection 'Frontend', // Module name true // Track usage ); $translator = new Translator($factory); $translator->setLocale('de_DE');
Advanced Usage
Customizing Plural Rules
ElCheco Translator includes built-in plural rules for many languages. If you need to add custom rules, you can extend the PluralRules
class:
use ElCheco\Translator\PluralRules; class MyPluralRules extends PluralRules { // Add custom language rules }
Creating Custom Dictionary Implementations
You can create your own dictionary implementation by implementing the DictionaryInterface
:
use ElCheco\Translator\DictionaryInterface; class MyCustomDictionary implements DictionaryInterface { public function get(string $message): string|array { // Your implementation } public function has(string $message): bool { // Your implementation } }
Note: Inspired by rostenkowski/translate, but I required support for Nette Framework versions ^3.2 and ^4.0, as well as a fallback translation option. I also refactored the pluralization to make it more naturally understandable and to support complex plural forms, such as those found in many Slavic languages. And newly added the DbDictionary feature for improved development and management of translations.
License
MIT License