What’s new in Gutenberg? (May the 4th)

Things are going well on the road towards completing the first phase of the editor project. Most of the work is centered around polish, getting things ready for merge, and tightening existing APIs.



This release has many refinements and improves the capabilities of the Block and Plugin APIs. It also adds a new “spacer” block for generating visual space. The color palette component has been improved to be based on classes instead of inline styles (for registered colors) and includes some important accessibility improvements (like naming the color). Thank you to everyone involved!

2.8 🌌

Screen readers can announce the color by name.

Other changes

#core-editor, #editor, #gutenberg

JavaScript Internationalization: The Missing Pieces

Back in 2016, work started on building a proper JavaScript internationalization API and the tooling to support it throughout WordPress core and WordPress.org. Many ideas and patches were being discussed. A summary of that can be found in this blog post. With Gutenberg on the rise, JavaScript I18N is more urgent than ever. WordPress needs a robust solution for that, and some things have already been built. Let’s have a look at where we currently stand.

Status Quo

Right now, Gutenberg is using a custom built JS I18N library that is similar to the one originally proposed in 2016 as part of #20491. It lies on top of a library called Jed which bring Gettext functionality to JavaScript. This means developers can use the same __() function as in PHP and therefore don’t have to learn anything new. WordPress can take it from there.

Unfortunately, WordPress doesn’t yet support JS I18N library. Gutenberg (or any other plugin that uses said library, really) has to jump through quite some hoops to actually localize their JavaScript:

  1. Scan JavaScript files to extract internationalization functions and create a POT file using tools like babel-plugin-makepotPoedit or xgettext-js.
  2. Use that POT file to write the exact same internationalization functions in a “fake” PHP file that can be scanned by the WordPress.org translation platform. This will result in PO and MO files containing all of your plugin’s translations.
  3. Figure out a way to load these translations and make them available to your JavaScript using wp_add_inline_script(). Ideally you’d only load the ones needed by that specific script as you don’t want to print thousands of strings in that inline JS when you only need a few of them.

An example of that process can be found in my demo Gutenberg I18N Block plugin.

At this point you might want to go back to good old wp_localize_script() and simply keep using that for internationalization purposes. I don’t blame you.

However, this complicated process is only needed because the work on JavaScript internationalization is far from done yet. Gutenberg made it quite obvious where things need to be improved.

What’s Missing

Scanning JavaScript files for internationalization functions

First and foremost, the WordPress.org translation platform needs to be able to scan JavaScript files for internationalization functions in addition to just the PHP files. However, that’s not as straightforward as it sounds.

The platform uses a script called makepot.php to scan PHP files all across the WordPress.org ecosystem, i.e. core, meta, and all default themes. In addition to regular Gettext function calls it also scans plugin and theme file headers. Being included in many other libraries, makepot is a widely used tool. Most recently, its functionality was ported to a WP-CLI command to make string extraction easier to use.

On the other side we have babel-plugin-makepot, a tool written in JavaScript to scan JavaScript files. With the ECMAScript standard evolving so quickly, it is natural to write such a tool in the same language. However, it’s not a requirement, as this pull request for said WP-CLI command demonstrates. This opens some questions:

Can we simply use that Babel plugin on WordPress.org? What happens to makepot.php? What are the implications for all the developers out there not hosting their projects on WordPress.org? Not everyone uses the Babel transpiler, and certainly not everyone wants to use two separate tools just to extract some internationalization functions.

Loading only specific set of translations

All translations for a plugin or theme are stored in one single PO / MO file per locale. Loading these translations is a slow process.  We’ve made some improvements in that regard over the years, for example by introducing just-in-time loading of translations in WordPress 4.6.

However, if you only need a handful of translations for a single script in your plugin, it does not make sense to load the entire MO file which can be dozens of kilobytes in size. There’s currently no way to load only a specific set of translations in WordPress. This is something that came up in Gutenberg before, see issue 6015.

Binary MO files don’t make sense in a JavaScript context anyway. Lucky for us, GlotPress—the software that powers translate.wordpress.org—has been able to export translations in a Jed-compatible JSON format since 2016. We just need to use that to export a JSON file for all strings extracted from JavaScript files

So in theory the WordPress.org translation platform could export PO and MO files as usual for strings extracted from PHP files, and a JSON file for all strings coming from JavaScript files. This would be already a huge improvement. But can we take this even further?

Option A

Use a different text domain per JavaScript module. Export a JSON file per text domain. This is appealing, but has to be ruled out quickly: the text domain is not known to GlotPress and is not stored in the database or anything.

Option B

GlotPress doesn’t know about the text domain, but it does know a string’s source file. What if it would export one JSON file per source file it has scanned? This way WordPress has full control over the translations and one could specify which JSON files need to be loaded for a specific module.

The big drawback here: a single module might consist of dozens of source files. Having one JSON file for each of those is not going to scale well.

