Performance Chat Summary: 25 March 2025

The full chat log is available beginning here on Slack.

Performance Lab plugins

  • As a consequence from the previous meeting and last week’s release (which for the first time saw releases for only a few of the performance plugins, without Performance Lab), changes to the release cadence were defined
  • Specifically, the team will change release cadence from monthly to on-demand (which could be more frequent or less frequent).
  • Consequently, the release procedure will be much more streamlined, avoiding the previously used “release party” format in favor of someone simply following the release handbook and sharing progress along the way.
  • Related to that, @westonruter has taken the separate release party chats handbook docs and moved the relevant example chats inline with the sections in the releasing the plugin handbook page. This eliminates the duplication of release instructions between the two resources.
  • @mukesh27 shared that PRs #1795 and #1818 are ready for review.

Our next chat will be held on Tuesday, April 8, 2025 at 15:00 UTC in the #core-performance channel in Slack.

#core-performance, #hosting, #performance, #performance-chat, #summary

Internationalization improvements in 6.8

Various internationalization (i18n) improvements are in WordPress 6.8, and this developers note focuses on these.

Localized PHPMailer messages

Over 12 years after #23311 was reported, WordPress 6.8 now properly localizes any user-visible PHPMailer error messages. To achieve this, a new WP_PHPMailer class extending PHPMailer was introduced to leverage the WordPress i18ni18n Internationalization, or the act of writing and preparing code to be fully translatable into other languages. Also see localization. Often written with a lowercase i so it is not confused with a lowercase L or the numeral 1. Often an acquired skill. system with PHPMailer. Note that developers don’t typically interact with this class directly outside of wp_mail() or the phpmailer_init action.

See [59592] for more context.

PluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party update emails in the adminadmin (and super admin)’s localeLocale A locale is a combination of language and regional dialect. Usually locales correspond to countries, as is the case with Portuguese (Portugal) and Portuguese (Brazil). Other examples of locales include Canadian English and U.S. English.

This was reported and fixed in #62496. It’s a follow-up to the email localization change introduced in WordPress 6.7, where this instance was missed. Now, plugin update emails are correctly sent in the admin locale (if the admin email matches a user on the site).

See [59460] and [59478] for details.

Just-in-time translationtranslation The process (or result) of changing text, words, and display formatting to support another language. Also see localization, internationalization. loading for plugins/themes not in the WordPress.orgWordPress.org The community site where WordPress code is created and shared by the users. This is where you can download the source code for WordPress core, plugins and themes as well as the central location for community conversations and organization. https://wordpress.org/ directory

Back in version 4.6, WordPress introduced just-in-time translation loading for any plugin or theme that is hosted on WordPress.org. That meant plugins no longer had to call load_plugin_textdomain() or load_theme_textdomain().

With WordPress 6.8, this is now expanded to all other plugins and themes by looking at the text domain information provided by the plugin/theme. Extensions with a custom Text Domain and Domain Path headerHeader The header of your site is typically the first thing people will experience. The masthead or header art located across the top of your page is part of the look and feel of your website. It can influence a visitor’s opinion about your content and you/ your organization’s brand. It may also look different on different screen sizes. no longer need to call load_plugin_textdomain() or load_theme_textdomain(). This reduces the risk of calling them too late, after some translation calls already happened, and generally makes it easier to properly internationalize a plugin or theme.

In short:

  • If your plugin/theme is hosted on WordPress.org and requires WordPress 4.6 or higher: you don’t need to use load_*_textdomain()
  • Else, if your plugin/theme provides the Text Domain and Domain Path headers and requires WordPress 6.8 or higher: you don’t need to use load_*_textdomain()

See #62244 for more.


Props to @audrasjb, @stevenlinx for review.

#6-8, #dev-notes, #dev-notes-6-8, #i18n

Internationalization improvements in 6.7

Various internationalization (i18n) improvements are in WordPress 6.7, and this developers note focuses on these.

Determining whether a translationtranslation The process (or result) of changing text, words, and display formatting to support another language. Also see localization, internationalization. exists

Sometimes it can be useful to know whether a translation already exists for in memory without having to first load the translation for the given text domain. The new has_translation() function allows for exactly that.

See #52696 / [59029] for more details.

Sending emails in the adminadmin (and super admin)’s localeLocale A locale is a combination of language and regional dialect. Usually locales correspond to countries, as is the case with Portuguese (Portugal) and Portuguese (Brazil). Other examples of locales include Canadian English and U.S. English.

Back in version 4.7, WordPress added the ability for users to set their preferred locale. When sending emails to a user, they are always sent in that locale, and everyone else receives the email in the site’s locale.

Now, WordPress 6.7 is going a step further: every time an email is sent to the administrator email address (admin_email), WordPress checks if a user with the same email address exists. If so, the email is sent in that user’s locale.

See #61518 / [59128] for more details.

