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

Add theme.json i18n mechanism and JSON file specifying which theme.json paths are translatable #27380

Conversation

jorgefilipecosta
Copy link
Member

This PR exposes a JSON file with the theme.json paths that are translatable as suggested in wp-cli/i18n-command#224 (comment) by @schlessera.
For now this file is part of Gutenberg plugin but it should be part of core when we update the Gutenberg release core contains.
This file can be used by wp-cli to know which strings to extract from theme.json.

This PR also makes sure we call the WordPress translation functions on the theme.json structure from core, and themes. In order to have the strings translated.
To iterate on the tree and know the paths that are translatable we rely on the same JSON file.

How has this been tested?

I changed the translate function call to a hard-coded value that appends both parameters and I verified the "translation" was applied.

@jorgefilipecosta jorgefilipecosta added Internationalization (i18n) Issues or PRs related to internationalization efforts Global Styles Anything related to the broader Global Styles efforts, including Styles Engine and theme.json labels Nov 30, 2020
@github-actions
Copy link

github-actions bot commented Nov 30, 2020

Size Change: 0 B

Total Size: 1.28 MB

ℹ️ View Unchanged
Filename Size Change
build/a11y/index.js 1.14 kB 0 B
build/annotations/index.js 3.8 kB 0 B
build/api-fetch/index.js 3.42 kB 0 B
build/autop/index.js 2.83 kB 0 B
build/blob/index.js 665 B 0 B
build/block-directory/index.js 9.03 kB 0 B
build/block-directory/style-rtl.css 1.01 kB 0 B
build/block-directory/style.css 1.01 kB 0 B
build/block-editor/index.js 121 kB 0 B
build/block-editor/style-rtl.css 11.7 kB 0 B
build/block-editor/style.css 11.7 kB 0 B
build/block-library/blocks/archives/editor-rtl.css 196 B 0 B
build/block-library/blocks/archives/editor.css 196 B 0 B
build/block-library/blocks/audio/editor-rtl.css 194 B 0 B
build/block-library/blocks/audio/editor.css 194 B 0 B
build/block-library/blocks/audio/style-rtl.css 225 B 0 B
build/block-library/blocks/audio/style.css 225 B 0 B
build/block-library/blocks/block/editor-rtl.css 283 B 0 B
build/block-library/blocks/block/editor.css 283 B 0 B
build/block-library/blocks/button/editor-rtl.css 576 B 0 B
build/block-library/blocks/button/editor.css 577 B 0 B
build/block-library/blocks/button/style-rtl.css 552 B 0 B
build/block-library/blocks/button/style.css 552 B 0 B
build/block-library/blocks/buttons/editor-rtl.css 345 B 0 B
build/block-library/blocks/buttons/editor.css 346 B 0 B
build/block-library/blocks/buttons/style-rtl.css 419 B 0 B
build/block-library/blocks/buttons/style.css 419 B 0 B
build/block-library/blocks/calendar/style-rtl.css 319 B 0 B
build/block-library/blocks/calendar/style.css 319 B 0 B
build/block-library/blocks/categories/editor-rtl.css 210 B 0 B
build/block-library/blocks/categories/editor.css 209 B 0 B
build/block-library/blocks/categories/style-rtl.css 208 B 0 B
build/block-library/blocks/categories/style.css 208 B 0 B
build/block-library/blocks/code/style-rtl.css 216 B 0 B
build/block-library/blocks/code/style.css 216 B 0 B
build/block-library/blocks/columns/editor-rtl.css 300 B 0 B
build/block-library/blocks/columns/editor.css 299 B 0 B
build/block-library/blocks/columns/style-rtl.css 529 B 0 B
build/block-library/blocks/columns/style.css 528 B 0 B
build/block-library/blocks/cover/editor-rtl.css 508 B 0 B
build/block-library/blocks/cover/editor.css 506 B 0 B
build/block-library/blocks/cover/style-rtl.css 1.32 kB 0 B
build/block-library/blocks/cover/style.css 1.32 kB 0 B
build/block-library/blocks/embed/editor-rtl.css 594 B 0 B
build/block-library/blocks/embed/editor.css 595 B 0 B
build/block-library/blocks/embed/style-rtl.css 489 B 0 B
build/block-library/blocks/embed/style.css 489 B 0 B
build/block-library/blocks/file/editor-rtl.css 314 B 0 B
build/block-library/blocks/file/editor.css 313 B 0 B
build/block-library/blocks/file/style-rtl.css 352 B 0 B
build/block-library/blocks/file/style.css 352 B 0 B
build/block-library/blocks/freeform/editor-rtl.css 2.55 kB 0 B
build/block-library/blocks/freeform/editor.css 2.55 kB 0 B
build/block-library/blocks/gallery/editor-rtl.css 749 B 0 B
build/block-library/blocks/gallery/editor.css 750 B 0 B
build/block-library/blocks/gallery/style-rtl.css 1.17 kB 0 B
build/block-library/blocks/gallery/style.css 1.17 kB 0 B
build/block-library/blocks/group/editor-rtl.css 433 B 0 B
build/block-library/blocks/group/editor.css 432 B 0 B
build/block-library/blocks/group/style-rtl.css 190 B 0 B
build/block-library/blocks/group/style.css 190 B 0 B
build/block-library/blocks/heading/editor-rtl.css 248 B 0 B
build/block-library/blocks/heading/editor.css 248 B 0 B
build/block-library/blocks/heading/style-rtl.css 212 B 0 B
build/block-library/blocks/heading/style.css 212 B 0 B
build/block-library/blocks/html/editor-rtl.css 384 B 0 B
build/block-library/blocks/html/editor.css 385 B 0 B
build/block-library/blocks/image/editor-rtl.css 801 B 0 B
build/block-library/blocks/image/editor.css 800 B 0 B
build/block-library/blocks/image/style-rtl.css 569 B 0 B
build/block-library/blocks/image/style.css 570 B 0 B
build/block-library/blocks/latest-comments/editor-rtl.css 277 B 0 B
build/block-library/blocks/latest-comments/editor.css 275 B 0 B
build/block-library/blocks/latest-comments/style-rtl.css 382 B 0 B
build/block-library/blocks/latest-comments/style.css 382 B 0 B
build/block-library/blocks/latest-posts/editor-rtl.css 254 B 0 B
build/block-library/blocks/latest-posts/editor.css 254 B 0 B
build/block-library/blocks/latest-posts/style-rtl.css 634 B 0 B
build/block-library/blocks/latest-posts/style.css 634 B 0 B
build/block-library/blocks/list/editor-rtl.css 203 B 0 B
build/block-library/blocks/list/editor.css 203 B 0 B
build/block-library/blocks/list/style-rtl.css 201 B 0 B
build/block-library/blocks/list/style.css 201 B 0 B
build/block-library/blocks/media-text/editor-rtl.css 311 B 0 B
build/block-library/blocks/media-text/editor.css 311 B 0 B
build/block-library/blocks/media-text/style-rtl.css 642 B 0 B
build/block-library/blocks/media-text/style.css 640 B 0 B
build/block-library/blocks/more/editor-rtl.css 545 B 0 B
build/block-library/blocks/more/editor.css 545 B 0 B
build/block-library/blocks/navigation-link/editor-rtl.css 503 B 0 B
build/block-library/blocks/navigation-link/editor.css 504 B 0 B
build/block-library/blocks/navigation-link/style-rtl.css 805 B 0 B
build/block-library/blocks/navigation-link/style.css 803 B 0 B
build/block-library/blocks/navigation/editor-rtl.css 1.38 kB 0 B
build/block-library/blocks/navigation/editor.css 1.38 kB 0 B
build/block-library/blocks/navigation/style-rtl.css 274 B 0 B
build/block-library/blocks/navigation/style.css 274 B 0 B
build/block-library/blocks/nextpage/editor-rtl.css 507 B 0 B
build/block-library/blocks/nextpage/editor.css 507 B 0 B
build/block-library/blocks/paragraph/editor-rtl.css 236 B 0 B
build/block-library/blocks/paragraph/editor.css 236 B 0 B
build/block-library/blocks/paragraph/style-rtl.css 351 B 0 B
build/block-library/blocks/paragraph/style.css 352 B 0 B
build/block-library/blocks/post-author/editor-rtl.css 329 B 0 B
build/block-library/blocks/post-author/editor.css 329 B 0 B
build/block-library/blocks/post-author/style-rtl.css 303 B 0 B
build/block-library/blocks/post-author/style.css 303 B 0 B
build/block-library/blocks/post-comments-form/style-rtl.css 358 B 0 B
build/block-library/blocks/post-comments-form/style.css 358 B 0 B
build/block-library/blocks/post-content/editor-rtl.css 262 B 0 B
build/block-library/blocks/post-content/editor.css 262 B 0 B
build/block-library/blocks/post-excerpt/editor-rtl.css 206 B 0 B
build/block-library/blocks/post-excerpt/editor.css 206 B 0 B
build/block-library/blocks/post-featured-image/editor-rtl.css 453 B 0 B
build/block-library/blocks/post-featured-image/editor.css 453 B 0 B
build/block-library/blocks/post-featured-image/style-rtl.css 223 B 0 B
build/block-library/blocks/post-featured-image/style.css 223 B 0 B
build/block-library/blocks/preformatted/style-rtl.css 193 B 0 B
build/block-library/blocks/preformatted/style.css 193 B 0 B
build/block-library/blocks/pullquote/editor-rtl.css 304 B 0 B
build/block-library/blocks/pullquote/editor.css 304 B 0 B
build/block-library/blocks/pullquote/style-rtl.css 428 B 0 B
build/block-library/blocks/pullquote/style.css 428 B 0 B
build/block-library/blocks/query-loop/editor-rtl.css 217 B 0 B
build/block-library/blocks/query-loop/editor.css 216 B 0 B
build/block-library/blocks/query-loop/style-rtl.css 427 B 0 B
build/block-library/blocks/query-loop/style.css 429 B 0 B
build/block-library/blocks/query/editor-rtl.css 279 B 0 B
build/block-library/blocks/query/editor.css 279 B 0 B
build/block-library/blocks/quote/editor-rtl.css 195 B 0 B
build/block-library/blocks/quote/editor.css 195 B 0 B
build/block-library/blocks/quote/style-rtl.css 284 B 0 B
build/block-library/blocks/quote/style.css 285 B 0 B
build/block-library/blocks/rss/editor-rtl.css 307 B 0 B
build/block-library/blocks/rss/editor.css 309 B 0 B
build/block-library/blocks/rss/style-rtl.css 394 B 0 B
build/block-library/blocks/rss/style.css 393 B 0 B
build/block-library/blocks/search/editor-rtl.css 285 B 0 B
build/block-library/blocks/search/editor.css 285 B 0 B
build/block-library/blocks/search/style-rtl.css 454 B 0 B
build/block-library/blocks/search/style.css 456 B 0 B
build/block-library/blocks/separator/editor-rtl.css 229 B 0 B
build/block-library/blocks/separator/editor.css 229 B 0 B
build/block-library/blocks/separator/style-rtl.css 352 B 0 B
build/block-library/blocks/separator/style.css 352 B 0 B
build/block-library/blocks/shortcode/editor-rtl.css 603 B 0 B
build/block-library/blocks/shortcode/editor.css 603 B 0 B
build/block-library/blocks/site-logo/editor-rtl.css 321 B 0 B
build/block-library/blocks/site-logo/editor.css 321 B 0 B
build/block-library/blocks/site-logo/style-rtl.css 238 B 0 B
build/block-library/blocks/site-logo/style.css 238 B 0 B
build/block-library/blocks/social-link/editor-rtl.css 283 B 0 B
build/block-library/blocks/social-link/editor.css 283 B 0 B
build/block-library/blocks/social-links/editor-rtl.css 811 B 0 B
build/block-library/blocks/social-links/editor.css 810 B 0 B
build/block-library/blocks/social-links/style-rtl.css 1.44 kB 0 B
build/block-library/blocks/social-links/style.css 1.44 kB 0 B
build/block-library/blocks/spacer/editor-rtl.css 391 B 0 B
build/block-library/blocks/spacer/editor.css 391 B 0 B
build/block-library/blocks/spacer/style-rtl.css 184 B 0 B
build/block-library/blocks/spacer/style.css 184 B 0 B
build/block-library/blocks/subhead/editor-rtl.css 223 B 0 B
build/block-library/blocks/subhead/editor.css 223 B 0 B
build/block-library/blocks/subhead/style-rtl.css 210 B 0 B
build/block-library/blocks/subhead/style.css 210 B 0 B
build/block-library/blocks/table/editor-rtl.css 593 B 0 B
build/block-library/blocks/table/editor.css 593 B 0 B
build/block-library/blocks/table/style-rtl.css 501 B 0 B
build/block-library/blocks/table/style.css 501 B 0 B
build/block-library/blocks/tag-cloud/editor-rtl.css 237 B 0 B
build/block-library/blocks/tag-cloud/editor.css 235 B 0 B
build/block-library/blocks/tag-cloud/style-rtl.css 221 B 0 B
build/block-library/blocks/tag-cloud/style.css 221 B 0 B
build/block-library/blocks/template-part/editor-rtl.css 714 B 0 B
build/block-library/blocks/template-part/editor.css 714 B 0 B
build/block-library/blocks/text-columns/editor-rtl.css 220 B 0 B
build/block-library/blocks/text-columns/editor.css 220 B 0 B
build/block-library/blocks/text-columns/style-rtl.css 283 B 0 B
build/block-library/blocks/text-columns/style.css 283 B 0 B
build/block-library/blocks/verse/editor-rtl.css 194 B 0 B
build/block-library/blocks/verse/editor.css 194 B 0 B
build/block-library/blocks/verse/style-rtl.css 215 B 0 B
build/block-library/blocks/verse/style.css 215 B 0 B
build/block-library/blocks/video/editor-rtl.css 617 B 0 B
build/block-library/blocks/video/editor.css 617 B 0 B
build/block-library/blocks/video/style-rtl.css 303 B 0 B
build/block-library/blocks/video/style.css 304 B 0 B
build/block-library/common-rtl.css 1.01 kB 0 B
build/block-library/common.css 1.01 kB 0 B
build/block-library/editor-rtl.css 8.94 kB 0 B
build/block-library/editor.css 8.94 kB 0 B
build/block-library/index.js 141 kB 0 B
build/block-library/style-rtl.css 8.52 kB 0 B
build/block-library/style.css 8.52 kB 0 B
build/block-library/theme-rtl.css 860 B 0 B
build/block-library/theme.css 860 B 0 B
build/block-serialization-default-parser/index.js 1.88 kB 0 B
build/block-serialization-spec-parser/index.js 3.06 kB 0 B
build/blocks/index.js 48.1 kB 0 B
build/components/index.js 173 kB 0 B
build/components/style-rtl.css 15.5 kB 0 B
build/components/style.css 15.5 kB 0 B
build/compose/index.js 11.2 kB 0 B
build/core-data/index.js 15.2 kB 0 B
build/data-controls/index.js 829 B 0 B
build/data/index.js 8.97 kB 0 B
build/date/index.js 31.8 kB 0 B
build/deprecated/index.js 768 B 0 B
build/dom-ready/index.js 571 B 0 B
build/dom/index.js 4.95 kB 0 B
build/edit-navigation/index.js 11.1 kB 0 B
build/edit-navigation/style-rtl.css 938 B 0 B
build/edit-navigation/style.css 944 B 0 B
build/edit-post/index.js 306 kB 0 B
build/edit-post/style-rtl.css 6.64 kB 0 B
build/edit-post/style.css 6.63 kB 0 B
build/edit-site/index.js 24 kB 0 B
build/edit-site/style-rtl.css 4.05 kB 0 B
build/edit-site/style.css 4.04 kB 0 B
build/edit-widgets/index.js 23.6 kB 0 B
build/edit-widgets/style-rtl.css 3.22 kB 0 B
build/edit-widgets/style.css 3.22 kB 0 B
build/editor/editor-styles-rtl.css 476 B 0 B
build/editor/editor-styles.css 478 B 0 B
build/editor/index.js 42.3 kB 0 B
build/editor/style-rtl.css 3.89 kB 0 B
build/editor/style.css 3.89 kB 0 B
build/element/index.js 4.62 kB 0 B
build/escape-html/index.js 735 B 0 B
build/format-library/index.js 6.75 kB 0 B
build/format-library/style-rtl.css 620 B 0 B
build/format-library/style.css 621 B 0 B
build/hooks/index.js 2.27 kB 0 B
build/html-entities/index.js 623 B 0 B
build/i18n/index.js 3.57 kB 0 B
build/is-shallow-equal/index.js 698 B 0 B
build/keyboard-shortcuts/index.js 2.54 kB 0 B
build/keycodes/index.js 1.94 kB 0 B
build/list-reusable-blocks/index.js 3.15 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.31 kB 0 B
build/notices/index.js 1.86 kB 0 B
build/nux/index.js 3.42 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.54 kB 0 B
build/primitives/index.js 1.43 kB 0 B
build/priority-queue/index.js 789 B 0 B
build/redux-routine/index.js 2.84 kB 0 B
build/reusable-blocks/index.js 2.91 kB 0 B
build/rich-text/index.js 13.5 kB 0 B
build/server-side-render/index.js 2.77 kB 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

