返回 CodeWhale
types.ts
根目录 / web / lib / i18n / dictionaries / types.ts
1 /**
2 * Dictionary shapes for the website localization layer (#3091, #4934).
3 *
4 * `ChromeDict` covers shared chrome: the newspaper masthead, nav, mobile
5 * menu, theme toggle, live ticker, footer, and the locale switcher with its
6 * visible partial-pack badge. `HomeDict` covers the landing page
7 * (`app/[locale]/page.tsx`). Templates use `{name}` tokens interpolated
8 * with `fill()` from dictionaries/index.ts — never concatenate translated
9 * sentences around variables in JSX.
10 *
11 * English (`dictionaries/en/`) is the reference shape; every routed locale —
12 * including Chinese — must define exactly the same keys. Parity is enforced
13 * by `web/scripts/check-locales.mjs` and `web/lib/i18n/dictionaries.test.ts`.
14 * A locale without a dictionary falls back to the English one at lookup
15 * time, so an untranslated string renders English copy — never a key.
16 *
17 * Code-owned strings stay out of these dictionaries per docs/VOICE.md:
18 * "Plan · Act · Operate", "Ask · Auto-Review · Full Access",
19 * "TUI · exec · web · API", "Codewhale", "GitHub", "Issues",
20 * `npm install -g codewhale`, `cargo test --locked`, `codewhale exec`,
21 * package-manager proper nouns, mirror names, and `/codewhale-tui.png`.
22 */
23
24 export interface ChromeDict {
25 // --- primary nav labels (components/nav.tsx via lib/i18n/links.ts) ---
26 navDocs: string;
27 navStart: string;
28 navInstall: string;
29 navFaq: string;
30 navCommunity: string;
31 navContribute: string;
32
33 /**
34 * Bilingual secondary nav labels — the small companion label the
35 * newspaper masthead sets beside each primary link.
36 *
37 * The English edition uses the Han seal pair (文档 / 指引 / …) as an
38 * editorial device; every other locale supplies its OWN pairing (native
39 * primary, short English secondary). Never hardcode Han characters at a
40 * call site — a locale that wants no second label still needs a value
41 * here, because empty strings are rejected by dictionaries.test.ts.
42 */
43 navDocsSecondary: string;
44 navStartSecondary: string;
45 navInstallSecondary: string;
46 navFaqSecondary: string;
47 navCommunitySecondary: string;
48 navContributeSecondary: string;
49
50 /**
51 * Skip-to-content link rendered before the nav in app/[locale]/layout.tsx.
52 * It sits on EVERY page of EVERY locale, so it belongs to shared chrome —
53 * leaving it hardcoded is what kept an EN/ZH branch alive in the layout.
54 */
55 skipToContent: string;
56
57 /** aria-label for the primary <nav> landmark (components/nav-links.tsx). */
58 navPrimaryAria: string;
59 /** aria-label for the wordmark link back to the locale home. */
60 navHomeAria: string;
61
62 /** Mobile-menu and masthead call to action, e.g. "Install →". */
63 installCta: string;
64
65 /** Wordmark seal glyph beside the masthead brand (components/seal.tsx). */
66 wordmarkSeal: string;
67 /** Wordmark strapline under the brand, e.g. "any model, local-first". */
68 wordmarkTag: string;
69
70 /** Masthead issue line, e.g. "Issue {date}". */
71 issueLabel: string;
72 /**
73 * BCP 47 tag used for the masthead weekday via `toLocaleDateString` — not
74 * rendered copy, but per-locale, so it belongs beside it. Without this the
75 * masthead date renders in English for every non-Chinese locale.
76 */
77 dateLocale: string;
78
79 /** aria-label on the star-count link, e.g. "GitHub stars". */
80 starsAria: string;
81 /** Star-badge label when the live count is unavailable. */
82 githubFallback: string;
83
84 /** Live-ticker seal label (components/ticker.tsx). */
85 tickerLiveLabel: string;
86 /** Live-ticker mono tag beside the seal label, e.g. "LIVE". */
87 tickerLiveTag: string;
88
89 /**
90 * Ticker event verbs — the chrome around the repository's own record.
91 * Pull-request titles, issue titles, release tags, and contributor handles
92 * are CONTENT and stay verbatim in every locale; these verbs are copy and
93 * must be translated.
94 *
95 * `tickerReleased` covers `state: "published"`, and `tickerOpened` covers
96 * both a newly filed issue and an open pull request. There is deliberately
97 * no draft verb: the strip reports events, and a draft pull request is one
98 * its author has marked not-ready (components/ticker.tsx `EVENT_STATES`).
99 */
100 tickerMerged: string;
101 tickerOpened: string;
102 tickerClosed: string;
103 tickerReleased: string;
104 /**
105 * Mark shown when GitHub itself reports the author as a
106 * FIRST_TIME_CONTRIBUTOR — the warmest item on the strip, and never our
107 * inference. Keep it short; it sits inline in a scrolling mono line.
108 */
109 tickerFirstContribution: string;
110 /**
111 * By-line template carrying a `{handle}` token, e.g. "by {handle}". The
112 * handle is typeset in its own element, so a locale may place it anywhere
113 * (or make it the whole value, as ja/ko do with an honorific suffix).
114 */
115 tickerBy: string;
116 /** aria-label for the ticker's group landmark. */
117 tickerAria: string;
118
119 /** TerminalPlayer title-bar label, e.g. "reasoning trace". */
120 traceLabel: string;
121 /** aria-label for the TerminalPlayer scene tablist. */
122 traceTabsAria: string;
123
124 /** Mobile-menu toggle labels. */
125 menuOpen: string;
126 menuClose: string;
127
128 /** Docs theme toggle: the three cycle states. */
129 themeAuto: string;
130 themeLight: string;
131 themeDark: string;
132 /** Theme toggle aria-label, e.g. "Docs theme: {mode} (click to cycle)". */
133 themeAria: string;
134 /** Theme toggle title attribute. */
135 themeTitle: string;
136
137 // --- footer ---
138 footerTagline: string;
139 footerProduct: string;
140 footerProject: string;
141 footerDocs: string;
142 footerGuide: string;
143 footerInstall: string;
144 footerModels: string;
145 footerRuntime: string;
146 footerFaq: string;
147 footerIssues: string;
148 footerContribute: string;
149 footerLicense: string;
150 /** Prefix before the canonical-source link, e.g. "Canonical source: ". */
151 footerCanonicalSource: string;
152 /** Separator + label before the releases link, e.g. " · Releases: ". */
153 footerReleases: string;
154 /** Link text for the GitHub releases page. */
155 footerReleasesLink: string;
156 /** Link text for the security-contact mailto. */
157 footerSecurity: string;
158
159 /** aria-label for the locale switcher control. */
160 switcherLabel: string;
161 /** Two-locale toggle aria-label, e.g. "Switch to {label}". */
162 switcherSwitchTo: string;
163 /**
164 * Visible badge marking a partial locale pack in the switcher, e.g.
165 * "(partial)" — honest scope signal, per the localization quality
166 * contract. Keep it short.
167 */
168 partialBadge: string;
169 }
170
171 export interface HomeDict {
172 /**
173 * `<title>` and meta description for the locale home route, consumed by
174 * `generateMetadata` in app/[locale]/layout.tsx. These were the last
175 * inline EN/ZH pair on the required slice; per-locale metadata is the
176 * whole point of routing a locale, so it lives in the dictionary.
177 */
178 metaTitle: string;
179 metaDescription: string;
180
181 /** Hero pill, e.g. "Open source · Any model · Runs in your terminal". */
182 kicker: string;
183 heroTitleA: string;
184 heroTitleB: string;
185 /**
186 * Hero lede. Carries a `{brand}` token so the brand can be typeset in its
187 * own span wherever the sentence needs it — the page splits on the token
188 * instead of concatenating fragments around it.
189 */
190 heroIntro: string;
191 install: string;
192 docs: string;
193 copy: string;
194 copied: string;
195
196 /** Eyebrow above the one-line install block, e.g. "one-line install". */
197 installEyebrow: string;
198 /** Install prerequisite line, e.g. "needs Node 18+ — no Rust toolchain". */
199 installRequirement: string;
200 /** Link to the other install methods, e.g. "other ways →". */
201 installOtherWays: string;
202
203 /** "Latest release {tag}" */
204 latestRelease: string;
205 releaseUnavailable: string;
206 /** "Current source" / "Source candidate" — prepended to `v{version}:`. */
207 currentSource: string;
208 sourceCandidate: string;
209 /** "{count} provider routes" */
210 providerRoutes: string;
211 /** "published release" / "source candidate" — the source-state label. */
212 publishedRelease: string;
213 figcaptionSourceCandidate: string;
214
215 /** Screenshot toolbar label, e.g. "Current session". */
216 shotSession: string;
217 /** Screenshot alt text for /codewhale-tui.png. */
218 screenshotAlt: string;
219 /** Screenshot figcaption. */
220 figcaption: string;
221
222 proofHeading: string;
223 proofBody: string;
224
225 /** Section seal glyph for the "see how it decides" band. */
226 sealDecides: string;
227 decidesEyebrow: string;
228 decidesHeading: string;
229 decidesLede: string;
230
231 /** Section seal glyph for the workflow band. */
232 sealWorkflow: string;
233 workflowHeading: string;
234 /** Four [title, description] steps. */
235 workflow: [string, string][];
236 receiptAria: string;
237 /**
238 * Right-hand column of the example receipt. The verbs (inspect / act /
239 * verify / report), `$ codewhale exec …`, and `cargo test --locked` stay
240 * code-owned literals in the JSX per docs/VOICE.md.
241 */
242 receiptInspect: string;
243 receiptAct: string;
244 receiptReport: string;
245
246 /** Section seal glyph for the getting-started band. */
247 sealStart: string;
248 startHeading: string;
249 startLede: string;
250 startGuideLink: string;
251 startVocabularyLink: string;
252
253 /** Section seal glyph for the boundaries band. */
254 sealBoundaries: string;
255 boundariesHeadingA: string;
256 boundariesHeadingB: string;
257 boundariesBody: string;
258 hostedGatewayLocal: string;
259 planActOperateDesc: string;
260 askAutoReviewDesc: string;
261 tuiExecWebDesc: string;
262
263 /** Section seal glyph for the surfaces band. */
264 sealSurfaces: string;
265 surfacesHeading: string;
266 /** Five [name, description] surfaces. */
267 surfaces: [string, string][];
268 runtimeLink: string;
269
270 installBandHeading: string;
271 binaries: string;
272 chinaMirrors: string;
273 installGuideLink: string;
274
275 /** Section seal glyph for the community band. */
276 sealCommunity: string;
277 communityHeading: string;
278 communityBody: string;
279 communityLinksAria: string;
280 contribute: string;
281 }
282
282 lines TYPESCRIPT