Skip Navigation

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 7 replies, has 0 voices.

Last updated by ielyzavetaS 4 days, 2 hours ago.

Assisted by: Dražen.

Author Posts
April 10, 2025 at 4:47 pm #16919897

ielyzavetaS

Background of the issue:
I am trying to translate a string that is output via a custom YayMail hook in WooCommerce transactional emails. The string is added to the email via a PHP hook and displays correctly in English. The domain shows as flatsome, and the string is visible in WPML's string translation table. Link to a page where the issue can be seen: hidden link

Symptoms:
The translated version does not show in the final email. Instead, I got the untranslated English string in the email, despite the translation existing in WPML's String Translation.

Questions:
Why is the translated string not appearing in the email?
How can I ensure the translation is applied correctly in WooCommerce emails?

April 15, 2025 at 6:22 am #16931632

Dražen
Supporter

Languages: English (English )

Timezone: Europe/Zagreb (GMT+02:00)

Hello,

thanks for contacting us.

1) Can you please share the code you used to add the text?

2) Did you try to add that text via extra content inside Email builder and in that way add different language content?

- hidden link

Regards,
Drazen

April 15, 2025 at 11:13 am #16933679

ielyzavetaS

Hello Drazen,

Thanks for your response.
However, the content I'm trying to translate is not added manually via YayMail's extra content editor. Instead, it’s injected programmatically via the woocommerce_email_before_order_table hook using a custom function.

What else is needed from my end for debugging?
Thank you in advance!

Screenshot 2025-04-15 at 12.47.11.png
Screenshot 2025-04-15 at 13.11.51.png
Screenshot 2025-04-15 at 12.59.57.png
Screenshot 2025-04-15 at 12.51.36.png
April 15, 2025 at 11:25 am #16933804

Dražen
Supporter

Languages: English (English )

Timezone: Europe/Zagreb (GMT+02:00)

Hello,

Thanks for getting back.

1) You mentioned woocommerce_email_before_order_table, that is WC hook, so the issue should happen also without YayMail addon, right? Can you please test?

2) Please share the hook snippet you added.

Regards,
Drazen

April 22, 2025 at 10:50 am #16954618

ielyzavetaS

Hello Drazen,

I'm sorry for taking this so long.

1. Yes, these fields are localized in the UI (see the screenshot).
2. Snippet:

<?php
/**
* Woocommerce Checkout change.
*
* @package iwpdev/flatsome-child
*/

namespace Iwpdev\FlatsomeChild\WooCommerce;

use WC_Checkout;
use WC_Order;

