From 75d8f98e4289223273e4d6882949279d7409d122 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?marker=20dao=20=C2=AE?= Date: Tue, 21 Apr 2026 12:48:36 +0200 Subject: [PATCH 1/2] DateBox: Use localized day period names (T1327076) --- .../__internal/ui/date_box/date_box.mask.ts | 18 +++++++------ .../datebox.mask.tests.js | 26 +++++++++++++++++++ 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/packages/devextreme/js/__internal/ui/date_box/date_box.mask.ts b/packages/devextreme/js/__internal/ui/date_box/date_box.mask.ts index 0a725c0ecb32..c803eddc2d4d 100644 --- a/packages/devextreme/js/__internal/ui/date_box/date_box.mask.ts +++ b/packages/devextreme/js/__internal/ui/date_box/date_box.mask.ts @@ -1,6 +1,5 @@ import eventsEngine from '@js/common/core/events/core/events_engine'; import { addNamespace, isCommandKeyPressed, normalizeKeyName } from '@js/common/core/events/utils/index'; -import defaultDateNames from '@js/common/core/localization/default_date_names'; import { getFormat } from '@js/common/core/localization/ldml/date.format'; import { getRegExpInfo } from '@js/common/core/localization/ldml/date.parser'; import numberLocalization from '@js/common/core/localization/number'; @@ -136,7 +135,6 @@ class DateBoxMask extends DateBoxBase { const delta = currentValue - originalValue; this._loadMaskValue(this._initialMaskValue); - this._changePartValue(delta + step, true); } @@ -153,12 +151,12 @@ class DateBoxMask extends DateBoxBase { _toggleAmPm(): void { const currentValue = this._getActivePartProp('text'); - const indexOfCurrentValue = defaultDateNames - // @ts-expect-error getPeriodNames type should be fixed - .getPeriodNames(this._formatPattern) - .indexOf(currentValue); + const periodNames = dateLocalization.getPeriodNames(this._formatPattern); + const indexOfCurrentValue = periodNames.indexOf(currentValue); + // eslint-disable-next-line no-bitwise const newValue = indexOfCurrentValue ^ 1; + this._setActivePartValue(newValue); } @@ -554,8 +552,11 @@ class DateBoxMask extends DateBoxBase { _getActivePartValue(dateValue?: Date | null): number { const date = dateValue ?? this._maskValue as Date; const getter = this._getActivePartProp('getter'); + const isGetterFunction = isFunction(getter); + + const activePartValue = isGetterFunction ? getter(date) : date[getter]() as number; - return isFunction(getter) ? getter(date) : date[getter]() as number; + return activePartValue; } _addLeadingZeroes(value: number): string { @@ -568,6 +569,7 @@ class DateBoxMask extends DateBoxBase { _setActivePartValue(value: number | string, dateValue?: Date): void { let newValue: number | string = +value; + const newDateValue = dateValue ?? this._maskValue as Date; const setter = this._getActivePartProp('setter'); const limits = this._getActivePartLimits(); @@ -580,8 +582,8 @@ class DateBoxMask extends DateBoxBase { } else { newDateValue[setter](newValue); } - this._renderDisplayText(this._getDisplayedText(newDateValue)); + this._renderDisplayText(this._getDisplayedText(newDateValue)); this._renderDateParts(); } diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.editors/datebox.mask.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.editors/datebox.mask.tests.js index a59aa82941ed..29528ade4fa8 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.editors/datebox.mask.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.editors/datebox.mask.tests.js @@ -2,6 +2,7 @@ import $ from 'jquery'; import { renderDateParts, getDatePartIndexByPosition } from '__internal/ui/date_box/date_box.mask.parts'; import dateParser from '__internal/core/localization/ldml/dateParserModule'; import dateLocalization from 'common/core/localization/date'; +import localization from 'localization'; import { noop } from 'core/utils/common'; import pointerMock from '../../helpers/pointerMock.js'; import 'ui/date_box'; @@ -1290,6 +1291,31 @@ module('Date AM/PM Handling', setupModule, () => { assert.strictEqual(this.$input.val(), 'PM'); }); }); + + test('up/down arrows should continue to switch AM/PM on subsequent presses when locale has localized period names (T1327076)', function(assert) { + const defaultLocale = localization.locale(); + + try { + localization.locale('es-ES'); + + const [amName, pmName] = dateLocalization.getPeriodNames(); + + this.instance.option({ + value: new Date('10/10/2012 22:00'), + displayFormat: 'a' + }); + + assert.strictEqual(this.$input.val(), pmName, 'initial value is localized PM'); + + this.keyboard.press('up'); + assert.strictEqual(this.$input.val(), amName, 'value changed to localized AM after first press'); + + this.keyboard.press('up'); + assert.strictEqual(this.$input.val(), pmName, 'value returned to localized PM after second press'); + } finally { + localization.locale(defaultLocale); + } + }); }); module('TimeZone Handling', setupModule, () => { From d2898450cd34fcea06e7450a1a2b0fafcc8e5dc3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?marker=20dao=20=C2=AE?= Date: Wed, 22 Apr 2026 14:42:15 +0200 Subject: [PATCH 2/2] fix(datebox): isStub && Update test --- .../devextreme/js/__internal/ui/date_box/date_box.mask.ts | 2 +- .../tests/DevExpress.ui.widgets.editors/datebox.mask.tests.js | 4 +++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/devextreme/js/__internal/ui/date_box/date_box.mask.ts b/packages/devextreme/js/__internal/ui/date_box/date_box.mask.ts index c803eddc2d4d..73e8c69f628d 100644 --- a/packages/devextreme/js/__internal/ui/date_box/date_box.mask.ts +++ b/packages/devextreme/js/__internal/ui/date_box/date_box.mask.ts @@ -514,7 +514,7 @@ class DateBoxMask extends DateBoxBase { const activePartIndex = this._activePartIndex ?? 0; let index = fitIntoRange(activePartIndex + step, 0, this._dateParts.length - 1); - if (this._dateParts[index].isStub) { + if (this._dateParts[index]?.isStub) { const isBoundaryIndex = (index === 0 && step < 0) || (index === this._dateParts.length - 1 && step > 0); if (!isBoundaryIndex) { diff --git a/packages/devextreme/testing/tests/DevExpress.ui.widgets.editors/datebox.mask.tests.js b/packages/devextreme/testing/tests/DevExpress.ui.widgets.editors/datebox.mask.tests.js index 29528ade4fa8..9108ef9127b3 100644 --- a/packages/devextreme/testing/tests/DevExpress.ui.widgets.editors/datebox.mask.tests.js +++ b/packages/devextreme/testing/tests/DevExpress.ui.widgets.editors/datebox.mask.tests.js @@ -8,6 +8,7 @@ import pointerMock from '../../helpers/pointerMock.js'; import 'ui/date_box'; import keyboardMock from '../../helpers/keyboardMock.js'; import devices from '__internal/core/m_devices'; +import es from 'localization/messages/es.json!'; const { test, module } = QUnit; @@ -1302,7 +1303,8 @@ module('Date AM/PM Handling', setupModule, () => { this.instance.option({ value: new Date('10/10/2012 22:00'), - displayFormat: 'a' + displayFormat: 'a', + useMaskBehavior: true, }); assert.strictEqual(this.$input.val(), pmName, 'initial value is localized PM');