This is an automated email from the ASF dual-hosted git repository.
Baoyuantop pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/apisix-dashboard.git
The following commit(s) were added to refs/heads/master by this push:
new 03d3e8e78 fix(header): guard missing translation progress in language
menu (#3380)
03d3e8e78 is described below
commit 03d3e8e780c4dd78fa6d04e9cd8d87f381b3c089
Author: 梁桂锋 <[email protected]>
AuthorDate: Tue Jun 2 16:21:23 2026 +0800
fix(header): guard missing translation progress in language menu (#3380)
---
e2e/tests/language-switch.spec.ts | 64 ++++++++++++++++++++++++++++++++++
src/components/Header/LanguageMenu.tsx | 2 +-
vite.config.ts | 4 ++-
3 files changed, 68 insertions(+), 2 deletions(-)
diff --git a/e2e/tests/language-switch.spec.ts
b/e2e/tests/language-switch.spec.ts
new file mode 100644
index 000000000..bf9351724
--- /dev/null
+++ b/e2e/tests/language-switch.spec.ts
@@ -0,0 +1,64 @@
+/**
+ * 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 { test } from '@e2e/utils/test';
+import { expect } from '@playwright/test';
+
+// All non-default languages to switch to (default is 'en')
+const switchTargets = ['Deutsch', '中文', 'Español', 'Türkçe', 'English'];
+
+test(
+ 'switching all languages should not crash the page',
+ { tag: '@i18n' },
+ async ({ page }) => {
+ const errors: string[] = [];
+ page.on('pageerror', (error) => errors.push(error.message));
+
+ for (const lang of switchTargets) {
+ await test.step(`switch to ${lang}`, async () => {
+ const langMenuTrigger = page.locator('button[aria-haspopup="menu"]');
+ await langMenuTrigger.click();
+
+ const menuItem = page.getByRole('menuitem', { name: lang });
+ await expect(menuItem).toBeVisible();
+ await menuItem.click();
+
+ // Verify the page didn't crash
+ await expect(page.locator('header')).toBeVisible();
+ });
+ }
+
+ expect(errors).toEqual([]);
+ }
+);
+
+test(
+ 'language menu shows all supported languages',
+ { tag: '@i18n' },
+ async ({ page }) => {
+ const allLanguages = ['English', 'Deutsch', '中文', 'Español', 'Türkçe'];
+
+ const langMenuTrigger = page.locator('button[aria-haspopup="menu"]');
+ await langMenuTrigger.click();
+
+ for (const lang of allLanguages) {
+ await expect(
+ page.getByRole('menuitem', { name: lang })
+ ).toBeVisible();
+ }
+ }
+);
diff --git a/src/components/Header/LanguageMenu.tsx
b/src/components/Header/LanguageMenu.tsx
index 48fcd8f0e..316daf05e 100644
--- a/src/components/Header/LanguageMenu.tsx
+++ b/src/components/Header/LanguageMenu.tsx
@@ -30,7 +30,7 @@ const LangMap: Record<keyof Resources, string> = {
};
const TranslationProgress = ({ lang }: { lang: string }) => {
- const percent = i18nProgress[lang].percent;
+ const percent = i18nProgress[lang as keyof typeof i18nProgress]?.percent;
if (typeof percent === 'number' && percent < 100) {
return (
<span
diff --git a/vite.config.ts b/vite.config.ts
index 799fdf323..cb00b0226 100644
--- a/vite.config.ts
+++ b/vite.config.ts
@@ -14,6 +14,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+import { readdirSync } from 'node:fs';
+
import { TanStackRouterVite } from '@tanstack/router-plugin/vite';
import react from '@vitejs/plugin-react-swc';
import observerPlugin from 'mobx-react-observer/swc-plugin';
@@ -91,7 +93,7 @@ export default defineConfig({
semicolons: false,
}),
i18nProgress({
- langs: ['en', 'es', 'de', 'zh'],
+ langs: readdirSync('./src/locales'),
baseLang: 'en',
getTranslationDir: (lang) => `./src/locales/${lang}`,
}),