Skip to content

Commit 2953832

Browse files
ericyangpanclaude
andcommitted
feat(i18n): add 8 new supported languages (es, fr, id, ja, pt, ru, tr, zh-Hant)
Extended internationalization from 4 to 12 languages. Added Spanish, French, Indonesian, Japanese, Portuguese, Russian, Turkish, and Traditional Chinese. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <noreply@anthropic.com>
1 parent 62cb038 commit 2953832

File tree

4 files changed

+201
-22
lines changed

4 files changed

+201
-22
lines changed

cspell.json

Lines changed: 159 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
{
22
"$schema": "https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json",
33
"version": "0.2",
4-
"language": "en,de,es,fr,pt,ru",
5-
"dictionaries": ["de", "es", "fr", "pt", "ru"],
4+
"language": "en,de,es,fr,id,it,pt,ru,tr",
5+
"dictionaries": ["de", "es", "fr", "id", "it", "pt", "ru", "tr"],
66
"dictionaryDefinitions": [
77
{
88
"name": "de",
@@ -19,6 +19,16 @@
1919
"path": "node_modules/@cspell/dict-fr-fr/fr-fr.trie.gz",
2020
"description": "French dictionary"
2121
},
22+
{
23+
"name": "id",
24+
"path": "node_modules/@cspell/dict-id-id/dict/id-id.trie",
25+
"description": "Indonesian dictionary"
26+
},
27+
{
28+
"name": "it",
29+
"path": "node_modules/@cspell/dict-it-it/dict/it-it.trie",
30+
"description": "Italian dictionary"
31+
},
2232
{
2333
"name": "pt",
2434
"path": "node_modules/@cspell/dict-pt-pt/dict/Portuguese-European.trie.gz",
@@ -28,29 +38,75 @@
2838
"name": "ru",
2939
"path": "node_modules/@cspell/dict-ru_ru/ru_ru.trie.gz",
3040
"description": "Russian dictionary"
41+
},
42+
{
43+
"name": "tr",
44+
"path": "node_modules/@cspell/dict-tr-tr/Turkish.trie.gz",
45+
"description": "Turkish dictionary"
3146
}
3247
],
3348
"useGitignore": true,
3449
"ignorePaths": ["cloudflare-env.d.ts", "docs", ".claude"],
3550
"words": [
36-
"agentic",
37-
"agentischer",
38-
"AiCodingStack",
51+
"Anthropics",
52+
"Benefíciate",
53+
"bienvene",
3954
"berechtigungsbasierter",
4055
"BMAD",
4156
"BYOK",
57+
"Coden",
58+
"Codierungsaufgaben",
59+
"Codierungsbenchmarks",
60+
"Codierungsmodell",
61+
"fortschrittlichestes",
62+
"Funktionsaufrufung",
63+
"gtag",
64+
"görselleştirin",
65+
"hochkapazitatives",
66+
"Intinya",
67+
"Maks",
68+
"Multimodal",
69+
"Optimierung",
70+
"orkestr",
71+
"Porcentagem",
72+
"Sugeriendo",
73+
"RAG",
74+
"refactorización",
75+
"refactorieren",
76+
"refatoração",
77+
"Refatoração",
78+
"Spesifikasyon",
79+
"Spesifikasyonlar",
80+
"spesifikasyonlar",
81+
"spesifikasyonları",
82+
"spesifikasyonlarını",
83+
"TTFB",
84+
"Türkçe",
85+
"Vervollständigungstool",
86+
"yığınınızı",
87+
"Бенчмарки",
88+
"Мультимодальное",
89+
"мультимодальные",
90+
"İndir",
91+
"İzleme",
92+
"İNDEKS",
93+
"agentic",
94+
"agentischer",
95+
"AiCodingStack",
4296
"CLIs",
97+
"CLI'lere",
4398
"cmdk",
4499
"Codierungs",
45100
"Codierungsassistent",
46101
"Codierungsassistenz",
47-
"Codierungserfahrung",
48102
"Codierungsplattform",
49103
"Codierungsunterstützung",
50104
"deepv",
51105
"dvcode",
52106
"Entwicklungsworkflows",
53107
"hrefs",
108+
"IDE'lere",
109+
"IDE'lerin",
54110
"Integrationen",
55111
"Junie",
56112
"Kuaishou",
@@ -64,11 +120,106 @@
64120
"Qoder",
65121
"QoderCLI",
66122
"Qwen",
67-
"RLHF",
68123
"Roo",
69124
"shareAI",
70125
"TRAE",
71-
"linkedin"
126+
"linkedin",
127+
"Видеоклауд",
128+
"Сообщественная",
129+
"агентачный",
130+
"агентного",
131+
"агентные",
132+
"агентным",
133+
"агентными",
134+
"интеллекцию",
135+
"инференса",
136+
"кодерского",
137+
"мульти",
138+
"мультимодальная",
139+
"мультимодальным",
140+
"мультимодальных",
141+
"настр",
142+
"настраивае",
143+
"оркестрирует",
144+
"пания",
145+
"помошник",
146+
"фронтенд",
147+
"agenticen",
148+
"ajent",
149+
"akislari",
150+
"akislarindaki",
151+
"akislarini",
152+
"akislarni",
153+
"alaninda",
154+
"anlayisi",
155+
"aracilar",
156+
"araciligiyla",
157+
"araclari",
158+
"arastirma",
159+
"autó",
160+
"autono",
161+
"autônoma",
162+
"autônomo",
163+
"autônomos",
164+
"ayiklama",
165+
"berbayar",
166+
"cagirme",
167+
"calistiran",
168+
"calistirin",
169+
"canli",
170+
"CI'nizde",
171+
"construíndo",
172+
"customizaveis",
173+
"d'intelligenc",
174+
"demokratizasyonunu",
175+
"desteg",
176+
"detayli",
177+
"didesain",
178+
"Droid'ları",
179+
"Experitez",
180+
"Granüler",
181+
"hatalari",
182+
"hizlandiran",
183+
"hizli",
184+
"hook'larını",
185+
"IDE'nize",
186+
"İnsanlar",
187+
"karmaik",
188+
"komutlari",
189+
"kullanin",
190+
"kullanir",
191+
"kurallarinizi",
192+
"Mengkonversi",
193+
"mengorkestrasi",
194+
"modalli",
195+
"modlu",
196+
"modu",
197+
"odakli",
198+
"optimizasyon",
199+
"orkestrasyonu",
200+
"orkestre",
201+
"pengkodean",
202+
"pengodean",
203+
"privibilidade",
204+
"programcıdır",
205+
"projectos",
206+
"refactorisation",
207+
"Refactorisent",
208+
"Refactorizan",
209+
"Refatoram",
210+
"saglayicinin",
211+
"saglayicisiyla",
212+
"satci",
213+
"specialisée",
214+
"tabanli",
215+
"tasarlanmisitir",
216+
"tasarlanmistir",
217+
"teknologların",
218+
"yanitlar",
219+
"yardimci",
220+
"yardimcisidir",
221+
"yayin",
222+
"yazin"
72223
],
73224
"allowCompoundWords": true
74225
}

