Skip to content

Commit b7c730b

Browse files
authored
refactor: Extract i18n out of nav definitions (#1347)
* refactor: Extract i18n out of nav definitions * chore: Sort keys * chore: Appease TS * refactor: Flatten "/about" routes * junk: REVERT ME * refactor: Fix temporary translation hook standin * junk: REVERT ME TOO - checking size * refactor: Mostly works * refactor: Simplify implementation * refactor: Go back to Object.keys? * refactor: Remove '/about' path as it does not actually exist * refactor: Explicitly list all routes to prerender
1 parent 7964690 commit b7c730b

32 files changed

Lines changed: 1013 additions & 1209 deletions

jsconfig.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,5 +9,6 @@
99
"noEmit": true,
1010
"allowJs": true,
1111
"checkJs": true
12-
}
12+
},
13+
"exclude": ["node_modules", "build"]
1314
}

plugins/generate-llms-txt.js

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,8 @@ import fsSync from 'fs';
33
import path from 'path';
44
import { fileURLToPath } from 'url';
55
import { parseFrontmatter, cleanReplComments } from '../src/lib/frontmatter.js';
6-
import { v10StructuredDocRoutes } from '../src/lib/route-utils.js';
6+
import { docPages } from '../src/route-config.js';
7+
import englishTranslations from '../src/locales/en.json';
78

89
const __filename = fileURLToPath(import.meta.url);
910
const __dirname = path.dirname(__filename);
@@ -43,10 +44,10 @@ Preact is a fast, lightweight alternative to React that provides the same modern
4344

4445
let content = header;
4546

