Commit 65832200a5d for woocommerce
commit 65832200a5d112390554316e987692d89b31dc6a
Author: Pavel Dohnal <pavel.dohnal@automattic.com>
Date: Tue Mar 31 13:06:11 2026 +0200
Fix RTL text alignment in email order details table headers (#63921)
diff --git a/plugins/woocommerce/changelog/fix-rtl-email-order-details-alignment b/plugins/woocommerce/changelog/fix-rtl-email-order-details-alignment
new file mode 100644
index 00000000000..465239a58b3
--- /dev/null
+++ b/plugins/woocommerce/changelog/fix-rtl-email-order-details-alignment
@@ -0,0 +1,4 @@
+Significance: patch
+Type: fix
+
+Fix RTL text alignment in email order details table headers by replacing inline styles with RTL-aware CSS classes.
diff --git a/plugins/woocommerce/templates/emails/email-order-details.php b/plugins/woocommerce/templates/emails/email-order-details.php
index 127199fad62..9f27979a4a3 100644
--- a/plugins/woocommerce/templates/emails/email-order-details.php
+++ b/plugins/woocommerce/templates/emails/email-order-details.php
@@ -12,15 +12,13 @@
*
* @see https://woocommerce.com/document/template-structure/
* @package WooCommerce\Templates\Emails
- * @version 10.7.0
+ * @version 10.8.0
*/
use Automattic\WooCommerce\Utilities\FeaturesUtil;
defined( 'ABSPATH' ) || exit;
-$text_align = is_rtl() ? 'right' : 'left';
-
$email_improvements_enabled = FeaturesUtil::feature_is_enabled( 'email_improvements' );
$block_email_editor_enabled = FeaturesUtil::feature_is_enabled( 'block_email_editor' );
/**
@@ -83,9 +81,9 @@ do_action( 'woocommerce_email_before_order_table', $order, $sent_to_admin, $plai
<?php if ( ! $block_email_editor_enabled ) : ?>
<thead>
<tr>
- <th class="td" scope="col" style="text-align:<?php echo esc_attr( $text_align ); ?>;"><?php esc_html_e( 'Product', 'woocommerce' ); ?></th>
- <th class="td" scope="col" style="text-align:<?php echo esc_attr( $order_quantity_text_align ); ?>;"><?php esc_html_e( 'Quantity', 'woocommerce' ); ?></th>
- <th class="td" scope="col" style="text-align:<?php echo esc_attr( $order_total_text_align ); ?>;"><?php esc_html_e( 'Price', 'woocommerce' ); ?></th>
+ <th class="td text-align-left" scope="col"><?php esc_html_e( 'Product', 'woocommerce' ); ?></th>
+ <th class="td text-align-<?php echo esc_attr( $order_quantity_text_align ); ?>" scope="col"><?php esc_html_e( 'Quantity', 'woocommerce' ); ?></th>
+ <th class="td text-align-<?php echo esc_attr( $order_total_text_align ); ?>" scope="col"><?php esc_html_e( 'Price', 'woocommerce' ); ?></th>
</tr>
</thead>
<?php endif; ?>
diff --git a/plugins/woocommerce/templates/emails/email-styles.php b/plugins/woocommerce/templates/emails/email-styles.php
index 5b91470c7ba..e751982c2d8 100644
--- a/plugins/woocommerce/templates/emails/email-styles.php
+++ b/plugins/woocommerce/templates/emails/email-styles.php
@@ -12,7 +12,7 @@
*
* @see https://woocommerce.com/document/template-structure/
* @package WooCommerce\Templates\Emails
- * @version 10.7.0
+ * @version 10.8.0
*/
use Automattic\WooCommerce\Internal\Email\EmailFont;
@@ -31,7 +31,7 @@ $body = get_option( 'woocommerce_email_body_background_color' );
$base = get_option( 'woocommerce_email_base_color' );
$text = get_option( 'woocommerce_email_text_color' );
$footer_text = get_option( 'woocommerce_email_footer_text_color' );
-$header_alignment = get_option( 'woocommerce_email_header_alignment', $email_improvements_enabled ? 'left' : false );
+$header_alignment = get_option( 'woocommerce_email_header_alignment', $email_improvements_enabled ? ( is_rtl() ? 'right' : 'left' ) : false );
$logo_image_width = get_option( 'woocommerce_email_header_image_width', '120' );
$default_font = 'Helvetica';
$font_family = $email_improvements_enabled ? get_option( 'woocommerce_email_font_family', $default_font ) : $default_font;
diff --git a/plugins/woocommerce/tests/php/includes/emails/class-wc-email-order-details-rtl-test.php b/plugins/woocommerce/tests/php/includes/emails/class-wc-email-order-details-rtl-test.php
new file mode 100644
index 00000000000..0558c5078a8
--- /dev/null
+++ b/plugins/woocommerce/tests/php/includes/emails/class-wc-email-order-details-rtl-test.php
@@ -0,0 +1,91 @@
+<?php
+declare( strict_types = 1 );
+
+/**
+ * RTL support tests for `email-order-details.php` template.
+ *
+ * @covers `email-order-details.php` template
+ */
+class WC_Email_Order_Details_RTL_Test extends \WC_Unit_Test_Case {
+
+ /**
+ * Tear down after each test.
+ */
+ public function tearDown(): void {
+ parent::tearDown();
+ update_option( 'woocommerce_feature_email_improvements_enabled', 'no' );
+ $GLOBALS['wp_locale']->text_direction = 'ltr';
+ }
+
+ /**
+ * Renders the order details template and returns the HTML.
+ *
+ * @return string
+ */
+ private function render_order_details_template(): string {
+ $order = wc_create_order();
+ return wc_get_template_html(
+ 'emails/email-order-details.php',
+ array(
+ 'order' => $order,
+ 'sent_to_admin' => false,
+ 'plain_text' => false,
+ 'email' => new WC_Email(),
+ )
+ );
+ }
+
+ /**
+ * @testdox Table headers use CSS classes for alignment with email improvements enabled.
+ */
+ public function test_th_elements_use_css_classes_with_improvements(): void {
+ update_option( 'woocommerce_feature_email_improvements_enabled', 'yes' );
+
+ $content = $this->render_order_details_template();
+
+ $this->assertStringContainsString( 'class="td text-align-left" scope="col"', $content, 'Product header should use text-align-left CSS class' );
+ $this->assertStringContainsString( 'class="td text-align-right" scope="col"', $content, 'Quantity/Price headers should use text-align-right CSS class' );
+ $this->assertDoesNotMatchRegularExpression( '/<th[^>]*style="text-align:[^"]*"/', $content, 'No <th> elements should have inline text-align styles' );
+ }
+
+ /**
+ * @testdox Table headers use text-align-left CSS class when email improvements are disabled.
+ */
+ public function test_th_elements_use_text_align_left_without_improvements(): void {
+ update_option( 'woocommerce_feature_email_improvements_enabled', 'no' );
+
+ $content = $this->render_order_details_template();
+
+ $this->assertStringContainsString( 'class="td text-align-left" scope="col"', $content, 'All headers should use text-align-left CSS class when improvements disabled' );
+ $this->assertDoesNotMatchRegularExpression( '/<th[^>]*text-align-right/', $content, 'No headers should use text-align-right when improvements disabled' );
+ $this->assertDoesNotMatchRegularExpression( '/<th[^>]*style="text-align:[^"]*"/', $content, 'No <th> elements should have inline text-align styles' );
+ }
+
+ /**
+ * @testdox Table headers use correct CSS classes in RTL locale with email improvements enabled.
+ */
+ public function test_th_elements_use_css_classes_in_rtl_with_improvements(): void {
+ $GLOBALS['wp_locale']->text_direction = 'rtl';
+ update_option( 'woocommerce_feature_email_improvements_enabled', 'yes' );
+
+ $content = $this->render_order_details_template();
+
+ $this->assertStringContainsString( 'class="td text-align-left" scope="col"', $content, 'Product header should use text-align-left class in RTL (CSS handles flipping)' );
+ $this->assertStringContainsString( 'class="td text-align-right" scope="col"', $content, 'Quantity/Price headers should use text-align-right class in RTL (CSS handles flipping)' );
+ $this->assertDoesNotMatchRegularExpression( '/<th[^>]*style="text-align:[^"]*"/', $content, 'No <th> elements should have inline text-align styles in RTL' );
+ }
+
+ /**
+ * @testdox Table headers use correct CSS classes in RTL locale with email improvements disabled.
+ */
+ public function test_th_elements_use_css_classes_in_rtl_without_improvements(): void {
+ $GLOBALS['wp_locale']->text_direction = 'rtl';
+ update_option( 'woocommerce_feature_email_improvements_enabled', 'no' );
+
+ $content = $this->render_order_details_template();
+
+ $this->assertStringContainsString( 'class="td text-align-left" scope="col"', $content, 'All headers should use text-align-left class in RTL when improvements disabled' );
+ $this->assertDoesNotMatchRegularExpression( '/<th[^>]*text-align-right/', $content, 'No headers should use text-align-right in RTL when improvements disabled' );
+ $this->assertDoesNotMatchRegularExpression( '/<th[^>]*style="text-align:[^"]*"/', $content, 'No <th> elements should have inline text-align styles in RTL' );
+ }
+}