• Resolved mystertaran

    (@mystertaran)


    For the past few days I have been trying to deal with the problem of translating emails. I have the following plugins installed: WooCommerce, WooCoomerce wFirma (it is for invoices, receipt and finances), Polylang for WooCommerce, WooCommerce Multilingual & Multicurrency, WPML for Polylang and Loco Translate. All email templates from WooCommerce -> Settings -> Email are in English (title, header and content in PHP), in addition, in the Email tab I also have emails from the wFirma plugin, which look more or less like this:

    <?php do_action( 'woocommerce_email_header', $email_heading, $email ); ?>
    
    <b><?php printf( __('Please find attached an invoice for your order %s.', 'woocommerce-wfirma'), $order->get_order_number() ); ?></b><br/><br/>
    <?php
    if( isset( $download_url ) ) {
    	printf( __('Receipt for order: <a href="%s"><b>Download PDF.</b></a>', 'woocommerce-wfirma'), $download_url );
    	echo '<br/><br/>';
    } ?>
    <h2><?php echo __( 'Order #', 'woocommerce' ) . $order->get_order_number(); ?> (<?php printf( '<time datetime="%s">%s</time>', date_i18n( 'c', strtotime( $order->get_date_created() ) ), date_i18n( wc_date_format(), strtotime( $order->get_date_created() ) ) ); ?>)</h2>
    
    <table cellspacing="0" cellpadding="6" style="width: 100%; border: 1px solid #eee;" border="1" bordercolor="#eee">
    	<thead>
    	<tr>
    		<th scope="col" style="text-align:left; border: 1px solid #eee;"><?php _e( 'Product', 'woocommerce' ); ?></th>
    		<th scope="col" style="text-align:left; border: 1px solid #eee;"><?php _e( 'Quantity', 'woocommerce' ); ?></th>
    		<th scope="col" style="text-align:left; border: 1px solid #eee;"><?php _e( 'Price', 'woocommerce' ); ?></th>
    	</tr>
    	</thead>
    	<tbody>
    	<?php
    	switch ( $order->get_status() ) {
    		case "completed" :
    			if ( version_compare( WC_VERSION, '3.0', '<' ) ) {
    				echo $order->email_order_items_table(array());
    			}
    			else {
    				echo wc_get_email_order_items( $order);
    			}
    			break;
    		case "processing" :
    			if ( version_compare( WC_VERSION, '3.0', '<' ) ) {
    				echo $order->email_order_items_table(array());
    			}
    			else {
    				echo wc_get_email_order_items( $order);
    			}
    			break;
    		default :
    			if ( version_compare( WC_VERSION, '3.0', '<' ) ) {
    				echo $order->email_order_items_table(array());
    			}
    			else {
    				echo wc_get_email_order_items( $order);
    			}
    			break;
    	}
    	?>
    	</tbody>
    	<tfoot>
    	<?php
    	if ( $totals = $order->get_order_item_totals() ) {
    		$i = 0;
    		foreach ( $totals as $total ) {
    			$i++;
    			?><tr>
    			<th scope="row" colspan="2" style="text-align:left; border: 1px solid #eee; <?php if ( $i == 1 ) echo 'border-top-width: 4px;'; ?>"><?php echo $total['label']; ?></th>
    			<td style="text-align:left; border: 1px solid #eee; <?php if ( $i == 1 ) echo 'border-top-width: 4px;'; ?>"><?php echo $total['value']; ?></td>
    			</tr><?php
    		}
    	}
    	?>
    	</tfoot>
    </table>
    
    <?php do_action( 'woocommerce_email_after_order_table', $order, $sent_to_admin, $plain_text, $email ); ?>
    
    <?php do_action( 'woocommerce_email_order_meta', $order, $sent_to_admin, $plain_text, $email ) ?>
    
    <h2><?php _e( 'Customer details', 'woocommerce' ); ?></h2>
    
    <?php if ( $order->get_billing_email() ) : ?>
    	<p><strong><?php _e( 'Email:', 'woocommerce' ); ?></strong> <?php echo $order->get_billing_email(); ?></p>
    <?php endif; ?>
    <?php if ( $order->get_billing_phone() ) : ?>
    	<p><strong><?php _e( 'Tel:', 'woocommerce' ); ?></strong> <?php echo $order->get_billing_phone(); ?></p>
    <?php endif; ?>
    
    <?php wc_get_template( 'emails/email-addresses.php', array( 'order' => $order ) ); ?>
    
    <?php do_action( 'woocommerce_email_footer' ); ?>

    In the standard they were in Polish, but I changed them to English everywhere. In addition, I used Loco Translate to translate everything that can be used in these emails (on the Woo and wFirma side). In the WordPress settings, I set the default language as English (UK).

    The problem is that when a user enters the homepage, selects a language (Polish or English) and makes a purchase, I get an email in the appropriate language, while each subsequent one, e.g. from wFirma, is only in English (including the email title), and each subsequent one from WooCommerce has only the email title, header translated, while the content is in English.

    Has anyone encountered this problem before and knows where to look for the cause?

    The page I need help with: [log in to see the link]