/**
* Checkout class file.
*/
class Checkout {
/**
* Checkout construct.
*/
public function __construct() {
$this->init();
}

/**
* Init actions and filters.
*
* @return void
*/
private function init(): void {
add_action( 'woocommerce_after_checkout_billing_form', [ $this, 'add_unknown_address_checkbox' ] );
add_action( 'woocommerce_after_checkout_billing_form', [ $this, 'add_not_vat_invoice' ] );
add_action( 'woocommerce_checkout_update_order_meta', [ $this, 'save_date_unknown_address' ] );
add_action( 'woocommerce_checkout_update_order_meta', [ $this, 'save_date_not_vat_invoice' ] );
add_action( 'woocommerce_admin_order_data_after_billing_address', [ $this, 'show_unknown_address_in_order' ] );
add_action( 'woocommerce_admin_order_data_after_billing_address', [ $this, 'show_not_vat_in_order' ] );
add_action( 'woocommerce_checkout_order_created', [ $this, 'set_invoice_number' ] );
add_action( 'woocommerce_email_before_order_table', [ $this, 'set_phone_number_in_email' ] );
add_action( 'wpo_wcpdf_document_is_allowed', [ $this, 'generate_invoice' ], 10, 2 );
add_action( 'woocommerce_shipping_fields', [ $this, 'add_phone_shipping_address' ], 10, 2 );
add_action( 'woocommerce_checkout_update_order_meta', [ $this, 'save_phone_shipping_address' ], 10, 2 );
add_action(
'woocommerce_admin_order_data_after_shipping_address',
[
$this,
'display_phone_shipping_address',
]
);
}

/**
* Set phone number in email.
*
* @param WC_Checkout $checkout Woocommerce Checkout class.
*
* @return void
*/
public static function set_phone_number_in_email( $order ) {
$receiver_phone = get_post_meta( $order->get_id(), '_receiver_phone', true );
$unknown_address = get_post_meta( $order->get_id(), '_unknown_address', true );
$phone_field = get_post_meta( $order->get_id(), '_shipping_phone_number', true );
$photo_to_email_address = get_post_meta( $order->get_id(), '_photo_to_email_address', true );

if ( $unknown_address === 'yes' ) {
echo '<p>' . __( 'I don\'t know the recipient\'s address', 'flatsome' ) . ': ✔</p>';
if ( $receiver_phone ) {
echo '<p>' . __( 'Phone of the recipient', 'flatsome' ) . ': ' . esc_html( $receiver_phone ) . '</p>';
}
}

if ( ! empty( $phone_field ) ) {
echo '<p>' . __( 'Phone of the recipient', 'flatsome' ) . ': ' . esc_html( $phone_field ) . '</p>';
}

if ( 'yes' === $photo_to_email_address ) {
echo '<p>' . __( 'I want to receive a photo of the bouquet by e-mail ', 'flatsome' ) . ': ✔</p>';
}
}

/**
* Generate invoice.
*
* @param $allowed
* @param $document
*
* @return false|mixed
*/
public static function generate_invoice( $allowed, $document ) {
$nip = get_post_meta( $document->order->get_id(), '_company_nip', true );

if ( empty( $nip ) ) {
return false;
}

return $allowed;
}

/**
* Add Not VAT Invoice.
*
* @param WC_Checkout $checkout Woocommerce Checkout class.
*
* @return void
*/
public function add_not_vat_invoice( WC_Checkout $checkout ): void {
echo '<div id="not_vat_checkbox">';
woocommerce_form_field(
'not_vat',
[
'type' => 'checkbox',
'class' => [ 'form-row-wide' ],
'label' => __( 'Invoice (not VAT)', 'flatsome' ),
],
$checkout->get_value( 'not_vat' )
);

echo '<div id="company_name_field" style="display:none;">';
woocommerce_form_field(
'company_name',
[
'type' => 'text',
'class' => [ 'form-row-wide' ],
'label' => __( 'Company Name', 'flatsome' ),
'required' => true,
'placeholder' => __( 'Enter your company name', 'flatsome' ),
],
$checkout->get_value( 'company_name' )
);
echo '</div>';
echo '<div id="company_address_field" style="display:none;">';
woocommerce_form_field(
'company_address',
[
'type' => 'text',
'class' => [ 'form-row-wide' ],
'label' => __( 'Company Address', 'flatsome' ),
'required' => true,
'placeholder' => __( 'Enter your company address', 'flatsome' ),
],
$checkout->get_value( 'company_address' )
);
echo '</div>';
echo '<div id="company_nip_field" style="display:none;">';
woocommerce_form_field(
'company_nip',
[
'type' => 'text',
'class' => [ 'form-row-wide' ],
'label' => __( 'Company NIP', 'flatsome' ),
'required' => true,
'placeholder' => __( 'Enter your company NIP', 'flatsome' ),
],
$checkout->get_value( 'company_nip' )
);
echo '</div></div>';
}

/**
* Add Unknown Address Checkbox.
*
* @param WC_Checkout $checkout Checkout class.
*
* @return void
*/
public function add_unknown_address_checkbox( WC_Checkout $checkout ): void {
echo '<div id="unknown_address_checkbox">';
woocommerce_form_field(
'unknown_address',
[
'type' => 'checkbox',
'class' => [ 'form-row-wide' ],
'label' => __( 'I don\'t know the recipient\'s address, contact by phone', 'flatsome' ),
],
$checkout->get_value( 'unknown_address' )
);

echo '<div id="receiver_phone_field" style="display:none;">';
woocommerce_form_field(
'receiver_phone',
[
'type' => 'tel',
'class' => [ 'form-row-wide' ],
'label' => __( 'Phone of the recipient', 'flatsome' ),
'required' => true,
'placeholder' => __( 'Enter your phone number', 'flatsome' ),
],
$checkout->get_value( 'receiver_phone' )
);
echo '</div></div>';
echo '<div id="photo_to_address_checkbox">';
woocommerce_form_field(
'photo_to_email_address',
[
'type' => 'checkbox',
'class' => [ 'form-row-wide' ],
'label' => __( 'I want to receive a photo of the bouquet by e-mail', 'flatsome' ),
],
$checkout->get_value( 'unknown_address' )
);
echo '</div>';
}

/**
* Save Data Not VAT Invoice.
*
* @param int $order_id Order ID.
*
* @return void
*/
public function save_date_not_vat_invoice( int $order_id ): void {
update_post_meta( $order_id, '_not_vat', ! empty( $_POST['not_vat'] ) ? 'yes' : 'no' );

if ( ! empty( $_POST['company_name'] ) ) {
update_post_meta( $order_id, '_company_name', sanitize_text_field( wp_unslash( $_POST['company_name'] ) ) );
}

if ( ! empty( $_POST['company_address'] ) ) {
update_post_meta( $order_id, '_company_address', sanitize_text_field( wp_unslash( $_POST['company_address'] ) ) );
}

if ( ! empty( $_POST['company_nip'] ) ) {
update_post_meta( $order_id, '_company_nip', sanitize_text_field( wp_unslash( $_POST['company_nip'] ) ) );
}
}

/**
* Save Data Unknown Address.
*
* @param int $order_id Order ID.
*
* @return void
*/
public function save_date_unknown_address( int $order_id ): void {
update_post_meta( $order_id, '_unknown_address', ! empty( $_POST['unknown_address'] ) ? 'yes' : 'no' );
update_post_meta( $order_id, '_photo_to_email_address', ! empty( $_POST['photo_to_email_address'] ) ? 'yes' : 'no' );

if ( ! empty( $_POST['receiver_phone'] ) ) {
update_post_meta( $order_id, '_receiver_phone', sanitize_text_field( wp_unslash( $_POST['receiver_phone'] ) ) );
}
}

/**
* Show Not VAT in Order.
*
* @param WC_Order $order WooCommerce Order class.
*
* @return void
*/
public function show_not_vat_in_order( WC_Order $order ): void {
$not_vat = get_post_meta( $order->get_id(), '_not_vat', true );
$company_name = get_post_meta( $order->get_id(), '_company_name', true );
$company_address = get_post_meta( $order->get_id(), '_company_address', true );
$company_nip = get_post_meta( $order->get_id(), '_company_nip', true );

if ( $not_vat === 'yes' ) {
echo '<p>' . __( 'Invoice (not VAT)', 'flatsome' ) . ': ✔</p>';
if ( $company_name ) {
echo '<p>' . __( 'Company Name', 'flatsome' ) . ': ' . esc_html( $company_name ) . '</p>';
}

if ( $company_address ) {
echo '<p>' . __( 'Company Address', 'flatsome' ) . ': ' . esc_html( $company_address ) . '</p>';
}

if ( $company_nip ) {
echo '<p>' . __( 'Company NIP', 'flatsome' ) . ': ' . esc_html( $company_nip ) . '</p>';
}
}
}

/**
* Show Unknown Address in Order.
*
* @param WC_Order $order WooCommerce Order class.
*
* @return void
*/
public function show_unknown_address_in_order( WC_Order $order ): void {
$unknown_address = get_post_meta( $order->get_id(), '_unknown_address', true );
$receiver_phone = get_post_meta( $order->get_id(), '_receiver_phone', true );
$photo_to_email_address = get_post_meta( $order->get_id(), '_photo_to_email_address', true );

if ( $unknown_address === 'yes' ) {
echo '<p>' . __( 'I don\'t know the recipient\'s address', 'flatsome' ) . ': ✔</p>';
if ( $receiver_phone ) {
echo '<p>' . __( 'Phone of the recipient', 'flatsome' ) . ': ' . esc_html( $receiver_phone ) . '</p>';
}
}

if ( 'yes' === $photo_to_email_address ) {
echo '<p>' . __( 'I want to receive a photo of the bouquet by e-mail ', 'flatsome' ) . ': ✔</p>';
}
}

/**
* Set invoice number.
*
* @return void
*/
public function set_invoice_number(): void {
$invoice_number = (int) get_transient( 'fl_invoice_number' );

if ( ! empty( $invoice_number ) ) {
$invoice_number ++;
set_transient( 'fl_invoice_number', $invoice_number, MONTH_IN_SECONDS );
}
}

/**
* Add phone shipping address
*
* @param array $fields
*
* @return array
*/
public function add_phone_shipping_address( array $fields ): array {
$fields['shipping_phone_number'] = [
'label' => __( 'Recipient\'s phone', 'flatsome' ),
'placeholder' => __( 'Enter the recipient\'s phone', 'flatsome' ),
'required' => true,
'class' => [ 'form-row-wide' ],
'clear' => true,
];

return $fields;
}

/**
* Save phone shipping address.
*
* @param int $order_id Order ID.
*
* @return void
*/
public function save_phone_shipping_address( int $order_id ): void {
if ( ! empty( $_POST['shipping_phone_number'] ) ) {
update_post_meta( $order_id, '_shipping_phone_number', sanitize_text_field( $_POST['shipping_phone_number'] ) );
}
}

/**
* Display phone shipping address.
*
* @param WC_Order $order WooCommerce Order class.
*
* @return void
*/
public function display_phone_shipping_address( $order ) {
$custom_field = get_post_meta( $order->get_id(), '_shipping_phone_number', true );
if ( $custom_field ) {
echo '<p>' . __( 'Recipient\'s phone:', 'flatsome' ) . ' ' . esc_html( $custom_field ) . '</p>';
}
}
}

