Skip to content

Commit 994eb8d

Browse files
authored
feat(i18n): added japanese and german translations (#1428)
* feat(changelog): added changelog * feat(i18n): added japanese and german translations * reordered --------- Co-authored-by: waleed <waleed>
1 parent fbb164d commit 994eb8d

File tree

4 files changed

+45
-14
lines changed

4 files changed

+45
-14
lines changed

.github/workflows/i18n.yml

Lines changed: 10 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ jobs:
5555
with:
5656
token: ${{ secrets.GH_PAT }}
5757
commit-message: "feat(i18n): update translations"
58-
title: "🌐 Auto-update translations"
58+
title: "feat(i18n): update translations"
5959
body: |
6060
## Summary
6161
Automated translation updates triggered by changes to documentation.
@@ -76,8 +76,10 @@ jobs:
7676
## Testing
7777
This PR includes automated translations for modified English documentation content:
7878
- 🇪🇸 Spanish (es) translations
79-
- 🇫🇷 French (fr) translations
79+
- 🇫🇷 French (fr) translations
8080
- 🇨🇳 Chinese (zh) translations
81+
- 🇯🇵 Japanese (ja) translations
82+
- 🇩🇪 German (de) translations
8183
8284
**What reviewers should focus on:**
8385
- Verify translated content accuracy and context
@@ -137,15 +139,21 @@ jobs:
137139
es_count=$(find content/docs/es -name "*.mdx" 2>/dev/null | wc -l || echo 0)
138140
fr_count=$(find content/docs/fr -name "*.mdx" 2>/dev/null | wc -l || echo 0)
139141
zh_count=$(find content/docs/zh -name "*.mdx" 2>/dev/null | wc -l || echo 0)
142+
ja_count=$(find content/docs/ja -name "*.mdx" 2>/dev/null | wc -l || echo 0)
143+
de_count=$(find content/docs/de -name "*.mdx" 2>/dev/null | wc -l || echo 0)
140144
141145
es_percentage=$((es_count * 100 / en_count))
142146
fr_percentage=$((fr_count * 100 / en_count))
143147
zh_percentage=$((zh_count * 100 / en_count))
148+
ja_percentage=$((ja_count * 100 / en_count))
149+
de_percentage=$((de_count * 100 / en_count))
144150
145151
echo "### Coverage Statistics" >> $GITHUB_STEP_SUMMARY
146152
echo "- **🇬🇧 English**: $en_count files (source)" >> $GITHUB_STEP_SUMMARY
147153
echo "- **🇪🇸 Spanish**: $es_count/$en_count files ($es_percentage%)" >> $GITHUB_STEP_SUMMARY
148154
echo "- **🇫🇷 French**: $fr_count/$en_count files ($fr_percentage%)" >> $GITHUB_STEP_SUMMARY
149155
echo "- **🇨🇳 Chinese**: $zh_count/$en_count files ($zh_percentage%)" >> $GITHUB_STEP_SUMMARY
156+
echo "- **🇯🇵 Japanese**: $ja_count/$en_count files ($ja_percentage%)" >> $GITHUB_STEP_SUMMARY
157+
echo "- **🇩🇪 German**: $de_count/$en_count files ($de_percentage%)" >> $GITHUB_STEP_SUMMARY
150158
echo "" >> $GITHUB_STEP_SUMMARY
151159
echo "🔄 **Auto-translation PR**: Check for new pull request with updated translations" >> $GITHUB_STEP_SUMMARY

apps/docs/components/ui/language-dropdown.tsx

Lines changed: 33 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,19 +2,22 @@
22

33
import { useEffect, useState } from 'react'
44
import { Check, ChevronDown } from 'lucide-react'
5-
import { useParams, usePathname } from 'next/navigation'
5+
import { useParams, usePathname, useRouter } from 'next/navigation'
66

77
const languages = {
88
en: { name: 'English', flag: '🇺🇸' },
99
es: { name: 'Español', flag: '🇪🇸' },
1010
fr: { name: 'Français', flag: '🇫🇷' },
11+
de: { name: 'Deutsch', flag: '🇩🇪' },
12+
ja: { name: '日本語', flag: '🇯🇵' },
1113
zh: { name: '简体中文', flag: '🇨🇳' },
1214
}
1315

1416
export function LanguageDropdown() {
1517
const [isOpen, setIsOpen] = useState(false)
1618
const pathname = usePathname()
1719
const params = useParams()
20+
const router = useRouter()
1821

1922
const [currentLang, setCurrentLang] = useState(() => {
2023
const langFromParams = params?.lang as string
@@ -56,9 +59,18 @@ export function LanguageDropdown() {
5659
newPath = `/${locale}${segments.length > 0 ? `/${segments.join('/')}` : '/introduction'}`
5760
}
5861

59-
window.location.href = newPath
62+
router.push(newPath)
6063
}
6164

65+
useEffect(() => {
66+
if (!isOpen) return
67+
const onKey = (e: KeyboardEvent) => {
68+
if (e.key === 'Escape') setIsOpen(false)
69+
}
70+
window.addEventListener('keydown', onKey)
71+
return () => window.removeEventListener('keydown', onKey)
72+
}, [isOpen])
73+
6274
return (
6375
<div className='relative'>
6476
<button
@@ -67,9 +79,12 @@ export function LanguageDropdown() {
6779
e.stopPropagation()
6880
setIsOpen(!isOpen)
6981
}}
70-
className='flex items-center gap-2 rounded-xl border border-border/20 bg-muted/50 px-3 py-2 text-sm backdrop-blur-sm transition-colors hover:bg-muted'
82+
aria-haspopup='listbox'
83+
aria-expanded={isOpen}
84+
aria-controls='language-menu'
85+
className='flex items-center gap-1.5 rounded-lg border border-border/30 bg-muted/40 px-2.5 py-1.5 text-sm shadow-sm backdrop-blur-sm transition-colors hover:bg-muted focus:outline-none focus-visible:ring-2 focus-visible:ring-ring'
7186
>
72-
<span className='text-base'>{languages[currentLang as keyof typeof languages]?.flag}</span>
87+
<span className='text-sm'>{languages[currentLang as keyof typeof languages]?.flag}</span>
7388
<span className='font-medium text-foreground'>
7489
{languages[currentLang as keyof typeof languages]?.name}
7590
</span>
@@ -80,8 +95,12 @@ export function LanguageDropdown() {
8095

8196
{isOpen && (
8297
<>
83-
<div className='fixed inset-0 z-10' onClick={() => setIsOpen(false)} />
84-
<div className='absolute top-full left-0 z-20 mt-1 w-48 rounded-lg border border-border/50 bg-background/95 shadow-xl backdrop-blur-md'>
98+
<div className='fixed inset-0 z-[1000]' aria-hidden onClick={() => setIsOpen(false)} />
99+
<div
100+
id='language-menu'
101+
role='listbox'
102+
className='absolute top-full left-0 z-[1001] mt-1 max-h-[75vh] w-56 overflow-auto rounded-xl border border-border/50 bg-white shadow-2xl md:w-44 md:bg-background/95 md:backdrop-blur-md dark:bg-neutral-950 md:dark:bg-background/95'
103+
>
85104
{Object.entries(languages).map(([code, lang]) => (
86105
<button
87106
key={code}
@@ -90,13 +109,17 @@ export function LanguageDropdown() {
90109
e.stopPropagation()
91110
handleLanguageChange(code)
92111
}}
93-
className={`flex w-full items-center gap-3 px-3 py-2.5 text-sm transition-colors first:rounded-t-lg last:rounded-b-lg hover:bg-muted/80 ${
112+
role='option'
113+
aria-selected={currentLang === code}
114+
className={`flex w-full items-center gap-3 px-3 py-3 text-base transition-colors first:rounded-t-xl last:rounded-b-xl hover:bg-muted/80 focus:outline-none focus-visible:ring-2 focus-visible:ring-ring md:gap-2 md:px-2.5 md:py-2 md:text-sm ${
94115
currentLang === code ? 'bg-muted/60 font-medium text-primary' : 'text-foreground'
95116
}`}
96117
>
97-
<span className='text-base'>{lang.flag}</span>
98-
<span>{lang.name}</span>
99-
{currentLang === code && <Check className='ml-auto h-4 w-4 text-primary' />}
118+
<span className='text-base md:text-sm'>{lang.flag}</span>
119+
<span className='leading-none'>{lang.name}</span>
120+
{currentLang === code && (
121+
<Check className='ml-auto h-4 w-4 text-primary md:h-3.5 md:w-3.5' />
122+
)}
100123
</button>
101124
))}
102125
</div>

apps/docs/i18n.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
"version": 1.8,
44
"locale": {
55
"source": "en",
6-
"targets": ["es", "fr", "zh"]
6+
"targets": ["es", "fr", "zh", "ja", "de"]
77
},
88
"buckets": {
99
"mdx": {

apps/docs/lib/i18n.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { defineI18n } from 'fumadocs-core/i18n'
22

33
export const i18n = defineI18n({
44
defaultLanguage: 'en',
5-
languages: ['en', 'es', 'fr', 'zh'],
5+
languages: ['en', 'es', 'fr', 'de', 'ja', 'zh'],
66
hideLocale: 'default-locale',
77
parser: 'dir',
88
})

0 commit comments

Comments
 (0)