Support

Account

Home Forums Gutenberg block.json with translated title and description (i18n & L10n) Reply To: block.json with translated title and description (i18n & L10n)

  • Update! I’ve stumbled across this article saying that it can’t be done like any of the methods above for the time being. Instead you’d have to add the strings in an extra step and registering the blocks with register_block_type_from_metadata() instead of register_block_type().

    However the strings in your block.json remains not translated. Unfortunately we have to add these manually to register_block_type_from_metadata(). This might change in the future, but as for the time of writing this (WordPress 5.8+) we need this one additional step.

    My previous function looked like this:

    function register_acf_blocks() {
    	foreach ( glob( get_stylesheet_directory() . '/includes/blocks/*' ) as $path ) {
    		register_block_type( $path . '/block.json' );
    	}
    }

    Then I tried getting and using the strings from the block.json files, but without success (I guess the same problem as in my first post. You can’t pass a variable into a gettext function).

    add_action( 'init', 'register_acf_blocks', 5 );
    function register_acf_blocks() {
    	foreach ( glob( get_stylesheet_directory() . '/includes/blocks/*' ) as $path ) {
    		$str = file_get_contents( $path . '/block.json' );
    		$json = json_decode($str, true);
    		$title = $json['title'];
    		$desc = $json['description'];
    
    		register_block_type_from_metadata( $path . '/block.json', [
    			'title' => _x( $title, 'block title', 'mytextdomain' ),
    			'description' => _x( $desc, 'block description', 'mytextdomain' ),
    		] );
    	}
    }

    So then I guess we’re left with the manual and double declaration way, as the article above states.

    add_action( 'init', 'register_acf_blocks', 5 );
    function register_acf_blocks() {
    	$path = get_stylesheet_directory() . '/includes/blocks/';
    
    	register_block_type_from_metadata( $path . 'my-block-1/block.json', [
    		'title' => _x( 'Title text of block #1', 'block title', 'theme-textdomain' ),
    		'description' => _x( 'This is the description of block #1', 'block description', 'theme-textdomain' ),
    	] );
    
    	register_block_type_from_metadata( $path . 'my-block-2/block.json', [
    		'title' => _x( 'Title text of block #2', 'block title', 'theme-textdomain' ),
    		'description' => _x( 'This is the description of block #2', 'block description', 'theme-textdomain' ),
    	] );
    
    	register_block_type_from_metadata( $path . 'my-block-3/block.json', [
    		'title' => _x( 'Title text of block #3', 'block title', 'theme-textdomain' ),
    		'description' => _x( 'This is the description of block #3', 'block description', 'theme-textdomain' ),
    	] );
    
    }

    Voilà! It works!

    A good thing about this is that I can use the theme’s textdomain (using a custom textdomain for your blocks would need a separate load_theme_textdomain() function in functions.php and creating .pot/.po files), allowing me to only have one .po file for all theme related strings and also no need for anything wp-cli i18n, npm etc. The downside is that you’d have to register each block manually and also handle double title and description texts (not sure if you can omit them from block.json).

    To make it more modular I can add register_block_type_from_metadata() in a separate php file (like setup.inc.php) in each block folder and then use the second approach above, looping through all folders and include the php file instead. That way you wouldn’t need to edit function.php for adding/removing blocks.

    functions.php:

    add_action( 'init', 'register_acf_blocks', 5 );
    function register_acf_blocks() {
    	global $path;
    
    	foreach ( glob( get_stylesheet_directory() . '/includes/blocks/*' ) as $path ) {
    		include $path . '/setup.inc.php';
    	}
    
    }

    In each of my block folders I add a new file setup.inc.php:

    <?php
    register_block_type_from_metadata( $path . '/block.json', [
        'title' => _x( 'Title of this block', 'block title', 'theme-textdomain' ),
        'description' => _x( 'This is the description of this block', 'block description', 'theme-textdomain' ),
    ] );

    Now, I’m no developer, more of an UI/UX guy. So this can probably be written even better. But I think this approach should be reviewed by the ACF devs and maybe added to the docs as an alternative to register_block_type() if this is the only way to handle translations of block.json strings. Since there is a vast amount of non-english installs of WP and by using ACF we actively want to build custom blocks with PHP (= .po) rather than JS. 🙂