celestifyx / lingo
A comprehensive internationalization framework for PHP with pluralization, custom formats, and extensible rules
Requires
- php: ^8.3
- celestifyx/stellaris: 1.0.5
README
A comprehensive internationalization framework for PHP with pluralization, custom formats, and extensible rules.
Features
- Multiple Placeholder Formats: Support for
{key}
,{{key}}
,:key
,%key%
,%key
<key>
, and$key
formats - Smart Key Resolution: Handles both literal dot keys and nested dot notation
- Custom Rules System: Extensible rule engine for custom translation logic
- Fallback Language Support: Automatic fallback to default language when translations are missing
- Caching Integration: Built-in cache support via Stellaris
- Multiple Config Formats: JSON, JSON5, YAML, TOML, and more via Stellaris
- Immutable Design: Thread-safe immutable operations
- Global Functions: Convenient global helper functions
Installation
composer require celestifyx/lingo
Quick Start
<?php
require_once 'vendor/autoload.php';
// Initialize Lingo
lingo_init('/path/to/translations', 'en', 'en');
// Load a language file
lingo_switch_language('messages.json');
// Translate
echo t('welcome.message'); // "Welcome to our application"
echo t('user.greeting', ['name' => 'John']); // "Hello, John!"
Translation Files
Create translation files in your translations directory:
en.json
{
"welcome": {
"message": "Welcome to our application",
"title": "Welcome"
},
"user": {
"greeting": "Hello, {name}!",
"count": "You have {count} messages"
}
}
Core Functions
Translation Functions
// Basic translation
t('key.path')
// Translation with parameters
t('user.greeting', ['name' => 'John'])
// Translation with context for rules
t('user.count', ['count' => 5], ['context' => 'plural'])
Language Management
// Switch language and load file
lingo_switch_language('messages.json');
lingo_switch_language('config.yaml', ConfigFormat::YAML);
// Get current language
$current = lingo_current_language();
// Get available languages
$languages = lingo_available_languages();
// Set fallback language
lingo_set_fallback_language('en');
Advanced Features
// Add custom rule
lingo_add_rule(new MyCustomRule());
// Add custom placeholder format
lingo_add_placeholder_format(new MyCustomFormat());
// Get debug information
$debug = lingo_debug_info();
Placeholder Formats
Lingo supports multiple placeholder formats out of the box:
Format | Example | Usage |
---|---|---|
Single Brace | {name} | t('greeting', ['name' => 'John']) |
Double Brace | {{name}} | t('greeting', ['name' => 'John']) |
Colon | :name | t('greeting', ['name' => 'John']) |
Percent | %name% | t('greeting', ['name' => 'John']) |
Percent | %name | t('greeting', ['name' => 'John']) |
Angle Bracket | <name> | t('greeting', ['name' => 'John']) |
Dollar | $name | t('greeting', ['name' => 'John']) |
Smart Key Resolution
Lingo intelligently handles both literal keys with dots and nested dot notation:
{
"app.config.database": { // Literal key with dots
"host": "localhost",
"port": 3306
},
"user": {
"profile": {
"name": "User Name"
}
}
}
// Both work correctly:
t('app.config.database.host') // "localhost"
t('user.profile.name') // "User Name"
Custom Rules
Create custom translation rules by implementing RuleInterface
:
use Lingo\Rule\RuleInterface;
class PluralRule implements RuleInterface {
/**
* @param string $translation
* @param array $context
* @return string
*/
function apply(string $translation, array $context = []): string {
$count = ($context['count'] ?? 1);
if ($count === 1) return str_replace('{plural}', 'item', $translation);
return str_replace('{plural}', 'items', $translation);
}
/**
* @return string
*/
function getName(): string {
return 'plural';
}
/**
* @return int
*/
function getPriority(): int {
return 100;
}
/**
* @param array $context
* @return bool
*/
function shouldApply(array $context = []): bool {
return isset($context['count']);
}
}
// Register the rule
lingo_add_rule(new PluralRule());
// Use with context
t('user.items', ['count' => 5], ['count' => 5]); // "You have 5 items"
Custom Placeholder Formats
Create custom placeholder formats:
use Lingo\PlaceholderFormat\PlaceholderFormatInterface;
class HashFormat implements PlaceholderFormatInterface {
/**
* @return string
*/
function getPattern(): string {
return '/#(\w+)#/'; // Matches #KEY#
}
/**
* @return string
*/
function getName(): string {
return 'hash';
}
}
// Register the format
lingo_add_placeholder_format(new HashFormat());
// Now you can use #key# in translations
t('message', ['user' => 'John']); // Works with "Hello #user#!"
Supported File Formats
lingo_switch_language('messages.json5', ConfigFormat::JSON5);
lingo_switch_language('config.yaml', ConfigFormat::YAML);
lingo_switch_language('settings.toml', ConfigFormat::TOML);
Caching
Enable caching for better performance:
use Stellaris\Cache\FileCache;
$cache = new FileCache('/tmp/lingo-cache');
lingo_init('/path/to/translations', 'en', 'en', $cache);
Object-Oriented Usage
For more control, use the Lingo class directly:
use Lingo\Lingo;
use Stellaris\Enum\ConfigFormat;
$lingo = Lingo::create('/path/to/translations', 'en', 'en');
$lingo = $lingo->switchLanguage('messages.json5', ConfigFormat::JSON5);
$translation = $lingo->t('welcome.message', ['name' => 'John']);
🔒 Error Handling
- Missing translations return the key itself
- Invalid language codes throw
InvalidArgumentException
- File loading errors are handled gracefully with fallbacks
- Nested key navigation provides detailed error messages
📋 Requirements
- PHP 8.2+ - Modern PHP with strong typing support
- celestifyx/stellaris - A powerful, elegant, and extensible configuration management library for PHP.
📄 License
This project is licensed under the GNU General Public License v3.0 or later - see the LICENSE file for details.
Lingo - A comprehensive internationalization framework for PHP with pluralization, custom formats, and extensible rules. ⭐
Built with ❤️ by the CELESTIFYX Team