Maybe 财务软件界面翻译(增强版)

翻译 maybe 网站界面为中文,支持 SPA 页面跳转与日期翻译等增强功能。

目前為 2025-07-03 提交的版本,檢視 最新版本

您需要先安裝使用者腳本管理器擴展,如 TampermonkeyGreasemonkeyViolentmonkey 之後才能安裝該腳本。

You will need to install an extension such as Tampermonkey to install this script.

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyViolentmonkey 後才能安裝該腳本。

您需要先安裝使用者腳本管理器擴充功能,如 TampermonkeyUserscripts 後才能安裝該腳本。

你需要先安裝一款使用者腳本管理器擴展,比如 Tampermonkey,才能安裝此腳本

您需要先安裝使用者腳本管理器擴充功能後才能安裝該腳本。

(我已經安裝了使用者腳本管理器,讓我安裝!)

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展,比如 Stylus,才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

你需要先安裝一款使用者樣式管理器擴展後才能安裝此樣式

(我已經安裝了使用者樣式管理器,讓我安裝!)

// ==UserScript==
// @name         Maybe 财务软件界面翻译(增强版)
// @namespace    http://tampermonkey.net/
// @version      2.21
// @description  翻译 maybe 网站界面为中文,支持 SPA 页面跳转与日期翻译等增强功能。
// @author       ChatGPT
// @match        *://*/*
// @grant        none
// @run-at       document-end
// ==/UserScript==

