diff --git a/superset-frontend/packages/superset-ui-core/src/components/EmptyState/index.tsx b/superset-frontend/packages/superset-ui-core/src/components/EmptyState/index.tsx
index b8f655c2760..05e39eed9b7 100644
--- a/superset-frontend/packages/superset-ui-core/src/components/EmptyState/index.tsx
+++ b/superset-frontend/packages/superset-ui-core/src/components/EmptyState/index.tsx
@@ -128,7 +128,7 @@ const ImageContainer = ({
);
diff --git a/superset-frontend/plugins/plugin-chart-ag-grid-table/src/AgGridTable/index.tsx b/superset-frontend/plugins/plugin-chart-ag-grid-table/src/AgGridTable/index.tsx
index fc4e7b9000c..7804a02f743 100644
--- a/superset-frontend/plugins/plugin-chart-ag-grid-table/src/AgGridTable/index.tsx
+++ b/superset-frontend/plugins/plugin-chart-ag-grid-table/src/AgGridTable/index.tsx
@@ -40,7 +40,7 @@ import {
} from 'ag-grid-community';
import { AgGridReact } from 'ag-grid-react';
import { type FunctionComponent } from 'react';
-import { JsonObject, DataRecordValue, DataRecord } from '@superset-ui/core';
+import { JsonObject, DataRecordValue, DataRecord, t } from '@superset-ui/core';
import { SearchOutlined } from '@ant-design/icons';
import { debounce, isEqual } from 'lodash';
import Pagination from './components/Pagination';
@@ -326,6 +326,79 @@ const AgGridDataTable: FunctionComponent = memo(
paginationPageSizeSelector={PAGE_SIZE_OPTIONS}
suppressDragLeaveHidesColumns
pinnedBottomRowData={showTotals ? [cleanedTotals] : undefined}
+ localeText={{
+ // Pagination controls
+ next: t('Next'),
+ previous: t('Previous'),
+ page: t('Page'),
+ more: t('More'),
+ to: t('to'),
+ of: t('of'),
+ first: t('First'),
+ last: t('Last'),
+ loadingOoo: t('Loading...'),
+ // Set Filter
+ selectAll: t('Select All'),
+ searchOoo: t('Search...'),
+ blanks: t('Blanks'),
+ // Filter operations
+ filterOoo: t('Filter'),
+ applyFilter: t('Apply Filter'),
+ equals: t('Equals'),
+ notEqual: t('Not Equal'),
+ lessThan: t('Less Than'),
+ greaterThan: t('Greater Than'),
+ lessThanOrEqual: t('Less Than or Equal'),
+ greaterThanOrEqual: t('Greater Than or Equal'),
+ inRange: t('In Range'),
+ contains: t('Contains'),
+ notContains: t('Not Contains'),
+ startsWith: t('Starts With'),
+ endsWith: t('Ends With'),
+ // Logical conditions
+ andCondition: t('AND'),
+ orCondition: t('OR'),
+ // Panel and group labels
+ group: t('Group'),
+ columns: t('Columns'),
+ filters: t('Filters'),
+ valueColumns: t('Value Columns'),
+ pivotMode: t('Pivot Mode'),
+ groups: t('Groups'),
+ values: t('Values'),
+ pivots: t('Pivots'),
+ toolPanelButton: t('Tool Panel'),
+ // Enterprise menu items
+ pinColumn: t('Pin Column'),
+ valueAggregation: t('Value Aggregation'),
+ autosizeThiscolumn: t('Autosize This Column'),
+ autosizeAllColumns: t('Autosize All Columns'),
+ groupBy: t('Group By'),
+ ungroupBy: t('Ungroup By'),
+ resetColumns: t('Reset Columns'),
+ expandAll: t('Expand All'),
+ collapseAll: t('Collapse All'),
+ toolPanel: t('Tool Panel'),
+ export: t('Export'),
+ csvExport: t('CSV Export'),
+ excelExport: t('Excel Export'),
+ excelXmlExport: t('Excel XML Export'),
+ // Aggregation functions
+ sum: t('Sum'),
+ min: t('Min'),
+ max: t('Max'),
+ none: t('None'),
+ count: t('Count'),
+ average: t('Average'),
+ // Standard menu items
+ copy: t('Copy'),
+ copyWithHeaders: t('Copy with Headers'),
+ paste: t('Paste'),
+ // Column menu and sorting
+ sortAscending: t('Sort Ascending'),
+ sortDescending: t('Sort Descending'),
+ sortUnSort: t('Clear Sort'),
+ }}
context={{
onColumnHeaderClicked: handleColumnHeaderClick,
initialSortState: getInitialSortState(
diff --git a/superset-frontend/plugins/plugin-chart-ag-grid-table/src/consts.ts b/superset-frontend/plugins/plugin-chart-ag-grid-table/src/consts.ts
index d4db087c304..995e43ea672 100644
--- a/superset-frontend/plugins/plugin-chart-ag-grid-table/src/consts.ts
+++ b/superset-frontend/plugins/plugin-chart-ag-grid-table/src/consts.ts
@@ -17,10 +17,6 @@
* under the License.
*/
import { formatSelectOptions } from '@superset-ui/chart-controls';
-import { addLocaleData } from '@superset-ui/core';
-import i18n from './i18n';
-
-addLocaleData(i18n);
export const SERVER_PAGE_SIZE_OPTIONS = formatSelectOptions([
10, 20, 50, 100, 200,
diff --git a/superset-frontend/plugins/plugin-chart-ag-grid-table/src/i18n.ts b/superset-frontend/plugins/plugin-chart-ag-grid-table/src/i18n.ts
deleted file mode 100644
index 3ea82b00e07..00000000000
--- a/superset-frontend/plugins/plugin-chart-ag-grid-table/src/i18n.ts
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { Locale } from '@superset-ui/core';
-
-const en = {
- 'Query Mode': [''],
- Aggregate: [''],
- 'Raw Records': [''],
- 'Emit Filter Events': [''],
- 'Show Cell Bars': [''],
- 'page_size.show': ['Show'],
- 'page_size.all': ['All'],
- 'page_size.entries': ['entries'],
- 'table.previous_page': ['Previous'],
- 'table.next_page': ['Next'],
- 'search.num_records': ['%s record', '%s records...'],
-};
-
-const translations: Partial> = {
- en,
- fr: {
- 'Query Mode': [''],
- Aggregate: [''],
- 'Raw Records': [''],
- 'Emit Filter Events': [''],
- 'Show Cell Bars': [''],
- 'page_size.show': ['Afficher'],
- 'page_size.all': ['tous'],
- 'page_size.entries': ['entrées'],
- 'table.previous_page': ['Précédent'],
- 'table.next_page': ['Suivante'],
- 'search.num_records': ['%s enregistrement', '%s enregistrements...'],
- },
- zh: {
- 'Query Mode': ['查询模式'],
- Aggregate: ['分组聚合'],
- 'Raw Records': ['原始数据'],
- 'Emit Filter Events': ['关联看板过滤器'],
- 'Show Cell Bars': ['为指标添加条状图背景'],
- 'page_size.show': ['每页显示'],
- 'page_size.all': ['全部'],
- 'page_size.entries': ['条'],
- 'table.previous_page': ['上一页'],
- 'table.next_page': ['下一页'],
- 'search.num_records': ['%s条记录...'],
- },
-};
-
-export default translations;
diff --git a/superset-frontend/plugins/plugin-chart-table/src/consts.ts b/superset-frontend/plugins/plugin-chart-table/src/consts.ts
index c2cd9dfa66f..58f60d049f5 100644
--- a/superset-frontend/plugins/plugin-chart-table/src/consts.ts
+++ b/superset-frontend/plugins/plugin-chart-table/src/consts.ts
@@ -17,10 +17,7 @@
* under the License.
*/
import { formatSelectOptions } from '@superset-ui/chart-controls';
-import { addLocaleData, t } from '@superset-ui/core';
-import i18n from './i18n';
-
-addLocaleData(i18n);
+import { t } from '@superset-ui/core';
export const PAGE_SIZE_OPTIONS = formatSelectOptions([
[0, t('page_size.all')],
diff --git a/superset-frontend/plugins/plugin-chart-table/src/i18n.ts b/superset-frontend/plugins/plugin-chart-table/src/i18n.ts
deleted file mode 100644
index 3ea82b00e07..00000000000
--- a/superset-frontend/plugins/plugin-chart-table/src/i18n.ts
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one
- * or more contributor license agreements. See the NOTICE file
- * distributed with this work for additional information
- * regarding copyright ownership. The ASF licenses this file
- * to you under the Apache License, Version 2.0 (the
- * "License"); you may not use this file except in compliance
- * with the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing,
- * software distributed under the License is distributed on an
- * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
- * KIND, either express or implied. See the License for the
- * specific language governing permissions and limitations
- * under the License.
- */
-
-import { Locale } from '@superset-ui/core';
-
-const en = {
- 'Query Mode': [''],
- Aggregate: [''],
- 'Raw Records': [''],
- 'Emit Filter Events': [''],
- 'Show Cell Bars': [''],
- 'page_size.show': ['Show'],
- 'page_size.all': ['All'],
- 'page_size.entries': ['entries'],
- 'table.previous_page': ['Previous'],
- 'table.next_page': ['Next'],
- 'search.num_records': ['%s record', '%s records...'],
-};
-
-const translations: Partial> = {
- en,
- fr: {
- 'Query Mode': [''],
- Aggregate: [''],
- 'Raw Records': [''],
- 'Emit Filter Events': [''],
- 'Show Cell Bars': [''],
- 'page_size.show': ['Afficher'],
- 'page_size.all': ['tous'],
- 'page_size.entries': ['entrées'],
- 'table.previous_page': ['Précédent'],
- 'table.next_page': ['Suivante'],
- 'search.num_records': ['%s enregistrement', '%s enregistrements...'],
- },
- zh: {
- 'Query Mode': ['查询模式'],
- Aggregate: ['分组聚合'],
- 'Raw Records': ['原始数据'],
- 'Emit Filter Events': ['关联看板过滤器'],
- 'Show Cell Bars': ['为指标添加条状图背景'],
- 'page_size.show': ['每页显示'],
- 'page_size.all': ['全部'],
- 'page_size.entries': ['条'],
- 'table.previous_page': ['上一页'],
- 'table.next_page': ['下一页'],
- 'search.num_records': ['%s条记录...'],
- },
-};
-
-export default translations;
diff --git a/superset-frontend/src/components/Chart/MenuItemWithTruncation.tsx b/superset-frontend/src/components/Chart/MenuItemWithTruncation.tsx
index 0b0b87e89a0..00311c38ad0 100644
--- a/superset-frontend/src/components/Chart/MenuItemWithTruncation.tsx
+++ b/superset-frontend/src/components/Chart/MenuItemWithTruncation.tsx
@@ -109,7 +109,7 @@ export const MenuItemWithTruncation = ({
display: flex;
line-height: 1.5em;
`}
- eventKey={menuKey}
+ key={menuKey}
onClick={onClick}
style={style}
>
diff --git a/superset/app.py b/superset/app.py
index 22d3a6ba7d6..0a8f73d53e7 100644
--- a/superset/app.py
+++ b/superset/app.py
@@ -30,7 +30,7 @@ else:
from _typeshed.wsgi import StartResponse, WSGIApplication, WSGIEnvironment
-from flask import Flask
+from flask import Flask, Response
from werkzeug.exceptions import NotFound
from superset.initialization import SupersetAppInitializer
@@ -77,7 +77,24 @@ def create_app(
class SupersetApp(Flask):
- pass
+ def send_static_file(self, filename: str) -> Response:
+ """Override to prevent webpack hot-update 404s from spamming logs.
+
+ Webpack HMR can create race conditions where the browser requests
+ hot-update files that no longer exist. Return 204 instead of 404
+ for these files to keep logs clean.
+ """
+ if ".hot-update." in filename:
+ # First try to serve it normally - it might exist
+ try:
+ return super().send_static_file(filename)
+ except NotFound:
+ logger.debug(
+ "Webpack hot-update file not found (likely HMR "
+ f"race condition): {filename}"
+ )
+ return Response("", status=204) # No Content
+ return super().send_static_file(filename)
class AppRootMiddleware:
diff --git a/superset/db_engine_specs/__init__.py b/superset/db_engine_specs/__init__.py
index 8fddccbb724..a68e8847bec 100644
--- a/superset/db_engine_specs/__init__.py
+++ b/superset/db_engine_specs/__init__.py
@@ -154,7 +154,7 @@ def get_available_engine_specs() -> dict[type[BaseEngineSpec], set[str]]: # noq
try:
dialect = ep.load()
except Exception as ex: # pylint: disable=broad-except
- logger.warning("Unable to load SQLAlchemy dialect %s: %s", ep.name, ex)
+ logger.debug("Unable to load SQLAlchemy dialect %s: %s", ep.name, ex)
else:
backend = dialect.name
if isinstance(backend, bytes):