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}`,
     }),

Reply via email to