prinsfrank/transliteration
Typed PHP 8.1+ wrapper around ICU Transliterator. Build transliterators with strict, documented arguments instead of opaque rule strings, plus ready-to-use conversion sets for common transformations (e.g., names/addresses, identity verification, multi-language support).
Installation:
composer require prinsfrank/transliteration
Ensure your project uses PHP 8.1+.
First Use Case: Convert a string to ASCII for a multilingual support system:
use PrinsFrank\Transliteration\TransliteratorBuilder;
use PrinsFrank\Transliteration\ConversionSet\ToASCII;
$builder = new TransliteratorBuilder();
$builder->applyConversionSet(new ToASCII());
$transliterated = $builder->transliterate('アマゾン'); // Output: 'amazon'
Where to Look First:
TransliteratorBuilder: Core class for constructing transliterators.ConversionSet: Predefined sets like ToASCII, IPAToEnglishApproximation, or ScriptLanguage.Builder Pattern: Chain methods to construct transliterators:
$builder
->applyConversionSet(new ToASCII())
->applyConversionSet(new IPAToEnglishApproximation())
->transliterate('naɕi gʌba'); // 'naci guba'
Conversion Sets:
ToASCII, ScriptLanguage).ConversionSet interface for domain-specific rules:
class CustomSet implements ConversionSet {
public function apply(TransliteratorBuilder $builder): void {
$builder->addConversion(new Conversion('ß', 'ss'));
}
}
Script/Language Conversion: Convert between scripts (e.g., Cyrillic to Latin):
use PrinsFrank\Transliteration\ConversionSet\ScriptLanguage;
use PrinsFrank\Transliteration\Target\ScriptName;
$builder->applyConversionSet(
new ScriptLanguage(ScriptName::CYRILLIC, ScriptName::LATIN)
);
$builder->transliterate('Иван'); // 'Ivan'
Contextual Replacements:
Use Conversion with context (e.g., beforeContext, afterContext):
$builder->addConversion(
new Conversion('ß', 'ss', 'beforeContext: e')
);
$builder->transliterate('Straße'); // 'Strasse' (only replaces 'ß' before 'e')
Variable Definitions: Reuse complex patterns:
$builder->addVariableDefinition(new VariableDefinition('foo', 'bar'));
$builder->addConversion(new Conversion('{foo}', 'baz')); // Replaces 'bar' with 'baz'
$transliterator = $builder->getTransliterator();
// Reuse $transliterator later
try-catch for invalid inputs:
try {
$result = $builder->transliterate($input);
} catch (TransliteratorException $e) {
log($e);
return $input; // Fallback
}
Recursive ConversionSets:
Nesting A in B and B in A throws an exception. Avoid circular dependencies.
Undocumented ICU Rules:
beforeContext/afterContext require ICU’s rule syntax.new Conversion('ß', 'ss', 'beforeContext: e') only replaces ß before e.Variable Naming:
Variable names in VariableDefinition must be alphanumeric (no special chars). Escaping is automatic for values.
Filter Scope:
Global filters (e.g., Filter::addRange()) apply to all SingleIDs. Prefer per-ID filters to avoid side effects.
PHP Extensions:
Requires intl extension. Verify with:
php -m | grep intl
Inspect Rule Sets: Log the generated ICU rule string for debugging:
$ruleSet = $builder->getTransliterator()->getID();
// Output: 'Any-Latin;Latin-ASCII;' (e.g., for ToASCII)
Test Edge Cases:
Performance:
ConversionSets) slow down transliteration. Benchmark with microtime().Custom Targets/Sources:
Extend Target\ScriptName, Target\LanguageTag, etc., for domain-specific tags.
Filter Logic:
Override Filter::addRange() to implement custom character ranges (e.g., emoji support).
Transliterator Caching:
Cache built transliterators in a service container (e.g., Laravel’s app binding):
$this->app->singleton(TransliteratorBuilder::class, function () {
return new TransliteratorBuilder();
});
Laravel Integration: Create a facade or service provider for global access:
// app/Providers/TransliterationServiceProvider.php
public function register() {
$this->app->singleton('transliterator', function () {
return new TransliteratorBuilder();
});
}
How can I help you explore Laravel packages today?