Drupal 8 was a big leap forward to perfect multilingual handling. When it comes to content, user interface or configuration, everything is translatable. So internationalization was done pretty well, but what about localization? So you’d like to translate your website into Italian, Spanish, German, Hungarian, well, likely it just works. How about Mongolian, Persian or Arabic? Either you make a trade-off or something must be done, for sure with dates at least.
The Problem
Case #1
Given a Persian website, the date should use Persian scripts for the numbers inside the dates.
A quick search reveals that the only meaningful answer using PHP is the Intl extension. Alright, but Drupal core decided to drop it, but with plans to re-introduce it again after the related issues are resolved. It is proved to be hard to provide a migration path between date patterns, moreover there was an issue with translating Intl-based date formats.
Case #2
Given a Mongolian website, the month should be translated differently if it displays without a day.
To easily understand that, here are two examples, the first is a full date, the second one is without the day part:
- 2021 оны долоодугаар сарын 20
- 2021 оны Долоодугаар сар
Only the case is different for the month, but still, how would you solve it using regular date patterns, or even using custom code? The first idea is to use translation context. Then should we ask translators to translate every month name twice for certain languages? How do we inject context when needed, in the middle of date formatting? Probably with overriding the date formatter? Sounds problematic and complex to implement.
Proposed Resolution
Drupal core dropped Intl efforts for a good reason, as we mentioned, but we envisioned that it should be implemented as
a contrib module. It means no need to worry about backwards compatibility, detection of support and so on.
It could be a module that only does one thing: provides date formatting for Drupal 8/9 using IntlDateFormatter
.
The Result
As a fusion of Drupal core date formatter concept and our custom code, we released intl_date that provides:
- Date field formatter
- Timestamp field formatter
- Twig filter to format dates
Mostly it’s a drop-in replacement to date formatting in Drupal core; it provides exactly the same date formats.
So for an existing site, all you need to do is to enable the module and change date format plugin IDs from:
datetime_default
to datetime_intl_default
.
Well, for complex sites, it’s more than that, but it’s a good start. Our approach is typically custom-code based, formatting timestamps and dates in Twig templates becomes handy too:
{{ 1626255230|intl_format_date_pattern('medium') }}
Similarly, for a date field on a node:
{{ node.field_date.value|date('U')|intl_format_date_pattern('medium') }}
As we would do with the core formatter, there’s a conversion to Unix timestamps, then we can format it freely.
Here’s a short screencast with the capabilities of the module and how to install it on an existing site.
Limitations
Did we already say that tests are useful? The module comes with a simple unit test that confirms basic functionality. It turned out that DDEV provides more complete language support than Drupal testbot environment, so I simplified the tests to at least have some coverage. Before you start building on this module, execute the test suite on a production-like environment, so there won’t be any surprises that what works locally fails immediately after the deployment.