Warnings if translations are loaded too early

WordPress now warns developers if they are loading translations too early in a pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party or theme, before the current user is known. Existing functions like load_plugin_textdomain() and load_theme_textdomain() were updated to defer the actual loading to the existing just-in-time translation logic in coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress.. This reduces the likelihood of triggering the warning, and even improves performance in some situations by avoiding loading translations if they are not needed on a given page.

Reminder: if your plugin or theme is hosted on WordPress.orgWordPress.org The community site where WordPress code is created and shared by the users. This is where you can download the source code for WordPress core, plugins and themes as well as the central location for community conversations and organization. https://wordpress.org/ and is still using load_*_textdomain(), you can remove this call. Since WordPress 4.6, plugins and themes no longer need load_plugin_textdomain() or load_theme_textdomain(). WordPress automatically loads the translations for you when needed. If you still support older WordPress versions or do not host your plugin/theme on WordPress.org, move the function call to a later hook such as init.

When attempting to load translations before after_setup_theme or init, WordPress tries to load the current user earlier than usual, without giving other plugins a chance to potentially hook into the process. It also prevents any plugins from filtering translation calls, e.g. for switching the locale or file location. Hence the addition of this warning to call out this unexpected behavior.

See #44937, [59127], and [59157] for more details.

Your plugin might be _doing_it_wrong() if you for example directly call get_plugin_data() (which attempts to load translations by default) or __() without waiting for the init hook. Here is a common example that was found in an actual plugin that was fixed:

/**
 * Plugin Name: Awesome Plugin
 */

function myplugin_get_version() {
	require_once ABSPATH . 'wp-admin/includes/plugin.php';
	// Prevent early translation call by setting $translate to false.
	$plugin_data = get_plugin_data( __FILE__, false, /* $translate */ false );
	return $plugin_data['Version'];
}

define( 'MYPLUGIN_VERSION', myplugin_get_version() );

If you do not explicitly set $translate set to false when calling get_plugin_data(), the function translates the plugin metadata by default. Since this plugin just needs the version number, there is no need for translating any of the other fields.

Another example:

/**
 * Plugin Name: Awesome Plugin
 */

class My_Awesome_Plugin {
	public $name;
	public function __construct() {
		// This triggers just-in-time translation loading
		$this->name = __( 'My Awesome Plugin', 'my-awesome-plugin' );

		// ... do something
	}
}

// This immediately instantiates the class, way before `init`.
$myplugin = new My_Awesome_Plugin();

Here, a class is immediately instantiated in the main plugin file, and code within the class constructor uses a translation function. This can be avoided by deferring the class instantiation until after init, or deferring the translation call until later when it is actually needed.

If your plugin is affected by this warning, you can use code like follows to find out the code path that triggers it:

add_action(
	'doing_it_wrong_run',
	static function ( $function_name ) {
		if ( '_load_textdomain_just_in_time' === $function_name ) {
			debug_print_backtrace();
		}
	}
);

Developer tools such as Query Monitor are also helpful in situations like this.


Props to @ocean90, @fabiankaegy for review.

#6-7, #dev-notes, #dev-notes-6-7, #i18n

Miscellaneous developer changes in WordPress 6.6


Table of contents


Autosave

Allowed disabling autosave support for individual post types

[58201] added a way to allow disabling autosave support for individual post types. Not all post types support autosaving. By making autosave a post type feature, support can be more granularly handled without any workarounds or hardcoded allowlists. For backward compatibility reasons, adding editor support implies autosave support, so one would need to explicitly use remove_post_type_support() to remove it.

See #41172 for more details.

Bundled Theme

Twenty Sixteen: Fixed mismatch of visual and DOM order of elements

Starting in Twenty Sixteen’s version 3.3 (released with WordPress 6.6), the site information links remain below the social navigation at any screen size. Before that, the social navigation had displayed after the site information on larger screens, which created a mismatch between the visual order and the Document Object Model (DOM) order.

Site, Privacy Policy, and Proudly powered by WordPress links appear beneath three social icon links in the site footer
The two footer elements are stacked, now at screen widths larger than 910 pixels.

If you would like to have the two elements side-by-side, with the social navigation first, you could paste styles in a child themeChild theme A Child Theme is a customized theme based upon a Parent Theme. It’s considered best practice to create a child theme if you want to modify the CSS of your theme. https://developer.wordpress.org/themes/advanced-topics/child-themes/. or in the Customizer’s Additional CSS panel.

Check the instructions on how to do this
@media screen and (min-width: 56.875em) {
	/*
	  1. Reset the social navigation width.
	  2. Adjust margins to place site info along the right edge.
	*/
	.site-footer .social-navigation {
		width: auto;
		margin: 0.538461538em auto 0.538461538em 0;
	}
	.site-info {
		margin: 0;
	}


	/* Reverse the margins for right-to-left languages. */
	.rtl .site-footer .social-navigation {
		margin: 0;
	}
	.rtl .site-info {
		margin: 0.538461538em auto 0.538461538em 0;
	}
}
Three social icon links appear on the left side of the site footer, but Site, Privacy Policy, and Proudly powered by WordPress links are on the right.
Custom CSSCSS Cascading Style Sheets. could place the site information links on the right side.

