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

Extract translatable strings from theme.json files #224

Closed
1 task done
jorgefilipecosta opened this issue Sep 3, 2020 · 10 comments · Fixed by #254
Closed
1 task done

Extract translatable strings from theme.json files #224

jorgefilipecosta opened this issue Sep 3, 2020 · 10 comments · Fixed by #254

Comments

@jorgefilipecosta
Copy link

Feature Request

Describe your use case and the problem you are facing

For supporting the next generation of themes, we need to extract strings from theme.json files.

Describe the solution you'd like

wp i18n make-pot should parse theme.json files and extract all strings it finds with the additional context.

Sample file:

{
	"global": {
		"presets": {
			"color": [
				{
					"slug": "blue",
					"value": "#00f",
					"name": "Red"
				}
			],
			"font-size": [
				{
					"slug": "small",
					"value": 13,
					"name": "Small"
				}
			],
			"font-family": [
				{
					"value": "-apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,Oxygen-Sans,Ubuntu,Cantarell,\"Helvetica Neue\",sans-serif",
					"slug": "system",
					"name": "System"
				}
			],
			"gradient": [
				{
					"slug": "blush-bordeaux",
					"value": "linear-gradient(135deg,rgb(254,205,165) 0%,rgb(254,45,45) 50%,rgb(107,0,62) 100%)",
					"name": "Another gradient"
				}
			]
		}
	},
	"core/paragraph": {
		"presets": {
			"color": [
				{
					"slug": "red",
					"value": "#f00",
					"name": "Red"
				}
			],
			"font-size": [
				{
					"slug": "small",
					"value": 13,
					"name": "Small"
				}
			],
			"font-family": [
				{
					"value": "-apple-system,BlinkMacSystemFont,\"Segoe UI\",Roboto,Oxygen-Sans,Ubuntu,Cantarell,\"Helvetica Neue\",sans-serif",
					"slug": "system",
					"name": "System"
				}
			],
			"gradient": [
				{
					"slug": "blush-bordeaux",
					"value": "linear-gradient(135deg,rgb(254,205,165) 0%,rgb(254,45,45) 50%,rgb(107,0,62) 100%)",
					"name": "Simple gradient"
				}
			]
		}
	}
}

In all these cases "name" should be translatable.
For now, these files are named experimental-theme.json (future theme.json) on WordPress themes, and experimental-default-theme.json (future default-theme.json) for the core own default file.

It is very related to the work done for block.json #210.

@swissspidy
Copy link
Member

Thanks for opening this, @jorgefilipecosta!

How far advanced is the work on this? I hesitate a bit to add this as long as it's still experimental.

Also, is there a JSON schema for what the theme.json file looks like? As discussed in #210, such a schema would be very helpful to know which fields are allowed in that file. Otherwise we have to loop through all fields and extract all name values - which seems a bit error prone.

You mention theme.json and default-theme.json - what's the difference there? Which other file names could there be? We need to know exactly which files to look for.

@jorgefilipecosta
Copy link
Author

Hi @swissspidy,

How far advanced is the work on this? I hesitate a bit to add this as long as it's still experimental.

We already have a very concrete idea of the strings that should be translatable. We may need to add more translatable keys in the future. But I guess it will not be hard to add more keys.

We don't have a schema but I guess we can specify what settings are translable using something like:

$translatable_theme_json_settings = array(
	array( 'typography', 'fontSizes', '[]', 'name' ),
	array( 'typography', 'fontFamilies', '[]', 'name' ),
	array( 'color', 'palette', '[]', 'name' ),
	array( 'color', 'gradients', '[]', 'name' )
);

Or we can even assume only presets are translatable and what is translatable is the name and we can represent translatable presets as:
$translatable_presets = array(
array( 'typography', 'fontSizes' ),
array( 'typography', 'fontFamilies' ),
array( 'color', 'palette' ),
array( 'color', 'gradients' )
);

Regarding the theme.json structure at the top level, we have an object whose keys are selectors:

{
	"global": {},
	"core/paragraph": {},
	"core/heading/h1": {},
	...
}

A selector can be "global" applies styles and settings to the root of the website, a block identifier, e.g.: "core/paragraph", or a custom selector defined by the block for blocks supporting multiple selectors like "core/heading/h1".

Inside the object of each selector, we have "styles" and "settings".

{
	"global": {
		styles: {},
		settings: {},
	},
	...
}

Styles don't need any translation, while the settings may need.

Inside each settings object, we have a group of settings e.g.:

{
	"global": {
		settings: {
			typography: {},
			color: {},
			...
		},
	},
	...
}

Some of the settings can be translatable like all the following names:

{
	"global": {
		settings: {
			typography: {
				"fontSizes": [
					{
						"slug": "extra-small",
						"size": "16px"
						"name": "Extra Small"
					},
					{
						"slug": "small",
						"size": "18px"
						"name": "Small"
					}
				],
				fontFamilies: [
					{
						"fontFamily": "Helvetica Neue, Helvetica, Arial, sans-serif",
						"slug": "helvetica-arial",
						"name": "Helvetica"
					},
					{
						"fontFamily": "Geneva, Tahoma, Verdana, sans-serif",
						"slug": "geneva-verdana",
						"name": "Geneva"
					},
				]
			},
			color: {
				"palette": [
					{
						"slug": "black",
						"color": "#000000",
						"name": "Black"
					},
					{
						"slug": "dark-gray",
						"color": "#28303D",
						"name": "Dark gray"
					}
				],
				"gradients": [
					{
						"name": "Vivid cyan blue to vivid purple",
						"gradient": "linear-gradient(135deg,rgba(6,147,227,1) 0%,rgb(155,81,224) 100%)",
						"slug": "vivid-cyan-blue-to-vivid-purple"
					},
					{
						"name": "Vivid green cyan to vivid cyan blue",
						"gradient": "linear-gradient(135deg,rgba(0,208,132,1) 0%,rgba(6,147,227,1) 100%)",
						"slug": "vivid-green-cyan-to-vivid-cyan-blue"
					}
				]
			},
			...
		},
	},
	...
}

You mention theme.json and default-theme.json - what's the difference there? Which other file names could there be? We need to know exactly which files to look for.

The translatable files are:

  • experimental-theme.json or theme.json(future) under the themes directory.
  • experimental-default-theme.json or default-theme.json(future) on the Gutenberg repository under lib/experimental-default-theme.json. In the future, the core will also have this file.

There is no difference in the shape of theme.json and default-theme.json. They are the same thing. The default-theme.json contains the WordPress theme.json default file.

Let me know if there is anything that is not clear regarding what part of theme.json files are translatable. And thank you for looking into this issue @swissspidy!

@swissspidy
Copy link
Member

Thanks for the update @jorgefilipecosta!

Sounds straightforward enough to be able to put together a first working version of this.

@jorgefilipecosta
Copy link
Author

Thank you @swissspidy, would you be able to work on the first version?
If yes let me know if you any additional information, PR reviews, help in a specific part, or any other insight :)

@schlessera
Copy link
Member

schlessera commented Nov 20, 2020

@jorgefilipecosta The above $translatable_theme_json_settings still puts the discovery of possible translations within WP-CLI, which will cause problems. WP-CLI releases are not directly tied to WordPress Core releases. Therefore, if a WordPress release adds or removes a translatable string with a new release, translations will be broken until WP-CLI releases the corresponding update as well.

We don't need a full-blown schema for this, but the discovery itself needs to be part of WordPress Core in some shape.

For a very simple solution, can we have the above information as a JSON file updated and shipped with WordPress Core (can be in any subfolder as long as we can tell WP-CLI where to look for it):

{
  "typography": {
    "fontSizes": [
      "name"
    ],
    "fontFamilies": [
      "name"
    ]
  },
  "color": {
    "palette": [
      "name"
    ],
    "gradients": [
      "name"
    ]
  }
}

As soon as we have something like this within WordPress Core, you can change the strings around as much as you want (provided you update the above file), and WP-CLI will always work with the latest and greatest changes without any modifications at all.

@swissspidy
Copy link
Member

We don't need a full-blown schema for this, but the discovery itself needs to be part of WordPress Core in some shape.

@schlessera Is core the right place? String extraction currently works without requiring a WP installation and I don't think this should be changed. So if all I have is a theme folder, how would WP-CLI know where to find the file? Should there be a cached copy bundled with the command? Does the user need to provide the path to it?

@schlessera
Copy link
Member

@swissspidy If we know where the file is located, we can always download the latest version of the file as needed. This is not necessarily about having it available at the currently used installation, it's more about having it be versioned together with Core releases, and WP-CLI just using whatever is the latest version.
It could also be an API on wordpress.org, but I think versioning it with the Core file is both easier and more reliable.

@jorgefilipecosta
Copy link
Author

I'm trying the approach of exposing a file that contains translatable paths in WordPress/gutenberg#27380. If we merge it to Gutenberg the file should make its way into the core during the next core Gutenberg update.

@gziolo
Copy link
Contributor

gziolo commented Dec 3, 2020

Let's follow the same approach for block.json. As soon as we have this issue resolved, I can open a patch in WordPress Core that adds the required definition and integrates it within register_block_type_from_metadata. There is also a related issue in Gutenberg: WordPress/gutenberg#23636.

@oandregal
Copy link
Contributor

👋 There were recent changes to the theme.json format and more things need to be translated. I was trying to add a translation for a new field that wasn't a preset (it lived in a different subtree) at WordPress/gutenberg#28783

During that process, I realized a potentially simpler way to extract strings for translation in JSON files: what if we marked the strings to translate directly in the source JSON file (block.json, theme.json) instead of having intermediate structures (code, i18.json file)? I implemented this at WordPress/gutenberg#28976 as a prototype for you all to look at. Would love your thoughts over there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants