Commit b2e7345efab for woocommerce
commit b2e7345efab6fe658d235c14ffef10bb7379db08
Author: Miroslav Mitev <m1r0@users.noreply.github.com>
Date: Thu Aug 27 13:21:09 2026 +0300
Add localized thousands separators to legacy report counts (#68051)
* Format legacy report legend counts with number_format_i18n()
diff --git a/plugins/woocommerce/changelog/67978-add-localized-thousands-separators-to-legacy-report-counts b/plugins/woocommerce/changelog/67978-add-localized-thousands-separators-to-legacy-report-counts
new file mode 100644
index 00000000000..03ac6ba9484
--- /dev/null
+++ b/plugins/woocommerce/changelog/67978-add-localized-thousands-separators-to-legacy-report-counts
@@ -0,0 +1,4 @@
+Significance: minor
+Type: enhancement
+
+Format count values in the legacy Reports chart legends with locale-aware thousands separators.
diff --git a/plugins/woocommerce/includes/admin/reports/class-wc-report-coupon-usage.php b/plugins/woocommerce/includes/admin/reports/class-wc-report-coupon-usage.php
index e5e8aade6d6..4fb6d93a915 100644
--- a/plugins/woocommerce/includes/admin/reports/class-wc-report-coupon-usage.php
+++ b/plugins/woocommerce/includes/admin/reports/class-wc-report-coupon-usage.php
@@ -116,7 +116,7 @@ class WC_Report_Coupon_Usage extends WC_Admin_Report {
$legend[] = array(
/* translators: %s: coupons amount */
- 'title' => sprintf( __( '%s coupons used in total', 'woocommerce' ), '<strong>' . $total_coupons . '</strong>' ),
+ 'title' => sprintf( __( '%s coupons used in total', 'woocommerce' ), '<strong>' . number_format_i18n( $total_coupons ) . '</strong>' ),
'color' => $this->chart_colours['coupon_count'],
'highlight_series' => 0,
);
diff --git a/plugins/woocommerce/includes/admin/reports/class-wc-report-customers.php b/plugins/woocommerce/includes/admin/reports/class-wc-report-customers.php
index 42ac76f73a6..35ef5a5acde 100644
--- a/plugins/woocommerce/includes/admin/reports/class-wc-report-customers.php
+++ b/plugins/woocommerce/includes/admin/reports/class-wc-report-customers.php
@@ -41,7 +41,7 @@ class WC_Report_Customers extends WC_Admin_Report {
$legend[] = array(
/* translators: %s: signups amount */
- 'title' => sprintf( __( '%s signups in this period', 'woocommerce' ), '<strong>' . count( $this->customers ) . '</strong>' ),
+ 'title' => sprintf( __( '%s signups in this period', 'woocommerce' ), '<strong>' . number_format_i18n( count( $this->customers ) ) . '</strong>' ),
'color' => $this->chart_colours['signups'],
'highlight_series' => 2,
);
diff --git a/plugins/woocommerce/includes/admin/reports/class-wc-report-sales-by-date.php b/plugins/woocommerce/includes/admin/reports/class-wc-report-sales-by-date.php
index c7c900682bd..a6df6ac8f9c 100644
--- a/plugins/woocommerce/includes/admin/reports/class-wc-report-sales-by-date.php
+++ b/plugins/woocommerce/includes/admin/reports/class-wc-report-sales-by-date.php
@@ -523,7 +523,7 @@ class WC_Report_Sales_By_Date extends WC_Admin_Report {
'title' => sprintf(
/* translators: %s: total orders */
__( '%s orders placed', 'woocommerce' ),
- '<strong>' . $data->total_orders . '</strong>'
+ '<strong>' . number_format_i18n( absint( $data->total_orders ) ) . '</strong>'
),
'color' => $this->chart_colours['order_count'],
'highlight_series' => 1,
@@ -533,7 +533,7 @@ class WC_Report_Sales_By_Date extends WC_Admin_Report {
'title' => sprintf(
/* translators: %s: total items */
__( '%s items purchased', 'woocommerce' ),
- '<strong>' . $data->total_items . '</strong>'
+ '<strong>' . number_format_i18n( absint( $data->total_items ) ) . '</strong>'
),
'color' => $this->chart_colours['item_count'],
'highlight_series' => 0,
@@ -541,10 +541,10 @@ class WC_Report_Sales_By_Date extends WC_Admin_Report {
$legend[] = array(
'title' => sprintf(
/* translators: 1: total refunds 2: total refunded orders 3: refunded items */
- _n( '%1$s refunded %2$d order (%3$d item)', '%1$s refunded %2$d orders (%3$d items)', $this->report_data->total_refunded_orders, 'woocommerce' ),
+ _n( '%1$s refunded %2$s order (%3$s item)', '%1$s refunded %2$s orders (%3$s items)', $this->report_data->total_refunded_orders, 'woocommerce' ),
'<strong>' . wc_price( $data->total_refunds ) . '</strong>',
- $this->report_data->total_refunded_orders,
- $this->report_data->refunded_order_items
+ number_format_i18n( absint( $this->report_data->total_refunded_orders ) ),
+ number_format_i18n( absint( $this->report_data->refunded_order_items ) )
),
'color' => $this->chart_colours['refund_amount'],
'highlight_series' => 8,
diff --git a/plugins/woocommerce/includes/admin/reports/class-wc-report-sales-by-product.php b/plugins/woocommerce/includes/admin/reports/class-wc-report-sales-by-product.php
index a365dd78f60..14ac4cb0d7b 100644
--- a/plugins/woocommerce/includes/admin/reports/class-wc-report-sales-by-product.php
+++ b/plugins/woocommerce/includes/admin/reports/class-wc-report-sales-by-product.php
@@ -127,7 +127,7 @@ class WC_Report_Sales_By_Product extends WC_Admin_Report {
$legend[] = array(
/* translators: %s: total items purchased */
- 'title' => sprintf( __( '%s purchases for the selected items', 'woocommerce' ), '<strong>' . ( $total_items ) . '</strong>' ),
+ 'title' => sprintf( __( '%s purchases for the selected items', 'woocommerce' ), '<strong>' . number_format_i18n( $total_items ) . '</strong>' ),
'color' => $this->chart_colours['item_count'],
'highlight_series' => 0,
);
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/admin/reports/class-wc-tests-report-customers.php b/plugins/woocommerce/tests/legacy/unit-tests/admin/reports/class-wc-tests-report-customers.php
new file mode 100644
index 00000000000..af381ec042b
--- /dev/null
+++ b/plugins/woocommerce/tests/legacy/unit-tests/admin/reports/class-wc-tests-report-customers.php
@@ -0,0 +1,63 @@
+<?php
+/**
+ * Class WC_Tests_Report_Customers file.
+ *
+ * @package WooCommerce\Tests\Admin\Reports
+ */
+
+declare(strict_types=1);
+
+/**
+ * Tests for the WC_Report_Customers class.
+ */
+class WC_Tests_Report_Customers extends WC_Unit_Test_Case {
+
+ /**
+ * Thousands separator to restore after a test overrides it.
+ *
+ * @var string|null
+ */
+ private $original_thousands_sep = null;
+
+ /**
+ * Load the necessary files, as they're not automatically loaded by WooCommerce.
+ */
+ public static function setUpBeforeClass(): void {
+ parent::setUpBeforeClass();
+
+ include_once WC_Unit_Tests_Bootstrap::instance()->plugin_dir . '/includes/admin/reports/class-wc-admin-report.php';
+ include_once WC_Unit_Tests_Bootstrap::instance()->plugin_dir . '/includes/admin/reports/class-wc-report-customers.php';
+ }
+
+ /**
+ * Tear down the test.
+ */
+ public function tearDown(): void {
+ global $wp_locale;
+
+ if ( null !== $this->original_thousands_sep ) {
+ $wp_locale->number_format['thousands_sep'] = $this->original_thousands_sep;
+ $this->original_thousands_sep = null;
+ }
+
+ parent::tearDown();
+ }
+
+ /**
+ * @testdox Should format the signup count with the locale thousands separator.
+ */
+ public function test_get_chart_legend_formats_signups_with_locale_separator() {
+ global $wp_locale;
+
+ $this->original_thousands_sep = $wp_locale->number_format['thousands_sep'];
+ $wp_locale->number_format['thousands_sep'] = '.';
+
+ $report = new WC_Report_Customers();
+ $report->customers = array_fill( 0, 1500, 0 );
+ $report->chart_colours = array( 'signups' => '#000000' );
+
+ $legend = implode( ' ', wp_list_pluck( $report->get_chart_legend(), 'title' ) );
+
+ $this->assertStringContainsString( '<strong>1.500</strong> signups in this period', $legend );
+ }
+}
diff --git a/plugins/woocommerce/tests/legacy/unit-tests/admin/reports/class-wc-tests-report-sales-by-date.php b/plugins/woocommerce/tests/legacy/unit-tests/admin/reports/class-wc-tests-report-sales-by-date.php
index b871119e446..569eed535c4 100644
--- a/plugins/woocommerce/tests/legacy/unit-tests/admin/reports/class-wc-tests-report-sales-by-date.php
+++ b/plugins/woocommerce/tests/legacy/unit-tests/admin/reports/class-wc-tests-report-sales-by-date.php
@@ -12,6 +12,20 @@ use Automattic\WooCommerce\Enums\OrderStatus;
*/
class WC_Tests_Report_Sales_By_Date extends WC_Unit_Test_Case {
+ /**
+ * Thousands separator to restore after a test overrides it.
+ *
+ * @var string|null
+ */
+ private $original_thousands_sep = null;
+
+ /**
+ * Counts to give the report through the woocommerce_admin_report_data filter.
+ *
+ * @var array
+ */
+ private $report_counts = array();
+
/**
* Load the necessary files, as they're not automatically loaded by WooCommerce.
*/
@@ -23,13 +37,17 @@ class WC_Tests_Report_Sales_By_Date extends WC_Unit_Test_Case {
}
/**
- * Set up the test.
+ * Tear down the test.
*/
- public function setUp(): void {
- parent::setUp();
- if ( \Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled() ) {
- $this->markTestSkipped( 'This test is not compatible with the custom orders table.' );
+ public function tearDown(): void {
+ global $wp_locale;
+
+ if ( null !== $this->original_thousands_sep ) {
+ $wp_locale->number_format['thousands_sep'] = $this->original_thousands_sep;
+ $this->original_thousands_sep = null;
}
+
+ parent::tearDown();
}
/**
@@ -45,6 +63,10 @@ class WC_Tests_Report_Sales_By_Date extends WC_Unit_Test_Case {
* Test: get_report_data
*/
public function test_get_report_data() {
+ if ( \Automattic\WooCommerce\Utilities\OrderUtil::custom_orders_table_usage_is_enabled() ) {
+ $this->markTestSkipped( 'This test is not compatible with the custom orders table.' );
+ }
+
update_option( 'woocommerce_default_customer_address', 'base' );
update_option( 'woocommerce_tax_based_on', 'base' );
update_option( 'woocommerce_calc_taxes', 'yes' );
@@ -159,4 +181,90 @@ class WC_Tests_Report_Sales_By_Date extends WC_Unit_Test_Case {
$this->assertEquals( 0, $data->total_shipping_tax_refunded );
$this->assertEquals( 0, $data->total_refunded_orders );
}
+
+ /**
+ * @testdox Should format chart legend counts with the locale thousands separator.
+ *
+ * @dataProvider provide_legend_counts
+ *
+ * @param array $counts Counts to give the report.
+ * @param string[] $expected Strings the legend should contain.
+ */
+ public function test_get_chart_legend_formats_counts_with_locale_separator( $counts, $expected ) {
+ global $wp_locale;
+
+ $this->original_thousands_sep = $wp_locale->number_format['thousands_sep'];
+ $wp_locale->number_format['thousands_sep'] = '.';
+
+ $this->report_counts = $counts;
+ add_filter( 'woocommerce_admin_report_data', array( $this, 'set_report_counts' ) );
+
+ $report = new WC_Report_Sales_By_Date();
+ $report->chart_colours = array_fill_keys(
+ array( 'sales_amount', 'average', 'net_sales_amount', 'net_average', 'order_count', 'item_count', 'refund_amount', 'shipping_amount', 'coupon_amount' ),
+ '#000000'
+ );
+ $report->start_date = strtotime( '-1 month' );
+ $report->end_date = time();
+ $report->chart_groupby = 'day';
+ $report->group_by_query = 'YEAR(posts.post_date), MONTH(posts.post_date), DAY(posts.post_date)';
+
+ $legend = implode( ' ', wp_list_pluck( $report->get_chart_legend(), 'title' ) );
+
+ foreach ( $expected as $needle ) {
+ $this->assertStringContainsString( $needle, $legend, 'Legend counts should use the locale thousands separator.' );
+ }
+ }
+
+ /**
+ * Counts to render the legend with, and the strings they should produce.
+ *
+ * The refund line is a _n() string, so it needs a case for each form.
+ *
+ * @return array[]
+ */
+ public function provide_legend_counts() {
+ return array(
+ 'plural refunds' => array(
+ array(
+ 'total_orders' => 12345,
+ 'total_items' => 67890,
+ 'total_refunded_orders' => 1234,
+ 'refunded_order_items' => 5678,
+ ),
+ array(
+ '<strong>12.345</strong> orders placed',
+ '<strong>67.890</strong> items purchased',
+ 'refunded 1.234 orders (5.678 items)',
+ ),
+ ),
+ 'singular refund' => array(
+ array(
+ 'total_orders' => 1000,
+ 'total_items' => 2000,
+ 'total_refunded_orders' => 1,
+ 'refunded_order_items' => 1500,
+ ),
+ array(
+ '<strong>1.000</strong> orders placed',
+ '<strong>2.000</strong> items purchased',
+ 'refunded 1 order (1.500 item)',
+ ),
+ ),
+ );
+ }
+
+ /**
+ * Give the report the counts the running test needs.
+ *
+ * @param stdClass $data Report data.
+ * @return stdClass
+ */
+ public function set_report_counts( $data ) {
+ foreach ( $this->report_counts as $key => $value ) {
+ $data->$key = $value;
+ }
+
+ return $data;
+ }
}