Migration
Migration from Versions 2.x to 3.0
New Features and Enhancements
Migration to Container-Driven Caching via Translation Collectors
The Translator component no longer manages caching internally, and the legacy $translator->setCache() method has been entirely removed.
Caching is now decoupled from the translator itself and is handled architectural-level by wrapping translation lookup routines inside specific Translation Collectors.
When the AggregateCollector is resolved from the dependency injection container, an internal delegator factory checks the application configuration for a defined PSR-6 or PSR-16 cache service.
If a valid cache service name is found and successfully retrieved from the container, the factory automatically wraps the AggregateCollector in a CachingCollector.
This decorator transparently proxies all lookup tasks via TranslationCollectorInterface::collect() and caches the results.
Configuration Changes
To enable translation caching, the caching service must be registered within the dependency container and point to its service name under the consolidated laminas-i18n configuration block.
Either a standard PSR-6 (psr6_cache) or a PSR-16 (psr16_cache) storage implementation can be provided.
An optional cache_key_prefix can also be supplied to prevent key collisions in shared cache environments.
Type Errors on Direct Injections
Manual invocation of caching configurations on the translator object or attempting to pass raw legacy laminas-cache adapter instances via configuration arrays will result in a TypeError.
All caching must be registered as container services.
Prior to 3.0.0
$cache = Laminas\Cache\StorageFactory::factory([
'adapter' => 'filesystem',
]);
$translator = new Laminas\I18n\Translator\Translator();
$translator->setCache($cache);
Since 3.0.0
return [
'dependencies' => [
'factories' => [
// Register the PSR-6 or PSR-16 compliant cache service factory
'MyApp\CacheService' => MyApp\Cache\CacheFactory::class,
],
],
'laminas-i18n' => [
'translator' => [
// Point to the service container key
'psr6_cache' => 'MyApp\CacheService',
// Alternatively, use a PSR-16 cache provider:
// 'psr16_cache' => 'MyApp\SimpleCacheService',
// Optional: Customize the translation cache isolation
'cache_key_prefix' => 'app_translation_',
'translation_file_patterns' => [
[
'type' => 'phparray',
'base_dir' => dirname(__DIR__, 2) . '/data/languages',
'pattern' => '%s.php',
],
],
],
],
];
Implicit Event Dispatcher Activation
The internal property eventsEnabled along with the manual toggle methods enableEventManager(), disableEventManager(), and isEventManagerEnabled() have been completely removed from the Translator class.
The Translator now implicitly manages events based entirely on the presence of a PSR-14 event dispatcher. If an EventDispatcherInterface instance is supplied to the constructor, events (such as MissingTranslationEvent or NoMessagesLoadedEvent) will automatically be active. If no dispatcher is supplied (or it is null), event management remains inactive without causing overhead or requiring code initialization.
In alignment with this architectural change, the 'event_manager_enabled' configuration option flag has been removed from the factory configuration payload.
Prior to 3.0.0
use Laminas\I18n\Translator\Translator;
// 1. Array configuration toggle
$translator = Translator::factory([
'event_manager_enabled' => true,
]);
// 2. Direct method calls
$translator->enableEventManager();
$translator->disableEventManager();
Since 3.0.0
use Laminas\I18n\Translator\Translator;
// Events are implicitly ACTIVE because a dispatcher instance is provided to the constructor
$translatorWithEvents = new Translator(
$collector,
'en_US',
null,
'default',
$eventDispatcher
);
// Events are implicitly INACTIVE because no dispatcher is present
$translatorWithoutEvents = new Translator(
$collector,
'en_US'
);
Migration Action Required
- Remove the
'event_manager_enabled'option key from your configuration files and factory option arrays. - Remove any direct calls to
enableEventManager(),disableEventManager(), orisEventManagerEnabled().
Propagation Control for Translator Events
Both MissingTranslationEvent and NoMessagesLoadedEvent now implement Psr\EventDispatcher\StoppableEventInterface.
This allows listeners to stop event propagation by providing a translation or a text domain dynamically.
For MissingTranslationEvent, calling setTranslation() will automatically stop further propagation, and the provided translation will be used by the translator.
Introduction of I18nDefaults
A new Laminas\I18n\I18nDefaults value object has been introduced to encapsulate shared internationalization settings such as default locale, timezone, currency, and country.
This object is registered in the service container and can be used by satellite packages to ensure consistent defaults across the application.
Default Text Domain Support
The Translator now supports a configurable default text domain. This can be set via the default_text_domain configuration key under the translator block.
If not specified, it continues to default to default.
Since 3.0.0
return [
'laminas-i18n' => [
'translator' => [
'default_text_domain' => 'my-app-domain',
// ...
],
],
];
Structural Changes
TextDomain and Exception Finality
The Laminas\I18n\Translator\TextDomain class and all exception classes in Laminas\I18n\Exception have been marked as final.
This change reinforces the architectural decision to favor composition over inheritance and ensures consistency across the component.
Interface Namespace Extraction / Consolidation
To better split component responsibilities and streamline the core architecture, core interfaces have been extracted or moved to separate, dedicated packages.
Usages of Laminas\I18n\Translator\TranslatorInterface must be replaced with Laminas\Translator\TranslatorInterface.
Extraction of I18n Filters to Satellite Package
The component's built-in filtering capabilities have been extracted into an external standalone package: laminas/laminas-i18n-filter.
The following filter classes are no longer present in laminas-i18n:
Laminas\I18n\Filter\AlnumLaminas\I18n\Filter\AlphaLaminas\I18n\Filter\NumberFormatLaminas\I18n\Filter\NumberParse
Additionally, these filters have been reworked to ensure native compatibility with laminas-filter v3 execution pipelines.
Migration Action Required
If your application relies on these filters, you must explicitly require the new satellite package:
$ composer require laminas/laminas-i18n-filter
Extraction of I18n Validators to Satellite Package
The component's built-in validation capabilities have been extracted into an external standalone package: laminas/laminas-i18n-validator.
The following validator classes are no longer present directly within laminas-i18n:
Laminas\I18n\Validator\AlnumLaminas\I18n\Validator\AlphaLaminas\I18n\Validator\CountryCodeLaminas\I18n\Validator\DateTimeLaminas\I18n\Validator\IsFloatLaminas\I18n\Validator\IsIntLaminas\I18n\Validator\PhoneNumber(Note: Historical wrapper configuration only; see above for full structural replacement details)Laminas\I18n\Validator\PostCode
Additionally, these extracted validators have been internally refactored to achieve seamless native compatibility with the laminas-validator v3 engine and plugin management layers.
Migration Action Required
If your validation chains or forms rely on any of these i18n validation plugins, you must explicitly require the new satellite package via Composer:
composer require laminas/laminas-i18n-validator
Extraction of I18n View Helpers to Satellite Package
The component's built-in view helper capabilities have been extracted into an external standalone package: laminas/laminas-i18n-view.
Laminas\I18n\View\Helper\CurrencyFormatLaminas\I18n\View\Helper\DateFormatLaminas\I18n\View\Helper\NumberFormatLaminas\I18n\View\Helper\PluralLaminas\I18n\View\Helper\TranslateLaminas\I18n\View\Helper\TranslatePlural
Additionally, these extracted view helpers have been internally refactored to support laminas-view with version 3.
Migration Action Required
To obtain or retain support from the helpers, the package must also be installed:
composer require laminas/laminas-i18n-view
Laminas\I18n\Translator\Loader\Ini Initialization
Due to the removal of laminas-config, the Ini translator loader no longer implicitly instantiates an internal configuration reader.
It now requires Laminas\I18n\Translator\Loader\IniFileReader passed explicitly to its constructor.
Service Container Notice
If your application resolves the Ini translation loader via a service container (such as Laminas\ServiceManager), this instantiation change is automatically handled by the component's internal factories.
Manual intervention is only required if you instantiate the loader directly in your code.
Prior to 3.0.0
use Laminas\I18n\Translator\Loader\Ini as IniLoader;
$loader = new IniLoader();
Since 3.0.0
$loader = new Laminas\I18n\Translator\Loader\Ini(
new Laminas\I18n\Translator\Loader\IniFileReader()
);
Config Namespace Consolidation
To prevent configuration key pollution in global configurations, all translator top-level options must now be nested under the laminas-i18n configuration key.
Prior to 3.0.0
return [
'translator' => [
'translation_file_patterns' => [
[
'type' => 'phparray',
'base_dir' => dirname(__DIR__, 2) . '/data/languages',
'pattern' => '%s.php',
],
],
],
];
Since 3.0.0
return [
'laminas-i18n' => [
'translator' => [
'translation_file_patterns' => [
[
'type' => 'phparray',
'base_dir' => dirname(__DIR__, 2) . '/data/languages',
'pattern' => '%s.php',
],
],
],
],
];
Behaviour Changes
The deprecated static constructor Laminas\I18n\Exception\InvalidArgumentException::withUnknownCountryCode() has been removed.
Removed Features
Drop MVC Support (Laminas\I18n\Module Removal)
The MVC Module class has been entirely removed from the package.
No Migration Path for MVC Applications
Integration with laminas-mvc is completely dropped.
There is no official upgrade path for legacy MVC applications because laminas-mvc will not be updated to support ServiceManager v4.
Consequently, version 3.0+ of this component cannot be installed alongside the core MVC framework stack.
Removed Dependencies
laminas/laminas-config
The dependency on laminas/laminas-config has been removed. The component now utilizes a built-in INI file reader implementation instead.
Removed Classes
Laminas\I18n\Validator\PhoneNumber
The deprecated phone number validator has been removed in favour of the standalone library laminas-i18n-phone-number.
In most cases, the phone number library can be used as a direct replacement by using Laminas\I18n\PhoneNumber\Validator\PhoneNumber.
Removed Exceptions
The following unused exception classes have been removed:
Laminas\I18n\Exception\OutOfBoundsExceptionLaminas\I18n\Exception\ExtensionNotLoadedException