Skip to content

Commit a7c8b6e

Browse files
committed
Add language default label to date/time formats
1 parent 4bdcb35 commit a7c8b6e

3 files changed

Lines changed: 482 additions & 13 deletions

File tree

src/wp-admin/options-general.php

Lines changed: 58 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -486,26 +486,66 @@ class="<?php echo esc_attr( $classes_for_button ); ?>"
486486
<td>
487487
<fieldset><legend class="screen-reader-text"><span><?php echo $date_format_title; ?></span></legend>
488488
<?php
489-
/**
490-
* Filters the default date formats.
491-
*
492-
* @since 2.7.0
493-
* @since 4.0.0 Replaced the `Y/m/d` format with `Y-m-d` (ISO date standard YYYY-MM-DD).
494-
* @since 6.8.0 Added the `d.m.Y` format.
495-
*
496-
* @param string[] $default_date_formats Array of default date formats.
497-
*/
498-
$date_formats = array_unique( apply_filters( 'date_formats', array( __( 'F j, Y' ), 'Y-m-d', 'm/d/Y', 'd/m/Y', 'd.m.Y' ) ) );
489+
/**
490+
* Determine which format string is the default for the site's configured locale.
491+
*
492+
* get_locale() always returns the site locale (WPLANG option/constant).
493+
* determine_locale() returns the user locale in admin contexts.
494+
*
495+
* We briefly switch to the site locale only when the two differ and
496+
* the language pack is installed. If the switch fails (pack missing),
497+
* $site_locale_date_default stays null and no label is shown — that is
498+
* intentionally safe: we never guess.
499+
*
500+
* @since 7.1.0
501+
* @ticket 64102
502+
*/
503+
$site_locale = get_locale();
504+
$current_locale = determine_locale();
499505

500-
$custom = true;
506+
$site_locale_date_default = null;
507+
$site_locale_time_default = null;
508+
509+
if ( $site_locale === $current_locale ) {
510+
// Already running in the site locale — __() gives the correct translation.
511+
$site_locale_date_default = __( 'F j, Y' );
512+
$site_locale_time_default = __( 'g:i a' );
513+
} else {
514+
// User locale differs from site locale. switch_to_locale() returns false
515+
// when the language pack isn't installed on disk, keeping both vars null.
516+
$locale_switched = switch_to_locale( $site_locale );
517+
if ( $locale_switched ) {
518+
$site_locale_date_default = __( 'F j, Y' );
519+
$site_locale_time_default = __( 'g:i a' );
520+
restore_previous_locale();
521+
}
522+
}
523+
524+
/**
525+
* Filters the default date formats.
526+
*
527+
* @since 2.7.0
528+
* @since 4.0.0 Replaced the `Y/m/d` format with `Y-m-d` (ISO date standard YYYY-MM-DD).
529+
* @since 6.8.0 Added the `d.m.Y` format.
530+
*
531+
* @param string[] $default_date_formats Array of default date formats.
532+
*/
533+
$date_formats = array_unique( apply_filters( 'date_formats', array( __( 'F j, Y' ), 'Y-m-d', 'm/d/Y', 'd/m/Y', 'd.m.Y' ) ) );
534+
535+
$custom = true;
501536

502537
foreach ( $date_formats as $format ) {
503538
echo "\t<label><input type='radio' name='date_format' value='" . esc_attr( $format ) . "'";
504539
if ( get_option( 'date_format' ) === $format ) { // checked() uses "==" rather than "===".
505540
echo " checked='checked'";
506541
$custom = false;
507542
}
508-
echo ' /> <span class="date-time-text format-i18n">' . date_i18n( $format ) . '</span><code>' . esc_html( $format ) . "</code></label><br />\n";
543+
echo ' /> <span class="date-time-text format-i18n">' . date_i18n( $format ) . '</span><code>' . esc_html( $format ) . '</code>';
544+
if ( null !== $site_locale_date_default && $format === $site_locale_date_default ) {
545+
/* translators: Shown next to the date/time format that is the default for the site's language. */
546+
echo ' <span class="description">' . __( '(Language default)' ) . '</span>';
547+
}
548+
echo "</label><br />\n";
509549
}
510550

511551
echo '<label><input type="radio" name="date_format" id="date_format_custom_radio" value="\c\u\s\t\o\m"';
@@ -550,7 +590,12 @@ class="<?php echo esc_attr( $classes_for_button ); ?>"
550590
echo " checked='checked'";
551591
$custom = false;
552592
}
553-
echo ' /> <span class="date-time-text format-i18n">' . date_i18n( $format ) . '</span><code>' . esc_html( $format ) . "</code></label><br />\n";
593+
echo ' /> <span class="date-time-text format-i18n">' . date_i18n( $format ) . '</span><code>' . esc_html( $format ) . '</code>';
594+
if ( null !== $site_locale_time_default && $format === $site_locale_time_default ) {
595+
/* translators: Shown next to the date/time format that is the default for the site's language. */
596+
echo ' <span class="description">' . __( '(Language default)' ) . '</span>';
597+
}
598+
echo "</label><br />\n";
554599
}
555600

556601
echo '<label><input type="radio" name="time_format" id="time_format_custom_radio" value="\c\u\s\t\o\m"';
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
/**
2+
* E2E tests for the "(Language default)" label on Settings > General.
3+
*
4+
* @ticket 64102
5+
*/
6+
import { test, expect } from '@wordpress/e2e-test-utils-playwright';
7+
8+
test.describe( 'Settings -> General: Date/Time format language default label', () => {
9+
test.beforeEach( async ( { admin } ) => {
10+
await admin.visitAdminPage( '/options-general.php' );
11+
} );
12+
13+
test( 'Shows "(Language default)" label next to exactly one date format option', async ( { page } ) => {
14+
const labels = page.locator( 'input[name="date_format"] ~ .description' );
15+
await expect( labels.filter( { hasText: 'Language default' } ) ).toHaveCount( 1 );
16+
} );
17+
18+
test( 'Shows "(Language default)" label next to exactly one time format option', async ( { page } ) => {
19+
const labels = page.locator( 'input[name="time_format"] ~ .description' );
20+
await expect( labels.filter( { hasText: 'Language default' } ) ).toHaveCount( 1 );
21+
} );
22+
23+
test( 'Date format preview text is not affected by the language default label', async ( { page } ) => {
24+
// Click the first (non-custom) date format radio.
25+
await page.locator( 'input[name="date_format"]' ).first().click();
26+
// The .example span should not include the label text.
27+
await expect( page.locator( 'fieldset:has(input[name="date_format"]) .example' ) ).not.toContainText( 'Language default' );
28+
} );
29+
30+
test( 'Time format preview text is not affected by the language default label', async ( { page } ) => {
31+
await page.locator( 'input[name="time_format"]' ).first().click();
32+
await expect( page.locator( 'fieldset:has(input[name="time_format"]) .example' ) ).not.toContainText( 'Language default' );
33+
} );
34+
35+
test( 'Language default label is not inside the .format-i18n span', async ( { page } ) => {
36+
const formatI18nSpans = page.locator( '.format-i18n' );
37+
const count = await formatI18nSpans.count();
38+
for ( let i = 0; i < count; i++ ) {
39+
await expect( formatI18nSpans.nth( i ) ).not.toContainText( 'Language default' );
40+
}
41+
} );
42+
} );

0 commit comments

Comments
 (0)