@jorgefilipecosta jorgefilipecosta force-pushed the add/json-file-exposing-the-translatable-paths-and-a-theme-json-translation-mechanism branch from 08d698d to 8effe79 Compare November 30, 2020 22:40
@swissspidy swissspidy requested a review from ocean90 December 2, 2020 10:45
@swissspidy
Copy link
Member

Is there a similar effort for block.json?

* @param string $domain Optional. Text domain. Unique identifier for retrieving translated strings.
* Default 'default'.
*/
private static function apply_theme_json_translations( &$theme_json_structure, $domain = 'default' ) {
Copy link
Member

Choose a reason for hiding this comment

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

Any specific reason for call by reference vs call by value?

Copy link
Member Author

Choose a reason for hiding this comment

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

The only reason why I am passing by reference instead of returning a newly translated theme.json is to avoid copying the entire tree. I don't think it makes a big difference so if you think it is better to return I can change.

@gziolo
Copy link
Member

gziolo commented Dec 2, 2020

Is there a similar effort for block.json?

There is #23636 that still needs work. register_block_type_from_metadata doesn't have any hooks exposed, sadly, so we should start on it in WordPress core first.

@jorgefilipecosta jorgefilipecosta mentioned this pull request Dec 4, 2020
82 tasks
@jorgefilipecosta jorgefilipecosta force-pushed the add/json-file-exposing-the-translatable-paths-and-a-theme-json-translation-mechanism branch from 0d9e815 to 949ecee Compare December 9, 2020 22:06
@jorgefilipecosta
Copy link
Member Author

jorgefilipecosta commented Dec 9, 2020

Hi @swissspidy, @nosolosw thank you a lot for providing feedback. It was applied.

@swissspidy let me know if you prefer passing by value instead of reference and in that case, I will update the code.

@oandregal
Copy link
Member

@jorgefilipecosta I've reviewed this and the cli issue and wanted to ask how do we manage the scenario where Gutenberg, the plugin, needs to add more presets to be translated? Is it ok to not allow translating the new ones until they are part of WordPress core?

*
* @return array An array of arrays each one containing a translatable path and an array of properties that are translatable.
*/
private static function theme_json_i18_file_structure_to_paths( $file_structure_partial, $current_path = array() ) {
Copy link
Member

Choose a reason for hiding this comment

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

This processing logic is tied to how presets are structured and can't be used for anything else. I don't anticipate that we want to translate any other thing in theme.json either. So, given this context, what do you think of making the naming of everything this PR adds more explicit: translate_presets instead of apply_theme_json_translations, get_presets_to_translate instead of get_theme_json_i18n, etc.

Copy link
Member

Choose a reason for hiding this comment

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

Ideally, it isn't tied to themes.json as well. We need it for block.json 😄

Copy link
Member

Choose a reason for hiding this comment

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

oh, so is it the idea that the file lib/experimental-i18n-theme.json and this code is used for both block.json and theme.json? If that's the case, it sounds like something independent from the WP_Theme_JSON_Resolver class.

Copy link
Member

Choose a reason for hiding this comment

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

The definition with config can (or maybe even should) be in their own files for blocks and themes. However the logic that applies translation functions could be shared 😃

Copy link
Member Author

Choose a reason for hiding this comment

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

Well, it is a fact that this code and even the structure is focused on presets.
All these functions were not implemented with block.json in consideration, but I guess we can in fact have a genetic data structure translation tool outside WP_Theme_JSON_Resolver (but used by WP_Theme_JSON_Resolver) this independent class could be used by both block.json and by theme.json.

We would need a specification format that can handle block.json and theme.json independent of presets I guess something like that would work

{
	'*': {
		"settings": {
			"typography": {
				"fontSizes": {
					'*': [ 
						'name'
					]
				}
			}
		}
	}
}

But this is not very future proof as soon as we had nesting this specification would not work.

Being totally generic seems to bring more complexity to the specification structure. Maybe it is fine to have a set of functions focused on theme.json and presets and then we have something similar for block.json?

Copy link
Member

Choose a reason for hiding this comment

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

It can be two different helpers if that makes it simpler 👍

Copy link
Member Author

Choose a reason for hiding this comment

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

Hi @nosolosw, I renamed the functions as suggested.

@jorgefilipecosta jorgefilipecosta force-pushed the add/json-file-exposing-the-translatable-paths-and-a-theme-json-translation-mechanism branch from 949ecee to 8bd502e Compare December 14, 2020 13:00
@TimothyBJacobs
Copy link
Member

@jorgefilipecosta I've reviewed this and the cli issue and wanted to ask how do we manage the scenario where Gutenberg, the plugin, needs to add more presets to be translated? Is it ok to not allow translating the new ones until they are part of WordPress core?

I agree this is an issue. I think it might be worth exploring having the .json file itself also be able to specify what paths are translatable. Perhaps using something like a $schema keyword. Core could infer it if it didn't exist, but otherwise it could point to a schema definition file that was a JSON schema with a new translatable keyword.

Related: https://core.trac.wordpress.org/ticket/50615

@jorgefilipecosta
Copy link
Member Author

jorgefilipecosta commented Dec 15, 2020

@jorgefilipecosta I've reviewed this and the cli issue and wanted to ask how do we manage the scenario where Gutenberg, the plugin, needs to add more presets to be translated? Is it ok to not allow translating the new ones until they are part of WordPress core?

I agree this is an issue. I think it might be worth exploring having the .json file itself also be able to specify what paths are translatable. Perhaps using something like a $schema keyword. Core could infer it if it didn't exist, but otherwise it could point to a schema definition file that was a JSON schema with a new translatable keyword.

Hi @nosolosw, @TimothyBJacobs, I think it is ok to not translate new ones until they are in the core. If we really need the new presets translated we can go for a temporary solution relying on filters&code as we are doing now, or we can simply update the file on WordPress trunk updating the JSON file of core does not seems like a big effort.

@oandregal
Copy link
Member

Hi @nosolosw, @TimothyBJacobs, I think it is ok to not translate new ones until they are in the core. If we really need the new presets translated we can go for a temporary solution relying on filters&code as we are doing now, or we can simply update the file on WordPress trunk updating the JSON file of core does not seems like a big effort.

I don't think I have enough context to understand whether this is an ok trade-off, so would like to hear thoughts from people more experienced, cc @mcsf @youknowriad @mtias If we have the greenlight on that specific point (people can't translate new presets that are added in the plugin OR we enable a mechanism for them to do it, etc), I can expedite a review to merge this PR.

@jorgefilipecosta
Copy link
Member Author

jorgefilipecosta commented Dec 18, 2020

I don't think I have enough context to understand whether this is an ok trade-off, so would like to hear thoughts from people more experienced, cc @mcsf @youknowriad @mtias If we have the greenlight on that specific point (people can't translate new presets that are added in the plugin OR we enable a mechanism for them to do it, etc)

