Block themes translate WordPress other than a typical approach. Traditional PHP template files with translation functions do not work with HTML templates, Javascript-driven blocks and the site editor. This shift requires that you understand WordPress blocking systems differently.
This guide offers strategies to make your block themes multilingual. You learn how to navigate the challenges of Blokhema translation, implement solutions and integrate with translation plug -in.
Why block themes to break through traditional translation methods (and how to repair them)
Blocking themes replace many of the PHP files from WordPress by HTML templates that contain block marking. However, this switch creates challenges because HTML templates cannot perform PHP translation functions, such as such as _() or _e(). As a result, the translation series that you are already unusable in static files are.
WordPress 6.8 entails some improvements that simplify the internationalization of the block theme. In the first place themes with the right Text domain And Domain path headers) no longer necessary manual load_theme_textdomain() to call to action.
Instead, WordPress transparent files are automatically loaded and prioritized wp-content/languages/themes/ About theme folders for performance.
To begin with, set your theme using a classic approach by adding metadata to the style.css file.
/*
Theme Name: My Block Theme
Text Domain: my-block-theme
Domain Path: /languages
*/
Note that the Text domain header must match the folder name of your theme (usually in kebab) To ensure that translation files are correctly loaded in recent WordPress versions.
Just like style.cssyour functions.php File requires minimum setting:
The most important difference between classic and block themes here is that the latest translation responsibility splits between Server-Side PHP and client-side Javascript. Classic themes, on the other hand, must trust PHP to process most translations.
How to build block.json translation
The Block.json file is your ‘configuration hub’ for the block that you want to translate. Setting the right internationalization ensures that your blocks correctly translate, both in the editor and the front-end.
The Canonical way to register a block is through block.json. Starting with the textdomain configuration means that WordPress the title” descriptionAnd keywords fields when the textdomain is set:
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "my-theme/testimonial",
"title": "Testimonial",
"category": "text",
"description": "Display customer testimonials",
"keywords": ["quote", "review", "testimonial"],
"textdomain": "my-block-theme",
"attributes": {
"content": {
"type": "string",
"source": "html",
"selector": "blockquote"
}
}
}
Scenarios that require ‘context’, however, require registration of server-side. Context, in this case, is important because the same word could otherwise translate based on its use. ‘Post’ for example as an independent versus as a verb requires different translations in many languages:
function my_theme_register_testimonial_block() {
register_block_type_from_metadata(
get_template_directory() . '/blocks/testimonial',
array(
'title' => _x( 'Testimonial', 'block title', 'my-block-theme' ),
'description' => _x(
'Display customer testimonials',Â
'block description',Â
'my-block-theme'
),
'keywords' => array(
_x( 'quote', 'block keyword', 'my-block-theme' ),
_x( 'review', 'block keyword', 'my-block-theme' )
)
)
);
}
add_action( 'init', 'my_theme_register_testimonial_block' );
All block variations that you include also need structured naming, because WordPress is looking for specific patterns when loading your translations. Each variation name becomes part of the translation test:
{
"name": "my-theme/button",
"title": "Button",
"textdomain": "my-block-theme",
"variations": [{
"name": "primary",
"title": "Primary Button",
"attributes": {
"className": "is-style-primary"
}
},
{
"name": "secondary",
"title": "Secondary Button",
"attributes": {
"className": "is-style-secondary"
}
}
]
}
JavaScript -Internationalization requires you import WordPress I18N functions And configure the script translations. This is because the site editor is executed in the browser instead of on the server. Because PHP translation functions do not exist in JavaScript, WordPress offers equivalent functions via the @wordpress/i18n package:
import {
registerBlockType
} from '@wordpress/blocks';
import {
__
} from '@wordpress/i18n';
import {
useBlockProps,
RichText
} from '@wordpress/block-editor';
registerBlockType('my-theme/testimonial', {
edit: ({
attributes,
setAttributes
}) => {
const blockProps = useBlockProps();
return ( < div { ...blockProps } >
< RichText tagName = "blockquote" value = { attributes.content } onChange = { (content) => setAttributes({
content
})
}
placeholder = {
__('Add testimonial text...', 'my-block-theme')
}
/> < cite >
< RichText tagName = "span" value = { attributes.author } onChange = { (author) => setAttributes({
author
})
}
placeholder = {
__('Author name', 'my-block-theme')
}
/> < /cite> < /div>
);
}
});
Moreover, it is a good idea to generate JSON translation files for Javascript because WordPress uses a different format for translations to the client-side. PHP use .mo Files, but JavaScript needs .json Files with specific naming conventions. You can automate this with the help of WP-Cli assignments:
# Extract strings from JavaScript files into POT
wp i18n make-pot . languages/my-block-theme.pot
# Convert PO files to JSON for JavaScript
wp i18n make-json languages/ --no-purge --pretty-print
The resulting JSON files follow a consistent pattern: {textdomain}-{locale}-{handle}.json. WordPress can then load it when you call wp_set_script_translations().
Convert your static HTML templates into translation-ready PHP components
Given that HTML templates are static, working with them for internationalization of the theme is because your existing translation functions and techniques will not work.
PHP-driven template parts can solve this problem because WordPress processes them as PHP files, even though they are referred in HTML templates. This hybrid approach maintains the block theme structure and makes dynamic content possible:
Developer Guide: WordPress block -themes Multilingualy
   Â
