Skip to content

Commit 02dfbcc

Browse files
authored
feat(ui5-date/time*): introduce translatable fallback placeholder (#11739)
Previously, when no `placeholder` was provided in our Date/Time components, the default placeholder simply displayed the `formatPattern` string (e.g., `MMM d, y`, `dd/MM/yyyy - dd/MM/yyyy`). With this change, if no `placeholder` is set, the default placeholder now displays a translatable example value in the correct `formatPattern`/`displayFormat`— using the last value of the relevant period (such as the last day of the year, last hour of the day, etc.). Examples: `e.g. 23:59:59` `e.g. Dec 31, 2025`
1 parent 55e1527 commit 02dfbcc

File tree

5 files changed

+47
-4
lines changed

5 files changed

+47
-4
lines changed

packages/main/cypress/specs/DatePicker.cy.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -849,7 +849,7 @@ describe("Date Picker Tests", () => {
849849
cy.get("[ui5-date-picker]")
850850
.as("datePicker")
851851
.ui5DatePickerGetInnerInput()
852-
.should("have.attr", "placeholder", "MMM d, y");
852+
.should("have.attr", "placeholder", "e.g. Dec 31, 2025");
853853

854854
cy.get<DatePicker>("@datePicker")
855855
.should("not.have.attr", "placeholder");

packages/main/src/DatePicker.ts

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import i18n from "@ui5/webcomponents-base/dist/decorators/i18n.js";
88
import type I18nBundle from "@ui5/webcomponents-base/dist/i18nBundle.js";
99
import type DateFormat from "@ui5/webcomponents-localization/dist/DateFormat.js";
1010
import CalendarDate from "@ui5/webcomponents-localization/dist/dates/CalendarDate.js";
11+
import UI5Date from "@ui5/webcomponents-localization/dist/dates/UI5Date.js";
1112
import modifyDateBy from "@ui5/webcomponents-localization/dist/dates/modifyDateBy.js";
1213
import getRoundedTimestamp from "@ui5/webcomponents-localization/dist/dates/getRoundedTimestamp.js";
1314
import getTodayUTCTimestamp from "@ui5/webcomponents-localization/dist/dates/getTodayUTCTimestamp.js";
@@ -38,6 +39,7 @@ import "@ui5/webcomponents-icons/dist/appointment-2.js";
3839
import {
3940
DATEPICKER_OPEN_ICON_TITLE,
4041
DATEPICKER_DATE_DESCRIPTION,
42+
DATETIME_COMPONENTS_PLACEHOLDER_PREFIX,
4143
INPUT_SUGGESTIONS_TITLE,
4244
FORM_TEXTFIELD_REQUIRED,
4345
DATEPICKER_POPOVER_ACCESSIBLE_NAME,
@@ -655,11 +657,22 @@ class DatePicker extends DateComponentBase implements IFormInputElement {
655657
return this.getFormat().oFormatOptions.pattern as string;
656658
}
657659

660+
get _lastDayOfTheYear() {
661+
const currentYear = UI5Date.getInstance().getFullYear();
662+
const lastDayOfTheYear = UI5Date.getInstance(currentYear, 11, 31, 23, 59, 59);
663+
return this.getFormat().format(lastDayOfTheYear);
664+
}
665+
658666
/**
659667
* @protected
660668
*/
661669
get _placeholder() {
662-
return this.placeholder !== undefined ? this.placeholder : this._displayFormat;
670+
if (this.placeholder) {
671+
return this.placeholder;
672+
}
673+
674+
// translatable placeholder – for example "e.g. 2025-12-31"
675+
return `${DatePicker.i18nBundle.getText(DATETIME_COMPONENTS_PLACEHOLDER_PREFIX)} ${this._lastDayOfTheYear}`;
663676
}
664677

665678
get _headerTitleText() {

packages/main/src/DateRangePicker.ts

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,13 @@ import property from "@ui5/webcomponents-base/dist/decorators/property.js";
33
import { renderFinished } from "@ui5/webcomponents-base/dist/Render.js";
44
import type { IFormInputElement } from "@ui5/webcomponents-base/dist/features/InputElementsFormSupport.js";
55
import CalendarDate from "@ui5/webcomponents-localization/dist/dates/CalendarDate.js";
6+
import UI5Date from "@ui5/webcomponents-localization/dist/dates/UI5Date.js";
67
import modifyDateBy from "@ui5/webcomponents-localization/dist/dates/modifyDateBy.js";
78
import getTodayUTCTimestamp from "@ui5/webcomponents-localization/dist/dates/getTodayUTCTimestamp.js";
89
import {
910
DATERANGE_DESCRIPTION,
1011
DATERANGEPICKER_POPOVER_ACCESSIBLE_NAME,
12+
DATETIME_COMPONENTS_PLACEHOLDER_PREFIX,
1113
} from "./generated/i18n/i18n-defaults.js";
1214
import DateRangePickerTemplate from "./DateRangePickerTemplate.js";
1315

@@ -187,11 +189,24 @@ class DateRangePicker extends DatePicker implements IFormInputElement {
187189
return this._calendarSelectedDates[1] || "";
188190
}
189191

192+
get _lastDateRangeForTheCurrentYear() {
193+
const currentYear = UI5Date.getInstance().getFullYear();
194+
const lastDayOfTheYear = UI5Date.getInstance(currentYear, 11, 31, 23, 59, 59);
195+
const sevenDaysBeforeLastDayOfYear = UI5Date.getInstance(currentYear, 11, 24, 23, 59, 59);
196+
197+
return `${this.getFormat().format(sevenDaysBeforeLastDayOfYear)} ${this._effectiveDelimiter} ${this.getFormat().format(lastDayOfTheYear)}`;
198+
}
199+
190200
/**
191201
* @override
192202
*/
193203
get _placeholder() {
194-
return this.placeholder !== undefined ? this.placeholder : `${this._displayFormat} ${this._effectiveDelimiter} ${this._displayFormat}`;
204+
if (this.placeholder) {
205+
return this.placeholder;
206+
}
207+
208+
// translatable placeholder – for example "e.g. 2025-12-27 - 2025-12-31"
209+
return `${DateRangePicker.i18nBundle.getText(DATETIME_COMPONENTS_PLACEHOLDER_PREFIX)} ${this._lastDateRangeForTheCurrentYear}`;
195210
}
196211

197212
/**

packages/main/src/TimePicker.ts

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@ import {
4545
TIMEPICKER_CANCEL_BUTTON,
4646
TIMEPICKER_INPUT_DESCRIPTION,
4747
TIMEPICKER_POPOVER_ACCESSIBLE_NAME,
48+
DATETIME_COMPONENTS_PLACEHOLDER_PREFIX,
4849
FORM_TEXTFIELD_REQUIRED,
4950
VALUE_STATE_ERROR,
5051
VALUE_STATE_INFORMATION,
@@ -374,11 +375,22 @@ class TimePicker extends UI5Element implements IFormInputElement {
374375
return this.getFormat().parse(this._effectiveValue) as Date;
375376
}
376377

378+
get _lastAvailableTime() {
379+
const date = UI5Date.getInstance();
380+
date.setHours(23, 59, 59, 999);
381+
return this.getFormat().format(date);
382+
}
383+
377384
/**
378385
* @protected
379386
*/
380387
get _placeholder() {
381-
return this.placeholder !== undefined ? this.placeholder : this._displayFormat;
388+
if (this.placeholder) {
389+
return this.placeholder;
390+
}
391+
392+
// translatable placeholder – for example "e.g. 23:59:59"
393+
return `${TimePicker.i18nBundle.getText(DATETIME_COMPONENTS_PLACEHOLDER_PREFIX)} ${this._lastAvailableTime}`;
382394
}
383395

384396
/**

packages/main/src/i18n/messagebundle.properties

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,9 @@ DATERANGE_DESCRIPTION=Date Range Input
187187
#XACT: Aria information for the Date Picker popover
188188
DATEPICKER_POPOVER_ACCESSIBLE_NAME=Choose Date
189189

190+
#XTXT: Date Picker placeholder prefix
191+
DATETIME_COMPONENTS_PLACEHOLDER_PREFIX=e.g.
192+
190193
#XACT: Aria information for the Date Time Picker popover
191194
DATETIMEPICKER_POPOVER_ACCESSIBLE_NAME=Choose Date and Time
192195

0 commit comments

Comments
 (0)