feat(ui): translate main component strings to Chinese

- Add i18n to app-render.ts (gateway disconnected message)
- Add i18n to app-render.helpers.ts (theme, chat controls, language selector)
- Add i18n to app-channels.ts (Nostr profile messages)
- Add translation keys for theme, chat controls, gateway, and nostrProfile

https://claude.ai/code/session_01UK3kVX7BRyE1zEHVh3vrFY
This commit is contained in:
Claude 2026-01-29 10:29:30 +00:00
parent cdaf6b86da
commit 0622f2c752
No known key found for this signature in database
5 changed files with 74 additions and 19 deletions

View File

@ -687,6 +687,33 @@ export const enUS = {
light: "Light",
dark: "Dark",
system: "System",
ariaLabel: "Theme",
systemAriaLabel: "System theme",
lightAriaLabel: "Light theme",
darkAriaLabel: "Dark theme",
},
// Chat controls
chatControls: {
disabledDuringOnboarding: "Disabled during onboarding",
toggleThinking: "Toggle assistant thinking/working output",
toggleFocusMode: "Toggle focus mode (hide sidebar + page header)",
selectLanguage: "Select language",
},
// Gateway connection
gateway: {
disconnected: "Disconnected from gateway.",
},
// Nostr profile messages
nostrProfile: {
publishFailed: "Profile publish failed on all relays.",
publishSuccess: "Profile published to relays.",
updateFailed: "Profile update failed",
importFailed: "Profile import failed",
importedFromRelays: "Profile imported from relays. Review and publish.",
importedReviewPublish: "Profile imported. Review and publish.",
},
// Time/date formatting

View File

@ -694,6 +694,33 @@ export const zhTW = {
light: "淺色",
dark: "深色",
system: "跟隨系統",
ariaLabel: "主題",
systemAriaLabel: "跟隨系統主題",
lightAriaLabel: "淺色主題",
darkAriaLabel: "深色主題",
},
// 對話控制
chatControls: {
disabledDuringOnboarding: "引導期間已停用",
toggleThinking: "切換助手思考/工作輸出",
toggleFocusMode: "切換專注模式(隱藏側邊欄和頁首)",
selectLanguage: "選擇語言",
},
// 閘道器連線
gateway: {
disconnected: "已與閘道器斷線。",
},
// Nostr 個人檔案訊息
nostrProfile: {
publishFailed: "個人檔案發布至所有中繼站失敗。",
publishSuccess: "個人檔案已發布至中繼站。",
updateFailed: "個人檔案更新失敗",
importFailed: "個人檔案匯入失敗",
importedFromRelays: "已從中繼站匯入個人檔案。請檢視並發布。",
importedReviewPublish: "已匯入個人檔案。請檢視並發布。",
},
// 時間/日期格式

View File