It is not that people can not translate new presets that are added in the plugin it is more. Core is the source of truth regarding what properties are translatable. We can always add more translatable properties to the core trunk. That is a simple change and makes things in the plugin also translatable.

I guess if this proves to a be problem it would also be possible to add --gutenberg parameter to wp-cli extraction command that would make wp-cli use the translation file from the Gutenberg repository instead of the one from the core.

@gziolo
Copy link
Member

gziolo commented Dec 23, 2020

I did some checks in the WordPress core to compare how translations are applied to the plugin's metadata. There is some more processing because translated strings are also escaped there. Do we need it here, too? The code snippet for reference:

https://github.com/WordPress/wordpress-develop/blob/d2c8fae049e80f5726653c61361d467fad1a8a0b/src/wp-admin/includes/plugin.php#L149-L194

There is also is_textdomain_loaded check to ensure that translations are loaded. Not sure if that would be an issue here, but I still wanted to flag it.

Copy link
Member

@gziolo gziolo left a comment

Choose a reason for hiding this comment

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

I've reviewed this and the cli issue and wanted to ask how do we manage the scenario where Gutenberg, the plugin, needs to add more presets to be translated? Is it ok to not allow translating the new ones until they are part of WordPress core?

If WP-CLI is going to use the JSON file from the trunk of wordpress-develop repository then it should be as simple as committing the change directly there. The only case where it wouldn't be possible is the RC phase of the WordPress release, at most 3 weeks, but in practice, I think the release branch is created earlier. In the plugin, we still would have to keep overrides between WordPress releases and that's why I asked in another comment whether we should add a filter to account for that.