src/components/controls/LanguageSwitcher.tsx

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ import { Languages } from 'lucide-react'
44
import { usePathname, useRouter } from 'next/navigation'
55
import { useLocale, useTranslations } from 'next-intl'
66
import { useEffect, useRef, useState } from 'react'
7-
import { type Locale, localeLabels, locales } from '@/i18n/config'
7+
import { type Locale, localeNames, locales } from '@/i18n/config'
88

99
// Type definition for Cookie Store API
1010
interface CookieStoreSetOptions {
@@ -125,7 +125,7 @@ export default function LanguageSwitcher() {
125125
aria-expanded={isOpen}
126126
>
127127
<Languages className="footer-control-icon" />
128-
{localeLabels[locale]}
128+
{localeNames[locale]}
129129
</button>
130130

131131
{isOpen && (
@@ -139,7 +139,7 @@ export default function LanguageSwitcher() {
139139
loc === locale ? 'bg-[var(--color-hover)] font-medium' : 'font-light'
140140
}`}
141141
>
142-
{localeLabels[loc]}
142+
{localeNames[loc]}
143143
{loc === locale && ' ✓'}
144144
</button>
145145
))}

src/i18n/config.ts

Lines changed: 32 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,21 +1,34 @@
1-
export const locales = ['en', 'de', 'zh-Hans', 'ko'] as const
1+
export const locales = [
2+
'en',
3+
'de',
4+
'es',
5+
'fr',
6+
'id',
7+
'ja',
8+
'ko',
9+
'pt',
10+
'ru',
11+
'tr',
12+
'zh-Hans',
13+
'zh-Hant',
14+
] as const
215
export type Locale = (typeof locales)[number]
316

417
export const defaultLocale: Locale = 'en'
518

619
export const localeNames: Record<Locale, string> = {
720
en: 'English',
821
de: 'Deutsch',
9-
'zh-Hans': '简体中文',
10-
ko: '한국어',
11-
}
12-
13-
export const localeLabels: Record<Locale, string> = {
14-
en: 'EN',
15-
de: 'DE',
16-
'zh-Hans': '简中',
17-
22+
es: 'Español',
23+
fr: 'Français',
24+
id: 'Bahasa Indonesia',
25+
ja: '日本語',
1826
ko: '한국어',
27+
pt: 'Português',
28+
ru: 'Русский',
29+
tr: 'Türkçe',
30+
'zh-Hans': '简体中文',
31+
'zh-Hant': '繁體中文',
1932
}
2033

2134
/**
@@ -25,6 +38,14 @@ export const localeLabels: Record<Locale, string> = {
2538
export const localeToOgLocale: Record<Locale, string> = {
2639
en: 'en_US',
2740
de: 'de_DE',
28-
'zh-Hans': 'zh_CN',
41+
es: 'es_ES',
42+
fr: 'fr_FR',
43+
id: 'id_ID',
44+
ja: 'ja_JP',
2945
ko: 'ko_KR',
46+
pt: 'pt_PT',
47+
ru: 'ru_RU',
48+
tr: 'tr_TR',
49+
'zh-Hans': 'zh_CN',
50+
'zh-Hant': 'zh_TW',
3051
}

vitest.config.ts

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import path from 'node:path'
12
import { defineConfig } from 'vitest/config'
23

34
/**
@@ -6,6 +7,12 @@ import { defineConfig } from 'vitest/config'
67
* We run validations in a Node environment (filesystem + schemas + JSON parsing).
78
*/
89
export default defineConfig({
10+
resolve: {
11+
alias: {
12+
'@': path.resolve(__dirname, './src'),
13+
'@content': path.resolve(__dirname, './content'),
14+
},
15+
},
916
test: {
1017
environment: 'node',
1118
// Use threads pool to avoid fork process termination issues in constrained environments.

0 commit comments

Comments
 (0)