Implement internationalization support by adding translation functionality and updating UI components to use translated strings. Add language configuration in .env.example and integrate translations across various strategy and UI components.

This commit is contained in:
discountry
2025-12-09 00:35:28 +08:00
parent 03df1006cc
commit 85e7f245c0
17 changed files with 1166 additions and 295 deletions
+39 -16
View File
@@ -6,12 +6,13 @@ import { buildAdapterFromEnv } from "../exchanges/resolve-from-env";
import { GuardianEngine, type GuardianEngineSnapshot } from "../strategy/guardian-engine";
import { formatNumber } from "../utils/format";
import { DataTable, type TableColumn } from "./components/DataTable";
import { t } from "../i18n";
interface GuardianAppProps {
onExit: () => void;
}
const READY_MESSAGE = "正在等待行情/账户推送…";
const READY_MESSAGE = t("guardian.readyMessage");
const inputSupported = Boolean(process.stdin && (process.stdin as any).isTTY);
export function GuardianApp({ onExit }: GuardianAppProps) {
@@ -55,8 +56,8 @@ export function GuardianApp({ onExit }: GuardianAppProps) {
if (error) {
return (
<Box flexDirection="column" padding={1}>
<Text color="red">Guardian : {error.message}</Text>
<Text color="gray"></Text>
<Text color="red">{t("guardian.startFailed", { message: error.message })}</Text>
<Text color="gray">{t("common.checkEnv")}</Text>
</Box>
);
}
@@ -64,7 +65,7 @@ export function GuardianApp({ onExit }: GuardianAppProps) {
if (!snapshot) {
return (
<Box padding={1}>
<Text> Guardian </Text>
<Text>{t("guardian.initializing")}</Text>
</Box>
);
}
@@ -97,43 +98,65 @@ export function GuardianApp({ onExit }: GuardianAppProps) {
return (
<Box flexDirection="column" paddingX={1} paddingY={0}>
<Box flexDirection="column" marginBottom={1}>
<Text color="cyanBright">Guardian Strategy Dashboard</Text>
<Text color="cyanBright">{t("guardian.title")}</Text>
<Text>
: {exchangeName} : {snapshot.symbol} : {formatNumber(snapshot.lastPrice, 2)} : {ready ? "实时运行" : READY_MESSAGE}
{t("guardian.headerLine", {
exchange: exchangeName,
symbol: snapshot.symbol,
lastPrice: formatNumber(snapshot.lastPrice, 2),
status: ready ? t("status.live") : READY_MESSAGE,
})}
</Text>
<Text color="gray">/ Esc </Text>
<Text color="gray">{t("guardian.hint")}</Text>
</Box>
<Box flexDirection="column" marginBottom={1}>
<Text color="greenBright"></Text>
<Text color="greenBright">{t("guardian.positionTitle")}</Text>
{hasPosition ? (
<>
<Text>
: {position.positionAmt > 0 ? "多" : "空"} : {formatNumber(Math.abs(position.positionAmt), 4)} : {formatNumber(position.entryPrice, 2)} : {formatNumber(snapshot.pnl, 4)} USDT
{t("guardian.positionLine", {
direction: position.positionAmt > 0 ? t("common.direction.long") : t("common.direction.short"),
qty: formatNumber(Math.abs(position.positionAmt), 4),
entry: formatNumber(position.entryPrice, 2),
pnl: formatNumber(snapshot.pnl, 4),
})}
</Text>
<Text>
: {formatNumber(snapshot.targetStopPrice, 2)} : {formatNumber(stopOrderPrice, 2)} : {formatNumber(snapshot.trailingActivationPrice, 2)} : {formatNumber(trailingActivate, 2)}
{t("guardian.stopLine", {
targetStop: formatNumber(snapshot.targetStopPrice, 2),
stopOrder: formatNumber(stopOrderPrice, 2),
trailingTrigger: formatNumber(snapshot.trailingActivationPrice, 2),
trailingOrder: formatNumber(trailingActivate, 2),
})}
</Text>
<Text color={snapshot.requiresStop ? "yellow" : "gray"}>
Guardian : {guardStatus === "protecting" ? "已挂止损" : guardStatus === "pending" ? "缺少止损,正在同步" : "监听中"}
{t("guardian.stateLabel", {
state:
guardStatus === "protecting"
? t("guardian.status.protecting")
: guardStatus === "pending"
? t("guardian.status.pending")
: t("guardian.status.listening"),
})}
</Text>
</>
) : (
<Text color="gray">Guardian </Text>
<Text color="gray">{t("guardian.noPosition")}</Text>
)}
</Box>
<Box flexDirection="column" marginBottom={1}>
<Text color="yellow"></Text>
<Text color="yellow">{t("common.section.orders")}</Text>
{orderRows.length > 0 ? (
<DataTable columns={orderColumns} rows={orderRows} />
) : (
<Text color="gray"></Text>
<Text color="gray">{t("guardian.noProtectiveOrders")}</Text>
)}
</Box>
<Box flexDirection="column">
<Text color="yellow"></Text>
<Text color="yellow">{t("common.section.recent")}</Text>
{lastLogs.length > 0 ? (
lastLogs.map((item, index) => (
<Text key={`${item.time}-${index}`}>
@@ -141,7 +164,7 @@ export function GuardianApp({ onExit }: GuardianAppProps) {
</Text>
))
) : (
<Text color="gray"></Text>
<Text color="gray">{t("common.noLogs")}</Text>
)}
</Box>
</Box>