Last week, I got a report about a broken site, that caught me a bit by surprise. I’ll recreate the issue with a dummy plugin here, so show what went wrong. When navigating to the page with the error, this message was presented to me:
Fatal error: Uncaught Error: Missing format specifier at end of string in /var/www/html/wp-content/plugins/broken-format-string/broken-format-string.php on line 15
I looked at the code and saw something like:
printf( __( 'Publish date: %s', 'broken-format-string' ), date_i18n( get_option( 'date_format' ), get_post_datetime() ) );
Nothing fancy so far. Just a format string with a placeholder for a string, that gets replaced with the post date in the WordPress date format.
As I couldn’t see any issue here, I was first a bit confused, what the issue would be. But since the website language was not set to “English (US)”, I’ve checked the translation file. Again, here is an example of a translation with a similar issue:
#: broken-format-string.php:14 msgid "Publish date: %s" msgstr "Veröffentlichungsdatum: %"
This German translation is translating the “Publish date:” part, but as the placeholder, it is only using a
% instead of a
%s and this causes the issue. WordPress would translate the original string to German and then pass it to the
printf() function, which then exists with a “Fatal error”.
Different error handing with PHP 8+
When you run this code with PHP 7.4 and earlier, you don’t get a fatal error. You don’t even get a PHP notice or warning. It would just not replace the placeholder correctly. The
% would just be replaced with an empty string. But as soon as you upgrade to PHP 8+ you will have a broken site.
This was one of the first real issues I have recognized with PHP 8+ on a WordPress site. Maybe I was just lucky, or translation always had all the placeholders translated correctly.
I’ve done some checks for PHP 8+ compatibility with the PHPCompatibilityWP and so far it never failed me. But I would never have imagined, that an incorrect translation would cause a fatal error. When translations are made with GlotPress (used on translate.wordpress.org), you will see a warning, that the translation is missing a placeholder. But tools like Poedit don’t show such a warning. So when you have someone translating a plugin/theme into a language you don’t speak, better make sure that format strings are correct.