April 22, 2025 at 11:08 am #16954715

Dražen
Supporter

Languages: English (English )

Timezone: Europe/Zagreb (GMT+02:00)

Hello,

thanks, so as I can see, you are editingthe Flatsome child theme and adding custom code/string there.

1) Does the issue happen with only WPML plugins and WooCommerce, all other disabled?

2) Are you adding any other custom code to your child theme?

3) If the issue still happens after step 1, can you please go to the next test site and try to reproduce the same issue. Share steps with me what have you done.

I suspect issue is with custom code, but since we can not support custom code / solutions I am trying to see the issue in example / minimal test site, so I can easily consult with our 2nd tier.

- hidden link

Let me know how it goes.

Regards,
Drazen

April 22, 2025 at 11:33 am #16955002

ielyzavetaS

Hello Drazen,

Thanks for getting back to me.

1. Plugin Deactivation:
Due to the complexity of our site and the fact that everything else — including WooCommerce, YayMail, and other plugins — functions correctly, we're unable to deactivate all plugins. The issue seems to be isolated to WPML not applying translations when the strings are inserted via hooks in WooCommerce email templates.

2. Custom Code:
Yes, we are using some custom code in the child theme to extend functionality not available out of the box. However, the strings are wrapped in `__()` with the correct text domain and show up correctly in the WPML String Translation interface. The issue is not with them registering — it’s that WPML doesn’t apply the translations in this context.

