From eb999e069b03c60342bd343d73cb728011d5eace Mon Sep 17 00:00:00 2001
From: J_Sinclair <56301946+E-R-Butch@users.noreply.github.com>
Date: Mon, 7 Sep 2026 18:12:58 +0800
Subject: [PATCH] fix(ui): complete blog dropdown localization and address
review comments
---
.../src/components/LanguageSwitcher.tsx | 4 +-
.../BlogDropdown.integration.test.tsx | 78 +++++++++++++++++++
.../Navbar/BlogDropdown/BlogDropdown.tsx | 10 +--
.../src/i18n/LanguageProvider.tsx | 4 +-
ui/litellm-dashboard/src/i18n/locales/en.json | 1 +
.../src/i18n/locales/zh-CN.json | 1 +
6 files changed, 87 insertions(+), 11 deletions(-)
create mode 100644 ui/litellm-dashboard/src/components/Navbar/BlogDropdown/BlogDropdown.integration.test.tsx
diff --git a/ui/litellm-dashboard/src/components/LanguageSwitcher.tsx b/ui/litellm-dashboard/src/components/LanguageSwitcher.tsx
index a81a34fcb44..c95565e1869 100644
--- a/ui/litellm-dashboard/src/components/LanguageSwitcher.tsx
+++ b/ui/litellm-dashboard/src/components/LanguageSwitcher.tsx
@@ -20,9 +20,7 @@ export default function LanguageSwitcher() {
void i18n.changeLanguage(language);
try {
window.localStorage.setItem(LANGUAGE_STORAGE_KEY, language);
- } catch {
- // Storage can be disabled by the browser; keep the current selection usable
- }
+ } catch {}
};
return (
diff --git a/ui/litellm-dashboard/src/components/Navbar/BlogDropdown/BlogDropdown.integration.test.tsx b/ui/litellm-dashboard/src/components/Navbar/BlogDropdown/BlogDropdown.integration.test.tsx
new file mode 100644
index 00000000000..fc69c1a59ea
--- /dev/null
+++ b/ui/litellm-dashboard/src/components/Navbar/BlogDropdown/BlogDropdown.integration.test.tsx
@@ -0,0 +1,78 @@
+import { act } from "@testing-library/react";
+import userEvent from "@testing-library/user-event";
+import { I18nextProvider } from "react-i18next";
+import { beforeEach, describe, expect, it, vi } from "vitest";
+import { createDashboardI18n } from "@/i18n";
+import { renderWithProviders, screen } from "../../../../tests/test-utils";
+import { BlogDropdown } from "./BlogDropdown";
+
+const mockRefetch = vi.fn();
+let mockIsError = false;
+
+vi.mock("@/app/(dashboard)/hooks/useDisableBlogPosts", () => ({
+ useDisableBlogPosts: () => false,
+}));
+
+vi.mock("@/app/(dashboard)/hooks/blogPosts/useBlogPosts", () => ({
+ useBlogPosts: () => ({
+ data: { posts: [{ title: "Post One", date: "2026-02-01", description: "Description one", url: "https://example.com/1" }] },
+ isLoading: false,
+ isError: mockIsError,
+ refetch: mockRefetch,
+ }),
+}));
+
+async function openDropdown() {
+ await userEvent.setup().hover(screen.getByRole("button", { name: "Blog" }));
+}
+
+describe("blog dropdown language changes", () => {
+ beforeEach(() => {
+ vi.clearAllMocks();
+ mockIsError = false;
+ });
+
+ it("should translate Retry after switching languages and still refetch posts", async () => {
+ mockIsError = true;
+ const user = userEvent.setup();
+ const i18n = createDashboardI18n();
+ renderWithProviders(
+
{post.description}
diff --git a/ui/litellm-dashboard/src/i18n/LanguageProvider.tsx b/ui/litellm-dashboard/src/i18n/LanguageProvider.tsx index de9efbb532c..c68a018b044 100644 --- a/ui/litellm-dashboard/src/i18n/LanguageProvider.tsx +++ b/ui/litellm-dashboard/src/i18n/LanguageProvider.tsx @@ -15,9 +15,7 @@ export default function LanguageProvider({ children }: { children: ReactNode }) try { const stored = window.localStorage.getItem(LANGUAGE_STORAGE_KEY); if (isLanguage(stored)) void instance.changeLanguage(stored); - } catch { - // Storage can be disabled by the browser; language selection still works in memory - } + } catch {} updateDocumentLanguage(instance.language); return () => { instance.off("languageChanged", updateDocumentLanguage); diff --git a/ui/litellm-dashboard/src/i18n/locales/en.json b/ui/litellm-dashboard/src/i18n/locales/en.json index 4886c58c131..67ea7246186 100644 --- a/ui/litellm-dashboard/src/i18n/locales/en.json +++ b/ui/litellm-dashboard/src/i18n/locales/en.json @@ -73,6 +73,7 @@ "Prompts": "Prompts", "Read the docs": "Read the docs", "Response Cache": "Response Cache", + "Retry": "Retry", "Role": "Role", "Route every request to the cheapest model that can handle it, no prompt changes needed.": "Route every request to the cheapest model that can handle it, no prompt changes needed.", "Router Settings": "Router Settings", diff --git a/ui/litellm-dashboard/src/i18n/locales/zh-CN.json b/ui/litellm-dashboard/src/i18n/locales/zh-CN.json index bf2706ad15c..0bb1cf75bb7 100644 --- a/ui/litellm-dashboard/src/i18n/locales/zh-CN.json +++ b/ui/litellm-dashboard/src/i18n/locales/zh-CN.json @@ -73,6 +73,7 @@ "Prompts": "提示词", "Read the docs": "查看文档", "Response Cache": "响应缓存", + "Retry": "重试", "Role": "角色", "Route every request to the cheapest model that can handle it, no prompt changes needed.": "自动将每个请求分配给能够处理它的最低成本模型,无需修改提示词。", "Router Settings": "路由设置",