See #60496 for more details.

Comments

Default length of time for comment author cookies has changed

[58401] changed the default length of time for comment author cookies from 0.95129375951 of a year to 1 year by taking advantage of the YEAR_IN_SECONDS constant. The comment_cookie_lifetime filterFilter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output. can still be used to change this value.

See #61421 for more details.

Editor

Site Editor Patterns on Classic Themes

#61109 now directs a classic theme’s Appearance > Patterns menu to the site editor Patterns view (/wp-admin/site-editor.php?path=/patterns), providing a consistent pattern and template management experience regardless of theme type. For themes with block-template-parts support, the Appearance > Template Parts menu has been removed, with template parts now accessible under the site editor’s Patterns > Template Parts view.

Fluid Typography

Some theme.json presets require custom logic to generate their values, for example, when converting font size preset values to clamp() values.

The custom logic is handled by callback functions defined against the value_func key in WP_Theme_JSON::PRESETS_METADATA. The callback functions are invoked in WP_Theme_JSON::get_settings_values_by_slug().

In WordPress 6.6, settings of the current WP_Theme_JSON instance, are now passed to these callback functions. The permits callback functions to return values that rely on other settings in the theme.jsonJSON JSON, or JavaScript Object Notation, is a minimal, readable format for structuring data. It is used primarily to transmit data between a server and web application, as an alternative to XML. tree.

In the case of font sizes presets, it fixes a bug whereby the callback function — wp_get_typography_font_size_value() — was not taking into account settings values passed directly to the WP_Theme_JSON class.

External libraries

jQuery UIUI User interface library update

The jQuery UI library was updated to version 1.13.3. For more information on the changes included, see jQuery UI 1.13.3 release notes.

Login and Registration

New array arguments for wp_login_form

The wp_login_form() function has two new array arguments: required_username and required_password. Passing true to these arguments adds the ‘required’ attribute to the input fields.

$args = array(
    'required_username' => true,
    'required_password' => true,
);
wp_login_form( $args );

There is no change to the default field output.

See #60062 for more details.

Multisitemultisite Used to describe a WordPress installation with a network of multiple blogs, grouped by sites. This installation type has shared users tables, and creates separate database tables for each blog (wp_posts becomes wp_0_posts). See also network, blog, site

Custom ports for multisite site addresses

#21077 made it possible to install and operate a Multisite installation on a host name that includes a port number, and the corresponding #52088 added full support for this to the local development environment. This means it’s now possible to run Multisite on an address such as localhost:8889.

Update enabled mime types for new multisite installs

In #53167, the list of mime types that are enabled for upload were aligned to those enabled by regular sites by switching from a hard-coded list of types (that had become outdated) to using coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress.’s get_allowed_mime_types function. This ensures that new multisite installs are up to date with the current mime types supported in core, including the recently enabled image/webp and image/avif types.

Note that, since this is only used to populate the schema for new networks, it will only affect newly created multisite networks – it does not change the allowed mime types for existing networks. To adjust the mime types allowed for existing sites, developers can continue to use an approach as follows for filtering the upload_filetypes option:

Script Loader

Obsolete polyfills dependencies have been removed

In [57981], now obsolete polyfills such as wp-polyfill, wp-polyfill-inert and regenerator-runtime were removed from the react script dependency in WordPress, as they are no longer needed in modern browsers supported by WordPress. Developers relying on wp-polyfill need to manually add it as a dependency to their scripts.

See #60962 for more details.

Script modules can now be used in the WordPress adminadmin (and super admin)

With #61086, script modules can now be used in the WordPress admin. Before WordPress 6.6, script modules were only available on the front end.

Toolbar

Search has a much later priority

In [58215], the search input on the front-end admin bar is added at a different priority. It was previously inserted at priority 4 and then floated to appear at the end of the admin bar. It is now inserted at priority 9999 to load at the end of the admin bar without CSS manipulation.

Extenders placing admin bar nodes after the search or replacing core search should take the new priority into consideration.

Example: Assign different priority based on WordPress version

$priority = ( version_compare( $GLOBALS['wp_version'], '6.6-alpha', '>=' ) ) ? 4 : 9999;
add_action( 'admin_bar_menu', 'wpadmin_toolbar_test_link', $priority );
/**
 * Add a node to the WP admin toolbar.
 *
 * @param object $wp_admin_bar WP Admin Bar object.
 */
