elcheco / translator
Translation system using neon files, supports plurals and string replacements, fallback language. Extension to Nette Framework ^3.0
Installs: 1 589
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; // Create dictionary factory $factory = new NeonDictionaryFactory( __DIR__ . '/translations', // Directory with translation files __DIR__ . '/temp/cache', // Cache directory true // Auto refresh ); // Create dictionary $dictionary = $factory->create('fr_FR', 'en_US'); // locale, fallbackLocale // Create translator $translator = new Translator($dictionary);
DB Dictionary With Usage Tracking
use ElCheco\Translator\DbDictionary\DbDictionaryFactory; use ElCheco\Translator\Translator; // Create dictionary factory $factory = new DbDictionaryFactory( $connection, // Dibi or other DB connection 'Frontend', // Module name true // Track usage ); // Create dictionary $dictionary = $factory->create('de_DE', 'en_US'); // locale, fallbackLocale // Create translator $translator = new Translator($dictionary); // When application shuts down, save usage statistics $dictionary->saveUsageStats();
Advanced Usage
Customizing Plural Rules
ElCheco Translator includes built-in plural rules for many languages. If you need to add custom rules for specific languages or dialects, you can implement the PluralRulesInterface
:
use ElCheco\Translator\PluralRulesInterface; use ElCheco\Translator\Translation; class MyPluralRules implements PluralRulesInterface { public static function getNormalizedCount(string $locale, int $count): int { // Your custom rules here if ($locale === 'custom_locale') { // Custom logic for your locale return $count === 1 ? 1 : 2; } // For other locales, fall back to default rules return \ElCheco\Translator\PluralRules::getNormalizedCount($locale, $count); } } // Register your custom rules Translation::setCustomPluralRules(new MyPluralRules());
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