Skip to content

Commit aa330ac

Browse files
authored
Merge pull request #184 from aicodingstack/codex/seo
feat(seo): add localized comparison guides
2 parents 1d7b6d8 + 0794922 commit aa330ac

22 files changed

Lines changed: 3411 additions & 149 deletions

File tree

data/data-health.json

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -73,59 +73,59 @@
7373
},
7474
"translationsByLocale": {
7575
"de": {
76-
"totalStrings": 423,
76+
"totalStrings": 442,
7777
"matchingEnglish": 106,
78-
"matchingEnglishPercent": 25.1
78+
"matchingEnglishPercent": 24
7979
},
8080
"es": {
81-
"totalStrings": 423,
81+
"totalStrings": 442,
8282
"matchingEnglish": 98,
83-
"matchingEnglishPercent": 23.2
83+
"matchingEnglishPercent": 22.2
8484
},
8585
"fr": {
86-
"totalStrings": 423,
86+
"totalStrings": 442,
8787
"matchingEnglish": 108,
88-
"matchingEnglishPercent": 25.5
88+
"matchingEnglishPercent": 24.4
8989
},
9090
"id": {
91-
"totalStrings": 423,
91+
"totalStrings": 442,
9292
"matchingEnglish": 142,
93-
"matchingEnglishPercent": 33.6
93+
"matchingEnglishPercent": 32.1
9494
},
9595
"ja": {
96-
"totalStrings": 423,
96+
"totalStrings": 442,
9797
"matchingEnglish": 100,
98-
"matchingEnglishPercent": 23.6
98+
"matchingEnglishPercent": 22.6
9999
},
100100
"ko": {
101-
"totalStrings": 423,
101+
"totalStrings": 442,
102102
"matchingEnglish": 108,
103-
"matchingEnglishPercent": 25.5
103+
"matchingEnglishPercent": 24.4
104104
},
105105
"pt": {
106-
"totalStrings": 423,
106+
"totalStrings": 442,
107107
"matchingEnglish": 108,
108-
"matchingEnglishPercent": 25.5
108+
"matchingEnglishPercent": 24.4
109109
},
110110
"ru": {
111-
"totalStrings": 423,
111+
"totalStrings": 442,
112112
"matchingEnglish": 117,
113-
"matchingEnglishPercent": 27.7
113+
"matchingEnglishPercent": 26.5
114114
},
115115
"tr": {
116-
"totalStrings": 423,
116+
"totalStrings": 442,
117117
"matchingEnglish": 119,
118-
"matchingEnglishPercent": 28.1
118+
"matchingEnglishPercent": 26.9
119119
},
120120
"zh-Hans": {
121-
"totalStrings": 423,
121+
"totalStrings": 442,
122122
"matchingEnglish": 92,
123-
"matchingEnglishPercent": 21.7
123+
"matchingEnglishPercent": 20.8
124124
},
125125
"zh-Hant": {
126-
"totalStrings": 423,
126+
"totalStrings": 442,
127127
"matchingEnglish": 92,
128-
"matchingEnglishPercent": 21.7
128+
"matchingEnglishPercent": 20.8
129129
}
130130
},
131131
"issues": [

docs/DATA-HEALTH.md

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -37,17 +37,17 @@ Exact English matches are a triage signal; product names and technical terms can
3737

3838
| Locale | Comparable strings | Exact English matches | Match rate |
3939
| --- | ---: | ---: | ---: |
40-
| de | 423 | 106 | 25.1% |
41-
| es | 423 | 98 | 23.2% |
42-
| fr | 423 | 108 | 25.5% |
43-
| id | 423 | 142 | 33.6% |
44-
| ja | 423 | 100 | 23.6% |
45-
| ko | 423 | 108 | 25.5% |
46-
| pt | 423 | 108 | 25.5% |
47-
| ru | 423 | 117 | 27.7% |
48-
| tr | 423 | 119 | 28.1% |
49-
| zh-Hans | 423 | 92 | 21.7% |
50-
| zh-Hant | 423 | 92 | 21.7% |
40+
| de | 442 | 106 | 24% |
41+
| es | 442 | 98 | 22.2% |
42+
| fr | 442 | 108 | 24.4% |
43+
| id | 442 | 142 | 32.1% |
44+
| ja | 442 | 100 | 22.6% |
45+
| ko | 442 | 108 | 24.4% |
46+
| pt | 442 | 108 | 24.4% |
47+
| ru | 442 | 117 | 26.5% |
48+
| tr | 442 | 119 | 26.9% |
49+
| zh-Hans | 442 | 92 | 20.8% |
50+
| zh-Hant | 442 | 92 | 20.8% |
5151

5252
## Backlog by Issue Type
5353

src/app/[locale]/clis/comparison/page.client.tsx

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,13 @@ import { AppleIcon, LinuxIcon, WindowsIcon } from '@/components/controls/Platfor
66
import Footer from '@/components/Footer'
77
import Header from '@/components/Header'
88
import { Breadcrumb } from '@/components/navigation/Breadcrumb'
9+
import ComparisonGuide, {
10+
type ComparisonGuideContent,
11+
type ComparisonGuideItem,
12+
type ComparisonProfileItem,
13+
} from '@/components/product/ComparisonGuide'
914
import ComparisonTable, { type ComparisonColumn } from '@/components/product/ComparisonTable'
1015
import { PricingSummaryValue } from '@/components/product/ProductPricing'
11-
import { Link } from '@/i18n/navigation'
1216
import { withVendorCommunityUrlsForCatalog } from '@/lib/community-urls'
1317
import { clisData, vendorsData } from '@/lib/generated'
1418
import { getGithubStars } from '@/lib/generated/github-stars'
@@ -28,6 +32,19 @@ type Props = {
2832
export default function CLIComparisonPageClient({ locale: _locale }: Props) {
2933
const tPage = useTranslations('pages.comparison')
3034
const tShared = useTranslations('shared')
35+
const guideContent: ComparisonGuideContent = {
36+
title: tPage('clis.guide.title'),
37+
intro: tPage('clis.guide.intro', { count: clis.length }),
38+
criteria: tPage.raw('clis.guide.criteria') as ComparisonGuideItem[],
39+
shortlistTitle: tPage('clis.guide.shortlistTitle'),
40+
shortlistIntro: tPage('clis.guide.shortlistIntro'),
41+
steps: tPage.raw('clis.guide.steps') as ComparisonGuideItem[],
42+
profilesTitle: tPage('clis.guide.profilesTitle'),
43+
profilesIntro: tPage('clis.guide.profilesIntro'),
44+
profiles: tPage.raw('clis.guide.profiles') as ComparisonProfileItem[],
45+
faqTitle: tPage('clis.guide.faqTitle'),
46+
faqs: tPage.raw('clis.guide.faqs') as ComparisonGuideItem[],
47+
}
3148

3249
const columns: ComparisonColumn[] = [
3350
{
@@ -279,7 +296,7 @@ export default function CLIComparisonPageClient({ locale: _locale }: Props) {
279296
/>
280297

281298
{/* Page Header */}
282-
<section className="py-[var(--spacing-lg)] border-[var(--color-border)]">
299+
<section className="pt-[var(--spacing-lg)] pb-[var(--spacing-md)]">
283300
<div className="max-w-8xl mx-auto px-[var(--spacing-md)]">
284301
<h1 className="text-3xl font-semibold tracking-[-0.03em] mb-[var(--spacing-sm)]">
285302
{tPage('clis.title')}
@@ -291,28 +308,23 @@ export default function CLIComparisonPageClient({ locale: _locale }: Props) {
291308
</section>
292309

293310
{/* Comparison Table */}
294-
<section className="pb-[var(--spacing-lg)] border-b border-[var(--color-border)]">
311+
<section
312+
id="comparison-table"
313+
className="scroll-mt-32 pb-[var(--spacing-xl)] border-b border-[var(--color-border)]"
314+
>
295315
<div className="max-w-8xl mx-auto px-[var(--spacing-md)]">
296316
<ComparisonTable
297317
items={clis as unknown as Record<string, unknown>[]}
298318
columns={columns}
299319
itemLinkPrefix={`/clis`}
300320
nameColumnLabel={tShared('labels.name')}
321+
caption={tPage('clis.title')}
322+
scrollHint={tPage('table.scrollHint')}
301323
/>
302324
</div>
303325
</section>
304326

305-
{/* Back Navigation */}
306-
<section className="py-[var(--spacing-lg)] border-b border-[var(--color-border)]">
307-
<div className="max-w-8xl mx-auto px-[var(--spacing-md)]">
308-
<Link
309-
href="/clis"
310-
className="inline-flex items-center gap-[var(--spacing-xs)] text-sm text-[var(--color-text-secondary)] hover:text-[var(--color-text)] transition-colors"
311-
>
312-
{tPage('clis.backTo')}
313-
</Link>
314-
</div>
315-
</section>
327+
<ComparisonGuide content={guideContent} />
316328

317329
<Footer />
318330
</>

src/app/[locale]/extensions/comparison/page.client.tsx

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,13 @@ import { useTranslations } from 'next-intl'
55
import Footer from '@/components/Footer'
66
import Header from '@/components/Header'
77
import { Breadcrumb } from '@/components/navigation/Breadcrumb'
8+
import ComparisonGuide, {
9+
type ComparisonGuideContent,
10+
type ComparisonGuideItem,
11+
type ComparisonProfileItem,
12+
} from '@/components/product/ComparisonGuide'
813
import ComparisonTable, { type ComparisonColumn } from '@/components/product/ComparisonTable'
914
import { PricingSummaryValue } from '@/components/product/ProductPricing'
10-
import { Link } from '@/i18n/navigation'
1115
import { withVendorCommunityUrlsForCatalog } from '@/lib/community-urls'
1216
import { extensionsData, vendorsData } from '@/lib/generated'
1317
import { getGithubStars } from '@/lib/generated/github-stars'
@@ -27,6 +31,19 @@ type Props = {
2731
export default function ExtensionComparisonPageClient({ locale: _locale }: Props) {
2832
const tPage = useTranslations('pages.comparison')
2933
const tShared = useTranslations('shared')
34+
const guideContent: ComparisonGuideContent = {
35+
title: tPage('extensions.guide.title'),
36+
intro: tPage('extensions.guide.intro', { count: extensions.length }),
37+
criteria: tPage.raw('extensions.guide.criteria') as ComparisonGuideItem[],
38+
shortlistTitle: tPage('extensions.guide.shortlistTitle'),
39+
shortlistIntro: tPage('extensions.guide.shortlistIntro'),
40+
steps: tPage.raw('extensions.guide.steps') as ComparisonGuideItem[],
41+
profilesTitle: tPage('extensions.guide.profilesTitle'),
42+
profilesIntro: tPage('extensions.guide.profilesIntro'),
43+
profiles: tPage.raw('extensions.guide.profiles') as ComparisonProfileItem[],
44+
faqTitle: tPage('extensions.guide.faqTitle'),
45+
faqs: tPage.raw('extensions.guide.faqs') as ComparisonGuideItem[],
46+
}
3047

3148
const columns: ComparisonColumn[] = [
3249
{
@@ -265,7 +282,7 @@ export default function ExtensionComparisonPageClient({ locale: _locale }: Props
265282
/>
266283

267284
{/* Page Header */}
268-
<section className="py-[var(--spacing-lg)] border-[var(--color-border)]">
285+
<section className="pt-[var(--spacing-lg)] pb-[var(--spacing-md)]">
269286
<div className="max-w-8xl mx-auto px-[var(--spacing-md)]">
270287
<h1 className="text-3xl font-semibold tracking-[-0.03em] mb-[var(--spacing-sm)]">
271288
{tPage('extensions.title')}
@@ -277,28 +294,20 @@ export default function ExtensionComparisonPageClient({ locale: _locale }: Props
277294
</section>
278295

279296
{/* Comparison Table */}
280-
<section className="pb-[var(--spacing-lg)] border-b border-[var(--color-border)]">
297+
<section className="pb-[var(--spacing-xl)] border-b border-[var(--color-border)]">
281298
<div className="max-w-8xl mx-auto px-[var(--spacing-md)]">
282299
<ComparisonTable
283300
items={extensions as unknown as Record<string, unknown>[]}
284301
columns={columns}
285302
itemLinkPrefix={`/extensions`}
286303
nameColumnLabel={tShared('labels.name')}
304+
caption={tPage('extensions.title')}
305+
scrollHint={tPage('table.scrollHint')}
287306
/>
288307
</div>
289308
</section>
290309

291-
{/* Back Navigation */}
292-
<section className="py-[var(--spacing-lg)] border-b border-[var(--color-border)]">
293-
<div className="max-w-8xl mx-auto px-[var(--spacing-md)]">
294-
<Link
295-
href="/extensions"
296-
className="inline-flex items-center gap-[var(--spacing-xs)] text-sm text-[var(--color-text-secondary)] hover:text-[var(--color-text)] transition-colors"
297-
>
298-
{tPage('extensions.backTo')}
299-
</Link>
300-
</div>
301-
</section>
310+
<ComparisonGuide content={guideContent} />
302311

303312
<Footer />
304313
</>

src/app/[locale]/ides/comparison/page.client.tsx

Lines changed: 23 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,13 @@ import { AppleIcon, LinuxIcon, WindowsIcon } from '@/components/controls/Platfor
66
import Footer from '@/components/Footer'
77
import Header from '@/components/Header'
88
import { Breadcrumb } from '@/components/navigation/Breadcrumb'
9+
import ComparisonGuide, {
10+
type ComparisonGuideContent,
11+
type ComparisonGuideItem,
12+
type ComparisonProfileItem,
13+
} from '@/components/product/ComparisonGuide'
914
import ComparisonTable, { type ComparisonColumn } from '@/components/product/ComparisonTable'
1015
import { PricingSummaryValue } from '@/components/product/ProductPricing'
11-
import { Link } from '@/i18n/navigation'
1216
import { withVendorCommunityUrlsForCatalog } from '@/lib/community-urls'
1317
import { idesData, vendorsData } from '@/lib/generated'
1418
import { getGithubStars } from '@/lib/generated/github-stars'
@@ -28,6 +32,19 @@ type Props = {
2832
export default function IDEComparisonPageClient({ locale: _locale }: Props) {
2933
const tPage = useTranslations('pages.comparison')
3034
const tShared = useTranslations('shared')
35+
const guideContent: ComparisonGuideContent = {
36+
title: tPage('ides.guide.title'),
37+
intro: tPage('ides.guide.intro', { count: ides.length }),
38+
criteria: tPage.raw('ides.guide.criteria') as ComparisonGuideItem[],
39+
shortlistTitle: tPage('ides.guide.shortlistTitle'),
40+
shortlistIntro: tPage('ides.guide.shortlistIntro'),
41+
steps: tPage.raw('ides.guide.steps') as ComparisonGuideItem[],
42+
profilesTitle: tPage('ides.guide.profilesTitle'),
43+
profilesIntro: tPage('ides.guide.profilesIntro'),
44+
profiles: tPage.raw('ides.guide.profiles') as ComparisonProfileItem[],
45+
faqTitle: tPage('ides.guide.faqTitle'),
46+
faqs: tPage.raw('ides.guide.faqs') as ComparisonGuideItem[],
47+
}
3148

3249
const columns: ComparisonColumn[] = [
3350
{
@@ -279,7 +296,7 @@ export default function IDEComparisonPageClient({ locale: _locale }: Props) {
279296
/>
280297

281298
{/* Page Header */}
282-
<section className="py-[var(--spacing-lg)] border-[var(--color-border)]">
299+
<section className="pt-[var(--spacing-lg)] pb-[var(--spacing-md)]">
283300
<div className="max-w-8xl mx-auto px-[var(--spacing-md)]">
284301
<h1 className="text-3xl font-semibold tracking-[-0.03em] mb-[var(--spacing-sm)]">
285302
{tPage('ides.title')}
@@ -291,28 +308,20 @@ export default function IDEComparisonPageClient({ locale: _locale }: Props) {
291308
</section>
292309

293310
{/* Comparison Table */}
294-
<section className="pb-[var(--spacing-lg)] border-b border-[var(--color-border)]">
311+
<section className="pb-[var(--spacing-xl)] border-b border-[var(--color-border)]">
295312
<div className="max-w-8xl mx-auto px-[var(--spacing-md)]">
296313
<ComparisonTable
297314
items={ides as unknown as Record<string, unknown>[]}
298315
columns={columns}
299316
itemLinkPrefix={`/ides`}
300317
nameColumnLabel={tShared('labels.name')}
318+
caption={tPage('ides.title')}
319+
scrollHint={tPage('table.scrollHint')}
301320
/>
302321
</div>
303322
</section>
304323

305-
{/* Back Navigation */}
306-
<section className="py-[var(--spacing-lg)] border-b border-[var(--color-border)]">
307-
<div className="max-w-8xl mx-auto px-[var(--spacing-md)]">
308-
<Link
309-
href="/ides"
310-
className="inline-flex items-center gap-[var(--spacing-xs)] text-sm text-[var(--color-text-secondary)] hover:text-[var(--color-text)] transition-colors"
311-
>
312-
{tPage('ides.backTo')}
313-
</Link>
314-
</div>
315-
</section>
324+
<ComparisonGuide content={guideContent} />
316325

317326
<Footer />
318327
</>

0 commit comments

Comments
 (0)