function wpadmin_toolbar_test_link( $wp_admin_bar ) {
	$wp_admin_bar->add_node(
		array(
			'parent' => 'top-secondary',
			'id'     => 'mylink',
			'href'   => '#',
			'title'  => __( 'My Link' ),
		)
	);
}

See #60685 for more details.


Props to @swissspidy, @jorbin, @johnbillion, @audrasjb, @joedolson, @ironprogrammer, @ramonopoly, @jonsurrell, @sabernhardt, @jdy68, @afercia and @juanmaguitar for their contribution and/or reviews.

#6-6, #dev-notes, #dev-notes-6-6

Internationalization improvements in 6.6

Various internationalization (i18n) improvements are in WordPress 6.6, and this developers note focuses on these.

Enhanced support for only using PHPPHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 7.4 or higher translationtranslation The process (or result) of changing text, words, and display formatting to support another language. Also see localization, internationalization. files

WordPress 6.5 shipped with a completely new localization system with improved performance, which uses .l10n.php files in addition to .po and .mo files. This system was slightly enhanced in 6.6 to better support scenarios where only these PHP translation files exist, but not the others. This specifically applies to wp_get_installed_translations(), which is used to check which translations are installed, and the Language_Pack_Upgrader for updating translations.

See #60554 for more details.

New lang_dir_for_domain filterFilter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output.

A new lang_dir_for_domain filter has been added to WP_Textdomain_Registry, allowing plugins to override the determined languages folder when using just-in-time translation loading. This is mostly useful for multilingual plugins.

See #61206 for more details.

Additional context for the load_translation_file filter

The load_translation_file filter was introduced in WordPress 6.5 to support changing the file path when loading translation files, regardless if it’s a PHP or an MO translation file. In 6.6, the localeLocale A locale is a combination of language and regional dialect. Usually locales correspond to countries, as is the case with Portuguese (Portugal) and Portuguese (Brazil). Other examples of locales include Canadian English and U.S. English. is passed as an additional argument to this filter, bringing it more in line with similar i18ni18n Internationalization, or the act of writing and preparing code to be fully translatable into other languages. Also see localization. Often written with a lowercase i so it is not confused with a lowercase L or the numeral 1. Often an acquired skill. filters.

See #61108 for more details.

Props to @audrasjb and @juanmaguitar for review.

#6-6, #dev-notes, #dev-notes-6-6, #i18n

Merge Proposal: Preferred Languages

Almost 8 years ago the Preferred Languages feature project was kicked off in response to a feature requestfeature request A feature request should generally begin the process in the ideas forum, on a mailing list, as a plugin, or brought to the attention of the core team, such as through scope meetings held for each major release. Unsolicited tickets of this variety are typically, therefore, discouraged. in #28197. Right now it is probably the oldest active feature pluginFeature Plugin A plugin that was created with the intention of eventually being proposed for inclusion in WordPress Core. See Features as Plugins.. Over time there were numerous updates, bugbug A bug is an error or unexpected result. Performance improvements, code optimization, and are considered enhancements, not defects. After feature freeze, only bugs are dealt with, with regressions (adverse changes from the previous version) being the highest priority. fixes, and even a complete refactor. Preferred Languages was always built and maintained with the goal in mind to merge it into coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. one day. Now the time is finally right to do so.

Purpose & Goals

As a quick reminder, Preferred Languages replaces the existing languages dropdown with a supercharged version that lets you select multiple preferred languages. WordPress then tries to load the translations for the first language that’s available, falling back to the next language in your list otherwise. Without this, WordPress would just fall back to English (US) in such cases, which is not a great experience. Such a UIUI User interface is a pretty standard feature that can be seen for example also in operating system and browser settings.

Preferred Languages UI, showing the list of selected languages on the settings page.
Example of the Preferred Languages UI on the settings page

Note: Preferred Languages works for both the site language (can be set at Settings -> General) and the user language (can be set in the profile).

Project Background

You may wonder why it took such a long time. Since the project’s inception, a lot has changed in WordPress. For example, GutenbergGutenberg The Gutenberg project is the new Editor Interface for WordPress. The editor improves the process and experience of creating new content, making writing rich content much simpler. It uses ‘blocks’ to add richness rather than shortcodes, custom HTML etc. https://wordpress.org/gutenberg/ happened. That’s why Preferred Languages saw a complete rewrite using the same ReactReact React is a JavaScript library that makes it easy to reason about, construct, and maintain stateless and stateful user interfaces. https://reactjs.org/. components that also power the blockBlock Block is the abstract term used to describe units of markup that, composed together, form the content or layout of a webpage using the WordPress editor. The idea combines concepts of what in the past may have achieved with shortcodes, custom HTML, and embed discovery into a single consistent API and user experience. editor. With Gutenberg we also saw the introduction of JavaScript localization, which required further iterations to Preferred Languages. Then there was a need for merging incomplete translations, reducing the chances that you see missing strings in English. However, merging translations was very bad for performance, as it involves loading lots of translationtranslation The process (or result) of changing text, words, and display formatting to support another language. Also see localization, internationalization. files. In WordPress 6.5 we finally completely replaced the localization library with a more performant solution that natively supports loading multiple files at once. So this last remaining blockerblocker A bug which is so severe that it blocks a release. is now finally resolved!