@ -8,6 +8,7 @@ import { loadConfig, saveConfig } from "./controllers/config";
import type { MoltbotApp } from "./app";
import type { NostrProfile } from "./types";
import { createNostrProfileFormState } from "./views/channels.nostr-profile-form";
import { t } from "../i18n";
export async function handleWhatsAppStart(host: MoltbotApp, force: boolean) {
await startWhatsAppLogin(host, force);
@ -142,7 +143,7 @@ export async function handleNostrProfileSave(host: MoltbotApp) {
host.nostrProfileFormState = {
...state,
saving: false,
error: "Profile publish failed on all relays.",
error: t("nostrProfile.publishFailed"),
success: null,
};
return;
@ -152,7 +153,7 @@ export async function handleNostrProfileSave(host: MoltbotApp) {
...state,
saving: false,
error: null,
success: "Profile published to relays.",
success: t("nostrProfile.publishSuccess"),
fieldErrors: {},
original: { ...state.values },
};
@ -161,7 +162,7 @@ export async function handleNostrProfileSave(host: MoltbotApp) {
host.nostrProfileFormState = {
...state,
saving: false,
error: `Profile update failed: ${String(err)}`,
error: `${t("nostrProfile.updateFailed")}: ${String(err)}`,
success: null,
};
}
@ -214,8 +215,8 @@ export async function handleNostrProfileImport(host: MoltbotApp) {
values: nextValues,
error: null,
success: data.saved
? "Profile imported from relays. Review and publish."
: "Profile imported. Review and publish.",
? t("nostrProfile.importedFromRelays")
: t("nostrProfile.importedReviewPublish"),
showAdvanced,
};
@ -226,7 +227,7 @@ export async function handleNostrProfileImport(host: MoltbotApp) {
host.nostrProfileFormState = {
...state,
importing: false,
error: `Profile import failed: ${String(err)}`,
error: `${t("nostrProfile.importFailed")}: ${String(err)}`,
success: null,
};
}

View File

@ -107,8 +107,8 @@ export function renderChatControls(state: AppViewState) {
}}
aria-pressed=${showThinking}
title=${disableThinkingToggle
? "Disabled during onboarding"
: "Toggle assistant thinking/working output"}
? t("chatControls.disabledDuringOnboarding")
: t("chatControls.toggleThinking")}
>
${icons.brain}
</button>
@ -124,8 +124,8 @@ export function renderChatControls(state: AppViewState) {
}}
aria-pressed=${focusActive}
title=${disableFocusToggle
? "Disabled during onboarding"
: "Toggle focus mode (hide sidebar + page header)"}
? t("chatControls.disabledDuringOnboarding")
: t("chatControls.toggleFocusMode")}
>
${focusIcon}
</button>
@ -172,14 +172,14 @@ export function renderThemeToggle(state: AppViewState) {
return html`
<div class="theme-toggle" style="--theme-index: ${index};">
<div class="theme-toggle__track" role="group" aria-label="Theme">
<div class="theme-toggle__track" role="group" aria-label="${t("theme.ariaLabel")}">
<span class="theme-toggle__indicator"></span>
<button
class="theme-toggle__button ${state.theme === "system" ? "active" : ""}"
@click=${applyTheme("system")}
aria-pressed=${state.theme === "system"}
aria-label="System theme"
title="System"
aria-label="${t("theme.systemAriaLabel")}"
title="${t("theme.system")}"
>
${renderMonitorIcon()}
</button>
@ -187,8 +187,8 @@ export function renderThemeToggle(state: AppViewState) {
class="theme-toggle__button ${state.theme === "light" ? "active" : ""}"
@click=${applyTheme("light")}
aria-pressed=${state.theme === "light"}
aria-label="Light theme"
title="Light"
aria-label="${t("theme.lightAriaLabel")}"
title="${t("theme.light")}"
>
${renderSunIcon()}
</button>
@ -196,8 +196,8 @@ export function renderThemeToggle(state: AppViewState) {
class="theme-toggle__button ${state.theme === "dark" ? "active" : ""}"
@click=${applyTheme("dark")}
aria-pressed=${state.theme === "dark"}
aria-label="Dark theme"
title="Dark"
aria-label="${t("theme.darkAriaLabel")}"
title="${t("theme.dark")}"
>
${renderMoonIcon()}
</button>
@ -263,7 +263,7 @@ export function renderLanguageSwitcher() {
class="language-switcher__select"
.value=${currentLocale}
@change=${handleChange}
aria-label="Select language"
aria-label="${t("chatControls.selectLanguage")}"
>
${locales.map(
(locale) => html`

View File

@ -106,7 +106,7 @@ export function renderApp(state: AppViewState) {
const presenceCount = state.presenceEntries.length;
const sessionsCount = state.sessionsResult?.count ?? null;
const cronNext = state.cronStatus?.nextWakeAtMs ?? null;
const chatDisabledReason = state.connected ? null : "Disconnected from gateway.";
const chatDisabledReason = state.connected ? null : t("gateway.disconnected");
const isChat = state.tab === "chat";
const chatFocus = isChat && (state.settings.chatFocusMode || state.onboarding);
const showThinking = state.onboarding ? false : state.settings.chatShowThinking;