(function () {
  'use strict';
  /* -------- ① 早退判断 -------- */
  if (!/Maybe/i.test(document.title)) return;
  /* --------------------------------------------------
     静态文本翻译表(完整,不遗漏任何键)
  -------------------------------------------------- */
const translations = {
  // 常规 ——————————————————————————————————
  "Transaction": "交易", // 已添加
  "Category": "分类", // 已添加
  "Amount": "金额", // 已添加
  "Home": "首页",
  "Default": "默认",
  "Account": "账户",
  "name": "名称",
  "Enter asset details": "输入资产明细",
  "Dashboard": "仪表盘",
  "Transactions": "交易",
  "Budgets": "预算",
  "Assets": "资产",
  "Debts": "负债",
  "All": "全部",
  "New debt": "新增负债",
  "New budget": "新增预算",
  "New transaction": "新增交易",
  "New account": "新增账户",
  "New asset": "新增资产",
  "New import": "新增导入",
  "New rule": "新增规则",
  "New tag": "新增标签",
  "New category": "新增分类",
  "New merchant": "新增商家",
  "Import": "导入",
  "Edit rules": "编辑规则",
  "Edit categories": "编辑分类",
  "Edit tags": "编辑标签",
  "Edit merchants": "编辑商家",
  "Edit imports": "编辑导入",
  "Total transactions": "交易总数",
  "No entries found": "未找到记录",
  "Try adding an entry, editing filters or refining your search": "请尝试添加记录、调整筛选或优化搜索",
  "Welcome back": "欢迎回来",
  "Welcome back, xiangshan": "欢迎回来,xiangshan",
  "Here's what's happening with your finances": "您的财务概况",
  "No accounts yet": "暂无账户",
  "Add account": "添加账户",
  "Add accounts to display net worth data": "添加账户以显示净资产",
  "Preferences": "偏好设置",
  "Security": "安全设置",
  "Self hosting": "自托管",
  "Accounts": "账户",
  "Account": "账户",
  "Imports": "数据导入",
  "Tags": "标签",
  "Categories": "分类",
  "Rules": "规则",
  "Merchants": "商家",
  "More": "更多",
  "What's new": "更新日志",
  "Feedback": "反馈",
  "Logout": "退出登录",
  "Save": "保存",
  "Reset account": "重置账户",
  "Delete account": "删除账户",
  "Amount": "金额",
  "Date format": "日期格式",
  "Default Period": "默认周期",
  "Country": "国家/地区",
  "Language": "语言",
  "Timezone": "时区",
  "Currency": "货币",
  "Chinese Renminbi Yuan (CNY)": "人民币 (CNY)",
  "Chinese (Simplified) (zh-CN)": "中文(简体)",
  "Today": "今天",
  "Oops!": "哎呀!",
  "Use defaults (recommended)": "使用默认分类(推荐)",
  "Add an account either via connection, importing or entering manually.": "通过连接、导入或手动方式添加账户。",
  "AI-enabled rule actions will cost money. Be sure to filter as narrowly as possible to avoid unnecessary costs.": "启用 AI 的规则会产生费用,请尽量精确过滤条件以避免不必要的支出。",
  "Set up rules to perform actions to your transactions and other data on every account sync.": "设置规则,在每次账户同步时自动处理交易等数据。",
  "Imports · 1": "导入 · 1",
  "View": "查看",
  "Delete": "删除",
  "Require invite code for signup": "注册需邀请码",
  "Every new user that joins your instance of Maybe can only do so via an invite code": "新用户注册必须使用邀请码",
  "Require email confirmation": "需要邮箱验证",
  "Generated codes": "已生成的邀请码",
  "Generate new code": "生成新邀请码",
  "Clear data cache": "清除数据缓存",
  "Clearing the data cache will remove all exchange rates, security prices, account balances, and other data. This will not delete accounts, transactions, categories, or other user-owned data.": "此操作会清除汇率、证券价格、账户余额等缓存,不会删除账户、交易和分类等用户数据。",
  "Hostings": "托管",
  "Self-Hosting": "自托管",
  "General Settings": "通用设置",
  "Synth Settings": "Synth 设置",
  "Input the API key provided by Synth": "输入 Synth 提供的 API Key",
  "API Key": "API Key",
  "Enter your API key here": "在此输入 API Key",
  "In progress": "进行中",

  // 仪表盘 ——————————————————————————
  "Net Worth": "净资产",
  "vs. last month": "较上月",
  "No Liabilities yet": "暂无负债",
  "Add your Liabilities accounts to see a full breakdown": "添加负债账户以查看完整明细",
  "No cash flow data for this time period": "该周期暂无现金流数据",
  "Add transactions to display cash flow data or expand the time period": "添加交易以查看现金流,或扩大时间范围",
  "Add transaction": "新增交易",
  "Weight": "占比",
  "Value": "价值",
// 设置页面 —— 新的设置项翻译
"One-time Income": "一次性收入",
"One-time transactions will be excluded from certain budgeting calculations and reports to help you see what's really important.":
  "一次性交易将被排除在某些预算计算和报告之外,帮助你查看最重要的内容。",
"Transfer or Debt Payment?": "转账或债务支付?",
"Transfers and payments are special types of transactions that indicate money movement between 2 accounts.":
  "转账和支付是特殊类型的交易,表示资金在两个账户之间的流动。",
"Delete transaction": "删除交易",
"This permanently deletes the transaction, affects your historical balances, and cannot be undone.":
  "此操作会永久删除交易,影响历史余额,且无法恢复。",

  // 预算设置——Setup your budget
  "Setup your budget": "设置预算",
  "Enter your monthly earnings and planned spending below to setup your budget.": "请输入您的月收入和计划支出以设置预算。",
  "Budgeted spending": "预算支出",
  "Expected income": "预期收入",
  "Autosuggest income & spending budget": "自动推荐收入和支出预算",
  "This will be based on transaction history. AI can make mistakes, verify before continuing.": "此功能基于交易历史,AI 可能出错,请核对后继续。",
  "Continue": "继续",

  // 编辑分类预算——Edit your category budgets
  "Edit your category budgets": "编辑分类预算",
  "Adjust category budgets to set spending limits. Unallocated funds will be automatically assigned as uncategorized.":
    "调整各分类预算以设置支出限额。未分配资金将自动归为未分类。",
  "% set": "% 已设置",
  "left to allocate": "剩余可分配",
  "Confirm": "确认",
  // 时间段控件 ——————————————————————
  "1D": "1 天",
  "7D": "7 天",
  "30D": "30 天",
  "90D": "90 天",
  "365D": "365 天",
  "5Y": "5 年",
  "WTD": "本周",
  "MTD": "本月",
  "YTD": "年初至今",

  // AI 提示 —————————————————————————
  "Enable Maybe AI": "启用 Maybe AI",
  "AI responses are informational only and are not financial advice.": "AI 回答仅供参考,并非财务建议。",
  "To use the AI assistant, you need to set the OPENAI_ACCESS_TOKEN environment variable in your self-hosted instance.": "要使用 AI 助手,请在自托管实例中设置环境变量 OPENAI_ACCESS_TOKEN。",
  "Disable anytime. All data sent to our LLM providers is anonymized.": "可随时停用。发送至大模型服务商的数据均已匿名化。",

  // 导航辅助 ————————————————————————
  "Back": "返回",
  "Next": "下一步",
  "esc": "关闭",
  "Filter": "筛选",
  "Clear filters": "清空筛选",
  "Tag": "标签",
  "Merchant": "商户",
  // 规则页面 ————————————————————————
  "New transaction rule": "新增交易规则",
  "Rule name (optional)": "规则名称(可选)",
  "Enter a name for this rule": "请输入规则名称",
  "IF": "如果",
  "Add condition": "添加条件",
  "Add condition group": "添加条件组",
  "THEN": "那么",
  "Add action": "添加动作",
  "FOR": "作用范围",
  "All past and future transactions": "所有历史及未来交易",
  "Starting from": "起始日期",
  "yyyy/mm/日": "年/月/日",

  // 分类设置 ————————————————————————
  "unassigned": "未分配",
  "categories": "分类",
  "Income categories": "收入分类",
  "Expense categories": "支出分类",
  "Name": "名称",
  "Edit": "编辑",
  "Classification": "分类类型",
  // Settings
  "One-time Income": "一次性收入",
  "One-time transactions will be excluded from certain budgeting calculations and reports to help you see what's really important": "一次性交易将被排除在某些预算计算和报告之外,帮助您看到真正重要的内容。",
  "Transfer or Debt Payment?": "转账或债务支付?",
  "Transfers and payments are special types of transactions that indicate money movement between 2 accounts": "转账和支付是特殊类型的交易,表示在两个账户之间的资金流动。",
  "Delete transaction": "删除交易",
  "This permanently deletes the transaction, affects your historical balances, and cannot be undone": "此操作将永久删除交易,影响您的历史余额,且无法撤销。",
  
  // Assign your categories
  "Assign your categories": "分配您的分类",
  "Assign all of your imported file’s categories to Maybe’s existing categories. You can also add new categories or leave them uncategorized": "将您导入文件的所有分类分配给Maybe的现有分类。您还可以添加新分类或将其留为未分类。",
  "CATEGORY IN CSV": "CSV中的分类",
  "CATEGORY IN MAYBE": "MAYBE中的分类",
  "ROWS": "行数",
  
  // Assign your tags
  "Assign your tags": "分配您的标签",
  "Assign all of your imported file’s tags to Maybe’s existing tags. You can also add new tags or leave them uncategorized": "将您导入文件的所有标签分配给Maybe的现有标签。您还可以添加新标签或将其留为未分类。",
  "TAG IN CSV": "CSV中的标签",
  "TAG IN MAYBE": "MAYBE中的标签",
  
  // Assign your accounts
  "Assign your accounts": "分配您的账户",
  "Assign all of your imported file’s accounts to Maybe’s existing accounts. You can also add new accounts or leave them uncategorized": "将您导入文件的所有账户分配给Maybe的现有账户。您还可以添加新账户或将其留为未分类。",
  "ACCOUNT IN CSV": "CSV中的账户",
  "ACCOUNT IN MAYBE": "MAYBE中的账户",
  "Need to create a new account for unassigned rows?": "需要为未分配的行创建新账户吗?",
  "Create account": "创建账户",

  // Reverting import failed
  "Reverting import failed": "撤销导入失败",
  "Please try again or contact support": "请重试或联系客服。",
  "Try again": "重试",

  // Enter account balance
  "Account name": "账户名称",
  "Current balance": "当前余额",
  "Subtype": "子类型",
  "Select investment type": "选择投资类型",
  "None": "无",
  "Brokerage": "经纪账户",
  "Pension": "养老金",
  "Retirement": "退休账户",
  "401(k)": "401(k)账户",
  "Roth 401(k)": "Roth 401(k)账户",
  "529 Plan": "529计划",
  "Health Savings Account (HSA)": "健康储蓄账户 (HSA)",
  "Mutual Fund": "共同基金",
  "Traditional IRA": "传统IRA",
  "Roth IRA": "Roth IRA",
  "Angel": "天使投资",
  // 账户类型选择 —————————————————————
  "Enter": "输入",
  "account balance": "账户余额",
  "balance": "余额",
  "Select account type": "选择账户类型",
  "Select": "选择",
  "None": "无",
  "Checking": "支票账户",
  "Savings": "储蓄账户",
  "Health Savings Account": "健康储蓄账户 (HSA)",
  "Certificate of Deposit": "定期存款 (CD)",
  "Money Market": "货币市场账户",

  // 账户添加 ————————————————————————
  "What would you like to add?": "请选择要添加的账户类型",
  "Cash": "现金账户",
  "Investment": "投资账户",
  "Crypto": "加密资产",
  "Property": "房产",
  "Vehicle": "车辆",
  "Credit Card": "信用卡",
  "Loan": "贷款",
  "Other Asset": "其他资产",
  "Other Liability": "其他负债",
  "Import accounts": "导入账户",
  "Select": "选择",
  "Navigate": "导航",
  "Close": "关闭",

  // 规则设置 ————————————————————————
  "Rule": "规则",
  "Transaction name": "交易名称",
  "Transaction amount": "交易金额",
  "Transaction merchant": "交易商户",
  "Contains": "包含",
  "Equal to": "等于",
  "match": "满足",
  "all": "全部条件",
  "any": "任一条件",
  "none": "不包含",
  "enter a value": "输入值",
  "of the following conditions": "以下条件",
  "Set transaction category": "设置交易分类",
  "Set transaction tags": "设置交易标签",
  "Set transaction merchant": "设置交易商户",
  "Set transaction name": "设置交易名称",

  // 转账 / 新增交易 ————————————————————
  "New transfer": "新增转账",
  "Expense": "支出",
  "Income": "收入",
  "Expenses": "支出",
  "Transfer": "转账",
  "From": "转出账户",
  "To": "转入账户",
  "Select account": "选择账户",
  "Date": "日期",
  "Create transfer": "创建转账",

  // 交易字段 ————————————————————————
  "Description": "交易说明",
  "Description*": "交易说明 *",
  "Description *": "交易说明 *",
  "Describe transaction": "请输入交易说明",
  "Account*": "账户 *",
  "Select an Account": "选择账户",
  "Category": "分类",
  "Select a Category": "选择分类",
  "Details": "详细信息",
  "Notes": "备注",
  "Enter a note": "请输入备注",
  "(none)": "无",

  // 账户详情 ————————————————————————
  "Other Assets": "其他资产",
  "Cash Flow": "现金流",
  "Balance": "余额",
  "no change vs. last month": "与上月持平",
  "Import transactions": "导入交易",
  "Activity": "活动",
  "Search entries by name": "按名称搜索条目",
  "New": "新增",
  "Delete Account?": "删除账户?",
  "Are you sure you want to delete account?": "确定要删除账户吗?",
  "This is not reversible.": "此操作不可撤销。",
  "Delete Account": "删除账户",
  "BALANCE": "余额",
  // 房产相关 ————————————————————————————
  "Select property type": "选择房产类型",
  "Single Family Home": "独立住宅",
  "Multi-Family Home": "多户住宅",
  "Condominium": "公寓",
  "Townhouse": "联排别墅",
  "Investment Property": "投资房产",
  "Second Home": "第二住宅",
  "Year built": "建造年份",
  "Living area": "居住面积",
  "Street address": "街道地址",
  "City": "城市",
  "ZIP/Postal code": "邮政编码",
  "Unit of measurement": "计量单位",
  "Square Feet": "平方英尺",
  "State/Province": "州/省",
  // 其他 ————————————————————————————
  "Liabilities": "负债",
  "Cashflow": "现金流",
  "Confirm": "确认",
// 导入 ————————————————————————————
  "No imports yet.": "尚未导入数据。",
  "New CSV Import": "新的 CSV 导入",
  "You can manually import various types of data via CSV or use one of our import templates like Mint.": "您可以通过 CSV 手动导入各种数据,或使用我们的导入模板,如 Mint。",
  "SOURCES": "来源",
  "Import investments": "导入投资",
  "Import from Mint": "从 Mint 导入",
  "Import your data": "导入您的数据",
  "Paste or upload your CSV file below. Please review the instructions in the table below before beginning.": "在下方粘贴或上传您的 CSV 文件。请在开始之前查看表格中的说明。",
  "Upload CSV Copy & Paste": "上传 CSV 或复制粘贴",
  "Browse to add your CSV file here": "浏览以添加您的 CSV 文件",
  "Upload CSV": "上传 CSV",
  "Download a sample CSV to see the required CSV format": "下载样本 CSV 查看所需的 CSV 格式",
  "Resume Account Import": "恢复账户导入",
  "Please finalize your file upload.": "请完成文件上传。",
  "Account (optional)": "账户(可选)",
  "Multi-account import": "多账户导入",
  "Paste your CSV file contents here": "在此粘贴您的 CSV 文件内容",
  "Configure your import": "配置您的导入",
  "Select the columns that correspond to each field in your CSV.": "选择与 CSV 中每个字段对应的列。",
  "Custom column": "自定义列",
  "Amount type strategy": "金额类型设置", // 更加准确的翻译
  "Signed amount": "带符号金额", // 更加准确的翻译
  "Incomes are positive": "收入为正数",
  "Incomes are negative": "收入为负数",
  "Leave empty": "留空",
  "Apply configuration": "应用配置",
  "Sample data from your uploaded CSV": "来自您上传的 CSV 的示例数据",
  "Please configure your import before proceeding": "请在继续之前配置您的导入",
  "as amount type column": "将其设置为金额类型列",
  "Set": "设置",
  "Select column": "选择列",
  "Upload": "上传",
  "Configure": "配置",
  "Clean": "清理",
  "Map": "映射",
  // CSV 相关术语
  "Comma (,)": "逗号 (,)",
  "Semicolon (;)": "分号 (;)",
  "Col sep": "列分隔符",
  "IMPORTS": "导入",
  "Import": "导入",
  "Transaction": "交易",
  "Account": "账户",
  "Revert import?": "撤销导入?",
  "This will delete transactions that were imported, but you will still be able to review and re-import your data at any time.":
    "这将删除已导入的交易,但您仍然可以随时查看并重新导入数据。",
  "Revert": "撤销",
"Template configuration found": "检测到模板配置",
"We found a configuration from a previous import for this account. Would you like to apply it to this import?":
  "检测到此前为此账户保存的导入配置,是否应用到本次导入?",
"Manually configure": "手动配置",
"Apply template": "应用模板",
    // 页面中的动态日期翻译
    "Depositories": "存款账户",
    "Current Balance": "当前余额",
    "Initial Balance": "初始余额",
    "Activity": "活动",
    "Amount": "金额",
    "Remaining": "剩余金额",
    "Search entries by name": "按名称搜索记录",
    "New": "新增",
    "Date": "日期",
      // 分类弹窗 ————————————————————————
  "Uncategorized": "未分类",
  "OVERVIEW": "概览",
  "Monthly average spending": "平均月支出",
  "Monthly median spending": "月支出中位数",
  "RECENT TRANSACTIONS": "最近交易",
  "No transactions found for this budget period.": "此预算周期内未找到交易。"

};



  /* --------------------------------------------------
     月份 & 星期映射(含缩写)
  -------------------------------------------------- */
  const monthMap = {
    January: '1月',  Jan: '1月',
    February: '2月', Feb: '2月',
    March: '3月',    Mar: '3月',
    April: '4月',    Apr: '4月',
    May: '5月',
    June: '6月',     Jun: '6月',
    July: '7月',     Jul: '7月',
    August: '8月',   Aug: '8月',
    September: '9月',Sep: '9月', Sept: '9月',
    October: '10月', Oct: '10月',
    November: '11月',Nov: '11月',
    December: '12月',Dec: '12月'
  };

  const weekdayMap = {
    Monday: '星期一',    Mon: '星期一',
    Tuesday: '星期二',   Tue: '星期二',
    Wednesday: '星期三', Wed: '星期三',
    Thursday: '星期四',  Thu: '星期四',
    Friday: '星期五',    Fri: '星期五',
    Saturday: '星期六',  Sat: '星期六',
    Sunday: '星期日',    Sun: '星期日'
  };

  /* --------------------------------------------------
     动态文本翻译函数
  -------------------------------------------------- */
  // 金额 + avg   e.g. "¥0.00 avg"
  const translateAmountAvg = txt => {
    const m = txt.match(/^(.+?)\s+avg$/i);
    return m ? `${m[1]} 平均` : null;
  };
  // AM/PM 转换
  const timeMap = {
    "AM": "上午",
    "PM": "下午"
  };
  // 日期翻译函数
  const translateFullDate = txt => {
    const m = txt.match(
      /^(Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|May|Jun(?:e)?|Jul(?:y)?|Aug(?:ust)?|Sep(?:t(?:ember)?)?|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?)\s+(\d{1,2}),\s+(\d{4})\s+at\s+(\d{1,2}):(\d{2})\s(AM|PM)$/i
    );
    if (m) {
      return `${m[3]}年${monthMap[m[1]]}${parseInt(m[2], 10)}日 ${timeMap[m[6]]} ${m[4]}:${m[5]}`;
    }
    return null;
  };

  // "Jun 2025 spending"
  const translateMonthlySpending = txt => {
    const m = txt.match(
      /^(Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|May|Jun(?:e)?|Jul(?:y)?|Aug(?:ust)?|Sep(?:t(?:ember)?)?|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?)\s(\d{4})\sspending$/i
    );
    return m ? `${m[2]}年${monthMap[m[1]]}支出` : null;
  };

  // "May 2025"
  const translateYearMonth = txt => {
    const m = txt.match(
      /^(Jan(?:uary)?|Feb(?:ruary)?|Mar(?:ch)?|Apr(?:il)?|May|Jun(?:e)?|Jul(?:y)?|Aug(?:ust)?|Sep(?:t(?:ember)?)?|Oct(?:ober)?|Nov(?:ember)?|Dec(?:ember)?)\s(\d{4})$/i
    );
    return m ? `${m[2]}年${monthMap[m[1]]}` : null;
  };

  // on or after / before YYYY-MM-DD
  const translateDateRange = txt => {
    const after = txt.match(/^on or after (\d{4}-\d{2}-\d{2})$/);
    if (after) return `起始日期:${after[1]}`;
    const before = txt.match(/^on or before (\d{4}-\d{2}-\d{2})$/);
    return before ? `结束日期:${before[1]}` : null;
  };

  // 30D / 1W / 12M / 1Y
  const translateShorthandPeriod = txt => {
    const m = txt.match(/^(\d+)([DWMY])$/);
    if (!m) return null;
    const map = { D: "天", W: "周", M: "月", Y: "年" };
    return `${m[1]}${map[m[2]]}`;
  };

  // Last 30 days
  const translateLastPeriod = txt => {
    const m = txt.match(/^Last (\d+) (days?|weeks?|months?|years?)$/i);
    if (!m) return null;
    const unit = m[2].toLowerCase().startsWith("day")
      ? "天"
      : m[2].startsWith("week")
      ? "周"
      : m[2].startsWith("month")
      ? "个月"
      : "年";
    return `最近${m[1]}${unit}`;
  };

const translateTransactionImport = txt => {
  const m = txt.match(/^Transaction Import: (.*) at (\d{1,2}):(\d{2}) (AM|PM)$/i);
  if (m) {
    const monthDayYear = `${m[1].replace(/\d{4}/, (match) => `${match}年`)}`; // 修改为包含中文年份
    const time = `${m[2]}:${m[3]} ${m[4] === 'AM' ? '上午' : '下午'}`;
    return `交易导入:${monthDayYear} ${time} 完成`;
  }
  return null;
};

// "¥0/m avg" -> "¥0.00/月 平均"
const translatePerMonthAvg = txt => {
  const m = txt.match(/^(.+?)\/m avg$/i);
  return m ? `${m[1]}/月 平均` : null;
};

// ---------------------------------------------
// 动态翻译函数列表更新
// ---------------------------------------------
const dynamicFns = [
  translateTransactionImport,
  translatePerMonthAvg,
  translateAmountAvg,
  translateFullDate,
  translateMonthlySpending,
  translateYearMonth,
  translateDateRange,
  translateShorthandPeriod,
  translateLastPeriod
];

  /* --------------------------------------------------
     文本节点翻译入口
  -------------------------------------------------- */
  // 动态文本翻译函数
  const translateTextNode = node => {
    if (!node || node.nodeType !== 3) return;
    const raw = node.textContent;
    const txt = raw.trim();
    if (!txt) return;

    // 1) 静态翻译(大小写不敏感)
    const cand =
      translations[txt] ||
      translations[txt.toUpperCase()] ||
      translations[txt.toLowerCase()];
    if (cand) {
      node.textContent = raw.replace(txt, cand);
      return;
    }

    // 2) 动态翻译: 日期
    const dateTranslated = translateFullDate(txt);
    if (dateTranslated) {
      node.textContent = raw.replace(txt, dateTranslated);
      return;
    }

    // 3) 单独月份或星期
    if (monthMap[txt]) {
      node.textContent = raw.replace(txt, monthMap[txt]);
    } else if (weekdayMap[txt]) {
      node.textContent = raw.replace(txt, weekdayMap[txt]);
    }
  };

  const translatePage = () => {
    const walker = document.createTreeWalker(
      document.body,
      NodeFilter.SHOW_TEXT,
      null,
      false
    );
    let n;
    while ((n = walker.nextNode())) translateTextNode(n);
  };

  // 初始 + 轮询
  translatePage();
  const INTERVAL = 300;
  setInterval(translatePage, INTERVAL);

  // 监听 SPA 路由变化
  let lastUrl = location.href;
  setInterval(() => {
    if (location.href !== lastUrl) {
      lastUrl = location.href;
      setTimeout(translatePage, 500);
    }
  }, 500);
})();