Internationalization and localization is a core part of WordPress and relevant for more than half of all users. That’s why this functionality belongs natively into WordPress core and not in a (canonical) plugin. Merging Preferred Languages into core would allow the fallback logic to run much closer to where translation loading happens, reducing the risk for bugs and pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party incompatibilities. Plus, the UI impact is minimal, as it simply expands an existing language dropdown with additional features.

Implementation Details

The UI is built using TypeScript and React and the @wordpress/* npm packages also used for Gutenberg. This makes for a consistent look & feel and will make it easy to integrate it into any revamped WordPress adminadmin (and super admin) UI. The back end parts were developed in such a way that merging them into core eventually is as straightforward as possible, so a patchpatch A special text file that describes changes to code, by identifying the files and lines which are added, removed, and altered. It may also be referred to as a diff. A patch can be applied to a codebase for testing. can be developed relatively quickly.

Preferred Languages has been tested in production websites over numerous years by thousands of users. It works in all major browsers supported by WordPress, follows accessibilityAccessibility Accessibility (commonly shortened to a11y) refers to the design of products, devices, services, or environments for people with disabilities. The concept of accessible design ensures both “direct access” (i.e. unassisted) and “indirect access” meaning compatibility with a person’s assistive technology (for example, computer screen readers). (https://en.wikipedia.org/wiki/Accessibility) best practices, and gracefully falls back to the old single language dropdown if JavaScriptJavaScript JavaScript or JS is an object-oriented computer programming language commonly used to create interactive effects within web browsers. WordPress makes extensive use of JS for a better user experience. While PHP is executed on the server, JS executes within a user’s browser. https://www.javascript.com/. is disabled.

Contributors and Feedback

While I (@swissspidy) have been the lead developer of the plugin, valuable input and contributions have come from others in the community.

This is a proposal and is subject to revision based on your feedback. If you haven’t already tried out the plugin, please download and install it from WordPress.orgWordPress.org The community site where WordPress code is created and shared by the users. This is where you can download the source code for WordPress core, plugins and themes as well as the central location for community conversations and organization. https://wordpress.org/ or the comfort of your WordPress admin. You can review the current code and leave feedback at the project’s GitHub repository or in #core-i18n on SlackSlack Slack is a Collaborative Group Chat Platform https://slack.com/. The WordPress community has its own Slack Channel at https://make.wordpress.org/chat/..

All feedback will be collected over the next couple of weeks. After that, the received feedback will be discussed and next steps determined. The goal is to work on and land a patch quickly to ensure that the feature gets plenty of testing in WordPress trunktrunk A directory in Subversion containing the latest development code in preparation for the next major release cycle. If you are running "trunk", then you are on the latest revision..

Props to @ocean90 for reviewing this post.

#6-6, #feature-plugins, #feature-projects, #i18n, #merge-proposals, #polyglots, #preferred-languages

I18N Improvements in 6.5 (Performant Translations)

Various internationalization (i18n) improvements are in WordPress 6.5, and this developers note will focus on these.

New localization system with improved performance

Over the past year, WordPress contributors have meticulously analyzed performance of the existing i18ni18n Internationalization, or the act of writing and preparing code to be fully translatable into other languages. Also see localization. Often written with a lowercase i so it is not confused with a lowercase L or the numeral 1. Often an acquired skill. system in WordPress and ultimately created a new Performant Translations feature pluginFeature Plugin A plugin that was created with the intention of eventually being proposed for inclusion in WordPress Core. See Features as Plugins. that provided a completely overhauled system with significantly better performance. After thousands of betaBeta A pre-release of software that is given out to a large group of users to trial under real conditions. Beta versions have gone through alpha testing in-house and are generally fairly close in look, feel and function to the final product; however, design changes often occur as part of the process. testers and a merge announcement late last year, this new library is now included in WordPress 6.5! See #59656 for all the details.

The Performant Translations pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party is still useful and will continue to be maintained to build on top of the coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. solution with a distinct additional feature. As is already the case today, the plugin will automatically convert any .mo files to PHPPHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 7.4 or higher files if a PHP file does not currently exist. This is useful for sites where translations are not coming from translate.wordpress.org or only exist locally on that server.

This new library is faster at loading binary .mo files and uses less memory. It even supports loading multiple locales at the same time, which makes locale switching faster. In addition to that, it supports translations contained in PHP files, avoiding a binary file format and leveraging OPCache if available.

The new library is so fast, in fact, that it paves the way for the Preferred Languages feature plugin to merge translations of multiple locales by default starting with WordPress 6.5.

While this is in large part a silent and backward-compatible under-the-hood change, there are still a few things to be aware of:

New .l10n.php translationtranslation The process (or result) of changing text, words, and display formatting to support another language. Also see localization, internationalization. file format

When downloading language packs from WordPress.orgWordPress.org The community site where WordPress code is created and shared by the users. This is where you can download the source code for WordPress core, plugins and themes as well as the central location for community conversations and organization. https://wordpress.org/, there will be a new .l10n.php file in addition to the .mo and .po files you are already familiar with. If an .mo translation file has a corresponding .l10n.php file, the latter will be loaded instead, making things even faster and use even less memory.

This is a progressive enhancementenhancement Enhancements are simple improvements to WordPress, such as the addition of a hook, a new feature, or an improvement to an existing feature., so if there’s only an .mo file but no PHP file, translations will still be loaded as expected. However, the opposite is also true! So you can theoretically use only .l10n.php translation files in your project and features such as the just-in-time translation loading continue to work. Right now, WordPress still expects corresponding .po and .mo files for things like update checks. However, this limitation will be addressed in the future, see #60554 for more information.

Note: if you don’t see any .l10n.php translation files in wp-content/languages yet, it might be that the language pack hasn’t been updated in a while, i.e. there were no new translations.

Here’s an example of a PHP translation file as supported by WordPress 6.5:

<?php
return [
'project-id-version' => 'WordPress - 6.5.x - Development',
'report-msgid-bugs-to' => 'polyglots@example.com',
'messages' =>
[
'original' => 'translation',
'contextEOToriginal with context' => 'translation with context',
'plural0' => 'translation0' . "\0" . 'translation1',
'contextEOTplural0 with context' => 'translation0 with context' . "\0" . 'translation1 with context',
'Product' => 'Produkt' . "\0" . 'Produkte',
],
];

Note: EOT here stands for the “End of Transmission” character (U+0004, or "\4" in PHP). It’s the same delimiter as in gettext used to glue the context with the singular string.

Generating PHP translation files

If you would like to generate these PHP translation files yourself, version 4.0 of GlotPress, the plugin that powers translate.WordPress.org, already supports the new .l10n.php format.

In addition to that, WP-CLI 2.10.0 (i18n-command 2.6.0) provides a new wp i18n make-php command to create these PHP files from a given .po file. Examples:

# Create PHP files for all PO files in the current directory.
$ wp i18n make-php .

# Create a PHP file from a single PO file in a specific directory.
$ wp i18n make-php example-plugin-de_DE.po languages

If you are developing a WordPress plugin that deals with translations, you can also use the new WP_Translation_File class to convert an .mo file into a PHP file. Example:

$contents = WP_Translation_File::transform( $mofile, 'php' );
if ( $contents ) {
file_put_contents( $path_to_php_file, $contents );
}

New filters to customize this behavior

If you would like to disable the support for PHP files for some reason; for example, if you don’t have any yet in your project and want to prevent the extra file lookup operation, you can use the new translation_file_format filterFilter Filters are one of the two types of Hooks https://codex.wordpress.org/Plugin_API/Hooks. They provide a way for functions to modify data of other functions. They are the counterpart to Actions. Unlike Actions, filters are meant to work in an isolated manner, and should never have side effects such as affecting global variables and output. to change the preferred format (default is php) like so:

add_filter(
'translation_file_format',
static function () {
return 'mo';
}
);

The existing load_textdomain_mofile filter can still be used to filter the .mo file path for loading translations for a specific text domain. However, it only works for .mo files. To filter the path for a translation file, be it a .l10n.php or a .mo file, use the new load_translation_file filter.

Working with the $l10n global variable

Previously, when loading translations, WordPress would store an instance of the MO class in the $l10n global variable. With WordPress 6.5, this will be an instance of a new WP_Translations class that acts as a shim with similar characteristics. If your project directly works with this global variable or the MO class in some way, this is an area to keep an eye on.

Cached list of language file paths

This another slight performance improvement but unrelated to the new localization library covered above.

In places such as get_available_languages() and WP_Textdomain_Registry, WordPress used to directly use the glob() function to retrieve all .mo files in a specific directory. This is important for just-in-time translation loading and generally knowing which translations are installed. However, on sites with a large number of language files, the glob() operation can become expensive.

Because of this, a new caching mechanism was introduced in #58919 / [57287]. The file lookup is now handled centrally in WP_Textdomain_Registry and stored in the object cache in the translations group, with the cache key having the format cached_mo_files_<hash>, where <hash> is the MD5 hash of the scanned directory, e.g. wp-content/languages. The cache is cleared whenever language packs are updated.

Also, the lookup now also scans for .l10n.php files in addition to .mo files, in case only the former exist on a site.

More questions? Please let us know

If you have any questions, please leave a comment below or file a new ticket on Trac under the I18N component if you’ve encountered any bugs.

Props to @joemcgill, @stevenlinx for review.

#6-5, #dev-notes, #dev-notes-6-5, #i18n

Merging Performant Translations into Core

The coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. performance team spent a lot of time this year looking into the performance of the i18ni18n Internationalization, or the act of writing and preparing code to be fully translatable into other languages. Also see localization. Often written with a lowercase i so it is not confused with a lowercase L or the numeral 1. Often an acquired skill./l10nL10n Localization, or the act of translating code into one's own language. Also see internationalization. Often written with an uppercase L so it is not confused with the capital letter i or the numeral 1. WordPress has a capable and dynamic group of polyglots who take WordPress to more than 70 different locales. system in WordPress, after proving that loading translations had a significant hit on response time. This led to an in-depth performance analysis, followed by a dedicated Performant Translations feature pluginFeature Plugin A plugin that was created with the intention of eventually being proposed for inclusion in WordPress Core. See Features as Plugins. offering significant performance boosts for all WordPress sites with zero configuration. Thousands of sites successfully tested the pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party under a wide variety of conditions. Now, the team believes the solution is ready for inclusion in WordPress core.

What it does

Performant Translations is powered by a new, lightweight i18n library that is faster at loading binary MO files and uses less memory. It even supports loading multiple locales at the same time, which makes locale switching faster. In addition to that, it supports translations contained in PHPPHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 7.4 or higher files, avoiding a binary file format and leveraging OPCache if available. If an MO translationtranslation The process (or result) of changing text, words, and display formatting to support another language. Also see localization, internationalization. file has a corresponding PHP file, the latter will be loaded instead, making things even faster and use even less memory. In raw numbers, this is how great the optimization is with this approach:

LocaleLocale A locale is a combination of language and regional dialect. Usually locales correspond to countries, as is the case with Portuguese (Portugal) and Portuguese (Brazil). Other examples of locales include Canadian English and U.S. English.ScenarioMemory UsageLoad Time
en_USDefault15 MB159 ms
de_DEDefault29 MB217 ms
de_DEPerformant Translations17 MB166 ms

These numbers were taken by testing the Performant Translations plugin against WordPress 6.5-alpha-57028 with the Twenty Twenty-One theme and a few active plugins. As you can see, memory usage and load time overhead are reduced to a minimum.

Next steps

The core performance team has opened #59656 to track merging Performant Translations into core in time for the next 6.5 release. A pull request is already available and currently undergoing code review. Once that is completed, it will be ready to be merged into trunktrunk A directory in Subversion containing the latest development code in preparation for the next major release cycle. If you are running "trunk", then you are on the latest revision. where the library will be able to see even wider testing.

There is also a Meta patch ready for serving PHP files as part of language packs shipped by translate.wordpress.org, building upon a GlotPress PR. Both are in need of code review right now. While these two changes unlock the full power of Performant Translations, they are not blockers for the core merge and could even land later.

The Performant Translations plugin will continue to be maintained even after a core merge to build on top of the core solution with a distinct additional feature. As is already the case today, the plugin will automatically convert any MO files to PHP files if a PHP file does not currently exist. This is useful for sites where translations are not coming from translate.wordpress.org or only exist locally on that server.


Thank you to @mukesh27, @westonruter for reviewing and helping with this post.

#core, #i18n, #performance

WordPress core is now using Playwright for all browser-based tests

Early last year, a plan was outlined to phase out all Puppeteer usage across WordPress coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. and GutenbergGutenberg The Gutenberg project is the new Editor Interface for WordPress. The editor improves the process and experience of creating new content, making writing rich content much simpler. It uses ‘blocks’ to add richness rather than shortcodes, custom HTML etc. https://wordpress.org/gutenberg/ step by step. Since then, a lot of progress has been made:

  • The @wordpress/e2e-test-utils-playwright package has become more mature and already provides many useful utilities that cover the needs for core and Gutenberg.
  • The @wordpress/scripts package, which is widely used in the ecosystem, now not only supports Puppeteer but also Playwright, making it straightforward for projects to migrate their existing setups.
  • The majority of e2e tests in Gutenberg have already been migrated from Puppeteer to Playwright, as can be seen in this tracking issue. This includes all performance tests.

Now, another major milestone has been reached: all browser-based tests in WordPress core now use Playwright! This includes end-to-end (e2e) tests, performance tests, and visual regressionregression A software bug that breaks or degrades something that previously worked. Regressions are often treated as critical bugs or blockers. Recent regressions may be given higher priorities. A "3.6 regression" would be a bug in 3.6 that worked as intended in 3.5. tests. See #59517 for full details.

How does this affect contributors?

As mentioned in the original proposal, Playwright makes it easier to write stable tests. Thanks to a built-in test runner with superior debugging tools, auto-waiting, and advanced selectors support, Playwright offers the tools necessary to write tests that are easy to understand and cause less headaches because of random timeouts or similar. It also supports many browsers out of the box, which will help strengthen the end-to-end test coverage in core.

Since Playwright is originally a forked version of Puppeteer, it offers a very similar APIAPI An API or Application Programming Interface is a software intermediary that allows programs to interact with each other and share data in limited, clearly defined ways., so contributors writing and debugging tests should be familiar with the way things work.

If you want to get familiar with Playwright, check out Gutenberg’s migration guide as well as the official Playwright documentation. The migrationMigration Moving the code, database and media files for a website site from one server to another. Most typically done when changing hosting companies. guide can be used to migrate Puppeteer-based tests from unmerged patches/PRs to the new setup.

End-to-end tests are still run using npm run test:e2e, with npm run test:e2e -- --ui running them in an interactive mode for easier debugging.

Playwright support was just added recently, so you might need to run npm install first to ensure the latest dependencies are installed.

Note: If you previously ran visual regression tests using npm run test:visual, the storage location for visual snapshots was changed from tests/visual-regression/specs/image_snapshots to tests/visual-regression/specs/snapshots. You can safely remove the files from the old folder if they show up in version controlversion control A version control system keeps track of the source code and revisions to the source code. WordPress uses Subversion (SVN) for version control, with Git mirrors for most repositories..


Props to @mamaduka for reviewing this post.

#e2e-tests, #gutenberg, #playwright, #puppeteer

Call for Testing: Performant Translations

The coreCore Core is the set of software required to run WordPress. The Core Development Team builds WordPress. performance team recently conducted an in-depth i18n performance analysis. It showed that localized WordPress sites load significantly slower than a site without translations. The blogblog (versus network, site) post presented and compared multiple solutions to this problem, and now the team would like to test the most promising approach at a wider scale using a dedicated pluginPlugin A plugin is a piece of software containing a group of functions that can be added to a WordPress website. They can extend functionality or add new features to your WordPress websites. WordPress plugins are written in the PHP programming language and integrate seamlessly with WordPress. These can be free in the WordPress.org Plugin Directory https://wordpress.org/plugins/ or can be cost-based plugin from a third-party.

Introducing the Performant Translations plugin

What it does

The Performant Translations plugin uses a new approach to handle translationtranslation The process (or result) of changing text, words, and display formatting to support another language. Also see localization, internationalization. files in WordPress, making localization blazing fast. The primary purpose of this plugin is to allow broader testing of these enhancements, for which the goal is to eventually land in WordPress core.

This plugin helps to make localized WordPress sites faster by replacing the traditional MO translation files with PHPPHP The web scripting language in which WordPress is primarily architected. WordPress requires PHP 7.4 or higher files, which are much faster to parse. Plus, PHP files can be stored in the so-called OPcache, which provides an additional speed boost.

If your site is using a language other than English (US), you should see immediate speed improvements simply by activating this plugin. No further action is required.

The Performant Translations plugin is available for download on WordPress.orgWordPress.org The community site where WordPress code is created and shared by the users. This is where you can download the source code for WordPress core, plugins and themes as well as the central location for community conversations and organization. https://wordpress.org/ or directly from your WordPress adminadmin (and super admin).

What to test and expect

Since the Performant Translations plugin requires no configuration, all that’s needed to benefit from its speed improvements is to activate the plugin.

To verify that something has changed, you could use a tool like Query Monitor or an external tool for testing server response times. In Query Monitor, the page load time and memory usage should drop quite a bit after plugin activation:

In Query Monitor you will also see how translations are loaded from PHP files from now on:

Query Monitor development tools, showing a list of text domains

While the plugin is mostly considered to be a betaBeta A pre-release of software that is given out to a large group of users to trial under real conditions. Beta versions have gone through alpha testing in-house and are generally fairly close in look, feel and function to the final product; however, design changes often occur as part of the process. testing plugin, it has been tested and established to a degree where it should be okay to use in production. Still, as with every plugin, you are doing so at your own risk.

It’s also worth noting that the plugin has been successfully tested with common multilingual plugins, such as WPML, Weglot, TranslatePress, MultilingualPress, and Polylang. It also works fine with Loco Translate and the Preferred Languages feature pluginFeature Plugin A plugin that was created with the intention of eventually being proposed for inclusion in WordPress Core. See Features as Plugins..

Should you choose to stop testing the Performant Translation plugins, uninstalling it will remove all of its traces.

Provide your feedback

If you encounter any issues or simply have questions about the plugin, please leave a comment below or open a new support topic. In addition to that, contributions can be made on GitHub.

The performance team’s goal is to get as much feedback as possible and further refine the approach so that it can ultimately be proposed to be merged into WordPress core 6.5. That means testing will last for a few months at least.

+make.wordpress.org/test/

#call-for-testing, #core, #feature-plugins, #i18n, #needs-testing, #performance