-
Notifications
You must be signed in to change notification settings - Fork 667
T1312423 - CardView – Missing translation for Filter Panel title and related texts #32491
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: 26_1
Are you sure you want to change the base?
Conversation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pull request overview
This PR adjusts several grid/CardView-related option defaults so that localized strings are resolved at usage time (via messageLocalization.format(...)) rather than being precomputed in defaultOptions, and adds a comprehensive Jest localization test suite + supporting page-object models to prevent regressions.
Changes:
- Replace many localized string defaults in option objects with
undefinedand add runtime localization fallbacks in views/controllers. - Add CardView localization Jest tests covering column chooser, filter panel, filter builder operations, pager aria-label, sorting context menu, boolean display text, no-data text, header filter texts, search placeholder, and editing texts.
- Add/extend test page-object models (Popup, Pager, HeaderPanel, CardView, etc.) to support the new localization tests.
Reviewed changes
Copilot reviewed 40 out of 40 changed files in this pull request and generated 10 comments.
Show a summary per file
| File | Description |
|---|---|
| packages/devextreme/js/__internal/ui/tests/mock/model/tree_view.ts | Exposes getNodeByText for tests. |
| packages/devextreme/js/__internal/ui/tests/mock/model/textbox.ts | Adds input accessor for placeholder assertions. |
| packages/devextreme/js/__internal/ui/tests/mock/model/popup.ts | New popup POM used by multiple test models. |
| packages/devextreme/js/__internal/pagination/content.tsx | Adds localized fallback for navigation aria-label. |
| packages/devextreme/js/__internal/pagination/common/base_pagination_props.ts | Removes eager localization from default props (label: undefined). |
| packages/devextreme/js/__internal/pagination/tests/mock/model/pager.ts | New Pager POM for aria-label tests. |
| packages/devextreme/js/__internal/grids/new/grid_core/sorting_controller/options.ts | Removes eager localization from sorting option defaults. |
| packages/devextreme/js/__internal/grids/new/grid_core/search/view.tsx | Adds localized fallback for search placeholder in the view. |
| packages/devextreme/js/__internal/grids/new/grid_core/search/options.ts | Removes eager localization from search placeholder default. |
| packages/devextreme/js/__internal/grids/new/grid_core/pager/options.ts | Removes eager localization from pager aria label default. |
| packages/devextreme/js/__internal/grids/new/grid_core/filtering/header_filter/options.ts | Removes eager localization from header filter texts defaults. |
| packages/devextreme/js/__internal/grids/new/grid_core/filtering/header_filter/legacy_header_filter.ts | Adds localized fallback for header filter empty value text. |
| packages/devextreme/js/__internal/grids/new/grid_core/filtering/filter_panel/options.ts | Removes eager localization from filter panel / filter builder text defaults. |
| packages/devextreme/js/__internal/grids/new/grid_core/editing/popup/view.ts | Adds localized fallbacks for editing popup texts. |
| packages/devextreme/js/__internal/grids/new/grid_core/editing/options.ts | Removes eager localization from editing text defaults. |
| packages/devextreme/js/__internal/grids/new/grid_core/editing/controller.ts | Adds localized fallback for confirm delete message; adjusts awaits. |
| packages/devextreme/js/__internal/grids/new/grid_core/content_view/view.tsx | Adds localized fallback for no-data text rendering. |
| packages/devextreme/js/__internal/grids/new/grid_core/content_view/options.ts | Removes eager localization from no-data text default. |
| packages/devextreme/js/__internal/grids/new/grid_core/columns_controller/options.ts | Removes eager localization for boolean true/false texts and adds runtime fallback. |
| packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/view.tsx | Adds localized fallback for empty panel text; simplifies popup toolbar usage. |
| packages/devextreme/js/__internal/grids/new/grid_core/column_chooser/column_chooser.tsx | Ensures toolbar title has a localized fallback at render time. |
| packages/devextreme/js/__internal/grids/new/card_view/context_menu/controller.ts | Adds localized fallbacks for sorting context menu item texts. |
| packages/devextreme/js/__internal/grids/new/card_view/tests/cardview.localization.test.ts | New end-to-end localization coverage for CardView behaviors. |
| packages/devextreme/js/__internal/grids/new/card_view/tests/mock/model/header_panel.ts | New HeaderPanel POM for context-menu / header filter tests. |
| packages/devextreme/js/__internal/grids/new/card_view/tests/mock/model/header_item.ts | New HeaderItem POM for header interactions. |
| packages/devextreme/js/__internal/grids/new/card_view/tests/mock/model/card_view.ts | New CardView POM integrating common grid-core POMs. |
| packages/devextreme/js/__internal/grids/new/card_view/tests/mock/model/card.ts | New Card POM for boolean localization assertions. |
| packages/devextreme/js/__internal/grids/new/card_view/tests/mock/helpers/utils.ts | New CardView test harness (setup/teardown/flush helpers). |
| packages/devextreme/js/__internal/grids/grid_core/header_filter/m_header_filter_core.ts | Adds localized fallbacks for OK/Cancel button texts. |
| packages/devextreme/js/__internal/grids/grid_core/filter/m_filter_panel.ts | Adds localized fallbacks for filter panel texts and makes defaults undefined. |
| packages/devextreme/js/__internal/grids/grid_core/column_chooser/const.ts | Changes column chooser defaults to undefined. |
| packages/devextreme/js/__internal/grids/grid_core/tests/mock/model/header_filter.ts | New HeaderFilter POM built atop Popup POM. |
| packages/devextreme/js/__internal/grids/grid_core/tests/mock/model/grid_core.ts | Enhances shared grid-core POM and adds CardView compatibility/helpers. |
| packages/devextreme/js/__internal/grids/grid_core/tests/mock/model/filter_panel.ts | New FilterPanel POM (supports different widget prefixes). |
| packages/devextreme/js/__internal/grids/grid_core/tests/mock/model/edit_form.ts | Extends edit-form POM with popup toolbar accessors. |
| packages/devextreme/js/__internal/grids/grid_core/tests/mock/model/data_grid_base.ts | New base POM restoring DataGrid-only APIs removed from GridCoreModel. |
| packages/devextreme/js/__internal/grids/grid_core/tests/mock/model/confirmation_dialog.ts | New ConfirmationDialog POM for delete-confirmation localization. |
| packages/devextreme/js/__internal/grids/grid_core/tests/mock/model/column_chooser.ts | Refactors ColumnChooser POM to reuse PopupModel and support multiple widgets. |
| packages/devextreme/js/__internal/grids/data_grid/tests/mock/model/data_grid.ts | Switches DataGrid POM to extend the new DataGridBaseModel. |
| packages/devextreme/js/__internal/filter_builder/tests/mock/model/filter_builder.ts | New FilterBuilder POM for verifying localized operations. |
| export class PopupModel { | ||
| protected getPopupWrapper(): HTMLElement { | ||
| return document.body.querySelector(`.${CLASSES.popupWrapper}`) as HTMLElement; | ||
| } |
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getPopupWrapper() currently selects the first .dx-popup-wrapper in document.body. If multiple popups are present, derived models (ColumnChooser, dialogs, header filter, etc.) may attach to the wrong popup and make tests flaky. Consider allowing PopupModel to be constructed with an identifying selector/class, or selecting the most recently opened wrapper (e.g., last match) when appropriate.
| public getInput(): HTMLInputElement { | ||
| return this.root.querySelector('input') as HTMLInputElement; | ||
| } |
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getInput() casts the result of querySelector('input') to HTMLInputElement, but querySelector can return null (and this selector may match unintended inputs). Consider querying a more specific selector (e.g., .dx-texteditor-input) and returning HTMLInputElement | null (or throwing if absence is an error for the test).
| this.onSaving.peek()(eventArgs); | ||
|
|
||
| // eslint-disable-next-line @typescript-eslint/await-thenable | ||
| await eventArgs.promise; |
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Same issue as in addCard(): eventArgs.promise is optional but awaited directly. Consider awaiting eventArgs.promise ?? Promise.resolve() to avoid awaiting undefined and potential lint/type issues.
| await eventArgs.promise; | |
| await (eventArgs.promise ?? Promise.resolve()); |
| const actualTitle = title || messageLocalization.format('dxDataGrid-columnChooserTitle'); | ||
| const toolbarItems = [ | ||
| { text: actualTitle, toolbar: 'top' as const, location: 'before' as const }, | ||
| ]; | ||
|
|
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
actualTitle is computed for the toolbar, but setPopupAttributes() still sets the popup aria-label to the localized default (dxDataGrid-columnChooserTitle) regardless of a custom title prop. For accessibility consistency, consider using actualTitle (or title ?? localizedDefault) for the aria-label as well.
| width: 250, | ||
| height: 260, | ||
| get title() { | ||
| return messageLocalization.format('dxDataGrid-columnChooserTitle'); | ||
| }, | ||
| get emptyPanelText() { | ||
| return messageLocalization.format('dxDataGrid-columnChooserEmptyText'); | ||
| }, | ||
| title: undefined, | ||
| emptyPanelText: undefined, |
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
columnChooser.title and columnChooser.emptyPanelText defaults were changed to undefined, but m_column_chooser.ts uses columnChooserOptions.title directly for the popup toolbar item text. With these defaults, the Column Chooser popup title/empty text can become blank unless the user provides them. Consider restoring the localized default (e.g., via getters) or add a fallback at the usage site (e.g., ?? messageLocalization.format(...)).
| export class PopupModel { | ||
| protected getPopupWrapper(): HTMLElement { | ||
| return document.body.querySelector(`.${CLASSES.popupWrapper}`) as HTMLElement; | ||
| } | ||
|
|
||
| public getOverlayContent(): HTMLElement { | ||
| const wrapper = this.getPopupWrapper(); | ||
| return wrapper?.querySelector(`.${CLASSES.overlayContent}`) as HTMLElement; | ||
| } |
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
getPopupWrapper() / getOverlayContent() are typed to always return HTMLElement, but querySelector(...) can return null at runtime. This causes misleading typing (e.g., isVisible() and callers can assume non-null) and may lead to runtime errors when the popup is not present. Consider returning HTMLElement | null and either guarding in callers or throwing with a clear error when the popup is expected to exist.
| this.onInitNewCard.peek()(eventArgs); | ||
|
|
||
| // eslint-disable-next-line @typescript-eslint/await-thenable | ||
| await eventArgs.promise; |
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
eventArgs.promise is optional (promise?: Promise<void>), but the code does await eventArgs.promise;. If the action doesn't set promise, this awaits undefined (a no-op) and can also trigger @typescript-eslint/await-thenable depending on lint/type inference. Consider await (eventArgs.promise ?? Promise.resolve()); (same applies to the similar pattern in save()).
| await eventArgs.promise; | |
| await (eventArgs.promise ?? Promise.resolve()); |
| private readonly dragAndDropModeConfig: ReadonlySignal<TreeViewProperties> = computed(() => ({ | ||
| noDataText: this.options.oneWay('columnChooser.emptyPanelText').value, | ||
| noDataText: this.options.oneWay('columnChooser.emptyPanelText').value | ||
| || messageLocalization.format('dxDataGrid-columnChooserEmptyText'), |
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This fallback uses ||, so an explicitly configured empty string for columnChooser.emptyPanelText will be ignored and replaced with the localized default. If empty string should be a valid override, prefer ?? instead of ||.
| || messageLocalization.format('dxDataGrid-columnChooserEmptyText'), | |
| ?? messageLocalization.format('dxDataGrid-columnChooserEmptyText'), |
| }); | ||
| $element.attr('title', this.option('filterPanel.texts.filterEnabledHint')!); | ||
| const filterEnabledHint = this.option('filterPanel.texts.filterEnabledHint') | ||
| || messageLocalization.format('dxDataGrid-filterPanelFilterEnabledHint'); |
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
These fallbacks use ||, so an explicitly configured empty string for filterPanel.texts.* will be ignored and replaced with the localized default. If empty string should be a valid override, prefer ?? instead of || (and apply the same change to the other filterPanel.texts.* fallbacks in this file).
| || messageLocalization.format('dxDataGrid-filterPanelFilterEnabledHint'); | |
| ?? messageLocalization.format('dxDataGrid-filterPanelFilterEnabledHint'); |
| public getOverlayContent(): HTMLElement { | ||
| const wrapper = this.getPopupWrapper(); | ||
| return wrapper?.querySelector(`.${CLASSES.overlayContent}`) as HTMLElement; | ||
| } | ||
|
|
||
| public isVisible(): boolean { | ||
| return this.getOverlayContent() !== null; | ||
| } |
Copilot
AI
Feb 10, 2026
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
isVisible() checks this.getOverlayContent() !== null, but getOverlayContent() can return undefined (when getPopupWrapper() returns null and optional chaining is used). In that case undefined !== null is true, so isVisible() may report visible when no popup exists. Consider returning HTMLElement | null from getOverlayContent() and using a truthiness check like return !!this.getOverlayContent(); (or != null).
No description provided.