The built JavaScript file can’t be scanned either, because tools like UglifyJS rename functions and strip out comments.

Option C

Don’t do anything fancy. Sticking with a JSON file already guarantees that a plugin doesn’t unnecessarily load all the translations needed just in PHP. So the file size is definitely smaller. Still, this file alone can be very large for an application like Gutenberg.

Option D

Keep one single JSON file for all translations, but use some PHP code to only ever pass the strings to a module / script handle that it actually needs. However, there’s probably no real benefit in doing so.

Easily load translations

Up until WordPress 4.6, developers needed to use load_plugin_textdomain or load_theme_textdomain() to make sure translations are properly loaded. Now, you only need to use the various translation functions and the rest just works. The only requirement is that your translation files reside in wp-content/languages. This is usually the case when your project is hosted on WordPress.org.

We should aim for a similar experience for JavaScript translations as well. While just-in-time loading of translation files via HTTP isn’t really possible due to the asynchronous nature of JavaScript, WordPress should still make it as easy as possible.

Imagine having a plugin foo-plugin and you’re enqueuing your JavaScript like this:

wp_enqueue_script( 'foo-script', plugins_url( '/foo-script.js' , __FILE__ ) );

Ideally, all you’d need to do to translate it is calling a function like load_js_textdomain( 'foo-plugin' ).  WordPress would then do all the heavy lifting.

However, other options might exist, and this solution would need to be tested in the wild with bigger projects like Gutenberg.

Discussion

Bringing a JavaScript I18N API to WordPress will have a huge impact. We need to make sure we end up with a solid plan that works for as many plugins and themes as possible.

Ideally, we hold a separate JS I18N meeting with all the teams primarily involved: #core-i18n, #core-js, #core-editor, #meta-i18n and #cli. Everyone is welcome to attend though 🎉

I suggest the following date for such a meeting: Tuesday, May 8 15:00 UTC. Of course I’m open for other suggestions. The Slack channel would be #core-i18n.

At this meeting we can discuss the missing pieces outlined in this post and the overall next steps for JavaScript I18N in WordPress.

If you have any questions or concerns about this post or the overall topic, please leave a comment below.

+make.wordpress.org/polyglots

What’s new in Gutenberg? (5th April)

This release introduces drag and drop capabilities for sorting blocks, various refinements to the block visual interface (including a label with block type identifier) and extensibility APIs, plus a lot of bug fixes. Thanks to everyone who contributed for all the ongoing efforts!

2.6 🐉 💧

Other changes

#core-editor, #editor, #gutenberg

Dev Chat Agenda: 28th March (4.9.5 week 8)

This is the agenda for the weekly dev meeting on Wednesday, 28 March 2018, 20:00 GMT / March 28, 2018 at 20:00 UTC:

  • The #core-editor team are skipping this weeks developer chat.
  • 4.9.5 RC planning & testing.
  • All component maintainers are being audited to make sure all components have a maintainer and in case anyone wishes to step down. More details can be found in the handbook and the maintainer list.
    • If you are interested in becoming a component maintainer, please get in touch with @jeffpaul on Slack.
  • Updates from focus leads and component maintainers (also see above).
  • General announcements.

If there is anything you'd like to add to the agenda, please leave a comment and we can add it to the discussion points for later on in the meeting. Thank you!

#4-9-5#agenda#core#dev-chat

#4-9-5

Core editor bug scrub time shift

With the shifts in local times, we’ll adjust the weekly core editor bug scrub starting this week to be Thursdays at 16:00 UTC and held as usual in #core-editor. Our focus will continue to be on Issues in the Merge Proposal milestone so please join the weekly discussion!

#bug-scrub, #core-editor, #gutenberg

Core editor meeting time shift

Due to timezones being timezones, the weekly core editor meeting will change from next week to be 13:00 UTC and held as usual in #core-editor on chat.wordpress.org. This is to adjust for those places that spring forward this time of the year.

What’s new in Gutenberg? (25th January)

This release iterates further on some design and writing flow details — lighter up/down movers, engaging the UI-less focus mode more often, etc. It also brings many extensibility API improvements, exposing internal editor state through selectors, enhancements to the meta-box handling, and implements the "Copy All" button as if it was a plugin as an example of how to leverage native hooks.

2.1 🦔

  • Iterate on the design of up/down arrows and how focus is managed. This seeks to further reduce the visual and cognitive weight of the up/down movers.
  • Show immediate visual feedback when dragging and dropping images into the editor. (Expands on the previous release work.)
  • Expose state through data module using selectors. This is an important piece of the extensibility puzzle.
  • New button outline and focus styles.
  • Show original block icon after converting to reusable block. Also hides the generic reusable block from inserters. This moves data logic out of the inserter.
  • Introduce a migration function for block versioning.
  • Add HTML handler to dropzone. Allows drag and dropping images from other web pages directly.
  • Trigger typing mode when ENTER or BACKSPACE are pressed. This improves the writing flow but engaging the UI-less mode more frequently.

