Skip to content

Commit 709692d

Browse files
authored
Merge pull request #29 from objectstack-ai/copilot/add-language-auto-detection
2 parents 361fa92 + 29b039c commit 709692d

1 file changed

Lines changed: 61 additions & 2 deletions

File tree

app/page.tsx

Lines changed: 61 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,64 @@
11
import { redirect } from 'next/navigation';
2+
import { headers } from 'next/headers';
3+
import { i18n } from '@/lib/i18n';
24

3-
export default function HomePage() {
4-
redirect('/en/docs');
5+
export default async function HomePage() {
6+
const headersList = await headers();
7+
const acceptLanguage = headersList.get('accept-language') || '';
8+
9+
// Parse the Accept-Language header and find the best match
10+
const preferredLang = getPreferredLanguage(acceptLanguage, i18n.languages);
11+
12+
redirect(`/${preferredLang}/docs`);
13+
}
14+
15+
function getPreferredLanguage(acceptLanguage: string, availableLanguages: readonly string[]): string {
16+
// Parse Accept-Language header (e.g., "zh-CN,zh;q=0.9,en;q=0.8")
17+
const languages = acceptLanguage
18+
.split(',')
19+
.map(lang => {
20+
const parts = lang.trim().split(';');
21+
const code = parts[0].trim();
22+
23+
// Skip empty language codes
24+
if (!code) {
25+
return null;
26+
}
27+
28+
// Parse quality value, default to 1.0 if not present or invalid
29+
let quality = 1.0;
30+
if (parts[1]) {
31+
const qPart = parts[1].trim();
32+
if (qPart.startsWith('q=')) {
33+
const parsedQuality = parseFloat(qPart.substring(2));
34+
if (!isNaN(parsedQuality)) {
35+
quality = parsedQuality;
36+
}
37+
}
38+
}
39+
40+
return { code, quality };
41+
})
42+
.filter((lang): lang is { code: string; quality: number } => lang !== null)
43+
.sort((a, b) => b.quality - a.quality);
44+
45+
// Try to find the best match (exact or partial) respecting quality order
46+
for (const lang of languages) {
47+
// Try exact match first
48+
if (availableLanguages.includes(lang.code)) {
49+
return lang.code;
50+
}
51+
52+
// Try partial match (e.g., "zh" matches "zh-CN")
53+
const langPrefix = lang.code.split('-')[0].toLowerCase();
54+
const match = availableLanguages.find(available =>
55+
available.toLowerCase().startsWith(langPrefix)
56+
);
57+
if (match) {
58+
return match;
59+
}
60+
}
61+
62+
// Default to the configured default language
63+
return i18n.defaultLanguage;
564
}

0 commit comments

Comments
 (0)