-
Notifications
You must be signed in to change notification settings - Fork 0
Add automatic language detection from Accept-Language header #29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||||||||||||
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| @@ -1,5 +1,64 @@ | ||||||||||||||||||||
| import { redirect } from 'next/navigation'; | ||||||||||||||||||||
| import { headers } from 'next/headers'; | ||||||||||||||||||||
| import { i18n } from '@/lib/i18n'; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| export default function HomePage() { | ||||||||||||||||||||
| redirect('/en/docs'); | ||||||||||||||||||||
| export default async function HomePage() { | ||||||||||||||||||||
| const headersList = await headers(); | ||||||||||||||||||||
| const acceptLanguage = headersList.get('accept-language') || ''; | ||||||||||||||||||||
|
|
||||||||||||||||||||
| // Parse the Accept-Language header and find the best match | ||||||||||||||||||||
| const preferredLang = getPreferredLanguage(acceptLanguage, i18n.languages); | ||||||||||||||||||||
|
|
||||||||||||||||||||
| redirect(`/${preferredLang}/docs`); | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| function getPreferredLanguage(acceptLanguage: string, availableLanguages: readonly string[]): string { | ||||||||||||||||||||
| // Parse Accept-Language header (e.g., "zh-CN,zh;q=0.9,en;q=0.8") | ||||||||||||||||||||
| const languages = acceptLanguage | ||||||||||||||||||||
| .split(',') | ||||||||||||||||||||
| .map(lang => { | ||||||||||||||||||||
| const parts = lang.trim().split(';'); | ||||||||||||||||||||
| const code = parts[0].trim(); | ||||||||||||||||||||
|
|
||||||||||||||||||||
| // Skip empty language codes | ||||||||||||||||||||
| if (!code) { | ||||||||||||||||||||
| return null; | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| // Parse quality value, default to 1.0 if not present or invalid | ||||||||||||||||||||
| let quality = 1.0; | ||||||||||||||||||||
| if (parts[1]) { | ||||||||||||||||||||
| const qPart = parts[1].trim(); | ||||||||||||||||||||
| if (qPart.startsWith('q=')) { | ||||||||||||||||||||
| const parsedQuality = parseFloat(qPart.substring(2)); | ||||||||||||||||||||
| if (!isNaN(parsedQuality)) { | ||||||||||||||||||||
| quality = parsedQuality; | ||||||||||||||||||||
| } | ||||||||||||||||||||
| } | ||||||||||||||||||||
| } | ||||||||||||||||||||
|
|
||||||||||||||||||||
| return { code, quality }; | ||||||||||||||||||||
| }) | ||||||||||||||||||||
| .filter((lang): lang is { code: string; quality: number } => lang !== null) | ||||||||||||||||||||
| .sort((a, b) => b.quality - a.quality); | ||||||||||||||||||||
|
|
||||||||||||||||||||
| // Try to find the best match (exact or partial) respecting quality order | ||||||||||||||||||||
| for (const lang of languages) { | ||||||||||||||||||||
| // Try exact match first | ||||||||||||||||||||
| if (availableLanguages.includes(lang.code)) { | ||||||||||||||||||||
| return lang.code; | ||||||||||||||||||||
|
Comment on lines
+47
to
+49
|
||||||||||||||||||||
| // Try exact match first | |
| if (availableLanguages.includes(lang.code)) { | |
| return lang.code; | |
| // Try exact match first (case-insensitive) | |
| const exactMatch = availableLanguages.find( | |
| available => available.toLowerCase() === lang.code.toLowerCase() | |
| ); | |
| if (exactMatch) { | |
| return exactMatch; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The getPreferredLanguage function lacks test coverage for critical edge cases including empty Accept-Language headers, malformed quality values, case sensitivity handling, and fallback behavior. Consider adding unit tests to verify correct behavior across these scenarios.