Block themes translate WordPress other than a typical approach. Traditional PHP template files with translation functions do not work with HTML templates, Javascript-driven blocks and the site editor. This shift requires that you understand WordPress blocking systems differently.
This guide offers strategies to make your block themes multilingual. You learn how to navigate the challenges of Blokhema translation, implement solutions and integrate with translation plug -in.
Why block themes to break through traditional translation methods (and how to repair them)
Blocking themes replace many of the PHP files from WordPress by HTML templates that contain block marking. However, this switch creates challenges because HTML templates cannot perform PHP translation functions, such as such as _() or _e(). As a result, the translation series that you are already unusable in static files are.
WordPress 6.8 entails some improvements that simplify the internationalization of the block theme. In the first place themes with the right Text domain And Domain path headers) no longer necessary manual load_theme_textdomain() to call to action.
Instead, WordPress transparent files are automatically loaded and prioritized wp-content/languages/themes/ About theme folders for performance.
To begin with, set your theme using a classic approach by adding metadata to the style.css file.
/*
Theme Name: My Block Theme
Text Domain: my-block-theme
Domain Path: /languages
*/
Note that the Text domain header must match the folder name of your theme (usually in kebab) To ensure that translation files are correctly loaded in recent WordPress versions.
Just like style.cssyour functions.php File requires minimum setting:
The most important difference between classic and block themes here is that the latest translation responsibility splits between Server-Side PHP and client-side Javascript. Classic themes, on the other hand, must trust PHP to process most translations.
How to build block.json translation
The Block.json file is your ‘configuration hub’ for the block that you want to translate. Setting the right internationalization ensures that your blocks correctly translate, both in the editor and the front-end.
The Canonical way to register a block is through block.json. Starting with the textdomain configuration means that WordPress the title” descriptionAnd keywords fields when the textdomain is set:
{
"$schema": "https://schemas.wp.org/trunk/block.json",
"apiVersion": 3,
"name": "my-theme/testimonial",
"title": "Testimonial",
"category": "text",
"description": "Display customer testimonials",
"keywords": ["quote", "review", "testimonial"],
"textdomain": "my-block-theme",
"attributes": {
"content": {
"type": "string",
"source": "html",
"selector": "blockquote"
}
}
}
Scenarios that require ‘context’, however, require registration of server-side. Context, in this case, is important because the same word could otherwise translate based on its use. ‘Post’ for example as an independent versus as a verb requires different translations in many languages:
function my_theme_register_testimonial_block() {
register_block_type_from_metadata(
get_template_directory() . '/blocks/testimonial',
array(
'title' => _x( 'Testimonial', 'block title', 'my-block-theme' ),
'description' => _x(
'Display customer testimonials',Â
'block description',Â
'my-block-theme'
),
'keywords' => array(
_x( 'quote', 'block keyword', 'my-block-theme' ),
_x( 'review', 'block keyword', 'my-block-theme' )
)
)
);
}
add_action( 'init', 'my_theme_register_testimonial_block' );
All block variations that you include also need structured naming, because WordPress is looking for specific patterns when loading your translations. Each variation name becomes part of the translation test:
{
"name": "my-theme/button",
"title": "Button",
"textdomain": "my-block-theme",
"variations": [{
"name": "primary",
"title": "Primary Button",
"attributes": {
"className": "is-style-primary"
}
},
{
"name": "secondary",
"title": "Secondary Button",
"attributes": {
"className": "is-style-secondary"
}
}
]
}
JavaScript -Internationalization requires you import WordPress I18N functions And configure the script translations. This is because the site editor is executed in the browser instead of on the server. Because PHP translation functions do not exist in JavaScript, WordPress offers equivalent functions via the @wordpress/i18n package:
import {
registerBlockType
} from '@wordpress/blocks';
import {
__
} from '@wordpress/i18n';
import {
useBlockProps,
RichText
} from '@wordpress/block-editor';
registerBlockType('my-theme/testimonial', {
edit: ({
attributes,
setAttributes
}) => {
const blockProps = useBlockProps();
return ( < div { ...blockProps } >
< RichText tagName = "blockquote" value = { attributes.content } onChange = { (content) => setAttributes({
content
})
}
placeholder = {
__('Add testimonial text...', 'my-block-theme')
}
/> < cite >
< RichText tagName = "span" value = { attributes.author } onChange = { (author) => setAttributes({
author
})
}
placeholder = {
__('Author name', 'my-block-theme')
}
/> < /cite> < /div>
);
}
});
Moreover, it is a good idea to generate JSON translation files for Javascript because WordPress uses a different format for translations to the client-side. PHP use .mo Files, but JavaScript needs .json Files with specific naming conventions. You can automate this with the help of WP-Cli assignments:
# Extract strings from JavaScript files into POT
wp i18n make-pot . languages/my-block-theme.pot
# Convert PO files to JSON for JavaScript
wp i18n make-json languages/ --no-purge --pretty-print
The resulting JSON files follow a consistent pattern: {textdomain}-{locale}-{handle}.json. WordPress can then load it when you call wp_set_script_translations().
Convert your static HTML templates into translation-ready PHP components
Given that HTML templates are static, working with them for internationalization of the theme is because your existing translation functions and techniques will not work.
PHP-driven template parts can solve this problem because WordPress processes them as PHP files, even though they are referred in HTML templates. This hybrid approach maintains the block theme structure and makes dynamic content possible:
Developer Guide: WordPress block -themes Multilingualy
   Â
   Â
