The WordPress coreCoreCore is the set of software required to run WordPress. The Core Development Team builds WordPress. development team builds WordPress! Follow this site for general updates, status reports, and the occasional code debate. There’s lots of ways to contribute:
Found a bugbugA 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.?Create a ticket in the bug tracker.
Almost 8 years ago the Preferred Languages feature project was kicked off in response to a feature requestfeature requestA 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 PluginA 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, bugbugA 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 coreCoreCore 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 UIUIUser interface is a pretty standard feature that can be seen for example also in operating system and browser settings.
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, GutenbergGutenbergThe 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 ReactReactReact 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 blockBlockBlock 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 translationtranslationThe 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 blockerblockerA 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 pluginPluginA 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 patchpatchA 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 accessibilityAccessibilityAccessibility (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 JavaScriptJavaScriptJavaScript 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.orgThe 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 SlackSlackSlack 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 trunktrunkA 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..
Welcome back to a new issue of Week in CoreCoreCore is the set of software required to run WordPress. The Core Development Team builds WordPress.. Let’s take a look at what changed on TracTracAn open source project by Edgewall Software that serves as a bug tracker and project management tool for WordPress. between February 12 and February 19, 2024.
23 commits
43 contributors
81 tickets created
13 tickets reopened
88 tickets closed
TicketticketCreated for both bug reports and feature development on the bug tracker. numbers are based on the Trac timeline for the period above. The following is a summary of commits, organized by component and/or focus.
Code changes
Build/Test Tools
Ignore src/wp-content/fonts from version controlversion controlA 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. – #60337
Remove more unnecessary direct dependencies – #59658
Use assertSame() in WP_Query tests involving ::$max_num_pages property – #58683, #59655
Use assertSame() in get_comment_pages_count() tests – #58683, #59655
Bundled Themes
Twenty Nineteen: Update selectors used to change the primary color in the CustomizerCustomizerTool built into WordPress core that hooks into most modern themes. You can use it to preview and modify many of your site’s appearance settings. – #59922
Twenty Twenty-Four: Increase the color contrast of the Ember style variation – #60459
Support pullquote blockBlockBlock 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. typography options in Twenty Twenty-One – #57854
Canonical
Limit post types searched by redirect_guess_404_permalink() – #59795
Rename admin_canonical_urlfilterFilterFilters 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 wp_admin_canonical_url – #59545
Coding Standards
Allow $newlineEscape parameter in WP_Text_Diff_Renderer_inline::_splitOnWords() – #59650
Docs
Various improvements and corrections to inline documentation – #59651
Editor
Check PHPPHPThe web scripting language in which WordPress is primarily architected. WordPress requires PHP 5.6.20 or higher 8.1.12 for woff/woff2 mime types in WP_Font_Utils – 60536
Merge uses_context defined by block bindings sources with block types – #60525
Prevent PHP warning when parsing duotone hue values – #59496
Interactivity APIAPIAn 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.: Skip instead of bail out if HTMLHTMLHyperText Markup Language. The semantic scripting language primarily used for outputting content in web browsers. contains SVG or MATH – #60517
Interactivity API: Use string instead of object in data-wp-interactive attribute – #60542, #60356
General
Consistently cast return value to int in functions that use ceil() – #58683
Further improve language in SimplePie code comments – #60247
I18Ni18nInternationalization, 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.
Prevent incorrect language dropdown entries when there are .l10n.php files – #59656, #60553
REST APIREST APIThe REST API is an acronym for the RESTful Application Program Interface (API) that uses HTTP requests to GET, PUT, POST and DELETE data. It is how the front end of an application (think “phone app” or “website”) can communicate with the data store (think “database” or “file system”) https://developer.wordpress.org/rest-api/.
Clarify documentation for methods and filters relating to REST API search endpoints – #59651
Welcome back to a new issue of Week in CoreCoreCore is the set of software required to run WordPress. The Core Development Team builds WordPress.. Let’s take a look at what changed on TracTracAn open source project by Edgewall Software that serves as a bug tracker and project management tool for WordPress. between February 5 and February 12, 2024.
71 commits
245 contributors
82 tickets created
11 tickets reopened
82 tickets closed
TicketticketCreated for both bug reports and feature development on the bug tracker. numbers are based on the Trac timeline for the period above. The following is a summary of commits, organized by component and/or focus.
Code changes
Administration
Improve contrast and consistency of focus styles – #51870
Bundled Themes
Twenty Fifteen: Add top margin to the File blockBlockBlock 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. button styles – #58498
Twenty Nineteen: Add border-radius to avatarAvatarAn avatar is an image or illustration that specifically refers to a character that represents an online user. It’s usually a square box that appears next to the user’s name. images in the editor – #59285
Twenty Nineteen: Correct line height for Button block – #58443
Twenty Nineteen: Restore transition property to a single line – #58443
Twenty Sixteen: Add border-radius to avatar images in the editor – #59253
Twenty Twenty-Four: Add missing translationtranslationThe process (or result) of changing text, words, and display formatting to support another language. Also see localization, internationalization. functions to text strings – #60298
Twenty Twenty-Four: Prefix the block pattern categoryCategoryThe 'category' taxonomy lets you group posts / content together that share a common bond. Categories are pre-defined and broad ranging. name – #59839
Twenty Twenty-Three: Include Latin-extended characters in DM Sans font files – #59008
Twenty Twenty-Two: Prefix the pages block pattern category name – #59839
Twenty Twenty: Scope .privacy-policy styles to the footer only – #60469
Improve focus outline in Twenty Twenty-Four – #60334
Cast font URLURLA specific web address of a website or web page on the Internet, such as a website’s URL www.wordpress.org functions to string for add_editor_style() – #59704
Build/Test Tools
Fix bugbugA 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. pulling local environment containers on Apple silicone – #59930
Generate a human-readable HTMLHTMLHyperText Markup Language. The semantic scripting language primarily used for outputting content in web browsers. coverage report – #60476
Unpin PHPPHPThe web scripting language in which WordPress is primarily architected. WordPress requires PHP 5.6.20 or higher 7.4 from the test coverage workflow – #59647
Adjust the metaMetaMeta is a term that refers to the inside workings of a group. For us, this is the team that works on internal WordPress sites like WordCamp Central and Make WordPress. key time in wp_scheduled_delete() tests – #59938
Canonical
Introduce admin_canonical_urlfilterFilterFilters 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. – #59545
Coding Standards
Add missing fullstop to docblocks in wp-includes/vars.php – #41877
Add viewScriptModule handling to block.json metadata – #60233
Add wakeup magic method to the block bindings registry – #60282
Avoid double escaping on value passed for attribute in HTML tagtagA directory in Subversion. WordPress uses tags to store a single snapshot of a version (3.6, 3.6.1, etc.), the common convention of tags in version control systems. (Not to be confused with post tags.) processor
Update pattern overrides attribute format – #60456
Update the WordPress packages to GutenbergGutenbergThe 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/ 17.7RC1 – #60315
Block HooksHooksIn WordPress theme and development, hooks are functions that can be applied to an action or a Filter in WordPress. Actions are functions performed when a certain event occurs in WordPress. Filters allow you to modify certain functions. Arguments used to hook both filters and actions look the same.: Inject hooked blocks into modified templates and parts – #59646
Blocks: Allow reading the script handle from asset files – #60485
Interactivity APIAPIAn 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.: Integrate Server Directive Processing – #60356
Add an option to configure the site icon in general settings – #54370, #16434
Remove ableist language from code comments – #60247
HTML API
Add subclassed has_bookmark() and fix seek() – #60474
Join text nodes on invalidinvalidA resolution on the bug tracker (and generally common in software development, sometimes also notabug) that indicates the ticket is not a bug, is a support request, or is generally invalid.-tag-name boundaries – #60385
I18Ni18nInternationalization, 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.
Store pluginPluginA 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 deletion results in temporary option – #59433
Quick/Bulk Edit
Pre-fill category fields with their status – #11302
REST APIREST APIThe REST API is an acronym for the RESTful Application Program Interface (API) that uses HTTP requests to GET, PUT, POST and DELETE data. It is how the front end of an application (think “phone app” or “website”) can communicate with the data store (think “database” or “file system”) https://developer.wordpress.org/rest-api/.
Add featured_media field to attachments endpoint – #41692
Improve error handling in REST meta fields – #48823
Introduce the necessary endpoints for the font library – #59166
Provide detailed error data in REST API response – #60014
Script Loader
Add a timezone offset display value to wp.date.setSettings – #60105
Improve translators comments for wp.date.setSettings in compat file – #60412
always output core block global styles after base global styles – #60280
Micro-optimizations for getting plugin_file in plugins loader loopLoopThe Loop is PHP code used by WordPress to display posts. Using The Loop, WordPress processes each post to be displayed on the current page, and formats it according to how it matches specified criteria within The Loop tags. Any HTML or PHP code in the Loop will be processed on each post. https://codex.wordpress.org/The_Loop. – #60510
Remove unnecessary individual subfiles from $_old_files array – #58995
Users
Replace table tags for color palettes in profiles – #53157
Welcome back to a new issue of Week in CoreCoreCore is the set of software required to run WordPress. The Core Development Team builds WordPress.. Let’s take a look at what changed on TracTracAn open source project by Edgewall Software that serves as a bug tracker and project management tool for WordPress. between January 29 and February 5, 2024.
66 commits
117 contributors
79 tickets created
8 tickets reopened
56 tickets closed
TicketticketCreated for both bug reports and feature development on the bug tracker. numbers are based on the Trac timeline for the period above. The following is a summary of commits, organized by component and/or focus.
Code changes
Administration
AccessibilityAccessibilityAccessibility (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): Use the default cursor style for labels and disabled form controls – #59733
Mock pluginPluginA 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-partyAPIAPIAn 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. response in WP_REST_Plugins_Controller_Test – #59647
Some improvements to the Props Bot workflow – #60417
Test against MySQLMySQLMySQL is a relational database management system. A database is a structured collection of data where content, configuration and other options are stored. https://www.mysql.com/. 8.3 – #59779
Remove redundant unregister call in blockBlockBlock 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. bindings tear down – #60282
Bundled Themes
Twenty Eleven: Fix typo in twentyeleven_widgets_init() description – #60383
Twenty Fifteen: Fix typo in css/blocks.css – #60383
Twenty Twenty-Three: Rename Comments template part – #56999
Coding Standards
Remove unnecessary access and internal annotations from two functions in WP_REST_Templates_Controller – #60358
Rename the $ID parameter to $post_id in trackback() – #59650
Rename the $expires_offset variable in cache_javascript_headers() – #59650
Add allowed_blocks field to block registration and REST APIREST APIThe REST API is an acronym for the RESTful Application Program Interface (API) that uses HTTP requests to GET, PUT, POST and DELETE data. It is how the front end of an application (think “phone app” or “website”) can communicate with the data store (think “database” or “file system”) https://developer.wordpress.org/rest-api/. – #60403
Add viewStyle property to block.json for frontend-only block style – #59673
Add deprecated functions from interactivity core blocks – #60380
Fix PHPPHPThe web scripting language in which WordPress is primarily architected. WordPress requires PHP 5.6.20 or higher warning in Layout block support – #60327
Fix Theme.jsonJSONJSON, 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. font settings in unit testunit testCode written to test a small piece of code or functionality within a larger application. Everything from themes to WordPress core have a series of unit tests. Also see regression. – #60341
Refactor the way block bindings sources are handled – #60282
Remove shadow support via direct attribute – #60377
Sanitize nested array in theme.json properly – #60360
Update WordPress packages to GutenbergGutenbergThe 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/ 16.7 RC3 – #60315
Update the WordPress packages to the Gutenberg 16.7 RC2 version – #60315
Update the minimum compatible version of Gutenberg – #60315
fix small typos in block bindings API docblocks – #60282, #60386
introduce dimensions.aspectRatio block support – #60365
reduce specificity of block style variation selector – #60312
General
Add tests for array_is_list polyfill added in r57337 – #55105
HTMLHTMLHyperText Markup Language. The semantic scripting language primarily used for outputting content in web browsers. API
Fix CDATA lookalike matching invalidinvalidA resolution on the bug tracker (and generally common in software development, sometimes also notabug) that indicates the ticket is not a bug, is a support request, or is generally invalid. CDATA – #60406
Fix void tagtagA directory in Subversion. WordPress uses tags to store a single snapshot of a version (3.6, 3.6.1, etc.), the common convention of tags in version control systems. (Not to be confused with post tags.) nesting with next_token – #60382
Reset parser state after seeking to bookmark – #60428
HTTPHTTPHTTP is an acronym for Hyper Text Transfer Protocol. HTTP is the underlying protocol used by the World Wide Web and this protocol defines how messages are formatted and transmitted, and what actions Web servers and browsers should take in response to various commands. API
I18Ni18nInternationalization, 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.
Add type declaration to new method missed in [57518] – #59656
Delete .l10n.php files when deleting a theme – #59656
Ensure .l10n.php files are deleted when upgrading language packs – #59656
Fix plural forms parsing in WP_Translation_File – #59656
Improve singular lookup of pluralized strings – #59656
Improve singular lookup of pluralized strings – #59656
Load new translationtranslationThe process (or result) of changing text, words, and display formatting to support another language. Also see localization, internationalization. library in wp_load_translations_early() – #59656
Revert [57386] pending further investigation – #59656
Support loading .l10n.php translation files on their own – #59656
Upgrade/Install
When populating options, maybe_serialize instead of always serialize
Media
Prevent local edits during media upload – #58783, #23374
Add route for single styles revisionsRevisionsThe WordPress revisions system stores a record of each saved draft or published update. The revision system allows you to see what changes were made in each revision by dragging a slider (or using the Next/Previous buttons). The display indicates what has changed in each revision. – #59810
Support assigning terms when creating attachments – #57897
Happy new year, everyone! Here’s some aggregate data for 2023 about WordPress CoreCoreCore is the set of software required to run WordPress. The Core Development Team builds WordPress. contribution on TracTracAn open source project by Edgewall Software that serves as a bug tracker and project management tool for WordPress..
Please note:
These data only include code contributions to WordPress codebase, not contributions on GitHubGitHubGitHub is a website that offers online implementation of git repositories that can easily be shared, copied and modified by other developers. Public repositories are free to host, private repositories require a paid subscription. GitHub introduced the concept of the ‘pull request’ where code changes done in branches by contributors can be reviewed and discussed before being merged be the repository owner. https://github.com/ repositories such as GutenbergGutenbergThe 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/.
The raw data for this post are available on this public spreadsheet. You might find that much easier to read if you have low vision or colorblindness; the graphics below are a snapshot pulled together to include as much information as possible in this blogpost, but they are hard to make accessible to everyone.
All the links for the graphics below open a new tab to display them in full size.
General Trac overview
In 2023, the WordPress Core team shipped 2211 commits (2597 in 2022). 2751 tickets were opened, 2545 tickets were closed, and 365 were reopened.
Also, 1079 people contributed to WordPress source code using Trac (988 in 2022), and 472 people made their very first contribution to WordPress Core ♥️ (398 in 2022).
January
February
March
April
May
June
July
August
September
October
November
December
Total
Commits
148
265
179
84
174
246
209
173
250
288
108
87
2211
Tickets closed
181
297
218
156
179
259
211
277
239
268
148
112
2545
Tickets reopened
25
36
36
19
25
40
42
29
35
40
28
10
365
Tickets created
185
234
208
188
208
255
256
310
250
270
212
175
2751
New contributors
18
91
23
18
25
74
51
31
75
46
12
8
472
Contributors
137
295
155
87
150
279
217
182
295
249
111
93
1079
This chart shows the number of commits per month in 2023, and the number of closed, reopened and created tickets per month. It also shows the number of contributors per month in 2023. It can be scrolled horizontally.
Check out the Trac timeline in the graphs below:
Here’s how many props and new contributors the Core project had per month. The most prolific months were February and September with 295 contributors each, followed by June and October. 42 of the new contributors received their first props on a commit related to the Twenty Twenty-Four theme.
Components activity
How did 2023’s commits break out by Core Component?
The most prolific components were:
Editor with 284 commits (12.8% of all listed commits)
Build/Test Tools with 265 commits (12% of all listed commits)
Docs with 188 commits (8.5% of all listed commits)
Coding Standards with 154 commits (7% of all listed commits)
Bundled Themes with 130 commits (5.9% of all listed commits)
Then came Media, Help/About, Code Modernization (which is not an official component), Themes, Administration, General, HTMLHTMLHyperText Markup Language. The semantic scripting language primarily used for outputting content in web browsers.APIAPIAn 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., Internationalization, REST APIREST APIThe REST API is an acronym for the RESTful Application Program Interface (API) that uses HTTP requests to GET, PUT, POST and DELETE data. It is how the front end of an application (think “phone app” or “website”) can communicate with the data store (think “database” or “file system”) https://developer.wordpress.org/rest-api/. and Upgrade/Install. The other components each had fewer than 30 commits this year.
Contributors data retrieved from WordPress.orgWordPress.orgThe 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/ profiles
The data below comes from matching contributors’ usernames, as mentioned in Trac props, with their profiles on WordPress.org.
One caveat: this ignores usernames that did not match a profile on dotorg, plus any that had blank or unusable country/company information (“The Universe” or “Unicorn land” are not known countries 🙂).
Contributions by country
The next graph shows the number of props received by country. The top eight countries, based on the number of props received, are these:
United States with 2062 contributions (1255 in 2022)
Russiawith 795 contributions (1152 in 2022)
India with 683 contributions (317 in 2022)
France with 680 contributions (739 in 2022)
Australia with 611 contributions (386 in 2022)
United Kingdom with 471 contributions (216 in 2022)
Ireland with 403 contributions
Bangladesh with 340 contributions (145 in 2022)
Contributors (people) by country
In 2023, people from at least 62 countries contributed to WordPress Core (57 countries in 2022).
Here are the top eight countries by number of contributors:
United States with 164 people (152 in 2022)
Bangladesh with 105 people (only 43 in 2022)
India with 93 people (77 in 2022)
United Kingdom with 31 people (38 in 2022)
France with 30 people (22 in 2022)
Canada with 25 people (17 in 2022)
Germany with 21 people (25 in 2022)
Netherlands with 21 people (23 in 2022)
Spain with 19 people (12 in 2022)
Contributions by company
In 2023, people from at least 286 companies contributed to WP Core.
These companies (well, their employees) each contributed to more than 100 commits:
Automattic with 1770 contributions (866 in 2022)
Yoast with 985 contributions (1452 in 2022)
10up with 904 contributions (501 in 2022)
Whodunit with 561 contributions (676 in 2022)
Google with 404 contributions (130 in 2022)
Bluehost with 238 contributions (226 in 2022)
XWP with 224 contributions (14 in 2022)
Human Made with 177 contributions (126 in 2022)
Advies en zo with 143 contributions (220 in 2022)
Dream Encode with 128 contributions (124 in 2022)
Emilia Capital with 123 contributions
Accessible WD with 120 contributions (53 in 2022)
GoDaddy with 111 contributions (42 in 2022)
Contributors (people) by company
A huge number of companies have only one contributor—or very few contributors. The exceptions are Automattic, with 108 core contributorsCore ContributorsCore contributors are those who have worked on a release of WordPress, by creating the functions or finding and patching bugs. These contributions are done through Trac. https://core.trac.wordpress.org. on Trac in 2023, WPDeveloper (39 contributors), 10up with 25 contributors, AuthLab (21 contributors), rtCamp (17 contributors), Awsm (12 contributors), Human Made (12 contributors), Multidots (12 contributors), and Yoast (10 contributors). Only these 9 companies had at least 10 people credited on Trac in 2023.
What did 2022 hold for Core Committers?
39 Core Committers committed code to the WordPress SVNSVNSubversion, the popular version control system (VCS) by the Apache project, used by WordPress to manage changes to its codebase. repository this year (32 in 2022):
Of the 2211 commits, 555 (25%) were made by people working at Yoast, 413 (19%) from people working at Whodunit, 399 (18%) from employees of Automattic, followed by Google (151 commits), Bluehost (148 commits) and 10up (123 commits).
Automattic is the only company with more than 10 active Core Committers, and 12 of them committed code in 2023. Google has 4 people allowed to commit code to WordPress, followed by 10up with 3 Core Committers.
Worth noting that 15 of the 39 active committers come from the US, which represents 38% of the Core Committers squad. Australia, Canada, Italy, Poland and United Kingdom each had 2 committers.
More than 30% of the commits were handled by committers located in the United States, 26% by committers located in Russia, and 19% by committers located in France.
Sponsorship
In 2023, 21.6% of the contributors and 23.1% of the committers indicated that a company sponsors their contributions.
Many thanks to @audrasjb for help collecting the 2023 data and for adding several graphics.
Welcome back to a new issue of Week in CoreCoreCore is the set of software required to run WordPress. The Core Development Team builds WordPress.. Let’s take a look at what changed on TracTracAn open source project by Edgewall Software that serves as a bug tracker and project management tool for WordPress. between August 21 and September 4, 2023.
75 commits
150 contributors (!)
25 new contributors (!)
129 tickets created
13 tickets reopened
117 tickets closed
TicketticketCreated for both bug reports and feature development on the bug tracker. numbers are based on the Trac timeline for the period above. The following is a summary of commits, organized by component and/or focus.
Code changes
Administration
Escape post type output as field attribute – #59190
Build/Test Tools
Avoid doing copy:dynamic when running grunt watch when using --dev option – #59196
Change the version of Node.js in the Codespaces container – #56658
Compare results in performance measurement workflow – #58358, #58359
Enable running the tests on PHPPHPThe web scripting language in which WordPress is primarily architected. WordPress requires PHP 5.6.20 or higher 8.3 – #59231
Ensure database containers are prepared for commands – #30462, #58867
Expand database testing to account for all supported versions and types – #30462
Implicitly pass secrets to the called workflow – #30462
Twenty Nineteen: Improve social media icon dimension attributes – #45950
Ensure that pull quotes are able to use the correct font size – #57854
Coding Standards
Remove unused global variables in various /wp-admin/includes/ files – #59254
Use strict comparison in wp-includes/class-wp-hook.php – #58831
Use strict comparison in wp-includes/class-wp-widget.php – #58831
Use strict comparison in wp-includes/ms-files.php – #58831
Use strict comparison in wp-includes/ms-site.php – #58831
CustomizerCustomizerTool built into WordPress core that hooks into most modern themes. You can use it to preview and modify many of your site’s appearance settings.
use the correct X-Robots-TagheaderHeaderThe 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. – #58865
Database
Improve the documentation for various methods in the wpdb class – #58833
Add missing param description in WP_Comment class – #58890
Clarify post_date_column_timefilterFilterFilters 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. description – #59029
Correct default post type in page_template_dropdown()docblockdocblock(phpdoc, xref, inline docs) – #58972
Docblock improvements in _deprecated_class() function, as per docblocks standards – #58833
Fix typo in a translator comment in _deprecated_class() – #58833
Add relative time strings for the wp-date inline script output – #59219, #47373
Don’t use fluid layout value in typography – #58754
Ensure main query loopLoopThe Loop is PHP code used by WordPress to display posts. Using The Loop, WordPress processes each post to be displayed on the current page, and formats it according to how it matches specified criteria within The Loop tags. Any HTML or PHP code in the Loop will be processed on each post. https://codex.wordpress.org/The_Loop. is entered for singular content in blockBlockBlock 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. themes – #58154
Optimize wp_get_block_css_selector to remove array_merge calls for better performance – #59178
Preserve block style variations when securing theme – #59108
Introduce font-face styles generator and printer – #59165
Replace two esc_url_raw() calls in core with sanitize_url() – #59247
Use regular core button styles for page header actions – #41986
HTMLHTMLHyperText Markup Language. The semantic scripting language primarily used for outputting content in web browsers.APIAPIAn 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.
Stop processing HTML when encountering unsupported markup – #59167
Update WP_Http class to avoid PHP deprecation warnings – #58876
Help/About
Match icon and text in Help for bulk edit button – #58785
Login and Registration
Improve test coverage for sign on related functions – #36476
Media
Add a filter to the get_available_post_mime_types() function to allow overriding its database query – #52759
Prevent warning if shortcodeShortcodeA shortcode is a placeholder used within a WordPress post, page, or widget to insert a form or function generated by a plugin in a specific location on your site. is used without attributes – #59206
Remove unused $is_IE and $is_opera globals in media_upload_form() – #59254
Menus
Fix proximity of controls to Save and Delete menus – #56594
Options, MetaMetaMeta is a term that refers to the inside workings of a group. For us, this is the team that works on internal WordPress sites like WordCamp Central and Make WordPress. APIs
Introduce prime_options() to load multiple options with a single database request – #58962
Reinstate missing sort_column options in get_pages() – #59226
Remove redundant function calls in get_body_class() – #43661
REST APIREST APIThe REST API is an acronym for the RESTful Application Program Interface (API) that uses HTTP requests to GET, PUT, POST and DELETE data. It is how the front end of an application (think “phone app” or “website”) can communicate with the data store (think “database” or “file system”) https://developer.wordpress.org/rest-api/.
Remove misleading comment in WP_REST_Blocks_Controller->get_item_schema – #59193
RevisionsRevisionsThe WordPress revisions system stores a record of each saved draft or published update. The revision system allows you to see what changes were made in each revision by dragging a slider (or using the Next/Previous buttons). The display indicates what has changed in each revision.
Add missing escaping function for $post_edit_link in wp-admin/revision.php – #59141
Rewrite Rules
Prevent stampedes when flush_rewrite_rules() is called – #58998
Site Health
Show correct debug value for file uploads – #58737
fix check name used for REST API permission checks – #59236
Upgrade/Install
Add missing escaping function for get_option( 'home' ) in upgrade.php – #59199
Remove unused globals in core_upgrade_preamble() – #59254
Upload
Add a MIME type exception for .docx generated by Google Docs – #57898
Correct duplicate MIME type for .xlsx files generated by Google Docs – #57898
Users
Call add_user_meta() instead of update_user_meta() when adding metadata to a new user – #59212
Properly deprecate both constructors in WP_User_Search – #41125
Remove unused wpdb global in check_password_reset_key() – #59185
Widgets
Improve performance of has_content method in WP_Widget_Media_Gallery class – #58757
XML-RPC
Remove unused wpdb global in wp_xmlrpc_server::mw_newMediaObject() – #59185
Props
Thanks to the 150 (!) people who contributed to WordPress Core on Trac last week:
“What’s new in GutenbergGutenbergThe 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/…” posts (labeled with the #gutenberg-new tag) are posted following every Gutenberg release on a biweekly basis, showcasing new features included in each release. As a reminder, here’s an overview of different ways to keep up with Gutenberg and the Site Editor project (formerly called Full Site Editing).
This latest release comes packed with improvements and bugfixes, including an enhancementenhancementEnhancements are simple improvements to WordPress, such as the addition of a hook, a new feature, or an improvement to an existing feature. to the List View in the post editor, introducing a horizontal scrollbar for heavily nested list views, a fix for the Cover BlockBlockBlock 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. on Safari on iPad, addressing an issue where images with a “Fixed background” were zoomed in excessively, and more!
Table of Contents
PluginPluginA 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-inserted blocks.
Captured toolbars.
Changelog.
Block hooksHooksIn WordPress theme and development, hooks are functions that can be applied to an action or a Filter in WordPress. Actions are functions performed when a certain event occurs in WordPress. Filters allow you to modify certain functions. Arguments used to hook both filters and actions look the same., formerly known as Auto-inserted blocks
On activation, plugins are now equipped with the capability to auto-insert blocks, enhancing the integration and automation between plugins and the Gutenberg editor. Early versions of this experiment were called Auto-inserted blocks, but after some discussion, they have now been dubbed Block hooks. (#52969, #54029, #54024, #54147)
Captured toolbars for an easier editing experience
Toolbars for child blocks are now seamlessly attached to their parent blocks, offering a more intuitive and organized editing experience. This feature is currently supported for Navigation, List, and Quote blocks. (#53699, #53697)
Other Notable Highlights:
Make mid size parameter settable for Query Pagination block. (#51216)
Add keyboard shortcut for duplicating blocks. (#53559)
Add toggle list view command in site editor. (53983)
Changelog
Features
Interactivity APIAPIAn 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.
Popover: Update @floating-ui to latest version, remove custom fix for iframeiframeiFrame is an acronym for an inline frame. An iFrame is used inside a webpage to load another HTML document and render it. This HTML document may also contain JavaScript and/or CSS which is loaded at the time when iframe tag is parsed by the user’s browser. positioning and scaling. (46845)
AlignmentMatrixControl: Replace act() with userEvent. (53703)
ProgressBar: Add transition to determinate indicator. (53877)
Block Library
Blocks: Move bootstrapped block types to Redux state. (53807)
Router with region-based client-side navigation. (53733)
Bug Fixes
Add missing aria roles for block locking toolbar and menu buttons. (53734)
Block Editor: Fix cleanup in the ‘useNavModeExit’ hook. (53795)
Command Palette: Fix crash on block-related commands. (53923)
Date: Add relative time translations for moment.js. (53931)
Date: Update translationtranslationThe process (or result) of changing text, words, and display formatting to support another language. Also see localization, internationalization. domains for strings to be translatable. (53995)
getInsertionPoint: Fix type check for the state value. (53793)
npm Packages
Workflow: Run Learn directly from GitHubGitHubGitHub is a website that offers online implementation of git repositories that can easily be shared, copied and modified by other developers. Public repositories are free to host, private repositories require a paid subscription. GitHub introduced the concept of the ‘pull request’ where code changes done in branches by contributors can be reviewed and discussed before being merged be the repository owner. https://github.com/ action when publishing to npm targeting WP core. (53762)
Workflows: Fix issues with the npm publishing workflow when using locally. (53565)
Themes
Command Palette: Proper handling of page/post links in all themes. (53718)
Fix query loopLoopThe Loop is PHP code used by WordPress to display posts. Using The Loop, WordPress processes each post to be displayed on the current page, and formats it according to how it matches specified criteria within The Loop tags. Any HTML or PHP code in the Loop will be processed on each post. https://codex.wordpress.org/The_Loop. bugs by correctly relying on the main query and removing problematic workaround. (49904)
Block Editor
Fix: Indicator style when block moving mode. (53972)
Icons
Fix invalidinvalidA resolution on the bug tracker (and generally common in software development, sometimes also notabug) that indicates the ticket is not a bug, is a support request, or is generally invalid. namespaces. (53955)
Patterns
Disable the preview option button when editing. (53913)
Global Styles
Gallery: Re-enable block spacing at block level while still hiding in global styles. (53900)
Layout
BlockList: Ensure element styles (and svg) are always appended at the end of the document. (53859)
Interactivity API
Add “supports.interactivity” to Image block. (53850)
Style Variations
Block Styles: Fix misplaced preview popover on RTL site. (53726)
List View
Recalculate window list when expanded state changes (fix logic for long nested lists). (53716)
Widgets Editor
Block WidgetWidgetA WordPress Widget is a small block that performs a specific function. You can add these widgets in sidebars also known as widget-ready areas on your web page. WordPress widgets were originally created to provide a simple and easy-to-use way of giving design and structure control of the WordPress theme to the user.: Fix content cutoff in the keyboard shortcut modal. (53638)
AccessibilityAccessibilityAccessibility (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)
Edit site: Add missing label to post status password protected input field. (52885)
[a11yAccessibilityAccessibility (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)] Fix: Aria-haspop, aria-expanded attributes on the link format button. (53691)
Site Editor
Add missing aria roles to the ‘Create template part’ menu item. (53754)
Unify the delete button style in the dropdown menu with red. (52597)
Block Library
Add missing aria roles to the ‘Replace template part’ menu item. (53755)
Patterns
Add missing aria roles to the ‘Create pattern’ menu item. (53739)
List View
[a11y] Fix: Aria-haspop and aria-expanded attributes on list view button. (53693)
Block Editor
[a11y] Fix: Aria-haspop and aria-expanded attributes on the inserter button. (53692)
Performance
Revert “Switch performance tests to Playwright (#52022)”. (53741)
StartPageOptions: Load and parse patterns only after establishing the need for them. (53673)
Switch performance tests to Playwright: Take 2. (53768)
Adds explanatory text to view.js template. (53870)
Clarification for parent and ancestor hierarchical relationships. (53855)
Docs: Extend the information about using render with block.json. (53973)
Docs: Remove duplicate sections from FAQ page. (53830)
Document the naming convention for block-libraryPHPPHPThe web scripting language in which WordPress is primarily architected. WordPress requires PHP 5.6.20 or higher functions. (53777)
Fix ‘lerna’ links in the release documentation. (53770)
Fix typo in code sample for Interactivity API. (53916)
Edit Site: Rename CanvasSpinner to CanvasLoader. (53728)
Enforce valid function names in the packages/block-library/src//.php files. (53438)
Fonts Library: Update properties name from snake case to camel case to match the rest of the properties. (53746)
Block API
Auto-inserting blocks: Remove obsolete TODO, fix REST APIREST APIThe REST API is an acronym for the RESTful Application Program Interface (API) that uses HTTP requests to GET, PUT, POST and DELETE data. It is how the front end of an application (think “phone app” or “website”) can communicate with the data store (think “database” or “file system”) https://developer.wordpress.org/rest-api/. field description. (54208)
Post Editor
Editor: Fix the ‘useSelect’ warning in the ‘useIsDirty’ hook. (53759)
Fix browser console error when changing device preview mode. (53969)
Refactor latest content selectors in ‘CopyContentMenuItem’ components. (53676)
Update Jest to latest version, and use optimized JSDOM. (53736)
Plugin
BackportbackportA port is when code from one branch (or trunk) is merged into another branch or trunk. Some changes in WordPress point releases are the result of backporting code from trunk to the release branch. themes is_block_theme collection param from core. (53846)
First time contributors
The following PRs were merged by first time contributors:
@JEverhart383: Fix typo in code sample for Interactivity API. (53916)
@krokodok: Make mid size parameter settable for Query Pagination block. (51216)
@mklute101: Update local instructions on the dev env documentation. (53924)
Contributors
The following contributors merged PRs in this release:
Many thanks to @jameskoster for the release assets, @annezazu and @priethorfor the general support and help collecting highlights, and @jeffikus for the copy check!
A recent in-depth performance analysis of WordPress core showed that loading translations had a significant hit on a site’s server response time. Given that more than half of all WordPress sites use a language other than English (US), the performance team identified this as an area worth looking into more closely. The team spent the last couple of months exploring this in more detail and the results are now shared in this blogblog(versus network, site) post.
This is merely an analysis of the current i18ni18nInternationalization, 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 with some proposed under-the-hood performance improvements. No decisions have been made on any of these proposals.
Context
Initial benchmarks showed that the median loading time for a localized site can be up to 50% slower than for non-localized sites, depending on which themes and plugins are being used. This was measured using both the wpp-research CLI tool and also a dedicated benchmark environment (as elaborated in the Comparison section towards the end).
The WordPress i18n system is based on gettext, which uses source .po (Portable Object) files and binary .mo (Machine Object) files for storing and loading translations. It is not using the C gettext APIAPIAn 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. itself but a custom userland implementation that works without any external dependencies.
In addition to coreCoreCore is the set of software required to run WordPress. The Core Development Team builds WordPress. itself, each pluginPluginA 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 and theme has its own translationtranslationThe process (or result) of changing text, words, and display formatting to support another language. Also see localization, internationalization. file, which has to be loaded and parsed on every request. Loading and parsing all these translation files is an expensive task.
In the past, various solutions have been discussed and explored to improve the i18n performance of WordPress. A non-exhaustive list:
Use a more lightweight MO parser
Improve translation lookups by using the hash map in MO files (e.g. with DynaMo)
Caching translations in the object cache
Caching translations in APCu (an in-memory key-value store for PHPPHPThe web scripting language in which WordPress is primarily architected. WordPress requires PHP 5.6.20 or higher)
Other more elaborated forms of caching (e.g. per request)
Using the native PHP gettext extension
Use a custom PHP extension to handle the MO file parsing)
Using lazily evaluated translation calls (see #41305 for details)
Using a different file format than .mo files, e.g. plain .php files
For this analysis, many of these solutions were looked at, focusing on their advantages and disadvantages. At the end of this post there is a comparison table with some much needed numbers as well, based on custom-built benchmarks.
Solutions
Solution A: Use different file format
Use a different file format for translations instead of .mo files to avoid the overhead of loading and parsing binary files.
Design considerations
With this solution, translations will be stored in plain .php files returning an associative array of translation strings. Whenever a .php file is available, it will be preferred over the .mo file, which is still used as a fallback. The rest of the architecture remains the same.
When a localized WordPress site downloads language packs from the translate.wordpress.org translation platform, it downloads .po and .mo files containing all the translations. This will be modified to include .php files. GlotPress, which the platform is built on, will be updated to support this new output format. Additionally, WordPress core itself could be modified to generate PHP files whenever they are missing.
In theory, nothing is faster in PHP than loading and executing another PHP file. .json, .ini, or .xml would all be much slower.
Initial benchmarks show consistent significant performance improvements
Relatively trivial to implement
Maintains backward compatibility thanks to graceful fallback
Makes it easier for users to inspect and change translations (no need to compile .po to .mo)
Avoids loading and parsing binary .mo files, which is the main bottleneck
Lets PHP store translations in OPcache for an additional performance benefit
Battle-tested approach in the PHP ecosystem (for example in Laravel)
Caveats and risks
Requires not only changes to WordPress core, but also tools like GlotPress and WP-CLIWP-CLIWP-CLI is the Command Line Interface for WordPress, used to do administrative and development tasks in a programmatic way. The project page is http://wp-cli.org/https://make.wordpress.org/cli/
Adds maintenance overhead by introducing a new file format on top of the existing one
As shown by the proof of concept, the overhead is minimal
In the long term, .mo support could be deprecated
Security considerations due to essentially executing remotely fetched PHP files
Not really different from downloading plugins/themes from WordPress.org
WordPress considers translations to be trusted
Hosting providers could be blocking PHP execution in wp-content/languages
Could potentially use checksum verifications or static analysis at install time to detect anomalies
Effort and timeline
The proof of concept using PHP files is in a very solid state already. There are also examples for changes to WP-CLI (PR) and GlotPress (PR). This makes it suitable for a feature project to expand testing with very little effort required. Even a core merge would be very straightforward in a relatively short time, potentially already in Q4 2023. The security aspect when using PHP files could be a potential blockerblockerA bug which is so severe that it blocks a release., so it’s important to loopLoopThe Loop is PHP code used by WordPress to display posts. Using The Loop, WordPress processes each post to be displayed on the current page, and formats it according to how it matches specified criteria within The Loop tags. Any HTML or PHP code in the Loop will be processed on each post. https://codex.wordpress.org/The_Loop. in the WordPress security team and hosting providers early on.
More time is required to test other file formats and compare results.
Solution B: Native gettext extension
Use the native gettext PHP extension written in C when available, instead of the custom built-in parser in WordPress.
Design considerations
WordPress has always used a custom MO file parser, because the native gettext extension is not necessarily available on the server. With this solution, the existing system is adapted to use the extension whenever available and falling back to the custom implementation if not.
This has been previously explored in #17268 and implemented in WP Performance Pack and Native Gettext. These implementations can serve as inspiration for the initial design. They all work similarly in that they symlink or copy the translation files to a new directory structure that is compatible with the gettext extension.
As of July 2023, around 66% of all localized WordPress sites have the gettext extension installed, according to information from the WordPress update requests.
Benefits
Significant performance improvements for eligible sites
Initial benchmarks show that loading time and memory usage basically do not differ from non-localized sites
Caveats and risks
The gettext extension is not commonly available
Smaller incentive to implement and lower impact overall
Requires locales to be installed on the server
Servers rarely have many installed locales
Locales often need to be compiled first and take up a lot of space
WordPress on the other hand supports over 200 locales
Potential clashes with the custom locales WordPress supports
For example, locales like pt_PT_ao90, de_DE_formal or roh might not even be supported
Outreach to hosting providers would be necessary
Adds maintenance overhead by essentially adding a second gettext implementation
Poor API
Requires setting environment variables (such as LC_MESSAGES and LANGUAGE), which might not be possible or cause conflicts on certain servers/sites
Requires symlinks or hard file copies
Symlinks might not be possible on the server; copying all translation files means doubling disk usage
Translation files are cached by PHP, thus any translation change requires restarting the web server
There are workarounds such as cache busting using random file names or fstat, however they might not work on all environments
Has not been tested on a wider scale, despite being discussed for years
While there are existing implementations that could be leveraged for this solution, further field testing is required to assess whether the extension actually works under all circumstances. Given the limitations around the poor API and requirements for installing locales, it does not seem like a viable solution at all.
Solution C: Cache translations
Cache translations somehow to avoid expensive .mo parsing.
Design considerations
Cache translations either on disk, in the database, or the object cache to avoid expensive .mo file parsing on subsequent requests. This can be done in a generalized manner or also on a per-request basis to only load translations required for the current URLURLA specific web address of a website or web page on the Internet, such as a website’s URL www.wordpress.org.
Many different caching strategies have been explored in various forms in the past, each with their own pros and cons. Some could even be combined. Defining the exact implementation requires further exploration and testing, which warrants its own exploration post.
Benefits
Caching translations after one time .mo parsing potentially improves performance for future requests
Caveats and risks
Caching using persistent object cache (e.g. Memcached, Redis) or APCu:
Not available on most sites, making this not an ideal solution
Availability according to data from WordPress update requests:
Memcached: ~25%
Redis: ~25%
APCu: ~6%
Can potentially significantly increase cache size or exceed cache key limits
Database caching:
Moves the problem from disk reads to database reads
Can potentially significantly increase database size
Alternatively, use sqlite as a cache backend
Untested approach
Available on around 90% of sites
Disk caching:
Not always possible, depending on server environment
Still causes file reads, only with fewer or other files
Multiple cache groups (e.g. per-request or frontend/adminadmin(and super admin) split)
Smarter cache logic to only load translations that are needed for the majority of requests
Can potentially significantly increase cache size
Unlikely that different requests use very different translations
Cache retrieval adds overhead
Exact performance gains depend on implementation method and need to be measured first
No performance gains with cold cache
Cache invalidation logic TBD
Effort and timeline
Given the existing solutions in the ecosystem, the engineering effort itself would not be too big, but the right caching implementation (e.g. disk cache or object cache) needs to be evaluated first.
However, the right caching strategy probably does not exist because of all the different hosting environments. Since it’s unrealistic for core to support multiple types of caching, this solution seems better suited for plugins rather than core.
Solution D: Lazily evaluated translation calls
Use lazily evaluated translation calls to reduce the number of function calls in certain cases, leading to improved performance.
Design considerations
The idea of lazily evaluated translation calls has been first discussed in #41305. It enables avoiding string-specific expensive translation lookups until the translations are actually needed, by passing around proxy objects.
In other words: beyond just-in-time loading of translation files (which WordPress already does), this would add just-in-time lookup of individual strings in the translations. Check out this proof of concept to get a better picture.
It can be integrated essentially in two ways, both of which are explained on the core ticketticketCreated for both bug reports and feature development on the bug tracker.:
Change all translation calls to be lazily evaluated by default
Make this opt-in, either with new function arguments or new functions altogether
Benefits
Reduces the number of translation lookups, in some scenarios drastically
On a regular home page request there are ~60% less translation calls, saving around ~10ms (as measured by XHProf)
As a side effect, solves UXUXUser experience issues such as #38643
Caveats and risks
Depending on implementation this either breaks backward compatibility or risks not gaining enough adoption
Documentation, tooling, and developer education can help mitigate this to a certain extent
Adoption could be done gradually, e.g. starting with an opt-in approach and eventually making it the default
Likely will not have a significant impact on typical frontend page loads, as it’s mostly useful for areas like the REST APIREST APIThe REST API is an acronym for the RESTful Application Program Interface (API) that uses HTTP requests to GET, PUT, POST and DELETE data. It is how the front end of an application (think “phone app” or “website”) can communicate with the data store (think “database” or “file system”) https://developer.wordpress.org/rest-api/. schema output, where a lot of translation calls are made without actually using the translations
Needs analysis in more scenarios to measure impact
The REST API schema already has a workaround by using a cache in a static variable
Does not improve situation for actually loading translation files
Initial testing shows that this actually hurts performance due to the additional thousands of proxy objects being created
Effort and timeline
Gradual adoption would mean a multi-year effort to establish lazily evaluated translation calls, while enabling this by default is a significant backward compatibility break that could affect thousands of plugins and themes in the ecosystem. And since it does actually slow down performance in some cases, this solution is not a great candidate for implementation.
Solution E: Optimize/Rewrite existing MO parser
Refactor the existing MO parser in WordPress to be more performant.
Design considerations
Completely overhaul the existing MO translation file parser in WordPress with performance in mind. For example by using Ginger MO, WP Performance Pack, or other existing solutions as a base.
While for instance Altis DXP (Human Made) have actually replaced the existing MO parser with a custom-made PHP extension written in Rust, such an approach is obviously not feasible for core. The new solution needs to be written in userland PHP.
Initial testings with an updated fork of Ginger MO show some noticeable speedups and lower memory usage. It also supports multiple translation files per text domain and multiple locales loaded at once, which could prove beneficial for improving the localeLocaleA 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. switching functionality in WordPress core.
Besides that, plugins like WP Performance Pack and DynaMo have implemented partial lookups using the MO hash table or binary search, avoiding reading the whole file and storing it in memory. That slightly reduces memory usage and performance.
Benefits
Can be used without necessarily introducing another file format
Opens up potential performance enhancements in other areas, i.e. locale switching
Mostly maintains backward compatibility
Caveats and risks
Still a risk of breaking backward compatibility
Effort and timeline
There already is a working proof of concept for this solution, but more testing is required to further refine it and improve its backward compatibility layer. With such an effort being an ideal candidate for a feature pluginFeature PluginA plugin that was created with the intention of eventually being proposed for inclusion in WordPress Core. See Features as Plugins., this could be achieved relatively quickly in a few months.
Solution F: Splitting up translation files
Split translation files from plugins and themes into smaller chunks to make loading them more efficient.
Design considerations
Depending on the project’s size, translation files can be quite big. That’s why WordPress itself uses separate translation files for the admin and everything else, so that not too many strings are unnecessarily loaded.
This strategy could be applied to plugins and themes as well. Either by allowing them to use multiple text domains (which would require developer education and changes to tooling), or by somehow doing this automatically (exact method TBD)
Benefits
Faster loading times due to loading smaller files
Caveats and risks
Risk of breaking backward compatibility
Opt-in approach requires tooling and distribution changes and risks slow adoption
Effort and timeline
Further research is required to evaluate this properly.
Comparison
At first glance, solution A (PHP translation files) is a relatively straightforward enhancementenhancementEnhancements are simple improvements to WordPress, such as the addition of a hook, a new feature, or an improvement to an existing feature. that maintains backward compatibility and shows promising improvements. However, it does not only require changes to core itself, but also to the translation platform. The security aspect remains a risk, although discussing it early on with stakeholders and gathering more testers would help mitigate it.
Leveraging the native gettext extension as in solution B shows stunning results, but the lack of availability and the non-ideal API are a concern. Still, it’s a progressive enhancement that cannot be ignored. Especially since it could pretty much eliminate the need for additional caching as in solution C.
Caching already loaded translations as in solution C does not eliminate the root cause of the i18n slowness, but can speed up subsequent requests. Unfortunately, persistent object caches or APCu are rather uncommon (though we do not have exact data on the former yet, see #58808), and implementing more complex types of caching (e.g. per-request caching) would require significant exploration effort before becoming a viable option.
Lazily evaluated translation calls (solution D) can shave time off translation calls in some situations, but overall actually decrease performance. While it could help solve some actual UX issues in core, the backward compatibility and adoption concerns make it even less of a suitable solution.
Existing plugins like Ginger MO and WP Performance Pack show that the existing MO parser in WordPress can be further improved (solution E).
Benchmarks
Now to the most interesting part: the hard numbers!
These benchmarks are powered by a custom-built performance testing environment using @wordpress/env and Playwright. The environment has been configured with some additional plugins and the PHP extensions required for some of the solutions. Tests have been performed against the 6.3 RCrelease candidateOne of the final stages in the version release cycle, this version signals the potential to be a final release to the public. Also see alpha (beta). by visiting the home page and the dashboard 30 times each and then using the median values.
BlockBlockBlock 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. Theme
Locale
Scenario
Object Cache
Memory Usage
Total Load Time
en_US
Default
15.60 MB
133.58 ms
de_DE
Default
29.14 MB
181.95 ms
de_DE
Ginger MO (MO)
19.24 MB
159.18 ms
de_DE
Ginger MO (PHP)
16.98 MB
138.14 ms
de_DE
Ginger MO (JSONJSONJSON, 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.)
19.24 MB
153.39 ms
de_DE
Native Gettext
15.99 MB
142.12 ms
de_DE
DynaMo
19.62 MB
157.93 ms
de_DE
Cache in APCu
50.37 MB
181.51 ms
en_US
Default
✅
15.67 MB
121.53 ms
de_DE
Default
✅
29.01 MB
167.67 ms
de_DE
Ginger MO (MO)
✅
19.11 MB
147.19 ms
de_DE
Ginger MO (PHP)
✅
16.85 MB
127.97 ms
de_DE
Ginger MO (JSON)
✅
19.11 MB
144.43 ms
de_DE
Native Gettext
✅
15.86 MB
129.19 ms
de_DE
DynaMo
✅
18.57 MB
133.46 ms
de_DE
Cache in APCu
✅
50.30 MB
170.19 ms
de_DE
Cache in object cache
✅
29.07 MB
173.19 ms
Benchmarks using the Twenty Twenty-Three block theme
Classic Theme
Locale
Scenario
Object Cache
Memory Usage
Total Load Time
en_US
Default
15.35 MB
120.79 ms
de_DE
Default
28.79 MB
172.10 ms
de_DE
Ginger MO (MO)
18.85 MB
145.68 ms
de_DE
Ginger MO (PHP)
16.56 MB
124.73 ms
de_DE
Ginger MO (JSON)
18.84 MB
140.78 ms
de_DE
Native Gettext
15.58 MB
128.26 ms
de_DE
DynaMo
19.24 MB
146.09 ms
de_DE
Cache in APCu
50.13 MB
167.28 ms
en_US
Default
✅
15.19 MB
107.26 ms
de_DE
Default
✅
28.59 MB
154.30 ms
de_DE
Ginger MO (MO)
✅
18.64 MB
133.21 ms
de_DE
Ginger MO (PHP)
✅
16.37 MB
112.94 ms
de_DE
Ginger MO (JSON)
✅
18.64 MB
128.94 ms
de_DE
Native Gettext
✅
15.38 MB
115.11 ms
de_DE
DynaMo
✅
18.10 MB
120.72 ms
de_DE
Cache in APCu
✅
49.99 MB
151.82 ms
de_DE
Cache in object cache
✅
28.65 MB
156.36 ms
Benchmarks using the Twenty Twenty-One classic theme
Admin
Locale
Scenario
Object Cache
Memory Usage
Total Load Time
en_US
Default
15.42 MB
139.83 ms
de_DE
Default
31.92 MB
187.76 ms
de_DE
Ginger MO (MO)
20.07 MB
164.94 ms
de_DE
Ginger MO (PHP)
17.09 MB
139.66 ms
de_DE
Ginger MO (JSON)
20.06 MB
160.87 ms
de_DE
Native Gettext
15.95 MB
143.43 ms
de_DE
DynaMo
20.58 MB
166.79 ms
de_DE
Cache in APCu
58.13 MB
190.38 ms
en_US
Default
✅
15.66 MB
112.69 ms
de_DE
Default
✅
31.84 MB
164.26 ms
de_DE
Ginger MO (MO)
✅
19.99 MB
140.70 ms
de_DE
Ginger MO (PHP)
✅
17.01 MB
118.52 ms
de_DE
Ginger MO (JSON)
✅
19.98 MB
138.49 ms
de_DE
Native Gettext
✅
15.87 MB
120.01 ms
de_DE
DynaMo
✅
19.73 MB
120.26 ms
de_DE
Cache in APCu
✅
58.07 MB
162.41 ms
de_DE
Cache in object cache
✅
31.86 MB
164.28 ms
Benchmarks visiting the WordPress admin
Conclusion
Finding the right path forward means weighing all the pros and cons of each solution and looking at both horizontal and vertical impact, i.e. how much faster can i18n be made for how many sites.
When looking at all these factors, it appears that a revamped translations parser (solution E) could bring the most significant improvements to all localized WordPress sites. Especially when combined with a new PHP translation file format (solution A), which Ginger MO supports, the i18n overhead becomes negligible. Of course the same risks associated with introducing a new format apply.
On top of that, a revamped i18n library like Ginger MO could also be combined with other solutions such as caching or dynamic MO loading to potentially gain further improvements. However, those routes have yet to be explored.
Next steps
The WordPress performance team wants to further dive into this topic and test some of the above solutions (and combinations thereof) on a wider scale through efforts like the Performance Lab feature project. We are looking forward to hearing your feedback on this analysis and welcome any additional comments, insights, and tinkering.
Deadline August 6, 2023
After the deadline passes, the performance team will discuss the received feedback and determine next steps.