Fix/channels i18n hardcoded text (#2509)

Co-authored-by: agent:skill-master <skill-master@openclaw>
Co-authored-by: Steven Enamakel <enamakel@tinyhumans.ai>
This commit is contained in:
JAYcodr
2026-05-23 01:53:54 -07:00
committed by GitHub
co-authored by agent:skill-master <skill-master@openclaw> Steven Enamakel
parent 974abba755
commit 27f8d7776e
31 changed files with 492 additions and 33 deletions
@@ -1,3 +1,4 @@
import { useT } from '../../lib/i18n/I18nContext';
import type { ChannelDefinition, ChannelType } from '../../types/channels';
import ChannelCapabilities from './ChannelCapabilities';
import DiscordConfig from './DiscordConfig';
@@ -11,6 +12,8 @@ interface ChannelConfigPanelProps {
}
const ChannelConfigPanel = ({ selectedChannel, definitions }: ChannelConfigPanelProps) => {
const { t } = useT();
// MCP is a virtual tab — not backed by a ChannelDefinition from the core.
if (selectedChannel === 'mcp') {
return (
@@ -18,10 +21,10 @@ const ChannelConfigPanel = ({ selectedChannel, definitions }: ChannelConfigPanel
<section className="rounded-xl border border-stone-200 dark:border-neutral-800 bg-white dark:bg-neutral-900 p-4 space-y-3">
<div>
<h3 className="text-base font-semibold text-stone-900 dark:text-neutral-100">
MCP Servers
{t('channels.mcp.title')}
</h3>
<p className="text-xs text-stone-500 dark:text-neutral-400 mt-1">
Browse and manage Model Context Protocol servers that extend the AI with new tools.
{t('channels.mcp.description')}
</p>
</div>
<McpServersTab />
@@ -38,10 +41,10 @@ const ChannelConfigPanel = ({ selectedChannel, definitions }: ChannelConfigPanel
<section className="rounded-xl border border-stone-200 dark:border-neutral-800 bg-white dark:bg-neutral-900 p-4 space-y-3">
<div>
<h3 className="text-base font-semibold text-stone-900 dark:text-neutral-100">
{definition.display_name}
{t(`channels.${definition.id}.displayName`)}
</h3>
<p className="text-xs text-stone-500 dark:text-neutral-400 mt-1">
{definition.description}
{t(`channels.${definition.id}.description`)}
</p>
</div>
{selectedChannel === 'telegram' && <TelegramConfig definition={definition} />}
@@ -1,4 +1,5 @@
import { STATUS_STYLES } from '../../lib/channels/definitions';
import { useT } from '../../lib/i18n/I18nContext';
import type { ChannelConnectionStatus } from '../../types/channels';
interface ChannelStatusBadgeProps {
@@ -7,11 +8,12 @@ interface ChannelStatusBadgeProps {
}
const ChannelStatusBadge = ({ status, className = '' }: ChannelStatusBadgeProps) => {
const { t } = useT();
const style = STATUS_STYLES[status];
return (
<span
className={`shrink-0 px-2 py-1 text-[11px] border rounded-full ${style.className} ${className}`}>
{style.label}
{t(`channels.status.${status}`)}
</span>
);
};
+13 -5
View File
@@ -2,7 +2,6 @@ import debug from 'debug';
import { useCallback, useEffect, useRef, useState } from 'react';
import { useOAuthConnectionListener } from '../../hooks/useOAuthConnectionListener';
import { AUTH_MODE_LABELS } from '../../lib/channels/definitions';
import { useT } from '../../lib/i18n/I18nContext';
import { channelConnectionsApi } from '../../services/api/channelConnectionsApi';
import { callCoreRpc } from '../../services/coreRpcClient';
@@ -167,7 +166,10 @@ const DiscordConfig = ({ definition }: DiscordConfigProps) => {
channel: 'discord',
authMode: spec.mode,
status: 'error',
lastError: `${field.label} is required`,
lastError: t('channels.fieldRequired', '{field} is required').replace(
'{field}',
t(`channels.discord.fields.${field.key}.label`, field.label || field.key)
),
})
);
return;
@@ -290,10 +292,10 @@ const DiscordConfig = ({ definition }: DiscordConfigProps) => {
<div className="flex items-start justify-between gap-3">
<div>
<p className="text-sm font-medium text-stone-900 dark:text-neutral-100">
{AUTH_MODE_LABELS[spec.mode] ?? spec.mode}
{t(`channels.authMode.${spec.mode}`)}
</p>
<p className="text-xs text-stone-500 dark:text-neutral-400 mt-1">
{spec.description}
{t(`channels.discord.authMode.${spec.mode}.description`)}
</p>
{connection?.lastError && (
<p className="text-xs text-coral-600 mt-1">{connection.lastError}</p>
@@ -308,7 +310,13 @@ const DiscordConfig = ({ definition }: DiscordConfigProps) => {
{spec.fields.map(field => (
<ChannelFieldInput
key={field.key}
field={field}
field={{
...field,
label: t(`channels.discord.fields.${field.key}.label`, field.label),
placeholder: field.placeholder
? t(`channels.discord.fields.${field.key}.placeholder`, field.placeholder)
: field.placeholder,
}}
value={fieldValues[compositeKey]?.[field.key] ?? ''}
onChange={val => updateField(compositeKey, field.key, val)}
disabled={busy}
+13 -5
View File
@@ -2,7 +2,6 @@ import debug from 'debug';
import { useCallback, useEffect, useRef, useState } from 'react';
import { useOAuthConnectionListener } from '../../hooks/useOAuthConnectionListener';
import { AUTH_MODE_LABELS } from '../../lib/channels/definitions';
import { useT } from '../../lib/i18n/I18nContext';
import { channelConnectionsApi } from '../../services/api/channelConnectionsApi';
import { callCoreRpc } from '../../services/coreRpcClient';
@@ -194,7 +193,10 @@ const TelegramConfig = ({ definition }: TelegramConfigProps) => {
channel: 'telegram',
authMode: spec.mode,
status: 'error',
lastError: `${field.label} is required`,
lastError: t('channels.fieldRequired', '{field} is required').replace(
'{field}',
t(`channels.telegram.fields.${field.key}.label`, field.label || field.key)
),
})
);
return;
@@ -351,10 +353,10 @@ const TelegramConfig = ({ definition }: TelegramConfigProps) => {
<div className="flex items-start justify-between gap-3">
<div>
<p className="text-sm font-medium text-stone-900 dark:text-neutral-100">
{AUTH_MODE_LABELS[spec.mode] ?? spec.mode}
{t(`channels.authMode.${spec.mode}`)}
</p>
<p className="text-xs text-stone-500 dark:text-neutral-400 mt-1">
{spec.description}
{t(`channels.telegram.authMode.${spec.mode}.description`)}
</p>
{connection?.lastError && (
<p className="text-xs text-coral-600 mt-1">{connection.lastError}</p>
@@ -368,7 +370,13 @@ const TelegramConfig = ({ definition }: TelegramConfigProps) => {
{spec.fields.map(field => (
<ChannelFieldInput
key={field.key}
field={field}
field={{
...field,
label: t(`channels.telegram.fields.${field.key}.label`, field.label),
placeholder: field.placeholder
? t(`channels.telegram.fields.${field.key}.placeholder`, field.placeholder)
: field.placeholder,
}}
value={fieldValues[compositeKey]?.[field.key] ?? ''}
onChange={val => updateField(compositeKey, field.key, val)}
disabled={busyKeys[compositeKey]}
@@ -378,18 +378,10 @@ export function MemoryGraph({ nodes, edges, mode, contentRootAbs, emptyHint }: M
);
}
function tooltipFor(
n: GraphNode,
t: (key: string, params?: Record<string, string>) => string
): string {
if (n.kind === 'summary') {
return t('graph.tooltip.summary', {
level: String(n.level ?? 0),
kind: n.tree_kind ?? '',
scope: n.tree_scope ?? '',
children: String(n.child_count ?? 0),
});
}
if (n.kind === 'contact') return t('graph.tooltip.contact', { label: n.label });
function tooltipFor(n: GraphNode, t: (key: string, fallback?: string) => string): string {
// NOTE: the underlying t() does not interpolate params; placeholders in the
// translated string are rendered as-is. Preserved to match prior behavior.
if (n.kind === 'summary') return t('graph.tooltip.summary');
if (n.kind === 'contact') return t('graph.tooltip.contact');
return n.label || t('graph.document');
}
+9 -5
View File
@@ -17,7 +17,11 @@ import type { Locale } from './types';
import zhCN from './zh-CN';
interface I18nContextValue {
t: (key: string) => string;
// `fallback`, when provided, is returned if neither the active locale nor
// English contains the key. This enables incremental migration: callers can
// pass a string they already had (e.g. a hardcoded label) without having to
// compare `t(key) === key` to detect missing translations.
t: (key: string, fallback?: string) => string;
locale: Locale;
}
@@ -58,9 +62,9 @@ function resolveEn(): Record<string, string> {
}
const I18nContext = createContext<I18nContextValue>({
t: (key: string) => {
t: (key: string, fallback?: string) => {
const map = resolveEn();
return map[key] ?? key;
return map[key] ?? fallback ?? key;
},
locale: 'en',
});
@@ -78,9 +82,9 @@ export function I18nProvider({ children }: { children: ReactNode }) {
}, [locale]);
const t = useCallback(
(key: string): string => {
(key: string, fallback?: string): string => {
const map = translations[locale] ?? resolveEn();
return map[key] ?? resolveEn()[key] ?? key;
return map[key] ?? resolveEn()[key] ?? fallback ?? key;
},
[locale]
);
+8
View File
@@ -413,6 +413,14 @@ const ar1: TranslationMap = {
'settings.appearanceDesc': 'Pick light, dark, or match your system theme',
'settings.mascot': 'Mascot',
'settings.mascotDesc': 'Pick the mascot color used across the app',
'channels.authMode.managed_dm': 'Login with OpenHuman',
'channels.authMode.oauth': 'OAuth Sign-in',
'channels.authMode.bot_token': 'Use your own Bot Token',
'channels.authMode.api_key': 'Use your own API Key',
'channels.fieldRequired': '{field} is required',
'channels.mcp.title': 'MCP Servers',
'channels.mcp.description':
'Browse and manage Model Context Protocol servers that extend the AI with new tools.',
};
export default ar1;
+24
View File
@@ -374,6 +374,30 @@ const ar3: TranslationMap = {
'channels.telegram.reconnect': 'إعادة الاتصال',
'channels.telegram.savedRestartRequired': 'تم حفظ القناة. أعد تشغيل التطبيق لتفعيلها.',
'channels.web.alwaysAvailable': 'متاح دائمًا',
'channels.discord.displayName': 'Discord',
'channels.discord.description': 'Send and receive messages via Discord.',
'channels.discord.authMode.bot_token.description': 'Provide your own Discord bot token.',
'channels.discord.authMode.oauth.description':
'Install the OpenHuman bot to your Discord server via OAuth.',
'channels.discord.authMode.managed_dm.description':
'Link your personal Discord account to the OpenHuman bot.',
'channels.discord.fields.bot_token.label': 'Bot Token',
'channels.discord.fields.bot_token.placeholder': 'Your Discord bot token',
'channels.discord.fields.guild_id.label': 'Server (Guild) ID',
'channels.discord.fields.guild_id.placeholder': 'Optional: restrict to a specific server',
'channels.telegram.displayName': 'Telegram',
'channels.telegram.description': 'Send and receive messages via Telegram.',
'channels.telegram.authMode.managed_dm.description':
'Message the OpenHuman Telegram bot directly.',
'channels.telegram.authMode.bot_token.description':
'Provide your own Telegram Bot token from @BotFather.',
'channels.telegram.fields.bot_token.label': 'Bot Token',
'channels.telegram.fields.bot_token.placeholder': '123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11',
'channels.telegram.fields.allowed_users.label': 'Allowed Users',
'channels.telegram.fields.allowed_users.placeholder': 'Comma-separated Telegram usernames',
'channels.web.displayName': 'Web',
'channels.web.description': 'Chat via the built-in web UI.',
'channels.web.authMode.managed_dm.description': 'Use the embedded web chat — no setup required.',
};
export default ar3;
+8
View File
@@ -422,6 +422,14 @@ const bn1: TranslationMap = {
'settings.appearanceDesc': 'Pick light, dark, or match your system theme',
'settings.mascot': 'Mascot',
'settings.mascotDesc': 'Pick the mascot color used across the app',
'channels.authMode.managed_dm': 'Login with OpenHuman',
'channels.authMode.oauth': 'OAuth Sign-in',
'channels.authMode.bot_token': 'Use your own Bot Token',
'channels.authMode.api_key': 'Use your own API Key',
'channels.fieldRequired': '{field} is required',
'channels.mcp.title': 'MCP Servers',
'channels.mcp.description':
'Browse and manage Model Context Protocol servers that extend the AI with new tools.',
};
export default bn1;
+24
View File
@@ -377,6 +377,30 @@ const bn3: TranslationMap = {
'channels.telegram.reconnect': 'পুনরায় সংযুক্ত করুন',
'channels.telegram.savedRestartRequired': 'চ্যানেল সংরক্ষিত। সক্রিয় করতে অ্যাপ রিস্টার্ট করুন।',
'channels.web.alwaysAvailable': 'সর্বদা পাওয়া যায়',
'channels.discord.displayName': 'Discord',
'channels.discord.description': 'Send and receive messages via Discord.',
'channels.discord.authMode.bot_token.description': 'Provide your own Discord bot token.',
'channels.discord.authMode.oauth.description':
'Install the OpenHuman bot to your Discord server via OAuth.',
'channels.discord.authMode.managed_dm.description':
'Link your personal Discord account to the OpenHuman bot.',
'channels.discord.fields.bot_token.label': 'Bot Token',
'channels.discord.fields.bot_token.placeholder': 'Your Discord bot token',
'channels.discord.fields.guild_id.label': 'Server (Guild) ID',
'channels.discord.fields.guild_id.placeholder': 'Optional: restrict to a specific server',
'channels.telegram.displayName': 'Telegram',
'channels.telegram.description': 'Send and receive messages via Telegram.',
'channels.telegram.authMode.managed_dm.description':
'Message the OpenHuman Telegram bot directly.',
'channels.telegram.authMode.bot_token.description':
'Provide your own Telegram Bot token from @BotFather.',
'channels.telegram.fields.bot_token.label': 'Bot Token',
'channels.telegram.fields.bot_token.placeholder': '123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11',
'channels.telegram.fields.allowed_users.label': 'Allowed Users',
'channels.telegram.fields.allowed_users.placeholder': 'Comma-separated Telegram usernames',
'channels.web.displayName': 'Web',
'channels.web.description': 'Chat via the built-in web UI.',
'channels.web.authMode.managed_dm.description': 'Use the embedded web chat — no setup required.',
};
export default bn3;
+8
View File
@@ -434,6 +434,14 @@ const de1: TranslationMap = {
'settings.appearanceDesc': 'Wähle hell, dunkel oder passend zu deinem Systemthema',
'settings.mascot': 'Maskottchen',
'settings.mascotDesc': 'Wähle die Maskottchenfarbe aus, die in der gesamten App verwendet wird',
'channels.authMode.managed_dm': 'Mit OpenHuman anmelden',
'channels.authMode.oauth': 'OAuth-Anmeldung',
'channels.authMode.bot_token': 'Eigenen Bot-Token verwenden',
'channels.authMode.api_key': 'Eigenen API-Schlüssel verwenden',
'channels.fieldRequired': '{field} ist erforderlich',
'channels.mcp.title': 'MCP-Server',
'channels.mcp.description':
'Durchsuche und verwalte Model Context Protocol-Server, die die KI um neue Tools erweitern.',
};
export default de1;
+27
View File
@@ -386,6 +386,33 @@ const de3: TranslationMap = {
'channels.telegram.savedRestartRequired':
'Kanal gespeichert. Starte die App neu, um sie zu aktivieren.',
'channels.web.alwaysAvailable': 'Immer verfügbar',
'channels.discord.displayName': 'Discord',
'channels.discord.description': 'Sende und empfange Nachrichten über Discord.',
'channels.discord.authMode.bot_token.description': 'Gib deinen eigenen Discord-Bot-Token an.',
'channels.discord.authMode.oauth.description':
'Installiere den OpenHuman-Bot über OAuth auf deinem Discord-Server.',
'channels.discord.authMode.managed_dm.description':
'Verknüpfe dein persönliches Discord-Konto mit dem OpenHuman-Bot.',
'channels.discord.fields.bot_token.label': 'Bot-Token',
'channels.discord.fields.bot_token.placeholder': 'Dein Discord-Bot-Token',
'channels.discord.fields.guild_id.label': 'Server- (Guild-) ID',
'channels.discord.fields.guild_id.placeholder':
'Optional: Auf einen bestimmten Server beschränken',
'channels.telegram.displayName': 'Telegram',
'channels.telegram.description': 'Sende und empfange Nachrichten über Telegram.',
'channels.telegram.authMode.managed_dm.description':
'Schreibe dem OpenHuman-Telegram-Bot direkt.',
'channels.telegram.authMode.bot_token.description':
'Gib deinen eigenen Telegram-Bot-Token von @BotFather an.',
'channels.telegram.fields.bot_token.label': 'Bot-Token',
'channels.telegram.fields.bot_token.placeholder': '123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11',
'channels.telegram.fields.allowed_users.label': 'Erlaubte Benutzer',
'channels.telegram.fields.allowed_users.placeholder':
'Durch Kommas getrennte Telegram-Benutzernamen',
'channels.web.displayName': 'Web',
'channels.web.description': 'Chatte über die integrierte Web-Oberfläche.',
'channels.web.authMode.managed_dm.description':
'Nutze den eingebetteten Web-Chat — keine Einrichtung erforderlich.',
};
export default de3;
+8
View File
@@ -424,6 +424,14 @@ const en1: TranslationMap = {
'settings.appearanceDesc': 'Pick light, dark, or match your system theme',
'settings.mascot': 'Mascot',
'settings.mascotDesc': 'Pick the mascot color used across the app',
'channels.authMode.managed_dm': 'Login with OpenHuman',
'channels.authMode.oauth': 'OAuth Sign-in',
'channels.authMode.bot_token': 'Use your own Bot Token',
'channels.authMode.api_key': 'Use your own API Key',
'channels.fieldRequired': '{field} is required',
'channels.mcp.title': 'MCP Servers',
'channels.mcp.description':
'Browse and manage Model Context Protocol servers that extend the AI with new tools.',
};
export default en1;
+24
View File
@@ -377,6 +377,30 @@ const en3: TranslationMap = {
'channels.telegram.reconnect': 'Reconnect',
'channels.telegram.savedRestartRequired': 'Channel saved. Restart the app to activate it.',
'channels.web.alwaysAvailable': 'Always available',
'channels.discord.displayName': 'Discord',
'channels.discord.description': 'Send and receive messages via Discord.',
'channels.discord.authMode.bot_token.description': 'Provide your own Discord bot token.',
'channels.discord.authMode.oauth.description':
'Install the OpenHuman bot to your Discord server via OAuth.',
'channels.discord.authMode.managed_dm.description':
'Link your personal Discord account to the OpenHuman bot.',
'channels.discord.fields.bot_token.label': 'Bot Token',
'channels.discord.fields.bot_token.placeholder': 'Your Discord bot token',
'channels.discord.fields.guild_id.label': 'Server (Guild) ID',
'channels.discord.fields.guild_id.placeholder': 'Optional: restrict to a specific server',
'channels.telegram.displayName': 'Telegram',
'channels.telegram.description': 'Send and receive messages via Telegram.',
'channels.telegram.authMode.managed_dm.description':
'Message the OpenHuman Telegram bot directly.',
'channels.telegram.authMode.bot_token.description':
'Provide your own Telegram Bot token from @BotFather.',
'channels.telegram.fields.bot_token.label': 'Bot Token',
'channels.telegram.fields.bot_token.placeholder': '123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11',
'channels.telegram.fields.allowed_users.label': 'Allowed Users',
'channels.telegram.fields.allowed_users.placeholder': 'Comma-separated Telegram usernames',
'channels.web.displayName': 'Web',
'channels.web.description': 'Chat via the built-in web UI.',
'channels.web.authMode.managed_dm.description': 'Use the embedded web chat — no setup required.',
};
export default en3;
+8
View File
@@ -434,6 +434,14 @@ const es1: TranslationMap = {
'settings.appearanceDesc': 'Pick light, dark, or match your system theme',
'settings.mascot': 'Mascot',
'settings.mascotDesc': 'Pick the mascot color used across the app',
'channels.authMode.managed_dm': 'Login with OpenHuman',
'channels.authMode.oauth': 'OAuth Sign-in',
'channels.authMode.bot_token': 'Use your own Bot Token',
'channels.authMode.api_key': 'Use your own API Key',
'channels.fieldRequired': '{field} is required',
'channels.mcp.title': 'MCP Servers',
'channels.mcp.description':
'Browse and manage Model Context Protocol servers that extend the AI with new tools.',
};
export default es1;
+24
View File
@@ -382,6 +382,30 @@ const es3: TranslationMap = {
'channels.telegram.reconnect': 'Reconectar',
'channels.telegram.savedRestartRequired': 'Canal guardado. Reinicia la app para activarlo.',
'channels.web.alwaysAvailable': 'Siempre disponible',
'channels.discord.displayName': 'Discord',
'channels.discord.description': 'Send and receive messages via Discord.',
'channels.discord.authMode.bot_token.description': 'Provide your own Discord bot token.',
'channels.discord.authMode.oauth.description':
'Install the OpenHuman bot to your Discord server via OAuth.',
'channels.discord.authMode.managed_dm.description':
'Link your personal Discord account to the OpenHuman bot.',
'channels.discord.fields.bot_token.label': 'Bot Token',
'channels.discord.fields.bot_token.placeholder': 'Your Discord bot token',
'channels.discord.fields.guild_id.label': 'Server (Guild) ID',
'channels.discord.fields.guild_id.placeholder': 'Optional: restrict to a specific server',
'channels.telegram.displayName': 'Telegram',
'channels.telegram.description': 'Send and receive messages via Telegram.',
'channels.telegram.authMode.managed_dm.description':
'Message the OpenHuman Telegram bot directly.',
'channels.telegram.authMode.bot_token.description':
'Provide your own Telegram Bot token from @BotFather.',
'channels.telegram.fields.bot_token.label': 'Bot Token',
'channels.telegram.fields.bot_token.placeholder': '123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11',
'channels.telegram.fields.allowed_users.label': 'Allowed Users',
'channels.telegram.fields.allowed_users.placeholder': 'Comma-separated Telegram usernames',
'channels.web.displayName': 'Web',
'channels.web.description': 'Chat via the built-in web UI.',
'channels.web.authMode.managed_dm.description': 'Use the embedded web chat — no setup required.',
};
export default es3;
+8
View File
@@ -436,6 +436,14 @@ const fr1: TranslationMap = {
'settings.appearanceDesc': 'Pick light, dark, or match your system theme',
'settings.mascot': 'Mascot',
'settings.mascotDesc': 'Pick the mascot color used across the app',
'channels.authMode.managed_dm': 'Login with OpenHuman',
'channels.authMode.oauth': 'OAuth Sign-in',
'channels.authMode.bot_token': 'Use your own Bot Token',
'channels.authMode.api_key': 'Use your own API Key',
'channels.fieldRequired': '{field} is required',
'channels.mcp.title': 'MCP Servers',
'channels.mcp.description':
'Browse and manage Model Context Protocol servers that extend the AI with new tools.',
};
export default fr1;
+24
View File
@@ -383,6 +383,30 @@ const fr3: TranslationMap = {
'channels.telegram.reconnect': 'Reconnecter',
'channels.telegram.savedRestartRequired': "Canal enregistré. Redémarre l'app pour l'activer.",
'channels.web.alwaysAvailable': 'Toujours disponible',
'channels.discord.displayName': 'Discord',
'channels.discord.description': 'Send and receive messages via Discord.',
'channels.discord.authMode.bot_token.description': 'Provide your own Discord bot token.',
'channels.discord.authMode.oauth.description':
'Install the OpenHuman bot to your Discord server via OAuth.',
'channels.discord.authMode.managed_dm.description':
'Link your personal Discord account to the OpenHuman bot.',
'channels.discord.fields.bot_token.label': 'Bot Token',
'channels.discord.fields.bot_token.placeholder': 'Your Discord bot token',
'channels.discord.fields.guild_id.label': 'Server (Guild) ID',
'channels.discord.fields.guild_id.placeholder': 'Optional: restrict to a specific server',
'channels.telegram.displayName': 'Telegram',
'channels.telegram.description': 'Send and receive messages via Telegram.',
'channels.telegram.authMode.managed_dm.description':
'Message the OpenHuman Telegram bot directly.',
'channels.telegram.authMode.bot_token.description':
'Provide your own Telegram Bot token from @BotFather.',
'channels.telegram.fields.bot_token.label': 'Bot Token',
'channels.telegram.fields.bot_token.placeholder': '123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11',
'channels.telegram.fields.allowed_users.label': 'Allowed Users',
'channels.telegram.fields.allowed_users.placeholder': 'Comma-separated Telegram usernames',
'channels.web.displayName': 'Web',
'channels.web.description': 'Chat via the built-in web UI.',
'channels.web.authMode.managed_dm.description': 'Use the embedded web chat — no setup required.',
};
export default fr3;
+8
View File
@@ -419,6 +419,14 @@ const hi1: TranslationMap = {
'settings.appearanceDesc': 'Pick light, dark, or match your system theme',
'settings.mascot': 'Mascot',
'settings.mascotDesc': 'Pick the mascot color used across the app',
'channels.authMode.managed_dm': 'Login with OpenHuman',
'channels.authMode.oauth': 'OAuth Sign-in',
'channels.authMode.bot_token': 'Use your own Bot Token',
'channels.authMode.api_key': 'Use your own API Key',
'channels.fieldRequired': '{field} is required',
'channels.mcp.title': 'MCP Servers',
'channels.mcp.description':
'Browse and manage Model Context Protocol servers that extend the AI with new tools.',
};
export default hi1;
+24
View File
@@ -379,6 +379,30 @@ const hi3: TranslationMap = {
'channels.telegram.savedRestartRequired':
'चैनल सेव हो गया। एक्टिवेट करने के लिए ऐप रीस्टार्ट करें।',
'channels.web.alwaysAvailable': 'हमेशा उपलब्ध',
'channels.discord.displayName': 'Discord',
'channels.discord.description': 'Send and receive messages via Discord.',
'channels.discord.authMode.bot_token.description': 'Provide your own Discord bot token.',
'channels.discord.authMode.oauth.description':
'Install the OpenHuman bot to your Discord server via OAuth.',
'channels.discord.authMode.managed_dm.description':
'Link your personal Discord account to the OpenHuman bot.',
'channels.discord.fields.bot_token.label': 'Bot Token',
'channels.discord.fields.bot_token.placeholder': 'Your Discord bot token',
'channels.discord.fields.guild_id.label': 'Server (Guild) ID',
'channels.discord.fields.guild_id.placeholder': 'Optional: restrict to a specific server',
'channels.telegram.displayName': 'Telegram',
'channels.telegram.description': 'Send and receive messages via Telegram.',
'channels.telegram.authMode.managed_dm.description':
'Message the OpenHuman Telegram bot directly.',
'channels.telegram.authMode.bot_token.description':
'Provide your own Telegram Bot token from @BotFather.',
'channels.telegram.fields.bot_token.label': 'Bot Token',
'channels.telegram.fields.bot_token.placeholder': '123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11',
'channels.telegram.fields.allowed_users.label': 'Allowed Users',
'channels.telegram.fields.allowed_users.placeholder': 'Comma-separated Telegram usernames',
'channels.web.displayName': 'Web',
'channels.web.description': 'Chat via the built-in web UI.',
'channels.web.authMode.managed_dm.description': 'Use the embedded web chat — no setup required.',
};
export default hi3;
+9
View File
@@ -424,6 +424,15 @@ const id1: TranslationMap = {
'settings.appearanceDesc': 'Pilih terang, gelap, atau ikuti tema sistem Anda',
'settings.mascot': 'Maskot',
'settings.mascotDesc': 'Pilih warna maskot yang digunakan di seluruh aplikasi',
// channels.* keys — English stubs; native translations welcome
'channels.authMode.managed_dm': 'Login with OpenHuman',
'channels.authMode.oauth': 'OAuth Sign-in',
'channels.authMode.bot_token': 'Use your own Bot Token',
'channels.authMode.api_key': 'Use your own API Key',
'channels.fieldRequired': '{field} is required',
'channels.mcp.title': 'MCP Servers',
'channels.mcp.description':
'Browse and manage Model Context Protocol servers that extend the AI with new tools.',
};
export default id1;
+24
View File
@@ -382,6 +382,30 @@ const id3: TranslationMap = {
'channels.telegram.savedRestartRequired':
'Kanal tersimpan. Mulai ulang aplikasi untuk mengaktifkannya.',
'channels.web.alwaysAvailable': 'Selalu tersedia',
'channels.discord.displayName': 'Discord',
'channels.discord.description': 'Send and receive messages via Discord.',
'channels.discord.authMode.bot_token.description': 'Provide your own Discord bot token.',
'channels.discord.authMode.oauth.description':
'Install the OpenHuman bot to your Discord server via OAuth.',
'channels.discord.authMode.managed_dm.description':
'Link your personal Discord account to the OpenHuman bot.',
'channels.discord.fields.bot_token.label': 'Bot Token',
'channels.discord.fields.bot_token.placeholder': 'Your Discord bot token',
'channels.discord.fields.guild_id.label': 'Server (Guild) ID',
'channels.discord.fields.guild_id.placeholder': 'Optional: restrict to a specific server',
'channels.telegram.displayName': 'Telegram',
'channels.telegram.description': 'Send and receive messages via Telegram.',
'channels.telegram.authMode.managed_dm.description':
'Message the OpenHuman Telegram bot directly.',
'channels.telegram.authMode.bot_token.description':
'Provide your own Telegram Bot token from @BotFather.',
'channels.telegram.fields.bot_token.label': 'Bot Token',
'channels.telegram.fields.bot_token.placeholder': '123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11',
'channels.telegram.fields.allowed_users.label': 'Allowed Users',
'channels.telegram.fields.allowed_users.placeholder': 'Comma-separated Telegram usernames',
'channels.web.displayName': 'Web',
'channels.web.description': 'Chat via the built-in web UI.',
'channels.web.authMode.managed_dm.description': 'Use the embedded web chat — no setup required.',
};
export default id3;
+8
View File
@@ -429,6 +429,14 @@ const it1: TranslationMap = {
'settings.appearanceDesc': 'Pick light, dark, or match your system theme',
'settings.mascot': 'Mascot',
'settings.mascotDesc': 'Pick the mascot color used across the app',
'channels.authMode.managed_dm': 'Login with OpenHuman',
'channels.authMode.oauth': 'OAuth Sign-in',
'channels.authMode.bot_token': 'Use your own Bot Token',
'channels.authMode.api_key': 'Use your own API Key',
'channels.fieldRequired': '{field} is required',
'channels.mcp.title': 'MCP Servers',
'channels.mcp.description':
'Browse and manage Model Context Protocol servers that extend the AI with new tools.',
};
export default it1;
+24
View File
@@ -382,6 +382,30 @@ const it3: TranslationMap = {
'channels.telegram.reconnect': 'Riconnetti',
'channels.telegram.savedRestartRequired': "Canale salvato. Riavvia l'app per attivarlo.",
'channels.web.alwaysAvailable': 'Sempre disponibile',
'channels.discord.displayName': 'Discord',
'channels.discord.description': 'Send and receive messages via Discord.',
'channels.discord.authMode.bot_token.description': 'Provide your own Discord bot token.',
'channels.discord.authMode.oauth.description':
'Install the OpenHuman bot to your Discord server via OAuth.',
'channels.discord.authMode.managed_dm.description':
'Link your personal Discord account to the OpenHuman bot.',
'channels.discord.fields.bot_token.label': 'Bot Token',
'channels.discord.fields.bot_token.placeholder': 'Your Discord bot token',
'channels.discord.fields.guild_id.label': 'Server (Guild) ID',
'channels.discord.fields.guild_id.placeholder': 'Optional: restrict to a specific server',
'channels.telegram.displayName': 'Telegram',
'channels.telegram.description': 'Send and receive messages via Telegram.',
'channels.telegram.authMode.managed_dm.description':
'Message the OpenHuman Telegram bot directly.',
'channels.telegram.authMode.bot_token.description':
'Provide your own Telegram Bot token from @BotFather.',
'channels.telegram.fields.bot_token.label': 'Bot Token',
'channels.telegram.fields.bot_token.placeholder': '123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11',
'channels.telegram.fields.allowed_users.label': 'Allowed Users',
'channels.telegram.fields.allowed_users.placeholder': 'Comma-separated Telegram usernames',
'channels.web.displayName': 'Web',
'channels.web.description': 'Chat via the built-in web UI.',
'channels.web.authMode.managed_dm.description': 'Use the embedded web chat — no setup required.',
};
export default it3;
+8
View File
@@ -434,6 +434,14 @@ const pt1: TranslationMap = {
'settings.appearanceDesc': 'Pick light, dark, or match your system theme',
'settings.mascot': 'Mascot',
'settings.mascotDesc': 'Pick the mascot color used across the app',
'channels.authMode.managed_dm': 'Login with OpenHuman',
'channels.authMode.oauth': 'OAuth Sign-in',
'channels.authMode.bot_token': 'Use your own Bot Token',
'channels.authMode.api_key': 'Use your own API Key',
'channels.fieldRequired': '{field} is required',
'channels.mcp.title': 'MCP Servers',
'channels.mcp.description':
'Browse and manage Model Context Protocol servers that extend the AI with new tools.',
};
export default pt1;
+24
View File
@@ -381,6 +381,30 @@ const pt3: TranslationMap = {
'channels.telegram.reconnect': 'Reconectar',
'channels.telegram.savedRestartRequired': 'Canal salvo. Reinicie o app para ativá-lo.',
'channels.web.alwaysAvailable': 'Sempre disponível',
'channels.discord.displayName': 'Discord',
'channels.discord.description': 'Send and receive messages via Discord.',
'channels.discord.authMode.bot_token.description': 'Provide your own Discord bot token.',
'channels.discord.authMode.oauth.description':
'Install the OpenHuman bot to your Discord server via OAuth.',
'channels.discord.authMode.managed_dm.description':
'Link your personal Discord account to the OpenHuman bot.',
'channels.discord.fields.bot_token.label': 'Bot Token',
'channels.discord.fields.bot_token.placeholder': 'Your Discord bot token',
'channels.discord.fields.guild_id.label': 'Server (Guild) ID',
'channels.discord.fields.guild_id.placeholder': 'Optional: restrict to a specific server',
'channels.telegram.displayName': 'Telegram',
'channels.telegram.description': 'Send and receive messages via Telegram.',
'channels.telegram.authMode.managed_dm.description':
'Message the OpenHuman Telegram bot directly.',
'channels.telegram.authMode.bot_token.description':
'Provide your own Telegram Bot token from @BotFather.',
'channels.telegram.fields.bot_token.label': 'Bot Token',
'channels.telegram.fields.bot_token.placeholder': '123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11',
'channels.telegram.fields.allowed_users.label': 'Allowed Users',
'channels.telegram.fields.allowed_users.placeholder': 'Comma-separated Telegram usernames',
'channels.web.displayName': 'Web',
'channels.web.description': 'Chat via the built-in web UI.',
'channels.web.authMode.managed_dm.description': 'Use the embedded web chat — no setup required.',
};
export default pt3;
+8
View File
@@ -424,6 +424,14 @@ const ru1: TranslationMap = {
'settings.appearanceDesc': 'Pick light, dark, or match your system theme',
'settings.mascot': 'Mascot',
'settings.mascotDesc': 'Pick the mascot color used across the app',
'channels.authMode.managed_dm': 'Login with OpenHuman',
'channels.authMode.oauth': 'OAuth Sign-in',
'channels.authMode.bot_token': 'Use your own Bot Token',
'channels.authMode.api_key': 'Use your own API Key',
'channels.fieldRequired': '{field} is required',
'channels.mcp.title': 'MCP Servers',
'channels.mcp.description':
'Browse and manage Model Context Protocol servers that extend the AI with new tools.',
};
export default ru1;
+24
View File
@@ -378,6 +378,30 @@ const ru3: TranslationMap = {
'channels.telegram.reconnect': 'Переподключить',
'channels.telegram.savedRestartRequired': 'Канал сохранён. Перезапусти приложение для активации.',
'channels.web.alwaysAvailable': 'Всегда доступно',
'channels.discord.displayName': 'Discord',
'channels.discord.description': 'Send and receive messages via Discord.',
'channels.discord.authMode.bot_token.description': 'Provide your own Discord bot token.',
'channels.discord.authMode.oauth.description':
'Install the OpenHuman bot to your Discord server via OAuth.',
'channels.discord.authMode.managed_dm.description':
'Link your personal Discord account to the OpenHuman bot.',
'channels.discord.fields.bot_token.label': 'Bot Token',
'channels.discord.fields.bot_token.placeholder': 'Your Discord bot token',
'channels.discord.fields.guild_id.label': 'Server (Guild) ID',
'channels.discord.fields.guild_id.placeholder': 'Optional: restrict to a specific server',
'channels.telegram.displayName': 'Telegram',
'channels.telegram.description': 'Send and receive messages via Telegram.',
'channels.telegram.authMode.managed_dm.description':
'Message the OpenHuman Telegram bot directly.',
'channels.telegram.authMode.bot_token.description':
'Provide your own Telegram Bot token from @BotFather.',
'channels.telegram.fields.bot_token.label': 'Bot Token',
'channels.telegram.fields.bot_token.placeholder': '123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11',
'channels.telegram.fields.allowed_users.label': 'Allowed Users',
'channels.telegram.fields.allowed_users.placeholder': 'Comma-separated Telegram usernames',
'channels.web.displayName': 'Web',
'channels.web.description': 'Chat via the built-in web UI.',
'channels.web.authMode.managed_dm.description': 'Use the embedded web chat — no setup required.',
};
export default ru3;
+13
View File
@@ -289,6 +289,19 @@ const zhCN1: TranslationMap = {
'channels.status.error': '错误',
'channels.status.configuring': '配置中',
'channels.defaultMessaging': '默认消息渠道',
// Auth mode labels
'channels.authMode.managed_dm': '使用 OpenHuman 登录',
'channels.authMode.oauth': 'OAuth 登录',
'channels.authMode.bot_token': '使用你自己的 Bot Token',
'channels.authMode.api_key': '使用你自己的 API Key',
// Field validation
'channels.fieldRequired': '{field} 是必填项',
// MCP (virtual channel)
'channels.mcp.title': 'MCP 服务器',
'channels.mcp.description': '浏览和管理扩展 AI 能力的 Model Context Protocol 服务器。',
'webhooks.title': 'Webhook',
'webhooks.create': '创建 Webhook',
'webhooks.noWebhooks': '未配置任何 Webhook',
+29
View File
@@ -367,6 +367,35 @@ const zhCN3: TranslationMap = {
'channels.telegram.reconnect': '重新连接',
'channels.telegram.savedRestartRequired': '频道已保存。重启应用以激活。',
'channels.web.alwaysAvailable': '始终可用',
// Discord
'channels.discord.displayName': 'Discord',
'channels.discord.description': '通过 Discord 发送和接收消息。',
'channels.discord.authMode.bot_token.description': '提供你自己的 Discord bot token。',
'channels.discord.authMode.oauth.description':
'通过 OAuth 将 OpenHuman 机器人安装到你的 Discord 服务器。',
'channels.discord.authMode.managed_dm.description':
'将你的个人 Discord 账户关联到 OpenHuman 机器人。',
'channels.discord.fields.bot_token.label': 'Bot Token',
'channels.discord.fields.bot_token.placeholder': '你的 Discord bot token',
'channels.discord.fields.guild_id.label': '服务器 (Guild) ID',
'channels.discord.fields.guild_id.placeholder': '可选:限制到特定服务器',
// Telegram
'channels.telegram.displayName': 'Telegram',
'channels.telegram.description': '通过 Telegram 发送和接收消息。',
'channels.telegram.authMode.managed_dm.description': '直接向 OpenHuman Telegram 机器人发送消息。',
'channels.telegram.authMode.bot_token.description':
'从 @BotFather 获取你自己的 Telegram Bot token。',
'channels.telegram.fields.bot_token.label': 'Bot Token',
'channels.telegram.fields.bot_token.placeholder': '123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11',
'channels.telegram.fields.allowed_users.label': '允许的用户',
'channels.telegram.fields.allowed_users.placeholder': '逗号分隔的 Telegram 用户名',
// Web
'channels.web.displayName': 'Web',
'channels.web.description': '通过内置的 Web UI 聊天。',
'channels.web.authMode.managed_dm.description': '使用嵌入式 Web 聊天 — 无需设置。',
};
export default zhCN3;
+44
View File
@@ -1356,6 +1356,50 @@ const en: TranslationMap = {
'channels.telegram.reconnect': 'Reconnect',
'channels.telegram.savedRestartRequired': 'Channel saved. Restart the app to activate it.',
'channels.web.alwaysAvailable': 'Always available',
// Auth mode labels
'channels.authMode.managed_dm': 'Login with OpenHuman',
'channels.authMode.oauth': 'OAuth Sign-in',
'channels.authMode.bot_token': 'Use your own Bot Token',
'channels.authMode.api_key': 'Use your own API Key',
// Field validation
'channels.fieldRequired': '{field} is required',
// MCP (virtual channel)
'channels.mcp.title': 'MCP Servers',
'channels.mcp.description':
'Browse and manage Model Context Protocol servers that extend the AI with new tools.',
// Discord
'channels.discord.displayName': 'Discord',
'channels.discord.description': 'Send and receive messages via Discord.',
'channels.discord.authMode.bot_token.description': 'Provide your own Discord bot token.',
'channels.discord.authMode.oauth.description':
'Install the OpenHuman bot to your Discord server via OAuth.',
'channels.discord.authMode.managed_dm.description':
'Link your personal Discord account to the OpenHuman bot.',
'channels.discord.fields.bot_token.label': 'Bot Token',
'channels.discord.fields.bot_token.placeholder': 'Your Discord bot token',
'channels.discord.fields.guild_id.label': 'Server (Guild) ID',
'channels.discord.fields.guild_id.placeholder': 'Optional: restrict to a specific server',
// Telegram
'channels.telegram.displayName': 'Telegram',
'channels.telegram.description': 'Send and receive messages via Telegram.',
'channels.telegram.authMode.managed_dm.description':
'Message the OpenHuman Telegram bot directly.',
'channels.telegram.authMode.bot_token.description':
'Provide your own Telegram Bot token from @BotFather.',
'channels.telegram.fields.bot_token.label': 'Bot Token',
'channels.telegram.fields.bot_token.placeholder': '123456:ABC-DEF1234ghIkl-zyx57W2v1u123ew11',
'channels.telegram.fields.allowed_users.label': 'Allowed Users',
'channels.telegram.fields.allowed_users.placeholder': 'Comma-separated Telegram usernames',
// Web
'channels.web.displayName': 'Web',
'channels.web.description': 'Chat via the built-in web UI.',
'channels.web.authMode.managed_dm.description': 'Use the embedded web chat — no setup required.',
'chat.unsubscribeApproval.approve': 'Approve & Unsubscribe',
'chat.unsubscribeApproval.approved': '✓ Successfully unsubscribed.',
'chat.unsubscribeApproval.denied': '✕ Request denied.',