Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Blocks: Introduce registerBlockTypeFromMetadata API #30293

Merged
merged 8 commits into from
Apr 27, 2021

Conversation

gziolo
Copy link
Member

@gziolo gziolo commented Mar 26, 2021

Description

Fixes #23636.

  1. JSON imports work only in Node.js or with webpack tool. In Gutenberg, we use a custom plugin that inlines JSON in JavaScript as a plain object. We should decide whether we add the same plugin to the shared Babel preset (@wordpress/babel-preset-default) distributed as part of WordPress packages.
  2. We miss the logic that wraps translatable fields with i18n functions, it still needs to be added. In the past, there was a failed attempt to build a Babel macro that would address both points but it wasn’t as straightforward as expected. We were afraid it could be a point of bugs when not configured properly. Related PR: Babel macro: Add new Babel macro which handles block.json file transformation #16088.

This PR proposes we introduce a new API method registerBlockTypeFromMetadata that processes metadata loaded from block.json and applies translations on the fly to the corresponding fields.

Dev Note

In JavaScript, you can use now registerBlockTypeFromMetadata method from @wordpress/blocks package to register a block type using the metadata loaded from block.json file. All localized properties get automatically wrapped in _x (from @wordpress/i18n package) function calls similar to how it works in PHP with register_block_type_from_metadata. The only requirement is to set the textdomain property in the block.json file.

Example:

block.json

{
	"name": "my-plugin/translatable-block",
	"title": "My translatable block",
	"description": "My block with translatable metadata",
	"keywords": [ "translatable" ],
	"textdomain": "my-plugin"
}

index.js

import { registerBlockTypeFromMetadata } from '@wordpress/blocks';
import Edit from './edit';
import metadata from './block.json';

registerBlockTypeFromMetadata( metadata, {
	edit: Edit,
	// ...other client-side settings
} );

How has this been tested?

npm run test-unit

Types of changes

New API.

Checklist:

  • My code is tested.
  • My code follows the WordPress code style.
  • My code follows the accessibility standards.
  • I've tested my changes with keyboard and screen readers.
  • My code has proper inline documentation.
  • I've included developer documentation if appropriate.
  • I've updated all React Native files affected by any refactorings/renamings in this PR (please manually search all *.native.js files for terms that need renaming or removal).

@gziolo gziolo self-assigned this Mar 26, 2021
@gziolo gziolo added [Status] In Progress Tracking issues with work in progress [Feature] Blocks Overall functionality of blocks [Feature] Block API API that allows to express the block paradigm. [Type] New API New API to be used by plugin developers or package users. and removed [Feature] Blocks Overall functionality of blocks labels Mar 26, 2021
@github-actions
Copy link

github-actions bot commented Mar 26, 2021

Size Change: +647 B (0%)

Total Size: 1.47 MB

