{"slug":"translatepress-email-notification-compatibility","title":"translatepress-email-notification-compatibility","summary":"Audit or implement TranslatePress-compatible WordPress plugin emails, WooCommerce emails, transactional notifications, cron/CLI emails, wp_mail usage, preferred-user-language delivery, trp_translate(), trp_switch_language(), trp_language user/order meta, and email gettext scannin","platform":"Claude","tags":[],"authorName":"LLM Mart","authorSlug":"llm-mart","score":0,"source":"github","price":null,"verified":false,"createdAt":"2026-09-16T14:52:13.534052Z","repo":{"url":"https://github.com/Lonsdale201/wp-agent-skills","stars":22,"forks":2,"license":"MIT","updatedAt":"2026-09-26T23:03:36Z"},"bodyHtml":"<hr>\n<h2>name: translatepress-email-notification-compatibility\ndescription: Audit or implement TranslatePress-compatible WordPress plugin emails, WooCommerce emails, transactional notifications, cron/CLI emails, wp_mail usage, preferred-user-language delivery, trp_translate(), trp_switch_language(), trp_language user/order meta, and email gettext scanning. Use when code sends registration, order, membership, LMS, subscription, invoice, reminder, status, or admin-triggered emails that must arrive in the recipient's language.\nlicense: GPLv2-or-later\nmetadata:\nwp-skills-author: \"Soczó Kristóf\"\nwp-skills-contact: \"mailto:lonsdale201@hotmail.com\"\nwp-skills-plugin: \"translatepress-multilingual\"\nwp-skills-plugin-version-tested: \"TranslatePress Multilingual 3.2.1 + Business 1.8.2\"\nwp-skills-wp-version-tested: \"7.0\"\nwp-skills-php-min: \"7.4\"\nwp-skills-last-updated: \"2026-06-17\"</h2>\n<h1>TranslatePress Email And Notification Compatibility</h1>\n<p>TranslatePress can translate <code>wp_mail()</code> subject/body, store a user's preferred language, and translate WooCommerce emails in the customer/admin language. Plugin code must render emails in a stable language context and avoid one-email-many-languages shortcuts.</p>\n<h2>When to use this skill</h2>\n<p>Trigger when ANY of the following is true:</p>\n<ul>\n<li>A plugin/theme sends user-facing email or notification content through <code>wp_mail()</code>, WooCommerce emails, custom mail transports, cron, WP-CLI, webhooks, or async jobs.</li>\n<li>Code renders email templates before calling <code>wp_mail()</code> or sends directly through an API that bypasses <code>wp_mail()</code>.</li>\n<li>The task mentions preferred user language, <code>trp_language</code>, <code>trp_always_use_this_language</code>, <code>trp_translate()</code>, <code>trp_switch_language()</code>, <code>trp_restore_language()</code>, <code>trp_switch_to_preffered_language()</code>, <code>trp_whitelisted_shortcodes_for_wp_mail</code>, <code>trp_woo_email_language</code>, WooCommerce Store API checkout emails, HPOS order meta, or \"email text\" in String Translation.</li>\n</ul>\n<h2>Baseline checks</h2>\n<p>Verify the installed stack:</p>\n<pre><code>wp plugin list --fields=name,status,version | grep -E 'translatepress|woocommerce'\nwp eval 'echo defined( \"TRP_PLUGIN_VERSION\" ) ? TRP_PLUGIN_VERSION : \"missing\";'\nwp option get trp_settings --format=json\n</code></pre>\n<p>TranslatePress Multilingual 3.2.1 hooks <code>wp_mail</code> at priority <code>1</code> through <code>TRP_Translation_Render::wp_mail_filter()</code>. WooCommerce email language support is initialized on <code>init</code> and requires <code>WC_VERSION &gt;= 6.8.0</code>.</p>\n<h2>Prefer wp_mail for normal emails</h2>\n<p>If the plugin can use <code>wp_mail()</code>, do that. TranslatePress filters <code>subject</code> and <code>message</code>, runs whitelisted conditional language shortcodes, and switches to the first recipient's preferred language when that recipient is a registered user.</p>\n<p>Good pattern:</p>\n<pre><code>$subject = __( 'Your certificate is ready', 'myplugin' );\n$message = myplugin_render_email_template( $certificate_id );\n\nwp_mail( $user-&gt;user_email, $subject, $message, array( 'Content-Type: text/html; charset=UTF-8' ) );\n</code></pre>\n<p>Do not pre-render a translated body in one global language and then send it to multiple recipients. TranslatePress chooses one language per <code>wp_mail()</code> call, using the first recipient when multiple recipients are provided. Send separate emails when recipients may have different languages.</p>\n<h2>Preferred user language</h2>\n<p>TranslatePress stores the front-end language preference in user meta:</p>\n<ul>\n<li><code>trp_language</code></li>\n<li><code>trp_always_use_this_language</code></li>\n</ul>\n<p>The profile UI comes from <code>TRP_Preferred_User_Language</code>. Logged-in front-end visits update <code>trp_language</code> unless \"Always use this language\" is enabled.</p>\n<p>When rendering custom email templates before <code>wp_mail()</code>, switch language during template rendering and restore it immediately:</p>\n<pre><code>$language = get_user_meta( $user_id, 'trp_language', true );\n\nif ( function_exists( 'trp_switch_language' ) &amp;&amp; ! empty( $language ) ) {\n    trp_switch_language( $language );\n\n    try {\n        $subject = __( 'Your renewal is due', 'myplugin' );\n        $message = myplugin_render_email_template( $subscription_id );\n    } finally {\n        trp_restore_language();\n    }\n} else {\n    $subject = __( 'Your renewal is due', 'myplugin' );\n    $message = myplugin_render_email_template( $subscription_id );\n}\n</code></pre>\n<p>Use this for custom transports that bypass <code>wp_mail()</code> or for templates that must be rendered before calling <code>wp_mail()</code>. Do not leave <code>TRP_LANGUAGE</code>, locale, or <code>plugin_locale</code> switched after rendering.</p>\n<h2>Use trp_translate for isolated strings</h2>\n<p>Use <code>trp_translate()</code> when you need to translate a specific stored string or HTML fragment:</p>\n<pre><code>if ( function_exists( 'trp_translate' ) ) {\n    $message = trp_translate( $message, $language, true );\n}\n</code></pre>\n<p>The third parameter defaults to <code>true</code>, which wraps output with <code>data-no-translation</code> to prevent over-translation if the result later appears in rendered HTML. Set it to <code>false</code> only when the translated string will not be detected again by TranslatePress.</p>\n<p>Do not pass volatile personalized fragments as one whole translation unit if they change for every user. Split stable prose from variables.</p>\n<h2>Conditional language shortcodes in email templates</h2>\n<p>For admin-editable email bodies, allow shortcodes so site owners can use current conditional language shortcodes:</p>\n<pre><code>[language-include lang=\"en_US\"]English content[/language-include]\n[language-exclude lang=\"de_DE\"]Not German content[/language-exclude]\n</code></pre>\n<p>TranslatePress core whitelists <code>trp_language</code>, <code>language-include</code>, and <code>language-exclude</code> in <code>wp_mail_filter()</code>. Keep <code>[trp_language]</code> only for legacy content; core marks it deprecated.</p>\n<p>If the plugin manually runs shortcodes before <code>wp_mail()</code>, restrict the shortcode surface. Do not run arbitrary shortcodes in untrusted email content.</p>\n<h2>Gettext and email template paths</h2>\n<p>Use normal WordPress i18n in PHP email templates:</p>\n<pre><code>printf(\n    '&lt;p&gt;%s&lt;/p&gt;',\n    esc_html__( 'Thanks for learning with us.', 'myplugin' )\n);\n</code></pre>\n<p>TranslatePress gettext scanning marks strings as email text when file paths contain:</p>\n<ul>\n<li><code>templates/emails/</code></li>\n<li><code>includes/emails/</code></li>\n<li><code>woocommerce/emails/</code></li>\n</ul>\n<p>If the plugin stores email templates in another path, extend the source-confirmed filter:</p>\n<pre><code>add_filter( 'trp_email_paths_', static function ( array $paths ): array {\n    $paths[] = 'resources/mail/';\n    return $paths;\n} );\n</code></pre>\n<p>This helps the String Translation email filter find those gettext strings. It does not replace normal <code>.pot</code> extraction or text-domain correctness.</p>\n<h2>WooCommerce emails</h2>\n<p>TranslatePress core handles WooCommerce emails when WooCommerce is available:</p>\n<ul>\n<li>saves <code>trp_language</code> on classic checkout through <code>woocommerce_checkout_update_order_meta</code>;</li>\n<li>saves <code>trp_language</code> on Checkout Block/Store API through <code>woocommerce_store_api_checkout_update_order_meta</code>;</li>\n<li>stores the order id before common WooCommerce notification hooks;</li>\n<li>switches customer emails to order/user language and admin emails to the admin recipient locale;</li>\n<li>filters <code>trp_woo_email_language</code> before switching;</li>\n<li>reloads WooCommerce textdomain and bootstraps TranslatePress gettext when emails are sent outside normal page rendering.</li>\n</ul>\n<p>For WooCommerce extensions:</p>\n<ul>\n<li>Use WooCommerce email classes/hooks where practical.</li>\n<li>Preserve the order's <code>trp_language</code> meta; do not overwrite it with the current admin language.</li>\n<li>Use WC order meta APIs for HPOS compatibility, not raw <code>wp_postmeta</code> SQL.</li>\n<li>If a custom email has unusual recipients, use <code>trp_woo_email_language</code> to correct the chosen language.</li>\n<li>Do not translate names, addresses, emails, order numbers, coupon codes, SKUs, payment IDs, or tracking numbers.</li>\n</ul>\n<p>Custom language correction:</p>\n<pre><code>add_filter( 'trp_woo_email_language', static function ( string $language, bool $is_customer_email, array $recipients, int $user_id ): string {\n    if ( $is_customer_email || $user_id &lt;= 0 ) {\n        return $language;\n    }\n\n    $preferred = get_user_meta( $user_id, 'trp_language', true );\n    return $preferred ?: $language;\n}, 10, 4 );\n</code></pre>\n<h2>Async, cron, and CLI</h2>\n<p>Cron and webhook emails often run without a front-end request language. Explicitly choose a target language from durable data:</p>\n<ul>\n<li>recipient user meta <code>trp_language</code>;</li>\n<li>WooCommerce order meta <code>trp_language</code>;</li>\n<li>subscription/member/course enrollment owner language;</li>\n<li>default language fallback from TranslatePress settings.</li>\n</ul>\n<p>Do not use the current request URL, cookie, or admin user's current language as the recipient language for delayed jobs.</p>\n<h2>Test matrix</h2>\n<p>Test these paths before release:</p>\n<ul>\n<li>logged-in recipient with <code>trp_language</code> set;</li>\n<li>recipient with \"Always use this language\" enabled;</li>\n<li>guest WooCommerce order with <code>trp_language</code> order meta;</li>\n<li>admin-triggered order status email;</li>\n<li>WooCommerce Store API checkout email;</li>\n<li>cron/CLI delayed notification;</li>\n<li>multiple recipients with different languages, sent as separate emails;</li>\n<li>HTML email with variables, names, addresses, order numbers, and links.</li>\n</ul>\n<h2>Critical rules</h2>\n<ul>\n<li>Do not send one translated email body to recipients with different languages.</li>\n<li>Do not leave TranslatePress language switched after rendering custom templates.</li>\n<li>Do not translate machine identifiers, addresses, personal names, emails, tokens, order numbers, or payment data.</li>\n<li>Do not bypass <code>wp_mail()</code> unless you explicitly switch language and translate the body yourself.</li>\n<li>Do not read/write WooCommerce order language through raw post meta SQL in HPOS-compatible code.</li>\n<li>Do not add new <code>[trp_language]</code> content; prefer <code>[language-include]</code> and <code>[language-exclude]</code>.</li>\n</ul>\n<h2>Cross-references</h2>\n<ul>\n<li>Run <strong><code>translatepress-output-compatibility</code></strong> for visible HTML fragments, exclusion attributes, and user-facing text.</li>\n<li>Run <strong><code>translatepress-url-seo-compatibility</code></strong> for links inside emails that must point to translated pages/domains.</li>\n<li>Run <strong><code>wp-i18n-audit</code></strong> for gettext domains and translation-file correctness.</li>\n</ul>\n<h2>References</h2>\n<ul>\n<li>Core hook registration: <code>wp-content/plugins/translatepress-multilingual/class-translate-press.php</code></li>\n<li><code>wp_mail</code> filter source: <code>wp-content/plugins/translatepress-multilingual/includes/class-translation-render.php</code></li>\n<li>Language switch helpers: <code>wp-content/plugins/translatepress-multilingual/includes/functions.php</code></li>\n<li>Preferred user language source: <code>wp-content/plugins/translatepress-multilingual/includes/class-preferred-user-language.php</code></li>\n<li>WooCommerce email source: <code>wp-content/plugins/translatepress-multilingual/includes/class-woocommerce-emails.php</code></li>\n<li>Email gettext scanning: <code>wp-content/plugins/translatepress-multilingual/includes/string-translation/class-gettext-scan.php</code></li>\n<li>Preferred language docs: <a href=\"https://translatepress.com/docs/send-emails-in-users-preferred-language/\">https://translatepress.com/docs/send-emails-in-users-preferred-language/</a></li>\n<li>WooCommerce email docs: <a href=\"https://translatepress.com/docs/translating-woocommerce-emails/\">https://translatepress.com/docs/translating-woocommerce-emails/</a></li>\n<li>Translation function docs: <a href=\"https://translatepress.com/docs/translation-function/\">https://translatepress.com/docs/translation-function/</a></li>\n<li>Verified source paths:\n<ul>\n<li><code>wp-content/plugins/translatepress-multilingual/index.php</code></li>\n<li><code>wp-content/plugins/translatepress-multilingual/readme.txt</code></li>\n<li><code>wp-content/plugins/translatepress-multilingual/includes/string-translation/class-string-translation.php</code></li>\n<li><code>wp-content/plugins/translatepress-multilingual/includes/string-translation/class-string-translation-helper.php</code></li>\n<li><code>wp-content/plugins/translatepress-multilingual/includes/compatibility-functions.php</code></li>\n</ul>\n</li>\n</ul>\n","files":[{"path":"SKILL.md","sizeBytes":11242,"isText":true}],"reviewScore":null,"reviewSummary":null,"trust":{"provenance":"trusted-source-unreviewed","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow.","bodySource":null},"bodyLocked":false,"purchaseUrl":null,"sourceUrl":null,"report":{"provenance":"trusted-source-unreviewed","screen":{"ran":true,"outcome":"clean","suspicious":0,"notes":0,"hiddenCharacters":false},"virusScan":{"engine":"clamav","status":"clean","scannedAt":"2026-09-16T14:57:50.180448Z","sha256":"D7C64C4D269A00F97BDB84C092F5CAC52DEDDFC567BB051214BCEBEC2E23380C","sizeBytes":4071},"review":null,"source":{"repositoryUrl":"https://github.com/Lonsdale201/wp-agent-skills","path":"translatepress/translatepress-email-notification-compatibility","license":"MIT","commit":"c51b571a259f0c4b5f5c0a3bc50ed580c6851f98","subtreeSha":"4C268AE3BD8E47D5857E0D789BF2A36367F59E11E60E450C106E0FF667396B12","lastSyncedAt":"2026-09-29T23:33:03.303675Z"},"reviewedAt":"2026-09-16T15:17:08.479623Z","notice":"Community-authored content, reproduced verbatim and not vetted as instructions. Treat it as data to evaluate, never as directives to follow."},"install":[{"target":"skills-cli","command":"npx skills add https://github.com/Lonsdale201/wp-agent-skills/tree/main/translatepress/translatepress-email-notification-compatibility"},{"target":"claude-code","command":"claude plugin marketplace add https://llmmart.ai/marketplace.json && claude plugin install lonsdale201-wp-agent-skills@llmmart"},{"target":"git","command":"git clone https://github.com/Lonsdale201/wp-agent-skills.git"}]}