Complex blocks have the render.php File because some content Server-Side processing requires that block brands just cannot become. Database questions, conditional logic and dynamic content generation all require PHP version:
// blocks/recent-posts/render.php
$attributes['count'] ?? 5Â
) );
?>
>
   Â
    Â
    Â
           -
          Â
          Â
          Â
          Â
          Â
          Â
          Â
       Â
       Â
   Â
       Â
   Â
This means that you configure your block to use the render file block.json:
{
"name": "my-theme/recent-posts",
"render": "file:./render.php",
"attributes": {
"count": {
"type": "number",
"default": 5
}
}
}
How you can implement dynamic content translation for custom fields and user input
Despite the prevalence on WordPress websites, dynamic content can cause translation problems because it exists in the database instead of the files of your theme. As such, each external translation plug-ins that you use must identify and manage these content separately from static theme strings.
This is where registering adapted fields with the correct Meta configuration is valuable because Translation -Plug -Ins hooks in the WordPress meta system to detect any translatable content. The show_in_rest Parameter makes compatibility with the site -editor possible:
function my_theme_register_meta_fields() {
    register_post_meta( 'page', 'custom_subtitle', array(
        'type' => 'string',
        'description' => __( 'Page subtitle', 'my-block-theme' ),
        'single' => true,
        'show_in_rest' => true,
        'auth_callback' => function() {
            return current_user_can( 'edit_posts' );
        }
    ));
}
add_action( 'init', 'my_theme_register_meta_fields' );
// Display with plugin compatibility
function my_theme_display_subtitle( $post_id ) {
    $subtitle = get_post_meta( $post_id, 'custom_subtitle', true );
    if ( ! $subtitle ) {
        return;
    }
    // WPML compatibility
    // (documented at wpml.org/documentation/support/wpml-coding-api/wpml-hooks-reference/)
    if ( function_exists( 'icl_t' ) ) {
        $subtitle = icl_t(Â
            'my-block-theme',Â
            'subtitle_' . $post_id,Â
            $subtitleÂ
        );
    }
    // Polylang compatibility
    // (documented at polylang.pro/doc/function-reference/)
    if ( function_exists( 'pll_translate_string' ) ) {
        $subtitle = pll_translate_string( $subtitle, 'my-block-theme' );
    }
    echo '' . esc_html( $subtitle ) . '
';
}
Database questions also need language filtering because WordPress does not automatically filter the content per language. Transletplug -Ins add query adjustments that you must house for:
function my_theme_get_localized_posts( $args = array() ) {
    $defaults = array(
        'post_type' => 'post',
        'posts_per_page' => 10
    );
    $args = wp_parse_args( $args, $defaults );
    // Polylang adds language taxonomy
    // (documented at polylang.pro/doc/developpers-how-to/)
    if ( function_exists( 'pll_current_language' ) ) {
        $args['lang'] = pll_current_language();
    }
    // WPML filters queries automatically when suppress_filters is false
    // (wpml.org/documentation/getting-started-guide/translating-custom-posts/)
    if ( defined( 'ICL_LANGUAGE_CODE' ) ) {
        $args['suppress_filters'] = false;
    }
    return get_posts( $args );
}
Your form processing combines dynamic and static content, but forms labels, error messages and admin reports that all need language-conscious translation. The e -mail recipients can also vary per language:
function my_theme_process_contact_form() {
if ( ! isset( $_POST['contact_nonce'] ) ||Â
! wp_verify_nonce( $_POST['contact_nonce'], 'contact_form' ) ) {
return;
}
$name = sanitize_text_field( $_POST['name'] );
$email = sanitize_email( $_POST['email'] );
$message = sanitize_textarea_field( $_POST['message'] );
// Get admin email in current language
$admin_email = get_option( 'admin_email' );
// For language-specific admin emails, use WPML's string translation
// (documented at wpml.org/documentation/support/wpml-coding-api/wpml-hooks-reference/)
if ( function_exists( 'icl_t' ) ) {
// First register the string if not already registered
if ( function_exists( 'icl_register_string' ) ) {
icl_register_string( 'my-block-theme', 'contact_email', $admin_email );
}
$admin_email = icl_t(
'my-block-theme',
'contact_email',
$admin_email
);
}
$subject = sprintf(
/* translators: %s: Sender name */
__( 'Contact form submission from %s', 'my-block-theme' ),
$name
);
wp_mail( $admin_email, $subject, $message );
}
add_action( 'init', 'my_theme_process_contact_form' );
It is also important to assess your navigation language consciousness, because menu items, URLs and structure can differ between languages. Your translation plug -probably has an API for building language switches:
function my_theme_language_switcher_block() {
    if ( ! function_exists( 'pll_the_languages' ) &&Â
         ! function_exists( 'icl_get_languages' ) ) {
        return;
    }
    $output="";
    // Polylang language switcherÂ
    // (documented at polylang.pro/doc/function-reference/)
    if ( function_exists( 'pll_the_languages' ) ) {
        $languages = pll_the_languages( array( 'raw' => 1 ) );
        foreach ( $languages as $lang ) {
            $output .= sprintf(
                '%s',
                esc_url( $lang['url'] ),
                $lang['current_lang'] ? 'current-lang' : '',
                esc_html( $lang['name'] )
            );
        }
    }
    // WPML language switcher
    // (documented at wpml.org/documentation/support/wpml-coding-api/multi-language-api/)
    elseif ( function_exists( 'icl_get_languages' ) ) {
        $languages = icl_get_languages();
        foreach ( $languages as $lang ) {
            $output .= sprintf(
                '%s',
                esc_url( $lang['url'] ),
                $lang['active'] ? 'current-lang' : '',
                esc_html( $lang['native_name'] )
            );
        }
    }
    $output .= '';
    return $output;
}
Working with translation plug -in is probably a large part of your work, so let’s follow this aspect.
Working with Translation Plug -S: Compatibility and optimization
Every WordPress -Real language plug -in a unique way in a unique way. Insight into the approaches that take different solutions help you build compatibility and flexibility from the start.
WPML’s full site -Processing documentation outlines how to need a specific configuration for block themes:
// WPML FSE compatibility based on official documentation
add_action( 'init', function() {
if ( ! defined( 'WPML_VERSION' ) ) {
return;
}
// FSE themes are automatically detected in WPML 4.5.3+ // Enable FSE support
add_filter( 'wpml_is_fse_theme', '__return_true' );
// Register custom strings per WPML String Translation documentation
// (documented at wpml.org/documentation/support/wpml-coding-api/wpml-hooks-reference/)
if ( function_exists( 'icl_register_string' ) ) {
icl_register_string(
'my-block-theme',
'footer-copyright',
'© My Company.'
);
}
});
Polylang Pro has supported the site editor since version 3.2. The plug -in deals with block themes via the standard string -dealing interface:
// Polylang string registration per official documentation
if ( function_exists( 'pll_register_string' ) ) {
pll_register_string(Â
'Footer Copyright',
'© My Company.',
'my-block-theme',
true // Multiline support
);
}
TranslatePress documentation Show that certain dynamic elements need exclusion for optimum performance:
// TranslatePress optimization based on official recommendations
// (documented at translatepress.com/docs/developers/)
add_filter( 'trp_stop_translating_page', function( $stop, $url ) {
// Skip admin and API requests per TranslatePress documentation
if ( is_admin() || wp_is_json_request() ) {
return true;
}
// Skip pattern preview URLs that can cause rendering issues
    if ( strpos( $url, 'pattern-preview' ) !== false ) {
    return true;
}
return $stop;
}, 10, 2 );
Finally, there are a few tips for general purposes to pass on when working with code bases from third parties (such as plug-ins). First make sure you use a systematic approach to debug translation problems.
// Debug helper for translation issues
function my_theme_debug_translations() {
if ( ! WP_DEBUG || ! current_user_can( 'manage_options' ) ) {
return;
}
error_log( 'Text domain loaded: ' . is_textdomain_loaded(
'my-block-theme' ) );
    error_log( 'Current locale: ' . get_locale() );
    error_log( 'Translation test: ' . __(
'Hello World',
'my-block-theme'
)
);
// Check JSON translations for blocks
    $json_file = WP_LANG_DIR . '/themes/my-block-theme-' . get_locale() . '-script-handle.json';
error_log( 'JSON translation exists: ' . file_exists( $json_file ) );
}
add_action( 'init', 'my_theme_debug_translations' );
Site -caching can interfere with translation updates, so you may want to delete caches when translation files change:
# Clear WordPress transients
wp transient delete --all
# Generate fresh translation files
wp i18n make-pot . languages/my-block-theme.pot
wp i18n make-json languages/ --no-purge
Performance -optimization becomes critical with translation plug -in. Each plug -in adds database -queries and process overhead, which again benefits from caching often used translations:
function my_theme_cached_translation( $text, $domain = 'my-block-theme' ) {
    $cache_key = 'translation_' . md5( $text . get_locale() );
    $cached = wp_cache_get( $cache_key, 'my_theme_translations' );
    if ( false === $cached ) {
        $cached = __( $text, $domain );
        wp_cache_set( $cache_key, $cached, 'my_theme_translations', HOUR_IN_SECONDS );
    }
    return $cached;
}
Alternatively, it might be wise to skip caching until you are ready to implement. The use of an stenciling environment is ideal for this and you usually do not need the performance boost that Caching offers.
Summary
The internationalization of the block theme requires that you work with both WordPress translation methods and use new approaches within the site -editor.
By configuring your theme metadata, implementing template strategies and understanding the requirements of translation plug-ins, you can create multilingual block themes that perform well and offer a high-quality user experience.
When you are ready to launch, Kinsta’s managed hosting for WordPress delivers the performance and global scope, your site needs, with built-in caching, a 37-location CDN and tools such as GIT integration and scening.
#Developer #Guide #WordPress #block #themes #Multilingualy
    Complex blocks have the render.php File because some content Server-Side processing requires that block brands just cannot become. Database questions, conditional logic and dynamic content generation all require PHP version:
// blocks/recent-posts/render.php
$attributes['count'] ?? 5Â
) );
?>
>
   Â
    Â
    Â
           -
          Â
          Â
          Â
          Â
          Â
          Â
          Â
       Â
       Â
   Â
       Â
   Â
This means that you configure your block to use the render file block.json:
{
"name": "my-theme/recent-posts",
"render": "file:./render.php",
"attributes": {
"count": {
"type": "number",
"default": 5
}
}
}
How you can implement dynamic content translation for custom fields and user input
Despite the prevalence on WordPress websites, dynamic content can cause translation problems because it exists in the database instead of the files of your theme. As such, each external translation plug-ins that you use must identify and manage these content separately from static theme strings.
This is where registering adapted fields with the correct Meta configuration is valuable because Translation -Plug -Ins hooks in the WordPress meta system to detect any translatable content. The show_in_rest Parameter makes compatibility with the site -editor possible:
function my_theme_register_meta_fields() {
    register_post_meta( 'page', 'custom_subtitle', array(
        'type' => 'string',
        'description' => __( 'Page subtitle', 'my-block-theme' ),
        'single' => true,
        'show_in_rest' => true,
        'auth_callback' => function() {
            return current_user_can( 'edit_posts' );
        }
    ));
}
add_action( 'init', 'my_theme_register_meta_fields' );
// Display with plugin compatibility
function my_theme_display_subtitle( $post_id ) {
    $subtitle = get_post_meta( $post_id, 'custom_subtitle', true );
    if ( ! $subtitle ) {
        return;
    }
    // WPML compatibility
    // (documented at wpml.org/documentation/support/wpml-coding-api/wpml-hooks-reference/)
    if ( function_exists( 'icl_t' ) ) {
        $subtitle = icl_t(Â
            'my-block-theme',Â
            'subtitle_' . $post_id,Â
            $subtitleÂ
        );
    }
    // Polylang compatibility
    // (documented at polylang.pro/doc/function-reference/)
    if ( function_exists( 'pll_translate_string' ) ) {
        $subtitle = pll_translate_string( $subtitle, 'my-block-theme' );
    }
    echo '' . esc_html( $subtitle ) . '
';
}
Database questions also need language filtering because WordPress does not automatically filter the content per language. Transletplug -Ins add query adjustments that you must house for:
function my_theme_get_localized_posts( $args = array() ) {
    $defaults = array(
        'post_type' => 'post',
        'posts_per_page' => 10
    );
    $args = wp_parse_args( $args, $defaults );
    // Polylang adds language taxonomy
    // (documented at polylang.pro/doc/developpers-how-to/)
    if ( function_exists( 'pll_current_language' ) ) {
        $args['lang'] = pll_current_language();
    }
    // WPML filters queries automatically when suppress_filters is false
    // (wpml.org/documentation/getting-started-guide/translating-custom-posts/)
    if ( defined( 'ICL_LANGUAGE_CODE' ) ) {
        $args['suppress_filters'] = false;
    }
    return get_posts( $args );
}
Your form processing combines dynamic and static content, but forms labels, error messages and admin reports that all need language-conscious translation. The e -mail recipients can also vary per language:
function my_theme_process_contact_form() {
if ( ! isset( $_POST['contact_nonce'] ) ||Â
! wp_verify_nonce( $_POST['contact_nonce'], 'contact_form' ) ) {
return;
}
$name = sanitize_text_field( $_POST['name'] );
$email = sanitize_email( $_POST['email'] );
$message = sanitize_textarea_field( $_POST['message'] );
// Get admin email in current language
$admin_email = get_option( 'admin_email' );
// For language-specific admin emails, use WPML's string translation
// (documented at wpml.org/documentation/support/wpml-coding-api/wpml-hooks-reference/)
if ( function_exists( 'icl_t' ) ) {
// First register the string if not already registered
if ( function_exists( 'icl_register_string' ) ) {
icl_register_string( 'my-block-theme', 'contact_email', $admin_email );
}
$admin_email = icl_t(
'my-block-theme',
'contact_email',
$admin_email
);
}
$subject = sprintf(
/* translators: %s: Sender name */
__( 'Contact form submission from %s', 'my-block-theme' ),
$name
);
wp_mail( $admin_email, $subject, $message );
}
add_action( 'init', 'my_theme_process_contact_form' );
It is also important to assess your navigation language consciousness, because menu items, URLs and structure can differ between languages. Your translation plug -probably has an API for building language switches:
function my_theme_language_switcher_block() {
    if ( ! function_exists( 'pll_the_languages' ) &&Â
         ! function_exists( 'icl_get_languages' ) ) {
        return;
    }
    $output="";
    // Polylang language switcherÂ
    // (documented at polylang.pro/doc/function-reference/)
    if ( function_exists( 'pll_the_languages' ) ) {
        $languages = pll_the_languages( array( 'raw' => 1 ) );
        foreach ( $languages as $lang ) {
            $output .= sprintf(
                '%s',
                esc_url( $lang['url'] ),
                $lang['current_lang'] ? 'current-lang' : '',
                esc_html( $lang['name'] )
            );
        }
    }
    // WPML language switcher
    // (documented at wpml.org/documentation/support/wpml-coding-api/multi-language-api/)
    elseif ( function_exists( 'icl_get_languages' ) ) {
        $languages = icl_get_languages();
        foreach ( $languages as $lang ) {
            $output .= sprintf(
                '%s',
                esc_url( $lang['url'] ),
                $lang['active'] ? 'current-lang' : '',
                esc_html( $lang['native_name'] )
            );
        }
    }
    $output .= '';
    return $output;
}
Working with translation plug -in is probably a large part of your work, so let’s follow this aspect.
Working with Translation Plug -S: Compatibility and optimization
Every WordPress -Real language plug -in a unique way in a unique way. Insight into the approaches that take different solutions help you build compatibility and flexibility from the start.
WPML’s full site -Processing documentation outlines how to need a specific configuration for block themes:
// WPML FSE compatibility based on official documentation
add_action( 'init', function() {
if ( ! defined( 'WPML_VERSION' ) ) {
return;
}
// FSE themes are automatically detected in WPML 4.5.3+ // Enable FSE support
add_filter( 'wpml_is_fse_theme', '__return_true' );
// Register custom strings per WPML String Translation documentation
// (documented at wpml.org/documentation/support/wpml-coding-api/wpml-hooks-reference/)
if ( function_exists( 'icl_register_string' ) ) {
icl_register_string(
'my-block-theme',
'footer-copyright',
'© My Company.'
);
}
});
Polylang Pro has supported the site editor since version 3.2. The plug -in deals with block themes via the standard string -dealing interface:
// Polylang string registration per official documentation
if ( function_exists( 'pll_register_string' ) ) {
pll_register_string(Â
'Footer Copyright',
'© My Company.',
'my-block-theme',
true // Multiline support
);
}
TranslatePress documentation Show that certain dynamic elements need exclusion for optimum performance:
// TranslatePress optimization based on official recommendations
// (documented at translatepress.com/docs/developers/)
add_filter( 'trp_stop_translating_page', function( $stop, $url ) {
// Skip admin and API requests per TranslatePress documentation
if ( is_admin() || wp_is_json_request() ) {
return true;
}
// Skip pattern preview URLs that can cause rendering issues
    if ( strpos( $url, 'pattern-preview' ) !== false ) {
    return true;
}
return $stop;
}, 10, 2 );
Finally, there are a few tips for general purposes to pass on when working with code bases from third parties (such as plug-ins). First make sure you use a systematic approach to debug translation problems.
// Debug helper for translation issues
function my_theme_debug_translations() {
if ( ! WP_DEBUG || ! current_user_can( 'manage_options' ) ) {
return;
}
error_log( 'Text domain loaded: ' . is_textdomain_loaded(
'my-block-theme' ) );
    error_log( 'Current locale: ' . get_locale() );
    error_log( 'Translation test: ' . __(
'Hello World',
'my-block-theme'
)
);
// Check JSON translations for blocks
    $json_file = WP_LANG_DIR . '/themes/my-block-theme-' . get_locale() . '-script-handle.json';
error_log( 'JSON translation exists: ' . file_exists( $json_file ) );
}
add_action( 'init', 'my_theme_debug_translations' );
Site -caching can interfere with translation updates, so you may want to delete caches when translation files change:
# Clear WordPress transients
wp transient delete --all
# Generate fresh translation files
wp i18n make-pot . languages/my-block-theme.pot
wp i18n make-json languages/ --no-purge
Performance -optimization becomes critical with translation plug -in. Each plug -in adds database -queries and process overhead, which again benefits from caching often used translations:
function my_theme_cached_translation( $text, $domain = 'my-block-theme' ) {
    $cache_key = 'translation_' . md5( $text . get_locale() );
    $cached = wp_cache_get( $cache_key, 'my_theme_translations' );
    if ( false === $cached ) {
        $cached = __( $text, $domain );
        wp_cache_set( $cache_key, $cached, 'my_theme_translations', HOUR_IN_SECONDS );
    }
    return $cached;
}
Alternatively, it might be wise to skip caching until you are ready to implement. The use of an stenciling environment is ideal for this and you usually do not need the performance boost that Caching offers.
Summary
The internationalization of the block theme requires that you work with both WordPress translation methods and use new approaches within the site -editor.
By configuring your theme metadata, implementing template strategies and understanding the requirements of translation plug-ins, you can create multilingual block themes that perform well and offer a high-quality user experience.
When you are ready to launch, Kinsta’s managed hosting for WordPress delivers the performance and global scope, your site needs, with built-in caching, a 37-location CDN and tools such as GIT integration and scening.


