Skip to content Skip to sidebar

This thread is resolved. Here is a description of the problem and solution.

Problem:
The client is experiencing an issue where newly added strings in Twig templates are not being detected by WPML String Translation. This problem only affects Twig templates, as strings added in PHP files are still detected and translated correctly.

Solution:
We recommend handling string registration and translation retrieval in PHP, keeping Twig as the presentation layer. Here is a step-by-step guide:

1. Register strings using the

wpml_register_single_string

action and retrieve translations using the

wpml_translate_single_string

filter in PHP. Example:

function theme_t(string $name, string $default, string $context = 'Theme strings'): string {<br />    do_action('wpml_register_single_string', $context, $name, $default);<br />    return apply_filters('wpml_translate_single_string', $default, $context, $name);<br />}<br />$context['i18n'] = [<br />    'read_more' => theme_t('button.read_more', 'Read more'),<br />    'search_placeholder' => theme_t('search.placeholder', 'Search'),<br />];<br />Timber::render('template.twig', $context);

2. Consider maintaining a centralized PHP file for translations or separate files per component/block for larger projects.

3. For block-based architectures, manage translations at the block level. Example:

function get_card_block_i18n(): array {<br />    return [<br />        'title' => theme_t('blocks.card.title', 'Featured article', 'Theme blocks'),<br />        'cta'   => theme_t('blocks.card.cta', 'Read more', 'Theme blocks'),<br />    ];<br />}

Documentation on string registration and translation can be found at:
wpml_register_single_string
wpml_translate_single_string

If this solution does not resolve your issue or seems outdated, we highly recommend checking related known issues at https://wpml.org/known-issues/, verifying the version of the permanent fix, and confirming that you have installed the latest versions of themes and plugins. If needed, please open a new support ticket at WPML support forum.

This is the technical support forum for WPML - the multilingual WordPress plugin.

Everyone can read, but only WPML clients can post here. WPML team is replying on the forum 6 days per week, 22 hours per day.

This topic contains 4 replies, has 0 voices.

Last updated by Andrey 1 month, 1 week ago.

Assisted by: Andrey.

Author Posts
June 9, 2026 at 3:02 pm #18091052

enriqueE-3

Hi WPML Team,

We are experiencing an issue where newly added strings in Twig templates are no longer being detected by WPML String Translation.

Historically, we have used the standard WordPress translation function directly in Twig:

.twig file
{{ __('Sorry, no content', 'Global Theme') }}

After adding a new string, we would typically:

* Scan the theme for strings
* Visit the page where the string is rendered
* Rescan strings if needed
* Clear caches

The string would then appear in WPML → String Translation and could be translated normally.

Recently, this workflow has stopped working for new strings added in .twig files. The strings are rendered correctly on the frontend, but they never appear in WPML String Translation.

A few important observations:

* This issue only affects Twig templates.
* Strings added in PHP files are still detected and translated correctly.
* Existing Twig translations continue to work.
* Only newly added Twig strings are not being detected.
* We have tested this on multiple projects, including Jameson.

As a workaround, we created a custom Twig helper:

In a .php helper file

function gtp_wpml_translate(string $text, string $domain = 'Global Theme'): string
{
$name = md5($text);

if (function_exists('icl_register_string')) {
icl_register_string($domain, $name, $text);
}

return apply_filters('wpml_translate_single_string', $text, $domain, $name);
}

And in Twig:
{{ wpml_t('Sorry, no content', 'Global Theme') }}

This works correctly because the string is manually registered with WPML and then translated using String Translation.

We also found that using md5($text) as the string name works reliably. If we use the original text as the string name, WPML appears to fall back to MO file resolution instead of retrieving the translation from the database.

Our questions are:

1. Has anything changed recently regarding WPML detection of strings inside Twig templates?
2. Is there a recommended way to register and translate strings from Twig templates going forward?
3. Is our custom helper approach the recommended solution, or are we missing a configuration or scanning step that should still allow {{ __('text', 'domain') }} to be detected automatically?

Any guidance would be greatly appreciated.

Thank you.

June 10, 2026 at 8:19 pm #18094653

Andrey
WPML Supporter since 06/2013

Languages: English (English ) Russian (Русский )

Timezone: Europe/Kyiv (GMT+03:00)

Thank you for contacting WPML support.

I’m sorry you’ve run into this issue.

WPML no longer supports string Twig templates, so this functionality will not work as you expected. I understand this can be frustrating, and I apologize for the inconvenience. Decisions to remove functionality are not taken lightly, but in this case, the change was necessary for security reasons.

If you need to register strings for translation, they should be registered from PHP files, as you are already aware.

Regarding your current workaround, if it is working reliably in your setup, you can continue using it. While it is not an officially supported approach, nothing prevents you from using it if it meets your requirements.

June 12, 2026 at 9:10 am #18098873

enriqueE-3

Thank you for the clarification regarding Twig support.

I have a few follow-up questions regarding the recommended approach moving forward.

