qwerty-cli 0.0.1-alpha.18 → 0.0.1-alpha.20
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/ConfigEditor-YYZQ7TUJ.js +2 -0
- package/dist/ConfigEditor-YYZQ7TUJ.js.map +1 -0
- package/dist/{DictBrowser-ZQ773KQV.js → DictBrowser-I6AEYY2I.js} +2 -2
- package/dist/{HelpScreen-Y3TWEEWZ.js → HelpScreen-IKHDZGTG.js} +2 -2
- package/dist/PracticeScreen-4GUFONK5.js +2 -0
- package/dist/PracticeScreen-4GUFONK5.js.map +1 -0
- package/dist/{StatsViewer-XARAMVZW.js → StatsViewer-JIFWFPDL.js} +2 -2
- package/dist/{WordLookup-LKBEPDTB.js → WordLookup-6JFXQYSQ.js} +2 -2
- package/dist/{chunk-DURXS5MX.js → chunk-EBAA2ZKH.js} +2 -2
- package/dist/{chunk-TCYEMBFW.js → chunk-G2SXVAHM.js} +2 -2
- package/dist/{chunk-CQRKGMPU.js → chunk-MFGIEKBU.js} +2 -2
- package/dist/chunk-VIOZNKSK.js +2 -0
- package/dist/chunk-VIOZNKSK.js.map +1 -0
- package/dist/chunk-VTIB5Q36.js +2 -0
- package/dist/chunk-VTIB5Q36.js.map +1 -0
- package/dist/cli.js +1 -1
- package/dist/{config.impl-3O5SL5QY.js → config.impl-55HI447G.js} +2 -2
- package/dist/{dict.impl-JAQ2GXCS.js → dict.impl-2SWDIDWC.js} +2 -2
- package/dist/{doctor.impl-XVZCEC2O.js → doctor.impl-KOEIKBKP.js} +2 -2
- package/dist/{menu.impl-HBP6CFSW.js → menu.impl-A3NQTDOR.js} +2 -2
- package/dist/{practice.impl-AVTRDL7X.js → practice.impl-FQ4HFJAL.js} +2 -2
- package/dist/{word.impl-CUBY4EZ4.js → word.impl-EJNGBD7U.js} +2 -2
- package/package.json +1 -1
- package/dist/ConfigEditor-ZJ52VG3I.js +0 -2
- package/dist/ConfigEditor-ZJ52VG3I.js.map +0 -1
- package/dist/PracticeScreen-PWXXG33U.js +0 -2
- package/dist/PracticeScreen-PWXXG33U.js.map +0 -1
- package/dist/chunk-7LTZGB7F.js +0 -2
- package/dist/chunk-7LTZGB7F.js.map +0 -1
- package/dist/chunk-FQ2MEK7M.js +0 -2
- package/dist/chunk-FQ2MEK7M.js.map +0 -1
- /package/dist/{DictBrowser-ZQ773KQV.js.map → DictBrowser-I6AEYY2I.js.map} +0 -0
- /package/dist/{HelpScreen-Y3TWEEWZ.js.map → HelpScreen-IKHDZGTG.js.map} +0 -0
- /package/dist/{StatsViewer-XARAMVZW.js.map → StatsViewer-JIFWFPDL.js.map} +0 -0
- /package/dist/{WordLookup-LKBEPDTB.js.map → WordLookup-6JFXQYSQ.js.map} +0 -0
- /package/dist/{chunk-DURXS5MX.js.map → chunk-EBAA2ZKH.js.map} +0 -0
- /package/dist/{chunk-TCYEMBFW.js.map → chunk-G2SXVAHM.js.map} +0 -0
- /package/dist/{chunk-CQRKGMPU.js.map → chunk-MFGIEKBU.js.map} +0 -0
- /package/dist/{config.impl-3O5SL5QY.js.map → config.impl-55HI447G.js.map} +0 -0
- /package/dist/{dict.impl-JAQ2GXCS.js.map → dict.impl-2SWDIDWC.js.map} +0 -0
- /package/dist/{doctor.impl-XVZCEC2O.js.map → doctor.impl-KOEIKBKP.js.map} +0 -0
- /package/dist/{menu.impl-HBP6CFSW.js.map → menu.impl-A3NQTDOR.js.map} +0 -0
- /package/dist/{practice.impl-AVTRDL7X.js.map → practice.impl-FQ4HFJAL.js.map} +0 -0
- /package/dist/{word.impl-CUBY4EZ4.js.map → word.impl-EJNGBD7U.js.map} +0 -0
package/dist/chunk-FQ2MEK7M.js
DELETED
|
@@ -1,2 +0,0 @@
|
|
|
1
|
-
import{createContext as k,useContext as E,useState as v,useCallback as g}from"react";import{jsx as L}from"react/jsx-runtime";var h=k(null);function N({initial:t,children:e}){let[n,r]=v([t]),s=g(i=>{r(o=>[...o,i])},[]),a=g(i=>{r(o=>o.length===0?[i]:[...o.slice(0,-1),i])},[]),u=g(()=>{r(i=>i.length>1?i.slice(0,-1):i)},[]),c=g(i=>{r([i])},[]),l=n[n.length-1];return L(h.Provider,{value:{current:l,stack:n,navigate:s,replace:a,back:u,reset:c},children:e})}function D(){let t=E(h);if(!t)throw new Error("useNav must be used inside NavProvider");return t}import{createContext as x,useContext as S,useMemo as $}from"react";var d={app:{title:"qwerty",subtitle:"typing practice for the terminal"},common:{back:"back",quit:"quit",on:"on",off:"off",cancel:"cancel"},mainMenu:{items:{practiceLabel:"Practice",practiceHintWith:t=>`start ${t}`,practiceHintNone:"pick a dictionary",dictLabel:"Dictionaries",dictHint:"browse, pull, set default",wordLabel:"Word lookup",wordHint:"search local dicts",statsLabel:"Stats",statsHint:"history & trends",configLabel:"Config",configHint:"edit preferences",stealthLabel:"Stealth",stealthHint:"quiet practice mode",quitLabel:"Quit",quitHint:"Esc or Ctrl+C also exits"},hint:"\u2191/\u2193 navigate \xB7 Enter select \xB7 letters jump",helpHint:"? help"},dict:{title:"Dictionaries",loading:"loading dictionaries\u2026",entries:t=>`${t} entries`,filterPlaceholder:"type to filter",local:"local \u2713",notLocal:"not local",defaultMark:"default \u2605",tagsLabel:t=>`tags: ${t}`,wordsLabel:t=>`${t} words`,pulling:t=>`pulling ${t}\u2026`,removing:t=>`removing ${t}\u2026`,errorOn:(t,e)=>`error on ${t}: ${e}`,footer:"\u2191/\u2193 select \xB7 Enter actions \xB7 Ctrl+K more \xB7 Esc back",action:{title:"current dictionary",setDefault:"set as default",practice:"practice now",delete:"delete local"},command:{title:"more actions",pull:"pull selected",import:"import .json",refreshList:"update dictionary list"}},config:{title:"Config",fields:{defaultDict:"default dict",defaultMode:"default mode",accent:"accent",mirror:"dict mirror",chapterSize:"chapter size",autoplayPronunciation:"autoplay pronunciation",soundsMaster:"sounds master",soundsKeystroke:"sounds keystroke",soundsFeedback:"sounds feedback",soundsPronunciationRate:"pronunciation rate",soundsPronunciationSource:"pronunciation source",language:"language",stealth:"stealth mode"},enumValues:{stealth:{off:"off",menu:"show in menu",default:"default practice"},soundsPronunciationSource:{youdao:"Youdao",dictapi:"Wiktionary"},defaultMode:{order:"order",dictation:"dictation",review:"review",random:"random",loop:"loop"}},hints:{editing:"type to edit \xB7 Enter save \xB7 Esc cancel",bool:"space toggle \xB7 \u2191/\u2193 move \xB7 Esc back",enum:"\u2190/\u2192 cycle \xB7 \u2191/\u2193 move \xB7 Esc back",dictRef:"Enter pick dict \xB7 \u2191/\u2193 move \xB7 Esc back",stringOrInt:"Enter edit \xB7 \u2191/\u2193 move \xB7 Esc back"}},stats:{title:"Stats \xB7 overview",loading:"loading stats\u2026",none:"No practice history yet.",nonePractice:"Run a practice session first.",lifetime:"lifetime",sessions:"sessions",words:"words",errors:"errors",wpm:"wpm",accuracy:"accuracy",streak:"streak",last:t=>`last ${t} days (\u2190/\u2192 cycle window)`,cycleWindow:"\u2190/\u2192 cycle window \xB7 Esc back",recent:"recent sessions",topMistakes:"top mistakes",footer:"\u2190/\u2192 cycle window \xB7 Esc back",maxLabel:"max",recentUnits:{words:"w",errors:"err",wpm:"wpm"},multiDictSuffix:t=>` +${t} more`,bars:{speed:"speed",accuracy:"accuracy",sessions:"sessions"}},word:{title:"Word lookup",indexing:"indexing local dictionaries\u2026",none:"No local dictionaries.",pullFirst:"Pull one in Dictionaries first.",countAcross:t=>`${t} words across local dicts`,noMatches:t=>`no matches for "${t}"`,inDict:t=>`in: ${t}`,mistakes:(t,e)=>`mistakes: ${t} (last ${e})`,footer:"type to filter \xB7 \u2191/\u2193 select \xB7 Esc back"},practice:{loading:"loading\u2026",paused:"PAUSED",chapterComplete:"CHAPTER COMPLETE",chapterLabel:(t,e)=>`chapter ${t}/${e}`,reviewLabel:"review",statusBar:{mode:"mode",accent:"accent"},modes:{order:"order",dictation:"dictation",review:"review",random:"random",loop:"loop"},accents:{us:"us",uk:"uk"},statCards:{words:"words",errors:"errors",wpm:"wpm",accuracy:"accuracy",elapsed:t=>`elapsed ${t}`},pause:{title:"PAUSED",chapter:(t,e)=>`chapter ${t}/${e}`,progress:(t,e)=>`${t}/${e}`,hint:"Enter resume \xB7 Esc back to menu"},summary:{loopAgain:"again",nextChapter:"next chapter",reviewMistakes:"review mistakes",backMenu:"back to menu"},footers:{typing:"Ctrl+N skip \xB7 Esc pause \xB7 Tab replay"},errors:{noMistakes:"No mistakes to review yet. Practice some chapters first.",dictEmpty:t=>`Dictionary ${t} is empty.`,unknown:"Unknown error"},imeWarning:"! Non-English input detected \u2014 switch your IME to English.",imeWarningShort:"! IME",audioWarningShort:"! audio"},audio:{noPlayer:"! No audio player found on PATH (looked for afplay/ffplay/mpg123/paplay/aplay/powershell). Sounds disabled."},report:{title:"Session summary",duration:"duration",practiced:"practiced",chapters:"chapters",words:"words",accuracy:"accuracy",wpm:"wpm",newMistakes:"new mistakes",farewell:"see you next time.",notPracticed:"no practice this run"},help:{title:"Help",subtitle:"all shortcuts",sections:{main:"main menu",practice:"practice",dict:"dictionaries",config:"config",stats:"stats",word:"word lookup",global:"global"},keys:{navigate:"\u2191/\u2193 navigate items",select:"Enter confirm / continue",letterJump:"letter jump to menu item",pause:"Esc pause practice",skip:"Ctrl+N skip current word (neutral)",replay:"Tab replay pronunciation",resume:"Enter resume from pause",backMenu:"Esc back to previous screen",backScreen:"Esc close panel or back",nextChapter:"Enter next chapter",reviewMistakes:"m review mistakes",filter:"type to filter list",itemActions:"Enter open actions panel",moreActions:"Ctrl+K more actions panel",cycleWindow:"\u2190/\u2192 cycle day window",stealthToggle:"Ctrl+I toggle stealth info row",helpScreen:"? open this help screen",quit:"Ctrl+C quit immediately"},footer:"Esc back"},stealth:{paused:"paused",chapterDone:"chapter done",resumeHint:"Enter resume \xB7 Esc menu",nextHint:"Enter next \xB7 Esc menu",pausedHintRight:"Enter resume",nextHintRight:"Enter next",infoChipLabel:"info",infoFmt:(t,e,n,r,s,a)=>`${t} \xB7 ${e} \xB7 ${n}/${r} \xB7 ${s} wpm \xB7 ${a}%`}},p={app:{title:"qwerty",subtitle:"\u7EC8\u7AEF\u952E\u76D8\u7EC3\u4E60"},common:{back:"\u8FD4\u56DE",quit:"\u9000\u51FA",on:"\u5F00",off:"\u5173",cancel:"\u53D6\u6D88"},mainMenu:{items:{practiceLabel:"\u7EC3\u4E60",practiceHintWith:t=>`\u5F00\u59CB ${t}`,practiceHintNone:"\u8BF7\u5148\u9009\u8BCD\u5178",dictLabel:"\u8BCD\u5178",dictHint:"\u6D4F\u89C8\u3001\u4E0B\u8F7D\u3001\u8BBE\u4E3A\u9ED8\u8BA4",wordLabel:"\u67E5\u8BCD",wordHint:"\u5728\u672C\u5730\u8BCD\u5178\u4E2D\u641C\u7D22",statsLabel:"\u7EDF\u8BA1",statsHint:"\u5386\u53F2\u4E0E\u8D8B\u52BF",configLabel:"\u8BBE\u7F6E",configHint:"\u4FEE\u6539\u504F\u597D",stealthLabel:"\u795E\u9690",stealthHint:"\u795E\u9690\u7EC3\u4E60\u6A21\u5F0F",quitLabel:"\u9000\u51FA",quitHint:"Esc \u6216 Ctrl+C \u9000\u51FA"},hint:"\u2191/\u2193 \u79FB\u52A8 \xB7 Enter \u786E\u8BA4 \xB7 \u5B57\u6BCD\u76F4\u8FBE",helpHint:"? \u5E2E\u52A9"},dict:{title:"\u8BCD\u5178",loading:"\u52A0\u8F7D\u8BCD\u5178\u4E2D\u2026",entries:t=>`${t} \u90E8\u8BCD\u5178`,filterPlaceholder:"\u8F93\u5165\u8FC7\u6EE4",local:"\u5DF2\u4E0B\u8F7D \u2713",notLocal:"\u672A\u4E0B\u8F7D",defaultMark:"\u9ED8\u8BA4 \u2605",tagsLabel:t=>`\u6807\u7B7E:${t}`,wordsLabel:t=>`${t} \u8BCD`,pulling:t=>`\u62C9\u53D6 ${t} \u4E2D\u2026`,removing:t=>`\u5220\u9664 ${t} \u4E2D\u2026`,errorOn:(t,e)=>`${t} \u51FA\u9519:${e}`,footer:"\u2191/\u2193 \u9009\u62E9 \xB7 Enter \u64CD\u4F5C \xB7 Ctrl+K \u66F4\u591A \xB7 Esc \u8FD4\u56DE",action:{title:"\u5F53\u524D\u8BCD\u5178",setDefault:"\u8BBE\u4E3A\u9ED8\u8BA4",practice:"\u7ACB\u5373\u7EC3\u4E60",delete:"\u5220\u9664\u672C\u5730"},command:{title:"\u66F4\u591A\u529F\u80FD",pull:"\u62C9\u53D6\u9009\u4E2D",import:"\u5BFC\u5165 .json",refreshList:"\u66F4\u65B0\u8BCD\u5178\u5217\u8868"}},config:{title:"\u8BBE\u7F6E",fields:{defaultDict:"\u9ED8\u8BA4\u8BCD\u5178",defaultMode:"\u9ED8\u8BA4\u6A21\u5F0F",accent:"\u53D1\u97F3",mirror:"\u8BCD\u5178\u955C\u50CF\u6E90",chapterSize:"\u7AE0\u8282\u5355\u8BCD\u6570",autoplayPronunciation:"\u81EA\u52A8\u64AD\u653E\u53D1\u97F3",soundsMaster:"\u97F3\u6548\u603B\u5F00\u5173",soundsKeystroke:"\u6309\u952E\u97F3",soundsFeedback:"\u53CD\u9988\u97F3",soundsPronunciationRate:"\u53D1\u97F3\u901F\u7387",soundsPronunciationSource:"\u53D1\u97F3\u97F3\u6E90",language:"\u8BED\u8A00",stealth:"\u795E\u9690\u6A21\u5F0F"},enumValues:{stealth:{off:"\u5173\u95ED",menu:"\u4E3B\u83DC\u5355\u663E\u793A",default:"\u9ED8\u8BA4\u7EC3\u4E60\u6A21\u5F0F"},soundsPronunciationSource:{youdao:"\u6709\u9053\u8BCD\u5178",dictapi:"\u7EF4\u57FA\u8BCD\u5178"},defaultMode:{order:"\u987A\u5E8F",dictation:"\u9ED8\u5199",review:"\u590D\u4E60",random:"\u4E71\u5E8F",loop:"\u5FAA\u73AF"}},hints:{editing:"\u8F93\u5165\u4FEE\u6539 \xB7 Enter \u4FDD\u5B58 \xB7 Esc \u53D6\u6D88",bool:"\u7A7A\u683C\u5207\u6362 \xB7 \u2191/\u2193 \u79FB\u52A8 \xB7 Esc \u8FD4\u56DE",enum:"\u2190/\u2192 \u5207\u6362 \xB7 \u2191/\u2193 \u79FB\u52A8 \xB7 Esc \u8FD4\u56DE",dictRef:"Enter \u9009\u8BCD\u5178 \xB7 \u2191/\u2193 \u79FB\u52A8 \xB7 Esc \u8FD4\u56DE",stringOrInt:"Enter \u7F16\u8F91 \xB7 \u2191/\u2193 \u79FB\u52A8 \xB7 Esc \u8FD4\u56DE"}},stats:{title:"\u7EDF\u8BA1 \xB7 \u6982\u89C8",loading:"\u52A0\u8F7D\u7EDF\u8BA1\u4E2D\u2026",none:"\u8FD8\u6CA1\u6709\u7EC3\u4E60\u8BB0\u5F55\u3002",nonePractice:"\u5148\u6765\u4E00\u6B21\u7EC3\u4E60\u5427\u3002",lifetime:"\u7D2F\u8BA1",sessions:"\u4F1A\u8BDD",words:"\u8BCD\u6570",errors:"\u9519\u8BEF",wpm:"\u901F\u5EA6",accuracy:"\u51C6\u786E\u7387",streak:"\u8FDE\u7EED\u5929\u6570",last:t=>`\u6700\u8FD1 ${t} \u5929 (\u2190/\u2192 \u5207\u6362\u7A97\u53E3)`,cycleWindow:"\u2190/\u2192 \u5207\u6362\u7A97\u53E3 \xB7 Esc \u8FD4\u56DE",recent:"\u6700\u8FD1\u4F1A\u8BDD",topMistakes:"\u9AD8\u9891\u9519\u8BCD",footer:"\u2190/\u2192 \u5207\u6362\u7A97\u53E3 \xB7 Esc \u8FD4\u56DE",maxLabel:"\u6700\u5927",recentUnits:{words:"\u8BCD",errors:"\u9519",wpm:"\u901F"},multiDictSuffix:t=>` \u7B49 ${t} \u90E8`,bars:{speed:"\u901F\u5EA6",accuracy:"\u51C6\u786E\u7387",sessions:"\u4F1A\u8BDD"}},word:{title:"\u67E5\u8BCD",indexing:"\u7D22\u5F15\u672C\u5730\u8BCD\u5178\u4E2D\u2026",none:"\u6CA1\u6709\u672C\u5730\u8BCD\u5178\u3002",pullFirst:"\u5148\u5728\u300C\u8BCD\u5178\u300D\u4E2D\u62C9\u53D6\u4E00\u90E8\u3002",countAcross:t=>`\u672C\u5730\u8BCD\u5178\u5171 ${t} \u8BCD`,noMatches:t=>`\u6CA1\u6709\u5339\u914D\u300C${t}\u300D\u7684\u8BCD`,inDict:t=>`\u6765\u6E90:${t}`,mistakes:(t,e)=>`\u9519\u8FC7 ${t} \u6B21 (\u6700\u8FD1 ${e})`,footer:"\u8F93\u5165\u8FC7\u6EE4 \xB7 \u2191/\u2193 \u9009\u62E9 \xB7 Esc \u8FD4\u56DE"},practice:{loading:"\u52A0\u8F7D\u4E2D\u2026",paused:"\u5DF2\u6682\u505C",chapterComplete:"\u672C\u7AE0\u5B8C\u6210",chapterLabel:(t,e)=>`\u7B2C ${t}/${e} \u7AE0`,reviewLabel:"\u590D\u4E60",statusBar:{mode:"\u6A21\u5F0F",accent:"\u53D1\u97F3"},modes:{order:"\u987A\u5E8F",dictation:"\u9ED8\u5199",review:"\u590D\u4E60",random:"\u4E71\u5E8F",loop:"\u5FAA\u73AF"},accents:{us:"\u7F8E",uk:"\u82F1"},statCards:{words:"\u8BCD\u6570",errors:"\u9519\u8BEF",wpm:"\u901F\u5EA6",accuracy:"\u51C6\u786E\u7387",elapsed:t=>`\u8017\u65F6 ${t}`},pause:{title:"\u5DF2\u6682\u505C",chapter:(t,e)=>`\u7B2C ${t}/${e} \u7AE0`,progress:(t,e)=>`${t}/${e}`,hint:"Enter \u7EE7\u7EED \xB7 Esc \u8FD4\u56DE\u83DC\u5355"},summary:{loopAgain:"\u518D\u6765\u4E00\u904D",nextChapter:"\u4E0B\u4E00\u7AE0",reviewMistakes:"\u590D\u4E60\u9519\u8BCD",backMenu:"\u8FD4\u56DE\u83DC\u5355"},footers:{typing:"Ctrl+N \u8DF3\u8FC7 \xB7 Esc \u6682\u505C \xB7 Tab \u91CD\u64AD"},errors:{noMistakes:"\u9519\u8BCD\u672C\u662F\u7A7A\u7684\u3002\u5148\u7EC3\u4E60\u51E0\u7AE0\u5427\u3002",dictEmpty:t=>`\u8BCD\u5178 ${t} \u662F\u7A7A\u7684\u3002`,unknown:"\u672A\u77E5\u9519\u8BEF"},imeWarning:"! \u68C0\u6D4B\u5230\u4E2D\u6587/\u65E5\u6587/\u97E9\u6587\u8F93\u5165\uFF0C\u8BF7\u5207\u6362\u5230\u82F1\u6587\u8F93\u5165\u6CD5",imeWarningShort:"! \u4E2D\u6587\u8F93\u5165",audioWarningShort:"! \u65E0\u97F3\u6548"},audio:{noPlayer:"! \u672A\u5728 PATH \u4E2D\u627E\u5230\u97F3\u9891\u64AD\u653E\u5668(\u5C1D\u8BD5 afplay/ffplay/mpg123/paplay/aplay/powershell)\u3002\u97F3\u6548\u5DF2\u7981\u7528\u3002"},report:{title:"\u672C\u6B21\u4F1A\u8BDD",duration:"\u603B\u65F6\u957F",practiced:"\u7EC3\u4E60\u7528\u65F6",chapters:"\u5B8C\u6210\u7AE0\u8282",words:"\u8BCD\u6570",accuracy:"\u51C6\u786E\u7387",wpm:"\u901F\u5EA6",newMistakes:"\u65B0\u9519\u8BCD",farewell:"\u4E0B\u6B21\u89C1\u3002",notPracticed:"\u672C\u6B21\u672A\u7EC3\u4E60"},help:{title:"\u5E2E\u52A9",subtitle:"\u5168\u90E8\u5FEB\u6377\u952E",sections:{main:"\u4E3B\u83DC\u5355",practice:"\u7EC3\u4E60",dict:"\u8BCD\u5178",config:"\u8BBE\u7F6E",stats:"\u7EDF\u8BA1",word:"\u67E5\u8BCD",global:"\u5168\u5C40"},keys:{navigate:"\u2191/\u2193 \u79FB\u52A8\u9009\u9879",select:"Enter \u786E\u8BA4 / \u7EE7\u7EED",letterJump:"\u5B57\u6BCD\u952E \u76F4\u8FBE\u83DC\u5355\u9879",pause:"Esc \u6682\u505C\u7EC3\u4E60",skip:"Ctrl+N \u8DF3\u8FC7\u5F53\u524D\u8BCD(\u4E0D\u8BA1\u9519)",replay:"Tab \u91CD\u64AD\u53D1\u97F3",resume:"Enter \u7EE7\u7EED\u7EC3\u4E60",backMenu:"Esc \u8FD4\u56DE\u4E0A\u4E00\u5C4F",backScreen:"Esc \u5173\u95ED\u9762\u677F / \u8FD4\u56DE",nextChapter:"Enter \u4E0B\u4E00\u7AE0",reviewMistakes:"m \u590D\u4E60\u9519\u8BCD",filter:"\u8F93\u5165 \u8FC7\u6EE4\u5217\u8868",itemActions:"Enter \u5F39\u51FA\u52A8\u4F5C\u9762\u677F",moreActions:"Ctrl+K \u5F39\u51FA\u66F4\u591A\u529F\u80FD",cycleWindow:"\u2190/\u2192 \u5207\u6362\u65E5\u7A97\u53E3",stealthToggle:"Ctrl+I \u5207\u6362\u795E\u9690\u4FE1\u606F\u884C",helpScreen:"? \u6253\u5F00\u672C\u5E2E\u52A9\u9875",quit:"Ctrl+C \u7ACB\u5373\u9000\u51FA"},footer:"Esc \u8FD4\u56DE"},stealth:{paused:"paused",chapterDone:"chapter done",resumeHint:"Enter resume \xB7 Esc menu",nextHint:"Enter next \xB7 Esc menu",pausedHintRight:"Enter \u7EE7\u7EED",nextHintRight:"Enter \u4E0B\u4E00\u7AE0",infoChipLabel:"\u4FE1\u606F",infoFmt:(t,e,n,r,s,a)=>`${t} \xB7 ${e} \xB7 ${n}/${r} \xB7 ${s} wpm \xB7 ${a}%`}};function b(t){if(!t)return null;let e=t.toLowerCase();return e.startsWith("zh")?"zh":e.startsWith("en")?"en":null}function m(t){if(t==="zh"||t==="en")return t;let e=process.env.LC_ALL||process.env.LC_MESSAGES||process.env.LANG||process.env.LANGUAGE,n=b(e);if(n)return n;try{let r=Intl.DateTimeFormat().resolvedOptions().locale,s=b(r);if(s)return s}catch{}return"en"}import{jsx as P}from"react/jsx-runtime";var w=x(null);function I({pref:t,children:e}){let n=$(()=>{let r=m(t);return{lang:r,t:r==="zh"?p:d}},[t]);return P(w.Provider,{value:n,children:e})}function O(){let t=S(w);if(!t)throw new Error("useStrings must be used inside StringsProvider");return t.t}function K(t){let e=m(t);return{lang:e,t:e==="zh"?p:d}}import{Box as C,Text as M}from"ink";import{jsx as y}from"react/jsx-runtime";var f={accent:"#5eead4",muted:"#6b7280",text:"#e5e7eb",primary:"#7dcfff",success:"#86efac",warning:"#fbbf24",error:"#f87171"};function G({target:t,typed:e,error:n=!1,hideTarget:r=!1}){let s=[...t],a=[...e];return y(C,{paddingY:4,justifyContent:"center",children:s.map((u,c)=>{let l=c<a.length,i=r&&!l?"_":l?a[c]:u,o=n?f.error:l?f.accent:f.muted;return y(M,{bold:!0,color:o,children:i},c)})})}export{N as a,D as b,I as c,O as d,K as e,f,G as g};
|
|
2
|
-
//# sourceMappingURL=chunk-FQ2MEK7M.js.map
|
|
@@ -1 +0,0 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/ui/nav.tsx","../src/i18n/context.tsx","../src/i18n/strings.ts","../src/i18n/locale.ts","../src/ui/components/BigWord.tsx"],"sourcesContent":["import { createContext, useContext, useState, useCallback, type ReactNode } from 'react';\n\nexport type ScreenName =\n | 'main'\n | 'practice'\n | 'dict'\n | 'config'\n | 'stats'\n | 'word'\n | 'help';\n\nexport type PracticeParams = {\n dictId: string;\n chapterIndex: number;\n mode: 'order' | 'dictation' | 'review' | 'random' | 'loop';\n stealth?: boolean;\n};\n\nexport type DictParams = {\n pickerMode?: 'set-default' | 'choose-then-practice';\n};\n\nexport type ScreenFrame =\n | { name: 'main' }\n | { name: 'practice'; params: PracticeParams }\n | { name: 'dict'; params?: DictParams }\n | { name: 'config' }\n | { name: 'stats' }\n | { name: 'word' }\n | { name: 'help' };\n\ntype NavContextValue = {\n current: ScreenFrame;\n stack: ScreenFrame[];\n navigate: (frame: ScreenFrame) => void;\n replace: (frame: ScreenFrame) => void;\n back: () => void;\n reset: (frame: ScreenFrame) => void;\n};\n\nconst NavContext = createContext<NavContextValue | null>(null);\n\nexport function NavProvider({ initial, children }: { initial: ScreenFrame; children: ReactNode }) {\n const [stack, setStack] = useState<ScreenFrame[]>([initial]);\n\n const navigate = useCallback((frame: ScreenFrame) => {\n setStack((s) => [...s, frame]);\n }, []);\n const replace = useCallback((frame: ScreenFrame) => {\n setStack((s) => (s.length === 0 ? [frame] : [...s.slice(0, -1), frame]));\n }, []);\n const back = useCallback(() => {\n setStack((s) => (s.length > 1 ? s.slice(0, -1) : s));\n }, []);\n const reset = useCallback((frame: ScreenFrame) => {\n setStack([frame]);\n }, []);\n\n const current = stack[stack.length - 1]!;\n return (\n <NavContext.Provider value={{ current, stack, navigate, replace, back, reset }}>\n {children}\n </NavContext.Provider>\n );\n}\n\nexport function useNav(): NavContextValue {\n const ctx = useContext(NavContext);\n if (!ctx) throw new Error('useNav must be used inside NavProvider');\n return ctx;\n}\n","import { createContext, useContext, useMemo, type ReactNode } from 'react';\nimport { en, zh, type Strings } from './strings.js';\nimport { detectLocale, type Lang, type LangPref } from './locale.js';\n\nconst StringsContext = createContext<{ lang: Lang; t: Strings } | null>(null);\n\nexport function StringsProvider({\n pref,\n children,\n}: {\n pref: LangPref;\n children: ReactNode;\n}) {\n const value = useMemo(() => {\n const lang = detectLocale(pref);\n return { lang, t: lang === 'zh' ? zh : en };\n }, [pref]);\n return <StringsContext.Provider value={value}>{children}</StringsContext.Provider>;\n}\n\nexport function useStrings(): Strings {\n const ctx = useContext(StringsContext);\n if (!ctx) throw new Error('useStrings must be used inside StringsProvider');\n return ctx.t;\n}\n\nexport function useLang(): Lang {\n const ctx = useContext(StringsContext);\n if (!ctx) throw new Error('useLang must be used inside StringsProvider');\n return ctx.lang;\n}\n\nexport function pickStrings(pref: LangPref): { lang: Lang; t: Strings } {\n const lang = detectLocale(pref);\n return { lang, t: lang === 'zh' ? zh : en };\n}\n","// Centralized string table for the qwerty-cli TUI.\n//\n// Print-only subcommands (qwerty config list, qwerty dict list, etc.) keep\n// English output regardless of locale so shell scripts stay predictable.\n// Only the interactive TUI is localized via this table.\n\nexport type Strings = {\n app: {\n title: string;\n subtitle: string;\n };\n common: {\n back: string;\n quit: string;\n on: string;\n off: string;\n cancel: string;\n };\n mainMenu: {\n items: {\n practiceLabel: string;\n practiceHintWith: (name: string) => string;\n practiceHintNone: string;\n dictLabel: string;\n dictHint: string;\n wordLabel: string;\n wordHint: string;\n statsLabel: string;\n statsHint: string;\n configLabel: string;\n configHint: string;\n stealthLabel: string;\n stealthHint: string;\n quitLabel: string;\n quitHint: string;\n };\n hint: string;\n helpHint: string;\n };\n dict: {\n title: string;\n loading: string;\n entries: (n: number) => string;\n filterPlaceholder: string;\n local: string;\n notLocal: string;\n defaultMark: string;\n tagsLabel: (tags: string) => string;\n wordsLabel: (n: number) => string;\n pulling: (id: string) => string;\n removing: (id: string) => string;\n errorOn: (id: string, msg: string) => string;\n footer: string;\n action: {\n title: string;\n setDefault: string;\n practice: string;\n delete: string;\n };\n command: {\n title: string;\n pull: string;\n import: string;\n refreshList: string;\n };\n };\n config: {\n title: string;\n fields: {\n defaultDict: string;\n defaultMode: string;\n accent: string;\n mirror: string;\n chapterSize: string;\n autoplayPronunciation: string;\n soundsMaster: string;\n soundsKeystroke: string;\n soundsFeedback: string;\n soundsPronunciationRate: string;\n soundsPronunciationSource: string;\n language: string;\n stealth: string;\n };\n enumValues: {\n stealth: { off: string; menu: string; default: string };\n soundsPronunciationSource: { youdao: string; dictapi: string };\n defaultMode: { order: string; dictation: string; review: string; random: string; loop: string };\n };\n hints: {\n editing: string;\n bool: string;\n enum: string;\n dictRef: string;\n stringOrInt: string;\n };\n };\n stats: {\n title: string;\n loading: string;\n none: string;\n nonePractice: string;\n lifetime: string;\n sessions: string;\n words: string;\n errors: string;\n wpm: string;\n accuracy: string;\n streak: string;\n last: (n: number) => string;\n cycleWindow: string;\n recent: string;\n topMistakes: string;\n footer: string;\n maxLabel: string;\n recentUnits: { words: string; errors: string; wpm: string };\n multiDictSuffix: (n: number) => string;\n bars: { speed: string; accuracy: string; sessions: string };\n };\n word: {\n title: string;\n indexing: string;\n none: string;\n pullFirst: string;\n countAcross: (n: number) => string;\n noMatches: (q: string) => string;\n inDict: (name: string) => string;\n mistakes: (n: number, date: string) => string;\n footer: string;\n };\n practice: {\n loading: string;\n paused: string;\n chapterComplete: string;\n chapterLabel: (c: number, t: number) => string;\n reviewLabel: string;\n statusBar: {\n mode: string;\n accent: string;\n };\n modes: {\n order: string;\n dictation: string;\n review: string;\n random: string;\n loop: string;\n };\n accents: {\n us: string;\n uk: string;\n };\n statCards: {\n words: string;\n errors: string;\n wpm: string;\n accuracy: string;\n elapsed: (t: string) => string;\n };\n pause: {\n title: string;\n chapter: (c: number, t: number) => string;\n progress: (completed: number, total: number) => string;\n hint: string;\n };\n summary: {\n loopAgain: string;\n nextChapter: string;\n reviewMistakes: string;\n backMenu: string;\n };\n footers: {\n typing: string;\n };\n errors: {\n noMistakes: string;\n dictEmpty: (id: string) => string;\n unknown: string;\n };\n imeWarning: string;\n imeWarningShort: string;\n audioWarningShort: string;\n };\n audio: {\n noPlayer: string;\n };\n report: {\n title: string;\n duration: string;\n practiced: string;\n chapters: string;\n words: string;\n accuracy: string;\n wpm: string;\n newMistakes: string;\n farewell: string;\n notPracticed: string;\n };\n help: {\n title: string;\n subtitle: string;\n sections: {\n main: string;\n practice: string;\n dict: string;\n config: string;\n stats: string;\n word: string;\n global: string;\n };\n keys: {\n navigate: string;\n select: string;\n letterJump: string;\n pause: string;\n skip: string;\n replay: string;\n resume: string;\n backMenu: string;\n backScreen: string;\n nextChapter: string;\n reviewMistakes: string;\n filter: string;\n itemActions: string;\n moreActions: string;\n cycleWindow: string;\n stealthToggle: string;\n helpScreen: string;\n quit: string;\n };\n footer: string;\n };\n stealth: {\n paused: string;\n chapterDone: string;\n resumeHint: string;\n nextHint: string;\n pausedHintRight: string;\n nextHintRight: string;\n infoChipLabel: string;\n infoFmt: (\n dict: string,\n chapter: string,\n completed: number,\n total: number,\n wpm: number,\n accPct: number,\n ) => string;\n };\n};\n\nexport const en: Strings = {\n app: {\n title: 'qwerty',\n subtitle: 'typing practice for the terminal',\n },\n common: {\n back: 'back',\n quit: 'quit',\n on: 'on',\n off: 'off',\n cancel: 'cancel',\n },\n mainMenu: {\n items: {\n practiceLabel: 'Practice',\n practiceHintWith: (name) => `start ${name}`,\n practiceHintNone: 'pick a dictionary',\n dictLabel: 'Dictionaries',\n dictHint: 'browse, pull, set default',\n wordLabel: 'Word lookup',\n wordHint: 'search local dicts',\n statsLabel: 'Stats',\n statsHint: 'history & trends',\n configLabel: 'Config',\n configHint: 'edit preferences',\n stealthLabel: 'Stealth',\n stealthHint: 'quiet practice mode',\n quitLabel: 'Quit',\n quitHint: 'Esc or Ctrl+C also exits',\n },\n hint: '↑/↓ navigate · Enter select · letters jump',\n helpHint: '? help',\n },\n dict: {\n title: 'Dictionaries',\n loading: 'loading dictionaries…',\n entries: (n) => `${n} entries`,\n filterPlaceholder: 'type to filter',\n local: 'local ✓',\n notLocal: 'not local',\n defaultMark: 'default ★',\n tagsLabel: (tags) => `tags: ${tags}`,\n wordsLabel: (n) => `${n} words`,\n pulling: (id) => `pulling ${id}…`,\n removing: (id) => `removing ${id}…`,\n errorOn: (id, msg) => `error on ${id}: ${msg}`,\n footer: '↑/↓ select · Enter actions · Ctrl+K more · Esc back',\n action: {\n title: 'current dictionary',\n setDefault: 'set as default',\n practice: 'practice now',\n delete: 'delete local',\n },\n command: {\n title: 'more actions',\n pull: 'pull selected',\n import: 'import .json',\n refreshList: 'update dictionary list',\n },\n },\n config: {\n title: 'Config',\n fields: {\n defaultDict: 'default dict',\n defaultMode: 'default mode',\n accent: 'accent',\n mirror: 'dict mirror',\n chapterSize: 'chapter size',\n autoplayPronunciation: 'autoplay pronunciation',\n soundsMaster: 'sounds master',\n soundsKeystroke: 'sounds keystroke',\n soundsFeedback: 'sounds feedback',\n soundsPronunciationRate: 'pronunciation rate',\n soundsPronunciationSource: 'pronunciation source',\n language: 'language',\n stealth: 'stealth mode',\n },\n enumValues: {\n stealth: { off: 'off', menu: 'show in menu', default: 'default practice' },\n soundsPronunciationSource: { youdao: 'Youdao', dictapi: 'Wiktionary' },\n defaultMode: { order: 'order', dictation: 'dictation', review: 'review', random: 'random', loop: 'loop' },\n },\n hints: {\n editing: 'type to edit · Enter save · Esc cancel',\n bool: 'space toggle · ↑/↓ move · Esc back',\n enum: '←/→ cycle · ↑/↓ move · Esc back',\n dictRef: 'Enter pick dict · ↑/↓ move · Esc back',\n stringOrInt: 'Enter edit · ↑/↓ move · Esc back',\n },\n },\n stats: {\n title: 'Stats · overview',\n loading: 'loading stats…',\n none: 'No practice history yet.',\n nonePractice: 'Run a practice session first.',\n lifetime: 'lifetime',\n sessions: 'sessions',\n words: 'words',\n errors: 'errors',\n wpm: 'wpm',\n accuracy: 'accuracy',\n streak: 'streak',\n last: (n) => `last ${n} days (←/→ cycle window)`,\n cycleWindow: '←/→ cycle window · Esc back',\n recent: 'recent sessions',\n topMistakes: 'top mistakes',\n footer: '←/→ cycle window · Esc back',\n maxLabel: 'max',\n recentUnits: { words: 'w', errors: 'err', wpm: 'wpm' },\n multiDictSuffix: (n) => ` +${n} more`,\n bars: { speed: 'speed', accuracy: 'accuracy', sessions: 'sessions' },\n },\n word: {\n title: 'Word lookup',\n indexing: 'indexing local dictionaries…',\n none: 'No local dictionaries.',\n pullFirst: 'Pull one in Dictionaries first.',\n countAcross: (n) => `${n} words across local dicts`,\n noMatches: (q) => `no matches for \"${q}\"`,\n inDict: (name) => `in: ${name}`,\n mistakes: (n, date) => `mistakes: ${n} (last ${date})`,\n footer: 'type to filter · ↑/↓ select · Esc back',\n },\n practice: {\n loading: 'loading…',\n paused: 'PAUSED',\n chapterComplete: 'CHAPTER COMPLETE',\n chapterLabel: (c, t) => `chapter ${c}/${t}`,\n reviewLabel: 'review',\n statusBar: {\n mode: 'mode',\n accent: 'accent',\n },\n modes: {\n order: 'order',\n dictation: 'dictation',\n review: 'review',\n random: 'random',\n loop: 'loop',\n },\n accents: {\n us: 'us',\n uk: 'uk',\n },\n statCards: {\n words: 'words',\n errors: 'errors',\n wpm: 'wpm',\n accuracy: 'accuracy',\n elapsed: (t) => `elapsed ${t}`,\n },\n pause: {\n title: 'PAUSED',\n chapter: (c, t) => `chapter ${c}/${t}`,\n progress: (completed, total) => `${completed}/${total}`,\n hint: 'Enter resume · Esc back to menu',\n },\n summary: {\n loopAgain: 'again',\n nextChapter: 'next chapter',\n reviewMistakes: 'review mistakes',\n backMenu: 'back to menu',\n },\n footers: {\n typing: 'Ctrl+N skip · Esc pause · Tab replay',\n },\n errors: {\n noMistakes: 'No mistakes to review yet. Practice some chapters first.',\n dictEmpty: (id) => `Dictionary ${id} is empty.`,\n unknown: 'Unknown error',\n },\n imeWarning: '! Non-English input detected — switch your IME to English.',\n imeWarningShort: '! IME',\n audioWarningShort: '! audio',\n },\n audio: {\n noPlayer: '! No audio player found on PATH (looked for afplay/ffplay/mpg123/paplay/aplay/powershell). Sounds disabled.',\n },\n report: {\n title: 'Session summary',\n duration: 'duration',\n practiced: 'practiced',\n chapters: 'chapters',\n words: 'words',\n accuracy: 'accuracy',\n wpm: 'wpm',\n newMistakes: 'new mistakes',\n farewell: 'see you next time.',\n notPracticed: 'no practice this run',\n },\n help: {\n title: 'Help',\n subtitle: 'all shortcuts',\n sections: {\n main: 'main menu',\n practice: 'practice',\n dict: 'dictionaries',\n config: 'config',\n stats: 'stats',\n word: 'word lookup',\n global: 'global',\n },\n keys: {\n navigate: '↑/↓ navigate items',\n select: 'Enter confirm / continue',\n letterJump: 'letter jump to menu item',\n pause: 'Esc pause practice',\n skip: 'Ctrl+N skip current word (neutral)',\n replay: 'Tab replay pronunciation',\n resume: 'Enter resume from pause',\n backMenu: 'Esc back to previous screen',\n backScreen: 'Esc close panel or back',\n nextChapter: 'Enter next chapter',\n reviewMistakes: 'm review mistakes',\n filter: 'type to filter list',\n itemActions: 'Enter open actions panel',\n moreActions: 'Ctrl+K more actions panel',\n cycleWindow: '←/→ cycle day window',\n stealthToggle: 'Ctrl+I toggle stealth info row',\n helpScreen: '? open this help screen',\n quit: 'Ctrl+C quit immediately',\n },\n footer: 'Esc back',\n },\n stealth: {\n paused: 'paused',\n chapterDone: 'chapter done',\n resumeHint: 'Enter resume · Esc menu',\n nextHint: 'Enter next · Esc menu',\n pausedHintRight: 'Enter resume',\n nextHintRight: 'Enter next',\n infoChipLabel: 'info',\n infoFmt: (dict, chapter, completed, total, wpm, accPct) =>\n `${dict} · ${chapter} · ${completed}/${total} · ${wpm} wpm · ${accPct}%`,\n },\n};\n\nexport const zh: Strings = {\n app: {\n title: 'qwerty',\n subtitle: '终端键盘练习',\n },\n common: {\n back: '返回',\n quit: '退出',\n on: '开',\n off: '关',\n cancel: '取消',\n },\n mainMenu: {\n items: {\n practiceLabel: '练习',\n practiceHintWith: (name) => `开始 ${name}`,\n practiceHintNone: '请先选词典',\n dictLabel: '词典',\n dictHint: '浏览、下载、设为默认',\n wordLabel: '查词',\n wordHint: '在本地词典中搜索',\n statsLabel: '统计',\n statsHint: '历史与趋势',\n configLabel: '设置',\n configHint: '修改偏好',\n stealthLabel: '神隐',\n stealthHint: '神隐练习模式',\n quitLabel: '退出',\n quitHint: 'Esc 或 Ctrl+C 退出',\n },\n hint: '↑/↓ 移动 · Enter 确认 · 字母直达',\n helpHint: '? 帮助',\n },\n dict: {\n title: '词典',\n loading: '加载词典中…',\n entries: (n) => `${n} 部词典`,\n filterPlaceholder: '输入过滤',\n local: '已下载 ✓',\n notLocal: '未下载',\n defaultMark: '默认 ★',\n tagsLabel: (tags) => `标签:${tags}`,\n wordsLabel: (n) => `${n} 词`,\n pulling: (id) => `拉取 ${id} 中…`,\n removing: (id) => `删除 ${id} 中…`,\n errorOn: (id, msg) => `${id} 出错:${msg}`,\n footer: '↑/↓ 选择 · Enter 操作 · Ctrl+K 更多 · Esc 返回',\n action: {\n title: '当前词典',\n setDefault: '设为默认',\n practice: '立即练习',\n delete: '删除本地',\n },\n command: {\n title: '更多功能',\n pull: '拉取选中',\n import: '导入 .json',\n refreshList: '更新词典列表',\n },\n },\n config: {\n title: '设置',\n fields: {\n defaultDict: '默认词典',\n defaultMode: '默认模式',\n accent: '发音',\n mirror: '词典镜像源',\n chapterSize: '章节单词数',\n autoplayPronunciation: '自动播放发音',\n soundsMaster: '音效总开关',\n soundsKeystroke: '按键音',\n soundsFeedback: '反馈音',\n soundsPronunciationRate: '发音速率',\n soundsPronunciationSource: '发音音源',\n language: '语言',\n stealth: '神隐模式',\n },\n enumValues: {\n stealth: { off: '关闭', menu: '主菜单显示', default: '默认练习模式' },\n soundsPronunciationSource: { youdao: '有道词典', dictapi: '维基词典' },\n defaultMode: { order: '顺序', dictation: '默写', review: '复习', random: '乱序', loop: '循环' },\n },\n hints: {\n editing: '输入修改 · Enter 保存 · Esc 取消',\n bool: '空格切换 · ↑/↓ 移动 · Esc 返回',\n enum: '←/→ 切换 · ↑/↓ 移动 · Esc 返回',\n dictRef: 'Enter 选词典 · ↑/↓ 移动 · Esc 返回',\n stringOrInt: 'Enter 编辑 · ↑/↓ 移动 · Esc 返回',\n },\n },\n stats: {\n title: '统计 · 概览',\n loading: '加载统计中…',\n none: '还没有练习记录。',\n nonePractice: '先来一次练习吧。',\n lifetime: '累计',\n sessions: '会话',\n words: '词数',\n errors: '错误',\n wpm: '速度',\n accuracy: '准确率',\n streak: '连续天数',\n last: (n) => `最近 ${n} 天 (←/→ 切换窗口)`,\n cycleWindow: '←/→ 切换窗口 · Esc 返回',\n recent: '最近会话',\n topMistakes: '高频错词',\n footer: '←/→ 切换窗口 · Esc 返回',\n maxLabel: '最大',\n recentUnits: { words: '词', errors: '错', wpm: '速' },\n multiDictSuffix: (n) => ` 等 ${n} 部`,\n bars: { speed: '速度', accuracy: '准确率', sessions: '会话' },\n },\n word: {\n title: '查词',\n indexing: '索引本地词典中…',\n none: '没有本地词典。',\n pullFirst: '先在「词典」中拉取一部。',\n countAcross: (n) => `本地词典共 ${n} 词`,\n noMatches: (q) => `没有匹配「${q}」的词`,\n inDict: (name) => `来源:${name}`,\n mistakes: (n, date) => `错过 ${n} 次 (最近 ${date})`,\n footer: '输入过滤 · ↑/↓ 选择 · Esc 返回',\n },\n practice: {\n loading: '加载中…',\n paused: '已暂停',\n chapterComplete: '本章完成',\n chapterLabel: (c, t) => `第 ${c}/${t} 章`,\n reviewLabel: '复习',\n statusBar: {\n mode: '模式',\n accent: '发音',\n },\n modes: {\n order: '顺序',\n dictation: '默写',\n review: '复习',\n random: '乱序',\n loop: '循环',\n },\n accents: {\n us: '美',\n uk: '英',\n },\n statCards: {\n words: '词数',\n errors: '错误',\n wpm: '速度',\n accuracy: '准确率',\n elapsed: (t) => `耗时 ${t}`,\n },\n pause: {\n title: '已暂停',\n chapter: (c, t) => `第 ${c}/${t} 章`,\n progress: (completed, total) => `${completed}/${total}`,\n hint: 'Enter 继续 · Esc 返回菜单',\n },\n summary: {\n loopAgain: '再来一遍',\n nextChapter: '下一章',\n reviewMistakes: '复习错词',\n backMenu: '返回菜单',\n },\n footers: {\n typing: 'Ctrl+N 跳过 · Esc 暂停 · Tab 重播',\n },\n errors: {\n noMistakes: '错词本是空的。先练习几章吧。',\n dictEmpty: (id) => `词典 ${id} 是空的。`,\n unknown: '未知错误',\n },\n imeWarning: '! 检测到中文/日文/韩文输入,请切换到英文输入法',\n imeWarningShort: '! 中文输入',\n audioWarningShort: '! 无音效',\n },\n audio: {\n noPlayer: '! 未在 PATH 中找到音频播放器(尝试 afplay/ffplay/mpg123/paplay/aplay/powershell)。音效已禁用。',\n },\n report: {\n title: '本次会话',\n duration: '总时长',\n practiced: '练习用时',\n chapters: '完成章节',\n words: '词数',\n accuracy: '准确率',\n wpm: '速度',\n newMistakes: '新错词',\n farewell: '下次见。',\n notPracticed: '本次未练习',\n },\n help: {\n title: '帮助',\n subtitle: '全部快捷键',\n sections: {\n main: '主菜单',\n practice: '练习',\n dict: '词典',\n config: '设置',\n stats: '统计',\n word: '查词',\n global: '全局',\n },\n keys: {\n navigate: '↑/↓ 移动选项',\n select: 'Enter 确认 / 继续',\n letterJump: '字母键 直达菜单项',\n pause: 'Esc 暂停练习',\n skip: 'Ctrl+N 跳过当前词(不计错)',\n replay: 'Tab 重播发音',\n resume: 'Enter 继续练习',\n backMenu: 'Esc 返回上一屏',\n backScreen: 'Esc 关闭面板 / 返回',\n nextChapter: 'Enter 下一章',\n reviewMistakes: 'm 复习错词',\n filter: '输入 过滤列表',\n itemActions: 'Enter 弹出动作面板',\n moreActions: 'Ctrl+K 弹出更多功能',\n cycleWindow: '←/→ 切换日窗口',\n stealthToggle: 'Ctrl+I 切换神隐信息行',\n helpScreen: '? 打开本帮助页',\n quit: 'Ctrl+C 立即退出',\n },\n footer: 'Esc 返回',\n },\n stealth: {\n paused: 'paused',\n chapterDone: 'chapter done',\n resumeHint: 'Enter resume · Esc menu',\n nextHint: 'Enter next · Esc menu',\n pausedHintRight: 'Enter 继续',\n nextHintRight: 'Enter 下一章',\n infoChipLabel: '信息',\n infoFmt: (dict, chapter, completed, total, wpm, accPct) =>\n `${dict} · ${chapter} · ${completed}/${total} · ${wpm} wpm · ${accPct}%`,\n },\n};\n","export type Lang = 'zh' | 'en';\nexport type LangPref = 'auto' | Lang;\n\nfunction pickFromString(s: string | undefined): Lang | null {\n if (!s) return null;\n const lower = s.toLowerCase();\n if (lower.startsWith('zh')) return 'zh';\n if (lower.startsWith('en')) return 'en';\n return null;\n}\n\nexport function detectLocale(pref: LangPref): Lang {\n if (pref === 'zh' || pref === 'en') return pref;\n const env =\n process.env.LC_ALL ||\n process.env.LC_MESSAGES ||\n process.env.LANG ||\n process.env.LANGUAGE;\n const fromEnv = pickFromString(env);\n if (fromEnv) return fromEnv;\n try {\n const intlLocale = Intl.DateTimeFormat().resolvedOptions().locale;\n const fromIntl = pickFromString(intlLocale);\n if (fromIntl) return fromIntl;\n } catch {\n // ignore\n }\n return 'en';\n}\n","import { Box, Text } from 'ink';\n\nexport const PALETTE = {\n accent: '#5eead4',\n muted: '#6b7280',\n text: '#e5e7eb',\n primary: '#7dcfff',\n success: '#86efac',\n warning: '#fbbf24',\n error: '#f87171',\n} as const;\n\ntype Props = {\n target: string;\n typed: string;\n error?: boolean;\n hideTarget?: boolean;\n};\n\nexport function BigWord({ target, typed, error = false, hideTarget = false }: Props) {\n const chars = [...target];\n const typedChars = [...typed];\n\n return (\n <Box paddingY={4} justifyContent=\"center\">\n {chars.map((ch, i) => {\n const isTyped = i < typedChars.length;\n const display = hideTarget && !isTyped ? '_' : isTyped ? typedChars[i]! : ch;\n const color = error\n ? PALETTE.error\n : isTyped\n ? PALETTE.accent\n : PALETTE.muted;\n return (\n <Text key={i} bold color={color}>\n {display}\n </Text>\n );\n })}\n </Box>\n );\n}\n"],"mappings":"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","names":["createContext","useContext","useState","useCallback","jsx","NavContext","NavProvider","initial","children","stack","setStack","navigate","frame","s","replace","back","reset","current","useNav","ctx","createContext","useContext","useMemo","en","name","n","tags","id","msg","q","date","c","t","completed","total","dict","chapter","wpm","accPct","zh","pickFromString","s","lower","detectLocale","pref","env","fromEnv","intlLocale","fromIntl","jsx","StringsContext","createContext","StringsProvider","pref","children","value","useMemo","lang","detectLocale","zh","en","useStrings","ctx","useContext","pickStrings","pref","lang","detectLocale","zh","en","Box","Text","jsx","PALETTE","BigWord","target","typed","error","hideTarget","chars","typedChars","ch","i","isTyped","display","color"]}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|