From 61a1ad1bbe61a6055d1ad10f835d94d68fa384d0 Mon Sep 17 00:00:00 2001 From: Namnarak Date: Fri, 6 Nov 2026 19:41:25 +0700 Subject: [PATCH] fix(i18n): complete English UI localization coverage --- engine/i18n-localization.test.ts | 22 + src/App.tsx | 453 ++++++++++--------- src/components/FlexMessage.tsx | 49 +- src/components/FriendSyncDiagnostics.tsx | 54 +-- src/components/ImageViewerOverlay.tsx | 36 +- src/components/LineAlbumsModal.tsx | 34 +- src/components/LineChatManageModal.tsx | 58 +-- src/components/LineNotesModal.tsx | 52 +-- src/components/LineProfileSettings.tsx | 58 +-- src/components/RichMessage.tsx | 12 +- src/lib/i18n.tsx | 548 +++++++++++++++++++++++ 11 files changed, 993 insertions(+), 383 deletions(-) create mode 100644 engine/i18n-localization.test.ts create mode 100644 src/lib/i18n.tsx diff --git a/engine/i18n-localization.test.ts b/engine/i18n-localization.test.ts new file mode 100644 index 0000000..4be3c2f --- /dev/null +++ b/engine/i18n-localization.test.ts @@ -0,0 +1,22 @@ +import { describe, expect, test } from "bun:test"; +import { translateText } from "../src/lib/i18n"; + +describe("UI translations", () => { + test("keeps Thai text in Thai mode", () => { + expect(translateText("th", "เริ่มแชตใหม่")).toBe("เริ่มแชตใหม่"); + }); + + test("translates common chat navigation labels", () => { + expect(translateText("en", "เพื่อน")).toBe("Friends"); + expect(translateText("en", "รายการโปรด")).toBe("Favorites"); + }); + + test("interpolates values after translation", () => { + expect(translateText("en", "แสดงกลุ่มเก่า ({{count}})", { count: 12 })).toBe("Show archived groups (12)"); + }); + + test("preserves user-provided text without a translation entry", () => { + const userText = "ชื่อเพื่อนที่ผู้ใช้ตั้งเอง"; + expect(translateText("en", userText)).toBe(userText); + }); +}); diff --git a/src/App.tsx b/src/App.tsx index 71e961a..ca6e4e0 100644 --- a/src/App.tsx +++ b/src/App.tsx @@ -67,6 +67,7 @@ import { FriendSyncDiagnostics } from "./components/FriendSyncDiagnostics"; import { LineChatManageModal } from "./components/LineChatManageModal"; import { ImageViewerOverlay } from "./components/ImageViewerOverlay"; import { EngineRequestError, lineyEngine } from "./lib/engine"; +import { LanguageProvider, useAppTranslation } from "./lib/i18n"; import { callMessagePreview, liveMessagePreview, notificationSenderName, officialLineMessageUrl } from "./lib/message-presentation"; import { notificationAvatarUrl, prepareNotificationArtwork } from "./lib/notification-avatar"; import { MarketingSite, type MarketingView } from "./marketing/MarketingSite"; @@ -3569,11 +3570,16 @@ function MainApp() { ); if (usesEngineRuntime && !authenticated) { - return
{renderAuthDialog(true)}
; + return ( + +
{renderAuthDialog(true)}
+
+ ); } return ( -
+ +
{ setSection(next); setListFilter("all"); setMobileConversationOpen(false); setReplyTarget(null); }} onNotifications={() => { setSection("messages"); setListFilter("unread"); setMobileConversationOpen(false); setReplyTarget(null); }} onSettings={() => { setSettingsInitialTab("ทั่วไป"); setSettingsOpen(true); }} onProfile={() => setAuthOpen(true)} authenticated={authenticated} openchatEnabled={settings.openchat} unreadCount={totalUnread} /> -
+
+ ); } @@ -3758,8 +3765,9 @@ function DetachedImageViewer() { function NavRail({ section, onSection, onNotifications, onSettings, onProfile, authenticated, openchatEnabled, unreadCount }: { section: Section; onSection: (s: Section) => void; onNotifications: () => void; onSettings: () => void; onProfile: () => void; authenticated: boolean; openchatEnabled: boolean; unreadCount: number }) { + const { t } = useAppTranslation(); return ( -