mirror of
https://github.com/openclaw/openclaw.git
synced 2026-07-21 10:16:44 +00:00
fix(ui): localize channel and session views
This commit is contained in:
@@ -93,11 +93,13 @@ function renderChannelConfigForm(props: ChannelConfigFormProps) {
|
||||
const analysis = analyzeConfigSchema(props.schema);
|
||||
const normalized = analysis.schema;
|
||||
if (!normalized) {
|
||||
return html` <div class="callout danger">Schema unavailable. Use Raw.</div> `;
|
||||
return html` <div class="callout danger">${t("channels.config.schemaUnavailable")}</div> `;
|
||||
}
|
||||
const node = resolveSchemaNode(normalized, ["channels", props.channelId]);
|
||||
if (!node) {
|
||||
return html` <div class="callout danger">Channel config schema unavailable.</div> `;
|
||||
return html`
|
||||
<div class="callout danger">${t("channels.config.channelSchemaUnavailable")}</div>
|
||||
`;
|
||||
}
|
||||
const configValue = props.configValue ?? {};
|
||||
const value = resolveChannelValue(configValue, props.channelId);
|
||||
@@ -124,7 +126,7 @@ export function renderChannelConfigSection(params: { channelId: string; props: C
|
||||
return html`
|
||||
<div style="margin-top: 16px;">
|
||||
${props.configSchemaLoading
|
||||
? html` <div class="muted">Loading config schema…</div> `
|
||||
? html` <div class="muted">${t("channels.config.loadingSchema")}</div> `
|
||||
: renderChannelConfigForm({
|
||||
channelId,
|
||||
configValue: props.configForm,
|
||||
@@ -139,7 +141,7 @@ export function renderChannelConfigSection(params: { channelId: string; props: C
|
||||
?disabled=${disabled || !props.configFormDirty}
|
||||
@click=${() => props.onConfigSave()}
|
||||
>
|
||||
${props.configSaving ? "Saving…" : "Save"}
|
||||
${props.configSaving ? t("common.saving") : t("common.save")}
|
||||
</button>
|
||||
<button class="btn" ?disabled=${disabled} @click=${() => props.onConfigReload()}>
|
||||
${t("common.reload")}
|
||||
|
||||
@@ -20,8 +20,8 @@ export function renderDiscordCard(params: {
|
||||
const configured = resolveChannelConfigured("discord", props);
|
||||
|
||||
return renderSingleAccountChannelCard({
|
||||
title: "Discord",
|
||||
subtitle: "Bot status and channel configuration.",
|
||||
title: t("channels.discord.title"),
|
||||
subtitle: t("channels.discord.subtitle"),
|
||||
accountCountLabel,
|
||||
statusRows: [
|
||||
{ label: t("common.configured"), value: formatNullableBoolean(configured) },
|
||||
|
||||
@@ -20,8 +20,8 @@ export function renderGoogleChatCard(params: {
|
||||
const configured = resolveChannelConfigured("googlechat", props);
|
||||
|
||||
return renderSingleAccountChannelCard({
|
||||
title: "Google Chat",
|
||||
subtitle: "Chat API webhook status and channel configuration.",
|
||||
title: t("channels.googleChat.title"),
|
||||
subtitle: t("channels.googleChat.subtitle"),
|
||||
accountCountLabel,
|
||||
statusRows: [
|
||||
{ label: t("common.configured"), value: formatNullableBoolean(configured) },
|
||||
|
||||
@@ -20,8 +20,8 @@ export function renderIMessageCard(params: {
|
||||
const configured = resolveChannelConfigured("imessage", props);
|
||||
|
||||
return renderSingleAccountChannelCard({
|
||||
title: "iMessage",
|
||||
subtitle: "macOS bridge status and channel configuration.",
|
||||
title: t("channels.imessage.title"),
|
||||
subtitle: t("channels.imessage.subtitle"),
|
||||
accountCountLabel,
|
||||
statusRows: [
|
||||
{ label: t("common.configured"), value: formatNullableBoolean(configured) },
|
||||
|
||||
@@ -202,12 +202,12 @@ export function renderNostrProfileForm(params: {
|
||||
: nothing}
|
||||
${renderPicturePreview()}
|
||||
${renderField("name", t("channels.nostr.username"), {
|
||||
placeholder: "satoshi",
|
||||
placeholder: t("channels.nostr.placeholders.username"),
|
||||
maxLength: 256,
|
||||
help: t("channels.nostr.usernameHelp"),
|
||||
})}
|
||||
${renderField("displayName", t("channels.nostr.displayName"), {
|
||||
placeholder: "Satoshi Nakamoto",
|
||||
placeholder: t("channels.nostr.placeholders.displayName"),
|
||||
maxLength: 256,
|
||||
help: t("channels.nostr.displayNameHelp"),
|
||||
})}
|
||||
@@ -219,7 +219,7 @@ export function renderNostrProfileForm(params: {
|
||||
})}
|
||||
${renderField("picture", t("channels.nostr.avatarUrl"), {
|
||||
type: "url",
|
||||
placeholder: "https://example.com/avatar.jpg",
|
||||
placeholder: t("channels.nostr.placeholders.avatarUrl"),
|
||||
help: t("channels.nostr.avatarHelp"),
|
||||
})}
|
||||
${state.showAdvanced
|
||||
@@ -233,20 +233,20 @@ export function renderNostrProfileForm(params: {
|
||||
|
||||
${renderField("banner", t("channels.nostr.bannerUrl"), {
|
||||
type: "url",
|
||||
placeholder: "https://example.com/banner.jpg",
|
||||
placeholder: t("channels.nostr.placeholders.bannerUrl"),
|
||||
help: t("channels.nostr.bannerHelp"),
|
||||
})}
|
||||
${renderField("website", t("channels.nostr.website"), {
|
||||
type: "url",
|
||||
placeholder: "https://example.com",
|
||||
placeholder: t("channels.nostr.placeholders.website"),
|
||||
help: t("channels.nostr.websiteHelp"),
|
||||
})}
|
||||
${renderField("nip05", t("channels.nostr.nip05Identifier"), {
|
||||
placeholder: "you@example.com",
|
||||
placeholder: t("channels.nostr.placeholders.nip05"),
|
||||
help: t("channels.nostr.nip05Help"),
|
||||
})}
|
||||
${renderField("lud16", t("channels.nostr.lightningAddress"), {
|
||||
placeholder: "you@getalby.com",
|
||||
placeholder: t("channels.nostr.placeholders.lightningAddress"),
|
||||
help: t("channels.nostr.lightningHelp"),
|
||||
})}
|
||||
</div>
|
||||
|
||||
@@ -194,8 +194,8 @@ export function renderNostrCard(params: {
|
||||
|
||||
return html`
|
||||
<div class="card">
|
||||
<div class="card-title">Nostr</div>
|
||||
<div class="card-sub">Decentralized DMs via Nostr relays (NIP-04).</div>
|
||||
<div class="card-title">${t("channels.nostr.title")}</div>
|
||||
<div class="card-sub">${t("channels.nostr.subtitle")}</div>
|
||||
${accountCountLabel}
|
||||
${hasMultipleAccounts
|
||||
? html`
|
||||
|
||||
@@ -20,8 +20,8 @@ export function renderSignalCard(params: {
|
||||
const configured = resolveChannelConfigured("signal", props);
|
||||
|
||||
return renderSingleAccountChannelCard({
|
||||
title: "Signal",
|
||||
subtitle: "signal-cli status and channel configuration.",
|
||||
title: t("channels.signal.title"),
|
||||
subtitle: t("channels.signal.subtitle"),
|
||||
accountCountLabel,
|
||||
statusRows: [
|
||||
{ label: t("common.configured"), value: formatNullableBoolean(configured) },
|
||||
|
||||
@@ -20,8 +20,8 @@ export function renderSlackCard(params: {
|
||||
const configured = resolveChannelConfigured("slack", props);
|
||||
|
||||
return renderSingleAccountChannelCard({
|
||||
title: "Slack",
|
||||
subtitle: "Socket mode status and channel configuration.",
|
||||
title: t("channels.slack.title"),
|
||||
subtitle: t("channels.slack.subtitle"),
|
||||
accountCountLabel,
|
||||
statusRows: [
|
||||
{ label: t("common.configured"), value: formatNullableBoolean(configured) },
|
||||
|
||||
@@ -59,8 +59,8 @@ export function renderTelegramCard(params: {
|
||||
if (hasMultipleAccounts) {
|
||||
return html`
|
||||
<div class="card">
|
||||
<div class="card-title">Telegram</div>
|
||||
<div class="card-sub">Bot status and channel configuration.</div>
|
||||
<div class="card-title">${t("channels.telegram.title")}</div>
|
||||
<div class="card-sub">${t("channels.telegram.subtitle")}</div>
|
||||
${accountCountLabel}
|
||||
|
||||
<div class="account-card-list">
|
||||
@@ -86,8 +86,8 @@ export function renderTelegramCard(params: {
|
||||
}
|
||||
|
||||
return renderSingleAccountChannelCard({
|
||||
title: "Telegram",
|
||||
subtitle: "Bot status and channel configuration.",
|
||||
title: t("channels.telegram.title"),
|
||||
subtitle: t("channels.telegram.subtitle"),
|
||||
accountCountLabel,
|
||||
statusRows: [
|
||||
{ label: t("common.configured"), value: formatNullableBoolean(configured) },
|
||||
|
||||
@@ -89,7 +89,7 @@ export function renderChannels(props: ChannelsProps) {
|
||||
${showingStaleSnapshot
|
||||
? html`
|
||||
<div class="callout info" style="margin-top: 12px;">
|
||||
Refreshing channel status in the background; showing the last successful snapshot.
|
||||
${t("channels.refreshingStaleSnapshot")}
|
||||
</div>
|
||||
`
|
||||
: nothing}
|
||||
|
||||
@@ -22,8 +22,8 @@ export function renderWhatsAppCard(params: {
|
||||
const hasQr = props.whatsappQrDataUrl != null;
|
||||
|
||||
return renderSingleAccountChannelCard({
|
||||
title: "WhatsApp",
|
||||
subtitle: "Link WhatsApp Web and monitor connection health.",
|
||||
title: t("channels.whatsapp.title"),
|
||||
subtitle: t("channels.whatsapp.subtitle"),
|
||||
accountCountLabel,
|
||||
statusRows: [
|
||||
{ label: t("common.configured"), value: formatNullableBoolean(configured) },
|
||||
|
||||
@@ -941,7 +941,10 @@ export function renderSessions(props: SessionsProps) {
|
||||
: nothing}
|
||||
|
||||
<div class="data-table-wrapper">
|
||||
<div class="sessions-toolbar sessions-filter-bar" aria-label="Session filters">
|
||||
<div
|
||||
class="sessions-toolbar sessions-filter-bar"
|
||||
aria-label=${t("sessionsView.filterControls")}
|
||||
>
|
||||
<div class="data-table-search sessions-toolbar__search">
|
||||
${icons.search}
|
||||
<input
|
||||
@@ -1176,8 +1179,11 @@ export function renderSessions(props: SessionsProps) {
|
||||
? html`
|
||||
<div class="data-table-pagination">
|
||||
<div class="data-table-pagination__info">
|
||||
${page * props.pageSize + 1}-${Math.min((page + 1) * props.pageSize, totalRows)}
|
||||
of ${totalRows} row${totalRows === 1 ? "" : "s"}
|
||||
${t("sessionsView.pagination", {
|
||||
start: String(page * props.pageSize + 1),
|
||||
end: String(Math.min((page + 1) * props.pageSize, totalRows)),
|
||||
total: String(totalRows),
|
||||
})}
|
||||
</div>
|
||||
<div class="data-table-pagination__controls">
|
||||
<select
|
||||
@@ -1186,10 +1192,15 @@ export function renderSessions(props: SessionsProps) {
|
||||
@change=${(e: Event) =>
|
||||
props.onPageSizeChange(Number((e.target as HTMLSelectElement).value))}
|
||||
>
|
||||
${PAGE_SIZES.map((s) => html`<option value=${s}>${s} per page</option>`)}
|
||||
${PAGE_SIZES.map(
|
||||
(s) =>
|
||||
html`<option value=${s}>
|
||||
${t("sessionsView.rowsPerPage", { count: String(s) })}
|
||||
</option>`,
|
||||
)}
|
||||
</select>
|
||||
<button ?disabled=${page <= 0} @click=${() => props.onPageChange(page - 1)}>
|
||||
Previous
|
||||
${t("common.previous")}
|
||||
</button>
|
||||
<button
|
||||
?disabled=${page >= totalPages - 1}
|
||||
|
||||
Reference in New Issue
Block a user