46-
for (const section of v10StructuredDocRoutes) {
47-
content += `## ${section.name}\n\n`;
47+
for (const section in docPages.v10) {
48+
content += `## ${englishTranslations.sidebarSections[section]}\n\n`;
4849

49-
for (const route of section.routes) {
50+
for (const route in docPages.v10[section]) {
5051
const { filename, content: fileContent } = files.find(
5152
file => file.filename === `${route.replace('/', '')}.md`
5253
);

plugins/rss-feed.js

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import { Feed } from 'feed';
2-
import config from '../src/config.json';
2+
import { blogPosts } from '../src/route-config.js';
3+
import englishTranslations from '../src/locales/en.json';
34

45
/**
56
* @returns {import('vite').Plugin}
@@ -24,12 +25,14 @@ export function rssFeedPlugin() {
2425
}
2526
});
2627

27-
config.blog.forEach(post => {
28+
Object.entries(blogPosts).map(([postPath, post]) => {
29+
const postTranslation = englishTranslations.blogPosts[post.label];
30+
2831
feed.addItem({
29-
title: post.name.en,
30-
id: `https://preactjs.com${post.path}`,
31-
link: `https://preactjs.com${post.path}`,
32-
description: post.excerpt.en,
32+
title: postTranslation.label,
33+
id: `https://preactjs.com${postPath}`,
34+
link: `https://preactjs.com${postPath}`,
35+
description: postTranslation.excerpt,
3336
date: new Date(post.date)
3437
});
3538
});

src/components/blog-overview/index.jsx

Lines changed: 9 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,28 @@
1-
import config from '../../config.json';
2-
import { useLanguage, useTranslation, getRouteName } from '../../lib/i18n';
1+
import { blogPosts } from '../../route-config.js';
2+
import { useTranslate } from '../../lib/i18n';
33
import { Time } from '../time';
44
import s from './style.module.css';
55

66
export default function BlogOverview() {
7-
const [lang] = useLanguage();
8-
const continueReading = useTranslation('continueReading');
7+
const translate = useTranslate();
98

109
return (
1110
<div>
1211
<div class={s.postList}>
13-
{config.blog.map(post => {
14-
const name = getRouteName(post, lang);
15-
const excerpt = post.excerpt[lang] || post.excerpt.en;
12+
{Object.entries(blogPosts).map(([postPath, post]) => {
13+
const translatedBlog = translate('blogPosts', post.label);
1614

1715
return (
1816
<article class={s.post}>
1917
<div class={s.meta}>
2018
<Time value={post.date} />
2119
</div>
2220
<h2 class={s.title}>
23-
<a href={post.path}>{name}</a>
21+
<a href={postPath}>{translatedBlog.label}</a>
2422
</h2>
25-
<p class={s.excerpt}>{excerpt}</p>
26-
<a href={post.path} class="btn-small">
27-
{continueReading} &rarr;
23+
<p class={s.excerpt}>{translatedBlog.excerpt}</p>
24+
<a href={postPath} class="btn-small">
25+
{translate('i18n', 'continueReading')} &rarr;
2826
</a>
2927
</article>
3028
);

src/components/controllers/blog-page.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,12 +3,12 @@ import { useContent } from '../../lib/use-content';
33
import { NotFound } from './not-found';
44
import { MarkdownRegion } from './markdown-region';
55
import Footer from '../footer/index';
6-
import { blogRoutes } from '../../lib/route-utils';
6+
import { blogPosts } from '../../route-config.js';
77
import style from './style.module.css';
88

99
export default function BlogPage() {
1010
const { slug } = useRoute().params;
11-
const isValidRoute = blogRoutes[`/blog/${slug}`];
11+
const isValidRoute = blogPosts[`/blog/${slug}`];
1212

1313
return (
1414
<ErrorBoundary>

src/components/controllers/guide-page.jsx

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,19 @@
11
import { useState, useEffect } from 'preact/hooks';
22
import { useRoute, ErrorBoundary } from 'preact-iso';
33
import { useContent } from '../../lib/use-content';
4-
import { useLanguage } from '../../lib/i18n.jsx';
5-
import config from '../../config.json';
4+
import { useLanguageContext } from '../../lib/i18n.jsx';
65
import { NotFound } from './not-found';
76
import cx from '../../lib/cx';
87
import { MarkdownRegion } from './markdown-region';
98
import Sidebar from '../sidebar';
109
import Footer from '../footer/index';
11-
import { docRoutes } from '../../lib/route-utils';
10+
import { flatDocPages } from '../../route-config.js';
1211
import { LATEST_MAJOR, PREVIEW_MAJOR } from '../doc-version';
1312
import style from './style.module.css';
1413

1514
export function GuidePage() {
1615
const { version, name } = useRoute().params;
17-
const isValidRoute = docRoutes[version]['/' + name];
16+
const isValidRoute = flatDocPages[version]['/' + name];
1817

1918
return (
2019
<ErrorBoundary>
@@ -57,9 +56,7 @@ function OldDocsWarning() {
5756
}
5857

5958
const outdatedVersion = version !== PREVIEW_MAJOR;
60-
const latestExists = config.docs[LATEST_MAJOR].some(section =>
61-
section.routes.some(route => route.path === '/' + name)
62-
);
59+
const latestExists = flatDocPages[LATEST_MAJOR]['/' + name];
6360

6461
return (
6562
<div class={style.stickyWarning}>
@@ -93,7 +90,7 @@ const MAINTAINED_LANGUAGES = ['en', 'ru', 'zh'];
9390
function UnmaintainedTranslationWarning({ meta }) {
9491
const { path, params } = useRoute();
9592
const { name, version } = params;
96-
const [lang, setLang] = useLanguage();
93+
const { lang, setLang } = useLanguageContext();
9794

9895
if (
9996
version !== LATEST_MAJOR ||

src/components/controllers/page.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
11
import { useRoute, ErrorBoundary } from 'preact-iso';
2-
import { navRoutes } from '../../lib/route-utils';
32
import { useContent } from '../../lib/use-content';
43
import { NotFound } from './not-found';
54
import { MarkdownRegion } from './markdown-region';
65
import Footer from '../footer/index';
76
import style from './style.module.css';
7+
import { headerNav } from '../../route-config.js';
88

99
// Supports generic pages like `/`, `/about/*`, `/blog`, etc.
1010
export function Page() {
1111
const { path } = useRoute();
12-
const isValidRoute = navRoutes[path];
12+
const isValidRoute = headerNav[path];
1313

1414
return (
1515
<ErrorBoundary>

src/components/controllers/tutorial-page.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@ import { Tutorial } from './tutorial';
44
import { SolutionProvider } from './tutorial/contexts';
55
import { NotFound } from './not-found';
66
import { useContent, prefetchContent } from '../../lib/use-content';
7-
import { tutorialRoutes } from '../../lib/route-utils';
7+
import { tutorialPages } from '../../route-config.js';
88

99
import style from './tutorial/style.module.css';
1010

1111
export default function TutorialPage() {
1212
const { step } = useRoute().params;
13-
const isValidRoute = tutorialRoutes[`/tutorial${step ? `/${step}` : ''}`];
13+
const isValidRoute = tutorialPages[`/tutorial${step ? `/${step}` : ''}`];
1414

1515
return (
1616
<ErrorBoundary>

src/components/controllers/tutorial/index.jsx

Lines changed: 8 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,7 @@ import { TutorialContext, SolutionContext } from './contexts';
1313
import { parseStackTrace } from '../repl/errors';
1414
import cx from '../../../lib/cx';
1515
import { CodeEditor, Runner, ErrorOverlay, Splitter } from '../../routes';
16-
import { useLanguage } from '../../../lib/i18n';
17-
import config from '../../../config.json';
16+
import { useTranslate } from '../../../lib/i18n.jsx';
1817
import { MarkdownRegion } from '../markdown-region';
1918
import style from './style.module.css';
2019

@@ -75,7 +74,6 @@ export function Tutorial({ html, meta }) {
7574
return () => clearTimeout(delay);
7675
}, [editorCode]);
7776

78-
7977
const useResult = fn => {
8078
useEffect(() => {
8179
resultHandlers.add(fn);
@@ -197,15 +195,15 @@ export function Tutorial({ html, meta }) {
197195
components={TUTORIAL_COMPONENTS}
198196
/>
199197

200-
{meta.tutorial?.setup &&
198+
{meta.tutorial?.setup && (
201199
<TutorialSetupBlock
202200
code={meta.tutorial.setup}
203201
runner={runner}
204202
useResult={useResult}
205203
useRealm={useRealm}
206204
useError={useError}
207205
/>
208-
}
206+
)}
209207

210208
<ButtonContainer meta={meta} showCode={showCode} help={help} />
211209
</div>
@@ -217,13 +215,13 @@ export function Tutorial({ html, meta }) {
217215
}
218216

219217
function ButtonContainer({ meta, showCode, help }) {
220-
const [lang] = useLanguage();
218+
const translate = useTranslate();
221219

222220
return (
223221
<div class={style.buttonContainer}>
224222
{meta.prev && (
225223
<a class={style.prevButton} href={meta.prev}>
226-
{config.i18n.previous[lang] || config.i18n.previous.en}
224+
{translate('i18n', 'previousPage')}
227225
</a>
228226
)}
229227
{meta.solvable && (
@@ -233,16 +231,14 @@ function ButtonContainer({ meta, showCode, help }) {
233231
disabled={!showCode}
234232
title="Show solution to this example"
235233
>
236-
{config.i18n.tutorial.solve[lang] ||
237-
config.i18n.tutorial.solve.en}
234+
{translate('i18n', 'solve')}
238235
</button>
239236
)}
240237
{meta.next && (
241238
<a class={style.nextButton} href={meta.next}>
242239
{meta.code == false
243-
? (config.i18n.tutorial.begin[lang] || config.i18n.tutorial.begin.en)
244-
: (config.i18n.next[lang] || config.i18n.next.en)
245-
}
240+
? translate('i18n', 'beginTutorial')
241+
: translate('i18n', 'nextPage')}
246242
</a>
247243
)}
248244
</div>

src/components/doc-version/index.jsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { useCallback } from 'preact/hooks';
22
import { useLocation, useRoute } from 'preact-iso';
3-
import { docRoutes } from '../../lib/route-utils.js';
3+
import { flatDocPages } from '../../route-config.js';
44
import style from './style.module.css';
55

66
export const LATEST_MAJOR = 'v10';
@@ -18,7 +18,7 @@ export default function DocVersion() {
1818
const onChange = useCallback(
1919
e => {
2020
const version = e.currentTarget.value;
21-
const url = docRoutes[version]?.[`/${name}`]
21+
const url = flatDocPages[version]?.[`/${name}`]
2222
? path.replace(/(v\d{1,2})/, version)
2323
: `/guide/${version}/getting-started`;
2424
route(url);

0 commit comments

Comments
 (0)