Viewing 6 replies - 1 through 6 (of 6 total)
  • Plugin Support Chrystl

    (@chrystl)

    Hello,

    You mention that you are using our premuim addon Polylang for WooCommerce. We are not allowed to support Premium plugin in this forum. Please contact the helpdesk: https://polylang.pro/support/, don’t forget to add your license key to your support request.

    User

    (@lostguybrazil)

    Hi @mystertaran did you solve this issue?

    Thread Starter mystertaran

    (@mystertaran)

    hi @lostguybrazil . Unfortunetly not, my customer decide to switch from Woo to Shopify.

    User

    (@lostguybrazil)

    Hi @mystertaran, I tried to solve this issue today with the following code. Unfortunately it did not work.

    // WooCommerce - Order email notifications language set based on order using Polylang
    // Last update: 2024-08-27


    if (class_exists('WooCommerce') && WC() && class_exists('Polylang')) {

    add_action($hook_name = 'woocommerce_email_header', $callback = 'set_email_language_based_on_order', $priority = 10, $accepted_args = 2);

    function set_email_language_based_on_order($email_heading, $email)
    {
    // Ensure it's an order-related email
    if (isset($email->object) && is_a($email->object, 'WC_Order')) {
    $order = $email->object;
    $order_language = pll_get_post_language($order->get_id());
    $current_language = pll_current_language(); // Get the current language

    if ($order_language && $order_language !== $current_language) {
    // Switch language if it's different from the current language
    pll_switch_language($order_language);
    }
    }
    }

    add_action($hook_name = 'woocommerce_email_footer', $callback = 'restore_language_after_email', $priority = 10, $accepted_args = 1);

    function restore_language_after_email($email)
    {
    // Restore the language to the default or previously active language
    pll_restore_previous_language();
    }
    }
    User

    (@lostguybrazil)

    Hi @mystertaran, I have solved this issue.

    I retrieve the language in which the order was placed in Polylang (pll_get_post_language($order->get_id(), 'slug')) and then I temporary switch the locale (switch_to_locale($order_locale)) so that the email is send in the correct language. It’s similar to the approach described in the Polylang documentation.

    Please find the code below – the // Check if the object is a Shipment or Invoice from Germanized for WooCommerce part can be removed as it’s specific for the Germanized for WooCommerce plugin.

    <?php

    // WooCommerce - Order email notifications language set based on order using Polylang
    // Last update: 2024-08-29


    // To prevent issues where simultaneous purchases by different users in different languages might result in email notifications being sent in the wrong language, the code avoids using global variables. Instead, it handles locale switching in an isolated manner for each request.


    if (class_exists('WooCommerce') && WC() && class_exists('Polylang')) {

    class WC_Email_Locale_Handler
    {
    public function __construct()
    {
    // Hook into the email header to switch locale before email content
    add_action($hook_name = 'woocommerce_email_header', $callback = [$this, 'set_email_locale_based_on_order'], $priority = 10, $accepted_args = 2);

    // Hook into the email footer to restore the original locale after email content
    add_action($hook_name = 'woocommerce_email_footer', $callback = [$this, 'restore_email_locale'], $priority = 10, $accepted_args = 1);

    // Hook into resending emails to handle locale switching
    add_action($hook_name = 'woocommerce_before_resend_order_emails', $callback = [$this, 'set_locale_before_resending_email'], $priority = 10, $accepted_args = 1);
    }

    public function set_email_locale_based_on_order($email_heading, $email)
    {
    if (isset($email->object)) {
    // Get the language locale of the order
    $order_locale = $this->get_locale_from_object($email->object);

    if ($order_locale) {
    // Switch to the order's locale
    switch_to_locale($order_locale);
    }
    }
    }

    public function restore_email_locale()
    {
    restore_previous_locale();
    }

    public function set_locale_before_resending_email($order)
    {
    if ($order) {
    // Get the language locale of the order
    $order_locale = $this->get_locale_from_object($order);

    if ($order_locale) {
    // Switch to the order's locale
    switch_to_locale($order_locale);
    }
    }
    }

    private function map_language_to_locale($language_slug)
    {
    // Define a mapping of language slugs to locale codes
    $mapping = array(
    'de' => 'de_DE',
    'en' => 'en_US',
    'pt' => 'pt_BR',
    // Add more languages as needed
    );

    return isset($mapping[$language_slug]) ? $mapping[$language_slug] : false;
    }

    private function get_locale_from_object($object)
    {
    $order = null;

    // Check if the object is a WC_Order
    if (is_a($object, 'WC_Order')) {
    $order = $object;
    }

    // Check if the object is a Shipment or Invoice from Germanized for WooCommerce
    elseif (is_a($object, 'Vendidero\Germanized\Shipments\Shipment') || is_a($object, 'Vendidero\StoreaBill\Invoice\Invoice')) {
    $order = $object->get_order();
    }

    if ($order && function_exists('pll_get_post_language')) {
    // Get the language slug of the order
    $order_language = pll_get_post_language($order->get_id(), 'slug');

    // Map the language slug to a locale code
    return $this->map_language_to_locale($order_language);
    }

    return null;
    }
    }

    // Initialize the handler class
    new WC_Email_Locale_Handler();
    }
    User

    (@lostguybrazil)

    I had to make some changes to work also with the email subject and email content heading. For reference, the updated code can be found here: https://stackoverflow.com/a/79002683/9195104

Viewing 6 replies - 1 through 6 (of 6 total)
  • You must be logged in to reply to this topic.