private static function get_presets_to_translate() {
static $theme_json_i18n = null;
if ( null === $theme_json_i18n ) {
$file_structure = self::get_from_file( __DIR__ . '/experimental-i18n-theme.json' );
Copy link
Member

Choose a reason for hiding this comment

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

Is the plan to always keep a local copy of the file with the schema for translations? It usually gives us more flexibility when there is a hook introduced upfront. This way the filters let to add only new keys that need to be translated.

Copy link
Member Author

Choose a reason for hiding this comment

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

Is the plan to always keep a local copy of the file with the schema for translations?

Yes, the plan is for the file to always exist locally.

It usually gives us more flexibility when there is a hook introduced upfront. This way the filters let to add only new keys that need to be translated.

If we had a hook that allowed to add new keys to be translatable, wp-cli would not be aware of the hook and would not extract the strings anyway, so the strings would not be translatable anyway.

The keys that are translatable are something static like in https://github.com/WordPress/wordpress-develop/blob/d2c8fae049e80f5726653c61361d467fad1a8a0b/src/wp-admin/includes/plugin.php#L149-L194 a plugin can not add other $plugin_data keys to be translatable.

If a plugin wants to inject translatable information in the theme.json structure, the plugin would use the filters that allow to change the structure and do something like $theme_json['settings'][mycustomPreset]= array( array( 'customPorperty' => __( 'translatable string' ) ) ); Given that it is done in code the string extraction would work as expected. So it would be possible for a plugin to inject translatable information using code not requiring to filter this file.

Copy link
Member

Choose a reason for hiding this comment

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

I'm sure that some sort of filter is going to be necessary. Once you have the definition of translatable fields in the WordPress core, you might end up willing to expand it in Gutenberg when a new section is added to theme.json file. You can always simply override experimental-i18n-theme.json in Gutenberg and call it the day, but we should account for that when backporting logic to the WP core 😄

@oandregal
Copy link
Member

After a translation session in a WordCamp, I've just prepared a PR to add some context for translators in block's titles at #27933 I've used the _x function. I also know that we have the ability to add comments before the i18n call such as /* translators: some comment here */ that will show up in GlotPress as well (differently and with a poorer UI than the context, though).

I wonder how can we enable this kind of context/comments for the fields translated via theme.json?

@swissspidy
Copy link
Member

I wonder how can we enable this kind of context/comments for the fields translated via theme.json?

That's rather simple:

  1. WP-CLI adds context to all the extracted strings (see https://github.com/wp-cli/i18n-command/blob/0fa24efa7460564d17fa4c6e1763e806eb1613c3/src/BlockExtractor.php#L43-L69 how it's done for block.json already
  2. The code in WordPress that actually loads the theme.json (and also block.json) file will run all strings through translate_with_gettext_context() with the same context.

Note that context is more appropriate here than translator comments.

Copy link
Member

@gziolo gziolo left a comment

Choose a reason for hiding this comment

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

Let's get this PR finally merged and see how it works in action. It will give us some time to test it before WordPress 5.7 cycle begins. We also need to start preparation to backport this functionality to the WordPress core.

@jorgefilipecosta jorgefilipecosta force-pushed the add/json-file-exposing-the-translatable-paths-and-a-theme-json-translation-mechanism branch from 8bd502e to 93c3c87 Compare January 12, 2021 20:51
@jorgefilipecosta jorgefilipecosta merged commit 9c9617d into master Jan 12, 2021
@jorgefilipecosta jorgefilipecosta deleted the add/json-file-exposing-the-translatable-paths-and-a-theme-json-translation-mechanism branch January 12, 2021 21:48
@github-actions github-actions bot added this to the Gutenberg 9.8 milestone Jan 12, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Global Styles Anything related to the broader Global Styles efforts, including Styles Engine and theme.json Internationalization (i18n) Issues or PRs related to internationalization efforts
Projects
None yet
Development

Successfully merging this pull request may close these issues.

7 participants