Filename Size Change
build/annotations/index.js 3.78 kB -3 B (0%)
build/api-fetch/index.js 3.42 kB +2 B (0%)
build/block-editor/index.js 132 kB +2 B (0%)
build/block-library/index.js 153 kB +156 B (0%)
build/blocks/index.js 49.2 kB +474 B (+1%)
build/components/index.js 288 kB +4 B (0%)
build/core-data/index.js 17.1 kB +2 B (0%)
build/customize-widgets/index.js 8.27 kB +1 B (0%)
build/edit-navigation/index.js 17.1 kB -3 B (0%)
build/edit-post/index.js 339 kB -7 B (0%)
build/edit-site/index.js 28.9 kB +7 B (0%)
build/edit-widgets/index.js 16.7 kB -1 B (0%)
build/editor/index.js 42.6 kB -2 B (0%)
build/format-library/index.js 6.77 kB +2 B (0%)
build/keyboard-shortcuts/index.js 2.54 kB +6 B (0%)
build/nux/index.js 3.42 kB +3 B (0%)
build/primitives/index.js 1.42 kB +1 B (0%)
build/rich-text/index.js 13.5 kB +4 B (0%)
build/server-side-render/index.js 2.6 kB -1 B (0%)
ℹ️ View Unchanged
Filename Size Change
build/a11y/index.js 1.14 kB 0 B
build/autop/index.js 2.83 kB 0 B
build/blob/index.js 664 B 0 B
build/block-directory/index.js 8.63 kB 0 B
build/block-directory/style-rtl.css 1 kB 0 B
build/block-directory/style.css 1.01 kB 0 B
build/block-editor/style-rtl.css 13.1 kB 0 B
build/block-editor/style.css 13.1 kB 0 B
build/block-library/blocks/archives/editor-rtl.css 61 B 0 B
build/block-library/blocks/archives/editor.css 60 B 0 B
build/block-library/blocks/audio/editor-rtl.css 58 B 0 B
build/block-library/blocks/audio/editor.css 58 B 0 B
build/block-library/blocks/audio/style-rtl.css 112 B 0 B
build/block-library/blocks/audio/style.css 112 B 0 B
build/block-library/blocks/block/editor-rtl.css 161 B 0 B
build/block-library/blocks/block/editor.css 161 B 0 B
build/block-library/blocks/button/editor-rtl.css 475 B 0 B
build/block-library/blocks/button/editor.css 474 B 0 B
build/block-library/blocks/button/style-rtl.css 503 B 0 B
build/block-library/blocks/button/style.css 503 B 0 B
build/block-library/blocks/buttons/editor-rtl.css 315 B 0 B
build/block-library/blocks/buttons/editor.css 315 B 0 B
build/block-library/blocks/buttons/style-rtl.css 368 B 0 B
build/block-library/blocks/buttons/style.css 368 B 0 B
build/block-library/blocks/calendar/style-rtl.css 208 B 0 B
build/block-library/blocks/calendar/style.css 208 B 0 B
build/block-library/blocks/categories/editor-rtl.css 84 B 0 B
build/block-library/blocks/categories/editor.css 83 B 0 B
build/block-library/blocks/categories/style-rtl.css 79 B 0 B
build/block-library/blocks/categories/style.css 79 B 0 B
build/block-library/blocks/code/style-rtl.css 90 B 0 B
build/block-library/blocks/code/style.css 90 B 0 B
build/block-library/blocks/columns/editor-rtl.css 190 B 0 B
build/block-library/blocks/columns/editor.css 190 B 0 B
build/block-library/blocks/columns/style-rtl.css 436 B 0 B
build/block-library/blocks/columns/style.css 435 B 0 B
build/block-library/blocks/cover/editor-rtl.css 605 B 0 B
build/block-library/blocks/cover/editor.css 605 B 0 B
build/block-library/blocks/cover/style-rtl.css 1.23 kB 0 B
build/block-library/blocks/cover/style.css 1.23 kB 0 B
build/block-library/blocks/embed/editor-rtl.css 486 B 0 B
build/block-library/blocks/embed/editor.css 486 B 0 B
build/block-library/blocks/embed/style-rtl.css 401 B 0 B
build/block-library/blocks/embed/style.css 400 B 0 B
build/block-library/blocks/file/editor-rtl.css 301 B 0 B
build/block-library/blocks/file/editor.css 300 B 0 B
build/block-library/blocks/file/frontend.js 765 B 0 B
build/block-library/blocks/file/style-rtl.css 255 B 0 B
build/block-library/blocks/file/style.css 255 B 0 B
build/block-library/blocks/freeform/editor-rtl.css 2.44 kB 0 B
build/block-library/blocks/freeform/editor.css 2.44 kB 0 B
build/block-library/blocks/gallery/editor-rtl.css 704 B 0 B
build/block-library/blocks/gallery/editor.css 705 B 0 B
build/block-library/blocks/gallery/style-rtl.css 1.09 kB 0 B
build/block-library/blocks/gallery/style.css 1.09 kB 0 B
build/block-library/blocks/group/editor-rtl.css 160 B 0 B
build/block-library/blocks/group/editor.css 160 B 0 B
build/block-library/blocks/group/style-rtl.css 57 B 0 B
build/block-library/blocks/group/style.css 57 B 0 B
build/block-library/blocks/heading/editor-rtl.css 129 B 0 B
build/block-library/blocks/heading/editor.css 129 B 0 B
build/block-library/blocks/heading/style-rtl.css 76 B 0 B
build/block-library/blocks/heading/style.css 76 B 0 B
build/block-library/blocks/html/editor-rtl.css 281 B 0 B
build/block-library/blocks/html/editor.css 281 B 0 B
build/block-library/blocks/image/editor-rtl.css 717 B 0 B
build/block-library/blocks/image/editor.css 716 B 0 B
build/block-library/blocks/image/style-rtl.css 476 B 0 B
build/block-library/blocks/image/style.css 478 B 0 B
build/block-library/blocks/latest-comments/style-rtl.css 281 B 0 B
build/block-library/blocks/latest-comments/style.css 282 B 0 B
build/block-library/blocks/latest-posts/editor-rtl.css 137 B 0 B
build/block-library/blocks/latest-posts/editor.css 137 B 0 B
build/block-library/blocks/latest-posts/style-rtl.css 523 B 0 B
build/block-library/blocks/latest-posts/style.css 522 B 0 B
build/block-library/blocks/legacy-widget/editor-rtl.css 398 B 0 B
build/block-library/blocks/legacy-widget/editor.css 399 B 0 B
build/block-library/blocks/list/style-rtl.css 63 B 0 B
build/block-library/blocks/list/style.css 63 B 0 B
build/block-library/blocks/media-text/editor-rtl.css 191 B 0 B
build/block-library/blocks/media-text/editor.css 191 B 0 B
build/block-library/blocks/media-text/style-rtl.css 535 B 0 B
build/block-library/blocks/media-text/style.css 532 B 0 B
build/block-library/blocks/more/editor-rtl.css 434 B 0 B
build/block-library/blocks/more/editor.css 434 B 0 B
build/block-library/blocks/navigation-link/editor-rtl.css 597 B 0 B
build/block-library/blocks/navigation-link/editor.css 597 B 0 B
build/block-library/blocks/navigation-link/style-rtl.css 1.17 kB 0 B
build/block-library/blocks/navigation-link/style.css 1.18 kB 0 B
build/block-library/blocks/navigation/editor-rtl.css 1.19 kB 0 B
build/block-library/blocks/navigation/editor.css 1.19 kB 0 B
build/block-library/blocks/navigation/style-rtl.css 272 B 0 B
build/block-library/blocks/navigation/style.css 271 B 0 B
build/block-library/blocks/nextpage/editor-rtl.css 395 B 0 B
build/block-library/blocks/nextpage/editor.css 395 B 0 B
build/block-library/blocks/page-list/editor-rtl.css 239 B 0 B
build/block-library/blocks/page-list/editor.css 240 B 0 B
build/block-library/blocks/page-list/style-rtl.css 167 B 0 B
build/block-library/blocks/page-list/style.css 167 B 0 B
build/block-library/blocks/paragraph/editor-rtl.css 157 B 0 B
build/block-library/blocks/paragraph/editor.css 157 B 0 B
build/block-library/blocks/paragraph/style-rtl.css 247 B 0 B
build/block-library/blocks/paragraph/style.css 248 B 0 B
build/block-library/blocks/post-author/editor-rtl.css 209 B 0 B
build/block-library/blocks/post-author/editor.css 209 B 0 B
build/block-library/blocks/post-author/style-rtl.css 183 B 0 B
build/block-library/blocks/post-author/style.css 184 B 0 B
build/block-library/blocks/post-comments-form/style-rtl.css 250 B 0 B
build/block-library/blocks/post-comments-form/style.css 250 B 0 B
build/block-library/blocks/post-content/editor-rtl.css 139 B 0 B
build/block-library/blocks/post-content/editor.css 139 B 0 B
build/block-library/blocks/post-excerpt/editor-rtl.css 73 B 0 B
build/block-library/blocks/post-excerpt/editor.css 73 B 0 B
build/block-library/blocks/post-excerpt/style-rtl.css 69 B 0 B
build/block-library/blocks/post-excerpt/style.css 69 B 0 B
build/block-library/blocks/post-featured-image/editor-rtl.css 338 B 0 B
build/block-library/blocks/post-featured-image/editor.css 338 B 0 B
build/block-library/blocks/post-featured-image/style-rtl.css 100 B 0 B
build/block-library/blocks/post-featured-image/style.css 100 B 0 B
build/block-library/blocks/post-title/style-rtl.css 60 B 0 B
build/block-library/blocks/post-title/style.css 60 B 0 B
build/block-library/blocks/preformatted/style-rtl.css 103 B 0 B
build/block-library/blocks/preformatted/style.css 103 B 0 B
build/block-library/blocks/pullquote/editor-rtl.css 183 B 0 B
build/block-library/blocks/pullquote/editor.css 183 B 0 B
build/block-library/blocks/pullquote/style-rtl.css 318 B 0 B
build/block-library/blocks/pullquote/style.css 318 B 0 B
build/block-library/blocks/query-loop/editor-rtl.css 83 B 0 B
build/block-library/blocks/query-loop/editor.css 82 B 0 B
build/block-library/blocks/query-loop/style-rtl.css 315 B 0 B
build/block-library/blocks/query-loop/style.css 317 B 0 B
build/block-library/blocks/query-pagination-numbers/editor-rtl.css 122 B 0 B
build/block-library/blocks/query-pagination-numbers/editor.css 121 B 0 B
build/block-library/blocks/query-pagination/editor-rtl.css 270 B 0 B
build/block-library/blocks/query-pagination/editor.css 262 B 0 B
build/block-library/blocks/query-pagination/style-rtl.css 168 B 0 B
build/block-library/blocks/query-pagination/style.css 168 B 0 B
build/block-library/blocks/query-title/editor-rtl.css 86 B 0 B
build/block-library/blocks/query-title/editor.css 86 B 0 B
build/block-library/blocks/query/editor-rtl.css 131 B 0 B
build/block-library/blocks/query/editor.css 132 B 0 B
build/block-library/blocks/quote/style-rtl.css 169 B 0 B
build/block-library/blocks/quote/style.css 169 B 0 B
build/block-library/blocks/rss/editor-rtl.css 201 B 0 B
build/block-library/blocks/rss/editor.css 202 B 0 B
build/block-library/blocks/rss/style-rtl.css 290 B 0 B
build/block-library/blocks/rss/style.css 290 B 0 B
build/block-library/blocks/search/editor-rtl.css 189 B 0 B
build/block-library/blocks/search/editor.css 189 B 0 B
build/block-library/blocks/search/style-rtl.css 359 B 0 B
build/block-library/blocks/search/style.css 362 B 0 B
build/block-library/blocks/separator/editor-rtl.css 99 B 0 B
build/block-library/blocks/separator/editor.css 99 B 0 B
build/block-library/blocks/separator/style-rtl.css 251 B 0 B
build/block-library/blocks/separator/style.css 251 B 0 B
build/block-library/blocks/shortcode/editor-rtl.css 512 B 0 B
build/block-library/blocks/shortcode/editor.css 512 B 0 B
build/block-library/blocks/site-logo/editor-rtl.css 440 B 0 B
build/block-library/blocks/site-logo/editor.css 441 B 0 B
build/block-library/blocks/site-logo/style-rtl.css 154 B 0 B
build/block-library/blocks/site-logo/style.css 154 B 0 B
build/block-library/blocks/social-link/editor-rtl.css 164 B 0 B
build/block-library/blocks/social-link/editor.css 165 B 0 B
build/block-library/blocks/social-links/editor-rtl.css 796 B 0 B
build/block-library/blocks/social-links/editor.css 795 B 0 B
build/block-library/blocks/social-links/style-rtl.css 1.32 kB 0 B
build/block-library/blocks/social-links/style.css 1.33 kB 0 B
build/block-library/blocks/spacer/editor-rtl.css 308 B 0 B
build/block-library/blocks/spacer/editor.css 308 B 0 B
build/block-library/blocks/spacer/style-rtl.css 48 B 0 B
build/block-library/blocks/spacer/style.css 48 B 0 B
build/block-library/blocks/table/editor-rtl.css 478 B 0 B
build/block-library/blocks/table/editor.css 478 B 0 B
build/block-library/blocks/table/style-rtl.css 402 B 0 B
build/block-library/blocks/table/style.css 402 B 0 B
build/block-library/blocks/tag-cloud/editor-rtl.css 118 B 0 B
build/block-library/blocks/tag-cloud/editor.css 118 B 0 B
build/block-library/blocks/tag-cloud/style-rtl.css 94 B 0 B
build/block-library/blocks/tag-cloud/style.css 94 B 0 B
build/block-library/blocks/template-part/editor-rtl.css 552 B 0 B
build/block-library/blocks/template-part/editor.css 551 B 0 B
build/block-library/blocks/term-description/editor-rtl.css 90 B 0 B
build/block-library/blocks/term-description/editor.css 90 B 0 B
build/block-library/blocks/text-columns/editor-rtl.css 95 B 0 B
build/block-library/blocks/text-columns/editor.css 95 B 0 B
build/block-library/blocks/text-columns/style-rtl.css 166 B 0 B
build/block-library/blocks/text-columns/style.css 166 B 0 B
build/block-library/blocks/verse/style-rtl.css 87 B 0 B
build/block-library/blocks/verse/style.css 87 B 0 B
build/block-library/blocks/video/editor-rtl.css 568 B 0 B
build/block-library/blocks/video/editor.css 569 B 0 B
build/block-library/blocks/video/style-rtl.css 173 B 0 B
build/block-library/blocks/video/style.css 173 B 0 B
build/block-library/common-rtl.css 1.31 kB 0 B
build/block-library/common.css 1.31 kB 0 B
build/block-library/editor-rtl.css 9.41 kB 0 B
build/block-library/editor.css 9.41 kB 0 B
build/block-library/reset-rtl.css 502 B 0 B
build/block-library/reset.css 503 B 0 B
build/block-library/style-rtl.css 9.55 kB 0 B
build/block-library/style.css 9.56 kB 0 B
build/block-library/theme-rtl.css 692 B 0 B
build/block-library/theme.css 693 B 0 B
build/block-serialization-default-parser/index.js 1.87 kB 0 B
build/block-serialization-spec-parser/index.js 3.06 kB 0 B
build/components/style-rtl.css 16.3 kB 0 B
build/components/style.css 16.3 kB 0 B
build/compose/index.js 11.6 kB 0 B
build/customize-widgets/style-rtl.css 666 B 0 B
build/customize-widgets/style.css 667 B 0 B
build/data-controls/index.js 838 B 0 B
build/data/index.js 9.2 kB 0 B
build/date/index.js 31.9 kB 0 B
build/deprecated/index.js 787 B 0 B
build/dom-ready/index.js 576 B 0 B
build/dom/index.js 5.12 kB 0 B
build/edit-navigation/style-rtl.css 2.86 kB 0 B
build/edit-navigation/style.css 2.86 kB 0 B
build/edit-post/classic-rtl.css 454 B 0 B
build/edit-post/classic.css 454 B 0 B
build/edit-post/style-rtl.css 6.96 kB 0 B
build/edit-post/style.css 6.95 kB 0 B
build/edit-site/style-rtl.css 4.9 kB 0 B
build/edit-site/style.css 4.89 kB 0 B
build/edit-widgets/style-rtl.css 2.97 kB 0 B
build/edit-widgets/style.css 2.98 kB 0 B
build/editor/style-rtl.css 3.9 kB 0 B
build/editor/style.css 3.9 kB 0 B
build/element/index.js 4.62 kB 0 B
build/escape-html/index.js 735 B 0 B
build/format-library/style-rtl.css 637 B 0 B
build/format-library/style.css 639 B 0 B
build/hooks/index.js 2.28 kB 0 B
build/html-entities/index.js 623 B 0 B
build/i18n/index.js 4.04 kB 0 B
build/is-shallow-equal/index.js 698 B 0 B
build/keycodes/index.js 1.95 kB 0 B
build/list-reusable-blocks/index.js 3.19 kB 0 B
build/list-reusable-blocks/style-rtl.css 629 B 0 B
build/list-reusable-blocks/style.css 628 B 0 B
build/media-utils/index.js 5.39 kB 0 B
build/notices/index.js 1.85 kB 0 B
build/nux/style-rtl.css 731 B 0 B
build/nux/style.css 727 B 0 B
build/plugins/index.js 2.95 kB 0 B
build/priority-queue/index.js 790 B 0 B
build/react-i18n/index.js 1.45 kB 0 B
build/redux-routine/index.js 2.83 kB 0 B
build/reusable-blocks/index.js 3.8 kB 0 B
build/reusable-blocks/style-rtl.css 225 B 0 B
build/reusable-blocks/style.css 225 B 0 B
build/shortcode/index.js 1.7 kB 0 B
build/token-list/index.js 1.27 kB 0 B
build/url/index.js 3.01 kB 0 B
build/viewport/index.js 1.85 kB 0 B
build/warning/index.js 1.14 kB 0 B
build/wordcount/index.js 1.22 kB 0 B