Other changes:

What's next?

As we approach the final stages of features, we are looking at finalizing the nested blocks interface (with its own Columns component), some remaining important extensibility hooks for plugins, and adding drag-drop functionality for moving and inserting blocks. ⛰

#core-editor, #editor, #gutenberg

What’s new in Gutenberg? (12th January)

Hope everyone has had some good time! We are resuming the releases of Gutenberg for this new year. The first one — 2.0 — is rather big, with updates across the board. The highlights cover several pasting improvements, a more polished publish flow, block API tweaks and extensibility additions, various accessibility improvements, block library updates (like new querying by category in latest posts), etc.

2.0 🦕

Design and editing experience

Components

Accessibility

Mobile

  • Render toolbar always by the block on mobile.
  • Improve performance of responsive calculations using matchMedia.
  • Avoid shifts around toolbar and scrolling issues on mobile.
  • Improve how the fixed-to-block toolbar looks on mobile. Change how the fixed position toolbars behave, making them sticky.
  • Prevent Mobile Safari from zooming the entire page when you open the inserter.

Block API and Misc.

Bug Fixes

#core-editor, #editor, #gutenberg

Dev Chat Summary: December 20th (4.9.2 week 3)

This post summarizes the dev chat meeting from December 20th (agenda, Slack archive).

4.9.2 planning

  • @sergey to be release lead, @williampatton to be deputy release lead
  • @desrosj able to help with bug scrubs
  • Tentative release timing of 1/16 for beta, 1/23 for RC, and 1/30 for release

Confirm definition of "minor release"

  • Confirmed definition: Bugfixes and enhancements that do not add new deployed files and are at the discretion of the release lead with suggestions/input from component maintainers and committers.
  • @jbpaul17 added that definition to the handbook for future reference (see here, here, and here)

Updates from focus leads and component maintainers

  • Team Editor (Gutenberg): They have no more meetings until January 3rd in #core-editor. The channel is of course open all the time, but meetings will resume then. They also have a request for assistance on video processing of the usability videos from WCUS. Please check the post if you’re available / have interest.
  • Teams Customize and REST API are both on hiatus through the holidays and have no updates this week.
  • Multisite published a post about their roadmap

Meeting hiatus over holidays

  • There will be a two week hiatus for devchat, final meeting for 2017 is today (December 20th). First meeting for 2018 will be January 10th.

General announcements

  • @presskopp looking for advice on getting patches reviewed. Advice given is to ping component maintainers, mention it during devchat's General announcements section, or mention it during a bug scrub.
  • @schlessera looking for advice on getting something on the devchat agenda for January 10th. Advice given is to ping @jbpaul17, mention it during devchat's General announcements section, or add it as a comment to the agenda post. Also noted that Make/Core posts can be a good idea for things that need some discussion and can happen at any time.
  • @schlessera to work on a Make/Core post around the topic of "Servehappy project – current status and how to proceed to have the effort blessed"

#4-9-2, #core, #dev-chat, #summary

What’s new in Gutenberg? (11th December)

Gutenberg is back to a regular schedule after a great WCUS in Nashville which included many conversations and exchanges of ideas. If you missed it, checkout Matt’s State of the Word presentation for an overview of how the year has gone and what lies ahead for Gutenberg. (It also includes a demo of the plugin in action.) It was great to have new people helping at contributor day and submitting pull requests. Thanks!


This release introduces global reusable blocks as the main highlight, but there are also improvements to templates (ability to lock them down), versioning block attributes so markup can be migrated, and many extensibility additions as well as bug fixes.

1.9 🐆

  • Introducing reusable global blocks. (Stored in a wp_blocks post type.)
  • Add ability to lock down the editor when using templates so edits can happen but blocks can't be removed, moved, nor added.
  • Handle and upgrade deprecated blocks. This allows to migrate attributes without invalidating blocks and an important part of the block API.
  • Drag and drop upload support to gallery block.
  • Extensibility:
    • Expose packages/hooks public API under wp.hooks.
    • Introduces withFilters higher-order component to make component filtering easier.
    • Introduces getWrapperDisplayName helper function to make debugging React tree easier.
    • Introduces compose function to unify composing higher-order components.
    • Exposes hook for Block component.

Other changes

From 1.8.1

  • Add ability to switch published post back to draft.
  • Fix issue when changing column count in "text columns" block.
  • Prioritize common items in the autocomplete inserter.
  • Avoid changing publish/update button label when saving draft.
  • Add bottom padding to the editor container to improve experience of writing long posts.
  • Adjust the Classic block toolbar so it doesn't jump.
  • Colorize the little arrow on the left of the admin menu to white to match body content.
  • Update autocomplete suggestions colors to have a sufficient color contrast ratio.
  • Abort focus update when editor is not yet initialized.

#core-editor, #editor, #gutenberg