mirror of
https://github.com/discountry/ritmex-bot.git
synced 2026-09-12 01:38:07 +00:00
i18n(core): route order-coordinator and token/margin guards through t()
These files bypassed the i18n table entirely, so a user running LANG=en still got Chinese order logs. Migrating them surfaced structural duplication too: the five order paths each spelled out their own 'quantity invalid' string, now one key parameterised by an order-kind label. Also fixes a type that carried display text as its domain: TrendLabel was '做多' | '做空' | '无信号', so the engine's snapshot value *was* the Chinese string and English rendering depended on matching it. Now 'long' | 'short' | 'none', translated at the edge. Order-coordinator tests asserted the Chinese literals, which is exactly what made the gap invisible; they now assert the resolved key so they hold in either language. 39 new translation keys. 271 pass; tsc and oxlint clean.
This commit is contained in:
@@ -1,5 +1,6 @@
|
||||
import type { AccountSnapshot } from "../../exchanges/types";
|
||||
import { extractMessage } from "../../utils/errors";
|
||||
import { t } from "../../i18n";
|
||||
import type { LogHandler } from "./subscriptions";
|
||||
|
||||
/** Snapshot refreshes to wait through before giving up on the switch (~5s total). */
|
||||
@@ -74,15 +75,15 @@ export class IsolatedMarginGuard {
|
||||
this.deps.applySnapshot(next);
|
||||
}
|
||||
if (this.currentMode() === "isolated") {
|
||||
this.deps.log("info", "已切换为逐仓模式 (isolated),恢复策略运行");
|
||||
this.deps.log("info", t("log.margin.switched"));
|
||||
return true;
|
||||
}
|
||||
await sleep(CONFIRM_INTERVAL_MS);
|
||||
}
|
||||
this.deps.log("warn", `逐仓模式切换未确认,当前模式: ${this.currentMode() ?? "unknown"}`);
|
||||
this.deps.log("warn", t("log.margin.switchUnconfirmed", { mode: this.currentMode() ?? "unknown" }));
|
||||
return false;
|
||||
} catch (error) {
|
||||
this.deps.log("error", `切换逐仓模式失败: ${extractMessage(error)}`);
|
||||
this.deps.log("error", t("log.margin.switchFailed", { error: extractMessage(error) }));
|
||||
return false;
|
||||
} finally {
|
||||
this.ensuring = null;
|
||||
|
||||
@@ -6,6 +6,7 @@ import {
|
||||
type TokenExpiryState,
|
||||
type TokenExpiryStatus,
|
||||
} from "../../utils/standx-token-expiry";
|
||||
import { t } from "../../i18n";
|
||||
import type { LogHandler } from "./subscriptions";
|
||||
|
||||
/** What the engine should do for the rest of this tick. */
|
||||
@@ -76,13 +77,13 @@ export class TokenExpiryGuard {
|
||||
if (status.state === "expired_with_position") {
|
||||
if (!this.closeOnly) {
|
||||
this.closeOnly = true;
|
||||
this.deps.log("info", "Token 过期,强制进入平仓模式,仅允许 reduce-only 订单");
|
||||
this.deps.log("info", t("log.token.closeOnlyForced"));
|
||||
}
|
||||
return { halt: false, closeOnly: true };
|
||||
}
|
||||
|
||||
if (status.state === "silent" && previousState !== "silent") {
|
||||
this.deps.log("info", "进入静默数据接收模式,不再进行任何交易操作");
|
||||
this.deps.log("info", t("log.token.silentEntered"));
|
||||
}
|
||||
return { halt: true, closeOnly: this.closeOnly };
|
||||
}
|
||||
@@ -120,18 +121,18 @@ export class TokenExpiryGuard {
|
||||
if (this.cancelDone || openOrderCount === 0) return;
|
||||
try {
|
||||
await this.deps.cancelAllOrders();
|
||||
this.deps.log("order", "Token 过期,已撤销所有挂单");
|
||||
this.deps.log("order", t("log.token.ordersCancelled"));
|
||||
this.deps.onOrdersCancelled();
|
||||
this.cancelDone = true;
|
||||
} catch (error) {
|
||||
if (isUnknownOrderError(error)) {
|
||||
// Nothing left to cancel is the outcome we wanted.
|
||||
this.deps.log("order", "Token 过期撤单时订单已不存在");
|
||||
this.deps.log("order", t("log.token.cancelOrderMissing"));
|
||||
this.cancelDone = true;
|
||||
return;
|
||||
}
|
||||
// Leave cancelDone false so the next tick retries.
|
||||
this.deps.log("error", `Token 过期撤单失败: ${extractMessage(error)}`);
|
||||
this.deps.log("error", t("log.token.cancelFailed", { error: extractMessage(error) }));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,10 +213,8 @@ export class MakerPointsEngine {
|
||||
type: "token_expired",
|
||||
level: "warn",
|
||||
symbol: this.config.symbol,
|
||||
title: "Token 已过期",
|
||||
message: hasPosition
|
||||
? "Token 已过期,进入平仓模式,不再开新仓"
|
||||
: "Token 已过期,策略进入静默模式",
|
||||
title: t("notify.token.title"),
|
||||
message: hasPosition ? t("notify.token.closeOnly") : t("notify.token.silent"),
|
||||
details: { hasPosition, hasOpenOrders, state },
|
||||
}),
|
||||
cancelAllOrders: () => this.exchange.cancelAllOrders({ symbol: this.config.symbol }),
|
||||
|
||||
@@ -32,6 +32,7 @@ import { createTradeLog, type TradeLogEntry } from "../logging/trade-log";
|
||||
import { decryptCopyright } from "../utils/copyright";
|
||||
import { isRateLimitError } from "../utils/errors";
|
||||
import { RateLimitController } from "../core/lib/rate-limit";
|
||||
import type { TrendLabel } from "../utils/format";
|
||||
import { StrategyEventEmitter } from "./common/event-emitter";
|
||||
import { createPrecisionSyncer, type PrecisionSyncer } from "./common/precision-syncer";
|
||||
import { safeSubscribe, type LogHandler } from "./common/subscriptions";
|
||||
@@ -44,7 +45,7 @@ export interface TrendEngineSnapshot {
|
||||
lastPrice: number | null;
|
||||
sma30: number | null;
|
||||
bollingerBandwidth: number | null;
|
||||
trend: "做多" | "做空" | "无信号";
|
||||
trend: TrendLabel;
|
||||
position: PositionSnapshot;
|
||||
pnl: number;
|
||||
unrealized: number;
|
||||
@@ -978,13 +979,14 @@ export class TrendEngine {
|
||||
const position = getPosition(this.accountSnapshot, this.config.symbol);
|
||||
const price = this.tickerSnapshot ? Number(this.tickerSnapshot.lastPrice) : null;
|
||||
const sma30 = this.lastSma30;
|
||||
const trend = price == null || sma30 == null
|
||||
? "无信号"
|
||||
: price > sma30
|
||||
? "做多"
|
||||
: price < sma30
|
||||
? "做空"
|
||||
: "无信号";
|
||||
const trend: TrendLabel =
|
||||
price == null || sma30 == null
|
||||
? "none"
|
||||
: price > sma30
|
||||
? "long"
|
||||
: price < sma30
|
||||
? "short"
|
||||
: "none";
|
||||
const pnl = price != null ? computePositionPnl(position, price, price) : 0;
|
||||
return {
|
||||
ready: this.isReady(),
|
||||
|
||||
Reference in New Issue
Block a user