compressed-size-action

@gziolo gziolo force-pushed the add/register-block-type-from-metadata branch 3 times, most recently from dd78fb3 to 1a6154e Compare March 30, 2021 09:37
@gziolo gziolo force-pushed the add/register-block-type-from-metadata branch from 1a6154e to a0bba9e Compare April 13, 2021 14:11
@gziolo gziolo requested review from oandregal and mcsf April 13, 2021 14:18
@gziolo
Copy link
Member Author

gziolo commented Apr 13, 2021

It's nearly ready. I still have to find out how to dynamically translate the value read from the block.json. Covering it with unit tests might be yet another challenge as it needs some mocking.

@gziolo gziolo added the Needs Dev Note Requires a developer note for a major WordPress release cycle label Apr 13, 2021
@gziolo gziolo force-pushed the add/register-block-type-from-metadata branch from a0bba9e to c0b328d Compare April 22, 2021 11:40
@gziolo gziolo removed the [Status] In Progress Tracking issues with work in progress label Apr 22, 2021
@gziolo gziolo marked this pull request as ready for review April 22, 2021 13:56
@gziolo gziolo requested a review from a team April 22, 2021 14:03
@gziolo gziolo force-pushed the add/register-block-type-from-metadata branch from c0b328d to 7f6d4cb Compare April 22, 2021 14:43
@gziolo gziolo requested review from nerrad and ntwb as code owners April 22, 2021 14:43
@gziolo gziolo added the [Package] Blocks /packages/blocks label Apr 22, 2021
@gziolo gziolo force-pushed the add/register-block-type-from-metadata branch from 7f6d4cb to d9ba0cb Compare April 22, 2021 14:44
textdomain
) {
if ( isString( i18nSchema ) && isString( settingValue ) ) {
// eslint-disable-next-line @wordpress/i18n-no-variables, @wordpress/i18n-text-domain
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@swissspidy, do we need to do something special to ensure this particular translation call is ignored during WP-CLI processing?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

String extraction will skip anything that‘s not a string literal, so no.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks!

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gziolo How are the translations supposed to be in wp.i18n without a specific wp.i18n.setLocaleData() call? The strings from the block.json aren't assigned to a JavaScript file thus not automatically part of a JSON translation file. But I might be missing something here? Or are we fully relying on server-side registration for the strings?

Copy link
Member Author

@gziolo gziolo Jun 21, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the context of WordPress core, they are always registered on the server and translated there before passed to the client. At the moment, there is a temporary JS method unstable__bootstrapServerSideBlockDefinitions that takes care of setting data generated with PHP. In the future, we are going to use the REST API endpoint for blocks, but the general idea is going to be the same - translations get applied when registering a block on the server.

In practice, this implementation is a fallback for everything else that depends only on JavaScript:

  • standalone block editor like Storybook integration (although this is a bad example as it is never translated)
  • native mobile apps still consume only JavaScript codebase so they have to collect all translations themselves (it might change when we start using the REST API endpoint for blocks)

@gziolo gziolo requested a review from swissspidy April 22, 2021 15:05
@@ -0,0 +1,12 @@
{
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@gwwar, should we put here variations as well which we plan to integrate with block.json soon?

There is one more place where we would need to put it on the allow list.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it'd be worth a try, will it affect the needed PR order?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let me think about what we need to change to enable variations in block.json on the PHP side. As far as I can tell, it's mostly the same set of changes like here now that WP_Block_Type and the REST API endpoint support block variations. Given that you won't be able to register block variations on the server until WP 5.8 is out the order shouldn't matter at all. We also have a mechanism in place that favors definitions from the server but fallback to the client when not set there. I think it's safe to change here at the same time 👍🏻

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Added in b851c2f. Every change to docs get synced with https://developer.wordpress.org/block-editor/reference-guides/block-api/block-metadata/ so I will open another PR that covers the part that describes variations in the block.json file. We should plan to merge it around WordPress 5.8 RC.1 when all Dev Notes get published.

@gziolo
Copy link
Member Author

gziolo commented Apr 23, 2021

I opened #31120 that is based on this branch and it presents how it will simplify handling blocks:

diff --git a/packages/block-library/src/archives/block.json b/packages/block-library/src/archives/block.json
index d35f8b05001c..0c94c4b44b35 100644
--- a/packages/block-library/src/archives/block.json
+++ b/packages/block-library/src/archives/block.json
@@ -1,7 +1,10 @@
 {
 	"apiVersion": 2,
 	"name": "core/archives",
+	"title": "Archives",
+	"description": "Display a monthly archive of your posts.",
 	"category": "widgets",
+	"textdomain": "default",
 	"attributes": {
 		"displayAsDropdown": {
 			"type": "boolean",
diff --git a/packages/block-library/src/archives/index.js b/packages/block-library/src/archives/index.js
index 6bfdbef7abce..e1f01f30a718 100644
--- a/packages/block-library/src/archives/index.js
+++ b/packages/block-library/src/archives/index.js
@@ -2,7 +2,6 @@
  * WordPress dependencies
  */
 import { archive as icon } from '@wordpress/icons';
-import { __, _x } from '@wordpress/i18n';
 
 /**
  * Internal dependencies
@@ -15,8 +14,6 @@ const { name } = metadata;
 export { metadata, name };
 
 export const settings = {
-	title: _x( 'Archives', 'block title' ),
-	description: __( 'Display a monthly archive of your posts.' ),
 	icon,
 	example: {},
 	edit,

@gziolo gziolo force-pushed the add/register-block-type-from-metadata branch from b851c2f to f371ba8 Compare April 23, 2021 10:05
'icon',
'description',
'keywords',
'attributes',
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does i18n support get added for string default values? For example let's say we have

"attributes": {
		"label": {
			"type": "string",
                         "default": "Home",
		},
		"opensInNewTab": {
			"type": "boolean",
                         "default": false,
		},
}

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

No, we should rather avoid it because it won't produce predictable content. Depending on the language picked in the admin UI, you could get a different output for the same block. We need to remember also that, the value of an attribute when strictly equal to the default value it doesn't get stored in HTML comment of the block definition. The other challenge is, how would you decide which default values need to be translated and for which blocks?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need to remember also that, the value of an attribute when strictly equal to the default value it doesn't get stored in HTML comment of the block definition.

🤔 good to highlight this case.

The other challenge is, how would you decide which default values need to be translated and for which blocks?

If we wanted to support it, we could add an additional attribute. I found that I did need it in one of the blocks, but the behavior can also be simulated with a useEffect hook in the block.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If we wanted to support it, we could add an additional attribute. I found that I did need it in one of the blocks, but the behavior can also be simulated with a useEffect hook in the block.

When using a side effect as part of the React component lifecycle, you are updating an attribute that might create an undo level so you need to use a special version of the store action that mitigates that. Another approach is to use a block variation that gets applied as the default one in the inserter. The benefit of that is that it sets attributes dynamically when inserting the block.

@gwwar
Copy link
Contributor

gwwar commented Apr 23, 2021

Let us know what type of feedback/testng you'd like on this one @gziolo to help move this forward.

) {
if ( isString( i18nSchema ) && isString( settingValue ) ) {
// eslint-disable-next-line @wordpress/i18n-no-variables, @wordpress/i18n-text-domain
return _x( settingValue, i18nSchema, textdomain );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Aren't we going to cause a string extraction because of the usage of _x function? Maybe because we are using variables the extraction does not happen? On the PHP side, we use an internal function to avoid this issue.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See comment from @swissspidy in #30293 (comment):

String extraction will skip anything that‘s not a string literal

) {
if ( isString( i18nSchema ) && isString( settingValue ) ) {
// eslint-disable-next-line @wordpress/i18n-no-variables, @wordpress/i18n-text-domain
return _x( settingValue, i18nSchema, textdomain );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Things like the block description currently don't have a context and now are going to have one. I guess their current translation will be invalidated, should we make some dev note or something equivalent to dev note for translators?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I understand it will be automatically handled during the WordPress release cycle, and it's the same process that happens for every newly added or updated translation. We did a batch updated of UI labels in the block editor in the past, and I don't remember any dev notes related to that.

) {
if ( isString( i18nSchema ) && isString( settingValue ) ) {
// eslint-disable-next-line @wordpress/i18n-no-variables, @wordpress/i18n-text-domain
return _x( settingValue, i18nSchema, textdomain );
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the branch of PR #31120, I made a simple test and replaced "return _x( settingValue, i18nSchema, textdomain );" with "return 'ok';". Nothing changed. With this change shouldn't all the block titles and descriptions appear as "ok"?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It might require adding a fallback to read the value from the client when it isn't provided from the server. It would be useful for WordPress 5.7 when using with the Gutenberg plugin.

Copy link
Member Author

@gziolo gziolo Apr 26, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I investigate it further and it's a different use case than apiVersion setting that I was referring to:

if ( serverSideBlockDefinitions[ blockName ] ) {
// We still need to polyfill `apiVersion` for WordPress version
// lower than 5.7. If it isn't present in the definition shared
// from the server, we try to fallback to the definition passed.
// @see https://github.com/WordPress/gutenberg/pull/29279
if (
serverSideBlockDefinitions[ blockName ].apiVersion ===
undefined &&
definitions[ blockName ].apiVersion
) {
serverSideBlockDefinitions[ blockName ].apiVersion =
definitions[ blockName ].apiVersion;
}
continue;
}

We register all blocks on the server and we set now all translatable fields there and they are exposed to the client. The values from the server take precedence to respect all PHP filters that could get applied to the metadata. It's the same data after all, so there is no reason to override it with the same metadata read on the client.

To test it, you could change the method I embedded above and enforce that those fields get overridden with the values loaded on the client. Maybe you could also tweak register_block_type_from_metadata calls on the server to somehow ignore translatable fields using block_type_metadata_settings filter, but you rather would need to prevent registration of the block you want to test with on the server.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the clarification 👍

@gziolo
Copy link
Member Author

gziolo commented Apr 26, 2021

Let us know what type of feedback/testng you'd like on this one @gziolo to help move this forward.

I opened #31120 which is based on this branch that moves all translatable fields to block.json. The challenge with testing is that it's going to use all metadata from the server and happy all translations there for the WordPress scenario. To test how it works on the client you can check with the React Native mobile app or with Storybook (npm run storybook:build). Storybook doesn't apply translations but it could be tested with i18n hooks like in unit tests or with the changes that @jorgefilipecosta mentioned in #30293 (comment).

Copy link
Member

@jorgefilipecosta jorgefilipecosta left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM 👍

Copy link
Contributor

@gwwar gwwar left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Stepping through the code I think this looks correct ✅


const settings = pick( metadata, allowedFields );

if ( textdomain ) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

As far as I checked, in the native version we set the locale data without defining a text domain, not sure if this could be a problem if in the future we move some of the fields to the block.json file to do the on fly translation.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

default is the default text domain, so this is what I'm using in #31120. I think it should be fine.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
[Feature] Block API API that allows to express the block paradigm. Internationalization (i18n) Issues or PRs related to internationalization efforts [Package] Blocks /packages/blocks [Type] New API New API to be used by plugin developers or package users.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Block API: Add i18n support to block.json metadata file
7 participants