diff --git a/packages/devextreme/js/__internal/ui/calendar/m_calendar.base_view.ts b/packages/devextreme/js/__internal/ui/calendar/m_calendar.base_view.ts index 0238d2d842a4..af12441db9b4 100644 --- a/packages/devextreme/js/__internal/ui/calendar/m_calendar.base_view.ts +++ b/packages/devextreme/js/__internal/ui/calendar/m_calendar.base_view.ts @@ -138,11 +138,49 @@ const BaseView = (Widget as any).inherit({ }, _getMultipleModeAriaLabel() { - const ariaLabel = this._getLocalizedWidgetName(); + const localizedWidgetName = this._getLocalizedWidgetName(); + const selectedRangesText = this._getMultipleRangesText(); + + const ariaLabel = `${localizedWidgetName}. ${selectedRangesText}`; return ariaLabel; }, + _getMultipleRangesText() { + const { value } = this.option(); + const ranges = coreDateUtils.getRangesByDates(value.map((date) => new Date(date))); + + if (ranges.length > 2) { + // @ts-expect-error + const dateRangeCountText = messageLocalization.format('dxCalendar-selectedDateRangeCount', ranges.length); + + return dateRangeCountText; + } + + const selectedDatesText = messageLocalization.format('dxCalendar-selectedDates'); + const rangesText = ranges + .map((range) => this._getRangeText(range)) + .join(', '); + + const result = `${selectedDatesText}: ${rangesText}`; + + return result; + }, + + _getRangeText(range) { + const [startDate, endDate] = range; + + const formattedStartDate = dateLocalization.format(startDate, ARIA_LABEL_DATE_FORMAT); + const formattedEndDate = dateLocalization.format(endDate, ARIA_LABEL_DATE_FORMAT); + + const selectedDatesText = startDate && endDate + // @ts-expect-error + ? messageLocalization.format('dxCalendar-selectedMultipleDateRange', formattedStartDate, formattedEndDate) + : formattedStartDate; + + return selectedDatesText; + }, + _getTableAriaLabel() { const { value, selectionMode } = this.option(); diff --git a/packages/devextreme/js/core/utils/date.js b/packages/devextreme/js/core/utils/date.js index 7aa54270e76d..7c9dde7451c4 100644 --- a/packages/devextreme/js/core/utils/date.js +++ b/packages/devextreme/js/core/utils/date.js @@ -5,6 +5,7 @@ import { adjust } from './math'; import { each } from './iterator'; import { camelize } from './inflector'; import { toMilliseconds } from '../../renovation/ui/common/utils/date/index'; +import dateSerialization from './date_serialization'; const DAYS_IN_WEEK = 7; const THURSDAY_WEEK_NUMBER = 4; @@ -689,6 +690,37 @@ const getMachineTimezoneName = () => { : null; }; +const getRangesByDates = (dates) => { + const datesInMilliseconds = dates.map((value) => correctDateWithUnitBeginning(value, 'day').getTime()); + const sortedDates = datesInMilliseconds.sort((a, b) => a - b); + + const msInDay = toMilliseconds('day'); + const ranges = []; + + let startDate = sortedDates[0]; + + for(let i = 1; i <= sortedDates.length; ++i) { + const nextDate = sortedDates[i]; + const currentDate = sortedDates[i - 1]; + + const isNewRange = nextDate - currentDate > msInDay; + + if(isNewRange || i === sortedDates.length) { + const range = startDate === sortedDates[i - 1] + ? [startDate] + : [startDate, sortedDates[i - 1]]; + + const serializedRange = range.map((value) => dateSerialization.deserializeDate(value)); + + ranges.push(serializedRange); + + startDate = nextDate; + } + } + + return ranges; +}; + const dateUtils = { dateUnitIntervals: dateUnitIntervals, @@ -752,6 +784,8 @@ const dateUtils = { createDateWithFullYear: createDateWithFullYear, getMachineTimezoneName: getMachineTimezoneName, + + getRangesByDates: getRangesByDates, }; dateUtils.sameView = function(view, date1, date2) { diff --git a/packages/devextreme/js/localization/messages/ar.json b/packages/devextreme/js/localization/messages/ar.json index 753fad7c14b4..25f03d6cccf8 100644 --- a/packages/devextreme/js/localization/messages/ar.json +++ b/packages/devextreme/js/localization/messages/ar.json @@ -316,7 +316,10 @@ "dxCalendar-captionDecadeLabel": "Decade selection", "dxCalendar-captionCenturyLabel": "Century selection", "dxCalendar-selectedDate": "The selected date is {0}", + "dxCalendar-selectedDates": "The selected dates", "dxCalendar-selectedDateRange": "The selected date range is from {0} to {1}", + "dxCalendar-selectedMultipleDateRange": "from {0} to {1}", + "dxCalendar-selectedDateRangeCount": "There are {0} selected date ranges", "dxCalendar-readOnlyLabel": "Read-only calendar", "dxChat-emptyListMessage": "There are no messages in this chat", diff --git a/packages/devextreme/js/localization/messages/ca.json b/packages/devextreme/js/localization/messages/ca.json index b146d5465681..607dc809dc02 100644 --- a/packages/devextreme/js/localization/messages/ca.json +++ b/packages/devextreme/js/localization/messages/ca.json @@ -316,7 +316,10 @@ "dxCalendar-captionDecadeLabel": "Decade selection", "dxCalendar-captionCenturyLabel": "Century selection", "dxCalendar-selectedDate": "The selected date is {0}", + "dxCalendar-selectedDates": "The selected dates", "dxCalendar-selectedDateRange": "The selected date range is from {0} to {1}", + "dxCalendar-selectedMultipleDateRange": "from {0} to {1}", + "dxCalendar-selectedDateRangeCount": "There are {0} selected date ranges", "dxCalendar-readOnlyLabel": "Read-only calendar", "dxChat-emptyListMessage": "There are no messages in this chat", diff --git a/packages/devextreme/js/localization/messages/cs.json b/packages/devextreme/js/localization/messages/cs.json index 2405d3d02520..fa4bbcff1b95 100644 --- a/packages/devextreme/js/localization/messages/cs.json +++ b/packages/devextreme/js/localization/messages/cs.json @@ -316,7 +316,10 @@ "dxCalendar-captionDecadeLabel": "Decade selection", "dxCalendar-captionCenturyLabel": "Century selection", "dxCalendar-selectedDate": "The selected date is {0}", + "dxCalendar-selectedDates": "The selected dates", "dxCalendar-selectedDateRange": "The selected date range is from {0} to {1}", + "dxCalendar-selectedMultipleDateRange": "from {0} to {1}", + "dxCalendar-selectedDateRangeCount": "There are {0} selected date ranges", "dxCalendar-readOnlyLabel": "Read-only calendar", "dxChat-emptyListMessage": "There are no messages in this chat", diff --git a/packages/devextreme/js/localization/messages/de.json b/packages/devextreme/js/localization/messages/de.json index 0cf05aabee86..a9ada04b98f4 100644 --- a/packages/devextreme/js/localization/messages/de.json +++ b/packages/devextreme/js/localization/messages/de.json @@ -316,7 +316,10 @@ "dxCalendar-captionDecadeLabel": "Decade selection", "dxCalendar-captionCenturyLabel": "Century selection", "dxCalendar-selectedDate": "The selected date is {0}", + "dxCalendar-selectedDates": "The selected dates", "dxCalendar-selectedDateRange": "The selected date range is from {0} to {1}", + "dxCalendar-selectedMultipleDateRange": "from {0} to {1}", + "dxCalendar-selectedDateRangeCount": "There are {0} selected date ranges", "dxCalendar-readOnlyLabel": "Read-only calendar", "dxChat-emptyListMessage": "There are no messages in this chat", diff --git a/packages/devextreme/js/localization/messages/el.json b/packages/devextreme/js/localization/messages/el.json index 2c731baf352e..680c048f8d90 100644 --- a/packages/devextreme/js/localization/messages/el.json +++ b/packages/devextreme/js/localization/messages/el.json @@ -316,7 +316,10 @@ "dxCalendar-captionDecadeLabel": "Decade selection", "dxCalendar-captionCenturyLabel": "Century selection", "dxCalendar-selectedDate": "The selected date is {0}", + "dxCalendar-selectedDates": "The selected dates", "dxCalendar-selectedDateRange": "The selected date range is from {0} to {1}", + "dxCalendar-selectedMultipleDateRange": "from {0} to {1}", + "dxCalendar-selectedDateRangeCount": "There are {0} selected date ranges", "dxCalendar-readOnlyLabel": "Read-only calendar", "dxChat-emptyListMessage": "There are no messages in this chat", diff --git a/packages/devextreme/js/localization/messages/en.json b/packages/devextreme/js/localization/messages/en.json index 270bebfa79da..43391d6418e5 100644 --- a/packages/devextreme/js/localization/messages/en.json +++ b/packages/devextreme/js/localization/messages/en.json @@ -316,7 +316,10 @@ "dxCalendar-captionDecadeLabel": "Decade selection", "dxCalendar-captionCenturyLabel": "Century selection", "dxCalendar-selectedDate": "The selected date is {0}", + "dxCalendar-selectedDates": "The selected dates", "dxCalendar-selectedDateRange": "The selected date range is from {0} to {1}", + "dxCalendar-selectedMultipleDateRange": "from {0} to {1}", + "dxCalendar-selectedDateRangeCount": "There are {0} selected date ranges", "dxCalendar-readOnlyLabel": "Read-only calendar", "dxChat-emptyListMessage": "There are no messages in this chat", diff --git a/packages/devextreme/js/localization/messages/es.json b/packages/devextreme/js/localization/messages/es.json index e0a432d189f3..e4a3b2a06a5d 100644 --- a/packages/devextreme/js/localization/messages/es.json +++ b/packages/devextreme/js/localization/messages/es.json @@ -316,7 +316,10 @@ "dxCalendar-captionDecadeLabel": "Decade selection", "dxCalendar-captionCenturyLabel": "Century selection", "dxCalendar-selectedDate": "The selected date is {0}", + "dxCalendar-selectedDates": "The selected dates", "dxCalendar-selectedDateRange": "The selected date range is from {0} to {1}", + "dxCalendar-selectedMultipleDateRange": "from {0} to {1}", + "dxCalendar-selectedDateRangeCount": "There are {0} selected date ranges", "dxCalendar-readOnlyLabel": "Read-only calendar", "dxChat-emptyListMessage": "There are no messages in this chat", diff --git a/packages/devextreme/js/localization/messages/fa.json b/packages/devextreme/js/localization/messages/fa.json index e1f725fb53be..c2a653aaa1bb 100644 --- a/packages/devextreme/js/localization/messages/fa.json +++ b/packages/devextreme/js/localization/messages/fa.json @@ -316,7 +316,10 @@ "dxCalendar-captionDecadeLabel": "Decade selection", "dxCalendar-captionCenturyLabel": "Century selection", "dxCalendar-selectedDate": "The selected date is {0}", + "dxCalendar-selectedDates": "The selected dates", "dxCalendar-selectedDateRange": "The selected date range is from {0} to {1}", + "dxCalendar-selectedMultipleDateRange": "from {0} to {1}", + "dxCalendar-selectedDateRangeCount": "There are {0} selected date ranges", "dxCalendar-readOnlyLabel": "Read-only calendar", "dxChat-emptyListMessage": "There are no messages in this chat", diff --git a/packages/devextreme/js/localization/messages/fi.json b/packages/devextreme/js/localization/messages/fi.json index ed11dd9f5b5e..33f74ceac40f 100644 --- a/packages/devextreme/js/localization/messages/fi.json +++ b/packages/devextreme/js/localization/messages/fi.json @@ -316,7 +316,10 @@ "dxCalendar-captionDecadeLabel": "Decade selection", "dxCalendar-captionCenturyLabel": "Century selection", "dxCalendar-selectedDate": "The selected date is {0}", + "dxCalendar-selectedDates": "The selected dates", "dxCalendar-selectedDateRange": "The selected date range is from {0} to {1}", + "dxCalendar-selectedMultipleDateRange": "from {0} to {1}", + "dxCalendar-selectedDateRangeCount": "There are {0} selected date ranges", "dxCalendar-readOnlyLabel": "Read-only calendar", "dxChat-emptyListMessage": "There are no messages in this chat", diff --git a/packages/devextreme/js/localization/messages/fr.json b/packages/devextreme/js/localization/messages/fr.json index 09a188cc040b..b37bea59f093 100644 --- a/packages/devextreme/js/localization/messages/fr.json +++ b/packages/devextreme/js/localization/messages/fr.json @@ -316,7 +316,10 @@ "dxCalendar-captionDecadeLabel": "Decade selection", "dxCalendar-captionCenturyLabel": "Century selection", "dxCalendar-selectedDate": "The selected date is {0}", + "dxCalendar-selectedDates": "The selected dates", "dxCalendar-selectedDateRange": "The selected date range is from {0} to {1}", + "dxCalendar-selectedMultipleDateRange": "from {0} to {1}", + "dxCalendar-selectedDateRangeCount": "There are {0} selected date ranges", "dxCalendar-readOnlyLabel": "Read-only calendar", "dxChat-emptyListMessage": "There are no messages in this chat", diff --git a/packages/devextreme/js/localization/messages/hu.json b/packages/devextreme/js/localization/messages/hu.json index fdd23c370c5a..c7d74d3c58b0 100644 --- a/packages/devextreme/js/localization/messages/hu.json +++ b/packages/devextreme/js/localization/messages/hu.json @@ -316,7 +316,10 @@ "dxCalendar-captionDecadeLabel": "Decade selection", "dxCalendar-captionCenturyLabel": "Century selection", "dxCalendar-selectedDate": "The selected date is {0}", + "dxCalendar-selectedDates": "The selected dates", "dxCalendar-selectedDateRange": "The selected date range is from {0} to {1}", + "dxCalendar-selectedMultipleDateRange": "from {0} to {1}", + "dxCalendar-selectedDateRangeCount": "There are {0} selected date ranges", "dxCalendar-readOnlyLabel": "Read-only calendar", "dxChat-emptyListMessage": "There are no messages in this chat", diff --git a/packages/devextreme/js/localization/messages/it.json b/packages/devextreme/js/localization/messages/it.json index 7b7be5cfb681..d5dd66f942ee 100644 --- a/packages/devextreme/js/localization/messages/it.json +++ b/packages/devextreme/js/localization/messages/it.json @@ -316,7 +316,10 @@ "dxCalendar-captionDecadeLabel": "Decade selection", "dxCalendar-captionCenturyLabel": "Century selection", "dxCalendar-selectedDate": "The selected date is {0}", + "dxCalendar-selectedDates": "The selected dates", "dxCalendar-selectedDateRange": "The selected date range is from {0} to {1}", + "dxCalendar-selectedMultipleDateRange": "from {0} to {1}", + "dxCalendar-selectedDateRangeCount": "There are {0} selected date ranges", "dxCalendar-readOnlyLabel": "Read-only calendar", "dxChat-emptyListMessage": "There are no messages in this chat", diff --git a/packages/devextreme/js/localization/messages/ja.json b/packages/devextreme/js/localization/messages/ja.json index 85dae1cbe842..ece2ba683b2a 100644 --- a/packages/devextreme/js/localization/messages/ja.json +++ b/packages/devextreme/js/localization/messages/ja.json @@ -316,7 +316,10 @@ "dxCalendar-captionDecadeLabel": "Decade selection", "dxCalendar-captionCenturyLabel": "Century selection", "dxCalendar-selectedDate": "The selected date is {0}", + "dxCalendar-selectedDates": "The selected dates", "dxCalendar-selectedDateRange": "The selected date range is from {0} to {1}", + "dxCalendar-selectedMultipleDateRange": "from {0} to {1}", + "dxCalendar-selectedDateRangeCount": "There are {0} selected date ranges", "dxCalendar-readOnlyLabel": "Read-only calendar", "dxChat-emptyListMessage": "There are no messages in this chat", diff --git a/packages/devextreme/js/localization/messages/lt.json b/packages/devextreme/js/localization/messages/lt.json index ee5e80194864..674272cbf1c5 100644 --- a/packages/devextreme/js/localization/messages/lt.json +++ b/packages/devextreme/js/localization/messages/lt.json @@ -316,7 +316,10 @@ "dxCalendar-captionDecadeLabel": "Decade selection", "dxCalendar-captionCenturyLabel": "Century selection", "dxCalendar-selectedDate": "The selected date is {0}", + "dxCalendar-selectedDates": "The selected dates", "dxCalendar-selectedDateRange": "The selected date range is from {0} to {1}", + "dxCalendar-selectedMultipleDateRange": "from {0} to {1}", + "dxCalendar-selectedDateRangeCount": "There are {0} selected date ranges", "dxCalendar-readOnlyLabel": "Read-only calendar", "dxChat-emptyListMessage": "There are no messages in this chat", diff --git a/packages/devextreme/js/localization/messages/lv.json b/packages/devextreme/js/localization/messages/lv.json index b56dce083fa5..dc77c798e269 100644 --- a/packages/devextreme/js/localization/messages/lv.json +++ b/packages/devextreme/js/localization/messages/lv.json @@ -316,7 +316,10 @@ "dxCalendar-captionDecadeLabel": "Decade selection", "dxCalendar-captionCenturyLabel": "Century selection", "dxCalendar-selectedDate": "The selected date is {0}", + "dxCalendar-selectedDates": "The selected dates", "dxCalendar-selectedDateRange": "The selected date range is from {0} to {1}", + "dxCalendar-selectedMultipleDateRange": "from {0} to {1}", + "dxCalendar-selectedDateRangeCount": "There are {0} selected date ranges", "dxCalendar-readOnlyLabel": "Read-only calendar", "dxChat-emptyListMessage": "There are no messages in this chat", diff --git a/packages/devextreme/js/localization/messages/nb.json b/packages/devextreme/js/localization/messages/nb.json index 9e2363308a23..4fff740a80c1 100644 --- a/packages/devextreme/js/localization/messages/nb.json +++ b/packages/devextreme/js/localization/messages/nb.json @@ -316,7 +316,10 @@ "dxCalendar-captionDecadeLabel": "Decade selection", "dxCalendar-captionCenturyLabel": "Century selection", "dxCalendar-selectedDate": "The selected date is {0}", + "dxCalendar-selectedDates": "The selected dates", "dxCalendar-selectedDateRange": "The selected date range is from {0} to {1}", + "dxCalendar-selectedMultipleDateRange": "from {0} to {1}", + "dxCalendar-selectedDateRangeCount": "There are {0} selected date ranges", "dxCalendar-readOnlyLabel": "Read-only calendar", "dxChat-emptyListMessage": "There are no messages in this chat", diff --git a/packages/devextreme/js/localization/messages/nl.json b/packages/devextreme/js/localization/messages/nl.json index 2c30f6c2a789..b1f567ff64bd 100644 --- a/packages/devextreme/js/localization/messages/nl.json +++ b/packages/devextreme/js/localization/messages/nl.json @@ -316,7 +316,10 @@ "dxCalendar-captionDecadeLabel": "Decade selection", "dxCalendar-captionCenturyLabel": "Century selection", "dxCalendar-selectedDate": "The selected date is {0}", + "dxCalendar-selectedDates": "The selected dates", "dxCalendar-selectedDateRange": "The selected date range is from {0} to {1}", + "dxCalendar-selectedMultipleDateRange": "from {0} to {1}", + "dxCalendar-selectedDateRangeCount": "There are {0} selected date ranges", "dxCalendar-readOnlyLabel": "Read-only calendar", "dxChat-emptyListMessage": "There are no messages in this chat", diff --git a/packages/devextreme/js/localization/messages/pl.json b/packages/devextreme/js/localization/messages/pl.json index bbf0df0392ce..46302751dfc1 100644 --- a/packages/devextreme/js/localization/messages/pl.json +++ b/packages/devextreme/js/localization/messages/pl.json @@ -316,7 +316,10 @@ "dxCalendar-captionDecadeLabel": "Decade selection", "dxCalendar-captionCenturyLabel": "Century selection", "dxCalendar-selectedDate": "The selected date is {0}", + "dxCalendar-selectedDates": "The selected dates", "dxCalendar-selectedDateRange": "The selected date range is from {0} to {1}", + "dxCalendar-selectedMultipleDateRange": "from {0} to {1}", + "dxCalendar-selectedDateRangeCount": "There are {0} selected date ranges", "dxCalendar-readOnlyLabel": "Read-only calendar", "dxChat-emptyListMessage": "There are no messages in this chat", diff --git a/packages/devextreme/js/localization/messages/pt.json b/packages/devextreme/js/localization/messages/pt.json index 0c128f97c493..5614182d032d 100644 --- a/packages/devextreme/js/localization/messages/pt.json +++ b/packages/devextreme/js/localization/messages/pt.json @@ -316,7 +316,10 @@ "dxCalendar-captionDecadeLabel": "Decade selection", "dxCalendar-captionCenturyLabel": "Century selection", "dxCalendar-selectedDate": "The selected date is {0}", + "dxCalendar-selectedDates": "The selected dates", "dxCalendar-selectedDateRange": "The selected date range is from {0} to {1}", + "dxCalendar-selectedMultipleDateRange": "from {0} to {1}", + "dxCalendar-selectedDateRangeCount": "There are {0} selected date ranges", "dxCalendar-readOnlyLabel": "Read-only calendar", "dxChat-emptyListMessage": "There are no messages in this chat", diff --git a/packages/devextreme/js/localization/messages/ro.json b/packages/devextreme/js/localization/messages/ro.json index 984b6ee557bb..9a8fc8971b9b 100644 --- a/packages/devextreme/js/localization/messages/ro.json +++ b/packages/devextreme/js/localization/messages/ro.json @@ -316,7 +316,10 @@ "dxCalendar-captionDecadeLabel": "Decade selection", "dxCalendar-captionCenturyLabel": "Century selection", "dxCalendar-selectedDate": "The selected date is {0}", + "dxCalendar-selectedDates": "The selected dates", "dxCalendar-selectedDateRange": "The selected date range is from {0} to {1}", + "dxCalendar-selectedMultipleDateRange": "from {0} to {1}", + "dxCalendar-selectedDateRangeCount": "There are {0} selected date ranges", "dxCalendar-readOnlyLabel": "Read-only calendar", "dxChat-emptyListMessage": "There are no messages in this chat", diff --git a/packages/devextreme/js/localization/messages/ru.json b/packages/devextreme/js/localization/messages/ru.json index 979f5aab0183..45bdc2cb1b13 100644 --- a/packages/devextreme/js/localization/messages/ru.json +++ b/packages/devextreme/js/localization/messages/ru.json @@ -316,7 +316,10 @@ "dxCalendar-captionDecadeLabel": "Decade selection", "dxCalendar-captionCenturyLabel": "Century selection", "dxCalendar-selectedDate": "The selected date is {0}", + "dxCalendar-selectedDates": "The selected dates", "dxCalendar-selectedDateRange": "The selected date range is from {0} to {1}", + "dxCalendar-selectedMultipleDateRange": "from {0} to {1}", + "dxCalendar-selectedDateRangeCount": "There are {0} selected date ranges", "dxCalendar-readOnlyLabel": "Read-only calendar", "dxChat-emptyListMessage": "There are no messages in this chat", diff --git a/packages/devextreme/js/localization/messages/sl.json b/packages/devextreme/js/localization/messages/sl.json index 1f71b3c0125c..2b9fbe6d5f11 100644 --- a/packages/devextreme/js/localization/messages/sl.json +++ b/packages/devextreme/js/localization/messages/sl.json @@ -316,7 +316,10 @@ "dxCalendar-captionDecadeLabel": "Decade selection", "dxCalendar-captionCenturyLabel": "Century selection", "dxCalendar-selectedDate": "The selected date is {0}", + "dxCalendar-selectedDates": "The selected dates", "dxCalendar-selectedDateRange": "The selected date range is from {0} to {1}", + "dxCalendar-selectedMultipleDateRange": "from {0} to {1}", + "dxCalendar-selectedDateRangeCount": "There are {0} selected date ranges", "dxCalendar-readOnlyLabel": "Read-only calendar", "dxChat-emptyListMessage": "There are no messages in this chat", diff --git a/packages/devextreme/js/localization/messages/sv.json b/packages/devextreme/js/localization/messages/sv.json index ca2549af7f42..c15f92060b15 100644 --- a/packages/devextreme/js/localization/messages/sv.json +++ b/packages/devextreme/js/localization/messages/sv.json @@ -316,7 +316,10 @@ "dxCalendar-captionDecadeLabel": "Decade selection", "dxCalendar-captionCenturyLabel": "Century selection", "dxCalendar-selectedDate": "The selected date is {0}", + "dxCalendar-selectedDates": "The selected dates", "dxCalendar-selectedDateRange": "The selected date range is from {0} to {1}", + "dxCalendar-selectedMultipleDateRange": "from {0} to {1}", + "dxCalendar-selectedDateRangeCount": "There are {0} selected date ranges", "dxCalendar-readOnlyLabel": "Read-only calendar", "dxChat-emptyListMessage": "There are no messages in this chat", diff --git a/packages/devextreme/js/localization/messages/tr.json b/packages/devextreme/js/localization/messages/tr.json index 9bcfdbd0fe0e..efb859c2d609 100644 --- a/packages/devextreme/js/localization/messages/tr.json +++ b/packages/devextreme/js/localization/messages/tr.json @@ -316,7 +316,10 @@ "dxCalendar-captionDecadeLabel": "Decade selection", "dxCalendar-captionCenturyLabel": "Century selection", "dxCalendar-selectedDate": "The selected date is {0}", + "dxCalendar-selectedDates": "The selected dates", "dxCalendar-selectedDateRange": "The selected date range is from {0} to {1}", + "dxCalendar-selectedMultipleDateRange": "from {0} to {1}", + "dxCalendar-selectedDateRangeCount": "There are {0} selected date ranges", "dxCalendar-readOnlyLabel": "Read-only calendar", "dxChat-emptyListMessage": "There are no messages in this chat", diff --git a/packages/devextreme/js/localization/messages/vi.json b/packages/devextreme/js/localization/messages/vi.json index 81b046660828..4babd4ed8bc1 100644 --- a/packages/devextreme/js/localization/messages/vi.json +++ b/packages/devextreme/js/localization/messages/vi.json @@ -316,7 +316,10 @@ "dxCalendar-captionDecadeLabel": "Decade selection", "dxCalendar-captionCenturyLabel": "Century selection", "dxCalendar-selectedDate": "The selected date is {0}", + "dxCalendar-selectedDates": "The selected dates", "dxCalendar-selectedDateRange": "The selected date range is from {0} to {1}", + "dxCalendar-selectedMultipleDateRange": "from {0} to {1}", + "dxCalendar-selectedDateRangeCount": "There are {0} selected date ranges", "dxCalendar-readOnlyLabel": "Read-only calendar", "dxChat-emptyListMessage": "There are no messages in this chat", diff --git a/packages/devextreme/js/localization/messages/zh-tw.json b/packages/devextreme/js/localization/messages/zh-tw.json index f8deed2ee768..a161ece8c721 100644 --- a/packages/devextreme/js/localization/messages/zh-tw.json +++ b/packages/devextreme/js/localization/messages/zh-tw.json @@ -316,7 +316,10 @@ "dxCalendar-captionDecadeLabel": "Decade selection", "dxCalendar-captionCenturyLabel": "Century selection", "dxCalendar-selectedDate": "The selected date is {0}", + "dxCalendar-selectedDates": "The selected dates", "dxCalendar-selectedDateRange": "The selected date range is from {0} to {1}", + "dxCalendar-selectedMultipleDateRange": "from {0} to {1}", + "dxCalendar-selectedDateRangeCount": "There are {0} selected date ranges", "dxCalendar-readOnlyLabel": "Read-only calendar", "dxChat-emptyListMessage": "There are no messages in this chat", diff --git a/packages/devextreme/js/localization/messages/zh.json b/packages/devextreme/js/localization/messages/zh.json index c7f7dcd0bed9..3050a1b5fe1e 100644 --- a/packages/devextreme/js/localization/messages/zh.json +++ b/packages/devextreme/js/localization/messages/zh.json @@ -316,7 +316,10 @@ "dxCalendar-captionDecadeLabel": "Decade selection", "dxCalendar-captionCenturyLabel": "Century selection", "dxCalendar-selectedDate": "The selected date is {0}", + "dxCalendar-selectedDates": "The selected dates", "dxCalendar-selectedDateRange": "The selected date range is from {0} to {1}", + "dxCalendar-selectedMultipleDateRange": "from {0} to {1}", + "dxCalendar-selectedDateRangeCount": "There are {0} selected date ranges", "dxCalendar-readOnlyLabel": "Read-only calendar", "dxChat-emptyListMessage": "There are no messages in this chat", diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.editors/calendar.markup.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.editors/calendar.markup.tests.js index 12b4e3a0cfd5..7c06483a693f 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.editors/calendar.markup.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.editors/calendar.markup.tests.js @@ -26,6 +26,10 @@ const toSelector = function(className) { return '.' + className; }; +const getFormattedDate = (date) => { + return dateLocalization.format(new Date(date), ARIA_LABEL_DATE_FORMAT); +}; + const { module: testModule, test } = QUnit; QUnit.module('Calendar markup', { @@ -461,18 +465,41 @@ QUnit.module('Aria accessibility', { checkTableAttribute(assert, this.$element, 'aria-label', expectedAriaLabel); }); - QUnit.test(`table aria-label should be equal to "Calendar" when selectionMode=multiple, zoomLevel=${zoomLevel}`, function(assert) { - const date = new Date(2024, 3, 21); - - this.$element.dxCalendar({ - zoomLevel, - selectionMode: 'multiple', - value: [date], + [ + { + value: [ new Date(1726765744957) ], + expectedAriaLabel: `Calendar. The selected dates: ${getFormattedDate(1726765744957)}`, + }, + { + value: [ '2017-03-27T16:54:48' ], + expectedAriaLabel: `Calendar. The selected dates: ${getFormattedDate('2017-03-27T16:54:48')}`, + }, + { + value: [ 1726938544957 ], + expectedAriaLabel: `Calendar. The selected dates: ${getFormattedDate(1726938544957)}`, + }, + { + value: [ '2024-09-21T17:09:04', '2024-09-20T17:09:04', '2024-09-19T17:09:04' ], + expectedAriaLabel: `Calendar. The selected dates: from ${getFormattedDate('2024-09-19T17:09:04')} to ${getFormattedDate('2024-09-21T17:09:04')}`, + }, + { + value: [ '2024-09-21T17:09:04', '2024-09-20T17:09:04', '2024-09-19T17:09:04', '2024-09-23T17:09:04', '2024-09-24T17:09:04', ], + expectedAriaLabel: `Calendar. The selected dates: from ${getFormattedDate('2024-09-19T17:09:04')} to ${getFormattedDate('2024-09-21T17:09:04')}, from ${getFormattedDate('2024-09-23T17:09:04')} to ${getFormattedDate('2024-09-24T17:09:04')}`, + }, + { + value: [ '2024-09-21T17:09:04', '2024-09-20T17:09:04', '2024-09-19T17:09:04', '2024-09-23T17:09:04', '2024-09-24T17:09:04', '2024-09-27T10:55:11' ], + expectedAriaLabel: 'Calendar. There are 3 selected date ranges', + }, + ].forEach(({ value, expectedAriaLabel }) => { + QUnit.test(`table aria-label should be correct when selectionMode=multiple,value=${value},zoomLevel=${zoomLevel}`, function(assert) { + this.$element.dxCalendar({ + zoomLevel, + selectionMode: 'multiple', + value, + }).dxCalendar('instance'); + + checkTableAttribute(assert, this.$element, 'aria-label', expectedAriaLabel); }); - - const expectedAriaLabel = 'Calendar'; - - checkTableAttribute(assert, this.$element, 'aria-label', expectedAriaLabel); }); QUnit.test(`table aria-label should contain selected date when selectionMode=range, zoomLevel=${zoomLevel}`, function(assert) { @@ -548,21 +575,23 @@ QUnit.module('Aria accessibility', { checkTableAttribute(assert, this.$element, 'aria-label', expectedAriaLabel); }); - QUnit.test('table aria-label should not contain new selected date after value changed when selectionMode=multiple', function(assert) { + QUnit.test('table aria-label should contain new selected dates after value changed when selectionMode=multiple', function(assert) { const firstDate = new Date(2024, 3, 21); const secondDate = new Date(2024, 3, 23); - const newFirstDate = new Date(2024, 3, 27); - const newSecondDate = new Date(2024, 3, 29); - const instance = this.$element.dxCalendar({ selectionMode: 'multiple', value: [firstDate, secondDate], }).dxCalendar('instance'); + checkTableAttribute(assert, this.$element, 'aria-label', 'Calendar. The selected dates: April 21, 2024, April 23, 2024'); + + const newFirstDate = new Date(2024, 3, 27); + const newSecondDate = new Date(2024, 3, 29); + instance.option({ value: [newFirstDate, newSecondDate] }); - checkTableAttribute(assert, this.$element, 'aria-label', 'Calendar'); + checkTableAttribute(assert, this.$element, 'aria-label', 'Calendar. The selected dates: April 27, 2024, April 29, 2024'); }); QUnit.test('table should have an aria-label "Calendar" when value is [null, null], selectionMode=range', function(assert) { diff --git a/packages/devextreme/testing/tests/DevExpress.utils/utils.date.tests.js b/packages/devextreme/testing/tests/DevExpress.utils/utils.date.tests.js new file mode 100644 index 000000000000..b1f84e14cf9e --- /dev/null +++ b/packages/devextreme/testing/tests/DevExpress.utils/utils.date.tests.js @@ -0,0 +1,76 @@ +import dateUtils from 'core/utils/date'; +const { test, module } = QUnit; + +module('getRangesByDates', {}, () => { + test('getRangesByDates should generate correct ranges when dates is empty array', function(assert) { + const dates = []; + const expectedResult = []; + + const result = dateUtils.getRangesByDates(dates); + + assert.deepEqual(result, expectedResult); + }); + + test('getRangesByDates should generate correct ranges when dates is 1-length array', function(assert) { + const dates = [ new Date('2024-11-27T13:27:01') ]; + const expectedResult = [ [ new Date('2024-11-27T00:00:00') ] ]; + + const result = dateUtils.getRangesByDates(dates); + + assert.deepEqual(result, expectedResult); + }); + + test('getRangesByDates should generate correct ranges when dates is array with single range', function(assert) { + const dates = [ + new Date('2024-09-27T02:17:07'), + new Date('2024-09-28T02:17:07'), + new Date('2024-09-29T02:17:07'), + ]; + + const expectedResult = [ + [ + new Date('2024-09-27T00:00:00'), + new Date('2024-09-29T00:00:00'), + ], + ]; + + const result = dateUtils.getRangesByDates(dates); + + assert.deepEqual(result, expectedResult); + }); + + test('getRangesByDates should generate correct ranges', function(assert) { + const dates = [ + new Date('2024-11-27T13:27:01'), + new Date('2024-10-27T16:54:10'), + new Date('2024-09-20T16:54:48'), + new Date('2024-09-21T18:54:21'), + new Date('2024-09-23T16:54:04'), + new Date('2024-09-24T02:54:12'), + new Date('2024-09-27T02:17:07'), + new Date('2024-09-26T18:28:11'), + new Date('2024-09-25T00:28:10'), + ]; + + const expectedResult = [ + [ + new Date('2024-09-20T00:00:00'), + new Date('2024-09-21T00:00:00'), + ], + [ + new Date('2024-09-23T00:00:00'), + new Date('2024-09-27T00:00:00'), + ], + [ + new Date('2024-10-27T00:00:00'), + ], + [ + new Date('2024-11-27T00:00:00'), + ] + ]; + + const result = dateUtils.getRangesByDates(dates); + + assert.deepEqual(result, expectedResult); + }); +});