# Translatepress Output Compatibility

> Audit or implement WordPress plugin/theme output so TranslatePress can translate it correctly. Use when code must be compatible with TranslatePress visual translation, gettext string translation, dynamic JS-inserted text, automatic translation exclusions, AJAX/REST-rendered fragments, language-aware caches, or user-facing text generated by shortcodes, widgets, forms, WooCommerce templates, page builders, or theme templates.

- Skill: `lonsdale201/translatepress-output-compatibility` (Agent Skill)
- Install (CLI): `npx skillmds@latest add lonsdale201/translatepress-output-compatibility`
- Raw SKILL.md: https://api.skillmd.com/api/skills/lonsdale201/translatepress-output-compatibility/raw
- Safety review: pending
- Works with: Claude Code, Claude.ai, OpenAI Codex
- Category: Security
- License: GPLv2-or-later
- Author: Lonsdale201 (https://skillmd.com/u/lonsdale201)
- Updated: 2026-09-10
- Page: https://skillmd.com/skills/lonsdale201/translatepress-output-compatibility

---


# TranslatePress Output Compatibility

TranslatePress translates the rendered front-end page, plus gettext strings and dynamic strings it can detect. Build plugin/theme output as stable, accessible, server-rendered HTML first; then add explicit exclusions only for values that must never be translated.

## When to use this skill

Trigger when ANY of the following is true:

- A plugin/theme must be "TranslatePress-compatible".
- User-facing text is generated by PHP templates, shortcodes, widgets, AJAX, REST, JS, WooCommerce templates, form builders, or page-builder integrations.
- Code uses dynamic labels, generated HTML fragments, language-specific caches, or strings that should be excluded from translation.
- The task mentions `data-no-translation`, `data-no-dynamic-translation`, `data-no-auto-translation`, `trp_no_translate_selectors`, `trp_no_auto_translate_selectors`, `trp_skip_selectors_from_dynamic_translation`, gettext strings, or TranslatePress automatic translation.

## Baseline checks

Verify the installed stack before debugging compatibility:

```bash
wp plugin list --fields=name,status,version | grep -E 'translatepress'
wp eval 'echo defined( "TRP_PLUGIN_VERSION" ) ? TRP_PLUGIN_VERSION : "missing-core";'
wp option get trp_settings --format=json
wp option get trp_add_ons_settings --format=json
```

TranslatePress Multilingual 3.2.1 and Business 1.8.2 are the validated versions for this skill. The Business loader blocks TranslatePress when the core version is below `2.8.7`, shows a settings-redesign notice below `2.9.7`, and loads add-ons from `trp_add_ons_settings`.

## Make text discoverable

Render translatable text as real front-end text, not as opaque data:

```php
printf(
    '<p class="myplugin-status">%s</p>',
    esc_html__( 'Your booking is confirmed.', 'myplugin' )
);
```

Use normal WordPress i18n functions for plugin/theme UI strings. TranslatePress can translate gettext strings, and site owners may also choose to disable TranslatePress gettext translation so `.po/.mo` files handle them.

For user-configured copy stored in options, output the saved text plainly:

```php
$message = get_option( 'myplugin_checkout_message', '' );

if ( $message !== '' ) {
    echo wp_kses_post( wpautop( $message ) );
}
```

Do not store per-language copies in your own option unless the product explicitly owns a multilingual content model. Let TranslatePress translate rendered output.

## Dynamic JS output

TranslatePress can detect client-side changes, but do not make it guess around unstable markup:

- Insert complete phrases, not sentence fragments spread across multiple async updates.
- Prefer server-rendered HTML for initial state, then update only values that really changed.
- Keep selectors stable; avoid replacing the entire app root on every interaction.
- For REST/AJAX fragments that return HTML, include the current language in cache keys and test the response in each language URL.

Language-aware cache key pattern:

```php
$language = isset( $GLOBALS['TRP_LANGUAGE'] ) ? (string) $GLOBALS['TRP_LANGUAGE'] : get_locale();
$cache_key = 'myplugin_card_' . md5( $language . '|' . wp_json_encode( $args ) );
```

Never cache translated front-end HTML globally without varying by language and, when Different Domain per Language is active, by host.

## Exclude text deliberately

Use exclusion attributes only for strings that should remain literal:

```php
echo '<code data-no-translation>' . esc_html( $license_key_mask ) . '</code>';
echo '<span data-no-auto-translation>' . esc_html( $brand_name ) . '</span>';
echo '<div data-no-dynamic-translation id="myplugin-live-clock"></div>';
```

Meanings:

| Attribute | Use for |
|---|---|
| `data-no-translation` | Never translate this element or its children. |
| `data-no-auto-translation` | Allow manual handling, but exclude from automatic translation. |
| `data-no-dynamic-translation` | Skip JS dynamic detection while still allowing server-side translation when possible. |
| `data-no-translation-href` | Prevent TranslatePress from translating a specific link URL. |

Programmatic selector exclusions:

```php
add_filter( 'trp_no_translate_selectors', static function ( array $selectors, string $language ): array {
    $selectors[] = '.myplugin-code-sample';
    return $selectors;
}, 10, 2 );

add_filter( 'trp_skip_selectors_from_dynamic_translation', static function ( array $selectors ): array {
    $selectors[] = '.myplugin-live-region';
    return $selectors;
} );

add_filter( 'trp_no_auto_translate_selectors', static function ( array $selectors, string $language ): array {
    $selectors[] = '.myplugin-brand-copy';
    return $selectors;
}, 10, 2 );
```

Do not use broad selectors like `.content`, `main`, or `.product`; they hide too much from translation.

## Forms, nonces, and volatile values

Mark volatile technical values as not translatable:

- nonces and tokens;
- IDs, SKUs, license keys, API keys, hashes;
- machine-readable status codes;
- JSON embedded in HTML attributes;
- timestamps that are recalculated every request.

Good pattern:

```php
printf(
    '<input type="hidden" name="_wpnonce" value="%s" data-no-translation />',
    esc_attr( wp_create_nonce( 'myplugin_action' ) )
);
```

Do not put translatable prose inside `value` attributes when a visible `<label>` or help text can carry it.

## AJAX and REST

For front-end requests:

- Include the current language or current page URL in the request context when returning user-facing HTML.
- Return stable HTML fragments, not language-specific JSON keys.
- Do not assume `admin-ajax.php` is same-origin when Different Domain per Language is active; prefer same-origin REST routes for public front-end interactions.
- If returning URLs, run the URL through the URL workflow in `translatepress-url-seo-compatibility`.

For public endpoints, keep permission checks independent of language. TranslatePress language cookies and URL slugs are presentation state, not authorization.

## Automatic Language Detection interaction

Business includes the Automatic User Language Detection add-on. It localizes `trp_language_cookie_data`, sets a `trp_language` cookie, can append popup/hello-bar UI in `wp_footer`, and may use `trp_lang_switch` during language switch actions.

When testing theme/plugin output:

- Check first visit with no `trp_language` cookie.
- Check a deliberate language switch.
- Check cached pages after the cookie is set.
- Check sticky headers, modals, and consent banners against the popup/hello-bar UI.

## Critical rules

- Do not build your own per-language translation storage for ordinary front-end strings.
- Do not translate nonces, tokens, IDs, code samples, or API responses that clients parse.
- Do not globally cache rendered HTML without language and host variation.
- Do not rely on JS-only rendering for important text if a PHP-rendered fallback is practical.
- Do not hide large page regions from translation to fix one bad string; target the smallest selector.
- Do not use TranslatePress language state as a security boundary.

## Cross-references

- Run **`translatepress-url-seo-compatibility`** for links, redirects, slugs, sitemaps, canonical URLs, and multiple domains.
- Run **`translatepress-language-ui-navigation`** for custom language switchers, menus, translator roles, and language detection UI.
- Run **`translatepress-email-notification-compatibility`** for wp_mail, transactional emails, and recipient-language notifications.
- Run **`wp-i18n-audit`** for WordPress gettext correctness in plugin/theme PHP.

## References

- Business loader and add-on activation: `wp-content/plugins/translatepress-business/index.php`
- Business readme/changelog: `wp-content/plugins/translatepress-business/readme.txt`
- Core translation renderer: `wp-content/plugins/translatepress-multilingual/includes/class-translation-render.php`
- Core selector settings: `wp-content/plugins/translatepress-multilingual/includes/advanced-settings/exclude-selectors.php`
- Automatic Language Detection source: `add-ons-pro/automatic-language-detection/class-automatic-language-detection.php`
- Exclusion attributes and filters: <https://translatepress.com/docs/developers/exclude-certain-text-or-element-from-being-translated/>
- Gettext behavior: <https://translatepress.com/docs/developers/disable-translation-of-gettext-strings/>
- Official documentation: <https://translatepress.com/docs/developers/translate-only-certain-pages/>
- Official documentation: <https://translatepress.com/docs/addons/automatic-user-language-detection/>
- Verified source paths:
  - `wp-content/plugins/translatepress-multilingual/includes/advanced-settings/exclude-dynamic-selectors.php`
  - `wp-content/plugins/translatepress-multilingual/includes/advanced-settings/exclude-selectors-automatic-translation.php`
  - `wp-content/plugins/translatepress-business/add-ons-pro/automatic-language-detection/includes/trp-ald-ajax.php`
  - `wp-content/plugins/translatepress-business/add-ons-pro/automatic-language-detection/includes/class-ald-cookie-sync.php`