Many of our projects are built using Timber/Twig and contain a large number of translatable strings within Twig templates. Since Twig string detection is no longer supported, what is the recommended long-term solution for projects like these?

Specifically:

1. What is the recommended way to register strings from PHP for use in Twig templates?
2. For larger projects, is it acceptable to maintain a centralized PHP file (or multiple PHP files per component/block) containing translatable strings and then pass the translated values into Twig?
3. Is there a recommended pattern from WPML for block-based architectures where only the strings required by the currently rendered block are loaded?
4. Is there any supported or automated mechanism to help migrate existing Twig-based translations to the new approach without manually registering every string?
5. If a string is registered from PHP, translated in WPML, and later the registration code is removed, will WPML still be able to resolve and return the translation, or must the registration remain permanently available in the codebase?
6. For performance-sensitive sites, is it better to:
* register strings only in the admin area and perform translation lookups on the frontend, or
* register and translate strings during normal page rendering?

We are trying to implement a solution that is scalable, performant, and aligned with WPML best practices for modern Twig-based themes.

Thank you.

June 12, 2026 at 9:15 am #18098876

enriqueE-3

One additional question:

Could you please point me to any release notes, changelog entries, documentation, or announcements related to the removal of Twig string translation support?

I reviewed the WPML release notes but was unable to find any reference to this change, so I would appreciate any documentation you can share.

Thank you.

June 12, 2026 at 1:16 pm #18099943

Andrey
WPML Supporter since 06/2013

Languages: English (English ) Russian (Русский )

Timezone: Europe/Kyiv (GMT+03:00)

Thank you for your feedback.

Unfortunately, I cannot provide project-specific recommendations on how to structure or maintain your Twig templates. The officially supported approach is to register strings using PHP. You can find more information about WordPress internationalization here:

WordPress Internationalization Guide:
https://developer.wordpress.org/plugins/internationalization/how-to-internationalize-your-plugin/
hidden link
https://developer.wordpress.org/plugins/internationalization/

Based on the available information, I can share the following suggestions:

1. What is the recommended way to register strings from PHP for use in Twig templates?

You can keep Twig as the presentation layer and handle string registration and translation retrieval in PHP.

For example:

function theme_t( string $name, string $default, string $context = 'Theme strings' ): string {
    do_action( 'wpml_register_single_string', $context, $name, $default );
    return apply_filters(
        'wpml_translate_single_string',
        $default,
        $context,
        $name
    );
}
$context['i18n'] = [
    'read_more' => theme_t( 'button.read_more', 'Read more' ),
    'search_placeholder' => theme_t( 'search.placeholder', 'Search' ),
];
Timber::render( 'template.twig', $context );

Twig:

<em><u>hidden link</u></em>
<input placeholder="{{ i18n.search_placeholder }}">

WPML provides the following hooks for this purpose:

- wpml_register_single_string – register strings
- wpml_translate_single_string – retrieve translations

Documentation:

https://wpml.org/wpml-hook/wpml_register_single_string/

2. Is a centralized PHP file acceptable?

Yes, a centralized i18n.php file, or separate files per component/block, can be a reasonable long-term approach. For larger projects, keeping strings close to the components that use them may improve maintainability.

3. Is there a recommended pattern for block-based architectures?

We do not have an official WPML-recommended pattern for this use case.

One possible approach would be:

function get_card_block_i18n(): array {
    return [
        'title' => theme_t( 'blocks.card.title', 'Featured article', 'Theme blocks' ),
        'cta'   => theme_t( 'blocks.card.cta', 'Read more', 'Theme blocks' ),
    ];
}

This function would only be called when the corresponding block is rendered.

For grouped block/package-style strings, WPML also provides:

wpml_register_string
wpml_translate_string

Documentation:

https://wpml.org/wpml-hook/wpml_register_string/

4. Is there an automated migration path for existing Twig-based translations?

At this time, there is no supported WPML tool that automatically migrates Twig-detected strings to PHP registrations.

The practical approach would be to identify the existing Twig strings, register them in PHP using stable names/keys, and then recreate or map the translations accordingly.

5. Can the registration code be removed after translations are created?

WPML retrieves translations using the string name and context/domain and falls back to the original string when no translation is available.

Although existing translations may continue to work if the lookup remains unchanged, I would recommend keeping the registration code in place. This ensures the strings remain discoverable and can be properly restored after database migrations, cleanups, or deployments to new environments.

6. What is the recommended approach for performance-sensitive sites?

A common approach is to register strings when they are created, updated, or when relevant administrative screens are loaded, and then perform translation lookups on the frontend.

WPML notes that repeated registration calls are ignored when the string has not changed, and String Translation data is cached, so the overhead is generally limited.

Additional information:

https://wpml.org/documentation/support/translation-for-texts-by-other-plugins-and-themes/

Regarding documentation for this change, none is available. The first announcement mentioning the removal of Twig template support was published here:
WPML 4.8 Will Drop Support for Twig Templates
https://wpml.org/changelog/2025/05/wpml-4-8-will-drop-support-for-twig-templates/