diff --git a/AGENTS.md b/AGENTS.md index 4d87c2f3..3fdc476b 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -1,7 +1,7 @@ # GitNexus — Code Intelligence -This project is indexed by GitNexus as **qinglong** (2740 symbols, 6583 relationships, 230 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely. +This project is indexed by GitNexus as **qinglong** (2778 symbols, 6698 relationships, 233 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely. > Index stale? Run `node .gitnexus/run.cjs analyze` from the project root — it auto-selects an available runner. No `.gitnexus/run.cjs` yet? `npx gitnexus analyze` (npm 11 crash → `npm i -g gitnexus`; #1939). @@ -40,4 +40,4 @@ This project is indexed by GitNexus as **qinglong** (2740 symbols, 6583 relation | Tools, resources, schema reference | `.claude/skills/gitnexus/gitnexus-guide/SKILL.md` | | Index, status, clean, wiki CLI commands | `.claude/skills/gitnexus/gitnexus-cli/SKILL.md` | - \ No newline at end of file + diff --git a/CLAUDE.md b/CLAUDE.md deleted file mode 100644 index 4d87c2f3..00000000 --- a/CLAUDE.md +++ /dev/null @@ -1,43 +0,0 @@ - -# GitNexus — Code Intelligence - -This project is indexed by GitNexus as **qinglong** (2740 symbols, 6583 relationships, 230 execution flows). Use the GitNexus MCP tools to understand code, assess impact, and navigate safely. - -> Index stale? Run `node .gitnexus/run.cjs analyze` from the project root — it auto-selects an available runner. No `.gitnexus/run.cjs` yet? `npx gitnexus analyze` (npm 11 crash → `npm i -g gitnexus`; #1939). - -## Always Do - -- **MUST run impact analysis before editing any symbol.** Before modifying a function, class, or method, run `impact({target: "symbolName", direction: "upstream"})` and report the blast radius (direct callers, affected processes, risk level) to the user. -- **MUST run `detect_changes()` before committing** to verify your changes only affect expected symbols and execution flows. For regression review, compare against the default branch: `detect_changes({scope: "compare", base_ref: "develop"})`. -- **MUST warn the user** if impact analysis returns HIGH or CRITICAL risk before proceeding with edits. -- When exploring unfamiliar code, use `query({query: "concept"})` to find execution flows instead of grepping. It returns process-grouped results ranked by relevance. -- When you need full context on a specific symbol — callers, callees, which execution flows it participates in — use `context({name: "symbolName"})`. - -## Never Do - -- NEVER edit a function, class, or method without first running `impact` on it. -- NEVER ignore HIGH or CRITICAL risk warnings from impact analysis. -- NEVER rename symbols with find-and-replace — use `rename` which understands the call graph. -- NEVER commit changes without running `detect_changes()` to check affected scope. - -## Resources - -| Resource | Use for | -|----------|---------| -| `gitnexus://repo/qinglong/context` | Codebase overview, check index freshness | -| `gitnexus://repo/qinglong/clusters` | All functional areas | -| `gitnexus://repo/qinglong/processes` | All execution flows | -| `gitnexus://repo/qinglong/process/{name}` | Step-by-step execution trace | - -## CLI - -| Task | Read this skill file | -|------|---------------------| -| Understand architecture / "How does X work?" | `.claude/skills/gitnexus/gitnexus-exploring/SKILL.md` | -| Blast radius / "What breaks if I change X?" | `.claude/skills/gitnexus/gitnexus-impact-analysis/SKILL.md` | -| Trace bugs / "Why is X failing?" | `.claude/skills/gitnexus/gitnexus-debugging/SKILL.md` | -| Rename / extract / split / refactor | `.claude/skills/gitnexus/gitnexus-refactoring/SKILL.md` | -| Tools, resources, schema reference | `.claude/skills/gitnexus/gitnexus-guide/SKILL.md` | -| Index, status, clean, wiki CLI commands | `.claude/skills/gitnexus/gitnexus-cli/SKILL.md` | - - \ No newline at end of file diff --git a/back/loaders/initData.ts b/back/loaders/initData.ts index 96b7033e..7662ae87 100644 --- a/back/loaders/initData.ts +++ b/back/loaders/initData.ts @@ -19,7 +19,7 @@ import { shareStore } from '../shared/store'; import Logger from './logger'; import { AppModel } from '../data/open'; import { InstanceStatus, RunningInstanceModel } from '../data/runningInstance'; -import { setLang } from '../shared/i18n'; +import { setLang, systemLang } from '../shared/i18n'; export default async () => { const cronService = Container.get(CronService); @@ -223,18 +223,20 @@ export default async () => { } }); - // 初始化保存一次ck和定时任务数据 - await cronService.autosave_crontab(); + // 初始化语言(必须在 autosave_crontab 之前) + const lang = systemConfig.info?.lang || systemLang(); + setLang(lang); - // 确保 lang_env.sh 存在,提供默认 QL_LANG + // 确保 lang_env.sh 存在 try { const langEnvExist = await fileExist(config.langEnvFile); if (!langEnvExist) { - const lang = systemConfig.info?.lang || 'zh'; await writeFile(config.langEnvFile, `export QL_LANG='${lang}'\n`); } } catch { } - setLang(systemConfig.info?.lang || 'zh'); + + // 初始化保存一次ck和定时任务数据 + await cronService.autosave_crontab(); await envService.set_envs(); diff --git a/back/shared/i18n.ts b/back/shared/i18n.ts index 1edd2bb0..827fab87 100644 --- a/back/shared/i18n.ts +++ b/back/shared/i18n.ts @@ -1,3 +1,5 @@ +import { shareStore } from './store'; + const messages: Record> = { zh: {}, en: { @@ -148,10 +150,13 @@ let currentLang: string = 'zh'; export function setLang(lang: string) { currentLang = lang || 'zh'; + shareStore.setLang(currentLang); } -export function getLang(): string { - return currentLang; +/** 系统默认语言:Intl 检测 → 'zh'(仅返回 zh/en) */ +export function systemLang(): string { + const prefix = Intl.DateTimeFormat().resolvedOptions().locale.split('-')[0]; + return prefix === 'en' ? 'en' : 'zh'; } export function t(key: string, lang?: string): string { diff --git a/back/shared/store.ts b/back/shared/store.ts index 186adf43..aefa392a 100644 --- a/back/shared/store.ts +++ b/back/shared/store.ts @@ -8,11 +8,13 @@ import path from 'path'; export enum EKeyv { 'apps' = 'apps', 'authInfo' = 'authInfo', + 'lang' = 'lang', } export interface IKeyvStore { apps: App[]; authInfo: AuthInfo; + lang: string; } const keyvSqlite = new KeyvSqlite(path.join(config.dbPath, 'keyv.sqlite')); @@ -31,4 +33,10 @@ export const shareStore = { updateApps(apps: App[]) { return keyvStore.set(EKeyv.apps, apps); }, + getLang() { + return keyvStore.get(EKeyv.lang); + }, + setLang(value: IKeyvStore['lang']) { + return keyvStore.set(EKeyv.lang, value); + }, };