MDL-83412 core: Use LLL/LLLL for standalone Month names

We currently use MMM and MMMM which mean 'month in year', however in
some locales this is context-specific and should only be used in
conjunction with a day, for example "10 October 2024".

LLL and LLLL are for "stand-alone on the in year" and should be used
when a month is used without a day.
This commit is contained in:
Andrew Nicols
2024-11-28 11:55:25 +08:00
committed by Jun Pataleta
parent 505987af6c
commit 213b37077c
2 changed files with 110 additions and 5 deletions
+19 -5
View File
@@ -741,13 +741,14 @@ class core_date {
$intl_formats = [
'%a' => 'EEE', // An abbreviated textual representation of the day Sun through Sat
'%A' => 'EEEE', // A full textual representation of the day Sunday through Saturday
'%b' => 'MMM', // Abbreviated month name, based on the locale Jan through Dec
'%B' => 'MMMM', // Full month name, based on the locale January through December
'%h' => 'MMM', // Abbreviated month name, based on the locale (an alias of %b) Jan through Dec
];
$intl_formatter = function (DateTimeInterface $timestamp, string $format) use ($intl_formats, $locale) {
$originalformat = $format;
$intl_formatter = function (DateTimeInterface $timestamp, string $format) use (
$intl_formats,
$locale,
$originalformat,
) {
// Map IANA timezone DB names (used by PHP) to those used internally by the "intl" extension. The extension uses its
// own data based on ICU timezones, which may not necessarily be in-sync with IANA depending on the version installed
// on the local system. See: https://unicode-org.github.io/icu/userguide/datetime/timezone/#updating-the-time-zone-data
@@ -789,6 +790,19 @@ class core_date {
$time_type = IntlDateFormatter::MEDIUM;
break;
case "%B":
case "%b":
case "%h":
// Check for any day (%d, or %e) in the string.
if (preg_match('/%[de]/', $originalformat)) {
// The day is present so use the standard format.
$pattern = $format === '%B' ? 'MMMM' : 'MMM';
} else {
// The day is not present so use the stand-alone format.
$pattern = $format === '%B' ? 'LLLL' : 'LLL';
}
break;
default:
$pattern = $intl_formats[$format];
}
+91
View File
@@ -627,6 +627,36 @@ class date_test extends advanced_testcase {
"%c",
"20 February 2024 at 1:09pm",
],
'Month Year only' => [
"1708405742",
"%B %Y",
"February 2024",
],
'Abbreviated Month Year only' => [
"1708405742",
"%b %Y",
"Feb 2024",
],
'DD Month Year' => [
"1708405742",
"%d %B %Y",
"20 February 2024",
],
'D Month Year' => [
"1708405742",
"%e %B %Y",
"20 February 2024",
],
'Abbreviated DD Month Year' => [
"1708405742",
"%d %b %Y",
"20 Feb 2024",
],
'Abbreviated D Month Year' => [
"1708405742",
"%e %b %Y",
"20 Feb 2024",
],
'numeric_c' => [
1708405742,
"%c",
@@ -666,4 +696,65 @@ class date_test extends advanced_testcase {
public function test_strftime(mixed $input, string $format, string $expected): void {
$this->assertEqualsIgnoringWhitespace($expected, core_date::strftime($format, $input));
}
public static function get_strftime_locale_provider(): array {
return [
'Month Year only' => [
"1728487000",
'ru_RU.UTF-8',
"%B %Y",
"октябрь 2024",
],
'DD Month Year' => [
"1728487000",
'ru_RU.UTF-8',
"%d %B %Y",
"09 октября 2024",
],
'D Month Year' => [
"1728487000",
'ru_RU.UTF-8',
"%e %B %Y",
" 9 октября 2024",
],
'Abbreviated Month Year only' => [
"1728487000",
'ru_RU.UTF-8',
"%b %Y",
"окт. 2024",
],
'Abbreviated DD Month Year' => [
"1728487000",
'ru_RU.UTF-8',
"%d %b %Y",
"09 окт. 2024",
],
'Abbreviated D Month Year' => [
"1728487000",
'ru_RU.UTF-8',
"%e %b %Y",
" 9 окт. 2024",
],
];
}
/**
* Test \core_date::strftime function with alternate languages.
*
* @dataProvider get_strftime_locale_provider
* @param mixed $input Input passed to strftime
* @param string $locale The locale
* @param string $format The date format to pass to strftime, falls back to '%c' if null
* @param string $expected The output generated by strftime
*/
public function test_strftime_locale(
mixed $input,
string $locale,
string $format,
string $expected,
): void {
$this->assertEqualsIgnoringWhitespace(
$expected,
core_date::strftime($format, $input, $locale));
}
}