3. Sandbox Testing:
I understand the need for a minimal test case. However, since this is a custom WooCommerce/YayMail integration that reproduces fine on our live site, could you please confirm if WPML supports translation of strings added via `woocommerce_email_before_order_table` hooks? If so, we’ll do our best to replicate it on the sandbox.

4. Environment Details:
Here are our current environment details for reference:

- WordPress version: 6.7.2
- Active theme: Flatsome (3.19.10)
- WooCommerce version: 9.7.0
- PHP version: 8.3.11
- YayMail Pro (email builder)
- WPML Multilingual CMS (all updated to latest version)

Let me know how you'd like us to proceed regarding the hook behavior — happy to test further if needed.

Kind regards,
Elizabeth

April 22, 2025 at 12:48 pm #16955315

Dražen
Supporter

Languages: English (English )

Timezone: Europe/Zagreb (GMT+02:00)

Hello Elizabeth,

1) I know, but we need to confirm if issue is related to only WooCommerce or any other plugin or your website specifically, so that is one way to move forward with debugging the issue.

3) I think it should support. What you can try is add a string as in our example docs, see if that translates and if yes adjust your current code with same.

<p><?php printf( _e( 'CUSTOM TEXT', 'woocommerce' ); ?></p>

- https://wpml.org/documentation/related-projects/woocommerce-multilingual/how-to-translate-woocommerce-emails/

If nothing helps, then the best and quickest would be to move with a sandbox test website, reproduce the case, and then I can consult further on this with our 2nd tier.

Regards,
Drazen

April 26, 2025 at 7:56 am #16970413

ielyzavetaS

Hello Drazen,

Thank you for your pieces of advice.
This is helped:

<?php printf( _e(

The ticket can be closed.

BR,
Elizabeth