11const state = {
22 status : null ,
33 guide : null ,
4+ lang : detectLanguage ( ) ,
45} ;
56
67const $ = ( id ) => document . getElementById ( id ) ;
78
9+ const messages = {
10+ en : {
11+ appTitle : "Local Console" ,
12+ languageLabel : "Language" ,
13+ setupStatus : "Setup Status" ,
14+ refresh : "Refresh" ,
15+ provider : "Provider" ,
16+ pending : "pending" ,
17+ authEnv : "Auth env" ,
18+ searchAuto : "Search auto" ,
19+ readerFallback : "Reader fallback" ,
20+ saveProvider : "Save Provider" ,
21+ envFile : "Env File" ,
22+ key : "Key" ,
23+ value : "Value" ,
24+ overwrite : "Overwrite" ,
25+ saveEnv : "Save Env" ,
26+ searchTest : "Search Test" ,
27+ query : "Query" ,
28+ runSearch : "Run Search" ,
29+ readerTest : "Reader Test" ,
30+ runReader : "Run Reader" ,
31+ agentGuide : "Agent Guide" ,
32+ copy : "Copy" ,
33+ copied : "Copied" ,
34+ diagnostics : "Diagnostics" ,
35+ exportJson : "Export JSON" ,
36+ version : "version" ,
37+ skillInstalled : "skill installed" ,
38+ skillMissing : "skill missing" ,
39+ authReady : "auth ready" ,
40+ authMissing : "auth missing" ,
41+ readerAutoOn : "reader auto on" ,
42+ readerAutoOff : "reader auto off" ,
43+ configured : "configured" ,
44+ missing : "missing" ,
45+ repository : "Repository" ,
46+ installCLI : "Install CLI" ,
47+ installSkill : "Install or update skill" ,
48+ check : "Check" ,
49+ usage : "Usage" ,
50+ readerAuto : "Reader auto" ,
51+ repair : "Repair" ,
52+ } ,
53+ zh : {
54+ appTitle : "本地控制台" ,
55+ languageLabel : "语言" ,
56+ setupStatus : "设置状态" ,
57+ refresh : "刷新" ,
58+ provider : "Provider" ,
59+ pending : "待检查" ,
60+ authEnv : "认证环境变量" ,
61+ searchAuto : "搜索自动链" ,
62+ readerFallback : "读取 fallback" ,
63+ saveProvider : "保存 Provider" ,
64+ envFile : "Env 文件" ,
65+ key : "键" ,
66+ value : "值" ,
67+ overwrite : "覆盖已有值" ,
68+ saveEnv : "保存 Env" ,
69+ searchTest : "搜索测试" ,
70+ query : "查询" ,
71+ runSearch : "运行搜索" ,
72+ readerTest : "读取测试" ,
73+ runReader : "运行读取" ,
74+ agentGuide : "Agent 指引" ,
75+ copy : "复制" ,
76+ copied : "已复制" ,
77+ diagnostics : "诊断" ,
78+ exportJson : "导出 JSON" ,
79+ version : "版本" ,
80+ skillInstalled : "skill 已安装" ,
81+ skillMissing : "skill 缺失" ,
82+ authReady : "认证可用" ,
83+ authMissing : "认证缺失" ,
84+ readerAutoOn : "reader auto 已启用" ,
85+ readerAutoOff : "reader auto 未启用" ,
86+ configured : "已配置" ,
87+ missing : "缺失" ,
88+ repository : "仓库" ,
89+ installCLI : "安装 CLI" ,
90+ installSkill : "安装或更新 skill" ,
91+ check : "检查" ,
92+ usage : "使用示例" ,
93+ readerAuto : "Reader auto" ,
94+ repair : "修复建议" ,
95+ } ,
96+ } ;
97+
98+ function t ( key ) {
99+ return messages [ state . lang ] [ key ] || messages . en [ key ] || key ;
100+ }
101+
102+ function detectLanguage ( ) {
103+ const saved = localStorage . getItem ( "web-tools-language" ) ;
104+ if ( saved === "zh" || saved === "en" ) return saved ;
105+ const langs = navigator . languages && navigator . languages . length ? navigator . languages : [ navigator . language || "en" ] ;
106+ return langs . some ( ( lang ) => String ( lang ) . toLowerCase ( ) . startsWith ( "zh" ) ) ? "zh" : "en" ;
107+ }
108+
109+ function applyLanguage ( ) {
110+ document . documentElement . lang = state . lang === "zh" ? "zh-CN" : "en" ;
111+ document . title = state . lang === "zh" ? "web-tools 控制台" : "web-tools console" ;
112+ document . querySelectorAll ( "[data-i18n]" ) . forEach ( ( el ) => {
113+ el . textContent = t ( el . dataset . i18n ) ;
114+ } ) ;
115+ $ ( "refresh" ) . title = t ( "refresh" ) ;
116+ const selector = $ ( "language-select" ) ;
117+ selector . value = state . lang ;
118+ }
119+
8120async function api ( path , options = { } ) {
9121 const res = await fetch ( path , {
10122 headers : { "Content-Type" : "application/json" } ,
@@ -30,15 +142,15 @@ function renderStatus(data) {
30142 const setup = data . setup ;
31143 $ ( "summary" ) . innerHTML = "" ;
32144 $ ( "summary" ) . append (
33- pill ( `version ${ data . version || "dev" } ` , "ok" ) ,
34- pill ( setup . skill . installed ? "skill installed" : "skill missing" , setup . skill . installed ? "ok" : "warn" ) ,
35- pill ( setup . provider . auth_configured ? "auth ready" : "auth missing" , setup . provider . auth_configured ? "ok" : "warn" ) ,
36- pill ( setup . reader_auto . contains ? "reader auto on" : "reader auto off" , setup . reader_auto . contains ? "ok" : "warn" ) ,
145+ pill ( `${ t ( " version" ) } ${ data . version || "dev" } ` , "ok" ) ,
146+ pill ( setup . skill . installed ? t ( "skillInstalled" ) : t ( "skillMissing" ) , setup . skill . installed ? "ok" : "warn" ) ,
147+ pill ( setup . provider . auth_configured ? t ( "authReady" ) : t ( "authMissing" ) , setup . provider . auth_configured ? "ok" : "warn" ) ,
148+ pill ( setup . reader_auto . contains ? t ( "readerAutoOn" ) : t ( "readerAutoOff" ) , setup . reader_auto . contains ? "ok" : "warn" ) ,
37149 ) ;
38150
39- $ ( "provider-pill" ) . textContent = setup . provider . configured ? "configured" : "missing" ;
151+ $ ( "provider-pill" ) . textContent = setup . provider . configured ? t ( "configured" ) : t ( "missing" ) ;
40152 $ ( "provider-pill" ) . className = `pill ${ setup . provider . configured ? "ok" : "warn" } ` ;
41- $ ( "env-pill" ) . textContent = setup . env_file . user_exists ? setup . env_file . user_permission : "missing" ;
153+ $ ( "env-pill" ) . textContent = setup . env_file . user_exists ? setup . env_file . user_permission : t ( "missing" ) ;
42154 $ ( "env-pill" ) . className = `pill ${ setup . env_file . user_permission === "ok" ? "ok" : "warn" } ` ;
43155
44156 $ ( "checks" ) . innerHTML = setup . checks
@@ -57,25 +169,25 @@ function renderStatus(data) {
57169
58170function renderGuide ( guide ) {
59171 const lines = [
60- `Repository : ${ guide . repository_url } ` ,
172+ `${ t ( "repository" ) } : ${ guide . repository_url } ` ,
61173 "" ,
62- "Install CLI:" ,
174+ ` ${ t ( "installCLI" ) } :` ,
63175 ...guide . install_cli . map ( ( line ) => ` ${ line } ` ) ,
64176 "" ,
65- "Install or update skill:" ,
177+ ` ${ t ( "installSkill" ) } :` ,
66178 ...guide . install_skill . map ( ( line ) => ` ${ line } ` ) ,
67179 "" ,
68- "Check:" ,
180+ ` ${ t ( "check" ) } :` ,
69181 ...guide . check_commands . map ( ( line ) => ` ${ line } ` ) ,
70182 "" ,
71- "Usage:" ,
183+ ` ${ t ( "usage" ) } :` ,
72184 ...guide . usage_examples . map ( ( line ) => ` ${ line } ` ) ,
73185 ] ;
74186 if ( guide . reader_auto_note ) {
75- lines . push ( "" , `Reader auto : ${ guide . reader_auto_note } ` ) ;
187+ lines . push ( "" , `${ t ( "readerAuto" ) } : ${ guide . reader_auto_note } ` ) ;
76188 }
77189 if ( guide . repair_commands && guide . repair_commands . length ) {
78- lines . push ( "" , "Repair:" ) ;
190+ lines . push ( "" , ` ${ t ( "repair" ) } :` ) ;
79191 guide . repair_commands . forEach ( ( item ) => {
80192 lines . push ( ` # ${ item . message } ` , ` ${ item . command } ` ) ;
81193 } ) ;
@@ -137,6 +249,13 @@ function escapeHTML(value) {
137249}
138250
139251$ ( "refresh" ) . addEventListener ( "click" , refresh ) ;
252+ $ ( "language-select" ) . addEventListener ( "change" , ( event ) => {
253+ state . lang = event . target . value === "zh" ? "zh" : "en" ;
254+ localStorage . setItem ( "web-tools-language" , state . lang ) ;
255+ applyLanguage ( ) ;
256+ if ( state . status ) renderStatus ( state . status ) ;
257+ if ( state . guide ) renderGuide ( state . guide ) ;
258+ } ) ;
140259$ ( "provider-form" ) . addEventListener ( "submit" , ( event ) => {
141260 event . preventDefault ( ) ;
142261 submitForm ( event . currentTarget , "/api/setup/provider" ) ;
@@ -155,6 +274,11 @@ $("reader-form").addEventListener("submit", (event) => {
155274} ) ;
156275$ ( "copy-guide" ) . addEventListener ( "click" , async ( ) => {
157276 await navigator . clipboard . writeText ( $ ( "agent-guide" ) . textContent ) ;
277+ const button = $ ( "copy-guide" ) ;
278+ button . textContent = t ( "copied" ) ;
279+ setTimeout ( ( ) => {
280+ button . textContent = t ( "copy" ) ;
281+ } , 1200 ) ;
158282} ) ;
159283$ ( "download-diagnostics" ) . addEventListener ( "click" , async ( ) => {
160284 const data = await api ( "/api/diagnostics" ) ;
@@ -167,6 +291,7 @@ $("download-diagnostics").addEventListener("click", async () => {
167291 URL . revokeObjectURL ( url ) ;
168292} ) ;
169293
294+ applyLanguage ( ) ;
170295refresh ( ) . catch ( ( err ) => {
171296 $ ( "output" ) . textContent = err . message ;
172297} ) ;
0 commit comments