Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions plugin/lib/google.ts
Original file line number Diff line number Diff line change
Expand Up @@ -362,6 +362,10 @@ export async function queryGoogleUsage(): Promise<QueryResult> {
output: outputs.join("\n\n"),
};
} catch (err) {
// 文件不存在表示用户未配置 Google 账号,静默跳过
if (err instanceof Error && (err as NodeJS.ErrnoException).code === "ENOENT") {
return { success: true, output: "" };
}
return {
success: false,
error: err instanceof Error ? err.message : String(err),
Expand Down
82 changes: 81 additions & 1 deletion plugin/lib/i18n.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
// 类型定义
// ============================================================================

export type Language = "zh" | "en";
export type Language = "zh" | "zh-tw" | "en";
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Adding "zh-tw" to Language means any existing currentLang === "zh" ? ... : ... branches will now incorrectly treat Traditional Chinese users as non-Chinese (e.g., plugin/lib/google.ts returns English "reset" for zh-tw). Please audit/update those conditionals (or centralize via a helper like “isChinese”) so zh-tw gets the intended Chinese output.

Copilot uses AI. Check for mistakes.

// ============================================================================
// 语言检测
Expand All @@ -25,6 +25,7 @@ function detectLanguage(): Language {
// 1. 优先使用 Intl API(更可靠)
try {
const intlLocale = Intl.DateTimeFormat().resolvedOptions().locale;
if (intlLocale.startsWith("zh-TW") || intlLocale.startsWith("zh-Hant")) return "zh-tw";
if (intlLocale.startsWith("zh")) return "zh";
Comment on lines +28 to 29
Copy link

Copilot AI Feb 28, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

detectLanguage() maps env var zh_HK to zh-tw, but the Intl-based path doesn’t handle locales like zh-HK (common) and will fall through to the generic zh check. Consider treating zh-HK as Traditional Chinese too (or more generally, detect script Hant / region TW|HK consistently for the Intl branch).

Suggested change
if (intlLocale.startsWith("zh-TW") || intlLocale.startsWith("zh-Hant")) return "zh-tw";
if (intlLocale.startsWith("zh")) return "zh";
// 规范化 locale(将下划线替换为连字符),并解析 BCP 47 子标签
const normalizedLocale = intlLocale.replace(/_/g, "-");
const parts = normalizedLocale.split("-");
const baseLang = parts[0]?.toLowerCase();
if (baseLang === "zh") {
const subtags = parts.slice(1).map((p) => p.toLowerCase());
// 传统中文:脚本为 Hant 或地区为 TW/HK
if (
subtags.includes("hant") ||
subtags.includes("tw") ||
subtags.includes("hk")
) {
return "zh-tw";
}
return "zh";
}

Copilot uses AI. Check for mistakes.
} catch {
// Intl API 不可用,继续尝试环境变量
Expand All @@ -33,6 +34,7 @@ function detectLanguage(): Language {
// 2. 回退到环境变量
const lang =
process.env.LANG || process.env.LC_ALL || process.env.LANGUAGE || "";
if (lang.startsWith("zh_TW") || lang.startsWith("zh_HK")) return "zh-tw";
if (lang.startsWith("zh")) return "zh";

// 3. 默认英文
Expand Down Expand Up @@ -122,6 +124,84 @@ const translations = {
"• 在 VS Code 中点击状态栏的 Copilot 图标查看配额\n" +
"• 访问 https://github.com/settings/billing 查看使用情况",
},
"zh-tw": {
// 時間單位
days: (n: number) => `${n}天`,
hours: (n: number) => `${n}小時`,
minutes: (n: number) => `${n}分鐘`,

// 限額相關
hourLimit: (h: number) => `${h}小時限額`,
dayLimit: (d: number) => `${d}天限額`,
remaining: (p: number) => `剩餘 ${p}%`,
resetIn: (t: string) => `重置: ${t}後`,
limitReached: "⚠️ 已達到限額上限!",

// 通用
account: "Account:",
unknown: "未知",
used: "已用",

// 錯誤訊息
authError: (path: string, err: string) =>
`❌ 無法讀取認證檔案: ${path}\n錯誤: ${err}`,
apiError: (status: number, text: string) =>
`OpenAI API 請求失敗 (${status}): ${text}`,
timeoutError: (seconds: number) => `請求逾時 (${seconds}秒)`,
tokenExpired:
"⚠️ OAuth 授權已過期,請在 OpenCode 中使用一次 OpenAI 模型以重新整理授權。",
noAccounts:
"未找到任何已設定的帳號。\n\n支援的帳號類型:\n- OpenAI (Plus/Team/Pro 訂閱用戶)\n- 智譜 AI (Coding Plan)\n- Z.ai (Coding Plan)\n- Google Cloud (Antigravity)",
queryFailed: "❌ 查詢失敗的帳號:\n",

// 平台標題
openaiTitle: "## OpenAI 帳號額度",
zhipuTitle: "## 智譜 AI 帳號額度",
zaiTitle: "## Z.ai 帳號額度",

// 智譜 AI 相關
zhipuApiError: (status: number, text: string) =>
`智譜 API 請求失敗 (${status}): ${text}`,
zaiApiError: (status: number, text: string) =>
`Z.ai API 請求失敗 (${status}): ${text}`,
zhipuTokensLimit: "5 小時 Token 限額",
zhipuMcpLimit: "MCP 月度配額",
zhipuAccountName: "Coding Plan",
zaiAccountName: "Z.ai",
noQuotaData: "暫無配額資料",

// Google 相關
googleTitle: "## Google Cloud 帳號額度",
googleApiError: (status: number, text: string) =>
`Google API 請求失敗 (${status}): ${text}`,
googleNoProjectId: "⚠️ 缺少 project_id,無法查詢額度。",

// GitHub Copilot 相關
copilotTitle: "## GitHub Copilot 帳號額度",
copilotApiError: (status: number, text: string) =>
`GitHub Copilot API 請求失敗 (${status}): ${text}`,
premiumRequests: "Premium",
chatQuota: "Chat",
completionsQuota: "Completions",
overage: "超額使用",
overageRequests: "次請求",
quotaResets: "配額重置",
resetsSoon: "即將重置",
modelBreakdown: "模型使用明細:",
billingPeriod: "計費週期",
copilotQuotaUnavailable:
"⚠️ GitHub Copilot 配額查詢暫時不可用。\n" +
"OpenCode 的新 OAuth 整合不支援存取配額 API。",
copilotQuotaWorkaround:
"解決方案:\n" +
"1. 建立一個 fine-grained PAT (前往 https://github.com/settings/tokens?type=beta)\n" +
"2. 在 'Account permissions' 中將 'Plan' 設為 'Read-only'\n" +
"3. 建立設定檔 ~/.config/opencode/copilot-quota-token.json:\n" +
' {"token": "github_pat_xxx...", "username": "你的使用者名稱"}\n\n' +
"其他方法:\n" +
"• 在 VS Code 中點擊狀態列的 Copilot 圖示查看配額\n" +
"• 前往 https://github.com/settings/billing 查看使用情況",
},
en: {
// 时间单位
days: (n: number) => `${n}d`,
Expand Down
Loading